Mercurial > hg > icedtea6
changeset 2254:c764b38139a5
PR556: Re-implement applet initialization to be serialialized, to fix current
and future possible race conditions.
author | Deepak Bhole <dbhole@redhat.com> |
---|---|
date | Thu, 16 Sep 2010 13:03:57 -0400 |
parents | 1c5acca8abfd |
children | a1ccc755c8f7 |
files | ChangeLog NEWS plugin/icedteanp/IcedTeaJavaRequestProcessor.h plugin/icedteanp/IcedTeaNPPlugin.cc plugin/icedteanp/IcedTeaNPPlugin.h plugin/icedteanp/IcedTeaPluginUtils.cc plugin/icedteanp/java/sun/applet/PluginAppletViewer.java plugin/icedteanp/java/sun/applet/PluginMessageConsumer.java |
diffstat | 8 files changed, 234 insertions(+), 317 deletions(-) [+] |
line wrap: on
line diff
--- a/ChangeLog Mon Sep 13 10:21:58 2010 -0400 +++ b/ChangeLog Thu Sep 16 13:03:57 2010 -0400 @@ -1,3 +1,44 @@ +2010-09-15 Deepak Bhole <dbhole@redhat.com> + + PR556: Re-implement applet initialization to be serialialized, to fix + current and future possible race conditions. + * plugin/icedteanp/IcedTeaJavaRequestProcessor.h: Updated timeout to 3 + minutes. + * plugin/icedteanp/IcedTeaNPPlugin.cc + (ITNP_New): Remove the tag_message string, don't send any data to Java + side and instead, populate the new ITNPPluginData.applet_tag field with + the tag info. Do cleanup accordingly. + (ITNP_SetWindow): Send all (handle, size and tag) initialization + information to java in a single message. Cleanup accordingly for newly + added variables. + * plugin/icedteanp/IcedTeaPluginUtils.cc + (getReference): Use a negative decreasing reference count to prevent + clashes with references for Java-side requests. + * plugin/icedteanp/IcedTeaNPPlugin.h: Rename the instance_string field of + ITNPPluginData to instance_id, and add an applet_tag field. + * plugin/icedteanp/java/sun/applet/PluginAppletViewer.java + (PluginAppletPanelFactory.createPanel): Remove code that tried to account + for percent heights and widths. This is done by the browser now. + (reFrame): Same. + (PluginAppletViewer): Update constructor to not take height and width + factor information. + (handleMessage): Update function for new protocol that now passes all + information relevant to initialization in a single message. + (skipSpace): Accept a new int array that contains the character at the + current position in the stream. Use the value accordingly. + (scanIdentifier): Same. + (skipComment): Same. + (scanTag): Same. + (parse): Updated all function signatures to accept width and height info. + Initialize an int array (for fake pass-by-reference) that contains + position of current character in the stream. Inject width and height + information into the atts table. + * plugin/icedteanp/java/sun/applet/PluginMessageConsumer.java: Updated + thread count needed for initialization. + (okayToProcess): Remove function that is no longer needed with the + serialized initialization code. + (ConsumerThread.run): Remove call to okayToProcess(). + 2010-09-13 Omair Majid <omajid@redhat.com> Add a new man page for netx's javaws.
--- a/NEWS Mon Sep 13 10:21:58 2010 -0400 +++ b/NEWS Thu Sep 16 13:03:57 2010 -0400 @@ -16,6 +16,8 @@ - S6438179: XToolkit.isTraySupported() result has nothing to do with the system tray * Netx - A new man page for javaws. +* Plugin + - PR556: Applet initialization code is prone to race conditions New in release 1.9 (2010-09-07):
--- a/plugin/icedteanp/IcedTeaJavaRequestProcessor.h Mon Sep 13 10:21:58 2010 -0400 +++ b/plugin/icedteanp/IcedTeaJavaRequestProcessor.h Thu Sep 16 13:03:57 2010 -0400 @@ -46,7 +46,7 @@ #include "IcedTeaNPPlugin.h" #include "IcedTeaPluginUtils.h" -#define REQUESTTIMEOUT 120 +#define REQUESTTIMEOUT 180 /* * This struct holds data specific to a Java operation requested by the plugin
--- a/plugin/icedteanp/IcedTeaNPPlugin.cc Mon Sep 13 10:21:58 2010 -0400 +++ b/plugin/icedteanp/IcedTeaNPPlugin.cc Thu Sep 16 13:03:57 2010 -0400 @@ -249,7 +249,7 @@ // Creates a new icedtea np plugin instance. This function creates a // ITNPPluginData* and stores it in instance->pdata. The following -// ITNPPluginData fiels are initialized: instance_string, in_pipe_name, +// ITNPPluginData fiels are initialized: instance_id, in_pipe_name, // in_from_appletviewer, in_watch_source, out_pipe_name, // out_to_appletviewer, out_watch_source, appletviewer_mutex, owner, // appletviewer_alive. In addition two pipe files are created. All @@ -284,7 +284,6 @@ gchar* documentbase = NULL; gchar* read_message = NULL; gchar* applet_tag = NULL; - gchar* tag_message = NULL; gchar* cookie_info = NULL; NPObject* npPluginObj = NULL; @@ -308,17 +307,17 @@ // start the jvm if needed start_jvm_if_needed(); - // Initialize data->instance_string. + // Initialize data->instance_id. // - // instance_string should be unique for this process so we use a + // instance_id should be unique for this process so we use a // combination of getpid and plugin_instance_counter. // // Critical region. Reference and increment plugin_instance_counter // global. g_mutex_lock (plugin_instance_mutex); - // data->instance_string - data->instance_string = g_strdup_printf ("%d", + // data->instance_id + data->instance_id = g_strdup_printf ("%d", instance_counter); g_mutex_unlock (plugin_instance_mutex); @@ -335,11 +334,8 @@ // Send applet tag message to appletviewer. applet_tag = plugin_create_applet_tag (argc, argn, argv); - tag_message = (gchar*) malloc(strlen(applet_tag)*sizeof(gchar) + strlen(documentbase)*sizeof(gchar) + 32); - g_sprintf(tag_message, "instance %d tag %s %s", instance_counter, documentbase, applet_tag); - - //plugin_send_message_to_appletviewer (data, data->instance_string); - plugin_send_message_to_appletviewer (tag_message); + data->applet_tag = (gchar*) malloc(strlen(applet_tag)*sizeof(gchar) + strlen(documentbase)*sizeof(gchar) + 32); + g_sprintf(data->applet_tag, "tag %s %s", documentbase, applet_tag); data->is_applet_instance = true; } @@ -371,8 +367,12 @@ data->appletviewer_mutex = NULL; // cleanup_instance_string: - g_free (data->instance_string); - data->instance_string = NULL; + g_free (data->instance_id); + data->instance_id = NULL; + + // cleanup applet tag: + g_free (data->applet_tag); + data->applet_tag = NULL; // cleanup_data: // Eliminate back-pointer to plugin instance. @@ -385,8 +385,6 @@ instance->pdata = NULL; cleanup_done: - g_free (tag_message); - tag_message = NULL; g_free (applet_tag); applet_tag = NULL; g_free (read_message); @@ -750,28 +748,33 @@ } else { + // Else this is initialization PLUGIN_DEBUG ("ITNP_SetWindow: setting window.\n"); // Critical region. Send messages to appletviewer. g_mutex_lock (data->appletviewer_mutex); - gchar *window_message = g_strdup_printf ("instance %d handle %ld", - id, (gulong) window->window); - plugin_send_message_to_appletviewer (window_message); - g_free (window_message); - - window_message = g_strdup_printf ("instance %d width %d height %d", - id, - window->width, - window->height); - plugin_send_message_to_appletviewer (window_message); - g_free (window_message); - window_message = NULL; + // Store the window handle and dimensions + data->window_handle = window->window; + data->window_width = window->width; + data->window_height = window->height; + + // Now we have everything. Send this data to the Java side + + gchar* instance_msg = g_strdup_printf ("instance %s handle %ld width %d height %d %s", + data->instance_id, + (gulong) data->window_handle, + data->window_width, + data->window_height, + data->applet_tag); + + plugin_send_message_to_appletviewer (instance_msg); + + g_free(instance_msg); + instance_msg = NULL; g_mutex_unlock (data->appletviewer_mutex); - // Store the window handle. - data->window_handle = window->window; } PLUGIN_DEBUG ("ITNP_SetWindow return\n"); @@ -1921,8 +1924,12 @@ tofree->appletviewer_mutex = NULL; // cleanup_instance_string: - g_free (tofree->instance_string); - tofree->instance_string = NULL; + g_free (tofree->instance_id); + tofree->instance_id = NULL; + + // cleanup applet tag + g_free (tofree->applet_tag); + tofree->applet_tag = NULL; g_free(tofree->source); tofree->source = NULL;
--- a/plugin/icedteanp/IcedTeaNPPlugin.h Mon Sep 13 10:21:58 2010 -0400 +++ b/plugin/icedteanp/IcedTeaNPPlugin.h Thu Sep 16 13:03:57 2010 -0400 @@ -68,7 +68,9 @@ struct ITNPPluginData { // A unique identifier for this plugin window. - gchar* instance_string; + gchar* instance_id; + // The applet tag sent to Java side + gchar* applet_tag; // Mutex to protect appletviewer_alive. GMutex* appletviewer_mutex; // Back-pointer to the plugin instance to which this data belongs.
--- a/plugin/icedteanp/IcedTeaPluginUtils.cc Mon Sep 13 10:21:58 2010 -0400 +++ b/plugin/icedteanp/IcedTeaPluginUtils.cc Thu Sep 16 13:03:57 2010 -0400 @@ -49,7 +49,7 @@ ************************************************/ // Initialize static variables -int IcedTeaPluginUtilities::reference = 0; +int IcedTeaPluginUtilities::reference = -1; pthread_mutex_t IcedTeaPluginUtilities::reference_mutex = PTHREAD_MUTEX_INITIALIZER; std::map<void*, NPP>* IcedTeaPluginUtilities::instance_map = new std::map<void*, NPP>(); std::map<std::string, NPObject*>* IcedTeaPluginUtilities::object_map = new std::map<std::string, NPObject*>(); @@ -224,11 +224,11 @@ pthread_mutex_lock(&reference_mutex); // If we are nearing the max, reset - if (reference > 0x7FFFFFFF - 10) { - reference = 0; + if (reference < -0x7FFFFFFF + 10) { + reference = -1; } - reference++; + reference--; pthread_mutex_unlock(&reference_mutex); return reference;
--- a/plugin/icedteanp/java/sun/applet/PluginAppletViewer.java Mon Sep 13 10:21:58 2010 -0400 +++ b/plugin/icedteanp/java/sun/applet/PluginAppletViewer.java Thu Sep 16 13:03:57 2010 -0400 @@ -137,21 +137,10 @@ } }); - double heightFactor = 1.0; - double widthFactor = 1.0; - - if (atts.get("heightPercentage") != null) { - heightFactor = (Integer) atts.get("heightPercentage")/100.0; - } - - if (atts.get("widthPercentage") != null) { - widthFactor = (Integer) atts.get("widthPercentage")/100.0; - } // put inside initial 0 handle frame - PluginAppletViewer.reFrame(null, identifier, System.out, - heightFactor, widthFactor, 0, panel); + PluginAppletViewer.reFrame(null, identifier, System.out, 0, panel); panel.init(); @@ -362,14 +351,12 @@ private static HashMap<Integer, PAV_INIT_STATUS> status = new HashMap<Integer,PAV_INIT_STATUS>(); - private double proposedHeightFactor; - private double proposedWidthFactor; private long handle = 0; private WindowListener windowEventListener = null; private AppletEventListener appletEventListener = null; - public static final int APPLET_TIMEOUT = 60000; + public static final int APPLET_TIMEOUT = 180000; private static Long requestIdentityCounter = 0L; @@ -381,8 +368,7 @@ public static void reFrame(PluginAppletViewer oldFrame, int identifier, PrintStream statusMsgStream, - double heightFactor, double widthFactor, long handle, - AppletViewerPanel panel) { + long handle, AppletViewerPanel panel) { PluginDebug.debug("Reframing " + panel); @@ -393,7 +379,7 @@ if (oldFrame != null && handle == oldFrame.handle) return; - PluginAppletViewer newFrame = new PluginAppletViewer(handle, identifier, statusMsgStream, heightFactor, widthFactor, panel); + PluginAppletViewer newFrame = new PluginAppletViewer(handle, identifier, statusMsgStream, panel); if (oldFrame != null) { applets.remove(oldFrame.identifier); @@ -423,14 +409,12 @@ * Create new plugin appletviewer frame */ private PluginAppletViewer(long handle, final int identifier, - PrintStream statusMsgStream, double heightFactor, - double widthFactor, AppletViewerPanel appletPanel) { + PrintStream statusMsgStream, + AppletViewerPanel appletPanel) { super(handle, true); this.statusMsgStream = statusMsgStream; this.identifier = identifier; - this.proposedHeightFactor = heightFactor; - this.proposedWidthFactor = widthFactor; this.panel = appletPanel; if (!appletPanels.contains(panel)) @@ -525,87 +509,63 @@ PluginDebug.debug("PAV handling: " + message); try { - if (message.startsWith("tag")) { + if (message.startsWith("handle")) { - // tag and handle must both be set before parsing, so we need - // synchronization here, as the setting of these variables - // may happen in independent threads + // Extract the information from the message + String[] msgParts = new String[4]; + for (int i=0; i < 3; i++) { + int spaceLocation = message.indexOf(' '); + int nextSpaceLocation = message.indexOf(' ', spaceLocation+1); + msgParts[i] = message.substring(spaceLocation + 1, nextSpaceLocation); + message = message.substring(nextSpaceLocation + 1); + } - synchronized(requests) { + long handle = Long.parseLong(msgParts[0]); + String width = msgParts[1]; + String height = msgParts[2]; - // Check if we should proceed with init - // (=> no if destroy was called after tag, but before - // handle) - if (status.containsKey(identifier) && - status.get(identifier).equals(PAV_INIT_STATUS.INACTIVE)) { + int spaceLocation = message.indexOf(' ', "tag".length()+1); + String documentBase = + UrlUtil.decode(message.substring("tag".length() + 1, spaceLocation)); + String tag = message.substring(spaceLocation+1); - PluginDebug.debug("Inactive flag set. Refusing to initialize instance " + identifier); - requests.remove(identifier); - return; - - } + System.err.println("Handle = " + handle + "\n" + + "Width = " + width + "\n" + + "Height = " + height + "\n" + + "DocumentBase = " + documentBase + "\n" + + "Tag = " + tag); status.put(identifier, PAV_INIT_STATUS.PRE_INIT); + PluginAppletViewer.parse + (identifier, handle, width, height, + new StringReader(tag), + new URL(documentBase)); - PluginParseRequest request = requests.get(identifier); - if (request == null) { - request = new PluginParseRequest(); - requests.put(identifier, request); - } - int index = message.indexOf(' ', "tag".length() + 1); - request.documentbase = - UrlUtil.decode(message.substring("tag".length() + 1, index)); - request.tag = message.substring(index + 1); - PluginDebug.debug ("REQUEST TAG: " + request.tag + " " + - Thread.currentThread()); + + int maxWait = APPLET_TIMEOUT; // wait for applet to fully load + int wait = 0; + while (!status.get(identifier).equals(PAV_INIT_STATUS.INIT_COMPLETE) && + (wait < maxWait)) { - PluginDebug.debug ("REQUEST TAG, PARSING " + - Thread.currentThread()); - PluginAppletViewer.parse - (identifier, request.handle, - new StringReader(request.tag), - new URL(request.documentbase)); - requests.remove(identifier); + try { + Thread.sleep(50); + wait += 50; + } catch (InterruptedException ie) { + // just wait + } + } - // Panel initialization cannot be aborted mid-way. - // Once it is initialized, double check to see if this - // panel needs to stay around.. - if (status.get(identifier).equals(PAV_INIT_STATUS.INACTIVE)) { - PluginDebug.debug("Inactive flag set. Destroying applet instance " + identifier); - applets.get(identifier).handleMessage(-1, "destroy"); - } - } + if (!status.get(identifier).equals(PAV_INIT_STATUS.INIT_COMPLETE)) + throw new Exception("Applet initialization timeout"); + + PluginAppletViewer oldFrame = applets.get(identifier); + reFrame(oldFrame, oldFrame.identifier, oldFrame.statusMsgStream, + handle, oldFrame.panel); } else { PluginDebug.debug ("Handling message: " + message + " instance " + identifier + " " + Thread.currentThread()); - // Destroy may be called while initialization is still going - // on. We therefore special case it. - if (!applets.containsKey(identifier) && message.equals("destroy")) { - - // Set the status to inactive right away. Doesn't matter if it - // gets clobbered during init. due to a race. That is what the - // double check below is for. - PluginDebug.debug("Destroy called during initialization. Delaying destruction."); - status.put(identifier, PAV_INIT_STATUS.INACTIVE); - - // We have set the flags. We now lock what stage 1 and 2 - // lock on, and force a synchronous status check+action. - synchronized (requests) { - // re-check (inside lock) if the applet is - // initialized at this point. - if (applets.containsKey(identifier)) { - PluginDebug.debug("Init done. destroying normally."); - applets.get(identifier).handleMessage(reference, message); - } else { - } - } // unlock - - // we're done here - return; - } - - // For messages other than destroy, wait till initialization finishes + // Wait till initialization finishes while (!applets.containsKey(identifier) && ( !status.containsKey(identifier) || @@ -617,37 +577,7 @@ if (status.get(identifier).equals(PAV_INIT_STATUS.INACTIVE)) return; - if (message.startsWith("handle")) { - - PluginDebug.debug("handle command waiting for applet to complete loading."); - int maxWait = APPLET_TIMEOUT; // wait for applet to fully load - int wait = 0; - while (!status.get(identifier).equals(PAV_INIT_STATUS.INIT_COMPLETE) && - (wait < maxWait)) { - - try { - Thread.sleep(50); - wait += 50; - } catch (InterruptedException ie) { - // just wait - } - } - - if (!status.get(identifier).equals(PAV_INIT_STATUS.INIT_COMPLETE)) - throw new Exception("Applet initialization timeout"); - - PluginDebug.debug("Applet loading complete. Proceeding to reframe."); - long handle = Long.parseLong - (message.substring("handle".length() + 1)); - - PluginAppletViewer oldFrame = applets.get(identifier); - reFrame(oldFrame, oldFrame.identifier, oldFrame.statusMsgStream, - oldFrame.proposedHeightFactor, oldFrame.proposedWidthFactor, - handle, oldFrame.panel); - - } else { - applets.get(identifier).handleMessage(reference, message); - } + applets.get(identifier).handleMessage(reference, message); } } catch (Exception e) { @@ -668,21 +598,23 @@ // Wait for panel to come alive int maxWait = APPLET_TIMEOUT; // wait for panel to come alive - int wait = 0; + int wait = 0; while (!status.get(identifier).equals(PAV_INIT_STATUS.INIT_COMPLETE) && wait < maxWait) { - try { - Thread.sleep(50); - wait += 50; - } catch (InterruptedException ie) { - // just wait - } - } + + try { + Thread.sleep(50); + wait += 50; + } catch (InterruptedException ie) { + // just wait + } + } + // 0 => width, 1=> width_value, 2 => height, 3=> height_value String[] dimMsg = message.split(" "); - final int height = (int) (proposedHeightFactor*Integer.parseInt(dimMsg[3])); - final int width = (int) (proposedWidthFactor*Integer.parseInt(dimMsg[1])); + final int height = (int) (Integer.parseInt(dimMsg[3])); + final int width = (int) (Integer.parseInt(dimMsg[1])); if (panel instanceof NetxPanel) ((NetxPanel) panel).updateSizeInAtts(height, width); @@ -708,6 +640,9 @@ panel.setSize(width, height); panel.validate(); + + panel.applet.resize(width, height); + panel.applet.validate(); } }); } catch (InterruptedException e) { @@ -1642,60 +1577,55 @@ /** - * The current character. - */ - static int c; - - /** * Scan spaces. */ - public static void skipSpace(Reader in) throws IOException { - while ((c >= 0) && - ((c == ' ') || (c == '\t') || (c == '\n') || (c == '\r'))) { - c = in.read(); + public static void skipSpace(int[] c, Reader in) throws IOException { + while ((c[0] >= 0) && + ((c[0] == ' ') || (c[0] == '\t') || (c[0] == '\n') || (c[0] == '\r'))) { + c[0] = in.read(); } } /** * Scan identifier */ - public static String scanIdentifier(Reader in) throws IOException { + public static String scanIdentifier(int[] c, Reader in) throws IOException { StringBuffer buf = new StringBuffer(); - if (c == '!') { + if (c[0] == '!') { // Technically, we should be scanning for '!--' but we are reading // from a stream, and there is no way to peek ahead. That said, // a ! at this point can only mean comment here afaik, so we // should be okay - skipComment(in); + skipComment(c, in); return ""; } while (true) { - if (((c >= 'a') && (c <= 'z')) || - ((c >= 'A') && (c <= 'Z')) || - ((c >= '0') && (c <= '9')) || (c == '_')) { - buf.append((char)c); - c = in.read(); + if (((c[0] >= 'a') && (c[0] <= 'z')) || + ((c[0] >= 'A') && (c[0] <= 'Z')) || + ((c[0] >= '0') && (c[0] <= '9')) || (c[0] == '_')) { + buf.append((char)c[0]); + c[0] = in.read(); } else { return buf.toString(); } } } - public static void skipComment(Reader in) throws IOException { + public static void skipComment(int[] c, Reader in) throws IOException { StringBuffer buf = new StringBuffer(); boolean commentHeaderPassed = false; - c = in.read(); - buf.append((char)c); + c[0] = in.read(); + buf.append((char)c[0]); while (true) { - if (c == '-' && (c = in.read()) == '-') { - buf.append((char)c); + if (c[0] == '-' && (c[0] = in.read()) == '-') { + buf.append((char)c[0]); if (commentHeaderPassed) { // -- encountered ... is > next? - if ((c = in.read()) == '>') { - buf.append((char)c); + if ((c[0] = in.read()) == '>') { + buf.append((char)c[0]); PluginDebug.debug("Comment skipped: " + buf.toString()); @@ -1708,46 +1638,46 @@ } } else if (commentHeaderPassed == false) { - buf.append((char)c); + buf.append((char)c[0]); PluginDebug.debug("Warning: Attempted to skip comment, but this tag does not appear to be a comment: " + buf.toString()); return; } - c = in.read(); - buf.append((char)c); + c[0] = in.read(); + buf.append((char)c[0]); } } /** * Scan tag */ - public static Hashtable scanTag(Reader in) throws IOException { + public static Hashtable scanTag(int[] c, Reader in) throws IOException { Hashtable atts = new Hashtable(); - skipSpace(in); - while (c >= 0 && c != '>') { - String att = scanIdentifier(in); + skipSpace(c, in); + while (c[0] >= 0 && c[0] != '>') { + String att = scanIdentifier(c, in); String val = ""; - skipSpace(in); - if (c == '=') { + skipSpace(c, in); + if (c[0] == '=') { int quote = -1; - c = in.read(); - skipSpace(in); - if ((c == '\'') || (c == '\"')) { - quote = c; - c = in.read(); + c[0] = in.read(); + skipSpace(c, in); + if ((c[0] == '\'') || (c[0] == '\"')) { + quote = c[0]; + c[0] = in.read(); } StringBuffer buf = new StringBuffer(); - while ((c > 0) && - (((quote < 0) && (c != ' ') && (c != '\t') && - (c != '\n') && (c != '\r') && (c != '>')) - || ((quote >= 0) && (c != quote)))) { - buf.append((char)c); - c = in.read(); + while ((c[0] > 0) && + (((quote < 0) && (c[0] != ' ') && (c[0] != '\t') && + (c[0] != '\n') && (c[0] != '\r') && (c[0] != '>')) + || ((quote >= 0) && (c[0] != quote)))) { + buf.append((char)c[0]); + c[0] = in.read(); } - if (c == quote) { - c = in.read(); + if (c[0] == quote) { + c[0] = in.read(); } - skipSpace(in); + skipSpace(c, in); val = buf.toString(); } @@ -1767,12 +1697,12 @@ atts.put(att.toLowerCase(java.util.Locale.ENGLISH), val); while (true) { - if ((c == '>') || (c < 0) || - ((c >= 'a') && (c <= 'z')) || - ((c >= 'A') && (c <= 'Z')) || - ((c >= '0') && (c <= '9')) || (c == '_')) + if ((c[0] == '>') || (c[0] < 0) || + ((c[0] >= 'a') && (c[0] <= 'z')) || + ((c[0] >= 'A') && (c[0] <= 'Z')) || + ((c[0] >= '0') && (c[0] <= '9')) || (c[0] == '_')) break; - c = in.read(); + c[0] = in.read(); } //skipSpace(in); } @@ -1815,23 +1745,25 @@ /** * Scan an html file for <applet> tags */ - public static void parse(int identifier, long handle, Reader in, URL url, String enc) + public static void parse(int identifier, long handle, String width, String height, Reader in, URL url, String enc) throws IOException { encoding = enc; - parse(identifier, handle, in, url, System.out, new PluginAppletPanelFactory()); + parse(identifier, handle, width, height, in, url, System.out, new PluginAppletPanelFactory()); } - public static void parse(int identifier, long handle, Reader in, URL url) + public static void parse(int identifier, long handle, String width, String height, Reader in, URL url) throws IOException { final int fIdentifier = identifier; final long fHandle = handle; + final String fWidth = width; + final String fHeight = height; final Reader fIn = in; final URL fUrl = url; PrivilegedAction pa = new PrivilegedAction() { public Object run() { try { - parse(fIdentifier, fHandle, fIn, fUrl, System.out, new PluginAppletPanelFactory()); + parse(fIdentifier, fHandle, fWidth, fHeight, fIn, fUrl, System.out, new PluginAppletPanelFactory()); } catch (IOException ioe) { return ioe; } @@ -1846,7 +1778,8 @@ } } - public static void parse(int identifier, long handle, Reader in, URL url, + public static void parse(int identifier, long handle, String width, + String height, Reader in, URL url, PrintStream statusMsgStream, PluginAppletPanelFactory factory) throws IOException @@ -1856,6 +1789,11 @@ boolean isObjectTag = false; boolean isEmbedTag = false; boolean objectTagAlreadyParsed = false; + // The current character + // FIXME: This is an evil hack to force pass-by-reference.. the + // parsing code needs to be rewritten from scratch to prevent such + //a need + int[] c = new int[1]; // warning messages String requiresNameWarning = amh.getMessage("parse.warning.requiresname"); @@ -1881,15 +1819,15 @@ Hashtable atts = null; while(true) { - c = in.read(); - if (c == -1) + c[0] = in.read(); + if (c[0] == -1) break; - if (c == '<') { - c = in.read(); - if (c == '/') { - c = in.read(); - String nm = scanIdentifier(in); + if (c[0] == '<') { + c[0] = in.read(); + if (c[0] == '/') { + c[0] = in.read(); + String nm = scanIdentifier(c, in); if (nm.equalsIgnoreCase("applet") || nm.equalsIgnoreCase("object") || nm.equalsIgnoreCase("embed")) { @@ -1930,9 +1868,9 @@ } } else { - String nm = scanIdentifier(in); + String nm = scanIdentifier(c, in); if (nm.equalsIgnoreCase("param")) { - Hashtable t = scanTag(in); + Hashtable t = scanTag(c, in); String att = (String)t.get("name"); if (atts.containsKey(att)) @@ -1967,7 +1905,7 @@ } else if (nm.equalsIgnoreCase("applet")) { isAppletTag = true; - atts = scanTag(in); + atts = scanTag(c, in); // If there is a classid and no code tag present, transform it to code tag if (atts.get("code") == null && atts.get("classid") != null && !((String) atts.get("classid")).startsWith("clsid:")) { @@ -1985,21 +1923,11 @@ } if (atts.get("width") == null || !isInt(atts.get("width"))) { - atts.put("width", "1000"); - atts.put("widthPercentage", 100); - } else if (((String) atts.get("width")).endsWith("%")) { - String w = (String) atts.get("width"); - atts.put("width", "100"); - atts.put("widthPercentage", Integer.parseInt((w.substring(0, w.length() -1)))); + atts.put("width", width); } if (atts.get("height") == null || !isInt(atts.get("height"))) { - atts.put("height", "1000"); - atts.put("heightPercentage", 100); - } else if (((String) atts.get("height")).endsWith("%")) { - String h = (String) atts.get("height"); - atts.put("height", "100"); - atts.put("heightPercentage", Integer.parseInt(h.substring(0, h.length() -1))); + atts.put("height", height); } } else if (nm.equalsIgnoreCase("object")) { @@ -2008,7 +1936,7 @@ // Once code is set, additional nested objects are ignored if (!objectTagAlreadyParsed) { objectTagAlreadyParsed = true; - atts = scanTag(in); + atts = scanTag(c, in); } // If there is a classid and no code tag present, transform it to code tag @@ -2048,26 +1976,16 @@ } if (atts.get("width") == null || !isInt(atts.get("width"))) { - atts.put("width", "1000"); - atts.put("widthPercentage", 100); - } else if (((String) atts.get("width")).endsWith("%")) { - String w = (String) atts.get("width"); - atts.put("width", "100"); - atts.put("widthPercentage", Integer.parseInt(w.substring(0, w.length() -1))); + atts.put("width", width); } if (atts.get("height") == null || !isInt(atts.get("height"))) { - atts.put("height", "1000"); - atts.put("heightPercentage", 100); - } else if (((String) atts.get("height")).endsWith("%")) { - String h = (String) atts.get("height"); - atts.put("height", "100"); - atts.put("heightPercentage", Integer.parseInt(h.substring(0, h.length() -1))); + atts.put("height", height); } } else if (nm.equalsIgnoreCase("embed")) { isEmbedTag = true; - atts = scanTag(in); + atts = scanTag(c, in); // If there is a classid and no code tag present, transform it to code tag if (atts.get("code") == null && atts.get("classid") != null && !((String) atts.get("classid")).startsWith("clsid:")) { @@ -2107,21 +2025,11 @@ } if (atts.get("width") == null || !isInt(atts.get("width"))) { - atts.put("width", "1000"); - atts.put("widthPercentage", 100); - } else if (((String) atts.get("width")).endsWith("%")) { - String w = (String) atts.get("width"); - atts.put("width", "100"); - atts.put("widthPercentage", Integer.parseInt(w.substring(0, w.length() -1))); + atts.put("width", width); } if (atts.get("height") == null || !isInt(atts.get("height"))) { - atts.put("height", "1000"); - atts.put("heightPercentage", 100); - } else if (((String) atts.get("height")).endsWith("%")) { - String h = (String) atts.get("height"); - atts.put("height", "100"); - atts.put("heightPercentage", Integer.parseInt(h.substring(0, h.length() -1))); + atts.put("height", height); } } }
--- a/plugin/icedteanp/java/sun/applet/PluginMessageConsumer.java Mon Sep 13 10:21:58 2010 -0400 +++ b/plugin/icedteanp/java/sun/applet/PluginMessageConsumer.java Thu Sep 16 13:03:57 2010 -0400 @@ -50,7 +50,7 @@ // Each initialization requires 5 responses (tag, handle, width, proxy, cookie) // before the message stack unlocks/collapses. This works out well because we // want to allow upto 5 parallel tasks anyway - private static int MAX_WORKERS = MAX_PARALLEL_INITS*5; + private static int MAX_WORKERS = MAX_PARALLEL_INITS*4; private static int PRIORITY_WORKERS = MAX_PARALLEL_INITS*2; private static Hashtable<Integer, PluginMessageHandlerWorker> initWorkers = new Hashtable<Integer, PluginMessageHandlerWorker>(2); @@ -150,41 +150,6 @@ } } - private boolean okayToProcess(String[] msgParts) { - - if (msgParts[2].equals("tag")) { - - Integer instanceNum = new Integer(msgParts[1]); - - synchronized(initWorkers) { - if (initWorkers.size() >= MAX_PARALLEL_INITS) { - return false; - } - } - - registerPriorityWait("instance " + instanceNum + " handle"); - - } else if (msgParts[2].equals("handle")) { - Integer instanceNum = new Integer(msgParts[1]); - - // If this instance is not in init, return false immediately. - // Handle messages should NEVER go before tag messages - if (!isInInit(instanceNum)) - return false; - - registerPriorityWait("instance " + instanceNum + " width"); - } else if (msgParts[2].equals("width")) { - - // width messages cannot proceed until handle and tag have been resolved - Integer instanceNum = new Integer(msgParts[1]); - - if (!processedIds.contains(instanceNum)) { - return false; - } - } - - return true; - } public void notifyWorkerIsFree(PluginMessageHandlerWorker worker) { synchronized (initWorkers) { @@ -225,14 +190,6 @@ String[] msgParts = message.split(" "); - // if it is no okay to process just yet, push it back and - if (!okayToProcess(msgParts)) { - synchronized(readQueue) { - readQueue.addLast(message); - } - - continue; // re-loop to try next msg - } String priorityStr = getPriorityStrIfPriority(message); boolean isPriorityResponse = (priorityStr != null);