My Photo
Powered by TypePad

« The Tradeshow Season | Main | Tell Us What You Need – We're Listening! »

October 13, 2006

JavaScripting in Applets - Getting Out of the Sandbox

I'd like to describe a recent discovery with regards to using JavaScript with Applets, and running into security problems. First, I'll give an overview of "The Applet Sandbox", and using JavaScript to call into an Applet.

The Sandbox

When developers are introduced to Java Applet technology, one of the first things they learn about is the Java Applet Sandbox. The sandbox refers to a set of security restrictions imposed on an Applet. The sandbox exists to prevent potentially dangerous code from being executed on a user's machine when they simply browse to a website.

Three of the basic restrictions are as follows:

  • No access to the client's local file system.
  • No network access to a remote system other than the Applet's host machine.
  • No access to the client's printer.

There is a way to break out of the sandbox, via signing. A company can establish itself as a trusted vendor by purchasing certificates from a company like VeriSign. You can then "sign" your Applet and have the ability to do things such as read local files, and connect to an arbitrary URL. In order to write the most powerful Java Applets, this is the way to go.

Calling Applet methods via JavaScript

Since Applets are meant to be embedded in web pages, it would be nice to have your web page interact with your Applet. The way to do this is via JavaScript. Here's a really basic example.

Our Applet has one method, changeColor:

public class ColorApplet extends Applet
{   
    public void changeColor (String color)
    {
        if (color.equals("red"))
        {
            setBackground(Color.red);
        }
        else if (color.equals("blue"))
        {
            setBackground(Color.blue);            
        }   
    }   
}

This is a pretty worthless Applet without some kind of external access into the changeColor method. Here's the HTML to call into the method:

<html>
<body>
<applet height="100" width="100" code="ColorApplet.class" name="ColorApplet"></applet>
<a onclick="javascript:ColorApplet.changeColor('red');" href="#">Red</a>
<a onclick="javascript:ColorApplet.changeColor('blue');" href="#">Blue</a>
</body>
</html>

By clicking on the "Red" and "Blue" Links in the html page, the Applet's background would change accordingly.

Using JavaScript to call restricted methods.

Changing colors in an Applet doesn't seem very useful. But lets say I have an Applet that can open up images from a file name or from a URL. The JavaScript hyperlinks can be used to open different files and URLs in the applet. I implemented a public method,

       public void openFile (String filename) 

 

This method will open up a local file or URL and display the image in the Applet. This works fine with any filename or URL since our Applet is signed. However, when I tried to call this method from an html page with JavaScript, I got the following error:

java.security.AccessControlException: access denied (java.io.FilePermission C:\images\img1.tif read)
at java.security.AccessControlContext.checkPermission(Unknown Source)
at java.security.AccessController.checkPermission(Unknown Source)
at java.lang.SecurityManager.checkPermission(Unknown Source)
at java.lang.SecurityManager.checkWrite(Unknown Source)

 

I was baffled. I retested openFile via my file menu, and the image opened up fine, so I knew I had signed the applet properly. I tested the JavaScript again and no luck. Hmm. Then I tried another JavaScript method that simply printed out some text to the console and that worked. Finally, I figured that there must be some additional security layer that prevents JavaScript from calling into the sandbox-restricted methods, even if the Applet is signed. After a quick Google search, I found some forum threads such as this one, which confirmed my suspicions. So what to do? I figured I would use the JavaScript method just to set some properties in the Applet. I would then create a separate thread that could be responsible for listening to changes in these fields, and calling the openFile method on behalf of the JavaScript. Here's how that worked. I made a new method called jsOpenFile, like this:

  /**
     * @param name
     */
    public void jsOpenFile(String name)
    {
        gJavascriptFilename = name;
        gJavascriptCalled = true;
    }

Then I defined a thread in the init() method of my applet, like this:

            Thread javascriptListener = new Thread()
            {
                public void run()
                {
                    while (true)
                    {
                        if (gJavascriptCalled)
                        {
                            gJavascriptCalled = false;
                            openFile(gJavascriptFilename);
                        }
                        try
                        {
                            sleep(JAVA_SCRIPT_POLL_INTERVAL);
                        }
                        catch (Throwable t)
                        {
                            t.printStackTrace();
                        }
                    }
                }
            };
            javascriptListener.start();

Sure enough it works!

-Alex

TrackBack

TrackBack URL for this entry:
http://www.typepad.com/services/trackback/6a00d83453a2c069e200d83462837c69e2

Listed below are links to weblogs that reference JavaScripting in Applets - Getting Out of the Sandbox:

» Nightmare: Java Applet and JavaScript from iDeas wHizz
I met the same thing about 2 years ago. And many of my JavaScript calls are restricted so the calls need to be asynchronized. But my JavaScript calls just should be a syncrhronous call. So callbacks [Read More]

Comments

Wow, complicated workaround ! (same as mine to indent code below ;-) )
just to inform you that it exist another way to do that quickly when surrounding the content of your method with java.security.AccessController.doPrivileged(new java.security.PrivilegedAction() {
See example below:


_ public static void doSpecialWork(String param1) {
_ _ final String fParam1 = param1;
_ _ java.security.AccessController.doPrivileged(new java.security.PrivilegedAction() {
_ _ _ public Object run() {
_ _ _ _ _ //Put the code of your method here
_ _ _ _ _ ...
_ _ _ _ _ ...
_ _ _ _ _ return "";
_ _ _ }
_ _ }
_ _ );
_ }

You only have to convert all method params into final (see fParam1).
No change in your javascript.

Regards,
SteF.

Stéphane Bury
Developper Analyst
IRIS S.A.
http://www.irislink.com

Hi,
I have created an applet that does the functionality of connecting to remote host using SFTP. When i tried to launch my applet, exception "AccessControlException, access denied" is thrown. I have self signed my jar file. But still same problem persists. How do i solve this issue???

Thank you so much for your workaround! It has worked for me, while the AccessController one couldn't...Don't know why. Anyway, the important thing is that it works and that my job is going on! :) THANK YOU!!! :)

Hello,

thank you very very much for this example!!!

i have tried both examples...with one strange fact:

When i trigger the action for the first time it is pretty slow until i get a result back.

When i trigger the actions again it work as i would expected...so nearly realtime.

Is this problem familiar to someone?

If yes...any help is very much appreciated!

Kind regards,

Sebastian

Verify your Comment

Previewing your Comment

This is only a preview. Your comment has not yet been posted.

Working...
Your comment could not be posted. Error type:
Your comment has been saved. Comments are moderated and will not appear until approved by the author. Post another comment

The letters and numbers you entered did not match the image. Please try again.

As a final step before posting your comment, enter the letters and numbers you see in the image below. This prevents automated programs from posting comments.

Having trouble reading this image? View an alternate.

Working...

Post a comment

Comments are moderated, and will not appear until the author has approved them.