views:

631

answers:

5

On setVisible(true), I call the following code to start a modal dialog:

private synchronized void startModal () {
  try {
    if (SwingUtilities.isEventDispatchThread()) {
      EventQueue theQueue = getToolkit().getSystemEventQueue();
      while (isVisible()) {
        AWTEvent event = theQueue.getNextEvent();
        Object source = event.getSource();
        if (event instanceof ActiveEvent) {
          ((ActiveEvent) event).dispatch();
        } else if (source instanceof Component) {
          ((Component) source).dispatchEvent(event);
        } else if (source instanceof MenuComponent) {
          ((MenuComponent) source).dispatchEvent(event);
        } else {
          System.err.println("Unable to dispatch: " + event);
        }
      }
    } else {
      while (isVisible()) {
        wait();
      }
    }
  } catch (InterruptedException ignored) { }
}

This works just great in most browsers. However, in Opera and Safari for Windows, I am confronted with the following big-nasty-exception:

java.security.AccessControlException: access denied (java.awt.AWTPermission accessEventQueue)
    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.checkAwtEventQueueAccess(Unknown Source)
    at java.awt.Toolkit.getSystemEventQueue(Unknown Source)

Is there a workaround for generating fake-modal dialogs in these browsers?

+1  A: 

That permission should be granted unless you have a strange implementation (Sun PlugIn has been granting it since 1.2.2, IIRC). Which versions are we talking about?

That probably isn't the best dispatch loop.

You probably should call isVisible off the EDT.

Modal interfaces are generally nasty.

What's wrong with a modal dialog?

Tom Hawtin - tackline
Its Java 1.6u13 (among others). But, as state, its in the Opera and Safari on Windows browsers, which both have their own Java plugin.
jsight
Modal dialog won't work, because these aren't really dialogs. They just need to block the calling code (which is on the EDT) until the dialog is closed. We could rewrite it with a different approach, but would prefer to stick with the modal approach instead of rewriting things for two weird browsers.
jsight
IIRC, Opera uses ye olde "Firefox 2" plugin, which should behave the same as far as this goes. They really ought to get on with the new Firefox 3/Chrome plugin interface. You can open a dialog without decoration off screen. That's what WebStart and PlugIn security dialogs do (although, IIRC, they leave the decoration on, which isn't so bright).
Tom Hawtin - tackline
Actually, Opera has their own, non-Sun plugin. The console is different, as is the sec mgr, apparently. These aren't really dialogs at all (JInternalframes, being used strangely for usability reasons). They work beautifully on all but these two browsers.
jsight
+1  A: 

If I might offer a different approach that could work, instead of intercepting the events in the event thread, you could use the glass pane to block all input requests.

Mario Ortegón
Yes, I should have mentioned that in the original question. It "works", but exposes tons of hard to workaround bugs in the swing controls when placed on a glasspane. It also doesn't fully solve the modality issue (its not just hiding events, its also causing setVisible(true) to hang the caller until the dialog is hidden).
jsight
+1  A: 

The reason of having a problem with Opera might be that Opera has its own java.policy file named as opera.policy (under Opera_installation_directory\classes folder). Though, in my Opera installation, I couldn't see any permission that is not granted in Opera but granted in the default java.policy file.

hakan
The Sun PlugIn and WebStart grant this permission.
Tom Hawtin - tackline
+1  A: 

Don't you need to sign your applet in order this to work?

Signing an applet

The way to allow an applet to do all those things is to digitally sign it. In effect the signer says "This applet is safe to use, and if you trust me, you can trust this applet, because through my signature you can be assured that it has not been tampered with since I signed it." The user will then be asked if she wants to trust the signer (usually in a little dialog box), and if she does, the applet can proceed with full privileges. If the trust is denied, the applet continues to run inside the sandbox with limited privileges.

The decision of whether to trust an applet should be made very judiciously, because a trusted applet has the same privileges a locally started application would have: It can read and delete files, and transmit data over the network.

A more thorough explanation of the applet security model can be found here. That includes a full list of the applet restrictions.

For an introduction to applet signing and links to more information read this and especially this. Internet Explorer (and the MS JVM) are a bit non-standard; read this for an overview of what to do.

If, even after signing the applet, you still get a SecurityException, try running the code as privileged code:

AccessController.doPrivileged(new PrivilegedAction() { public Object run() { // perform the security-sensitive operation here return null; } });

JavaDoc:java.security.AccessController

Policy files

An alternative way to grant an applet additional capabilities is the use of Policy files, about which Sun has an introductory article, and another one here specifically for applets. Using policies it is possible to control in a more fine-grained way which privileges to grant an applet. E.g., it becomes possible to grant applets access to the local file system, but not any of the other capabilities they are denied. Here is an example of that.

The drawback to using policy files is that they reside on the local file system, so users must make changes to a file that is normally out of their sight, and the contents of which are not trivial to understand.

The following example shows how to revoke most of an applets restrictions. Any of the permissions can be made more specific, e.g. FilePermission can be given for only selected files, and with read-only access. The javadocs for each Permission class explain in detail what's possible. It is good practice to use the most restricted setting possible. RuntimePermission in particular can be used to create ClassLoaders and SecurityManagers, which can circumvent even more applet restrictions.

 grant codeBase "http://geosim.cs.vt.edu/geosim/-" {
   permission java.io.FilePermission "<<ALL FILES>>", "read, write, execute, delete";
   permission java.net.SocketPermission "*", "accept, connect, listen, resolve";
   permission java.util.PropertyPermission "*", "read, write";
   permission java.lang.RuntimePermission "*";
   permission java.awt.AWTPermission "showWindowWithoutWarningBanner";
 };

Javadocs

JavaDoc:java.awt.AWTPermission JavaDoc:java.io.FilePermission JavaDoc:java.lang.RuntimePermission JavaDoc:java.net.SocketPermission JavaDoc:java.util.PropertyPermission

Kamia
A: 

For fake modal internal frames, see the following Sun article.

Pool
The question requires fake-modal dialogs (using a JInternalFrame and blocking the caller). This solution doesn't do that.
jsight
You didn't add any requirement for JInternalFrame.
Pool
The Frame ancestor of Applet is an implementation detail and may disappear without warning.
Tom Hawtin - tackline
Yes, I've removed that completely, now he wants to use a JInternalFrame...
Pool