merge from m-c. manually merging modules/plugin/test/testplugin/nptest.cpp dom/plugins/PluginModuleChild.cpp.
authorDoug Turner <dougt@dougt.org>
Fri, 26 Mar 2010 14:22:48 -0700
changeset 46772 d5341d4414d2f838d92afe1d25c580d17ee6c071
parent 46771 cd86e0ea3d2d549a5a7a7c3ca066e4b4fd39a3ea (current diff)
parent 39885 6017d45d157e524a040cf3ec60e817d30469be1d (diff)
child 46773 794f4bacbdcc5898cb3e97565ba6155b28d4e4c7
push idunknown
push userunknown
push dateunknown
milestone1.9.3a4pre
merge from m-c. manually merging modules/plugin/test/testplugin/nptest.cpp dom/plugins/PluginModuleChild.cpp.
browser/components/microsummaries/Makefile.in
browser/components/microsummaries/public/Makefile.in
browser/components/microsummaries/public/nsIMicrosummaryService.idl
browser/components/microsummaries/src/Makefile.in
browser/components/microsummaries/src/nsMicrosummaryService.js
browser/components/places/public/nsIPlacesImportExportService.idl
browser/components/places/src/nsPlacesImportExportService.cpp
browser/components/places/src/nsPlacesImportExportService.h
content/base/src/nsObjectLoadingContent.cpp
content/canvas/src/nsCanvasRenderingContext2D.cpp
content/events/src/nsDOMEvent.cpp
content/events/src/nsDOMEvent.h
content/xul/content/src/nsXULElement.cpp
dom/base/nsGlobalWindow.cpp
dom/base/nsGlobalWindow.h
dom/base/nsJSEnvironment.cpp
dom/plugins/PPluginInstance.ipdl
dom/plugins/PluginInstanceChild.cpp
dom/plugins/PluginInstanceParent.cpp
dom/plugins/PluginInstanceParent.h
dom/plugins/PluginMessageUtils.h
dom/plugins/PluginModuleChild.cpp
dom/plugins/PluginModuleChild.h
dom/plugins/PluginModuleParent.cpp
ipc/glue/IPCMessageUtils.h
ipc/glue/RPCChannel.cpp
ipc/glue/RPCChannel.h
ipc/ipdl/ipdl/lower.py
js/ctypes/Function.cpp
js/ctypes/Function.h
layout/base/nsPresContext.cpp
modules/freetype2/README.CVS
modules/freetype2/src/base/ftnames.c
modules/plugin/base/src/nsPluginHost.cpp
modules/plugin/test/testplugin/nptest.cpp
parser/html/nsHtml5SpeculativeLoader.cpp
parser/html/nsHtml5SpeculativeLoader.h
toolkit/crashreporter/nsExceptionHandler.cpp
toolkit/library/libxul-config.mk
toolkit/toolkit-makefiles.sh
toolkit/toolkit-tiers.mk
toolkit/xre/nsEmbedFunctions.cpp
widget/src/qt/nsWindow.cpp
widget/src/qt/nsWindow.h
widget/src/windows/nsWindow.cpp
xpcom/build/nsXULAppAPI.h
xpfe/Makefile.in
--- a/Makefile.in
+++ b/Makefile.in
@@ -56,20 +56,25 @@ default::
 TIERS += base
 
 #
 # tier "base" - basic setup
 #
 tier_base_dirs = \
 	config \
 	build \
-	memory \
 	probes \
 	$(NULL)
 
+ifndef LIBXUL_SDK
+tier_base_dirs += \
+	memory \
+	$(NULL)
+endif
+
 ifdef COMPILE_ENVIRONMENT
 include $(topsrcdir)/$(MOZ_BUILD_APP)/build.mk
 endif
 
 TIERS += testharness
 
 # test harnesses
 ifdef ENABLE_TESTS
--- a/allmakefiles.sh
+++ b/allmakefiles.sh
@@ -80,17 +80,17 @@ if [ "$WINCE" ]; then
     build/wince/shunt/Makefile
     build/wince/shunt/include/windows.h
     build/wince/shunt/include/ymath.h
     build/wince/shunt/include/stdlib.h
     build/wince/shunt/include/sys/Makefile
   "
 fi
 
-if [ "$MOZ_MEMORY" ]; then
+if [ "$MOZ_MEMORY" -a "$LIBXUL_SDK" -eq ""]; then
   add_makefiles "
     memory/jemalloc/Makefile
   "
 fi
 
 #
 # Application-specific makefiles
 #
--- a/browser/app/Makefile.in
+++ b/browser/app/Makefile.in
@@ -307,16 +307,18 @@ libs:: $(srcdir)/blocklist.xml
 ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 
 APP_NAME = $(MOZ_APP_DISPLAYNAME)
 
 ifdef MOZ_DEBUG
 APP_NAME := $(APP_NAME)Debug
 endif
 
+LOWER_APP_NAME = $(shell echo $(APP_NAME) | tr '[A-Z]' '[a-z]')
+
 AB_CD = $(MOZ_UI_LOCALE)
 
 AB := $(firstword $(subst -, ,$(AB_CD)))
 
 clean clobber repackage::
 	rm -rf $(DIST)/$(APP_NAME).app
 
 ifdef LIBXUL_SDK
@@ -325,18 +327,18 @@ else
 APPFILES = MacOS
 endif
 
 libs repackage:: $(PROGRAM) application.ini
 	mkdir -p $(DIST)/$(APP_NAME).app/Contents/MacOS
 	rsync -a --exclude CVS --exclude "*.in" $(srcdir)/macbuild/Contents $(DIST)/$(APP_NAME).app --exclude English.lproj
 	mkdir -p $(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj
 	rsync -a --exclude CVS --exclude "*.in" $(srcdir)/macbuild/Contents/Resources/English.lproj/ $(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj
-	sed -e "s/%APP_VERSION%/$(APP_VERSION)/" -e "s/%APP_NAME%/$(APP_NAME)/" $(srcdir)/macbuild/Contents/Info.plist.in > $(DIST)/$(APP_NAME).app/Contents/Info.plist
-	sed -e "s/%APP_VERSION%/$(APP_VERSION)/" -e "s/%APP_NAME%/$(APP_NAME)/" $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > $(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj/InfoPlist.strings
+	sed -e "s/%APP_VERSION%/$(APP_VERSION)/" -e "s/%APP_NAME%/$(APP_NAME)/" -e "s/%LOWER_APP_NAME%/$(LOWER_APP_NAME)/" $(srcdir)/macbuild/Contents/Info.plist.in > $(DIST)/$(APP_NAME).app/Contents/Info.plist
+	sed -e "s/%APP_NAME%/$(APP_NAME)/" $(srcdir)/macbuild/Contents/Resources/English.lproj/InfoPlist.strings.in | iconv -f UTF-8 -t UTF-16 > $(DIST)/$(APP_NAME).app/Contents/Resources/$(AB).lproj/InfoPlist.strings
 	rsync -a $(DIST)/bin/ $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)
 	$(RM) $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)/mangle $(DIST)/$(APP_NAME).app/Contents/$(APPFILES)/shlibsign
 ifdef LIBXUL_SDK
 	cp $(LIBXUL_DIST)/bin/$(XR_STUB_NAME) $(DIST)/$(APP_NAME).app/Contents/MacOS/firefox-bin
 else
 	rm -f $(DIST)/$(APP_NAME).app/Contents/MacOS/$(PROGRAM)
 	rsync -aL $(PROGRAM) $(DIST)/$(APP_NAME).app/Contents/MacOS
 endif
--- a/browser/app/macbuild/Contents/Info.plist.in
+++ b/browser/app/macbuild/Contents/Info.plist.in
@@ -73,17 +73,17 @@
 	</array>
 	<key>CFBundleExecutable</key>
 	<string>firefox-bin</string>
 	<key>CFBundleGetInfoString</key>
 	<string>%APP_NAME% %APP_VERSION%</string>
 	<key>CFBundleIconFile</key>
 	<string>firefox</string>
 	<key>CFBundleIdentifier</key>
-	<string>org.mozilla.firefox</string>
+	<string>org.mozilla.%LOWER_APP_NAME%</string>
 	<key>CFBundleInfoDictionaryVersion</key>
 	<string>6.0</string>
 	<key>CFBundleName</key>
 	<string>%APP_NAME%</string>
 	<key>CFBundlePackageType</key>
 	<string>APPL</string>
 	<key>CFBundleShortVersionString</key>
 	<string>%APP_VERSION%</string>
--- a/browser/base/content/browser-fullZoom.js
+++ b/browser/base/content/browser-fullZoom.js
@@ -269,17 +269,31 @@ var FullZoom = {
    * @param aIsTabSwitch
    *        Whether this location change has happened because of a tab switch.
    * @param aBrowser
    *        (optional) browser object displaying the document
    */
   onLocationChange: function FullZoom_onLocationChange(aURI, aIsTabSwitch, aBrowser) {
     if (!aURI || (aIsTabSwitch && !this.siteSpecific))
       return;
-    this._applyPrefToSetting(this._cps.getPref(aURI, this.name), aBrowser);
+
+    // Avoid the cps roundtrip and apply the default/global pref.
+    if (aURI.spec == "about:blank") {
+      this._applyPrefToSetting();
+      return;
+    }
+
+    var self = this;
+    this._cps.getPref(aURI, this.name, function(aResult) {
+      // Check that we're still where we expect to be in case this took a while.
+      let isSaneURI = (aBrowser && aBrowser.currentURI) ?
+        aURI.equals(aBrowser.currentURI) : false;
+      if (!aBrowser || isSaneURI)
+        self._applyPrefToSetting(aResult, aBrowser);
+    });
   },
 
   // update state of zoom type menu item
 
   updateMenu: function FullZoom_updateMenu() {
     var menuItem = document.getElementById("toggle_zoom");
 
     menuItem.setAttribute("checked", !ZoomManager.useFullZoom);
@@ -326,17 +340,17 @@ var FullZoom = {
    * We don't check first to see if the new value is the same as the current
    * one.
    **/
   _applyPrefToSetting: function FullZoom__applyPrefToSetting(aValue, aBrowser) {
     if ((!this.siteSpecific && !this._inPrivateBrowsing) ||
         gInPrintPreviewMode)
       return;
 
-    var browser = aBrowser || gBrowser.selectedBrowser;
+    var browser = aBrowser || (gBrowser && gBrowser.selectedBrowser);
     try {
       if (browser.contentDocument instanceof Ci.nsIImageDocument ||
           this._inPrivateBrowsing)
         ZoomManager.setZoomForBrowser(browser, 1);
       else if (typeof aValue != "undefined")
         ZoomManager.setZoomForBrowser(browser, this._ensureValid(aValue));
       else if (typeof this.globalValue != "undefined")
         ZoomManager.setZoomForBrowser(browser, this.globalValue);
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -627,17 +627,17 @@ var HistoryMenu = {
       m.setAttribute("label", undoItems[i].title);
       if (undoItems[i].image) {
         let iconURL = undoItems[i].image;
         // don't initiate a connection just to fetch a favicon (see bug 467828)
         if (/^https?:/.test(iconURL))
           iconURL = "moz-anno:favicon:" + iconURL;
         m.setAttribute("image", iconURL);
       }
-      m.setAttribute("class", "menuitem-iconic bookmark-item");
+      m.setAttribute("class", "menuitem-iconic bookmark-item menuitem-with-favicon");
       m.setAttribute("value", i);
       m.setAttribute("oncommand", "undoCloseTab(" + i + ");");
 
       // Set the targetURI attribute so it will be shown in tooltip and statusbar.
       // SessionStore uses one-based indexes, so we need to normalize them.
       let tabData = undoItems[i].state;
       let activeIndex = (tabData.index || tabData.entries.length) - 1;
       if (activeIndex >= 0 && tabData.entries[activeIndex])
@@ -709,17 +709,17 @@ var HistoryMenu = {
       let selectedTab = undoItem.tabs[undoItem.selected - 1];
       if (selectedTab.attributes.image) {
         let iconURL = selectedTab.attributes.image;
         // don't initiate a connection just to fetch a favicon (see bug 467828)
         if (/^https?:/.test(iconURL))
           iconURL = "moz-anno:favicon:" + iconURL;
         m.setAttribute("image", iconURL);
       }
-      m.setAttribute("class", "menuitem-iconic bookmark-item");
+      m.setAttribute("class", "menuitem-iconic bookmark-item menuitem-with-favicon");
       m.setAttribute("oncommand", "undoCloseWindow(" + i + ");");
 
       // Set the targetURI attribute so it will be shown in tooltip and statusbar.
       // SessionStore uses one-based indexes, so we need to normalize them.
       let activeIndex = (selectedTab.index || selectedTab.entries.length) - 1;
       if (activeIndex >= 0 && selectedTab.entries[activeIndex])
         m.setAttribute("targetURI", selectedTab.entries[activeIndex].url);
 
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -109,24 +109,16 @@ toolbar[mode="icons"] > #reload-button[d
 .unified-nav-current {
   font-weight: bold;
 }
 
 toolbarbutton.bookmark-item {
   max-width: 13em;
 }
 
-%ifdef MOZ_WIDGET_GTK2
-/* Bookmarks override the "images-in-menus" metric in xul.css */
-.bookmark-item > .menu-iconic-left,
-.searchbar-engine-menuitem > .menu-iconic-left {
-  visibility: inherit;
-}
-%endif
-
 #editBMPanel_tagsSelector {
   /* override default listbox width from xul.css */
   width: auto;
 }
 
 menuitem.spell-suggestion {
   font-weight: bold;
 }
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -258,17 +258,17 @@ function SetClickAndHoldHandlers() {
                         .firstChild.cloneNode(true);
     var backButton = document.getElementById("back-button");
     backButton.setAttribute("type", "menu");
     backButton.appendChild(popup);
     _addClickAndHoldListenersOnElement(backButton);
     var forwardButton = document.getElementById("forward-button");
     popup = popup.cloneNode(true);
     forwardButton.setAttribute("type", "menu");
-    forwardButton.appendChild(popup);    
+    forwardButton.appendChild(popup);
     _addClickAndHoldListenersOnElement(forwardButton);
     unifiedButton._clickHandlersAttached = true;
   }
 }
 #endif
 
 function BookmarkThisTab(aTab) {
   PlacesCommandHook.bookmarkPage(aTab.linkedBrowser,
@@ -290,31 +290,31 @@ const gSessionHistoryObserver = {
       // Clear undo history of the URL bar
       gURLBar.editor.transactionManager.clear()
     }
   }
 };
 
 /**
  * Given a starting docshell and a URI to look up, find the docshell the URI
- * is loaded in. 
+ * is loaded in.
  * @param   aDocument
- *          A document to find instead of using just a URI - this is more specific. 
+ *          A document to find instead of using just a URI - this is more specific.
  * @param   aDocShell
  *          The doc shell to start at
  * @param   aSoughtURI
  *          The URI that we're looking for
- * @returns The doc shell that the sought URI is loaded in. Can be in 
+ * @returns The doc shell that the sought URI is loaded in. Can be in
  *          subframes.
  */
 function findChildShell(aDocument, aDocShell, aSoughtURI) {
   aDocShell.QueryInterface(Components.interfaces.nsIWebNavigation);
   aDocShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
   var doc = aDocShell.getInterface(Components.interfaces.nsIDOMDocument);
-  if ((aDocument && doc == aDocument) || 
+  if ((aDocument && doc == aDocument) ||
       (aSoughtURI && aSoughtURI.spec == aDocShell.currentURI.spec))
     return aDocShell;
 
   var node = aDocShell.QueryInterface(Components.interfaces.nsIDocShellTreeNode);
   for (var i = 0; i < node.childCount; ++i) {
     var docShell = node.getChildAt(i);
     docShell = findChildShell(aDocument, docShell, aSoughtURI);
     if (docShell)
@@ -869,17 +869,17 @@ let gGestureSupport = {
 
   /**
    * Convert the swipe gesture into a browser action based on the direction
    *
    * @param aEvent
    *        The swipe event to handle
    */
   onSwipe: function GS_onSwipe(aEvent) {
-    // Figure out which one (and only one) direction was triggered 
+    // Figure out which one (and only one) direction was triggered
     ["UP", "RIGHT", "DOWN", "LEFT"].forEach(function (dir) {
       if (aEvent.direction == aEvent["DIRECTION_" + dir])
         return this._doAction(aEvent, ["swipe", dir.toLowerCase()]);
     }, this);
   },
 
   /**
    * Get a gesture preference or use a default if it doesn't exist
@@ -891,17 +891,17 @@ let gGestureSupport = {
    */
   _getPref: function GS__getPref(aPref, aDef) {
     // Preferences branch under which all gestures preferences are stored
     const branch = "browser.gesture.";
 
     try {
       // Determine what type of data to load based on default value's type
       let type = typeof aDef;
-      let getFunc = "get" + (type == "boolean" ? "Bool" : 
+      let getFunc = "get" + (type == "boolean" ? "Bool" :
                              type == "number" ? "Int" : "Char") + "Pref";
       return gPrefService[getFunc](branch + aPref);
     }
     catch (e) {
       return aDef;
     }
   },
 };
@@ -921,17 +921,17 @@ function BrowserStartup() {
   if ("arguments" in window && window.arguments[0])
     uriToLoad = window.arguments[0];
 
   var isLoadingBlank = uriToLoad == "about:blank";
   var mustLoadSidebar = false;
 
   prepareForStartup();
 
-  if (uriToLoad && !isLoadingBlank) { 
+  if (uriToLoad && !isLoadingBlank) {
     if (uriToLoad instanceof Ci.nsISupportsArray) {
       let count = uriToLoad.Count();
       let specs = [];
       for (let i = 0; i < count; i++) {
         let urisstring = uriToLoad.GetElementAt(i).QueryInterface(Ci.nsISupportsString);
         specs.push(urisstring.data);
       }
 
@@ -1192,17 +1192,17 @@ function delayedStartup(isLoadingBlank, 
 
   if (mustLoadSidebar) {
     let sidebar = document.getElementById("sidebar");
     let sidebarBox = document.getElementById("sidebar-box");
     sidebar.setAttribute("src", sidebarBox.getAttribute("src"));
   }
 
   UpdateUrlbarSearchSplitterState();
-  
+
   PlacesStarButton.init();
 
   // called when we go into full screen, even if it is
   // initiated by a web page script
   window.addEventListener("fullscreen", onFullScreen, true);
 
   if (isLoadingBlank && gURLBar && isElementVisible(gURLBar))
     gURLBar.focus();
@@ -1319,17 +1319,17 @@ function delayedStartup(isLoadingBlank, 
     try {
       Cc["@mozilla.org/microsummary/service;1"].getService(Ci.nsIMicrosummaryService);
     } catch (ex) {
       Components.utils.reportError("Failed to init microsummary service:\n" + ex);
     }
   }, 4000);
 
   // Delayed initialization of the livemarks update timer.
-  // Livemark updates don't need to start until after bookmark UI 
+  // Livemark updates don't need to start until after bookmark UI
   // such as the toolbar has initialized. Starting 5 seconds after
   // delayedStartup in order to stagger this after the microsummary
   // service (see above) and before the download manager starts (see below).
   setTimeout(function() PlacesUtils.livemarks.start(), 5000);
 
   // Initialize the download manager some time after the app starts so that
   // auto-resume downloads begin (such as after crashing or quitting with
   // active downloads) and speeds up the first-load of the download manager UI.
@@ -1491,17 +1491,17 @@ function nonBrowserWindowStartup()
 
   setTimeout(nonBrowserWindowDelayedStartup, 0);
 }
 
 function nonBrowserWindowDelayedStartup()
 {
   // initialise the offline listener
   BrowserOffline.init();
-  
+
   // Set up Sanitize Item
   initializeSanitizer();
 
   // initialize the private browsing UI
   gPrivateBrowsingUI.init();
 }
 
 function nonBrowserWindowShutdown()
@@ -1734,17 +1734,17 @@ function loadOneOrMoreURIs(aURIString)
     window.openDialog(getBrowserURL(), "_blank", "all,dialog=no", aURIString);
     return;
   }
 #endif
   // This function throws for certain malformed URIs, so use exception handling
   // so that we don't disrupt startup
   try {
     gBrowser.loadTabs(aURIString.split("|"), false, true);
-  } 
+  }
   catch (e) {
   }
 }
 
 function focusAndSelectUrlBar() {
   if (gURLBar && !gURLBar.readOnly) {
     if (window.fullScreen)
       FullScreen.mouseoverToggle(true);
@@ -1971,23 +1971,23 @@ function getShortcutOrURI(aURL, aPostDat
     // the original URL.
     aPostDataRef.value = null;
 
     return aURL;
   }
 
   return shortcutURL;
 }
- 
+
 function getPostDataStream(aStringData, aKeyword, aEncKeyword, aType) {
   var dataStream = Cc["@mozilla.org/io/string-input-stream;1"].
                    createInstance(Ci.nsIStringInputStream);
   aStringData = aStringData.replace(/%s/g, aEncKeyword).replace(/%S/g, aKeyword);
   dataStream.data = aStringData;
- 
+
   var mimeStream = Cc["@mozilla.org/network/mime-input-stream;1"].
                    createInstance(Ci.nsIMIMEInputStream);
   mimeStream.addHeader("Content-Type", aType);
   mimeStream.addContentLength = true;
   mimeStream.setData(dataStream);
   return mimeStream.QueryInterface(Ci.nsIInputStream);
 }
 
@@ -2329,45 +2329,45 @@ function BrowserOnCommand(event) {
     var ot = event.originalTarget;
     var errorDoc = ot.ownerDocument;
 
     // If the event came from an ssl error page, it is probably either the "Add
     // Exception…" or "Get me out of here!" button
     if (/^about:certerror/.test(errorDoc.documentURI)) {
       if (ot == errorDoc.getElementById('exceptionDialogButton')) {
         var params = { exceptionAdded : false, handlePrivateBrowsing : true };
-        
+
         try {
           switch (gPrefService.getIntPref("browser.ssl_override_behavior")) {
             case 2 : // Pre-fetch & pre-populate
               params.prefetchCert = true;
             case 1 : // Pre-populate
               params.location = errorDoc.location.href;
           }
         } catch (e) {
           Components.utils.reportError("Couldn't get ssl_override pref: " + e);
         }
-        
+
         window.openDialog('chrome://pippki/content/exceptionDialog.xul',
                           '','chrome,centerscreen,modal', params);
-        
+
         // If the user added the exception cert, attempt to reload the page
         if (params.exceptionAdded)
           errorDoc.location.reload();
       }
       else if (ot == errorDoc.getElementById('getMeOutOfHereButton')) {
         getMeOutOfHere();
       }
     }
     else if (/^about:blocked/.test(errorDoc.documentURI)) {
       // The event came from a button on a malware/phishing block page
       // First check whether it's malware or phishing, so that we can
       // use the right strings/links
       var isMalware = /e=malwareBlocked/.test(errorDoc.documentURI);
-      
+
       if (ot == errorDoc.getElementById('getMeOutButton')) {
         getMeOutOfHere();
       }
       else if (ot == errorDoc.getElementById('reportButton')) {
         // This is the "Why is this site blocked" button.  For malware,
         // we can fetch a site-specific report, for phishing, we redirect
         // to the generic page describing phishing protection.
 
@@ -2418,17 +2418,17 @@ function BrowserOnCommand(event) {
           buttons[1] = {
             label: gNavigatorBundle.getString("safebrowsing.notAForgeryButton.label"),
             accessKey: gNavigatorBundle.getString("safebrowsing.notAForgeryButton.accessKey"),
             callback: function() {
               openUILinkIn(safebrowsing.getReportURL('Error'), 'tab');
             }
           };
         }
-        
+
         let notificationBox = gBrowser.getNotificationBox();
         let value = "blocked-badware-page";
 
         let previousNotification = notificationBox.getNotificationWithValue(value);
         if (previousNotification)
           notificationBox.removeNotification(previousNotification);
 
         notificationBox.appendNotification(
@@ -2632,17 +2632,17 @@ function FillInHTMLTooltip(tipElement)
     if (tipElement.nodeType == Node.ELEMENT_NODE) {
       titleText = tipElement.getAttribute("title");
       if ((tipElement instanceof HTMLAnchorElement && tipElement.href) ||
           (tipElement instanceof HTMLAreaElement && tipElement.href) ||
           (tipElement instanceof HTMLLinkElement && tipElement.href) ||
           (tipElement instanceof SVGAElement && tipElement.hasAttributeNS(XLinkNS, "href"))) {
         XLinkTitleText = tipElement.getAttributeNS(XLinkNS, "title");
       }
-      if (lookingForSVGTitle && 
+      if (lookingForSVGTitle &&
           !(tipElement instanceof SVGElement &&
             tipElement.parentNode instanceof SVGElement &&
             !(tipElement.parentNode instanceof SVGForeignObjectElement))) {
         lookingForSVGTitle = false;
       }
       if (lookingForSVGTitle) {
         let length = tipElement.childNodes.length;
         for (let i = 0; i < length; i++) {
@@ -2661,17 +2661,17 @@ function FillInHTMLTooltip(tipElement)
       direction = defView.getComputedStyle(tipElement, "")
         .getPropertyValue("direction");
     }
     tipElement = tipElement.parentNode;
   }
 
   var tipNode = document.getElementById("aHTMLTooltip");
   tipNode.style.direction = direction;
-  
+
   [titleText, XLinkTitleText, SVGTitleText].forEach(function (t) {
     if (t && /\S/.test(t)) {
 
       // Per HTML 4.01 6.2 (CDATA section), literal CRs and tabs should be
       // replaced with spaces, and LFs should be removed entirely.
       // XXX Bug 322270: We don't preserve the result of entities like &#13;,
       // which should result in a line break in the tooltip, because we can't
       // distinguish that from a literal character in the source by this point.
@@ -3049,23 +3049,23 @@ const BrowserSearch = {
     else {
       browser.engines = engines;
       if (browser == gBrowser.selectedBrowser)
         this.updateSearchButton();
     }
   },
 
   /**
-   * Update the browser UI to show whether or not additional engines are 
-   * available when a page is loaded or the user switches tabs to a page that 
+   * Update the browser UI to show whether or not additional engines are
+   * available when a page is loaded or the user switches tabs to a page that
    * has search engines.
    */
   updateSearchButton: function() {
     var searchBar = this.searchBar;
-    
+
     // The search bar binding might not be applied even though the element is
     // in the document (e.g. when the navigation toolbar is hidden), so check
     // for .searchButton specifically.
     if (!searchBar || !searchBar.searchButton)
       return;
 
     var engines = gBrowser.selectedBrowser.engines;
     if (engines && engines.length > 0)
@@ -3123,33 +3123,33 @@ const BrowserSearch = {
    *        The search terms to use for the search.
    *
    * @param useNewTab
    *        Boolean indicating whether or not the search should load in a new
    *        tab.
    */
   loadSearch: function BrowserSearch_search(searchText, useNewTab) {
     var engine;
-  
+
     // If the search bar is visible, use the current engine, otherwise, fall
     // back to the default engine.
     if (isElementVisible(this.searchBar))
       engine = Services.search.currentEngine;
     else
       engine = Services.search.defaultEngine;
-  
+
     var submission = engine.getSubmission(searchText, null); // HTML response
 
     // getSubmission can return null if the engine doesn't have a URL
     // with a text/html response type.  This is unlikely (since
     // SearchService._addEngineToStore() should fail for such an engine),
     // but let's be on the safe side.
     if (!submission)
       return;
-  
+
     if (useNewTab) {
       gBrowser.loadOneTab(submission.uri.spec, {
                           postData: submission.postData,
                           relatedToCurrent: true});
     } else
       loadURI(submission.uri.spec, null, submission.postData, false);
   },
 
@@ -3225,25 +3225,25 @@ function FillHistoryMenu(aParent) {
         let iconURL = Cc["@mozilla.org/browser/favicon-service;1"]
                          .getService(Ci.nsIFaviconService)
                          .getFaviconForPage(entry.URI).spec;
         item.style.listStyleImage = "url(" + iconURL + ")";
       } catch (ex) {}
     }
 
     if (j < index) {
-      item.className = "unified-nav-back menuitem-iconic";
+      item.className = "unified-nav-back menuitem-iconic menuitem-with-favicon";
       item.setAttribute("tooltiptext", tooltipBack);
     } else if (j == index) {
       item.setAttribute("type", "radio");
       item.setAttribute("checked", "true");
       item.className = "unified-nav-current";
       item.setAttribute("tooltiptext", tooltipCurrent);
     } else {
-      item.className = "unified-nav-forward menuitem-iconic";
+      item.className = "unified-nav-forward menuitem-iconic menuitem-with-favicon";
       item.setAttribute("tooltiptext", tooltipForward);
     }
 
     aParent.appendChild(item);
   }
   return true;
 }
 
@@ -3419,17 +3419,17 @@ function BrowserToolboxCustomizeChange()
  * edit-related items in the context menu, and edit-related toolbar buttons
  * is visible, then update the edit commands' enabled state accordingly.  We use
  * this flag to skip updating the edit commands on focus or selection changes
  * when no UI is visible to improve performance (including pageload performance,
  * since focus changes when you load a new page).
  *
  * If UI is visible, we use goUpdateGlobalEditMenuItems to set the commands'
  * enabled state so the UI will reflect it appropriately.
- * 
+ *
  * If the UI isn't visible, we enable all edit commands so keyboard shortcuts
  * still work and just lazily disable them as needed when the user presses a
  * shortcut.
  *
  * This doesn't work on Mac, since Mac menus flash when users press their
  * keyboard shortcuts, so edit UI is essentially always visible on the Mac,
  * and we need to always update the edit commands.  Thus on Mac this function
  * is a no op.
@@ -3779,17 +3779,17 @@ var FullScreen =
 };
 
 /**
  * Returns true if |aMimeType| is text-based, false otherwise.
  *
  * @param aMimeType
  *        The MIME type to check.
  *
- * If adding types to this function, please also check the similar 
+ * If adding types to this function, please also check the similar
  * function in findbar.xml
  */
 function mimeTypeIsTextBased(aMimeType)
 {
   return /^text\/|\+xml$/.test(aMimeType) ||
          aMimeType == "application/x-javascript" ||
          aMimeType == "application/javascript" ||
          aMimeType == "application/xml" ||
@@ -3900,17 +3900,17 @@ var XULBrowserWindow = {
 
     // check the current value so we don't trigger an attribute change
     // and cause needless (slow!) UI updates
     if (this.statusText != text) {
       this.statusTextField.label = text;
       this.statusText = text;
     }
   },
-  
+
   onLinkIconAvailable: function (aBrowser, aIconURL) {
     if (gProxyFavIcon && gBrowser.userTypedValue === null)
       PageProxySetIcon(aIconURL); // update the favicon in the URL bar
   },
 
   onProgressChange: function (aWebProgress, aRequest,
                               aCurSelfProgress, aMaxSelfProgress,
                               aCurTotalProgress, aMaxTotalProgress) {
@@ -4139,17 +4139,17 @@ var XULBrowserWindow = {
 
     // See bug 358202, when tabs are switched during a drag operation,
     // timers don't fire on windows (bug 203573)
     if (aRequest)
       setTimeout(function () { XULBrowserWindow.asyncUpdateUI(); }, 0);
     else
       this.asyncUpdateUI();
   },
-  
+
   asyncUpdateUI: function () {
     FeedHandler.updateFeeds();
     BrowserSearch.updateSearchButton();
   },
 
   onStatusChange: function (aWebProgress, aRequest, aStatus, aMessage) {
     this.status = aMessage;
     this.updateStatusField();
@@ -4166,17 +4166,17 @@ var XULBrowserWindow = {
     if (this._state == aState &&
         this._tooltipText == gBrowser.securityUI.tooltipText &&
         !this._hostChanged) {
 #ifdef DEBUG
       try {
         var contentHost = gBrowser.contentWindow.location.host;
         if (this._host !== undefined && this._host != contentHost) {
             Components.utils.reportError(
-              "ASSERTION: browser.js host is inconsistent. Content window has " + 
+              "ASSERTION: browser.js host is inconsistent. Content window has " +
               "<" + contentHost + "> but cached host is <" + this._host + ">.\n"
             );
         }
       } catch (ex) {}
 #endif
       return;
     }
     this._state = aState;
@@ -4227,17 +4227,17 @@ var XULBrowserWindow = {
       this.securityButton.hidden = true;
       this.securityButton.removeAttribute("level");
       if (gURLBar)
         gURLBar.removeAttribute("level");
     }
 
     this.securityButton.setAttribute("tooltiptext", this._tooltipText);
 
-    // Don't pass in the actual location object, since it can cause us to 
+    // Don't pass in the actual location object, since it can cause us to
     // hold on to the window object too long.  Just pass in the fields we
     // care about. (bug 424829)
     var location = gBrowser.contentWindow.location;
     var locationObj = {};
     try {
       locationObj.host = location.host;
       locationObj.hostname = location.hostname;
       locationObj.port = location.port;
@@ -4271,17 +4271,17 @@ var XULBrowserWindow = {
     this.onProgressChange(gBrowser.webProgress, 0, 0, aTotalProgress, 1);
   },
 
   startDocumentLoad: function (aRequest) {
     // clear out feed data
     gBrowser.selectedBrowser.feeds = null;
 
     // clear out search-engine data
-    gBrowser.selectedBrowser.engines = null;    
+    gBrowser.selectedBrowser.engines = null;
 
     var uri = aRequest.QueryInterface(Ci.nsIChannel).URI;
 
     if (gURLBar &&
         gURLBar.value == "" &&
         getWebNavigation().currentURI.spec == "about:blank")
       URLBarSetURI(uri);
 
@@ -4397,17 +4397,17 @@ var TabsProgressListener = {
 #endif
   },
 
   onLocationChange: function (aBrowser, aWebProgress, aRequest, aLocationURI) {
     // Filter out any sub-frame loads
     if (aBrowser.contentWindow == aWebProgress.DOMWindow)
       FullZoom.onLocationChange(aLocationURI, false, aBrowser);
   },
-  
+
   onStatusChange: function (aBrowser, aWebProgress, aRequest, aStatus, aMessage) {
   },
 
   onRefreshAttempted: function (aBrowser, aWebProgress, aURI, aDelay, aSameURI) {
     if (gPrefService.getBoolPref("accessibility.blockautorefresh")) {
       let brandBundle = document.getElementById("bundle_brand");
       let brandShortName = brandBundle.getString("brandShortName");
       let refreshButtonText =
@@ -4605,17 +4605,17 @@ function displaySecurityInfo()
  * @param forceOpen boolean indicating whether the sidebar should be
  *                  opened regardless of its current state (optional).
  * @note
  * We expect to find a xul:broadcaster element with the specified ID.
  * The following attributes on that element may be used and/or modified:
  *  - id           (required) the string to match commandID. The convention
  *                 is to use this naming scheme: 'view<sidebar-name>Sidebar'.
  *  - sidebarurl   (required) specifies the URL to load in this sidebar.
- *  - sidebartitle or label (in that order) specify the title to 
+ *  - sidebartitle or label (in that order) specify the title to
  *                 display on the sidebar.
  *  - checked      indicates whether the sidebar is currently displayed.
  *                 Note that toggleSidebar updates this attribute when
  *                 it changes the sidebar's visibility.
  *  - group        this attribute must be set to "sidebar".
  */
 function toggleSidebar(commandID, forceOpen) {
 
@@ -4900,17 +4900,17 @@ function asyncOpenWebPanel(event)
          if (wrapper.href.substr(0, 5) === "data:")
            return true;
 
          try {
            urlSecurityCheck(wrapper.href, wrapper.ownerDocument.nodePrincipal);
          }
          catch(ex) {
            return false;
-         } 
+         }
 
          var postData = { };
          var url = getShortcutOrURI(wrapper.href, postData);
          if (!url)
            return true;
          loadURI(url, null, postData.value, false);
          event.preventDefault();
          return false;
@@ -4973,24 +4973,24 @@ function handleLinkClick(event, href, li
       if (event.ctrlKey) {
 #endif
         openNewTabWith(href, doc, null, event, false);
         event.stopPropagation();
         return true;
       }
 
       if (event.shiftKey && event.altKey) {
-        var feedService = 
+        var feedService =
             Cc["@mozilla.org/browser/feeds/result-service;1"].
             getService(Ci.nsIFeedResultService);
         feedService.forcePreviewPage = true;
         loadURI(href, null, null, false);
         return false;
       }
-                                                       
+
       if (event.shiftKey) {
         openNewWindowWith(href, doc, null, false);
         event.stopPropagation();
         return true;
       }
 
       if (event.altKey) {
         saveURL(href, linkNode ? gatherTextUnder(linkNode) : "", null, true,
@@ -5341,17 +5341,17 @@ var BrowserOffline = {
   {
     var ioService = Services.io;
 
     // Stop automatic management of the offline status
     try {
       ioService.manageOfflineStatus = false;
     } catch (ex) {
     }
-  
+
     if (!ioService.offline && !this._canGoOffline()) {
       this._updateOfflineUI(false);
       return;
     }
 
     ioService.offline = !ioService.offline;
 
     // Save the current state for later use as the initial state
@@ -5795,17 +5795,17 @@ function AddKeywordForSearchField() {
                        charset);
 
   var formURI = makeURI(node.form.getAttribute("action"),
                         charset,
                         docURI);
 
   var spec = formURI.spec;
 
-  var isURLEncoded = 
+  var isURLEncoded =
                (node.form.method.toUpperCase() == "POST"
                 && (node.form.enctype == "application/x-www-form-urlencoded" ||
                     node.form.enctype == ""));
 
   var title = gNavigatorBundle.getFormattedString("addKeywordTitleAutoFill",
                                                   [node.ownerDocument.title]);
   var description = PlacesUIUtils.getDescriptionFromDocument(node.ownerDocument);
 
@@ -5828,17 +5828,17 @@ function AddKeywordForSearchField() {
     if (el == node) {
       formData.push((isURLEncoded) ? escapeNameValuePair(el.name, "%s", true) :
                                      // Don't escape "%s", just append
                                      escapeNameValuePair(el.name, "", false) + "%s");
       continue;
     }
 
     type = el.type.toLowerCase();
-    
+
     if ((type == "text" || type == "hidden" || type == "textarea") ||
         ((type == "checkbox" || type == "radio") && el.checked)) {
       formData.push(escapeNameValuePair(el.name, el.value, isURLEncoded));
     } else if (el instanceof HTMLSelectElement && el.selectedIndex >= 0) {
       for (var j=0; j < el.options.length; j++) {
         if (el.options[j].selected)
           formData.push(escapeNameValuePair(el.name, el.options[j].value,
                                             isURLEncoded));
@@ -5877,17 +5877,17 @@ function getPluginInfo(pluginElement)
     }
 
     // only attempt if a pluginsPage is defined.
     if (pluginsPage) {
       var doc = pluginElement.ownerDocument;
       var docShell = findChildShell(doc, gBrowser.docShell, null);
       try {
         pluginsPage = makeURI(pluginsPage, doc.characterSet, docShell.currentURI).spec;
-      } catch (ex) { 
+      } catch (ex) {
         pluginsPage = "";
       }
     }
 
     tagMimetype = pluginElement.QueryInterface(Components.interfaces.nsIObjectLoadingContent)
                                .actualType;
 
     if (tagMimetype == "") {
@@ -5909,40 +5909,41 @@ var gMissingPluginInstaller = {
   get crashReportHelpURL() {
     delete this.crashReportHelpURL;
     let url = formatURL("app.support.baseURL", true);
     url += "plugin-crashed";
     this.crashReportHelpURL = url;
     return this.crashReportHelpURL;
   },
 
-  addLinkClickCallback: function (linkNode, callbackName, callbackArg) {
+  addLinkClickCallback: function (linkNode, callbackName /*callbackArgs...*/) {
     // XXX just doing (callback)(arg) was giving a same-origin error. bug?
     let self = this;
+    let callbackArgs = Array.prototype.slice.call(arguments).slice(2);
     linkNode.addEventListener("click",
                               function(evt) {
                                 if (!evt.isTrusted)
                                   return;
                                 evt.preventDefault();
-                                if (callbackArg == undefined)
-                                  callbackArg = evt;
-                                (self[callbackName])(callbackArg);
+                                if (callbackArgs.length == 0)
+                                  callbackArgs = [ evt ];
+                                (self[callbackName]).apply(self, callbackArgs);
                               },
                               true);
 
     linkNode.addEventListener("keydown",
                               function(evt) {
                                 if (!evt.isTrusted)
                                   return;
                                 if (evt.keyCode == evt.DOM_VK_RETURN) {
                                   evt.preventDefault();
-                                  if (callbackArg == undefined)
-                                    callbackArg = evt;
+                                  if (callbackArgs.length == 0)
+                                    callbackArgs = [ evt ];
                                   evt.preventDefault();
-                                  (self[callbackName])(callbackArg);
+                                  (self[callbackName]).apply(self, callbackArgs);
                                 }
                               },
                               true);
   },
 
   // Callback for user clicking on a missing (unsupported) plugin.
   installSinglePlugin: function (aEvent) {
     var missingPluginsArray = {};
@@ -5956,20 +5957,22 @@ var gMissingPluginInstaller = {
   },
 
   // Callback for user clicking on a disabled plugin
   managePlugins: function (aEvent) {
     BrowserOpenAddonsMgr("plugins");
   },
 
   // Callback for user clicking "submit a report" link
-  submitReport : function(minidumpID) {
+  submitReport : function(pluginDumpID, browserDumpID) {
     // The crash reporter wants a DOM element it can append an IFRAME to,
     // which it uses to submit a form. Let's just give it gBrowser.
-    this.CrashSubmit.submit(minidumpID, gBrowser, null, null);
+    this.CrashSubmit.submit(pluginDumpID, gBrowser, null, null);
+    if (browserDumpID)
+      this.CrashSubmit.submit(browserDumpID, gBrowser, null, null);
   },
 
   // Callback for user clicking a "reload page" link
   reloadPage: function (browser) {
     browser.reload();
   },
 
   // Callback for user clicking the help icon
@@ -6098,17 +6101,17 @@ var gMissingPluginInstaller = {
       let iconURL = "chrome://mozapps/skin/plugins/pluginGeneric-16.png";
       let messageString = gNavigatorBundle.getString("missingpluginsMessage.title");
       let buttons = [{
         label: gNavigatorBundle.getString("missingpluginsMessage.button.label"),
         accessKey: gNavigatorBundle.getString("missingpluginsMessage.button.accesskey"),
         popup: null,
         callback: showPluginsMissing
       }];
-    
+
       notificationBox.appendNotification(messageString, "missing-plugins",
                                          iconURL, priority, buttons);
     }
   },
 
   newDisabledPlugin: function (aEvent) {
     // Since we are expecting also untrusted events, make sure
     // that the target is a plugin
@@ -6122,23 +6125,24 @@ var gMissingPluginInstaller = {
   // are dispatched to individual plugin instances.
   pluginCrashed : function(subject, topic, data) {
     let propertyBag = subject;
     if (!(propertyBag instanceof Ci.nsIPropertyBag2) ||
         !(propertyBag instanceof Ci.nsIWritablePropertyBag2))
      return;
 
 #ifdef MOZ_CRASHREPORTER
-    let minidumpID   = propertyBag.getPropertyAsAString("minidumpID");
+    let pluginDumpID = propertyBag.getPropertyAsAString("pluginDumpID");
+    let browserDumpID= propertyBag.getPropertyAsAString("browserDumpID");
     let shouldSubmit = gCrashReporter.submitReports;
     let doPrompt     = true; // XXX followup to get via gCrashReporter
 
     // Submit automatically when appropriate.
-    if (minidumpID && shouldSubmit && !doPrompt) {
-      this.submitReport(minidumpID);
+    if (pluginDumpID && shouldSubmit && !doPrompt) {
+      this.submitReport(pluginDumpID, browserDumpID);
       // Submission is async, so we can't easily show failure UI.
       propertyBag.setPropertyAsBool("submittedCrashReport", true);
     }
 #endif
   },
 
   // Crashed-plugin event listener. Called for every instance of a
   // plugin in content.
@@ -6151,17 +6155,18 @@ var gMissingPluginInstaller = {
 
     if (!(aEvent instanceof Ci.nsIDOMDataContainerEvent))
       return;
 
     let submittedReport = aEvent.getData("submittedCrashReport");
     let doPrompt        = true; // XXX followup for .getData("doPrompt");
     let submitReports   = true; // XXX followup for .getData("submitReports");
     let pluginName      = aEvent.getData("pluginName");
-    let minidumpID      = aEvent.getData("minidumpID");
+    let pluginDumpID    = aEvent.getData("pluginDumpID");
+    let browserDumpID   = aEvent.getData("browserDumpID");
 
     // We're expecting this to be a plugin.
     let plugin = aEvent.target;
     if (!(plugin instanceof Ci.nsIObjectLoadingContent))
       return;
 
     // Force a style flush, so that we ensure our binding is attached.
     plugin.clientTop;
@@ -6188,22 +6193,23 @@ var gMissingPluginInstaller = {
     else if (!submitReports && !doPrompt) {
       showClass = "msg msgNotSubmitted";
     }
     else { // doPrompt
       showClass = "msg msgPleaseSubmit";
       // XXX can we make the link target actually be blank?
       let pleaseLink = doc.getAnonymousElementByAttribute(
                             plugin, "class", "pleaseSubmitLink");
-      self.addLinkClickCallback(pleaseLink, "submitReport", minidumpID);
+      self.addLinkClickCallback(pleaseLink, "submitReport",
+                                pluginDumpID, browserDumpID);
     }
 
     // If we don't have a minidumpID, we can't (or didn't) submit anything.
     // This can happen if the plugin is killed from the task manager.
-    if (!minidumpID) {
+    if (!pluginDumpID) {
         showClass = "msg msgNoCrashReport";
     }
 
     let textToShow = doc.getAnonymousElementByAttribute(plugin, "class", showClass);
     textToShow.style.display = "block";
 
     let bottomLinks = doc.getAnonymousElementByAttribute(plugin, "class", "msg msgBottomLinks");
     bottomLinks.style.display = "block";
@@ -6217,17 +6223,17 @@ var gMissingPluginInstaller = {
       let observer = {
         QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
                                                Ci.nsISupportsWeakReference]),
         observe : function(subject, topic, data) {
           let propertyBag = subject;
           if (!(propertyBag instanceof Ci.nsIPropertyBag2))
             return;
           // Ignore notifications for other crashes.
-          if (propertyBag.get("minidumpID") != minidumpID)
+          if (propertyBag.get("minidumpID") != pluginDumpID)
             return;
           self.updateSubmissionStatus(plugin, propertyBag, data);
         },
 
         handleEvent : function(event) {
             // Not expected to be called, just here for the closure.
         }
       }
@@ -6261,60 +6267,61 @@ var gMissingPluginInstaller = {
                            (overlay.scrollHeight - 5 > pluginRect.height);
     if (isObjectTooSmall) {
         // Hide the overlay's contents. Use visibility style, so that it
         // doesn't collapse down to 0x0.
         overlay.style.visibility = "hidden";
         // If another plugin on the page was large enough to show our UI, we
         // don't want to show a notification bar.
         if (!doc.mozNoPluginCrashedNotification)
-          showNotificationBar(minidumpID);
+          showNotificationBar(pluginDumpID, browserDumpID);
     } else {
         // If a previous plugin on the page was too small and resulted in
         // adding a notification bar, then remove it because this plugin
         // instance it big enough to serve as in-content notification.
         hideNotificationBar();
         doc.mozNoPluginCrashedNotification = true;
     }
 
     function hideNotificationBar() {
       let notification = notificationBox.getNotificationWithValue("plugin-crashed");
       if (notification)
         notificationBox.removeNotification(notification, true);
     }
 
-    function showNotificationBar(minidumpID) {
+    function showNotificationBar(pluginDumpID, browserDumpID) {
       // If there's already an existing notification bar, don't do anything.
       let notification = notificationBox.getNotificationWithValue("plugin-crashed");
       if (notification)
         return;
 
       // Configure the notification bar
       let priority = notificationBox.PRIORITY_WARNING_MEDIUM;
       let iconURL = "chrome://mozapps/skin/plugins/pluginGeneric-16.png";
       let reloadLabel = gNavigatorBundle.getString("crashedpluginsMessage.reloadButton.label");
       let reloadKey   = gNavigatorBundle.getString("crashedpluginsMessage.reloadButton.accesskey");
       let submitLabel = gNavigatorBundle.getString("crashedpluginsMessage.submitButton.label");
       let submitKey   = gNavigatorBundle.getString("crashedpluginsMessage.submitButton.accesskey");
 
-      let buttons = [
+      let buttons = [{
+        label: reloadLabel,
+        accessKey: reloadKey,
+        popup: null,
+        callback: function() { browser.reload(); },
+      }];
 #ifdef MOZ_CRASHREPORTER
-        {
-          label: submitLabel,
-          accessKey: submitKey,
-          popup: null,
-          callback: function() { gMissingPluginInstaller.submitReport(minidumpID); },
-        },
+      let submitButton = {
+        label: submitLabel,
+        accessKey: submitKey,
+        popup: null,
+          callback: function() { gMissingPluginInstaller.submitReport(pluginDumpID, browserDumpID); },
+      };
+      if (minidumpID)
+        buttons.push(submitButton);
 #endif
-        {
-          label: reloadLabel,
-          accessKey: reloadKey,
-          popup: null,
-          callback: function() { browser.reload(); },
-        }];
 
       let notification = notificationBox.appendNotification(messageString, "plugin-crashed",
                                                             iconURL, priority, buttons);
 
       // Add the "learn more" link.
       let XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
       let link = notification.ownerDocument.createElementNS(XULNS, "label");
       link.className = "text-link";
@@ -6374,45 +6381,45 @@ function convertFromUnicode(charset, str
   try {
     var unicodeConverter = Components
        .classes["@mozilla.org/intl/scriptableunicodeconverter"]
        .createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
     unicodeConverter.charset = charset;
     str = unicodeConverter.ConvertFromUnicode(str);
     return str + unicodeConverter.Finish();
   } catch(ex) {
-    return null; 
+    return null;
   }
 }
 
 /**
  * The Feed Handler object manages discovery of RSS/ATOM feeds in web pages
- * and shows UI when they are discovered. 
+ * and shows UI when they are discovered.
  */
 var FeedHandler = {
   /**
    * The click handler for the Feed icon in the location bar. Opens the
    * subscription page if user is not given a choice of feeds.
-   * (Otherwise the list of available feeds will be presented to the 
+   * (Otherwise the list of available feeds will be presented to the
    * user in a popup menu.)
    */
   onFeedButtonClick: function(event) {
     event.stopPropagation();
 
     if (event.target.hasAttribute("feed") &&
         event.eventPhase == Event.AT_TARGET &&
         (event.button == 0 || event.button == 1)) {
         this.subscribeToFeed(null, event);
     }
   },
-  
+
   /**
-   * Called when the user clicks on the Feed icon in the location bar. 
+   * Called when the user clicks on the Feed icon in the location bar.
    * Builds a menu of unique feeds associated with the page, and if there
-   * is only one, shows the feed inline in the browser window. 
+   * is only one, shows the feed inline in the browser window.
    * @param   menuPopup
    *          The feed list menupopup to be populated.
    * @returns true if the menu should be shown, false if there was only
    *          one feed and the feed should be shown inline in the browser
    *          window (do not show the menupopup).
    */
   buildFeedList: function(menuPopup) {
     var feeds = gBrowser.selectedBrowser.feeds;
@@ -6432,43 +6439,43 @@ var FeedHandler = {
 
     if (feeds.length == 1) {
       var feedButton = document.getElementById("feed-button");
       if (feedButton)
         feedButton.setAttribute("feed", feeds[0].href);
       return false;
     }
 
-    // Build the menu showing the available feed choices for viewing. 
+    // Build the menu showing the available feed choices for viewing.
     for (var i = 0; i < feeds.length; ++i) {
       var feedInfo = feeds[i];
       var menuItem = document.createElement("menuitem");
       var baseTitle = feedInfo.title || feedInfo.href;
       var labelStr = gNavigatorBundle.getFormattedString("feedShowFeedNew", [baseTitle]);
       menuItem.setAttribute("class", "feed-menuitem");
       menuItem.setAttribute("label", labelStr);
       menuItem.setAttribute("feed", feedInfo.href);
       menuItem.setAttribute("tooltiptext", feedInfo.href);
       menuItem.setAttribute("crop", "center");
       menuPopup.appendChild(menuItem);
     }
     return true;
   },
-  
+
   /**
    * Subscribe to a given feed.  Called when
    *   1. Page has a single feed and user clicks feed icon in location bar
    *   2. Page has a single feed and user selects Subscribe menu item
    *   3. Page has multiple feeds and user selects from feed icon popup
    *   4. Page has multiple feeds and user selects from Subscribe submenu
    * @param   href
    *          The feed to subscribe to. May be null, in which case the
    *          event target's feed attribute is examined.
    * @param   event
-   *          The event this method is handling. Used to decide where 
+   *          The event this method is handling. Used to decide where
    *          to open the preview UI. (Optional, unless href is null)
    */
   subscribeToFeed: function(href, event) {
     // Just load the feed in the content area to either subscribe or show the
     // preview UI
     if (!href)
       href = event.target.getAttribute("feed");
     urlSecurityCheck(href, gBrowser.contentPrincipal,
@@ -6482,25 +6489,25 @@ var FeedHandler = {
   },
 
   loadFeed: function(href, event) {
     var feeds = gBrowser.selectedBrowser.feeds;
     try {
       openUILink(href, event, false, true, false, null);
     }
     finally {
-      // We might default to a livebookmarks modal dialog, 
+      // We might default to a livebookmarks modal dialog,
       // so reset that if the user happens to click it again
       gBrowser.selectedBrowser.feeds = feeds;
     }
   },
 
   /**
    * Update the browser UI to show whether or not feeds are available when
-   * a page is loaded or the user switches tabs to a page that has feeds. 
+   * a page is loaded or the user switches tabs to a page that has feeds.
    */
   updateFeeds: function() {
     var feedButton = document.getElementById("feed-button");
     if (!this._feedMenuitem)
       this._feedMenuitem = document.getElementById("subscribeToPageMenuitem");
     if (!this._feedMenupopup)
       this._feedMenupopup = document.getElementById("subscribeToPageMenupopup");
 
@@ -6511,33 +6518,33 @@ var FeedHandler = {
         feedButton.removeAttribute("feed");
       }
       this._feedMenuitem.setAttribute("disabled", "true");
       this._feedMenupopup.setAttribute("hidden", "true");
       this._feedMenuitem.removeAttribute("hidden");
     } else {
       if (feedButton)
         feedButton.collapsed = false;
-      
+
       if (feeds.length > 1) {
         this._feedMenuitem.setAttribute("hidden", "true");
         this._feedMenupopup.removeAttribute("hidden");
         if (feedButton)
           feedButton.removeAttribute("feed");
       } else {
         if (feedButton)
           feedButton.setAttribute("feed", feeds[0].href);
 
         this._feedMenuitem.setAttribute("feed", feeds[0].href);
         this._feedMenuitem.removeAttribute("disabled");
         this._feedMenuitem.removeAttribute("hidden");
         this._feedMenupopup.setAttribute("hidden", "true");
       }
     }
-  }, 
+  },
 
   addFeed: function(link, targetDoc) {
     // find which tab this is for, and set the attribute on the browser
     var browserForLink = gBrowser.getBrowserForDocument(targetDoc);
     if (!browserForLink) {
       // ignore feeds loaded in subframes (see bug 305472)
       return;
     }
@@ -6572,21 +6579,21 @@ function undoCloseTab(aIndex) {
       !gBrowser.selectedTab.hasAttribute("busy"))
     blankTabToRemove = gBrowser.selectedTab;
 
   var tab = null;
   var ss = Cc["@mozilla.org/browser/sessionstore;1"].
            getService(Ci.nsISessionStore);
   if (ss.getClosedTabCount(window) > (aIndex || 0)) {
     tab = ss.undoCloseTab(window, aIndex || 0);
-    
+
     if (blankTabToRemove)
       gBrowser.removeTab(blankTabToRemove);
   }
-  
+
   return tab;
 }
 
 /**
  * Re-open a closed window.
  * @param aIndex
  *        The index of the window (via nsSessionStore.getClosedWindowData)
  * @returns a reference to the reopened window.
@@ -6745,55 +6752,55 @@ var gIdentityHandler = {
   /**
    * Handler for mouseclicks on the "More Information" button in the
    * "identity-popup" panel.
    */
   handleMoreInfoClick : function(event) {
     displaySecurityInfo();
     event.stopPropagation();
   },
-  
+
   /**
    * Helper to parse out the important parts of _lastStatus (of the SSL cert in
    * particular) for use in constructing identity UI strings
   */
   getIdentityData : function() {
     var result = {};
     var status = this._lastStatus.QueryInterface(Components.interfaces.nsISSLStatus);
     var cert = status.serverCert;
-    
+
     // Human readable name of Subject
     result.subjectOrg = cert.organization;
-    
+
     // SubjectName fields, broken up for individual access
     if (cert.subjectName) {
       result.subjectNameFields = {};
       cert.subjectName.split(",").forEach(function(v) {
         var field = v.split("=");
         this[field[0]] = field[1];
       }, result.subjectNameFields);
-      
+
       // Call out city, state, and country specifically
       result.city = result.subjectNameFields.L;
       result.state = result.subjectNameFields.ST;
       result.country = result.subjectNameFields.C;
     }
-    
+
     // Human readable name of Certificate Authority
     result.caOrg =  cert.issuerOrganization || cert.issuerCommonName;
     result.cert = cert;
-    
+
     return result;
   },
-  
+
   /**
    * Determine the identity of the page being displayed by examining its SSL cert
    * (if available) and, if necessary, update the UI to reflect this.  Intended to
    * be called by onSecurityChange
-   * 
+   *
    * @param PRUint32 state
    * @param JS Object location that mirrors an nsLocation (i.e. has .host and
    *                           .hostname and .port)
    */
   checkIdentity : function(state, location) {
     var currentStatus = gBrowser.securityUI
                                 .QueryInterface(Components.interfaces.nsISSLStatusProvider)
                                 .SSLStatus;
@@ -6805,96 +6812,96 @@ var gIdentityHandler = {
       this.setMode(this.IDENTITY_MODE_IDENTIFIED);
     else if (state & nsIWebProgressListener.STATE_SECURE_HIGH)
       this.setMode(this.IDENTITY_MODE_DOMAIN_VERIFIED);
     else if (state & nsIWebProgressListener.STATE_IS_BROKEN)
       this.setMode(this.IDENTITY_MODE_MIXED_CONTENT);
     else
       this.setMode(this.IDENTITY_MODE_UNKNOWN);
   },
-  
+
   /**
    * Return the eTLD+1 version of the current hostname
    */
   getEffectiveHost : function() {
     // Cache the eTLDService if this is our first time through
     if (!this._eTLDService)
       this._eTLDService = Cc["@mozilla.org/network/effective-tld-service;1"]
                          .getService(Ci.nsIEffectiveTLDService);
     try {
       return this._eTLDService.getBaseDomainFromHost(this._lastLocation.hostname);
     } catch (e) {
       // If something goes wrong (e.g. hostname is an IP address) just fail back
       // to the full domain.
       return this._lastLocation.hostname;
     }
   },
-  
+
   /**
    * Update the UI to reflect the specified mode, which should be one of the
    * IDENTITY_MODE_* constants.
    */
   setMode : function(newMode) {
     if (!this._identityBox) {
       // No identity box means the identity box is not visible, in which
       // case there's nothing to do.
       return;
     }
 
     this._identityBox.className = newMode;
     this.setIdentityMessages(newMode);
-    
+
     // Update the popup too, if it's open
     if (this._identityPopup.state == "open")
       this.setPopupMessages(newMode);
   },
-  
+
   /**
    * Set up the messages for the primary identity UI based on the specified mode,
    * and the details of the SSL cert, where applicable
    *
    * @param newMode The newly set identity mode.  Should be one of the IDENTITY_MODE_* constants.
    */
   setIdentityMessages : function(newMode) {
     if (newMode == this.IDENTITY_MODE_DOMAIN_VERIFIED) {
-      var iData = this.getIdentityData();     
-      
+      var iData = this.getIdentityData();
+
       // It would be sort of nice to use the CN= field in the cert, since that's
       // typically what we want here, but thanks to x509 certs being extensible,
       // it's not the only place you have to check, there can be more than one domain,
       // et cetera, ad nauseum.  We know the cert is valid for location.host, so
       // let's just use that. Check the pref to determine how much of the verified
       // hostname to show
       var icon_label = "";
       var icon_country_label = "";
       var icon_labels_dir = "ltr";
       switch (gPrefService.getIntPref("browser.identity.ssl_domain_display")) {
         case 2 : // Show full domain
           icon_label = this._lastLocation.hostname;
           break;
         case 1 : // Show eTLD.
           icon_label = this.getEffectiveHost();
       }
-      
+
       // We need a port number for all lookups.  If one hasn't been specified, use
       // the https default
       var lookupHost = this._lastLocation.host;
       if (lookupHost.indexOf(':') < 0)
         lookupHost += ":443";
 
       // Verifier is either the CA Org, for a normal cert, or a special string
       // for certs that are trusted because of a security exception.
       var tooltip = gNavigatorBundle.getFormattedString("identity.identified.verifier",
                                                         [iData.caOrg]);
-      
+
       // Check whether this site is a security exception. XPConnect does the right
       // thing here in terms of converting _lastLocation.port from string to int, but
       // the overrideService doesn't like undefined ports, so make sure we have
       // something in the default case (bug 432241).
-      if (this._overrideService.hasMatchingOverride(this._lastLocation.hostname, 
+      if (this._overrideService.hasMatchingOverride(this._lastLocation.hostname,
                                                     (this._lastLocation.port || 443),
                                                     iData.cert, {}, {}))
         tooltip = gNavigatorBundle.getString("identity.identified.verified_by_you");
     }
     else if (newMode == this.IDENTITY_MODE_IDENTIFIED) {
       // If it's identified, then we can populate the dialog with credentials
       iData = this.getIdentityData();
       tooltip = gNavigatorBundle.getFormattedString("identity.identified.verifier",
@@ -6912,115 +6919,115 @@ var gIdentityHandler = {
                         "rtl" : "ltr";
     }
     else {
       tooltip = gNavigatorBundle.getString("identity.unknown.tooltip");
       icon_label = "";
       icon_country_label = "";
       icon_labels_dir = "ltr";
     }
-    
+
     // Push the appropriate strings out to the UI
     this._identityBox.tooltipText = tooltip;
     this._identityIconLabel.value = icon_label;
     this._identityIconCountryLabel.value = icon_country_label;
     // Set cropping and direction
     this._identityIconLabel.crop = icon_country_label ? "end" : "center";
     this._identityIconLabel.parentNode.style.direction = icon_labels_dir;
     // Hide completely if the organization label is empty
     this._identityIconLabel.parentNode.hidden = icon_label ? false : true;
   },
-  
+
   /**
    * Set up the title and content messages for the identity message popup,
    * based on the specified mode, and the details of the SSL cert, where
    * applicable
    *
    * @param newMode The newly set identity mode.  Should be one of the IDENTITY_MODE_* constants.
    */
   setPopupMessages : function(newMode) {
-      
+
     this._identityPopup.className = newMode;
     this._identityPopupContentBox.className = newMode;
-    
+
     // Set the static strings up front
     this._identityPopupEncLabel.textContent = this._encryptionLabel[newMode];
-    
+
     // Initialize the optional strings to empty values
     var supplemental = "";
     var verifier = "";
-    
+
     if (newMode == this.IDENTITY_MODE_DOMAIN_VERIFIED) {
       var iData = this.getIdentityData();
       var host = this.getEffectiveHost();
       var owner = gNavigatorBundle.getString("identity.ownerUnknown2");
       verifier = this._identityBox.tooltipText;
       supplemental = "";
     }
     else if (newMode == this.IDENTITY_MODE_IDENTIFIED) {
       // If it's identified, then we can populate the dialog with credentials
       iData = this.getIdentityData();
       host = this.getEffectiveHost();
-      owner = iData.subjectOrg; 
+      owner = iData.subjectOrg;
       verifier = this._identityBox.tooltipText;
 
       // Build an appropriate supplemental block out of whatever location data we have
       if (iData.city)
-        supplemental += iData.city + "\n";        
+        supplemental += iData.city + "\n";
       if (iData.state && iData.country)
         supplemental += gNavigatorBundle.getFormattedString("identity.identified.state_and_country",
                                                             [iData.state, iData.country]);
       else if (iData.state) // State only
         supplemental += iData.state;
       else if (iData.country) // Country only
         supplemental += iData.country;
     }
     else {
       // These strings will be hidden in CSS anyhow
       host = "";
       owner = "";
     }
-    
+
     // Push the appropriate strings out to the UI
     this._identityPopupContentHost.textContent = host;
     this._identityPopupContentOwner.textContent = owner;
     this._identityPopupContentSupp.textContent = supplemental;
     this._identityPopupContentVerif.textContent = verifier;
   },
 
   hideIdentityPopup : function() {
     this._identityPopup.hidePopup();
   },
 
   /**
-   * Click handler for the identity-box element in primary chrome.  
+   * Click handler for the identity-box element in primary chrome.
    */
   handleIdentityButtonEvent : function(event) {
-  
+
     event.stopPropagation();
- 
+
     if ((event.type == "click" && event.button != 0) ||
         (event.type == "keypress" && event.charCode != KeyEvent.DOM_VK_SPACE &&
          event.keyCode != KeyEvent.DOM_VK_RETURN))
       return; // Left click, space or enter only
 
     // Revert the contents of the location bar, see bug 406779
     gURLBar.handleRevert();
 
     // Make sure that the display:none style we set in xul is removed now that
     // the popup is actually needed
     this._identityPopup.hidden = false;
-    
+
     // Tell the popup to consume dismiss clicks, to avoid bug 395314
     this._identityPopup.popupBoxObject
         .setConsumeRollupEvent(Ci.nsIPopupBoxObject.ROLLUP_CONSUME);
-    
+
     // Update the popup strings
     this.setPopupMessages(this._identityBox.className);
-    
+
     // Make sure the identity popup hangs toward the middle of the location bar
     // in RTL builds
     var position = (getComputedStyle(gNavToolbox, "").direction == "rtl") ? 'after_end' : 'after_start';
 
     // Add the "open" attribute to the identity box for styling
     this._identityBox.setAttribute("open", "true");
     var self = this;
     this._identityPopup.addEventListener("popuphidden", function (e) {
@@ -7089,17 +7096,17 @@ let DownloadMonitorPanel = {
 
     // Hide the panel and reset the "last time" if there's no downloads
     if (numActive == 0) {
       this._panel.hidden = true;
       this._lastTime = Infinity;
 
       return;
     }
-  
+
     // Find the download with the longest remaining time
     let numPaused = 0;
     let maxTime = -Infinity;
     let dls = gDownloadMgr.activeDownloads;
     while (dls.hasMoreElements()) {
       let dl = dls.getNext().QueryInterface(Ci.nsIDownload);
       if (dl.state == gDownloadMgr.DOWNLOAD_DOWNLOADING) {
         // Figure out if this download takes longer
@@ -7290,17 +7297,17 @@ let gPrivateBrowsingUI = {
       this._searchBarValue = BrowserSearch.searchBar.textbox.value;
 
     if (gFindBar)
       this._findBarValue = gFindBar.getElement("findbar-textbox").value;
 
     this._setPBMenuTitle("stop");
 
     document.getElementById("menu_import").setAttribute("disabled", "true");
-    
+
     // Disable the Clear Recent History... menu item when in PB mode
     // temporary fix until bug 463607 is fixed
     document.getElementById("Tools:Sanitize").setAttribute("disabled", "true");
 
     if (this._privateBrowsingService.autoStarted) {
       // Disable the menu item in auto-start mode
       document.getElementById("privateBrowsingItem")
               .setAttribute("disabled", "true");
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -73,16 +73,20 @@
             <xul:browser flex="1" type="content-primary" message="true" disablehistory="true"
                          xbl:inherits="tooltip=contenttooltip,contextmenu=contentcontextmenu,autocompletepopup"/>
           </xul:notificationbox>
         </xul:tabpanels>
       </xul:tabbox>
       <children/>
     </content>
     <implementation implements="nsIDOMEventListener">
+
+      <property name="tabContextMenu" readonly="true"
+                onget="return this.tabContainer.contextMenu;"/>
+
       <field name="tabContainer" readonly="true">
         document.getElementById(this.getAttribute("tabcontainer"));
       </field>
       <field name="tabs" readonly="true">
         this.tabContainer.childNodes;
       </field>
       <field name="mURIFixup" readonly="true">
         Components.classes["@mozilla.org/docshell/urifixup;1"]
@@ -432,19 +436,23 @@
             },
 
             onLocationChange : function(aWebProgress, aRequest, aLocation)
             {
               // The document loaded correctly, clear the value if we should
               if (this.mBrowser.userTypedClear > 0)
                 this.mBrowser.userTypedValue = null;
 
+              // Don't clear the favicon if this onLocationChange was triggered
+              // by a pushState or a replaceState.  See bug 550565.
               if (aWebProgress.DOMWindow == this.mBrowser.contentWindow &&
-                  aWebProgress.isLoadingDocument)
-                this.mTabBrowser.getBrowserForTab(this.mTab).mIconURL = null;
+                  aWebProgress.isLoadingDocument &&
+                  !(this.mBrowser.docShell.loadType & Ci.nsIDocShell.LOAD_CMD_PUSHSTATE)) {
+                this.mBrowser.mIconURL = null;
+              }
 
               // changing location, clear out the missing plugins list
               this.mBrowser.missingPlugins = null;
 
               if (this.mBlank)
                 return;
 
               if (this.mTabBrowser.mCurrentTab == this.mTab) {
@@ -2277,16 +2285,41 @@
       <property name="mContextTab" readonly="true"
                 onget="return this.tabContainer._contextTab;"/>
       <property name="mPrefs" readonly="true"
                 onget="return Services.prefs;"/>
       <property name="mTabContainer" readonly="true"
                 onget="return this.tabContainer;"/>
       <property name="mTabs" readonly="true"
                 onget="return this.tabs;"/>
+      <!--
+        - Compatibility hack: several extensions depend on this property to
+        - access the tab context menu or tab container, so keep that working for
+        - now. Ideally we can remove this once extensions are using
+        - tabbrowser.tabContextMenu and tabbrowser.tabContainer directly.
+        -->
+      <property name="mStrip" readonly="true">
+        <getter>
+        <![CDATA[
+          return ({
+            self: this,
+            childNodes: [null, this.tabContextMenu, this.tabContainer],
+            firstChild: { nextSibling: this.tabContextMenu },
+            getElementsByAttribute: function (attr, attrValue) {
+              if (attr == "anonid" && attrValue == "tabContextMenu")
+                return [this.self.tabContextMenu];
+              return [];
+            },
+            // Also support adding event listeners (forward to the tab container)
+            addEventListener: function (a,b,c) { this.self.tabContainer.addEventListener(a,b,c); },
+            removeEventListener: function (a,b,c) { this.self.tabContainer.removeEventListener(a,b,c); }
+          });
+        ]]>
+        </getter>
+      </property>
     </implementation>
 
     <handlers>
       <handler event="DOMWindowClose" phase="capturing">
         <![CDATA[
           if (!event.isTrusted)
             return;
 
@@ -2482,16 +2515,20 @@
       <field name="tabbrowser" readonly="true">
         document.getElementById(this.getAttribute("tabbrowser"));
       </field>
 
       <field name="tabbox" readonly="true">
         this.tabbrowser.mTabBox;
       </field>
 
+      <field name="contextMenu" readonly="true">
+        document.getAnonymousElementByAttribute(this, "anonid", "tabContextMenu");
+      </field>
+
       <field name="mTabstripWidth">0</field>
 
       <field name="mTabstrip">
         document.getAnonymousElementByAttribute(this, "anonid", "arrowscrollbox");
       </field>
 
       <field name="mTabstripClosebutton">
         document.getAnonymousElementByAttribute(this, "anonid", "tabs-closebutton");
--- a/browser/base/content/test/browser_bug386835.js
+++ b/browser/base/content/test/browser_bug386835.js
@@ -36,122 +36,109 @@ function secondPageLoaded() {
 }
 
 function thirdPageLoaded() {
   zoomTest(gTab1, gLevel, "Tab 1 should still be zoomed");
   zoomTest(gTab2, 1, "Tab 2 should still not be affected");
   zoomTest(gTab3, gLevel, "Tab 3 should have zoomed as it was loading in the background");
 
   // Switching to tab 2 should update its zoom setting.
-  gBrowser.selectedTab = gTab2;
+  afterZoom(function() {
+    zoomTest(gTab1, gLevel, "Tab 1 should still be zoomed");
+    zoomTest(gTab2, gLevel, "Tab 2 should be zoomed now");
+    zoomTest(gTab3, gLevel, "Tab 3 should still be zoomed");
 
-  zoomTest(gTab1, gLevel, "Tab 1 should still be zoomed");
-  zoomTest(gTab2, gLevel, "Tab 2 should be zoomed now");
-  zoomTest(gTab3, gLevel, "Tab 3 should still be zoomed");
+    load(gTab1, gTestImage, imageLoaded);
+  });
 
-  load(gTab1, gTestImage, imageLoaded);
+  gBrowser.selectedTab = gTab2;
 }
 
 function imageLoaded() {
   zoomTest(gTab1, 1, "Zoom should be 1 when image was loaded in the background");
+  afterZoom(function() {
+    zoomTest(gTab1, 1, "Zoom should still be 1 when tab with image is selected");
+
+    executeSoon(imageZoomSwitch);
+  });
   gBrowser.selectedTab = gTab1;
-  zoomTest(gTab1, 1, "Zoom should still be 1 when tab with image is selected");
-
-  executeSoon(imageZoomSwitch);
 }
 
 function imageZoomSwitch() {
   navigate(BACK, function () {
     navigate(FORWARD, function () {
       zoomTest(gTab1, 1, "Tab 1 should not be zoomed when an image loads");
-      gBrowser.selectedTab = gTab2;
-      zoomTest(gTab1, 1, "Tab 1 should still not be zoomed when deselected");
-
-      // Mac OS X does not support print preview, so skip those tests
-      let isOSX = ("nsILocalFileMac" in Components.interfaces);
-      if (isOSX)
-        finishTest();
-      else
-        runPrintPreviewTests();
-    });
-  });
-}
 
-function runPrintPreviewTests() {
-  // test print preview on image document
-  testPrintPreview(gTab1, function() {
-    // test print preview on HTML document
-    testPrintPreview(gTab2, function() {
-      // test print preview on image document with siteSpecific set to false
-      gPrefService.setBoolPref("browser.zoom.siteSpecific", false);
-      testPrintPreview(gTab1, function() {
-        // test print preview of HTML document with siteSpecific set to false
-        testPrintPreview(gTab2, function() {
-          if (gPrefService.prefHasUserValue("browser.zoom.siteSpecific"))
-            gPrefService.clearUserPref("browser.zoom.siteSpecific");
-          finishTest();
-        });
+      afterZoom(function() {
+        zoomTest(gTab1, 1, "Tab 1 should still not be zoomed when deselected");
+        finishTest();
       });
+      gBrowser.selectedTab = gTab2;
+
+      finishTest();
     });
   });
 }
 
-function testPrintPreview(aTab, aCallback) {
-  gBrowser.selectedTab = aTab;
-  FullZoom.enlarge();
-  let level = ZoomManager.zoom;
-
-  let onEnterOrig = PrintPreviewListener.onEnter;
-  PrintPreviewListener.onEnter = function () {
-    PrintPreviewListener.onEnter = onEnterOrig;
-    PrintPreviewListener.onEnter.apply(PrintPreviewListener, arguments);
-    PrintUtils.exitPrintPreview();
-  };
-
-  let onExitOrig = PrintPreviewListener.onExit;
-  PrintPreviewListener.onExit = function () {
-    PrintPreviewListener.onExit = onExitOrig;
-    PrintPreviewListener.onExit.apply(PrintPreviewListener, arguments);
-
-    zoomTest(aTab, level, "Toggling print preview mode should not affect zoom level");
-
-    FullZoom.reset();
-    aCallback();
-  };
-
-  executeSoon(function () {
-    document.getElementById("cmd_printPreview").doCommand();
-  });
-}
-
 function finishTest() {
   gBrowser.selectedTab = gTab1;
   FullZoom.reset();
   gBrowser.removeTab(gTab1);
   FullZoom.reset();
   gBrowser.removeTab(gTab2);
   FullZoom.reset();
   gBrowser.removeTab(gTab3);
   finish();
 }
 
 function zoomTest(tab, val, msg) {
   is(ZoomManager.getZoomForBrowser(tab.linkedBrowser), val, msg);
 }
 
 function load(tab, url, cb) {
+  let didLoad = didZoom = false;
   tab.linkedBrowser.addEventListener("load", function (event) {
     event.currentTarget.removeEventListener("load", arguments.callee, true);
-    cb();
+    didLoad = true;
+    if (didZoom)
+      executeSoon(cb);
   }, true);
+
+  afterZoom(function() {
+    didZoom = true;
+    if (didLoad)
+      executeSoon(cb);
+  });
+
   tab.linkedBrowser.loadURI(url);
 }
 
 function navigate(direction, cb) {
+  let didPs = didZoom = false;
   gBrowser.addEventListener("pageshow", function (event) {
     gBrowser.removeEventListener("pageshow", arguments.callee, true);
-    executeSoon(cb);
+    didPs = true;
+    if (didZoom)
+      executeSoon(cb);
   }, true);
+
+  afterZoom(function() {
+    didZoom = true;
+    if (didPs)
+      executeSoon(cb);
+  });
+
   if (direction == BACK)
     gBrowser.goBack();
   else if (direction == FORWARD)
     gBrowser.goForward();
 }
+
+function afterZoom(cb) {
+  let oldAPTS = FullZoom._applyPrefToSetting;
+  FullZoom._applyPrefToSetting = function(value, browser) {
+    if (!value)
+      value = undefined;
+    oldAPTS.call(FullZoom, value, browser);
+    FullZoom._applyPrefToSetting = oldAPTS;
+    executeSoon(cb);
+  };
+}
--- a/browser/base/content/test/browser_bug416661.js
+++ b/browser/base/content/test/browser_bug416661.js
@@ -1,49 +1,63 @@
 var tabElm, zoomLevel;
 function start_test_prefNotSet() {
-  tabElm.linkedBrowser.removeEventListener("load", start_test_prefNotSet, true);
-  tabElm.linkedBrowser.addEventListener("load", continue_test_prefNotSet, true);
-
   is(ZoomManager.zoom, 1, "initial zoom level should be 1");
   FullZoom.enlarge();
 
   //capture the zoom level to test later
   zoomLevel = ZoomManager.zoom;
   isnot(zoomLevel, 1, "zoom level should have changed");
 
+  afterZoomAndLoad(continue_test_prefNotSet);
   content.location = 
     "http://mochi.test:8888/browser/browser/base/content/test/moz.png";
 }
 
 function continue_test_prefNotSet () {
-  tabElm.linkedBrowser.removeEventListener("load", continue_test_prefNotSet, true);
-  tabElm.linkedBrowser.addEventListener("load", end_test_prefNotSet, true);
-
   is(ZoomManager.zoom, 1, "zoom level pref should not apply to an image");
   FullZoom.reset();
 
+  afterZoomAndLoad(end_test_prefNotSet);
   content.location = 
     "http://mochi.test:8888/browser/browser/base/content/test/zoom_test.html";
 }
 
 function end_test_prefNotSet() {
-  tabElm.linkedBrowser.removeEventListener("load", end_test_prefNotSet, true);
   is(ZoomManager.zoom, zoomLevel, "the zoom level should have persisted");
 
   // Reset the zoom so that other tests have a fresh zoom level
   FullZoom.reset();
   gBrowser.removeCurrentTab();
   finish();
 }
 
 
 function test() {
   waitForExplicitFinish();
 
   tabElm = gBrowser.addTab();
   gBrowser.selectedTab = tabElm;
-  tabElm.linkedBrowser.addEventListener("load", start_test_prefNotSet, true);
 
+  afterZoomAndLoad(start_test_prefNotSet);
   content.location = 
     "http://mochi.test:8888/browser/browser/base/content/test/zoom_test.html";
+}
 
+function afterZoomAndLoad(cb) {
+  let didLoad = didZoom = false;
+  tabElm.linkedBrowser.addEventListener("load", function() {
+    tabElm.linkedBrowser.removeEventListener("load", arguments.callee, true);
+    didLoad = true;
+    if (didZoom)
+      executeSoon(cb);
+  }, true);
+  let oldAPTS = FullZoom._applyPrefToSetting;
+  FullZoom._applyPrefToSetting = function(value, browser) {
+    if (!value)
+      value = undefined;
+    oldAPTS.call(FullZoom, value, browser);
+    FullZoom._applyPrefToSetting = oldAPTS;
+    didZoom = true;
+    if (didLoad)
+      executeSoon(cb);
+  };
 }
--- a/browser/base/content/test/browser_bug419612.js
+++ b/browser/base/content/test/browser_bug419612.js
@@ -7,29 +7,43 @@ function test() {
     event.currentTarget.removeEventListener("load", arguments.callee, true);
 
     let tab2 = gBrowser.addTab();
     tab2.linkedBrowser.addEventListener("load", (function(event) {
       event.currentTarget.removeEventListener("load", arguments.callee, true);
 
       FullZoom.enlarge();
       let tab1Zoom = ZoomManager.getZoomForBrowser(tab1.linkedBrowser);
-      gBrowser.selectedTab = tab2;
-      let tab2Zoom = ZoomManager.getZoomForBrowser(tab2.linkedBrowser);
-      is(tab2Zoom, tab1Zoom, "Zoom should affect background tabs");
+
+      afterZoom(function() {
+        let tab2Zoom = ZoomManager.getZoomForBrowser(tab2.linkedBrowser);
+        is(tab2Zoom, tab1Zoom, "Zoom should affect background tabs");
 
-      gPrefService.setBoolPref("browser.zoom.updateBackgroundTabs", false);
-      FullZoom.reset();
-      gBrowser.selectedTab = tab1;
-      tab1Zoom = ZoomManager.getZoomForBrowser(tab1.linkedBrowser);
-      tab2Zoom = ZoomManager.getZoomForBrowser(tab2.linkedBrowser);
-      isnot(tab1Zoom, tab2Zoom, "Zoom should not affect background tabs");
+        gPrefService.setBoolPref("browser.zoom.updateBackgroundTabs", false);
+        FullZoom.reset();
+        gBrowser.selectedTab = tab1;
+        tab1Zoom = ZoomManager.getZoomForBrowser(tab1.linkedBrowser);
+        tab2Zoom = ZoomManager.getZoomForBrowser(tab2.linkedBrowser);
+        isnot(tab1Zoom, tab2Zoom, "Zoom should not affect background tabs");
 
-      if (gPrefService.prefHasUserValue("browser.zoom.updateBackgroundTabs"))
-        gPrefService.clearUserPref("browser.zoom.updateBackgroundTabs");
-      gBrowser.removeTab(tab1);
-      gBrowser.removeTab(tab2);
-      finish();
+        if (gPrefService.prefHasUserValue("browser.zoom.updateBackgroundTabs"))
+          gPrefService.clearUserPref("browser.zoom.updateBackgroundTabs");
+        gBrowser.removeTab(tab1);
+        gBrowser.removeTab(tab2);
+        finish();
+      });
+      gBrowser.selectedTab = tab2;
     }), true);
     tab2.linkedBrowser.loadURI(testPage);
   }), true);
   content.location = testPage;
 }
+
+function afterZoom(cb) {
+  let oldAPTS = FullZoom._applyPrefToSetting;
+  FullZoom._applyPrefToSetting = function(value, browser) {
+    if (!value)
+      value = undefined;
+    oldAPTS.call(FullZoom, value, browser);
+    FullZoom._applyPrefToSetting = oldAPTS;
+    executeSoon(cb);
+  };
+}
--- a/browser/components/Makefile.in
+++ b/browser/components/Makefile.in
@@ -57,17 +57,16 @@ EXTRA_PP_COMPONENTS = \
 
 EXTRA_JS_MODULES = distribution.js
 
 PARALLEL_DIRS = \
   about \
   certerror \
   dirprovider \
   feeds \
-  microsummaries \
   places \
   preferences \
   privatebrowsing \
   search \
   sessionstore \
   shell \
   sidebar \
   $(NULL)
--- a/browser/components/build/Makefile.in
+++ b/browser/components/build/Makefile.in
@@ -38,17 +38,16 @@ LOCAL_INCLUDES = \
 	$(NULL)
 
 ifeq ($(OS_ARCH),WINNT)
 OS_LIBS += $(call EXPAND_LIBNAME,version)
 endif
 
 SHARED_LIBRARY_LIBS = \
 	../feeds/src/$(LIB_PREFIX)browser_feeds_s.$(LIB_SUFFIX) \
-	../places/src/$(LIB_PREFIX)browserplaces_s.$(LIB_SUFFIX) \
 	../privatebrowsing/src/$(LIB_PREFIX)privatebrowsing_s.$(LIB_SUFFIX) \
 	../about/$(LIB_PREFIX)browserabout_s.$(LIB_SUFFIX) \
 	../dirprovider/$(LIB_PREFIX)browserdir_s.$(LIB_SUFFIX) \
 	$(NULL)
 
 ifneq (,$(filter windows cocoa gtk2, $(MOZ_WIDGET_TOOLKIT)))
 SHARED_LIBRARY_LIBS += ../shell/src/$(LIB_PREFIX)shellservice_s.$(LIB_SUFFIX)
 endif
--- a/browser/components/build/nsBrowserCompsCID.h
+++ b/browser/components/build/nsBrowserCompsCID.h
@@ -86,23 +86,16 @@
 { 0x6893e69, 0x71d8, 0x4b23, { 0x81, 0xeb, 0x80, 0x31, 0x4d, 0xaf, 0x3e, 0x66 } }
 
 #define NS_FEEDSNIFFER_CONTRACTID \
   "@mozilla.org/browser/feeds/sniffer;1"
 
 #define NS_ABOUTFEEDS_CID \
 { 0x12ff56ec, 0x58be, 0x402c, { 0xb0, 0x57, 0x1, 0xf9, 0x61, 0xde, 0x96, 0x9b } }
 
-// 6fb0c970-e1b1-11db-8314-0800200c9a66
-#define NS_PLACESIMPORTEXPORTSERVICE_CID \
-{ 0x6fb0c970, 0xe1b1, 0x11db, { 0x83, 0x14, 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66 } }
-
-#define NS_PLACESIMPORTEXPORTSERVICE_CONTRACTID \
-  "@mozilla.org/browser/places/import-export-service;1"
-
 // 136e2c4d-c5a4-477c-b131-d93d7d704f64
 #define NS_PRIVATE_BROWSING_SERVICE_WRAPPER_CID \
 { 0x136e2c4d, 0xc5a4, 0x477c, { 0xb1, 0x31, 0xd9, 0x3d, 0x7d, 0x70, 0x4f, 0x64 } }
 
 // 7e4bb6ad-2fc4-4dc6-89ef-23e8e5ccf980
 #define NS_BROWSER_ABOUT_REDIRECTOR_CID \
 { 0x7e4bb6ad, 0x2fc4, 0x4dc6, { 0x89, 0xef, 0x23, 0xe8, 0xe5, 0xcc, 0xf9, 0x80 } }
 
--- a/browser/components/build/nsModule.cpp
+++ b/browser/components/build/nsModule.cpp
@@ -35,17 +35,16 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsIGenericFactory.h"
 
 #include "nsBrowserCompsCID.h"
 #include "DirectoryProvider.h"
-#include "nsPlacesImportExportService.h"
 
 #if defined(XP_WIN)
 #include "nsWindowsShellService.h"
 #elif defined(XP_MACOSX)
 #include "nsMacShellService.h"
 #elif defined(MOZ_WIDGET_GTK2)
 #include "nsGNOMEShellService.h"
 #endif
@@ -81,17 +80,16 @@
 #include "nsPrivateBrowsingServiceWrapper.h"
 #include "nsNetCID.h"
 
 using namespace mozilla::browser;
 
 /////////////////////////////////////////////////////////////////////////////
 
 NS_GENERIC_FACTORY_CONSTRUCTOR(DirectoryProvider)
-NS_GENERIC_FACTORY_CONSTRUCTOR(nsPlacesImportExportService)
 #if defined(XP_WIN)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsWindowsShellService)
 #elif defined(XP_MACOSX)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMacShellService)
 #elif defined(MOZ_WIDGET_GTK2)
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGNOMEShellService, Init)
 #endif
 
@@ -143,22 +141,16 @@ static const nsModuleComponentInfo compo
 #elif defined(MOZ_WIDGET_GTK2)
   { "Browser Shell Service",
     NS_SHELLSERVICE_CID,
     NS_SHELLSERVICE_CONTRACTID,
     nsGNOMEShellServiceConstructor },
 
 #endif
 
-
-  { "Places Import/Export Service",
-    NS_PLACESIMPORTEXPORTSERVICE_CID,
-    NS_PLACESIMPORTEXPORTSERVICE_CONTRACTID,
-    nsPlacesImportExportServiceConstructor},
-
   { "Feed Sniffer",
     NS_FEEDSNIFFER_CID,
     NS_FEEDSNIFFER_CONTRACTID,
     nsFeedSnifferConstructor,
     nsFeedSniffer::Register },
 
 #ifdef MOZ_SAFE_BROWSING
   { "about:blocked",
--- a/browser/components/dirprovider/DirectoryProvider.cpp
+++ b/browser/components/dirprovider/DirectoryProvider.cpp
@@ -94,25 +94,16 @@ DirectoryProvider::GetFile(const char *a
     rv = NS_GetSpecialDirectory(NS_APP_DEFAULTS_50_DIR,
                                 getter_AddRefs(file));
     NS_ENSURE_SUCCESS(rv, rv);
 
     file->AppendNative(NS_LITERAL_CSTRING("existing-profile-defaults.js"));
     file.swap(*aResult);
     return NS_OK;
   }
-  else if (!strcmp(aKey, NS_APP_USER_MICROSUMMARY_DIR)) {
-    rv = NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR,
-                                getter_AddRefs(file));
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    file->AppendNative(NS_LITERAL_CSTRING("microsummary-generators"));
-    file.swap(*aResult);
-    return NS_OK;
-  }
   else {
     return NS_ERROR_FAILURE;
   }
 
   nsDependentCString leafstr(leafName);
 
   nsCOMPtr<nsIFile> parentDir;
   if (file) {
--- a/browser/components/dirprovider/nsBrowserDirectoryServiceDefs.h
+++ b/browser/components/dirprovider/nsBrowserDirectoryServiceDefs.h
@@ -49,15 +49,9 @@
 //=============================================================================
 
 // ----------------------------------------------------------------------------
 // Files and directories that exist on a per-browser basis.
 // ----------------------------------------------------------------------------
 
 #define NS_APP_EXISTING_PREF_OVERRIDE           "ExistingPrefOverride"
 
-// ----------------------------------------------------------------------------
-// Files and directories that exist on a per-profile basis.
-// ----------------------------------------------------------------------------
-
-#define NS_APP_USER_MICROSUMMARY_DIR            "UsrMicsumGens"
-         
 #endif
--- a/browser/components/dirprovider/tests/unit/test_keys.js
+++ b/browser/components/dirprovider/tests/unit/test_keys.js
@@ -29,35 +29,16 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-function test_usr_micsum() {
-  let mdir = gProfD.clone();
-  mdir.append("microsummary-generators");
-
-  let tmdir = gDirSvc.get("UsrMicsumGens", Ci.nsIFile);
-  do_check_true(tmdir.equals(mdir));
-
-  if (!tmdir.exists())
-    tmdir.create(Ci.nsIFile.DIRECTORY_TYPE, 0777);
-
-  do_check_true(tmdir.isWritable());
-
-  let tfile = writeTestFile(tmdir, "usrmicsum");
-  do_check_true(tfile.exists());
-
-  mdir.append(tfile.leafName);
-  do_check_true(mdir.exists());
-}
-
 function test_bookmarkhtml() {
   let bmarks = gProfD.clone();
   bmarks.append("bookmarks.html");
 
   let tbmarks = gDirSvc.get("BMarks", Ci.nsIFile);
   do_check_true(bmarks.equals(tbmarks));
 }
 
@@ -65,18 +46,17 @@ function test_prefoverride() {
   let dir = gDirSvc.get("DefRt", Ci.nsIFile);
   dir.append("existing-profile-defaults.js");
 
   let tdir = gDirSvc.get("ExistingPrefOverride", Ci.nsIFile);
   do_check_true(dir.equals(tdir));
 }
 
 function run_test() {
-  [test_usr_micsum,
-   test_bookmarkhtml,
+  [test_bookmarkhtml,
    test_prefoverride
   ].forEach(function(f) {
     do_test_pending();
     print("Running test: " + f.name);
     f();
     do_test_finished();
   });
 }
deleted file mode 100644
--- a/browser/components/microsummaries/Makefile.in
+++ /dev/null
@@ -1,46 +0,0 @@
-# ***** BEGIN LICENSE BLOCK *****
-# Version: MPL 1.1/GPL 2.0/LGPL 2.1
-#
-# The contents of this file are subject to the Mozilla Public License Version
-# 1.1 (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-# http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-# for the specific language governing rights and limitations under the
-# License.
-#
-# The Original Code is Microsummarizer.
-#
-# The Initial Developer of the Original Code is Mozilla.
-# Portions created by the Initial Developer are Copyright (C) 2006
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#   Myk Melez <myk@mozilla.org>
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either the GNU General Public License Version 2 or later (the "GPL"), or
-# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-# in which case the provisions of the GPL or the LGPL are applicable instead
-# of those above. If you wish to allow use of your version of this file only
-# under the terms of either the GPL or the LGPL, and not to allow others to
-# use your version of this file under the terms of the MPL, indicate your
-# decision by deleting the provisions above and replace them with the notice
-# and other provisions required by the GPL or the LGPL. If you do not delete
-# the provisions above, a recipient may use your version of this file under
-# the terms of any one of the MPL, the GPL or the LGPL.
-#
-# ***** END LICENSE BLOCK *****
-
-DEPTH		= ../../..
-topsrcdir	= @top_srcdir@
-srcdir		= @srcdir@
-VPATH		= @srcdir@
-
-include $(DEPTH)/config/autoconf.mk
-
-DIRS = public src
-
-include $(topsrcdir)/config/rules.mk
deleted file mode 100644
--- a/browser/components/microsummaries/public/Makefile.in
+++ /dev/null
@@ -1,49 +0,0 @@
-# ***** BEGIN LICENSE BLOCK *****
-# Version: MPL 1.1/GPL 2.0/LGPL 2.1
-#
-# The contents of this file are subject to the Mozilla Public License Version
-# 1.1 (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-# http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-# for the specific language governing rights and limitations under the
-# License.
-#
-# The Original Code is Microsummarizer.
-#
-# The Initial Developer of the Original Code is Mozilla.
-# Portions created by the Initial Developer are Copyright (C) 2006
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#   Myk Melez <myk@mozilla.org>
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either the GNU General Public License Version 2 or later (the "GPL"), or
-# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-# in which case the provisions of the GPL or the LGPL are applicable instead
-# of those above. If you wish to allow use of your version of this file only
-# under the terms of either the GPL or the LGPL, and not to allow others to
-# use your version of this file under the terms of the MPL, indicate your
-# decision by deleting the provisions above and replace them with the notice
-# and other provisions required by the GPL or the LGPL. If you do not delete
-# the provisions above, a recipient may use your version of this file under
-# the terms of any one of the MPL, the GPL or the LGPL.
-#
-# ***** END LICENSE BLOCK *****
-
-DEPTH		= ../../../..
-topsrcdir	= @top_srcdir@
-srcdir		= @srcdir@
-VPATH		= @srcdir@
-
-include $(DEPTH)/config/autoconf.mk
-
-MODULE        = microsummaries
-XPIDL_MODULE  = microsummaries
-
-XPIDLSRCS = nsIMicrosummaryService.idl
-
-include $(topsrcdir)/config/rules.mk
deleted file mode 100644
--- a/browser/components/microsummaries/src/Makefile.in
+++ /dev/null
@@ -1,48 +0,0 @@
-# ***** BEGIN LICENSE BLOCK *****
-# Version: MPL 1.1/GPL 2.0/LGPL 2.1
-#
-# The contents of this file are subject to the Mozilla Public License Version
-# 1.1 (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-# http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-# for the specific language governing rights and limitations under the
-# License.
-#
-# The Original Code is Microsummarizer.
-#
-# The Initial Developer of the Original Code is Mozilla.
-# Portions created by the Initial Developer are Copyright (C) 2006
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#   Myk Melez <myk@mozilla.org>
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either the GNU General Public License Version 2 or later (the "GPL"), or
-# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-# in which case the provisions of the GPL or the LGPL are applicable instead
-# of those above. If you wish to allow use of your version of this file only
-# under the terms of either the GPL or the LGPL, and not to allow others to
-# use your version of this file under the terms of the MPL, indicate your
-# decision by deleting the provisions above and replace them with the notice
-# and other provisions required by the GPL or the LGPL. If you do not delete
-# the provisions above, a recipient may use your version of this file under
-# the terms of any one of the MPL, the GPL or the LGPL.
-#
-# ***** END LICENSE BLOCK *****
-
-DEPTH   = ../../../..
-topsrcdir = @top_srcdir@
-srcdir    = @srcdir@
-VPATH   = @srcdir@
-
-include $(DEPTH)/config/autoconf.mk
-
-MODULE = microsummaries
-
-EXTRA_PP_COMPONENTS = nsMicrosummaryService.js
-
-include $(topsrcdir)/config/rules.mk
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -205,16 +205,23 @@ BrowserGlue.prototype = {
           this._backupBookmarks();
         break;
       case "distribution-customization-complete":
         this._observerService
             .removeObserver(this, "distribution-customization-complete");
         // Customization has finished, we don't need the customizer anymore.
         delete this._distributionCustomizer;
         break;
+      case "bookmarks-restore-success":
+      case "bookmarks-restore-failed":
+        this._observerService.removeObserver(this, "bookmarks-restore-success");
+        this._observerService.removeObserver(this, "bookmarks-restore-failed");
+        if (topic == "bookmarks-restore-success" && data == "html-initial")
+          this.ensurePlacesDefaultQueriesInitialized();
+        break;
     }
   }, 
 
   // initialization (called on application startup) 
   _init: function BG__init() {
     // observer registration
     const osvr = this._observerService;
     osvr.addObserver(this, "xpcom-shutdown", false);
@@ -672,23 +679,26 @@ BrowserGlue.prototype = {
         }
         else {
           // ...otherwise we will restore defaults
           restoreDefaultBookmarks = true;
         }
       }
     }
 
+    // If bookmarks are not imported, then initialize smart bookmarks.  This
+    // happens during a common startup.
+    // Otherwise, if any kind of import runs, smart bookmarks creation should be
+    // delayed till the import operations has finished.  Not doing so would
+    // cause them to be overwritten by the newly imported bookmarks.
     if (!importBookmarks) {
-      // Call it here for Fx3 profiles created before the Places folder
-      // has been added, otherwise it's called during import.
       this.ensurePlacesDefaultQueriesInitialized();
     }
     else {
-      // ensurePlacesDefaultQueriesInitialized() is called by import.
+      // An import operation is about to run.
       // Don't try to recreate smart bookmarks if autoExportHTML is true or
       // smart bookmarks are disabled.
       var autoExportHTML = false;
       try {
         autoExportHTML = this._prefs.getBoolPref("browser.bookmarks.autoExportHTML");
       } catch(ex) {}
       var smartBookmarksVersion = 0;
       try {
@@ -706,24 +716,31 @@ BrowserGlue.prototype = {
         // User wants to restore bookmarks.html file from default profile folder
         bookmarksFile = dirService.get("profDef", Ci.nsILocalFile);
         bookmarksFile.append("bookmarks.html");
       }
       else
         bookmarksFile = dirService.get("BMarks", Ci.nsILocalFile);
 
       if (bookmarksFile.exists()) {
-        // import the file
+        // Add an import observer.  It will ensure that smart bookmarks are
+        // created once the operation is complete.
+        this._observerService.addObserver(this, "bookmarks-restore-success", false);
+        this._observerService.addObserver(this, "bookmarks-restore-failed", false);
+
+        // Import from bookmarks.html file.
         try {
           var importer = Cc["@mozilla.org/browser/places/import-export-service;1"].
                          getService(Ci.nsIPlacesImportExportService);
           importer.importHTMLFromFile(bookmarksFile, true /* overwrite existing */);
         } catch (err) {
           // Report the error, but ignore it.
           Cu.reportError("Bookmarks.html file could be corrupt. " + err);
+          this._observerService.removeObserver(this, "bookmarks-restore-success");
+          this._observerService.removeObserver(this, "bookmarks-restore-failed");
         }
       }
       else
         Cu.reportError("Unable to find bookmarks.html file.");
 
       // Reset preferences, so we won't try to import again at next run
       if (importBookmarksHTML)
         this._prefs.setBoolPref("browser.places.importBookmarksHTML", false);
--- a/browser/components/places/content/utils.js
+++ b/browser/components/places/content/utils.js
@@ -1016,17 +1016,17 @@ var PlacesUIUtils = {
   function PUU_createMenuItemForNode(aNode) {
     var element;
     var type = aNode.type;
     if (type == Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR)
       element = document.createElement("menuseparator");
     else {
       if (PlacesUtils.uriTypes.indexOf(type) != -1) {
         element = document.createElement("menuitem");
-        element.className = "menuitem-iconic bookmark-item";
+        element.className = "menuitem-iconic bookmark-item menuitem-with-favicon";
         element.setAttribute("scheme", this.guessUrlSchemeForUI(aNode.uri));
       }
       else if (PlacesUtils.containerTypes.indexOf(type) != -1) {
         element = document.createElement("menu");
         element.setAttribute("container", "true");
 
         if (aNode.type == Ci.nsINavHistoryResultNode.RESULT_TYPE_QUERY) {
           element.setAttribute("query", "true");
--- a/browser/components/places/public/Makefile.in
+++ b/browser/components/places/public/Makefile.in
@@ -41,13 +41,12 @@ topsrcdir = @top_srcdir@
 srcdir = @srcdir@
 VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 MODULE = browserplaces
 XPIDL_MODULE = browserplaces
 
-XPIDLSRCS  = nsIPlacesImportExportService.idl \
-             nsIPlacesTransactionsService.idl \
+XPIDLSRCS  = nsIPlacesTransactionsService.idl \
              $(NULL)
 
 include $(topsrcdir)/config/rules.mk
--- a/browser/components/places/src/Makefile.in
+++ b/browser/components/places/src/Makefile.in
@@ -39,27 +39,16 @@
 
 DEPTH = ../../../..
 topsrcdir = @top_srcdir@
 srcdir = @srcdir@
 VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
-MODULE = browserplaces
-LIBRARY_NAME  = browserplaces_s
-FORCE_STATIC_LIB = 1
-FORCE_USE_PIC = 1
-ifndef MOZ_MEMORY
-USE_STATIC_LIBS = 1
-endif
-
-
-CPPSRCS = nsPlacesImportExportService.cpp
-
 EXTRA_COMPONENTS = \
   nsPlacesTransactionsService.js \
   PlacesProtocolHandler.js \
   $(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
 XPIDL_FLAGS += -I$(topsrcdir)/browser/components
--- a/browser/components/places/tests/unit/test_browserGlue_corrupt.js
+++ b/browser/components/places/tests/unit/test_browserGlue_corrupt.js
@@ -36,16 +36,42 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 /**
  * Tests that nsBrowserGlue correctly restores bookmarks from a JSON backup if
  * database is corrupt and one backup is available.
  */
 
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyServiceGetter(this, "bs",
+                                   "@mozilla.org/browser/nav-bookmarks-service;1",
+                                   "nsINavBookmarksService");
+XPCOMUtils.defineLazyServiceGetter(this, "anno",
+                                   "@mozilla.org/browser/annotation-service;1",
+                                   "nsIAnnotationService");
+
+let bookmarksObserver = {
+  onBeginUpdateBatch: function() {},
+  onEndUpdateBatch: function() {
+    let itemId = bs.getIdForItemAt(bs.toolbarFolder, 0);
+    do_check_neq(itemId, -1);
+    if (anno.itemHasAnnotation(itemId, "Places/SmartBookmark"))
+      continue_test();
+  },
+  onItemAdded: function() {},
+  onBeforeItemRemoved: function(id) {},
+  onItemRemoved: function(id, folder, index, itemType) {},
+  onItemChanged: function() {},
+  onItemVisited: function(id, visitID, time) {},
+  onItemMoved: function() {},
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsINavBookmarkObserver])
+};
+
 function run_test() {
   do_test_pending();
 
   // Create our bookmarks.html copying bookmarks.glue.html to the profile
   // folder.  It should be ignored.
   create_bookmarks_html("bookmarks.glue.html");
 
   // Create our JSON backup copying bookmarks.glue.json to the profile folder.
@@ -69,39 +95,24 @@ function run_test() {
 
   // Initialize Places through the History Service.
   let hs = Cc["@mozilla.org/browser/nav-history-service;1"].
            getService(Ci.nsINavHistoryService);
   // Check the database was corrupt.
   // nsBrowserGlue uses databaseStatus to manage initialization.
   do_check_eq(hs.databaseStatus, hs.DATABASE_STATUS_CORRUPT);
 
-  // Wait for restore to finish.
-  let os = Cc["@mozilla.org/observer-service;1"].
-           getService(Ci.nsIObserverService);
-  let observer = {
-    observe: function(aSubject, aTopic, aData) {
-      os.removeObserver(observer, "bookmarks-restore-success");
-      os.removeObserver(observer, "bookmarks-restore-failed");
-      do_check_eq(aTopic, "bookmarks-restore-success");
-      do_check_eq(aData, "json");
-      continue_test();
-    }
-  }
-  os.addObserver(observer, "bookmarks-restore-success", false);
-  os.addObserver(observer, "bookmarks-restore-failed", false);
+  // The test will continue once restore has finished and smart bookmarks
+  // have been created.
+  bs.addObserver(bookmarksObserver, false);
 }
 
 function continue_test() {
-  let bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
-           getService(Ci.nsINavBookmarksService);
-
   // Check that JSON backup has been restored.
   // Notice restore from JSON notification is fired before smart bookmarks creation.
-  let itemId = bs.getIdForItemAt(bs.toolbarFolder, 0);
-  do_check_neq(itemId, -1);
+  let itemId = bs.getIdForItemAt(bs.toolbarFolder, SMART_BOOKMARKS_ON_TOOLBAR);
   do_check_eq(bs.getItemTitle(itemId), "examplejson");
 
   remove_bookmarks_html();
   remove_all_JSON_backups();
 
   do_test_finished();
 }
--- a/browser/components/places/tests/unit/test_browserGlue_corrupt_nobackup.js
+++ b/browser/components/places/tests/unit/test_browserGlue_corrupt_nobackup.js
@@ -36,16 +36,42 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 /**
  * Tests that nsBrowserGlue correctly imports from bookmarks.html if database
  * is corrupt but a JSON backup is not available.
  */
 
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyServiceGetter(this, "bs",
+                                   "@mozilla.org/browser/nav-bookmarks-service;1",
+                                   "nsINavBookmarksService");
+XPCOMUtils.defineLazyServiceGetter(this, "anno",
+                                   "@mozilla.org/browser/annotation-service;1",
+                                   "nsIAnnotationService");
+
+let bookmarksObserver = {
+  onBeginUpdateBatch: function() {},
+  onEndUpdateBatch: function() {
+    let itemId = bs.getIdForItemAt(bs.toolbarFolder, 0);
+    do_check_neq(itemId, -1);
+    if (anno.itemHasAnnotation(itemId, "Places/SmartBookmark"))
+      continue_test();
+  },
+  onItemAdded: function() {},
+  onBeforeItemRemoved: function(id) {},
+  onItemRemoved: function(id, folder, index, itemType) {},
+  onItemChanged: function() {},
+  onItemVisited: function(id, visitID, time) {},
+  onItemMoved: function() {},
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsINavBookmarkObserver])
+};
+
 function run_test() {
   do_test_pending();
 
   // Create bookmarks.html in the profile.
   create_bookmarks_html("bookmarks.glue.html");
   // Remove JSON backup from profile.
   remove_all_JSON_backups();
 
@@ -67,38 +93,22 @@ function run_test() {
 
   // Initialize Places through the History Service.
   let hs = Cc["@mozilla.org/browser/nav-history-service;1"].
            getService(Ci.nsINavHistoryService);
   // Check the database was corrupt.
   // nsBrowserGlue uses databaseStatus to manage initialization.
   do_check_eq(hs.databaseStatus, hs.DATABASE_STATUS_CORRUPT);
 
-  // Wait for restore to finish.
-  let os = Cc["@mozilla.org/observer-service;1"].
-           getService(Ci.nsIObserverService);
-  let observer = {
-    observe: function(aSubject, aTopic, aData) {
-      os.removeObserver(observer, "bookmarks-restore-success");
-      os.removeObserver(observer, "bookmarks-restore-failed");
-      do_check_eq(aTopic, "bookmarks-restore-success");
-      do_check_eq(aData, "html-initial");
-      continue_test();
-    }
-  }
-  os.addObserver(observer, "bookmarks-restore-success", false);
-  os.addObserver(observer, "bookmarks-restore-failed", false);
+  // The test will continue once import has finished and smart bookmarks
+  // have been created.
+  bs.addObserver(bookmarksObserver, false);
 }
 
 function continue_test() {
-  let bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
-           getService(Ci.nsINavBookmarksService);
-
   // Check that bookmarks html has been restored.
-  // Notice restore from HTML notification is fired after smart bookmarks creation.
   let itemId = bs.getIdForItemAt(bs.toolbarFolder, SMART_BOOKMARKS_ON_TOOLBAR);
-  do_check_neq(itemId, -1);
   do_check_eq(bs.getItemTitle(itemId), "example");
 
   remove_bookmarks_html();
 
   do_test_finished();
 }
--- a/browser/components/places/tests/unit/test_browserGlue_corrupt_nobackup_default.js
+++ b/browser/components/places/tests/unit/test_browserGlue_corrupt_nobackup_default.js
@@ -36,16 +36,42 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 /**
  * Tests that nsBrowserGlue correctly restores default bookmarks if database is
  * corrupt, nor a JSON backup nor bookmarks.html are available.
  */
 
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyServiceGetter(this, "bs",
+                                   "@mozilla.org/browser/nav-bookmarks-service;1",
+                                   "nsINavBookmarksService");
+XPCOMUtils.defineLazyServiceGetter(this, "anno",
+                                   "@mozilla.org/browser/annotation-service;1",
+                                   "nsIAnnotationService");
+
+let bookmarksObserver = {
+  onBeginUpdateBatch: function() {},
+  onEndUpdateBatch: function() {
+    let itemId = bs.getIdForItemAt(bs.toolbarFolder, 0);
+    do_check_neq(itemId, -1);
+    if (anno.itemHasAnnotation(itemId, "Places/SmartBookmark"))
+      continue_test();
+  },
+  onItemAdded: function() {},
+  onBeforeItemRemoved: function(id) {},
+  onItemRemoved: function(id, folder, index, itemType) {},
+  onItemChanged: function() {},
+  onItemVisited: function(id, visitID, time) {},
+  onItemMoved: function() {},
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsINavBookmarkObserver])
+};
+
 function run_test() {
   do_test_pending();
 
   // Remove bookmarks.html from profile.
   remove_bookmarks_html();
   // Remove JSON backup from profile.
   remove_all_JSON_backups();
 
@@ -67,35 +93,21 @@ function run_test() {
 
   // Initialize Places through the History Service.
   let hs = Cc["@mozilla.org/browser/nav-history-service;1"].
            getService(Ci.nsINavHistoryService);
   // Check the database was corrupt.
   // nsBrowserGlue uses databaseStatus to manage initialization.
   do_check_eq(hs.databaseStatus, hs.DATABASE_STATUS_CORRUPT);
 
-  // Wait for restore to finish.
-  let os = Cc["@mozilla.org/observer-service;1"].
-           getService(Ci.nsIObserverService);
-  let observer = {
-    observe: function(aSubject, aTopic, aData) {
-      os.removeObserver(observer, "bookmarks-restore-success");
-      os.removeObserver(observer, "bookmarks-restore-failed");
-      do_check_eq(aTopic, "bookmarks-restore-success");
-      do_check_eq(aData, "html-initial");
-      continue_test();
-    }
-  }
-  os.addObserver(observer, "bookmarks-restore-success", false);
-  os.addObserver(observer, "bookmarks-restore-failed", false);
+  // The test will continue once import has finished and smart bookmarks
+  // have been created.
+  bs.addObserver(bookmarksObserver, false);
 }
 
 function continue_test() {
-  let bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
-           getService(Ci.nsINavBookmarksService);
-
   // Check that default bookmarks have been restored.
   let itemId = bs.getIdForItemAt(bs.toolbarFolder, SMART_BOOKMARKS_ON_TOOLBAR);
   do_check_true(itemId > 0);
   do_check_eq(bs.getItemTitle(itemId), "Getting Started");
 
   do_test_finished();
 }
--- a/browser/components/places/tests/unit/test_browserGlue_migrate.js
+++ b/browser/components/places/tests/unit/test_browserGlue_migrate.js
@@ -37,68 +37,85 @@
  * ***** END LICENSE BLOCK ***** */
 
 /**
  * Tests that nsBrowserGlue does not overwrite bookmarks imported from the
  * migrators.  They usually run before nsBrowserGlue, so if we find any
  * bookmark on init, we should not try to import.
  */
 
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyServiceGetter(this, "bs",
+                                   "@mozilla.org/browser/nav-bookmarks-service;1",
+                                   "nsINavBookmarksService");
+XPCOMUtils.defineLazyServiceGetter(this, "anno",
+                                   "@mozilla.org/browser/annotation-service;1",
+                                   "nsIAnnotationService");
+
+let bookmarksObserver = {
+  onBeginUpdateBatch: function() {},
+  onEndUpdateBatch: function() {
+    let itemId = bs.getIdForItemAt(bs.toolbarFolder, 0);
+    do_check_neq(itemId, -1);
+    if (anno.itemHasAnnotation(itemId, "Places/SmartBookmark"))
+      continue_test();
+  },
+  onItemAdded: function() {},
+  onBeforeItemRemoved: function(id) {},
+  onItemRemoved: function(id, folder, index, itemType) {},
+  onItemChanged: function() {},
+  onItemVisited: function(id, visitID, time) {},
+  onItemMoved: function() {},
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsINavBookmarkObserver])
+};
+
 const PREF_SMART_BOOKMARKS_VERSION = "browser.places.smartBookmarksVersion";
 
 function run_test() {
+  do_test_pending();
+
   // Create our bookmarks.html copying bookmarks.glue.html to the profile
   // folder.  It will be ignored.
   create_bookmarks_html("bookmarks.glue.html");
 
   // Remove current database file.
   let db = gProfD.clone();
   db.append("places.sqlite");
   if (db.exists()) {
     db.remove(false);
     do_check_false(db.exists());
   }
 
-  // Disable Smart Bookmarks creation.
-  let ps = Cc["@mozilla.org/preferences-service;1"].
-           getService(Ci.nsIPrefBranch);
-  ps.setIntPref(PREF_SMART_BOOKMARKS_VERSION, -1);
-
   // Initialize Places through the History Service.
   let hs = Cc["@mozilla.org/browser/nav-history-service;1"].
            getService(Ci.nsINavHistoryService);
   // Check a new database has been created.
   // nsBrowserGlue uses databaseStatus to manage initialization.
   do_check_eq(hs.databaseStatus, hs.DATABASE_STATUS_CREATE);
 
   // A migrator would run before nsBrowserGlue, so we mimic that behavior
   // adding a bookmark.
-  let bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
-           getService(Ci.nsINavBookmarksService);
   bs.insertBookmark(bs.bookmarksMenuFolder, uri("http://mozilla.org/"),
                     bs.DEFAULT_INDEX, "migrated");
 
   // Initialize nsBrowserGlue.
   let bg = Cc["@mozilla.org/browser/browserglue;1"].
            getService(Ci.nsIBrowserGlue);
 
-  // Import could take some time, usually less than 1s, but to be sure we will
-  // check after 3s.
-  do_test_pending();
-  do_timeout(3000, continue_test);
+  // The test will continue once import has finished and smart bookmarks
+  // have been created.
+  bs.addObserver(bookmarksObserver, false);
 }
 
 function continue_test() {
-  let bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
-           getService(Ci.nsINavBookmarksService);
-
   // Check the created bookmarks still exist.
-  let itemId = bs.getIdForItemAt(bs.bookmarksMenuFolder, 0);
+  let itemId = bs.getIdForItemAt(bs.bookmarksMenuFolder, SMART_BOOKMARKS_ON_MENU);
   do_check_eq(bs.getItemTitle(itemId), "migrated");
 
   // Check that we have not imported any new bookmark.
-  do_check_eq(bs.getIdForItemAt(bs.bookmarksMenuFolder, 1), -1);
-  do_check_eq(bs.getIdForItemAt(bs.toolbarFolder, 0), -1);
+  do_check_eq(bs.getIdForItemAt(bs.bookmarksMenuFolder, SMART_BOOKMARKS_ON_MENU + 1), -1);
+  do_check_eq(bs.getIdForItemAt(bs.toolbarFolder, SMART_BOOKMARKS_ON_MENU), -1);
 
   remove_bookmarks_html();
 
   do_test_finished();
 }
--- a/browser/components/places/tests/unit/test_browserGlue_restore.js
+++ b/browser/components/places/tests/unit/test_browserGlue_restore.js
@@ -36,16 +36,42 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 /**
  * Tests that nsBrowserGlue correctly restores bookmarks from a JSON backup if
  * database has been created and one backup is available.
  */
 
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyServiceGetter(this, "bs",
+                                   "@mozilla.org/browser/nav-bookmarks-service;1",
+                                   "nsINavBookmarksService");
+XPCOMUtils.defineLazyServiceGetter(this, "anno",
+                                   "@mozilla.org/browser/annotation-service;1",
+                                   "nsIAnnotationService");
+
+let bookmarksObserver = {
+  onBeginUpdateBatch: function() {},
+  onEndUpdateBatch: function() {
+    let itemId = bs.getIdForItemAt(bs.toolbarFolder, 0);
+    do_check_neq(itemId, -1);
+    if (anno.itemHasAnnotation(itemId, "Places/SmartBookmark"))
+      continue_test();
+  },
+  onItemAdded: function() {},
+  onBeforeItemRemoved: function(id) {},
+  onItemRemoved: function(id, folder, index, itemType) {},
+  onItemChanged: function() {},
+  onItemVisited: function(id, visitID, time) {},
+  onItemMoved: function() {},
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsINavBookmarkObserver])
+};
+
 function run_test() {
   do_test_pending();
 
   // Create our bookmarks.html copying bookmarks.glue.html to the profile
   // folder.  It will be ignored.
   create_bookmarks_html("bookmarks.glue.html");
 
   // Create our JSON backup copying bookmarks.glue.json to the profile
@@ -65,38 +91,24 @@ function run_test() {
 
   // Initialize Places through the History Service.
   let hs = Cc["@mozilla.org/browser/nav-history-service;1"].
            getService(Ci.nsINavHistoryService);
   // Check a new database has been created.
   // nsBrowserGlue uses databaseStatus to manage initialization.
   do_check_eq(hs.databaseStatus, hs.DATABASE_STATUS_CREATE);
 
-  // Wait for restore to finish.
-  let os = Cc["@mozilla.org/observer-service;1"].
-           getService(Ci.nsIObserverService);
-  let observer = {
-    observe: function(aSubject, aTopic, aData) {
-      os.removeObserver(observer, "bookmarks-restore-success");
-      os.removeObserver(observer, "bookmarks-restore-failed");
-      do_check_eq(aTopic, "bookmarks-restore-success");
-      do_check_eq(aData, "json");
-      continue_test();
-    }
-  }
-  os.addObserver(observer, "bookmarks-restore-success", false);
-  os.addObserver(observer, "bookmarks-restore-failed", false);
+  // The test will continue once restore has finished and smart bookmarks
+  // have been created.
+  bs.addObserver(bookmarksObserver, false);
 }
 
 function continue_test() {
-  let bs = Cc["@mozilla.org/browser/nav-bookmarks-service;1"].
-           getService(Ci.nsINavBookmarksService);
-
   // Check that JSON backup has been restored.
   // Notice restore from JSON notification is fired before smart bookmarks creation.
-  let itemId = bs.getIdForItemAt(bs.toolbarFolder, 0);
+  let itemId = bs.getIdForItemAt(bs.toolbarFolder, SMART_BOOKMARKS_ON_TOOLBAR);
   do_check_eq(bs.getItemTitle(itemId), "examplejson");
 
   remove_bookmarks_html();
   remove_all_JSON_backups();
 
   do_test_finished();
 }
--- a/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_zoomrestore.js
+++ b/browser/components/privatebrowsing/test/browser/browser_privatebrowsing_zoomrestore.js
@@ -37,18 +37,16 @@
 
 // This test makes sure that about:privatebrowsing does not appear zoomed in
 // if there is already a zoom site pref for about:blank (bug 487656).
 
 function test() {
   // initialization
   let pb = Cc["@mozilla.org/privatebrowsing;1"].
            getService(Ci.nsIPrivateBrowsingService);
-  let cps = Cc["@mozilla.org/content-pref/service;1"].
-            getService(Ci.nsIContentPrefService);
   waitForExplicitFinish();
 
   let tabBlank = gBrowser.selectedTab;
   gBrowser.removeAllTabsBut(tabBlank);
 
   let blankBrowser = gBrowser.getBrowserForTab(tabBlank);
   blankBrowser.addEventListener("load", function() {
     blankBrowser.removeEventListener("load", arguments.callee, true);
@@ -61,34 +59,17 @@ function test() {
     pb.privateBrowsingEnabled = true;
     let tabAboutPB = gBrowser.selectedTab;
     let browserAboutPB = gBrowser.getBrowserForTab(tabAboutPB);
     browserAboutPB.addEventListener("load", function() {
       browserAboutPB.removeEventListener("load", arguments.callee, true);
       setTimeout(function() {
         // make sure the zoom level is set to 1
         is(ZoomManager.zoom, 1, "Zoom level for about:privatebrowsing should be reset");
-
-        // Mac OS X does not support print preview, so skip those tests
-        let isOSX = ("nsILocalFileMac" in Components.interfaces);
-        if (isOSX) {
-          finishTest();
-          return;
-        }
-
-        // test print preview on HTML document
-        testPrintPreview(browserAboutPB, function() {
-          browserAboutPB.addEventListener("load", function() {
-            browserAboutPB.removeEventListener("load", arguments.callee, true);
-
-            // test print preview on image document
-            testPrintPreview(browserAboutPB, finishTest);
-          }, true);
-          browserAboutPB.loadURI("about:logo");
-        });
+        finishTest();
       }, 0);
     }, true);
   }, true);
   blankBrowser.loadURI("about:blank");
 }
 
 function finishTest() {
   let pb = Cc["@mozilla.org/privatebrowsing;1"].
@@ -102,36 +83,8 @@ function finishTest() {
 
     executeSoon(function() {
       // cleanup
       FullZoom.reset();
       finish();
     });
   }, true);
 }
-
-function testPrintPreview(aBrowser, aCallback) {
-  FullZoom.enlarge();
-  let level = ZoomManager.getZoomForBrowser(aBrowser);
-
-  let onEnterOrig = PrintPreviewListener.onEnter;
-  PrintPreviewListener.onEnter = function () {
-    PrintPreviewListener.onEnter = onEnterOrig;
-    PrintPreviewListener.onEnter.apply(PrintPreviewListener, arguments);
-    PrintUtils.exitPrintPreview();
-  };
-
-  let onExitOrig = PrintPreviewListener.onExit;
-  PrintPreviewListener.onExit = function () {
-    PrintPreviewListener.onExit = onExitOrig;
-    PrintPreviewListener.onExit.apply(PrintPreviewListener, arguments);
-
-    is(ZoomManager.getZoomForBrowser(aBrowser), level,
-       "Toggling print preview mode should not affect zoom level");
-
-    FullZoom.reset();
-    aCallback();
-  };
-
-  let printPreview = new Function(document.getElementById("cmd_printPreview")
-                                          .getAttribute("oncommand"));
-  executeSoon(printPreview);
-}
--- a/browser/components/search/content/search.xml
+++ b/browser/components/search/content/search.xml
@@ -398,17 +398,17 @@
                "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
           var engines = this.engines;
           for (var i = engines.length - 1; i >= 0; --i) {
             var menuitem = document.createElementNS(kXULNS, "menuitem");
             var name = engines[i].name;
             menuitem.setAttribute("label", name);
             menuitem.setAttribute("id", name);
-            menuitem.setAttribute("class", "menuitem-iconic searchbar-engine-menuitem");
+            menuitem.setAttribute("class", "menuitem-iconic searchbar-engine-menuitem menuitem-with-favicon");
             // Since this menu is rebuilt by the observer method whenever a new
             // engine is selected, the "selected" attribute does not need to be
             // explicitly cleared anywhere.
             if (engines[i] == this.currentEngine)
               menuitem.setAttribute("selected", "true");
             var tooltip = this._stringBundle.getFormattedString("searchtip", [name]);
             menuitem.setAttribute("tooltiptext", tooltip);
             if (engines[i].iconURI)
--- a/browser/makefiles.sh
+++ b/browser/makefiles.sh
@@ -42,19 +42,16 @@ browser/app/profile/extensions/Makefile
 browser/base/Makefile
 browser/components/Makefile
 browser/components/build/Makefile
 browser/components/certerror/Makefile
 browser/components/dirprovider/Makefile
 browser/components/feeds/Makefile
 browser/components/feeds/public/Makefile
 browser/components/feeds/src/Makefile
-browser/components/microsummaries/Makefile
-browser/components/microsummaries/public/Makefile
-browser/components/microsummaries/src/Makefile
 browser/components/migration/Makefile
 browser/components/migration/public/Makefile
 browser/components/migration/src/Makefile
 browser/components/places/Makefile
 browser/components/places/public/Makefile
 browser/components/places/src/Makefile
 browser/components/preferences/Makefile
 browser/components/privatebrowsing/Makefile
--- a/browser/themes/pinstripe/browser/browser.css
+++ b/browser/themes/pinstripe/browser/browser.css
@@ -1588,17 +1588,17 @@ toolbarbutton.chevron > .toolbarbutton-m
 }
 
 .tabbrowser-tabs {
   -moz-box-align: stretch;
   height: 25px;
 }
 
 .tabbrowser-tabs:not([overflow="true"]) {
-  -moz-padding-start: 3px;
+  -moz-margin-start: 3px;
 }
 
 /**
  * Tab Drag and Drop
  */
 
 .tab-drop-indicator {
   margin-top: -8px !important;
--- a/browser/themes/winstripe/browser/browser-aero.css
+++ b/browser/themes/winstripe/browser/browser-aero.css
@@ -1,65 +1,125 @@
 %include browser.css
 
 /* ::::: Main Window Styling ::::: */
-#navigator-toolbox:-moz-system-metric(windows-default-theme) > toolbar {
-  -moz-appearance: none;
-  border-style: none;
-}
+@media all and (-moz-windows-compositor) {
+  #main-window:not(:-moz-lwtheme) {
+    -moz-appearance: -moz-win-glass;
+    background: transparent;
+  }
+
+  #navigator-toolbox:not(:-moz-lwtheme),
+  #navigator-toolbox > toolbar {
+    -moz-appearance: none;
+    background: transparent;
+    border-style: none;
+  }
 
-#print-preview-toolbar:not(:-moz-lwtheme) {
-  -moz-appearance: -moz-win-browsertabbar-toolbox;
-}
+  #navigator-toolbox:not(:-moz-lwtheme),
+  #FindToolbar:not(:-moz-lwtheme) {
+    color: black;
+    text-shadow: 0 0 .6em white, 0 0 .6em white, 0 0 .6em white;
+  }
 
-/* ::::: Location Bar AutoComplete Styling ::::: */
+  #urlbar,
+  .searchbar-textbox {
+    background-color: rgba(255,255,255,.725);
+    color: black;
+  }
+
+  /*XXX :-moz-placeholder isn't implemented yet (bug 457801)
+  #urlbar > .autocomplete-textbox-container > .textbox-input-box > html|*.textbox-input:-moz-placeholder,
+  .searchbar-textbox > .autocomplete-textbox-container > .textbox-input-box > html|*.textbox-input:-moz-placeholder {
+    color: #777;
+  }
+  */
 
-.ac-url-text:-moz-system-metric(windows-default-theme) {
-  color: -moz-nativehyperlinktext;
-}
+  #urlbar:hover,
+  .searchbar-textbox:hover {
+    background-color: rgba(255,255,255,.898);
+  }
 
-/* ::::: Identity Indicator Styling ::::: */
+  #urlbar[focused="true"],
+  .searchbar-textbox[focused="true"] {
+    background-color: white;
+  }
+
+  #TabsToolbar:not(:-moz-lwtheme) {
+    margin-bottom: 0;
+    -moz-box-shadow: ThreeDDarkShadow 0 -1px inset;
+  }
 
-/* Bug 413060, comment 16: Vista Aero is a special case where we use a
-   tooltip appearance for the address bar popup panels */
-#identity-popup:-moz-system-metric(windows-default-theme),
-#editBookmarkPanel:-moz-system-metric(windows-default-theme) {
-  -moz-appearance: tooltip;
-  color: InfoText;
+  .tabbrowser-tab:not(:-moz-lwtheme),
+  .tabbrowser-arrowscrollbox > .scrollbutton-up:not(:-moz-lwtheme),
+  .tabbrowser-arrowscrollbox > .scrollbutton-down:not(:-moz-lwtheme),
+  .tabs-newtab-button:not(:-moz-lwtheme),
+  .tabs-alltabs-button:not(:-moz-lwtheme) {
+    background-color: rgba(255,255,255,.25);
+    text-shadow: 0 1px 0 rgba(255,255,255,.2);
+  }
+
+  .tabbrowser-tab[selected="true"]:not(:-moz-lwtheme) {
+    background-color: white;
+    text-shadow: none;
+  }
+
+  #allTabs-panel,
+  #ctrlTab-panel {
+    background: transparent;
+    -moz-appearance: -moz-win-glass;
+    -moz-border-radius: 0;
+    border: none;
+    font: normal 1.2em "Segoe UI";
+    color: black;
+    text-shadow: white -1px -1px .5em, white -1px 1px .5em, white 1px 1px .5em, white 1px -1px .5em;
+  }
 }
 
-/* Make the left and right paddings smaller, to compensate for the horizontal
-   space added by the tooltip appearance, see bug 432529. */
-#identity-popup-container:-moz-system-metric(windows-default-theme) {
-  -moz-padding-start: 6px;
-  -moz-padding-end: 6px;
+@media not all and (-moz-windows-compositor) {
+  #print-preview-toolbar:not(:-moz-lwtheme) {
+    -moz-appearance: -moz-win-browsertabbar-toolbox;
+  }
 }
 
-#sidebar-splitter:-moz-system-metric(windows-default-theme) {
-  border: 0;
-  -moz-border-end: 1px solid;
-  -moz-border-right-colors: #A9B7C9;
-  -moz-border-left-colors: #A9B7C9;
-  min-width: 0;
-  width: 3px;
-  background-color: transparent;
-  -moz-margin-start: -3px;
-  position: relative;
-  z-index: 10;
-}
+@media all and (-moz-windows-default-theme) {
+  #navigator-toolbox > toolbar {
+    -moz-appearance: none;
+    border-style: none;
+  }
+
+  .ac-url-text {
+    color: -moz-nativehyperlinktext;
+  }
+
+  /* Bug 413060, comment 16: Vista Aero is a special case where we use a
+     tooltip appearance for the address bar popup panels */
+  #identity-popup,
+  #editBookmarkPanel {
+    -moz-appearance: tooltip;
+    color: InfoText;
+  }
 
-#allTabs-panel:-moz-system-metric(windows-compositor),
-#ctrlTab-panel:-moz-system-metric(windows-compositor) {
-  background: transparent;
-  -moz-appearance: -moz-win-glass;
-  -moz-border-radius: 0;
-  border: none;
-  font: normal 1.2em "Segoe UI";
-  color: black;
-  text-shadow: white -1px -1px .5em, white -1px 1px .5em, white 1px 1px .5em, white 1px -1px .5em;
+  /* Make the left and right paddings smaller, to compensate for the horizontal
+     space added by the tooltip appearance, see bug 432529. */
+  #identity-popup-container {
+    -moz-padding-start: 6px;
+    -moz-padding-end: 6px;
+  }
+
+  #sidebar-splitter {
+    border: 0;
+    -moz-border-end: 1px solid #A9B7C9;
+    min-width: 0;
+    width: 3px;
+    background-color: transparent;
+    -moz-margin-start: -3px;
+    position: relative;
+    z-index: 10;
+  }
 }
 
 /* ::::: fullscreen window controls ::::: */
 
 #window-controls {
   -moz-box-align: start;
 }
 
--- a/browser/themes/winstripe/browser/browser.css
+++ b/browser/themes/winstripe/browser/browser.css
@@ -263,19 +263,21 @@ toolbar[iconsize="small"][mode="icons"] 
 
 .toolbarbutton-menubutton-button:not([disabled="true"]):not(:active):hover,
 toolbarbutton[type="menu-button"]:not([open="true"]):not(:active):hover > .toolbarbutton-menubutton-dropmarker:not([disabled="true"]),
 .toolbarbutton-1:not([disabled="true"]):not([checked="true"]):not(:active):hover {
   background-color: hsla(190,60%,70%,.5);
   border-color: hsla(190,50%,65%,.8) hsla(190,50%,50%,.8) hsla(190,50%,40%,.8);
   -moz-box-shadow: 0 0 0 1px rgba(255,255,255,.3) inset,
                    0 0 0 2px rgba(255,255,255,.1) inset,
-                   0 0 5px hsl(190,90%,80%),
-                   0 1px 0 rgba(0,0,0,.1);
-  -moz-transition: background-color .5s ease-in;
+                   0 1px 0 rgba(0,0,0,.1),
+                   0 0 5px hsl(190,90%,80%);
+  -moz-transition: background-color .4s ease-in,
+                   border-color .3s ease-in,
+                   -moz-box-shadow .3s ease-in;
 }
 
 .toolbarbutton-menubutton-button:not([disabled="true"]):hover:active,
 toolbarbutton[type="menu-button"]:hover:active > .toolbarbutton-menubutton-dropmarker:not([disabled="true"]),
 toolbarbutton[type="menu-button"][open="true"] > .toolbarbutton-menubutton-dropmarker,
 .toolbarbutton-1:not([disabled="true"]):hover:active,
 .toolbarbutton-1[checked="true"],
 .toolbarbutton-1[open="true"] {
@@ -359,19 +361,21 @@ toolbar:not([iconsize="small"])[mode="ic
 toolbar:not([iconsize="small"])[mode="icons"] #forward-button {
   /*mask: url(keyhole-forward-mask.svg#mask); XXX: this regresses twinopen */
   mask: url(chrome://browser/content/browser.xul#winstripe-keyhole-forward-mask);
   -moz-margin-start: -6px;
   padding-left: 7px;
   padding-right: 3px;
 }
 
-toolbar:not([iconsize="small"])[mode="icons"] #forward-button:not([disabled="true"]):hover {
+toolbar:not([iconsize="small"])[mode="icons"] #forward-button:not([disabled="true"]):not(:active):hover {
   /*mask: url(keyhole-forward-mask.svg#mask-hover);*/
   mask: url(chrome://browser/content/browser.xul#winstripe-keyhole-forward-mask-hover);
+  /* Don't animate the box shadow, as the blur and spread radii affect the mask. */
+  -moz-transition: background-color .4s ease-in;
 }
 
 #back-forward-dropmarker {
   -moz-appearance: none;
   padding: 0;
   -moz-padding-end: 2px;
   -moz-margin-start: -3px;
   border: none;
@@ -534,17 +538,17 @@ toolbar:not([iconsize="small"])[mode="ic
   width: 7em;
   min-width: 7em;
 }
 
 #urlbar,
 .searchbar-textbox {
   -moz-appearance: none;
   margin: 1px 3px;
-  padding: 1px;
+  padding: 2px;
   -moz-background-clip: padding;
   border: 1px solid;
   border-color: rgba(0,0,0,.2) rgba(0,0,0,.25) rgba(0,0,0,.3);
   -moz-border-radius: 4px;
   -moz-box-shadow: 0 1px 0 rgba(0,0,0,.1) inset,
                    0 1px 0 rgba(255,255,255,.4);
 }
 
@@ -607,17 +611,16 @@ toolbar:not([iconsize="small"])[mode="ic
 }
 
 /* identity box */
 
 #identity-box {
   background-color: -moz-dialog;
   background-image: -moz-linear-gradient(rgba(255,255,255,.25), rgba(0,0,0,.15));
   color: -moz-dialogText;
-  margin: 1px;
   -moz-border-radius: 2px;
 }
 
 #identity-box:hover {
   background-image: -moz-linear-gradient(rgba(255,255,255,.5), rgba(50%,50%,50%,.2), rgba(0,0,0,.15));
 }
 
 #identity-box[open="true"],
@@ -648,17 +651,17 @@ toolbar:not([iconsize="small"])[mode="ic
 #identity-box.verifiedDomain:focus ,
 #identity-box.verifiedIdentity:focus {
   outline-color: white;
 }
 
 #identity-icon-labels {
   -moz-margin-start: 1px;
   -moz-margin-end: 3px;
-  margin-bottom: 1px;
+  -moz-transform: translate(0, -1px);
 }
 
 /* Location bar dropmarker */
 
 #urlbar > .autocomplete-history-dropmarker {
   -moz-appearance: none;
   padding: 0 1px;
   background-color: transparent;
@@ -899,17 +902,17 @@ toolbar:not([iconsize="small"])[mode="ic
   -moz-box-shadow: ThreeDShadow 0 -1px inset, -moz-dialog 0 2px;
 }
 
 .tabbrowser-tabs:-moz-system-metric(touch-enabled) {
   min-height: .81cm;
 }
 
 .tabbrowser-tabs:not([overflow="true"]) {
-  -moz-padding-start: 3px;
+  -moz-margin-start: 3px;
 }
 
 /* Tabs */
 .tabbrowser-tab,
 .tabbrowser-arrowscrollbox > .scrollbutton-up,
 .tabbrowser-arrowscrollbox > .scrollbutton-down,
 .tabs-newtab-button,
 .tabs-alltabs-button {
--- a/browser/themes/winstripe/browser/places/organizer-aero.css
+++ b/browser/themes/winstripe/browser/places/organizer-aero.css
@@ -23,19 +23,17 @@
 
 #placesMenu > menu > .menubar-text:-moz-system-metric(windows-default-theme) {
   -moz-padding-end: 15px;
   background-image: url(chrome://browser/skin/places/dropDown.png);
 }
 
 #placesView > splitter:-moz-system-metric(windows-default-theme) {
   border: 0;
-  -moz-border-end: 1px solid;
-  -moz-border-right-colors: #A9B7C9;
-  -moz-border-left-colors: #A9B7C9;
+  -moz-border-end: 1px solid #A9B7C9;
   min-width: 0;
   width: 3px !important;
   background-color: transparent;
   -moz-margin-start: -3px;
   position: relative;
   z-index: 10;
 }
 
--- a/browser/themes/winstripe/browser/searchbar.css
+++ b/browser/themes/winstripe/browser/searchbar.css
@@ -13,17 +13,17 @@
 
 /* ::::: searchbar-engine-button ::::: */
 
 .searchbar-engine-image {
   height: 16px;
   width: 16px;
   list-style-image: url("chrome://global/skin/icons/folder-item.png");
   -moz-image-region: rect(0px, 16px, 16px, 0px);
-  -moz-margin-start: 3px;
+  -moz-margin-start: 2px;
 }
 
 .searchbar-engine-button {
   -moz-appearance: none;
   min-width: 0;
   margin: 0;
   padding: 0;
   -moz-padding-end: 2px;
@@ -58,17 +58,17 @@
 
 /* ::::: search-go-button ::::: */
 
 .search-go-container {
   -moz-box-align: center;
 }
 
 .search-go-button {
-  padding: 2px;
+  padding: 1px;
   list-style-image: url("chrome://global/skin/icons/Search-glass.png");
   -moz-image-region: rect(0px 16px 16px 0px);
 }
 
 .search-go-button:-moz-system-metric(touch-enabled) {
   -moz-padding-start: 5px;
   -moz-padding-end: 3px;
 }
--- a/build/win32/Makefile.in
+++ b/build/win32/Makefile.in
@@ -38,19 +38,23 @@
 DEPTH = ../..
 topsrcdir = @top_srcdir@
 srcdir = @srcdir@
 VPATH = @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
 ifdef ENABLE_TESTS
+
+ifdef _MSC_VER
+DIRS += vmwarerecordinghelper
+endif
+
 DIRS += \
   crashinjectdll \
-  vmwarerecordinghelper \
   $(NULL)
 
 PROGRAM = crashinject$(BIN_SUFFIX)
 USE_STATIC_LIBS = 1
 CPPSRCS = crashinject.cpp
 
 endif
 
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -138,17 +138,16 @@ MOZ_UPDATER	= @MOZ_UPDATER@
 MOZ_UPDATE_PACKAGING	= @MOZ_UPDATE_PACKAGING@
 MOZ_NO_ACTIVEX_SUPPORT = @MOZ_NO_ACTIVEX_SUPPORT@
 MOZ_ACTIVEX_SCRIPTING_SUPPORT = @MOZ_ACTIVEX_SCRIPTING_SUPPORT@
 MOZ_DISABLE_VISTA_SDK_REQUIREMENTS = @MOZ_DISABLE_VISTA_SDK_REQUIREMENTS@
 MOZ_DISABLE_PARENTAL_CONTROLS = @MOZ_DISABLE_PARENTAL_CONTROLS@
 XPC_IDISPATCH_SUPPORT = @XPC_IDISPATCH_SUPPORT@
 NS_ENABLE_TSF = @NS_ENABLE_TSF@
 MOZ_SPELLCHECK = @MOZ_SPELLCHECK@
-MOZ_XPFE_COMPONENTS = @MOZ_XPFE_COMPONENTS@
 MOZ_PROFILELOCKING = @MOZ_PROFILELOCKING@
 MOZ_FEEDS = @MOZ_FEEDS@
 MOZ_TOOLKIT_SEARCH = @MOZ_TOOLKIT_SEARCH@
 MOZ_PLACES = @MOZ_PLACES@
 MOZ_PLACES_BOOKMARKS = @MOZ_PLACES_BOOKMARKS@
 MOZ_STORAGE = @MOZ_STORAGE@
 MOZ_SAFE_BROWSING = @MOZ_SAFE_BROWSING@
 MOZ_FASTSTART = @MOZ_FASTSTART@
--- a/config/config.mk
+++ b/config/config.mk
@@ -763,24 +763,24 @@ MAKE_JARS_FLAGS += -c $(LOCALE_SRCDIR)
 ifdef LOCALE_MERGEDIR
 MAKE_JARS_FLAGS += -c $(topsrcdir)/$(relativesrcdir)/en-US
 endif
 endif
 
 ifdef WINCE
 RUN_TEST_PROGRAM = $(PYTHON) $(topsrcdir)/build/mobile/devicemanager-run-test.py
 else
-ifeq (,$(filter WINCE WINNT OS2,$(OS_ARCH)))
+ifeq (OS2,$(OS_ARCH))
+RUN_TEST_PROGRAM = $(topsrcdir)/build/os2/test_os2.cmd "$(DIST)"
+else
+ifneq (WINNT,$(OS_ARCH))
 RUN_TEST_PROGRAM = $(DIST)/bin/run-mozilla.sh
-endif
-
-ifeq ($(OS_ARCH),OS2)
-RUN_TEST_PROGRAM = $(topsrcdir)/build/os2/test_os2.cmd "$(DIST)"
-endif
-endif
+endif # ! WINNT
+endif # ! OS2
+endif # ! WINCE
 
 #
 # Java macros
 #
 
 # Make sure any compiled classes work with at least JVM 1.4
 JAVAC_FLAGS += -source 1.4
 
--- a/configure.in
+++ b/configure.in
@@ -2022,17 +2022,17 @@ case "$target" in
         MOZ_DEBUG_FLAGS="-g"
     elif test "$GNU_CC" || test "$GNU_CXX"; then
         GCC_VERSION=`$CC -v 2>&1 | awk '/^gcc version/ { print $3 }'`
         case $GCC_VERSION in
         4.1.*|4.2.*)
             # -Os is broken on gcc 4.1.x and 4.2.x, we need to tweak it to get good results.
             MOZ_OPTIMIZE_SIZE_TWEAK="-finline-limit=50"
         esac
-        MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks -fno-reorder-functions $MOZ_OPTIMIZE_SIZE_TWEAK"
+        MOZ_OPTIMIZE_FLAGS="-Os -freorder-blocks -fno-reorder-functions -fomit-frame-pointer $MOZ_OPTIMIZE_SIZE_TWEAK"
         MOZ_DEBUG_FLAGS="-g"
     fi
 
     TARGET_NSPR_MDCPUCFG='\"md/_linux.cfg\"'
 
     MOZ_MEMORY=1
 
     case "${target_cpu}" in
@@ -4744,17 +4744,16 @@ MOZ_STORAGE=1
 MOZ_SVG=1
 MOZ_TIMELINE=
 MOZ_TOOLKIT_SEARCH=1
 MOZ_UI_LOCALE=en-US
 MOZ_UNIVERSALCHARDET=1
 MOZ_URL_CLASSIFIER=
 MOZ_USE_NATIVE_UCONV=
 MOZ_VIEW_SOURCE=1
-MOZ_XPFE_COMPONENTS=1
 MOZ_XPINSTALL=1
 MOZ_XSLT_STANDALONE=
 MOZ_XTF=1
 MOZ_XUL=1
 MOZ_ZIPWRITER=1
 NS_PRINTING=1
 NECKO_WIFI=1
 NECKO_COOKIES=1
@@ -5003,17 +5002,17 @@ cairo-os2)
     TK_LIBS='$(MOZ_CAIRO_LIBS)'
     ;;
 
 cairo-cocoa)
     MOZ_WIDGET_TOOLKIT=cocoa
     AC_DEFINE(MOZ_WIDGET_COCOA)
     MOZ_USER_DIR="Mozilla"
     AC_DEFINE(XP_MACOSX)
-    TK_LIBS='-framework Carbon -framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework AddressBook'
+    TK_LIBS='-framework QuartzCore -framework Carbon -framework CoreAudio -framework AudioToolbox -framework AudioUnit -framework AddressBook'
     TK_CFLAGS="-DNO_X11"
     LDFLAGS="$LDFLAGS -framework Cocoa -lobjc"
     CFLAGS="$CFLAGS $TK_CFLAGS"
     CXXFLAGS="$CXXFLAGS $TK_CFLAGS"
     LIBXUL_LIBS='$(XPCOM_FROZEN_LDOPTS) $(LIBXUL_DIST)/bin/XUL'
     MOZ_FS_LAYOUT=bundle
     MOZ_WEBGL=1
     ;;
@@ -5168,18 +5167,18 @@ MOZ_ARG_WITH_STRING(branding,
 [  --with-branding=dir    Use branding from the specified directory.],
     MOZ_BRANDING_DIRECTORY=$withval)
 
 REAL_BRANDING_DIRECTORY="${MOZ_BRANDING_DIRECTORY}"
 if test -z "$REAL_BRANDING_DIRECTORY"; then
   REAL_BRANDING_DIRECTORY=${MOZ_BUILD_APP}/branding/nightly
 fi
 
-if test -f "$topsrcdir/$REAL_BRANDING_DIRECTORY/configure.sh"; then
-  . "$topsrcdir/$REAL_BRANDING_DIRECTORY/configure.sh"
+if test -f "${_topsrcdir}/$REAL_BRANDING_DIRECTORY/configure.sh"; then
+  . "${_topsrcdir}/$REAL_BRANDING_DIRECTORY/configure.sh"
 fi
 
 AC_SUBST(MOZ_BRANDING_DIRECTORY)
 
 dnl ========================================================
 dnl = Distribution ID
 dnl ========================================================
 MOZ_ARG_WITH_STRING(distribution-id,
@@ -5563,25 +5562,16 @@ case "$target" in
     if test "$ac_cv_header_oleacc_idl" = "no"; then
         AC_MSG_ERROR([System header oleacc.idl is not available. See http://developer.mozilla.org/en/docs/oleacc.idl for details on fixing this problem.])
     fi
     ;;
 esac
 fi
 
 dnl ========================================================
-dnl xpfe/components on by default
-dnl ========================================================
-MOZ_ARG_DISABLE_BOOL(xpfe-components,
-[  --disable-xpfe-components
-                          Disable xpfe components],
-    MOZ_XPFE_COMPONENTS=,
-    MOZ_XPFE_COMPONENTS=1 )
-
-dnl ========================================================
 dnl xpinstall support on by default
 dnl ========================================================
 MOZ_ARG_DISABLE_BOOL(xpinstall,
 [  --disable-xpinstall     Disable xpinstall support],
     MOZ_XPINSTALL=,
     MOZ_XPINSTALL=1 )
 if test "$MOZ_XPINSTALL"; then
     AC_DEFINE(MOZ_XPINSTALL)
@@ -5863,23 +5853,30 @@ if test -n "${MOZ_JAVAXPCOM}"; then
     AC_MSG_ERROR([The programs java, javac and jar were not found.  Set \$JAVA_HOME to your java sdk directory, use --with-java-bin-path={java-bin-dir}, or reconfigure with --disable-javaxpcom.])
   fi
 fi
 
 dnl ========================================================
 dnl = Breakpad crash reporting (on by default on supported platforms)
 dnl ========================================================
 
-if (test "$OS_ARCH" = "WINNT" -a -z "$GNU_CC" \
-    || test "$OS_ARCH" = "Darwin" \
-    || test "$OS_ARCH" = "Linux" -a "$CPU_ARCH" = "x86" \
-    || test "$OS_ARCH" = "SunOS") \
-   && test -z "$HAVE_64BIT_OS"; then
-   MOZ_CRASHREPORTER=1
-fi
+case $target in
+i?86-*-mingw*)
+  MOZ_CRASHREPORTER=1
+  ;;
+i?86-apple-darwin*|powerpc-apple-darwin*)
+  MOZ_CRASHREPORTER=1
+  ;;
+i?86-*-linux*|x86_64-*-linux*)
+  MOZ_CRASHREPORTER=1
+  ;;
+*solaris*)
+  MOZ_CRASHREPORTER=1
+  ;;
+esac
 
 MOZ_ARG_DISABLE_BOOL(crashreporter,
 [  --disable-crashreporter          Disable breakpad crash reporting],
     MOZ_CRASHREPORTER=,
     MOZ_CRASHREPORTER=1)
 
 if test -n "$MOZ_CRASHREPORTER"; then
    AC_DEFINE(MOZ_CRASHREPORTER)
@@ -8276,17 +8273,16 @@ AC_SUBST(BUILD_STATIC_LIBS)
 AC_SUBST(MOZ_ENABLE_LIBXUL)
 AC_SUBST(ENABLE_TESTS)
 AC_SUBST(IBMBIDI)
 AC_SUBST(MOZ_UNIVERSALCHARDET)
 AC_SUBST(ACCESSIBILITY)
 AC_SUBST(MOZ_XPINSTALL)
 AC_SUBST(MOZ_VIEW_SOURCE)
 AC_SUBST(MOZ_SPELLCHECK)
-AC_SUBST(MOZ_XPFE_COMPONENTS)
 AC_SUBST(MOZ_USER_DIR)
 AC_SUBST(MOZ_CRASHREPORTER)
 
 AC_SUBST(ENABLE_STRIP)
 AC_SUBST(PKG_SKIP_STRIP)
 AC_SUBST(USE_ELF_DYNSTR_GC)
 AC_SUBST(INCREMENTAL_LINKER)
 AC_SUBST(MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS)
new file mode 100644
--- /dev/null
+++ b/content/base/crashtests/554230-1.xhtml
@@ -0,0 +1,15 @@
+<html class="reftest-wait" xmlns="http://www.w3.org/1999/xhtml"><iframe contenteditable="true"></iframe><span></span><script style="display: none;" id="fuzz1" type="text/javascript">
+<![CDATA[
+
+function boom()
+{
+  document.getElementsByTagName("iframe")[0].focus();
+  document.getElementsByTagName("span")[0].appendChild(document.createElementNS("http://www.w3.org/1999/xhtml", "div"));
+  document.execCommand("selectAll", false, null);
+  document.documentElement.removeAttribute("class");
+}
+
+window.addEventListener("load", boom, false);
+
+]]>
+</script></html>
--- a/content/base/crashtests/crashtests.list
+++ b/content/base/crashtests/crashtests.list
@@ -55,8 +55,9 @@ skip load 458637-1.html # sporadically t
 load 472593-1.html
 load 474041-1.svg
 load 483818-1.html
 load 493281-1.html
 load 493281-2.html
 load 490760-1.xhtml
 load 494810-1.html
 load 529670.html
+load 554230-1.xhtml
--- a/content/base/public/nsIObjectLoadingContent.idl
+++ b/content/base/public/nsIObjectLoadingContent.idl
@@ -42,17 +42,17 @@ interface nsIObjectFrame;
 interface nsIPluginInstance;
 interface nsIPluginTag;
 interface nsIDOMElement;
 interface nsIDOMClientRect;
 
 /**
  * This interface represents a content node that loads objects.
  */
-[scriptable, uuid(1d89f35e-8f4b-4b79-b622-7be812a8babe)]
+[scriptable, uuid(9558649a-7255-4b00-afb4-1171e9cdcead)]
 interface nsIObjectLoadingContent : nsISupports
 {
   const unsigned long TYPE_LOADING  = 0;
   const unsigned long TYPE_IMAGE    = 1;
   const unsigned long TYPE_PLUGIN   = 2;
   const unsigned long TYPE_DOCUMENT = 3;
   const unsigned long TYPE_NULL     = 4;
 
@@ -121,11 +121,12 @@ interface nsIObjectLoadingContent : nsIS
    * If this object is in going to be printed, this method
    * returns the nsIObjectFrame object which should be used when
    * printing the plugin. The returned nsIFrame is in the original document,
    * not in the static clone.
    */
   [noscript] nsIFrame getPrintFrame();
 
   [noscript] void pluginCrashed(in nsIPluginTag pluginTag,
-                                in AString minidumpID,
+                                in AString pluginDumpID,
+                                in AString browserDumpID,
                                 in boolean submittedCrashReport);
 };
--- a/content/base/src/nsContentSink.cpp
+++ b/content/base/src/nsContentSink.cpp
@@ -1723,21 +1723,23 @@ nsContentSink::WillBuildModelImpl()
 
     DoProcessLinkHeader();
   }
 }
 
 void
 nsContentSink::ContinueInterruptedParsingIfEnabled()
 {
+  // This shouldn't be called in the HTML5 case.
   if (mParser && mParser->IsParserEnabled()) {
     mParser->ContinueInterruptedParsing();
   }
 }
 
+// Overridden in the HTML5 case
 void
 nsContentSink::ContinueInterruptedParsingAsync()
 {
   nsCOMPtr<nsIRunnable> ev = new nsRunnableMethod<nsContentSink>(this,
     &nsContentSink::ContinueInterruptedParsingIfEnabled);
 
   NS_DispatchToCurrentThread(ev);
 }
@@ -1760,16 +1762,19 @@ IsAttrURI(nsIAtom *aName)
 // Thanks to Mark Pilgrim and Sam Ruby for the initial whitelist
 //
 nsIAtom** const kDefaultAllowedTags [] = {
   &nsGkAtoms::a,
   &nsGkAtoms::abbr,
   &nsGkAtoms::acronym,
   &nsGkAtoms::address,
   &nsGkAtoms::area,
+#ifdef MOZ_MEDIA
+  &nsGkAtoms::audio,
+#endif
   &nsGkAtoms::b,
   &nsGkAtoms::bdo,
   &nsGkAtoms::big,
   &nsGkAtoms::blockquote,
   &nsGkAtoms::br,
   &nsGkAtoms::button,
   &nsGkAtoms::caption,
   &nsGkAtoms::center,
@@ -1812,16 +1817,19 @@ nsIAtom** const kDefaultAllowedTags [] =
   &nsGkAtoms::option,
   &nsGkAtoms::p,
   &nsGkAtoms::pre,
   &nsGkAtoms::q,
   &nsGkAtoms::s,
   &nsGkAtoms::samp,
   &nsGkAtoms::select,
   &nsGkAtoms::small,
+#ifdef MOZ_MEDIA
+  &nsGkAtoms::source,
+#endif
   &nsGkAtoms::span,
   &nsGkAtoms::strike,
   &nsGkAtoms::strong,
   &nsGkAtoms::sub,
   &nsGkAtoms::sup,
   &nsGkAtoms::table,
   &nsGkAtoms::tbody,
   &nsGkAtoms::td,
@@ -1829,44 +1837,54 @@ nsIAtom** const kDefaultAllowedTags [] =
   &nsGkAtoms::tfoot,
   &nsGkAtoms::th,
   &nsGkAtoms::thead,
   &nsGkAtoms::tr,
   &nsGkAtoms::tt,
   &nsGkAtoms::u,
   &nsGkAtoms::ul,
   &nsGkAtoms::var,
+#ifdef MOZ_MEDIA
+  &nsGkAtoms::video,
+#endif
   nsnull
 };
 
 nsIAtom** const kDefaultAllowedAttributes [] = {
   &nsGkAtoms::abbr,
   &nsGkAtoms::accept,
   &nsGkAtoms::acceptcharset,
   &nsGkAtoms::accesskey,
   &nsGkAtoms::action,
   &nsGkAtoms::align,
   &nsGkAtoms::alt,
   &nsGkAtoms::autocomplete,
+#ifdef MOZ_MEDIA
+  &nsGkAtoms::autobuffer,
+  &nsGkAtoms::autoplay,
+#endif
   &nsGkAtoms::axis,
   &nsGkAtoms::background,
   &nsGkAtoms::bgcolor,
   &nsGkAtoms::border,
   &nsGkAtoms::cellpadding,
   &nsGkAtoms::cellspacing,
   &nsGkAtoms::_char,
   &nsGkAtoms::charoff,
   &nsGkAtoms::charset,
   &nsGkAtoms::checked,
   &nsGkAtoms::cite,
   &nsGkAtoms::_class,
   &nsGkAtoms::clear,
   &nsGkAtoms::cols,
   &nsGkAtoms::colspan,
   &nsGkAtoms::color,
+#ifdef MOZ_MEDIA
+  &nsGkAtoms::controls,
+#endif
   &nsGkAtoms::compact,
   &nsGkAtoms::coords,
   &nsGkAtoms::datetime,
   &nsGkAtoms::dir,
   &nsGkAtoms::disabled,
   &nsGkAtoms::enctype,
   &nsGkAtoms::_for,
   &nsGkAtoms::frame,
@@ -1875,25 +1893,37 @@ nsIAtom** const kDefaultAllowedAttribute
   &nsGkAtoms::href,
   &nsGkAtoms::hreflang,
   &nsGkAtoms::hspace,
   &nsGkAtoms::id,
   &nsGkAtoms::ismap,
   &nsGkAtoms::label,
   &nsGkAtoms::lang,
   &nsGkAtoms::longdesc,
+#ifdef MOZ_MEDIA
+  &nsGkAtoms::loopend,
+  &nsGkAtoms::loopstart,
+#endif
   &nsGkAtoms::maxlength,
   &nsGkAtoms::media,
   &nsGkAtoms::method,
   &nsGkAtoms::multiple,
   &nsGkAtoms::name,
   &nsGkAtoms::nohref,
   &nsGkAtoms::noshade,
   &nsGkAtoms::nowrap,
+#ifdef MOZ_MEDIA
+  &nsGkAtoms::pixelratio,
+  &nsGkAtoms::playbackrate,
+  &nsGkAtoms::playcount,
+#endif
   &nsGkAtoms::pointSize,
+#ifdef MOZ_MEDIA
+  &nsGkAtoms::poster,
+#endif
   &nsGkAtoms::prompt,
   &nsGkAtoms::readonly,
   &nsGkAtoms::rel,
   &nsGkAtoms::rev,
   &nsGkAtoms::role,
   &nsGkAtoms::rows,
   &nsGkAtoms::rowspan,
   &nsGkAtoms::rules,
--- a/content/base/src/nsContentSink.h
+++ b/content/base/src/nsContentSink.h
@@ -295,17 +295,17 @@ protected:
 
 private:
   // People shouldn't be allocating this class directly.  All subclasses should
   // be allocated using a zeroing operator new.
   void* operator new(size_t sz) CPP_THROW_NEW;  // Not to be implemented
 
 protected:
 
-  void ContinueInterruptedParsingAsync();
+  virtual void ContinueInterruptedParsingAsync();
   void ContinueInterruptedParsingIfEnabled();
 
   nsCOMPtr<nsIDocument>         mDocument;
   nsCOMPtr<nsIParser>           mParser;
   nsCOMPtr<nsIURI>              mDocumentURI;
   nsCOMPtr<nsIURI>              mDocumentBaseURI;
   nsCOMPtr<nsIDocShell>         mDocShell;
   nsRefPtr<mozilla::css::Loader> mCSSLoader;
--- a/content/base/src/nsCopySupport.cpp
+++ b/content/base/src/nsCopySupport.cpp
@@ -624,16 +624,17 @@ nsCopySupport::GetSelectionForCopy(nsIDo
 PRBool
 nsCopySupport::CanCopy(nsIDocument* aDocument)
 {
   if (!aDocument)
     return PR_FALSE;
 
   nsCOMPtr<nsISelection> sel;
   GetSelectionForCopy(aDocument, getter_AddRefs(sel));
+  NS_ENSURE_TRUE(sel, PR_FALSE);
 
   PRBool isCollapsed;
   sel->GetIsCollapsed(&isCollapsed);
   return !isCollapsed;
 }
 
 PRBool
 nsCopySupport::FireClipboardEvent(PRInt32 aType, nsIPresShell* aPresShell, nsISelection* aSelection)
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -3993,17 +3993,17 @@ nsDocument::DispatchContentLoadedEvents(
         // dispatching code.
 
         nsEvent* innerEvent = privateEvent->GetInternalNSEvent();
         if (innerEvent) {
           nsEventStatus status = nsEventStatus_eIgnore;
 
           nsIPresShell *shell = parent->GetPrimaryShell();
           if (shell) {
-            nsCOMPtr<nsPresContext> context = shell->GetPresContext();
+            nsRefPtr<nsPresContext> context = shell->GetPresContext();
 
             if (context) {
               nsEventDispatcher::Dispatch(parent, context, innerEvent, event,
                                           &status);
             }
           }
         }
       }
@@ -6193,17 +6193,17 @@ nsDocument::RemoveEventListener(const ns
   return RemoveGroupedEventListener(aType, aListener, aUseCapture, nsnull);
 }
 
 NS_IMETHODIMP
 nsDocument::DispatchEvent(nsIDOMEvent* aEvent, PRBool *_retval)
 {
   // Obtain a presentation context
   nsIPresShell *shell = GetPrimaryShell();
-  nsCOMPtr<nsPresContext> context;
+  nsRefPtr<nsPresContext> context;
   if (shell) {
      context = shell->GetPresContext();
   }
 
   nsEventStatus status = nsEventStatus_eIgnore;
   nsresult rv =
     nsEventDispatcher::DispatchDOMEvent(static_cast<nsINode*>(this),
                                         nsnull, aEvent, context, &status);
--- a/content/base/src/nsObjectLoadingContent.cpp
+++ b/content/base/src/nsObjectLoadingContent.cpp
@@ -216,26 +216,29 @@ nsPluginErrorEvent::Run()
 }
 
 /**
  * A task for firing PluginCrashed DOM Events.
  */
 class nsPluginCrashedEvent : public nsRunnable {
 public:
   nsCOMPtr<nsIContent> mContent;
-  nsString mMinidumpID;
+  nsString mPluginDumpID;
+  nsString mBrowserDumpID;
   nsString mPluginName;
   PRBool mSubmittedCrashReport;
 
   nsPluginCrashedEvent(nsIContent* aContent,
-                       const nsAString& aMinidumpID,
+                       const nsAString& aPluginDumpID,
+                       const nsAString& aBrowserDumpID,
                        const nsAString& aPluginName,
                        PRBool submittedCrashReport)
     : mContent(aContent),
-      mMinidumpID(aMinidumpID),
+      mPluginDumpID(aPluginDumpID),
+      mBrowserDumpID(aBrowserDumpID),
       mPluginName(aPluginName),
       mSubmittedCrashReport(submittedCrashReport)
   {}
 
   ~nsPluginCrashedEvent() {}
 
   NS_IMETHOD Run();
 };
@@ -264,24 +267,33 @@ nsPluginCrashedEvent::Run()
   }
 
   event->InitEvent(NS_LITERAL_STRING("PluginCrashed"), PR_TRUE, PR_TRUE);
   privateEvent->SetTrusted(PR_TRUE);
   privateEvent->GetInternalNSEvent()->flags |= NS_EVENT_FLAG_ONLY_CHROME_DISPATCH;
   
   nsCOMPtr<nsIWritableVariant> variant;
 
-  // add a "minidumpID" property to this event
+  // add a "pluginDumpID" property to this event
   variant = do_CreateInstance("@mozilla.org/variant;1");
   if (!variant) {
-    NS_WARNING("Couldn't create minidumpID variant for PluginCrashed event!");
+    NS_WARNING("Couldn't create pluginDumpID variant for PluginCrashed event!");
     return NS_OK;
   }
-  variant->SetAsAString(mMinidumpID);
-  containerEvent->SetData(NS_LITERAL_STRING("minidumpID"), variant);
+  variant->SetAsAString(mPluginDumpID);
+  containerEvent->SetData(NS_LITERAL_STRING("pluginDumpID"), variant);
+
+  // add a "browserDumpID" property to this event
+  variant = do_CreateInstance("@mozilla.org/variant;1");
+  if (!variant) {
+    NS_WARNING("Couldn't create browserDumpID variant for PluginCrashed event!");
+    return NS_OK;
+  }
+  variant->SetAsAString(mBrowserDumpID);
+  containerEvent->SetData(NS_LITERAL_STRING("browserDumpID"), variant);
 
   // add a "pluginName" property to this event
   variant = do_CreateInstance("@mozilla.org/variant;1");
   if (!variant) {
     NS_WARNING("Couldn't create pluginName variant for PluginCrashed event!");
     return NS_OK;
   }
   variant->SetAsAString(mPluginName);
@@ -2022,31 +2034,33 @@ nsObjectLoadingContent::SetAbsoluteScree
   if (!frame)
     return NS_ERROR_NOT_AVAILABLE;
 
   return frame->SetAbsoluteScreenPosition(element, position, clip);
 }
 
 NS_IMETHODIMP
 nsObjectLoadingContent::PluginCrashed(nsIPluginTag* aPluginTag,
-                                      const nsAString& minidumpID,
+                                      const nsAString& pluginDumpID,
+                                      const nsAString& browserDumpID,
                                       PRBool submittedCrashReport)
 {
   AutoNotifier notifier(this, PR_TRUE);
   UnloadContent();
   mFallbackReason = ePluginCrashed;
   nsCOMPtr<nsIContent> thisContent = do_QueryInterface(static_cast<nsIImageLoadingContent*>(this));
 
   // Note that aPluginTag in invalidated after we're called, so copy 
   // out any data we need now.
   nsCAutoString pluginName;
   aPluginTag->GetName(pluginName);
 
   nsCOMPtr<nsIRunnable> ev = new nsPluginCrashedEvent(thisContent,
-                                                      minidumpID,
+                                                      pluginDumpID,
+                                                      browserDumpID,
                                                       NS_ConvertUTF8toUTF16(pluginName),
                                                       submittedCrashReport);
   nsresult rv = NS_DispatchToCurrentThread(ev);
   if (NS_FAILED(rv)) {
     NS_WARNING("failed to dispatch nsPluginCrashedEvent");
   }
   return NS_OK;
 }
--- a/content/base/src/nsScriptElement.cpp
+++ b/content/base/src/nsScriptElement.cpp
@@ -53,17 +53,17 @@ nsScriptElement::ScriptAvailable(nsresul
                                  PRBool aIsInline,
                                  nsIURI *aURI,
                                  PRInt32 aLineNo)
 {
   if (!aIsInline && NS_FAILED(aResult)) {
     nsCOMPtr<nsIContent> cont =
       do_QueryInterface((nsIScriptElement*) this);
 
-    nsCOMPtr<nsPresContext> presContext =
+    nsRefPtr<nsPresContext> presContext =
       nsContentUtils::GetContextForContent(cont);
 
     nsEventStatus status = nsEventStatus_eIgnore;
     nsScriptErrorEvent event(PR_TRUE, NS_LOAD_ERROR);
 
     event.lineNr = aLineNo;
 
     NS_NAMED_LITERAL_STRING(errorString, "Error loading script");
@@ -86,17 +86,17 @@ nsScriptElement::ScriptEvaluated(nsresul
                                  nsIScriptElement *aElement,
                                  PRBool aIsInline)
 {
   nsresult rv = NS_OK;
   if (!aIsInline) {
     nsCOMPtr<nsIContent> cont =
       do_QueryInterface((nsIScriptElement*) this);
 
-    nsCOMPtr<nsPresContext> presContext =
+    nsRefPtr<nsPresContext> presContext =
       nsContentUtils::GetContextForContent(cont);
 
     nsEventStatus status = nsEventStatus_eIgnore;
     PRUint32 type = NS_SUCCEEDED(aResult) ? NS_LOAD : NS_LOAD_ERROR;
     nsEvent event(PR_TRUE, type);
     if (type == NS_LOAD) {
       // Load event doesn't bubble.
       event.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
--- a/content/base/src/nsXHTMLContentSerializer.cpp
+++ b/content/base/src/nsXHTMLContentSerializer.cpp
@@ -456,28 +456,36 @@ nsXHTMLContentSerializer::AppendEndOfEle
   NS_ASSERTION(!mIsHTMLSerializer, "nsHTMLContentSerializer shouldn't call this method !");
 
   if (kNameSpaceID_XHTML != aNamespaceID) {
     nsXMLContentSerializer::AppendEndOfElementStart(aOriginalElement, aName,
                                                     aNamespaceID, aStr);
     return;
   }
 
-  nsIParserService* parserService = nsContentUtils::GetParserService();
+  nsCOMPtr<nsIContent> content = do_QueryInterface(aOriginalElement);
+
+  // for non empty elements, even if they are not a container, we always
+  // serialize their content, because the XHTML element could contain non XHTML
+  // nodes useful in some context, like in an XSLT stylesheet
+  if (HasNoChildren(content)) {
 
-  if (parserService) {
-    PRBool isContainer;
-    parserService->IsContainer(parserService->HTMLAtomTagToId(aName),
-                             isContainer);
-    if (!isContainer) {
-      // for backward compatibility with HTML 4 user agents
-      // only non-container HTML elements can be closed immediatly,
-      // and a space is added before />
-      AppendToString(NS_LITERAL_STRING(" />"), aStr);
-      return;
+    nsIParserService* parserService = nsContentUtils::GetParserService();
+  
+    if (parserService) {
+      PRBool isContainer;
+      parserService->IsContainer(parserService->HTMLAtomTagToId(aName),
+                                 isContainer);
+      if (!isContainer) {
+        // for backward compatibility with HTML 4 user agents
+        // only non-container HTML elements can be closed immediatly,
+        // and a space is added before />
+        AppendToString(NS_LITERAL_STRING(" />"), aStr);
+        return;
+      }
     }
   }
   AppendToString(kGreaterThan, aStr);
 }
 
 void
 nsXHTMLContentSerializer::AfterElementStart(nsIContent * aContent,
                                             nsIDOMElement *aOriginalElement,
@@ -600,27 +608,29 @@ nsXHTMLContentSerializer::CheckElementEn
       NS_ASSERTION((!mOLStateStack.IsEmpty()), "Cannot have an empty OL Stack");
       /* Though at this point we must always have an state to be deleted as all 
       the OL opening tags are supposed to push an olState object to the stack*/
       if (!mOLStateStack.IsEmpty()) {
         mOLStateStack.RemoveElementAt(mOLStateStack.Length() -1);
       }
     }
 
-    nsIParserService* parserService = nsContentUtils::GetParserService();
+    if (HasNoChildren(aContent)) {
+      nsIParserService* parserService = nsContentUtils::GetParserService();
 
-    if (parserService) {
-      PRBool isContainer;
+      if (parserService) {
+        PRBool isContainer;
 
-      parserService->IsContainer(parserService->HTMLAtomTagToId(name),
-                                 isContainer);
-      if (!isContainer) {
-        // non-container HTML elements are already closed,
-        // see AppendEndOfElementStart
-        return PR_FALSE;
+        parserService->IsContainer(parserService->HTMLAtomTagToId(name),
+                                   isContainer);
+        if (!isContainer) {
+          // non-container HTML elements are already closed,
+          // see AppendEndOfElementStart
+          return PR_FALSE;
+        }
       }
     }
     // for backward compatibility with old HTML user agents,
     // empty elements should have an ending tag, so we mustn't call
     // nsXMLContentSerializer::CheckElementEnd
     return PR_TRUE;
   }
 
@@ -1061,8 +1071,27 @@ nsXHTMLContentSerializer::IsFirstChildOf
         return PR_TRUE;
     }
 
     return PR_FALSE;
   }
   else
     return PR_FALSE;
 }
+
+PRBool
+nsXHTMLContentSerializer::HasNoChildren(nsIContent * aContent) {
+
+  PRUint32 i, childCount = aContent->GetChildCount();
+
+  for (i = 0; i < childCount; ++i) {
+
+    nsIContent* child = aContent->GetChildAt(i);
+
+    if (!child->IsNodeOfType(nsINode::eTEXT))
+      return PR_FALSE;
+
+    if (child->TextLength())
+      return PR_FALSE;
+  }
+
+  return PR_TRUE;
+}
--- a/content/base/src/nsXHTMLContentSerializer.h
+++ b/content/base/src/nsXHTMLContentSerializer.h
@@ -195,14 +195,15 @@ class nsXHTMLContentSerializer : public 
     // is true only before the serialization of the first li of an ol
     // should be false for other li in the list
     PRBool isFirstListItem;
   };
 
   // Stack to store one olState struct per <OL>.
   nsAutoTArray<olState, 8> mOLStateStack;
 
+  PRBool HasNoChildren(nsIContent* aContent);
 };
 
 nsresult
 NS_NewXHTMLContentSerializer(nsIContentSerializer** aSerializer);
 
 #endif
--- a/content/base/test/Makefile.in
+++ b/content/base/test/Makefile.in
@@ -357,16 +357,19 @@ include $(topsrcdir)/config/rules.mk
  		file_CSP_evalscript_main.html^headers^ \
  		file_CSP_evalscript_main.js \
 		test_bug540854.html \
 		bug540854.sjs \
 		test_bug548463.html \
 		test_bug545644.html \
 		test_bug545644.xhtml \
 		test_bug553896.xhtml \
+		test_bug541937.html \
+		file_bug541937.html \
+		file_bug541937.xhtml \
 		$(NULL)
 
 # This test fails on the Mac for some reason
 ifneq (,$(filter gtk2 windows,$(MOZ_WIDGET_TOOLKIT)))
 _TEST_FILES += 	test_copyimage.html \
 		$(NULL)
 endif
 
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_bug541937.html
@@ -0,0 +1,8 @@
+<!DOCTYPE html><html><head><meta http-equiv="content-type" content="text/html; charset=UTF-8">
+  <title>Test</title>
+   <link rel="Top" href="">  foo </link>
+
+</head><body>
+  <p>Hello world</p>
+</body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/file_bug541937.xhtml
@@ -0,0 +1,12 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+   <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
+  <title>Test</title>
+   <link rel="Top" href="">  foo </link>
+
+</head>
+<body>
+  <p>Hello world</p>
+</body>
+</html>
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/content/base/test/test_bug541937.html
@@ -0,0 +1,121 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+-->
+<head>
+  <title>Test for XHTML serializer, bug 541937</title>
+  <script type="text/javascript" src="/MochiKit/packed.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=541937">Mozilla Bug </a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  <iframe id="testframe" src="file_bug541937.html">
+  </iframe>
+  <iframe id="testframe2" src="file_bug541937.xhtml">
+  </iframe>
+</div>
+
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+function testSerializer () {
+  netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
+  const de = Components.interfaces.nsIDocumentEncoder
+  var encoder = Components.classes["@mozilla.org/layout/documentEncoder;1?type=text/html"]
+                   .createInstance(Components.interfaces.nsIDocumentEncoder);
+
+  var parser = new DOMParser();
+  var serializer = new XMLSerializer();
+
+  // with content
+  var str = '<?xml version="1.0"?><doc>\n<link xmlns="http://www.w3.org/1999/xhtml"><!-- child nodes -->  \n<content xmlns=""/></link>\n</doc>';
+  var expected = '<?xml version="1.0" encoding="UTF-8"?>\n<doc>\n<link xmlns="http://www.w3.org/1999/xhtml"><!-- child nodes -->  \n<content xmlns=""/></link>\n</doc>';
+
+  var doc = parser.parseFromString(str,"application/xml");
+  var result = serializer.serializeToString(doc);
+  result = result.replace(/\r\n/mg, "\n");
+  is(result, expected, "serialization of a link element inside an xml document with children");
+
+  // with only whitespaces
+  str = '<?xml version="1.0"?><doc>\n<link xmlns="http://www.w3.org/1999/xhtml">       \n    </link>\n</doc>';
+  expected = '<?xml version="1.0" encoding="UTF-8"?>\n<doc>\n<link xmlns="http://www.w3.org/1999/xhtml">       \n    </link>\n</doc>';  
+
+  doc = parser.parseFromString(str,"application/xml");
+  result = serializer.serializeToString(doc);
+  result = result.replace(/\r\n/mg, "\n");
+  is(result, expected, "serialization of a link element with only whitespaces as content, inside an xml document");
+  
+  // with only one space as content
+  str = '<?xml version="1.0"?><doc>\n<link xmlns="http://www.w3.org/1999/xhtml"> </link>\n</doc>';
+  expected = '<?xml version="1.0" encoding="UTF-8"?>\n<doc>\n<link xmlns="http://www.w3.org/1999/xhtml"> </link>\n</doc>';  
+
+  doc = parser.parseFromString(str,"application/xml");
+  result = serializer.serializeToString(doc);
+  result = result.replace(/\r\n/mg, "\n");
+  is(result, expected, "serialization of a link element with only one space as content, inside an xml document");
+  
+  // let's remove the content
+  str = '<?xml version="1.0"?><doc>\n<link xmlns="http://www.w3.org/1999/xhtml"> <!-- child nodes -->  \ndeleted content<content xmlns=""/> </link>\n</doc>';
+  expected = '<?xml version="1.0" encoding="UTF-8"?>\n<doc>\n<link xmlns="http://www.w3.org/1999/xhtml" />\n</doc>';  
+
+  doc = parser.parseFromString(str,"application/xml");
+  doc.documentElement.firstElementChild.textContent = '';
+  result = serializer.serializeToString(doc);
+  result = result.replace(/\r\n/mg, "\n");
+  is(result, expected, "serialization of a link element on which we removed dynamically the content, inside an xml document");
+  
+  // with no content but an ended tag
+  str = '<?xml version="1.0"?><doc>\n<link xmlns="http://www.w3.org/1999/xhtml"></link>\n</doc>';
+  expected = '<?xml version="1.0" encoding="UTF-8"?>\n<doc>\n<link xmlns="http://www.w3.org/1999/xhtml" />\n</doc>';  
+
+  doc = parser.parseFromString(str,"application/xml");
+  result = serializer.serializeToString(doc);
+  result = result.replace(/\r\n/mg, "\n");
+  is(result, expected, "serialization of a link element with no content but with an ended tag, inside an xml document");
+  
+  // with no content
+  str = '<?xml version="1.0"?><doc>\n<link xmlns="http://www.w3.org/1999/xhtml"/>\n</doc>';
+  expected = '<?xml version="1.0" encoding="UTF-8"?>\n<doc>\n<link xmlns="http://www.w3.org/1999/xhtml" />\n</doc>';  
+
+  doc = parser.parseFromString(str,"application/xml");
+  result = serializer.serializeToString(doc);
+  result = result.replace(/\r\n/mg, "\n");
+  is(result, expected, "serialization of a link element with no content, inside an xml document");
+  
+  
+  doc = $("testframe").contentDocument;
+  encoder.init(doc, "text/html", de.OutputLFLineBreak);
+  encoder.setCharset("UTF-8");
+  result = encoder.encodeToString();
+  expected = '<!DOCTYPE HTML>\n<html><head><meta http-equiv=\"content-type\" content=\"text/html; \ncharset=UTF-8\">\n  <title>Test</title>\n';
+  expected += '   <link rel=\"Top\" href=\"\"> ';
+  expected += ' </head><body>foo \n\n\n  <p>Hello world</p>\n</body></html>';
+  is(result, expected, "serialization of a link element with content, inside an html document");
+
+  doc = $("testframe2").contentDocument;
+  encoder.init(doc, "application/xhtml+xml", de.OutputLFLineBreak);
+  encoder.setCharset("UTF-8");
+  result = encoder.encodeToString();
+  expected = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">\n';
+  expected += '<html xmlns="http://www.w3.org/1999/xhtml">\n<head>\n   <meta http-equiv="content-type" content="text/html; charset=UTF-8" />\n  <title>Test</title>\n';
+  expected += '   <link rel="Top" href="">  foo </link>\n';
+  expected += '\n</head>\n<body>\n  <p>Hello world</p>\n</body>\n</html>';
+  is(result, expected, "serialization of a link element with content, inside an xhtml document");
+
+  SimpleTest.finish();
+}
+
+
+SimpleTest.waitForExplicitFinish();
+
+addLoadEvent(testSerializer);
+
+</script>
+</pre>
+</body>
+</html>
+
+
--- a/content/canvas/src/nsCanvasRenderingContext2D.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2D.cpp
@@ -3470,17 +3470,17 @@ nsCanvasRenderingContext2D::DrawWindow(n
       // XXX ERRMSG we need to report an error to developers here! (bug 329026)
         return NS_ERROR_DOM_SECURITY_ERR;
     }
 
     // Flush layout updates
     if (!(flags & nsIDOMCanvasRenderingContext2D::DRAWWINDOW_DO_NOT_FLUSH))
         FlushLayoutForTree(aWindow);
 
-    nsCOMPtr<nsPresContext> presContext;
+    nsRefPtr<nsPresContext> presContext;
     nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(aWindow);
     if (win) {
         nsIDocShell* docshell = win->GetDocShell();
         if (docshell) {
             docshell->GetPresContext(getter_AddRefs(presContext));
         }
     }
     if (!presContext)
--- a/content/events/src/nsContentEventHandler.cpp
+++ b/content/events/src/nsContentEventHandler.cpp
@@ -934,18 +934,18 @@ nsContentEventHandler::OnSelectionEvent(
   } else {
     rv = Init(aEvent);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   // Get range from offset and length
   nsRefPtr<nsRange> range = new nsRange();
   NS_ENSURE_TRUE(range, NS_ERROR_OUT_OF_MEMORY);
-  rv = SetRangeFromFlatTextOffset(range, aEvent->mOffset,
-                                  aEvent->mLength, PR_TRUE);
+  rv = SetRangeFromFlatTextOffset(range, aEvent->mOffset, aEvent->mLength,
+                                  aEvent->mExpandToClusterBoundary);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsINode* startNode = range->GetStartParent();
   nsINode* endNode = range->GetEndParent();
   PRInt32 startOffset = range->StartOffset();
   PRInt32 endOffset = range->EndOffset();
   AdjustRangeForSelection(mRootContent, &startNode, &startOffset);
   AdjustRangeForSelection(mRootContent, &endNode, &endOffset);
--- a/content/events/src/nsDOMDataTransfer.cpp
+++ b/content/events/src/nsDOMDataTransfer.cpp
@@ -44,16 +44,17 @@
 #include "nsISupportsPrimitives.h"
 #include "nsDOMClassInfo.h"
 #include "nsDOMLists.h"
 #include "nsGUIEvent.h"
 #include "nsDOMError.h"
 #include "nsIDragService.h"
 #include "nsIScriptableRegion.h"
 #include "nsContentUtils.h"
+#include "nsIContent.h"
 
 NS_IMPL_CYCLE_COLLECTION_2(nsDOMDataTransfer, mDragTarget, mDragImage)
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDOMDataTransfer)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDOMDataTransfer)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDOMDataTransfer)
   NS_INTERFACE_MAP_ENTRY(nsIDOMDataTransfer)
@@ -552,16 +553,20 @@ nsDOMDataTransfer::MozClearDataAt(const 
 }
 
 NS_IMETHODIMP
 nsDOMDataTransfer::SetDragImage(nsIDOMElement* aImage, PRInt32 aX, PRInt32 aY)
 {
   if (mReadOnly)
     return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
 
+  if (aImage) {
+    nsCOMPtr<nsIContent> content = do_QueryInterface(aImage);
+    NS_ENSURE_TRUE(content, NS_ERROR_INVALID_ARG);
+  }
   mDragImage = aImage;
   mDragImageX = aX;
   mDragImageY = aY;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMDataTransfer::AddElement(nsIDOMElement* aElement)
--- a/content/events/src/nsDOMEvent.cpp
+++ b/content/events/src/nsDOMEvent.cpp
@@ -230,17 +230,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
         NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mEvent->mRelatedNode");
         cb.NoteXPCOMChild(
           static_cast<nsMutationEvent*>(tmp->mEvent)->mRelatedNode);
         break;
       default:
         break;
     }
   }
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mPresContext)
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mPresContext.get(), nsPresContext)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mTmpRealOriginalTarget)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mExplicitOriginalTarget)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 // nsIDOMEventInterface
 NS_METHOD nsDOMEvent::GetType(nsAString& aType)
 {
   if (!mCachedType.IsEmpty()) {
--- a/content/events/src/nsDOMEvent.h
+++ b/content/events/src/nsDOMEvent.h
@@ -207,17 +207,17 @@ public:
 protected:
 
   // Internal helper functions
   nsresult SetEventType(const nsAString& aEventTypeArg);
   already_AddRefed<nsIDOMEventTarget> GetTargetFromFrame();
   nsresult ReportWrongPropertyAccessWarning(const char* aPropertyName);
 
   nsEvent*                    mEvent;
-  nsCOMPtr<nsPresContext>     mPresContext;
+  nsRefPtr<nsPresContext>     mPresContext;
   nsCOMPtr<nsIDOMEventTarget> mTmpRealOriginalTarget;
   nsCOMPtr<nsIDOMEventTarget> mExplicitOriginalTarget;
   nsString                    mCachedType;
   PRPackedBool                mEventIsInternal;
   PRPackedBool                mPrivateDataDuplicated;
 };
 
 #define NS_FORWARD_TO_NSDOMEVENT \
--- a/content/events/src/nsDOMMouseEvent.cpp
+++ b/content/events/src/nsDOMMouseEvent.cpp
@@ -49,16 +49,19 @@ nsDOMMouseEvent::nsDOMMouseEvent(nsPresC
                  new nsMouseEvent(PR_FALSE, 0, nsnull,
                                   nsMouseEvent::eReal))
 {
   // There's no way to make this class' ctor allocate an nsMouseScrollEvent.
   // It's not that important, though, since a scroll event is not a real
   // DOM event.
   
   if (aEvent) {
+    NS_ASSERTION(static_cast<nsMouseEvent*>(mEvent)->reason
+                 != nsMouseEvent::eSynthesized,
+                 "Don't dispatch DOM events from synthesized mouse events");
     mEventIsInternal = PR_FALSE;
   }
   else {
     mEventIsInternal = PR_TRUE;
     mEvent->time = PR_Now();
     mEvent->refPoint.x = mEvent->refPoint.y = 0;
   }
 
--- a/content/events/src/nsEventDispatcher.cpp
+++ b/content/events/src/nsEventDispatcher.cpp
@@ -502,17 +502,17 @@ nsEventDispatcher::Dispatch(nsISupports*
   }
 #endif
 
   nsresult rv = NS_OK;
   PRBool externalDOMEvent = !!(aDOMEvent);
 
   // If we have a PresContext, make sure it doesn't die before
   // event dispatching is finished.
-  nsCOMPtr<nsPresContext> kungFuDeathGrip(aPresContext);
+  nsRefPtr<nsPresContext> kungFuDeathGrip(aPresContext);
   ChainItemPool pool;
   NS_ENSURE_TRUE(pool.GetPool(), NS_ERROR_OUT_OF_MEMORY);
 
   // Create the event target chain item for the event target.
   nsEventTargetChainItem* targetEtci =
     nsEventTargetChainItem::Create(pool.GetPool(), target);
   NS_ENSURE_TRUE(targetEtci, NS_ERROR_OUT_OF_MEMORY);
   if (!targetEtci->IsValid()) {
--- a/content/events/src/nsEventListenerManager.cpp
+++ b/content/events/src/nsEventListenerManager.cpp
@@ -1309,17 +1309,17 @@ nsEventListenerManager::DispatchEvent(ns
 
   // Do nothing if the element does not belong to a document
   if (!document) {
     return NS_OK;
   }
 
   // Obtain a presentation shell
   nsIPresShell *shell = document->GetPrimaryShell();
-  nsCOMPtr<nsPresContext> context;
+  nsRefPtr<nsPresContext> context;
   if (shell) {
     context = shell->GetPresContext();
   }
 
   nsEventStatus status = nsEventStatus_eIgnore;
   nsresult rv =
     nsEventDispatcher::DispatchDOMEvent(targetNode, nsnull, aEvent,
                                         context, &status);
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -179,30 +179,39 @@ static nsITimerCallback* gUserInteractio
 // Pixel scroll accumulation for synthetic line scrolls
 static nscoord gPixelScrollDeltaX = 0;
 static nscoord gPixelScrollDeltaY = 0;
 static PRUint32 gPixelScrollDeltaTimeout = 0;
 
 static nscoord
 GetScrollableLineHeight(nsIFrame* aTargetFrame);
 
+static inline PRBool
+IsMouseEventReal(nsEvent* aEvent)
+{
+  NS_ABORT_IF_FALSE(aEvent->eventStructType == NS_MOUSE_EVENT,
+                    "Not a mouse event");
+  // Return true if not synthesized.
+  return static_cast<nsMouseEvent*>(aEvent)->reason == nsMouseEvent::eReal;
+}
+
 #ifdef DEBUG_DOCSHELL_FOCUS
 static void
 PrintDocTree(nsIDocShellTreeItem* aParentItem, int aLevel)
 {
   for (PRInt32 i=0;i<aLevel;i++) printf("  ");
 
   PRInt32 childWebshellCount;
   aParentItem->GetChildCount(&childWebshellCount);
   nsCOMPtr<nsIDocShell> parentAsDocShell(do_QueryInterface(aParentItem));
   PRInt32 type;
   aParentItem->GetItemType(&type);
   nsCOMPtr<nsIPresShell> presShell;
   parentAsDocShell->GetPresShell(getter_AddRefs(presShell));
-  nsCOMPtr<nsPresContext> presContext;
+  nsRefPtr<nsPresContext> presContext;
   parentAsDocShell->GetPresContext(getter_AddRefs(presContext));
   nsCOMPtr<nsIContentViewer> cv;
   parentAsDocShell->GetContentViewer(getter_AddRefs(cv));
   nsCOMPtr<nsIDOMDocument> domDoc;
   if (cv)
     cv->GetDOMDocument(getter_AddRefs(domDoc));
   nsCOMPtr<nsIDocument> doc = do_QueryInterface(domDoc);
   nsCOMPtr<nsIDOMWindowInternal> domwin = doc ? doc->GetWindow() : nsnull;
@@ -504,17 +513,17 @@ nsMouseWheelTransaction::OnEvent(nsEvent
           OutOfTime(sMouseMoved, GetIgnoreMoveDelayTime())) {
         // Terminate the current mousewheel transaction if the mouse moved more
         // than ignoremovedelay milliseconds ago
         EndTransaction();
       }
       return;
     case NS_MOUSE_MOVE:
     case NS_DRAGDROP_OVER:
-      if (((nsMouseEvent*)aEvent)->reason == nsMouseEvent::eReal) {
+      if (IsMouseEventReal(aEvent)) {
         // If the cursor is moving to be outside the frame,
         // terminate the scrollwheel transaction.
         nsIntPoint pt = GetScreenPoint((nsGUIEvent*)aEvent);
         nsIntRect r = sTargetFrame->GetScreenRectExternal();
         if (!r.Contains(pt)) {
           EndTransaction();
           return;
         }
@@ -1026,17 +1035,17 @@ nsEventStateManager::PreHandleEvent(nsPr
     NS_ASSERTION(mCurrentTarget, "mCurrentTarget is null.  this should not happen.  see bug #13007");
     if (!mCurrentTarget) return NS_ERROR_NULL_POINTER;
   }
 
   // Do not take account NS_MOUSE_ENTER/EXIT so that loading a page
   // when user is not active doesn't change the state to active.
   if (NS_IS_TRUSTED_EVENT(aEvent) &&
       ((aEvent->eventStructType == NS_MOUSE_EVENT  &&
-        static_cast<nsMouseEvent*>(aEvent)->reason == nsMouseEvent::eReal &&
+        IsMouseEventReal(aEvent) &&
         aEvent->message != NS_MOUSE_ENTER &&
         aEvent->message != NS_MOUSE_EXIT) ||
        aEvent->eventStructType == NS_MOUSE_SCROLL_EVENT ||
        aEvent->eventStructType == NS_KEY_EVENT)) {
     if (gMouseOrKeyboardEventCounter == 0) {
       nsCOMPtr<nsIObserverService> obs =
         do_GetService("@mozilla.org/observer-service;1");
       if (obs) {
@@ -2814,23 +2823,25 @@ nsEventStateManager::PostHandleEvent(nsP
         // any of our own processing of a drag. Workaround for bug 43258.
         StopTrackingDragGesture();
       }
     }
     break;
   case NS_MOUSE_BUTTON_UP:
     {
       SetContentState(nsnull, NS_EVENT_STATE_ACTIVE);
-      if (!mCurrentTarget) {
-        nsIFrame* targ;
-        GetEventTarget(&targ);
-      }
-      if (mCurrentTarget) {
-        ret =
-          CheckForAndDispatchClick(presContext, (nsMouseEvent*)aEvent, aStatus);
+      if (IsMouseEventReal(aEvent)) {
+        if (!mCurrentTarget) {
+          nsIFrame* targ;
+          GetEventTarget(&targ);
+        }
+        if (mCurrentTarget) {
+          ret = CheckForAndDispatchClick(presContext, (nsMouseEvent*)aEvent,
+                                         aStatus);
+        }
       }
 
       nsIPresShell *shell = presContext->GetPresShell();
       if (shell) {
         nsCOMPtr<nsFrameSelection> frameSelection = shell->FrameSelection();
         frameSelection->SetMouseDownState(PR_FALSE);
       }
     }
@@ -3453,19 +3464,19 @@ nsEventStateManager::NotifyMouseOut(nsGU
   if (mLastMouseOverFrame) {
     // if the frame is associated with a subdocument,
     // tell the subdocument that we're moving out of it
     nsIFrameFrame* subdocFrame = do_QueryFrame(mLastMouseOverFrame.GetFrame());
     if (subdocFrame) {
       nsCOMPtr<nsIDocShell> docshell;
       subdocFrame->GetDocShell(getter_AddRefs(docshell));
       if (docshell) {
-        nsCOMPtr<nsPresContext> presContext;
+        nsRefPtr<nsPresContext> presContext;
         docshell->GetPresContext(getter_AddRefs(presContext));
-        
+
         if (presContext) {
           nsEventStateManager* kidESM =
             static_cast<nsEventStateManager*>(presContext->EventStateManager());
           // Not moving into any element in this subdocument
           kidESM->NotifyMouseOut(aEvent, nsnull);
         }
       }
     }
--- a/content/html/content/src/nsHTMLButtonElement.cpp
+++ b/content/html/content/src/nsHTMLButtonElement.cpp
@@ -212,17 +212,17 @@ nsHTMLButtonElement::Click()
   mHandlingClick = PR_TRUE;
   // Hold on to the document in case one of the events makes it die or
   // something...
   nsCOMPtr<nsIDocument> doc = GetCurrentDoc();
 
   if (doc) {
     nsIPresShell *shell = doc->GetPrimaryShell();
     if (shell) {
-      nsCOMPtr<nsPresContext> context = shell->GetPresContext();
+      nsRefPtr<nsPresContext> context = shell->GetPresContext();
       if (context) {
         // Click() is never called from native code, but it may be
         // called from chrome JS. Mark this event trusted if Click()
         // is called from chrome code.
         nsMouseEvent event(nsContentUtils::IsCallerChrome(),
                            NS_MOUSE_CLICK, nsnull,
                            nsMouseEvent::eReal);
         nsEventStatus status = nsEventStatus_eIgnore;
--- a/content/html/content/src/nsHTMLFormElement.cpp
+++ b/content/html/content/src/nsHTMLFormElement.cpp
@@ -387,17 +387,17 @@ nsHTMLFormElement::SetTarget(const nsASt
   return SetAttr(kNameSpaceID_None, nsGkAtoms::target, aValue, PR_TRUE);
 }
 
 NS_IMETHODIMP
 nsHTMLFormElement::Submit()
 {
   // Send the submit event
   nsresult rv = NS_OK;
-  nsCOMPtr<nsPresContext> presContext = GetPresContext();
+  nsRefPtr<nsPresContext> presContext = GetPresContext();
   if (mPendingSubmission) {
     // aha, we have a pending submission that was not flushed
     // (this happens when form.submit() is called twice)
     // we have to delete it and build a new one since values
     // might have changed inbetween (we emulate IE here, that's all)
     mPendingSubmission = nsnull;
   }
 
--- a/content/html/content/src/nsHTMLInputElement.cpp
+++ b/content/html/content/src/nsHTMLInputElement.cpp
@@ -1392,17 +1392,17 @@ nsHTMLInputElement::SetCheckedInternal(P
 void
 nsHTMLInputElement::FireOnChange()
 {
   //
   // Since the value is changing, send out an onchange event (bug 23571)
   //
   nsEventStatus status = nsEventStatus_eIgnore;
   nsEvent event(PR_TRUE, NS_FORM_CHANGE);
-  nsCOMPtr<nsPresContext> presContext = GetPresContext();
+  nsRefPtr<nsPresContext> presContext = GetPresContext();
   nsEventDispatcher::Dispatch(static_cast<nsIContent*>(this), presContext,
                               &event, nsnull, &status);
 }
 
 NS_IMETHODIMP
 nsHTMLInputElement::Blur()
 {
   return nsGenericHTMLElement::Blur();
@@ -1450,17 +1450,17 @@ nsHTMLInputElement::Select()
 
   FocusTristate state = FocusState();
   if (state == eUnfocusable) {
     return NS_OK;
   }
 
   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
 
-  nsCOMPtr<nsPresContext> presContext = GetPresContext();
+  nsRefPtr<nsPresContext> presContext = GetPresContext();
   if (state == eInactiveWindow) {
     if (fm)
       fm->SetFocus(this, nsIFocusManager::FLAG_NOSCROLL);
     SelectAll(presContext);
     return NS_OK;
   }
 
   if (DispatchSelectEvent(presContext) && fm) {
@@ -1531,19 +1531,19 @@ nsHTMLInputElement::Click()
       mType == NS_FORM_INPUT_SUBMIT   ||
       mType == NS_FORM_INPUT_IMAGE) {
 
     // Strong in case the event kills it
     nsCOMPtr<nsIDocument> doc = GetCurrentDoc();
     if (!doc) {
       return rv;
     }
-    
+
     nsCOMPtr<nsIPresShell> shell = doc->GetPrimaryShell();
-    nsCOMPtr<nsPresContext> context = nsnull;
+    nsRefPtr<nsPresContext> context = nsnull;
     if (shell) {
       context = shell->GetPresContext();
     }
 
     if (!context) {
       doc->FlushPendingNotifications(Flush_Frames);
       shell = doc->GetPrimaryShell();
       if (shell) {
@@ -1871,17 +1871,17 @@ nsHTMLInputElement::PostHandleEvent(nsEv
               !(static_cast<nsFocusEvent *>(aVisitor.mEvent))->fromRaise &&
               SelectTextFieldOnFocus()) {
             nsIDocument* document = GetCurrentDoc();
             if (document) {
               PRUint32 lastFocusMethod;
               fm->GetLastFocusMethod(document->GetWindow(), &lastFocusMethod);
               if (lastFocusMethod &
                   (nsIFocusManager::FLAG_BYKEY | nsIFocusManager::FLAG_BYMOVEFOCUS)) {
-                nsCOMPtr<nsPresContext> presContext = GetPresContext();
+                nsRefPtr<nsPresContext> presContext = GetPresContext();
                 if (DispatchSelectEvent(presContext)) {
                   SelectAll(presContext);
                 }
               }
             }
           }
           break;
         }
--- a/content/html/content/src/nsHTMLTextAreaElement.cpp
+++ b/content/html/content/src/nsHTMLTextAreaElement.cpp
@@ -308,17 +308,17 @@ nsHTMLTextAreaElement::Select()
 
   FocusTristate state = FocusState();
   if (state == eUnfocusable) {
     return NS_OK;
   }
 
   nsIFocusManager* fm = nsFocusManager::GetFocusManager();
 
-  nsCOMPtr<nsPresContext> presContext = GetPresContext();
+  nsRefPtr<nsPresContext> presContext = GetPresContext();
   if (state == eInactiveWindow) {
     if (fm)
       fm->SetFocus(this, nsIFocusManager::FLAG_NOSCROLL);
     SelectAll(presContext);
     return NS_OK;
   }
 
   nsEventStatus status = nsEventStatus_eIgnore;
--- a/content/smil/nsSMILAnimationFunction.cpp
+++ b/content/smil/nsSMILAnimationFunction.cpp
@@ -296,17 +296,19 @@ nsSMILAnimationFunction::ComposeResult(c
 
     if (IsToAnimation() && mIsFrozen) {
       mFrozenValue = result;
     }
   }
 
   // If additive animation isn't required or isn't supported, set the value.
   if (!IsAdditive() || NS_FAILED(aResult.SandwichAdd(result))) {
-    aResult = result;
+    aResult.Swap(result);
+    // Note: The old value of aResult is now in |result|, and it will get
+    // cleaned up when |result| goes out of scope, when this function returns.
   }
 }
 
 PRInt8
 nsSMILAnimationFunction::CompareTo(const nsSMILAnimationFunction* aOther) const
 {
   NS_ENSURE_TRUE(aOther, 0);
 
--- a/content/smil/nsSMILCSSProperty.cpp
+++ b/content/smil/nsSMILCSSProperty.cpp
@@ -91,30 +91,37 @@ nsSMILCSSProperty::nsSMILCSSProperty(nsC
   NS_ABORT_IF_FALSE(IsPropertyAnimatable(mPropID),
                     "Creating a nsSMILCSSProperty for a property "
                     "that's not supported for animation");
 }
 
 nsSMILValue
 nsSMILCSSProperty::GetBaseValue() const
 {
+  // To benefit from Return Value Optimization and avoid copy constructor calls
+  // due to our use of return-by-value, we must return the exact same object
+  // from ALL return points. This function must only return THIS variable:
+  nsSMILValue baseValue;
+
   // SPECIAL CASE: Shorthands
   if (nsCSSProps::IsShorthand(mPropID)) {
     // We can't look up the base (computed-style) value of shorthand
     // properties, because they aren't guaranteed to have a consistent computed
     // value.  However, that's not a problem, because it turns out the caller
     // isn't going to end up using the value we return anyway. Base values only
     // get used when there's interpolation or addition, and the shorthand
     // properties we know about don't support those operations. So, we can just
     // return a dummy value (initialized with the right type, so as not to
     // indicate failure).
-    return nsSMILValue(&nsSMILCSSValueType::sSingleton);
+    nsSMILValue tmpVal(&nsSMILCSSValueType::sSingleton);
+    baseValue.Swap(tmpVal);
+    return baseValue;
   }
 
-  // GENERAL CASE: Non-Shorthands  
+  // GENERAL CASE: Non-Shorthands
   // (1) Put empty string in override style for property mPropID
   // (saving old override style value, so we can set it again when we're done)
   nsCOMPtr<nsIDOMCSSStyleDeclaration> overrideStyle;
   mElement->GetSMILOverrideStyle(getter_AddRefs(overrideStyle));
   nsCOMPtr<nsICSSDeclaration> overrideDecl = do_QueryInterface(overrideStyle);
   nsAutoString cachedOverrideStyleVal;
   if (overrideDecl) {
     overrideDecl->GetPropertyValue(mPropID, cachedOverrideStyleVal);
@@ -129,18 +136,17 @@ nsSMILCSSProperty::GetBaseValue() const
   PRBool didGetComputedVal = GetCSSComputedValue(mElement, mPropID,
                                                  computedStyleVal);
 
   // (3) Put cached override style back (if it's non-empty)
   if (overrideDecl && !cachedOverrideStyleVal.IsEmpty()) {
     overrideDecl->SetPropertyValue(mPropID, cachedOverrideStyleVal);
   }
 
-  // (4) Create a nsSMILValue from the computed style
-  nsSMILValue baseValue;
+  // (4) Populate our nsSMILValue from the computed style
   if (didGetComputedVal) {
     nsSMILCSSValueType::ValueFromString(mPropID, mElement,
                                         computedStyleVal, baseValue);
   }
   return baseValue;
 }
 
 nsresult
--- a/content/smil/nsSMILValue.cpp
+++ b/content/smil/nsSMILValue.cpp
@@ -33,16 +33,17 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsSMILValue.h"
 #include "nsDebug.h"
+#include <string.h>
 
 //----------------------------------------------------------------------
 // Public methods
 
 nsSMILValue::nsSMILValue(const nsISMILType* aType)
   : mType(&nsSMILNullType::sSingleton)
 {
   if (!aType) {
@@ -79,16 +80,29 @@ PRBool
 nsSMILValue::operator==(const nsSMILValue& aVal) const
 {
   if (&aVal == this)
     return PR_TRUE;
 
   return mType == aVal.mType && mType->IsEqual(*this, aVal);
 }
 
+void
+nsSMILValue::Swap(nsSMILValue& aOther)
+{
+  nsSMILValue tmp;
+  memcpy(&tmp,    &aOther, sizeof(nsSMILValue));  // tmp    = aOther
+  memcpy(&aOther, this,    sizeof(nsSMILValue));  // aOther = this
+  memcpy(this,    &tmp,    sizeof(nsSMILValue));  // this   = tmp
+
+  // |tmp| is about to die -- we need to clear its mType, so that its
+  // destructor doesn't muck with the data we just transferred out of it.
+  tmp.mType = &nsSMILNullType::sSingleton;
+}
+
 nsresult
 nsSMILValue::Add(const nsSMILValue& aValueToAdd, PRUint32 aCount)
 {
   if (aValueToAdd.mType != mType) {
     NS_ERROR("Trying to add incompatible types");
     return NS_ERROR_FAILURE;
   }
 
--- a/content/smil/nsSMILValue.h
+++ b/content/smil/nsSMILValue.h
@@ -63,16 +63,19 @@ public:
     return !(*this == aVal);
   }
 
   PRBool IsNull() const
   {
     return (mType == &nsSMILNullType::sSingleton);
   }
 
+  // Swaps the member data (mU & mPtr) of |this| with |aOther|
+  void     Swap(nsSMILValue& aOther);
+
   nsresult Add(const nsSMILValue& aValueToAdd, PRUint32 aCount = 1);
   nsresult SandwichAdd(const nsSMILValue& aValueToAdd);
   nsresult ComputeDistance(const nsSMILValue& aTo, double& aDistance) const;
   nsresult Interpolate(const nsSMILValue& aEndVal,
                        double aUnitDistance,
                        nsSMILValue& aResult) const;
 
   union {
--- a/content/svg/content/src/nsSVGAngle.cpp
+++ b/content/svg/content/src/nsSVGAngle.cpp
@@ -448,17 +448,17 @@ nsSVGAngle::SMILOrient::ValueFromString(
     nsresult rv = GetValueFromString(aStr, &value, &unitType);
     if (NS_FAILED(rv)) {
       return rv;
     }
     val.mU.mOrient.mAngle = value;
     val.mU.mOrient.mUnit = unitType;
     val.mU.mOrient.mOrientType = nsIDOMSVGMarkerElement::SVG_MARKER_ORIENT_ANGLE;
   }
-  aValue = val;
+  aValue.Swap(val);
   aCanCache = PR_TRUE;
 
   return NS_OK;
 }
 
 nsSMILValue
 nsSVGAngle::SMILOrient::GetBaseValue() const
 {
--- a/content/svg/content/src/nsSVGRectElement.cpp
+++ b/content/svg/content/src/nsSVGRectElement.cpp
@@ -170,19 +170,22 @@ void
 nsSVGRectElement::ConstructPath(gfxContext *aCtx)
 {
   float x, y, width, height, rx, ry;
 
   GetAnimatedLengthValues(&x, &y, &width, &height, &rx, &ry, nsnull);
 
   /* In a perfect world, this would be handled by the DOM, and
      return a DOM exception. */
-  if (width <= 0 || height <= 0 || ry < 0 || rx < 0)
+  if (width <= 0 || height <= 0)
     return;
 
+  rx = NS_MAX(rx, 0.0f);
+  ry = NS_MAX(ry, 0.0f);
+
   /* optimize the no rounded corners case */
   if (rx == 0 && ry == 0) {
     aCtx->Rectangle(gfxRect(x, y, width, height));
     return;
   }
 
   /* If either the 'rx' or the 'ry' attribute isn't set in the markup, then we
      have to set it to the value of the other. */
--- a/content/svg/content/src/nsSVGTransformSMILAttr.cpp
+++ b/content/svg/content/src/nsSVGTransformSMILAttr.cpp
@@ -69,30 +69,34 @@ nsSVGTransformSMILAttr::ValueFromString(
   ParseValue(aStr, transformType, aValue);
   aCanCache = PR_TRUE;
   return aValue.IsNull() ? NS_ERROR_FAILURE : NS_OK;
 }
 
 nsSMILValue
 nsSVGTransformSMILAttr::GetBaseValue() const
 {
+  // To benefit from Return Value Optimization and avoid copy constructor calls
+  // due to our use of return-by-value, we must return the exact same object
+  // from ALL return points. This function must only return THIS variable:
   nsSMILValue val(&nsSVGTransformSMILType::sSingleton);
-  if (val.IsNull())
-    return val; // Initialization failed
 
   nsIDOMSVGTransformList *list = mVal->mBaseVal.get();
 
   PRUint32 numItems = 0;
   list->GetNumberOfItems(&numItems);
   for (PRUint32 i = 0; i < numItems; i++) {
     nsCOMPtr<nsIDOMSVGTransform> transform;
     nsresult rv = list->GetItem(i, getter_AddRefs(transform));
     if (NS_SUCCEEDED(rv) && transform) {
       rv = AppendSVGTransformToSMILValue(transform.get(), val);
-      NS_ENSURE_SUCCESS(rv, nsSMILValue());
+      if (NS_FAILED(rv)) {   // Appending to |val| failed (OOM?)
+        val = nsSMILValue();
+        break;
+      }
     }
   }
 
   return val;
 }
 
 void
 nsSVGTransformSMILAttr::ClearAnimValue()
@@ -181,18 +185,18 @@ nsSVGTransformSMILAttr::ParseValue(const
   }
 
   nsSMILValue val(&nsSVGTransformSMILType::sSingleton);
   nsSVGSMILTransform transform(transformType, params);
   if (NS_FAILED(nsSVGTransformSMILType::AppendTransform(transform, val))) {
     return;
   }
 
-  // Success! Initialize our outparam with parsed value.
-  aResult = val;
+  // Success! Populate our outparam with parsed value.
+  aResult.Swap(val);
 }
 
 inline PRBool
 IsSpace(const char c)
 {
   return (c == 0x9 || c == 0xA || c == 0xD || c == 0x20);
 }
 
--- a/content/svg/content/src/nsSVGViewBox.cpp
+++ b/content/svg/content/src/nsSVGViewBox.cpp
@@ -279,35 +279,28 @@ nsSVGViewBox::SMILViewBox
                               PRBool& aCanCache) const
 {
   nsSVGViewBoxRect viewBox;
   nsresult res = ToSVGViewBoxRect(aStr, &viewBox);
   if (NS_FAILED(res)) {
     return res;
   }
   nsSMILValue val(&SVGViewBoxSMILType::sSingleton);
-  // Check for OOM when the nsSMILValue ctor called SVGViewBoxSMILType::Init:
-  if (val.IsNull()) {
-    return NS_ERROR_OUT_OF_MEMORY;
-  }
   *static_cast<nsSVGViewBoxRect*>(val.mU.mPtr) = viewBox;
-  aValue = val;
+  aValue.Swap(val);
   aCanCache = PR_TRUE;
   
   return NS_OK;
 }
 
 nsSMILValue
 nsSVGViewBox::SMILViewBox::GetBaseValue() const
 {
   nsSMILValue val(&SVGViewBoxSMILType::sSingleton);
-  // Check for OOM when the nsSMILValue ctor called SVGViewBoxSMILType::Init:
-  if (!val.IsNull()) {
-    *static_cast<nsSVGViewBoxRect*>(val.mU.mPtr) = mVal->mBaseVal;
-  }
+  *static_cast<nsSVGViewBoxRect*>(val.mU.mPtr) = mVal->mBaseVal;
   return val;
 }
 
 void
 nsSVGViewBox::SMILViewBox::ClearAnimValue()
 {
   if (mVal->mAnimVal) {
     mVal->mAnimVal = nsnull;
--- a/content/xbl/src/nsBindingManager.cpp
+++ b/content/xbl/src/nsBindingManager.cpp
@@ -1325,16 +1325,49 @@ EnumRuleProcessors(nsISupports *aKey, ns
       if (!set->IsInitialized() && !set->Init(16))
         return PL_DHASH_STOP;
       set->PutEntry(ruleProc);
     }
   }
   return PL_DHASH_NEXT;
 }
 
+struct WalkAllRulesData {
+  nsIStyleRuleProcessor::EnumFunc mFunc;
+  RuleProcessorData* mData;
+};
+
+static PLDHashOperator
+EnumWalkAllRules(nsVoidPtrHashKey *aKey, void* aClosure)
+{
+  nsIStyleRuleProcessor *ruleProcessor =
+    static_cast<nsIStyleRuleProcessor*>(const_cast<void*>(aKey->GetKey()));
+  WalkAllRulesData *data = static_cast<WalkAllRulesData*>(aClosure);
+
+  (*(data->mFunc))(ruleProcessor, data->mData);
+
+  return PL_DHASH_NEXT;
+}
+
+void
+nsBindingManager::WalkAllRules(nsIStyleRuleProcessor::EnumFunc aFunc,
+                               RuleProcessorData* aData)
+{
+  if (!mBindingTable.IsInitialized())
+    return;
+
+  RuleProcessorSet set;
+  mBindingTable.EnumerateRead(EnumRuleProcessors, &set);
+  if (!set.IsInitialized())
+    return;
+
+  WalkAllRulesData data = { aFunc, aData };
+  set.EnumerateEntries(EnumWalkAllRules, &data);
+}
+
 struct MediumFeaturesChangedData {
   nsPresContext *mPresContext;
   PRBool *mRulesChanged;
 };
 
 static PLDHashOperator
 EnumMediumFeaturesChanged(nsVoidPtrHashKey *aKey, void* aClosure)
 {
--- a/content/xbl/src/nsBindingManager.h
+++ b/content/xbl/src/nsBindingManager.h
@@ -199,16 +199,19 @@ public:
   void FlushSkinBindings();
 
   nsresult GetBindingImplementation(nsIContent* aContent, REFNSIID aIID, void** aResult);
 
   // Style rule methods
   nsresult WalkRules(nsIStyleRuleProcessor::EnumFunc aFunc,
                      RuleProcessorData* aData,
                      PRBool* aCutOffInheritance);
+
+  void WalkAllRules(nsIStyleRuleProcessor::EnumFunc aFunc,
+                    RuleProcessorData* aData);
   /**
    * Do any processing that needs to happen as a result of a change in
    * the characteristics of the medium, and return whether this rule
    * processor's rules have changed (e.g., because of media queries).
    */
   nsresult MediumFeaturesChanged(nsPresContext* aPresContext,
                                  PRBool* aRulesChanged);
 
--- a/content/xul/content/src/nsXULElement.cpp
+++ b/content/xul/content/src/nsXULElement.cpp
@@ -2059,17 +2059,17 @@ nsXULElement::Click()
     if (BoolAttrIsTrue(nsGkAtoms::disabled))
         return NS_OK;
 
     nsCOMPtr<nsIDocument> doc = GetCurrentDoc(); // Strong just in case
     if (doc) {
         nsCOMPtr<nsIPresShell> shell = doc->GetPrimaryShell();
         if (shell) {
             // strong ref to PresContext so events don't destroy it
-            nsCOMPtr<nsPresContext> context = shell->GetPresContext();
+            nsRefPtr<nsPresContext> context = shell->GetPresContext();
 
             PRBool isCallerChrome = nsContentUtils::IsCallerChrome();
 
             nsMouseEvent eventDown(isCallerChrome, NS_MOUSE_BUTTON_DOWN,
                                    nsnull, nsMouseEvent::eReal);
             nsMouseEvent eventUp(isCallerChrome, NS_MOUSE_BUTTON_UP,
                                  nsnull, nsMouseEvent::eReal);
             nsMouseEvent eventClick(isCallerChrome, NS_MOUSE_CLICK, nsnull,
--- a/content/xul/document/src/nsXULCommandDispatcher.cpp
+++ b/content/xul/document/src/nsXULCommandDispatcher.cpp
@@ -432,17 +432,17 @@ nsXULCommandDispatcher::UpdateCommands(c
               aeventnameC.get()));
     }
 #endif
 
     nsCOMPtr<nsIPresShell> shell = document->GetPrimaryShell();
     if (shell) {
 
       // Retrieve the context in which our DOM event will fire.
-      nsCOMPtr<nsPresContext> context = shell->GetPresContext();
+      nsRefPtr<nsPresContext> context = shell->GetPresContext();
 
       // Handle the DOM event
       nsEventStatus status = nsEventStatus_eIgnore;
 
       nsEvent event(PR_TRUE, NS_XUL_COMMAND_UPDATE);
 
       nsEventDispatcher::Dispatch(content, context, &event, nsnull, &status);
     }
--- a/content/xul/document/src/nsXULDocument.cpp
+++ b/content/xul/document/src/nsXULDocument.cpp
@@ -943,17 +943,17 @@ nsXULDocument::ExecuteOnBroadcastHandler
 
         // This is the right <observes> element. Execute the
         // |onbroadcast| event handler
         nsEvent event(PR_TRUE, NS_XUL_BROADCAST);
 
         nsCOMPtr<nsIPresShell> shell = GetPrimaryShell();
         if (shell) {
 
-            nsCOMPtr<nsPresContext> aPresContext = shell->GetPresContext();
+            nsRefPtr<nsPresContext> aPresContext = shell->GetPresContext();
 
             // Handle the DOM event
             nsEventStatus status = nsEventStatus_eIgnore;
             nsEventDispatcher::Dispatch(child, aPresContext, &event, nsnull,
                                         &status);
         }
     }
 
--- a/db/mork/src/morkRow.cpp
+++ b/db/mork/src/morkRow.cpp
@@ -266,16 +266,18 @@ morkRow::AcquireRowObject(morkEnv* ev, m
   morkRowObject* ro = mRow_Object;
   if ( ro ) // need new row object?
     ro->AddRef();
   else
   {
     nsIMdbHeap* heap = ioStore->mPort_Heap;
     ro = new(*heap, ev)
       morkRowObject(ev, morkUsage::kHeap, heap, this, ioStore);
+    if ( !ro )
+      return (morkRowObject*) 0;
 
     morkRowObject::SlotWeakRowObject(ro, ev, &mRow_Object);
     ro->AddRef();
   }
   return ro;
 }
 
 nsIMdbRow*
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -1601,17 +1601,17 @@ nsDocShell::GetPresContext(nsPresContext
 NS_IMETHODIMP
 nsDocShell::GetPresShell(nsIPresShell ** aPresShell)
 {
     nsresult rv = NS_OK;
 
     NS_ENSURE_ARG_POINTER(aPresShell);
     *aPresShell = nsnull;
 
-    nsCOMPtr<nsPresContext> presContext;
+    nsRefPtr<nsPresContext> presContext;
     (void) GetPresContext(getter_AddRefs(presContext));
 
     if (presContext) {
         NS_IF_ADDREF(*aPresShell = presContext->GetPresShell());
     }
 
     return rv;
 }
@@ -1619,17 +1619,17 @@ nsDocShell::GetPresShell(nsIPresShell **
 NS_IMETHODIMP
 nsDocShell::GetEldestPresShell(nsIPresShell** aPresShell)
 {
     nsresult rv = NS_OK;
 
     NS_ENSURE_ARG_POINTER(aPresShell);
     *aPresShell = nsnull;
 
-    nsCOMPtr<nsPresContext> presContext;
+    nsRefPtr<nsPresContext> presContext;
     (void) GetEldestPresContext(getter_AddRefs(presContext));
 
     if (presContext) {
         NS_IF_ADDREF(*aPresShell = presContext->GetPresShell());
     }
 
     return rv;
 }
@@ -2809,17 +2809,17 @@ PrintDocTree(nsIDocShellTreeItem * aPare
 
   PRInt32 childWebshellCount;
   aParentNode->GetChildCount(&childWebshellCount);
   nsCOMPtr<nsIDocShell> parentAsDocShell(do_QueryInterface(aParentNode));
   PRInt32 type;
   aParentNode->GetItemType(&type);
   nsCOMPtr<nsIPresShell> presShell;
   parentAsDocShell->GetPresShell(getter_AddRefs(presShell));
-  nsCOMPtr<nsPresContext> presContext;
+  nsRefPtr<nsPresContext> presContext;
   parentAsDocShell->GetPresContext(getter_AddRefs(presContext));
   nsIDocument *doc = presShell->GetDocument();
 
   nsCOMPtr<nsIDOMWindowInternal> domwin(doc->GetWindow());
 
   nsCOMPtr<nsIWidget> widget;
   nsIViewManager* vm = presShell->GetViewManager();
   if (vm) {
--- a/docshell/test/browser/Makefile.in
+++ b/docshell/test/browser/Makefile.in
@@ -44,17 +44,20 @@ include $(DEPTH)/config/autoconf.mk
 include $(topsrcdir)/config/rules.mk
 
 _BROWSER_TEST_FILES =	\
 		browser_bug349769.js \
 		browser_bug388121-1.js \
 		browser_bug388121-2.js \
 		browser_bug441169.js \
 		browser_bug503832.js \
+		browser_bug550565.js \
 		file_bug503832.html \
+		file_bug550565_popup.html \
+		file_bug550565_favicon.ico \
 		$(NULL)
 
 # the tests below use FUEL, which is a Firefox-specific feature
 ifdef MOZ_PHOENIX
 _BROWSER_TEST_FILES +=	\
 		browser_bug92473.js \
 		test-form_sjis.html \
 		browser_bug134911.js \
new file mode 100644
--- /dev/null
+++ b/docshell/test/browser/browser_bug550565.js
@@ -0,0 +1,19 @@
+function test() {
+  waitForExplicitFinish();
+
+  let testPath = "chrome://mochikit/content/browser/docshell/test/browser/";
+
+  let tab = gBrowser.addTab(testPath + "file_bug550565_popup.html");
+
+  tab.linkedBrowser.addEventListener('DOMContentLoaded', function() {
+    let expectedIcon = testPath + "file_bug550565_favicon.ico";
+
+    is(gBrowser.getIcon(tab), expectedIcon, "Correct icon before pushState.");
+    tab.linkedBrowser.contentWindow.history.pushState("page2", "page2", "page2");
+    is(gBrowser.getIcon(tab), expectedIcon, "Correct icon after pushState.");
+
+    gBrowser.removeTab(tab);
+
+    finish();
+  }, true);
+}
new file mode 100644
index 0000000000000000000000000000000000000000..d44438903b751f4732f5365783eb0229b0501f9a
GIT binary patch
literal 1406
zc${sNu}d656o=n};bd8o)56N#Jtc-%Pi19LTfxTKZb)No6UbH8fq*bwiX@OCjeo&a
zDdN=H#L7bO4x$jyCB@74W-i8r?B3hk_q&<*`*z;kiWHpvzNF*jBasEZpA#kxh(c!b
zkA?g>iii0yePlSyUv_dc8jWQ1Z6w!UKg!I^jLgo?N>x=dH#a8>3k$NixG2lZ%d)z<
zD!aS8vc0`68yg$4wzek2S1LO@DsSafbQ0yu>32E3yp%VeKI7mBPXr?7)NyfW4$YaS
zd5A~%+<0`4?ln&f=m9;D1oWV(ltlE19?>I0L|1Yp*O;x+>4`v?rrDm0gTcYzU~n)b
zBp4hF4h9E<gCSwU;9zhtI2arZ2^|IpgM-1r;9ziy28V;g8HZ|qyhLJWAR?jpkzw(e
zdyG6qJuGP%_|bFYVezn}Wr4%P;o<PXG|fu|hljz#;9;<(^Kf_=JPZ*p<(ifdpM1vY
z^14J6oaLIA8t(v8z%*bGU<!B#ehd@|!D?x4NAgC;Kj0tmw-yEbgXu5?7=mhQTkeEU
z?nY+qjW9&~B5V<kh+k^0aj*svj%XY_SZX(uA}kS>2t>p%Z2?#!6C;BnLWIS(MKl(A
z5@Ct99*M<vgLNUKt)wt03<`t7pfIHE1Ve;DVNe(%3~7tOpfD&53WLHxX#yPvg+XCZ
z02Kd7F=e7M$b0J%eN^+X+BU|^l6;W8y*)WNIFQ4`LpeG+l9Q7YIX*s?v$HcfKR=g?
ziwn8Bx{{ll8@ao?lk1-<@87-Se{BC~O&_tkDYLqks+9jZdPPy~Pwz!~n{79!=kH$}
z<GSmLr_<Msl#^avbPO2hT+6EM$RF49<MriRDSK7X4Z4C$(Ttb&wO_ZL%_!=6ywx`4
zgyE!JUClFXORIXNvkFB!=(@IFPD&fltZ*GPJq*jH8?3a&i}`+QhPP$YHpR1|=~tQH
w$7Vff2Tfh~eiKjn_2%S0`}?qUxPHyMZW^-w&wKL0`*KK);S<IY*Xw!iFYO$~&;S4c
new file mode 100644
--- /dev/null
+++ b/docshell/test/browser/file_bug550565_popup.html
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Test file for bug 550565.</title>
+
+  <!--Set a favicon; that's the whole point of this file.-->
+  <link rel="icon" href="chrome://mochikit/content/browser/docshell/test/browser/file_bug550565_favicon.ico" />
+</head>
+<body>
+  Test file for bug 550565.
+</body>
+</html>
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -103,17 +103,17 @@ nsDOMWindowUtils::~nsDOMWindowUtils()
 nsPresContext*
 nsDOMWindowUtils::GetPresContext()
 {
   if (!mWindow)
     return nsnull;
   nsIDocShell *docShell = mWindow->GetDocShell();
   if (!docShell)
     return nsnull;
-  nsCOMPtr<nsPresContext> presContext;
+  nsRefPtr<nsPresContext> presContext;
   docShell->GetPresContext(getter_AddRefs(presContext));
   return presContext;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetImageAnimationMode(PRUint16 *aMode)
 {
   NS_ENSURE_ARG_POINTER(aMode);
--- a/dom/base/nsFocusManager.cpp
+++ b/dom/base/nsFocusManager.cpp
@@ -1666,17 +1666,17 @@ public:
     nsFocusEvent event(PR_TRUE, mType);
     event.flags |= NS_EVENT_FLAG_CANT_BUBBLE;
     event.fromRaise = mWindowRaised;
     return nsEventDispatcher::Dispatch(mTarget, mContext, &event);
   }
 
   nsCOMPtr<nsISupports>   mTarget;
   PRUint32                mType;
-  nsCOMPtr<nsPresContext> mContext;
+  nsRefPtr<nsPresContext> mContext;
   PRBool                  mWindowRaised;
 };
 
 void
 nsFocusManager::SendFocusOrBlurEvent(PRUint32 aType,
                                      nsIPresShell* aPresShell,
                                      nsIDocument* aDocument,
                                      nsISupports* aTarget,
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -2460,18 +2460,19 @@ nsGlobalWindow::OnFinalize(PRUint32 aLan
 void
 nsGlobalWindow::SetScriptsEnabled(PRBool aEnabled, PRBool aFireTimeouts)
 {
   FORWARD_TO_INNER_VOID(SetScriptsEnabled, (aEnabled, aFireTimeouts));
 
   if (aEnabled && aFireTimeouts) {
     // Scripts are enabled (again?) on this context, run timeouts that
     // fired on this context while scripts were disabled.
-
-    RunTimeout(nsnull);
+    nsCOMPtr<nsIRunnable> event =
+      NS_NEW_RUNNABLE_METHOD(nsGlobalWindow, this, RunTimeout);
+    NS_DispatchToCurrentThread(event);
   }
 }
 
 nsresult
 nsGlobalWindow::SetArguments(nsIArray *aArguments, nsIPrincipal *aOrigin)
 {
   FORWARD_TO_OUTER(SetArguments, (aArguments, aOrigin),
                    NS_ERROR_NOT_INITIALIZED);
@@ -3207,83 +3208,83 @@ nsGlobalWindow::SetName(const nsAString&
 }
 
 // Helper functions used by many methods below.
 PRInt32
 nsGlobalWindow::DevToCSSIntPixels(PRInt32 px)
 {
   if (!mDocShell)
     return px; // assume 1:1
-    
-  nsCOMPtr<nsPresContext> presContext;
+
+  nsRefPtr<nsPresContext> presContext;
   mDocShell->GetPresContext(getter_AddRefs(presContext));
   if (!presContext)
     return px;
 
   return presContext->DevPixelsToIntCSSPixels(px);
 }
 
 PRInt32
 nsGlobalWindow::CSSToDevIntPixels(PRInt32 px)
 {
   if (!mDocShell)
     return px; // assume 1:1
-    
-  nsCOMPtr<nsPresContext> presContext;
+
+  nsRefPtr<nsPresContext> presContext;
   mDocShell->GetPresContext(getter_AddRefs(presContext));
   if (!presContext)
     return px;
 
   return presContext->CSSPixelsToDevPixels(px);
 }
 
 nsIntSize
 nsGlobalWindow::DevToCSSIntPixels(nsIntSize px)
 {
   if (!mDocShell)
     return px; // assume 1:1
-    
-  nsCOMPtr<nsPresContext> presContext;
+
+  nsRefPtr<nsPresContext> presContext;
   mDocShell->GetPresContext(getter_AddRefs(presContext));
   if (!presContext)
     return px;
-  
+
   return nsIntSize(
       presContext->DevPixelsToIntCSSPixels(px.width),
       presContext->DevPixelsToIntCSSPixels(px.height));
 }
 
 nsIntSize
 nsGlobalWindow::CSSToDevIntPixels(nsIntSize px)
 {
   if (!mDocShell)
     return px; // assume 1:1
-    
-  nsCOMPtr<nsPresContext> presContext;
+
+  nsRefPtr<nsPresContext> presContext;
   mDocShell->GetPresContext(getter_AddRefs(presContext));
   if (!presContext)
     return px;
-  
+
   return nsIntSize(
     presContext->CSSPixelsToDevPixels(px.width),
     presContext->CSSPixelsToDevPixels(px.height));
 }
 
 
 NS_IMETHODIMP
 nsGlobalWindow::GetInnerWidth(PRInt32* aInnerWidth)
 {
   FORWARD_TO_OUTER(GetInnerWidth, (aInnerWidth), NS_ERROR_NOT_INITIALIZED);
 
   NS_ENSURE_STATE(mDocShell);
 
   EnsureSizeUpToDate();
 
   nsCOMPtr<nsIBaseWindow> docShellWin(do_QueryInterface(mDocShell));
-  nsCOMPtr<nsPresContext> presContext;
+  nsRefPtr<nsPresContext> presContext;
   mDocShell->GetPresContext(getter_AddRefs(presContext));
 
   if (docShellWin && presContext) {
     PRInt32 width, notused;
     docShellWin->GetSize(&width, &notused);
     *aInnerWidth = nsPresContext::
       AppUnitsToIntCSSPixels(presContext->DevPixelsToAppUnits(width));
   } else {
@@ -3336,17 +3337,17 @@ nsGlobalWindow::GetInnerHeight(PRInt32* 
 {
   FORWARD_TO_OUTER(GetInnerHeight, (aInnerHeight), NS_ERROR_NOT_INITIALIZED);
 
   NS_ENSURE_STATE(mDocShell);
 
   EnsureSizeUpToDate();
 
   nsCOMPtr<nsIBaseWindow> docShellWin(do_QueryInterface(mDocShell));
-  nsCOMPtr<nsPresContext> presContext;
+  nsRefPtr<nsPresContext> presContext;
   mDocShell->GetPresContext(getter_AddRefs(presContext));
 
   if (docShellWin && presContext) {
     PRInt32 height, notused;
     docShellWin->GetSize(&notused, &height);
     *aInnerHeight = nsPresContext::
       AppUnitsToIntCSSPixels(presContext->DevPixelsToAppUnits(height));
   } else {
@@ -6584,17 +6585,17 @@ nsGlobalWindow::DispatchEvent(nsIDOMEven
   FORWARD_TO_INNER(DispatchEvent, (aEvent, _retval), NS_OK);
 
   if (!mDoc) {
     return NS_ERROR_FAILURE;
   }
 
   // Obtain a presentation shell
   nsIPresShell *shell = mDoc->GetPrimaryShell();
-  nsCOMPtr<nsPresContext> presContext;
+  nsRefPtr<nsPresContext> presContext;
   if (shell) {
     // Retrieve the context
     presContext = shell->GetPresContext();
   }
 
   nsEventStatus status = nsEventStatus_eIgnore;
   nsresult rv =
     nsEventDispatcher::DispatchDOMEvent(GetOuterWindow(), nsnull, aEvent,
@@ -7076,17 +7077,17 @@ nsGlobalWindow::DispatchSyncPopState()
     JSContext *cx = (JSContext*) scx->GetNativeContext();
 
     // If our json call triggers a JS-to-C++ call, we want that call to use cx
     // as the context.  So we push cx onto the context stack.
     nsCxPusher cxPusher;
 
     jsval jsStateObj = JSVAL_NULL;
     // Root the container which will hold our decoded state object.
-    nsAutoGCRoot(&jsStateObj, &rv);
+    nsAutoGCRoot root(&jsStateObj, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Deserialize the state object into an nsIVariant.
     nsCOMPtr<nsIJSON> json = do_GetService("@mozilla.org/dom/json;1");
     NS_ENSURE_TRUE(cxPusher.Push(cx), NS_ERROR_FAILURE);
     rv = json->DecodeToJSVal(stateObjJSON, cx, &jsStateObj);
     NS_ENSURE_SUCCESS(rv, rv);
     cxPusher.Pop();
@@ -7094,17 +7095,17 @@ nsGlobalWindow::DispatchSyncPopState()
     nsCOMPtr<nsIXPConnect> xpconnect = do_GetService(nsIXPConnect::GetCID());
     NS_ENSURE_TRUE(xpconnect, NS_ERROR_FAILURE);
     rv = xpconnect->JSValToVariant(cx, &jsStateObj, getter_AddRefs(stateObj));
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   // Obtain a presentation shell for use in creating a popstate event.
   nsIPresShell *shell = mDoc->GetPrimaryShell();
-  nsCOMPtr<nsPresContext> presContext;
+  nsRefPtr<nsPresContext> presContext;
   if (shell) {
     presContext = shell->GetPresContext();
   }
 
   // Create a new popstate event
   nsCOMPtr<nsIDOMEvent> domEvent;
   rv = nsEventDispatcher::CreateEvent(presContext, nsnull,
                                       NS_LITERAL_STRING("popstateevent"),
@@ -9350,17 +9351,17 @@ nsGlobalChromeWindow::SetCursor(const ns
         cursor = NS_STYLE_CURSOR_GRABBING;
       else if (cursorString.Equals("spinning"))
         cursor = NS_STYLE_CURSOR_SPINNING;
       else
         return NS_OK;
     }
   }
 
-  nsCOMPtr<nsPresContext> presContext;
+  nsRefPtr<nsPresContext> presContext;
   if (mDocShell) {
     mDocShell->GetPresContext(getter_AddRefs(presContext));
   }
 
   if (presContext) {
     // Need root widget.
     nsCOMPtr<nsIPresShell> presShell;
     mDocShell->GetPresShell(getter_AddRefs(presShell));
--- a/dom/base/nsGlobalWindow.h
+++ b/dom/base/nsGlobalWindow.h
@@ -557,16 +557,17 @@ protected:
   nsresult ClearTimeoutOrInterval(PRInt32 aTimerID);
 
   // JS specific timeout functions (JS args grabbed from context).
   nsresult SetTimeoutOrInterval(PRBool aIsInterval, PRInt32* aReturn);
   nsresult ClearTimeoutOrInterval();
 
   // The timeout implementation functions.
   void RunTimeout(nsTimeout *aTimeout);
+  void RunTimeout() { RunTimeout(nsnull); }
 
   void ClearAllTimeouts();
   // Insert aTimeout into the list, before all timeouts that would
   // fire after it, but no earlier than mTimeoutInsertionPoint, if any.
   void InsertTimeoutIntoList(nsTimeout *aTimeout);
   static void TimerCallback(nsITimer *aTimer, void *aClosure);
 
   // Helper Functions
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -391,17 +391,17 @@ PRBool
 NS_HandleScriptError(nsIScriptGlobalObject *aScriptGlobal,
                      nsScriptErrorEvent *aErrorEvent,
                      nsEventStatus *aStatus)
 {
   PRBool called = PR_FALSE;
   nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(aScriptGlobal));
   nsIDocShell *docShell = win ? win->GetDocShell() : nsnull;
   if (docShell) {
-    nsCOMPtr<nsPresContext> presContext;
+    nsRefPtr<nsPresContext> presContext;
     docShell->GetPresContext(getter_AddRefs(presContext));
 
     static PRInt32 errorDepth; // Recursion prevention
     ++errorDepth;
 
     if (presContext && errorDepth < 2) {
       // Dispatch() must be synchronous for the recursion block
       // (errorDepth) to work.
@@ -434,17 +434,17 @@ public:
     if (mDispatchEvent) {
       nsCOMPtr<nsPIDOMWindow> win(do_QueryInterface(mScriptGlobal));
       nsIDocShell* docShell = win ? win->GetDocShell() : nsnull;
       if (docShell &&
           !JSREPORT_IS_WARNING(mFlags) &&
           !sHandlingScriptError) {
         sHandlingScriptError = PR_TRUE; // Recursion prevention
 
-        nsCOMPtr<nsPresContext> presContext;
+        nsRefPtr<nsPresContext> presContext;
         docShell->GetPresContext(getter_AddRefs(presContext));
 
         if (presContext) {
           nsScriptErrorEvent errorevent(PR_TRUE, NS_LOAD_ERROR);
 
           errorevent.fileName = mFileName.get();
 
           nsCOMPtr<nsIScriptObjectPrincipal> sop(do_QueryInterface(win));
--- a/dom/plugins/Makefile.in
+++ b/dom/plugins/Makefile.in
@@ -58,16 +58,18 @@ EXPORTS_NAMESPACES = mozilla mozilla/plu
 EXPORTS_mozilla/plugins = \
   BrowserStreamChild.h \
   BrowserStreamParent.h \
   ChildAsyncCall.h \
   ChildTimer.h \
   NPEventOSX.h \
   NPEventWindows.h \
   NPEventX11.h \
+  PluginIdentifierChild.h \
+  PluginIdentifierParent.h \
   PluginInstanceChild.h \
   PluginInstanceParent.h \
   PluginMessageUtils.h \
   PluginModuleChild.h \
   PluginModuleParent.h \
   PluginProcessParent.h \
   PluginScriptableObjectChild.h \
   PluginScriptableObjectParent.h \
--- a/dom/plugins/NPEventOSX.h
+++ b/dom/plugins/NPEventOSX.h
@@ -58,20 +58,59 @@ namespace IPC {
 
 template <>
 struct ParamTraits<mozilla::plugins::NPRemoteEvent>
 {
     typedef mozilla::plugins::NPRemoteEvent paramType;
 
     static void Write(Message* aMsg, const paramType& aParam)
     {
+        // Make a non-const copy of aParam so that we can muck with
+        // its insides for transport
+        paramType paramCopy;
+
+        paramCopy.event = aParam.event;
+
+        switch (paramCopy.event.type) {
+            case NPCocoaEventMouseDown:
+            case NPCocoaEventMouseUp:
+            case NPCocoaEventMouseMoved:
+            case NPCocoaEventMouseEntered:
+            case NPCocoaEventMouseExited:
+            case NPCocoaEventMouseDragged:
+            case NPCocoaEventFocusChanged:
+            case NPCocoaEventWindowFocusChanged:
+            case NPCocoaEventScrollWheel:
+                // Nothing special to do for these events.
+                break;
+            case NPCocoaEventDrawRect:
+                // Don't serialize the context pointer
+                paramCopy.event.data.draw.context = NULL;
+                break;
+            case NPCocoaEventKeyDown:
+            case NPCocoaEventKeyUp:
+            case NPCocoaEventFlagsChanged:
+            case NPCocoaEventTextInput:
+            default:
+                // ignore any events we don't expect
+                return; 
+        }
+
+        aMsg->WriteBytes(&paramCopy, sizeof(paramType));
     }
 
     static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
     {
+        const char* bytes = 0;
+
+        if (!aMsg->ReadBytes(aIter, &bytes, sizeof(paramType))) {
+            return false;
+        }
+        memcpy(aResult, bytes, sizeof(paramType));
+
         return true;
     }
 
     static void Log(const paramType& aParam, std::wstring* aLog)
     {
         aLog->append(L"(NPCocoaEvent)");
     }
 };
new file mode 100644
--- /dev/null
+++ b/dom/plugins/PPluginIdentifier.ipdl
@@ -0,0 +1,56 @@
+/* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Plugins.
+ *
+ * The Initial Developer of the Original Code is
+ *   Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Ben Turner <bent.mozilla@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+include protocol "PPluginModule.ipdl";
+
+namespace mozilla {
+namespace plugins {
+
+/**
+ * Represents an NPIdentifier that wraps either a string or an integer.
+ */
+async protocol PPluginIdentifier
+{
+  manager PPluginModule;
+
+child:
+  async __delete__();
+};
+
+} // namespace plugins
+} // namespace mozilla
--- a/dom/plugins/PPluginInstance.ipdl
+++ b/dom/plugins/PPluginInstance.ipdl
@@ -45,16 +45,17 @@ include protocol "PStreamNotify.ipdl";
 
 include "mozilla/plugins/PluginMessageUtils.h";
 
 using NPError;
 using NPRemoteWindow;
 using NPRemoteEvent;
 using NPRect;
 using NPNURLVariable;
+using NPCoordinateSpace;
 using mozilla::plugins::NativeWindowHandle;
 
 namespace mozilla {
 namespace plugins {
 
 rpc protocol PPluginInstance
 {
   manager PPluginModule;
@@ -74,16 +75,19 @@ child:
     returns (bool value, NPError result);
   rpc NPP_GetValue_NPPVpluginScriptableNPObject()
     returns (nullable PPluginScriptableObject value, NPError result);
 
   rpc NPP_SetValue_NPNVprivateModeBool(bool value) returns (NPError result);
 
   rpc NPP_HandleEvent(NPRemoteEvent event)
     returns (int16_t handled);
+  // special cases where we need to a shared memory buffer
+  rpc NPP_HandleEvent_Shmem(NPRemoteEvent event, Shmem buffer)
+    returns (int16_t handled, Shmem rtnbuffer);
   // special cases of HandleEvent to make mediating races simpler
   rpc Paint(NPRemoteEvent event)
     returns (int16_t handled);
   // this is only used on windows to forward WM_WINDOWPOSCHANGE
   async WindowPosChanged(NPRemoteEvent event);
 
   rpc NPP_Destroy()
     returns (NPError rv);
@@ -101,16 +105,20 @@ parent:
     returns (bool value, NPError result);
   rpc NPN_GetValue_NPNVnetscapeWindow()
     returns (NativeWindowHandle value, NPError result);
 
   rpc NPN_SetValue_NPPVpluginWindow(bool windowed)
     returns (NPError result);
   rpc NPN_SetValue_NPPVpluginTransparent(bool transparent)
     returns (NPError result);
+  rpc NPN_SetValue_NPPVpluginDrawingModel(int drawingModel)
+    returns (NPError result);
+  rpc NPN_SetValue_NPPVpluginEventModel(int eventModel)
+    returns (NPError result);
 
   rpc NPN_GetURL(nsCString url, nsCString target)
     returns (NPError result);
   rpc NPN_PostURL(nsCString url, nsCString target, nsCString buffer, bool file)
     returns (NPError result);
 
   /**
    * Covers both NPN_GetURLNotify and NPN_PostURLNotify.
@@ -118,34 +126,36 @@ parent:
    *       but IPDL doesn't allow that for constructors.
    */
   rpc PStreamNotify(nsCString url, nsCString target, bool post,
                     nsCString buffer, bool file)
     returns (NPError result);
 
   async NPN_InvalidateRect(NPRect rect);
 
-  rpc NPN_PushPopupsEnabledState(bool aState)
-    returns (bool aSuccess);
+  rpc NPN_PushPopupsEnabledState(bool aState);
 
-  rpc NPN_PopPopupsEnabledState()
-    returns (bool aSuccess);
+  rpc NPN_PopPopupsEnabledState();
 
   rpc NPN_GetValueForURL(NPNURLVariable variable, nsCString url)
     returns (nsCString value, NPError result);
 
   rpc NPN_SetValueForURL(NPNURLVariable variable, nsCString url,
                          nsCString value)
     returns (NPError result);
 
   rpc NPN_GetAuthenticationInfo(nsCString protocol_, nsCString host,
                                 int32_t port, nsCString scheme,
                                 nsCString realm)
     returns (nsCString username, nsCString password, NPError result);
 
+  rpc NPN_ConvertPoint(double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
+                       NPCoordinateSpace destSpace)
+    returns (double destX, bool ignoreDestX, double destY, bool ignoreDestY, bool result);
+
 both:
   async PPluginScriptableObject();
 
 child:
   /* NPP_NewStream */
   rpc PBrowserStream(nsCString url,
                      uint32_t length,
                      uint32_t lastmodified,
--- a/dom/plugins/PPluginModule.ipdl
+++ b/dom/plugins/PPluginModule.ipdl
@@ -32,69 +32,63 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
+include protocol "PPluginIdentifier.ipdl";
 include protocol "PPluginInstance.ipdl";
 
 include "npapi.h";
 include "mozilla/plugins/PluginMessageUtils.h";
 
 using NPError;
 using NPNVariable;
-using mozilla::ipc::NPRemoteIdentifier;
 
 namespace mozilla {
 namespace plugins {
 
 rpc protocol PPluginModule
 {
   manages PPluginInstance;
+  manages PPluginIdentifier;
+
+both:
+  /**
+   * Sending a void string to this constructor creates an int identifier whereas
+   * sending a non-void string will create a string identifier. This constructor
+   * may be called by either child or parent. If a race occurs by calling the
+   * constructor with the same string or int argument then we create two actors
+   * and detect the second instance in the child. We prevent the parent's actor
+   * from leaking out to plugin code and only allow the child's to be used.
+   */
+  async PPluginIdentifier(nsCString aString,
+                          int32_t aInt);
 
 child:
   rpc NP_Initialize()
     returns (NPError rv);
 
   rpc PPluginInstance(nsCString aMimeType,
                       uint16_t aMode,
                       nsCString[] aNames,
                       nsCString[] aValues)
     returns (NPError rv);
 
   rpc NP_Shutdown()
     returns (NPError rv);
 
 parent:
+  async XXX_HACK_FIXME_cjones(Shmem _);
   rpc NPN_UserAgent()
     returns (nsCString userAgent);
 
-  sync NPN_GetStringIdentifier(nsCString aString)
-    returns (NPRemoteIdentifier aId);
-  sync NPN_GetIntIdentifier(int32_t aInt)
-    returns (NPRemoteIdentifier aId);
-
-  // for the following two methods, the returned value is valid iff
-  // |err == NPERR_NO_ERROR|
-  sync NPN_UTF8FromIdentifier(NPRemoteIdentifier aId)
-    returns (NPError err, nsCString aString);
-  // technically |aInt| is undefined when |aId| is invalid.  but it's
-  // nice to let the other side know that |aId| was invalid
-  sync NPN_IntFromIdentifier(NPRemoteIdentifier aId)
-    returns (NPError err, int32_t aInt);
-
-  sync NPN_IdentifierIsString(NPRemoteIdentifier aId)
-    returns (bool aIsString);
-
-  sync NPN_GetStringIdentifiers(nsCString[] aNames)
-    returns (NPRemoteIdentifier[] aIds);
-
   rpc NPN_GetValue_WithBoolReturn(NPNVariable aVariable)
     returns (NPError aError,
              bool aBoolVal);
 
   // Wake up and process a few native events.  Periodically called by
   // Gtk-specific code upon detecting that the plugin process has
   // entered a nested event loop.  If the browser doesn't process
   // native events, then "livelock" and some other glitches can occur.
--- a/dom/plugins/PPluginScriptableObject.ipdl
+++ b/dom/plugins/PPluginScriptableObject.ipdl
@@ -33,22 +33,22 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 include protocol "PPluginInstance.ipdl";
+include protocol "PPluginIdentifier.ipdl";
 
 include "npapi.h";
 include "npruntime.h";
 include "mozilla/plugins/PluginMessageUtils.h";
 
-using mozilla::ipc::NPRemoteIdentifier;
 using mozilla::void_t;
 using mozilla::null_t;
 
 namespace mozilla {
 namespace plugins {
 
 union Variant {
   void_t;
@@ -72,44 +72,44 @@ parent:
     returns (Variant aResult,
              bool aSuccess);
 
 child:
   rpc Invalidate();
 
 both:
   // NPClass methods
-  rpc HasMethod(NPRemoteIdentifier aId)
+  rpc HasMethod(PPluginIdentifier aId)
     returns (bool aHasMethod);
 
-  rpc Invoke(NPRemoteIdentifier aId,
+  rpc Invoke(PPluginIdentifier aId,
              Variant[] aArgs)
     returns (Variant aResult,
              bool aSuccess);
 
   rpc InvokeDefault(Variant[] aArgs)
     returns (Variant aResult,
              bool aSuccess);
 
-  rpc HasProperty(NPRemoteIdentifier aId)
+  rpc HasProperty(PPluginIdentifier aId)
     returns (bool aHasProperty);
 
-  rpc GetProperty(NPRemoteIdentifier aId)
+  rpc GetProperty(PPluginIdentifier aId)
     returns (Variant aResult,
              bool aSuccess);
 
-  rpc SetProperty(NPRemoteIdentifier aId,
+  rpc SetProperty(PPluginIdentifier aId,
                   Variant aValue)
     returns (bool aSuccess);
 
-  rpc RemoveProperty(NPRemoteIdentifier aId)
+  rpc RemoveProperty(PPluginIdentifier aId)
     returns (bool aSuccess);
 
   rpc Enumerate()
-    returns (NPRemoteIdentifier[] aProperties,
+    returns (PPluginIdentifier[] aProperties,
              bool aSuccess);
 
   rpc Construct(Variant[] aArgs)
     returns (Variant aResult,
              bool aSuccess);
 
   // Objects are initially unprotected, and the Protect and Unprotect functions
   // only affect protocol objects that represent NPObjects created in the same
new file mode 100644
--- /dev/null
+++ b/dom/plugins/PluginIdentifierChild.h
@@ -0,0 +1,140 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 et :
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Plugins.
+ *
+ * The Initial Developer of the Original Code is
+ *   Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Ben Turner <bent.mozilla@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef dom_plugins_PluginIdentifierChild_h
+#define dom_plugins_PluginIdentifierChild_h
+
+#include "mozilla/plugins/PPluginIdentifierChild.h"
+#include "mozilla/plugins/PluginModuleChild.h"
+
+#include "nsStringGlue.h"
+
+namespace mozilla {
+namespace plugins {
+
+class PluginIdentifierChild : public PPluginIdentifierChild
+{
+  friend class PluginModuleChild;
+public:
+  bool IsString()
+  {
+    return reinterpret_cast<intptr_t>(mCanonicalIdentifier) & 1;
+  }
+
+  NPIdentifier ToNPIdentifier()
+  {
+    return reinterpret_cast<PluginIdentifierChild*>(
+      reinterpret_cast<intptr_t>(mCanonicalIdentifier) & ~1);
+  }
+
+protected:
+  PluginIdentifierChild(bool aIsString)
+    : ALLOW_THIS_IN_INITIALIZER_LIST(mCanonicalIdentifier(this))
+  {
+    MOZ_COUNT_CTOR(PluginIdentifierChild);
+    if (aIsString) {
+      SetIsString();
+    }
+  }
+
+  virtual ~PluginIdentifierChild()
+  {
+    MOZ_COUNT_DTOR(PluginIdentifierChild);
+  }
+
+  void SetCanonicalIdentifier(PluginIdentifierChild* aIdentifier)
+  {
+    NS_ASSERTION(ToNPIdentifier() == this, "Already got one!");
+    bool isString = IsString();
+    mCanonicalIdentifier = aIdentifier;
+    if (isString) {
+      SetIsString();
+    }
+  }
+
+private:
+  void SetIsString()
+  {
+    mCanonicalIdentifier = reinterpret_cast<PluginIdentifierChild*>(
+      reinterpret_cast<intptr_t>(mCanonicalIdentifier) | 1);
+  }
+
+  PluginIdentifierChild* mCanonicalIdentifier;
+};
+
+class PluginIdentifierChildString : public PluginIdentifierChild
+{
+  friend class PluginModuleChild;
+public:
+  NPUTF8* ToString()
+  {
+    return ToNewCString(mString);
+  }
+
+protected:
+  PluginIdentifierChildString(const nsCString& aString)
+    : PluginIdentifierChild(true),
+      mString(aString)
+  { }
+
+  nsCString mString;
+};
+
+class PluginIdentifierChildInt : public PluginIdentifierChild
+{
+  friend class PluginModuleChild;
+public:
+  int32_t ToInt()
+  {
+    return mInt;
+  }
+
+protected:
+  PluginIdentifierChildInt(int32_t aInt)
+    : PluginIdentifierChild(false),
+      mInt(aInt)
+  { }
+
+  int32_t mInt;
+};
+
+} // namespace plugins
+} // namespace mozilla
+
+#endif // dom_plugins_PluginIdentifierChild_h
new file mode 100644
--- /dev/null
+++ b/dom/plugins/PluginIdentifierParent.h
@@ -0,0 +1,80 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
+ * vim: sw=2 ts=2 et :
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla Plugins.
+ *
+ * The Initial Developer of the Original Code is
+ *   Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Ben Turner <bent.mozilla@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef dom_plugins_PluginIdentifierParent_h
+#define dom_plugins_PluginIdentifierParent_h
+
+#include "mozilla/plugins/PPluginIdentifierParent.h"
+
+#include "npapi.h"
+#include "npruntime.h"
+
+namespace mozilla {
+namespace plugins {
+
+class PluginIdentifierParent : public PPluginIdentifierParent
+{
+  friend class PluginModuleParent;
+
+public:
+  NPIdentifier ToNPIdentifier()
+  {
+    return mIdentifier;
+  }
+
+protected:
+  PluginIdentifierParent(NPIdentifier aIdentifier)
+    : mIdentifier(aIdentifier)
+  {
+    MOZ_COUNT_CTOR(PluginIdentifierParent);
+  }
+
+  virtual ~PluginIdentifierParent()
+  {
+    MOZ_COUNT_DTOR(PluginIdentifierParent);
+  }
+
+private:
+  NPIdentifier mIdentifier;
+};
+
+} // namespace plugins
+} // namespace mozilla
+
+#endif // dom_plugins_PluginIdentifierParent_h
--- a/dom/plugins/PluginInstanceChild.cpp
+++ b/dom/plugins/PluginInstanceChild.cpp
@@ -72,18 +72,19 @@ static HWND sWinlessPopupSurrogateHWND =
 static User32TrackPopupMenu sUser32TrackPopupMenuStub = NULL;
 
 using mozilla::gfx::SharedDIB;
 
 #include <windows.h>
 #include <windowsx.h>
 
 #define NS_OOPP_DOUBLEPASS_MSGID TEXT("MozDoublePassMsg")
-
-#endif // defined(OS_WIN)
+#elif defined(XP_MACOSX)
+#include <ApplicationServices/ApplicationServices.h>
+#endif // defined(XP_MACOSX)
 
 PluginInstanceChild::PluginInstanceChild(const NPPluginFuncs* aPluginIface,
                                          const nsCString& aMimeType)
     : mPluginIface(aPluginIface)
     , mQuirks(0)
     , mCachedWindowActor(nsnull)
     , mCachedElementActor(nsnull)
 #if defined(OS_WIN)
@@ -315,16 +316,40 @@ PluginInstanceChild::NPN_GetValue(NPNVar
         NPError result;
         CallNPN_GetValue_NPNVnetscapeWindow(static_cast<XID*>(aValue), &result);
         return result;
 #else
         return NPERR_GENERIC_ERROR;
 #endif
     }
 
+#ifdef XP_MACOSX
+   case NPNVsupportsCoreGraphicsBool: {
+        *((NPBool*)aValue) = true;
+        return NPERR_NO_ERROR;
+    }
+
+    case NPNVsupportsCoreAnimationBool: {
+        *((NPBool*)aValue) = false;
+        return NPERR_NO_ERROR;
+    }
+
+    case NPNVsupportsCocoaBool: {
+        *((NPBool*)aValue) = true;
+        return NPERR_NO_ERROR;
+    }
+  
+#ifndef NP_NO_QUICKDRAW
+    case NPNVsupportsQuickDrawBool: {
+        *((NPBool*)aValue) = false;
+        return NPERR_NO_ERROR;
+    }
+#endif /* NP_NO_QUICKDRAW */
+#endif /* XP_MACOSX */
+
     default:
         PR_LOG(gPluginLog, PR_LOG_WARNING,
                ("In PluginInstanceChild::NPN_GetValue: Unhandled NPNVariable %i (%s)",
                 (int) aVar, NPNVariableToString(aVar)));
         return NPERR_GENERIC_ERROR;
     }
 
 }
@@ -354,16 +379,38 @@ PluginInstanceChild::NPN_SetValue(NPPVar
         bool transparent = (NPBool) (intptr_t) aValue;
 
         if (!CallNPN_SetValue_NPPVpluginTransparent(transparent, &rv))
             return NPERR_GENERIC_ERROR;
 
         return rv;
     }
 
+#ifdef XP_MACOSX
+    case NPPVpluginDrawingModel: {
+        NPError rv;
+        int drawingModel = (int16) (intptr_t) aValue;
+
+        if (!CallNPN_SetValue_NPPVpluginDrawingModel(drawingModel, &rv))
+            return NPERR_GENERIC_ERROR;
+
+        return rv;
+    }
+
+    case NPPVpluginEventModel: {
+        NPError rv;
+        int eventModel = (int16) (intptr_t) aValue;
+
+        if (!CallNPN_SetValue_NPPVpluginEventModel(eventModel, &rv))
+            return NPERR_GENERIC_ERROR;
+
+        return rv;
+    }
+#endif
+
     default:
         PR_LOG(gPluginLog, PR_LOG_WARNING,
                ("In PluginInstanceChild::NPN_SetValue: Unhandled NPPVariable %i (%s)",
                 (int) aVar, NPPVariableToString(aVar)));
         return NPERR_GENERIC_ERROR;
     }
 }
 
@@ -459,17 +506,17 @@ PluginInstanceChild::AnswerNPP_HandleEve
     AssertPluginThread();
 
 #if defined(OS_LINUX) && defined(DEBUG)
     if (GraphicsExpose == event.event.type)
         PLUGIN_LOG_DEBUG(("  received drawable 0x%lx\n",
                           event.event.xgraphicsexpose.drawable));
 #endif
 
-#ifdef OS_MACOSX
+#ifdef XP_MACOSX
     // Mac OS X does not define an NPEvent structure. It defines more specific types.
     NPCocoaEvent evcopy = event.event;
 #else
     // Make a copy since we may modify values.
     NPEvent evcopy = event.event;
 #endif
 
 #ifdef OS_WIN
@@ -508,16 +555,83 @@ PluginInstanceChild::AnswerNPP_HandleEve
         // an X event to the parent that the parent would wait for.
         XSync(mWsInfo.display, False);
     }
 #endif
 
     return true;
 }
 
+#ifdef XP_MACOSX
+bool
+PluginInstanceChild::AnswerNPP_HandleEvent_Shmem(const NPRemoteEvent& event,
+                                                 Shmem& mem,
+                                                 int16_t* handled,
+                                                 Shmem* rtnmem)
+{
+    PLUGIN_LOG_DEBUG_FUNCTION;
+    AssertPluginThread();
+
+    // We return access to the shared memory buffer after returning.
+
+    NPCocoaEvent evcopy = event.event;
+
+    if (evcopy.type == NPCocoaEventDrawRect) {
+        CGColorSpaceRef cSpace = ::CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+        if (!cSpace) {
+            PLUGIN_LOG_DEBUG(("Could not allocate ColorSpace."));
+            *handled = false;
+            *rtnmem = mem;
+            return true;
+        } 
+        void* cgContextByte = mem.get<char>();
+        CGContextRef ctxt = ::CGBitmapContextCreate(cgContextByte, mWindow.width, mWindow.height, 8, mWindow.width * 4, cSpace, kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host);
+        ::CGColorSpaceRelease(cSpace);
+        if (!ctxt) {
+            PLUGIN_LOG_DEBUG(("Could not allocate CGBitmapContext."));
+            *handled = false;
+            *rtnmem = mem;
+            return true;
+        }
+        evcopy.data.draw.context = ctxt; 
+    } else {
+        PLUGIN_LOG_DEBUG(("Invalid event type for AnswerNNP_HandleEvent_Shmem."));
+        *handled = false;
+        *rtnmem = mem;
+        return true;
+    } 
+
+    if (!mPluginIface->event) {
+        *handled = false;
+    } else {
+        *handled = mPluginIface->event(&mData, reinterpret_cast<void*>(&evcopy));
+    }
+
+    // Some events need cleaning up.
+    if (evcopy.type == NPCocoaEventDrawRect) {
+        ::CGContextRelease(evcopy.data.draw.context);
+    }
+
+    *rtnmem = mem;
+    return true;
+}
+
+#else
+bool
+PluginInstanceChild::AnswerNPP_HandleEvent_Shmem(const NPRemoteEvent& event,
+                                                 Shmem& mem,
+                                                 int16_t* handled,
+                                                 Shmem* rtnmem)
+{
+    NS_RUNTIMEABORT("not reached.");
+    *rtnmem = mem;
+    return true;
+}
+#endif
+
 bool
 PluginInstanceChild::RecvWindowPosChanged(const NPRemoteEvent& event)
 {
 #ifdef OS_WIN
     int16_t dontcare;
     return AnswerNPP_HandleEvent(event, &dontcare);
 #else
     NS_RUNTIMEABORT("WindowPosChanged is a windows-only message");
@@ -636,25 +750,28 @@ PluginInstanceChild::AnswerNPP_SetWindow
       break;
 
       default:
           NS_NOTREACHED("Bad plugin window type.");
           return false;
       break;
     }
 
-#elif defined(OS_MACOSX)
+#elif defined(XP_MACOSX)
 
     mWindow.x = aWindow.x;
     mWindow.y = aWindow.y;
     mWindow.width = aWindow.width;
     mWindow.height = aWindow.height;
     mWindow.clipRect = aWindow.clipRect;
     mWindow.type = aWindow.type;
 
+    if (mPluginIface->setwindow)
+        (void) mPluginIface->setwindow(&mData, &mWindow);
+
 #else
 #  error Implement me for your OS
 #endif
 
     return true;
 }
 
 bool
--- a/dom/plugins/PluginInstanceChild.h
+++ b/dom/plugins/PluginInstanceChild.h
@@ -83,16 +83,18 @@ protected:
     AnswerNPP_GetValue_NPPVpluginScriptableNPObject(PPluginScriptableObjectChild** value,
                                                     NPError* result);
 
     virtual bool
     AnswerNPP_SetValue_NPNVprivateModeBool(const bool& value, NPError* result);
 
     virtual bool
     AnswerNPP_HandleEvent(const NPRemoteEvent& event, int16_t* handled);
+    virtual bool
+    AnswerNPP_HandleEvent_Shmem(const NPRemoteEvent& event, Shmem& mem, int16_t* handled, Shmem* rtnmem);
 
     NS_OVERRIDE
     virtual bool
     AnswerPaint(const NPRemoteEvent& event, int16_t* handled)
     {
         return AnswerNPP_HandleEvent(event, handled);
     }
 
--- a/dom/plugins/PluginInstanceParent.cpp
+++ b/dom/plugins/PluginInstanceParent.cpp
@@ -52,31 +52,40 @@
 // Plugin focus event for widget.
 extern const PRUnichar* kOOPPPluginFocusEventId;
 UINT gOOPPPluginFocusEvent =
     RegisterWindowMessage(kOOPPPluginFocusEventId);
 UINT gOOPPSpinNativeLoopEvent =
     RegisterWindowMessage(L"SyncChannel Spin Inner Loop Message");
 UINT gOOPPStopNativeLoopEvent =
     RegisterWindowMessage(L"SyncChannel Stop Inner Loop Message");
-#endif
+#elif defined(MOZ_WIDGET_GTK2)
+#include <gdk/gdk.h>
+#elif defined(XP_MACOSX)
+#include <ApplicationServices/ApplicationServices.h>
+#endif // defined(XP_MACOSX)
 
 using namespace mozilla::plugins;
 
 PluginInstanceParent::PluginInstanceParent(PluginModuleParent* parent,
                                            NPP npp,
                                            const NPNetscapeFuncs* npniface)
   : mParent(parent)
     , mNPP(npp)
     , mNPNIface(npniface)
     , mWindowType(NPWindowTypeWindow)
 #if defined(OS_WIN)
     , mPluginHWND(NULL)
     , mPluginWndProc(NULL)
+    , mNestedEventState(false)
 #endif // defined(XP_WIN)
+#if defined(XP_MACOSX)
+    , mShWidth(0)
+    , mShHeight(0)
+#endif
 {
 }
 
 PluginInstanceParent::~PluginInstanceParent()
 {
     if (mNPP)
         mNPP->pdata = NULL;
 
@@ -180,16 +189,26 @@ PluginInstanceParent::AllocPPluginStream
 
 bool
 PluginInstanceParent::DeallocPPluginStream(PPluginStreamParent* stream)
 {
     delete stream;
     return true;
 }
 
+#ifdef MOZ_X11
+static Display* GetXDisplay() {
+#  ifdef MOZ_WIDGET_GTK2
+        return GDK_DISPLAY();
+#  elif defined(MOZ_WIDGET_QT)
+        return QX11Info::display();
+#  endif
+}
+#endif
+
 bool
 PluginInstanceParent::AnswerNPN_GetValue_NPNVjavascriptEnabledBool(
                                                        bool* value,
                                                        NPError* result)
 {
     NPBool v;
     *result = mNPNIface->getvalue(mNPP, NPNVjavascriptEnabledBool, &v);
     *value = v;
@@ -275,17 +294,16 @@ PluginInstanceParent::AnswerNPN_GetValue
                                                              NPError* result)
 {
     NPBool v;
     *result = mNPNIface->getvalue(mNPP, NPNVprivateModeBool, &v);
     *value = v;
     return true;
 }
 
-
 bool
 PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginWindow(
     const bool& windowed, NPError* result)
 {
     NPBool isWindowed = windowed;
     *result = mNPNIface->setvalue(mNPP, NPPVpluginWindowBool,
                                   (void*)isWindowed);
     return true;
@@ -296,16 +314,43 @@ PluginInstanceParent::AnswerNPN_SetValue
     const bool& transparent, NPError* result)
 {
     NPBool isTransparent = transparent;
     *result = mNPNIface->setvalue(mNPP, NPPVpluginTransparentBool,
                                   (void*)isTransparent);
     return true;
 }
 
+bool
+PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginDrawingModel(
+    const int& drawingModel, NPError* result)
+{
+#ifdef XP_MACOSX
+    *result = mNPNIface->setvalue(mNPP, NPPVpluginDrawingModel,
+                                  (void*)drawingModel);
+    return true;
+#else
+    *result = NPERR_GENERIC_ERROR;
+    return true;
+#endif
+}
+
+bool
+PluginInstanceParent::AnswerNPN_SetValue_NPPVpluginEventModel(
+    const int& eventModel, NPError* result)
+{
+#ifdef XP_MACOSX
+    *result = mNPNIface->setvalue(mNPP, NPPVpluginEventModel,
+                                  (void*)eventModel);
+    return true;
+#else
+    *result = NPERR_GENERIC_ERROR;
+    return true;
+#endif
+}
 
 bool
 PluginInstanceParent::AnswerNPN_GetURL(const nsCString& url,
                                        const nsCString& target,
                                        NPError* result)
 {
     *result = mNPNIface->geturl(mNPP,
                                 NullableStringGet(url),
@@ -420,16 +465,30 @@ PluginInstanceParent::NPP_SetWindow(cons
     window.x = aWindow->x;
     window.y = aWindow->y;
     window.width = aWindow->width;
     window.height = aWindow->height;
     window.clipRect = aWindow->clipRect; // MacOS specific
     window.type = aWindow->type;
 #endif
 
+#if defined(XP_MACOSX)
+    if (mShWidth * mShHeight != window.width * window.height) {
+        // XXX: benwa: OMG MEMORY LEAK! 
+        //      There is currently no way dealloc the shmem
+        //      so for now we will leak the memory and will fix this ASAP!
+        if (!AllocShmem(window.width * window.height * 4, &mShSurface)) {
+            PLUGIN_LOG_DEBUG(("Shared memory could not be allocated."));
+            return NPERR_GENERIC_ERROR;
+        }
+        mShWidth = window.width;
+        mShHeight = window.height;
+    }
+#endif
+
 #if defined(MOZ_X11) && defined(XP_UNIX) && !defined(XP_MACOSX)
     const NPSetWindowCallbackStruct* ws_info =
       static_cast<NPSetWindowCallbackStruct*>(aWindow->ws_info);
     window.visualID = ws_info->visual ? ws_info->visual->visualid : None;
     window.colormap = ws_info->colormap;
 #endif
 
     if (!CallNPP_SetWindow(window))
@@ -576,36 +635,94 @@ PluginInstanceParent::NPP_HandleEvent(vo
                 return 1;
             }
             break;
         }
     }
 #endif
 
 #if defined(MOZ_X11)
-    if (GraphicsExpose == npevent->type) {
+    switch (npevent->type) {
+    case GraphicsExpose:
         PLUGIN_LOG_DEBUG(("  schlepping drawable 0x%lx across the pipe\n",
                           npevent->xgraphicsexpose.drawable));
         // Make sure the X server has created the Drawable and completes any
         // drawing before the plugin draws on top.
         //
         // XSync() waits for the X server to complete.  Really this parent
         // process does not need to wait; the child is the process that needs
         // to wait.  A possibly-slightly-better alternative would be to send
         // an X event to the child that the child would wait for.
+        XSync(GetXDisplay(), False);
+        break;
+    case ButtonPress:
+        // Release any active pointer grab so that the plugin X client can
+        // grab the pointer if it wishes.
+        Display *dpy = GetXDisplay();
 #  ifdef MOZ_WIDGET_GTK2
-        XSync(GDK_DISPLAY(), False);
-#  elif defined(MOZ_WIDGET_QT)
-        XSync(QX11Info::display(), False);
+        // GDK attempts to (asynchronously) track whether there is an active
+        // grab so ungrab through GDK.
+        gdk_pointer_ungrab(npevent->xbutton.time);
+#  else
+        XUngrabPointer(dpy, npevent->xbutton.time);
 #  endif
+        // Wait for the ungrab to complete.
+        XSync(dpy, False);
+        break;
 
         return CallPaint(npremoteevent, &handled) ? handled : 0;
     }
 #endif
 
+#ifdef XP_MACOSX
+    if (npevent->type == NPCocoaEventDrawRect) {
+        if (mShWidth == 0 && mShHeight == 0) {
+            PLUGIN_LOG_DEBUG(("NPCocoaEventDrawRect on window of size 0."));
+            return false;
+        }
+        if (!mShSurface.IsReadable()) {
+            PLUGIN_LOG_DEBUG(("Shmem is not readable."));
+            return false;
+        }
+
+        if (!CallNPP_HandleEvent_Shmem(npremoteevent, mShSurface, &handled, &mShSurface)) 
+            return false; // no good way to handle errors here...
+
+        if (!mShSurface.IsReadable()) {
+            PLUGIN_LOG_DEBUG(("Shmem not returned. Either the plugin crashed or we have a bug."));
+            return false;
+        }
+
+        char* shContextByte = mShSurface.get<char>();
+
+        CGColorSpaceRef cSpace = ::CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
+        if (!cSpace) {
+            PLUGIN_LOG_DEBUG(("Could not allocate ColorSpace."));
+            return true;
+        } 
+        CGContextRef shContext = ::CGBitmapContextCreate(shContextByte, 
+                                mShWidth, mShHeight, 8, mShWidth*4, cSpace, 
+                                kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host);
+        ::CGColorSpaceRelease(cSpace);
+        if (!shContext) {
+            PLUGIN_LOG_DEBUG(("Could not allocate CGBitmapContext."));
+            return true;
+        }
+
+        CGImageRef shImage = ::CGBitmapContextCreateImage(shContext);
+        if (shImage) {
+            CGContextRef cgContext = npevent->data.draw.context;
+            ::CGContextDrawImage(cgContext, CGRectMake(0,0,mShWidth,mShHeight), shImage);
+            ::CGImageRelease(shImage);
+        }
+        ::CGContextRelease(shContext);
+        return handled;
+    }
+#endif
+
     if (!CallNPP_HandleEvent(npremoteevent, &handled))
         return 0; // no good way to handle errors here...
 
     return handled;
 }
 
 NPError
 PluginInstanceParent::NPP_NewStream(NPMIMEType type, NPStream* stream,
@@ -800,27 +917,26 @@ PluginInstanceParent::GetActorForNPObjec
         return nsnull;
     }
 
     actor->InitializeLocal(aObject);
     return actor;
 }
 
 bool
-PluginInstanceParent::AnswerNPN_PushPopupsEnabledState(const bool& aState,
-                                                       bool* aSuccess)
+PluginInstanceParent::AnswerNPN_PushPopupsEnabledState(const bool& aState)
 {
-    *aSuccess = mNPNIface->pushpopupsenabledstate(mNPP, aState ? 1 : 0);
+    mNPNIface->pushpopupsenabledstate(mNPP, aState ? 1 : 0);
     return true;
 }
 
 bool
-PluginInstanceParent::AnswerNPN_PopPopupsEnabledState(bool* aSuccess)
+PluginInstanceParent::AnswerNPN_PopPopupsEnabledState()
 {
-    *aSuccess = mNPNIface->poppopupsenabledstate(mNPP);
+    mNPNIface->poppopupsenabledstate(mNPP);
     return true;
 }
 
 bool
 PluginInstanceParent::AnswerNPN_GetValueForURL(const NPNURLVariable& variable,
                                                const nsCString& url,
                                                nsCString* value,
                                                NPError* result)
@@ -869,23 +985,42 @@ PluginInstanceParent::AnswerNPN_GetAuthe
                                                &u, &ulen, &p, &plen);
     if (NPERR_NO_ERROR == *result) {
         username->Adopt(u, ulen);
         password->Adopt(p, plen);
     }
     return true;
 }
 
+bool
+PluginInstanceParent::AnswerNPN_ConvertPoint(const double& sourceX,
+                                             const double& sourceY,
+                                             const NPCoordinateSpace& sourceSpace,
+                                             const NPCoordinateSpace& destSpace,
+                                             double *destX,
+                                             bool *ignoreDestX,
+                                             double *destY,
+                                             bool *ignoreDestY,
+                                             bool *result)
+{
+    *result = mNPNIface->convertpoint(mNPP, sourceX, sourceY, sourceSpace,
+                                      ignoreDestX ? nsnull : destX,
+                                      ignoreDestY ? nsnull : destY,
+                                      destSpace);
+
+    return true;
+}
+
 #if defined(OS_WIN)
 
 /*
   plugin focus changes between processes
 
   focus from dom -> child:
-    Focs manager calls on widget to set the focus on the window.
+    Focus manager calls on widget to set the focus on the window.
     We pick up the resulting wm_setfocus event here, and forward
     that over ipc to the child which calls set focus on itself. 
 
   focus from child -> focus manager:
     Child picks up the local wm_setfocus and sends it via ipc over
     here. We then post a custom event to widget/src/windows/nswindow
     which fires off a gui event letting the browser know.
 */
--- a/dom/plugins/PluginInstanceParent.h
+++ b/dom/plugins/PluginInstanceParent.h
@@ -121,16 +121,22 @@ public:
     virtual bool
     AnswerNPN_GetValue_NPNVprivateModeBool(bool* value, NPError* result);
 
     virtual bool
     AnswerNPN_SetValue_NPPVpluginWindow(const bool& windowed, NPError* result);
     virtual bool
     AnswerNPN_SetValue_NPPVpluginTransparent(const bool& transparent,
                                              NPError* result);
+    virtual bool
+    AnswerNPN_SetValue_NPPVpluginDrawingModel(const int& drawingModel,
+                                             NPError* result);
+    virtual bool
+    AnswerNPN_SetValue_NPPVpluginEventModel(const int& eventModel,
+                                             NPError* result);
 
     virtual bool
     AnswerNPN_GetURL(const nsCString& url, const nsCString& target,
                      NPError *result);
 
     virtual bool
     AnswerNPN_PostURL(const nsCString& url, const nsCString& target,
                       const nsCString& buffer, const bool& file,
@@ -152,21 +158,20 @@ public:
 
     virtual bool
     DeallocPStreamNotify(PStreamNotifyParent* notifyData);
 
     virtual bool
     RecvNPN_InvalidateRect(const NPRect& rect);
 
     virtual bool
-    AnswerNPN_PushPopupsEnabledState(const bool& aState,
-                                     bool* aSuccess);
+    AnswerNPN_PushPopupsEnabledState(const bool& aState);
 
     virtual bool
-    AnswerNPN_PopPopupsEnabledState(bool* aSuccess);
+    AnswerNPN_PopPopupsEnabledState();
 
     NS_OVERRIDE virtual bool
     AnswerNPN_GetValueForURL(const NPNURLVariable& variable,
                              const nsCString& url,
                              nsCString* value, NPError* result);
 
     NS_OVERRIDE virtual bool
     AnswerNPN_SetValueForURL(const NPNURLVariable& variable,
@@ -178,16 +183,27 @@ public:
                                     const nsCString& host,
                                     const int32_t& port,
                                     const nsCString& scheme,
                                     const nsCString& realm,
                                     nsCString* username,
                                     nsCString* password,
                                     NPError* result);
 
+    NS_OVERRIDE virtual bool
+    AnswerNPN_ConvertPoint(const double& sourceX,
+                           const double& sourceY,
+                           const NPCoordinateSpace& sourceSpace,
+                           const NPCoordinateSpace& destSpace,
+                           double *destX,
+                           bool *ignoreDestX,
+                           double *destY,
+                           bool *ignoreDestY,
+                           bool *result);
+
     NPError NPP_SetWindow(const NPWindow* aWindow);
 
     NPError NPP_GetValue(NPPVariable variable, void* retval);
     NPError NPP_SetValue(NPNVariable variable, void* value);
 
     NPError NPP_NewStream(NPMIMEType type, NPStream* stream,
                           NPBool seekable, uint16_t* stype);
     NPError NPP_DestroyStream(NPStream* stream, NPReason reason);
@@ -259,15 +275,21 @@ private:
 private:
     gfx::SharedDIBWin  mSharedSurfaceDib;
     nsIntRect          mPluginPort;
     nsIntRect          mSharedSize;
     HWND               mPluginHWND;
     WNDPROC            mPluginWndProc;
     bool               mNestedEventState;
 #endif // defined(XP_WIN)
+#if defined(OS_MACOSX)
+private:
+    Shmem mShSurface; 
+    size_t mShWidth;
+    size_t mShHeight;
+#endif // definied(OS_MACOSX)
 };
 
 
 } // namespace plugins
 } // namespace mozilla
 
 #endif // ifndef dom_plugins_PluginInstanceParent_h
--- a/dom/plugins/PluginMessageUtils.h
+++ b/dom/plugins/PluginMessageUtils.h
@@ -56,22 +56,16 @@
 
 namespace mozilla {
 
 // XXX might want to move these to nscore.h or something, they can be
 // generally useful
 struct void_t { };
 struct null_t { };
 
-namespace ipc {
-
-typedef intptr_t NPRemoteIdentifier;
-
-} /* namespace ipc */
-
 namespace plugins {
 
 enum ScriptableObjectType
 {
   LocalObject,
   Proxy
 };
 
@@ -199,23 +193,43 @@ NPNVariableToString(NPNVariable aVar)
 
         VARSTR(NPNVprivateModeBool);
 
     default: return "???";
     }
 }
 #undef VARSTR
 
+inline bool IsPluginThread()
+{
+  MessageLoop::Type type = MessageLoop::current()->type();
+  return type == MessageLoop::TYPE_UI;
+}
 
 inline void AssertPluginThread()
 {
-  NS_ASSERTION(MessageLoopForUI::current(),
-               "should be on the plugin's main thread!");
+  NS_ASSERTION(IsPluginThread(), "Should be on the plugin's main thread!");
 }
 
+#define ENSURE_PLUGIN_THREAD(retval) \
+  PR_BEGIN_MACRO \
+    if (!IsPluginThread()) { \
+      NS_WARNING("Not running on the plugin's main thread!"); \
+      return (retval); \
+    } \
+  PR_END_MACRO
+
+#define ENSURE_PLUGIN_THREAD_VOID() \
+  PR_BEGIN_MACRO \
+    if (!IsPluginThread()) { \
+      NS_WARNING("Not running on the plugin's main thread!"); \
+      return; \
+    } \
+  PR_END_MACRO
+
 void DeferNPObjectLastRelease(const NPNetscapeFuncs* f, NPObject* o);
 void DeferNPVariantLastRelease(const NPNetscapeFuncs* f, NPVariant* v);
 
 // in NPAPI, char* == NULL is sometimes meaningful.  the following is
 // helper code for dealing with nullable nsCString's
 inline nsCString
 NullableString(const char* aString)
 {
@@ -657,16 +671,45 @@ struct ParamTraits<NPNURLVariable>
         *aResult = paramType(intval);
         return true;
       }
     }
     return false;
   }
 };
 
+  
+template<>
+struct ParamTraits<NPCoordinateSpace>
+{
+  typedef NPCoordinateSpace paramType;
+
+  static void Write(Message* aMsg, const paramType& aParam)
+  {
+    WriteParam(aMsg, int32(aParam));
+  }
+
+  static bool Read(const Message* aMsg, void** aIter, paramType* aResult)
+  {
+    int32 intval;
+    if (ReadParam(aMsg, aIter, &intval)) {
+      switch (intval) {
+      case NPCoordinateSpacePlugin:
+      case NPCoordinateSpaceWindow:
+      case NPCoordinateSpaceFlippedWindow:
+      case NPCoordinateSpaceScreen:
+      case NPCoordinateSpaceFlippedScreen:
+        *aResult = paramType(intval);
+        return true;
+      }
+    }
+    return false;
+  }
+};
+
 } /* namespace IPC */
 
 
 // Serializing NPEvents is completely platform-specific and can be rather
 // intricate depending on the platform.  So for readability we split it
 // into separate files and have the only macro crud live here.
 // 
 // NB: these guards are based on those where struct NPEvent is defined
--- a/dom/plugins/PluginModuleChild.cpp
+++ b/dom/plugins/PluginModuleChild.cpp
@@ -55,21 +55,20 @@
 #include "nsPluginsDir.h"
 #include "nsXULAppAPI.h"
 
 #include "mozilla/plugins/PluginInstanceChild.h"
 #include "mozilla/plugins/StreamNotifyChild.h"
 #include "mozilla/plugins/BrowserStreamChild.h"
 #include "mozilla/plugins/PluginStreamChild.h"
 #include "mozilla/plugins/PluginThreadChild.h"
+#include "PluginIdentifierChild.h"
 
 #include "nsNPAPIPlugin.h"
 
-using mozilla::ipc::NPRemoteIdentifier;
-
 using namespace mozilla::plugins;
 
 namespace {
 PluginModuleChild* gInstance = nsnull;
 #ifdef MOZ_WIDGET_QT
 static QApplication *gQApp = nsnull;
 #endif
 }
@@ -123,16 +122,26 @@ PluginModuleChild::Init(const std::strin
 
     NS_ASSERTION(aChannel, "need a channel");
 
     if (!mObjectMap.Init()) {
        NS_WARNING("Failed to initialize object hashtable!");
        return false;
     }
 
+    if (!mStringIdentifiers.Init()) {
+       NS_ERROR("Failed to initialize string identifier hashtable!");
+       return false;
+    }
+
+    if (!mIntIdentifiers.Init()) {
+       NS_ERROR("Failed to initialize int identifier hashtable!");
+       return false;
+    }
+
     if (!InitGraphics())
         return false;
 
     nsCString filename;
     filename = aPluginFilename.c_str();
     nsCOMPtr<nsILocalFile> pluginFile;
     NS_NewNativeLocalFile(filename,
                           PR_TRUE,
@@ -185,16 +194,17 @@ PluginModuleChild::Init(const std::strin
 #  error Please copy the initialization code from nsNPAPIPlugin.cpp
 
 #endif
     return true;
 }
 
 #if defined(MOZ_WIDGET_GTK2)
 typedef void (*GObjectDisposeFn)(GObject*);
+typedef gboolean (*GtkWidgetScrollEventFn)(GtkWidget*, GdkEventScroll*);
 typedef void (*GtkPlugEmbeddedFn)(GtkPlug*);
 
 static GObjectDisposeFn real_gtk_plug_dispose;
 static GtkPlugEmbeddedFn real_gtk_plug_embedded;
 
 static void
 undo_bogus_unref(gpointer data, GObject* object, gboolean is_last_ref) {
     if (!is_last_ref) // recursion in g_object_ref
@@ -219,16 +229,102 @@ wrap_gtk_plug_dispose(GObject* object) {
     // A toggle ref is added to prevent premature deletion of the object
     // caused by Flash Player's extra unref, and to detect when there are
     // unexpectedly no other references.
     g_object_add_toggle_ref(object, undo_bogus_unref, NULL);
     (*real_gtk_plug_dispose)(object);
     g_object_remove_toggle_ref(object, undo_bogus_unref, NULL);
 }
 
+static gboolean
+gtk_plug_scroll_event(GtkWidget *widget, GdkEventScroll *gdk_event)
+{
+    if (!GTK_WIDGET_TOPLEVEL(widget)) // in same process as its GtkSocket
+        return FALSE; // event not handled; propagate to GtkSocket
+
+    GdkWindow* socket_window = GTK_PLUG(widget)->socket_window;
+    if (!socket_window)
+        return FALSE;
+
+    // Propagate the event to the embedder.
+    GdkScreen* screen = gdk_drawable_get_screen(socket_window);
+    GdkWindow* plug_window = widget->window;
+    GdkWindow* event_window = gdk_event->window;
+    gint x = gdk_event->x;
+    gint y = gdk_event->y;
+    unsigned int button;
+    unsigned int button_mask = 0;
+    XEvent xevent;
+    Display* dpy = GDK_WINDOW_XDISPLAY(socket_window);
+
+    /* Translate the event coordinates to the plug window,
+     * which should be aligned with the socket window.
+     */
+    while (event_window != plug_window)
+    {
+        gint dx, dy;
+
+        gdk_window_get_position(event_window, &dx, &dy);
+        x += dx;
+        y += dy;
+
+        event_window = gdk_window_get_parent(event_window);
+        if (!event_window)
+            return FALSE;
+    }
+
+    switch (gdk_event->direction) {
+    case GDK_SCROLL_UP:
+        button = 4;
+        button_mask = Button4Mask;
+        break;
+    case GDK_SCROLL_DOWN:
+        button = 5;
+        button_mask = Button5Mask;
+        break;
+    case GDK_SCROLL_LEFT:
+        button = 6;
+        break;
+    case GDK_SCROLL_RIGHT:
+        button = 7;
+        break;
+    default:
+        return FALSE; // unknown GdkScrollDirection
+    }
+
+    memset(&xevent, 0, sizeof(xevent));
+    xevent.xbutton.type = ButtonPress;
+    xevent.xbutton.window = GDK_WINDOW_XWINDOW(socket_window);
+    xevent.xbutton.root = GDK_WINDOW_XWINDOW(gdk_screen_get_root_window(screen));
+    xevent.xbutton.subwindow = GDK_WINDOW_XWINDOW(plug_window);
+    xevent.xbutton.time = gdk_event->time;
+    xevent.xbutton.x = x;
+    xevent.xbutton.y = y;
+    xevent.xbutton.x_root = gdk_event->x_root;
+    xevent.xbutton.y_root = gdk_event->y_root;
+    xevent.xbutton.state = gdk_event->state;
+    xevent.xbutton.button = button;
+    xevent.xbutton.same_screen = True;
+
+    gdk_error_trap_push();
+
+    XSendEvent(dpy, xevent.xbutton.window,
+               True, ButtonPressMask, &xevent);
+
+    xevent.xbutton.type = ButtonRelease;
+    xevent.xbutton.state |= button_mask;
+    XSendEvent(dpy, xevent.xbutton.window,
+               True, ButtonReleaseMask, &xevent);
+
+    gdk_display_sync(gdk_screen_get_display(screen));
+    gdk_error_trap_pop();
+
+    return TRUE; // event handled
+}
+
 static void
 wrap_gtk_plug_embedded(GtkPlug* plug) {
     GdkWindow* socket_window = plug->socket_window;
     if (socket_window &&
         g_object_get_data(G_OBJECT(socket_window),
                           "moz-existed-before-set-window")) {
         // Add missing reference for
         // https://bugzilla.gnome.org/show_bug.cgi?id=607061
@@ -255,17 +351,17 @@ static const guint kBrowserEventInterval
 // static
 gboolean
 PluginModuleChild::DetectNestedEventLoop(gpointer data)
 {
     PluginModuleChild* pmc = static_cast<PluginModuleChild*>(data);
 
     NS_ABORT_IF_FALSE(0 != pmc->mNestedLoopTimerId,
                       "callback after descheduling");
-    NS_ABORT_IF_FALSE(1 < g_main_depth(),
+    NS_ABORT_IF_FALSE(pmc->mTopLoopDepth < g_main_depth(),
                       "not canceled before returning to main event loop!");
 
     PLUGIN_LOG_DEBUG(("Detected nested glib event loop"));
     fprintf(stderr, "Detected nested glib event loop\n");
     fflush(stderr);
 
     // just detected a nested loop; start a timer that will
     // periodically rpc-call back into the browser and process some
@@ -279,24 +375,22 @@ PluginModuleChild::DetectNestedEventLoop
     // cancel the nested-loop detection timer
     return FALSE;
 }
 
 // static
 gboolean
 PluginModuleChild::ProcessBrowserEvents(gpointer data)
 {
-    NS_ABORT_IF_FALSE(1 < g_main_depth(),
+    PluginModuleChild* pmc = static_cast<PluginModuleChild*>(data);
+
+    NS_ABORT_IF_FALSE(pmc->mTopLoopDepth < g_main_depth(),
                       "not canceled before returning to main event loop!");
 
     PluginModuleChild* pmc = static_cast<PluginModuleChild*>(data);
-
-    fprintf(stderr, "Time to process browser events\n");
-    fflush(stderr);
-
     pmc->CallProcessSomeEvents();
 
     return TRUE;
 }
 
 void
 PluginModuleChild::EnteredCxxStack()
 {
@@ -304,16 +398,20 @@ PluginModuleChild::EnteredCxxStack()
                       "previous timer not descheduled");
 
     mNestedLoopTimerId =
         g_timeout_add_full(kNestedLoopDetectorPriority,
                            kNestedLoopDetectorIntervalMs,
                            PluginModuleChild::DetectNestedEventLoop,
                            this,
                            NULL);
+
+#ifdef DEBUG
+    mTopLoopDepth = g_main_depth();
+#endif
 }
 
 void
 PluginModuleChild::ExitedCxxStack()
 {
     NS_ABORT_IF_FALSE(0 < mNestedLoopTimerId,
                       "nested loop timeout not scheduled");
 
@@ -341,19 +439,34 @@ PluginModuleChild::InitGraphics()
     // called.  (Toggle references wouldn't detect if the reference count
     // might be higher.)
     GObjectDisposeFn* dispose = &G_OBJECT_CLASS(gtk_plug_class)->dispose;
     NS_ABORT_IF_FALSE(*dispose != wrap_gtk_plug_dispose,
                       "InitGraphics called twice");
     real_gtk_plug_dispose = *dispose;
     *dispose = wrap_gtk_plug_dispose;
 
-    GtkPlugEmbeddedFn* embedded = &GTK_PLUG_CLASS(gtk_plug_class)->embedded;
-    real_gtk_plug_embedded = *embedded;
-    *embedded = wrap_gtk_plug_embedded;
+    // If we ever stop setting GDK_NATIVE_WINDOWS, we'll also need to
+    // gtk_widget_add_events GDK_SCROLL_MASK or GDK client-side windows will
+    // not tell us about the scroll events that it intercepts.  With native
+    // windows, this is called when GDK intercepts the events; if GDK doesn't
+    // intercept the events, then the X server will instead send them directly
+    // to an ancestor (embedder) window.
+    GtkWidgetScrollEventFn* scroll_event =
+        &GTK_WIDGET_CLASS(gtk_plug_class)->scroll_event;
+    if (!*scroll_event) {
+        *scroll_event = gtk_plug_scroll_event;
+    }
+
+    if (gtk_check_version(2,18,7) != NULL) { // older
+        GtkPlugEmbeddedFn* embedded = &GTK_PLUG_CLASS(gtk_plug_class)->embedded;
+        real_gtk_plug_embedded = *embedded;
+        *embedded = wrap_gtk_plug_embedded;
+    }
+
 #elif defined(MOZ_WIDGET_QT)
     if (!qApp)
         gQApp = new QApplication(0, NULL);
 #else
     // may not be necessary on all platforms
 #endif
 #ifdef MOZ_X11
     // Do this after initializing GDK, or GDK will install its own handler.
@@ -523,35 +636,16 @@ static void* NP_CALLBACK
 // Deprecated entry points for the old Java plugin.
 static void* NP_CALLBACK /* OJI type: JRIEnv* */
 _getjavaenv(void);
 
 // Deprecated entry points for the old Java plugin.
 static void* NP_CALLBACK /* OJI type: jref */
 _getjavapeer(NPP aNPP);
 
-static NPIdentifier NP_CALLBACK
-_getstringidentifier(const NPUTF8* name);
-
-static void NP_CALLBACK
-_getstringidentifiers(const NPUTF8** names, int32_t nameCount,
-                      NPIdentifier *identifiers);
-
-static bool NP_CALLBACK
-_identifierisstring(NPIdentifier identifiers);
-
-static NPIdentifier NP_CALLBACK
-_getintidentifier(int32_t intid);
-
-static NPUTF8* NP_CALLBACK
-_utf8fromidentifier(NPIdentifier identifier);
-
-static int32_t NP_CALLBACK
-_intfromidentifier(NPIdentifier identifier);
-
 static bool NP_CALLBACK
 _invoke(NPP aNPP, NPObject* npobj, NPIdentifier method, const NPVariant *args,
         uint32_t argCount, NPVariant *result);
 
 static bool NP_CALLBACK
 _invokedefault(NPP aNPP, NPObject* npobj, const NPVariant *args,
                uint32_t argCount, NPVariant *result);
 
@@ -584,20 +678,20 @@ static bool NP_CALLBACK
            uint32_t argCount, NPVariant *result);
 
 static void NP_CALLBACK
 _releasevariantvalue(NPVariant *variant);
 
 static void NP_CALLBACK
 _setexception(NPObject* npobj, const NPUTF8 *message);
 
-static bool NP_CALLBACK
+static void NP_CALLBACK
 _pushpopupsenabledstate(NPP aNPP, NPBool enabled);
 
-static bool NP_CALLBACK
+static void NP_CALLBACK
 _poppopupsenabledstate(NPP aNPP);
 
 static void NP_CALLBACK
 _pluginthreadasynccall(NPP instance, PluginThreadCallback func,
                        void *userData);
 
 static NPError NP_CALLBACK
 _getvalueforurl(NPP npp, NPNURLVariable variable, const char *url,
@@ -652,22 +746,22 @@ const NPNetscapeFuncs PluginModuleChild:
     mozilla::plugins::child::_getjavapeer,
     mozilla::plugins::child::_geturlnotify,
     mozilla::plugins::child::_posturlnotify,
     mozilla::plugins::child::_getvalue,
     mozilla::plugins::child::_setvalue,
     mozilla::plugins::child::_invalidaterect,
     mozilla::plugins::child::_invalidateregion,
     mozilla::plugins::child::_forceredraw,
-    mozilla::plugins::child::_getstringidentifier,
-    mozilla::plugins::child::_getstringidentifiers,
-    mozilla::plugins::child::_getintidentifier,
-    mozilla::plugins::child::_identifierisstring,
-    mozilla::plugins::child::_utf8fromidentifier,
-    mozilla::plugins::child::_intfromidentifier,
+    PluginModuleChild::NPN_GetStringIdentifier,
+    PluginModuleChild::NPN_GetStringIdentifiers,
+    PluginModuleChild::NPN_GetIntIdentifier,
+    PluginModuleChild::NPN_IdentifierIsString,
+    PluginModuleChild::NPN_UTF8FromIdentifier,
+    PluginModuleChild::NPN_IntFromIdentifier,
     PluginModuleChild::NPN_CreateObject,
     PluginModuleChild::NPN_RetainObject,
     PluginModuleChild::NPN_ReleaseObject,
     mozilla::plugins::child::_invoke,
     mozilla::plugins::child::_invokedefault,
     mozilla::plugins::child::_evaluate,
     mozilla::plugins::child::_getproperty,
     mozilla::plugins::child::_setproperty,
@@ -701,32 +795,32 @@ namespace mozilla {
 namespace plugins {
 namespace child {
 
 NPError NP_CALLBACK
 _requestread(NPStream* aStream,
              NPByteRange* aRangeList)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
+    ENSURE_PLUGIN_THREAD(NPERR_INVALID_PARAM);
 
     BrowserStreamChild* bs =
         static_cast<BrowserStreamChild*>(static_cast<AStream*>(aStream->ndata));
     bs->EnsureCorrectStream(aStream);
     return bs->NPN_RequestRead(aRangeList);
 }
 
 NPError NP_CALLBACK
 _geturlnotify(NPP aNPP,
               const char* aRelativeURL,
               const char* aTarget,
               void* aNotifyData)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
+    ENSURE_PLUGIN_THREAD(NPERR_INVALID_PARAM);
 
     nsCString url = NullableString(aRelativeURL);
     StreamNotifyChild* sn = new StreamNotifyChild(url);
 
     NPError err;
     InstCast(aNPP)->CallPStreamNotifyConstructor(
         sn, url, NullableString(aTarget), false, nsCString(), false, &err);
 
@@ -740,17 +834,17 @@ NPError NP_CALLBACK
 }
 
 NPError NP_CALLBACK
 _getvalue(NPP aNPP,
           NPNVariable aVariable,
           void* aValue)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
+    ENSURE_PLUGIN_THREAD(NPERR_INVALID_PARAM);
 
     switch (aVariable) {
         // Copied from nsNPAPIPlugin.cpp
         case NPNVToolkit:
 #ifdef MOZ_WIDGET_GTK2
             *static_cast<NPNToolkitType*>(aValue) = NPNVGtk2;
             return NPERR_NO_ERROR;
 #endif
@@ -785,27 +879,27 @@ NPError NP_CALLBACK
 }
 
 NPError NP_CALLBACK
 _setvalue(NPP aNPP,
           NPPVariable aVariable,
           void* aValue)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
+    ENSURE_PLUGIN_THREAD(NPERR_INVALID_PARAM);
     return InstCast(aNPP)->NPN_SetValue(aVariable, aValue);
 }
 
 NPError NP_CALLBACK
 _geturl(NPP aNPP,
         const char* aRelativeURL,
         const char* aTarget)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
+    ENSURE_PLUGIN_THREAD(NPERR_INVALID_PARAM);
 
     NPError err;
     InstCast(aNPP)->CallNPN_GetURL(NullableString(aRelativeURL),
                                    NullableString(aTarget), &err);
     return err;
 }
 
 NPError NP_CALLBACK
@@ -813,17 +907,17 @@ NPError NP_CALLBACK
                const char* aRelativeURL,
                const char* aTarget,
                uint32_t aLength,
                const char* aBuffer,
                NPBool aIsFile,
                void* aNotifyData)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
+    ENSURE_PLUGIN_THREAD(NPERR_INVALID_PARAM);
 
     if (!aBuffer)
         return NPERR_INVALID_PARAM;
 
     nsCString url = NullableString(aRelativeURL);
     StreamNotifyChild* sn = new StreamNotifyChild(url);
 
     NPError err;
@@ -844,17 +938,17 @@ NPError NP_CALLBACK
 _posturl(NPP aNPP,
          const char* aRelativeURL,
          const char* aTarget,
          uint32_t aLength,
          const char* aBuffer,
          NPBool aIsFile)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
+    ENSURE_PLUGIN_THREAD(NPERR_INVALID_PARAM);
 
     NPError err;
     // FIXME what should happen when |aBuffer| is null?
     InstCast(aNPP)->CallNPN_PostURL(NullableString(aRelativeURL),
                                     NullableString(aTarget),
                                     nsDependentCString(aBuffer, aLength),
                                     aIsFile, &err);
     return err;
@@ -862,43 +956,43 @@ NPError NP_CALLBACK
 
 NPError NP_CALLBACK
 _newstream(NPP aNPP,
            NPMIMEType aMIMEType,
            const char* aWindow,
            NPStream** aStream)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
+    ENSURE_PLUGIN_THREAD(NPERR_INVALID_PARAM);
     return InstCast(aNPP)->NPN_NewStream(aMIMEType, aWindow, aStream);
 }
 
 int32_t NP_CALLBACK
 _write(NPP aNPP,
        NPStream* aStream,
        int32_t aLength,
        void* aBuffer)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
+    ENSURE_PLUGIN_THREAD(0);
 
     PluginStreamChild* ps =
         static_cast<PluginStreamChild*>(static_cast<AStream*>(aStream->ndata));
     ps->EnsureCorrectInstance(InstCast(aNPP));
     ps->EnsureCorrectStream(aStream);
     return ps->NPN_Write(aLength, aBuffer);
 }
 
 NPError NP_CALLBACK
 _destroystream(NPP aNPP,
                NPStream* aStream,
                NPError aReason)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
+    ENSURE_PLUGIN_THREAD(NPERR_INVALID_PARAM);
 
     PluginInstanceChild* p = InstCast(aNPP);
     AStream* s = static_cast<AStream*>(aStream->ndata);
     if (s->IsBrowserStream()) {
         BrowserStreamChild* bs = static_cast<BrowserStreamChild*>(s);
         bs->EnsureCorrectInstance(p);
         bs->NPN_DestroyStream(aReason);
     }
@@ -910,264 +1004,148 @@ NPError NP_CALLBACK
     return NPERR_NO_ERROR;
 }
 
 void NP_CALLBACK
 _status(NPP aNPP,
         const char* aMessage)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
+    ENSURE_PLUGIN_THREAD_VOID();
+    NS_WARNING("Not yet implemented!");
 }
 
 void NP_CALLBACK
 _memfree(void* aPtr)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
+    // Only assert plugin thread here for consistency with in-process plugins.
     AssertPluginThread();
     NS_Free(aPtr);
 }
 
 uint32_t NP_CALLBACK
 _memflush(uint32_t aSize)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
+    // Only assert plugin thread here for consistency with in-process plugins.
     AssertPluginThread();
     return 0;
 }
 
 void NP_CALLBACK
 _reloadplugins(NPBool aReloadPages)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
+    ENSURE_PLUGIN_THREAD_VOID();
+    NS_WARNING("Not yet implemented!");
 }
 
 void NP_CALLBACK
 _invalidaterect(NPP aNPP,
                 NPRect* aInvalidRect)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
+    ENSURE_PLUGIN_THREAD_VOID();
     // NULL check for nspluginwrapper (bug 548434)
     if (aNPP) {
         InstCast(aNPP)->InvalidateRect(aInvalidRect);
     }
 }
 
 void NP_CALLBACK
 _invalidateregion(NPP aNPP,
                   NPRegion aInvalidRegion)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
-    // Not implemented in Mozilla.
+    ENSURE_PLUGIN_THREAD_VOID();
+    NS_WARNING("Not yet implemented!");
 }
 
 void NP_CALLBACK
 _forceredraw(NPP aNPP)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
+    ENSURE_PLUGIN_THREAD_VOID();
+    NS_WARNING("Not yet implemented!");
 }
 
 const char* NP_CALLBACK
 _useragent(NPP aNPP)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
-
+    ENSURE_PLUGIN_THREAD(nsnull);
     return PluginModuleChild::current()->GetUserAgent();
 }
 
 void* NP_CALLBACK
 _memalloc(uint32_t aSize)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
+    // Only assert plugin thread here for consistency with in-process plugins.
     AssertPluginThread();
     return NS_Alloc(aSize);
 }
 
 // Deprecated entry points for the old Java plugin.
 void* NP_CALLBACK /* OJI type: JRIEnv* */
 _getjavaenv(void)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
     return 0;
 }
 
 void* NP_CALLBACK /* OJI type: jref */
 _getjavapeer(NPP aNPP)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
     return 0;
 }
 
-NPIdentifier NP_CALLBACK
-_getstringidentifier(const NPUTF8* aName)
-{
-    PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
-
-    NPRemoteIdentifier ident = 0;
-    if (aName)
-        PluginModuleChild::current()->
-            SendNPN_GetStringIdentifier(nsDependentCString(aName), &ident);
-    return (NPIdentifier)ident;
-}
-
-void NP_CALLBACK
-_getstringidentifiers(const NPUTF8** aNames,
-                      int32_t aNameCount,
-                      NPIdentifier* aIdentifiers)
-{
-    PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
-
-    if (!(aNames && aNameCount > 0 && aIdentifiers)) {
-        NS_RUNTIMEABORT("Bad input! Headed for a crash!");
-    }
-
-    // Initialize to zero in case of errors later
-    for (int32_t index = 0; index < aNameCount; ++index)
-        aIdentifiers[index] = 0;
-
-    nsTArray<nsCString> names;
-    nsTArray<NPRemoteIdentifier> ids;
-
-    names.SetLength(aNameCount);
-    for (int32_t index = 0; index < aNameCount; ++index) {
-        if (aNames[index]) {
-            names[index] = nsDependentCString(aNames[index]);
-        }
-        else {
-            names[index].SetIsVoid(true);
-        }
-    }
-
-    PluginModuleChild::current()->
-        SendNPN_GetStringIdentifiers(names, &ids);
-
-    for (int32_t index = 0; index < ids.Length(); ++index)
-        aIdentifiers[index] = (NPIdentifier)ids[index];
-}
-
-bool NP_CALLBACK
-_identifierisstring(NPIdentifier aIdentifier)
-{
-    PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
-
-    bool isString;
-    if (!PluginModuleChild::current()->
-             SendNPN_IdentifierIsString((NPRemoteIdentifier)aIdentifier,
-                                        &isString)) {
-        NS_WARNING("Failed to send message!");
-        isString = false;
-    }
-
-    return isString;
-}
-
-NPIdentifier NP_CALLBACK
-_getintidentifier(int32_t aIntId)
-{
-    PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
-
-    NPRemoteIdentifier ident;
-    if (!PluginModuleChild::current()->
-             SendNPN_GetIntIdentifier(aIntId, &ident)) {
-        NS_WARNING("Failed to send message!");
-        ident = 0;
-    }
-
-    return (NPIdentifier)ident;
-}
-
-NPUTF8* NP_CALLBACK
-_utf8fromidentifier(NPIdentifier aIdentifier)
-{
-    PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
-
-    NPError err;
-    nsCAutoString val;
-    if (!PluginModuleChild::current()->
-             SendNPN_UTF8FromIdentifier((NPRemoteIdentifier)aIdentifier,
-                                         &err, &val)) {
-        NS_WARNING("Failed to send message!");
-        return 0;
-    }
-
-    return (NPERR_NO_ERROR == err) ? strdup(val.get()) : 0;
-}
-
-int32_t NP_CALLBACK
-_intfromidentifier(NPIdentifier aIdentifier)
-{
-    PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
-
-    NPError err;
-    int32_t val;
-    if (!PluginModuleChild::current()->
-             SendNPN_IntFromIdentifier((NPRemoteIdentifier)aIdentifier,
-                                       &err, &val)) {
-        NS_WARNING("Failed to send message!");
-        return -1;
-    }
-
-    // -1 for consistency
-    return (NPERR_NO_ERROR == err) ? val : -1;
-}
-
 bool NP_CALLBACK
 _invoke(NPP aNPP,
         NPObject* aNPObj,
         NPIdentifier aMethod,
         const NPVariant* aArgs,
         uint32_t aArgCount,
         NPVariant* aResult)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
+    ENSURE_PLUGIN_THREAD(false);
 
     if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->invoke)
         return false;
 
     return aNPObj->_class->invoke(aNPObj, aMethod, aArgs, aArgCount, aResult);
 }
 
 bool NP_CALLBACK
 _invokedefault(NPP aNPP,
                NPObject* aNPObj,
                const NPVariant* aArgs,
                uint32_t aArgCount,
                NPVariant* aResult)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
+    ENSURE_PLUGIN_THREAD(false);
 
     if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->invokeDefault)
         return false;
 
     return aNPObj->_class->invokeDefault(aNPObj, aArgs, aArgCount, aResult);
 }
 
 bool NP_CALLBACK
 _evaluate(NPP aNPP,
           NPObject* aObject,
           NPString* aScript,
           NPVariant* aResult)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
+    ENSURE_PLUGIN_THREAD(false);
 
     if (!(aNPP && aObject && aScript && aResult)) {
         NS_ERROR("Bad arguments!");
         return false;
     }
 
     PluginScriptableObjectChild* actor =
       InstCast(aNPP)->GetActorForNPObject(aObject);
@@ -1181,89 +1159,89 @@ bool NP_CALLBACK
 
 bool NP_CALLBACK
 _getproperty(NPP aNPP,
              NPObject* aNPObj,
              NPIdentifier aPropertyName,
              NPVariant* aResult)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
+    ENSURE_PLUGIN_THREAD(false);
 
     if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->getProperty)
         return false;
 
     return aNPObj->_class->getProperty(aNPObj, aPropertyName, aResult);
 }
 
 bool NP_CALLBACK
 _setproperty(NPP aNPP,
              NPObject* aNPObj,
              NPIdentifier aPropertyName,
              const NPVariant* aValue)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
+    ENSURE_PLUGIN_THREAD(false);
 
     if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->setProperty)
         return false;
 
     return aNPObj->_class->setProperty(aNPObj, aPropertyName, aValue);
 }
 
 bool NP_CALLBACK
 _removeproperty(NPP aNPP,
                 NPObject* aNPObj,
                 NPIdentifier aPropertyName)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
+    ENSURE_PLUGIN_THREAD(false);
 
     if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->removeProperty)
         return false;
 
     return aNPObj->_class->removeProperty(aNPObj, aPropertyName);
 }
 
 bool NP_CALLBACK
 _hasproperty(NPP aNPP,
              NPObject* aNPObj,
              NPIdentifier aPropertyName)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
+    ENSURE_PLUGIN_THREAD(false);
 
     if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->hasProperty)
         return false;
 
     return aNPObj->_class->hasProperty(aNPObj, aPropertyName);
 }
 
 bool NP_CALLBACK
 _hasmethod(NPP aNPP,
            NPObject* aNPObj,
            NPIdentifier aMethodName)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
+    ENSURE_PLUGIN_THREAD(false);
 
     if (!aNPP || !aNPObj || !aNPObj->_class || !aNPObj->_class->hasMethod)
         return false;
 
     return aNPObj->_class->hasMethod(aNPObj, aMethodName);
 }
 
 bool NP_CALLBACK
 _enumerate(NPP aNPP,
            NPObject* aNPObj,
            NPIdentifier** aIdentifiers,
            uint32_t* aCount)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
+    ENSURE_PLUGIN_THREAD(false);
 
     if (!aNPP || !aNPObj || !aNPObj->_class)
         return false;
 
     if (!NP_CLASS_STRUCT_VERSION_HAS_ENUM(aNPObj->_class) ||
         !aNPObj->_class->enumerate) {
         *aIdentifiers = 0;
         *aCount = 0;
@@ -1276,31 +1254,32 @@ bool NP_CALLBACK
 bool NP_CALLBACK
 _construct(NPP aNPP,
            NPObject* aNPObj,
            const NPVariant* aArgs,
            uint32_t aArgCount,
            NPVariant* aResult)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
+    ENSURE_PLUGIN_THREAD(false);
 
     if (!aNPP || !aNPObj || !aNPObj->_class ||
         !NP_CLASS_STRUCT_VERSION_HAS_CTOR(aNPObj->_class) ||
         !aNPObj->_class->construct) {
         return false;
     }
 
     return aNPObj->_class->construct(aNPObj, aArgs, aArgCount, aResult);
 }
 
 void NP_CALLBACK
 _releasevariantvalue(NPVariant* aVariant)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
+    // Only assert plugin thread here for consistency with in-process plugins.
     AssertPluginThread();
 
     if (NPVARIANT_IS_STRING(*aVariant)) {
         NPString str = NPVARIANT_TO_STRING(*aVariant);
         free(const_cast<NPUTF8*>(str.UTF8Characters));
     }
     else if (NPVARIANT_IS_OBJECT(*aVariant)) {
         NPObject* object = NPVARIANT_TO_OBJECT(*aVariant);
@@ -1311,44 +1290,37 @@ void NP_CALLBACK
     VOID_TO_NPVARIANT(*aVariant);
 }
 
 void NP_CALLBACK
 _setexception(NPObject* aNPObj,
               const NPUTF8* aMessage)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
-    NS_NOTYETIMPLEMENTED("Implement me!");
+    ENSURE_PLUGIN_THREAD_VOID();
+    NS_WARNING("Not yet implemented!");
 }
 
-bool NP_CALLBACK
+void NP_CALLBACK
 _pushpopupsenabledstate(NPP aNPP,
                         NPBool aEnabled)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
-    bool retval;
-    if (InstCast(aNPP)->CallNPN_PushPopupsEnabledState(aEnabled ? true : false,
-                                                       &retval)) {
-        return retval;
-    }
-    return false;
+    ENSURE_PLUGIN_THREAD_VOID();
+
+    InstCast(aNPP)->CallNPN_PushPopupsEnabledState(aEnabled ? true : false);
 }
 
-bool NP_CALLBACK
+void NP_CALLBACK
 _poppopupsenabledstate(NPP aNPP)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
-    bool retval;
-    if (InstCast(aNPP)->CallNPN_PopPopupsEnabledState(&retval)) {
-        return retval;
-    }
-    return false;
+    ENSURE_PLUGIN_THREAD_VOID();
+
+    InstCast(aNPP)->CallNPN_PopPopupsEnabledState();
 }
 
 void NP_CALLBACK
 _pluginthreadasynccall(NPP aNPP,
                        PluginThreadCallback aFunc,
                        void* aUserData)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
@@ -1450,46 +1422,59 @@ NPError NP_CALLBACK
 }
 
 uint32_t NP_CALLBACK
 _scheduletimer(NPP npp, uint32_t interval, NPBool repeat,
                void (*timerFunc)(NPP npp, uint32_t timerID))
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
     AssertPluginThread();
-
     return InstCast(npp)->ScheduleTimer(interval, repeat, timerFunc);
 }
 
 void NP_CALLBACK
 _unscheduletimer(NPP npp, uint32_t timerID)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
     AssertPluginThread();
     InstCast(npp)->UnscheduleTimer(timerID);
 }
 
 NPError NP_CALLBACK
 _popupcontextmenu(NPP instance, NPMenu* menu)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
     AssertPluginThread();
-    NS_NOTYETIMPLEMENTED("Implement me!");
+    NS_WARNING("Not yet implemented!");
     return NPERR_GENERIC_ERROR;
 }
 
 NPBool NP_CALLBACK
 _convertpoint(NPP instance, 
               double sourceX, double sourceY, NPCoordinateSpace sourceSpace,
               double *destX, double *destY, NPCoordinateSpace destSpace)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
     AssertPluginThread();
-    NS_NOTYETIMPLEMENTED("Implement me!");
-    return 0;
+
+    double rDestX = 0;
+    bool ignoreDestX = !destX;
+    double rDestY = 0;
+    bool ignoreDestY = !destY;
+    bool result = false;
+    InstCast(instance)->CallNPN_ConvertPoint(sourceX, sourceY, sourceSpace, destSpace,
+                                             &rDestX, &ignoreDestX, &rDestY, &ignoreDestY, &result);
+    if (result) {
+        if (destX)
+            *destX = rDestX;
+        if (destY)
+            *destY = rDestY;
+    }
+
+    return result;
 }
 
 } /* namespace child */
 } /* namespace plugins */
 } /* namespace mozilla */
 
 //-----------------------------------------------------------------------------
 
@@ -1497,35 +1482,73 @@ bool
 PluginModuleChild::AnswerNP_Initialize(NPError* _retval)
 {
     PLUGIN_LOG_DEBUG_METHOD;
     AssertPluginThread();
 
 #if defined(OS_LINUX)
     *_retval = mInitializeFunc(&sBrowserFuncs, &mFunctions);
     return true;
+#elif defined(OS_WIN)
+    nsresult rv = mGetEntryPointsFunc(&mFunctions);
+    if (NS_FAILED(rv)) {
+        return false;
+    }
+    NS_ASSERTION(HIBYTE(mFunctions.version) >= NP_VERSION_MAJOR,
+                 "callback version is less than NP version");
 
-#elif defined(OS_WIN) || defined(OS_MACOSX)
+    *_retval = mInitializeFunc(&sBrowserFuncs);
+    return true;
+#elif defined(OS_MACOSX)
+    *_retval = mInitializeFunc(&sBrowserFuncs);
+
     nsresult rv = mGetEntryPointsFunc(&mFunctions);
     if (NS_FAILED(rv)) {
         return false;
     }
 
-#ifdef OS_WIN
-    NS_ASSERTION(HIBYTE(mFunctions.version) >= NP_VERSION_MAJOR,
-                 "callback version is less than NP version");
-#endif
-
-    *_retval = mInitializeFunc(&sBrowserFuncs);
     return true;
 #else
 #  error Please implement me for your platform
 #endif
 }
 
+PPluginIdentifierChild*
+PluginModuleChild::AllocPPluginIdentifier(const nsCString& aString,
+                                          const int32_t& aInt)
+{
+    // There's a possibility that we already have an actor that wraps the same
+    // string or int because we do all this identifier construction
+    // asynchronously. Check to see if we've already wrapped here, and then set
+    // canonical actor of the new one to the actor already in our hash.
+    PluginIdentifierChild* newActor;
+    PluginIdentifierChild* existingActor;
+
+    if (aString.IsVoid()) {
+        newActor = new PluginIdentifierChildInt(aInt);
+        if (mIntIdentifiers.Get(aInt, &existingActor)) {
+            newActor->SetCanonicalIdentifier(existingActor);
+        }
+    }
+    else {
+        newActor = new PluginIdentifierChildString(aString);
+        if (mStringIdentifiers.Get(aString, &existingActor)) {
+            newActor->SetCanonicalIdentifier(existingActor);
+        }
+    }
+    return newActor;
+}
+
+bool
+PluginModuleChild::DeallocPPluginIdentifier(PPluginIdentifierChild* aActor)
+{
+    delete aActor;
+    return true;
+}
+
 PPluginInstanceChild*
 PluginModuleChild::AllocPPluginInstance(const nsCString& aMimeType,
                                         const uint16_t& aMode,
                                         const nsTArray<nsCString>& aNames,
                                         const nsTArray<nsCString>& aValues,
                                         NPError* rv)
 {
     PLUGIN_LOG_DEBUG_METHOD;
@@ -1597,17 +1620,17 @@ PluginModuleChild::DeallocPPluginInstanc
 
     return true;
 }
 
 NPObject* NP_CALLBACK
 PluginModuleChild::NPN_CreateObject(NPP aNPP, NPClass* aClass)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
-    AssertPluginThread();
+    ENSURE_PLUGIN_THREAD(nsnull);
 
     PluginInstanceChild* i = InstCast(aNPP);
     if (i->mDeletingHash) {
         NS_ERROR("Plugin used NPP after NPP_Destroy");
         return NULL;
     }
 
     NPObject* newObject;
@@ -1704,8 +1727,116 @@ PluginModuleChild::CollectForInstance(NP
 {
     PluginInstanceChild* instance = static_cast<PluginInstanceChild*>(userArg);
     if (d->instance == instance) {
         NPObject* o = d->GetKey();
         instance->mDeletingHash->PutEntry(o);
     }
     return PL_DHASH_NEXT;
 }
+
+NPIdentifier NP_CALLBACK
+PluginModuleChild::NPN_GetStringIdentifier(const NPUTF8* aName)
+{
+    PLUGIN_LOG_DEBUG_FUNCTION;
+    AssertPluginThread();
+
+    if (!aName)
+        return 0;
+
+    PluginModuleChild* self = PluginModuleChild::current();
+    nsDependentCString name(aName);
+
+    PluginIdentifierChild* ident;
+    if (!self->mStringIdentifiers.Get(name, &ident)) {
+        nsCString nameCopy(name);
+
+        ident = new PluginIdentifierChildString(nameCopy);
+        self->SendPPluginIdentifierConstructor(ident, nameCopy, -1);
+        self->mStringIdentifiers.Put(nameCopy, ident);
+    }
+
+    return ident;
+}
+
+void NP_CALLBACK
+PluginModuleChild::NPN_GetStringIdentifiers(const NPUTF8** aNames,
+                                            int32_t aNameCount,
+                                            NPIdentifier* aIdentifiers)
+{
+    PLUGIN_LOG_DEBUG_FUNCTION;
+    AssertPluginThread();
+
+    if (!(aNames && aNameCount > 0 && aIdentifiers)) {
+        NS_RUNTIMEABORT("Bad input! Headed for a crash!");
+    }
+
+    PluginModuleChild* self = PluginModuleChild::current();
+
+    for (int32_t index = 0; index < aNameCount; ++index) {
+        if (!aNames[index]) {
+            aIdentifiers[index] = 0;
+            continue;
+        }
+        nsDependentCString name(aNames[index]);
+        PluginIdentifierChild* ident;
+        if (!self->mStringIdentifiers.Get(name, &ident)) {
+            nsCString nameCopy(name);
+
+            ident = new PluginIdentifierChildString(nameCopy);
+            self->SendPPluginIdentifierConstructor(ident, nameCopy, -1);
+            self->mStringIdentifiers.Put(nameCopy, ident);
+        }
+        aIdentifiers[index] = ident;
+    }
+}
+
+bool NP_CALLBACK
+PluginModuleChild::NPN_IdentifierIsString(NPIdentifier aIdentifier)
+{
+    PLUGIN_LOG_DEBUG_FUNCTION;
+
+    PluginIdentifierChild* ident =
+        static_cast<PluginIdentifierChild*>(aIdentifier);
+    return ident->IsString();
+}
+
+NPIdentifier NP_CALLBACK
+PluginModuleChild::NPN_GetIntIdentifier(int32_t aIntId)
+{
+    PLUGIN_LOG_DEBUG_FUNCTION;
+    AssertPluginThread();
+
+    PluginModuleChild* self = PluginModuleChild::current();
+
+    PluginIdentifierChild* ident;
+    if (!self->mIntIdentifiers.Get(aIntId, &ident)) {
+        nsCString voidString;
+        voidString.SetIsVoid(PR_TRUE);
+
+        ident = new PluginIdentifierChildInt(aIntId);
+        self->SendPPluginIdentifierConstructor(ident, voidString, aIntId);
+        self->mIntIdentifiers.Put(aIntId, ident);
+    }
+    return ident;
+}
+
+NPUTF8* NP_CALLBACK
+PluginModuleChild::NPN_UTF8FromIdentifier(NPIdentifier aIdentifier)
+{
+    PLUGIN_LOG_DEBUG_FUNCTION;
+
+    if (static_cast<PluginIdentifierChild*>(aIdentifier)->IsString()) {
+      return static_cast<PluginIdentifierChildString*>(aIdentifier)->ToString();
+    }
+    return nsnull;
+}
+
+int32_t NP_CALLBACK
+PluginModuleChild::NPN_IntFromIdentifier(NPIdentifier aIdentifier)
+{
+    PLUGIN_LOG_DEBUG_FUNCTION;
+
+    if (static_cast<PluginIdentifierChild*>(aIdentifier)->IsString()) {
+      return static_cast<PluginIdentifierChildInt*>(aIdentifier)->ToInt();
+    }
+    return PR_INT32_MIN;
+}
--- a/dom/plugins/PluginModuleChild.h
+++ b/dom/plugins/PluginModuleChild.h
@@ -46,21 +46,23 @@
 #include "base/basictypes.h"
 
 #include "prlink.h"
 
 #include "npapi.h"
 #include "npfunctions.h"
 
 #include "nsAutoPtr.h"
+#include "nsDataHashtable.h"
 #include "nsTHashtable.h"
 #include "nsHashKeys.h"
 
 #include "mozilla/plugins/PPluginModuleChild.h"
 #include "mozilla/plugins/PluginInstanceChild.h"
+#include "mozilla/plugins/PluginIdentifierChild.h"
 
 // NOTE: stolen from nsNPAPIPlugin.h
 
 /*
  * Use this macro before each exported function
  * (between the return address and the function
  * itself), to ensure that the function has the
  * right calling conventions on OS/2.
@@ -98,16 +100,23 @@ protected:
     MediateRPCRace(const Message& parent, const Message& child)
     {
         return MediateRace(parent, child);
     }
 
     // Implement the PPluginModuleChild interface
     virtual bool AnswerNP_Initialize(NPError* rv);
 
+    virtual PPluginIdentifierChild*
+    AllocPPluginIdentifier(const nsCString& aString,
+                           const int32_t& aInt);
+
+    virtual bool
+    DeallocPPluginIdentifier(PPluginIdentifierChild* aActor);
+
     virtual PPluginInstanceChild*
     AllocPPluginInstance(const nsCString& aMimeType,
                          const uint16_t& aMode,
                          const nsTArray<nsCString>& aNames,
                          const nsTArray<nsCString>& aValues,
                          NPError* rv);
 
     virtual bool
@@ -162,16 +171,28 @@ public:
      * The child implementation of NPN_RetainObject.
      */
     static NPObject* NP_CALLBACK NPN_RetainObject(NPObject* aNPObj);
     /**
      * The child implementation of NPN_ReleaseObject.
      */
     static void NP_CALLBACK NPN_ReleaseObject(NPObject* aNPObj);
 
+    /**
+     * The child implementations of NPIdentifier-related functions.
+     */
+    static NPIdentifier NP_CALLBACK NPN_GetStringIdentifier(const NPUTF8* aName);
+    static void NP_CALLBACK NPN_GetStringIdentifiers(const NPUTF8** aNames,
+                                                     int32_t aNameCount,
+                                                     NPIdentifier* aIdentifiers);
+    static NPIdentifier NP_CALLBACK NPN_GetIntIdentifier(int32_t aIntId);
+    static bool NP_CALLBACK NPN_IdentifierIsString(NPIdentifier aIdentifier);
+    static NPUTF8* NP_CALLBACK NPN_UTF8FromIdentifier(NPIdentifier aIdentifier);
+    static int32_t NP_CALLBACK NPN_IntFromIdentifier(NPIdentifier aIdentifier);
+
 private:
     bool InitGraphics();
 #if defined(MOZ_WIDGET_GTK2)
     static gboolean DetectNestedEventLoop(gpointer data);
     static gboolean ProcessBrowserEvents(gpointer data);
 
     NS_OVERRIDE
     virtual void EnteredCxxStack();
@@ -221,16 +242,23 @@ private:
     //
     // Because only timer (1) or (2) (or neither) may be active at any
     // point in time, we use the same member variable
     // |mNestedLoopTimerId| to refer to both.
     //
     // When the browser no longer might be blocked on a plugin's IPC
     // response, we deschedule whichever of (1) or (2) is active.
     guint mNestedLoopTimerId;
+#  ifdef DEBUG
+    // Depth of the stack of calls to g_main_context_dispatch before any
+    // nested loops are run.  This is 1 when IPC calls are dispatched from
+    // g_main_context_iteration, or 0 when dispatched directly from
+    // MessagePumpForUI.
+    int mTopLoopDepth;
+#  endif
 #endif
 
     struct NPObjectData : public nsPtrHashKey<NPObject>
     {
         NPObjectData(const NPObject* key)
             : nsPtrHashKey<NPObject>(key)
             , instance(NULL)
             , actor(NULL)
@@ -243,16 +271,19 @@ private:
         PluginScriptableObjectChild* actor;
     };
     /**
      * mObjectMap contains all the currently active NPObjects (from NPN_CreateObject until the
      * final release/dealloc, whether or not an actor is currently associated with the object.
      */
     nsTHashtable<NPObjectData> mObjectMap;
 
+    nsDataHashtable<nsCStringHashKey, PluginIdentifierChild*> mStringIdentifiers;
+    nsDataHashtable<nsUint32HashKey, PluginIdentifierChild*> mIntIdentifiers;
+
 public: // called by PluginInstanceChild
     /**
      * Dealloc an NPObject after last-release or when the associated instance
      * is destroyed. This function will remove the object from mObjectMap.
      */
     static void DeallocNPObject(NPObject* o);
 
     NPError NPP_Destroy(PluginInstanceChild* instance) {
--- a/dom/plugins/PluginModuleParent.cpp
+++ b/dom/plugins/PluginModuleParent.cpp
@@ -40,33 +40,34 @@
 #include <glib.h>
 #endif
 
 #include "base/process_util.h"
 
 #include "mozilla/ipc/SyncChannel.h"
 #include "mozilla/plugins/PluginModuleParent.h"
 #include "mozilla/plugins/BrowserStreamParent.h"
+#include "PluginIdentifierParent.h"
 
 #include "nsContentUtils.h"
 #include "nsCRT.h"
+#ifdef MOZ_CRASHREPORTER
+#include "nsExceptionHandler.h"
+#endif
 #include "nsNPAPIPlugin.h"
 
 using base::KillProcess;
 
 using mozilla::PluginLibrary;
-using mozilla::ipc::NPRemoteIdentifier;
 using mozilla::ipc::SyncChannel;
 
 using namespace mozilla::plugins;
 
 static const char kTimeoutPref[] = "dom.ipc.plugins.timeoutSecs";
 
-PR_STATIC_ASSERT(sizeof(NPIdentifier) == sizeof(void*));
-
 template<>
 struct RunnableMethodTraits<mozilla::plugins::PluginModuleParent>
 {
     typedef mozilla::plugins::PluginModuleParent Class;
     static void RetainCallee(Class* obj) { }
     static void ReleaseCallee(Class* obj) { }
 };
 
@@ -89,127 +90,113 @@ PluginModuleParent::LoadModule(const cha
 
 
 PluginModuleParent::PluginModuleParent(const char* aFilePath)
     : mSubprocess(new PluginProcessParent(aFilePath))
     , mShutdown(false)
     , mNPNIface(NULL)
     , mPlugin(NULL)
     , mProcessStartTime(time(NULL))
-    , mPluginCrashedTask(NULL)
+    , mTaskFactory(this)
 {
     NS_ASSERTION(mSubprocess, "Out of memory!");
 
-    if (!mValidIdentifiers.Init()) {
+    if (!mIdentifiers.Init()) {
         NS_ERROR("Out of memory");
     }
 
     nsContentUtils::RegisterPrefCallback(kTimeoutPref, TimeoutChanged, this);
 }
 
 PluginModuleParent::~PluginModuleParent()
 {
     NS_ASSERTION(OkToCleanup(), "unsafe destruction");
 
-    if (mPluginCrashedTask) {
-        mPluginCrashedTask->Cancel();
-        mPluginCrashedTask = 0;
-    }
-
     if (!mShutdown) {
         NS_WARNING("Plugin host deleted the module without shutting down.");
         NPError err;
         NP_Shutdown(&err);
     }
     NS_ASSERTION(mShutdown, "NP_Shutdown didn't");
 
     if (mSubprocess) {
         mSubprocess->Delete();
         mSubprocess = nsnull;
     }
 
     nsContentUtils::UnregisterPrefCallback(kTimeoutPref, TimeoutChanged, this);
 }
 
+#ifdef MOZ_CRASHREPORTER
 void
-PluginModuleParent::WriteExtraDataEntry(nsIFileOutputStream* stream,
-                                        const char* key,
-                                        const char* value)
+PluginModuleParent::WritePluginExtraDataForMinidump(const nsAString& id)
 {
-    PRUint32 written;
-    stream->Write(key, strlen(key), &written);
-    stream->Write("=", 1, &written);
-    stream->Write(value, strlen(value), &written);
-    stream->Write("\n", 1, &written);
-}
+    typedef nsDependentCString CS;
 
-void
-PluginModuleParent::WriteExtraDataForMinidump(nsIFile* dumpFile)
-{
-    // get a reference to the extra file, and add some more entries
-    nsCOMPtr<nsIFile> extraFile;
-    nsresult rv = dumpFile->Clone(getter_AddRefs(extraFile));
-    if (NS_FAILED(rv))
+    CrashReporter::AnnotationTable notes;
+    if (!notes.Init(32))
         return;
 
-    nsAutoString leafName;
-    rv = extraFile->GetLeafName(leafName);
-    if (NS_FAILED(rv))
-        return;
+    notes.Put(CS("ProcessType"), CS("plugin"));
 
-    leafName.Replace(leafName.Length() - 3, 3,
-                     NS_LITERAL_STRING("extra"));
-    rv = extraFile->SetLeafName(leafName);
-    if (NS_FAILED(rv))
-        return;
-
-    nsCOMPtr<nsIFileOutputStream> stream =
-        do_CreateInstance("@mozilla.org/network/file-output-stream;1");
-    // PR_WRONLY | PR_APPEND
-    rv = stream->Init(extraFile, 0x12, 0600, 0);
-    if (NS_FAILED(rv))
-        return;
-    WriteExtraDataEntry(stream, "ProcessType", "plugin");
     char startTime[32];
     sprintf(startTime, "%lld", static_cast<PRInt64>(mProcessStartTime));
-    WriteExtraDataEntry(stream, "StartupTime", startTime);
+    notes.Put(CS("StartupTime"), CS(startTime));
 
     // Get the plugin filename, try to get just the file leafname
     const std::string& pluginFile = mSubprocess->GetPluginFilePath();
     size_t filePos = pluginFile.rfind(FILE_PATH_SEPARATOR);
     if (filePos == std::string::npos)
         filePos = 0;
     else
         filePos++;
-    WriteExtraDataEntry(stream, "PluginFilename",
-                        pluginFile.substr(filePos).c_str());
+    notes.Put(CS("PluginFilename"), CS(pluginFile.substr(filePos).c_str()));
+
     //TODO: add plugin name and version: bug 539841
     // (as PluginName, PluginVersion)
-    WriteExtraDataEntry(stream, "PluginName", "");
-    WriteExtraDataEntry(stream, "PluginVersion", "");
+    notes.Put(CS("PluginName"), CS(""));
+    notes.Put(CS("PluginVersion"), CS(""));
+
+    if (!mCrashNotes.IsEmpty())
+        notes.Put(CS("Notes"), CS(mCrashNotes.get()));
 
-    if (!mCrashNotes.IsEmpty()) {
-        WriteExtraDataEntry(stream, "Notes", mCrashNotes.get());
-    }
+    if (!mHangID.IsEmpty())
+        notes.Put(CS("HangID"), NS_ConvertUTF16toUTF8(mHangID));
 
-    stream->Close();
+    if (!CrashReporter::AppendExtraData(id, notes))
+        NS_WARNING("problem appending plugin data to .extra");
 }
 
+void
+PluginModuleParent::WriteExtraDataForHang()
+{
+    // this writes HangID
+    WritePluginExtraDataForMinidump(mPluginDumpID);
+
+    CrashReporter::AnnotationTable notes;
+    if (!notes.Init(4))
+        return;
+
+    notes.Put(nsDependentCString("HangID"), NS_ConvertUTF16toUTF8(mHangID));
+    if (!CrashReporter::AppendExtraData(mBrowserDumpID, notes))
+        NS_WARNING("problem appending browser data to .extra");
+}
+#endif  // MOZ_CRASHREPORTER
 
 bool
 PluginModuleParent::RecvAppendNotesToCrashReport(const nsCString& aNotes)
 {
     mCrashNotes.Append(aNotes);
     return true;
 }
 
 int
 PluginModuleParent::TimeoutChanged(const char* aPref, void* aModule)
 {
-    AssertPluginThread();
+    NS_ASSERTION(NS_IsMainThread(), "Wrong thead!");
     NS_ABORT_IF_FALSE(!strcmp(aPref, kTimeoutPref),
                       "unexpected pref callback");
 
     PRInt32 timeoutSecs = nsContentUtils::GetIntPref(kTimeoutPref, 0);
     int32 timeoutMs = (timeoutSecs > 0) ? (1000 * timeoutSecs) :
                       SyncChannel::kNoTimeout;
 
     static_cast<PluginModuleParent*>(aModule)->SetReplyTimeoutMs(timeoutMs);
@@ -221,96 +208,129 @@ PluginModuleParent::CleanupFromTimeout()
 {
     if (!mShutdown)
         Close();
 }
 
 bool
 PluginModuleParent::ShouldContinueFromReplyTimeout()
 {
-    // FIXME/bug 544095: pop up a dialog asking the user what to do
-    bool waitMoar = false;
+#ifdef MOZ_CRASHREPORTER
+    nsCOMPtr<nsILocalFile> pluginDump;
+    nsCOMPtr<nsILocalFile> browserDump;
+    if (CrashReporter::CreatePairedMinidumps(OtherProcess(),
+                                             &mHangID,
+                                             getter_AddRefs(pluginDump),
+                                             getter_AddRefs(browserDump)) &&
+        CrashReporter::GetIDFromMinidump(pluginDump, mPluginDumpID) &&
+        CrashReporter::GetIDFromMinidump(browserDump, mBrowserDumpID)) {
 
-    if (!waitMoar) {
-        // We can't depend on the IO thread notifying us of a channel
-        // error, because there's an inherent race between killing the
-        // subprocess and shutting down the socket.  It would be nice
-        // to call Close() here and do all the IPDL cleanup
-        // immediately, but we might have arbitrary junk below us on
-        // the stack.  So, a compromise: enqueue an event now that
-        // will Close(), *before* killing the child process.  This
-        // guarantees that the Close() event will be processed before
-        // the IO error event, if it's delivered.
-        MessageLoop::current()->PostTask(
-            FROM_HERE,
-            NewRunnableMethod(this, &PluginModuleParent::CleanupFromTimeout));
+        PLUGIN_LOG_DEBUG(
+            ("generated paired browser/plugin minidumps: %s/%s (ID=%s)",
+             NS_ConvertUTF16toUTF8(mBrowserDumpID).get(),
+             NS_ConvertUTF16toUTF8(mPluginDumpID).get(),
+             NS_ConvertUTF16toUTF8(mHangID).get()));
+    }
+    else {
+        NS_WARNING("failed to capture paired minidumps from hang");
+    }
+#endif
 
-        // FIXME/bug 544095: kill the subprocess in a way that
-        // triggers breakpad, and also capture a minidump for this
-        // process
-        KillProcess(ChildProcessHandle(), 1, false);
-    }
-    
+    // this must run before the error notification from the channel,
+    // or not at all
+    MessageLoop::current()->PostTask(
+        FROM_HERE,
+        mTaskFactory.NewRunnableMethod(
+            &PluginModuleParent::CleanupFromTimeout));
 
-    return waitMoar;
+    if (!KillProcess(OtherProcess(), 1, false))
+        NS_WARNING("failed to kill subprocess!");
+
+    return false;
 }
 
 void
 PluginModuleParent::ActorDestroy(ActorDestroyReason why)
 {
     switch (why) {
     case AbnormalShutdown: {
-        nsCOMPtr<nsIFile> dump;
-        if (TakeMinidump(getter_AddRefs(dump))) {
-            WriteExtraDataForMinidump(dump);
-            if (NS_SUCCEEDED(dump->GetLeafName(mDumpID))) {
-                mDumpID.Replace(mDumpID.Length() - 4, 4,
-                                NS_LITERAL_STRING(""));
-            }
+#ifdef MOZ_CRASHREPORTER
+        nsCOMPtr<nsILocalFile> pluginDump;
+        if (TakeMinidump(getter_AddRefs(pluginDump)) &&
+            CrashReporter::GetIDFromMinidump(pluginDump, mPluginDumpID)) {
+            PLUGIN_LOG_DEBUG(("got child minidump: %s",
+                              NS_ConvertUTF16toUTF8(mPluginDumpID).get()));
+            WritePluginExtraDataForMinidump(mPluginDumpID);
+        }
+        else if (!mPluginDumpID.IsEmpty() && !mBrowserDumpID.IsEmpty()) {
+            WriteExtraDataForHang();
         }
         else {
             NS_WARNING("[PluginModuleParent::ActorDestroy] abnormal shutdown without minidump!");
         }
+#endif
 
         mShutdown = true;
         // Defer the PluginCrashed method so that we don't re-enter
         // and potentially modify the actor child list while enumerating it.
-        if (mPlugin) {
-            mPluginCrashedTask = NewRunnableMethod(
-                this, &PluginModuleParent::NotifyPluginCrashed);
-            MessageLoop::current()->PostTask(FROM_HERE, mPluginCrashedTask);
-        }
+        if (mPlugin)
+            MessageLoop::current()->PostTask(
+                FROM_HERE,
+                mTaskFactory.NewRunnableMethod(
+                    &PluginModuleParent::NotifyPluginCrashed));
         break;
     }
     case NormalShutdown:
         mShutdown = true;
         break;
 
     default:
         NS_ERROR("Unexpected shutdown reason for toplevel actor.");
     }
 }
 
 void
 PluginModuleParent::NotifyPluginCrashed()
 {
-    // MessageLoop owns this
-    mPluginCrashedTask = NULL;
-
     if (!OkToCleanup()) {
         // there's still plugin code on the C++ stack.  try again
-        mPluginCrashedTask = NewRunnableMethod(
-            this, &PluginModuleParent::NotifyPluginCrashed);
         MessageLoop::current()->PostDelayedTask(
-            FROM_HERE, mPluginCrashedTask, 10);
+            FROM_HERE,
+            mTaskFactory.NewRunnableMethod(
+                &PluginModuleParent::NotifyPluginCrashed), 10);
         return;
     }
 
     if (mPlugin)
-        mPlugin->PluginCrashed(mDumpID);
+        mPlugin->PluginCrashed(mPluginDumpID, mBrowserDumpID);
+}
+
+PPluginIdentifierParent*
+PluginModuleParent::AllocPPluginIdentifier(const nsCString& aString,
+                                           const int32_t& aInt)
+{
+    NPIdentifier npident = aString.IsVoid() ?
+        mozilla::plugins::parent::_getintidentifier(aInt) :
+        mozilla::plugins::parent::_getstringidentifier(aString.get());
+
+    if (!npident) {
+        NS_WARNING("Failed to get identifier!");
+        return nsnull;
+    }
+
+    PluginIdentifierParent* ident = new PluginIdentifierParent(npident);
+    mIdentifiers.Put(npident, ident);
+    return ident;
+}
+
+bool
+PluginModuleParent::DeallocPPluginIdentifier(PPluginIdentifierParent* aActor)
+{
+    delete aActor;
+    return true;
 }
 
 PPluginInstanceParent*
 PluginModuleParent::AllocPPluginInstance(const nsCString& aMimeType,
                                          const uint16_t& aMode,
                                          const nsTArray<nsCString>& aNames,
                                          const nsTArray<nsCString>& aValues,
                                          NPError* rv)
@@ -367,40 +387,16 @@ PluginModuleParent::NPP_Destroy(NPP inst
 
     NPError retval = parentInstance->Destroy();
     instance->pdata = nsnull;
 
     (void) PluginInstanceParent::Call__delete__(parentInstance);
     return retval;
 }
 
-bool
-PluginModuleParent::EnsureValidNPIdentifier(NPIdentifier aIdentifier)
-{
-    if (!mValidIdentifiers.GetEntry(aIdentifier)) {
-        nsVoidPtrHashKey* newEntry = mValidIdentifiers.PutEntry(aIdentifier);
-        if (!newEntry) {
-            NS_ERROR("Out of memory?");
-            return false;
-        }
-    }
-    return true;
-}
-
-NPIdentifier
-PluginModuleParent::GetValidNPIdentifier(NPRemoteIdentifier aRemoteIdentifier)
-{
-    NS_ASSERTION(mValidIdentifiers.IsInitialized(), "Not initialized!");
-    if (aRemoteIdentifier &&
-        mValidIdentifiers.GetEntry((NPIdentifier)aRemoteIdentifier)) {
-        return (NPIdentifier)aRemoteIdentifier;
-    }
-    return 0;
-}
-
 NPError
 PluginModuleParent::NPP_NewStream(NPP instance, NPMIMEType type,
                                   NPStream* stream, NPBool seekable,
                                   uint16_t* stype)
 {
     PluginInstanceParent* i = InstCast(instance);
     if (!i)
         return NPERR_GENERIC_ERROR;
@@ -521,151 +517,46 @@ PluginModuleParent::NPP_SetValue(NPP ins
 
 bool
 PluginModuleParent::AnswerNPN_UserAgent(nsCString* userAgent)
 {
     *userAgent = NullableString(mNPNIface->uagent(nsnull));
     return true;
 }
 
-bool
-PluginModuleParent::RecvNPN_GetStringIdentifier(const nsCString& aString,
-                                                NPRemoteIdentifier* aId)
-{
-    if (aString.IsVoid()) {
-        NS_ERROR("Someone sent over a void string?!");
-        return false;
-    }
-
-    NPIdentifier ident =
-        mozilla::plugins::parent::_getstringidentifier(aString.BeginReading());
-    if (!ident) {
-        *aId = 0;
-        return true;
-    }
-
-    if (!EnsureValidNPIdentifier(ident)) {
-        NS_ERROR("Out of memory?");
-        return false;
-    }
-
-    *aId = (NPRemoteIdentifier)ident;
-    return true;
-}
-
-bool
-PluginModuleParent::RecvNPN_GetIntIdentifier(const int32_t& aInt,
-                                             NPRemoteIdentifier* aId)
+PPluginIdentifierParent*
+PluginModuleParent::GetIdentifierForNPIdentifier(NPIdentifier aIdentifier)
 {
-    NPIdentifier ident = mozilla::plugins::parent::_getintidentifier(aInt);
-    if (!ident) {
-        *aId = 0;
-        return true;
-    }
-
-    if (!EnsureValidNPIdentifier(ident)) {
-        NS_ERROR("Out of memory?");
-        return false;
-    }
-
-    *aId = (NPRemoteIdentifier)ident;
-    return true;
-}
-
-bool
-PluginModuleParent::RecvNPN_UTF8FromIdentifier(const NPRemoteIdentifier& aId,
-                                               NPError *err,
-                                               nsCString* aString)
-{
-    NPIdentifier ident = GetValidNPIdentifier(aId);
-    if (!ident) {
-        *err = NPERR_INVALID_PARAM;
-        return true;
-    }
-
-    NPUTF8* val = mozilla::plugins::parent::_utf8fromidentifier(ident);
-    if (!val) {
-        *err = NPERR_INVALID_PARAM;
-        return true;
+    PluginIdentifierParent* ident;
+    if (!mIdentifiers.Get(aIdentifier, &ident)) {
+        nsCString string;
+        int32_t intval = -1;
+        if (mozilla::plugins::parent::_identifierisstring(aIdentifier)) {
+            NPUTF8* chars =
+                mozilla::plugins::parent::_utf8fromidentifier(aIdentifier);
+            if (!chars) {
+                return nsnull;
+            }
+            string.Adopt(chars);
+        }
+        else {
+            intval = mozilla::plugins::parent::_intfromidentifier(aIdentifier);
+            if (intval == -1) {
+                return nsnull;
+            }
+            string.SetIsVoid(PR_TRUE);
+        }
+        ident = new PluginIdentifierParent(aIdentifier);
+        if (!SendPPluginIdentifierConstructor(ident, string, intval)) {
+            delete ident;
+            return nsnull;
+        }
+        mIdentifiers.Put(aIdentifier, ident);
     }
-
-    aString->Assign(val);
-    *err = NPERR_NO_ERROR;
-    return true;
-}
-
-bool
-PluginModuleParent::RecvNPN_IntFromIdentifier(const NPRemoteIdentifier& aId,
-                                              NPError* err,
-                                              int32_t* aInt)
-{
-    NPIdentifier ident = GetValidNPIdentifier(aId);
-    if (!ident) {
-        *err = NPERR_INVALID_PARAM;
-        return true;
-    }
-
-    *aInt = mozilla::plugins::parent::_intfromidentifier(ident);
-    *err = NPERR_NO_ERROR;
-    return true;
-}
-
-bool
-PluginModuleParent::RecvNPN_IdentifierIsString(const NPRemoteIdentifier& aId,
-                                               bool* aIsString)
-{
-    NPIdentifier ident = GetValidNPIdentifier(aId);
-    if (!ident) {
-        *aIsString = false;
-        return true;
-    }
-
-    *aIsString = mozilla::plugins::parent::_identifierisstring(ident);
-    return true;
-}
-
-bool
-PluginModuleParent::RecvNPN_GetStringIdentifiers(const nsTArray<nsCString>& aNames,
-                                                 nsTArray<NPRemoteIdentifier>* aIds)
-{
-    NS_ASSERTION(aIds->IsEmpty(), "Non-empty array!");
-
-    PRUint32 count = aNames.Length();
-    if (!count) {
-        NS_ERROR("No names to get!");
-        return false;
-    }
-
-    nsTArray<NPUTF8*> buffers;
-    nsTArray<NPIdentifier> ids;
-
-    if (!(buffers.SetLength(count) &&
-          ids.SetLength(count))) {
-        NS_ERROR("Out of memory?");
-        return false;
-    }
-
-    for (PRUint32 index = 0; index < count; ++index)
-        buffers[index] = const_cast<NPUTF8*>(NullableStringGet(aNames[index]));
-
-    mozilla::plugins::parent::_getstringidentifiers(
-        const_cast<const NPUTF8**>(buffers.Elements()), count, ids.Elements());
-
-    for (PRUint32 index = 0; index < count; index++) {
-        NPIdentifier& id = ids[index];
-        if (id) {
-            if (!EnsureValidNPIdentifier(id)) {
-                NS_ERROR("Out of memory?");
-                return false;
-            }
-        }
-        aIds->AppendElement((NPRemoteIdentifier)id);
-    }
-
-    return true;
+    return ident;
 }
 
 PluginInstanceParent*
 PluginModuleParent::InstCast(NPP instance)
 {
     PluginInstanceParent* ip =
         static_cast<PluginInstanceParent*>(instance->pdata);
 
--- a/dom/plugins/PluginModuleParent.h
+++ b/dom/plugins/PluginModuleParent.h
@@ -49,19 +49,20 @@
 #include "npfunctions.h"
 
 #include "base/string_util.h"
 
 #include "mozilla/PluginLibrary.h"
 #include "mozilla/plugins/PPluginModuleParent.h"
 #include "mozilla/plugins/PluginInstanceParent.h"
 #include "mozilla/plugins/PluginProcessParent.h"
+#include "mozilla/plugins/PluginIdentifierParent.h"
 
 #include "nsAutoPtr.h"
-#include "nsTHashtable.h"
+#include "nsDataHashtable.h"
 #include "nsHashKeys.h"
 #include "nsIFileStreams.h"
 
 namespace mozilla {
 namespace plugins {
 //-----------------------------------------------------------------------------
 
 class BrowserStreamParent;
@@ -78,16 +79,24 @@ class BrowserStreamParent;
  * This class is responsible for "actually" making those function calls.
  */
 class PluginModuleParent : public PPluginModuleParent, PluginLibrary
 {
 private:
     typedef mozilla::PluginLibrary PluginLibrary;
 
 protected:
+
+    virtual PPluginIdentifierParent*
+    AllocPPluginIdentifier(const nsCString& aString,
+                           const int32_t& aInt);
+
+    virtual bool
+    DeallocPPluginIdentifier(PPluginIdentifierParent* aActor);
+
     PPluginInstanceParent*
     AllocPPluginInstance(const nsCString& aMimeType,
                          const uint16_t& aMode,
                          const nsTArray<nsCString>& aNames,
                          const nsTArray<nsCString>& aValues,
                          NPError* rv);
 
     virtual bool
@@ -113,58 +122,39 @@ public:
     static PluginLibrary* LoadModule(const char* aFilePath);
 
     const NPNetscapeFuncs* GetNetscapeFuncs() {
         return mNPNIface;
     }
 
     base::ProcessHandle ChildProcessHandle() { return mSubprocess->GetChildProcessHandle(); }
 
-    bool EnsureValidNPIdentifier(NPIdentifier aIdentifier);
-
     bool OkToCleanup() const {
         return !IsOnCxxStack();
     }
 
+    PPluginIdentifierParent*
+    GetIdentifierForNPIdentifier(NPIdentifier aIdentifier);
+
 protected:
     NS_OVERRIDE
     virtual mozilla::ipc::RPCChannel::RacyRPCPolicy
     MediateRPCRace(const Message& parent, const Message& child)
     {
         return MediateRace(parent, child);
     }
 
+    virtual bool RecvXXX_HACK_FIXME_cjones(Shmem& mem) { NS_RUNTIMEABORT("not reached"); return false; }
+
     NS_OVERRIDE
     virtual bool ShouldContinueFromReplyTimeout();
 
     virtual bool
     AnswerNPN_UserAgent(nsCString* userAgent);
 
-    // NPRemoteIdentifier funcs
-    virtual bool
-    RecvNPN_GetStringIdentifier(const nsCString& aString,
-                                NPRemoteIdentifier* aId);
-    virtual bool
-    RecvNPN_GetIntIdentifier(const int32_t& aInt,
-                             NPRemoteIdentifier* aId);
-    virtual bool
-    RecvNPN_UTF8FromIdentifier(const NPRemoteIdentifier& aId,
-                               NPError* err,
-                               nsCString* aString);
-    virtual bool
-    RecvNPN_IntFromIdentifier(const NPRemoteIdentifier& aId,
-                              NPError* err,
-                              int32_t* aInt);
-    virtual bool
-    RecvNPN_IdentifierIsString(const NPRemoteIdentifier& aId,
-                               bool* aIsString);
-    virtual bool
-    RecvNPN_GetStringIdentifiers(const nsTArray<nsCString>& aNames,
-                                 nsTArray<NPRemoteIdentifier>* aIds);
-
     virtual bool
     AnswerNPN_GetValue_WithBoolReturn(const NPNVariable& aVariable,
                                       NPError* aError,
                                       bool* aBoolVal);
 
     NS_OVERRIDE
     virtual bool AnswerProcessSomeEvents();
 
@@ -207,18 +197,16 @@ private:
     static int16_t NPP_HandleEvent(NPP instance, void* event);
     static void NPP_URLNotify(NPP instance, const char* url,
                               NPReason reason, void* notifyData);
     static NPError NPP_GetValue(NPP instance,
                                 NPPVariable variable, void *ret_value);
     static NPError NPP_SetValue(NPP instance, NPNVariable variable,
                                 void *value);
 
-    NPIdentifier GetValidNPIdentifier(NPRemoteIdentifier aRemoteIdentifier);
-
     virtual bool HasRequiredFunctions();
 
 #if defined(XP_UNIX) && !defined(XP_MACOSX)
     virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs, NPError* error);
 #else
     virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error);
 #endif
     virtual nsresult NP_Shutdown(NPError* error);
@@ -228,31 +216,31 @@ private:
 #if defined(XP_WIN) || defined(XP_MACOSX) || defined(XP_OS2)
     virtual nsresult NP_GetEntryPoints(NPPluginFuncs* pFuncs, NPError* error);
 #endif
     virtual nsresult NPP_New(NPMIMEType pluginType, NPP instance,
                              uint16_t mode, int16_t argc, char* argn[],
                              char* argv[], NPSavedData* saved,
                              NPError* error);
 private:
-    void WriteExtraDataForMinidump(nsIFile* dumpFile);
-    void WriteExtraDataEntry(nsIFileOutputStream* stream,
-                             const char* key,
-                             const char* value);
+    void WritePluginExtraDataForMinidump(const nsAString& id);
+    void WriteExtraDataForHang();
     void CleanupFromTimeout();
     static int TimeoutChanged(const char* aPref, void* aModule);
     void NotifyPluginCrashed();
 
     nsCString mCrashNotes;
     PluginProcessParent* mSubprocess;
     bool mShutdown;
     const NPNetscapeFuncs* mNPNIface;
-    nsTHashtable<nsVoidPtrHashKey> mValidIdentifiers;
+    nsDataHashtable<nsVoidPtrHashKey, PluginIdentifierParent*> mIdentifiers;
     nsNPAPIPlugin* mPlugin;
     time_t mProcessStartTime;
-    CancelableTask* mPluginCrashedTask;
-    nsString mDumpID;
+    ScopedRunnableMethodFactory<PluginModuleParent> mTaskFactory;
+    nsString mPluginDumpID;
+    nsString mBrowserDumpID;
+    nsString mHangID;
 };
 
 } // namespace plugins
 } // namespace mozilla
 
 #endif  // ifndef dom_plugins_PluginModuleParent_h
--- a/dom/plugins/PluginScriptableObjectChild.cpp
+++ b/dom/plugins/PluginScriptableObjectChild.cpp
@@ -33,19 +33,19 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "PluginScriptableObjectChild.h"
 #include "PluginScriptableObjectUtils.h"
+#include "PluginIdentifierChild.h"
 
 using namespace mozilla::plugins;
-using mozilla::ipc::NPRemoteIdentifier;
 
 // static
 NPObject*
 PluginScriptableObjectChild::ScriptableAllocate(NPP aInstance,
                                                 NPClass* aClass)
 {
   AssertPluginThread();
 
@@ -112,17 +112,17 @@ PluginScriptableObjectChild::ScriptableH
     return false;
   }
 
   ProtectedActor<PluginScriptableObjectChild> actor(object->parent);
   NS_ASSERTION(actor, "This shouldn't ever be null!");
   NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
 
   bool result;
-  actor->CallHasMethod((NPRemoteIdentifier)aName, &result);
+  actor->CallHasMethod(static_cast<PPluginIdentifierChild*>(aName), &result);
 
   return result;
 }
 
 // static
 bool
 PluginScriptableObjectChild::ScriptableInvoke(NPObject* aObject,
                                               NPIdentifier aName,
@@ -149,17 +149,18 @@ PluginScriptableObjectChild::ScriptableI
   ProtectedVariantArray args(aArgs, aArgCount, actor->GetInstance());
   if (!args.IsOk()) {
     NS_ERROR("Failed to convert arguments!");
     return false;
   }
 
   Variant remoteResult;
   bool success;
-  actor->CallInvoke((NPRemoteIdentifier)aName, args, &remoteResult, &success);
+  actor->CallInvoke(static_cast<PPluginIdentifierChild*>(aName), args,
+                    &remoteResult, &success);
 
   if (!success) {
     return false;
   }
 
   ConvertToVariant(remoteResult, *aResult);
   return true;
 }
@@ -222,17 +223,17 @@ PluginScriptableObjectChild::ScriptableH
     return false;
   }
 
   ProtectedActor<PluginScriptableObjectChild> actor(object->parent);
   NS_ASSERTION(actor, "This shouldn't ever be null!");
   NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
 
   bool result;
-  actor->CallHasProperty((NPRemoteIdentifier)aName, &result);
+  actor->CallHasProperty(static_cast<PPluginIdentifierChild*>(aName), &result);
 
   return result;
 }
 
 // static
 bool
 PluginScriptableObjectChild::ScriptableGetProperty(NPObject* aObject,
                                                    NPIdentifier aName,
@@ -251,17 +252,18 @@ PluginScriptableObjectChild::ScriptableG
   }
 
   ProtectedActor<PluginScriptableObjectChild> actor(object->parent);
   NS_ASSERTION(actor, "This shouldn't ever be null!");
   NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
 
   Variant result;
   bool success;
-  actor->CallGetProperty((NPRemoteIdentifier)aName, &result, &success);
+  actor->CallGetProperty(static_cast<PPluginIdentifierChild*>(aName), &result,
+                         &success);
 
   if (!success) {
     return false;
   }
 
   ConvertToVariant(result, *aResult);
   return true;
 }
@@ -290,17 +292,18 @@ PluginScriptableObjectChild::ScriptableS
 
   ProtectedVariant value(*aValue, actor->GetInstance());
   if (!value.IsOk()) {
     NS_WARNING("Failed to convert variant!");
     return false;
   }
 
   bool success;
-  actor->CallSetProperty((NPRemoteIdentifier)aName, value, &success);
+  actor->CallSetProperty(static_cast<PPluginIdentifierChild*>(aName), value,
+                         &success);
 
   return success;
 }
 
 // static
 bool
 PluginScriptableObjectChild::ScriptableRemoveProperty(NPObject* aObject,
                                                       NPIdentifier aName)
@@ -317,17 +320,18 @@ PluginScriptableObjectChild::ScriptableR
     return false;
   }
 
   ProtectedActor<PluginScriptableObjectChild> actor(object->parent);
   NS_ASSERTION(actor, "This shouldn't ever be null!");
   NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
 
   bool success;
-  actor->CallRemoveProperty((NPRemoteIdentifier)aName, &success);
+  actor->CallRemoveProperty(static_cast<PPluginIdentifierChild*>(aName),
+                            &success);
 
   return success;
 }
 
 // static
 bool
 PluginScriptableObjectChild::ScriptableEnumerate(NPObject* aObject,
                                                  NPIdentifier** aIdentifiers,
@@ -344,17 +348,17 @@ PluginScriptableObjectChild::ScriptableE
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
   ProtectedActor<PluginScriptableObjectChild> actor(object->parent);
   NS_ASSERTION(actor, "This shouldn't ever be null!");
   NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
 
-  nsAutoTArray<NPRemoteIdentifier, 10> identifiers;
+  nsAutoTArray<PPluginIdentifierChild*, 10> identifiers;
   bool success;
   actor->CallEnumerate(&identifiers, &success);
 
   if (!success) {
     return false;
   }
 
   *aCount = identifiers.Length();
@@ -366,17 +370,18 @@ PluginScriptableObjectChild::ScriptableE
   *aIdentifiers = reinterpret_cast<NPIdentifier*>(
       PluginModuleChild::sBrowserFuncs.memalloc(*aCount * sizeof(NPIdentifier)));
   if (!*aIdentifiers) {
     NS_ERROR("Out of memory!");
     return false;
   }
 
   for (PRUint32 index = 0; index < *aCount; index++) {
-    (*aIdentifiers)[index] = (NPIdentifier)identifiers[index];
+    (*aIdentifiers)[index] =
+      static_cast<PPluginIdentifierChild*>(identifiers[index]);
   }
   return true;
 }
 
 // static
 bool
 PluginScriptableObjectChild::ScriptableConstruct(NPObject* aObject,
                                                  const NPVariant* aArgs,
@@ -631,17 +636,17 @@ PluginScriptableObjectChild::AnswerInval
   }
 
   Unprotect();
 
   return true;
 }
 
 bool
-PluginScriptableObjectChild::AnswerHasMethod(const NPRemoteIdentifier& aId,
+PluginScriptableObjectChild::AnswerHasMethod(PPluginIdentifierChild* aId,
                                              bool* aHasMethod)
 {
   AssertPluginThread();
 
   if (mInvalidated) {
     NS_WARNING("Calling AnswerHasMethod with an invalidated object!");
     *aHasMethod = false;
     return true;
@@ -650,22 +655,23 @@ PluginScriptableObjectChild::AnswerHasMe
   NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
   NS_ASSERTION(mType == LocalObject, "Bad type!");
 
   if (!(mObject->_class && mObject->_class->hasMethod)) {
     *aHasMethod = false;
     return true;
   }
 
-  *aHasMethod = mObject->_class->hasMethod(mObject, (NPIdentifier)aId);
+  PluginIdentifierChild* id = static_cast<PluginIdentifierChild*>(aId);
+  *aHasMethod = mObject->_class->hasMethod(mObject, id->ToNPIdentifier());
   return true;
 }
 
 bool
-PluginScriptableObjectChild::AnswerInvoke(const NPRemoteIdentifier& aId,
+PluginScriptableObjectChild::AnswerInvoke(PPluginIdentifierChild* aId,
                                           const nsTArray<Variant>& aArgs,
                                           Variant* aResult,
                                           bool* aSuccess)
 {
   AssertPluginThread();
 
   if (mInvalidated) {
     NS_WARNING("Calling AnswerInvoke with an invalidated object!");
@@ -693,17 +699,18 @@ PluginScriptableObjectChild::AnswerInvok
   }
 
   for (PRUint32 index = 0; index < argCount; index++) {
     ConvertToVariant(aArgs[index], convertedArgs[index]);
   }
 
   NPVariant result;
   VOID_TO_NPVARIANT(result);
-  bool success = mObject->_class->invoke(mObject, (NPIdentifier)aId,
+  PluginIdentifierChild* id = static_cast<PluginIdentifierChild*>(aId);
+  bool success = mObject->_class->invoke(mObject, id->ToNPIdentifier(),
                                          convertedArgs.Elements(), argCount,
                                          &result);
 
   for (PRUint32 index = 0; index < argCount; index++) {
     PluginModuleChild::sBrowserFuncs.releasevariantvalue(&convertedArgs[index]);
   }
 
   if (!success) {
@@ -794,17 +801,17 @@ PluginScriptableObjectChild::AnswerInvok
   }
 
   *aResult = convertedResult;
   *aSuccess = true;
   return true;
 }
 
 bool
-PluginScriptableObjectChild::AnswerHasProperty(const NPRemoteIdentifier& aId,
+PluginScriptableObjectChild::AnswerHasProperty(PPluginIdentifierChild* aId,
                                                bool* aHasProperty)
 {
   AssertPluginThread();
 
   if (mInvalidated) {
     NS_WARNING("Calling AnswerHasProperty with an invalidated object!");
     *aHasProperty = false;
     return true;
@@ -813,22 +820,23 @@ PluginScriptableObjectChild::AnswerHasPr
   NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
   NS_ASSERTION(mType == LocalObject, "Bad type!");
 
   if (!(mObject->_class && mObject->_class->hasProperty)) {
     *aHasProperty = false;
     return true;
   }
 
-  *aHasProperty = mObject->_class->hasProperty(mObject, (NPIdentifier)aId);
+  PluginIdentifierChild* id = static_cast<PluginIdentifierChild*>(aId);
+  *aHasProperty = mObject->_class->hasProperty(mObject, id->ToNPIdentifier());
   return true;
 }
 
 bool
-PluginScriptableObjectChild::AnswerGetProperty(const NPRemoteIdentifier& aId,
+PluginScriptableObjectChild::AnswerGetProperty(PPluginIdentifierChild* aId,
                                                Variant* aResult,
                                                bool* aSuccess)
 {
   AssertPluginThread();
 
   if (mInvalidated) {
     NS_WARNING("Calling AnswerGetProperty with an invalidated object!");
     *aResult = void_t();
@@ -842,17 +850,18 @@ PluginScriptableObjectChild::AnswerGetPr
   if (!(mObject->_class && mObject->_class->getProperty)) {
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
 
   NPVariant result;
   VOID_TO_NPVARIANT(result);
-  if (!mObject->_class->getProperty(mObject, (NPIdentifier)aId, &result)) {
+  PluginIdentifierChild* id = static_cast<PluginIdentifierChild*>(aId);
+  if (!mObject->_class->getProperty(mObject, id->ToNPIdentifier(), &result)) {
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
 
   Variant converted;
   if ((*aSuccess = ConvertToRemoteVariant(result, converted, GetInstance(),
                                           false))) {
@@ -862,17 +871,17 @@ PluginScriptableObjectChild::AnswerGetPr
   else {
     *aResult = void_t();
   }
 
   return true;
 }
 
 bool
-PluginScriptableObjectChild::AnswerSetProperty(const NPRemoteIdentifier& aId,
+PluginScriptableObjectChild::AnswerSetProperty(PPluginIdentifierChild* aId,
                                                const Variant& aValue,
                                                bool* aSuccess)
 {
   AssertPluginThread();
 
   if (mInvalidated) {
     NS_WARNING("Calling AnswerSetProperty with an invalidated object!");
     *aSuccess = false;
@@ -885,25 +894,26 @@ PluginScriptableObjectChild::AnswerSetPr
   if (!(mObject->_class && mObject->_class->setProperty)) {
     *aSuccess = false;
     return true;
   }
 
   NPVariant converted;
   ConvertToVariant(aValue, converted);
 
-  if ((*aSuccess = mObject->_class->setProperty(mObject, (NPIdentifier)aId,
+  PluginIdentifierChild* id = static_cast<PluginIdentifierChild*>(aId);
+  if ((*aSuccess = mObject->_class->setProperty(mObject, id->ToNPIdentifier(),
                                                 &converted))) {
     PluginModuleChild::sBrowserFuncs.releasevariantvalue(&converted);
   }
   return true;
 }
 
 bool
-PluginScriptableObjectChild::AnswerRemoveProperty(const NPRemoteIdentifier& aId,
+PluginScriptableObjectChild::AnswerRemoveProperty(PPluginIdentifierChild* aId,
                                                   bool* aSuccess)
 {
   AssertPluginThread();
 
   if (mInvalidated) {
     NS_WARNING("Calling AnswerRemoveProperty with an invalidated object!");
     *aSuccess = false;
     return true;
@@ -912,22 +922,23 @@ PluginScriptableObjectChild::AnswerRemov
   NS_ASSERTION(mObject->_class != GetClass(), "Bad object type!");
   NS_ASSERTION(mType == LocalObject, "Bad type!");
 
   if (!(mObject->_class && mObject->_class->removeProperty)) {
     *aSuccess = false;
     return true;
   }
 
-  *aSuccess = mObject->_class->removeProperty(mObject, (NPIdentifier)aId);
+  PluginIdentifierChild* id = static_cast<PluginIdentifierChild*>(aId);
+  *aSuccess = mObject->_class->removeProperty(mObject, id->ToNPIdentifier());
   return true;
 }
 
 bool
-PluginScriptableObjectChild::AnswerEnumerate(nsTArray<NPRemoteIdentifier>* aProperties,
+PluginScriptableObjectChild::AnswerEnumerate(nsTArray<PPluginIdentifierChild*>* aProperties,
                                              bool* aSuccess)
 {
   AssertPluginThread();
 
   if (mInvalidated) {
     NS_WARNING("Calling AnswerEnumerate with an invalidated object!");
     *aSuccess = false;
     return true;
@@ -950,21 +961,18 @@ PluginScriptableObjectChild::AnswerEnume
 
   if (!aProperties->SetCapacity(idCount)) {
     PluginModuleChild::sBrowserFuncs.memfree(ids);
     *aSuccess = false;
     return true;
   }
 
   for (uint32_t index = 0; index < idCount; index++) {
-#ifdef DEBUG
-    NPRemoteIdentifier* remoteId =
-#endif
-    aProperties->AppendElement((NPRemoteIdentifier)ids[index]);
-    NS_ASSERTION(remoteId, "Shouldn't fail if SetCapacity above succeeded!");
+    PluginIdentifierChild* id = static_cast<PluginIdentifierChild*>(ids[index]);
+    aProperties->AppendElement(id);
   }
 
   PluginModuleChild::sBrowserFuncs.memfree(ids);
   *aSuccess = true;
   return true;
 }
 
 bool
--- a/dom/plugins/PluginScriptableObjectChild.h
+++ b/dom/plugins/PluginScriptableObjectChild.h
@@ -43,16 +43,17 @@
 
 #include "npruntime.h"
 
 namespace mozilla {
 namespace plugins {
 
 class PluginInstanceChild;
 class PluginScriptableObjectChild;
+class PPluginIdentifierChild;
 
 struct ChildNPObject : NPObject
 {
   ChildNPObject()
     : NPObject(), parent(NULL), invalidated(false)
   {
     MOZ_COUNT_CTOR(ChildNPObject);
   }
@@ -82,50 +83,50 @@ public:
   void
   InitializeLocal(NPObject* aObject);
 
 
   virtual bool
   AnswerInvalidate();
 
   virtual bool
-  AnswerHasMethod(const NPRemoteIdentifier& aId,
+  AnswerHasMethod(PPluginIdentifierChild* aId,
                   bool* aHasMethod);
 
   virtual bool
-  AnswerInvoke(const NPRemoteIdentifier& aId,
+  AnswerInvoke(PPluginIdentifierChild* aId,
                const nsTArray<Variant>& aArgs,
                Variant* aResult,
                bool* aSuccess);
 
   virtual bool
   AnswerInvokeDefault(const nsTArray<Variant>& aArgs,
                       Variant* aResult,
                       bool* aSuccess);
 
   virtual bool
-  AnswerHasProperty(const NPRemoteIdentifier& aId,
+  AnswerHasProperty(PPluginIdentifierChild* aId,
                     bool* aHasProperty);
 
   virtual bool
-  AnswerGetProperty(const NPRemoteIdentifier& aId,
+  AnswerGetProperty(PPluginIdentifierChild* aId,
                     Variant* aResult,
                     bool* aSuccess);
 
   virtual bool
-  AnswerSetProperty(const NPRemoteIdentifier& aId,
+  AnswerSetProperty(PPluginIdentifierChild* aId,
                     const Variant& aValue,
                     bool* aSuccess);
 
   virtual bool
-  AnswerRemoveProperty(const NPRemoteIdentifier& aId,
+  AnswerRemoveProperty(PPluginIdentifierChild* aId,
                        bool* aSuccess);
 
   virtual bool
-  AnswerEnumerate(nsTArray<NPRemoteIdentifier>* aProperties,
+  AnswerEnumerate(nsTArray<PPluginIdentifierChild*>* aProperties,
                   bool* aSuccess);
 
   virtual bool
   AnswerConstruct(const nsTArray<Variant>& aArgs,
                   Variant* aResult,
                   bool* aSuccess);
 
   virtual bool
--- a/dom/plugins/PluginScriptableObjectParent.cpp
+++ b/dom/plugins/PluginScriptableObjectParent.cpp
@@ -35,54 +35,53 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "PluginScriptableObjectParent.h"
 #include "PluginScriptableObjectUtils.h"
 
 using namespace mozilla::plugins;
-using mozilla::ipc::NPRemoteIdentifier;
 
 namespace {
 
 inline void
 ReleaseVariant(NPVariant& aVariant,
                PluginInstanceParent* aInstance)
 {
   const NPNetscapeFuncs* npn = GetNetscapeFuncs(aInstance);
   if (npn) {
     npn->releasevariantvalue(&aVariant);
   }
 }
 
-inline bool
-EnsureValidIdentifier(PluginInstanceParent* aInstance,
-                      NPIdentifier aIdentifier)
+inline PPluginIdentifierParent*
+GetIdentifier(PluginInstanceParent* aInstance,
+              NPIdentifier aIdentifier)
 {
   PluginModuleParent* module = aInstance->Module();
   if (!module) {
     NS_WARNING("Huh?!");
     return false;
   }
 
-  return module->EnsureValidNPIdentifier(aIdentifier);
+  return module->GetIdentifierForNPIdentifier(aIdentifier);
 }
 
-inline bool
-EnsureValidIdentifier(NPObject* aObject,
-                      NPIdentifier aIdentifier)
+inline PPluginIdentifierParent*
+GetIdentifier(NPObject* aObject,
+              NPIdentifier aIdentifier)
 {
   PluginInstanceParent* instance = GetInstance(aObject);
   if (!instance) {
     NS_WARNING("Huh?!");
     return false;
   }
 
-  return EnsureValidIdentifier(instance, aIdentifier);
+  return GetIdentifier(instance, aIdentifier);
 }
 
 } // anonymous namespace
 
 // static
 NPObject*
 PluginScriptableObjectParent::ScriptableAllocate(NPP aInstance,
                                                  NPClass* aClass)
@@ -148,29 +147,30 @@ PluginScriptableObjectParent::Scriptable
   }
 
   ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
   if (object->invalidated) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
-  if (!EnsureValidIdentifier(aObject, aName)) {
+  PPluginIdentifierParent* identifier = GetIdentifier(aObject, aName);
+  if (!identifier) {
     return false;
   }
 
   ProtectedActor<PluginScriptableObjectParent> actor(object->parent);
   if (!actor) {
     return false;
   }
 
   NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
 
   bool result;
-  if (!actor->CallHasMethod((NPRemoteIdentifier)aName, &result)) {
+  if (!actor->CallHasMethod(identifier, &result)) {
     NS_WARNING("Failed to send message!");
     return false;
   }
 
   return result;
 }
 
 // static
@@ -187,17 +187,18 @@ PluginScriptableObjectParent::Scriptable
   }
 
   ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
   if (object->invalidated) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
-  if (!EnsureValidIdentifier(aObject, aName)) {
+  PPluginIdentifierParent* identifier = GetIdentifier(aObject, aName);
+  if (!identifier) {
     return false;
   }
 
   ProtectedActor<PluginScriptableObjectParent> actor(object->parent);
   if (!actor) {
     return false;
   }
 
@@ -206,17 +207,17 @@ PluginScriptableObjectParent::Scriptable
   ProtectedVariantArray args(aArgs, aArgCount, actor->GetInstance());
   if (!args.IsOk()) {
     NS_ERROR("Failed to convert arguments!");
     return false;
   }
 
   Variant remoteResult;
   bool success;
-  if (!actor->CallInvoke((NPRemoteIdentifier)aName, args, &remoteResult,
+  if (!actor->CallInvoke(identifier, args, &remoteResult,
                          &success)) {
     NS_WARNING("Failed to send message!");
     return false;
   }
 
   if (!success) {
     return false;
   }
@@ -288,29 +289,30 @@ PluginScriptableObjectParent::Scriptable
   }
 
   ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
   if (object->invalidated) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
-  if (!EnsureValidIdentifier(aObject, aName)) {
+  PPluginIdentifierParent* identifier = GetIdentifier(aObject, aName);
+  if (!identifier) {
     return false;
   }
 
   ProtectedActor<PluginScriptableObjectParent> actor(object->parent);
   if (!actor) {
     return false;
   }
 
   NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
 
   bool result;
-  if (!actor->CallHasProperty((NPRemoteIdentifier)aName, &result)) {
+  if (!actor->CallHasProperty(identifier, &result)) {
     NS_WARNING("Failed to send message!");
     return false;
   }
 
   return result;
 }
 
 // static
@@ -325,30 +327,31 @@ PluginScriptableObjectParent::Scriptable
   }
 
   ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
   if (object->invalidated) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
-  if (!EnsureValidIdentifier(aObject, aName)) {
+  PPluginIdentifierParent* identifier = GetIdentifier(aObject, aName);
+  if (!identifier) {
     return false;
   }
 
   ProtectedActor<PluginScriptableObjectParent> actor(object->parent);
   if (!actor) {
     return false;
   }
 
   NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
 
   Variant result;
   bool success;
-  if (!actor->CallGetProperty((NPRemoteIdentifier)aName, &result, &success)) {
+  if (!actor->CallGetProperty(identifier, &result, &success)) {
     NS_WARNING("Failed to send message!");
     return false;
   }
 
   if (!success) {
     return false;
   }
 
@@ -372,17 +375,18 @@ PluginScriptableObjectParent::Scriptable
   }
 
   ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
   if (object->invalidated) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
-  if (!EnsureValidIdentifier(aObject, aName)) {
+  PPluginIdentifierParent* identifier = GetIdentifier(aObject, aName);
+  if (!identifier) {
     return false;
   }
 
   ProtectedActor<PluginScriptableObjectParent> actor(object->parent);
   if (!actor) {
     return false;
   }
 
@@ -390,17 +394,17 @@ PluginScriptableObjectParent::Scriptable
 
   ProtectedVariant value(*aValue, actor->GetInstance());
   if (!value.IsOk()) {
     NS_WARNING("Failed to convert variant!");
     return false;
   }
 
   bool success;
-  if (!actor->CallSetProperty((NPRemoteIdentifier)aName, value, &success)) {
+  if (!actor->CallSetProperty(identifier, value, &success)) {
     NS_WARNING("Failed to send message!");
     return false;
   }
 
   return success;
 }
 
 // static
@@ -414,29 +418,30 @@ PluginScriptableObjectParent::Scriptable
   }
 
   ParentNPObject* object = reinterpret_cast<ParentNPObject*>(aObject);
   if (object->invalidated) {
     NS_WARNING("Calling method on an invalidated object!");
     return false;
   }
 
-  if (!EnsureValidIdentifier(aObject, aName)) {
+  PPluginIdentifierParent* identifier = GetIdentifier(aObject, aName);
+  if (!identifier) {
     return false;
   }
 
   ProtectedActor<PluginScriptableObjectParent> actor(object->parent);
   if (!actor) {
     return false;
   }
 
   NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
 
   bool success;
-  if (!actor->CallRemoveProperty((NPRemoteIdentifier)aName, &success)) {
+  if (!actor->CallRemoveProperty(identifier, &success)) {
     NS_WARNING("Failed to send message!");
     return false;
   }
 
   return success;
 }
 
 // static
@@ -464,17 +469,17 @@ PluginScriptableObjectParent::Scriptable
   NS_ASSERTION(actor->Type() == Proxy, "Bad type!");
 
   const NPNetscapeFuncs* npn = GetNetscapeFuncs(aObject);
   if (!npn) {
     NS_ERROR("No netscape funcs!");
     return false;
   }
 
-  nsAutoTArray<NPRemoteIdentifier, 10> identifiers;
+  nsAutoTArray<PPluginIdentifierParent*, 10> identifiers;
   bool success;
   if (!actor->CallEnumerate(&identifiers, &success)) {
     NS_WARNING("Failed to send message!");
     return false;
   }
 
   if (!success) {
     return false;
@@ -488,21 +493,19 @@ PluginScriptableObjectParent::Scriptable
 
   *aIdentifiers = (NPIdentifier*)npn->memalloc(*aCount * sizeof(NPIdentifier));
   if (!*aIdentifiers) {
     NS_ERROR("Out of memory!");
     return false;
   }
 
   for (PRUint32 index = 0; index < *aCount; index++) {
-    NPIdentifier& id = *aIdentifiers[index];
-    id = (NPIdentifier)identifiers[index];
-    if (!EnsureValidIdentifier(aObject, id)) {
-      return false;
-    }
+    PluginIdentifierParent* id =
+      static_cast<PluginIdentifierParent*>(identifiers[index]);
+    *aIdentifiers[index] = id->ToNPIdentifier();
   }
   return true;
 }
 
 // static
 bool
 PluginScriptableObjectParent::ScriptableConstruct(NPObject* aObject,
                                                   const NPVariant* aArgs,
@@ -724,17 +727,17 @@ PluginScriptableObjectParent::DropNPObje
 
   instance->UnregisterNPObject(mObject);
   mObject = nsnull;
 
   (void) SendUnprotect();
 }
 
 bool
-PluginScriptableObjectParent::AnswerHasMethod(const NPRemoteIdentifier& aId,
+PluginScriptableObjectParent::AnswerHasMethod(PPluginIdentifierParent* aId,
                                               bool* aHasMethod)
 {
   if (!mObject) {
     NS_WARNING("Calling AnswerHasMethod with an invalidated object!");
     *aHasMethod = false;
     return true;
   }
 
@@ -750,28 +753,23 @@ PluginScriptableObjectParent::AnswerHasM
 
   const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
   if (!npn) {
     NS_ERROR("No netscape funcs?!");
     *aHasMethod = false;
     return true;
   }
 
-  if (!EnsureValidIdentifier(instance, (NPIdentifier)aId)) {
-    NS_WARNING("Invalid NPIdentifier!");
-    *aHasMethod = false;
-    return true;
-  }
-
-  *aHasMethod = npn->hasmethod(instance->GetNPP(), mObject, (NPIdentifier)aId);
+  PluginIdentifierParent* id = static_cast<PluginIdentifierParent*>(aId);
+  *aHasMethod = npn->hasmethod(instance->GetNPP(), mObject, id->ToNPIdentifier());
   return true;
 }
 
 bool
-PluginScriptableObjectParent::AnswerInvoke(const NPRemoteIdentifier& aId,
+PluginScriptableObjectParent::AnswerInvoke(PPluginIdentifierParent* aId,
                                            const nsTArray<Variant>& aArgs,
                                            Variant* aResult,
                                            bool* aSuccess)
 {
   if (!mObject) {
     NS_WARNING("Calling AnswerInvoke with an invalidated object!");
     *aResult = void_t();
     *aSuccess = false;
@@ -792,23 +790,16 @@ PluginScriptableObjectParent::AnswerInvo
   const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
   if (!npn) {
     NS_ERROR("No netscape funcs?!");
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
 
-  if (!EnsureValidIdentifier(instance, (NPIdentifier)aId)) {
-    NS_WARNING("Invalid NPIdentifier!");
-    *aResult = void_t();
-    *aSuccess = false;
-    return true;
-  }
-
   nsAutoTArray<NPVariant, 10> convertedArgs;
   PRUint32 argCount = aArgs.Length();
 
   if (!convertedArgs.SetLength(argCount)) {
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
@@ -820,18 +811,19 @@ PluginScriptableObjectParent::AnswerInvo
         ReleaseVariant(convertedArgs[index], instance);
       }
       *aResult = void_t();
       *aSuccess = false;
       return true;
     }
   }
 
+  PluginIdentifierParent* id = static_cast<PluginIdentifierParent*>(aId);
   NPVariant result;
-  bool success = npn->invoke(instance->GetNPP(), mObject, (NPIdentifier)aId,
+  bool success = npn->invoke(instance->GetNPP(), mObject, id->ToNPIdentifier(),
                              convertedArgs.Elements(), argCount, &result);
 
   for (PRUint32 index = 0; index < argCount; index++) {
     ReleaseVariant(convertedArgs[index], instance);
   }
 
   if (!success) {
     *aResult = void_t();
@@ -934,17 +926,17 @@ PluginScriptableObjectParent::AnswerInvo
   }
 
   *aResult = convertedResult;
   *aSuccess = true;
   return true;
 }
 
 bool
-PluginScriptableObjectParent::AnswerHasProperty(const NPRemoteIdentifier& aId,
+PluginScriptableObjectParent::AnswerHasProperty(PPluginIdentifierParent* aId,
                                                 bool* aHasProperty)
 {
   if (!mObject) {
     NS_WARNING("Calling AnswerHasProperty with an invalidated object!");
     *aHasProperty = false;
     return true;
   }
 
@@ -960,29 +952,24 @@ PluginScriptableObjectParent::AnswerHasP
 
   const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
   if (!npn) {
     NS_ERROR("No netscape funcs?!");
     *aHasProperty = false;
     return true;
   }
 
-  if (!EnsureValidIdentifier(instance, (NPIdentifier)aId)) {
-    NS_WARNING("Invalid NPIdentifier!");
-    *aHasProperty = false;
-    return true;
-  }
-
+  PluginIdentifierParent* id = static_cast<PluginIdentifierParent*>(aId);
   *aHasProperty = npn->hasproperty(instance->GetNPP(), mObject,
-                                   (NPIdentifier)aId);
+                                   id->ToNPIdentifier());
   return true;
 }
 
 bool
-PluginScriptableObjectParent::AnswerGetProperty(const NPRemoteIdentifier& aId,
+PluginScriptableObjectParent::AnswerGetProperty(PPluginIdentifierParent* aId,
                                                 Variant* aResult,
                                                 bool* aSuccess)
 {
   if (!mObject) {
     NS_WARNING("Calling AnswerGetProperty with an invalidated object!");
     *aResult = void_t();
     *aSuccess = false;
     return true;
@@ -1002,25 +989,19 @@ PluginScriptableObjectParent::AnswerGetP
   const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
   if (!npn) {
     NS_ERROR("No netscape funcs?!");
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
 
-  if (!EnsureValidIdentifier(instance, (NPIdentifier)aId)) {
-    NS_WARNING("Invalid NPIdentifier!");
-    *aResult = void_t();
-    *aSuccess = false;
-    return true;
-  }
-
+  PluginIdentifierParent* id = static_cast<PluginIdentifierParent*>(aId);
   NPVariant result;
-  if (!npn->getproperty(instance->GetNPP(), mObject, (NPIdentifier)aId,
+  if (!npn->getproperty(instance->GetNPP(), mObject, id->ToNPIdentifier(),
                         &result)) {
     *aResult = void_t();
     *aSuccess = false;
     return true;
   }
 
   Variant converted;
   if ((*aSuccess = ConvertToRemoteVariant(result, converted, instance))) {
@@ -1030,17 +1011,17 @@ PluginScriptableObjectParent::AnswerGetP
   else {
     *aResult = void_t();
   }
 
   return true;
 }
 
 bool
-PluginScriptableObjectParent::AnswerSetProperty(const NPRemoteIdentifier& aId,
+PluginScriptableObjectParent::AnswerSetProperty(PPluginIdentifierParent* aId,
                                                 const Variant& aValue,
                                                 bool* aSuccess)
 {
   if (!mObject) {
     NS_WARNING("Calling AnswerSetProperty with an invalidated object!");
     *aSuccess = false;
     return true;
   }
@@ -1057,37 +1038,32 @@ PluginScriptableObjectParent::AnswerSetP
 
   const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
   if (!npn) {
     NS_ERROR("No netscape funcs?!");
     *aSuccess = false;
     return true;
   }
 
-  if (!EnsureValidIdentifier(instance, (NPIdentifier)aId)) {
-    NS_WARNING("Invalid NPIdentifier!");
-    *aSuccess = false;
-    return true;
-  }
-
   NPVariant converted;
   if (!ConvertToVariant(aValue, converted, instance)) {
     *aSuccess = false;
     return true;
   }
 
+  PluginIdentifierParent* id = static_cast<PluginIdentifierParent*>(aId);
   if ((*aSuccess = npn->setproperty(instance->GetNPP(), mObject,
-                                    (NPIdentifier)aId, &converted))) {
+                                    id->ToNPIdentifier(), &converted))) {
     ReleaseVariant(converted, instance);
   }
   return true;
 }
 
 bool
-PluginScriptableObjectParent::AnswerRemoveProperty(const NPRemoteIdentifier& aId,
+PluginScriptableObjectParent::AnswerRemoveProperty(PPluginIdentifierParent* aId,
                                                    bool* aSuccess)
 {
   if (!mObject) {
     NS_WARNING("Calling AnswerRemoveProperty with an invalidated object!");
     *aSuccess = false;
     return true;
   }
 
@@ -1103,29 +1079,24 @@ PluginScriptableObjectParent::AnswerRemo
 
   const NPNetscapeFuncs* npn = GetNetscapeFuncs(instance);
   if (!npn) {
     NS_ERROR("No netscape funcs?!");
     *aSuccess = false;
     return true;
   }
 
-  if (!EnsureValidIdentifier(instance, (NPIdentifier)aId)) {
-    NS_WARNING("Invalid NPIdentifier!");
-    *aSuccess = false;
-    return true;
-  }
-
+  PluginIdentifierParent* id = static_cast<PluginIdentifierParent*>(aId);
   *aSuccess = npn->removeproperty(instance->GetNPP(), mObject,
-                                  (NPIdentifier)aId);
+                                  id->ToNPIdentifier());
   return true;
 }
 
 bool
-PluginScriptableObjectParent::AnswerEnumerate(nsTArray<NPRemoteIdentifier>* aProperties,
+PluginScriptableObjectParent::AnswerEnumerate(nsTArray<PPluginIdentifierParent*>* aProperties,
                                               bool* aSuccess)
 {
   if (!mObject) {
     NS_WARNING("Calling AnswerEnumerate with an invalidated object!");
     *aSuccess = false;
     return true;
   }
 
@@ -1155,23 +1126,17 @@ PluginScriptableObjectParent::AnswerEnum
 
   if (!aProperties->SetCapacity(idCount)) {
     npn->memfree(ids);
     *aSuccess = false;
     return true;
   }
 
   for (uint32_t index = 0; index < idCount; index++) {
-    NS_ASSERTION(EnsureValidIdentifier(instance, ids[index]),
-                 "Identifier not yet in hashset!");
-#ifdef DEBUG
-    NPRemoteIdentifier* remoteId =
-#endif
-    aProperties->AppendElement((NPRemoteIdentifier)ids[index]);