[rfc][icedtea-web] PR1271, Handle 'javascript:' urls, with tests

Jiri Vanek jvanek at redhat.com
Tue Sep 3 07:53:53 PDT 2013


Moreover ok, except one improvement.

On 08/06/2013 09:51 PM, Adam Domurad wrote:
> This fixes this bug http://icedtea.classpath.org/bugzilla/show_bug.cgi?id=1271
>
> Note the test case sometimes fails if the fix from '[rfc][icedtea-web] Fix NPE on Applet launch due to missing AppletStub' is not applied.
>
> ChangeLog:
>
> 2013-XX-XX  Adam Domurad <adomurad at redhat.com>
>          * plugin/icedteanp/java/sun/applet/PluginAppletViewer.java: Evaluate
>          javascript when it shows up in a 'showDocument' call.
>          * plugin/icedteanp/java/sun/applet/PluginMain.java: Install arbitrary
>          'javascript:' protocol handler.
>          * tests/rproducers/simple/JavascriptURLProtocol/resources/JavascriptProtocol.html:
>          Tests if javascript is run from a test applet using showDocument.
>          * tests/reproducers/simple/JavascriptURLProtocol/resources/JavascriptProtocol.js:
>          Same.
>          * tests/reproducers/simple/JavascriptURLProtocol/srcs/JavascriptProtocol.java:
>          Same.
>          * tests/reproducers/simple/JavascriptURLProtocol/testcases/JavascriptProtocolTest.java:
>          Same.
>
> Cheers,
> -Adam
>
>
> JavascriptURLProtocol.patch
>
>
> diff --git a/plugin/icedteanp/java/sun/applet/PluginAppletViewer.java b/plugin/icedteanp/java/sun/applet/PluginAppletViewer.java
> --- a/plugin/icedteanp/java/sun/applet/PluginAppletViewer.java
> +++ b/plugin/icedteanp/java/sun/applet/PluginAppletViewer.java
> @@ -115,6 +115,7 @@ import net.sourceforge.jnlp.security.app
>   import net.sourceforge.jnlp.splashscreen.SplashController;
>   import net.sourceforge.jnlp.splashscreen.SplashPanel;
>   import net.sourceforge.jnlp.splashscreen.SplashUtils;
> +import netscape.javascript.JSObject;
>   import sun.awt.AppContext;
>   import sun.awt.SunToolkit;
>   import sun.awt.X11.XEmbeddedFrame;
> @@ -903,18 +904,19 @@ public class PluginAppletViewer extends
>           return v.elements();
>       }
>
> -    /**
> -     * Ignore.
> -     */
>       public void showDocument(URL url) {
>           PluginDebug.debug("Showing document...");
>           showDocument(url, "_self");
>       }
>
> -    /**
> -     * Ignore.
> -     */
>       public void showDocument(URL url, String target) {
> +        // If it is a javascript document, eval on current page.
> +        if ("javascript".equals(url.getProtocol())) {
> +            // Snip protocol off string
> +            String evalString = url.toString().substring("javascript:".length());
> +            eval(getWindow(), evalString);
> +            return;
> +        }

This seems to me a bit redundant. I would rather see this in handler. See below
>           try {
>               Long reference = getRequestIdentifier();
>               write("reference " + reference +  " LoadURL " + UrlUtil.encode(url.toString(), "UTF-8") + " " + target);
> diff --git a/plugin/icedteanp/java/sun/applet/PluginMain.java b/plugin/icedteanp/java/sun/applet/PluginMain.java
> --- a/plugin/icedteanp/java/sun/applet/PluginMain.java
> +++ b/plugin/icedteanp/java/sun/applet/PluginMain.java
> @@ -66,11 +66,15 @@ import java.io.File;
>   import java.io.FileInputStream;
>   import java.io.FileOutputStream;
>   import java.io.IOException;
> +import java.lang.reflect.Field;
>   import java.net.Authenticator;
>   import java.net.CookieHandler;
>   import java.net.CookieManager;
>   import java.net.ProxySelector;
> +import java.net.URL;
> +import java.net.URLStreamHandler;
>   import java.util.Enumeration;
> +import java.util.Hashtable;
>   import java.util.Properties;
>   import sun.awt.AppContext;
>   import sun.awt.SunToolkit;
> @@ -91,6 +95,24 @@ public class PluginMain {
>       // on whether the property that uses it is necessary/standard.
>       private static final String theVersion = System.getProperty("java.version");
>
> +    /* Install a handler directly using reflection. This ensures that java doesn't error-out
> +     * when javascript is used in a URL. We can then handle these URLs correctly in eg PluginAppletViewer.showDocument().
> +     */
> +    static private void installDummyJavascriptProtocolHandler() {
> +        try {
> +            Field handlersField = URL.class.getDeclaredField("handlers");
> +            handlersField.setAccessible(true);
> +
> +            @SuppressWarnings("unchecked")
> +            Hashtable<String, URLStreamHandler>  handlers = (Hashtable<String,URLStreamHandler>)handlersField.get(null);
> +
> +            // Place an arbitrary handler, we only need the URL construction to not error-out
> +            handlers.put("javascript", new sun.net.www.protocol.http.Handler());

As we are installing handler here, maybe we can install not-so-dummy one, but extend sun.net.www.protocol.http.Handler to handle the  String evalString = url.toString().substring("javascript:".length()); more "inside"
But maybe it is not (easily) possible.


> +        } catch (Exception e) {
> +            PluginDebug.debug("Unable to install 'javascript:' URL protocol handler!");
> +        }
> +    }
> +
>       /**
>        * The main entry point into AppletViewer.
>        */
> @@ -99,6 +121,8 @@ public class PluginMain {
>           if (AppContext.getAppContext() == null) {
>               SunToolkit.createNewAppContext();
>           }
> +        installDummyJavascriptProtocolHandler();
> +
>           if (args.length != 2 || !(new File(args[0]).exists()) || !(new File(args[1]).exists())) {
>               System.err.println("Invalid pipe names provided. Refusing to proceed.");
>               System.exit(1);
> diff --git a/tests/reproducers/simple/JavascriptURLProtocol/resources/JavascriptProtocol.html b/tests/reproducers/simple/JavascriptURLProtocol/resources/JavascriptProtocol.html
> new file mode 100644
> --- /dev/null
> +++ b/tests/reproducers/simple/JavascriptURLProtocol/resources/JavascriptProtocol.html
> @@ -0,0 +1,50 @@
> +<!--
> +
> +This file is part of IcedTea.
> +
> +IcedTea is free software; you can redistribute it and/or modify
> +it under the terms of the GNU General Public License as published by
> +the Free Software Foundation; either version 2, or (at your option)
> +any later version.
> +
> +IcedTea is distributed in the hope that it will be useful, but
> +WITHOUT ANY WARRANTY; without even the implied warranty of
> +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +General Public License for more details.
> +
> +You should have received a copy of the GNU General Public License
> +along with IcedTea; see the file COPYING.  If not, write to the
> +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
> +02110-1301 USA.
> +
> +Linking this library statically or dynamically with other modules is
> +making a combined work based on this library.  Thus, the terms and
> +conditions of the GNU General Public License cover the whole
> +combination.
> +
> +As a special exception, the copyright holders of this library give you
> +permission to link this library with independent modules to produce an
> +executable, regardless of the license terms of these independent
> +modules, and to copy and distribute the resulting executable under
> +terms of your choice, provided that you also meet, for each linked
> +independent module, the terms and conditions of the license of that
> +module.  An independent module is a module which is not derived from
> +or based on this library.  If you modify this library, you may extend
> +this exception to your version of the library, but you are not
> +obligated to do so.  If you do not wish to do so, delete this
> +exception statement from your version.
> +
> + -->
> +<html>
> +<head></head>
> +<body>
> +	<applet
> +		id = "applet"
> +		code = "JavascriptProtocol.class"
> +		archive = "JavascriptURLProtocol.jar">
> +	</applet>
> +<script type = "text/javascript"
> +    	src = "JavascriptProtocol.js">
> +</script>
> +</body>
> +</html>
> diff --git a/tests/reproducers/simple/JavascriptURLProtocol/resources/JavascriptProtocol.js b/tests/reproducers/simple/JavascriptURLProtocol/resources/JavascriptProtocol.js
> new file mode 100644
> --- /dev/null
> +++ b/tests/reproducers/simple/JavascriptURLProtocol/resources/JavascriptProtocol.js
> @@ -0,0 +1,6 @@
> +var applet = document.getElementById('applet')
> +
> +function runSomeJS() {
> +    applet.print("Javascript URL string was evaluated.")
> +    applet.state = "HasRun";
> +}
> diff --git a/tests/reproducers/simple/JavascriptURLProtocol/srcs/JavascriptProtocol.java b/tests/reproducers/simple/JavascriptURLProtocol/srcs/JavascriptProtocol.java
> new file mode 100644
> --- /dev/null
> +++ b/tests/reproducers/simple/JavascriptURLProtocol/srcs/JavascriptProtocol.java
> @@ -0,0 +1,22 @@
> +import java.applet.Applet;
> +import java.net.URL;
> +import netscape.javascript.JSObject;
> +
> +public class JavascriptProtocol extends Applet {
> +    public String state = "HasntRun";
> +    @Override
> +    public void start() {
> +        try {
> +            getAppletContext().showDocument(new URL("javascript:runSomeJS()"));
> +            System.out.println("State after showDocument was " + state);
> +        } catch (Exception e) {
> +            e.printStackTrace();
> +        }
> +        System.out.println("*** APPLET FINISHED ***");
> +    }
> +    // Utility for JS side
> +    public void print(String s) {
> +        System.out.println(s);
> +    }
> +}
> +
> diff --git a/tests/reproducers/simple/JavascriptURLProtocol/testcases/JavascriptProtocolTest.java b/tests/reproducers/simple/JavascriptURLProtocol/testcases/JavascriptProtocolTest.java
> new file mode 100644
> --- /dev/null
> +++ b/tests/reproducers/simple/JavascriptURLProtocol/testcases/JavascriptProtocolTest.java
> @@ -0,0 +1,78 @@
> +/*
> +Copyright (C) 2012 Red Hat, Inc.
> +
> +This file is part of IcedTea.
> +
> +IcedTea is free software; you can redistribute it and/or
> +modify it under the terms of the GNU General Public License as published by
> +the Free Software Foundation, version 2.
> +
> +IcedTea is distributed in the hope that it will be useful,
> +but WITHOUT ANY WARRANTY; without even the implied warranty of
> +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +General Public License for more details.
> +
> +You should have received a copy of the GNU General Public License
> +along with IcedTea; see the file COPYING.  If not, write to
> +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
> +02110-1301 USA.
> +
> +Linking this library statically or dynamically with other modules is
> +making a combined work based on this library.  Thus, the terms and
> +conditions of the GNU General Public License cover the whole
> +combination.
> +
> +As a special exception, the copyright holders of this library give you
> +permission to link this library with independent modules to produce an
> +executable, regardless of the license terms of these independent
> +modules, and to copy and distribute the resulting executable under
> +terms of your choice, provided that you also meet, for each linked
> +independent module, the terms and conditions of the license of that
> +module.  An independent module is a module which is not derived from
> +or based on this library.  If you modify this library, you may extend
> +this exception to your version of the library, but you are not
> +obligated to do so.  If you do not wish to do so, delete this
> +exception statement from your version.
> + */
> +
> +import static org.junit.Assert.assertFalse;
> +import static org.junit.Assert.assertTrue;
> +
> +import net.sourceforge.jnlp.ProcessResult;
> +import net.sourceforge.jnlp.ServerAccess.AutoClose;
> +import net.sourceforge.jnlp.annotations.Bug;
> +import net.sourceforge.jnlp.annotations.NeedsDisplay;
> +import net.sourceforge.jnlp.annotations.TestInBrowsers;
> +import net.sourceforge.jnlp.browsertesting.BrowserTest;
> +import net.sourceforge.jnlp.browsertesting.Browsers;
> +import net.sourceforge.jnlp.closinglisteners.AutoOkClosingListener;
> +
> +import org.junit.Test;
> +
> +public class JavascriptProtocolTest extends BrowserTest {
> +
> +    private static final String END_STRING = AutoOkClosingListener.MAGICAL_OK_CLOSING_STRING;
> +
> +    private static void assertContains(String source, String message, String substring) {
> +        assertTrue(source + " should contain '" + substring + "' but did not!",
> +                message.contains(substring));
> +    }
> +    private static void assertNotContains(String source, String message, String substring) {
> +        assertFalse(source + " should not contain '" + substring + "' but did!",
> +                message.contains(substring));
> +    }
> +
> +    @Test
> +    @TestInBrowsers(testIn = { Browsers.all })
> +    @NeedsDisplay
> +    @Bug(id = { "PR1271" })
> +    public void testJavascriptProtocolFollowed() throws Exception {
> +        ProcessResult pr = server.executeBrowser("/JavascriptProtocol.html",
> +                AutoClose.CLOSE_ON_BOTH);
> +        assertNotContains("stdout", pr.stdout, "HasntRun");
> +        assertContains("stdout", pr.stdout, "Javascript URL string was evaluated.");
> +        assertContains("stdout", pr.stdout, "HasRun");
> +        assertContains("stdout", pr.stdout, END_STRING);
> +    }
> +
> +}




More information about the distro-pkg-dev mailing list