merge m-c to fx-team
authorGavin Sharp <gavin@gavinsharp.com>
Thu, 28 Jul 2011 09:52:15 -0700
changeset 73491 150b7109ac0108feeaf43a031c9ec556b49f8c2b
parent 73490 84a573a54dd7cdc3a7a93afd4425d7ba2a4fa309 (current diff)
parent 73476 2a797b4b48fdb9b2843d57772846e58d1940d8bc (diff)
child 73492 ac0fe0533586e0470dce181d2f3fd5d9ace50170
push idunknown
push userunknown
push dateunknown
milestone8.0a1
merge m-c to fx-team
browser/devtools/webconsole/test/browser/browser_webconsole_bug_595934_message_categories.js
browser/devtools/webconsole/test/browser/test-bug-603750-websocket.js
content/base/public/nsIWebSocket.idl
dom/interfaces/threads/Makefile.in
dom/interfaces/threads/nsIDOMWorkers.idl
dom/src/threads/Makefile.in
dom/src/threads/nsDOMThreadService.cpp
dom/src/threads/nsDOMThreadService.h
dom/src/threads/nsDOMWorker.cpp
dom/src/threads/nsDOMWorker.h
dom/src/threads/nsDOMWorkerEvents.cpp
dom/src/threads/nsDOMWorkerEvents.h
dom/src/threads/nsDOMWorkerLocation.cpp
dom/src/threads/nsDOMWorkerLocation.h
dom/src/threads/nsDOMWorkerMacros.h
dom/src/threads/nsDOMWorkerMessageHandler.cpp
dom/src/threads/nsDOMWorkerMessageHandler.h
dom/src/threads/nsDOMWorkerNavigator.cpp
dom/src/threads/nsDOMWorkerNavigator.h
dom/src/threads/nsDOMWorkerPool.cpp
dom/src/threads/nsDOMWorkerPool.h
dom/src/threads/nsDOMWorkerScriptLoader.cpp
dom/src/threads/nsDOMWorkerScriptLoader.h
dom/src/threads/nsDOMWorkerSecurityManager.cpp
dom/src/threads/nsDOMWorkerSecurityManager.h
dom/src/threads/nsDOMWorkerTimeout.cpp
dom/src/threads/nsDOMWorkerTimeout.h
dom/src/threads/nsDOMWorkerXHR.cpp
dom/src/threads/nsDOMWorkerXHR.h
dom/src/threads/nsDOMWorkerXHRProxiedFunctions.h
dom/src/threads/nsDOMWorkerXHRProxy.cpp
dom/src/threads/nsDOMWorkerXHRProxy.h
dom/src/threads/test/Makefile.in
dom/src/threads/test/WorkerTest.jsm
dom/src/threads/test/WorkerTest_badworker.js
dom/src/threads/test/WorkerTest_subworker.js
dom/src/threads/test/WorkerTest_worker.js
dom/src/threads/test/atob_worker.js
dom/src/threads/test/chromeWorker_subworker.js
dom/src/threads/test/chromeWorker_worker.js
dom/src/threads/test/closeOnGC_server.sjs
dom/src/threads/test/closeOnGC_worker.js
dom/src/threads/test/close_worker.js
dom/src/threads/test/errorPropagation_worker1.js
dom/src/threads/test/errorPropagation_worker2.js
dom/src/threads/test/fibonacci_worker.js
dom/src/threads/test/functionHandlers_worker.js
dom/src/threads/test/importScripts_worker.js
dom/src/threads/test/importScripts_worker_imported1.js
dom/src/threads/test/importScripts_worker_imported2.js
dom/src/threads/test/importScripts_worker_imported3.js
dom/src/threads/test/importScripts_worker_imported4.js
dom/src/threads/test/json_worker.js
dom/src/threads/test/location_worker.js
dom/src/threads/test/longThread_worker.js
dom/src/threads/test/navigator_worker.js
dom/src/threads/test/newError_worker.js
dom/src/threads/test/recursion_worker.js
dom/src/threads/test/regExpStatics_worker.js
dom/src/threads/test/relativeLoad_import.js
dom/src/threads/test/relativeLoad_sub_import.js
dom/src/threads/test/relativeLoad_sub_worker.js
dom/src/threads/test/relativeLoad_sub_worker2.js
dom/src/threads/test/relativeLoad_worker.js
dom/src/threads/test/relativeLoad_worker2.js
dom/src/threads/test/scopeOnerror_worker.js
dom/src/threads/test/simpleThread_worker.js
dom/src/threads/test/suspend_iframe.html
dom/src/threads/test/suspend_worker.js
dom/src/threads/test/terminate_worker.js
dom/src/threads/test/testXHR.txt
dom/src/threads/test/test_404.html
dom/src/threads/test/test_atob.html
dom/src/threads/test/test_chromeWorker.html
dom/src/threads/test/test_chromeWorker.xul
dom/src/threads/test/test_chromeWorkerComponent.xul
dom/src/threads/test/test_chromeWorkerJSM.xul
dom/src/threads/test/test_close.html
dom/src/threads/test/test_closeOnGC.html
dom/src/threads/test/test_errorPropagation.html
dom/src/threads/test/test_fibonacci.html
dom/src/threads/test/test_functionHandlers.html
dom/src/threads/test/test_importScripts.html
dom/src/threads/test/test_json.html
dom/src/threads/test/test_location.html
dom/src/threads/test/test_longThread.html
dom/src/threads/test/test_navigator.html
dom/src/threads/test/test_newError.html
dom/src/threads/test/test_recursion.html
dom/src/threads/test/test_regExpStatics.html
dom/src/threads/test/test_relativeLoad.html
dom/src/threads/test/test_scopeOnerror.html
dom/src/threads/test/test_simpleThread.html
dom/src/threads/test/test_suspend.html
dom/src/threads/test/test_terminate.html
dom/src/threads/test/test_threadErrors.html
dom/src/threads/test/test_threadTimeouts.html
dom/src/threads/test/test_throwingOnerror.html
dom/src/threads/test/test_xhr.html
dom/src/threads/test/test_xhrAbort.html
dom/src/threads/test/test_xpcom.html
dom/src/threads/test/threadErrors_worker1.js
dom/src/threads/test/threadErrors_worker2.js
dom/src/threads/test/threadErrors_worker3.js
dom/src/threads/test/threadErrors_worker4.js
dom/src/threads/test/threadTimeouts_worker.js
dom/src/threads/test/throwingOnerror_worker.js
dom/src/threads/test/xhrAbort_worker.js
dom/src/threads/test/xhr_worker.js
dom/src/threads/test/xpcom_worker.js
gfx/src/nsIRegion.h
gfx/src/nsThebesRegion.cpp
gfx/src/nsThebesRegion.h
js/src/jsdbgapiinlines.h
js/src/tests/ecma/String/15.5.4.11-2.js
js/src/tests/ecma/String/15.5.4.11-5.js
js/src/tests/ecma/String/15.5.4.12-1.js
js/src/tests/ecma/String/15.5.4.12-4.js
layout/reftests/ogg-video/poster-14.html
security/coreconf/Linux2.1.mk
security/coreconf/Linux2.2.mk
security/coreconf/Linux2.4.mk
security/coreconf/Linux2.5.mk
security/coreconf/Linux2.6.mk
security/coreconf/LinuxELF1.2.mk
security/coreconf/LinuxELF2.0.mk
security/patches/bug-662557-nss-debug-sec-error-no-memory.patch
services/sync/tests/unit/test_service_quota.js
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -838,34 +838,40 @@ var BookmarksEventHandler = {
 };
 
 
 // Handles special drag and drop functionality for Places menus that are not
 // part of a Places view (e.g. the bookmarks menu in the menubar).
 var PlacesMenuDNDHandler = {
   _springLoadDelay: 350, // milliseconds
   _loadTimer: null,
+  _closerTimer: null,
 
   /**
    * Called when the user enters the <menu> element during a drag.
    * @param   event
    *          The DragEnter event that spawned the opening. 
    */
   onDragEnter: function PMDH_onDragEnter(event) {
     // Opening menus in a Places popup is handled by the view itself.
     if (!this._isStaticContainer(event.target))
       return;
 
-    this._loadTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
-    this._loadTimer.initWithCallback(function() {
-      PlacesMenuDNDHandler._loadTimer = null;
-      event.target.lastChild.setAttribute("autoopened", "true");
-      event.target.lastChild.showPopup(event.target.lastChild);
-    }, this._springLoadDelay, Ci.nsITimer.TYPE_ONE_SHOT);
-    event.preventDefault();
+    let ip = new InsertionPoint(PlacesUtils.bookmarksMenuFolderId,
+                                PlacesUtils.bookmarks.DEFAULT_INDEX,
+                                Ci.nsITreeView.DROP_ON);
+    if (ip && PlacesControllerDragHelper.canDrop(ip, event.dataTransfer)) {
+      this._loadTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+      this._loadTimer.initWithCallback(function() {
+        PlacesMenuDNDHandler._loadTimer = null;
+        event.target.lastChild.setAttribute("autoopened", "true");
+        event.target.lastChild.showPopup(event.target.lastChild);
+      }, this._springLoadDelay, Ci.nsITimer.TYPE_ONE_SHOT);
+      event.preventDefault();
+    }
     event.stopPropagation();
   },
 
   /**
    * Handles dragexit on the <menu> element.
    * @returns true if the element is a container element (menu or 
    *          menu-toolbarbutton), false otherwise.
    */
@@ -873,18 +879,19 @@ var PlacesMenuDNDHandler = {
     // Closing menus in a Places popup is handled by the view itself.
     if (!this._isStaticContainer(event.target))
       return;
 
     if (this._loadTimer) {
       this._loadTimer.cancel();
       this._loadTimer = null;
     }
-    let closeTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
-    closeTimer.initWithCallback(function() {
+    this._closeTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+    this._closeTimer.initWithCallback(function() {
+      this._closeTimer = null;
       let node = PlacesControllerDragHelper.currentDropTarget;
       let inHierarchy = false;
       while (node && !inHierarchy) {
         inHierarchy = node == event.target;
         node = node.parentNode;
       }
       if (!inHierarchy && event.target.lastChild &&
           event.target.lastChild.hasAttribute("autoopened")) {
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -8,16 +8,17 @@ searchbar {
 tabbrowser {
   -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser");
 }
 
 .tabbrowser-tabs {
   -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-tabs");
 }
 
+#tabbrowser-tabs[drag=detach][closebuttons=hidden] > .tabbrowser-arrowscrollbox > .tabs-newtab-button,
 #tabbrowser-tabs:not([overflow="true"]) + #new-tab-button,
 #tabbrowser-tabs[overflow="true"] > .tabbrowser-arrowscrollbox > .tabs-newtab-button,
 #TabsToolbar[currentset]:not([currentset*="tabbrowser-tabs,new-tab-button"]) > #tabbrowser-tabs > .tabbrowser-arrowscrollbox > .tabs-newtab-button,
 #TabsToolbar[customizing="true"] > #tabbrowser-tabs > .tabbrowser-arrowscrollbox > .tabs-newtab-button {
   visibility: collapse;
 }
 
 .tabbrowser-tab {
@@ -57,16 +58,49 @@ tabbrowser {
   -moz-transition: opacity 250ms;
 }
 
 .tabbrowser-tabs[positionpinnedtabs] > .tabbrowser-tab[pinned] {
   position: fixed !important;
   display: block; /* position:fixed already does this (bug 579776), but let's be explicit */
 }
 
+.tabbrowser-tabs[drag] > .tabbrowser-tab {
+  pointer-events: none; /* suppress tooltips */
+}
+
+.tabbrowser-tabs[drag] > .tabbrowser-tab[selected] {
+  z-index: 2; /* ensure selected tab stays on top despite -moz-transform */
+}
+
+.tabbrowser-tabs[drag] > .tabbrowser-tab[dragged] {
+  -moz-transition: 0s; /* suppress opening animation when reattaching tab */
+}
+
+/* visibility: collapse might collapse the tab bar, so we use this instead */
+.tabbrowser-tabs[drag=detach] > .tabbrowser-tab[dragged]:not(:only-child) {
+  min-width: 0 !important;
+  max-width: 0 !important;
+  border: 0 !important;
+  opacity: 0;
+  overflow: hidden;
+  -moz-transition: max-width 150ms ease-out;
+}
+.tabbrowser-tabs[drag=detach] > .tabbrowser-tab[dragged]:only-child {
+  visibility: hidden;
+}
+
+.tabbrowser-tabs[drag=move] > .tabbrowser-tab[fadein]:not([dragged]) {
+  -moz-transition: -moz-transform 200ms ease-out;
+}
+
+.tabbrowser-tabs[drag=finish] > .tabbrowser-tab[dragged][fadein] {
+  -moz-transition: -moz-transform 100ms ease-out;
+}
+
 #alltabs-popup {
   -moz-binding: url("chrome://browser/content/tabbrowser.xml#tabbrowser-alltabs-popup");
 }
 
 toolbar[printpreview="true"] {
   -moz-binding: url("chrome://global/content/printPreviewBindings.xml#printpreviewtoolbar");
 }
 
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -394,16 +394,34 @@
     <panel id="customizeToolbarSheetPopup"
            noautohide="true">
       <iframe id="customizeToolbarSheetIFrame"
               style="&dialog.style;"
               hidden="true"/>
     </panel>
 
     <tooltip id="tabbrowser-tab-tooltip" onpopupshowing="gBrowser.createTooltip(event);"/>
+
+    <tooltip id="back-button-tooltip">
+      <label value="&backButton.tooltip;"/>
+#ifdef XP_MACOSX
+      <label value="&backForwardButtonMenuMac.tooltip;"/>
+#else
+      <label value="&backForwardButtonMenu.tooltip;"/>
+#endif
+    </tooltip>
+  
+    <tooltip id="forward-button-tooltip">
+      <label value="&forwardButton.tooltip;"/>
+#ifdef XP_MACOSX
+      <label value="&backForwardButtonMenuMac.tooltip;"/>
+#else
+      <label value="&backForwardButtonMenu.tooltip;"/>
+#endif
+    </tooltip>
   </popupset>
 
 #ifdef CAN_DRAW_IN_TITLEBAR
 <vbox id="titlebar">
   <hbox id="titlebar-content">
     <hbox id="appmenu-button-container">
       <button id="appmenu-button"
               type="menu"
@@ -463,22 +481,22 @@
 
       <toolbaritem id="unified-back-forward-button" class="chromeclass-toolbar-additional"
                    context="backForwardMenu" removable="true"
                    title="&backForwardItem.title;">
         <toolbarbutton id="back-button" class="toolbarbutton-1"
                        label="&backCmd.label;"
                        command="Browser:BackOrBackDuplicate"
                        onclick="checkForMiddleClick(this, event);"
-                       tooltiptext="&backButton.tooltip;"/>
+                       tooltip="back-button-tooltip"/>
         <toolbarbutton id="forward-button" class="toolbarbutton-1"
                        label="&forwardCmd.label;"
                        command="Browser:ForwardOrForwardDuplicate"
                        onclick="checkForMiddleClick(this, event);"
-                       tooltiptext="&forwardButton.tooltip;"/>
+                       tooltip="forward-button-tooltip"/>
       </toolbaritem>
 
       <toolbaritem id="urlbar-container" align="center" flex="400" persist="width" combined="true"
                    title="&locationItem.title;" class="chromeclass-location" removable="true">
         <textbox id="urlbar" flex="1"
                  placeholder="&urlbar.placeholder;"
                  type="autocomplete"
                  autocompletesearch="history"
--- a/browser/base/content/syncQuota.js
+++ b/browser/base/content/syncQuota.js
@@ -53,54 +53,69 @@ let gSyncQuota = {
     gUsageTreeView.init();
     this.tree = document.getElementById("usageTree");
     this.tree.view = gUsageTreeView;
 
     this.loadData();
   },
 
   loadData: function loadData() {
-    window.setTimeout(function() {
-      let usage = Weave.Service.getCollectionUsage();
+    this._usage_req = Weave.Service.getStorageInfo(Weave.INFO_COLLECTION_USAGE,
+                                                   function (error, usage) {
+      delete gSyncQuota._usage_req;
+      // displayUsageData handles null values, so no need to check 'error'.
       gUsageTreeView.displayUsageData(usage);
-    }, 0);
+    });
 
     let usageLabel = document.getElementById("usageLabel");
     let bundle = this.bundle;
-    window.setTimeout(function() {
-      let quota = Weave.Service.getQuota();
-      if (!quota) {
+
+    this._quota_req = Weave.Service.getStorageInfo(Weave.INFO_QUOTA,
+                                                   function (error, quota) {
+      delete gSyncQuota._quota_req;
+
+      if (error) {
         usageLabel.value = bundle.getString("quota.usageError.label");
         return;
       }
       let used = gSyncQuota.convertKB(quota[0]);
       if (!quota[1]) {
         // No quota on the server.
         usageLabel.value = bundle.getFormattedString(
           "quota.usageNoQuota.label", used);
         return;
       }
       let percent = Math.round(100 * quota[0] / quota[1]);
       let total = gSyncQuota.convertKB(quota[1]);
       usageLabel.value = bundle.getFormattedString(
         "quota.usagePercentage.label", [percent].concat(used).concat(total));
-    }, 0);
+    });
+  },
+
+  onCancel: function onCancel() {
+    if (this._usage_req) {
+      this._usage_req.abort();
+    }
+    if (this._quota_req) {
+      this._quota_req.abort();
+    }
+    return true;
   },
 
   onAccept: function onAccept() {
     let engines = gUsageTreeView.getEnginesToDisable();
     for each (let engine in engines) {
       Weave.Engines.get(engine).enabled = false;
     }
     if (engines.length) {
       // The 'Weave' object will disappear once the window closes.
       let Service = Weave.Service;
       Weave.Utils.nextTick(function() { Service.sync(); });
     }
-    return true;
+    return this.onCancel();
   },
 
   convertKB: function convertKB(value) {
     return DownloadUtils.convertByteUnits(value * 1024);
   }
 
 };
 
--- a/browser/base/content/syncQuota.xul
+++ b/browser/base/content/syncQuota.xul
@@ -51,17 +51,17 @@
 <dialog id="quotaDialog"
         windowtype="Sync:ViewQuota"
         persist="screenX screenY width height"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
         xmlns:html="http://www.w3.org/1999/xhtml"
         onload="gSyncQuota.init()"
         buttons="accept,cancel"
         title="&quota.dialogTitle.label;"
-        ondialogcancel="return true;"
+        ondialogcancel="return gSyncQuota.onCancel();"
         ondialogaccept="return gSyncQuota.onAccept();">
 
   <script type="application/javascript"
           src="chrome://browser/content/syncQuota.js"/>
 
   <stringbundleset id="stringbundleset">
     <stringbundle id="quotaStrings"
                   src="chrome://browser/locale/syncQuota.properties"/>
--- a/browser/base/content/tabbrowser.css
+++ b/browser/base/content/tabbrowser.css
@@ -33,16 +33,26 @@
 .tab-stack {
   vertical-align: top; /* for pinned tabs */
 }
 
 tabpanels {
   background-color: transparent;
 }
 
+.tab-drag-preview {
+  background: -moz-element(#content) left top;
+  background-clip: content-box;
+  background-size: cover;
+}
+
+.tab-drag-panel[target] > .tab-drag-preview {
+  display: none;
+}
+
 .tab-drop-indicator {
   position: relative;
   z-index: 2;
 }
 
 .tab-throbber:not([busy]),
 .tab-throbber[busy] + .tab-icon-image {
   display: none;
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -1492,16 +1492,19 @@
               return;
             }
 
             var isLastTab = (this.tabs.length - this._removingTabs.length == 1);
 
             if (!this._beginRemoveTab(aTab, false, null, true))
               return;
 
+            if (this.tabContainer.draggedTab == aTab)
+              this.tabContainer._endTabDrag();
+
             if (!aTab.pinned && !aTab.hidden && aTab._fullyOpen && byMouse)
               this.tabContainer._lockTabSizing(aTab);
             else
               this.tabContainer._unlockTabSizing();
 
             if (!animate /* the caller didn't opt in */ ||
                 isLastTab ||
                 aTab.pinned ||
@@ -1693,16 +1696,18 @@
                 this.tabContainer._positionPinnedTabs();
 
               // update tab close buttons state
               this.tabContainer.adjustTabstrip();
 
               setTimeout(function(tabs) {
                 tabs._lastTabClosedByMouse = false;
               }, 0, this.tabContainer);
+
+              this.tabContainer._handleTabDrag(); // Update drag feedback.
             }
 
             // update first-tab/last-tab/beforeselected/afterselected attributes
             this.selectedTab._selected = true;
 
             // Removing the panel requires fixing up selectedPanel immediately
             // (see below), which would be hindered by the potentially expensive
             // browser removal. So we remove the browser and the panel in two
@@ -2671,49 +2676,57 @@
         <body><![CDATA[
           return !tab.pinned && !tab.hidden;
         ]]></body>
       </method>
     </implementation>
 
     <handlers>
       <handler event="underflow" phase="capturing"><![CDATA[
-        if (event.detail == 0)
+        if (event.originalTarget != this._scrollbox || event.detail == 0)
           return; // Ignore vertical events
 
         var tabs = document.getBindingParent(this);
         tabs.removeAttribute("overflow");
 
         if (tabs._lastTabClosedByMouse)
           tabs._expandSpacerBy(this._scrollButtonDown.clientWidth);
 
         tabs.tabbrowser._removingTabs.forEach(tabs.tabbrowser.removeTab,
                                               tabs.tabbrowser);
 
         tabs._positionPinnedTabs();
       ]]></handler>
       <handler event="overflow"><![CDATA[
-        if (event.detail == 0)
+        if (event.originalTarget != this._scrollbox || event.detail == 0)
           return; // Ignore vertical events
 
         var tabs = document.getBindingParent(this);
         tabs.setAttribute("overflow", "true");
         tabs._positionPinnedTabs();
       ]]></handler>
     </handlers>
   </binding>
 
   <binding id="tabbrowser-tabs"
            extends="chrome://global/content/bindings/tabbox.xml#tabs">
     <resources>
       <stylesheet src="chrome://browser/content/tabbrowser.css"/>
     </resources>
 
+    <!-- The onpopupshowing/hiding handlers on the panel are to circumvent
+         noautohide=true disabling level=top on Linux. See bug 448929. -->
     <content>
       <xul:hbox align="end">
+        <xul:panel class="tab-drag-panel" anonid="tab-drag-panel" hidden="true" level="top"
+                   onpopupshowing="this.setAttribute('noautohide', true);"
+                   onpopuphiding="this.removeAttribute('noautohide');">
+          <xul:label class="tab-drag-label" crop="end"/>
+          <xul:box class="tab-drag-preview"/>
+        </xul:panel>
         <xul:image class="tab-drop-indicator" anonid="tab-drop-indicator" collapsed="true"/>
       </xul:hbox>
       <xul:arrowscrollbox anonid="arrowscrollbox" orient="horizontal" flex="1"
                           style="min-width: 1px;"
 #ifndef XP_MACOSX
                           clicktoscroll="true"
 #endif
                           class="tabbrowser-arrowscrollbox">
@@ -2799,16 +2812,476 @@
         }
       });]]></field>
       <field name="_blockDblClick">false</field>
 
       <field name="_tabDropIndicator">
         document.getAnonymousElementByAttribute(this, "anonid", "tab-drop-indicator");
       </field>
 
+      <method name="_positionDropIndicator">
+        <parameter name="event"/>
+        <parameter name="scrollOnly"/>
+        <body><![CDATA[
+          var effects = event.dataTransfer ? this._setEffectAllowedForDataTransfer(event) : "";
+
+          var ind = this._tabDropIndicator;
+          if (effects == "none") {
+            ind.collapsed = true;
+            return;
+          }
+          event.preventDefault();
+          event.stopPropagation();
+
+          var tabStrip = this.mTabstrip;
+          var ltr = (window.getComputedStyle(this).direction == "ltr");
+
+          // Autoscroll the tab strip if we drag over the scroll
+          // buttons, even if we aren't dragging a tab, but then
+          // return to avoid drawing the drop indicator.
+          var pixelsToScroll = 0;
+          var target = event.originalTarget;
+          if (target.ownerDocument == document &&
+              this.getAttribute("overflow") == "true") {
+            let targetAnonid = target.getAttribute("anonid");
+            switch (targetAnonid) {
+              case "scrollbutton-up":
+                pixelsToScroll = tabStrip.scrollIncrement * -1;
+                break;
+              case "scrollbutton-down":
+                pixelsToScroll = tabStrip.scrollIncrement;
+                break;
+            }
+            if (pixelsToScroll) {
+              if (effects)
+                tabStrip.scrollByPixels((ltr ? 1 : -1) * pixelsToScroll);
+              else
+                tabStrip._startScroll(pixelsToScroll < 0 ? -1 : 1);
+            }
+          }
+
+          if (scrollOnly) {
+            ind.collapsed = true;
+            return;
+          }
+
+          if (effects == "link") {
+            let tab = this._getDragTargetTab(event);
+            if (tab) {
+              if (!this._dragTime)
+                this._dragTime = Date.now();
+              if (Date.now() >= this._dragTime + this._dragOverDelay)
+                this.selectedItem = tab;
+              ind.collapsed = true;
+              return;
+            }
+          }
+
+          var newIndex = this._getDropIndex(event);
+          var scrollRect = tabStrip.scrollClientRect;
+          var rect = this.getBoundingClientRect();
+          var minMargin = scrollRect.left - rect.left;
+          var maxMargin = Math.min(minMargin + scrollRect.width,
+                                   scrollRect.right);
+          if (!ltr)
+            [minMargin, maxMargin] = [this.clientWidth - maxMargin,
+                                      this.clientWidth - minMargin];
+          var newMargin;
+          if (pixelsToScroll) {
+            // If we are scrolling, put the drop indicator at the edge,
+            // so that it doesn't jump while scrolling.
+            newMargin = (pixelsToScroll > 0) ? maxMargin : minMargin;
+          }
+          else {
+            if (newIndex == this.childNodes.length) {
+              let tabRect = this.childNodes[newIndex-1].getBoundingClientRect();
+              if (ltr)
+                newMargin = tabRect.right - rect.left;
+              else
+                newMargin = rect.right - tabRect.left;
+            }
+            else {
+              let tabRect = this.childNodes[newIndex].getBoundingClientRect();
+              if (ltr)
+                newMargin = tabRect.left - rect.left;
+              else
+                newMargin = rect.right - tabRect.right;
+            }
+          }
+
+          ind.collapsed = false;
+
+          newMargin += ind.clientWidth / 2;
+          if (!ltr)
+            newMargin *= -1;
+
+          ind.style.MozTransform = "translate(" + Math.round(newMargin) + "px)";
+          ind.style.MozMarginStart = (-ind.clientWidth) + "px";
+        ]]></body>
+      </method>
+
+      <field name="_tabDragPanel">
+        document.getAnonymousElementByAttribute(this, "anonid", "tab-drag-panel");
+      </field>
+
+      <field name="draggedTab">null</field>
+
+      <method name="_handleTabDrag">
+        <parameter name="event"/>
+        <body><![CDATA[
+          let draggedTab = this.draggedTab;
+          if (!draggedTab)
+            return;
+
+          if (event)
+            draggedTab._dragData._savedEvent = event;
+          else
+            event = draggedTab._dragData._savedEvent;
+
+          if (this._updateTabDetachState(event, draggedTab))
+            return;
+
+          // Keep the dragged tab visually within the region of like tabs.
+          let tabs = this.tabbrowser.visibleTabs;
+          let numPinned = this.tabbrowser._numPinnedTabs;
+          let leftmostTab = draggedTab.pinned ? tabs[0] : tabs[numPinned];
+          let rightmostTab = draggedTab.pinned ? tabs[numPinned-1] : tabs[tabs.length-1];
+          let tabWidth = draggedTab.getBoundingClientRect().width;
+          let ltr = (window.getComputedStyle(this).direction == "ltr");
+          if (!ltr)
+            [leftmostTab, rightmostTab] = [rightmostTab, leftmostTab];
+          let left = leftmostTab.boxObject.screenX;
+          let right = rightmostTab.boxObject.screenX + tabWidth;
+          let transformX = event.screenX - draggedTab._dragData._dragStartX;
+          if (!draggedTab.pinned)
+            transformX += this.mTabstrip.scrollPosition;
+          let tabX = draggedTab.boxObject.screenX + transformX;
+          draggedTab._dragData._dragDistX = transformX;
+          if (tabX < left)
+            transformX += left - tabX;
+          // Prevent unintended overflow, especially in RTL mode.
+          else if (tabX + tabWidth > right)
+            transformX += right - tabX - tabWidth - (ltr ? 0 : 1);
+          draggedTab.style.MozTransform = "translate(" + transformX + "px)";
+
+          let newIndex = this._getDropIndex(event, draggedTab);
+          let tabAtNewIndex = this.childNodes[newIndex > draggedTab._tPos ?
+                                              newIndex-1 : newIndex];
+          this._positionDropIndicator(event, tabAtNewIndex.pinned == draggedTab.pinned);
+
+          if (newIndex == draggedTab._dragData._dropIndex)
+            return;
+          draggedTab._dragData._dropIndex = newIndex;
+
+          if (!ltr)
+            tabWidth *= -1;
+          tabs.forEach(function(tab) {
+            if (tab == draggedTab || tab.pinned != draggedTab.pinned)
+              return;
+            else if (tab._tPos < draggedTab._tPos && tab._tPos >= newIndex)
+              tab.style.MozTransform = "translate(" + tabWidth + "px)";
+            else if (tab._tPos > draggedTab._tPos && tab._tPos < newIndex)
+              tab.style.MozTransform = "translate(" + -tabWidth + "px)";
+            else
+              tab.style.MozTransform = "";
+          });
+        ]]></body>
+      </method>
+
+      <method name="_updateTabDetachState">
+        <parameter name="event"/>
+        <parameter name="draggedTab"/>
+        <body><![CDATA[
+          let data = draggedTab._dragData;
+          if (data._targetWindow.closed) {
+            data._targetWindow = window;
+            window.focus();
+          }
+          else if (data._dropTarget) {
+            data._dropTarget._tabDropIndicator.collapsed = true;
+          }
+          delete data._dropTarget;
+
+          function isEventOutsideWindow(event, win) {
+            return (event.screenX < win.screenX || event.screenX >= win.screenX + win.outerWidth ||
+                    event.screenY < win.screenY || event.screenY >= win.screenY + win.outerHeight);
+          }
+          if (isEventOutsideWindow(event, data._targetWindow) ||
+              Services.ww.activeWindow != data._targetWindow) {
+            // Iterate through browser windows in hopefully front-to-back order.
+            let winEnum = Services.wm.getZOrderDOMWindowEnumerator("navigator:browser", true);
+            let wins = [];
+            while (winEnum.hasMoreElements())
+              wins.push(winEnum.getNext());
+            // Work around broken z-order enumerator on Linux. See bug 156333.
+            if (!wins.length) {
+              winEnum = Services.wm.getEnumerator("navigator:browser");
+              while (winEnum.hasMoreElements())
+                wins.unshift(winEnum.getNext());
+            }
+            wins.every(function(win) {
+              if (win.closed || win.windowState == STATE_MINIMIZED ||
+                  isEventOutsideWindow(event, win))
+                return true;
+              data._targetWindow = win;
+              win.focus(); // Raise window when cursor moves over it.
+            });
+          }
+
+          let detached = (this.getAttribute("drag") == "detach");
+          let loneTab = (this.childElementCount == 1);
+          let bo = loneTab ? draggedTab.boxObject : this.parentNode.boxObject;
+          // Detach tab if outside window, to the left or right of tab strip, or
+          // at least one tab height above or below it.
+          if (data._targetWindow != window ||
+              event.screenX < bo.screenX || event.screenX >= bo.screenX + bo.width ||
+              event.screenY < bo.screenY - (detached || loneTab ? 0 : 1) * bo.height ||
+              event.screenY >= bo.screenY + (detached || loneTab ? 1 : 2) * bo.height) {
+            if (data._targetWindow != window &&
+                data._targetWindow.windowState != STATE_MINIMIZED) {
+              let that = data._targetWindow.gBrowser.tabContainer;
+              let bo = that.parentNode.boxObject;
+              if (event.screenX >= bo.screenX && event.screenX < bo.screenX + bo.width &&
+                  event.screenY >= bo.screenY && event.screenY < bo.screenY + bo.height) {
+                that._positionDropIndicator(event);
+                data._dropTarget = that;
+              }
+            }
+
+            let dragPanel = this._tabDragPanel;
+            if (data._dropTarget)
+              dragPanel.setAttribute("target", "true");
+            else
+              dragPanel.removeAttribute("target");
+
+            if (!detached) {
+              this.setAttribute("drag", "detach");
+              this._clearDragTransforms();
+              this._tabDropIndicator.collapsed = true;
+              if (draggedTab.style.maxWidth) {
+                data._maxWidth = draggedTab.style.maxWidth;
+                draggedTab.style.maxWidth = "";
+              }
+              delete data._dropIndex;
+              let label = dragPanel.firstChild;
+              let preview = dragPanel.lastChild;
+              label.value = draggedTab.label;
+              label.width = preview.width = Math.min(outerWidth / 2, screen.availWidth / 5);
+              let aspectRatio = this.tabbrowser.clientWidth / this.tabbrowser.clientHeight;
+              preview.height = Math.min(preview.width / aspectRatio, screen.availHeight / 5);
+              dragPanel.hidden = false;
+              dragPanel.openPopupAtScreen(event.screenX, event.screenY, false);
+            }
+            let width = dragPanel.clientWidth;
+            let [left, top] = this._getAdjustedCoords(event.screenX, event.screenY, width,
+                                                      dragPanel.clientHeight, width / 2, 12, true);
+            dragPanel.moveTo(left, top);
+            return true;
+          }
+          if (detached) { // Otherwise, put tab back in the tab strip.
+            this.setAttribute("drag", "move");
+            if (data._maxWidth) {
+              draggedTab.style.setProperty("max-width", data._maxWidth, "important");
+              delete draggedTab._maxWidth;
+            }
+            this.mTabstrip._updateScrollButtonsDisabledState();
+            this._tabDragPanel.hidePopup();
+          }
+        ]]></body>
+      </method>
+
+      <method name="_getAdjustedCoords">
+        <parameter name="aLeft"/>
+        <parameter name="aTop"/>
+        <parameter name="aWidth"/>
+        <parameter name="aHeight"/>
+        <parameter name="aOffsetX"/>
+        <parameter name="aOffsetY"/>
+        <parameter name="isPanel"/>
+        <body><![CDATA[
+          // screen.availTop et al. only check the source window's screen, but
+          // we want to look at the target window's screen.
+          let sX = {}, sY = {}, sWidth = {}, sHeight = {};
+          Cc["@mozilla.org/gfx/screenmanager;1"]
+            .getService(Ci.nsIScreenManager)
+            .screenForRect(aLeft, aTop, 1, 1)
+            .GetAvailRect(sX, sY, sWidth, sHeight);
+          // Window manager repositions panels that are too close to the right
+          // or bottom of a screen, so leave a gutter to avoid that.
+          if (isPanel) {
+            sWidth.value -= 3;
+            sHeight.value -= 3;
+          }
+          // Ensure rect will be entirely onscreen.
+          let width = Math.min(aWidth, sWidth.value);
+          let height = Math.min(aHeight, sHeight.value);
+          let left = Math.min(Math.max(aLeft - aOffsetX, sX.value),
+                              sX.value + sWidth.value - width);
+          let top = Math.min(Math.max(aTop - aOffsetY, sY.value),
+                             sY.value + sHeight.value - height);
+          return [left, top, width, height];
+        ]]></body>
+      </method>
+
+      <method name="_handleTabDrop">
+        <parameter name="event"/>
+        <body><![CDATA[
+          let draggedTab = this.draggedTab;
+          if (this.getAttribute("drag") == "move") {
+            this._slideTab(event, draggedTab);
+            return;
+          }
+
+          do {
+            let that = draggedTab._dragData._dropTarget;
+            let win = draggedTab._dragData._targetWindow;
+            if (!that || win.closed)
+              break;
+            that._tabDropIndicator.collapsed = true;
+            if (win.windowState == STATE_MINIMIZED)
+              break;
+            this._endTabDrag();
+
+            // User dropped the tab onto another window's tab strip, so swap the
+            // tab with a new one we create in that window, and then close it in
+            // this window (making it seem to have moved between windows).
+            let newIndex = that._getDropIndex(event);
+            let newTab = that.tabbrowser.addTab("about:blank");
+            let newBrowser = that.tabbrowser.getBrowserForTab(newTab);
+            newBrowser.stop(); // Stop the about:blank load.
+            newBrowser.docShell; // Make sure it has a docshell.
+            let numPinned = that.tabbrowser._numPinnedTabs;
+            if (newIndex < numPinned || draggedTab.pinned && newIndex == numPinned)
+              that.tabbrowser.pinTab(newTab);
+            that.tabbrowser.moveTabTo(newTab, newIndex);
+            that.tabbrowser.swapBrowsersAndCloseOther(newTab, draggedTab);
+
+            // We need to select the tab after we've done
+            // swapBrowsersAndCloseOther, so that the updateCurrentBrowser
+            // it triggers will correctly update our URL bar.
+            that.selectedItem = newTab;
+            return;
+          } while (false);
+
+          let [left, top, width, height] = this._getAdjustedCoords(
+            event.screenX, event.screenY, outerWidth, outerHeight,
+            this._tabDragPanel.clientWidth / 2, draggedTab._dragData._dragOffsetY);
+          this._endTabDrag();
+
+          if (this.childElementCount == 1) {
+            // Resize _before_ move to ensure the window fits the new screen. If
+            // the window is too large for its screen, the window manager may do
+            // automatic repositioning.
+            window.resizeTo(width, height);
+            window.moveTo(left, top);
+            window.focus();
+            return;
+          }
+
+          draggedTab.collapsed = true;
+          this.tabbrowser.replaceTabWithWindow(draggedTab, { screenX: left,
+                                                             screenY: top,
+#ifndef XP_WIN
+                                                             outerWidth: width,
+                                                             outerHeight: height
+#endif
+                                                             });
+        ]]></body>
+      </method>
+
+      <method name="_slideTab">
+        <parameter name="event"/>
+        <parameter name="draggedTab"/>
+        <body><![CDATA[
+          let oldIndex = draggedTab._tPos;
+          let newIndex = draggedTab._dragData._dropIndex;
+          if (newIndex > oldIndex)
+            newIndex--;
+          this.removeAttribute("drag");
+          this._endTabDrag();
+
+          if (!draggedTab.pinned && newIndex < this.tabbrowser._numPinnedTabs)
+            this.tabbrowser.pinTab(draggedTab);
+          else if (draggedTab.pinned && newIndex >= this.tabbrowser._numPinnedTabs)
+            this.tabbrowser.unpinTab(draggedTab);
+          else if (Services.prefs.getBoolPref("browser.tabs.animate")) {
+            let difference = 0;
+            // Calculate number of visible tabs between start and destination.
+            if (newIndex != oldIndex) {
+              let tabs = this.tabbrowser.visibleTabs;
+              for (let i = 0; i < tabs.length; i++) {
+                let position = tabs[i]._tPos;
+                if (position <= newIndex && position > oldIndex)
+                  difference++;
+                else if (position >= newIndex && position < oldIndex)
+                  difference--;
+              }
+            }
+            let displacement = difference * draggedTab.getBoundingClientRect().width;
+            if (window.getComputedStyle(this).direction == "rtl")
+              displacement *= -1;
+            let destination = "translate(" + displacement + "px)";
+            if (draggedTab.style.MozTransform != destination) {
+              this.setAttribute("drag", "finish");
+              draggedTab.style.MozTransform = destination;
+              draggedTab.addEventListener("transitionend", function finish(event) {
+                if (event.eventPhase != Event.AT_TARGET ||
+                    event.propertyName != "-moz-transform")
+                  return;
+                draggedTab.removeEventListener("transitionend", finish);
+                draggedTab.removeAttribute("dragged");
+                let that = draggedTab.parentNode;
+                that.removeAttribute("drag");
+                that._clearDragTransforms();
+                that.tabbrowser.moveTabTo(draggedTab, newIndex);
+              });
+              return;
+            }
+          }
+          draggedTab.removeAttribute("dragged");
+          this._clearDragTransforms();
+          this.tabbrowser.moveTabTo(draggedTab, newIndex);
+        ]]></body>
+      </method>
+
+      <method name="_endTabDrag">
+        <body><![CDATA[
+          let tab = this.draggedTab;
+          if (!tab)
+            return;
+          this.draggedTab = null;
+          delete tab._dragData;
+
+          document.removeEventListener("mousemove", this);
+          document.removeEventListener("mouseup", this);
+          this.removeEventListener("TabSelect", this);
+          this.mTabstrip.removeEventListener("scroll", this);
+
+          this._tabDragPanel.hidePopup();
+          this._tabDragPanel.hidden = true;
+          this._tabDropIndicator.collapsed = true;
+
+          if (this.hasAttribute("drag")) {
+            if (this.getAttribute("drag") == "detach")
+              this._unlockTabSizing();
+            tab.removeAttribute("dragged");
+            this.removeAttribute("drag");
+            this._clearDragTransforms();
+          }
+        ]]></body>
+      </method>
+
+      <method name="_clearDragTransforms">
+        <body>
+          this.tabbrowser.visibleTabs.forEach(function(visibleTab) {
+            visibleTab.style.MozTransform = "";
+          });
+        </body>
+      </method>
+
       <field name="_dragOverDelay">350</field>
       <field name="_dragTime">0</field>
 
       <field name="_container" readonly="true"><![CDATA[
         this.parentNode && this.parentNode.localName == "toolbar" ? this.parentNode : this;
       ]]></field>
 
       <property name="visible"
@@ -2959,37 +3432,34 @@
               tab.style.setProperty("max-width", tabWidth, "important");
               if (!isEndTab) { // keep tabs the same width
                 tab.style.MozTransition = "none";
                 tab.clientTop; // flush styles to skip animation; see bug 649247
                 tab.style.MozTransition = "";
               }
             }
             this._hasTabTempMaxWidth = true;
-            this.tabbrowser.addEventListener("mousemove", this, false);
-            window.addEventListener("mouseout", this, false);
+            window.addEventListener("mouseout", this);
           }
         ]]></body>
       </method>
 
       <method name="_expandSpacerBy">
         <parameter name="pixels"/>
         <body><![CDATA[
           let spacer = this._closingTabsSpacer;
           spacer.style.width = parseFloat(spacer.style.width) + pixels + "px";
           this._usingClosingTabsSpacer = true;
-          this.tabbrowser.addEventListener("mousemove", this, false);
-          window.addEventListener("mouseout", this, false);
+          window.addEventListener("mouseout", this);
         ]]></body>
       </method>
 
       <method name="_unlockTabSizing">
         <body><![CDATA[
-          this.tabbrowser.removeEventListener("mousemove", this, false);
-          window.removeEventListener("mouseout", this, false);
+          window.removeEventListener("mouseout", this);
           if (this._hasTabTempMaxWidth) {
             this._hasTabTempMaxWidth = false;
             let tabs = this.tabbrowser.visibleTabs;
             for (let i = 0; i < tabs.length; i++)
               tabs[i].style.maxWidth = "";
           }
           if (this._usingClosingTabsSpacer) {
             this._usingClosingTabsSpacer = false;
@@ -3046,24 +3516,46 @@
                 this.adjustTabstrip();
                 this._fillTrailingGap();
                 this._handleTabSelect();
                 this.mTabstripWidth = width;
               }
               this.tabbrowser.updateWindowResizers();
               break;
             case "mouseout":
-              // If the "related target" (the node to which the pointer went) is not
-              // a child of the current document, the mouse just left the window.
-              let relatedTarget = aEvent.relatedTarget;
-              if (relatedTarget && relatedTarget.ownerDocument == document)
+              if (this.draggedTab)
+                break;
+              let bo = this.mTabstrip.boxObject;
+              if (aEvent.screenX >= bo.screenX && aEvent.screenX < bo.screenX + bo.width &&
+                  aEvent.screenY >= bo.screenY && aEvent.screenY < bo.screenY + bo.height)
+                break;
+              let tabContextMenu = document.getElementById("tabContextMenu");
+              if (tabContextMenu.state == "open")
+                tabContextMenu.addEventListener("popuphidden", this);
+              else
+                this._unlockTabSizing();
+              break;
+            case "popuphidden": // Tab context menu was closed.
+              if (aEvent.eventPhase != Event.AT_TARGET)
                 break;
+              aEvent.target.removeEventListener("popuphidden", this);
+              this._unlockTabSizing();
+              break;
             case "mousemove":
-              if (document.getElementById("tabContextMenu").state != "open")
-                this._unlockTabSizing();
+              this._handleTabDrag(aEvent);
+              break;
+            case "mouseup":
+              this._handleTabDrop(aEvent);
+              break;
+            case "TabSelect": // Focus was stolen from dragged tab!
+              this._endTabDrag(aEvent);
+              window.focus();
+              break;
+            case "scroll": // Tab strip was scrolled.
+              this._handleTabDrag();
               break;
           }
         ]]></body>
       </method>
 
       <field name="_animateElement">
         this.mTabstrip._scrollButtonDown;
       </field>
@@ -3120,83 +3612,74 @@
               return null;
           }
           return tab;
         ]]></body>
       </method>
 
       <method name="_getDropIndex">
         <parameter name="event"/>
+        <parameter name="draggedTab"/>
         <body><![CDATA[
-          var tabs = this.childNodes;
-          var tab = this._getDragTargetTab(event);
-          if (window.getComputedStyle(this, null).direction == "ltr") {
-            for (let i = tab ? tab._tPos : 0; i < tabs.length; i++)
-              if (event.screenX < tabs[i].boxObject.screenX + tabs[i].boxObject.width / 2)
-                return i;
-          } else {
-            for (let i = tab ? tab._tPos : 0; i < tabs.length; i++)
-              if (event.screenX > tabs[i].boxObject.screenX + tabs[i].boxObject.width / 2)
-                return i;
+          function compare(a, b, lessThan) lessThan ? a < b : a > b;
+          let ltr = (window.getComputedStyle(this).direction == "ltr");
+          let eX = event.screenX;
+          let tabs = this.tabbrowser.visibleTabs;
+
+          if (draggedTab) {
+            let dist = draggedTab._dragData._dragDistX;
+            let tabX = draggedTab.boxObject.screenX + dist;
+            let draggingRight = dist > 0;
+            if (draggingRight)
+              tabX += draggedTab.boxObject.width;
+            // iterate through app tabs first, since their z-index is higher
+            else if (!draggedTab.pinned)
+              for (let i = 0, numPinned = this.tabbrowser._numPinnedTabs; i < numPinned; i++)
+                if (compare(eX, tabs[i].boxObject.screenX + tabs[i].boxObject.width / 2, ltr))
+                  return i;
+
+            let i = tabs.indexOf(draggedTab), tab = draggedTab, next;
+            while (next = ltr ^ draggingRight ? tabs[--i] : tabs[++i]) {
+              let x = next.pinned == draggedTab.pinned ? tabX : eX;
+              let middleOfNextTab = next.boxObject.screenX + next.boxObject.width / 2;
+              if (!compare(x, middleOfNextTab, !draggingRight))
+                break;
+              // ensure an app tab is actually inside the normal tab region
+              if (draggedTab.pinned && !next.pinned &&
+                  x < this.mTabstrip._scrollButtonUp.boxObject.screenX)
+                break;
+              tab = next;
+            }
+            return tab._tPos + (ltr ^ draggingRight ? 0 : 1);
           }
-          return tabs.length;
+
+          let tab = this._getDragTargetTab(event);
+          for (let i = tab ? tab._tPos : 0; i < tabs.length; i++)
+            if (compare(eX, tabs[i].boxObject.screenX + tabs[i].boxObject.width / 2, ltr))
+              return tabs[i]._tPos;
+          return this.childElementCount;
         ]]></body>
       </method>
 
       <method name="_setEffectAllowedForDataTransfer">
         <parameter name="event"/>
         <body><![CDATA[
           var dt = event.dataTransfer;
           // Disallow dropping multiple items
           if (dt.mozItemCount > 1)
             return dt.effectAllowed = "none";
 
-          var types = dt.mozTypesAt(0);
-          var sourceNode = null;
-          // tabs are always added as the first type
-          if (types[0] == TAB_DROP_TYPE) {
-            var sourceNode = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
-            if (sourceNode instanceof XULElement &&
-                sourceNode.localName == "tab" &&
-                (sourceNode.parentNode == this ||
-                 (sourceNode.ownerDocument.defaultView instanceof ChromeWindow &&
-                  sourceNode.ownerDocument.documentElement.getAttribute("windowtype") == "navigator:browser"))) {
-              if (sourceNode.parentNode == this &&
-                  (event.screenX >= sourceNode.boxObject.screenX &&
-                    event.screenX <= (sourceNode.boxObject.screenX +
-                                       sourceNode.boxObject.width))) {
-                return dt.effectAllowed = "none";
-              }
-
-              return dt.effectAllowed = "copyMove";
-            }
-          }
-
           if (browserDragAndDrop.canDropLink(event)) {
             // Here we need to do this manually
             return dt.effectAllowed = dt.dropEffect = "link";
           }
           return dt.effectAllowed = "none";
         ]]></body>
       </method>
 
-      <method name="_continueScroll">
-        <parameter name="event"/>
-        <body><![CDATA[
-          // Workaround for bug 481904: Dragging a tab stops scrolling at
-          // the tab's position when dragging to the first/last tab and back.
-          var t = this.selectedItem;
-          if (event.screenX >= t.boxObject.screenX &&
-              event.screenX <= t.boxObject.screenX + t.boxObject.width &&
-              event.screenY >= t.boxObject.screenY &&
-              event.screenY <= t.boxObject.screenY + t.boxObject.height)
-            this.mTabstrip.ensureElementIsVisible(t);
-        ]]></body>
-      </method>
-
       <method name="_handleNewTab">
         <parameter name="tab"/>
         <body><![CDATA[
           if (tab.parentNode != this)
             return;
 
           this.adjustTabstrip();
 
@@ -3319,306 +3802,96 @@
             // shortcuts only.
             return;
         }
         event.stopPropagation();
         event.preventDefault();
       ]]></handler>
 
       <handler event="dragstart"><![CDATA[
+        if (this.draggedTab)
+          return;
         var tab = this._getDragTargetTab(event);
-        if (!tab)
+        if (!tab || !tab._fullyOpen || tab.closing)
           return;
 
-        let dt = event.dataTransfer;
-        dt.mozSetDataAt(TAB_DROP_TYPE, tab, 0);
-        let uri = this.tabbrowser.getBrowserForTab(tab).currentURI;
-        let spec = uri ? uri.spec : "about:blank";
-
-        // We must not set text/x-moz-url or text/plain data here,
-        // otherwise trying to deatch the tab by dropping it on the desktop
-        // may result in an "internet shortcut"
-        dt.mozSetDataAt("text/x-moz-text-internal", spec, 0);
-
-        // Set the cursor to an arrow during tab drags.
-        dt.mozCursor = "default";
-
-        let canvas = tabPreviews.capture(tab, false);
-        dt.setDragImage(canvas, 0, 0);
-
-        // _dragOffsetX/Y give the coordinates that the mouse should be
-        // positioned relative to the corner of the new window created upon
-        // dragend such that the mouse appears to have the same position
-        // relative to the corner of the dragged tab.
-        function clientX(ele) ele.getBoundingClientRect().left;
-        let tabOffsetX = clientX(tab) -
-                         clientX(this.children[0].pinned ? this.children[0] : this);
-        tab._dragOffsetX = event.screenX - window.screenX - tabOffsetX;
-        tab._dragOffsetY = event.screenY - window.screenY;
+        this.setAttribute("drag", "move");
+        this.draggedTab = tab;
+        tab.setAttribute("dragged", "true");
+        let data = tab._dragData = {};
+        data._dragStartX = event.screenX;
+        if (!tab.pinned)
+          data._dragStartX += this.mTabstrip.scrollPosition;
+        data._dragDistX = 0;
+        data._dragOffsetY = event.screenY - window.screenY;
+        data._dropIndex = tab._tPos;
+        data._savedEvent = event;
+        data._targetWindow = window;
+
+        document.addEventListener("mousemove", this);
+        document.addEventListener("mouseup", this);
+        this.addEventListener("TabSelect", this);
+        this.mTabstrip.addEventListener("scroll", this);
 
         event.stopPropagation();
       ]]></handler>
 
-      <handler event="dragover"><![CDATA[
-        var effects = this._setEffectAllowedForDataTransfer(event);
-
-        var ind = this._tabDropIndicator;
-        if (effects == "" || effects == "none") {
-          ind.collapsed = true;
-          this._continueScroll(event);
+      <handler event="dragover" action="this._positionDropIndicator(event);"/>
+
+      <handler event="drop"><![CDATA[
+        this._tabDropIndicator.collapsed = true;
+
+        let dt = event.dataTransfer;
+        if (dt.dropEffect != "link")
+          return;
+
+        let url = browserDragAndDrop.drop(event, { });
+
+        // Disallow dropping strings that contain spaces (not a valid url
+        // character). Also disallow dropping javascript: or data: urls.
+        if (!url || !url.length || url.indexOf(" ") != -1 ||
+            /^\s*(javascript|data):/.test(url))
           return;
-        }
-        event.preventDefault();
-        event.stopPropagation();
-
-        var tabStrip = this.mTabstrip;
-        var ltr = (window.getComputedStyle(this, null).direction == "ltr");
-
-        // autoscroll the tab strip if we drag over the scroll
-        // buttons, even if we aren't dragging a tab, but then
-        // return to avoid drawing the drop indicator
-        var pixelsToScroll = 0;
-        if (this.getAttribute("overflow") == "true") {
-          var targetAnonid = event.originalTarget.getAttribute("anonid");
-          switch (targetAnonid) {
-            case "scrollbutton-up":
-              pixelsToScroll = tabStrip.scrollIncrement * -1;
-              break;
-            case "scrollbutton-down":
-              pixelsToScroll = tabStrip.scrollIncrement;
-              break;
-          }
-          if (pixelsToScroll)
-            tabStrip.scrollByPixels((ltr ? 1 : -1) * pixelsToScroll);
-        }
-
-        if (effects == "link") {
-          let tab = this._getDragTargetTab(event);
-          if (tab) {
-            if (!this._dragTime)
-              this._dragTime = Date.now();
-            if (Date.now() >= this._dragTime + this._dragOverDelay)
+
+        let bgLoad = Services.prefs.getBoolPref("browser.tabs.loadInBackground");
+
+        if (event.shiftKey)
+          bgLoad = !bgLoad;
+
+        let tab = this._getDragTargetTab(event);
+        if (!tab) {
+          // We're adding a new tab.
+          let newIndex = this._getDropIndex(event);
+          let newTab = this.tabbrowser.loadOneTab(getShortcutOrURI(url), {inBackground: bgLoad});
+          this.tabbrowser.moveTabTo(newTab, newIndex);
+        } else {
+          // Load in an existing tab.
+          try {
+            this.tabbrowser.getBrowserForTab(tab).loadURI(getShortcutOrURI(url));
+            if (!bgLoad)
               this.selectedItem = tab;
             ind.collapsed = true;
             return;
-          }
-        }
-
-        var newIndex = this._getDropIndex(event);
-        var scrollRect = tabStrip.scrollClientRect;
-        var rect = this.getBoundingClientRect();
-        var minMargin = scrollRect.left - rect.left;
-        var maxMargin = Math.min(minMargin + scrollRect.width,
-                                 scrollRect.right);
-        if (!ltr)
-          [minMargin, maxMargin] = [this.clientWidth - maxMargin,
-                                    this.clientWidth - minMargin];
-        var newMargin;
-        if (pixelsToScroll) {
-          // if we are scrolling, put the drop indicator at the edge
-          // so that it doesn't jump while scrolling
-          newMargin = (pixelsToScroll > 0) ? maxMargin : minMargin;
-        }
-        else {
-          if (newIndex == this.childNodes.length) {
-            let tabRect = this.childNodes[newIndex-1].getBoundingClientRect();
-            if (ltr)
-              newMargin = tabRect.right - rect.left;
-            else
-              newMargin = rect.right - tabRect.left;
-          }
-          else {
-            let tabRect = this.childNodes[newIndex].getBoundingClientRect();
-            if (ltr)
-              newMargin = tabRect.left - rect.left;
-            else
-              newMargin = rect.right - tabRect.right;
+          } catch(ex) {
+            // Just ignore invalid urls.
           }
         }
-
-        ind.collapsed = false;
-
-        newMargin += ind.clientWidth / 2;
-        if (!ltr)
-          newMargin *= -1;
-
-        ind.style.MozTransform = "translate(" + Math.round(newMargin) + "px)";
-        ind.style.MozMarginStart = (-ind.clientWidth) + "px";
-      ]]></handler>
-
-      <handler event="drop"><![CDATA[
-        var dt = event.dataTransfer;
-        var dropEffect = dt.dropEffect;
-        var draggedTab;
-        if (dropEffect != "link") { // copy or move
-          draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
-          // not our drop then
-          if (!draggedTab)
-            return;
-        }
-
-        this._tabDropIndicator.collapsed = true;
-        event.stopPropagation();
-
-        if (draggedTab && (dropEffect == "copy" ||
-            draggedTab.parentNode == this)) {
-          let newIndex = this._getDropIndex(event);
-          if (dropEffect == "copy") {
-            // copy the dropped tab (wherever it's from)
-            let newTab = this.tabbrowser.duplicateTab(draggedTab);
-            this.tabbrowser.moveTabTo(newTab, newIndex);
-            if (draggedTab.parentNode != this || event.shiftKey)
-              this.selectedItem = newTab;
-          } else {
-            // move the dropped tab
-            if (newIndex > draggedTab._tPos)
-              newIndex--;
-
-            if (draggedTab.pinned) {
-              if (newIndex >= this.tabbrowser._numPinnedTabs)
-                this.tabbrowser.unpinTab(draggedTab);
-            } else {
-              if (newIndex <= this.tabbrowser._numPinnedTabs - 1)
-                this.tabbrowser.pinTab(draggedTab);
-            }
-
-            this.tabbrowser.moveTabTo(draggedTab, newIndex);
-          }
-        } else if (draggedTab) {
-          // swap the dropped tab with a new one we create and then close
-          // it in the other window (making it seem to have moved between
-          // windows)
-          let newIndex = this._getDropIndex(event);
-          let newTab = this.tabbrowser.addTab("about:blank");
-          let newBrowser = this.tabbrowser.getBrowserForTab(newTab);
-          // Stop the about:blank load
-          newBrowser.stop();
-          // make sure it has a docshell
-          newBrowser.docShell;
-
-          this.tabbrowser.moveTabTo(newTab, newIndex);
-
-          this.tabbrowser.swapBrowsersAndCloseOther(newTab, draggedTab);
-
-          // We need to select the tab after we've done
-          // swapBrowsersAndCloseOther, so that the updateCurrentBrowser
-          // it triggers will correctly update our URL bar.
-          this.tabbrowser.selectedTab = newTab;
-        } else {
-          let url = browserDragAndDrop.drop(event, { });
-
-          // valid urls don't contain spaces ' '; if we have a space it isn't a valid url.
-          // Also disallow dropping javascript: or data: urls--bail out
-          if (!url || !url.length || url.indexOf(" ", 0) != -1 ||
-              /^\s*(javascript|data):/.test(url))
-            return;
-
-          let bgLoad = Services.prefs.getBoolPref("browser.tabs.loadInBackground");
-
-          if (event.shiftKey)
-            bgLoad = !bgLoad;
-
-          let tab = this._getDragTargetTab(event);
-          if (!tab || dropEffect == "copy") {
-            // We're adding a new tab.
-            let newIndex = this._getDropIndex(event);
-            let newTab = this.tabbrowser.loadOneTab(getShortcutOrURI(url), {inBackground: bgLoad});
-            this.tabbrowser.moveTabTo(newTab, newIndex);
-          } else {
-            // Load in an existing tab.
-            try {
-              this.tabbrowser.getBrowserForTab(tab).loadURI(getShortcutOrURI(url));
-              if (!bgLoad)
-                this.selectedItem = tab;
-            } catch(ex) {
-              // Just ignore invalid urls
-            }
-          }
-        }
-
-        // these offsets are only used in dragend, but we need to free them here
-        // as well
-        delete draggedTab._dragOffsetX;
-        delete draggedTab._dragOffsetY;
-      ]]></handler>
-
-      <handler event="dragend"><![CDATA[
-        // Note: while this case is correctly handled here, this event
-        // isn't dispatched when the tab is moved within the tabstrip,
-        // see bug 460801.
-
-        // * mozUserCancelled = the user pressed ESC to cancel the drag
-        var dt = event.dataTransfer;
-        if (dt.mozUserCancelled || dt.dropEffect != "none")
-          return;
-
-        // Disable detach within the browser toolbox
-        var eX = event.screenX;
-        var eY = event.screenY;
-        var wX = window.screenX;
-        // check if the drop point is horizontally within the window
-        if (eX > wX && eX < (wX + window.outerWidth)) {
-          let bo = this.mTabstrip.boxObject;
-          // also avoid detaching if the the tab was dropped too close to
-          // the tabbar (half a tab)
-          let endScreenY = bo.screenY + 1.5 * bo.height;
-          if (eY < endScreenY && eY > window.screenY)
-            return;
-        }
-
-        var draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
-        // screen.availLeft et. al. only check the screen that this window is on,
-        // but we want to look at the screen the tab is being dropped onto.
-        var sX = {}, sY = {}, sWidth = {}, sHeight = {};
-        Cc["@mozilla.org/gfx/screenmanager;1"]
-          .getService(Ci.nsIScreenManager)
-          .screenForRect(eX, eY, 1, 1)
-          .GetAvailRect(sX, sY, sWidth, sHeight);
-        // ensure new window entirely within screen
-        var winWidth = Math.min(window.outerWidth, sWidth.value);
-        var winHeight = Math.min(window.outerHeight, sHeight.value);
-        var left = Math.min(Math.max(eX - draggedTab._dragOffsetX, sX.value),
-                            sX.value + sWidth.value - winWidth);
-        var top = Math.min(Math.max(eY - draggedTab._dragOffsetY, sY.value),
-                           sY.value + sHeight.value - winHeight);
-
-        delete draggedTab._dragOffsetX;
-        delete draggedTab._dragOffsetY;
-
-        if (this.tabbrowser.tabs.length == 1) {
-          // resize _before_ move to ensure the window fits the new screen.  if
-          // the window is too large for its screen, the window manager may do
-          // automatic repositioning.
-          window.resizeTo(winWidth, winHeight);
-          window.moveTo(left, top);
-          window.focus();
-        } else {
-          this.tabbrowser.replaceTabWithWindow(draggedTab, { screenX: left,
-                                                             screenY: top,
-#ifndef XP_WIN
-                                                             outerWidth: winWidth,
-                                                             outerHeight: winHeight
-#endif
-                                                             });
-        }
-        event.stopPropagation();
       ]]></handler>
 
       <handler event="dragexit"><![CDATA[
         this._dragTime = 0;
 
         // This does not work at all (see bug 458613)
         var target = event.relatedTarget;
         while (target && target != this)
           target = target.parentNode;
         if (target)
           return;
 
         this._tabDropIndicator.collapsed = true;
-        this._continueScroll(event);
         event.stopPropagation();
       ]]></handler>
     </handlers>
   </binding>
 
   <!-- close-tab-button binding
        This binding relies on the structure of the tabbrowser binding.
        Therefore it should only be used as a child of the tab or the tabs
@@ -3736,17 +4009,16 @@
       <property name="hidden" readonly="true">
         <getter>
           return this.getAttribute("hidden") == "true";
         </getter>
       </property>
 
       <field name="mOverCloseButton">false</field>
       <field name="mCorrespondingMenuitem">null</field>
-      <field name="_fullyOpen">false</field>
       <field name="closing">false</field>
     </implementation>
 
     <handlers>
       <handler event="mouseover">
         var anonid = event.originalTarget.getAttribute("anonid");
         if (anonid == "close-button")
           this.mOverCloseButton = true;
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -37,18 +37,16 @@
 # 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 *****
 
 // Services = object with smart getters for common XPCOM services
 Components.utils.import("resource://gre/modules/Services.jsm");
 
-var TAB_DROP_TYPE = "application/x-moz-tabbrowser-tab";
-
 var gBidiUI = false;
 
 function getBrowserURL()
 {
   return "chrome://browser/content/browser.xul";
 }
 
 function getTopWin(skipPopups) {
--- a/browser/components/migration/src/nsProfileMigrator.cpp
+++ b/browser/components/migration/src/nsProfileMigrator.cpp
@@ -277,21 +277,21 @@ nsProfileMigrator::GetDefaultBrowserMigr
 
 PRBool
 nsProfileMigrator::ImportRegistryProfiles(const nsACString& aAppName)
 {
   nsresult rv;
 
   nsCOMPtr<nsIToolkitProfileService> profileSvc
     (do_GetService(NS_PROFILESERVICE_CONTRACTID));
-  NS_ENSURE_TRUE(profileSvc, NS_ERROR_FAILURE);
+  NS_ENSURE_TRUE(profileSvc, PR_FALSE);
 
   nsCOMPtr<nsIProperties> dirService
     (do_GetService("@mozilla.org/file/directory_service;1"));
-  NS_ENSURE_TRUE(dirService, NS_ERROR_FAILURE);
+  NS_ENSURE_TRUE(dirService, PR_FALSE);
 
   nsCOMPtr<nsILocalFile> regFile;
 #ifdef XP_WIN
   rv = dirService->Get(NS_WIN_APPDATA_DIR, NS_GET_IID(nsILocalFile),
                        getter_AddRefs(regFile));
   NS_ENSURE_SUCCESS(rv, PR_FALSE);
   regFile->AppendNative(aAppName);
   regFile->AppendNative(NS_LITERAL_CSTRING("registry.dat"));
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -146,19 +146,18 @@ BrowserGlue.prototype = {
     const MAX_DELAY = 300;
     let delay = 3;
     let browserEnum = Services.wm.getEnumerator("navigator:browser");
     while (browserEnum.hasMoreElements()) {
       delay += browserEnum.getNext().gBrowser.tabs.length;
     }
     delay = delay <= MAX_DELAY ? delay : MAX_DELAY;
 
-    let syncTemp = {};
-    Cu.import("resource://services-sync/service.js", syncTemp);
-    syncTemp.Weave.Service.delayedAutoConnect(delay);
+    Cu.import("resource://services-sync/main.js");
+    Weave.SyncScheduler.delayedAutoConnect(delay);
   },
 #endif
 
   // nsIObserver implementation 
   observe: function BG_observe(subject, topic, data) {
     switch (topic) {
       case "xpcom-shutdown":
         this._dispose();
--- a/browser/components/places/content/controller.js
+++ b/browser/components/places/content/controller.js
@@ -1391,27 +1391,23 @@ let PlacesControllerDragHelper = {
     // Check every dragged item.
     for (let i = 0; i < dropCount; i++) {
       let flavor = this.getFirstValidFlavor(dt.mozTypesAt(i));
       if (!flavor)
         return false;
 
       // Urls can be dropped on any insertionpoint.
       // XXXmano: remember that this method is called for each dragover event!
-      // Thus we shouldn't use unwrapNodes here at all if possible.
-      // I think it would be OK to accept bogus data here (e.g. text which was
-      // somehow wrapped as TAB_DROP_TYPE, this is not in our control, and
-      // will just case the actual drop to be a no-op), and only rule out valid
+      // Thus we shouldn't use unwrapNodes here at all if possible. I think it
+      // would be OK to accept bogus data here (this is not in our control and
+      // will just case the actual drop to be a no-op) and only rule out valid
       // expected cases, which are either unsupported flavors, or items which
       // cannot be dropped in the current insertionpoint. The last case will
       // likely force us to use unwrapNodes for the private data types of
       // places.
-      if (flavor == TAB_DROP_TYPE)
-        continue;
-
       let data = dt.mozGetDataAt(flavor, i);
       let dragged;
       try {
         dragged = PlacesUtils.unwrapNodes(data, flavor)[0];
       }
       catch (e) {
         return false;
       }
@@ -1515,31 +1511,18 @@ let PlacesControllerDragHelper = {
     let movedCount = 0;
     for (let i = 0; i < dropCount; ++i) {
       let flavor = this.getFirstValidFlavor(dt.mozTypesAt(i));
       if (!flavor)
         return false;
 
       let data = dt.mozGetDataAt(flavor, i);
       let unwrapped;
-      if (flavor != TAB_DROP_TYPE) {
-        // There's only ever one in the D&D case.
-        unwrapped = PlacesUtils.unwrapNodes(data, flavor)[0];
-      }
-      else if (data instanceof XULElement && data.localName == "tab" &&
-               data.ownerDocument.defaultView instanceof ChromeWindow) {
-        let uri = data.linkedBrowser.currentURI;
-        let spec = uri ? uri.spec : "about:blank";
-        let title = data.label;
-        unwrapped = { uri: spec,
-                      title: data.label,
-                      type: PlacesUtils.TYPE_X_MOZ_URL};
-      }
-      else
-        throw("bogus data was passed as a tab")
+      // There's only ever one in the D&D case.
+      unwrapped = PlacesUtils.unwrapNodes(data, flavor)[0];
 
       let index = insertionPoint.index;
 
       // Adjust insertion index to prevent reversal of dragged items. When you
       // drag multiple elts upward: need to increment index or each successive
       // elt will be inserted at the same index, each above the previous.
       let dragginUp = insertionPoint.itemId == unwrapped.parent &&
                       index < PlacesUtils.bookmarks.getItemIndex(unwrapped.id);
@@ -1583,17 +1566,16 @@ let PlacesControllerDragHelper = {
                   PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR,
                   PlacesUtils.TYPE_X_MOZ_PLACE],
 
   // The order matters.
   GENERIC_VIEW_DROP_TYPES: [PlacesUtils.TYPE_X_MOZ_PLACE_CONTAINER,
                             PlacesUtils.TYPE_X_MOZ_PLACE_SEPARATOR,
                             PlacesUtils.TYPE_X_MOZ_PLACE,
                             PlacesUtils.TYPE_X_MOZ_URL,
-                            TAB_DROP_TYPE,
                             PlacesUtils.TYPE_UNICODE],
 };
 
 
 XPCOMUtils.defineLazyServiceGetter(PlacesControllerDragHelper, "dragService",
                                    "@mozilla.org/widget/dragservice;1",
                                    "nsIDragService");
 
--- a/browser/devtools/webconsole/test/browser/browser_webconsole_bug_595934_message_categories.js
+++ b/browser/devtools/webconsole/test/browser/browser_webconsole_bug_595934_message_categories.js
@@ -46,17 +46,17 @@ const TESTS = [
   },
   { // #6
     file: "test-bug-595934-svg.xhtml",
     category: "SVG",
     matchString: "fooBarSVG",
   },
   { // #7
     file: "test-bug-595934-workers.html",
-    category: "DOM Worker javascript",
+    category: "Web Worker",
     matchString: "fooBarWorker",
   },
   { // #8
     file: "test-bug-595934-dom-html-external.html",
     category: "DOM:HTML",
     matchString: "document.all",
   },
   { // #9
--- a/browser/devtools/webconsole/test/browser/test-bug-603750-websocket.js
+++ b/browser/devtools/webconsole/test/browser/test-bug-603750-websocket.js
@@ -1,18 +1,18 @@
 /*
  * Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/
  */
 
 window.addEventListener("load", function () {
-  var ws1 = new WebSocket("ws://0.0.0.0:81");
+  var ws1 = new MozWebSocket("ws://0.0.0.0:81");
   ws1.onopen = function() {
     ws1.send("test 1");
     ws1.close();
   };
 
-  var ws2 = new window.frames[0].WebSocket("ws://0.0.0.0:82");
+  var ws2 = new window.frames[0].MozWebSocket("ws://0.0.0.0:82");
   ws2.onopen = function() {
     ws2.send("test 2");
     ws2.close();
   };
 }, false);
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -106,16 +106,18 @@ can reach it easily. -->
 <!ENTITY bookmarksToolbarChevron.tooltip "Show more bookmarks">
 
 <!ENTITY backCmd.label                "Back">
 <!ENTITY backCmd.accesskey            "B">
 <!ENTITY backButton.tooltip           "Go back one page">
 <!ENTITY forwardCmd.label             "Forward">
 <!ENTITY forwardCmd.accesskey         "F">
 <!ENTITY forwardButton.tooltip        "Go forward one page">
+<!ENTITY backForwardButtonMenu.tooltip "Right-click or pull down to show history">
+<!ENTITY backForwardButtonMenuMac.tooltip "Pull down to show history">
 <!ENTITY reloadCmd.label              "Reload">
 <!ENTITY reloadCmd.accesskey          "R">
 <!ENTITY reloadButton.tooltip         "Reload current page">
 <!ENTITY stopCmd.label                "Stop">
 <!ENTITY stopCmd.accesskey            "S">
 <!ENTITY stopCmd.macCommandKey        ".">
 <!ENTITY stopButton.tooltip           "Stop loading this page">
 <!ENTITY goEndCap.tooltip             "Go to the address in the Location Bar">
--- a/browser/themes/gnomestripe/browser/browser.css
+++ b/browser/themes/gnomestripe/browser/browser.css
@@ -1595,16 +1595,20 @@ richlistitem[type~="action"][actiontype=
   list-style-image: url("moz-icon://stock/gtk-undelete?size=menu");
 }
 
 #context_closeTab {
   list-style-image: url("moz-icon://stock/gtk-close?size=menu");
 }
 
 /* Tab drag and drop */
+.tab-drag-label {
+  padding: 2px;
+}
+
 .tab-drop-indicator {
   list-style-image: url(chrome://browser/skin/tabbrowser/tabDragIndicator.png);
   margin-bottom: -11px;
 }
 
 /* In-tab close button */
 .tab-close-button > .toolbarbutton-icon {
   /* XXX Buttons have padding in widget/ that we don't want here but can't override with good CSS, so we must
--- a/browser/themes/pinstripe/browser/browser.css
+++ b/browser/themes/pinstripe/browser/browser.css
@@ -1555,16 +1555,17 @@ toolbarbutton.chevron > .toolbarbutton-m
                    margin 30ms ease-out 80ms;
 }
 
 .tab-stack {
   /* ensure stable tab height with and without toolbarbuttons on the tab bar */
   height: 26px;
 }
 
+.tab-drag-label,
 .tabbrowser-tab,
 .tabs-newtab-button {
   -moz-appearance: none;
   font: message-box;
   font-weight: bold;
   text-shadow: @loweredShadow@;
   margin: 0;
   padding: 0;
@@ -1832,16 +1833,29 @@ toolbarbutton.chevron > .toolbarbutton-m
 @TABSONBOTTOM_TAB_STACK@ > .tab-content {
   padding-bottom: 2px;
 }
 
 /**
  * Tab Drag and Drop
  */
 
+.tab-drag-label {
+  background: -moz-linear-gradient(#eee, #ccc);
+  padding: 4px 8px;
+  border-radius: 4px;
+  box-shadow: inset 0 1px 0 rgba(255,255,255,.6);
+}
+
+.tab-drag-panel:not([target]) > .tab-drag-label {
+  background: -moz-linear-gradient(#ddd, #bbb);
+  border-bottom: 1px solid #999;
+  border-radius: 3px 3px 0 0;
+}
+
 .tab-drop-indicator {
   list-style-image: url(chrome://browser/skin/tabbrowser/tabDragIndicator.png);
   margin-bottom: -8px;
 }
 
 /**
  * In-tab close button
  */
--- a/browser/themes/pinstripe/browser/places/organizer.css
+++ b/browser/themes/pinstripe/browser/places/organizer.css
@@ -90,16 +90,25 @@
 
 #placesToolbar > toolbarbutton:not([disabled="true"]):active:hover,
 #placesToolbar > toolbarbutton[open="true"] {
   background: @toolbarbuttonPressedBackgroundColor@;
   text-shadow: @loweredShadow@;
   box-shadow: @toolbarbuttonPressedInnerShadow@, @loweredShadow@;
 }
 
+#placesToolbar > toolbarbutton:-moz-focusring {
+  border-color: @toolbarbuttonFocusedBorderColorAqua@;
+  box-shadow: @focusRingShadow@;
+}
+
+#placesToolbar > toolbarbutton:-moz-system-metric(mac-graphite-theme):-moz-focusring {
+  border-color: @toolbarbuttonFocusedBorderColorGraphite@;
+}
+
 #placesToolbar > toolbarbutton:-moz-window-inactive {
   border-color: @toolbarbuttonInactiveBorderColor@;
   background-image: @toolbarbuttonInactiveBackgroundImage@;
 }
 
 #placesToolbar > toolbarbutton[disabled="true"] > .toolbarbutton-icon {
   opacity: 0.5;
 }
--- a/browser/themes/winstripe/browser/browser-aero.css
+++ b/browser/themes/winstripe/browser/browser-aero.css
@@ -6,26 +6,28 @@
 %define glassActiveBorderColor rgb(37, 44, 51)
 %define glassInactiveBorderColor rgb(102, 102, 102)
 
 @media not all and (-moz-windows-classic) {
   #main-window[sizemode="normal"] > #titlebar > #titlebar-content > #appmenu-button-container {
     margin-top: 1px;
   }
 
+  .tab-drag-preview::before,
   #appmenu-button {
     border-width: 2px;
     -moz-border-left-colors: @appMenuButtonBorderColor@;
     -moz-border-bottom-colors: @appMenuButtonBorderColor@;
     -moz-border-right-colors: @appMenuButtonBorderColor@;
     margin-bottom: 1px; /* compensate white outer border */
     box-shadow: 0 1px 0 rgba(255,255,255,.25) inset,
                 0 0 2px 1px rgba(255,255,255,.25) inset;
   }
 
+  #main-window[privatebrowsingmode=temporary] .tab-drag-preview::before,
   #main-window[privatebrowsingmode=temporary] #appmenu-button {
     -moz-border-left-colors: rgba(255,255,255,.5) rgba(43,8,65,.9);
     -moz-border-bottom-colors: rgba(255,255,255,.5) rgba(43,8,65,.9);
     -moz-border-right-colors: rgba(255,255,255,.5) rgba(43,8,65,.9);
   }
 
   #appmenu-popup {
     margin-top: -1px;
@@ -50,16 +52,17 @@
   }
 
   .tabbrowser-tab:not(:-moz-lwtheme):hover,
   .tabs-newtab-button:not(:-moz-lwtheme):hover {
     background-image: @toolbarShadowOnTab@, @bgTabTextureHover@,
                       -moz-linear-gradient(@customToolbarColor@, @customToolbarColor@);
   }
 
+  .tab-drag-label,
   .tabbrowser-tab[selected="true"]:not(:-moz-lwtheme) {
     background-image: -moz-linear-gradient(white, @toolbarHighlight@ 50%),
                       -moz-linear-gradient(@customToolbarColor@, @customToolbarColor@);
   }
 
   #main-window[tabsontop=false]:not([disablechrome]) .tabbrowser-tab[selected=true]:not(:-moz-lwtheme) {
     background-image: @toolbarShadowOnTab@,
                       -moz-linear-gradient(white, @toolbarHighlight@ 50%),
@@ -288,16 +291,41 @@
     text-shadow: white -1px -1px .35em, white -1px 1px .35em, white 1px 1px .35em, white 1px -1px .35em;
   }
 
   #tab-view:-moz-lwtheme {
     background-image: url("chrome://browser/skin/tabview/grain.png"),
                       -moz-linear-gradient(rgba(255,255,255,0), #CCD9EA 200px, #C7D5E7);
     background-attachment: fixed;
   }
+
+  .tab-drag-panel {
+    -moz-appearance: -moz-win-borderless-glass;
+  }
+  .tab-drag-label {
+    padding: 4px;
+    background-color: -moz-dialog;
+    border-radius: 3px;
+  }
+  .tab-drag-preview {
+    margin: 15px 7px 7px;
+  }
+  .tab-drag-panel:not([target]) > .tab-drag-preview {
+    display: block;
+  }
+  .tab-drag-preview::before { /* miniature appmenu button */
+    content: "";
+    display: block;
+    margin-top: -15px;
+    -moz-margin-start: -2px;
+    padding: 0;
+    width: 32px;
+    height: 7px;
+    border-radius: 0 0 3px 3px;
+  }
 }
 
 @media not all and (-moz-windows-compositor) {
   #main-window:-moz-system-metric(windows-default-theme) {
     background-color: rgb(185,209,234);
   }
   #main-window:-moz-system-metric(windows-default-theme):-moz-window-inactive {
     background-color: rgb(215,228,242);
--- a/browser/themes/winstripe/browser/browser.css
+++ b/browser/themes/winstripe/browser/browser.css
@@ -171,16 +171,17 @@
 %endif
 
 #appmenu-button:hover:active,
 #appmenu-button[open] {
   border-radius: 0;
 }
 
 %ifdef MOZ_OFFICIAL_BRANDING
+.tab-drag-preview::before,
 #appmenu-button {
   background-image: -moz-linear-gradient(rgb(247,182,82), rgb(215,98,10) 95%);
   border-color: rgba(83,42,6,.9);
   box-shadow: 0 1px 0 rgba(255,255,255,.25) inset,
               0 0 0 1px rgba(255,255,255,.25) inset;
 }
 #appmenu-button:hover:not(:active):not([open]) {
   background-image: -moz-radial-gradient(center bottom, farthest-side, rgba(252,240,89,.5) 10%, rgba(252,240,89,0) 70%),
@@ -194,16 +195,17 @@
 #appmenu-button:hover:active,
 #appmenu-button[open] {
   background-image: -moz-linear-gradient(rgb(246,170,69), rgb(209,74,0) 95%);
   box-shadow: 0 2px 3px rgba(0,0,0,.4) inset,
               0 1px 1px rgba(0,0,0,.2) inset;
 }
 %else
 %if MOZ_UPDATE_CHANNEL == aurora
+.tab-drag-preview::before,
 #appmenu-button {
   background-image: -moz-linear-gradient(hsl(208,99%,37%), hsl(214,90%,23%) 95%);
   border-color: hsla(214,89%,21%,.9);
   box-shadow: 0 1px 0 hsla(205,100%,72%,.2) inset,
               0 0 2px 1px hsla(205,100%,72%,.25) inset;
 }
 #appmenu-button:hover:not(:active):not([open]) {
   background-image: -moz-radial-gradient(center bottom, farthest-side, hsla(202,100%,85%,.5) 10%, hsla(202,100%,85%,0) 70%),
@@ -216,16 +218,17 @@
 }
 #appmenu-button:hover:active,
 #appmenu-button[open] {
   background-image: -moz-linear-gradient(hsl(208,95%,30%), hsl(214,85%,17%) 95%);
   box-shadow: 0 2px 3px rgba(0,0,0,.4) inset,
               0 1px 1px rgba(0,0,0,.2) inset;
 }
 %else
+.tab-drag-preview::before,
 #appmenu-button {
   background-image: -moz-linear-gradient(hsl(211,33%,32%), hsl(209,53%,10%) 95%);
   border-color: hsla(210,59%,13%,.9);
   box-shadow: 0 1px 0 hsla(210,48%,90%,.15) inset,
               0 0 2px 1px hsla(211,65%,85%,.15) inset;
 }
 #appmenu-button:hover:not(:active):not([open]) {
   background-image: -moz-radial-gradient(center bottom, farthest-side, hsla(210,48%,90%,.5) 10%, hsla(210,48%,90%,0) 70%),
@@ -240,16 +243,17 @@
 #appmenu-button[open] {
   background-image: -moz-linear-gradient(hsl(211,33%,26%), hsl(209,53%,6%) 95%);
   box-shadow: 0 2px 3px rgba(0,0,0,.4) inset,
               0 1px 1px rgba(0,0,0,.2) inset;
 }
 %endif
 %endif
 
+#main-window[privatebrowsingmode=temporary] .tab-drag-preview::before,
 #main-window[privatebrowsingmode=temporary] #appmenu-button {
   background-image: -moz-linear-gradient(rgb(153,38,211), rgb(105,19,163) 95%);
   border-color: rgba(43,8,65,.9);
 }
 
 #main-window[privatebrowsingmode=temporary] #appmenu-button:hover:not(:active):not([open]) {
   background-image: -moz-radial-gradient(center bottom, farthest-side, rgba(240,193,255,.5) 10%, rgba(240,193,255,0) 70%),
                     -moz-radial-gradient(center bottom, farthest-side, rgb(192,81,247), rgba(236,172,255,0)),
@@ -1801,17 +1805,35 @@ richlistitem[type~="action"][actiontype=
   -moz-margin-end: 5px;
 }
 
 /* tabbrowser-tab focus ring */
 .tabbrowser-tab:focus > .tab-stack {
   outline: 1px dotted;
 }
 
-/* Tab DnD indicator */
+/* Tab drag and drop */
+.tab-drag-panel {
+  border: 0 !important;
+}
+
+.tab-drag-label {
+  margin: 0 !important;
+  padding: 5px;
+  border: 1px solid DimGray;
+}
+
+.tab-drag-panel:not([target]) > .tab-drag-label {
+  display: none;
+}
+
+.tab-drag-preview {
+  border: 1px solid rgba(0,0,0,.5);
+}
+
 .tab-drop-indicator {
   list-style-image: url(chrome://browser/skin/tabbrowser/tabDragIndicator.png);
   margin-bottom: -11px;
 }
 
 /* Tab close button */
 .tab-close-button {
   -moz-appearance: none;
--- a/build/unix/check_debug_ranges.py
+++ b/build/unix/check_debug_ranges.py
@@ -48,33 +48,33 @@ def get_range_for(compilation_unit, debu
        in a given debug_info.'''
     name = ranges = ''
     search_cu = False
     for nfo in debug_info.splitlines():
         if 'DW_TAG_compile_unit' in nfo:
             search_cu = True
         elif 'DW_TAG_' in nfo or not nfo.strip():
             if name == compilation_unit:
-                return int(ranges, 0)
+                return int(ranges, 16)
             name = ranges = ''
             search_cu = False
         if search_cu:
             if 'DW_AT_name' in nfo:
                 name = nfo.rsplit(None, 1)[1]
             elif 'DW_AT_ranges' in nfo:
                 ranges = nfo.rsplit(None, 1)[1]
     return None
 
 def get_range_length(range, debug_ranges):
     '''Returns the number of items in the range starting at the
        given offset.'''
     length = 0
     for line in debug_ranges.splitlines():
         m = re.match('\s*([0-9a-fA-F]+)\s+([0-9a-fA-F]+)\s+([0-9a-fA-F]+)', line)
-        if m and int(m.group(1), 0) == range:
+        if m and int(m.group(1), 16) == range:
             length += 1
     return length
 
 def main(bin, compilation_unit):
     p = subprocess.Popen(['objdump', '-W', bin], stdout = subprocess.PIPE, stderr = subprocess.PIPE)
     (out, err) = p.communicate()
     sections = re.split('\n(Contents of the|The section) ', out)
     debug_info = [s for s in sections if s.startswith('.debug_info')]
--- a/build/unix/elfhack/Makefile.in
+++ b/build/unix/elfhack/Makefile.in
@@ -85,16 +85,18 @@ test$(DLL_SUFFIX): test.$(OBJ_SUFFIX) el
 	@echo ===
 	@rm -f $@.bak
 	$(CURDIR)/elfhack -b $@
 	# Fail if the backup file doesn't exist
 	[ -f "$@.bak" ]
 	# Fail if the new library doesn't contain less relocations
 	[ $$(objdump -R $@.bak | wc -l) -gt $$(objdump -R $@ | wc -l) ]
 
+.PRECIOUS: test$(DLL_SUFFIX)
+
 dummy: dummy.$(OBJ_SUFFIX) test$(DLL_SUFFIX)
 	$(CC) -o $@ $^ $(LDFLAGS)
 
 libs:: dummy
 	# Will either crash or return exit code 1 if elfhack is broken
 	LD_LIBRARY_PATH=$(CURDIR) $(CURDIR)/dummy
 
 CSRCS += test.c dummy.c
--- a/caps/src/nsScriptSecurityManager.cpp
+++ b/caps/src/nsScriptSecurityManager.cpp
@@ -2634,17 +2634,17 @@ nsScriptSecurityManager::IsCapabilityEna
         if (NS_FAILED(rv)) return rv;
         if (*result)
             return NS_OK;
 
         // Capabilities do not extend to calls into C/C++ and then back into
         // the JS engine via JS_EvaluateScript or similar APIs.
         if (JS_IsGlobalFrame(cx, fp))
             break;
-    } while ((fp = JS_FrameIterator(cx, &fp)) != nsnull);
+    } while (fp != target && (fp = JS_FrameIterator(cx, &fp)) != nsnull);
 
     if (!previousPrincipal)
     {
         // No principals on the stack, all native code.  Allow
         // execution if the subject principal is the system principal.
 
         return SubjectPrincipalIsSystem(result);
     }
--- a/config/JarMaker.py
+++ b/config/JarMaker.py
@@ -378,17 +378,17 @@ class JarMaker(object):
       elif src.startswith('/'):
         # path/in/jar/file_name.xul     (/path/in/sourcetree/file_name.xul)
         # refers to a path relative to topsourcedir, use that as base
         # and strip the leading '/'
         src_base = [topsourcedir]
         src = src[1:]
       else:
         # use srcdirs and the objdir (current working dir) for relative paths
-        src_base = sourcedirs + ['.']
+        src_base = sourcedirs + [os.getcwd()]
       # check if the source file exists
       realsrc = None
       for _srcdir in src_base:
         if os.path.isfile(os.path.join(_srcdir, src)):
           realsrc = os.path.join(_srcdir, src)
           break
       if realsrc is None:
         if jf is not None:
--- a/config/autoconf.mk.in
+++ b/config/autoconf.mk.in
@@ -325,16 +325,17 @@ PROFILE_USE_LDFLAGS = @PROFILE_USE_LDFLA
 XCFLAGS		= @XCFLAGS@
 XLDFLAGS	= @XLDFLAGS@
 XLIBS		= @XLIBS@
 XEXT_LIBS	= @XEXT_LIBS@
 XCOMPOSITE_LIBS	= @XCOMPOSITE_LIBS@
 XSS_LIBS	= @XSS_LIBS@
 
 MOZ_THUMB2	= @MOZ_THUMB2@
+MOZ_EGL_XRENDER_COMPOSITE	= @MOZ_EGL_XRENDER_COMPOSITE@
 
 WIN_TOP_SRC	= @WIN_TOP_SRC@
 AR		= @AR@
 AR_FLAGS	= @AR_FLAGS@
 AR_EXTRACT	= @AR_EXTRACT@
 AR_LIST		= @AR_LIST@
 AR_DELETE	= @AR_DELETE@
 AS		= @AS@
--- a/config/config.mk
+++ b/config/config.mk
@@ -159,20 +159,20 @@ endif
 
 CC := $(CC_WRAPPER) $(CC)
 CXX := $(CXX_WRAPPER) $(CXX)
 MKDIR ?= mkdir
 SLEEP ?= sleep
 TOUCH ?= touch
 
 ifndef .PYMAKE
-PYTHONPATH = $(PYTHON) $(topsrcdir)/config/pythonpath.py
+PYTHON_PATH = $(PYTHON) $(topsrcdir)/config/pythonpath.py
 else
 PYCOMMANDPATH += $(topsrcdir)/config
-PYTHONPATH = %pythonpath main
+PYTHON_PATH = %pythonpath main
 endif
 
 # determine debug-related options
 _DEBUG_CFLAGS :=
 _DEBUG_LDFLAGS :=
 
 ifdef MOZ_DEBUG
   _DEBUG_CFLAGS += $(MOZ_DEBUG_ENABLE_DEFS) $(MOZ_DEBUG_FLAGS)
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -1532,17 +1532,17 @@ endif
 
 XPIDL_DEPS = \
   $(topsrcdir)/xpcom/idl-parser/header.py \
   $(topsrcdir)/xpcom/idl-parser/xpidl.py \
   $(NULL)
 
 $(XPIDL_GEN_DIR)/%.h: %.idl $(XPIDL_DEPS) $(XPIDL_GEN_DIR)/.done
 	$(REPORT_BUILD)
-	$(PYTHONPATH) \
+	$(PYTHON_PATH) \
 	  -I$(topsrcdir)/other-licenses/ply \
 	  -I$(topsrcdir)/xpcom/idl-parser \
 	  $(topsrcdir)/xpcom/idl-parser/header.py --cachedir=$(topsrcdir)/xpcom/idl-parser $(XPIDL_FLAGS) $(_VPATH_SRCS) -d $(MDDEPDIR)/$(@F).pp -o $@
 	@if test -n "$(findstring $*.h, $(EXPORTS))"; \
 	  then echo "*** WARNING: file $*.h generated from $*.idl overrides $(srcdir)/$*.h"; else true; fi
 
 ifndef NO_GEN_XPT
 # generate intermediate .xpt files into $(XPIDL_GEN_DIR), then link
--- a/configure.in
+++ b/configure.in
@@ -4771,16 +4771,34 @@ MOZ_ARG_ENABLE_BOOL(system-hunspell,
 
 if test -n "$SYSTEM_HUNSPELL"; then
     PKG_CHECK_MODULES(MOZ_HUNSPELL, hunspell)
 fi
 
 AC_SUBST(SYSTEM_HUNSPELL)
 
 dnl ========================================================
+dnl system libffi Support
+dnl ========================================================
+MOZ_ARG_ENABLE_BOOL(system-ffi,
+[  --enable-system-ffi       Use system libffi (located with pkgconfig)],
+    MOZ_NATIVE_FFI=1 )
+
+if test -n "$MOZ_NATIVE_FFI"; then
+    # Vanilla libffi 3.0.9 needs a few patches from upcoming version 3.0.10
+    # for non-GCC compilers.
+    if test -z "$GNU_CC"; then
+        PKG_CHECK_MODULES(MOZ_FFI, libffi > 3.0.9)
+    else
+        PKG_CHECK_MODULES(MOZ_FFI, libffi >= 3.0.9)
+    fi
+    MOZ_JS_STATIC_LIBS="$MOZ_JS_STATIC_LIBS $MOZ_FFI_LIBS"
+fi
+
+dnl ========================================================
 dnl Java SDK support
 dnl ========================================================
 
 JAVA_BIN_PATH=
 MOZ_ARG_WITH_STRING(java-bin-path,
 [  --with-java-bin-path=dir
                           Location of Java binaries (java, javac, jar)],
     JAVA_BIN_PATH=$withval)
@@ -6961,24 +6979,26 @@ if test $MOZ_PLATFORM_MAEMO; then
    AC_SUBST(MOZ_PLATFORM_MAEMO_CFLAGS)
 fi
 
 dnl ========================================================
 dnl = ARM toolchain tweaks
 dnl ========================================================
 
 dnl Defaults
-case "${target}" in
-arm-android*|arm-linuxandroid*)
+case "${CPU_ARCH}-${OS_TARGET}" in
+arm-Android)
     MOZ_THUMB=yes
     MOZ_ARCH=armv7-a
     MOZ_FPU=vfp
     MOZ_FLOAT_ABI=softfp
-    ;;
-arm*-*)
+    # Temporarily set nspr flags via configure, until bug 674880 lands
+    NSPR_CONFIGURE_FLAGS="--with-thumb --with-arch=armv7-a --with-fpu=vfp --with-float-abi=softfp"
+    ;;
+arm-*)
     if test -n "$MOZ_PLATFORM_MAEMO"; then
         MOZ_THUMB=no
         MOZ_ARCH=armv7-a
         MOZ_FLOAT_ABI=softfp
     fi
     if test "$MOZ_PLATFORM_MAEMO" = 6; then
         MOZ_THUMB=yes
     fi
@@ -7156,16 +7176,30 @@ if test "$CPU_ARCH" = "arm"; then
       HAVE_ARM_NEON=1
   fi
 fi # CPU_ARCH = arm
 
 AC_SUBST(HAVE_ARM_SIMD)
 AC_SUBST(HAVE_ARM_NEON)
 
 dnl ========================================================
+dnl = XRender Composite
+dnl ========================================================
+MOZ_ARG_ENABLE_BOOL(egl-xrender-composite,
+[  --enable-egl-xrender-composite   
+                          Enable EGL xrender composite optimizations],
+    MOZ_EGL_XRENDER_COMPOSITE=1)
+
+if test -n "$MOZ_EGL_XRENDER_COMPOSITE"; then
+    AC_DEFINE(MOZ_EGL_XRENDER_COMPOSITE)
+fi
+
+AC_SUBST(MOZ_EGL_XRENDER_COMPOSITE)
+
+dnl ========================================================
 dnl = faststripe theme
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(faststripe,
 [  --enable-faststripe     Use faststripe theme],
     MOZ_THEME_FASTSTRIPE=1,
     MOZ_THEME_FASTSTRIPE= )
 AC_SUBST(MOZ_THEME_FASTSTRIPE)
 
@@ -7470,72 +7504,64 @@ else
   *-netbsd*)
     AC_DEFINE(MOZ_MEMORY_BSD)
     ;;
   *-solaris*)
     AC_DEFINE(MOZ_MEMORY_SOLARIS)
     ;;
   *-mingw*)
     AC_DEFINE(MOZ_MEMORY_WINDOWS)
-    dnl This is sort of awful. Will revisit if we add support for more versions
+    AC_MSG_CHECKING([for VC2005/2008++ CRT source])
     if test "$CC_VERSION" == "14.00.50727.762" -o "$CC_VERSION" == "15.00.30729.01"; then
-      WIN32_OLD_STYLE_JEMALLOC=1
-      AC_DEFINE(WIN32_OLD_STYLE_JEMALLOC)
-    elif test "$CC_VERSION" == "16.00.30319.01" -o "$CC_VERSION" == "16.00.40219.01"; then
-      WIN32_NEW_STYLE_JEMALLOC=1
-      AC_DEFINE(WIN32_NEW_STYLE_JEMALLOC)
-    else        
-      AC_MSG_ERROR([Building jemalloc requires exactly Visual C++ 2005 SP1 or 2008 SP1 or 2010 currently.])
-    fi
-    if test -z "$WIN32_CRT_SRC_DIR" -a -n "$WIN32_OLD_STYLE_JEMALLOC"; then
-      if test -z "$VCINSTALLDIR" -o ! -d "$VCINSTALLDIR"; then
-        AC_MSG_ERROR([When building jemalloc, set WIN32_CRT_SRC_DIR to the path to the Visual C++ CRT source (usually VCINSTALLDIR\crt\src, but VCINSTALLDIR is not set, so I can't autodetect it for you).])
-      else
+      if test -z "$WIN32_CRT_SRC_DIR" -a -n "$VCINSTALLDIR"; then
         WIN32_CRT_SRC_DIR="$VCINSTALLDIR\crt\src"
       fi
-    fi
-    dnl cpu check
-    case "${target_cpu}" in
-    i*86)
-      MOZ_CRT_CPU_ARCH=intel
-      ;;
-    x86_64)
-      MOZ_CRT_CPU_ARCH=amd64
-      ;;
-    *)
-      AC_MSG_ERROR([--enable-jemalloc not supported on ${target}])
-      ;;
-    esac
-
-    AC_SUBST(MOZ_CRT_CPU_ARCH)
-
-    if test -n "$WIN32_OLD_STYLE_JEMALLOC"; then
-      if test ! -d "$WIN32_CRT_SRC_DIR"; then
-        AC_MSG_ERROR([Invalid Win32 CRT source directory: ${WIN32_CRT_SRC_DIR}])
+      if test -n "$WIN32_CRT_SRC_DIR" -a -d "$WIN32_CRT_SRC_DIR"; then
+        AC_MSG_RESULT([yes])
+        dnl cpu check
+        case "${target_cpu}" in
+        i*86)
+          MOZ_CRT_CPU_ARCH=intel
+          ;;
+        x86_64)
+          MOZ_CRT_CPU_ARCH=amd64
+          ;;
+        *)
+          AC_MSG_ERROR([--enable-jemalloc not supported on ${target}])
+          ;;
+        esac
+        AC_SUBST(MOZ_CRT_CPU_ARCH)
+        WIN32_OLD_STYLE_JEMALLOC=1
+        AC_DEFINE(WIN32_OLD_STYLE_JEMALLOC)
+        WIN32_CRT_SRC_DIR=`cd "$WIN32_CRT_SRC_DIR" && pwd -W`
+        _objdir_win=`pwd -W`
+        WIN32_CUSTOM_CRT_DIR="$_objdir_win/memory/jemalloc/crtsrc/build/$MOZ_CRT_CPU_ARCH"
+        MOZ_MEMORY_LDFLAGS="-MANIFEST:NO -LIBPATH:\"$WIN32_CUSTOM_CRT_DIR\" -NODEFAULTLIB:msvcrt -NODEFAULTLIB:msvcrtd -NODEFAULTLIB:msvcprt -NODEFAULTLIB:msvcprtd -DEFAULTLIB:mozcrt19 -DEFAULTLIB:mozcpp19"
       fi
-      WIN32_CRT_SRC_DIR=`cd "$WIN32_CRT_SRC_DIR" && pwd -W`
-      _objdir_win=`pwd -W`
-      WIN32_CUSTOM_CRT_DIR="$_objdir_win/memory/jemalloc/crtsrc/build/$MOZ_CRT_CPU_ARCH"
-      MOZ_MEMORY_LDFLAGS="-MANIFEST:NO -LIBPATH:\"$WIN32_CUSTOM_CRT_DIR\" -NODEFAULTLIB:msvcrt -NODEFAULTLIB:msvcrtd -NODEFAULTLIB:msvcprt -NODEFAULTLIB:msvcprtd -DEFAULTLIB:mozcrt19 -DEFAULTLIB:mozcpp19"
-    else
+    fi
+    if test -z "$WIN32_OLD_STYLE_JEMALLOC"; then
+      AC_MSG_RESULT([no])
+      WIN32_NEW_STYLE_JEMALLOC=1
+      AC_DEFINE(WIN32_NEW_STYLE_JEMALLOC)
       if test -z "$MOZ_DEBUG"; then
         WIN32_CRT_LIBS="msvcrt.lib msvcprt.lib"
       else
         WIN32_CRT_LIBS="msvcrtd.lib msvcprtd.lib"
       fi
       dnl Look for a broken crtdll.obj
-      WIN32_CRTDLL_FULLPATH=`lib -list $WIN32_CRT_LIBS | grep crtdll\\.obj`
-      lib -OUT:crtdll.obj $WIN32_CRT_LIBS -EXTRACT:$WIN32_CRTDLL_FULLPATH
-      if grep -q '__imp__\{0,1\}free' crtdll.obj; then
+      WIN32_CRTDLL_FULLPATH=`lib -nologo -list $WIN32_CRT_LIBS | grep crtdll\\.obj`
+      lib -NOLOGO -OUT:crtdll.obj $WIN32_CRT_LIBS -EXTRACT:$WIN32_CRTDLL_FULLPATH
+      if grep -q __imp__\{0,1\}free crtdll.obj; then
         MOZ_MEMORY_LDFLAGS='-MANIFEST:NO -LIBPATH:$(DIST)/lib -NODEFAULTLIB:msvcrt -NODEFAULTLIB:msvcrtd -NODEFAULTLIB:msvcprt -NODEFAULTLIB:msvcprtd -DEFAULTLIB:mozcrt'
       else
         MOZ_MEMORY_LDFLAGS='$(DIST)/../memory/jemalloc/jemalloc.lib'
       fi
       rm crtdll.obj
     fi
+
     dnl Also pass this to NSPR/NSS
     DLLFLAGS="$DLLFLAGS $MOZ_MEMORY_LDFLAGS"
     export DLLFLAGS
     ;;
   *)
     AC_MSG_ERROR([--enable-jemalloc not supported on ${target}])
     ;;
   esac
@@ -7908,17 +7934,21 @@ dnl Omnijar packaging is compatible with
 dnl In unpackaged builds, omnijar looks for files as if
 dnl things were flat packaged. After packaging, all files
 dnl are loaded from a single jar. MOZ_CHROME_FILE_FORMAT
 dnl is set to flat since putting files into jars is only
 dnl done during packaging with omnijar.
 if test "$MOZ_CHROME_FILE_FORMAT" = "omni"; then
     MOZ_OMNIJAR=1
     AC_DEFINE(MOZ_OMNIJAR)
-    MOZ_CHROME_FILE_FORMAT=flat
+    if test "$OS_ARCH" = "WINNT"; then
+        MOZ_CHROME_FILE_FORMAT=flat
+    else
+        MOZ_CHROME_FILE_FORMAT=symlink
+    fi
 elif test "$MOZ_CHROME_FILE_FORMAT" = "jar"; then
     AC_DEFINE(MOZ_CHROME_FILE_FORMAT_JAR)
 fi
 
 AC_SUBST(MOZ_OMNIJAR)
 
 dnl ========================================================
 dnl = Define default location for MOZILLA_FIVE_HOME
@@ -8305,19 +8335,19 @@ fi
 MOZ_ARG_ENABLE_BOOL(shared-js,
 [  --enable-shared-js
                           Create a shared JavaScript library.],
     ENABLE_SHARED_JS=1,
     ENABLE_SHARED_JS=)
 
 if test -n "$ENABLE_SHARED_JS"; then
   JS_SHARED_LIBRARY=1
-  MOZ_JS_LIBS=$MOZ_JS_SHARED_LIBS
+  MOZ_JS_LIBS="$MOZ_JS_SHARED_LIBS"
 else
-  MOZ_JS_LIBS=$MOZ_JS_STATIC_LIBS
+  MOZ_JS_LIBS="$MOZ_JS_STATIC_LIBS"
   AC_DEFINE(MOZ_STATIC_JS)
 fi
 AC_SUBST(JS_SHARED_LIBRARY)
 
 AC_SUBST(LIBXUL_LIBS)
 XPCOM_LIBS="$LIBXUL_LIBS"
 
 dnl ========================================================
@@ -9379,21 +9409,30 @@ EOF
 
 _EGREP_PATTERN='^#define ('
 if test -n "$_NON_GLOBAL_ACDEFINES"; then
     for f in $_NON_GLOBAL_ACDEFINES; do
         _EGREP_PATTERN="${_EGREP_PATTERN}$f|"
     done
 fi
 _EGREP_PATTERN="${_EGREP_PATTERN}dummy_never_defined)"
- 
+
   sort confdefs.h | egrep -v "$_EGREP_PATTERN" >> $_CONFIG_TMP
 
+  if test "$?" != 0; then
+    AC_MSG_ERROR([Error outputting config definitions])
+  fi
+
   cat >> $_CONFIG_TMP <<\EOF
 
+/* The c99 defining the limit macros (UINT32_MAX for example), says:
+ * C++ implementations should define these macros only when __STDC_LIMIT_MACROS
+ * is defined before <stdint.h> is included. */
+#define __STDC_LIMIT_MACROS
+
 #endif /* _MOZILLA_CONFIG_H_ */
 
 EOF
 
   # Only write mozilla-config.h when something changes (or it doesn't exist)
   if cmp -s $_CONFIG_TMP $_CONFIG_DEFS_H; then
     rm $_CONFIG_TMP
   else
@@ -9403,16 +9442,19 @@ EOF
     echo ==== $_CONFIG_DEFS_H =================================
     cat $_CONFIG_DEFS_H
   fi
 
 dnl Probably shouldn't call this manually but we always want the output of DEFS
 rm -f confdefs.h.save
 mv confdefs.h confdefs.h.save
 egrep -v "$_EGREP_PATTERN" confdefs.h.save > confdefs.h
+if test "$?" != 0; then
+  AC_MSG_ERROR([Error outputting confdefs.h])
+fi
 AC_OUTPUT_MAKE_DEFS()
 MOZ_DEFINES=$DEFS
 AC_SUBST(MOZ_DEFINES)
 rm -f confdefs.h
 mv confdefs.h.save confdefs.h
 
 dnl Load the list of Makefiles to generate.
 dnl   To add new Makefiles, edit allmakefiles.sh.
@@ -9507,16 +9549,17 @@ if test -z "$MOZ_NATIVE_NSPR"; then
        ac_configure_args="$ac_configure_args --enable-debug --disable-optimize"
     fi
     if test -n "$HAVE_64BIT_OS"; then
         ac_configure_args="$ac_configure_args --enable-64bit"
     fi
     if test -n "$USE_ARM_KUSER"; then
         ac_configure_args="$ac_configure_args --with-arm-kuser"
     fi
+    ac_configure_args="$ac_configure_args $NSPR_CONFIGURE_FLAGS"
     AC_OUTPUT_SUBDIRS(nsprpub)
     ac_configure_args="$_SUBDIR_CONFIG_ARGS"
 fi
 
 if test -z "$MOZ_NATIVE_NSPR"; then
     # Hack to deal with the fact that we use NSPR_CFLAGS everywhere
     AC_MSG_WARN([Recreating autoconf.mk with updated nspr-config output])
     if test "$OS_ARCH" != "WINNT"; then
new file mode 100644
--- /dev/null
+++ b/content/base/crashtests/667336-1.html
@@ -0,0 +1,4 @@
+<!DOCTYPE html>
+<script>
+document.createElement("div").children.item(-1);
+</script>
--- a/content/base/crashtests/crashtests.list
+++ b/content/base/crashtests/crashtests.list
@@ -87,8 +87,9 @@ load 593302-2.html
 load 610571-1.html
 load 604262-1.html
 load 628599-1.html
 load 637214-1.svg
 load 637214-2.svg
 load 642022-1.html
 load 646184.html
 load 658845-1.svg
+load 667336-1.html
--- a/content/base/public/Makefile.in
+++ b/content/base/public/Makefile.in
@@ -116,14 +116,14 @@ XPIDLSRCS	= \
 		nsIScriptLoaderObserver.idl  \
 		nsIDroppedLinkHandler.idl \
 		nsIImageLoadingContent.idl \
 		nsIObjectLoadingContent.idl \
 		nsIFrameLoader.idl \
 		nsIXMLHttpRequest.idl \
 		nsIContentSecurityPolicy.idl \
 		nsIFrameMessageManager.idl \
-		nsIWebSocket.idl \
+		nsIMozWebSocket.idl \
 		nsIEventSource.idl \
 		$(NULL)
 
 include $(topsrcdir)/config/rules.mk
 
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -1719,16 +1719,23 @@ public:
   static PRBool IsPatternMatching(nsAString& aValue, nsAString& aPattern,
                                   nsIDocument* aDocument);
 
   /**
    * Calling this adds support for
    * ontouch* event handler DOM attributes.
    */
   static void InitializeTouchEventTable();
+
+  static nsresult Btoa(const nsAString& aBinaryData,
+                       nsAString& aAsciiBase64String);
+
+  static nsresult Atob(const nsAString& aAsciiString,
+                       nsAString& aBinaryData);
+  
 private:
   static PRBool InitializeEventTable();
 
   static nsresult EnsureStringBundle(PropertiesFile aFile);
 
   static nsIDOMScriptObjectFactory *GetDOMScriptObjectFactory();
 
   static nsresult HoldScriptObject(PRUint32 aLangID, void* aObject);
--- a/content/base/public/nsIFrameMessageManager.idl
+++ b/content/base/public/nsIFrameMessageManager.idl
@@ -76,17 +76,17 @@ interface nsIFrameMessageManager : nsISu
 interface nsISyncMessageSender : nsIFrameMessageManager
 {
   /**
    * Returns an array of JSON objects.
    */
   void sendSyncMessage(/*in messageName, in JSON*/);
 };
 
-[scriptable, uuid(c56e85b8-6736-4ae2-ae90-66bcef952a82)]
+[scriptable, uuid(6f23339f-2b5c-4f22-a03f-bb7ec101f83d)]
 interface nsIContentFrameMessageManager : nsISyncMessageSender
 {
   /**
    * The current top level window in the frame or null.
    */
   readonly attribute nsIDOMWindow content;
 
   /**
@@ -99,16 +99,22 @@ interface nsIContentFrameMessageManager 
    */
   void dump(in DOMString aStr);
 
   /**
    * If leak detection is enabled, print a note to the leak log that this
    * process will intentionally crash.
    */
   void privateNoteIntentionalCrash();
+
+   /**
+    * Ascii base64 data to binary data and vice versa
+    */
+   DOMString atob(in DOMString aAsciiString);
+   DOMString btoa(in DOMString aBase64Data);
 };
 
 [uuid(9c48d557-92fe-4edb-95fc-bfe97e77bdc3)]
 interface nsIInProcessContentFrameMessageManager : nsIContentFrameMessageManager
 {
   [notxpcom] nsIContent getOwnerContent();
 };
 
new file mode 100644
--- /dev/null
+++ b/content/base/public/nsIMozWebSocket.idl
@@ -0,0 +1,110 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set sw=2 ts=8 et tw=80 : */
+/* ***** 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.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Wellington Fernando de Macedo.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *    Wellington Fernando de Macedo <wfernandom2004@gmail.com> (original author)
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of 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 "nsISupports.idl"
+
+interface nsIDOMEventListener;
+interface nsIPrincipal;
+interface nsIScriptContext;
+interface nsPIDOMWindow;
+
+/**
+ * The nsIMozWebSocket interface enables Web applications to maintain
+ * bidirectional communications with server-side processes as described in:
+ *
+ * http://dev.w3.org/html5/websockets/
+ *
+ */
+[scriptable, uuid(eae76132-e4a4-4765-8494-5e136521c846)]
+interface nsIMozWebSocket : nsISupports
+{
+  readonly attribute DOMString url;
+  readonly attribute DOMString protocol;
+
+  //ready state
+  const unsigned short CONNECTING = 0;
+  const unsigned short OPEN = 1;
+  const unsigned short CLOSING = 2;
+  const unsigned short CLOSED = 3;
+  readonly attribute unsigned short readyState;
+
+  readonly attribute unsigned long bufferedAmount;
+
+  // event handler attributes
+  attribute nsIDOMEventListener onopen;
+  attribute nsIDOMEventListener onmessage;
+  attribute nsIDOMEventListener onerror;
+  attribute nsIDOMEventListener onclose;
+
+  /**
+   * Transmits data using the connection.
+   *
+   * @param data The data to be transmited.
+   * @return if the connection is still established (and the data was queued or
+   *         sent successfully).
+   */
+  boolean send(in DOMString data);
+
+  /**
+   * Closes the Web Socket connection or connection attempt, if any.
+   * If the connection is already closed, it does nothing.
+   */
+  void close();
+
+  /**
+   * Initialize the object for use from C++ code with the principal, script
+   * context, and owner window that should be used.
+   *
+   * @param principal The principal to use for the request. This must not be
+   *                  null.
+   * @param scriptContext The script context to use for the request. May be
+   *                      null.
+   * @param ownerWindow The associated window for the request. May be null.
+   * @param url The url for opening the socket. This must not be empty, and
+   *            must have an absolute url, using either the ws or wss schemes.
+   * @param protocol  Specifies a sub-protocol that the server must support for
+   *                  the connection to be successful. If empty, no protocol is
+   *                  specified.
+   */
+  [noscript] void init(in nsIPrincipal principal,
+                       in nsIScriptContext scriptContext,
+                       in nsPIDOMWindow ownerWindow,
+                       in DOMString url,
+                       in DOMString protocol);
+};
deleted file mode 100644
--- a/content/base/public/nsIWebSocket.idl
+++ /dev/null
@@ -1,110 +0,0 @@
-/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim: set sw=2 ts=8 et tw=80 : */
-/* ***** 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.org code.
- *
- * The Initial Developer of the Original Code is
- * Wellington Fernando de Macedo.
- * Portions created by the Initial Developer are Copyright (C) 2009
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *    Wellington Fernando de Macedo <wfernandom2004@gmail.com> (original author)
- *
- * Alternatively, the contents of this file may be used under the terms of
- * either of 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 "nsISupports.idl"
-
-interface nsIDOMEventListener;
-interface nsIPrincipal;
-interface nsIScriptContext;
-interface nsPIDOMWindow;
-
-/**
- * The nsIWebSocket interface enables Web applications to maintain
- * bidirectional communications with server-side processes as described in:
- *
- * http://dev.w3.org/html5/websockets/
- *
- */
-[scriptable, uuid(431aea4c-568a-470e-b876-c57a29ff0fc6)]
-interface nsIWebSocket : nsISupports
-{
-  readonly attribute DOMString url;
-  readonly attribute DOMString protocol;
-
-  //ready state
-  const unsigned short CONNECTING = 0;
-  const unsigned short OPEN = 1;
-  const unsigned short CLOSING = 2;
-  const unsigned short CLOSED = 3;
-  readonly attribute unsigned short readyState;
-
-  readonly attribute unsigned long bufferedAmount;
-
-  // event handler attributes
-  attribute nsIDOMEventListener onopen;
-  attribute nsIDOMEventListener onmessage;
-  attribute nsIDOMEventListener onerror;
-  attribute nsIDOMEventListener onclose;
-
-  /**
-   * Transmits data using the connection.
-   *
-   * @param data The data to be transmited.
-   * @return if the connection is still established (and the data was queued or
-   *         sent successfully).
-   */
-  boolean send(in DOMString data);
-
-  /**
-   * Closes the Web Socket connection or connection attempt, if any.
-   * If the connection is already closed, it does nothing.
-   */
-  void close();
-
-  /**
-   * Initialize the object for use from C++ code with the principal, script
-   * context, and owner window that should be used.
-   *
-   * @param principal The principal to use for the request. This must not be
-   *                  null.
-   * @param scriptContext The script context to use for the request. May be
-   *                      null.
-   * @param ownerWindow The associated window for the request. May be null.
-   * @param url The url for opening the socket. This must not be empty, and
-   *            must have an absolute url, using either the ws or wss schemes.
-   * @param protocol  Specifies a sub-protocol that the server must support for
-   *                  the connection to be successful. If empty, no protocol is
-   *                  specified.
-   */
-  [noscript] void init(in nsIPrincipal principal,
-                       in nsIScriptContext scriptContext,
-                       in nsPIDOMWindow ownerWindow,
-                       in DOMString url,
-                       in DOMString protocol);
-};
--- a/content/base/public/nsLineBreaker.h
+++ b/content/base/public/nsLineBreaker.h
@@ -224,17 +224,17 @@ private:
   // appropriate sink(s). Then we clear the current word state.
   nsresult FlushCurrentWord();
 
   void UpdateCurrentWordLangGroup(nsIAtom *aLangGroup);
 
   void FindHyphenationPoints(nsHyphenator *aHyphenator,
                              const PRUnichar *aTextStart,
                              const PRUnichar *aTextLimit,
-                             PRPackedBool *aBreakState);
+                             PRUint8 *aBreakState);
 
   nsAutoTArray<PRUnichar,100> mCurrentWord;
   // All the items that contribute to mCurrentWord
   nsAutoTArray<TextItem,2>    mTextItems;
   nsIAtom*                    mCurrentWordLangGroup;
   PRPackedBool                mCurrentWordContainsMixedLang;
   PRPackedBool                mCurrentWordContainsComplexChar;
 
--- a/content/base/src/Makefile.in
+++ b/content/base/src/Makefile.in
@@ -160,16 +160,19 @@ ifneq (,$(INTEL_ARCHITECTURE))
 CPPSRCS += nsTextFragmentSSE2.cpp
 
 # gcc requires -msse2 for this file since it uses SSE2 intrinsics.  (See bug
 # 585538 comment 12.)
 ifdef GNU_CC
 nsTextFragmentSSE2.$(OBJ_SUFFIX): CXXFLAGS+=-msse2
 endif
 
+ifdef SOLARIS_SUNPRO_CXX
+nsTextFragmentSSE2.$(OBJ_SUFFIX): CXXFLAGS+=-xarch=sse2 -xO4
+endif
 endif
 
 GQI_SRCS = contentbase.gqi
 
 # we don't want the shared lib, but we want to force the creation of a
 # static lib.
 FORCE_STATIC_LIB = 1
 
--- a/content/base/src/nsContentList.cpp
+++ b/content/base/src/nsContentList.cpp
@@ -522,17 +522,17 @@ nsContentList::Item(PRUint32 aIndex, PRB
     nsIDocument* doc = mRootNode->GetCurrentDoc();
     if (doc) {
       // Flush pending content changes Bug 4891.
       doc->FlushPendingNotifications(Flush_ContentAndNotify);
     }
   }
 
   if (mState != LIST_UP_TO_DATE)
-    PopulateSelf(aIndex+1);
+    PopulateSelf(NS_MIN(aIndex, PR_UINT32_MAX - 1) + 1);
 
   ASSERT_IN_SYNC;
   NS_ASSERTION(!mRootNode || mState != LIST_DIRTY,
                "PopulateSelf left the list in a dirty (useless) state!");
 
   return mElements.SafeObjectAt(aIndex);
 }
 
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -629,16 +629,71 @@ nsContentUtils::InitializeTouchEventTabl
         delete sStringEventTable;
         sStringEventTable = nsnull;
         return;
       }
     }
   }
 }
 
+static PRBool
+Is8bit(const nsAString& aString)
+{
+  static const PRUnichar EIGHT_BIT = PRUnichar(~0x00FF);
+
+  nsAString::const_iterator done_reading;
+  aString.EndReading(done_reading);
+
+  // for each chunk of |aString|...
+  PRUint32 fragmentLength = 0;
+  nsAString::const_iterator iter;
+  for (aString.BeginReading(iter); iter != done_reading;
+       iter.advance(PRInt32(fragmentLength))) {
+    fragmentLength = PRUint32(iter.size_forward());
+    const PRUnichar* c = iter.get();
+    const PRUnichar* fragmentEnd = c + fragmentLength;
+
+    // for each character in this chunk...
+    while (c < fragmentEnd) {
+      if (*c++ & EIGHT_BIT) {
+        return PR_FALSE;
+      }
+    }
+  }
+
+  return PR_TRUE;
+}
+
+nsresult
+nsContentUtils::Btoa(const nsAString& aBinaryData,
+                     nsAString& aAsciiBase64String)
+{
+  if (!Is8bit(aBinaryData)) {
+    aAsciiBase64String.Truncate();
+    return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
+  }
+
+  return nsXPConnect::Base64Encode(aBinaryData, aAsciiBase64String);
+}
+
+nsresult
+nsContentUtils::Atob(const nsAString& aAsciiBase64String,
+                     nsAString& aBinaryData)
+{
+  if (!Is8bit(aAsciiBase64String)) {
+    aBinaryData.Truncate();
+    return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
+  }
+
+  nsresult rv = nsXPConnect::Base64Decode(aAsciiBase64String, aBinaryData);
+  if (NS_FAILED(rv) && rv == NS_ERROR_INVALID_ARG) {
+    return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
+  }
+  return rv;
+}
 
 /**
  * Access a cached parser service. Don't addref. We need only one
  * reference to it and this class has that one.
  */
 /* static */
 nsIParserService*
 nsContentUtils::GetParserService()
--- a/content/base/src/nsDocument.cpp
+++ b/content/base/src/nsDocument.cpp
@@ -1645,17 +1645,16 @@ nsDocument::~nsDocument()
     // Could be null here if Init() failed
     mCSSLoader->DropDocumentReference();
     NS_RELEASE(mCSSLoader);
   }
 
   // XXX Ideally we'd do this cleanup in the nsIDocument destructor.
   if (mNodeInfoManager) {
     mNodeInfoManager->DropDocumentReference();
-    NS_RELEASE(mNodeInfoManager);
   }
 
   if (mAttrStyleSheet) {
     mAttrStyleSheet->SetOwningDocument(nsnull);
   }
   
   if (mStyleAttrStyleSheet) {
     mStyleAttrStyleSheet->SetOwningDocument(nsnull);
@@ -1831,18 +1830,16 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
     NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "mChildren[i]");
     cb.NoteXPCOMChild(tmp->mChildren.ChildAt(indx - 1));
   }
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_USERDATA
 
   // Traverse all nsIDocument pointer members.
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mCachedRootElement)
-  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mNodeInfoManager,
-                                                  nsNodeInfoManager)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mSecurityInfo)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDisplayDocument)
 
   // Traverse all nsDocument nsCOMPtrs.
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mParser)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mScriptGlobalObject)
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_MEMBER(mListenerManager,
                                                   nsEventListenerManager)
@@ -1951,16 +1948,22 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(ns
 
   tmp->mRadioGroups.Clear();
   
   // nsDocument has a pretty complex destructor, so we're going to
   // assume that *most* cycles you actually want to break somewhere
   // else, and not unlink an awful lot here.
 
   tmp->mIdentifierMap.Clear();
+
+#ifdef MOZ_SMIL
+  if (tmp->mAnimationController) {
+    tmp->mAnimationController->Unlink();
+  }
+#endif // MOZ_SMIL
   
   tmp->mInUnlinkOrDeletion = PR_FALSE;
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
 
 nsresult
 nsDocument::Init()
 {
@@ -1991,21 +1994,20 @@ nsDocument::Init()
   NS_ENSURE_TRUE(mCSSLoader, NS_ERROR_OUT_OF_MEMORY);
   NS_ADDREF(mCSSLoader);
   // Assume we're not quirky, until we know otherwise
   mCSSLoader->SetCompatibilityMode(eCompatibility_FullStandards);
 
   mNodeInfoManager = new nsNodeInfoManager();
   NS_ENSURE_TRUE(mNodeInfoManager, NS_ERROR_OUT_OF_MEMORY);
 
-  NS_ADDREF(mNodeInfoManager);
-
   nsresult  rv = mNodeInfoManager->Init(this);
   NS_ENSURE_SUCCESS(rv, rv);
 
+  // mNodeInfo keeps NodeInfoManager alive!
   mNodeInfo = mNodeInfoManager->GetDocumentNodeInfo();
   NS_ENSURE_TRUE(mNodeInfo, NS_ERROR_OUT_OF_MEMORY);
   NS_ABORT_IF_FALSE(mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_NODE,
                     "Bad NodeType in aNodeInfo");
 
   NS_ASSERTION(GetOwnerDoc() == this, "Our nodeinfo is busted!");
 
   mScriptLoader = new nsScriptLoader(this);
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -318,16 +318,30 @@ nsFrameMessageManager::GetContent(nsIDOM
 
 NS_IMETHODIMP
 nsFrameMessageManager::GetDocShell(nsIDocShell** aDocShell)
 {
   *aDocShell = nsnull;
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsFrameMessageManager::Btoa(const nsAString& aBinaryData,
+                            nsAString& aAsciiBase64String)
+{
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+nsFrameMessageManager::Atob(const nsAString& aAsciiString,
+                            nsAString& aBinaryData)
+{
+  return NS_OK;
+}
+
 nsresult
 nsFrameMessageManager::ReceiveMessage(nsISupports* aTarget,
                                       const nsAString& aMessage,
                                       PRBool aSync, const nsAString& aJSON,
                                       JSObject* aObjectsArray,
                                       InfallibleTArray<nsString>* aJSONRetVal,
                                       JSContext* aContext)
 {
@@ -403,17 +417,17 @@ nsFrameMessageManager::ReceiveMessage(ns
         JS_DefineProperty(ctx, param, "sync",
                           BOOLEAN_TO_JSVAL(aSync), NULL, NULL, JSPROP_ENUMERATE);
         JS_DefineProperty(ctx, param, "json", json, NULL, NULL, JSPROP_ENUMERATE);
         JS_DefineProperty(ctx, param, "objects", objectsv.jsval_value(), NULL, NULL, JSPROP_ENUMERATE);
 
         jsval thisValue = JSVAL_VOID;
 
         jsval funval = JSVAL_VOID;
-        if (JS_ObjectIsFunction(ctx, object)) {
+        if (JS_ObjectIsCallable(ctx, object)) {
           // If the listener is a JS function:
           funval = OBJECT_TO_JSVAL(object);
 
           // A small hack to get 'this' value right on content side where
           // messageManager is wrapped in TabChildGlobal.
           nsCOMPtr<nsISupports> defaultThisValue;
           if (mChrome) {
             defaultThisValue =
@@ -426,17 +440,17 @@ nsFrameMessageManager::ReceiveMessage(ns
                                      defaultThisValue, &thisValue, nsnull, PR_TRUE);
         } else {
           // If the listener is a JS object which has receiveMessage function:
           NS_ENSURE_STATE(JS_GetProperty(ctx, object, "receiveMessage",
                                          &funval) &&
                           JSVAL_IS_OBJECT(funval) &&
                           !JSVAL_IS_NULL(funval));
           JSObject* funobject = JSVAL_TO_OBJECT(funval);
-          NS_ENSURE_STATE(JS_ObjectIsFunction(ctx, funobject));
+          NS_ENSURE_STATE(JS_ObjectIsCallable(ctx, funobject));
           thisValue = OBJECT_TO_JSVAL(object);
         }
 
         jsval rval = JSVAL_VOID;
 
         js::AutoValueRooter argv(ctx);
         argv.set(OBJECT_TO_JSVAL(param));
 
@@ -575,16 +589,44 @@ ContentScriptErrorReporter(JSContext* aC
     return;
   }
 
   nsCOMPtr<nsIConsoleService> consoleService =
       do_GetService(NS_CONSOLESERVICE_CONTRACTID);
   if (consoleService) {
     (void) consoleService->LogMessage(scriptError);
   }
+
+#ifdef DEBUG
+  // Print it to stderr as well, for the benefit of those invoking
+  // mozilla with -console.
+  nsCAutoString error;
+  error.Assign("JavaScript ");
+  if (JSREPORT_IS_STRICT(flags)) {
+    error.Append("strict ");
+  }
+  if (JSREPORT_IS_WARNING(flags)) {
+    error.Append("warning: ");
+  } else {
+    error.Append("error: ");
+  }
+  error.Append(aReport->filename);
+  error.Append(", line ");
+  error.AppendInt(lineNumber, 10);
+  error.Append(": ");
+  if (aReport->ucmessage) {
+    AppendUTF16toUTF8(reinterpret_cast<const PRUnichar*>(aReport->ucmessage),
+                      error);
+  } else {
+    error.Append(aMessage);
+  }
+
+  fprintf(stderr, "%s\n", error.get());
+  fflush(stderr);
+#endif
 }
 
 nsDataHashtable<nsStringHashKey, nsFrameScriptExecutorJSObjectHolder*>*
   nsFrameScriptExecutor::sCachedScripts = nsnull;
 nsRefPtr<nsScriptCacheCleaner> nsFrameScriptExecutor::sScriptCacheCleaner;
 
 void
 nsFrameScriptExecutor::DidCreateCx()
--- a/content/base/src/nsGenericDOMDataNode.cpp
+++ b/content/base/src/nsGenericDOMDataNode.cpp
@@ -80,16 +80,19 @@ nsGenericDOMDataNode::nsGenericDOMDataNo
                     mNodeInfo->NodeType() == nsIDOMNode::DOCUMENT_TYPE_NODE,
                     "Bad NodeType in aNodeInfo");
 }
 
 nsGenericDOMDataNode::~nsGenericDOMDataNode()
 {
   NS_PRECONDITION(!IsInDoc(),
                   "Please remove this from the document properly");
+  if (GetParent()) {
+    NS_RELEASE(mParent);
+  }
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsGenericDOMDataNode)
 
 NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN(nsGenericDOMDataNode)
   NS_IMPL_CYCLE_COLLECTION_TRACE_PRESERVED_WRAPPER
 NS_IMPL_CYCLE_COLLECTION_TRACE_END
 
@@ -108,16 +111,17 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(
 
   nsIDocument* ownerDoc = tmp->GetOwnerDoc();
   if (ownerDoc) {
     ownerDoc->BindingManager()->Traverse(tmp, cb);
   }
 
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_LISTENERMANAGER
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_USERDATA
+  NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(GetParent())
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGenericDOMDataNode)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
   NS_IMPL_CYCLE_COLLECTION_UNLINK_LISTENERMANAGER
   NS_IMPL_CYCLE_COLLECTION_UNLINK_USERDATA
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
@@ -493,16 +497,19 @@ nsGenericDOMDataNode::BindToTree(nsIDocu
     slots->mBindingParent = aBindingParent; // Weak, so no addref happens.
     if (aParent->IsInNativeAnonymousSubtree()) {
       SetFlags(NODE_IS_IN_ANONYMOUS_SUBTREE);
     }
   }
 
   // Set parent
   if (aParent) {
+    if (!GetParent()) {
+      NS_ADDREF(aParent);
+    }
     mParent = aParent;
   }
   else {
     mParent = aDocument;
   }
   SetParentIsContent(aParent);
 
   // XXXbz sXBL/XBL2 issue!
@@ -541,17 +548,21 @@ nsGenericDOMDataNode::UnbindFromTree(PRB
   if (document) {
     // Notify XBL- & nsIAnonymousContentCreator-generated
     // anonymous content that the document is changing.
     // This is needed to update the insertion point.
     document->BindingManager()->RemovedFromDocument(this, document);
   }
 
   if (aNullParent) {
-    mParent = nsnull;
+    if (GetParent()) {
+      NS_RELEASE(mParent);
+    } else {
+      mParent = nsnull;
+    }
     SetParentIsContent(false);
   }
   ClearInDocument();
 
   nsDataSlots *slots = GetExistingDataSlots();
   if (slots) {
     slots->mBindingParent = nsnull;
   }
--- a/content/base/src/nsGenericElement.cpp
+++ b/content/base/src/nsGenericElement.cpp
@@ -2195,16 +2195,19 @@ nsGenericElement::nsGenericElement(alrea
   SetFlags((nsIProgrammingLanguage::JAVASCRIPT << NODE_SCRIPT_TYPE_OFFSET));
   SetIsElement();
 }
 
 nsGenericElement::~nsGenericElement()
 {
   NS_PRECONDITION(!IsInDoc(),
                   "Please remove this from the document properly");
+  if (GetParent()) {
+    NS_RELEASE(mParent);
+  }
 }
 
 NS_IMETHODIMP
 nsGenericElement::GetNodeName(nsAString& aNodeName)
 {
   aNodeName = NodeName();
   return NS_OK;
 }
@@ -2817,16 +2820,19 @@ nsGenericElement::BindToTree(nsIDocument
   if (aParent && aParent->IsInNativeAnonymousSubtree()) {
     SetFlags(NODE_IS_IN_ANONYMOUS_SUBTREE);
   }
 
   PRBool hadForceXBL = HasFlag(NODE_FORCE_XBL_BINDINGS);
 
   // Now set the parent and set the "Force attach xbl" flag if needed.
   if (aParent) {
+    if (!GetParent()) {
+      NS_ADDREF(aParent);
+    }
     mParent = aParent;
 
     if (aParent->HasFlag(NODE_FORCE_XBL_BINDINGS)) {
       SetFlags(NODE_FORCE_XBL_BINDINGS);
     }
   }
   else {
     mParent = aDocument;
@@ -2925,17 +2931,21 @@ nsGenericElement::UnbindFromTree(PRBool 
   NS_PRECONDITION(aDeep || (!GetCurrentDoc() && !GetBindingParent()),
                   "Shallow unbind won't clear document and binding parent on "
                   "kids!");
   // Make sure to unbind this node before doing the kids
   nsIDocument *document =
     HasFlag(NODE_FORCE_XBL_BINDINGS) ? GetOwnerDoc() : GetCurrentDoc();
 
   if (aNullParent) {
-    mParent = nsnull;
+    if (GetParent()) {
+      NS_RELEASE(mParent);
+    } else {
+      mParent = nsnull;
+    }
     SetParentIsContent(false);
   }
   ClearInDocument();
 
   if (document) {
     // Notify XBL- & nsIAnonymousContentCreator-generated
     // anonymous content that the document is changing.
     document->BindingManager()->RemovedFromDocument(this, document);
@@ -3610,17 +3620,17 @@ nsGenericElement::DispatchClickEvent(nsP
   }
   event.pressure = pressure;
   event.clickCount = clickCount;
   event.inputSource = inputSource;
   event.isShift = aSourceEvent->isShift;
   event.isControl = aSourceEvent->isControl;
   event.isAlt = aSourceEvent->isAlt;
   event.isMeta = aSourceEvent->isMeta;
-  event.flags = aFlags;
+  event.flags |= aFlags; // Be careful not to overwrite existing flags!
 
   return DispatchEvent(aPresContext, &event, aTarget, aFullDispatch, aStatus);
 }
 
 nsIFrame*
 nsGenericElement::GetPrimaryFrame(mozFlushType aType)
 {
   nsIDocument* doc = GetCurrentDoc();
@@ -3990,17 +4000,17 @@ nsINode::ReplaceOrInsertBefore(PRBool aR
 
     // Remove the children from the fragment.
     for (PRUint32 i = count; i > 0;) {
       newContent->RemoveChildAt(--i, PR_TRUE);
     }
 
     PRBool appending =
       !IsNodeOfType(eDOCUMENT) && PRUint32(insPos) == GetChildCount();
-    PRBool firstInsPos = insPos;
+    PRInt32 firstInsPos = insPos;
     nsIContent* firstInsertedContent = fragChildren[0];
 
     // Iterate through the fragment's children, and insert them in the new
     // parent
     for (PRUint32 i = 0; i < count; ++i, ++insPos) {
       // XXXbz how come no reparenting here?  That seems odd...
       // Insert the child.
       res = InsertChildAt(fragChildren[i], insPos, !appending);
@@ -4230,17 +4240,19 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_
       NS_CYCLE_COLLECTION_NOTE_EDGE_NAME(cb, "slots mAttributeMap");
       cb.NoteXPCOMChild(slots->mAttributeMap.get());
 
       if (tmp->IsXUL())
         cb.NoteXPCOMChild(slots->mControllers);
       cb.NoteXPCOMChild(
         static_cast<nsIDOMNodeList*>(slots->mChildrenList.get()));
     }
-  }
+    NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(GetParent())
+  }
+  
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 
 NS_INTERFACE_MAP_BEGIN(nsGenericElement)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRIES_CYCLE_COLLECTION(nsGenericElement)
   NS_INTERFACE_MAP_ENTRY(nsIContent)
   NS_INTERFACE_MAP_ENTRY(nsINode)
--- a/content/base/src/nsInProcessTabChildGlobal.cpp
+++ b/content/base/src/nsInProcessTabChildGlobal.cpp
@@ -184,16 +184,31 @@ nsInProcessTabChildGlobal::GetContent(ns
 NS_IMETHODIMP
 nsInProcessTabChildGlobal::GetDocShell(nsIDocShell** aDocShell)
 {
   NS_IF_ADDREF(*aDocShell = mDocShell);
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsInProcessTabChildGlobal::Btoa(const nsAString& aBinaryData,
+                            nsAString& aAsciiBase64String)
+{
+  return nsContentUtils::Btoa(aBinaryData, aAsciiBase64String);
+}
+
+NS_IMETHODIMP
+nsInProcessTabChildGlobal::Atob(const nsAString& aAsciiString,
+                            nsAString& aBinaryData)
+{
+  return nsContentUtils::Atob(aAsciiString, aBinaryData);
+}
+
+
+NS_IMETHODIMP
 nsInProcessTabChildGlobal::PrivateNoteIntentionalCrash()
 {
     return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 void
 nsInProcessTabChildGlobal::Disconnect()
 {
--- a/content/base/src/nsInProcessTabChildGlobal.h
+++ b/content/base/src/nsInProcessTabChildGlobal.h
@@ -73,16 +73,21 @@ public:
   }
   NS_IMETHOD GetContent(nsIDOMWindow** aContent);
   NS_IMETHOD GetDocShell(nsIDocShell** aDocShell);
   NS_IMETHOD Dump(const nsAString& aStr)
   {
     return mMessageManager ? mMessageManager->Dump(aStr) : NS_OK;
   }
   NS_IMETHOD PrivateNoteIntentionalCrash();
+  NS_IMETHOD Btoa(const nsAString& aBinaryData,
+                  nsAString& aAsciiBase64String);
+  NS_IMETHOD Atob(const nsAString& aAsciiString,
+                  nsAString& aBinaryData);
+
   NS_DECL_NSIINPROCESSCONTENTFRAMEMESSAGEMANAGER
 
   virtual nsresult PreHandleEvent(nsEventChainPreVisitor& aVisitor);
   NS_IMETHOD AddEventListener(const nsAString& aType,
                               nsIDOMEventListener* aListener,
                               PRBool aUseCapture)
   {
     // By default add listeners only for trusted events!
--- a/content/base/src/nsLineBreaker.cpp
+++ b/content/base/src/nsLineBreaker.cpp
@@ -307,17 +307,17 @@ nsLineBreaker::AppendText(nsIAtom* aLang
   }
   return NS_OK;
 }
 
 void
 nsLineBreaker::FindHyphenationPoints(nsHyphenator *aHyphenator,
                                      const PRUnichar *aTextStart,
                                      const PRUnichar *aTextLimit,
-                                     PRPackedBool *aBreakState)
+                                     PRUint8 *aBreakState)
 {
   nsDependentSubstring string(aTextStart, aTextLimit);
   nsAutoTArray<PRPackedBool,200> hyphens;
   if (NS_SUCCEEDED(aHyphenator->Hyphenate(string, hyphens))) {
     for (PRUint32 i = 0; i + 1 < string.Length(); ++i) {
       if (hyphens[i]) {
         aBreakState[i + 1] =
           gfxTextRun::CompressedGlyph::FLAG_BREAK_TYPE_HYPHEN;
@@ -409,17 +409,17 @@ nsLineBreaker::AppendText(nsIAtom* aLang
     mBreakHere = PR_FALSE;
     mAfterBreakableSpace = isBreakableSpace;
 
     if (isSpace) {
       if (offset > wordStart && wordHasComplexChar) {
         if (aSink && !(aFlags & BREAK_SUPPRESS_INSIDE)) {
           // Save current start-of-word state because GetJISx4051Breaks will
           // set it to false
-          PRPackedBool currentStart = breakState[wordStart];
+          PRUint8 currentStart = breakState[wordStart];
           nsContentUtils::LineBreaker()->
             GetJISx4051Breaks(aText + wordStart, offset - wordStart,
                               breakState.Elements() + wordStart);
           breakState[wordStart] = currentStart;
         }
         wordHasComplexChar = PR_FALSE;
       }
 
--- a/content/base/src/nsNodeInfo.cpp
+++ b/content/base/src/nsNodeInfo.cpp
@@ -94,21 +94,21 @@ nsNodeInfo::Create(nsIAtom *aName, nsIAt
     new (place) nsNodeInfo(aName, aPrefix, aNamespaceID, aNodeType, aExtraName,
                            aOwnerManager) :
     nsnull;
 }
 
 nsNodeInfo::~nsNodeInfo()
 {
   mOwnerManager->RemoveNodeInfo(this);
-  NS_RELEASE(mOwnerManager);
 
   NS_RELEASE(mInner.mName);
   NS_IF_RELEASE(mInner.mPrefix);
   NS_IF_RELEASE(mInner.mExtraName);
+  NS_RELEASE(mOwnerManager);
 }
 
 
 nsNodeInfo::nsNodeInfo(nsIAtom *aName, nsIAtom *aPrefix, PRInt32 aNamespaceID,
                        PRUint16 aNodeType, nsIAtom* aExtraName,
                        nsNodeInfoManager *aOwnerManager)
 {
   CHECK_VALID_NODEINFO(aNodeType, aName, aNamespaceID, aExtraName);
--- a/content/base/src/nsNodeInfoManager.cpp
+++ b/content/base/src/nsNodeInfoManager.cpp
@@ -107,16 +107,17 @@ nsNodeInfoManager::NodeInfoInnerKeyCompa
     return (node2->mName->Equals(*(node1->mNameString)));
   }
   return (node1->mNameString->Equals(*(node2->mNameString)));
 }
 
 
 nsNodeInfoManager::nsNodeInfoManager()
   : mDocument(nsnull),
+    mNonDocumentNodeInfos(0),
     mPrincipal(nsnull),
     mTextNodeInfo(nsnull),
     mCommentNodeInfo(nsnull),
     mDocumentNodeInfo(nsnull),
     mBindingManager(nsnull)
 {
   nsLayoutStatics::AddRef();
 
@@ -155,16 +156,19 @@ nsNodeInfoManager::~nsNodeInfoManager()
 }
 
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(nsNodeInfoManager)
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(nsNodeInfoManager, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(nsNodeInfoManager, Release)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_NATIVE_0(nsNodeInfoManager)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NATIVE_BEGIN(nsNodeInfoManager)
+  if (tmp->mNonDocumentNodeInfos) {
+    NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mDocument)
+  }
   NS_IMPL_CYCLE_COLLECTION_TRAVERSE_RAWPTR(mBindingManager)
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
 
 nsresult
 nsNodeInfoManager::Init(nsIDocument *aDocument)
 {
   NS_ENSURE_TRUE(mNodeInfoHash, NS_ERROR_OUT_OF_MEMORY);
 
@@ -204,18 +208,20 @@ nsNodeInfoManager::DropNodeInfoDocument(
 
 void
 nsNodeInfoManager::DropDocumentReference()
 {
   if (mBindingManager) {
     mBindingManager->DropDocumentReference();
   }
 
+  // This is probably not needed anymore.
   PL_HashTableEnumerateEntries(mNodeInfoHash, DropNodeInfoDocument, nsnull);
 
+  NS_ASSERTION(!mNonDocumentNodeInfos, "Shouldn't have non-document nodeinfos!");
   mDocument = nsnull;
 }
 
 
 already_AddRefed<nsINodeInfo>
 nsNodeInfoManager::GetNodeInfo(nsIAtom *aName, nsIAtom *aPrefix,
                                PRInt32 aNamespaceID, PRUint16 aNodeType,
                                nsIAtom* aExtraName /* = nsnull */)
@@ -241,16 +247,21 @@ nsNodeInfoManager::GetNodeInfo(nsIAtom *
   NS_ENSURE_TRUE(newNodeInfo, nsnull);
   
   PLHashEntry *he;
   he = PL_HashTableAdd(mNodeInfoHash, &newNodeInfo->mInner, newNodeInfo);
   NS_ENSURE_TRUE(he, nsnull);
 
   // Have to do the swap thing, because already_AddRefed<nsNodeInfo>
   // doesn't cast to already_AddRefed<nsINodeInfo>
+  ++mNonDocumentNodeInfos;
+  if (mNonDocumentNodeInfos == 1) {
+    NS_IF_ADDREF(mDocument);
+  }
+
   nsNodeInfo *nodeInfo = nsnull;
   newNodeInfo.swap(nodeInfo);
 
   return nodeInfo;
 }
 
 
 nsresult
@@ -285,16 +296,21 @@ nsNodeInfoManager::GetNodeInfo(const nsA
       nsNodeInfo::Create(nameAtom, aPrefix, aNamespaceID, aNodeType, nsnull,
                          this);
   NS_ENSURE_TRUE(newNodeInfo, NS_ERROR_OUT_OF_MEMORY);
 
   PLHashEntry *he;
   he = PL_HashTableAdd(mNodeInfoHash, &newNodeInfo->mInner, newNodeInfo);
   NS_ENSURE_TRUE(he, NS_ERROR_FAILURE);
 
+  ++mNonDocumentNodeInfos;
+  if (mNonDocumentNodeInfos == 1) {
+    NS_IF_ADDREF(mDocument);
+  }
+
   newNodeInfo.forget(aNodeInfo);
 
   return NS_OK;
 }
 
 
 nsresult
 nsNodeInfoManager::GetNodeInfo(const nsAString& aName, nsIAtom *aPrefix,
@@ -342,19 +358,24 @@ nsNodeInfoManager::GetCommentNodeInfo()
 
   return mCommentNodeInfo;
 }
 
 already_AddRefed<nsINodeInfo>
 nsNodeInfoManager::GetDocumentNodeInfo()
 {
   if (!mDocumentNodeInfo) {
+    NS_ASSERTION(mDocument, "Should have mDocument!");
     mDocumentNodeInfo = GetNodeInfo(nsGkAtoms::documentNodeName, nsnull,
                                     kNameSpaceID_None,
                                     nsIDOMNode::DOCUMENT_NODE, nsnull).get();
+    --mNonDocumentNodeInfos;
+    if (!mNonDocumentNodeInfos) {
+      mDocument->Release(); // Don't set mDocument to null!
+    }
   }
   else {
     NS_ADDREF(mDocumentNodeInfo);
   }
 
   return mDocumentNodeInfo;
 }
 
@@ -371,25 +392,34 @@ nsNodeInfoManager::SetDocumentPrincipal(
   NS_ADDREF(mPrincipal = aPrincipal);
 }
 
 void
 nsNodeInfoManager::RemoveNodeInfo(nsNodeInfo *aNodeInfo)
 {
   NS_PRECONDITION(aNodeInfo, "Trying to remove null nodeinfo from manager!");
 
-  // Drop weak reference if needed
-  if (aNodeInfo == mTextNodeInfo) {
-    mTextNodeInfo = nsnull;
-  }
-  else if (aNodeInfo == mCommentNodeInfo) {
-    mCommentNodeInfo = nsnull;
-  }
-  else if (aNodeInfo == mDocumentNodeInfo) {
+  if (aNodeInfo == mDocumentNodeInfo) {
     mDocumentNodeInfo = nsnull;
+    mDocument = nsnull;
+  } else {
+    if (--mNonDocumentNodeInfos == 0) {
+      if (mDocument) {
+        // Note, whoever calls this method should keep NodeInfoManager alive,
+        // even if mDocument gets deleted.
+        mDocument->Release();
+      }
+    }
+    // Drop weak reference if needed
+    if (aNodeInfo == mTextNodeInfo) {
+      mTextNodeInfo = nsnull;
+    }
+    else if (aNodeInfo == mCommentNodeInfo) {
+      mCommentNodeInfo = nsnull;
+    }
   }
 
 #ifdef DEBUG
   PRBool ret =
 #endif
   PL_HashTableRemove(mNodeInfoHash, &aNodeInfo->mInner);
 
   NS_POSTCONDITION(ret, "Can't find nsINodeInfo to remove!!!");
--- a/content/base/src/nsNodeInfoManager.h
+++ b/content/base/src/nsNodeInfoManager.h
@@ -153,16 +153,17 @@ protected:
 private:
   static PRIntn NodeInfoInnerKeyCompare(const void *key1, const void *key2);
   static PLHashNumber GetNodeInfoInnerHashValue(const void *key);
   static PRIntn DropNodeInfoDocument(PLHashEntry *he, PRIntn hashIndex,
                                      void *arg);
 
   PLHashTable *mNodeInfoHash;
   nsIDocument *mDocument; // WEAK
+  PRUint32 mNonDocumentNodeInfos;
   nsIPrincipal *mPrincipal; // STRONG, but not nsCOMPtr to avoid include hell
                             // while inlining DocumentPrincipal().  Never null
                             // after Init() succeeds.
   nsCOMPtr<nsIPrincipal> mDefaultPrincipal; // Never null after Init() succeeds
   nsINodeInfo *mTextNodeInfo; // WEAK to avoid circular ownership
   nsINodeInfo *mCommentNodeInfo; // WEAK to avoid circular ownership
   nsINodeInfo *mDocumentNodeInfo; // WEAK to avoid circular ownership
   nsBindingManager* mBindingManager; // STRONG, but not nsCOMPtr to avoid
--- a/content/base/src/nsWebSocket.cpp
+++ b/content/base/src/nsWebSocket.cpp
@@ -369,27 +369,27 @@ nsWebSocketEstablishedConnection::Close(
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
   if (!mOwner)
     return NS_OK;
 
   // Disconnect() can release this object, so we keep a
   // reference until the end of the method
   nsRefPtr<nsWebSocketEstablishedConnection> kungfuDeathGrip = this;
 
-  if (mOwner->mReadyState == nsIWebSocket::CONNECTING) {
-    mOwner->SetReadyState(nsIWebSocket::CLOSING);
-    mOwner->SetReadyState(nsIWebSocket::CLOSED);
+  if (mOwner->mReadyState == nsIMozWebSocket::CONNECTING) {
+    mOwner->SetReadyState(nsIMozWebSocket::CLOSING);
+    mOwner->SetReadyState(nsIMozWebSocket::CLOSED);
     Disconnect();
     return NS_OK;
   }
 
-  mOwner->SetReadyState(nsIWebSocket::CLOSING);
+  mOwner->SetReadyState(nsIMozWebSocket::CLOSING);
 
   if (mStatus == CONN_CLOSED) {
-    mOwner->SetReadyState(nsIWebSocket::CLOSED);
+    mOwner->SetReadyState(nsIMozWebSocket::CLOSED);
     Disconnect();
     return NS_OK;
   }
 
   return mWebSocketChannel->Close();
 }
 
 nsresult
@@ -503,49 +503,49 @@ nsWebSocketEstablishedConnection::OnStar
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
   if (!mOwner)
     return NS_OK;
 
   if (!mOwner->mProtocol.IsEmpty())
     mWebSocketChannel->GetProtocol(mOwner->mProtocol);
 
   mStatus = CONN_CONNECTED_AND_READY;
-  mOwner->SetReadyState(nsIWebSocket::OPEN);
+  mOwner->SetReadyState(nsIMozWebSocket::OPEN);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWebSocketEstablishedConnection::OnStop(nsISupports *aContext,
                                          nsresult aStatusCode)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
   if (!mOwner)
     return NS_OK;
 
   mClosedCleanly = NS_SUCCEEDED(aStatusCode);
 
   if (aStatusCode == NS_BASE_STREAM_CLOSED && 
-      mOwner->mReadyState >= nsIWebSocket::CLOSING) {
+      mOwner->mReadyState >= nsIMozWebSocket::CLOSING) {
     // don't generate an error event just because of an unclean close
     aStatusCode = NS_OK;
   }
 
   if (NS_FAILED(aStatusCode)) {
     ConsoleError();
-    if (mOwner && mOwner->mReadyState != nsIWebSocket::CONNECTING) {
+    if (mOwner && mOwner->mReadyState != nsIMozWebSocket::CONNECTING) {
       nsresult rv =
         mOwner->CreateAndDispatchSimpleEvent(NS_LITERAL_STRING("error"));
       if (NS_FAILED(rv))
         NS_WARNING("Failed to dispatch the error event");
     }
   }
 
   mStatus = CONN_CLOSED;
   if (mOwner) {
-    mOwner->SetReadyState(nsIWebSocket::CLOSED);
+    mOwner->SetReadyState(nsIMozWebSocket::CLOSED);
     Disconnect();
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWebSocketEstablishedConnection::OnAcknowledge(nsISupports *aContext,
                                                 PRUint32 aSize)
@@ -605,17 +605,17 @@ nsWebSocketEstablishedConnection::GetInt
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsWebSocket
 ////////////////////////////////////////////////////////////////////////////////
 
 nsWebSocket::nsWebSocket() : mKeepingAlive(PR_FALSE),
                              mCheckMustKeepAlive(PR_TRUE),
                              mTriggeredCloseEvent(PR_FALSE),
-                             mReadyState(nsIWebSocket::CONNECTING),
+                             mReadyState(nsIMozWebSocket::CONNECTING),
                              mOutgoingBufferedAmount(0),
                              mScriptLine(0),
                              mWindowID(0)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
 }
 
 nsWebSocket::~nsWebSocket()
@@ -654,22 +654,22 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_IN
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnOpenListener)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnMessageListener)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnCloseListener)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mOnErrorListener)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mPrincipal)
   NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mURI)
 NS_IMPL_CYCLE_COLLECTION_UNLINK_END
 
-DOMCI_DATA(WebSocket, nsWebSocket)
+DOMCI_DATA(MozWebSocket, nsWebSocket)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(nsWebSocket)
-  NS_INTERFACE_MAP_ENTRY(nsIWebSocket)
+  NS_INTERFACE_MAP_ENTRY(nsIMozWebSocket)
   NS_INTERFACE_MAP_ENTRY(nsIJSNativeInitializer)
-  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(WebSocket)
+  NS_DOM_INTERFACE_MAP_ENTRY_CLASSINFO(MozWebSocket)
 NS_INTERFACE_MAP_END_INHERITING(nsDOMEventTargetWrapperCache)
 
 NS_IMPL_ADDREF_INHERITED(nsWebSocket, nsDOMEventTargetWrapperCache)
 NS_IMPL_RELEASE_INHERITED(nsWebSocket, nsDOMEventTargetWrapperCache)
 
 //-----------------------------------------------------------------------------
 // nsWebSocket::nsIJSNativeInitializer methods:
 //-----------------------------------------------------------------------------
@@ -920,43 +920,43 @@ nsWebSocket::SetReadyState(PRUint16 aNew
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
   nsresult rv;
 
   if (mReadyState == aNewReadyState) {
     return;
   }
 
-  NS_ABORT_IF_FALSE((aNewReadyState == nsIWebSocket::OPEN)    ||
-                    (aNewReadyState == nsIWebSocket::CLOSING) ||
-                    (aNewReadyState == nsIWebSocket::CLOSED),
+  NS_ABORT_IF_FALSE((aNewReadyState == nsIMozWebSocket::OPEN)    ||
+                    (aNewReadyState == nsIMozWebSocket::CLOSING) ||
+                    (aNewReadyState == nsIMozWebSocket::CLOSED),
                     "unexpected readyState");
 
-  if (aNewReadyState == nsIWebSocket::OPEN) {
-    NS_ABORT_IF_FALSE(mReadyState == nsIWebSocket::CONNECTING,
+  if (aNewReadyState == nsIMozWebSocket::OPEN) {
+    NS_ABORT_IF_FALSE(mReadyState == nsIMozWebSocket::CONNECTING,
                       "unexpected readyState transition");
     mReadyState = aNewReadyState;
 
     rv = CreateAndDispatchSimpleEvent(NS_LITERAL_STRING("open"));
     if (NS_FAILED(rv)) {
       NS_WARNING("Failed to dispatch the open event");
     }
     UpdateMustKeepAlive();
     return;
   }
 
-  if (aNewReadyState == nsIWebSocket::CLOSING) {
-    NS_ABORT_IF_FALSE((mReadyState == nsIWebSocket::CONNECTING) ||
-                      (mReadyState == nsIWebSocket::OPEN),
+  if (aNewReadyState == nsIMozWebSocket::CLOSING) {
+    NS_ABORT_IF_FALSE((mReadyState == nsIMozWebSocket::CONNECTING) ||
+                      (mReadyState == nsIMozWebSocket::OPEN),
                       "unexpected readyState transition");
     mReadyState = aNewReadyState;
     return;
   }
 
-  if (aNewReadyState == nsIWebSocket::CLOSED) {
+  if (aNewReadyState == nsIMozWebSocket::CLOSED) {
     mReadyState = aNewReadyState;
 
     if (mConnection) {
       // The close event must be dispatched asynchronously.
       nsCOMPtr<nsIRunnable> event =
         new nsWSCloseEvent(this, mConnection->ClosedCleanly());
       mOutgoingBufferedAmount += mConnection->GetOutgoingBufferedAmount();
       mConnection = nsnull; // this is no longer necessary
@@ -1091,38 +1091,38 @@ nsWebSocket::UpdateMustKeepAlive()
     return;
   }
 
   PRBool shouldKeepAlive = PR_FALSE;
 
   if (mListenerManager) {
     switch (mReadyState)
     {
-      case nsIWebSocket::CONNECTING:
+      case nsIMozWebSocket::CONNECTING:
       {
         if (mListenerManager->HasListenersFor(NS_LITERAL_STRING("open")) ||
             mListenerManager->HasListenersFor(NS_LITERAL_STRING("message")) ||
             mListenerManager->HasListenersFor(NS_LITERAL_STRING("close"))) {
           shouldKeepAlive = PR_TRUE;
         }
       }
       break;
 
-      case nsIWebSocket::OPEN:
-      case nsIWebSocket::CLOSING:
+      case nsIMozWebSocket::OPEN:
+      case nsIMozWebSocket::CLOSING:
       {
         if (mListenerManager->HasListenersFor(NS_LITERAL_STRING("message")) ||
             mListenerManager->HasListenersFor(NS_LITERAL_STRING("close")) ||
             mConnection->HasOutgoingMessages()) {
           shouldKeepAlive = PR_TRUE;
         }
       }
       break;
 
-      case nsIWebSocket::CLOSED:
+      case nsIMozWebSocket::CLOSED:
       {
         shouldKeepAlive =
           (!mTriggeredCloseEvent &&
            mListenerManager->HasListenersFor(NS_LITERAL_STRING("close")));
       }
     }
   }
 
@@ -1176,17 +1176,17 @@ nsWebSocket::AddEventListener(const nsAS
                                                          optional_argc);
   if (NS_SUCCEEDED(rv)) {
     UpdateMustKeepAlive();
   }
   return rv;
 }
 
 //-----------------------------------------------------------------------------
-// nsWebSocket::nsIWebSocket methods:
+// nsWebSocket::nsIMozWebSocket methods:
 //-----------------------------------------------------------------------------
 
 NS_IMETHODIMP
 nsWebSocket::GetUrl(nsAString& aURL)
 {
   aURL = mOriginalURL;
   return NS_OK;
 }
@@ -1236,17 +1236,17 @@ NS_WEBSOCKET_IMPL_DOMEVENTLISTENER(messa
 NS_WEBSOCKET_IMPL_DOMEVENTLISTENER(close, mOnCloseListener)
 
 NS_IMETHODIMP
 nsWebSocket::Send(const nsAString& aData, PRBool *aRet)
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
   *aRet = PR_FALSE;
 
-  if (mReadyState == nsIWebSocket::CONNECTING) {
+  if (mReadyState == nsIMozWebSocket::CONNECTING) {
     return NS_ERROR_DOM_INVALID_STATE_ERR;
   }
 
   // Check for unpaired surrogates.
   PRUint32 i, length = aData.Length();
   for (i = 0; i < length; ++i) {
     if (NS_IS_LOW_SURROGATE(aData[i])) {
       return NS_ERROR_DOM_SYNTAX_ERR;
@@ -1255,49 +1255,49 @@ nsWebSocket::Send(const nsAString& aData
       if (i + 1 == length || !NS_IS_LOW_SURROGATE(aData[i + 1])) {
         return NS_ERROR_DOM_SYNTAX_ERR;
       }
       ++i;
       continue;
     }
   }
 
-  if (mReadyState == nsIWebSocket::CLOSING ||
-      mReadyState == nsIWebSocket::CLOSED) {
+  if (mReadyState == nsIMozWebSocket::CLOSING ||
+      mReadyState == nsIMozWebSocket::CLOSED) {
     mOutgoingBufferedAmount += NS_ConvertUTF16toUTF8(aData).Length();
     return NS_OK;
   }
 
   nsresult rv = mConnection->PostMessage(PromiseFlatString(aData));
   *aRet = NS_SUCCEEDED(rv);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWebSocket::Close()
 {
   NS_ABORT_IF_FALSE(NS_IsMainThread(), "Not running on main thread");
-  if (mReadyState == nsIWebSocket::CLOSING ||
-      mReadyState == nsIWebSocket::CLOSED) {
+  if (mReadyState == nsIMozWebSocket::CLOSING ||
+      mReadyState == nsIMozWebSocket::CLOSED) {
     return NS_OK;
   }
 
-  if (mReadyState == nsIWebSocket::CONNECTING) {
+  if (mReadyState == nsIMozWebSocket::CONNECTING) {
     // FailConnection() can release the object, so we keep a reference
     // before calling it
     nsRefPtr<nsWebSocket> kungfuDeathGrip = this;
 
     if (mConnection) {
       mConnection->FailConnection();
     }
     return NS_OK;
   }
 
-  // mReadyState == nsIWebSocket::OPEN
+  // mReadyState == nsIMozWebSocket::OPEN
   mConnection->Close();
 
   return NS_OK;
 }
 
 /**
  * This Init method should only be called by C++ consumers.
  */
--- a/content/base/src/nsWebSocket.h
+++ b/content/base/src/nsWebSocket.h
@@ -36,17 +36,17 @@
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsWebSocket_h__
 #define nsWebSocket_h__
 
 #include "nsISupportsUtils.h"
-#include "nsIWebSocket.h"
+#include "nsIMozWebSocket.h"
 #include "nsCOMPtr.h"
 #include "nsString.h"
 #include "nsIJSNativeInitializer.h"
 #include "nsIPrincipal.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsIDOMEventListener.h"
 #include "nsDOMEventTargetWrapperCache.h"
 #include "nsAutoPtr.h"
@@ -61,30 +61,30 @@
 
 #define NS_WEBSOCKET_CONTRACTID "@mozilla.org/websocket;1"
 
 class nsWSNetAddressComparator;
 class nsWebSocketEstablishedConnection;
 class nsWSCloseEvent;
 
 class nsWebSocket: public nsDOMEventTargetWrapperCache,
-                   public nsIWebSocket,
+                   public nsIMozWebSocket,
                    public nsIJSNativeInitializer
 {
 friend class nsWSNetAddressComparator;
 friend class nsWebSocketEstablishedConnection;
 friend class nsWSCloseEvent;
 
 public:
   nsWebSocket();
   virtual ~nsWebSocket();
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(nsWebSocket,
                                            nsDOMEventTargetWrapperCache)
-  NS_DECL_NSIWEBSOCKET
+  NS_DECL_NSIMOZWEBSOCKET
 
   // nsIJSNativeInitializer
   NS_IMETHOD Initialize(nsISupports* aOwner, JSContext* aContext,
                         JSObject* aObject, PRUint32 aArgc, jsval* aArgv);
 
   // nsIDOMEventTarget
   NS_IMETHOD AddEventListener(const nsAString& aType,
                               nsIDOMEventListener *aListener,
--- a/content/base/src/nsXMLHttpRequest.cpp
+++ b/content/base/src/nsXMLHttpRequest.cpp
@@ -2487,19 +2487,17 @@ nsXMLHttpRequest::SetRequestHeader(const
     rv = mCORSPreflightChannel->IsPending(&pending);
     NS_ENSURE_SUCCESS(rv, rv);
     
     if (pending) {
       return NS_ERROR_IN_PROGRESS;
     }
   }
 
-  PRUint16 state;
-  rv = GetReadyState(&state);
-  if (NS_FAILED(rv) || state != OPENED)
+  if (!(mState & XML_HTTP_REQUEST_OPENED))
     return NS_ERROR_IN_PROGRESS;
 
   if (!mChannel)             // open() initializes mChannel, and open()
     return NS_ERROR_FAILURE; // must be called before first setRequestHeader()
 
   nsCOMPtr<nsIHttpChannel> httpChannel(do_QueryInterface(mChannel));
   if (!httpChannel) {
     return NS_OK;
--- a/content/base/test/test_websocket.html
+++ b/content/base/test/test_websocket.html
@@ -38,20 +38,22 @@
  * 16. client calls close() and tries to send a message;
  * 17. see bug 572975 - all event listeners set
  * 18. client tries to connect to an http resource;
  * 19. server closes the tcp connection before establishing the ws connection;
  * 20. see bug 572975 - only on error and onclose event listeners set
  * 21. see bug 572975 - same as test 17, but delete strong event listeners when
  *     receiving the message event;
  * 22. server takes too long to establish the ws connection;
+ * 23. see bug 664692 - feature detection should detect MozWebSocket but not
+ *     WebSocket on window object;
  */
 
 var first_test = 1;
-var last_test = 22;
+var last_test = 23;
 
 var current_test = first_test;
 
 var timeoutToAbortTest = 60000;
 var all_ws = [];
 
 function shouldNotOpen(e)
 {
@@ -92,19 +94,19 @@ function shouldCloseNotCleanly(e)
 }
 
 function CreateTestWS(ws_location, ws_protocol)
 {
   var ws;
 
   try {
     if (ws_protocol == undefined) {
-      ws = new WebSocket(ws_location);
+      ws = new MozWebSocket(ws_location);
     } else {
-      ws = new WebSocket(ws_location, ws_protocol);
+      ws = new MozWebSocket(ws_location, ws_protocol);
     }
 
 
     ws._testNumber = current_test;
     ws._receivedCloseEvent = false;
     ok(true, "added testNumber: " + ws._testNumber +"\n");
 
     ws.onerror = function(e)
@@ -468,17 +470,17 @@ function test16()
   {
   }
 }
 
 var status_test17 = "not started";
 
 window._test17 = function()
 {
-  var local_ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-17");
+  var local_ws = new MozWebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-17");
   local_ws._testNumber = "local17";
   local_ws._testNumber = current_test++;
 
   status_test17 = "started";
 
   local_ws.onopen = function(e)
   {
     status_test17 = "opened";
@@ -541,17 +543,17 @@ function test19()
   {
     shouldCloseNotCleanly(e);
     doTest(20);
   };
 }
 
 window._test20 = function()
 {
-  var local_ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-20");
+  var local_ws = new MozWebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-20");
   local_ws._testNumber = "local20";
   local_ws._testNumber = current_test++;
 
   local_ws.onerror = function()
   {
     ok(false, "onerror called on test " + e.target._testNumber + "!");
   };
 
@@ -570,17 +572,17 @@ function test20()
 {
   window._test20();
 }
 
 var timeoutTest21;
 
 window._test21 = function()
 {
-  var local_ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-21");
+  var local_ws = new MozWebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket", "test-21");
   local_ws._testNumber = current_test++;
 
   local_ws.onopen = function(e)
   {
     e.target.send("client data");
     timeoutTest21 = setTimeout(function()
     {
       ok(false, "Didn't received message on test-21!");
@@ -626,16 +628,23 @@ function test22()
   ws.onopen = shouldNotOpen;
   ws.onclose = function(e)
   {
     shouldCloseNotCleanly(e);
     doTest(23);
   };
 }
 
+function test23()
+{
+  is(false, "WebSocket" in window, "WebSocket shouldn't be available on window object");
+  is(true, "MozWebSocket" in window, "MozWebSocket should be available on window object");
+  doTest(24);
+}
+
 function finishWSTest()
 {
   for (i = 0; i < all_ws.length; ++i) {
     if (all_ws[i] != shouldNotReceiveCloseEvent &&
         !all_ws[i]._receivedCloseEvent) {
       ok(false, "didn't called close on test " + all_ws[i]._testNumber + "!");
     }
   }
--- a/content/base/test/test_websocket_basic.html
+++ b/content/base/test/test_websocket_basic.html
@@ -27,17 +27,17 @@ function forcegc(){
 }
 
 function finishWSTest() {
     SimpleTest.finish();
 }
 
 function testWebSocket () {
   var url = "ws://mochi.test:8888/tests/content/base/test/file_websocket_basic";
-  ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket_basic", "test");
+  ws = new MozWebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket_basic", "test");
   is(ws.url, url, "Wrong Websocket.url!");
   ws.onopen = function(e) {
     for (var i = 0; i < params.length; ++i) {
       document.getElementById('log').textContent += "sending " + params[i] + "\n";
       ws.send(params[i]);
     }
   }
   ws.onclose = function(e) {
@@ -52,17 +52,17 @@ function testWebSocket () {
   ws.onmessage = function(e) {
     document.getElementById('log').textContent += "\n" + e.data;
     is(e.data, results[0], "Unexpected message");
     results.shift();
   }
 }
 
 function testWebSocket2() {
-  ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket_basic", "test");
+  ws = new MozWebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket_basic", "test");
   var testCount = 1000; // Send lots of messages
   var messageCount = 0;
   var testMessage = "test message";
   ws.onopen = function(e) {
     for (var i = 0; i < testCount; ++i) {
       ws.send(testMessage + (i + 1));
     }
     ws.send("end");
@@ -82,17 +82,17 @@ function testWebSocket2() {
     document.getElementById('log').textContent = messageCount;
     if (messageCount == testCount) {
       this.onmessage = null;
     }
   }
 }
 
 function testWebSocket3() {
-  ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket_basic", "test");
+  ws = new MozWebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket_basic", "test");
   var testCount = 100; // Send lots of messages
   var messageCount = 0;
   var testMessage = "test message";
   ws.onopen = function(e) {
     for (var i = 0; i < testCount; ++i) {
       forcegc(); // Do something evil, call cycle collector a lot.
       ws.send(testMessage + (i + 1));
     }
@@ -114,17 +114,17 @@ function testWebSocket3() {
     document.getElementById('log').textContent = messageCount;
     if (messageCount == testCount) {
       this.onmessage = null;
     }
   }
 }
 
 function testWebSocket4() {
-  ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket_basic", "test");
+  ws = new MozWebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket_basic", "test");
   // String length = (10,000 - 1) * 23 = 229,977 = almost 225 KiB.
   var longString = new Array(10000).join("-huge websocket message");
   ws.onopen = function(e) {
     is(this, ws, "'this' should point to the WebSocket. (1)");
     ws.send(longString);
   }
   ws.onclose = function(e) {
     is(this, ws, "'this' should point to the WebSocket. (2)");
@@ -141,17 +141,17 @@ function testWebSocket4() {
     is(e.data.length, longString.length, "Length of received message");
     ok(e.data == longString, "Content of received message");
     document.getElementById('log').textContent += "\nReceived the huge message";
     this.close();
   }
 }
 
 function testWebSocket5() {
-  ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket_basic", "test");
+  ws = new MozWebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket_basic", "test");
   ws.onopen = function(e) {
     this.close();
   }
   ws.onclose = function(e) {
     ok(e.wasClean, "Connection closed cleanly");
     is(this.bufferedAmount, 0, "Shouldn't have anything buffered");
     var msg = "some data";
     this.send(msg);
--- a/content/base/test/test_websocket_hello.html
+++ b/content/base/test/test_websocket_hello.html
@@ -14,17 +14,17 @@
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 <script class="testbody" type="text/javascript">
 
 var ws;
 
 function testWebSocket () {
-  ws = new WebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket_hello");
+  ws = new MozWebSocket("ws://mochi.test:8888/tests/content/base/test/file_websocket_hello");
   ws.onopen = function(e) {
     ws.send("data");
   }
   ws.onclose = function(e) {
   }
   ws.onerror = function(e) {
     ok(false, "onerror called!");
     SimpleTest.finish();
--- a/content/base/test/unit/test_bug553888.js
+++ b/content/base/test/unit/test_bug553888.js
@@ -53,30 +53,42 @@ function redirectHandler(metadata, respo
 
 function headerCheckHandler(metadata, response) {
   try {
     let headerValue = metadata.getHeader("X-Custom-Header");
     do_check_eq(headerValue, "present");
   } catch(e) {
     do_throw("No header present after redirect");
   }
+  try {
+    metadata.getHeader("X-Unwanted-Header");
+    do_throw("Unwanted header present after redirect");
+  } catch (x) {
+  }
   response.setStatusLine(metadata.httpVersion, 200, "OK");
   response.setHeader("Content-Type", "text/plain");
   response.write("");
 }
 
 function run_test() {
   var server = new nsHttpServer();
   server.registerPathHandler(redirectPath, redirectHandler);
   server.registerPathHandler(headerCheckPath, headerCheckHandler);
   server.start(SERVER_PORT);
 
   do_test_pending();
   var request = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
                 .createInstance(Components.interfaces.nsIXMLHttpRequest);
-  request.open("GET", redirectURL, false);
+  request.open("GET", redirectURL, true);
   request.setRequestHeader("X-Custom-Header", "present");
-  request.send(null);
-
-  do_check_eq(request.status, 200);
-
-  server.stop(do_test_finished);
+  request.onreadystatechange = function() {
+    if (request.readyState == 4) {
+      do_check_eq(request.status, 200);
+      server.stop(do_test_finished);
+    }
+  };
+  request.send();
+  try {
+    request.setRequestHeader("X-Unwanted-Header", "present");
+    do_throw("Shouldn't be able to set a header after send");
+  } catch (x) {
+  }    
 }
--- a/content/canvas/src/WebGLContext.cpp
+++ b/content/canvas/src/WebGLContext.cpp
@@ -92,17 +92,17 @@ NS_MEMORY_REPORTER_IMPLEMENT(WebGLTextur
 NS_MEMORY_REPORTER_IMPLEMENT(WebGLBufferMemoryUsed,
                              "webgl-buffer-memory",
                              KIND_OTHER,
                              UNITS_BYTES,
                              WebGLMemoryReporter::GetBufferMemoryUsed,
                              "Memory used by WebGL buffers. The OpenGL implementation is free to store these buffers in either video memory or main memory. This measurement is only a lower bound, actual memory usage may be higher for example if the storage is strided.")
 
 NS_MEMORY_REPORTER_IMPLEMENT(WebGLBufferCacheMemoryUsed,
-                             "webgl-buffer-cache-memory",
+                             "explicit/webgl/buffer-cache-memory",
                              KIND_HEAP,
                              UNITS_BYTES,
                              WebGLMemoryReporter::GetBufferCacheMemoryUsed,
                              "Memory used by WebGL buffer caches. The WebGL implementation caches the contents of element array buffers only. This adds up with the webgl-buffer-memory value, but contrary to it, this one represents bytes on the heap, not managed by OpenGL.")
 
 NS_MEMORY_REPORTER_IMPLEMENT(WebGLBufferCount,
                              "webgl-buffer-count",
                              KIND_OTHER,
@@ -120,24 +120,24 @@ NS_MEMORY_REPORTER_IMPLEMENT(WebGLRender
 NS_MEMORY_REPORTER_IMPLEMENT(WebGLRenderbufferCount,
                              "webgl-renderbuffer-count",
                              KIND_OTHER,
                              UNITS_COUNT,
                              WebGLMemoryReporter::GetRenderbufferCount,
                              "Number of WebGL renderbuffers.")
 
 NS_MEMORY_REPORTER_IMPLEMENT(WebGLShaderSourcesSize,
-                             "webgl-shader-sources-size",
+                             "explicit/webgl/shader-sources-size",
                              KIND_HEAP,
                              UNITS_BYTES,
                              WebGLMemoryReporter::GetShaderSourcesSize,
                              "Combined size of WebGL shader ASCII sources, cached on the heap. This should always be at most a few kilobytes, or dozen kilobytes for very shader-intensive WebGL demos.")
 
 NS_MEMORY_REPORTER_IMPLEMENT(WebGLShaderTranslationLogsSize,
-                             "webgl-shader-translationlogs-size",
+                             "explicit/webgl/shader-translationlogs-size",
                              KIND_HEAP,
                              UNITS_BYTES,
                              WebGLMemoryReporter::GetShaderTranslationLogsSize,
                              "Combined size of WebGL shader ASCII translation logs, cached on the heap.")
 
 NS_MEMORY_REPORTER_IMPLEMENT(WebGLShaderCount,
                              "webgl-shader-count",
                              KIND_OTHER,
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -4543,16 +4543,20 @@ WebGLContext::TexSubImage2D_base(WebGLen
 
     if (!tex)
         return ErrorInvalidOperation("texSubImage2D: no texture is bound to this target");
 
     size_t face = WebGLTexture::FaceForTarget(target);
     const WebGLTexture::ImageInfo &imageInfo = tex->ImageInfoAt(level, face);
     if (!CanvasUtils::CheckSaneSubrectSize(xoffset, yoffset, width, height, imageInfo.mWidth, imageInfo.mHeight))
         return ErrorInvalidValue("texSubImage2D: subtexture rectangle out of bounds");
+    
+    // Require the format and type in texSubImage2D to match that of the existing texture as created by texImage2D
+    if (imageInfo.mFormat != format || imageInfo.mType != type)
+        return ErrorInvalidOperation("texSubImage2D: format or type doesn't match the existing texture");
 
     MakeContextCurrent();
 
     int dstFormat = GetWebGLTexelFormat(format, type);
     int actualSrcFormat = srcFormat == WebGLTexelFormat::Auto ? dstFormat : srcFormat;
     size_t srcStride = srcStrideOrZero ? srcStrideOrZero : checked_alignedRowSize.value();
 
     size_t dstPlainRowSize = texelSize * width;
--- a/content/canvas/src/WebGLContextValidate.cpp
+++ b/content/canvas/src/WebGLContextValidate.cpp
@@ -594,17 +594,17 @@ WebGLContext::InitAndValidateGL()
             // gl_PointCoord is always available in ES2 GLSL and in newer desktop GLSL versions, but apparently
             // not in OpenGL 2 and apparently not (due to a driver bug) on certain NVIDIA setups. See:
             //   http://www.opengl.org/discussion_boards/ubbthreads.php?ubb=showflat&Number=261472
             gl->fEnable(LOCAL_GL_POINT_SPRITE);
         }
     }
 
     // Check the shader validator pref
-    NS_ENSURE_TRUE(Preferences::GetRootBranch(), NS_ERROR_FAILURE);
+    NS_ENSURE_TRUE(Preferences::GetRootBranch(), PR_FALSE);
 
     mShaderValidation =
         Preferences::GetBool("webgl.shader_validator", mShaderValidation);
 
 #if defined(USE_ANGLE)
     // initialize shader translator
     if (mShaderValidation) {
         if (!ShInitialize()) {
--- a/content/canvas/src/WebGLTexelConversions.h
+++ b/content/canvas/src/WebGLTexelConversions.h
@@ -28,22 +28,26 @@
 // the pixel conversions code here is originally from this file:
 //   http://trac.webkit.org/browser/trunk/WebCore/platform/graphics/GraphicsContext3D.cpp
 
 // Keep as much as possible unchanged to ease sharing code with the WebKit guys.
 // Changes:
 //  * added BGR8 path, we need it in Mozilla to load textures from DOMElements
 //  * enclosing in a namespace WebGLTexelConversions to make it clear it is, in profilers and in symbol table dumps
 //  * added __restrict keywords. Although non-standard, this is very well supported across all compilers
-//    that I know of (GCC/LLVM/MSC/ICC/Sun/XLC...)
+//    that I know of (GCC/LLVM/MSC/ICC/XLC...)
 //  * optimized scaleFactor computation in Unmultiply functions (1 div instead of 2)
 
 #ifndef WEBGLTEXELCONVERSIONS_H_
 #define WEBGLTEXELCONVERSIONS_H_
 
+#ifdef __SUNPRO_CC
+#define __restrict
+#endif
+
 #include "WebGLContext.h"
 
 namespace mozilla {
 
 typedef PRUint8  uint8_t;
 typedef PRUint16 uint16_t;
 
 namespace { // this is only included by WebGLContextGL.cpp anyway
--- a/content/canvas/test/webgl/failing_tests_linux.txt
+++ b/content/canvas/test/webgl/failing_tests_linux.txt
@@ -4,15 +4,12 @@ conformance/gl-uniform-bool.html
 conformance/glsl-2types-of-textures-on-same-unit.html
 conformance/glsl-conformance.html
 conformance/invalid-passed-params.html
 conformance/more/conformance/quickCheckAPI.html
 conformance/more/functions/copyTexImage2D.html
 conformance/more/functions/copyTexSubImage2D.html
 conformance/more/functions/deleteBufferBadArgs.html
 conformance/more/functions/texImage2DBadArgs.html
-conformance/more/functions/texSubImage2DBadArgs.html
-conformance/more/functions/texSubImage2DHTMLBadArgs.html
 conformance/more/functions/uniformfArrayLen1.html
 conformance/object-deletion-behaviour.html
 conformance/read-pixels-test.html
-conformance/tex-sub-image-2d-bad-args.html
 conformance/uninitialized-test.html
--- a/content/canvas/test/webgl/failing_tests_mac.txt
+++ b/content/canvas/test/webgl/failing_tests_mac.txt
@@ -1,17 +1,14 @@
 conformance/gl-getshadersource.html
 conformance/gl-object-get-calls.html
 conformance/texture-npot.html
 conformance/glsl-conformance.html
 conformance/invalid-passed-params.html
 conformance/object-deletion-behaviour.html
 conformance/read-pixels-test.html
 conformance/tex-input-validation.html
-conformance/tex-sub-image-2d-bad-args.html
 conformance/more/functions/copyTexImage2D.html
 conformance/more/functions/copyTexSubImage2D.html
 conformance/more/functions/deleteBufferBadArgs.html
 conformance/more/functions/texImage2DBadArgs.html
-conformance/more/functions/texSubImage2DBadArgs.html
-conformance/more/functions/texSubImage2DHTMLBadArgs.html
 conformance/more/functions/uniformfBadArgs.html
 conformance/more/functions/uniformiBadArgs.html
\ No newline at end of file
--- a/content/canvas/test/webgl/failing_tests_windows.txt
+++ b/content/canvas/test/webgl/failing_tests_windows.txt
@@ -1,14 +1,11 @@
 conformance/gl-getshadersource.html
 conformance/glsl-conformance.html
 conformance/invalid-passed-params.html
 conformance/object-deletion-behaviour.html
 conformance/read-pixels-test.html
-conformance/tex-sub-image-2d-bad-args.html
 conformance/more/conformance/quickCheckAPI.html
 conformance/more/functions/copyTexImage2D.html
 conformance/more/functions/copyTexSubImage2D.html
 conformance/more/functions/deleteBufferBadArgs.html
 conformance/more/functions/texImage2DBadArgs.html
-conformance/more/functions/texSubImage2DBadArgs.html
-conformance/more/functions/texSubImage2DHTMLBadArgs.html
 conformance/more/functions/uniformfArrayLen1.html
--- a/content/canvas/test/webgl/test_webgl_conformance_test_suite.html
+++ b/content/canvas/test/webgl/test_webgl_conformance_test_suite.html
@@ -358,24 +358,16 @@ function start() {
     failingTestsFilename = 'failing_tests_linux.txt';
   else if (kIsMac)
     failingTestsFilename = 'failing_tests_mac.txt';
 
   var testsExpectedToFail = loadTextFileSynchronous(failingTestsFilename)
                             .replace(/\r/g, '') // convert to unix line breaks
                             .split('\n');
 
-  if (kIsWindows && !kIsWindowsVistaOrHigher) {
-    testsExpectedToFail.push('conformance/framebuffer-object-attachment.html'); // NVIDIA 190.42 doesnt support DEPTH_STENCIL
-    testsExpectedToFail.push('conformance/gl-get-active-attribute.html'); // bug in NVIDIA 190.42, fixed in newer drivers
-    testsExpectedToFail.push('conformance/gl-uniform-bool.html'); // bug in NVIDIA 190.42, fixed in newer drivers
-    testsExpectedToFail.push('conformance/tex-image-and-sub-image-2d-with-array-buffer-view.html'); // ???
-    testsExpectedToFail.push('conformance/uninitialized-test.html'); // bug in NVIDIA 190.42, fixed in newer drivers
-  }
-
   var testsToIgnore = [];
 
   var testsSuccessful = [];
 
   runTestSuite();
 }
 
 </script>
--- a/content/events/src/nsIMEStateManager.cpp
+++ b/content/events/src/nsIMEStateManager.cpp
@@ -323,17 +323,20 @@ nsIMEStateManager::SetIMEState(PRUint32 
           if ((form = do_QueryInterface(formElement)) && form->GetDefaultSubmitElement()) {
             willSubmit = PR_TRUE;
           // is this an html form and does it only have a single text input element?
           } else if (formElement && formElement->Tag() == nsGkAtoms::form && formElement->IsHTML() &&
                      static_cast<nsHTMLFormElement*>(formElement)->HasSingleTextControl()) {
             willSubmit = PR_TRUE;
           }
         }
-        context.mActionHint.Assign(willSubmit ? NS_LITERAL_STRING("go") : NS_LITERAL_STRING("next"));
+        context.mActionHint.Assign(willSubmit ? control->GetType() == NS_FORM_INPUT_SEARCH
+                                                  ? NS_LITERAL_STRING("search")
+                                                  : NS_LITERAL_STRING("go")
+                                              : NS_LITERAL_STRING("next"));
       }
     }
 
     if (XRE_GetProcessType() == GeckoProcessType_Content) {
       context.mReason = aReason | IMEContext::FOCUS_FROM_CONTENT_PROCESS;
     } else {
       context.mReason = aReason;
     }
--- a/content/media/VideoUtils.h
+++ b/content/media/VideoUtils.h
@@ -37,16 +37,17 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef VideoUtils_h
 #define VideoUtils_h
 
 #include "mozilla/ReentrantMonitor.h"
 
 #include "nsRect.h"
+#include "nsIThreadManager.h"
 
 // This file contains stuff we'd rather put elsewhere, but which is
 // dependent on other changes which we don't want to wait for. We plan to
 // remove this file in the near future.
 
 
 // This belongs in prtypes.h
 /************************************************************************
@@ -152,9 +153,17 @@ PRBool UsecsToSamples(PRInt64 aUsecs, PR
 #define MAX_VIDEO_WIDTH  4000
 #define MAX_VIDEO_HEIGHT 3000
 
 // Scales the display rect aDisplay by aspect ratio aAspectRatio.
 // Note that aDisplay must be validated by nsVideoInfo::ValidateVideoRegion()
 // before being used!
 void ScaleDisplayByAspectRatio(nsIntSize& aDisplay, float aAspectRatio);
 
+// The amount of virtual memory reserved for thread stacks.
+#if defined(XP_WIN) || defined(XP_MACOSX) || defined(LINUX)
+#define MEDIA_THREAD_STACK_SIZE (128 * 1024)
+#else
+// All other platforms use their system defaults.
+#define MEDIA_THREAD_STACK_SIZE nsIThreadManager::DEFAULT_STACK_SIZE
 #endif
+
+#endif
--- a/content/media/nsAudioStream.cpp
+++ b/content/media/nsAudioStream.cpp
@@ -355,17 +355,19 @@ void nsAudioStream::ShutdownLibrary()
   delete gVolumeScaleLock;
   gVolumeScaleLock = nsnull;
 }
 
 nsIThread *
 nsAudioStream::GetThread()
 {
   if (!mAudioPlaybackThread) {
-    NS_NewThread(getter_AddRefs(mAudioPlaybackThread));
+    NS_NewThread(getter_AddRefs(mAudioPlaybackThread),
+                 nsnull,
+                 MEDIA_THREAD_STACK_SIZE);
   }
   return mAudioPlaybackThread;
 }
 
 nsAudioStream* nsAudioStream::AllocateStream()
 {
 #if defined(REMOTE_AUDIO)
   if (XRE_GetProcessType() == GeckoProcessType_Content) {
--- a/content/media/nsBuiltinDecoderStateMachine.cpp
+++ b/content/media/nsBuiltinDecoderStateMachine.cpp
@@ -221,17 +221,19 @@ nsBuiltinDecoderStateMachine::nsBuiltinD
   mRunAgain(PR_FALSE),
   mDispatchedRunEvent(PR_FALSE),
   mDecodeThreadWaiting(PR_FALSE)
 {
   MOZ_COUNT_CTOR(nsBuiltinDecoderStateMachine);
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
   if (gStateMachineCount == 0) {
     NS_ASSERTION(!gStateMachineThread, "Should have null state machine thread!");
-    nsresult res = NS_NewThread(&gStateMachineThread);
+    nsresult res = NS_NewThread(&gStateMachineThread,
+                                nsnull,
+                                MEDIA_THREAD_STACK_SIZE);
     NS_ABORT_IF_FALSE(NS_SUCCEEDED(res), "Can't create media state machine thread");
   }
   gStateMachineCount++;
 }
 
 nsBuiltinDecoderStateMachine::~nsBuiltinDecoderStateMachine()
 {
   NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
@@ -1047,17 +1049,19 @@ nsBuiltinDecoderStateMachine::StartDecod
 {
   NS_ASSERTION(OnStateMachineThread(), "Should be on state machine thread.");
   mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
   mStopDecodeThread = PR_FALSE;
   if ((mDecodeThread && !mDecodeThreadIdle) || mState >= DECODER_STATE_COMPLETED)
     return NS_OK;
 
   if (!mDecodeThread) {
-    nsresult rv = NS_NewThread(getter_AddRefs(mDecodeThread));
+    nsresult rv = NS_NewThread(getter_AddRefs(mDecodeThread),
+                               nsnull,
+                               MEDIA_THREAD_STACK_SIZE);
     if (NS_FAILED(rv)) {
       mState = DECODER_STATE_SHUTDOWN;
       return rv;
     }
   }
   nsCOMPtr<nsIRunnable> event =
     NS_NewRunnableMethod(this, &nsBuiltinDecoderStateMachine::DecodeThreadRun);
   mDecodeThread->Dispatch(event, NS_DISPATCH_NORMAL);
@@ -1068,17 +1072,19 @@ nsBuiltinDecoderStateMachine::StartDecod
 nsresult
 nsBuiltinDecoderStateMachine::StartAudioThread()
 {
   NS_ASSERTION(OnStateMachineThread() || OnDecodeThread(),
                "Should be on state machine or decode thread.");
   mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
   mStopAudioThread = PR_FALSE;
   if (HasAudio() && !mAudioThread) {
-    nsresult rv = NS_NewThread(getter_AddRefs(mAudioThread));
+    nsresult rv = NS_NewThread(getter_AddRefs(mAudioThread),
+                               nsnull,
+                               MEDIA_THREAD_STACK_SIZE);
     if (NS_FAILED(rv)) {
       mState = DECODER_STATE_SHUTDOWN;
       return rv;
     }
     nsCOMPtr<nsIRunnable> event =
       NS_NewRunnableMethod(this, &nsBuiltinDecoderStateMachine::AudioLoop);
     mAudioThread->Dispatch(event, NS_DISPATCH_NORMAL);
   }
new file mode 100644
--- /dev/null
+++ b/content/smil/crashtests/669225-1.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+
+<svg xmlns="http://www.w3.org/2000/svg">
+
+<script type="text/javascript">
+<![CDATA[
+
+function boom()
+{
+  document.documentElement.appendChild(document.getElementById("a"));
+}
+
+window.addEventListener("load", boom, false);
+
+]]>
+</script>
+
+<animate end="a.begin" id="a"/>
+<animate end="a.begin" id="a"/>
+
+</svg>
new file mode 100644
--- /dev/null
+++ b/content/smil/crashtests/669225-2.svg
@@ -0,0 +1,21 @@
+<?xml version="1.0"?>
+
+<svg xmlns="http://www.w3.org/2000/svg">
+
+<script type="text/javascript">
+<![CDATA[
+
+function boom()
+{
+  var a = document.getElementById("a");
+  a.removeAttribute("end");
+  a.setAttribute("end", "a.begin");
+}
+
+window.addEventListener("load", boom, false);
+
+]]>
+</script>
+
+<animate end="0" id="a" onend="boom()"/>
+</svg>
new file mode 100644
--- /dev/null
+++ b/content/smil/crashtests/670313-1.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0"?>
+<svg xmlns="http://www.w3.org/2000/svg"
+     class="reftest-wait">
+<script type="text/javascript">
+<![CDATA[
+
+function boom()
+{
+  try {
+    document.getElementById("x").beginElementAt(36028797018963970);
+  } catch (e) { }
+  document.documentElement.removeAttribute("class");
+}
+
+window.addEventListener("load", boom, false);
+
+]]>
+</script>
+<animate id="x" begin="a" />
+</svg>
--- a/content/smil/crashtests/crashtests.list
+++ b/content/smil/crashtests/crashtests.list
@@ -30,8 +30,11 @@ load 596796-1.svg
 load 605345-1.svg
 load 606101-1.svg
 load 608549-1.svg
 load 608295-1.html
 load 611927-1.svg
 load 615002-1.svg
 load 615872-1.svg
 load 665334-1.svg
+load 669225-1.svg
+load 670313-1.svg
+load 669225-2.svg
--- a/content/smil/nsSMILTimedElement.cpp
+++ b/content/smil/nsSMILTimedElement.cpp
@@ -49,16 +49,17 @@
 #include "nsMathUtils.h"
 #include "nsThreadUtils.h"
 #include "nsIPresShell.h"
 #include "prdtoa.h"
 #include "plstr.h"
 #include "prtime.h"
 #include "nsString.h"
 #include "mozilla/AutoRestore.h"
+#include "mozilla/Util.h"
 
 using namespace mozilla;
 
 //----------------------------------------------------------------------
 // Helper class: InstanceTimeComparator
 
 // Upon inserting an instance time into one of our instance time lists we assign
 // it a serial number. This allows us to sort the instance times in such a way
@@ -138,17 +139,17 @@ namespace
 // Helper class: AutoIntervalUpdateBatcher
 
 // RAII helper to set the mDeferIntervalUpdates flag on an nsSMILTimedElement
 // and perform the UpdateCurrentInterval when the object is destroyed.
 //
 // If several of these objects are allocated on the stack, the update will not
 // be performed until the last object for a given nsSMILTimedElement is
 // destroyed.
-NS_STACK_CLASS class nsSMILTimedElement::AutoIntervalUpdateBatcher
+class NS_STACK_CLASS nsSMILTimedElement::AutoIntervalUpdateBatcher
 {
 public:
   AutoIntervalUpdateBatcher(nsSMILTimedElement& aTimedElement)
     : mTimedElement(aTimedElement),
       mDidSetFlag(!aTimedElement.mDeferIntervalUpdates)
   {
     mTimedElement.mDeferIntervalUpdates = PR_TRUE;
   }
@@ -180,16 +181,28 @@ template <class TestFunctor>
 void
 nsSMILTimedElement::RemoveInstanceTimes(InstanceTimeList& aArray,
                                         TestFunctor& aTest)
 {
   InstanceTimeList newArray;
   for (PRUint32 i = 0; i < aArray.Length(); ++i) {
     nsSMILInstanceTime* item = aArray[i].get();
     if (aTest(item, i)) {
+      // As per bugs 665334 and 669225 we should be careful not to remove the
+      // instance time that corresponds to the previous interval's end time.
+      //
+      // Most functors supplied here fulfil this condition by checking if the
+      // instance time is marked as "ShouldPreserve" and if so, not deleting it.
+      //
+      // However, when filtering instance times, we sometimes need to drop even
+      // instance times marked as "ShouldPreserve". In that case we take special
+      // care not to delete the end instance time of the previous interval.
+      NS_ABORT_IF_FALSE(!GetPreviousInterval() ||
+        item != GetPreviousInterval()->End(),
+        "Removing end instance time of previous interval");
       item->Unlink();
     } else {
       newArray.AppendElement(item);
     }
   }
   aArray.Clear();
   aArray.SwapElements(newArray);
 }
@@ -257,23 +270,17 @@ nsSMILTimedElement::~nsSMILTimedElement(
   for (PRUint32 i = 0; i < mEndInstances.Length(); ++i) {
     mEndInstances[i]->Unlink();
   }
   mEndInstances.Clear();
 
   // Notify anyone listening to our intervals that they're gone
   // (We shouldn't get any callbacks from this because all our instance times
   // are now disassociated with any intervals)
-  mElementState = STATE_POSTACTIVE;
-  ResetCurrentInterval();
-
-  for (PRInt32 i = mOldIntervals.Length() - 1; i >= 0; --i) {
-    mOldIntervals[i]->Unlink();
-  }
-  mOldIntervals.Clear();
+  ClearIntervals();
 
   // The following assertions are important in their own right (for checking
   // correct behavior) but also because AutoIntervalUpdateBatcher holds pointers
   // to class so if they fail there's the possibility we might have dangling
   // pointers.
   NS_ABORT_IF_FALSE(!mDeferIntervalUpdates,
       "Interval updates should no longer be blocked when an nsSMILTimedElement "
       "disappears");
@@ -315,32 +322,28 @@ nsSMILTimedElement::GetTimeContainer()
 nsresult
 nsSMILTimedElement::BeginElementAt(double aOffsetSeconds)
 {
   nsSMILTimeContainer* container = GetTimeContainer();
   if (!container)
     return NS_ERROR_FAILURE;
 
   nsSMILTime currentTime = container->GetCurrentTime();
-  AddInstanceTimeFromCurrentTime(currentTime, aOffsetSeconds, PR_TRUE);
-
-  return NS_OK;
+  return AddInstanceTimeFromCurrentTime(currentTime, aOffsetSeconds, PR_TRUE);
 }
 
 nsresult
 nsSMILTimedElement::EndElementAt(double aOffsetSeconds)
 {
   nsSMILTimeContainer* container = GetTimeContainer();
   if (!container)
     return NS_ERROR_FAILURE;
 
   nsSMILTime currentTime = container->GetCurrentTime();
-  AddInstanceTimeFromCurrentTime(currentTime, aOffsetSeconds, PR_FALSE);
-
-  return NS_OK;
+  return AddInstanceTimeFromCurrentTime(currentTime, aOffsetSeconds, PR_FALSE);
 }
 
 //----------------------------------------------------------------------
 // nsSVGAnimationElement methods
 
 nsSMILTimeValue
 nsSMILTimedElement::GetStartTime() const
 {
@@ -417,29 +420,34 @@ nsSMILTimedElement::UpdateInstanceTime(n
 }
 
 void
 nsSMILTimedElement::RemoveInstanceTime(nsSMILInstanceTime* aInstanceTime,
                                        PRBool aIsBegin)
 {
   NS_ABORT_IF_FALSE(aInstanceTime, "Attempting to remove null instance time");
 
+  // If the instance time should be kept (because it is or was the fixed end
+  // point of an interval) then just disassociate it from the creator.
+  if (aInstanceTime->ShouldPreserve()) {
+    aInstanceTime->Unlink();
+    return;
+  }
+
   InstanceTimeList& instanceList = aIsBegin ? mBeginInstances : mEndInstances;
-#ifdef DEBUG
-  PRBool found =
-#endif
+  mozilla::DebugOnly<PRBool> found =
     instanceList.RemoveElementSorted(aInstanceTime, InstanceTimeComparator());
   NS_ABORT_IF_FALSE(found, "Couldn't find instance time to delete");
 
   UpdateCurrentInterval();
 }
 
 namespace
 {
-  class RemoveByCreator
+  class NS_STACK_CLASS RemoveByCreator
   {
   public:
     RemoveByCreator(const nsSMILTimeValueSpec* aCreator) : mCreator(aCreator)
     { }
 
     PRBool operator()(nsSMILInstanceTime* aInstanceTime, PRUint32 /*aIndex*/)
     {
       if (aInstanceTime->GetCreator() != mCreator)
@@ -716,17 +724,17 @@ namespace
   RemoveNonDynamic(nsSMILInstanceTime* aInstanceTime)
   {
     // Generally dynamically-generated instance times (DOM calls, event-based
     // times) are not associated with their creator nsSMILTimeValueSpec since
     // they may outlive them.
     NS_ABORT_IF_FALSE(!aInstanceTime->IsDynamic() ||
          !aInstanceTime->GetCreator(),
         "Dynamic instance time should be unlinked from its creator");
-    return !aInstanceTime->IsDynamic();
+    return !aInstanceTime->IsDynamic() && !aInstanceTime->ShouldPreserve();
   }
 }
 
 void
 nsSMILTimedElement::Rewind()
 {
   NS_ABORT_IF_FALSE(mAnimationElement,
       "Got rewind request before being attached to an animation element");
@@ -745,17 +753,20 @@ nsSMILTimedElement::Rewind()
     mSeekState = mElementState == STATE_ACTIVE ?
                  SEEK_BACKWARD_FROM_ACTIVE :
                  SEEK_BACKWARD_FROM_INACTIVE;
   }
   NS_ABORT_IF_FALSE(mSeekState == SEEK_BACKWARD_FROM_INACTIVE ||
                     mSeekState == SEEK_BACKWARD_FROM_ACTIVE,
                     "Rewind in the middle of a forwards seek?");
 
-  ClearIntervalProgress();
+  ClearIntervals();
+  // ClearIntervals puts us in to the POSTACTIVE state but we're doing a full
+  // rewind so go back to the startup state
+  mElementState = STATE_STARTUP;
 
   UnsetBeginSpec(RemoveNonDynamic);
   UnsetEndSpec(RemoveNonDynamic);
 
   if (mClient) {
     mClient->Inactivate(PR_FALSE);
   }
 
@@ -775,17 +786,17 @@ nsSMILTimedElement::Rewind()
   RegisterMilestone();
 }
 
 namespace
 {
   PRBool
   RemoveNonDOM(nsSMILInstanceTime* aInstanceTime)
   {
-    return !aInstanceTime->FromDOM();
+    return !aInstanceTime->FromDOM() && !aInstanceTime->ShouldPreserve();
   }
 }
 
 PRBool
 nsSMILTimedElement::SetAttr(nsIAtom* aAttribute, const nsAString& aValue,
                             nsAttrValue& aResult,
                             Element* aContextNode,
                             nsresult* aParseResult)
@@ -1221,30 +1232,36 @@ nsSMILTimedElement::Traverse(nsCycleColl
   }
 }
 
 void
 nsSMILTimedElement::Unlink()
 {
   AutoIntervalUpdateBatcher updateBatcher(*this);
 
+  // Remove dependencies on other elements
   PRUint32 count = mBeginSpecs.Length();
   for (PRUint32 i = 0; i < count; ++i) {
     nsSMILTimeValueSpec* beginSpec = mBeginSpecs[i];
     NS_ABORT_IF_FALSE(beginSpec,
         "null nsSMILTimeValueSpec in list of begin specs");
     beginSpec->Unlink();
   }
 
   count = mEndSpecs.Length();
   for (PRUint32 j = 0; j < count; ++j) {
     nsSMILTimeValueSpec* endSpec = mEndSpecs[j];
     NS_ABORT_IF_FALSE(endSpec, "null nsSMILTimeValueSpec in list of end specs");
     endSpec->Unlink();
   }
+
+  ClearIntervals();
+
+  // Make sure we don't notify other elements of new intervals
+  mTimeDependents.Clear();
 }
 
 //----------------------------------------------------------------------
 // Implementation helpers
 
 nsresult
 nsSMILTimedElement::SetBeginOrEndSpec(const nsAString& aSpec,
                                       Element* aContextNode,
@@ -1282,17 +1299,17 @@ nsSMILTimedElement::SetBeginOrEndSpec(co
 }
 
 namespace
 {
   // Adaptor functor for RemoveInstanceTimes that allows us to use function
   // pointers instead.
   // Without this we'd have to either templatize ClearSpecs and all its callers
   // or pass bool flags around to specify which removal function to use here.
-  class RemoveByFunction
+  class NS_STACK_CLASS RemoveByFunction
   {
   public:
     RemoveByFunction(nsSMILTimedElement::RemovalTestFunction aFunction)
       : mFunction(aFunction) { }
     PRBool operator()(nsSMILInstanceTime* aInstanceTime, PRUint32 /*aIndex*/)
     {
       return mFunction(aInstanceTime);
     }
@@ -1308,19 +1325,19 @@ nsSMILTimedElement::ClearSpecs(TimeValue
                                RemovalTestFunction aRemove)
 {
   aSpecs.Clear();
   RemoveByFunction removeByFunction(aRemove);
   RemoveInstanceTimes(aInstances, removeByFunction);
 }
 
 void
-nsSMILTimedElement::ClearIntervalProgress()
+nsSMILTimedElement::ClearIntervals()
 {
-  mElementState = STATE_STARTUP;
+  mElementState = STATE_POSTACTIVE;
   mCurrentRepeatIteration = 0;
   ResetCurrentInterval();
 
   // Remove old intervals
   for (PRInt32 i = mOldIntervals.Length() - 1; i >= 0; --i) {
     mOldIntervals[i]->Unlink();
   }
   mOldIntervals.Clear();
@@ -1352,17 +1369,17 @@ nsSMILTimedElement::ApplyEarlyEnd(const 
       updated = PR_TRUE;
     }
   }
   return updated;
 }
 
 namespace
 {
-  class RemoveReset
+  class NS_STACK_CLASS RemoveReset
   {
   public:
     RemoveReset(const nsSMILInstanceTime* aCurrentIntervalBegin)
       : mCurrentIntervalBegin(aCurrentIntervalBegin) { }
     PRBool operator()(nsSMILInstanceTime* aInstanceTime, PRUint32 /*aIndex*/)
     {
       // SMIL 3.0 section 5.4.3, 'Resetting element state':
       //   Any instance times associated with past Event-values, Repeat-values,
@@ -1500,17 +1517,17 @@ nsSMILTimedElement::FilterIntervals()
     }
   }
   mOldIntervals.Clear();
   mOldIntervals.SwapElements(filteredList);
 }
 
 namespace
 {
-  class RemoveFiltered
+  class NS_STACK_CLASS RemoveFiltered
   {
   public:
     RemoveFiltered(nsSMILTimeValue aCutoff) : mCutoff(aCutoff) { }
     PRBool operator()(nsSMILInstanceTime* aInstanceTime, PRUint32 /*aIndex*/)
     {
       // We can filter instance times that:
       // a) Precede the end point of the previous interval; AND
       // b) Are NOT syncbase times that might be updated to a time after the end
@@ -1520,31 +1537,31 @@ namespace
              aInstanceTime->IsFixedTime() &&
              !aInstanceTime->ShouldPreserve();
     }
 
   private:
     nsSMILTimeValue mCutoff;
   };
 
-  class RemoveBelowThreshold
+  class NS_STACK_CLASS RemoveBelowThreshold
   {
   public:
     RemoveBelowThreshold(PRUint32 aThreshold,
-                         const nsSMILInstanceTime* aCurrentIntervalBegin)
+                         nsTArray<const nsSMILInstanceTime *>& aTimesToKeep)
       : mThreshold(aThreshold),
-        mCurrentIntervalBegin(aCurrentIntervalBegin) { }
+        mTimesToKeep(aTimesToKeep) { }
     PRBool operator()(nsSMILInstanceTime* aInstanceTime, PRUint32 aIndex)
     {
-      return aInstanceTime != mCurrentIntervalBegin && aIndex < mThreshold;
+      return aIndex < mThreshold && !mTimesToKeep.Contains(aInstanceTime);
     }
 
   private:
     PRUint32 mThreshold;
-    const nsSMILInstanceTime* mCurrentIntervalBegin;
+    nsTArray<const nsSMILInstanceTime *>& mTimesToKeep;
   };
 }
 
 void
 nsSMILTimedElement::FilterInstanceTimes(InstanceTimeList& aList)
 {
   if (GetPreviousInterval()) {
     RemoveFiltered removeFiltered(GetPreviousInterval()->End()->Time());
@@ -1554,20 +1571,28 @@ nsSMILTimedElement::FilterInstanceTimes(
   // As with intervals it is possible to create a document that, even despite
   // our most aggressive filtering, will generate instance times indefinitely
   // (e.g. cyclic dependencies with TimeEvents---we can't filter such times as
   // they're unpredictable due to the possibility of seeking the document which
   // may prevent some events from being generated). Therefore we introduce
   // a hard cutoff at which point we just drop the oldest instance times.
   if (aList.Length() > sMaxNumInstanceTimes) {
     PRUint32 threshold = aList.Length() - sMaxNumInstanceTimes;
-    // We should still preserve the current interval begin time however
-    const nsSMILInstanceTime* currentIntervalBegin = mCurrentInterval ?
-      mCurrentInterval->Begin() : nsnull;
-    RemoveBelowThreshold removeBelowThreshold(threshold, currentIntervalBegin);
+    // There are a few instance times we should keep though, notably:
+    // - the current interval begin time,
+    // - the previous interval end time (see note in RemoveInstanceTimes)
+    nsTArray<const nsSMILInstanceTime *> timesToKeep;
+    if (mCurrentInterval) {
+      timesToKeep.AppendElement(mCurrentInterval->Begin());
+    }
+    const nsSMILInterval* prevInterval = GetPreviousInterval();
+    if (prevInterval) {
+      timesToKeep.AppendElement(prevInterval->End());
+    }
+    RemoveBelowThreshold removeBelowThreshold(threshold, timesToKeep);
     RemoveInstanceTimes(aList, removeBelowThreshold);
   }
 }
 
 //
 // This method is based on the pseudocode given in the SMILANIM spec.
 //
 // See:
@@ -2019,29 +2044,34 @@ nsSMILTimedElement::SampleFillValue()
 
   if (simpleTime == 0L && repeatIteration) {
     mClient->SampleLastValue(--repeatIteration);
   } else {
     mClient->SampleAt(simpleTime, mSimpleDur, repeatIteration);
   }
 }
 
-void
+nsresult
 nsSMILTimedElement::AddInstanceTimeFromCurrentTime(nsSMILTime aCurrentTime,
     double aOffsetSeconds, PRBool aIsBegin)
 {
   double offset = aOffsetSeconds * PR_MSEC_PER_SEC;
-  nsSMILTime timeWithOffset = aCurrentTime + PRInt64(NS_round(offset));
 
-  nsSMILTimeValue timeVal(timeWithOffset);
+  // Check we won't overflow the range of nsSMILTime
+  if (aCurrentTime + NS_round(offset) > LL_MAXINT)
+    return NS_ERROR_ILLEGAL_VALUE;
+
+  nsSMILTimeValue timeVal(aCurrentTime + PRInt64(NS_round(offset)));
 
   nsRefPtr<nsSMILInstanceTime> instanceTime =
     new nsSMILInstanceTime(timeVal, nsSMILInstanceTime::SOURCE_DOM);
 
   AddInstanceTime(instanceTime, aIsBegin);
+
+  return NS_OK;
 }
 
 void
 nsSMILTimedElement::RegisterMilestone()
 {
   nsSMILTimeContainer* container = GetTimeContainer();
   if (!container)
     return;
--- a/content/smil/nsSMILTimedElement.h
+++ b/content/smil/nsSMILTimedElement.h
@@ -404,17 +404,17 @@ protected:
 
   nsresult          SetBeginOrEndSpec(const nsAString& aSpec,
                                       Element* aContextNode,
                                       PRBool aIsBegin,
                                       RemovalTestFunction aRemove);
   void              ClearSpecs(TimeValueSpecList& aSpecs,
                                InstanceTimeList& aInstances,
                                RemovalTestFunction aRemove);
-  void              ClearIntervalProgress();
+  void              ClearIntervals();
   void              DoSampleAt(nsSMILTime aContainerTime, PRBool aEndOnly);
 
   /**
    * Helper function to check for an early end and, if necessary, update the
    * current interval accordingly.
    *
    * See SMIL 3.0, section 5.4.5, Element life cycle, "Active Time - Playing an
    * interval" for a description of ending early.
@@ -500,17 +500,17 @@ protected:
   nsSMILTimeValue   ApplyMinAndMax(const nsSMILTimeValue& aDuration) const;
   nsSMILTime        ActiveTimeToSimpleTime(nsSMILTime aActiveTime,
                                            PRUint32& aRepeatIteration);
   nsSMILInstanceTime* CheckForEarlyEnd(
                         const nsSMILTimeValue& aContainerTime) const;
   void              UpdateCurrentInterval(PRBool aForceChangeNotice = PR_FALSE);
   void              SampleSimpleTime(nsSMILTime aActiveTime);
   void              SampleFillValue();
-  void              AddInstanceTimeFromCurrentTime(nsSMILTime aCurrentTime,
+  nsresult          AddInstanceTimeFromCurrentTime(nsSMILTime aCurrentTime,
                         double aOffsetSeconds, PRBool aIsBegin);
   void              RegisterMilestone();
   PRBool            GetNextMilestone(nsSMILMilestone& aNextMilestone) const;
 
   // Notification methods. Note that these notifications can result in nested
   // calls to this same object. Therefore,
   // (i)  we should not perform notification until this object is in
   //      a consistent state to receive callbacks, and
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -242,17 +242,17 @@ static PRInt32 gNumberOfDocumentsLoading
 static PRInt32 gDocShellCount = 0;
 
 // Global reference to the URI fixup service.
 nsIURIFixup *nsDocShell::sURIFixup = 0;
 
 // True means we validate window targets to prevent frameset
 // spoofing. Initialize this to a non-bolean value so we know to check
 // the pref on the creation of the first docshell.
-static PRBool gValidateOrigin = (PRBool)0xffffffff;
+static PRUint32 gValidateOrigin = 0xffffffff;
 
 // Hint for native dispatch of events on how long to delay after 
 // all documents have loaded in milliseconds before favoring normal
 // native event dispatch priorites over performance
 #define NS_EVENT_STARVATION_DELAY_HINT 2000
 
 // This is needed for displaying an error message 
 // when navigation is attempted on a document when printing
@@ -4499,17 +4499,17 @@ nsDocShell::Create()
                  "Unexpected item type in docshell");
 
     NS_ENSURE_TRUE(Preferences::GetRootBranch(), NS_ERROR_FAILURE);
     mCreated = PR_TRUE;
 
     mAllowSubframes =
         Preferences::GetBool("browser.frames.enabled", mAllowSubframes);
 
-    if (gValidateOrigin == (PRBool)0xffffffff) {
+    if (gValidateOrigin == 0xffffffff) {
         // Check pref to see if we should prevent frameset spoofing
         gValidateOrigin =
             Preferences::GetBool("browser.frame.validate_origin", PR_TRUE);
     }
 
     // Should we use XUL error pages instead of alerts if possible?
     mUseErrorPages =
         Preferences::GetBool("browser.xul.error_pages.enabled", mUseErrorPages);
--- a/dom/Makefile.in
+++ b/dom/Makefile.in
@@ -57,17 +57,16 @@ DIRS = \
   interfaces/xbl \
   interfaces/xpath \
   interfaces/load-save \
   interfaces/xul \
   interfaces/storage \
   interfaces/json \
   interfaces/offline \
   interfaces/geolocation \
-  interfaces/threads \
   interfaces/notification \
   interfaces/svg \
   $(NULL)
 
 ifdef MOZ_SMIL
 DIRS += interfaces/smil
 endif
 
@@ -76,16 +75,17 @@ DIRS += \
   base \
   src \
   locales \
   plugins/base \
   plugins/ipc \
   indexedDB \
   system \
   ipc \
+  workers \
   $(NULL)
 
 ifdef ENABLE_TESTS
 DIRS += tests
 
 # These subdirs rely on GTK libraries and header files, it is not
 #  buildable on other non-GTK unix builds
 
--- a/dom/base/nsDOMClassInfo.cpp
+++ b/dom/base/nsDOMClassInfo.cpp
@@ -454,17 +454,17 @@
 
 // Geolocation
 #include "nsIDOMGeoGeolocation.h"
 #include "nsIDOMGeoPosition.h"
 #include "nsIDOMGeoPositionCoords.h"
 #include "nsIDOMGeoPositionError.h"
 
 // Workers
-#include "nsDOMWorker.h"
+#include "mozilla/dom/workers/Workers.h"
 
 #include "nsDOMFile.h"
 #include "nsDOMFileReader.h"
 #include "nsIDOMFileException.h"
 #include "nsIDOMFileError.h"
 #include "nsIDOMFormData.h"
 
 #include "nsIDOMDOMStringMap.h"
@@ -593,19 +593,16 @@ static const char kDOMStringBundleURL[] 
 DOMCI_DATA(Crypto, void)
 DOMCI_DATA(CRMFObject, void)
 DOMCI_DATA(SmartCardEvent, void)
 DOMCI_DATA(ContentFrameMessageManager, void)
 
 DOMCI_DATA(DOMPrototype, void)
 DOMCI_DATA(DOMConstructor, void)
 
-DOMCI_DATA(Worker, void)
-DOMCI_DATA(ChromeWorker, void)
-
 #define NS_DEFINE_CLASSINFO_DATA_WITH_NAME(_class, _name, _helper,            \
                                            _flags)                            \
   { #_name,                                                                   \
     nsnull,                                                                   \
     { _helper::doCreate },                                                    \
     nsnull,                                                                   \
     nsnull,                                                                   \
     nsnull,                                                                   \
@@ -1423,21 +1420,16 @@ static nsDOMClassInfoData sClassInfoData
   NS_DEFINE_CLASSINFO_DATA(SimpleGestureEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(MozTouchEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA_WITH_NAME(MathMLElement, Element, nsElementSH,
                                      ELEMENT_SCRIPTABLE_FLAGS)
 
-  NS_DEFINE_CLASSINFO_DATA(Worker, nsDOMGenericSH,
-                           DOM_DEFAULT_SCRIPTABLE_FLAGS)
-  NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(ChromeWorker, nsDOMGenericSH,
-                                       DOM_DEFAULT_SCRIPTABLE_FLAGS)
-
   NS_DEFINE_CLASSINFO_DATA(WebGLRenderingContext, nsWebGLViewportHandlerSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(WebGLBuffer, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(WebGLTexture, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(WebGLProgram, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
@@ -1477,17 +1469,17 @@ static nsDOMClassInfoData sClassInfoData
   NS_DEFINE_CLASSINFO_DATA(FormData, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(DesktopNotification, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(DesktopNotificationCenter, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
-  NS_DEFINE_CLASSINFO_DATA(WebSocket, nsEventTargetSH,
+  NS_DEFINE_CLASSINFO_DATA(MozWebSocket, nsEventTargetSH,
                            EVENTTARGET_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(CloseEvent, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
 
   NS_DEFINE_CLASSINFO_DATA(IDBFactory, nsDOMGenericSH,
                            DOM_DEFAULT_SCRIPTABLE_FLAGS)
   NS_DEFINE_CLASSINFO_DATA(IDBRequest, nsDOMGenericSH,
@@ -1546,17 +1538,17 @@ struct nsContractIDMapData
 
 static const nsContractIDMapData kConstructorMap[] =
 {
   NS_DEFINE_CONSTRUCTOR_DATA(DOMParser, NS_DOMPARSER_CONTRACTID)
   NS_DEFINE_CONSTRUCTOR_DATA(FileReader, NS_FILEREADER_CONTRACTID)
   NS_DEFINE_CONSTRUCTOR_DATA(FormData, NS_FORMDATA_CONTRACTID)
   NS_DEFINE_CONSTRUCTOR_DATA(XMLSerializer, NS_XMLSERIALIZER_CONTRACTID)
   NS_DEFINE_CONSTRUCTOR_DATA(XMLHttpRequest, NS_XMLHTTPREQUEST_CONTRACTID)
-  NS_DEFINE_CONSTRUCTOR_DATA(WebSocket, NS_WEBSOCKET_CONTRACTID)
+  NS_DEFINE_CONSTRUCTOR_DATA(MozWebSocket, NS_WEBSOCKET_CONTRACTID)
   NS_DEFINE_CONSTRUCTOR_DATA(XPathEvaluator, NS_XPATH_EVALUATOR_CONTRACTID)
   NS_DEFINE_CONSTRUCTOR_DATA(XSLTProcessor,
                              "@mozilla.org/document-transformer;1?type=xslt")
   NS_DEFINE_CONSTRUCTOR_DATA(EventSource, NS_EVENTSOURCE_CONTRACTID)
 };
 
 struct nsConstructorFuncMapData
 {
@@ -1564,18 +1556,16 @@ struct nsConstructorFuncMapData
   nsDOMConstructorFunc mConstructorFunc;
 };
 
 #define NS_DEFINE_CONSTRUCTOR_FUNC_DATA(_class, _func)                        \
   { eDOMClassInfo_##_class##_id, _func },
 
 static const nsConstructorFuncMapData kConstructorFuncMap[] =
 {
-  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(Worker, nsDOMWorker::NewWorker)
-  NS_DEFINE_CONSTRUCTOR_FUNC_DATA(ChromeWorker, nsDOMWorker::NewChromeWorker)
   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(File, nsDOMFileFile::NewFile)
   NS_DEFINE_CONSTRUCTOR_FUNC_DATA(MozBlobBuilder, NS_NewBlobBuilder)
 };
 
 nsIXPConnect *nsDOMClassInfo::sXPConnect = nsnull;
 nsIScriptSecurityManager *nsDOMClassInfo::sSecMan = nsnull;
 PRBool nsDOMClassInfo::sIsInitialized = PR_FALSE;
 PRBool nsDOMClassInfo::sDisableDocumentAllSupport = PR_FALSE;
@@ -4131,28 +4121,16 @@ nsDOMClassInfo::Init()
 
   DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(MathMLElement, nsIDOMElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSElement)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMNodeSelector)
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(Worker, nsIWorker)
-    DOM_CLASSINFO_MAP_ENTRY(nsIWorker)
-    DOM_CLASSINFO_MAP_ENTRY(nsIAbstractWorker)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
-  DOM_CLASSINFO_MAP_END
-
-  DOM_CLASSINFO_MAP_BEGIN(ChromeWorker, nsIWorker)
-    DOM_CLASSINFO_MAP_ENTRY(nsIWorker)
-    DOM_CLASSINFO_MAP_ENTRY(nsIAbstractWorker)
-    DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
-  DOM_CLASSINFO_MAP_END
-
   DOM_CLASSINFO_MAP_BEGIN(WebGLRenderingContext, nsIDOMWebGLRenderingContext)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMWebGLRenderingContext)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(WebGLBuffer, nsIWebGLBuffer)
     DOM_CLASSINFO_MAP_ENTRY(nsIWebGLBuffer)
   DOM_CLASSINFO_MAP_END
 
@@ -4229,18 +4207,18 @@ nsDOMClassInfo::Init()
   DOM_CLASSINFO_MAP_BEGIN(DesktopNotification, nsIDOMDesktopNotification)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDesktopNotification)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(DesktopNotificationCenter, nsIDOMDesktopNotificationCenter)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMDesktopNotificationCenter)
   DOM_CLASSINFO_MAP_END
 
-  DOM_CLASSINFO_MAP_BEGIN(WebSocket, nsIWebSocket)
-    DOM_CLASSINFO_MAP_ENTRY(nsIWebSocket)
+  DOM_CLASSINFO_MAP_BEGIN(MozWebSocket, nsIMozWebSocket)
+    DOM_CLASSINFO_MAP_ENTRY(nsIMozWebSocket)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget)
   DOM_CLASSINFO_MAP_END
 
   DOM_CLASSINFO_MAP_BEGIN(CloseEvent, nsIDOMCloseEvent)
     DOM_CLASSINFO_MAP_ENTRY(nsIDOMCloseEvent)
     DOM_CLASSINFO_EVENT_MAP_ENTRIES
   DOM_CLASSINFO_MAP_END
 
@@ -6053,18 +6031,40 @@ nsDOMConstructor::HasInstance(nsIXPConne
   JSClass *dom_class = JS_GET_CLASS(cx, dom_obj);
   if (!dom_class) {
     NS_ERROR("nsDOMConstructor::HasInstance can't get class.");
     return NS_ERROR_UNEXPECTED;
   }
 
   const nsGlobalNameStruct *name_struct;
   rv = GetNameStruct(NS_ConvertASCIItoUTF16(dom_class->name), &name_struct);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
   if (!name_struct) {
-    return rv;
+    // This isn't a normal DOM object, see if this constructor lives on its
+    // prototype chain.
+    jsval val;
+    if (!JS_GetProperty(cx, obj, "prototype", &val)) {
+      return NS_ERROR_UNEXPECTED;
+    }
+
+    JS_ASSERT(!JSVAL_IS_PRIMITIVE(val));
+    JSObject *dot_prototype = JSVAL_TO_OBJECT(val);
+
+    JSObject *proto = JS_GetPrototype(cx, dom_obj);
+    for ( ; proto; proto = JS_GetPrototype(cx, proto)) {
+      if (proto == dot_prototype) {
+        *bp = PR_TRUE;
+        break;
+      }
+    }
+
+    return NS_OK;
   }
 
   if (name_struct->mType != nsGlobalNameStruct::eTypeClassConstructor &&
       name_struct->mType != nsGlobalNameStruct::eTypeExternalClassInfo &&
       name_struct->mType != nsGlobalNameStruct::eTypeExternalConstructorAlias) {
     // Doesn't have DOM interfaces.
     return NS_OK;
   }
@@ -6497,17 +6497,17 @@ nsWindowSH::GlobalResolve(nsGlobalWindow
       name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) {
     // Don't expose chrome only constructors to content windows.
     if (name_struct->mChromeOnly &&
         !nsContentUtils::IsSystemPrincipal(aWin->GetPrincipal())) {
       return NS_OK;
     }
 
     // For now don't expose web sockets unless user has explicitly enabled them
-    if (name_struct->mDOMClassInfoID == eDOMClassInfo_WebSocket_id) {
+    if (name_struct->mDOMClassInfoID == eDOMClassInfo_MozWebSocket_id) {
       if (!nsWebSocket::PrefEnabled()) {
         return NS_OK;
       }
     }
 
     // For now don't expose server events unless user has explicitly enabled them
     if (name_struct->mDOMClassInfoID == eDOMClassInfo_EventSource_id) {
       if (!nsEventSource::PrefEnabled()) {
@@ -6689,16 +6689,20 @@ ContentWindowGetter(JSContext *cx, uintN
 {
   JSObject *obj = JS_THIS_OBJECT(cx, vp);
   if (!obj)
     return JS_FALSE;
 
   return ::JS_GetProperty(cx, obj, "content", vp);
 }
 
+static JSNewResolveOp sOtherResolveFuncs[] = {
+  mozilla::dom::workers::ResolveWorkerClasses
+};
+
 NS_IMETHODIMP
 nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
                        JSObject *obj, jsid id, PRUint32 flags,
                        JSObject **objp, PRBool *_retval)
 {
   nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper);
 
   if (!JSID_IS_STRING(id)) {
@@ -6915,16 +6919,26 @@ nsWindowSH::NewResolve(nsIXPConnectWrapp
   }
 
   // It is not worth calling GlobalResolve() if we are resolving
   // for assignment, since only read-write properties get dealt
   // with there.
   if (!(flags & JSRESOLVE_ASSIGNING)) {
     JSAutoRequest ar(cx);
 
+    // Resolve special classes.
+    for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(sOtherResolveFuncs); i++) {
+      if (!sOtherResolveFuncs[i](cx, obj, id, flags, objp)) {
+        return NS_ERROR_FAILURE;
+      }
+      if (*objp) {
+        return NS_OK;
+      }
+    }
+
     // Call GlobalResolve() after we call FindChildWithName() so
     // that named child frames will override external properties
     // which have been registered with the script namespace manager.
 
     JSBool did_resolve = JS_FALSE;
     rv = GlobalResolve(win, cx, obj, id, &did_resolve);
     NS_ENSURE_SUCCESS(rv, rv);
 
--- a/dom/base/nsDOMClassInfoClasses.h
+++ b/dom/base/nsDOMClassInfoClasses.h
@@ -456,19 +456,16 @@ DOMCI_CLASS(NotifyPaintEvent)
 DOMCI_CLASS(NotifyAudioAvailableEvent)
 
 DOMCI_CLASS(SimpleGestureEvent)
 
 DOMCI_CLASS(MozTouchEvent)
 
 DOMCI_CLASS(MathMLElement)
 
-DOMCI_CLASS(Worker)
-DOMCI_CLASS(ChromeWorker)
-
 // WebGL
 DOMCI_CLASS(WebGLRenderingContext)
 DOMCI_CLASS(WebGLBuffer)
 DOMCI_CLASS(WebGLTexture)
 DOMCI_CLASS(WebGLProgram)
 DOMCI_CLASS(WebGLShader)
 DOMCI_CLASS(WebGLFramebuffer)
 DOMCI_CLASS(WebGLRenderbuffer)
@@ -491,17 +488,17 @@ DOMCI_CLASS(AnimationEvent)
 DOMCI_CLASS(ContentFrameMessageManager)
 
 DOMCI_CLASS(FormData)
 
 DOMCI_CLASS(DesktopNotification)
 DOMCI_CLASS(DesktopNotificationCenter)
 
 // WebSocket
-DOMCI_CLASS(WebSocket)
+DOMCI_CLASS(MozWebSocket)
 DOMCI_CLASS(CloseEvent)
 
 DOMCI_CLASS(IDBFactory)
 DOMCI_CLASS(IDBRequest)
 DOMCI_CLASS(IDBDatabase)
 DOMCI_CLASS(IDBObjectStore)
 DOMCI_CLASS(IDBTransaction)
 DOMCI_CLASS(IDBCursor)
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -716,16 +716,29 @@ nsDOMWindowUtils::GarbageCollect(nsICycl
 #endif
 
   nsJSContext::GarbageCollectNow();
   nsJSContext::CycleCollectNow(aListener);
 
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsDOMWindowUtils::CycleCollect(nsICycleCollectorListener *aListener)
+{
+  // Always permit this in debug builds.
+#ifndef DEBUG
+  if (!IsUniversalXPConnectCapable()) {
+    return NS_ERROR_DOM_SECURITY_ERR;
+  }
+#endif
+
+  nsJSContext::CycleCollectNow(aListener);
+  return NS_OK;
+}
 
 NS_IMETHODIMP
 nsDOMWindowUtils::ProcessUpdates()
 {
   nsPresContext* presContext = GetPresContext();
   if (!presContext)
     return NS_ERROR_UNEXPECTED;
 
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -86,19 +86,19 @@
 #include "nsPluginHost.h"
 #include "nsIPluginInstanceOwner.h"
 #include "nsGeolocation.h"
 #include "nsDesktopNotification.h"
 #include "nsContentCID.h"
 #include "nsLayoutStatics.h"
 #include "nsCycleCollector.h"
 #include "nsCCUncollectableMarker.h"
-#include "nsDOMThreadService.h"
 #include "nsAutoJSValHolder.h"
 #include "nsDOMMediaQueryList.h"
+#include "mozilla/dom/workers/Workers.h"
 
 // Interfaces Needed
 #include "nsIFrame.h"
 #include "nsCanvasFrame.h"
 #include "nsIWidget.h"
 #include "nsIBaseWindow.h"
 #include "nsDeviceMotion.h"
 #include "nsIContent.h"
@@ -1239,28 +1239,21 @@ nsGlobalWindow::ClearScopeWhenAllScripts
 }
 
 void
 nsGlobalWindow::FreeInnerObjects(PRBool aClearScope)
 {
   NS_ASSERTION(IsInnerWindow(), "Don't free inner objects on an outer window");
 
   // Kill all of the workers for this window.
-  nsDOMThreadService* dts = nsDOMThreadService::get();
-  if (dts) {
-    nsIScriptContext *scx = GetContextInternal();
-
-    JSContext *cx = scx ? (JSContext *)scx->GetNativeContext() : nsnull;
-
-    // Have to suspend this request here because CancelWorkersForGlobal will
-    // lock until the worker has died and that could cause a deadlock.
-    JSAutoSuspendRequest asr(cx);
-
-    dts->CancelWorkersForGlobal(static_cast<nsIScriptGlobalObject*>(this));
-  }
+  nsIScriptContext *scx = GetContextInternal();
+  JSContext *cx = scx ?
+                  static_cast<JSContext*>(scx->GetNativeContext()) :
+                  nsnull;
+  mozilla::dom::workers::CancelWorkersForWindow(cx, this);
 
   // Close all IndexedDB databases for this window.
   indexedDB::IndexedDatabaseManager* idbManager =
     indexedDB::IndexedDatabaseManager::Get();
   if (idbManager) {
     idbManager->AbortCloseDatabasesForWindow(this);
   }
 
@@ -7171,68 +7164,28 @@ nsGlobalWindow::Find(const nsAString& aS
     // Launch the search with the passed in search string
     rv = finder->FindNext(aDidFind);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   return rv;
 }
 
-static PRBool
-Is8bit(const nsAString& aString)
-{
-  static const PRUnichar EIGHT_BIT = PRUnichar(~0x00FF);
-
-  nsAString::const_iterator done_reading;
-  aString.EndReading(done_reading);
-
-  // for each chunk of |aString|...
-  PRUint32 fragmentLength = 0;
-  nsAString::const_iterator iter;
-  for (aString.BeginReading(iter); iter != done_reading;
-       iter.advance(PRInt32(fragmentLength))) {
-    fragmentLength = PRUint32(iter.size_forward());
-    const PRUnichar* c = iter.get();
-    const PRUnichar* fragmentEnd = c + fragmentLength;
-
-    // for each character in this chunk...
-    while (c < fragmentEnd)
-      if (*c++ & EIGHT_BIT)
-        return PR_FALSE;
-  }
-
-  return PR_TRUE;
-}
-
 NS_IMETHODIMP
 nsGlobalWindow::Atob(const nsAString& aAsciiBase64String,
                      nsAString& aBinaryData)
 {
-  if (!Is8bit(aAsciiBase64String)) {
-    aBinaryData.Truncate();
-    return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
-  }
-
-  nsresult rv = nsXPConnect::Base64Decode(aAsciiBase64String, aBinaryData);
-  if (NS_FAILED(rv) && rv == NS_ERROR_INVALID_ARG) {
-    return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
-  }
-  return rv;
+  return nsContentUtils::Atob(aAsciiBase64String, aBinaryData);
 }
 
 NS_IMETHODIMP
 nsGlobalWindow::Btoa(const nsAString& aBinaryData,
                      nsAString& aAsciiBase64String)
 {
-  if (!Is8bit(aBinaryData)) {
-    aAsciiBase64String.Truncate();
-    return NS_ERROR_DOM_INVALID_CHARACTER_ERR;
-  }
-
-  return nsXPConnect::Base64Encode(aBinaryData, aAsciiBase64String);
+  return nsContentUtils::Btoa(aBinaryData, aAsciiBase64String);
 }
 
 //*****************************************************************************
 // nsGlobalWindow::nsIDOMEventTarget
 //*****************************************************************************
 
 NS_IMETHODIMP
 nsGlobalWindow::RemoveEventListener(const nsAString& aType,
@@ -9923,21 +9876,23 @@ nsGlobalWindow::SuspendTimeouts(PRUint32
   FORWARD_TO_INNER_VOID(SuspendTimeouts, (aIncrease, aFreezeChildren));
 
   PRBool suspended = (mTimeoutsSuspendDepth != 0);
   mTimeoutsSuspendDepth += aIncrease;
 
   if (!suspended) {
     DisableDeviceMotionUpdates();
 
-    nsDOMThreadService* dts = nsDOMThreadService::get();
-    if (dts) {
-      dts->SuspendWorkersForGlobal(static_cast<nsIScriptGlobalObject*>(this));
-    }
-  
+    // Suspend all of the workers for this window.
+    nsIScriptContext *scx = GetContextInternal();
+    JSContext *cx = scx ?
+                    static_cast<JSContext*>(scx->GetNativeContext()) :
+                    nsnull;
+    mozilla::dom::workers::SuspendWorkersForWindow(cx, this);
+
     TimeStamp now = TimeStamp::Now();
     for (nsTimeout *t = FirstTimeout(); IsTimeout(t); t = t->Next()) {
       // Set mTimeRemaining to be the time remaining for this timer.
       if (t->mWhen > now)
         t->mTimeRemaining = t->mWhen - now;
       else
         t->mTimeRemaining = TimeDuration(0);
   
@@ -9999,20 +9954,22 @@ nsGlobalWindow::ResumeTimeouts(PRBool aT
   NS_ASSERTION(mTimeoutsSuspendDepth, "Mismatched calls to ResumeTimeouts!");
   --mTimeoutsSuspendDepth;
   PRBool shouldResume = (mTimeoutsSuspendDepth == 0);
   nsresult rv;
 
   if (shouldResume) {
     EnableDeviceMotionUpdates();
 
-    nsDOMThreadService* dts = nsDOMThreadService::get();
-    if (dts) {
-      dts->ResumeWorkersForGlobal(static_cast<nsIScriptGlobalObject*>(this));
-    }
+    // Resume all of the workers for this window.
+    nsIScriptContext *scx = GetContextInternal();
+    JSContext *cx = scx ?
+                    static_cast<JSContext*>(scx->GetNativeContext()) :
+                    nsnull;
+    mozilla::dom::workers::ResumeWorkersForWindow(cx, this);
 
     // Restore all of the timeouts, using the stored time remaining
     // (stored in timeout->mTimeRemaining).
 
     TimeStamp now = TimeStamp::Now();
 
 #ifdef DEBUG
     PRBool _seenDummyTimeout = PR_FALSE;
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -3689,42 +3689,42 @@ ObjectPrincipalFinder(JSContext *cx, JSO
   // JS principals, but the caller of this function expects a weak
   // reference. So we need to release here.
 
   JSPRINCIPALS_DROP(cx, jsPrincipals);
 
   return jsPrincipals;
 }
 
-static JSObject*
-DOMReadStructuredClone(JSContext* cx,
-                       JSStructuredCloneReader* reader,
-                       uint32 tag,
-                       uint32 data,
-                       void* closure)
+JSObject*
+NS_DOMReadStructuredClone(JSContext* cx,
+                          JSStructuredCloneReader* reader,
+                          uint32 tag,
+                          uint32 data,
+                          void* closure)
 {
   // We don't currently support any extensions to structured cloning.
   nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_DOM_DATA_CLONE_ERR);
   return nsnull;
 }
 
-static JSBool
-DOMWriteStructuredClone(JSContext* cx,
-                        JSStructuredCloneWriter* writer,
-                        JSObject* obj,
-                        void *closure)
+JSBool
+NS_DOMWriteStructuredClone(JSContext* cx,
+                           JSStructuredCloneWriter* writer,
+                           JSObject* obj,
+                           void *closure)
 {
   // We don't currently support any extensions to structured cloning.
   nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_DOM_DATA_CLONE_ERR);
   return JS_FALSE;
 }
 
-static void
-DOMStructuredCloneError(JSContext* cx,
-                        uint32 errorid)
+void
+NS_DOMStructuredCloneError(JSContext* cx,
+                           uint32 errorid)
 {
   // We don't currently support any extensions to structured cloning.
   nsDOMClassInfo::ThrowJSException(cx, NS_ERROR_DOM_DATA_CLONE_ERR);
 }
 
 //static
 nsresult
 nsJSRuntime::Init()
@@ -3758,19 +3758,19 @@ nsJSRuntime::Init()
 
   JSSecurityCallbacks *callbacks = JS_GetRuntimeSecurityCallbacks(sRuntime);
   NS_ASSERTION(callbacks, "SecMan should have set security callbacks!");
 
   callbacks->findObjectPrincipals = ObjectPrincipalFinder;
 
   // Set up the structured clone callbacks.
   static JSStructuredCloneCallbacks cloneCallbacks = {
-    DOMReadStructuredClone,
-    DOMWriteStructuredClone,
-    DOMStructuredCloneError
+    NS_DOMReadStructuredClone,
+    NS_DOMWriteStructuredClone,
+    NS_DOMStructuredCloneError
   };
   JS_SetStructuredCloneCallbacks(sRuntime, &cloneCallbacks);
 
   // Set these global xpconnect options...
   Preferences::RegisterCallback(MaxScriptRunTimePrefChangedCallback,
                                 "dom.max_script_run_time");
   MaxScriptRunTimePrefChangedCallback("dom.max_script_run_time", nsnull);
 
--- a/dom/base/nsJSEnvironment.h
+++ b/dom/base/nsJSEnvironment.h
@@ -358,9 +358,19 @@ public:
 NS_DEFINE_STATIC_IID_ACCESSOR(nsIJSArgArray, NS_IJSARGARRAY_IID)
 
 /* factory functions */
 nsresult NS_CreateJSRuntime(nsIScriptRuntime **aRuntime);
 
 /* prototypes */
 void NS_ScriptErrorReporter(JSContext *cx, const char *message, JSErrorReport *report);
 
+JSObject* NS_DOMReadStructuredClone(JSContext* cx,
+                                    JSStructuredCloneReader* reader, uint32 tag,
+                                    uint32 data, void* closure);
+
+JSBool NS_DOMWriteStructuredClone(JSContext* cx,
+                                  JSStructuredCloneWriter* writer,
+                                  JSObject* obj, void *closure);
+
+void NS_DOMStructuredCloneError(JSContext* cx, uint32 errorid);
+
 #endif /* nsJSEnvironment_h___ */
--- a/dom/dom-config.mk
+++ b/dom/dom-config.mk
@@ -2,17 +2,17 @@ MODULE = dom
 
 DOM_SRCDIRS = \
   dom/base \
   dom/src/events \
   dom/src/storage \
   dom/src/offline \
   dom/src/geolocation \
   dom/src/notification \
-  dom/src/threads \
+  dom/workers \
   content/xbl/src \
   content/xul/document/src \
   content/events/src \
   content/base/src \
   content/html/content/src \
   content/html/document/src \
   content/svg/content/src \
   layout/generic \
--- a/dom/interfaces/base/nsIDOMWindowUtils.idl
+++ b/dom/interfaces/base/nsIDOMWindowUtils.idl
@@ -61,17 +61,17 @@ interface nsIDOMNode;
 interface nsIDOMNodeList;
 interface nsIDOMElement;
 interface nsIDOMHTMLCanvasElement;
 interface nsIDOMEvent;
 interface nsITransferable;
 interface nsIQueryContentEventResult;
 interface nsIDOMWindow;
 
-[scriptable, uuid(b46050ea-6f18-11e0-bf00-f389b7004a12)]
+[scriptable, uuid(d95fac68-4f0d-430f-9580-6dd8041f177e)]
 interface nsIDOMWindowUtils : nsISupports {
 
   /**
    * Image animation mode of the window. When this attribute's value
    * is changed, the implementation should set all images in the window
    * to the given value. That is, when set to kDontAnimMode, all images
    * will stop animating. The attribute's value must be one of the
    * animationMode values from imgIContainer.
@@ -359,16 +359,28 @@ interface nsIDOMWindowUtils : nsISupport
    *
    * @param aListener listener that receives information about the CC graph
    *                  (see @mozilla.org/cycle-collector-logger;1 for a logger
    *                   component)
    */
   void garbageCollect([optional] in nsICycleCollectorListener aListener);
 
   /**
+   * Force a cycle collection without garbage collection.
+   *
+   * Will throw a DOM security error if called without UniversalXPConnect
+   * privileges in non-debug builds. Available to all callers in debug builds.
+   *
+   * @param aListener listener that receives information about the CC graph
+   *                  (see @mozilla.org/cycle-collector-logger;1 for a logger
+   *                   component)
+   */
+  void cycleCollect([optional] in nsICycleCollectorListener aListener);
+
+  /**
    * Force processing of any queued paints
    */
 
   void processUpdates();
 
   /** Synthesize a simple gesture event for a window. The event types
    *  supported are: MozSwipeGesture, MozMagnifyGestureStart,
    *  MozMagnifyGestureUpdate, MozMagnifyGesture, MozRotateGestureStart,
deleted file mode 100644
--- a/dom/interfaces/threads/Makefile.in
+++ /dev/null
@@ -1,52 +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 mozilla.org code.
-#
-# The Initial Developer of the Original Code is Mozilla Foundation.
-# Portions created by the Initial Developer are Copyright (C) 2007
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#   Vladimir Vukicevic <vladimir@pobox.com> (Original Author)
-#   Ben Turner <bent.mozilla@gmail.com>
-#
-# Alternatively, the contents of this file may be used under the terms of
-# either of 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       = dom
-XPIDL_MODULE = dom_threads
-GRE_MODULE   = 1
-
-XPIDLSRCS    =  nsIDOMWorkers.idl
-
-include $(topsrcdir)/config/rules.mk
deleted file mode 100644
--- a/dom/interfaces/threads/nsIDOMWorkers.idl
+++ /dev/null
@@ -1,156 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* ***** 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 Web Workers.
- *
- * The Initial Developer of the Original Code is
- *   Mozilla Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2008
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Ben Turner <bent.mozilla@gmail.com> (Original Author)
- *
- * 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 ***** */
-
-/**
- * From http://www.whatwg.org/specs/web-workers/current-work
- */
-
-#include "nsIDOMEvent.idl"
-#include "nsIDOMEventTarget.idl"
-
-interface nsIDOMEventListener;
-
-[scriptable, uuid(ab3725b8-3fca-40cc-a42c-92fb154ef01d)]
-interface nsIWorkerMessagePort : nsISupports
-{
-  void postMessage(/* in JSObject aMessage */);
-};
-
-[scriptable, uuid(508f2d49-e9a0-4fe8-bd33-321820173b4a)]
-interface nsIWorkerMessageEvent : nsIDOMEvent
-{
-  readonly attribute DOMString data;
-  readonly attribute DOMString origin;
-
-  readonly attribute nsISupports source;
-
-  void initMessageEvent(in DOMString aTypeArg,
-                        in boolean aCanBubbleArg,
-                        in boolean aCancelableArg,
-                        in DOMString aDataArg,
-                        in DOMString aOriginArg,
-                        in nsISupports aSourceArg);
-};
-
-[scriptable, uuid(73d82c1d-05de-49c9-a23b-7121ff09a67a)]
-interface nsIWorkerErrorEvent : nsIDOMEvent
-{
-  readonly attribute DOMString message;
-  readonly attribute DOMString filename;
-
-  readonly attribute unsigned long lineno;
-
-  void initErrorEvent(in DOMString aTypeArg,
-                      in boolean aCanBubbleArg,
-                      in boolean aCancelableArg,
-                      in DOMString aMessageArg,
-                      in DOMString aFilenameArg,
-                      in unsigned long aLinenoArg);
-};
-
-[scriptable, uuid(17a005c3-4f2f-4bb6-b169-c181fa6873de)]
-interface nsIWorkerLocation : nsISupports
-{
-  readonly attribute AUTF8String href;
-  readonly attribute AUTF8String protocol;
-  readonly attribute AUTF8String host;
-  readonly attribute AUTF8String hostname;
-  readonly attribute AUTF8String port;
-  readonly attribute AUTF8String pathname;
-  readonly attribute AUTF8String search;
-  readonly attribute AUTF8String hash;
-
-  AUTF8String toString();
-};
-
-[scriptable, uuid(74fb665a-e477-4ce2-b3c6-c58b1b28b6c3)]
-interface nsIWorkerNavigator : nsISupports
-{
-  readonly attribute DOMString appName;
-  readonly attribute DOMString appVersion;
-  readonly attribute DOMString platform;
-  readonly attribute DOMString userAgent;
-};
-
-[scriptable, uuid(c111e7d3-8044-4458-aa7b-637696ffb841)]
-interface nsIWorkerGlobalScope : nsISupports
-{
-  readonly attribute nsIWorkerGlobalScope self;
-  readonly attribute nsIWorkerNavigator navigator;
-  readonly attribute nsIWorkerLocation location;
-
-  attribute nsIDOMEventListener onerror;
-};
-
-[scriptable, uuid(5c55ea4b-e4ac-4ceb-bfeb-46bd5e521b8a)]
-interface nsIWorkerScope : nsIWorkerGlobalScope
-{
-  void postMessage(/* in JSObject aMessage */);
-
-  void close();
-
-  attribute nsIDOMEventListener onmessage;
-  attribute nsIDOMEventListener onclose;
-};
-
-[scriptable, builtinclass, uuid(b90b7561-b5e2-4545-84b0-280dbaaa94ea)]
-interface nsIAbstractWorker : nsIDOMEventTarget
-{
-  attribute nsIDOMEventListener onerror;
-};
-
-[scriptable, builtinclass, uuid(daf945c3-8d29-4724-8939-dd383f7d27a7)]
-interface nsIWorker : nsIAbstractWorker
-{
-  void postMessage(/* in JSObject aMessage */);
-
-  attribute nsIDOMEventListener onmessage;
-
-  void terminate();
-};
-
-[scriptable, uuid(cfc4bb32-ca83-4d58-9b6f-66f8054a333a)]
-interface nsIWorkerFactory : nsISupports
-{
-    nsIWorker newChromeWorker(/* in DOMString aScriptURL */);
-};
-
-%{ C++
-#define NS_WORKERFACTORY_CONTRACTID \
-"@mozilla.org/threads/workerfactory;1"
-%}
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -239,19 +239,18 @@ TabChild::ExitModalEventLoop(nsresult aS
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 TabChild::SetStatusWithContext(PRUint32 aStatusType,
                                     const nsAString& aStatusText,
                                     nsISupports* aStatusContext)
 {
-  NS_NOTREACHED("TabChild::SetStatusWithContext not supported in TabChild");
-
-  return NS_ERROR_NOT_IMPLEMENTED;
+  // FIXME/bug 617804: should the platform support this?
+  return NS_OK;
 }
 
 NS_IMETHODIMP
 TabChild::SetDimensions(PRUint32 aFlags, PRInt32 aX, PRInt32 aY,
                              PRInt32 aCx, PRInt32 aCy)
 {
   NS_NOTREACHED("TabChild::SetDimensions not supported in TabChild");
 
@@ -1074,16 +1073,30 @@ TabChildGlobal::GetDocShell(nsIDocShell*
   *aDocShell = nsnull;
   if (!mTabChild)
     return NS_ERROR_NULL_POINTER;
   nsCOMPtr<nsIDocShell> docShell = do_GetInterface(mTabChild->WebNavigation());
   docShell.swap(*aDocShell);
   return NS_OK;
 }
 
+NS_IMETHODIMP
+TabChildGlobal::Btoa(const nsAString& aBinaryData,
+                     nsAString& aAsciiBase64String)
+{
+  return nsContentUtils::Btoa(aBinaryData, aAsciiBase64String);
+}
+
+NS_IMETHODIMP
+TabChildGlobal::Atob(const nsAString& aAsciiString,
+                     nsAString& aBinaryData)
+{
+  return nsContentUtils::Atob(aAsciiString, aBinaryData);
+}
+
 JSContext*
 TabChildGlobal::GetJSContextForEventHandlers()
 {
   if (!mTabChild)
     return nsnull;
   return mTabChild->GetJSContext();
 }
 
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -105,16 +105,20 @@ public:
   }
   NS_IMETHOD GetContent(nsIDOMWindow** aContent);
   NS_IMETHOD GetDocShell(nsIDocShell** aDocShell);
   NS_IMETHOD Dump(const nsAString& aStr)
   {
     return mMessageManager ? mMessageManager->Dump(aStr) : NS_OK;
   }
   NS_IMETHOD PrivateNoteIntentionalCrash();
+  NS_IMETHOD Btoa(const nsAString& aBinaryData,
+                  nsAString& aAsciiBase64String);
+  NS_IMETHOD Atob(const nsAString& aAsciiString,
+                  nsAString& aBinaryData);
 
   NS_IMETHOD AddEventListener(const nsAString& aType,
                               nsIDOMEventListener* aListener,
                               PRBool aUseCapture)
   {
     // By default add listeners only for trusted events!
     return nsDOMEventTargetHelper::AddEventListener(aType, aListener,
                                                     aUseCapture, PR_FALSE, 2);
--- a/dom/plugins/base/nsPluginNativeWindowWin.cpp
+++ b/dom/plugins/base/nsPluginNativeWindowWin.cpp
@@ -488,22 +488,16 @@ SetWindowLongWHook(HWND hWnd,
     reinterpret_cast<WNDPROC>(sUser32SetWindowLongWHookStub(hWnd, nIndex,
       reinterpret_cast<LONG_PTR>(PluginWndProc))));
   return proc;
 }
 
 static void
 HookSetWindowLongPtr()
 {
-#ifdef _WIN64
-  // XXX WindowsDllInterceptor doesn't support hooks
-  // in 64-bit builds, disabling this code for now.
-  return;
-#endif
-
   sUser32Intercept.Init("user32.dll");
 #ifdef _WIN64
   sUser32Intercept.AddHook("SetWindowLongPtrA", reinterpret_cast<intptr_t>(SetWindowLongPtrAHook),
                            (void**) &sUser32SetWindowLongAHookStub);
   sUser32Intercept.AddHook("SetWindowLongPtrW", reinterpret_cast<intptr_t>(SetWindowLongPtrWHook),
                            (void**) &sUser32SetWindowLongWHookStub);
 #else
   sUser32Intercept.AddHook("SetWindowLongA", reinterpret_cast<intptr_t>(SetWindowLongAHook),
--- a/dom/plugins/base/nsPluginStreamListenerPeer.cpp
+++ b/dom/plugins/base/nsPluginStreamListenerPeer.cpp
@@ -886,18 +886,17 @@ nsresult nsPluginStreamListenerPeer::Ser
   mPendingRequests = 0;
   
   return NS_OK;
 }
 
 PRBool
 nsPluginStreamListenerPeer::UseExistingPluginCacheFile(nsPluginStreamListenerPeer* psi)
 {
-  
-  NS_ENSURE_ARG_POINTER(psi);
+  NS_ENSURE_TRUE(psi, PR_FALSE);
   
   if (psi->mLength == mLength &&
       psi->mModified == mModified &&
       mStreamComplete &&
       mURLSpec.Equals(psi->mURLSpec))
   {
     return PR_TRUE;
   }
--- a/dom/plugins/ipc/PPluginModule.ipdl
+++ b/dom/plugins/ipc/PPluginModule.ipdl
@@ -34,16 +34,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 protocol PPluginIdentifier;
 include protocol PPluginInstance;
+include protocol PPluginScriptableObject;
 
 include "npapi.h";
 include "mozilla/plugins/PluginMessageUtils.h";
 
 using NPError;
 using NPNVariable;
 using base::FileDescriptor;
 using mozilla::plugins::NativeThreadId;
@@ -148,12 +149,15 @@ parent:
   async PluginHideWindow(uint32_t aWindowId);
 
   // OS X Specific calls to allow the plugin to manage the cursor.
   async SetCursor(NSCursorInfo cursorInfo);
   async ShowCursor(bool show);
   async PushCursor(NSCursorInfo cursorInfo);
   async PopCursor();
   sync GetNativeCursorsSupported() returns (bool supported);
+
+  sync NPN_SetException(nullable PPluginScriptableObject actor,
+                        nsCString message);
 };
 
 } // namespace plugins
 } // namespace mozilla
--- a/dom/plugins/ipc/PluginInstanceChild.cpp
+++ b/dom/plugins/ipc/PluginInstanceChild.cpp
@@ -55,16 +55,17 @@
 extern const PRUnichar* kFlashFullscreenClass;
 using mozilla::gfx::SharedDIBSurface;
 #endif
 #include "gfxSharedImageSurface.h"
 #include "gfxUtils.h"
 #include "gfxAlphaRecovery.h"
 
 #include "mozilla/ipc/SyncChannel.h"
+#include "mozilla/AutoRestore.h"
 
 using mozilla::ipc::ProcessChild;
 using namespace mozilla::plugins;
 
 #ifdef MOZ_WIDGET_GTK2
 
 #include <gtk/gtk.h>
 #include <gdk/gdkx.h>
@@ -1472,22 +1473,16 @@ PluginInstanceChild::SetWindowLongWHook(
         NS_ASSERTION(self->mPluginWndProc != PluginWindowProc, "Infinite recursion coming up!");
     }
     return proc;
 }
 
 void
 PluginInstanceChild::HookSetWindowLongPtr()
 {
-#ifdef _WIN64
-    // XXX WindowsDllInterceptor doesn't support hooks
-    // in 64-bit builds, disabling this code for now.
-    return;
-#endif
-
     if (!(GetQuirks() & PluginModuleChild::QUIRK_FLASH_HOOK_SETLONGPTR))
         return;
 
     sUser32Intercept.Init("user32.dll");
 #ifdef _WIN64
     sUser32Intercept.AddHook("SetWindowLongPtrA", reinterpret_cast<intptr_t>(SetWindowLongPtrAHook),
                              (void**) &sUser32SetWindowLongAHookStub);
     sUser32Intercept.AddHook("SetWindowLongPtrW", reinterpret_cast<intptr_t>(SetWindowLongPtrWHook),
@@ -1542,24 +1537,18 @@ PluginInstanceChild::TrackPopupHookProc(
   sWinlessPopupSurrogateHWND = NULL;
 
   // Popups that don't use TPM_RETURNCMD expect a final command message
   // when an item is selected and the context closes. Since we replace
   // the parent, we need to forward this back to the real parent so it
   // can act on the menu item selected.
   bool isRetCmdCall = (uFlags & TPM_RETURNCMD);
 
-  // A little trick scrounged from chromium's code - set the focus
-  // to our surrogate parent so keyboard nav events go to the menu. 
-  HWND focusHwnd = SetFocus(surrogateHwnd);
   DWORD res = sUser32TrackPopupMenuStub(hMenu, uFlags|TPM_RETURNCMD, x, y,
                                         nReserved, surrogateHwnd, prcRect);
-  if (IsWindow(focusHwnd)) {
-      SetFocus(focusHwnd);
-  }
 
   if (!isRetCmdCall && res) {
       SendMessage(hWnd, WM_COMMAND, MAKEWPARAM(res, 0), 0);
   }
 
   return res;
 }
 
@@ -1615,30 +1604,43 @@ int16_t
 PluginInstanceChild::WinlessHandleEvent(NPEvent& event)
 {
     if (!mPluginIface->event)
         return false;
 
     // Events that might generate nested event dispatch loops need
     // special handling during delivery.
     int16_t handled;
+    
+    HWND focusHwnd = NULL;
 
     // TrackPopupMenu will fail if the parent window is not associated with
     // our ui thread. So we hook TrackPopupMenu so we can hand in a surrogate
     // parent created in the child process.
     if ((GetQuirks() & PluginModuleChild::QUIRK_WINLESS_TRACKPOPUP_HOOK) && // XXX turn on by default?
           (event.event == WM_RBUTTONDOWN || // flash
            event.event == WM_RBUTTONUP)) {  // silverlight
       sWinlessPopupSurrogateHWND = mWinlessPopupSurrogateHWND;
+      
+      // A little trick scrounged from chromium's code - set the focus
+      // to our surrogate parent so keyboard nav events go to the menu. 
+      focusHwnd = SetFocus(mWinlessPopupSurrogateHWND);
     }
 
+    MessageLoop* loop = MessageLoop::current();
+    AutoRestore<bool> modalLoop(loop->os_modal_loop());
+
     handled = mPluginIface->event(&mData, reinterpret_cast<void*>(&event));
 
     sWinlessPopupSurrogateHWND = NULL;
 
+    if (IsWindow(focusHwnd)) {
+      SetFocus(focusHwnd);
+    }
+
     return handled;
 }
 
 /* windowless drawing helpers */
 
 bool
 PluginInstanceChild::SharedSurfaceSetWindow(const NPRemoteWindow& aWindow)
 {
@@ -1998,17 +2000,19 @@ PluginInstanceChild::AnswerSetPluginFocu
     PR_LOG(gPluginLog, PR_LOG_DEBUG, ("%s", FULLFUNCTION));
 
 #if defined(OS_WIN)
     // Parent is letting us know the dom set focus to the plugin. Note,
     // focus can change during transit in certain edge cases, for example
     // when a button click brings up a full screen window. Since we send
     // this in response to a WM_SETFOCUS event on our parent, the parent
     // should have focus when we receive this. If not, ignore the call.
-    if (::GetFocus() == mPluginWindowHWND || ::GetFocus() != mPluginParentHWND)
+    if (::GetFocus() == mPluginWindowHWND ||
+        ((GetQuirks() & PluginModuleChild::QUIRK_SILVERLIGHT_FOCUS_CHECK_PARENT) &&
+         (::GetFocus() != mPluginParentHWND)))
         return true;
     ::SetFocus(mPluginWindowHWND);
     return true;
 #else
     NS_NOTREACHED("PluginInstanceChild::AnswerSetPluginFocus not implemented!");
     return false;
 #endif
 }
--- a/dom/plugins/ipc/PluginModuleChild.cpp
+++ b/dom/plugins/ipc/PluginModuleChild.cpp
@@ -1511,17 +1511,29 @@ void NP_CALLBACK
 }
 
 void NP_CALLBACK
 _setexception(NPObject* aNPObj,
               const NPUTF8* aMessage)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
     ENSURE_PLUGIN_THREAD_VOID();
-    NS_WARNING("Not yet implemented!");
+
+    PluginModuleChild* self = PluginModuleChild::current();
+    PluginScriptableObjectChild* actor = NULL;
+    if (aNPObj) {
+        actor = self->GetActorForNPObject(aNPObj);
+        if (!actor) {
+            NS_ERROR("Failed to get actor!");
+            return;
+        }
+    }
+
+    self->SendNPN_SetException(static_cast<PPluginScriptableObjectChild*>(actor),
+                               NullableString(aMessage));
 }
 
 void NP_CALLBACK
 _pushpopupsenabledstate(NPP aNPP,
                         NPBool aEnabled)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
     ENSURE_PLUGIN_THREAD_VOID();
@@ -1905,16 +1917,17 @@ PluginModuleChild::InitQuirksModes(const
     mQuirks = 0;
     // application/x-silverlight
     // application/x-silverlight-2
     NS_NAMED_LITERAL_CSTRING(silverlight, "application/x-silverlight");
     if (FindInReadable(silverlight, aMimeType)) {
         mQuirks |= QUIRK_SILVERLIGHT_DEFAULT_TRANSPARENT;
 #ifdef OS_WIN
         mQuirks |= QUIRK_WINLESS_TRACKPOPUP_HOOK;
+        mQuirks |= QUIRK_SILVERLIGHT_FOCUS_CHECK_PARENT;
 #endif
     }
 
 #ifdef OS_WIN
     // application/x-shockwave-flash
     NS_NAMED_LITERAL_CSTRING(flash, "application/x-shockwave-flash");
     if (FindInReadable(flash, aMimeType)) {
         mQuirks |= QUIRK_WINLESS_TRACKPOPUP_HOOK;
@@ -1968,17 +1981,17 @@ PluginModuleChild::AnswerPPluginInstance
     *rv = mFunctions.newp((char*)NullableStringGet(aMimeType),
                           npp,
                           aMode,
                           argc,
                           argn,
                           argv,
                           0);
     if (NPERR_NO_ERROR != *rv) {
-        return false;
+        return true;
     }
 
 #if defined(XP_MACOSX) && defined(__i386__)
     // If an i386 Mac OS X plugin has selected the Carbon event model then
     // we have to fail. We do not support putting Carbon event model plugins
     // out of process. Note that Carbon is the default model so out of process
     // plugins need to actively negotiate something else in order to work
     // out of process.
@@ -2271,22 +2284,23 @@ PluginModuleChild::CallWindowProcHook(in
 }
 
 LRESULT CALLBACK
 PluginModuleChild::NestedInputEventHook(int nCode, WPARAM wParam, LPARAM lParam)
 {
     PluginModuleChild* self = current();
     PRUint32 len = self->mIncallPumpingStack.Length();
     if (nCode >= 0 && len && !self->mIncallPumpingStack[len - 1]._spinning) {
+        MessageLoop* loop = MessageLoop::current();
         self->SendProcessNativeEventsInRPCCall();
         IncallFrame& f = self->mIncallPumpingStack[len - 1];
         f._spinning = true;
-        MessageLoop* loop = MessageLoop::current();
         f._savedNestableTasksAllowed = loop->NestableTasksAllowed();
         loop->SetNestableTasksAllowed(true);
+        loop->set_os_modal_loop(true);
     }
 
     return CallNextHookEx(NULL, nCode, wParam, lParam);
 }
 
 void
 PluginModuleChild::SetEventHooks()
 {
--- a/dom/plugins/ipc/PluginModuleChild.h
+++ b/dom/plugins/ipc/PluginModuleChild.h
@@ -289,16 +289,20 @@ public:
         // window.
         QUIRK_FLASH_HOOK_GETWINDOWINFO                  = 1 << 5,
         // Win: Addresses a flash bug with mouse capture and full screen
         // windows.
         QUIRK_FLASH_FIXUP_MOUSE_CAPTURE                 = 1 << 6,
         // Win: QuickTime steals focus on SetWindow calls even if it's hidden.
         // Avoid calling SetWindow in that case.
         QUIRK_QUICKTIME_AVOID_SETWINDOW                 = 1 << 7,
+        // Win: Check to make sure the parent window has focus before calling
+        // set focus on the child. Addresses a full screen dialog prompt
+        // problem in Silverlight.
+        QUIRK_SILVERLIGHT_FOCUS_CHECK_PARENT            = 1 << 8,
     };
 
     int GetQuirks() { return mQuirks; }
 
 private:
     void AddQuirk(PluginQuirks quirk) {
       if (mQuirks == QUIRKS_NOT_INITIALIZED)
         mQuirks = 0;
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -1204,8 +1204,26 @@ PluginModuleParent::AddToRefreshTimer(Pl
 void
 PluginModuleParent::RemoveFromRefreshTimer(PluginInstanceParent *aInstance) {
     PRBool visibleRemoved = mCATimerTargets.RemoveElement(aInstance);
     if (visibleRemoved && mCATimerTargets.IsEmpty()) {
         mCATimer->Cancel();
     }
 }
 #endif
+
+bool
+PluginModuleParent::RecvNPN_SetException(PPluginScriptableObjectParent* aActor,
+                                         const nsCString& aMessage)
+{
+    PLUGIN_LOG_DEBUG(("%s", FULLFUNCTION));
+
+    NPObject* aNPObj = NULL;
+    if (aActor) {
+        aNPObj = static_cast<PluginScriptableObjectParent*>(aActor)->GetObject(true);
+        if (!aNPObj) {
+            NS_ERROR("Failed to get object!");
+            return false;
+        }
+    }
+    mozilla::plugins::parent::_setexception(aNPObj, NullableStringGet(aMessage));
+    return true;
+}
--- a/dom/plugins/ipc/PluginModuleParent.h
+++ b/dom/plugins/ipc/PluginModuleParent.h
@@ -205,16 +205,20 @@ protected:
     RecvPushCursor(const NSCursorInfo& aCursorInfo);
 
     NS_OVERRIDE virtual bool
     RecvPopCursor();
 
     NS_OVERRIDE virtual bool
     RecvGetNativeCursorsSupported(bool* supported);
 
+    NS_OVERRIDE virtual bool
+    RecvNPN_SetException(PPluginScriptableObjectParent* aActor,
+                         const nsCString& aMessage);
+
     static PluginInstanceParent* InstCast(NPP instance);
     static BrowserStreamParent* StreamCast(NPP instance, NPStream* s);
 
 private:
     void SetPluginFuncs(NPPluginFuncs* aFuncs);
 
     // Implement the module-level functions from NPAPI; these are
     // normally resolved directly from the DSO.
--- a/dom/plugins/test/mochitest/Makefile.in
+++ b/dom/plugins/test/mochitest/Makefile.in
@@ -97,20 +97,20 @@ include $(topsrcdir)/config/rules.mk
   test_bug539565-2.html \
   test_enumerate.html \
   test_npruntime_construct.html \
   307-xo-redirect.sjs \
   test_redirect_handling.html \
   test_clear_site_data.html \
   test_zero_opacity.html \
   test_NPPVpluginWantsAllNetworkStreams.html \
+  test_npruntime_npnsetexception.html \
   $(NULL)
 
 #  test_plugin_scroll_painting.html \ bug 596491
-#  test_npruntime_npnsetexception.html \ Disabled for e10s
 
 ifeq ($(OS_ARCH),WINNT)
 _MOCHITEST_FILES += \
   test_windowed_invalidate.html \
   $(NULL)
 
 # test_positioning.html \ disabled due to oddness, perhaps scrolling of the
 # mochitest window?
--- a/dom/plugins/test/mochitest/neverending.sjs
+++ b/dom/plugins/test/mochitest/neverending.sjs
@@ -1,15 +1,16 @@
+var timer = null; // declare timer outside to prevent premature GC
 function handleRequest(request, response)
 {
   response.processAsync();
   response.setHeader("Content-Type", "text/plain", false);
 
   for (var i = 0; i < 1000; ++i)
     response.write("Hello... ");
 
-  var timer = Components.classes["@mozilla.org/timer;1"]
+  timer = Components.classes["@mozilla.org/timer;1"]
     .createInstance(Components.interfaces.nsITimer);
   timer.initWithCallback(function() {
       response.write("world.\n");
       response.finish();
     }, 10 * 1000 /* 10 secs */, Components.interfaces.nsITimer.TYPE_ONE_SHOT);
 }
--- a/dom/plugins/test/testplugin/nptest_windows.cpp
+++ b/dom/plugins/test/testplugin/nptest_windows.cpp
@@ -503,17 +503,17 @@ LRESULT CALLBACK PluginWndProc(HWND hWnd
 {
 	WNDPROC wndProc = (WNDPROC)GetProp(hWnd, "MozillaWndProc");
   if (!wndProc)
     return 0;
   InstanceData* pInstance = (InstanceData*)GetProp(hWnd, "InstanceData");
   if (!pInstance)
     return 0;
 
-  NPEvent event = { uMsg, wParam, lParam };
+  NPEvent event = { static_cast<uint16_t>(uMsg), wParam, lParam };
 
   LRESULT result = 0;
   if (handleEventInternal(pInstance, &event, &result))
     return result;
 
   if (uMsg == WM_CLOSE) {
     ClearSubclass((HWND)pInstance->window.window);
   }
--- a/dom/src/Makefile.in
+++ b/dom/src/Makefile.in
@@ -37,11 +37,11 @@
 
 DEPTH		= ../..
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 
 include $(DEPTH)/config/autoconf.mk
 
-DIRS		= jsurl events storage offline json geolocation threads notification
+DIRS		= jsurl events storage offline json geolocation notification foo
 
 include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/dom/src/foo/Makefile.in
@@ -0,0 +1,55 @@
+# ***** 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 worker threads.
+#
+# The Initial Developer of the Original Code is
+#   Mozilla Corporation
+# Portions created by the Initial Developer are Copyright (C) 2008
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#   Vladimir Vukicevic <vladimir@pobox.com> (Original Author)
+#   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 *****
+
+DEPTH            = ../../..
+topsrcdir        = @top_srcdir@
+srcdir           = @srcdir@
+VPATH            = @srcdir@
+
+relativesrcdir   = dom/src/foo
+
+include $(DEPTH)/config/autoconf.mk
+
+include $(topsrcdir)/config/rules.mk
+
+_TEST_FILES = \
+  test_foo.html \
+  $(NULL)
+
+libs:: $(_TEST_FILES)
+	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/tests/$(relativesrcdir)
new file mode 100644
--- /dev/null
+++ b/dom/src/foo/test_foo.html
@@ -0,0 +1,27 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+Tests of DOM Worker Threads XHR(Bug 450452 )
+-->
+<head>
+  <title>Test for DOM Worker Threads XHR (Bug 450452 )</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=450452">DOM Worker Threads XHR (Bug 450452)</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="text/javascript">
+
+  ok(true, "passed");
+
+</script>
+</pre>
+</body>
+</html>
+
deleted file mode 100644
--- a/dom/src/threads/nsDOMThreadService.cpp
+++ /dev/null
@@ -1,1608 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* ***** 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 worker threads.
- *
- * The Initial Developer of the Original Code is
- *   Mozilla Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2008
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Vladimir Vukicevic <vladimir@pobox.com> (Original Author)
- *   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 "jscntxt.h"
-
-#include "nsDOMThreadService.h"
-
-// Interfaces
-#include "nsIComponentManager.h"
-#include "nsIConsoleService.h"
-#include "nsIDocument.h"
-#include "nsIDOMDocument.h"
-#include "nsIEventTarget.h"
-#include "nsIJSContextStack.h"
-#include "nsIJSRuntimeService.h"
-#include "nsIObserverService.h"
-#include "nsIScriptError.h"
-#include "nsIScriptGlobalObject.h"
-#include "nsIServiceManager.h"
-#include "nsISupportsPriority.h"
-#include "nsIThreadPool.h"
-#include "nsIXPConnect.h"
-#include "nsPIDOMWindow.h"
-
-// Other includes
-#include "nsAutoPtr.h"
-#include "nsContentUtils.h"
-#include "nsDeque.h"
-#include "nsGlobalWindow.h"
-#include "nsIClassInfoImpl.h"
-#include "nsStringBuffer.h"
-#include "nsThreadUtils.h"
-#include "nsXPCOM.h"
-#include "nsXPCOMCID.h"
-#include "nsXPCOMCIDInternal.h"
-#include "pratom.h"
-#include "prthread.h"
-#include "mozilla/Preferences.h"
-
-// DOMWorker includes
-#include "nsDOMWorker.h"
-#include "nsDOMWorkerEvents.h"
-#include "nsDOMWorkerMacros.h"
-#include "nsDOMWorkerMessageHandler.h"
-#include "nsDOMWorkerPool.h"
-#include "nsDOMWorkerSecurityManager.h"
-#include "nsDOMWorkerTimeout.h"
-
-using namespace mozilla;
-
-#ifdef PR_LOGGING
-PRLogModuleInfo *gDOMThreadsLog = nsnull;
-#endif
-#define LOG(_args) PR_LOG(gDOMThreadsLog, PR_LOG_DEBUG, _args)
-
-// The maximum number of threads in the internal thread pool
-#define THREADPOOL_MAX_THREADS 3
-
-PR_STATIC_ASSERT(THREADPOOL_MAX_THREADS >= 1);
-
-// The maximum number of idle threads in the internal thread pool
-#define THREADPOOL_IDLE_THREADS 3
-
-PR_STATIC_ASSERT(THREADPOOL_MAX_THREADS >= THREADPOOL_IDLE_THREADS);
-
-// As we suspend threads for various reasons (navigating away from the page,
-// loading scripts, etc.) we open another slot in the thread pool for another
-// worker to use. We can't do this forever so we set an absolute cap on the
-// number of threads we'll allow to prevent DOS attacks.
-#define THREADPOOL_THREAD_CAP 20
-
-PR_STATIC_ASSERT(THREADPOOL_THREAD_CAP >= THREADPOOL_MAX_THREADS);
-
-// A "bad" value for the NSPR TLS functions.
-#define BAD_TLS_INDEX (PRUintn)-1
-
-// Easy access for static functions. No reference here.
-static nsDOMThreadService* gDOMThreadService = nsnull;
-
-// These pointers actually carry references and must be released.
-static nsIObserverService* gObserverService = nsnull;
-static nsIJSRuntimeService* gJSRuntimeService = nsnull;
-static nsIThreadJSContextStack* gThreadJSContextStack = nsnull;
-static nsIXPCSecurityManager* gWorkerSecurityManager = nsnull;
-
-PRUintn gJSContextIndex = BAD_TLS_INDEX;
-
-static const char* sPrefsToWatch[] = {
-  "dom.max_script_run_time"
-};
-
-// The length of time the close handler is allowed to run in milliseconds.
-static PRUint32 gWorkerCloseHandlerTimeoutMS = 10000;
-
-/**
- * Simple class to automatically destroy a JSContext to make error handling
- * easier.
- */
-class JSAutoContextDestroyer
-{
-public:
-  JSAutoContextDestroyer(JSContext* aCx)
-  : mCx(aCx) { }
-
-  ~JSAutoContextDestroyer() {
-    if (mCx) {
-      nsContentUtils::XPConnect()->ReleaseJSContext(mCx, PR_TRUE);
-    }
-  }
-
-  operator JSContext*() {
-    return mCx;
-  }
-
-  JSContext* forget() {
-    JSContext* cx = mCx;
-    mCx = nsnull;
-    return cx;
-  }
-
-private:
-  JSContext* mCx;
-};
-
-class nsDestroyJSContextRunnable : public nsIRunnable
-{
-public:
-  NS_DECL_ISUPPORTS
-
-  nsDestroyJSContextRunnable(JSContext* aCx)
-  : mCx(aCx)
-  {
-    NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
-    NS_ASSERTION(aCx, "Null pointer!");
-    NS_ASSERTION(!JS_GetGlobalObject(aCx), "Should not have a global!");
-
-    // We're removing this context from this thread. Let the JS engine know.
-    JS_ClearContextThread(aCx);
-  }
-
-  NS_IMETHOD Run()
-  {
-    NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-
-    // We're about to use this context on this thread. Let the JS engine know.
-    if (!!JS_SetContextThread(mCx)) {
-      NS_WARNING("JS_SetContextThread failed!");
-    }
-
-    if (nsContentUtils::XPConnect()) {
-      nsContentUtils::XPConnect()->ReleaseJSContext(mCx, PR_TRUE);
-    }
-    else {
-      NS_WARNING("Failed to release JSContext!");
-    }
-
-    return NS_OK;
-  }
-
-private:
-  JSContext* mCx;
-};
-
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsDestroyJSContextRunnable, nsIRunnable)
-
-/**
- * This class is used as to post an error to the worker's outer handler.
- */
-class nsReportErrorRunnable : public nsIRunnable
-{
-public:
-  NS_DECL_ISUPPORTS
-
-  nsReportErrorRunnable(nsDOMWorker* aWorker,
-                        nsIScriptError* aScriptError)
-  : mWorker(aWorker), mWorkerWN(aWorker->GetWrappedNative()),
-    mScriptError(aScriptError) {
-      NS_ASSERTION(aScriptError, "Null pointer!");
-    }
-
-  NS_IMETHOD Run() {
-    if (mWorker->IsCanceled()) {
-      return NS_OK;
-    }
-
-#ifdef DEBUG
-    {
-      nsRefPtr<nsDOMWorker> parent = mWorker->GetParent();
-      if (NS_IsMainThread()) {
-        NS_ASSERTION(!parent, "Shouldn't have a parent on the main thread!");
-      }
-      else {
-        NS_ASSERTION(parent, "Should have a parent!");
-
-        JSContext* cx = nsDOMThreadService::get()->GetCurrentContext();
-        NS_ASSERTION(cx, "No context!");
-
-        nsDOMWorker* currentWorker = (nsDOMWorker*)JS_GetContextPrivate(cx);
-        NS_ASSERTION(currentWorker == parent, "Wrong worker!");
-      }
-    }
-#endif
-
-    NS_NAMED_LITERAL_STRING(errorStr, "error");
-
-    nsresult rv;
-
-    if (mWorker->HasListeners(errorStr)) {
-      // Construct the error event.
-      nsString message;
-      rv = mScriptError->GetErrorMessage(message);
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      nsString filename;
-      rv = mScriptError->GetSourceName(filename);
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      PRUint32 lineno;
-      rv = mScriptError->GetLineNumber(&lineno);
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      nsRefPtr<nsDOMWorkerErrorEvent> event(new nsDOMWorkerErrorEvent());
-      NS_ENSURE_TRUE(event, NS_ERROR_OUT_OF_MEMORY);
-
-      rv = event->InitErrorEvent(errorStr, PR_FALSE, PR_TRUE, message,
-                                 filename, lineno);
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      event->SetTarget(static_cast<nsDOMWorkerMessageHandler*>(mWorker));
-
-      PRBool stopPropagation = PR_FALSE;
-      rv = mWorker->DispatchEvent(static_cast<nsDOMWorkerEvent*>(event),
-                                  &stopPropagation);
-      if (NS_SUCCEEDED(rv) && stopPropagation) {
-        return NS_OK;
-      }
-    }
-
-    nsRefPtr<nsDOMWorker> parent = mWorker->GetParent();
-    if (!parent) {
-      NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-      nsCOMPtr<nsIConsoleService> consoleService =
-        do_GetService(NS_CONSOLESERVICE_CONTRACTID);
-      if (consoleService) {
-        rv = consoleService->LogMessage(mScriptError);
-        NS_ENSURE_SUCCESS(rv, rv);
-      }
-      return NS_OK;
-    }
-
-    nsRefPtr<nsReportErrorRunnable> runnable =
-      new nsReportErrorRunnable(parent, mScriptError);
-    if (runnable) {
-      nsRefPtr<nsDOMWorker> grandparent = parent->GetParent();
-      rv = grandparent ?
-           nsDOMThreadService::get()->Dispatch(grandparent, runnable) :
-           NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL);
-      NS_ENSURE_SUCCESS(rv, rv);
-    }
-
-    return NS_OK;
-  }
-
-private:
-  nsRefPtr<nsDOMWorker> mWorker;
-  nsCOMPtr<nsIXPConnectWrappedNative> mWorkerWN;
-  nsCOMPtr<nsIScriptError> mScriptError;
-};
-
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsReportErrorRunnable, nsIRunnable)
-
-/**
- * Used to post an expired timeout to the correct worker.
- */
-class nsDOMWorkerTimeoutRunnable : public nsIRunnable
-{
-public:
-  NS_DECL_ISUPPORTS
-
-  nsDOMWorkerTimeoutRunnable(nsDOMWorkerTimeout* aTimeout)
-  : mTimeout(aTimeout) { }
-
-  NS_IMETHOD Run() {
-    return mTimeout->Run();
-  }
-protected:
-  nsRefPtr<nsDOMWorkerTimeout> mTimeout;
-};
-
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsDOMWorkerTimeoutRunnable, nsIRunnable)
-
-class nsDOMWorkerKillRunnable : public nsIRunnable
-{
-public:
-  NS_DECL_ISUPPORTS
-
-  nsDOMWorkerKillRunnable(nsDOMWorker* aWorker)
-  : mWorker(aWorker) { }
-
-  NS_IMETHOD Run() {
-    NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-    mWorker->Kill();
-    return NS_OK;
-  }
-
-private:
-  nsRefPtr<nsDOMWorker> mWorker;
-};
-
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsDOMWorkerKillRunnable, nsIRunnable)
-
-/**
- * This class exists to solve a particular problem: Calling Dispatch on a
- * thread pool will always create a new thread to service the runnable as long
- * as the thread limit has not been reached. Since our DOM workers can only be
- * accessed by one thread at a time we could end up spawning a new thread that
- * does nothing but wait initially. There is no way to control this behavior
- * currently so we cheat by using a runnable that emulates a thread. The
- * nsDOMThreadService's monitor protects the queue of events.
- */
-class nsDOMWorkerRunnable : public nsIRunnable
-{
-  friend class nsDOMThreadService;
-
-public:
-  NS_DECL_ISUPPORTS
-
-  nsDOMWorkerRunnable(nsDOMWorker* aWorker)
-  : mWorker(aWorker), mCloseTimeoutInterval(0), mKillWorkerWhenDone(PR_FALSE) {
-  }
-
-  virtual ~nsDOMWorkerRunnable() {
-    ClearQueue();
-  }
-
-  void PutRunnable(nsIRunnable* aRunnable,
-                   PRIntervalTime aTimeoutInterval,
-                   PRBool aClearQueue) {
-    NS_ASSERTION(aRunnable, "Null pointer!");
-
-    gDOMThreadService->mReentrantMonitor.AssertCurrentThreadIn();
-
-    if (NS_LIKELY(!aTimeoutInterval)) {
-      NS_ADDREF(aRunnable);
-      mRunnables.Push(aRunnable);
-    }
-    else {
-      NS_ASSERTION(!mCloseRunnable, "More than one close runnable?!");
-      if (aClearQueue) {
-        ClearQueue();
-      }
-      mCloseRunnable = aRunnable;
-      mCloseTimeoutInterval = aTimeoutInterval;
-      mKillWorkerWhenDone = PR_TRUE;
-    }
-  }
-
-  void SetCloseRunnableTimeout(PRIntervalTime aTimeoutInterval) {
-    NS_ASSERTION(aTimeoutInterval, "No timeout specified!");
-    NS_ASSERTION(aTimeoutInterval!= PR_INTERVAL_NO_TIMEOUT, "Bad timeout!");
-
-    // No need to enter the monitor because we should already be in it.
-
-    NS_ASSERTION(mWorker->GetExpirationTime() == PR_INTERVAL_NO_TIMEOUT,
-                 "Asked to set timeout on a runnable with no close handler!");
-
-    // This may actually overflow but we don't care - the worst that could
-    // happen is that the close handler could run for a slightly different
-    // amount of time and the spec leaves the time up to us anyway.
-    mWorker->SetExpirationTime(PR_IntervalNow() + aTimeoutInterval);
-  }
-
-  NS_IMETHOD Run() {
-    NS_ASSERTION(!NS_IsMainThread(),
-                 "This should *never* run on the main thread!");
-
-    // This must have been set up by the thread service
-    NS_ASSERTION(gJSContextIndex != BAD_TLS_INDEX, "No context index!");
-
-    // Make sure we have a JSContext to run everything on.
-    JSContext* cx = (JSContext*)PR_GetThreadPrivate(gJSContextIndex);
-    if (!cx) {
-        NS_ERROR("nsDOMThreadService didn't give us a context! Are we out of memory?");
-        return NS_ERROR_FAILURE;
-    }
-
-    NS_ASSERTION(!JS_GetGlobalObject(cx), "Shouldn't have a global!");
-
-    if (mWorker->IsPrivileged()) {
-      JS_SetVersion(cx, JSVERSION_LATEST);
-    }
-    else {
-      JS_SetVersion(cx, JSVERSION_DEFAULT);
-    }
-
-    JS_SetContextPrivate(cx, mWorker);
-
-    // Go ahead and trigger the operation callback for this context before we
-    // try to run any JS. That way we'll be sure to cancel or suspend as soon as
-    // possible if the compilation takes too long.
-    JS_TriggerOperationCallback(cx);
-
-    PRBool killWorkerWhenDone;
-    {
-      nsLazyAutoRequest ar;
-      JSAutoEnterCompartment ac;
-
-      // Tell the worker which context it will be using
-      if (mWorker->SetGlobalForContext(cx, &ar, &ac)) {
-        NS_ASSERTION(ar.entered(), "SetGlobalForContext must enter request on success");
-        NS_ASSERTION(ac.entered(), "SetGlobalForContext must enter compartment on success");
-
-        RunQueue(cx, &killWorkerWhenDone);
-
-        // Remove the global object from the context so that it might be garbage
-        // collected.
-        JS_SetGlobalObject(cx, NULL);
-        JS_SetContextPrivate(cx, NULL);
-      }
-      else {
-        NS_ASSERTION(!ar.entered(), "SetGlobalForContext must not enter request on failure");
-        NS_ASSERTION(!ac.entered(), "SetGlobalForContext must not enter compartment on failure");
-
-        {
-          // Code in XPConnect assumes that the context's global object won't be
-          // replaced outside of a request.
-          JSAutoRequest ar2(cx);
-
-          // This is usually due to a parse error in the worker script...
-          JS_SetGlobalObject(cx, NULL);
-          JS_SetContextPrivate(cx, NULL);
-        }
-
-        ReentrantMonitorAutoEnter mon(gDOMThreadService->mReentrantMonitor);
-        killWorkerWhenDone = mKillWorkerWhenDone;
-        gDOMThreadService->WorkerComplete(this);
-        mon.NotifyAll();
-      }
-    }
-
-    if (killWorkerWhenDone) {
-      nsCOMPtr<nsIRunnable> runnable = new nsDOMWorkerKillRunnable(mWorker);
-      NS_ENSURE_TRUE(runnable, NS_ERROR_OUT_OF_MEMORY);
-
-      nsresult rv = NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL);
-      NS_ENSURE_SUCCESS(rv, rv);
-    }
-
-    return NS_OK;
-  }
-
-protected:
-  void ClearQueue() {
-    nsCOMPtr<nsIRunnable> runnable;
-    while ((runnable = dont_AddRef((nsIRunnable*)mRunnables.PopFront()))) {
-      // Loop until all the runnables are dead.
-    }
-  }
-
-  void RunQueue(JSContext* aCx, PRBool* aCloseRunnableSet) {
-    while (1) {
-      nsCOMPtr<nsIRunnable> runnable;
-      {
-        ReentrantMonitorAutoEnter mon(gDOMThreadService->mReentrantMonitor);
-
-        runnable = dont_AddRef((nsIRunnable*)mRunnables.PopFront());
-
-        if (!runnable && mCloseRunnable) {
-          PRIntervalTime expirationTime;
-          if (mCloseTimeoutInterval == PR_INTERVAL_NO_TIMEOUT) {
-            expirationTime = mCloseTimeoutInterval;
-          }
-          else {
-            expirationTime = PR_IntervalNow() + mCloseTimeoutInterval;
-          }
-          mWorker->SetExpirationTime(expirationTime);
-
-          runnable.swap(mCloseRunnable);
-        }
-
-        if (!runnable || mWorker->IsCanceled()) {
-#ifdef PR_LOGGING
-          if (mWorker->IsCanceled()) {
-            LOG(("Bailing out of run loop for canceled worker[0x%p]",
-                 static_cast<void*>(mWorker.get())));
-          }
-#endif
-          *aCloseRunnableSet = mKillWorkerWhenDone;
-          gDOMThreadService->WorkerComplete(this);
-          mon.NotifyAll();
-          return;
-        }
-      }
-
-      // Clear out any old cruft hanging around in the regexp statics.
-      if (JSObject *global = JS_GetGlobalObject(aCx))
-          JS_ClearRegExpStatics(aCx, global);
-
-      runnable->Run();
-    }
-    NS_NOTREACHED("Shouldn't ever get here!");
-  }
-
-  // Set at construction
-  nsRefPtr<nsDOMWorker> mWorker;
-
-  // Protected by mReentrantMonitor
-  nsDeque mRunnables;
-  nsCOMPtr<nsIRunnable> mCloseRunnable;
-  PRIntervalTime mCloseTimeoutInterval;
-  PRBool mKillWorkerWhenDone;
-};
-
-NS_IMPL_THREADSAFE_ISUPPORTS1(nsDOMWorkerRunnable, nsIRunnable)
-
-/*******************************************************************************
- * JS environment function and callbacks
- */
-
-JSBool
-DOMWorkerOperationCallback(JSContext* aCx)
-{
-  nsDOMWorker* worker = (nsDOMWorker*)JS_GetContextPrivate(aCx);
-  NS_ASSERTION(worker, "This must never be null!");
-
-  PRBool canceled = worker->IsCanceled();
-  if (!canceled && worker->IsSuspended()) {
-    JSAutoSuspendRequest suspended(aCx);
-
-    // Since we're going to block this thread we should open up a new thread
-    // in the thread pool for other workers. Must check the return value to
-    // make sure we don't decrement when we failed.
-    PRBool extraThreadAllowed =
-      NS_SUCCEEDED(gDOMThreadService->ChangeThreadPoolMaxThreads(1));
-
-    // Flush JIT caches now before suspending to avoid holding memory that we
-    // are not going to use.
-    JS_FlushCaches(aCx);
-
-    for (;;) {
-      ReentrantMonitorAutoEnter mon(worker->Pool()->GetReentrantMonitor());
-
-      // There's a small chance that the worker was canceled after our check
-      // above in which case we shouldn't wait here. We're guaranteed not to
-      // race here because the pool reenters its monitor after canceling each
-      // worker in order to notify its condition variable.
-      canceled = worker->IsCanceled();
-      if (!canceled && worker->IsSuspended()) {
-        mon.Wait();
-      }
-      else {
-        break;
-      }
-    }
-
-    if (extraThreadAllowed) {
-      gDOMThreadService->ChangeThreadPoolMaxThreads(-1);
-    }
-  }
-
-  if (canceled) {
-    LOG(("Forcefully killing JS for worker [0x%p]",
-         static_cast<void*>(worker)));
-    // Kill execution of the currently running JS.
-    JS_ClearPendingException(aCx);
-    return JS_FALSE;
-  }
-  return JS_TRUE;
-}
-
-void
-DOMWorkerErrorReporter(JSContext* aCx,
-                       const char* aMessage,
-                       JSErrorReport* aReport)
-{
-  NS_ASSERTION(!NS_IsMainThread(), "Huh?!");
-
-  nsDOMWorker* worker = (nsDOMWorker*)JS_GetContextPrivate(aCx);
-
-  if (worker->IsCanceled()) {
-    // We don't want to report errors from canceled workers. It's very likely
-    // that we only returned an error in the first place because the worker was
-    // already canceled.
-    return;
-  }
-
-  if (worker->mErrorHandlerRecursionCount == 2) {
-    // We've somehow ended up in a recursive onerror loop. Bail out.
-    return;
-  }
-
-  nsresult rv;
-  nsCOMPtr<nsIScriptError> scriptError;
-
-  {
-    // CreateInstance will lock, make sure we suspend our request!
-    JSAutoSuspendRequest ar(aCx);
-
-    scriptError = do_CreateInstance(NS_SCRIPTERROR_CONTRACTID, &rv);
-  }
-
-  if (NS_FAILED(rv)) {
-    return;
-  }
-
-  nsCOMPtr<nsIScriptError2> scriptError2(do_QueryInterface(scriptError));
-
-  nsAutoString message, filename, line;
-  PRUint32 lineNumber, columnNumber, flags, errorNumber;
-
-  if (aReport) {
-    if (aReport->ucmessage) {
-      message.Assign(reinterpret_cast<const PRUnichar*>(aReport->ucmessage));
-    }
-    filename.AssignWithConversion(aReport->filename);
-    line.Assign(reinterpret_cast<const PRUnichar*>(aReport->uclinebuf));
-    lineNumber = aReport->lineno;
-    columnNumber = aReport->uctokenptr - aReport->uclinebuf;
-    flags = aReport->flags;
-    errorNumber = aReport->errorNumber;
-  }
-  else {
-    lineNumber = columnNumber = errorNumber = 0;
-    flags = nsIScriptError::errorFlag | nsIScriptError::exceptionFlag;
-  }
-
-  if (message.IsEmpty()) {
-    message.AssignWithConversion(aMessage);
-  }
-
-  rv = scriptError2->InitWithWindowID(message.get(), filename.get(), line.get(),
-                                      lineNumber, columnNumber, flags,
-                                      "DOM Worker javascript",
-                                      worker->Pool()->WindowID());
-
-  if (NS_FAILED(rv)) {
-    return;
-  }
-
-  // Don't call the error handler if we're out of stack space.
-  if (errorNumber != JSMSG_OVER_RECURSED) {
-    // Try the onerror handler for the worker's scope.
-    nsRefPtr<nsDOMWorkerScope> scope = worker->GetInnerScope();
-    NS_ASSERTION(scope, "Null scope!");
-
-    PRBool hasListeners = scope->HasListeners(NS_LITERAL_STRING("error"));
-    if (hasListeners) {
-      nsRefPtr<nsDOMWorkerErrorEvent> event(new nsDOMWorkerErrorEvent());
-      if (event) {
-        rv = event->InitErrorEvent(NS_LITERAL_STRING("error"), PR_FALSE,
-                                   PR_TRUE, nsDependentString(message),
-                                   filename, lineNumber);
-        if (NS_SUCCEEDED(rv)) {
-          event->SetTarget(scope);
-
-          NS_ASSERTION(worker->mErrorHandlerRecursionCount >= 0,
-                       "Bad recursion count logic!");
-          worker->mErrorHandlerRecursionCount++;
-
-          PRBool preventDefaultCalled = PR_FALSE;
-          scope->DispatchEvent(static_cast<nsDOMWorkerEvent*>(event),
-                               &preventDefaultCalled);
-
-          worker->mErrorHandlerRecursionCount--;
-
-          if (preventDefaultCalled) {
-            return;
-          }
-        }
-      }
-    }
-  }
-
-  // Still unhandled, fire at the onerror handler on the worker.
-  nsCOMPtr<nsIRunnable> runnable =
-    new nsReportErrorRunnable(worker, scriptError);
-  NS_ENSURE_TRUE(runnable,);
-
-  nsRefPtr<nsDOMWorker> parent = worker->GetParent();
-
-  // If this worker has a parent then we need to send the message through the
-  // thread service to be run on the parent's thread. Otherwise it is a
-  // top-level worker and we send the message to the main thread.
-  rv = parent ? nsDOMThreadService::get()->Dispatch(parent, runnable)
-              : NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL);
-  if (NS_FAILED(rv)) {
-    return;
-  }
-}
-
-/*******************************************************************************
- * nsDOMThreadService
- */
-
-nsDOMThreadService::nsDOMThreadService()
-: mReentrantMonitor("nsDOMThreadServer.mReentrantMonitor"),
-  mNavigatorStringsLoaded(PR_FALSE)
-{
-  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-#ifdef PR_LOGGING
-  if (!gDOMThreadsLog) {
-    gDOMThreadsLog = PR_NewLogModule("nsDOMThreads");
-  }
-#endif
-  LOG(("Initializing DOM Thread service"));
-}
-
-nsDOMThreadService::~nsDOMThreadService()
-{
-  LOG(("DOM Thread service destroyed"));
-
-  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-
-  Cleanup();
-}
-
-NS_IMPL_THREADSAFE_ISUPPORTS3(nsDOMThreadService, nsIEventTarget,
-                                                  nsIObserver,
-                                                  nsIThreadPoolListener)
-
-nsresult
-nsDOMThreadService::Init()
-{
-  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-  NS_ASSERTION(!gDOMThreadService, "Only one instance should ever be created!");
-
-  nsresult rv;
-  nsCOMPtr<nsIObserverService> obs =
-    do_GetService(NS_OBSERVERSERVICE_CONTRACTID, &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = obs->AddObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID, PR_FALSE);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  obs.forget(&gObserverService);
-
-  RegisterPrefCallbacks();
-
-  mThreadPool = do_CreateInstance(NS_THREADPOOL_CONTRACTID, &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = mThreadPool->SetListener(this);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = mThreadPool->SetThreadLimit(THREADPOOL_MAX_THREADS);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = mThreadPool->SetIdleThreadLimit(THREADPOOL_IDLE_THREADS);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  PRBool success = mWorkersInProgress.Init();
-  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
-
-  success = mPools.Init();
-  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
-
-  success = mThreadsafeContractIDs.Init();
-  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
-
-  success = mJSContexts.SetCapacity(THREADPOOL_THREAD_CAP);
-  NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
-
-  nsCOMPtr<nsIJSRuntimeService>
-    runtimeSvc(do_GetService("@mozilla.org/js/xpc/RuntimeService;1"));
-  NS_ENSURE_TRUE(runtimeSvc, NS_ERROR_FAILURE);
-  runtimeSvc.forget(&gJSRuntimeService);
-
-  nsCOMPtr<nsIThreadJSContextStack>
-    contextStack(do_GetService("@mozilla.org/js/xpc/ContextStack;1"));
-  NS_ENSURE_TRUE(contextStack, NS_ERROR_FAILURE);
-  contextStack.forget(&gThreadJSContextStack);
-
-  nsCOMPtr<nsIXPCSecurityManager> secMan(new nsDOMWorkerSecurityManager());
-  NS_ENSURE_TRUE(secMan, NS_ERROR_OUT_OF_MEMORY);
-  secMan.forget(&gWorkerSecurityManager);
-
-  if (gJSContextIndex == BAD_TLS_INDEX &&
-      PR_NewThreadPrivateIndex(&gJSContextIndex, NULL) != PR_SUCCESS) {
-    NS_ERROR("PR_NewThreadPrivateIndex failed!");
-    gJSContextIndex = BAD_TLS_INDEX;
-    return NS_ERROR_FAILURE;
-  }
-
-  return NS_OK;
-}
-
-/* static */
-already_AddRefed<nsDOMThreadService>
-nsDOMThreadService::GetOrInitService()
-{
-  if (!gDOMThreadService) {
-    nsRefPtr<nsDOMThreadService> service = new nsDOMThreadService();
-    NS_ENSURE_TRUE(service, nsnull);
-
-    nsresult rv = service->Init();
-    NS_ENSURE_SUCCESS(rv, nsnull);
-
-    service.swap(gDOMThreadService);
-  }
-
-  nsRefPtr<nsDOMThreadService> service(gDOMThreadService);
-  return service.forget();
-}
-
-/* static */
-nsDOMThreadService*
-nsDOMThreadService::get()
-{
-  return gDOMThreadService;
-}
-
-/* static */
-JSContext*
-nsDOMThreadService::GetCurrentContext()
-{
-  JSContext* cx;
-
-  if (NS_IsMainThread()) {
-    nsresult rv = ThreadJSContextStack()->GetSafeJSContext(&cx);
-    NS_ENSURE_SUCCESS(rv, nsnull);
-  }
-  else {
-    NS_ENSURE_TRUE(gJSContextIndex, nsnull);
-    cx = static_cast<JSContext*>(PR_GetThreadPrivate(gJSContextIndex));
-  }
-
-  return cx;
-}
-
-/* static */
-void
-nsDOMThreadService::Shutdown()
-{
-  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-  NS_IF_RELEASE(gDOMThreadService);
-}
-
-void
-nsDOMThreadService::Cleanup()
-{
-  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-
-  // This will either be called at 'xpcom-shutdown' or earlier if the call to
-  // Init fails somehow. We can therefore assume that all services will still
-  // be available here.
-
-  // Cancel all workers that weren't tied to a window.
-  CancelWorkersForGlobal(nsnull);
-
-  {
-    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-
-    NS_ASSERTION(!mPools.Count(), "Live workers left!");
-    mPools.Clear();
-
-    NS_ASSERTION(!mSuspendedWorkers.Length(), "Suspended workers left!");
-    mSuspendedWorkers.Clear();
-  }
-
-  if (gObserverService) {
-    gObserverService->RemoveObserver(this, NS_XPCOM_SHUTDOWN_OBSERVER_ID);
-    NS_RELEASE(gObserverService);
-
-    UnregisterPrefCallbacks();
-  }
-
-  // The thread pool holds a circular reference to this service through its
-  // listener. We must shut down the thread pool manually to break this cycle.
-  if (mThreadPool) {
-    mThreadPool->Shutdown();
-    mThreadPool = nsnull;
-  }
-
-  // Need to force a GC so that all of our workers get cleaned up.
-  if (gThreadJSContextStack) {
-    JSContext* safeContext;
-    if (NS_SUCCEEDED(gThreadJSContextStack->GetSafeJSContext(&safeContext))) {
-      JS_GC(safeContext);
-    }
-    NS_RELEASE(gThreadJSContextStack);
-  }
-
-  // These must be released after the thread pool is shut down.
-  NS_IF_RELEASE(gJSRuntimeService);
-  NS_IF_RELEASE(gWorkerSecurityManager);
-}
-
-nsresult
-nsDOMThreadService::Dispatch(nsDOMWorker* aWorker,
-                             nsIRunnable* aRunnable,
-                             PRIntervalTime aTimeoutInterval,
-                             PRBool aClearQueue)
-{
-  NS_ASSERTION(aWorker, "Null pointer!");
-  NS_ASSERTION(aRunnable, "Null pointer!");
-
-  if (!mThreadPool) {
-    // This can happen from a nsDOMWorker::Finalize call after the thread pool
-    // has been shutdown. It should never be possible off the main thread.
-    NS_ASSERTION(NS_IsMainThread(),
-                 "This should be impossible on a non-main thread!");
-    return NS_ERROR_ILLEGAL_DURING_SHUTDOWN;
-  }
-
-  // Don't accept the runnable if the worker's close handler has been triggered
-  // (unless, of course, this is the close runnable as indicated by the non-0
-  // timeout value).
-  if (aWorker->IsClosing() && !aTimeoutInterval) {
-    LOG(("Will not dispatch runnable [0x%p] for closing worker [0x%p]",
-         static_cast<void*>(aRunnable), static_cast<void*>(aWorker)));
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  nsRefPtr<nsDOMWorkerRunnable> workerRunnable;
-  {
-    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-
-    if (mWorkersInProgress.Get(aWorker, getter_AddRefs(workerRunnable))) {
-      workerRunnable->PutRunnable(aRunnable, aTimeoutInterval, aClearQueue);
-      return NS_OK;
-    }
-
-    workerRunnable = new nsDOMWorkerRunnable(aWorker);
-    NS_ENSURE_TRUE(workerRunnable, NS_ERROR_OUT_OF_MEMORY);
-
-    workerRunnable->PutRunnable(aRunnable, aTimeoutInterval, PR_FALSE);
-
-    PRBool success = mWorkersInProgress.Put(aWorker, workerRunnable);
-    NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
-  }
-
-  nsresult rv = mThreadPool->Dispatch(workerRunnable, NS_DISPATCH_NORMAL);
-
-  // XXX This is a mess and it could probably be removed once we have an
-  // infallible malloc implementation.
-  if (NS_FAILED(rv)) {
-    NS_WARNING("Failed to dispatch runnable to thread pool!");
-
-    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-
-    // We exited the monitor after inserting the runnable into the table so make
-    // sure we're removing the right one!
-    nsRefPtr<nsDOMWorkerRunnable> tableRunnable;
-    if (mWorkersInProgress.Get(aWorker, getter_AddRefs(tableRunnable)) &&
-        workerRunnable == tableRunnable) {
-      mWorkersInProgress.Remove(aWorker);
-
-      // And don't forget to tell anyone who's waiting.
-      mon.NotifyAll();
-    }
-
-    return rv;
-  }
-
-  return NS_OK;
-}
-
-void
-nsDOMThreadService::SetWorkerTimeout(nsDOMWorker* aWorker,
-                                     PRIntervalTime aTimeoutInterval)
-{
-  NS_ASSERTION(aWorker, "Null pointer!");
-  NS_ASSERTION(aTimeoutInterval, "No timeout specified!");
-
-  NS_ASSERTION(mThreadPool, "Dispatch called after 'xpcom-shutdown'!");
-
-  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-
-  nsRefPtr<nsDOMWorkerRunnable> workerRunnable;
-  if (mWorkersInProgress.Get(aWorker, getter_AddRefs(workerRunnable))) {
-    workerRunnable->SetCloseRunnableTimeout(aTimeoutInterval);
-  }
-}
-
-void
-nsDOMThreadService::WorkerComplete(nsDOMWorkerRunnable* aRunnable)
-{
-  mReentrantMonitor.AssertCurrentThreadIn();
-
-#ifdef DEBUG
-  nsRefPtr<nsDOMWorker>& debugWorker = aRunnable->mWorker;
-
-  nsRefPtr<nsDOMWorkerRunnable> runnable;
-  NS_ASSERTION(mWorkersInProgress.Get(debugWorker, getter_AddRefs(runnable)) &&
-               runnable == aRunnable,
-               "Removing a worker that isn't in our hashtable?!");
-#endif
-
-  mWorkersInProgress.Remove(aRunnable->mWorker);
-}
-
-PRBool
-nsDOMThreadService::QueueSuspendedWorker(nsDOMWorkerRunnable* aRunnable)
-{
-  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-
-#ifdef DEBUG
-    {
-      // Make sure that the runnable is in mWorkersInProgress.
-      nsRefPtr<nsDOMWorkerRunnable> current;
-      mWorkersInProgress.Get(aRunnable->mWorker, getter_AddRefs(current));
-      NS_ASSERTION(current == aRunnable, "Something crazy wrong here!");
-    }
-#endif
-
-  return mSuspendedWorkers.AppendElement(aRunnable) ? PR_TRUE : PR_FALSE;
-}
-
-/* static */
-JSContext*
-nsDOMThreadService::CreateJSContext()
-{
-  JSRuntime* rt;
-  gJSRuntimeService->GetRuntime(&rt);
-  NS_ENSURE_TRUE(rt, nsnull);
-
-  JSAutoContextDestroyer cx(JS_NewContext(rt, 8192));
-  NS_ENSURE_TRUE(cx, nsnull);
-
-  JS_SetErrorReporter(cx, DOMWorkerErrorReporter);
-
-  JS_SetOperationCallback(cx, DOMWorkerOperationCallback);
-
-  static JSSecurityCallbacks securityCallbacks = {
-    nsDOMWorkerSecurityManager::JSCheckAccess,
-    nsDOMWorkerSecurityManager::JSTranscodePrincipals,
-    nsDOMWorkerSecurityManager::JSFindPrincipal
-  };
-  JS_SetContextSecurityCallbacks(cx, &securityCallbacks);
-
-  JS_ClearContextDebugHooks(cx);
-
-  nsresult rv = nsContentUtils::XPConnect()->
-    SetSecurityManagerForJSContext(cx, gWorkerSecurityManager, 0);
-  NS_ENSURE_SUCCESS(rv, nsnull);
-
-  JS_SetNativeStackQuota(cx, 256*1024);
-
-  JS_SetOptions(cx,
-    JS_GetOptions(cx) | JSOPTION_METHODJIT | JSOPTION_JIT | JSOPTION_PROFILING);
-  JS_SetGCParameterForThread(cx, JSGC_MAX_CODE_CACHE_BYTES, 1 * 1024 * 1024);
-
-  return cx.forget();
-}
-
-already_AddRefed<nsDOMWorkerPool>
-nsDOMThreadService::GetPoolForGlobal(nsIScriptGlobalObject* aGlobalObject,
-                                     PRBool aRemove)
-{
-  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-
-  nsRefPtr<nsDOMWorkerPool> pool;
-  mPools.Get(aGlobalObject, getter_AddRefs(pool));
-
-  if (aRemove) {
-    mPools.Remove(aGlobalObject);
-  }
-
-  return pool.forget();
-}
-
-void
-nsDOMThreadService::TriggerOperationCallbackForPool(nsDOMWorkerPool* aPool)
-{
-  mReentrantMonitor.AssertCurrentThreadIn();
-
-  // See if we need to trigger the operation callback on any currently running
-  // contexts.
-  PRUint32 contextCount = mJSContexts.Length();
-  for (PRUint32 index = 0; index < contextCount; index++) {
-    JSContext*& cx = mJSContexts[index];
-    nsDOMWorker* worker = (nsDOMWorker*)JS_GetContextPrivate(cx);
-    if (worker && worker->Pool() == aPool) {
-      JS_TriggerOperationCallback(cx);
-    }
-  }
-}
-
-void
-nsDOMThreadService::RescheduleSuspendedWorkerForPool(nsDOMWorkerPool* aPool)
-{
-  mReentrantMonitor.AssertCurrentThreadIn();
-
-  PRUint32 count = mSuspendedWorkers.Length();
-  if (!count) {
-    // Nothing to do here.
-    return;
-  }
-
-  nsTArray<nsDOMWorkerRunnable*> others(count);
-
-  for (PRUint32 index = 0; index < count; index++) {
-    nsDOMWorkerRunnable* runnable = mSuspendedWorkers[index];
-
-#ifdef DEBUG
-    {
-      // Make sure that the runnable never left mWorkersInProgress.
-      nsRefPtr<nsDOMWorkerRunnable> current;
-      mWorkersInProgress.Get(runnable->mWorker, getter_AddRefs(current));
-      NS_ASSERTION(current == runnable, "Something crazy wrong here!");
-    }
-#endif
-
-    if (runnable->mWorker->Pool() == aPool) {
-#ifdef DEBUG
-      nsresult rv =
-#endif
-      mThreadPool->Dispatch(runnable, NS_DISPATCH_NORMAL);
-      NS_ASSERTION(NS_SUCCEEDED(rv), "This shouldn't ever fail!");
-    }
-    else {
-      others.AppendElement(runnable);
-    }
-  }
-
-  mSuspendedWorkers.SwapElements(others);
-}
-
-void
-nsDOMThreadService::CancelWorkersForGlobal(nsIScriptGlobalObject* aGlobalObject)
-{
-  nsRefPtr<nsDOMWorkerPool> pool = GetPoolForGlobal(aGlobalObject, PR_TRUE);
-  if (pool) {
-    pool->Cancel();
-
-    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-
-    TriggerOperationCallbackForPool(pool);
-    RescheduleSuspendedWorkerForPool(pool);
-  }
-}
-
-void
-nsDOMThreadService::SuspendWorkersForGlobal(nsIScriptGlobalObject* aGlobalObject)
-{
-  NS_ASSERTION(aGlobalObject, "Null pointer!");
-
-  nsRefPtr<nsDOMWorkerPool> pool = GetPoolForGlobal(aGlobalObject, PR_FALSE);
-  if (pool) {
-    pool->Suspend();
-
-    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-    TriggerOperationCallbackForPool(pool);
-  }
-}
-
-void
-nsDOMThreadService::ResumeWorkersForGlobal(nsIScriptGlobalObject* aGlobalObject)
-{
-  NS_ASSERTION(aGlobalObject, "Null pointer!");
-
-  nsRefPtr<nsDOMWorkerPool> pool = GetPoolForGlobal(aGlobalObject, PR_FALSE);
-  if (pool) {
-    pool->Resume();
-
-    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-
-    TriggerOperationCallbackForPool(pool);
-    RescheduleSuspendedWorkerForPool(pool);
-  }
-}
-
-void
-nsDOMThreadService::NoteEmptyPool(nsDOMWorkerPool* aPool)
-{
-  NS_ASSERTION(aPool, "Null pointer!");
-
-  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-  mPools.Remove(aPool->ScriptGlobalObject());
-}
-
-void
-nsDOMThreadService::TimeoutReady(nsDOMWorkerTimeout* aTimeout)
-{
-  nsRefPtr<nsDOMWorkerTimeoutRunnable> runnable =
-    new nsDOMWorkerTimeoutRunnable(aTimeout);
-  NS_ENSURE_TRUE(runnable,);
-
-  Dispatch(aTimeout->GetWorker(), runnable);
-}
-
-nsresult
-nsDOMThreadService::ChangeThreadPoolMaxThreads(PRInt16 aDelta)
-{
-  NS_ENSURE_ARG(aDelta == 1 || aDelta == -1);
-
-  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-
-  PRUint32 currentThreadCount;
-  nsresult rv = mThreadPool->GetThreadLimit(&currentThreadCount);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  PRInt32 newThreadCount = (PRInt32)currentThreadCount + (PRInt32)aDelta;
-  NS_ASSERTION(newThreadCount >= THREADPOOL_MAX_THREADS,
-               "Can't go below initial thread count!");
-
-  if (newThreadCount > THREADPOOL_THREAD_CAP) {
-    NS_WARNING("Thread pool cap reached!");
-    return NS_ERROR_FAILURE;
-  }
-
-  rv = mThreadPool->SetThreadLimit((PRUint32)newThreadCount);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  // If we're allowing an extra thread then post a dummy event to the thread
-  // pool so that any pending workers can get started. The thread pool doesn't
-  // do this on its own like it probably should...
-  if (aDelta == 1) {
-    nsCOMPtr<nsIRunnable> dummy(new nsRunnable());
-    if (dummy) {
-      rv = mThreadPool->Dispatch(dummy, NS_DISPATCH_NORMAL);
-      NS_ENSURE_SUCCESS(rv, rv);
-    }
-  }
-
-  return NS_OK;
-}
-
-void
-nsDOMThreadService::NoteThreadsafeContractId(const nsACString& aContractId,
-                                             PRBool aIsThreadsafe)
-{
-  NS_ASSERTION(!aContractId.IsEmpty(), "Empty contract id!");
-
-  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-
-#ifdef DEBUG
-  {
-    PRBool isThreadsafe;
-    if (mThreadsafeContractIDs.Get(aContractId, &isThreadsafe)) {
-      NS_ASSERTION(aIsThreadsafe == isThreadsafe, "Inconsistent threadsafety!");
-    }
-  }
-#endif
-
-  if (!mThreadsafeContractIDs.Put(aContractId, aIsThreadsafe)) {
-    NS_WARNING("Out of memory!");
-  }
-}
-
-ThreadsafeStatus
-nsDOMThreadService::GetContractIdThreadsafeStatus(const nsACString& aContractId)
-{
-  NS_ASSERTION(!aContractId.IsEmpty(), "Empty contract id!");
-
-  ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-
-  PRBool isThreadsafe;
-  if (mThreadsafeContractIDs.Get(aContractId, &isThreadsafe)) {
-    return isThreadsafe ? Threadsafe : NotThreadsafe;
-  }
-
-  return Unknown;
-}
-
-// static
-nsIJSRuntimeService*
-nsDOMThreadService::JSRuntimeService()
-{
-  return gJSRuntimeService;
-}
-
-// static
-nsIThreadJSContextStack*
-nsDOMThreadService::ThreadJSContextStack()
-{
-  return gThreadJSContextStack;
-}
-
-// static
-nsIXPCSecurityManager*
-nsDOMThreadService::WorkerSecurityManager()
-{
-  return gWorkerSecurityManager;
-}
-
-/**
- * See nsIEventTarget
- */
-NS_IMETHODIMP
-nsDOMThreadService::Dispatch(nsIRunnable* aEvent,
-                             PRUint32 aFlags)
-{
-  NS_ENSURE_ARG_POINTER(aEvent);
-  NS_ENSURE_FALSE(aFlags & NS_DISPATCH_SYNC, NS_ERROR_NOT_IMPLEMENTED);
-
-  // This should only ever be called by the timer code! We run the event right
-  // now, but all that does is queue the real event for the proper worker.
-  aEvent->Run();
-
-  return NS_OK;
-}
-
-/**
- * See nsIEventTarget
- */
-NS_IMETHODIMP
-nsDOMThreadService::IsOnCurrentThread(PRBool* _retval)
-{
-  NS_NOTREACHED("No one should call this!");
-  return NS_ERROR_NOT_IMPLEMENTED;
-}
-
-/**
- * See nsIObserver
- */
-NS_IMETHODIMP
-nsDOMThreadService::Observe(nsISupports* aSubject,
-                            const char* aTopic,
-                            const PRUnichar* aData)
-{
-  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-
-  if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
-    Cleanup();
-    return NS_OK;
-  }
-
-  NS_NOTREACHED("Unknown observer topic!");
-  return NS_OK;
-}
-
-/**
- * See nsIThreadPoolListener
- */
-NS_IMETHODIMP
-nsDOMThreadService::OnThreadCreated()
-{
-  LOG(("Thread created"));
-
-  nsIThread* current = NS_GetCurrentThread();
-
-  // We want our worker threads to always have a lower priority than the main
-  // thread. NSPR docs say that this isn't incredibly reliable across all
-  // platforms but we hope for the best.
-  nsCOMPtr<nsISupportsPriority> priority(do_QueryInterface(current));
-  NS_ENSURE_TRUE(priority, NS_ERROR_FAILURE);
-
-  nsresult rv = priority->SetPriority(nsISupportsPriority::PRIORITY_LOWEST);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  NS_ASSERTION(gJSContextIndex != BAD_TLS_INDEX, "No context index!");
-
-  // Set the context up for the worker.
-  JSContext* cx = (JSContext*)PR_GetThreadPrivate(gJSContextIndex);
-  if (!cx) {
-    cx = nsDOMThreadService::CreateJSContext();
-    NS_ENSURE_TRUE(cx, NS_ERROR_FAILURE);
-
-    PRStatus status = PR_SetThreadPrivate(gJSContextIndex, cx);
-    if (status != PR_SUCCESS) {
-      NS_WARNING("Failed to set context on thread!");
-      nsContentUtils::XPConnect()->ReleaseJSContext(cx, PR_TRUE);
-      return NS_ERROR_FAILURE;
-    }
-
-    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-
-#ifdef DEBUG
-    JSContext** newContext =
-#endif
-    mJSContexts.AppendElement(cx);
-
-    // We ensure the capacity of this array in Init.
-    NS_ASSERTION(newContext, "Should never fail!");
-  }
-
-  // Make sure that XPConnect knows about this context.
-  gThreadJSContextStack->Push(cx);
-  gThreadJSContextStack->SetSafeJSContext(cx);
-
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsDOMThreadService::OnThreadShuttingDown()
-{
-  LOG(("Thread shutting down"));
-
-  NS_ASSERTION(gJSContextIndex != BAD_TLS_INDEX, "No context index!");
-
-  JSContext* cx = (JSContext*)PR_GetThreadPrivate(gJSContextIndex);
-  NS_WARN_IF_FALSE(cx, "Thread died with no context?");
-  if (cx) {
-    {
-      ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-      mJSContexts.RemoveElement(cx);
-    }
-
-    JSContext* pushedCx;
-    gThreadJSContextStack->Pop(&pushedCx);
-    NS_ASSERTION(pushedCx == cx, "Popped the wrong context!");
-
-    gThreadJSContextStack->SetSafeJSContext(nsnull);
-
-    // The cycle collector may be running on the main thread. If so we cannot
-    // simply destroy this context. Instead we proxy the context destruction to
-    // the main thread. If that fails somehow then we simply leak the context.
-    nsCOMPtr<nsIRunnable> runnable = new nsDestroyJSContextRunnable(cx);
-
-    if (NS_FAILED(NS_DispatchToMainThread(runnable, NS_DISPATCH_NORMAL))) {
-      NS_WARNING("Failed to dispatch release runnable!");
-    }
-  }
-
-  return NS_OK;
-}
-
-nsresult
-nsDOMThreadService::RegisterWorker(nsDOMWorker* aWorker,
-                                   nsIScriptGlobalObject* aGlobalObject)
-{
-  NS_ASSERTION(aWorker, "Null pointer!");
-
-  if (aGlobalObject && NS_IsMainThread()) {
-    nsCOMPtr<nsPIDOMWindow> domWindow(do_QueryInterface(aGlobalObject));
-    NS_ENSURE_TRUE(domWindow, NS_ERROR_NO_INTERFACE);
-
-    nsPIDOMWindow* innerWindow = domWindow->IsOuterWindow() ?
-                                 domWindow->GetCurrentInnerWindow() :
-                                 domWindow.get();
-    NS_ENSURE_STATE(innerWindow);
-
-    nsCOMPtr<nsIScriptGlobalObject> newGlobal(do_QueryInterface(innerWindow));
-    NS_ENSURE_TRUE(newGlobal, NS_ERROR_NO_INTERFACE);
-
-    aGlobalObject = newGlobal;
-  }
-
-  nsRefPtr<nsDOMWorkerPool> pool;
-  {
-    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-
-    if (!mThreadPool) {
-      // Shutting down!
-      return NS_ERROR_ILLEGAL_DURING_SHUTDOWN;
-    }
-
-    mPools.Get(aGlobalObject, getter_AddRefs(pool));
-  }
-
-  nsresult rv;
-
-  if (!pool) {
-    NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-
-    if (!mNavigatorStringsLoaded) {
-      rv = NS_GetNavigatorAppName(mAppName);
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      rv = NS_GetNavigatorAppVersion(mAppVersion);
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      rv = NS_GetNavigatorPlatform(mPlatform);
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      rv = NS_GetNavigatorUserAgent(mUserAgent);
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      mNavigatorStringsLoaded = PR_TRUE;
-    }
-
-    nsCOMPtr<nsIDocument> document;
-    if (aGlobalObject) {
-      nsCOMPtr<nsPIDOMWindow> domWindow(do_QueryInterface(aGlobalObject));
-      NS_ENSURE_TRUE(domWindow, NS_ERROR_NO_INTERFACE);
-
-      nsIDOMDocument* domDocument = domWindow->GetExtantDocument();
-      NS_ENSURE_STATE(domDocument);
-
-      document = do_QueryInterface(domDocument);
-      NS_ENSURE_STATE(document);
-    }
-
-    pool = new nsDOMWorkerPool(aGlobalObject, document);
-    NS_ENSURE_TRUE(pool, NS_ERROR_OUT_OF_MEMORY);
-
-    rv = pool->Init();
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    ReentrantMonitorAutoEnter mon(mReentrantMonitor);
-
-    PRBool success = mPools.Put(aGlobalObject, pool);
-    NS_ENSURE_TRUE(success, NS_ERROR_OUT_OF_MEMORY);
-  }
-
-  rv = pool->NoteWorker(aWorker);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  aWorker->SetPool(pool);
-  return NS_OK;
-}
-
-void
-nsDOMThreadService::GetAppName(nsAString& aAppName)
-{
-  NS_ASSERTION(mNavigatorStringsLoaded,
-               "Shouldn't call this before we have loaded strings!");
-  aAppName.Assign(mAppName);
-}
-
-void
-nsDOMThreadService::GetAppVersion(nsAString& aAppVersion)
-{
-  NS_ASSERTION(mNavigatorStringsLoaded,
-               "Shouldn't call this before we have loaded strings!");
-  aAppVersion.Assign(mAppVersion);
-}
-
-void
-nsDOMThreadService::GetPlatform(nsAString& aPlatform)
-{
-  NS_ASSERTION(mNavigatorStringsLoaded,
-               "Shouldn't call this before we have loaded strings!");
-  aPlatform.Assign(mPlatform);
-}
-
-void
-nsDOMThreadService::GetUserAgent(nsAString& aUserAgent)
-{
-  NS_ASSERTION(mNavigatorStringsLoaded,
-               "Shouldn't call this before we have loaded strings!");
-  aUserAgent.Assign(mUserAgent);
-}
-
-void
-nsDOMThreadService::RegisterPrefCallbacks()
-{
-  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-  for (PRUint32 index = 0; index < NS_ARRAY_LENGTH(sPrefsToWatch); index++) {
-    Preferences::RegisterCallback(PrefCallback, sPrefsToWatch[index]);
-    PrefCallback(sPrefsToWatch[index], nsnull);
-  }
-}
-
-void
-nsDOMThreadService::UnregisterPrefCallbacks()
-{
-  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-  for (PRUint32 index = 0; index < NS_ARRAY_LENGTH(sPrefsToWatch); index++) {
-    Preferences::UnregisterCallback(PrefCallback, sPrefsToWatch[index]);
-  }
-}
-
-// static
-int
-nsDOMThreadService::PrefCallback(const char* aPrefName,
-                                 void* aClosure)
-{
-  NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-  if(!strcmp(aPrefName, "dom.max_script_run_time")) {
-    // We assume atomic 32bit reads/writes. If this assumption doesn't hold on
-    // some wacky platform then the worst that could happen is that the close
-    // handler will run for a slightly different amount of time.
-    PRUint32 timeoutMS =
-      Preferences::GetUint(aPrefName, gWorkerCloseHandlerTimeoutMS);
-
-    // We must have a timeout value, 0 is not ok. If the pref is set to 0 then
-    // fall back to our default.
-    if (timeoutMS) {
-      gWorkerCloseHandlerTimeoutMS = timeoutMS;
-    }
-  }
-  return 0;
-}
-
-// static
-PRUint32
-nsDOMThreadService::GetWorkerCloseHandlerTimeoutMS()
-{
-  return gWorkerCloseHandlerTimeoutMS;
-}
deleted file mode 100644
--- a/dom/src/threads/nsDOMThreadService.h
+++ /dev/null
@@ -1,212 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* ***** 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 worker threads.
- *
- * The Initial Developer of the Original Code is
- *   Mozilla Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2008
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Vladimir Vukicevic <vladimir@pobox.com> (Original Author)
- *   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 __NSDOMTHREADSERVICE_H__
-#define __NSDOMTHREADSERVICE_H__
-
-// Interfaces
-#include "nsIEventTarget.h"
-#include "nsIObserver.h"
-#include "nsIThreadPool.h"
-
-// Other includes
-#include "jsapi.h"
-#include "mozilla/ReentrantMonitor.h"
-#include "nsAutoPtr.h"
-#include "nsCOMPtr.h"
-#include "nsDataHashtable.h"
-#include "nsRefPtrHashtable.h"
-#include "nsStringGlue.h"
-#include "nsTPtrArray.h"
-
-#include "prlog.h"
-#ifdef PR_LOGGING
-extern PRLogModuleInfo* gDOMThreadsLog;
-#endif
-
-class nsDOMWorker;
-class nsDOMWorkerPool;
-class nsDOMWorkerRunnable;
-class nsDOMWorkerTimeout;
-class nsIJSRuntimeService;
-class nsIScriptGlobalObject;
-class nsIThreadJSContextStack;
-class nsIXPConnect;
-class nsIXPCSecurityManager;
-
-enum ThreadsafeStatus
-{
-  Threadsafe,
-  NotThreadsafe,
-  Unknown
-};
-
-class nsDOMThreadService : public nsIEventTarget,
-                           public nsIObserver,
-                           public nsIThreadPoolListener
-{
-  friend class nsDOMWorker;
-  friend class nsDOMWorkerNavigator;
-  friend class nsDOMWorkerPool;
-  friend class nsDOMWorkerRunnable;
-  friend class nsDOMWorkerThread;
-  friend class nsDOMWorkerTimeout;
-  friend class nsDOMWorkerXHR;
-  friend class nsDOMWorkerXHRProxy;
-  friend class nsLayoutStatics;
-  friend class nsReportErrorRunnable;
-
-  friend void DOMWorkerErrorReporter(JSContext* aCx,
-                                     const char* aMessage,
-                                     JSErrorReport* aReport);
-
-public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSIEVENTTARGET
-  NS_DECL_NSIOBSERVER
-  NS_DECL_NSITHREADPOOLLISTENER
-
-  // Any DOM consumers that need access to this service should use this method.
-  static already_AddRefed<nsDOMThreadService> GetOrInitService();
-
-  // Simple getter for this service. This does not create the service if it
-  // hasn't been created already, and it never AddRef's!
-  static nsDOMThreadService* get();
-
-  static JSContext* GetCurrentContext();
-
-  // Easy access to the services we care about.
-  static nsIJSRuntimeService* JSRuntimeService();
-  static nsIThreadJSContextStack* ThreadJSContextStack();
-  static nsIXPCSecurityManager* WorkerSecurityManager();
-
-  void CancelWorkersForGlobal(nsIScriptGlobalObject* aGlobalObject);
-  void SuspendWorkersForGlobal(nsIScriptGlobalObject* aGlobalObject);
-  void ResumeWorkersForGlobal(nsIScriptGlobalObject* aGlobalObject);
-
-  nsresult ChangeThreadPoolMaxThreads(PRInt16 aDelta);
-
-  void NoteThreadsafeContractId(const nsACString& aContractId,
-                                PRBool aIsThreadsafe);
-
-  ThreadsafeStatus GetContractIdThreadsafeStatus(const nsACString& aContractId);
-
-private:
-  nsDOMThreadService();
-  ~nsDOMThreadService();
-
-  nsresult Init();
-  void Cleanup();
-
-  static void Shutdown();
-
-  nsresult Dispatch(nsDOMWorker* aWorker,
-                    nsIRunnable* aRunnable,
-                    PRIntervalTime aTimeoutInterval = 0,
-                    PRBool aClearQueue = PR_FALSE);
-
-  void SetWorkerTimeout(nsDOMWorker* aWorker,
-                        PRIntervalTime aTimeoutInterval);
-
-  void WorkerComplete(nsDOMWorkerRunnable* aRunnable);
-
-  static JSContext* CreateJSContext();
-
-  already_AddRefed<nsDOMWorkerPool>
-    GetPoolForGlobal(nsIScriptGlobalObject* aGlobalObject,
-                     PRBool aRemove);
-
-  void TriggerOperationCallbackForPool(nsDOMWorkerPool* aPool);
-  void RescheduleSuspendedWorkerForPool(nsDOMWorkerPool* aPool);
-
-  void NoteEmptyPool(nsDOMWorkerPool* aPool);
-
-  void TimeoutReady(nsDOMWorkerTimeout* aTimeout);
-
-  nsresult RegisterWorker(nsDOMWorker* aWorker,
-                          nsIScriptGlobalObject* aGlobalObject);
-
-  void GetAppName(nsAString& aAppName);
-  void GetAppVersion(nsAString& aAppVersion);
-  void GetPlatform(nsAString& aPlatform);
-  void GetUserAgent(nsAString& aUserAgent);
-
-  void RegisterPrefCallbacks();
-  void UnregisterPrefCallbacks();
-
-  static int PrefCallback(const char* aPrefName,
-                          void* aClosure);
-
-  static PRUint32 GetWorkerCloseHandlerTimeoutMS();
-
-  PRBool QueueSuspendedWorker(nsDOMWorkerRunnable* aRunnable);
-
-  // Our internal thread pool.
-  nsCOMPtr<nsIThreadPool> mThreadPool;
-
-  // Maps nsIScriptGlobalObject* to nsDOMWorkerPool.
-  nsRefPtrHashtable<nsVoidPtrHashKey, nsDOMWorkerPool> mPools;
-
-  // mReentrantMonitor protects all access to mWorkersInProgress and
-  // mCreationsInProgress.
-  mozilla::ReentrantMonitor mReentrantMonitor;
-
-  // A map from nsDOMWorkerThread to nsDOMWorkerRunnable.
-  nsRefPtrHashtable<nsVoidPtrHashKey, nsDOMWorkerRunnable> mWorkersInProgress;
-
-  // A list of active JSContexts that we've created. Always protected with
-  // mReentrantMonitor.
-  nsTArray<JSContext*> mJSContexts;
-
-  // A list of worker runnables that were never started because the worker was
-  // suspended. Always protected with mReentrantMonitor.
-  nsTArray<nsDOMWorkerRunnable*> mSuspendedWorkers;
-
-  // Always protected with mReentrantMonitor.
-  nsDataHashtable<nsCStringHashKey, PRBool> mThreadsafeContractIDs;
-
-  nsString mAppName;
-  nsString mAppVersion;
-  nsString mPlatform;
-  nsString mUserAgent;
-
-  PRBool mNavigatorStringsLoaded;
-};
-
-#endif /* __NSDOMTHREADSERVICE_H__ */
deleted file mode 100644
--- a/dom/src/threads/nsDOMWorker.cpp
+++ /dev/null
@@ -1,2752 +0,0 @@
-/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
-/* ***** 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 Web Workers.
- *
- * The Initial Developer of the Original Code is
- *   Mozilla Corporation.
- * Portions created by the Initial Developer are Copyright (C) 2008
- * the Initial Developer. All Rights Reserved.
- *
- * Contributor(s):
- *   Ben Turner <bent.mozilla@gmail.com> (Original Author)
- *
- * 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 "nsDOMWorker.h"
-
-#include "nsIDOMEvent.h"
-#include "nsIEventTarget.h"
-#include "nsIJSRuntimeService.h"
-#include "nsIXPConnect.h"
-
-#include "jscntxt.h"
-#ifdef MOZ_SHARK
-#include "jsdbgapi.h"
-#endif
-#include "nsAtomicRefcnt.h"
-#include "nsAXPCNativeCallContext.h"
-#include "nsContentUtils.h"
-#include "nsDOMClassInfo.h"
-#include "nsDOMClassInfoID.h"
-#include "nsGlobalWindow.h"
-#include "nsJSON.h"
-#include "nsJSUtils.h"
-#include "nsProxyRelease.h"
-#include "nsThreadUtils.h"
-#include "nsNativeCharsetUtils.h"
-#include "xpcprivate.h"
-
-#include "nsDOMThreadService.h"
-#include "nsDOMWorkerEvents.h"
-#include "nsDOMWorkerLocation.h"
-#include "nsDOMWorkerNavigator.h"
-#include "nsDOMWorkerPool.h"
-#include "nsDOMWorkerScriptLoader.h"
-#include "nsDOMWorkerTimeout.h"
-#include "nsDOMWorkerXHR.h"
-
-using namespace mozilla;
-
-class TestComponentThreadsafetyRunnable : public nsIRunnable
-{
-public:
-  NS_DECL_ISUPPORTS
-
-  TestComponentThreadsafetyRunnable(const nsACString& aContractId,
-                                    PRBool aService)
-  : mContractId(aContractId),
-    mService(aService),
-    mIsThreadsafe(PR_FALSE)
-  { }
-
-  NS_IMETHOD Run()
-  {
-    NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
-
-    nsresult rv;
-    nsCOMPtr<nsISupports> instance;
-    if (mService) {
-      instance = do_GetService(mContractId.get(), &rv);
-    }
-    else {
-      instance = do_CreateInstance(mContractId.get(), &rv);
-    }
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    nsCOMPtr<nsIClassInfo> classInfo = do_QueryInterface(instance, &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    PRUint32 flags;
-    rv = classInfo->GetFlags(&flags);
-    NS_ENSURE_SUCCESS(rv, rv);
-
-    mIsThreadsafe = !!(flags & nsIClassInfo::THREADSAFE);
-    return NS_OK;
-  }
-
-  PRBool IsThreadsafe()
-  {
-    NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
-    return mIsThreadsafe;
-  }
-
-private:
-  nsCString mContractId;
-  PRBool mService;
-  PRBool mIsThreadsafe;
-};
-
-NS_IMPL_THREADSAFE_ISUPPORTS1(TestComponentThreadsafetyRunnable, nsIRunnable)
-
-class nsDOMWorkerFunctions
-{
-public:
-  typedef nsDOMWorker::WorkerPrivilegeModel WorkerPrivilegeModel;
-
-  // Same as window.dump().
-  static JSBool
-  Dump(JSContext* aCx, uintN aArgc, jsval* aVp);
-
-  // Same as window.setTimeout().
-  static JSBool
-  SetTimeout(JSContext* aCx, uintN aArgc, jsval* aVp) {
-    return MakeTimeout(aCx, aArgc, aVp, PR_FALSE);
-  }
-
-  // Same as window.setInterval().
-  static JSBool
-  SetInterval(JSContext* aCx, uintN aArgc, jsval* aVp) {
-    return MakeTimeout(aCx, aArgc, aVp, PR_TRUE);
-  }
-
-  // Used for both clearTimeout() and clearInterval().
-  static JSBool
-  KillTimeout(JSContext* aCx, uintN aArgc, jsval* aVp);
-
-  static JSBool
-  LoadScripts(JSContext* aCx, uintN aArgc, jsval* aVp);
-
-  static JSBool
-  NewXMLHttpRequest(JSContext* aCx, uintN aArgc, jsval* aVp);
-
-  static JSBool
-  NewWorker(JSContext* aCx, uintN aArgc, jsval* aVp) {
-    return MakeNewWorker(aCx, aArgc, aVp, nsDOMWorker::CONTENT);
-  }
-
-  static JSBool
-  AtoB(JSContext* aCx, uintN aArgc, jsval* aVp);
-
-  static JSBool
-  BtoA(JSContext* aCx, uintN aArgc, jsval* aVp);
-
-  // Chrome-only functions
-  static JSBool
-  NewChromeWorker(JSContext* aCx, uintN aArgc, jsval* aVp);
-
-  static JSBool
-  XPCOMLazyGetter(JSContext* aCx, JSObject* aObj, jsid aId, jsval* aVp);
-
-  static JSBool
-  CreateInstance(JSContext* aCx, uintN aArgc, jsval* aVp) {
-    return GetInstanceCommon(aCx, aArgc, aVp, PR_FALSE);
-  }
-
-  static JSBool
-  GetService(JSContext* aCx, uintN aArgc, jsval* aVp) {
-    return GetInstanceCommon(aCx, aArgc, aVp, PR_TRUE);
-  }
-
-#ifdef BUILD_CTYPES
-  static JSBool
-  CTypesLazyGetter(JSContext* aCx, JSObject* aObj, jsid aId, jsval* aVp);
-#endif
-
-private:
-  // Internal helper for SetTimeout and SetInterval.
-  static JSBool
-  MakeTimeout(JSContext* aCx, uintN aArgc, jsval* aVp, PRBool aIsInterval);
-
-  static JSBool
-  MakeNewWorker(JSContext* aCx, uintN aArgc, jsval* aVp,
-                WorkerPrivilegeModel aPrivilegeModel);
-
-  static JSBool
-  GetInstanceCommon(JSContext* aCx, uintN aArgc, jsval* aVp, PRBool aService);
-};
-
-JSFunctionSpec gDOMWorkerXPCOMFunctions[] = {
-  {"createInstance", nsDOMWorkerFunctions::CreateInstance, 1, JSPROP_ENUMERATE},
-  {"getService",     nsDOMWorkerFunctions::GetService,     1, JSPROP_ENUMERATE},
-  { nsnull,          nsnull,                               0, 0 }
-};
-
-JSBool
-nsDOMWorkerFunctions::Dump(JSContext* aCx,
-                           uintN aArgc,
-                           jsval* aVp)
-{
-  JS_SET_RVAL(cx, aVp, JSVAL_VOID);
-  if (!nsGlobalWindow::DOMWindowDumpEnabled()) {
-    return JS_TRUE;
-  }
-
-  JSString* str;
-  if (aArgc && (str = JS_ValueToString(aCx, JS_ARGV(aCx, aVp)[0])) && str) {
-    nsDependentJSString depStr;
-    if (depStr.init(aCx, str)) {
-      fputs(NS_ConvertUTF16toUTF8(depStr).get(), stderr);
-      fflush(stderr);
-    }
-  }
-  return JS_TRUE;
-}
-
-JSBool
-nsDOMWorkerFunctions::MakeTimeout(JSContext* aCx,
-                                  uintN aArgc,
-                                  jsval* aVp,
-                                  PRBool aIsInterval)
-{
-  nsDOMWorker* worker = static_cast<nsDOMWorker*>(JS_GetContextPrivate(aCx));
-  NS_ASSERTION(worker, "This should be set by the DOM thread service!");
-
-  if (worker->IsCanceled()) {
-    return JS_FALSE;
-  }
-
-  PRUint32 id = worker->NextTimeoutId();
-
-  if (worker->IsClosing()) {
-    // Timeouts won't run in the close handler, fake success and bail.
-    JS_SET_RVAL(aCx, aVp, INT_TO_JSVAL(id));
-    return JS_TRUE;
-  }
-
-  nsRefPtr<nsDOMWorkerTimeout> timeout = new nsDOMWorkerTimeout(worker, id);
-  if (!timeout) {
-    JS_ReportOutOfMemory(aCx);
-    return JS_FALSE;
-  }
-
-  nsresult rv = timeout->Init(aCx, aArgc, JS_ARGV(aCx, aVp), aIsInterval);
-  if (NS_FAILED(rv)) {
-    JS_ReportError(aCx, "Failed to initialize timeout!");
-    return JS_FALSE;
-  }
-
-  rv = worker->AddFeature(timeout, aCx);
-  if (NS_FAILED(rv)) {
-    JS_ReportOutOfMemory(aCx);
-    return JS_FALSE;
-  }
-
-  rv = timeout->Start();
-  if (NS_FAILED(rv)) {
-    JS_ReportError(aCx, "Failed to start timeout!");
-    return JS_FALSE;
-  }
-
-  JS_SET_RVAL(aCx, aVp, INT_TO_JSVAL(id));
-  return JS_TRUE;
-}
-
-JSBool
-nsDOMWorkerFunctions::KillTimeout(JSContext* aCx,
-                                  uintN aArgc,
-                                  jsval* aVp)
-{
-  nsDOMWorker* worker = static_cast<nsDOMWorker*>(JS_GetContextPrivate(aCx));
-  NS_ASSERTION(worker, "This should be set by the DOM thread service!");
-
-  if (worker->IsCanceled()) {
-    return JS_FALSE;
-  }
-
-  if (!aArgc) {
-    JS_ReportError(aCx, "Function requires at least 1 parameter");
-    return JS_FALSE;
-  }
-
-  uint32 id;
-  if (!JS_ValueToECMAUint32(aCx, JS_ARGV(aCx, aVp)[0], &id)) {
-    JS_ReportError(aCx, "First argument must be a timeout id");
-    return JS_FALSE;
-  }
-
-  worker->CancelTimeoutWithId(PRUint32(id));
-  JS_SET_RVAL(aCx, aVp, JSVAL_VOID);
-  return JS_TRUE;
-}
-
-JSBool
-nsDOMWorkerFunctions::LoadScripts(JSContext* aCx,
-                                  uintN aArgc,
-                                  jsval* aVp)
-{
-  nsDOMWorker* worker = static_cast<nsDOMWorker*>(JS_GetContextPrivate(aCx));
-  NS_ASSERTION(worker, "This should be set by the DOM thread service!");
-
-  if (worker->IsCanceled()) {
-    return JS_FALSE;
-  }
-
-  if (!aArgc) {
-    // No argument is ok according to spec.
-    return JS_TRUE;
-  }
-
-  nsAutoTArray<nsString, 10> urls;
-
-  if (!urls.SetCapacity((PRUint32)aArgc)) {
-    JS_ReportOutOfMemory(aCx);
-    return JS_FALSE;
-  }
-
-  jsval* argv = JS_ARGV(aCx, aVp);
-  for (uintN index = 0; index < aArgc; index++) {
-    jsval val = argv[index];
-
-    if (!JSVAL_IS_STRING(val)) {
-      JS_ReportError(aCx, "Argument %d must be a string", index);
-      return JS_FALSE;
-    }
-
-    JSString* str = JS_ValueToString(aCx, val);
-    if (!str) {
-      JS_ReportError(aCx, "Couldn't convert argument %d to a string", index);
-      return JS_FALSE;
-    }
-
-    nsString* newURL = urls.AppendElement();
-    NS_ASSERTION(newURL, "Shouldn't fail if SetCapacity succeeded above!");
-
-    nsDependentJSString depStr;
-    if (!depStr.init(aCx, str)) {
-      return JS_FALSE;
-    }
-
-    newURL->Assign(depStr);
-  }
-
-  nsRefPtr<nsDOMWorkerScriptLoader> loader =
-    new nsDOMWorkerScriptLoader(worker);
-  if (!loader) {
-    JS_ReportOutOfMemory(aCx);
-    return JS_FALSE;
-  }
-
-  nsresult rv = worker->AddFeature(loader, aCx);
-  if (NS_FAILED(rv)) {
-    JS_ReportOutOfMemory(aCx);
-    return JS_FALSE;
-  }
-
-  rv = loader->LoadScripts(aCx, urls, PR_TRUE);
-  if (NS_FAILED(rv)) {
-    if (!JS_IsExceptionPending(aCx)) {
-      JS_ReportError(aCx, "Failed to load scripts");
-    }
-    return JS_FALSE;
-  }
-
-  JS_SET_RVAL(aCx, aVp, JSVAL_VOID);
-  return JS_TRUE;
-}
-
-JSBool
-nsDOMWorkerFunctions::NewXMLHttpRequest(JSContext* aCx,
-                                        uintN aArgc,
-                                        jsval* aVp)
-{
-  nsDOMWorker* worker = static_cast<nsDOMWorker*>(JS_GetContextPrivate(aCx));
-  NS_ASSERTION(worker, "This should be set by the DOM thread service!");
-
-  if (worker->IsCanceled()) {
-    return JS_FALSE;
-  }
-
-  if (aArgc) {
-    JS_ReportError(aCx, "XMLHttpRequest constructor takes no arguments!");
-    return JS_FALSE;
-  }
-
-  nsRefPtr<nsDOMWorkerXHR> xhr = new nsDOMWorkerXHR(worker);
-  if (!xhr) {
-    JS_ReportOutOfMemory(aCx);
-    return JS_FALSE;
-  }
-
-  nsresult rv = xhr->Init();
-  if (NS_FAILED(rv)) {
-    JS_ReportError(aCx, "Failed to construct XMLHttpRequest!");
-    return JS_FALSE;
-  }
-
-  rv = worker->AddFeature(xhr, aCx);
-  if (NS_FAILED(rv)) {
-    JS_ReportOutOfMemory(aCx);
-    return JS_FALSE;
-  }
-
-  nsCOMPtr<nsIXPConnectJSObjectHolder> xhrWrapped;
-  jsval v;
-  rv = nsContentUtils::WrapNative(aCx, JSVAL_TO_OBJECT(JS_CALLEE(aCx, aVp)),
-                                  static_cast<nsIXMLHttpRequest*>(xhr), &v,
-                                  getter_AddRefs(xhrWrapped));
-  if (NS_FAILED(rv)) {
-    JS_ReportError(aCx, "Failed to wrap XMLHttpRequest!");
-    return JS_FALSE;
-  }
-
-  JS_SET_RVAL(aCs, aVp, v);
-  return JS_TRUE;
-}
-
-JSBool
-nsDOMWorkerFunctions::AtoB(JSContext* aCx,
-                           uintN aArgc,
-                           jsval* aVp)
-{
-  nsDOMWorker* worker = static_cast<nsDOMWorker*>(JS_GetContextPrivate(aCx));
-  NS_ASSERTION(worker, "This should be set by the DOM thread service!");
-
-  if (worker->IsCanceled()) {
-    return JS_FALSE;
-  }
-
-  if (!aArgc) {
-    JS_ReportError(aCx, "Function requires at least 1 parameter");
-    return JS_FALSE;
-  }
-
-  return nsXPConnect::Base64Decode(aCx, JS_ARGV(aCx, aVp)[0],
-                                   &JS_RVAL(aCx, aVp));
-}
-
-JSBool
-nsDOMWorkerFunctions::BtoA(JSContext* aCx,
-                           uintN aArgc,
-                           jsval* aVp)
-{
-  nsDOMWorker* worker = static_cast<nsDOMWorker*>(JS_GetContextPrivate(aCx));
-  NS_ASSERTION(worker, "This should be set by the DOM thread service!");
-
-  if (worker->IsCanceled()) {
-    return JS_FALSE;
-  }
-
-  if (!aArgc) {
-    JS_ReportError(aCx, "Function requires at least 1 parameter");
-    return JS_FALSE;
-  }
-
-  return nsXPConnect::Base64Encode(aCx, JS_ARGV(aCx, aVp)[0],
-                                   &JS_RVAL(aCx, aVp));
-}
-
-JSBool
-nsDOMWorkerFunctions::NewChromeWorker(JSContext* aCx,
-                                      uintN aArgc,
-                                      jsval* aVp)
-{
-  nsDOMWorker* worker = static_cast<nsDOMWorker*>(JS_GetContextPrivate(aCx));
-  NS_ASSERTION(worker, "This should be set by the DOM thread service!");
-
-  if (!worker->IsPrivileged()) {
-    JS_ReportError(aCx, "Cannot create a priviliged worker!");
-    return JS_FALSE;
-  }
-
-  return MakeNewWorker(aCx, aArgc, aVp, nsDOMWorker::CHROME);
-}
-
-JSBool
-nsDOMWorkerFunctions::XPCOMLazyGetter(JSContext* aCx,
-                                      JSObject* aObj,
-                                      jsid aId,
-                                      jsval* aVp)
-{
-#ifdef DEBUG
-  {
-    NS_ASSERTION(JS_GetGlobalForObject(aCx, aObj) == aObj, "Bad object!");
-    NS_ASSERTION(JSID_IS_STRING(aId), "Not a string!");
-    NS_ASSERTION(nsDependentJSString(aId).EqualsLiteral("XPCOM"), "Bad id!");
-  }
-#endif
-  nsDOMWorker* worker = static_cast<nsDOMWorker*>(JS_GetContextPrivate(aCx));
-  NS_ASSERTION(worker, "This should be set by the DOM thread service!");
-
-  if (worker->IsCanceled()) {
-    return JS_FALSE;
-  }
-
-  PRUint16 dummy;
-  nsCOMPtr<nsIXPCSecurityManager> secMan;
-  nsContentUtils::XPConnect()->
-    GetSecurityManagerForJSContext(aCx, getter_AddRefs(secMan), &dummy);
-  if (!secMan) {
-    JS_ReportError(aCx, "Could not get security manager!");
-    return JS_FALSE;
-  }
-
-  nsCID dummyCID;
-  if (NS_FAILED(secMan->CanGetService(aCx, dummyCID))) {
-    JS_ReportError(aCx, "Access to the XPCOM object is denied!");
-    return JS_FALSE;
-  }
-
-  JSObject* xpcom = JS_NewObject(aCx, nsnull, nsnull, nsnull);
-  NS_ENSURE_TRUE(xpcom, JS_FALSE);
-
-  JSBool ok = JS_DefineFunctions(aCx, xpcom, gDOMWorkerXPCOMFunctions);
-  NS_ENSURE_TRUE(ok, JS_FALSE);
-
-  ok = JS_DeletePropertyById(aCx, aObj, aId);
-  NS_ENSURE_TRUE(ok, JS_FALSE);
-
-  jsval xpcomVal = OBJECT_TO_JSVAL(xpcom);
-  ok = JS_SetPropertyById(aCx, aObj, aId, &xpcomVal);
-  NS_ENSURE_TRUE(ok, JS_FALSE);
-
-  JS_SET_RVAL(aCx, aVp, xpcomVal);
-  return JS_TRUE;
-}
-
-JSBool
-nsDOMWorkerFunctions::GetInstanceCommon(JSContext* aCx,
-                                        uintN aArgc,
-                                        jsval* aVp,
-                                        PRBool aService)
-{
-  NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
-
-  nsDOMWorker* worker = static_cast<nsDOMWorker*>(JS_GetContextPrivate(aCx));
-  NS_ASSERTION(worker, "This should be set by the DOM thread service!");
-
-  if (worker->IsCanceled()) {
-    return JS_FALSE;
-  }
-
-  if (!aArgc) {
-    JS_ReportError(aCx, "Function requires at least 1 parameter");
-    return JS_FALSE;
-  }
-
-  JSString* str = JS_ValueToString(aCx, JS_ARGV(aCx, aVp)[0]);
-  if (!str) {
-    NS_ASSERTION(JS_IsExceptionPending(aCx), "Need to set an exception!");
-    return JS_FALSE;
-  }
-
-  JSAutoByteString strBytes(aCx, str);
-  if (!strBytes) {
-    NS_ASSERTION(JS_IsExceptionPending(aCx), "Need to set an exception!");
-    return JS_FALSE;
-  }
-
-  nsDependentCString contractId(strBytes.ptr(), JS_GetStringLength(str));
-
-  nsDOMThreadService* threadService = nsDOMThreadService::get();
-
-  ThreadsafeStatus status =
-    threadService->GetContractIdThreadsafeStatus(contractId);
-
-  if (status == Unknown) {
-    nsCOMPtr<nsIThread> mainThread;
-    nsresult rv = NS_GetMainThread(getter_AddRefs(mainThread));
-    if (NS_FAILED(rv)) {
-      JS_ReportError(aCx, "Failed to get main thread!");
-      return JS_FALSE;
-    }
-
-    nsRefPtr<TestComponentThreadsafetyRunnable> runnable =
-      new TestComponentThreadsafetyRunnable(contractId, aService);
-
-    rv = mainThread->Dispatch(runnable, NS_DISPATCH_SYNC);
-    if (NS_FAILED(rv)) {
-      JS_ReportError(aCx, "Failed to check threadsafety!");
-      return JS_FALSE;
-    }
-
-    // The worker may have been canceled while waiting above. Check again.
-    if (worker->IsCanceled()) {
-      return JS_FALSE;
-    }
-
-    if (runnable->IsThreadsafe()) {
-      threadService->NoteThreadsafeContractId(contractId, PR_TRUE);
-      status = Threadsafe;
-    }
-    else {
-      threadService->NoteThreadsafeContractId(contractId, PR_FALSE);
-      status = NotThreadsafe;
-    }
-  }
-
-  if (status == NotThreadsafe) {
-    JS_ReportError(aCx, "ChromeWorker may not create an XPCOM object that is "
-                   "not threadsafe!");
-    return JS_FALSE;
-  }
-
-  nsCOMPtr<nsISupports> instance;
-  if (aService) {
-    instance = do_GetService(contractId.get());
-    if (!instance) {
-      JS_ReportError(aCx, "Could not get the service!");
-      return JS_FALSE;
-    }
-  }
-  else {
-    instance = do_CreateInstance(contractId.get());
-    if (!instance) {
-      JS_ReportError(aCx, "Could not create the instance!");
-      return JS_FALSE;
-    }
-  }
-
-  JSObject* global = JS_GetGlobalForObject(aCx, JS_GetScopeChain(aCx));
-  if (!global) {
-    NS_ASSERTION(JS_IsExceptionPending(aCx), "Need to set an exception!");
-    return JS_FALSE;
-  }
-
-  jsval val;
-  nsCOMPtr<nsIXPConnectJSObjectHolder> wrapper;
-  if (NS_FAILED(nsContentUtils::WrapNative(aCx, global, instance, &val,
-                                           getter_AddRefs(wrapper)))) {
-    JS_ReportError(aCx, "Failed to wrap object!");
-    return JS_FALSE;
-  }
-
-  JS_SET_RVAL(aCx, aVp, val);
-  return JS_TRUE;
-}
-
-JSBool
-nsDOMWorkerFunctions::MakeNewWorker(JSContext* aCx,
-                                    uintN aArgc,
-                                    jsval* aVp,
-                                    WorkerPrivilegeModel aPrivilegeModel)
-{
-  JSObject *obj = JSVAL_TO_OBJECT(JS_CALLEE(aCx, aVp));
-    
-  nsDOMWorker* worker = static_cast<nsDOMWorker*>(JS_GetContextPrivate(aCx));
-  NS_ASSERTION(worker, "This should be set by the DOM thread service!");
-
-  if (worker->IsCanceled()) {
-    return JS_FALSE;
-  }
-
-  if (!aArgc) {
-    JS_ReportError(aCx, "Worker constructor must have an argument!");
-    return JS_FALSE;
-  }
-
-  // This pointer is protected by our pool, but it is *not* threadsafe and must
-  // not be used in any way other than to pass it along to the Initialize call.
-  nsIScriptGlobalObject* owner = worker->Pool()->ScriptGlobalObject();
-
-  nsCOMPtr<nsIXPConnectWrappedNative> wrappedWorker =
-    worker->GetWrappedNative();
-  if (!wrappedWorker) {
-    JS_ReportError(aCx, "Couldn't get wrapped native of worker!");
-    return JS_FALSE;
-  }
-
-  nsRefPtr<nsDOMWorker> newWorker =
-    new nsDOMWorker(worker, wrappedWorker, aPrivilegeModel);
-  if (!newWorker) {
-    JS_ReportOutOfMemory(aCx);
-    return JS_FALSE;
-  }
-
-  nsresult rv = newWorker->InitializeInternal(owner, aCx, obj, aArgc,
-                                              JS_ARGV(aCx, aVp));
-  if (NS_FAILED(rv)) {
-    JS_ReportError(aCx, "Couldn't initialize new worker!");
-    return JS_FALSE;
-  }
-
-  nsCOMPtr<nsIXPConnectJSObjectHolder> workerWrapped;
-  jsval v;
-  rv = nsContentUtils::WrapNative(aCx, obj, static_cast<nsIWorker*>(newWorker), &v, 
-                                  getter_AddRefs(workerWrapped));
-  if (NS_FAILED(rv)) {
-    JS_ReportError(aCx, "Failed to wrap new worker!");
-    return JS_FALSE;
-  }
-
-  JS_SET_RVAL(aCx, aVp, v);
-  return JS_TRUE;
-}
-
-#ifdef BUILD_CTYPES
-static char*
-UnicodeToNative(JSContext *cx, const jschar *source, size_t slen)
-{
-  nsCAutoString native;
-  nsDependentString unicode(reinterpret_cast<const PRUnichar*>(source), slen);
-  nsresult rv = NS_CopyUnicodeToNative(unicode, native);
-  if (NS_FAILED(rv)) {
-    JS_ReportError(cx, "could not convert string to native charset");
-    return NULL;
-  }
-
-  char* result = static_cast<char*>(JS_malloc(cx, native.Length() + 1));
-  if (!result)
-    return NULL;
-
-  memcpy(result, native.get(), native.Length() + 1);
-  return result;
-}
-
-static JSCTypesCallbacks sCallbacks = {
-  UnicodeToNative
-};
-
-JSBool
-nsDOMWorkerFunctions::CTypesLazyGetter(JSContext* aCx,
-                                       JSObject* aObj,
-                                       jsid aId,
-                                       jsval* aVp)
-{
-#ifdef DEBUG
-  {
-    NS_ASSERTION(JS_GetGlobalForObject(aCx, aObj) == aObj, "Bad object!");
-    NS_ASSERTION(JSID_IS_STRING(aId), "Not a string!");
-    NS_ASSERTION(nsDependentJSString(aId).EqualsLiteral("ctypes"), "Bad id!");
-  }
-#endif
-  nsDOMWorker* worker = static_cast<nsDOMWorker*>(JS_GetContextPrivate(aCx));
-  NS_ASSERTION(worker, "This should be set by the DOM thread service!");
-  NS_ASSERTION(worker->IsPrivileged(), "This shouldn't be possible!");
-
-  if (worker->IsCanceled()) {
-    return JS_FALSE;
-  }
-
-  jsval ctypes;
-  return JS_DeletePropertyById(aCx, aObj, aId) &&
-         JS_InitCTypesClass(aCx, aObj) &&
-         JS_GetProperty(aCx, aObj, "ctypes", &ctypes) &&
-         JS_SetCTypesCallbacks(aCx, JSVAL_TO_OBJECT(ctypes), &sCallbacks) &&
-         JS_GetPropertyById(aCx, aObj, aId, aVp);
-}
-#endif
-JSFunctionSpec gDOMWorkerFunctions[] = {
-  { "dump",                nsDOMWorkerFunctions::Dump,                1, 0 },
-  { "setTimeout",          nsDOMWorkerFunctions::SetTimeout,          1, 0 },
-  { "clearTimeout",        nsDOMWorkerFunctions::KillTimeout,         1, 0 },
-  { "setInterval",         nsDOMWorkerFunctions::SetInterval,         1, 0 },
-  { "clearInterval",       nsDOMWorkerFunctions::KillTimeout,         1, 0 },
-  { "importScripts",       nsDOMWorkerFunctions::LoadScripts,         1, 0 },
-  { "XMLHttpRequest",      nsDOMWorkerFunctions::NewXMLHttpRequest,   0, JSFUN_CONSTRUCTOR },
-  { "Worker",              nsDOMWorkerFunctions::NewWorker,           1, JSFUN_CONSTRUCTOR },
-  { "atob",                nsDOMWorkerFunctions::AtoB,                1, 0 },
-  { "btoa",                nsDOMWorkerFunctions::BtoA,                1, 0 },
-  { nsnull,                nsnull,                                    0, 0 }
-};
-JSFunctionSpec gDOMWorkerChromeFunctions[] = {
-  { "ChromeWorker",        nsDOMWorkerFunctions::NewChromeWorker,     1, JSFUN_CONSTRUCTOR },
-  { nsnull,                nsnull,                                    0, 0 }
-};
-enum DOMWorkerStructuredDataType
-{
-  // We have a special tag for XPCWrappedNatives that are being passed between
-  // threads. This will not work across processes and cannot be persisted. Only
-  // for ChromeWorker use at present.
-  DOMWORKER_SCTAG_WRAPPEDNATIVE = JS_SCTAG_USER_MIN + 0x1000,
-
-  DOMWORKER_SCTAG_END
-};
-
-PR_STATIC_ASSERT(DOMWORKER_SCTAG_END <= JS_SCTAG_USER_MAX);
-
-// static
-JSBool
-WriteStructuredClone(JSContext* aCx,
-                     JSStructuredCloneWriter* aWriter,
-                     JSObject* aObj,
-                     void* aClosure)
-{
-  NS_ASSERTION(aClosure, "Null pointer!");
-
-  // We'll stash any nsISupports pointers that need to be AddRef'd here.
-  nsTArray<nsCOMPtr<nsISupports> >* wrappedNatives =
-    static_cast<nsTArray<nsCOMPtr<nsISupports> >*>(aClosure);
-
-  // See if this is a wrapped native.
-  nsCOMPtr<nsIXPConnectWrappedNative> wrappedNative;
-  nsContentUtils::XPConnect()->
-    GetWrappedNativeOfJSObject(aCx, aObj, getter_AddRefs(wrappedNative));
-  if (wrappedNative) {
-    // Get the raw nsISupports out of it.
-    nsISupports* wrappedObject = wrappedNative->Native();
-    NS_ASSERTION(wrappedObject, "Null pointer?!");
-
-    // See if this nsISupports is threadsafe.
-    nsCOMPtr<nsIClassInfo> classInfo = do_QueryInterface(wrappedObject);
-    if (classInfo) {
-      PRUint32 flags;
-      if (NS_SUCCEEDED(classInfo->GetFlags(&flags)) &&
-          (flags & nsIClassInfo::THREADSAFE)) {
-        // Write the raw pointer into the stream, and add it to the list we're
-        // building.
-        return JS_WriteUint32Pair(aWriter, DOMWORKER_SCTAG_WRAPPEDNATIVE, 0) &&
-               JS_WriteBytes(aWriter, &wrappedObject, sizeof(wrappedObject)) &&
-               wrappedNatives->AppendElement(wrappedObject);
-      }
-    }
-  }
-
-  // Something failed above, try using the runtime callbacks instead.
-  const JSStructuredCloneCallbacks* runtimeCallbacks =
-    aCx->runtime->structuredCloneCallbacks;
-  if (runtimeCallbacks) {
-    return runtimeCallbacks->write(aCx, aWriter, aObj, nsnull);
-  }
-
-  // We can't handle this object, throw an exception if one hasn't been thrown
-  // already.
-  if (!JS_IsExceptionPending(aCx)) {
-    nsDOMClassInfo::ThrowJSException(aCx, NS_ERROR_DOM_DATA_CLONE_ERR);
-  }
-  return JS_FALSE;
-}
-
-nsDOMWorkerScope::nsDOMWorkerScope(nsDOMWorker* aWorker)
-: mWorker(aWorker),
-  mWrappedNative(nsnull),
-  mHasOnerror(PR_FALSE)
-{
-  NS_ASSERTION(aWorker, "Null pointer!");
-}
-
-NS_IMPL_ISUPPORTS_INHERITED3(nsDOMWorkerScope, nsDOMWorkerMessageHandler,
-                                               nsIWorkerScope,
-                                               nsIWorkerGlobalScope,
-                                               nsIXPCScriptable)
-
-NS_IMPL_CI_INTERFACE_GETTER4(nsDOMWorkerScope, nsIWorkerScope,
-                                               nsIWorkerGlobalScope,
-                                               nsIDOMEventTarget,
-                                               nsIXPCScriptable)
-
-NS_IMPL_THREADSAFE_DOM_CI_GETINTERFACES(nsDOMWorkerScope)
-NS_IMPL_THREADSAFE_DOM_CI_ALL_THE_REST(nsDOMWorkerScope)
-
-// Need to return a scriptable helper so that XPConnect can get our
-// nsIXPCScriptable flags properly (to not enumerate QI, for instance).
-NS_IMETHODIMP
-nsDOMWorkerScope::GetHelperForLanguage(PRUint32 aLanguage,
-                                       nsISupports** _retval)
-{
-  if (aLanguage == nsIProgrammingLanguage::JAVASCRIPT) {
-    NS_ADDREF(*_retval = NS_ISUPPORTS_CAST(nsIWorkerScope*, this));
-  }
-  else {
-    *_retval = nsnull;
-  }
-  return NS_OK;
-}
-
-// Use the xpc_map_end.h macros to generate the nsIXPCScriptable methods we want
-// for the scope.
-
-#define XPC_MAP_CLASSNAME nsDOMWorkerScope
-#define XPC_MAP_QUOTED_CLASSNAME "DedicatedWorkerGlobalScope"
-#define XPC_MAP_WANT_POSTCREATE
-#define XPC_MAP_WANT_TRACE
-#define XPC_MAP_WANT_FINALIZE
-
-#define XPC_MAP_FLAGS                                      \
-  nsIXPCScriptable::USE_JSSTUB_FOR_ADDPROPERTY           | \