diff options
author | Jiri Vanek <[email protected]> | 2012-11-02 12:22:09 +0100 |
---|---|---|
committer | Jiri Vanek <[email protected]> | 2012-11-02 12:22:09 +0100 |
commit | 489f58fa0aa123f73f9903180691ac4531d1d989 (patch) | |
tree | 3ca320545e62c6463dd94b962aff134d4c00aab1 | |
parent | 70681430e560a92c59175e7894ccc7820b33ee71 (diff) |
Splashscreen integrated to javaws and plugin
-rw-r--r-- | ChangeLog | 37 | ||||
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | launcher/javaws.in | 12 | ||||
-rw-r--r-- | netx/javaws_splash.png | bin | 0 -> 12142 bytes | |||
-rw-r--r-- | netx/net/sourceforge/jnlp/GuiLaunchHandler.java | 63 | ||||
-rw-r--r-- | netx/net/sourceforge/jnlp/JNLPSplashScreen.java | 107 | ||||
-rw-r--r-- | netx/net/sourceforge/jnlp/Launcher.java | 75 | ||||
-rw-r--r-- | netx/net/sourceforge/jnlp/NetxPanel.java | 36 | ||||
-rw-r--r-- | plugin/icedteanp/java/sun/applet/PluginAppletViewer.java | 181 | ||||
-rw-r--r-- | tests/reproducers/simple/CountingApplet1/resources/ParallelAppletsTest_1_x_2.html | 2 | ||||
-rw-r--r-- | tests/reproducers/simple/simpletest1/resources/netxPlugin.png | bin | 0 -> 47818 bytes |
12 files changed, 416 insertions, 100 deletions
@@ -1,3 +1,40 @@ +2012-11-02 Jiri Vanek <[email protected]> + + Splashscreen integrated to javaws and plugin + * Makefile.am: (edit_launcher_script) added JAVAWS_SPLASH_LOCATION + substitution for installed javaws_splash.png. + (install-exec-loca) added installation of javaws_splash.png. + * NEWS: mentioned splashscreen + * launcher/javaws.in: added SPLASH_LOCATION, as path to image with "java" + splash which s then shown until internal vector one appear. + * netx/net/sourceforge/jnlp/GuiLaunchHandler.java: splashScreen made volatile, + (launchInitialized) splashscreen is created and shown + * netx/net/sourceforge/jnlp/JNLPSplashScreen.java: (setSplashImageURL) + splash bg image is loaded from given url or default is used if not found + or not specified by jnlp/applet. (correctSize) width is calculated from + bg image or default is used when no image set. Splash is centered to + primary monitor. + * netx/net/sourceforge/jnlp/Launcher.java: (launchApplet) and + (launchApplication) enriched by handling of splashs. + (launchError) overloaded and is now handling forwarding of errors to + splash. All relevant calls of launchError enriched by appletInstance. + * netx/net/sourceforge/jnlp/NetxPanel.java: is now implementing + SplashController.This is done by setting and wrapping of splashController + variable. + * plugin/icedteanp/java/sun/applet/PluginAppletViewer.java: is now handling + splashscreen for applets in browsers. + (framePanel) is now providing panel to be processed (PluginAppletViewer) + is now invoking SplashCreator. (replaceSplash) new method which replace + splashscreen with error splashscreen. (removeSplash) new method to remove + splash when loading is done. (update) is added to call paint directly + (SplashCreator) new internal runnable to create splash + * tests/reproducers/simple/CountingApplet1/resources/ParallelAppletsTest_1_x_2.html: + second jar made XslowX to track two FIXME introduced in this patch - + Launcher's createApplet and PluginAppletViewer's framePanel. + * netx/javaws_splash.png: Binary image to be shown before java is launched + * tests/reproducers/simple/simpletest1/resources/netxPlugin.png: Binary image + to ne used for testing custom splashscreens + 2012-10-31 Jana Fabrikova <[email protected]> *tests/reproducers/simple/JSToJGet/testcases/JSToJGetTest.java: diff --git a/Makefile.am b/Makefile.am index 89579c7..563a477 100644 --- a/Makefile.am +++ b/Makefile.am @@ -178,6 +178,7 @@ itweb_settings:= $(shell echo itweb-settings | sed '@program_transform_name@') edit_launcher_script = sed \ -e 's|[@]LAUNCHER_BOOTCLASSPATH[@]|$(LAUNCHER_BOOTCLASSPATH)|g' \ -e 's|[@]JAVAWS_BIN_LOCATION[@]|$(bindir)/$(javaws)|g' \ + -e 's|[@]JAVAWS_SPLASH_LOCATION[@]|$(datadir)/$(PACKAGE_NAME)/javaws_splash.png|g' \ -e 's|[@]ITWEB_SETTINGS_BIN_LOCATION[@]|$(bindir)/$(itweb_settings)|g' \ -e 's|[@]JAVA[@]|$(JAVA)|g' \ -e 's|[@]JRE[@]|$(SYSTEM_JRE_DIR)|g' @@ -208,6 +209,7 @@ if ENABLE_PLUGIN ${INSTALL_DATA} $(abs_top_builddir)/liveconnect/lib/classes.jar $(DESTDIR)$(datadir)/$(PACKAGE_NAME)/plugin.jar endif ${INSTALL_DATA} $(NETX_DIR)/lib/classes.jar $(DESTDIR)$(datadir)/$(PACKAGE_NAME)/netx.jar + ${INSTALL_DATA} $(NETX_SRCDIR)/javaws_splash.png $(DESTDIR)$(datadir)/$(PACKAGE_NAME)/javaws_splash.png ${INSTALL_PROGRAM} launcher.build/$(javaws) $(DESTDIR)$(bindir) ${INSTALL_DATA} extra-lib/about.jar $(DESTDIR)$(datadir)/$(PACKAGE_NAME)/about.jar ${INSTALL_PROGRAM} launcher.build/$(itweb_settings) $(DESTDIR)$(bindir) @@ -9,6 +9,7 @@ GX - http://bugs.gentoo.org/show_bug.cgi?id=X CVE-XXXX-YYYY: http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=XXXX-YYYY New in release 1.4 (2012-XX-XX): +* Splash screen for javaws and plugin * Security updates - CVE-2012-3422, RH840592: Potential read from an uninitialized memory location - CVE-2012-3423, RH841345: Incorrect handling of not 0-terminated strings diff --git a/launcher/javaws.in b/launcher/javaws.in index e0e0fca..ae9a24d 100644 --- a/launcher/javaws.in +++ b/launcher/javaws.in @@ -5,6 +5,7 @@ LAUNCHER_BOOTCLASSPATH=@LAUNCHER_BOOTCLASSPATH@ LAUNCHER_FLAGS=-Xms8m CLASSNAME=net.sourceforge.jnlp.runtime.Boot BINARY_LOCATION=@JAVAWS_BIN_LOCATION@ +SPLASH_LOCATION=@JAVAWS_SPLASH_LOCATION@ PROGRAM_NAME=javaws CP=@JRE@/lib/rt.jar @@ -15,6 +16,10 @@ COMMAND=() i=0 j=0 +SPLASH="false" +if [ "x$ICEDTEA_WEB_SPLASH" = "x" ] ; then +SPLASH="true" +fi; while [ "$#" -gt "0" ]; do case "$1" in -J*) @@ -24,6 +29,9 @@ while [ "$#" -gt "0" ]; do *) ARGS[$j]="$1" j=$((j+1)) + if [ "$1" = "-headless" ] ; then + SPLASH="false" + fi ;; esac shift @@ -32,6 +40,10 @@ done k=0 COMMAND[k]="${JAVA}" k=$((k+1)) +if [ "$SPLASH" = "true" ] ; then +COMMAND[k]="-splash:${SPLASH_LOCATION}" +k=$((k+1)) +fi; COMMAND[k]="${LAUNCHER_BOOTCLASSPATH}" k=$((k+1)) COMMAND[k]="${LAUNCHER_FLAGS}" diff --git a/netx/javaws_splash.png b/netx/javaws_splash.png Binary files differnew file mode 100644 index 0000000..62111e9 --- /dev/null +++ b/netx/javaws_splash.png diff --git a/netx/net/sourceforge/jnlp/GuiLaunchHandler.java b/netx/net/sourceforge/jnlp/GuiLaunchHandler.java index ad8ba96..74960f0 100644 --- a/netx/net/sourceforge/jnlp/GuiLaunchHandler.java +++ b/netx/net/sourceforge/jnlp/GuiLaunchHandler.java @@ -1,5 +1,5 @@ /* GuiLaunchHandler.java - Copyright (C) 2011 Red Hat, Inc. + Copyright (C) 2012 Red Hat, Inc. This file is part of IcedTea. @@ -54,7 +54,7 @@ import net.sourceforge.jnlp.util.BasicExceptionDialog; */ public class GuiLaunchHandler extends AbstractLaunchHandler { - private JNLPSplashScreen splashScreen = null; + private volatile JNLPSplashScreen splashScreen = null; private final Object mutex = new Object(); private UpdatePolicy policy = UpdatePolicy.ALWAYS; @@ -80,10 +80,11 @@ public class GuiLaunchHandler extends AbstractLaunchHandler { } private void closeSplashScreen() { - synchronized(mutex) { + synchronized (mutex) { if (splashScreen != null) { if (splashScreen.isSplashScreenValid()) { splashScreen.setVisible(false); + splashScreen.stopAnimation(); } splashScreen.dispose(); } @@ -102,40 +103,56 @@ public class GuiLaunchHandler extends AbstractLaunchHandler { @Override public void launchInitialized(final JNLPFile file) { - + int preferredWidth = 500; int preferredHeight = 400; final URL splashImageURL = file.getInformation().getIconLocation( IconDesc.SPLASH, preferredWidth, preferredHeight); + final ResourceTracker resourceTracker = new ResourceTracker(true); if (splashImageURL != null) { - final ResourceTracker resourceTracker = new ResourceTracker(true); resourceTracker.addResource(splashImageURL, file.getFileVersion(), null, policy); - synchronized(mutex) { - try { - SwingUtilities.invokeAndWait(new Runnable() { - @Override - public void run() { - splashScreen = new JNLPSplashScreen(resourceTracker, file); - } - }); - } catch (InterruptedException ie) { - // Wait till splash screen is created - while (splashScreen == null); - } catch (InvocationTargetException ite) { - ite.printStackTrace(); - } + } + synchronized (mutex) { + try { + SwingUtilities.invokeAndWait(new Runnable() { + + @Override + public void run() { + splashScreen = new JNLPSplashScreen(resourceTracker, file); + } + }); + } catch (InterruptedException ie) { + // Wait till splash screen is created + while (splashScreen == null); + } catch (InvocationTargetException ite) { + ite.printStackTrace(); + } + try { + SwingUtilities.invokeAndWait(new Runnable() { - splashScreen.setSplashImageURL(splashImageURL); + @Override + public void run() { + splashScreen.setSplashImageURL(splashImageURL); + } + }); + } catch (InterruptedException ie) { + // Wait till splash screen is created + while (!splashScreen.isSplashImageLoaded()); + } catch (InvocationTargetException ite) { + ite.printStackTrace(); } + + } - + SwingUtilities.invokeLater(new Runnable() { + @Override public void run() { - if (splashImageURL != null) { - synchronized(mutex) { + if (splashScreen != null) { + synchronized (mutex) { if (splashScreen.isSplashScreenValid()) { splashScreen.setVisible(true); } diff --git a/netx/net/sourceforge/jnlp/JNLPSplashScreen.java b/netx/net/sourceforge/jnlp/JNLPSplashScreen.java index 212696a..77698db 100644 --- a/netx/net/sourceforge/jnlp/JNLPSplashScreen.java +++ b/netx/net/sourceforge/jnlp/JNLPSplashScreen.java @@ -43,19 +43,16 @@ import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Image; import java.awt.Insets; -import java.awt.Toolkit; import java.io.IOException; import java.net.URL; - import javax.imageio.ImageIO; import javax.swing.JDialog; - import net.sourceforge.jnlp.cache.ResourceTracker; import net.sourceforge.jnlp.runtime.JNLPRuntime; -import net.sourceforge.jnlp.util.ImageResources; import net.sourceforge.jnlp.splashscreen.SplashPanel; import net.sourceforge.jnlp.splashscreen.SplashUtils; import net.sourceforge.jnlp.splashscreen.parts.InformationElement; +import net.sourceforge.jnlp.util.ImageResources; public class JNLPSplashScreen extends JDialog { @@ -68,6 +65,7 @@ public class JNLPSplashScreen extends JDialog { public static final int DEF_WIDTH=635; public static final int DEF_HEIGHT=480; private SplashPanel componetSplash; + private boolean splashImageLoaded=false; public JNLPSplashScreen(ResourceTracker resourceTracker, final JNLPFile file) { @@ -78,61 +76,86 @@ public class JNLPSplashScreen extends JDialog { // JNLP file. this.resourceTracker = resourceTracker; - - this.file=file; + this.file=file; } public void setSplashImageURL(URL url) { - splashImageUrl = url; - splashImage = null; + splashImageLoaded = false; try { - splashImage = ImageIO.read(resourceTracker - .getCacheFile(splashImageUrl)); - if (splashImage == null) { - if (JNLPRuntime.isDebug()) { - System.err.println("Error loading splash image: " + url); + if (url != null) { + splashImageUrl = url; + splashImage = null; + try { + splashImage = ImageIO.read(resourceTracker.getCacheFile(splashImageUrl)); + if (splashImage == null) { + if (JNLPRuntime.isDebug()) { + System.err.println("Error loading splash image: " + url); + } + } + } catch (IOException e) { + if (JNLPRuntime.isDebug()) { + System.err.println("Error loading splash image: " + url); + } + splashImage = null; + } catch (IllegalArgumentException argumentException) { + if (JNLPRuntime.isDebug()) { + System.err.println("Error loading splash image: " + url); + } + splashImage = null; } - return; } - } catch (IOException e) { - if (JNLPRuntime.isDebug()) { - System.err.println("Error loading splash image: " + url); - } - splashImage = null; - return; - } catch (IllegalArgumentException argumentException) { - if (JNLPRuntime.isDebug()) { - System.err.println("Error loading splash image: " + url); + + if (splashImage == null) { + this.setLayout(new BorderLayout()); + SplashPanel splash = SplashUtils.getSplashScreen(DEF_WIDTH, DEF_HEIGHT); + if (splash != null) { + splash.startAnimation(); + splash.setInformationElement(InformationElement.createFromJNLP(file)); + this.add(splash.getSplashComponent()); + this.componetSplash = splash; + } } - splashImage = null; - return; + correctSize(); + } finally { + splashImageLoaded = true; } + } - correctSize(); + public boolean isSplashImageLoaded() { + return splashImageLoaded; } + public boolean isSplashScreenValid() { - return (splashImage != null); + return (splashImage != null) || (componetSplash != null); } private void correctSize() { - - Insets insets = getInsets(); - int minimumWidth = splashImage.getWidth(null) + insets.left - + insets.right; - int minimumHeight = splashImage.getHeight(null) + insets.top - + insets.bottom; - setMinimumSize(new Dimension(minimumWidth, minimumHeight)); - - Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); - setLocation((screenSize.width - minimumWidth) / 2, - (screenSize.height - minimumHeight) / 2); + int minimumWidth = DEF_WIDTH; + int minimumHeight = DEF_HEIGHT; + if (splashImage != null) { + Insets insets = getInsets(); + minimumWidth = splashImage.getWidth(null) + insets.left + + insets.right; + minimumHeight = splashImage.getHeight(null) + insets.top + + insets.bottom; + } + setMinimumSize(new Dimension(0, 0)); + setMaximumSize(new Dimension(Integer.MAX_VALUE, Integer.MAX_VALUE)); + setSize(new Dimension(minimumWidth, minimumHeight)); + setPreferredSize(new Dimension(minimumWidth, minimumHeight)); + // Centering to middle of Toolkit.getDefaultToolkit().getScreenSize() + // centers to the middle of all monitors. Let's center to the middle + // of the primary monitor instead. + // TODO center on the 'current' monitor to meet user expectation + setLocationRelativeTo(null); } @Override public void paint(Graphics g) { if (splashImage == null) { + super.paint(g); return; } @@ -141,4 +164,12 @@ public class JNLPSplashScreen extends JDialog { g2.drawImage(splashImage, getInsets().left, getInsets().top, null); } + + public boolean isCustomSplashscreen() { + return (componetSplash!=null); + } + + public void stopAnimation() { + if (isCustomSplashscreen()) componetSplash.stopAnimation(); + } } diff --git a/netx/net/sourceforge/jnlp/Launcher.java b/netx/net/sourceforge/jnlp/Launcher.java index 1692b0e..c6712cd 100644 --- a/netx/net/sourceforge/jnlp/Launcher.java +++ b/netx/net/sourceforge/jnlp/Launcher.java @@ -20,6 +20,7 @@ import static net.sourceforge.jnlp.runtime.Translator.R; import java.applet.Applet; import java.awt.Container; +import java.awt.SplashScreen; import java.io.File; import java.lang.reflect.Method; import java.net.InetAddress; @@ -42,6 +43,8 @@ import net.sourceforge.jnlp.services.ServiceUtil; import javax.swing.SwingUtilities; import javax.swing.text.html.parser.ParserDelegator; +import net.sourceforge.jnlp.runtime.AppletEnvironment; +import net.sourceforge.jnlp.splashscreen.SplashUtils; import sun.awt.SunToolkit; @@ -543,6 +546,12 @@ public class Launcher { } if (JNLPRuntime.getForksAllowed() && file.needsNewVM()) { + if (!JNLPRuntime.isHeadless()){ + SplashScreen sp = SplashScreen.getSplashScreen(); + if (sp!=null) { + sp.close(); + } + } List<String> netxArguments = new LinkedList<String>(); netxArguments.add("-Xnofork"); netxArguments.addAll(JNLPRuntime.getInitialArguments()); @@ -652,25 +661,42 @@ public class Launcher { * @param enableCodeBase whether to add the codebase URL to the classloader */ protected ApplicationInstance launchApplet(JNLPFile file, boolean enableCodeBase, Container cont) throws LaunchException { - if (!file.isApplet()) + if (!file.isApplet()) { throw launchError(new LaunchException(file, null, R("LSFatal"), R("LCClient"), R("LNotApplet"), R("LNotAppletInfo"))); - + } + + if (JNLPRuntime.getForksAllowed() && file.needsNewVM()) { + if (!JNLPRuntime.isHeadless()) { + SplashScreen sp = SplashScreen.getSplashScreen(); + if (sp != null) { + sp.close(); + } + } + } + if (handler != null) { + handler.launchInitialized(file); + } + + AppletInstance applet = null; try { ServiceUtil.checkExistingSingleInstance(file); - AppletInstance applet = createApplet(file, enableCodeBase, cont); + applet = createApplet(file, enableCodeBase, cont); applet.initialize(); - applet.getAppletEnvironment().startApplet(); // this should be a direct call to applet instance return applet; } catch (InstanceExistsException ieex) { if (JNLPRuntime.isDebug()) { System.out.println("Single instance applet is already running."); } - throw launchError(new LaunchException(file, ieex, R("LSFatal"), R("LCLaunching"), R("LCouldNotLaunch"), R("LSingleInstanceExists"))); + throw launchError(new LaunchException(file, ieex, R("LSFatal"), R("LCLaunching"), R("LCouldNotLaunch"), R("LSingleInstanceExists")), applet); } catch (LaunchException lex) { - throw launchError(lex); + throw launchError(lex, applet); } catch (Exception ex) { - throw launchError(new LaunchException(file, ex, R("LSFatal"), R("LCLaunching"), R("LCouldNotLaunch"), R("LCouldNotLaunchInfo"))); + throw launchError(new LaunchException(file, ex, R("LSFatal"), R("LCLaunching"), R("LCouldNotLaunch"), R("LCouldNotLaunchInfo")), applet); + }finally{ + if (handler != null) { + handler.launchStarting(applet); + } } } @@ -678,13 +704,13 @@ public class Launcher { * Gets an ApplicationInstance, but does not launch the applet. */ protected ApplicationInstance getApplet(JNLPFile file, boolean enableCodeBase, Container cont) throws LaunchException { - if (!file.isApplet()) + if (!file.isApplet()) { throw launchError(new LaunchException(file, null, R("LSFatal"), R("LCClient"), R("LNotApplet"), R("LNotAppletInfo"))); - + } + AppletInstance applet = null; try { ServiceUtil.checkExistingSingleInstance(file); - - AppletInstance applet = createApplet(file, enableCodeBase, cont); + applet = createApplet(file, enableCodeBase, cont); applet.initialize(); return applet; @@ -692,11 +718,11 @@ public class Launcher { if (JNLPRuntime.isDebug()) { System.out.println("Single instance applet is already running."); } - throw launchError(new LaunchException(file, ieex, R("LSFatal"), R("LCLaunching"), R("LCouldNotLaunch"), R("LSingleInstanceExists"))); + throw launchError(new LaunchException(file, ieex, R("LSFatal"), R("LCLaunching"), R("LCouldNotLaunch"), R("LSingleInstanceExists")), applet); } catch (LaunchException lex) { - throw launchError(lex); + throw launchError(lex, applet); } catch (Exception ex) { - throw launchError(new LaunchException(file, ex, R("LSFatal"), R("LCLaunching"), R("LCouldNotLaunch"), R("LCouldNotLaunchInfo"))); + throw launchError(new LaunchException(file, ex, R("LSFatal"), R("LCLaunching"), R("LCouldNotLaunch"), R("LCouldNotLaunchInfo")), applet); } } @@ -715,8 +741,13 @@ public class Launcher { * * @param enableCodeBase whether to add the code base URL to the classloader */ - protected AppletInstance createApplet(JNLPFile file, boolean enableCodeBase, Container cont) throws LaunchException { - try { + //FIXME - when multiple applets are on one page, this method is visited simultaneously + //and then appelts creates in little bit strange manner. This issue is visible with + //randomly showing/notshowing spalshscreens. + //See also PluginAppletViewer.framePanel + protected AppletInstance createApplet(JNLPFile file, boolean enableCodeBase, Container cont) throws LaunchException { + AppletInstance appletInstance = null; + try { JNLPClassLoader loader = JNLPClassLoader.getInstance(file, updatePolicy); if (enableCodeBase) { @@ -730,7 +761,6 @@ public class Launcher { // appletInstance is needed by ServiceManager when looking up // services. This could potentially be done in applet constructor // so initialize appletInstance before creating applet. - AppletInstance appletInstance; if (cont == null) appletInstance = new AppletInstance(file, group, loader, null); else @@ -751,7 +781,7 @@ public class Launcher { return appletInstance; } catch (Exception ex) { - throw launchError(new LaunchException(file, ex, R("LSFatal"), R("LCInit"), R("LInitApplet"), R("LInitAppletInfo"))); + throw launchError(new LaunchException(file, ex, R("LSFatal"), R("LCInit"), R("LInitApplet"), R("LInitAppletInfo")), appletInstance); } } @@ -822,6 +852,13 @@ public class Launcher { * caller. */ private LaunchException launchError(LaunchException ex) { + return launchError(ex, null); + } + + private LaunchException launchError(LaunchException ex, AppletInstance applet) { + if (applet != null) { + SplashUtils.showErrorCaught(ex, applet); + } if (handler != null) handler.launchError(ex); @@ -861,7 +898,7 @@ public class Launcher { new ParserDelegator(); } - /** + /** * This runnable is used to call the appropriate launch method * for the application, applet, or installer in its thread group. */ diff --git a/netx/net/sourceforge/jnlp/NetxPanel.java b/netx/net/sourceforge/jnlp/NetxPanel.java index 59c3ce0..f6496b6 100644 --- a/netx/net/sourceforge/jnlp/NetxPanel.java +++ b/netx/net/sourceforge/jnlp/NetxPanel.java @@ -1,5 +1,5 @@ /* - * Copyright 2007 Red Hat, Inc. + * Copyright 2012 Red Hat, Inc. * This file is part of IcedTea, http://icedtea.classpath.org * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -22,7 +22,6 @@ package net.sourceforge.jnlp; -import net.sourceforge.jnlp.AppletLog; import net.sourceforge.jnlp.runtime.AppletInstance; import net.sourceforge.jnlp.runtime.JNLPRuntime; @@ -32,6 +31,8 @@ import java.util.Hashtable; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import net.sourceforge.jnlp.splashscreen.SplashController; +import net.sourceforge.jnlp.splashscreen.SplashPanel; import sun.applet.AppletViewerPanel; import sun.awt.SunToolkit; @@ -42,10 +43,11 @@ import sun.awt.SunToolkit; * * @author Francis Kung <[email protected]> */ -public class NetxPanel extends AppletViewerPanel { +public class NetxPanel extends AppletViewerPanel implements SplashController { private PluginBridge bridge = null; private boolean exitOnFailure = true; private AppletInstance appInst = null; + private SplashController splashController; private boolean appletAlive; private final String uKey; @@ -232,4 +234,32 @@ public class NetxPanel extends AppletViewerPanel { SunToolkit.createNewAppContext(); } } + + + + + public void setAppletViewerFrame(SplashController framePanel) { + splashController=framePanel; + } + + @Override + public void removeSplash() { + splashController.removeSplash(); + } + + @Override + public void replaceSplash(SplashPanel r) { + splashController.replaceSplash(r); + } + + @Override + public int getSplashWidth() { + return splashController.getSplashWidth(); + } + + @Override + public int getSplashHeigth() { + return splashController.getSplashHeigth(); + } + } diff --git a/plugin/icedteanp/java/sun/applet/PluginAppletViewer.java b/plugin/icedteanp/java/sun/applet/PluginAppletViewer.java index b901074..974c2e4 100644 --- a/plugin/icedteanp/java/sun/applet/PluginAppletViewer.java +++ b/plugin/icedteanp/java/sun/applet/PluginAppletViewer.java @@ -76,6 +76,7 @@ import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import java.awt.print.PageFormat; import java.awt.print.Printable; +import java.awt.Component; import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; @@ -93,10 +94,8 @@ import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; import java.util.Enumeration; import java.util.HashMap; -import java.util.Hashtable; import java.util.Iterator; import java.util.Map; -import java.util.Vector; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -115,6 +114,11 @@ import sun.awt.X11.XEmbeddedFrame; import sun.misc.Ref; import com.sun.jndi.toolkit.url.UrlUtil; +import java.util.Hashtable; +import java.util.Vector; +import net.sourceforge.jnlp.splashscreen.SplashController; +import net.sourceforge.jnlp.splashscreen.SplashPanel; +import net.sourceforge.jnlp.splashscreen.SplashUtils; /** * Lets us construct one using unix-style one shot behaviors @@ -141,11 +145,15 @@ class PluginAppletPanelFactory { // isn't the case, the awt eventqueue thread's context classloader // won't be set to a JNLPClassLoader, and when an applet class needs // to be loaded from the awt eventqueue, it won't be found. + final int width = Integer.parseInt(atts.get("width")); + final int height = Integer.parseInt(atts.get("height")); Thread panelInit = new Thread(panel.getThreadGroup(), new Runnable() { @Override public void run() { panel.createNewAppContext(); // create the frame. - PluginAppletViewer.framePanel(identifier, handle, panel); + PluginDebug.debug("X and Y are: " + width + " " + height); + panel.setAppletViewerFrame(PluginAppletViewer.framePanel(identifier,handle, width, height, panel)); + panel.init(); // Start the applet initEventQueue(panel); @@ -185,7 +193,7 @@ class PluginAppletPanelFactory { try { SwingUtilities.invokeAndWait(new Runnable() { public void run() { - panel.getParent().setSize(Integer.valueOf(atts.get("width")), Integer.valueOf(atts.get("height"))); + panel.getParent().setSize(width, height); } }); } catch (InvocationTargetException ite) { @@ -198,6 +206,8 @@ class PluginAppletPanelFactory { ie.printStackTrace(); } + panel.removeSplash(); + AppletSecurityContextManager.getSecurityContext(0).associateSrc(panel.getAppletClassLoader(), doc); AppletSecurityContextManager.getSecurityContext(0).associateInstance(identifier, panel.getAppletClassLoader()); @@ -271,7 +281,7 @@ class PluginAppletPanelFactory { // FIXME: declare JSProxy implementation @SuppressWarnings("serial") public class PluginAppletViewer extends XEmbeddedFrame - implements AppletContext, Printable { + implements AppletContext, Printable, SplashController { /** * Enumerates the current status of an applet @@ -323,26 +333,36 @@ public class PluginAppletViewer extends XEmbeddedFrame private Image bufFrameImg; private Graphics bufFrameImgGraphics; + + private SplashPanel splashPanel; + /** * Null constructor to allow instantiation via newInstance() */ public PluginAppletViewer() { } - public static void framePanel(int identifier, long handle, NetxPanel panel) { + //FIXME - when multiple applets are on one page, this method is visited simultaneously + //and then appelts creates in little bit strange manner. This issue is visible with + //randomly showing/notshowing spalshscreens. + //See also Launcher.createApplet + public static PluginAppletViewer framePanel(int identifier,long handle, int width, int height, NetxPanel panel) { PluginDebug.debug("Framing ", panel); - - // SecurityManager MUST be set, and only privileged code may call reFrame() + + // SecurityManager MUST be set, and only privileged code may call framePanel() System.getSecurityManager().checkPermission(new AllPermission()); PluginAppletViewer appletFrame = new PluginAppletViewer(handle, identifier, panel); - - appletFrame.add("Center", panel); - appletFrame.pack(); - + appletFrame.appletEventListener = new AppletEventListener(appletFrame, appletFrame); panel.addAppletListener(appletFrame.appletEventListener); + // Clear references, if any + if (applets.containsKey(identifier)) { + PluginAppletViewer oldFrame = applets.get(identifier); + oldFrame.remove(panel); + panel.removeAppletListener(oldFrame.appletEventListener); + } appletsLock.lock(); applets.put(identifier, appletFrame); @@ -350,6 +370,7 @@ public class PluginAppletViewer extends XEmbeddedFrame appletsLock.unlock(); PluginDebug.debug(panel, " framed"); + return appletFrame; } /** @@ -383,9 +404,88 @@ public class PluginAppletViewer extends XEmbeddedFrame }; addWindowListener(windowEventListener); + final AppletPanel fPanel = panel; + try { + SwingUtilities.invokeAndWait(new SplashCreator(fPanel)); + } catch (Exception e) { + e.printStackTrace(); // Not much we can do other than print + } + + } + + public void replaceSplash(final SplashPanel newSplash) { + if (splashPanel == null) { + return; + } + if (newSplash == null) { + removeSplash(); + return; + } + try { + SwingUtilities.invokeAndWait(new Runnable() { + + public void run() { + splashPanel.getSplashComponent().setVisible(false); + splashPanel.stopAnimation(); + remove(splashPanel.getSplashComponent()); + newSplash.setPercentage(splashPanel.getPercentage()); + newSplash.setSplashWidth(splashPanel.getSplashWidth()); + newSplash.setSplashHeight(splashPanel.getSplashHeight()); + newSplash.adjustForSize(); + splashPanel = newSplash; + add("Center", splashPanel.getSplashComponent()); + pack(); + } + }); + } catch (Exception e) { + e.printStackTrace(); // Not much we can do other than print + } + } + + @Override + public void removeSplash() { + if (splashPanel == null) { + return; + } + try { + SwingUtilities.invokeAndWait(new Runnable() { + + public void run() { + splashPanel.getSplashComponent().setVisible(false); + splashPanel.stopAnimation(); + remove(splashPanel.getSplashComponent()); + splashPanel = null; + remove(panel); + // Re-add the applet to notify container + add(panel); + panel.setVisible(true); + pack(); + } + }); + } catch (Exception e) { + e.printStackTrace(); // Not much we can do other than print + } + } + @Override + public int getSplashWidth() { + if (splashPanel != null) { + return splashPanel.getSplashWidth(); + } else { + return -1; + } } + @Override + public int getSplashHeigth() { + if (splashPanel != null) { + return splashPanel.getSplashHeight(); + } else { + return -1; + } + } + + private static class AppletEventListener implements AppletListener { final Frame frame; final PluginAppletViewer appletViewer; @@ -401,7 +501,6 @@ public class PluginAppletViewer extends XEmbeddedFrame panelLock.lock(); panelLive.signalAll(); panelLock.unlock(); - switch (evt.getID()) { case AppletPanel.APPLET_RESIZE: { if (src != null) { @@ -436,6 +535,23 @@ public class PluginAppletViewer extends XEmbeddedFrame break; } + case AppletPanel.APPLET_START: { + if (src.status != AppletPanel.APPLET_INIT && src.status != AppletPanel.APPLET_STOP) { + String s="Applet started, but but reached invalid state"; + PluginDebug.debug(s); + SplashPanel sp=SplashUtils.getErrorSplashScreen(appletViewer.panel.getWidth(), appletViewer.panel.getHeight(), new Exception(s)); + appletViewer.replaceSplash(sp); + } + + break; + } + case AppletPanel.APPLET_ERROR: { + String s="Undefined error causing applet not to staart appeared"; + PluginDebug.debug(s); + SplashPanel sp=SplashUtils.getErrorSplashScreen(appletViewer.panel.getWidth(), appletViewer.panel.getHeight(), new Exception(s)); + appletViewer.replaceSplash(sp); + break; + } } } } @@ -517,6 +633,8 @@ public class PluginAppletViewer extends XEmbeddedFrame waitForAppletInit(applets.get(identifier).panel); // Should we proceed with reframing? + PluginDebug.debug("Init complete"); + if (updateStatus(identifier, PAV_INIT_STATUS.REFRAME_COMPLETE).equals(PAV_INIT_STATUS.INACTIVE)) { destroyApplet(identifier); return; @@ -656,6 +774,8 @@ public class PluginAppletViewer extends XEmbeddedFrame */ public static void waitForAppletInit(NetxPanel panel) { + PluginDebug.debug("Waiting for applet init"); + // Wait till initialization finishes long maxTimeToSleep = APPLET_TIMEOUT; @@ -2103,7 +2223,7 @@ public class PluginAppletViewer extends XEmbeddedFrame * the parent class's update() just does a couple of checks (both of * which are accounted for) and then calls paint anyway. */ - public void update(Graphics g) { + public void paint(Graphics g) { // If the image or the graphics don't exist, create new ones if (bufFrameImg == null || bufFrameImgGraphics == null) { @@ -2112,12 +2232,20 @@ public class PluginAppletViewer extends XEmbeddedFrame } // Paint off-screen - paint(bufFrameImgGraphics); + for (Component c: this.getComponents()) { + c.paint(bufFrameImgGraphics); + } // Draw the painted image g.drawImage(bufFrameImg, 0, 0, this); } - + + + @Override + public void update(Graphics g) { + paint(g); + } + /** * Waits on a given condition queue until timeout. * @@ -2151,4 +2279,25 @@ public class PluginAppletViewer extends XEmbeddedFrame // Return the difference return System.nanoTime() - sleepStart; } + + private class SplashCreator implements Runnable { + + private final AppletPanel fPanel; + + public SplashCreator(AppletPanel fPanel) { + this.fPanel = fPanel; + } + + public void run() { + add("Center", fPanel); + fPanel.setVisible(false); + splashPanel = SplashUtils.getSplashScreen(fPanel.getWidth(), fPanel.getHeight()); + if (splashPanel != null) { + splashPanel.startAnimation(); + PluginDebug.debug("Added splash " + splashPanel); + add("Center", splashPanel.getSplashComponent()); + } + pack(); + } + } } diff --git a/tests/reproducers/simple/CountingApplet1/resources/ParallelAppletsTest_1_x_2.html b/tests/reproducers/simple/CountingApplet1/resources/ParallelAppletsTest_1_x_2.html index 23e06f6..7c0a6dd 100644 --- a/tests/reproducers/simple/CountingApplet1/resources/ParallelAppletsTest_1_x_2.html +++ b/tests/reproducers/simple/CountingApplet1/resources/ParallelAppletsTest_1_x_2.html @@ -36,7 +36,7 @@ exception statement from your version. --> <html><head></head><body bgcolor="blue"> -<p><applet code="CountingApplet1.class" archive="CountingApplet1.jar" codebase="." width="50" height="100"> +<p><applet code="CountingApplet1.class" archive="XslowXCountingApplet1.jar" codebase="." width="50" height="100"> </applet></p> <p><applet code="CountingApplet2.class" archive="CountingApplet2.jar" codebase="." width="100" height="50"> </applet></p> diff --git a/tests/reproducers/simple/simpletest1/resources/netxPlugin.png b/tests/reproducers/simple/simpletest1/resources/netxPlugin.png Binary files differnew file mode 100644 index 0000000..e05a856 --- /dev/null +++ b/tests/reproducers/simple/simpletest1/resources/netxPlugin.png |