changeset 1805:8dc304404e01

Update plugin and javaws. 2009-05-13 Omair Majid <omajid@redhat.com> * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/JNLPSplashScreen.java: New file. This new class is responsible for displaying the splash screen. * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/Launcher.java (launchApplication): Show a splash screen if specified in the JNLP file while loading the remote jars. * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/cache/DefaultDownloadIndicator.java (getListener): Reposition the frame at the bottom right corner of the screen. 2009-05-13 Lillian Angel <langel@redhat.com> * plugin/icedtea/sun/applet/PluginAppletSecurityContext.java (PluginAppletSecurityContext): Added comment. * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java (checkPermission): Fixed style. 2009-05-11 Lillian Angel <langel@redhat.com> * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPRuntime.java (getDefaultBaseDir): Added check for home dir. Return null if homeDir not found in system properties. 2009-05-11 Lillian Angel <langel@redhat.com> * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPRuntime.java (getDefaultBaseDir): Added null check. 2009-05-11 Lillian Angel <langel@redhat.com> * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPRuntime.java (getDefaultBaseDir): Set basedir for netx applications to ~/.netx, rather than asking. Now consistant with the plugin. * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/InstallDialog.java: Removed. 2009-05-06 Lillian Angel <langel@redhat.com> Fixes bz#498108 * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/NetxPanel.java (runLoader): Pass false to JNLPRuntime.initialize, since this is an applet. * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java (PluginAppletSecurityContext): Likewise. * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/Boot.java (run): Pass true to JNLPRuntime.initialize, since this is a webstart app. * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPRuntime.java (initialize): Added new parameter isApplication, which is used to set global static variable isWebstartApplication. (isWebstartApplication): New accessor function. * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java: (checkPermission): Added call to JNLPRuntime.isWebstartApplication so the check is bypassed if the permissions are to be checked for a webstart application. 2009-04-30 Deepak Bhole <dbhole@redhat.com> * plugin/icedtea/sun/applet/PluginAppletSecurityContext.java: Forgo permission check if JS source is [System] (i.e. Mozilla extension/chrome). 2009-04-23 Deepak Bhole <dbhole@redhat.com> * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPClassLoader.java: Handle nested jars. * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPPolicy.java: Use site address when checking for policy against CodeSource. * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/tools/JarSigner.java: Handle nested jars. 2009-04-10 Deepak Bhole <dbhole@redhat.com> * IcedTeaPlugin.cc: Fix rhbz478561 (freeze with empty string return from Java side). * plugin/icedtea/sun/applet/PluginMessageConsumer.java: Bump max workers from 3 to 20, limiting initial to 3, and growing if/when needed. 2009-04-02 Deepak Bhole <dbhole@redhat.com> * IcedTeaPlugin.cc: Incremented timeout to 3 minutes. Added functions to process proxy and auth info requests (the latter is unused). * plugin/icedtea/sun/applet/PasswordAuthenticationDialog.java: New file. Displays a username/password input dialog to users for sites and proxies requiring http auth. * plugin/icedtea/sun/applet/PluginAppletViewer.java: Fix wait mechanism to detect applet initialization failures correctly. Add support for requesting proxy information from the browser. * plugin/icedtea/sun/applet/PluginCallRequestFactory.java: Add support for PluginProxyInfoRequest objects. * plugin/icedtea/sun/applet/PluginMain.java: Wire in custom authenticator and proxy selector. * plugin/icedtea/sun/applet/PluginProxyInfoRequest.java: New file. Object representing proxy information request from browser. * plugin/icedtea/sun/applet/PluginProxySelector.java: Custom proxy selector that requests information from browser and uses it. * plugin/icedtea/sun/applet/PluginStreamHandler.java: Improve handling code for "plugin specific" messages on the wire. * overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/NetxPanel.java: Add support for improved initialization failure detection.
author Andrew John Hughes <ahughes@redhat.com>
date Wed, 20 May 2009 21:17:02 +0100
parents bbac5c54022b
children 933d372e9ded
files ChangeLog IcedTeaPlugin.cc overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/JNLPFile.java overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/Launcher.java overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/NetxPanel.java overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/cache/DefaultDownloadIndicator.java overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/Boot.java overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/InstallDialog.java overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPClassLoader.java overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPPolicy.java overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPRuntime.java overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/tools/JarSigner.java plugin/icedtea/sun/applet/PasswordAuthenticationDialog.java plugin/icedtea/sun/applet/PluginAppletSecurityContext.java plugin/icedtea/sun/applet/PluginAppletViewer.java plugin/icedtea/sun/applet/PluginCallRequestFactory.java plugin/icedtea/sun/applet/PluginMain.java plugin/icedtea/sun/applet/PluginMessageConsumer.java plugin/icedtea/sun/applet/PluginProxyInfoRequest.java plugin/icedtea/sun/applet/PluginProxySelector.java plugin/icedtea/sun/applet/PluginStreamHandler.java
diffstat 22 files changed, 1095 insertions(+), 265 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed May 20 20:50:48 2009 +0100
+++ b/ChangeLog	Wed May 20 21:17:02 2009 +0100
@@ -1,3 +1,102 @@
+2009-05-13  Omair Majid  <omajid@redhat.com>
+
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/JNLPSplashScreen.java: New file. This new class
+	is responsible for displaying the splash screen.
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/Launcher.java (launchApplication): Show a splash
+	screen if specified in the JNLP file while loading the remote jars.
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/cache/DefaultDownloadIndicator.java (getListener):
+	Reposition the frame at the bottom right corner of the screen.
+
+2009-05-13  Lillian Angel  <langel@redhat.com>
+
+	* plugin/icedtea/sun/applet/PluginAppletSecurityContext.java
+	(PluginAppletSecurityContext): Added comment.	
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java
+	(checkPermission): Fixed style.
+
+2009-05-11  Lillian Angel  <langel@redhat.com>
+
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPRuntime.java
+	(getDefaultBaseDir): Added check for home dir. Return null if homeDir
+	not found in system properties.
+
+2009-05-11  Lillian Angel  <langel@redhat.com>
+
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPRuntime.java
+	(getDefaultBaseDir): Added null check.
+
+2009-05-11  Lillian Angel  <langel@redhat.com>
+
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPRuntime.java
+	(getDefaultBaseDir): Set basedir for netx applications to ~/.netx,
+	rather than asking. Now consistant with the plugin.
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/InstallDialog.java: Removed.
+
+2009-05-06  Lillian Angel  <langel@redhat.com>
+
+	Fixes bz#498108
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/NetxPanel.java
+	(runLoader): Pass false to JNLPRuntime.initialize, since this is an 
+	applet.
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java
+	(PluginAppletSecurityContext): Likewise.
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/Boot.java
+	(run): Pass true to JNLPRuntime.initialize, since this 
+	is a webstart app.
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPRuntime.java
+	(initialize): Added new parameter isApplication, which is used to set
+	global static variable isWebstartApplication.
+	(isWebstartApplication): New accessor function.
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java:
+	(checkPermission): Added call to JNLPRuntime.isWebstartApplication so
+	the check is bypassed if the permissions are to be checked for
+	a webstart application. 
+
+2009-04-30  Deepak Bhole  <dbhole@redhat.com>
+
+	* plugin/icedtea/sun/applet/PluginAppletSecurityContext.java: Forgo
+	permission check if JS source is [System] (i.e. Mozilla 
+	extension/chrome).
+
+2009-04-23  Deepak Bhole  <dbhole@redhat.com>
+
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPClassLoader.java: Handle nested
+	jars.
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPPolicy.java: Use site address when
+	checking for policy against CodeSource.
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/tools/JarSigner.java: Handle nested
+	jars.
+
+2009-04-10  Deepak Bhole  <dbhole@redhat.com>
+
+	* IcedTeaPlugin.cc: Fix rhbz478561 (freeze with empty string return from
+	Java side).
+	* plugin/icedtea/sun/applet/PluginMessageConsumer.java: Bump max workers
+	from 3 to 20, limiting initial to 3, and growing if/when needed.
+
+2009-04-02  Deepak Bhole  <dbhole@redhat.com>
+
+	* IcedTeaPlugin.cc: Incremented timeout to 3 minutes. Added functions to
+	process proxy and auth info requests (the latter is unused).
+	* plugin/icedtea/sun/applet/PasswordAuthenticationDialog.java: New file.
+	Displays a username/password input dialog to users for sites and proxies
+	requiring http auth.
+	* plugin/icedtea/sun/applet/PluginAppletViewer.java: Fix wait mechanism to 
+	detect applet initialization failures correctly. Add support for
+	requesting proxy information from the browser.
+	* plugin/icedtea/sun/applet/PluginCallRequestFactory.java: Add support for
+	PluginProxyInfoRequest objects.
+	* plugin/icedtea/sun/applet/PluginMain.java: Wire in custom authenticator
+	and proxy selector.
+	* plugin/icedtea/sun/applet/PluginProxyInfoRequest.java: New file. Object
+	representing proxy information request from browser.
+	* plugin/icedtea/sun/applet/PluginProxySelector.java: Custom proxy
+	selector that requests information from browser and uses it.
+	* plugin/icedtea/sun/applet/PluginStreamHandler.java: Improve handling
+	code for "plugin specific" messages on the wire.
+	* overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/NetxPanel.java: Add support for improved
+	initialization failure detection.
+
 2009-05-20  Andrew John Hughes  <ahughes@redhat.com>
 
 	* HACKING: Updated.
--- a/IcedTeaPlugin.cc	Wed May 20 20:50:48 2009 +0100
+++ b/IcedTeaPlugin.cc	Wed May 20 21:17:02 2009 +0100
@@ -85,7 +85,7 @@
 // #14 0x0153fdbf in ProxyJNIEnv::CallObjectMethod (env=0xa8b8040, obj=0x9dad690, methodID=0xa0ed070) at ProxyJNI.cpp:641
 
 // timeout (in seconds) for various calls to java side
-#define TIMEOUT 20
+#define TIMEOUT 180
 
 #define NOT_IMPLEMENTED() \
   PLUGIN_DEBUG_1ARG ("NOT IMPLEMENTED: %s\n", __PRETTY_FUNCTION__)
@@ -588,7 +588,7 @@
   PLUGIN_DEBUG_0ARG ("RECEIVE VALUE 1\n");                                             \
   ResultContainer *resultC;                                              \
   factory->result_map.Get(reference, &resultC);                         \
-  while (resultC->returnValue == "" && \
+  while (resultC->returnValue.IsVoid() == PR_TRUE && \
 	     resultC->errorOccurred == PR_FALSE)            \
     {                                                                      \
       PROCESS_PENDING_EVENTS_REF (reference);                                   \
@@ -607,7 +607,7 @@
   PLUGIN_DEBUG_0ARG("RECEIVE SIZE 1\n");                                 \
   ResultContainer *resultC;                                              \
   factory->result_map.Get(reference, &resultC);                         \
-  while (resultC->returnValue == "" && \
+  while (resultC->returnValue.IsVoid() == PR_TRUE && \
 	     resultC->errorOccurred == PR_FALSE) \
     {                                                           \
       PROCESS_PENDING_EVENTS_REF (reference);                        \
@@ -631,7 +631,7 @@
   PLUGIN_DEBUG_0ARG("RECEIVE STRING 1\n");                                 \
   ResultContainer *resultC;                                              \
   factory->result_map.Get(reference, &resultC);                         \
-  while (resultC->returnValue == "" && \
+  while (resultC->returnValue.IsVoid() == PR_TRUE && \
 	     resultC->errorOccurred == PR_FALSE)  \
     {                                                           \
       PROCESS_PENDING_EVENTS_REF (reference);                        \
@@ -655,7 +655,7 @@
   PLUGIN_DEBUG_0ARG("RECEIVE STRING UCS 1\n");                                 \
   ResultContainer *resultC;                                              \
   factory->result_map.Get(reference, &resultC);                         \
-  while (resultC->returnValueUCS.IsEmpty() && \
+  while (resultC->returnValueUCS.IsVoid() == PR_TRUE && \
 	     resultC->errorOccurred == PR_FALSE) \
     {                                                           \
       PROCESS_PENDING_EVENTS_REF (reference);                        \
@@ -855,6 +855,8 @@
 	returnIdentifier = -1;
 	returnValue.Truncate();
 	returnValueUCS.Truncate();
+	returnValue.SetIsVoid(PR_TRUE);
+	returnValueUCS.SetIsVoid(PR_TRUE);
 	errorMessage.Truncate();
 	errorOccurred = PR_FALSE;
 
@@ -877,6 +879,8 @@
 	returnIdentifier = -1;
 	returnValue.Truncate();
 	returnValueUCS.Truncate();
+	returnValue.SetIsVoid(PR_TRUE);
+	returnValueUCS.SetIsVoid(PR_TRUE);
 	errorMessage.Truncate();
 	errorOccurred = PR_FALSE;
 
@@ -1007,6 +1011,7 @@
   nsresult StartAppletviewer ();
   void ProcessMessage();
   void ConsumeMsgFromJVM();
+  nsresult GetProxyInfo(const char* siteAddr, char** proxyScheme, char** proxyHost, char** proxyPort);
   nsCOMPtr<IcedTeaEventSink> sink;
   nsCOMPtr<nsISocketTransport> transport;
   nsCOMPtr<nsIProcess> applet_viewer_process;
@@ -1792,7 +1797,7 @@
 NS_IMETHODIMP
 IcedTeaPluginFactory::Show (void)
 {
-  nsCString msg("showconsole");
+  nsCString msg("plugin showconsole");
   this->SendMessageToAppletViewer(msg);
   return NS_OK;
 }
@@ -1800,7 +1805,7 @@
 NS_IMETHODIMP
 IcedTeaPluginFactory::Hide (void)
 {
-  nsCString msg("hideconsole");
+  nsCString msg("plugin hideconsole");
   this->SendMessageToAppletViewer(msg);
   return NS_OK;
 }
@@ -2658,6 +2663,96 @@
   return factory->GetJavaObject (instance_identifier, object);
 }
 
+#include <nsIDNSRecord.h>
+#include <nsIDNSService.h>
+#include <nsIHttpAuthManager.h>
+#include <nsIProxyInfo.h>
+#include <nsIProtocolProxyService.h>
+#include <nsILoginManager.h>
+#include <nsILoginInfo.h>
+
+/** 
+ *
+ * Returns the proxy information for the given url
+ *
+ * The proxy query part of this function can be made much smaller by using 
+ * nsIPluginManager2::FindProxyForURL() .. however, because we need to parse 
+ * the return components in various ways, it is easier to query 
+ * nsIProtocolProxyService directly
+ *
+ * @param siteAddr The URL to check
+ * @param  proxyScheme Return parameter containing the proxy URI scheme (http/socks/etc.)
+ * @param proxyHost Return parameter containing the proxy host
+ * @param proxyPort Return parameter containing the proxy port
+ */
+
+NS_IMETHODIMP
+IcedTeaPluginFactory::GetProxyInfo(const char* siteAddr, char** proxyScheme, char** proxyHost, char** proxyPort)
+{
+  nsresult rv;
+
+  // Initialize service variables
+  nsCOMPtr<nsIProtocolProxyService> proxy_svc = do_GetService(NS_PROTOCOLPROXYSERVICE_CONTRACTID, &rv);
+
+  if (!proxy_svc) {
+	  printf("Cannot initialize proxy service\n");
+	  return rv;
+  }
+
+  nsCOMPtr<nsIIOService> io_svc = do_GetService(NS_IOSERVICE_CONTRACTID, &rv);
+
+  if (NS_FAILED(rv) || !io_svc) {
+    printf("Cannot initialize io service\n");
+    return NS_ERROR_FAILURE;
+  }
+
+  // uri which needs to be accessed
+  nsCOMPtr<nsIURI> uri;
+  io_svc->NewURI(nsCString(siteAddr), NULL, NULL, getter_AddRefs(uri));
+
+  // find the proxy address if any
+  nsCOMPtr<nsIProxyInfo> info;
+  proxy_svc->Resolve(uri, 0, getter_AddRefs(info));
+
+  // if there is no proxy found, return immediately
+  if (!info) {
+     PLUGIN_DEBUG_1ARG("%s does not need a proxy\n", siteAddr);
+	 return NS_ERROR_FAILURE;
+  }
+
+  // if proxy info is available, extract it
+  nsCString phost;
+  PRInt32 pport;
+  nsCString ptype;
+
+  info->GetHost(phost);
+  info->GetPort(&pport);
+  info->GetType(ptype);
+
+  // resolve the proxy address to an IP
+  nsCOMPtr<nsIDNSService> dns_svc = do_GetService(NS_DNSSERVICE_CONTRACTID, &rv);
+
+  if (!dns_svc) {
+      printf("Cannot initialize DNS service\n");
+      return rv;
+  }
+
+  nsCOMPtr<nsIDNSRecord> record;
+  dns_svc->Resolve(phost, 0U, getter_AddRefs(record));
+
+  // TODO: Add support for multiple ips
+  nsDependentCString ipAddr;
+  record->GetNextAddrAsString(ipAddr);
+
+  // pack information in return variables
+  snprintf(*proxyScheme, sizeof(char)*32, "%s", ptype.get());
+  snprintf(*proxyHost, sizeof(char)*64, "%s", ipAddr.get());
+  snprintf(*proxyPort, sizeof(char)*8, "%d", pport);
+
+  PLUGIN_DEBUG_4ARG("Proxy info for %s: %s %s %s\n", siteAddr, *proxyScheme, *proxyHost, *proxyPort);
+
+  return NS_OK;
+}
 
 NS_IMETHODIMP
 IcedTeaPluginInstance::GetCookie(const char* siteAddr, char** cookieString) 
@@ -2677,8 +2772,8 @@
     return NS_ERROR_FAILURE;
   }
 
-  nsIURI *uri;
-  io_svc->NewURI(nsCString(siteAddr), NULL, NULL, &uri);
+  nsCOMPtr<nsIURI> uri;
+  io_svc->NewURI(nsCString(siteAddr), NULL, NULL, getter_AddRefs(uri));
 
   nsCOMPtr<nsICookieService> cookie_svc = do_GetService(NS_COOKIESERVICE_CONTRACTID, &rv);
 
@@ -2902,6 +2997,13 @@
   nsDependentCSubstring prefix(pch, strlen(pch));
   pch = strtok (NULL, " ");
   PRUint32 identifier = nsDependentCSubstring(pch, strlen(pch)).ToInteger (&conversionResult);
+
+  /* Certain prefixes may not have an identifier. if they don't. we have a command here */
+  nsDependentCSubstring command;
+  if (NS_FAILED(conversionResult)) {
+    command.Rebind(pch, strlen(pch));
+  }
+
   PRUint32 reference = -1;
 
   if (strstr(message.get(), "reference") != NULL) {
@@ -2910,8 +3012,11 @@
 	  reference = nsDependentCSubstring(pch, strlen(pch)).ToInteger (&conversionResult);
   }
 
-  pch = strtok (NULL, " ");
-  nsDependentCSubstring command(pch, strlen(pch));
+  if (command.Length() == 0) {
+    pch = strtok (NULL, " ");
+    command.Rebind(pch, strlen(pch));
+  }
+
   pch = strtok (NULL, " ");
 
   nsDependentCSubstring rest("", 0);
@@ -3251,7 +3356,8 @@
           
 		   ResultContainer *resultC;
 		   result_map.Get(reference, &resultC);
-		   resultC->returnValue = rest; 
+		   resultC->returnValue = rest;
+		   resultC->returnValue.SetIsVoid(PR_FALSE);
            PLUGIN_DEBUG_1ARG ("PLUGIN GOT RETURN VALUE: %s\n", resultC->returnValue.get());
         }
       else if (command == "GetStringUTFChars")
@@ -3339,11 +3445,55 @@
 		  ResultContainer *resultC;
 		  result_map.Get(reference, &resultC);
 		  resultC->returnValueUCS = returnValueUCS;
+		  resultC->returnValueUCS.SetIsVoid(PR_FALSE);
 
         }
       // Do nothing for: SetStaticField, SetField, ExceptionClear,
       // DeleteGlobalRef, DeleteLocalRef
     }
+	else if (prefix == "plugin")
+    {
+
+        if (command == "PluginProxyInfo") {
+
+          nsresult rv;
+          nsCOMPtr<nsINetUtil> net_util = do_GetService(NS_NETUTIL_CONTRACTID, &rv);
+
+          if (!net_util)
+            printf("Error instantiating NetUtil service.\n");
+
+          // decode the url
+          nsDependentCSubstring url;
+          net_util->UnescapeString(rest, 0, url);
+
+          char* proxyScheme = (char*) malloc(sizeof(char)*32);
+          char* proxyHost = (char*) malloc(sizeof(char)*64);
+          char* proxyPort = (char*) malloc(sizeof(char)*8);
+
+          nsCString proxyInfo("plugin PluginProxyInfo ");
+
+          // get proxy info
+          if (GetProxyInfo(((nsCString) url).get(), &proxyScheme, &proxyHost, &proxyPort) == NS_OK)
+          {
+              proxyInfo += proxyScheme;
+              proxyInfo += " ";
+              proxyInfo += proxyHost;
+              proxyInfo += " ";
+              proxyInfo += proxyPort;
+
+              PLUGIN_DEBUG_4ARG("Proxy for %s is %s %s %s\n", ((nsCString) url).get(), proxyScheme, proxyHost, proxyPort);
+          } else {
+              PLUGIN_DEBUG_1ARG("No suitable proxy found for %s\n", ((nsCString) url).get());
+          }
+
+          // send back what we found
+          SendMessageToAppletViewer (proxyInfo);
+
+		  // free allocated memory
+          delete proxyScheme, proxyHost, proxyPort;
+
+		}
+	}
 }
 
 void IcedTeaPluginFactory::ProcessMessage ()
--- a/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/JNLPFile.java	Wed May 20 20:50:48 2009 +0100
+++ b/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/JNLPFile.java	Wed May 20 21:17:02 2009 +0100
@@ -106,7 +106,7 @@
             // null values will still work, and app can set defaults later
         }
     }
-
+    
     /**
      * Empty stub, allowing child classes to override the constructor
      */
--- a/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/Launcher.java	Wed May 20 20:50:48 2009 +0100
+++ b/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/Launcher.java	Wed May 20 21:17:02 2009 +0100
@@ -331,6 +331,22 @@
             throw launchError(new LaunchException(file, null, R("LSFatal"), R("LCClient"), R("LNotApplication"), R("LNotApplicationInfo")));
 
         try {
+            final int preferredWidth = 500;
+            final int preferredHeight = 400;
+            JNLPSplashScreen splashScreen = null;
+            URL splashImageURL = file.getInformation().getIconLocation(
+                    IconDesc.SPLASH, preferredWidth, preferredHeight);
+            if (splashImageURL != null) {
+                ResourceTracker resourceTracker = new ResourceTracker(true);
+                resourceTracker.addResource(splashImageURL, "SPLASH", file.getFileVersion(), updatePolicy);
+                splashScreen = new JNLPSplashScreen(resourceTracker, null, null);
+                splashScreen.setSplashImageURL(splashImageURL);
+                if (splashScreen.isSplashScreenValid()) {
+                    splashScreen.setVisible(true);
+                }
+            }
+
+
             ApplicationInstance app = createApplication(file);
             app.initialize();
 
@@ -361,6 +377,13 @@
             // required to make some apps work right
             Thread.currentThread().setContextClassLoader(app.getClassLoader());
 
+            if (splashScreen != null) {
+                if (splashScreen.isSplashScreenValid()) {
+                    splashScreen.setVisible(false);
+                }
+                splashScreen.dispose();
+            }
+
             main.invoke(null, new Object[] { args } );
 
             return app;
--- a/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/NetxPanel.java	Wed May 20 20:50:48 2009 +0100
+++ b/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/NetxPanel.java	Wed May 20 21:17:02 2009 +0100
@@ -42,6 +42,7 @@
     private boolean exitOnFailure = true;
     private AppletInstance appInst = null;
     private String cookieStr;
+    private boolean appletAlive;
 
     public NetxPanel(URL documentURL, Hashtable atts)
     {
@@ -54,6 +55,7 @@
         this(documentURL, atts);
         this.exitOnFailure = exitOnFailure;
         this.cookieStr = cookieStr;
+        this.appletAlive = true;
     }
 
     //Overriding to use Netx classloader. You might need to relax visibility
@@ -76,7 +78,7 @@
     			    if (JNLPRuntime.isDebug())
     			        System.out.println("initializing JNLPRuntime...");
 
-    				JNLPRuntime.initialize();
+    				JNLPRuntime.initialize(false);
     			} else {
     			    if (JNLPRuntime.isDebug())
     			        System.out.println("JNLPRuntime already initialized");
@@ -121,10 +123,11 @@
     			validate();
     		}
     	} catch (Exception e) {
+    	    this.appletAlive = false;
     		e.printStackTrace();
     	}
     }
-    
+
     // Reminder: Relax visibility in sun.applet.AppletPanel
     protected synchronized void createAppletThread() {
     	handler = new Thread(this);
@@ -139,5 +142,9 @@
     public ClassLoader getAppletClassLoader() {
         return appInst.getClassLoader();
     }
+    
+    public boolean isAlive() {
+        return handler.isAlive() && this.appletAlive;
+    }
 }
 
--- a/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/cache/DefaultDownloadIndicator.java	Wed May 20 20:50:48 2009 +0100
+++ b/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/cache/DefaultDownloadIndicator.java	Wed May 20 21:17:02 2009 +0100
@@ -110,9 +110,12 @@
         frame.pack();
 
         if (!frame.isVisible()) {
-            Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
-            frame.setLocation(screen.width/2-frame.getWidth()/2,
-                              screen.height/2-frame.getHeight()/2);
+            Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
+            Insets insets = Toolkit.getDefaultToolkit().getScreenInsets(frame.getGraphicsConfiguration());
+            Dimension screen = new Dimension(screenSize.width - insets.left , 
+                    screenSize.height - insets.top);
+            frame.setLocation(screen.width-frame.getWidth(),
+                              screen.height-frame.getHeight());
         }
 
         frame.show();
--- a/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/Boot.java	Wed May 20 20:50:48 2009 +0100
+++ b/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/Boot.java	Wed May 20 21:17:02 2009 +0100
@@ -17,17 +17,32 @@
 
 package net.sourceforge.jnlp.runtime;
 
-import java.util.*;
-import java.io.*;
-import java.net.*;
-import java.security.*;
+import java.io.File;
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.List;
 
-import net.sourceforge.jnlp.*;
-import net.sourceforge.jnlp.cache.*;
-import net.sourceforge.jnlp.runtime.*;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+
+import net.sourceforge.jnlp.AppletDesc;
+import net.sourceforge.jnlp.ApplicationDesc;
+import net.sourceforge.jnlp.JNLPFile;
+import net.sourceforge.jnlp.LaunchException;
+import net.sourceforge.jnlp.Launcher;
+import net.sourceforge.jnlp.ParseException;
+import net.sourceforge.jnlp.PropertyDesc;
+import net.sourceforge.jnlp.ResourcesDesc;
+import net.sourceforge.jnlp.cache.UpdatePolicy;
+import net.sourceforge.jnlp.security.VariableX509TrustManager;
 import net.sourceforge.jnlp.security.viewer.CertificateViewer;
-import net.sourceforge.jnlp.services.*;
-import net.sourceforge.jnlp.util.*;
+import net.sourceforge.jnlp.services.ServiceUtil;
 
 /**
  * This is the main entry point for the JNLP client.  The main
@@ -153,6 +168,20 @@
 
         if (null != getOption("-noupdate"))
             JNLPRuntime.setDefaultUpdatePolicy(UpdatePolicy.NEVER);
+        
+        // wire in custom authenticator
+        try {
+            SSLSocketFactory sslSocketFactory;
+            SSLContext context = SSLContext.getInstance("SSL");
+            TrustManager[] trust = new TrustManager[] { VariableX509TrustManager.getInstance() };
+            context.init(null, trust, null);
+            sslSocketFactory = context.getSocketFactory();
+            
+            HttpsURLConnection.setDefaultSSLSocketFactory(sslSocketFactory);
+        } catch (Exception e) {
+            System.err.println("Unable to set SSLSocketfactory (may _prevent_ access to sites that should be trusted)! Continuing anyway...");
+            e.printStackTrace();
+        }
 
         // do in a privileged action to clear the security context of
         // the Boot13 class, which doesn't have any privileges in
@@ -168,7 +197,7 @@
     public Object run() {
         JNLPRuntime.setBaseDir(getBaseDir());
         JNLPRuntime.setSecurityEnabled(null == getOption("-nosecurity"));
-        JNLPRuntime.initialize();
+        JNLPRuntime.initialize(true);
 
         try {
             new Launcher().launch(getFile());
--- a/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/InstallDialog.java	Wed May 20 20:50:48 2009 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,171 +0,0 @@
-// Copyright (C) 2001-2003 Jon A. Maxwell (JAM)
-// 
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2.1 of the License, or (at your option) any later version.
-// 
-// This library 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
-// Lesser General Public License for more details.
-// 
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
-
-
-package net.sourceforge.jnlp.runtime;
-
-import java.awt.*;
-import java.awt.event.*;
-import java.io.*;
-import java.net.*;
-import java.util.*;
-import java.util.List;
-import javax.swing.*;
-import javax.jnlp.*;
-
-import net.sourceforge.jnlp.*;
-
-/**
- * Prompt for an install location.
- *
- * @author <a href="mailto:jmaxwell@users.sourceforge.net">Jon A. Maxwell (JAM)</a> - initial author
- * @version $Revision: 1.7 $ 
- */
-class InstallDialog extends Dialog implements ActionListener {
-
-    private static String R(String key) { return JNLPRuntime.getMessage(key); }
-
-    private ImageIcon background;
-    private TextField installField = new TextField();
-    private Button ok = new Button(R("ButOk"));
-    private Button cancel = new Button(R("ButCancel"));
-    private Button browse = new Button(R("ButBrowse"));
-    private boolean canceled = false;
-
-    static Frame createFrame() {
-        Frame f = new Frame();
-        f.setIconImage(JNLPRuntime.getWindowIcon());
-        return f;
-    }
-
-    InstallDialog() {
-        super(createFrame(), R("CChooseCache"), true);
-
-        URL icon = (new sun.misc.Launcher()).getClassLoader().getResource("net/sourceforge/jnlp/resources/install.png");
-        
-        background = new ImageIcon(icon);
-        setLayout(new BorderLayout());
-        setBackground(Color.white);
-
-        String home = System.getProperty("java.io.tmpdir");
-        installField.setText((new File(home)).toString());
-
-        ok.addActionListener(this);
-        cancel.addActionListener(this);
-        browse.addActionListener(this);
-
-        Font f = new Font("SansSerif", Font.BOLD, 14);
-
-        installField.setFont(f);
-        ok.setFont(f);
-        cancel.setFont(f);
-        browse.setFont(f);
-
-        Panel top = new Panel(new GridLayout(2, 1, 0, 10));
-        Label l1 = new Label(R("CChooseCacheInfo"));
-        Label l2 = new Label(R("CChooseCacheDir")+":");
-        l1.setFont(f);
-        l2.setFont(f);
-        top.add(l1);
-        top.add(l2);
-
-        Panel field = new Panel(new BorderLayout());
-        field.add(top, BorderLayout.NORTH);
-        field.add(installField, BorderLayout.CENTER);
-        field.add(browse, BorderLayout.EAST);
-
-        Panel grid = new Panel(new GridLayout(1, 2, 8, 8));
-        grid.add(ok);
-        grid.add(cancel);
-        
-        Panel choice = new Panel(new FlowLayout(FlowLayout.CENTER, 4, 0));
-        choice.add(grid);
-
-        add(field, BorderLayout.NORTH);
-        add(new Panel(), BorderLayout.CENTER);
-        add(choice, BorderLayout.SOUTH);
-    }
-
-    public Insets getInsets() {
-        Insets s = super.getInsets();
-        return new Insets(s.top + 55, s.left + 7, s.bottom + 6, s.right + 4);
-        //return new Insets(s.top + 115, s.left + 7, s.bottom + 6, s.right + 4);
-    }
-
-    public Dimension getPreferredSize() {
-        Dimension d = super.getPreferredSize();
-        if (background == null)
-            return d;
-
-        Insets in = super.getInsets();
-        d.width = background.getIconWidth() + in.left + in.right;
-        d.height = Math.max(d.height + 8, background.getIconHeight() + 8 + in.top + in.bottom);
-
-        return d;
-    }
-
-    public void paint(Graphics g) {
-		
-        Insets sin = super.getInsets();
-        g.drawImage(background.getImage(), sin.left, sin.top, this);
-		
-    }
-
-    public void actionPerformed(ActionEvent evt) {
-        if (evt.getSource() == cancel) {
-            canceled = true;
-            dispose();
-        }
-        if (evt.getSource() == ok) {
-            File f = new File(installField.getText());
-
-            try {
-                f.mkdirs();
-                dispose();
-            }
-            catch (Exception ex) {
-                JOptionPane.showMessageDialog(this, "Install directory cannot be created.", 
-                                              "ERROR", JOptionPane.ERROR_MESSAGE); 
-            }
-        }
-        if (evt.getSource() == browse) {
-            JFileChooser fc = new JFileChooser();
-            fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
-            int r = fc.showOpenDialog(this); 
-            if (r == JFileChooser.APPROVE_OPTION)
-                installField.setText(fc.getSelectedFile().toString());
-        }
-    }
-
-
-    static File getInstallDir() {
-        InstallDialog id = new InstallDialog();
-
-        //id.setResizable(false);
-        id.pack();
-        Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
-        id.setLocation(screen.width/2-id.getWidth()/2,
-                       screen.height/2-id.getHeight()/2);
-        id.setVisible(true);
-
-        if (id.canceled)
-            return null;
-
-        return new File(id.installField.getText());
-    }
-
-}
-
--- a/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPClassLoader.java	Wed May 20 20:50:48 2009 +0100
+++ b/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPClassLoader.java	Wed May 20 21:17:02 2009 +0100
@@ -20,6 +20,7 @@
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLClassLoader;
@@ -344,24 +345,7 @@
 
 				//user does not trust this publisher
 				if (!js.getAlreadyTrustPublisher()) {
-					if (!js.getRootInCacerts()) { //root cert is not in cacerts
-						boolean b = SecurityWarningDialog.showCertWarningDialog(
-							SecurityWarningDialog.AccessType.UNVERIFIED, file, js);
-						if (!b)
-							throw new LaunchException(null, null, R("LSFatal"), 
-								R("LCLaunching"), R("LNotVerified"), "");
-					} else if (js.getRootInCacerts()) { //root cert is in cacerts
-						boolean b = false;
-						if (js.noSigningIssues())
-							b = SecurityWarningDialog.showCertWarningDialog(
-									SecurityWarningDialog.AccessType.VERIFIED, file, js);
-						else if (!js.noSigningIssues())
-							b = SecurityWarningDialog.showCertWarningDialog(
-									SecurityWarningDialog.AccessType.SIGNING_ERROR, file, js);
-						if (!b)
-							throw new LaunchException(null, null, R("LSFatal"),
-								R("LCLaunching"), R("LCancelOnUserRequest"), "");
-					}
+				    checkTrustWithUser(js);
 				} else {
 					/**
 					 * If the user trusts this publisher (i.e. the publisher's certificate
@@ -379,6 +363,27 @@
         activateJars(initialJars);
     }
 
+    private void checkTrustWithUser(JarSigner js) throws LaunchException {
+        if (!js.getRootInCacerts()) { //root cert is not in cacerts
+            boolean b = SecurityWarningDialog.showCertWarningDialog(
+                SecurityWarningDialog.AccessType.UNVERIFIED, file, js);
+            if (!b)
+                throw new LaunchException(null, null, R("LSFatal"), 
+                    R("LCLaunching"), R("LNotVerified"), "");
+        } else if (js.getRootInCacerts()) { //root cert is in cacerts
+            boolean b = false;
+            if (js.noSigningIssues())
+                b = SecurityWarningDialog.showCertWarningDialog(
+                        SecurityWarningDialog.AccessType.VERIFIED, file, js);
+            else if (!js.noSigningIssues())
+                b = SecurityWarningDialog.showCertWarningDialog(
+                        SecurityWarningDialog.AccessType.SIGNING_ERROR, file, js);
+            if (!b)
+                throw new LaunchException(null, null, R("LSFatal"),
+                    R("LCLaunching"), R("LCancelOnUserRequest"), "");
+        }
+    }
+
     /**
      * Add applet's codebase URL.  This allows compatibility with
      * applets that load resources from their codebase instead of
@@ -505,8 +510,49 @@
                             
                             JarFile jarFile = new JarFile(localFile);
                             Enumeration e = jarFile.entries();
-                            while (e.hasMoreElements())
-                                jarEntries.add(((JarEntry) e.nextElement()).getName());
+                            while (e.hasMoreElements()) {
+                                
+                                JarEntry je = (JarEntry) e.nextElement();
+                                
+                                // another jar in my jar? it is more likely than you think  
+                                if (je.getName().endsWith(".jar")) {
+                                    // We need to extract that jar so that it can be loaded 
+                                    // (inline loading with "jar:..!/..." path will not work 
+                                    // with standard classloader methods)
+
+                                    String extractedJarLocation = localFile.getParent() + "/" + je.getName();
+                                    FileOutputStream extractedJar = new FileOutputStream(extractedJarLocation);
+                                    InputStream is = jarFile.getInputStream(je);
+
+                                    byte[] bytes = new byte[1024];
+                                    int read = is.read(bytes);
+                                    while (read > 0) {
+                                        extractedJar.write(bytes, 0, read);
+                                        read = is.read(bytes);
+                                    }
+
+                                    is.close();
+                                    extractedJar.close();
+
+                                    JarSigner signer = new JarSigner();
+                                    signer.verifyJar(extractedJarLocation);
+
+                                    if (signer.anyJarsSigned() && !signer.getAlreadyTrustPublisher()) {
+                                        checkTrustWithUser(signer);
+                                    }
+
+                                    try {
+                                        addURL(new URL("file://" + extractedJarLocation));
+                                    } catch (MalformedURLException mfue) {
+                                        if (JNLPRuntime.isDebug())
+                                            System.err.println("Unable to add extracted nested jar to classpath");
+
+                                        mfue.printStackTrace();
+                                    }
+                                }
+
+                                jarEntries.add(je.getName());
+                            }
 
                         }
 
--- a/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPPolicy.java	Wed May 20 20:50:48 2009 +0100
+++ b/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPPolicy.java	Wed May 20 21:17:02 2009 +0100
@@ -65,7 +65,8 @@
         		PermissionCollection clPermissions = cl.getPermissions(source);
         		
         		// systempolicy permissions need to be accounted for as well
-        		Enumeration e = systemPolicy.getPermissions(source).elements();
+        		CodeSource appletCS = new CodeSource(JNLPRuntime.getApplication().getJNLPFile().getSourceLocation(), (java.security.cert.Certificate[]) null);
+        		Enumeration e = systemPolicy.getPermissions(appletCS).elements();
                 while (e.hasMoreElements())
                     clPermissions.add((Permission) e.nextElement());
 
--- a/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPRuntime.java	Wed May 20 20:50:48 2009 +0100
+++ b/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPRuntime.java	Wed May 20 21:17:02 2009 +0100
@@ -94,6 +94,9 @@
     /** mutex to wait on, for initialization */
     public static Object initMutex = new Object();
 
+    /** set to true if this is a webstart application. */
+    private static boolean isWebstartApplication; 
+
     /**
      * Returns whether the JNLP runtime environment has been
      * initialized.  Once initialized, some properties such as the
@@ -112,10 +115,14 @@
      * initialized, methods that alter the runtime can only be
      * called by the exit class.<p>
      *
+     * @param isApplication is true if a webstart application is being initialized
+     *
      * @throws IllegalStateException if the runtime was previously initialized
      */
-    public static void initialize() throws IllegalStateException {
+    public static void initialize(boolean isApplication) throws IllegalStateException {
         checkInitialized();
+     
+        isWebstartApplication = isApplication;
 
         if (headless == false)
             checkHeadless();
@@ -149,6 +156,14 @@
     }
 
     /**
+     * Returns true if a webstart application has been initialized, and false
+     * for a plugin applet.
+     */
+    public static boolean isWebstartApplication() {
+        return isWebstartApplication;
+    }
+
+    /**
      * Returns the window icon.
      */
     public static Image getWindowIcon() {
@@ -265,8 +280,9 @@
         if (isHeadless())
             return null;
 
-        File baseDir = InstallDialog.getInstallDir();
-        if (baseDir == null)
+        String homeDir = System.getProperty("user.home");
+	File baseDir = new File(homeDir + "/.netx/");
+	if (homeDir == null || !baseDir.mkdir())
             return null;
 
         props.setProperty("basedir", baseDir.toString());
@@ -285,14 +301,14 @@
         checkExitClass();
         security.setExitClass(exitClass);
     }
-
+    
     /**
      * Disables applets from calling exit.
      * 
      * Once disabled, exit cannot be re-enabled for the duration of the JVM instance
      */
     public static void disableExit() {
-      security.disableExit();
+    	security.disableExit();
     }
 
     /**
--- a/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java	Wed May 20 20:50:48 2009 +0100
+++ b/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/runtime/JNLPSecurityManager.java	Wed May 20 21:17:02 2009 +0100
@@ -103,7 +103,7 @@
 
     /** listener installs the app's classloader on the event dispatch thread */
     private ContextUpdater contextListener = new ContextUpdater();
-
+    
     /** Sets whether or not exit is allowed (in the context of the plugin, this is always false) */
     private boolean exitAllowed = true;
 
@@ -255,13 +255,14 @@
      */
     public void checkPermission(Permission perm) {
         String name = perm.getName();
-        
+
         // Enable this manually -- it'll produce too much output for -verbose
         // otherwise.
-//		if (true)
-//			System.out.println("Checking permission: " + perm.toString());
-        if ("setPolicy".equals(name) ||
-            "setSecurityManager".equals(name))
+	//	if (true)
+	//  	  System.out.println("Checking permission: " + perm.toString());
+
+        if (!JNLPRuntime.isWebstartApplication() && 
+	      ("setPolicy".equals(name) || "setSecurityManager".equals(name)))
             throw new SecurityException(R("RCantReplaceSM"));
 
         try {
@@ -279,7 +280,7 @@
 			try {
 				super.checkPermission(perm);
 			} catch (SecurityException se) {
-				
+
 				//This section is a special case for dealing with SocketPermissions.
 				if (JNLPRuntime.isDebug())
 					System.err.println("Requesting permission: " + perm.toString());
@@ -440,12 +441,13 @@
      * behave normally, and the exit class can always exit the JVM.
      */
     public void checkExit(int status) {
+
     	// applets are not allowed to exit, but the plugin main class (primordial loader) is
         Class stack[] = getClassContext();
         if (!exitAllowed) {
-	  for (int i=0; i < stack.length; i++)
-	    if (stack[i].getClassLoader() != null)
-	      throw new AccessControlException("Applets may not call System.exit()");
+        	for (int i=0; i < stack.length; i++)
+        		if (stack[i].getClassLoader() != null)
+        			throw new AccessControlException("Applets may not call System.exit()");
         }
 
     	super.checkExit(status);
@@ -482,6 +484,7 @@
     protected void disableExit() {
     	exitAllowed = false;
     }
+    
 }
 
 
--- a/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/tools/JarSigner.java	Wed May 20 20:50:48 2009 +0100
+++ b/overlays/openjdk/jdk/src/share/classes/net/sourceforge/jnlp/tools/JarSigner.java	Wed May 20 21:17:02 2009 +0100
@@ -218,7 +218,6 @@
 
                 String localFile = jarFile.getAbsolutePath();
                 boolean result = verifyJar(localFile);
-                checkTrustedCerts();
 
                 if (!result) {
                     //allVerified is true until we encounter a problem
@@ -241,6 +240,10 @@
         boolean hasUnsignedEntry = false;
         JarInputStream jis = null;
 
+        // certs could be uninitialized if one calls this method directly
+        if (certs == null)
+            certs = new ArrayList<CertPath>();
+        
         try {
             jis = new JarInputStream(new FileInputStream(jarName), true);
             Vector<JarEntry> entriesVec = new Vector<JarEntry>();
@@ -352,6 +355,9 @@
             }
         }
 
+        // check if the certs added above are in the trusted path
+        checkTrustedCerts();
+        
         //anySigned does not guarantee that all files were signed.
         return anySigned && !(hasUnsignedEntry || hasExpiredCert
                               || badKeyUsage || badExtendedKeyUsage || badNetscapeCertType
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugin/icedtea/sun/applet/PasswordAuthenticationDialog.java	Wed May 20 21:17:02 2009 +0100
@@ -0,0 +1,241 @@
+/* PasswordAuthenticationDialog -- requests authentication information from users
+   Copyright (C) 2009  Red Hat
+
+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. */
+
+package sun.applet;
+
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.net.PasswordAuthentication;
+
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JPasswordField;
+import javax.swing.JTextField;
+import javax.swing.SwingUtilities;
+
+/**
+ * Modal non-minimizable dialog to request http authentication credentials
+ */
+
+public class PasswordAuthenticationDialog extends JDialog {
+    
+    private JLabel jlInfo = new JLabel("");
+    private JTextField jtfUserName = new JTextField();
+    private JPasswordField jpfPassword = new JPasswordField();
+    private boolean userCancelled;
+
+    public PasswordAuthenticationDialog() {
+        initialize();
+    }
+
+    /**
+     * Initialized the dialog components
+     */
+    
+    public void initialize() {
+
+        setTitle("IcedTea Java Plugin - Authorization needed to proceed");
+
+        setLayout(new GridBagLayout());
+
+        JLabel jlUserName = new JLabel("Username: ");
+        JLabel jlPassword = new JLabel("Password: ");
+        JButton jbOK = new JButton("OK");
+        JButton jbCancel = new JButton("Cancel");
+
+        jtfUserName.setSize(20, 10);
+        jpfPassword.setSize(20, 10);
+
+        GridBagConstraints c;
+        
+        c = new GridBagConstraints();
+        c.fill = c.HORIZONTAL;
+        c.gridx = 0;
+        c.gridy = 0;
+        c.gridwidth = 2;
+        c.insets = new Insets(10, 5, 3, 3);
+        add(jlInfo, c);
+        
+        c = new GridBagConstraints();
+        c.gridx = 0;
+        c.gridy = 1;
+        c.insets = new Insets(10, 5, 3, 3);
+        add(jlUserName, c);
+        
+        c = new GridBagConstraints();
+        c.fill = c.HORIZONTAL;
+        c.gridx = 1;
+        c.gridy = 1;
+        c.insets = new Insets(10, 5, 3, 3);
+        c.weightx = 1.0;
+        add(jtfUserName, c);
+
+
+        c = new GridBagConstraints();
+        c.gridx = 0;
+        c.gridy = 2;
+        c.insets = new Insets(5, 5, 3, 3);
+        add(jlPassword, c);
+        
+        c = new GridBagConstraints();
+        c.fill = c.HORIZONTAL;
+        c.gridx = 1;
+        c.gridy = 2;
+        c.insets = new Insets(5, 5, 3, 3);
+        c.weightx = 1.0;
+        add(jpfPassword, c);
+
+        c = new GridBagConstraints();
+        c.anchor = c.SOUTHEAST;
+        c.gridx = 1;
+        c.gridy = 3;
+        c.insets = new Insets(5, 5, 3, 70);
+        c.weightx = 0.0;
+        add(jbCancel, c);
+        
+        c = new GridBagConstraints();
+        c.anchor = c.SOUTHEAST;
+        c.gridx = 1;
+        c.gridy = 3;
+        c.insets = new Insets(5, 5, 3, 3);
+        c.weightx = 0.0;
+        add(jbOK, c);
+        
+        setMinimumSize(new Dimension(400,150));
+        setMaximumSize(new Dimension(1024,150));
+        setAlwaysOnTop(true);
+        
+        setSize(400,150);
+        setLocationRelativeTo(null);
+
+        // OK => read supplied info and pass it on
+        jbOK.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                userCancelled = false;
+                dispose();
+            }
+        });
+        
+        // Cancel => discard supplied info and pass on an empty auth
+        jbCancel.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                userCancelled = true;
+                dispose();
+            }
+        });
+        
+        // "return" key in either user or password field => OK
+
+        jtfUserName.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                userCancelled = false;
+                dispose();
+            }
+        });
+        
+        jpfPassword.addActionListener(new ActionListener() {
+            public void actionPerformed(ActionEvent e) {
+                userCancelled = false;
+                dispose();
+            }
+        });
+    }
+
+    /**
+     * Present a dialog to the user asking them for authentication information
+     * 
+     * @param hostThe host for with authentication is needed
+     * @param port The port being accessed
+     * @param prompt The prompt (realm) as presented by the server
+     * @param type The type of server (proxy/web)
+     * @return PasswordAuthentication containing the credentials (empty credentials if user cancelled)
+     */
+    protected PasswordAuthentication askUser(String host, int port, String prompt, String type) {
+        PasswordAuthentication auth = null;
+
+        host += port != -1 ? ":" + port : "";
+
+        // This frame is reusable. So reset everything first.
+        userCancelled = true;
+        jlInfo.setText("<html>The " + type + " server at " + host + " is requesting authentication. It says \"" + prompt + "\"</html>");
+
+        try {
+            SwingUtilities.invokeAndWait( new Runnable() {
+                public void run() {
+                    // show dialog to user
+                    setVisible(true);
+                }
+            });
+        
+            PluginDebug.debug("password dialog shown");
+            
+            // wait until dialog is gone
+            while (this.isShowing()) {
+                try {
+                    Thread.sleep(200);
+                } catch (InterruptedException ie) {
+                }
+            }
+            
+            PluginDebug.debug("password dialog closed");
+
+            if (!userCancelled) {
+                auth = new PasswordAuthentication(jtfUserName.getText(), jpfPassword.getText().toCharArray());
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            
+            // Nothing else we can do. Empty auth will be returned
+        }
+
+        return auth;
+    }
+
+    public static void main(String[] args) {
+        PasswordAuthenticationDialog frame = new PasswordAuthenticationDialog();
+
+        PasswordAuthentication auth = frame.askUser("127.0.0.1", 3128, "Password for local proxy", "proxy");
+
+        System.err.println("Auth info: " + auth.getUserName() + ":" + new String(auth.getPassword()));
+        System.exit(0);
+    }
+}
--- a/plugin/icedtea/sun/applet/PluginAppletSecurityContext.java	Wed May 20 20:50:48 2009 +0100
+++ b/plugin/icedtea/sun/applet/PluginAppletSecurityContext.java	Wed May 20 21:17:02 2009 +0100
@@ -248,7 +248,7 @@
 		// an applet will be loaded at some point, we should make it the SM 
 		// that JNLPRuntime will try to install
 		if (System.getSecurityManager() == null) {
-			JNLPRuntime.initialize();
+			JNLPRuntime.initialize(/* isApplication */ false);
 		}
 
 		JNLPRuntime.disableExit();
@@ -1001,7 +1001,7 @@
 		PluginDebug.debug("target = " + target + " jsSrc=" + jsSrc + " classSrc=" + classSrc);
 		
 		// if src is not a file and class loader does not map to the same base, UniversalBrowserRead (BrowserReadPermission) must be set
-		if (jsSrc != "file://" && !classSrc.equals(jsSrc)) {
+		if (!jsSrc.equals("file://") && !jsSrc.equals("[System]") && !classSrc.equals(jsSrc)) {
 			acc.checkPermission(new BrowserReadPermission());
 		}
 	}
--- a/plugin/icedtea/sun/applet/PluginAppletViewer.java	Wed May 20 20:50:48 2009 +0100
+++ b/plugin/icedtea/sun/applet/PluginAppletViewer.java	Wed May 20 21:17:02 2009 +0100
@@ -87,6 +87,7 @@
 import java.lang.reflect.InvocationTargetException;
 import java.net.MalformedURLException;
 import java.net.SocketPermission;
+import java.net.URI;
 import java.net.URL;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
@@ -99,14 +100,14 @@
 
 import javax.swing.SwingUtilities;
 
-import com.sun.jndi.toolkit.url.UrlUtil;
-
 import net.sourceforge.jnlp.NetxPanel;
 import net.sourceforge.jnlp.runtime.JNLPClassLoader;
 import sun.awt.AppContext;
 import sun.awt.SunToolkit;
 import sun.awt.X11.XEmbeddedFrame;
 import sun.misc.Ref;
+
+import com.sun.jndi.toolkit.url.UrlUtil;
  
  /**
   * Lets us construct one using unix-style one shot behaviors
@@ -177,7 +178,7 @@
      private static PluginCallRequestFactory requestFactory;
      
      private static HashMap<Integer, String> siteCookies = new HashMap<Integer,String>();
-
+     
      private double proposedHeightFactor;
      private double proposedWidthFactor;
 
@@ -309,7 +310,7 @@
  	// Wait for the panel to initialize
     // (happens in a separate thread)
  	Applet a;
-    while ((a = panel.getApplet()) == null && panel.getAppletHandlerThread().isAlive()) {
+    while ((a = panel.getApplet()) == null && ((NetxPanel) panel).isAlive()) {
    	 try {
    		 Thread.sleep(2000);
    		 PluginDebug.debug("Waiting for applet to initialize... ");
@@ -493,7 +494,7 @@
 
              // Wait for the panel to initialize
              // (happens in a separate thread)
-             while ((o = panel.getApplet()) == null && panel.getAppletHandlerThread().isAlive()) {
+             while ((o = panel.getApplet()) == null && ((NetxPanel) panel).isAlive()) {
             	 try {
             		 Thread.sleep(2000);
             		 PluginDebug.debug("Waiting for applet to initialize...");
@@ -1005,6 +1006,49 @@
          return request.getObject();
      }
  
+     public static Object requestPluginProxyInfo(URI uri) {
+
+         String requestURI = null;
+
+         try {
+
+             // there is no easy way to get SOCKS proxy info. So, we tell mozilla that we want proxy for 
+             // an HTTP uri in case of non http/ftp protocols. If we get back a SOCKS proxy, we can 
+             // use that, if we get back an http proxy, we fallback to DIRECT connect
+
+             String scheme = uri.getScheme();
+             String port = uri.getPort() != -1 ? ":" + uri.getPort() : ""; 
+             if (!uri.getScheme().startsWith("http") && !uri.getScheme().equals("ftp"))
+                 scheme = "http";
+
+             requestURI = UrlUtil.encode(scheme + "://" + uri.getHost() + port + "/" + uri.getPath(), "UTF-8");
+         } catch (Exception e) {
+             PluginDebug.debug("Cannot construct URL from " + uri.toString() + " ... falling back to DIRECT proxy");
+             e.printStackTrace();
+             return null;
+         }
+
+         PluginCallRequest request = requestFactory.getPluginCallRequest("proxyinfo",
+                                            "plugin PluginProxyInfo " + requestURI, 
+                                            "plugin");
+         streamhandler.postCallRequest(request);
+         streamhandler.write(request.getMessage());
+         try {
+             PluginDebug.debug ("wait call request 1");
+             synchronized(request) {
+                 PluginDebug.debug ("wait call request 2");
+                 while (request.isDone() == false)
+                     request.wait();
+                 PluginDebug.debug ("wait call request 3");
+             }
+         } catch (InterruptedException e) {
+             throw new RuntimeException("Interrupted waiting for call request.",
+                                        e);
+         }
+         PluginDebug.debug (" Call DONE");
+         return request.getObject();
+     }
+     
      public static void JavaScriptFinalize(long internal)
      {
          // Prefix with dummy instance for convenience.
@@ -1591,12 +1635,14 @@
     							 att = att.replace("&amp;", "&");
     							 att = att.replace("&#10;", "\n");
     							 att = att.replace("&#13;", "\r");
+    							 att = att.replace("&quot;", "\"");
 
     							 val = val.replace("&gt;", ">");
     							 val = val.replace("&lt;", "<");
     							 val = val.replace("&amp;", "&");
     							 val = val.replace("&#10;", "\n");
     							 val = val.replace("&#13;", "\r");
+    							 val = val.replace("&quot;", "\"");
     							 PluginDebug.debug("PUT " + att + " = " + val);
    							     atts.put(att.toLowerCase(), val);
     						 } else {
@@ -1677,13 +1723,6 @@
                              atts.put("type", ((String) atts.get("java_type")));
                          }
 
-    					 // The <OBJECT> attribute codebase isn't what
-    					 // we want when not dealing with jars. If its 
-    					 // defined, remove it in that case.
-    					 if(atts.get("archive") == null && atts.get("codebase") != null) {
-    						 atts.remove("codebase");
-    					 }
-
     					 if (atts.get("width") == null || !isInt(atts.get("width"))) {
     						 atts.put("width", "1000");
     						 atts.put("widthPercentage", 100);
--- a/plugin/icedtea/sun/applet/PluginCallRequestFactory.java	Wed May 20 20:50:48 2009 +0100
+++ b/plugin/icedtea/sun/applet/PluginCallRequestFactory.java	Wed May 20 21:17:02 2009 +0100
@@ -49,7 +49,9 @@
 			return new VoidPluginCallRequest(message, returnString);
 		} else if (id == "window") {
 			return new GetWindowPluginCallRequest(message, returnString);
-		} else {
+		} else if (id == "proxyinfo") {
+            return new PluginProxyInfoRequest(message, returnString);
+        } else {
 			throw new RuntimeException ("Unknown plugin call request type requested from factory");
 		}
 		
--- a/plugin/icedtea/sun/applet/PluginMain.java	Wed May 20 20:50:48 2009 +0100
+++ b/plugin/icedtea/sun/applet/PluginMain.java	Wed May 20 21:17:02 2009 +0100
@@ -67,16 +67,18 @@
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.PrintStream;
-import java.net.Socket;
+import java.net.Authenticator;
+import java.net.PasswordAuthentication;
+import java.net.ProxySelector;
 import java.util.Enumeration;
+import java.util.HashMap;
 import java.util.Properties;
 
+import javax.net.ssl.HttpsURLConnection;
 import javax.net.ssl.SSLContext;
 import javax.net.ssl.SSLSocketFactory;
 import javax.net.ssl.TrustManager;
 
-import javax.net.ssl.HttpsURLConnection;
-
 import net.sourceforge.jnlp.security.VariableX509TrustManager;
 
 /**
@@ -212,6 +214,10 @@
 		    System.err.println("Unable to set SSLSocketfactory (may _prevent_ access to sites that should be trusted)! Continuing anyway...");
 		    e.printStackTrace();
 		}
+        
+		// plug in a custom authenticator and proxy selector
+        Authenticator.setDefault(new CustomAuthenticator());
+        ProxySelector.setDefault(new PluginProxySelector());
 	}
 
     static boolean messageAvailable() {
@@ -221,6 +227,26 @@
     static String getMessage() {
     	return streamHandler.getMessage();
     }
+    
+    static class CustomAuthenticator extends Authenticator {
+        
+        public PasswordAuthentication getPasswordAuthentication() {
+
+            // No security check is required here, because the only way to 
+            // set parameters for which auth info is needed 
+            // (Authenticator:requestPasswordAuthentication()), has a security 
+            // check
+
+            String type = this.getRequestorType() == RequestorType.PROXY ? "proxy" : "web"; 
+
+            // request auth info from user
+            PasswordAuthenticationDialog pwDialog = new PasswordAuthenticationDialog();
+            PasswordAuthentication auth = pwDialog.askUser(this.getRequestingHost(), this.getRequestingPort(), this.getRequestingPrompt(), type);
+            
+            // send it along
+            return auth;
+        }
+    }
 
     /**
      * Behaves like the 'tee' command, sends output to both actual std stream and a
@@ -264,7 +290,9 @@
         @Override
         public void write(byte[] buf, int off, int len) {
             logFile.write(buf, off, len);
-            super.write(buf, off, len);
+
+            if (!redirectStreams)
+                super.write(buf, off, len);
         }
 
         @Override
--- a/plugin/icedtea/sun/applet/PluginMessageConsumer.java	Wed May 20 20:50:48 2009 +0100
+++ b/plugin/icedtea/sun/applet/PluginMessageConsumer.java	Wed May 20 21:17:02 2009 +0100
@@ -35,7 +35,6 @@
 obligated to do so.  If you do not wish to do so, delete this
 exception statement from your version. */
 
-
 package sun.applet;
 
 import java.util.ArrayList;
@@ -45,17 +44,19 @@
 
 class PluginMessageConsumer {
 
-	int MAX_WORKERS = 3;
+	int MAX_WORKERS = 20;
 	LinkedList<String> readQueue = new LinkedList<String>();
 	ArrayList<PluginMessageHandlerWorker> workers = new ArrayList<PluginMessageHandlerWorker>();
 	PluginStreamHandler streamHandler = null;
+	AppletSecurity as;
 
 	public PluginMessageConsumer(PluginStreamHandler streamHandler) {
 		
-		AppletSecurity as = new AppletSecurity();
+		as = new AppletSecurity();
 		this.streamHandler = streamHandler;
 
-		for (int i=0; i < MAX_WORKERS; i++) {
+		// create some workers at the start...
+		for (int i=0; i < 3; i++) {
 			PluginDebug.debug("Creating worker " + i);
 			PluginMessageHandlerWorker worker = new PluginMessageHandlerWorker(streamHandler, i, as);
 			worker.start();
@@ -96,6 +97,19 @@
 					return worker;
 				}
 			}
+			
+			// If we have less than MAX_WORKERS, create a new worker
+			if (workers.size() < MAX_WORKERS) {
+			    PluginDebug.debug("Cannot find free worker, creating worker " + workers.size());
+			    PluginMessageHandlerWorker worker = new PluginMessageHandlerWorker(streamHandler, workers.size(), as);
+			    worker.start();
+			    workers.add(worker);
+			    worker.busy();
+			    return worker;
+			} else {
+			    // else wait
+			}
+
 			Thread.yield();
 		}
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugin/icedtea/sun/applet/PluginProxyInfoRequest.java	Wed May 20 21:17:02 2009 +0100
@@ -0,0 +1,85 @@
+/* PluginProxyInfoRequest -- Object representing a request for proxy information from the browser
+   Copyright (C) 2009  Red Hat
+
+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. */
+
+package sun.applet;
+
+import java.net.MalformedURLException;
+import java.net.URI;
+
+/**
+ * This class represents a request object for proxy information for a given URI
+ */
+
+public class PluginProxyInfoRequest extends PluginCallRequest {
+    
+    URI internal = null;
+
+    public PluginProxyInfoRequest(String message, String returnString) {
+        super(message, returnString);
+    }
+    
+    public void parseReturn(String proxyInfo) {
+
+        // try to parse the proxy information. If things go wrong, do nothing .. 
+        // this will keep internal = null which forces a direct connection
+
+    	PluginDebug.debug ("PluginProxyInfoRequest GOT: " + proxyInfo);
+    	String[] messageComponents = proxyInfo.split(" ");
+
+    	try {
+    	    internal = new URI(messageComponents[2], null, messageComponents[3], Integer.parseInt(messageComponents[4]), null, null, null);
+    	} catch (Exception e) {
+    	    // do nothing
+    	}
+
+        setDone(true);
+    }
+
+    /**
+     * Returns whether the given message is serviceable by this object
+     * 
+     * @param message The message to service
+     * @return boolean indicating if message is serviceable
+     */
+    public boolean serviceable(String message) {
+    	return message.startsWith("plugin PluginProxyInfo");
+    }
+
+    public URI getObject() {
+    	return this.internal;
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/plugin/icedtea/sun/applet/PluginProxySelector.java	Wed May 20 21:17:02 2009 +0100
@@ -0,0 +1,195 @@
+/* PluginProxySelector -- proxy selector for all connections from applets and the plugin
+   Copyright (C) 2009  Red Hat
+
+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. */
+
+package sun.applet;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.InetSocketAddress;
+import java.net.Proxy;
+import java.net.ProxySelector;
+import java.net.SocketAddress;
+import java.net.URI;
+import java.util.Date;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+/**
+ * Proxy selector implementation for plugin network functions.
+ * 
+ * This class fetches proxy information from the web browser and 
+ * uses that information in the context of all network connection 
+ * (plugin specific and applet connections) as applicable
+ * 
+ */
+
+public class PluginProxySelector extends ProxySelector {
+
+    private TimedHashMap<String, Proxy> proxyCache = new TimedHashMap<String, Proxy>(); 
+
+
+    @Override
+    public void connectFailed(URI uri, SocketAddress sa, IOException ioe) {
+        // If the connection fails, there is little we can do here. Just print the exception
+        ioe.printStackTrace();
+    }
+
+    /**
+     * Selects the appropriate proxy (or DIRECT connection method) for the given URI
+     * 
+     * @param uri The URI being accessed
+     * @return A list of Proxy objects that are usable for this URI
+     */
+    @Override
+    public List<Proxy> select(URI uri) {
+
+        List<Proxy> proxyList = new ArrayList<Proxy>();
+
+        // check cache first
+        Proxy cachedProxy = checkCache(uri);
+        if (cachedProxy != null) {
+            proxyList.add(cachedProxy);
+            return proxyList;
+        }
+
+        // Nothing usable in cache. Fetch info from browser
+        Proxy proxy = Proxy.NO_PROXY;
+        Object o = PluginAppletViewer.requestPluginProxyInfo(uri);
+
+        // If the browser returned anything, try to parse it. If anything in the try block fails, the fallback is direct connection
+        try {
+            if (o != null) {
+                PluginDebug.debug("Proxy URI = " + o);
+                URI proxyURI = (URI) o;
+                
+                // If origin uri is http/ftp, we're good. If origin uri is not that, the proxy _must_ be socks, else we fallback to direct
+                if (uri.getScheme().startsWith("http") || uri.getScheme().equals("ftp") || proxyURI.getScheme().startsWith("socks")) {
+
+                    Proxy.Type type = proxyURI.getScheme().equals("http") ? Proxy.Type.HTTP : Proxy.Type.SOCKS; 
+                    InetSocketAddress socketAddr = new InetSocketAddress(proxyURI.getHost(), proxyURI.getPort());
+
+                    proxy = new Proxy(type, socketAddr);
+
+                    String uriKey = uri.getScheme() + "://" + uri.getHost();
+                    proxyCache.put(uriKey, proxy);
+                } else {
+                    PluginDebug.debug("Proxy " + proxyURI + " cannot be used for " + uri + ". Falling back to DIRECT");
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        proxyList.add(proxy);
+
+        PluginDebug.debug("Proxy for " + uri.toString() + " is " + proxy);
+
+        return proxyList;
+    }
+
+    /** 
+     * Checks to see if proxy information is already cached. 
+     * 
+     * @param uri The URI to check
+     * @return The cached Proxy. null if there is no suitable cached proxy. 
+     */
+    private Proxy checkCache(URI uri) {
+        
+        String uriKey = uri.getScheme() + "://" + uri.getHost();
+        if (proxyCache.get(uriKey) != null) {
+            return proxyCache.get(uriKey);
+        }
+
+        return null;
+    }
+    
+    /**
+     * Simple utility class that extends HashMap by adding an expiry to the entries.
+     * 
+     * This map stores entries, and returns them only if the entries were last accessed within time t=10 seconds
+     *
+     * @param <K> The key type
+     * @param <V> The Object type
+     */
+
+    private class TimedHashMap<K,V> extends HashMap<K,V> {
+
+        HashMap<K, Long> timeStamps = new HashMap<K, Long>();
+        Long expiry = 10000L;
+        
+        /**
+         * Store the item in the map and associate a timestamp with it
+         * 
+         * @param key The key
+         * @param value The value to store
+         */
+        public V put(K key, V value) {
+            timeStamps.put(key, new Date().getTime());
+            return super.put(key, value);
+        }
+
+        /**
+         * Return cached item if it has not already expired.
+         * 
+         * Before returning, this method also resets the "last accessed" 
+         * time for this entry, so it is good for another 10 seconds
+         * 
+         * @param key The key
+         */
+        public V get(Object key) {
+
+            Long now = new Date().getTime();
+
+            if (super.containsKey(key)) {
+                Long age = now - timeStamps.get(key);
+
+                // Item exists. If it has not expired, renew its access time and return it 
+                if (age <= expiry) {
+                    PluginDebug.debug("Returning proxy " + super.get(key) + " from cache for " + key);
+                    timeStamps.put((K) key, (new Date()).getTime());
+                    return super.get(key);
+                } else {
+                    PluginDebug.debug("Proxy cache for " + key + " has expired (age=" + age/1000.0 + " seconds)");
+                }
+            } 
+
+            return null;
+        }
+    }
+    
+}
--- a/plugin/icedtea/sun/applet/PluginStreamHandler.java	Wed May 20 20:50:48 2009 +0100
+++ b/plugin/icedtea/sun/applet/PluginStreamHandler.java	Wed May 20 21:17:02 2009 +0100
@@ -134,7 +134,7 @@
     	    		long b4 = new Date().getTime();
 
     				String s = read();
-
+                    
     	    		long after = new Date().getTime();
 
     	    		totalWait += (after - b4);
@@ -228,7 +228,12 @@
     
 		if (msgComponents.length < 2)
 			return;
-	
+
+        if (msgComponents[0].startsWith("plugin")) {
+            handlePluginMessage(message);
+            return;
+        }
+
     	// type and identifier are guaranteed to be there
     	String type = msgComponents[0];
     	final int identifier = Integer.parseInt(msgComponents[1]);
@@ -297,6 +302,17 @@
     	}
     }
 
+    private void handlePluginMessage(String message) {
+        if (message.equals("plugin showconsole")) {
+            showConsole();
+        } else if (message.equals("plugin hideconsole")) {
+            hideConsole();            
+        } else {
+            // else this is something that was specifically requested
+            finishCallRequest(message);
+        }
+    }
+
     public void postCallRequest(PluginCallRequest request) {
         synchronized(queue) {
    			queue.post(request);
@@ -321,6 +337,8 @@
 
     			while (!request.serviceable(message)) {
 
+     				PluginDebug.debug(request + " cannot service " + message);
+    			    
     				// something is very wrong.. we have a message to 
     				// process, but no one to service it
     				if (count >= size) {
@@ -382,10 +400,6 @@
                 AppletSecurityContextManager.dumpStore(0);
                 PluginDebug.debug("APPLETVIEWER: exiting appletviewer");
                 System.exit(0);
-            } else if (message.equals("showconsole")) {
-                showConsole();
-            } else if (message.equals("hideconsole")) {
-                hideConsole();            
             }
     	} catch (IOException e) {
     	       e.printStackTrace();