The Java applet is not visible in Chrome

advertisements

I'm running into some kind race condition in a Java applet, peculiar to Google Chrome (win xp). I'm writing the <applet> tag into a popup window.

The problem is characterised by:

  1. The applet always shows fine in MS IE and Firefox.
  2. In Chrome The applet only displays about 50% of the time.
  3. When it doesn't display, the applet actually appears to be silently running perfectly from the Java console! No errors!
  4. The JApplet's init() and start() methods are always called.
  5. isShowing() and isDisplayable() always return true, even when the applet does not show.
  6. When it doesn't show, the paint() method isn't called.
  7. When the applet doesn't show, a transparent rectangular area (of the window background colour) where the applet should have been can be noticed when the text in the window is selected. From this I take it that the applet region is correctly placed in the window.

My code:

MyApplet.java

  package mypackage;
  public class MyApplet extends JApplet  {
    public void init(){
      super.init();
      getContentPane().add(new JLabel("Hello"), BorderLayout.CENTER);
      System.out.println("init ok");
    }
    public void start() {
      super.start();
      System.out.println("s parent:"+this.getParent());
      System.out.println("s disp:"+this.isDisplayable());
      System.out.println("s showing:"+this.isShowing());
    }
    public void paint(Graphics g){
      System.out.println("painting");
      super.paint(g);
    }
  }

test.html

<HTML>
<SCRIPT language='JavaScript'>
var jarpath='./myjar.jar';
var classname='mypackage.MyApplet';
function opentest(){
  applet=window.open('', '', "height=420,width=620");
  applet.document.write(
    '<html><body>'+
    '<OBJECT classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"'+
       'width=600 height=400>'+
        '<param name=code value="'+classname+'">'+
        '<param name=archive value="'+jarpath+'">'+
        '<param name=type value="application/x-java-applet;version1.3">'+
        '<COMMENT>'+
          '<EMBED code="'+classname+'" archive="'+jarpath+'" ' +
                  'type="application/x-java-applet;version=1.3" ' +
                  'width=600 height=400 ' +
              '>'+
            '<NOEMBED>' +
               'unavailable'+
            '</NOEMBED>'+
          '</EMBED>' +
        '</COMMENT>' +
     '</OBJECT>'+
   '</body></html>' );
}
</SCRIPT>

<BODY>
  Click here to open <A onclick="opentest()">Test</A>
</BODY>
</HTML>

Output from console

50% of the time I click on 'Test', the new window contains the 'Hello' label. The other 50% of the time, the window is blank as described. The console output seems identical when the applet loads and doesn't load. It seems blameless!

security: property package.access value sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.
security: property package.access new value sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.javaws
security: property package.access value sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.javaws
security: property package.access new value sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.javaws,com.sun.deploy
security: property package.access value sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.javaws,com.sun.deploy
security: property package.access new value sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.javaws,com.sun.deploy,com.sun.jnlp
security: property package.definition value null
security: property package.definition new value com.sun.javaws
security: property package.definition value com.sun.javaws
security: property package.definition new value com.sun.javaws,com.sun.deploy
security: property package.definition value com.sun.javaws,com.sun.deploy
security: property package.definition new value com.sun.javaws,com.sun.deploy,com.sun.jnlp
security: property package.access value sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.javaws,com.sun.deploy,com.sun.jnlp
security: property package.access new value sun.,com.sun.xml.internal.ws.,com.sun.xml.internal.bind.,com.sun.imageio.,com.sun.javaws,com.sun.deploy,com.sun.jnlp,org.mozilla.jss
security: property package.definition value com.sun.javaws,com.sun.deploy,com.sun.jnlp
security: property package.definition new value com.sun.javaws,com.sun.deploy,com.sun.jnlp,org.mozilla.jss
basic: Added progress listener: [email protected]
basic: Plugin2ClassLoader.addURL parent called for file:/E:/Java/eclipse/MyApplet/myjar.jar
network: Cache entry not found [url: file:/E:/Java/eclipse/MyApplet/myjar.jar, version: null]
network: Cache entry not found [url: file:/E:/Java/eclipse/MyApplet/myjar.jar, version: null]
basic: Applet loaded.
basic: Applet resized and added to parent container
basic: PERF: AppletExecutionRunnable - applet.init() BEGIN ; jvmLaunch dt 145396 us, pluginInit dt 331540 us, TotalTime: 476936 us
init ok
basic: Applet initialized
basic: Removed progress listener: [email protected]
basic: Applet made visible
basic: Starting applet
basic: completed perf rollup
s parent:sun.plugin2.main.client.PluginEmbeddedFrame[frame0,0,0,600x400,invalid,layout=java.awt.BorderLayout,title=,resizable,normal]
s disp:true
s showing:true
basic: Applet started
basic: Told clients applet is started

Update

Thanks to Ates, trying the following timeout makes the Applet appear correctly 100% of the time.

function opentest(){
  applet=window.open('', '', "height=420,width=620");
  setTimeout(function () {
    applet.document.write( ... ); } ,
    1000 );
}

  • As Ates mentions, we now see that our popup window doesn't like immediate document.writes!
  • Is this correct behaviour? Am I supposed to wait for some signal before writing to a document?
  • Should I be going about this a different way? Can I add some kind of listener to know when it is safe to call document.write()?

applet = window.open('', '', "height=420,width=620");
applet.document.write(...

This could be where your race condition starts. You may be trying to change the document of the newly opened window without the window being properly initialized. A quick thing to try is to let the currently running JavaScript thread "breathe", by deferring the rest of the code to a dummy timeout that will run asynchronously:

applet = window.open('', '', "height=420,width=620");
setTimeout(function () {
    applet.document.write(...
}, 0);

This is not necessarily the best way to resolve this issue, but it is a quick thing to try to see if this is in fact the source of the race condition.