Merge last PGO-green changeset of mozilla-inbound to mozilla-central
authorEd Morley <emorley@mozilla.com>
Wed, 12 Dec 2012 18:56:05 +0000
changeset 124888 1cc19f36ee663920b819411beda4652931571e10
parent 124835 352bd17710c8881a5c4dd913013eff96cfaf833b (current diff)
parent 124887 b4f3b4a3f0c45e50d41c309ec306c654de916f60 (diff)
child 124889 edd45de440ba0913b8226d4a47efe23962fe3003
child 138090 f8cf32e0d5b12dac15acc4ded48129ddd12da513
push id2151
push userlsblakk@mozilla.com
push dateTue, 19 Feb 2013 18:06:57 +0000
treeherdermozilla-beta@4952e88741ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone20.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge last PGO-green changeset of mozilla-inbound to mozilla-central
b2g/config/otoro/config.json
b2g/config/panda-gaia-central/config.json
b2g/config/panda/config.json
b2g/config/unagi/config.json
browser/base/content/test/browser_social.js
browser/base/content/test/browser_social_chatwindow.js
browser/base/content/test/browser_social_flyout.js
browser/base/content/test/browser_social_isVisible.js
browser/base/content/test/browser_social_mozSocial_API.js
browser/base/content/test/browser_social_multiprovider.js
browser/base/content/test/browser_social_shareButton.js
browser/base/content/test/browser_social_sidebar.js
browser/base/content/test/browser_social_toolbar.js
browser/base/content/test/social_chat.html
browser/base/content/test/social_flyout.html
browser/base/content/test/social_panel.html
browser/base/content/test/social_share_image.png
browser/base/content/test/social_sidebar.html
browser/base/content/test/social_window.html
browser/base/content/test/social_worker.js
dom/tests/browser/browser_ConsoleStoragePBTest.js
toolkit/components/places/tests/browser/browser_visituri_privatebrowsing.js
tools/rb/fix-macosx-stack.pl
--- a/accessible/src/base/AccTypes.h
+++ b/accessible/src/base/AccTypes.h
@@ -8,37 +8,37 @@
 
 namespace mozilla {
 namespace a11y {
 
 /**
  * Accessible object types used when creating an accessible based on the frame.
  */
 enum AccType {
-  eNoAccessible,
-  eHTMLBRAccessible,
-  eHTMLButtonAccessible,
-  eHTMLCanvasAccessible,
-  eHTMLCaptionAccessible,
-  eHTMLCheckboxAccessible,
-  eHTMLComboboxAccessible,
-  eHTMLFileInputAccessible,
-  eHTMLGroupboxAccessible,
-  eHTMLHRAccessible,
-  eHTMLImageMapAccessible,
-  eHTMLLabelAccessible,
-  eHTMLLiAccessible,
-  eHTMLSelectListAccessible,
-  eHTMLMediaAccessible,
-  eHTMLObjectFrameAccessible,
-  eHTMLRadioButtonAccessible,
-  eHTMLTableAccessible,
-  eHTMLTableCellAccessible,
-  eHTMLTableRowAccessible,
-  eHTMLTextFieldAccessible,
-  eHyperTextAccessible,
-  eImageAccessible,
-  eOuterDocAccessible,
-  eTextLeafAccessible
+  eNoType,
+  eHTMLBR,
+  eHTMLButton,
+  eHTMLCanvas,
+  eHTMLCaption,
+  eHTMLCheckbox,
+  eHTMLCombobox,
+  eHTMLFileInput,
+  eHTMLGroupbox,
+  eHTMLHR,
+  eHTMLImageMap,
+  eHTMLLabel,
+  eHTMLLi,
+  eHTMLSelectList,
+  eHTMLMedia,
+  eHTMLRadioButton,
+  eHTMLTable,
+  eHTMLTableCell,
+  eHTMLTableRow,
+  eHTMLTextField,
+  eHyperText,
+  eImage,
+  eOuterDoc,
+  ePlugin,
+  eTextLeaf
 };
 }
 }
 
--- a/accessible/src/base/nsAccessibilityService.cpp
+++ b/accessible/src/base/nsAccessibilityService.cpp
@@ -202,19 +202,19 @@ nsAccessibilityService::GetRootDocumentA
       return aCanCreate ?
         GetDocAccessible(documentNode) : GetDocAccessibleFromCache(documentNode);
     }
   }
   return nullptr;
 }
 
 already_AddRefed<Accessible>
-nsAccessibilityService::CreateHTMLObjectFrameAccessible(nsObjectFrame* aFrame,
-                                                        nsIContent* aContent,
-                                                        Accessible* aContext)
+nsAccessibilityService::CreatePluginAccessible(nsObjectFrame* aFrame,
+                                               nsIContent* aContent,
+                                               Accessible* aContext)
 {
   // nsObjectFrame means a plugin, so we need to use the accessibility support
   // of the plugin.
   if (aFrame->GetRect().IsEmpty())
     return nullptr;
 
 #if defined(XP_WIN) || defined(MOZ_ACCESSIBILITY_ATK)
   nsRefPtr<nsNPAPIPluginInstance> pluginInstance;
@@ -794,53 +794,53 @@ nsAccessibilityService::GetOrCreateAcces
   }
 
   if (!newAcc && isHTML) {  // HTML accessibles
     if (roleMapEntry) {
       // Create pure ARIA grid/treegrid related accessibles if they weren't used
       // on accessible HTML table elements.
       if ((roleMapEntry->accTypes & Accessible::eTableCellAccessible)) {
         if (aContext->IsOfType(Accessible::eTableRowAccessible) &&
-            (frame->AccessibleType() != eHTMLTableCellAccessible ||
+            (frame->AccessibleType() != eHTMLTableCell ||
              aContext->GetContent() != content->GetParent())) {
           newAcc = new ARIAGridCellAccessibleWrap(content, document);
         }
 
       } else if ((roleMapEntry->accTypes & Accessible::eTableAccessible) &&
-                 frame->AccessibleType() != eHTMLTableAccessible) {
+                 frame->AccessibleType() != eHTMLTable) {
         newAcc = new ARIAGridAccessibleWrap(content, document);
       }
     }
 
     if (!newAcc) {
       // Prefer to use markup (mostly tag name, perhaps attributes) to decide if
       // and what kind of accessible to create.
       newAcc = CreateHTMLAccessibleByMarkup(frame, content, aContext);
 
       // Try using frame to do it.
       if (!newAcc)
         newAcc = CreateAccessibleByFrameType(frame, content, aContext);
 
       // If table has strong ARIA role then all table descendants shouldn't
       // expose their native roles.
       if (!roleMapEntry && newAcc) {
-        if (frame->AccessibleType() == eHTMLTableRowAccessible) {
+        if (frame->AccessibleType() == eHTMLTableRow) {
           nsRoleMapEntry* contextRoleMap = aContext->ARIARoleMap();
           if (contextRoleMap &&
               !(contextRoleMap->accTypes & Accessible::eTableAccessible))
             roleMapEntry = &nsARIAMap::gEmptyRoleMap;
 
-        } else if (frame->AccessibleType() == eHTMLTableCellAccessible &&
+        } else if (frame->AccessibleType() == eHTMLTableCell &&
                    aContext->ARIARoleMap() == &nsARIAMap::gEmptyRoleMap) {
           roleMapEntry = &nsARIAMap::gEmptyRoleMap;
 
         } else if (content->Tag() == nsGkAtoms::dt ||
                    content->Tag() == nsGkAtoms::li ||
                    content->Tag() == nsGkAtoms::dd ||
-                   frame->AccessibleType() == eHTMLLiAccessible) {
+                   frame->AccessibleType() == eHTMLLi) {
           nsRoleMapEntry* contextRoleMap = aContext->ARIARoleMap();
           if (contextRoleMap &&
               !(contextRoleMap->accTypes & Accessible::eListAccessible))
             roleMapEntry = &nsARIAMap::gEmptyRoleMap;
         }
       }
     }
   }
@@ -1301,85 +1301,79 @@ already_AddRefed<Accessible>
 nsAccessibilityService::CreateAccessibleByFrameType(nsIFrame* aFrame,
                                                     nsIContent* aContent,
                                                     Accessible* aContext)
 {
   DocAccessible* document = aContext->Document();
 
   nsRefPtr<Accessible> newAcc;
   switch (aFrame->AccessibleType()) {
-    case eNoAccessible:
+    case eNoType:
       return nullptr;
-    case eHTMLBRAccessible:
+    case eHTMLBR:
       newAcc = new HTMLBRAccessible(aContent, document);
       break;
-    case eHTMLButtonAccessible:
+    case eHTMLButton:
       newAcc = new HTMLButtonAccessible(aContent, document);
       break;
-    case eHTMLCanvasAccessible:
+    case eHTMLCanvas:
       newAcc = new HTMLCanvasAccessible(aContent, document);
       break;
-    case eHTMLCaptionAccessible:
+    case eHTMLCaption:
       if (aContext->IsOfType(Accessible::eTableAccessible) &&
           aContext->GetContent() == aContent->GetParent()) {
         newAcc = new HTMLCaptionAccessible(aContent, document);
       }
       break;
-    case eHTMLCheckboxAccessible:
+    case eHTMLCheckbox:
       newAcc = new HTMLCheckboxAccessible(aContent, document);
       break;
-    case eHTMLComboboxAccessible:
+    case eHTMLCombobox:
       newAcc = new HTMLComboboxAccessible(aContent, document);
       break;
-    case eHTMLFileInputAccessible:
+    case eHTMLFileInput:
       newAcc = new HTMLFileInputAccessible(aContent, document);
       break;
-    case eHTMLGroupboxAccessible:
+    case eHTMLGroupbox:
       newAcc = new HTMLGroupboxAccessible(aContent, document);
       break;
-    case eHTMLHRAccessible:
+    case eHTMLHR:
       newAcc = new HTMLHRAccessible(aContent, document);
       break;
-    case eHTMLImageMapAccessible:
+    case eHTMLImageMap:
       newAcc = new HTMLImageMapAccessible(aContent, document);
       break;
-    case eHTMLLabelAccessible:
+    case eHTMLLabel:
       newAcc = new HTMLLabelAccessible(aContent, document);
       break;
-    case eHTMLLiAccessible:
+    case eHTMLLi:
       if (aContext->IsOfType(Accessible::eListAccessible) &&
           aContext->GetContent() == aContent->GetParent()) {
         newAcc = new HTMLLIAccessible(aContent, document);
       }
       break;
-    case eHTMLSelectListAccessible:
+    case eHTMLSelectList:
       newAcc = new HTMLSelectListAccessible(aContent, document);
       break;
-    case eHTMLMediaAccessible:
+    case eHTMLMedia:
       newAcc = new EnumRoleAccessible(aContent, document, roles::GROUPING);
       break;
-    case eHTMLObjectFrameAccessible: {
-      nsObjectFrame* objectFrame = do_QueryFrame(aFrame);
-      newAcc = CreateHTMLObjectFrameAccessible(objectFrame, aContent, aContext);
-      break;
-    }
-
-    case eHTMLRadioButtonAccessible:
+    case eHTMLRadioButton:
       newAcc = new HTMLRadioButtonAccessible(aContent, document);
       break;
-    case eHTMLTableAccessible:
+    case eHTMLTable:
       newAcc = new HTMLTableAccessibleWrap(aContent, document);
       break;
-    case eHTMLTableCellAccessible:
+    case eHTMLTableCell:
       // Accessible HTML table cell must be a child of accessible HTML table row.
       if (aContext->IsOfType(Accessible::eHTMLTableRowAccessible))
         newAcc = new HTMLTableCellAccessibleWrap(aContent, document);
       break;
 
-    case eHTMLTableRowAccessible: {
+    case eHTMLTableRow: {
       // Accessible HTML table row must be a child of tbody/tfoot/thead of
       // accessible HTML table or must be a child of accessible of HTML table.
       if (aContext->IsOfType(Accessible::eTableAccessible)) {
         nsIContent* parentContent = aContent->GetParent();
         nsIFrame* parentFrame = parentContent->GetPrimaryFrame();
         if (parentFrame->GetType() == nsGkAtoms::tableRowGroupFrame) {
           parentContent = parentContent->GetParent();
           parentFrame = parentContent->GetPrimaryFrame();
@@ -1387,31 +1381,36 @@ nsAccessibilityService::CreateAccessible
 
         if (parentFrame->GetType() == nsGkAtoms::tableOuterFrame &&
             aContext->GetContent() == parentContent) {
           newAcc = new HTMLTableRowAccessible(aContent, document);
         }
       }
       break;
     }
-    case eHTMLTextFieldAccessible:
+    case eHTMLTextField:
       newAcc = new HTMLTextFieldAccessible(aContent, document);
       break;
-    case eHyperTextAccessible:
+    case eHyperText:
       if (aContent->Tag() != nsGkAtoms::dt && aContent->Tag() != nsGkAtoms::dd)
         newAcc = new HyperTextAccessibleWrap(aContent, document);
       break;
 
-    case eImageAccessible:
+    case eImage:
       newAcc = new ImageAccessibleWrap(aContent, document);
       break;
-    case eOuterDocAccessible:
+    case eOuterDoc:
       newAcc = new OuterDocAccessible(aContent, document);
       break;
-    case eTextLeafAccessible:
+    case ePlugin: {
+      nsObjectFrame* objectFrame = do_QueryFrame(aFrame);
+      newAcc = CreatePluginAccessible(objectFrame, aContent, aContext);
+      break;
+    }
+    case eTextLeaf:
       newAcc = new TextLeafAccessibleWrap(aContent, document);
       break;
   }
 
   return newAcc.forget();
 }
 
 ////////////////////////////////////////////////////////////////////////////////
--- a/accessible/src/base/nsAccessibilityService.h
+++ b/accessible/src/base/nsAccessibilityService.h
@@ -49,18 +49,18 @@ public:
   NS_DECL_ISUPPORTS_INHERITED
   NS_DECL_NSIACCESSIBLERETRIEVAL
   NS_DECL_NSIOBSERVER
 
   // nsIAccessibilityService
   virtual Accessible* GetRootDocumentAccessible(nsIPresShell* aPresShell,
                                                 bool aCanCreate);
   already_AddRefed<Accessible>
-    CreateHTMLObjectFrameAccessible(nsObjectFrame* aFrame, nsIContent* aContent,
-                                    Accessible* aContext);
+    CreatePluginAccessible(nsObjectFrame* aFrame, nsIContent* aContent,
+                           Accessible* aContext);
 
   /**
    * Adds/remove ATK root accessible for gtk+ native window to/from children
    * of the application accessible.
    */
   virtual Accessible* AddNativeRootAccessible(void* aAtkAccessible);
   virtual void RemoveNativeRootAccessible(Accessible* aRootAccessible);
 
--- a/b2g/config/otoro/config.json
+++ b/b2g/config/otoro/config.json
@@ -1,18 +1,16 @@
 {
     "config_version": 1,
     "tooltool_manifest": "releng-otoro.tt",
     "mock_target": "mozilla-centos6-i386",
     "mock_packages": ["ccache", "make", "bison", "flex", "gcc", "g++", "mpfr", "zlib-devel", "ncurses-devel", "zip", "autoconf213", "glibc-static", "perl-Digest-SHA", "wget", "alsa-lib", "atk", "cairo", "dbus-glib", "fontconfig", "freetype", "glib2", "gtk2", "libXRender", "libXt", "pango", "mozilla-python27-mercurial", "openssh-clients", "nss-devel"],
     "mock_files": [["/home/cltbld/.ssh", "/home/mock_mozilla/.ssh"]],
     "build_targets": [],
     "upload_files": [
-        "{objdir}/dist/b2g-update/*.mar",
-        "{objdir}/dist/b2g-*.tar.gz",
         "{objdir}/dist/b2g-*.crashreporter-symbols.zip",
         "{workdir}/sources.xml"
     ],
     "zip_files": [
         ["{workdir}/out/target/product/otoro/*.img", "out/target/product/otoro/"],
         "{workdir}/boot.img",
         "{workdir}/flash.sh",
         "{workdir}/load-config.sh",
--- a/b2g/config/panda-gaia-central/config.json
+++ b/b2g/config/panda-gaia-central/config.json
@@ -3,18 +3,16 @@
     "tooltool_manifest": "releng-pandaboard.tt",
     "mock_target": "mozilla-centos6-i386",
     "mock_packages": ["ccache", "make", "bison", "flex", "gcc", "g++", "mpfr", "zlib-devel", "ncurses-devel", "zip", "autoconf213", "glibc-static", "perl-Digest-SHA", "wget", "alsa-lib", "atk", "cairo", "dbus-glib", "fontconfig", "freetype", "glib2", "gtk2", "libXRender", "libXt", "pango", "mozilla-python27-mercurial", "openssh-clients", "nss-devel"],
     "mock_files": [["/home/cltbld/.ssh", "/home/mock_mozilla/.ssh"]],
     "build_targets": ["boottarball", "systemtarball", "userdatatarball", "package-tests"],
     "upload_files": [
         "{workdir}/out/target/product/panda/*.tar.bz2",
         "{workdir}/out/target/product/panda/tests/*.zip",
-        "{objdir}/dist/b2g-update/*.mar",
-        "{objdir}/dist/b2g-*.tar.gz",
         "{objdir}/dist/b2g-*.crashreporter-symbols.zip",
         "{srcdir}/b2g/config/panda/README",
         "{workdir}/sources.xml"
     ],
     "gecko_l10n_root": "http://hg.mozilla.org/l10n-central",
     "gaia": {
         "vcs": "hgtool",
         "repo": "http://hg.mozilla.org/integration/gaia-central",
--- a/b2g/config/panda/config.json
+++ b/b2g/config/panda/config.json
@@ -3,18 +3,16 @@
     "tooltool_manifest": "releng-pandaboard.tt",
     "mock_target": "mozilla-centos6-i386",
     "mock_packages": ["ccache", "make", "bison", "flex", "gcc", "g++", "mpfr", "zlib-devel", "ncurses-devel", "zip", "autoconf213", "glibc-static", "perl-Digest-SHA", "wget", "alsa-lib", "atk", "cairo", "dbus-glib", "fontconfig", "freetype", "glib2", "gtk2", "libXRender", "libXt", "pango", "mozilla-python27-mercurial", "openssh-clients", "nss-devel"],
     "mock_files": [["/home/cltbld/.ssh", "/home/mock_mozilla/.ssh"]],
     "build_targets": ["boottarball", "systemtarball", "userdatatarball", "package-tests"],
     "upload_files": [
         "{workdir}/out/target/product/panda/*.tar.bz2",
         "{workdir}/out/target/product/panda/tests/*.zip",
-        "{objdir}/dist/b2g-update/*.mar",
-        "{objdir}/dist/b2g-*.tar.gz",
         "{objdir}/dist/b2g-*.crashreporter-symbols.zip",
         "{srcdir}/b2g/config/panda/README",
         "{workdir}/sources.xml"
     ],
     "gecko_l10n_root": "http://hg.mozilla.org/l10n-central",
     "gaia": {
         "vcs": "hgtool",
         "repo": "http://hg.mozilla.org/integration/gaia-nightly",
--- a/b2g/config/tooltool-manifests/macosx64/releng.manifest
+++ b/b2g/config/tooltool-manifests/macosx64/releng.manifest
@@ -1,17 +1,17 @@
 [
 {
-"clang_version": "r169139"
+"clang_version": "r169730"
 },
 {
 "size": 47,
 "digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa",
 "algorithm": "sha512",
 "filename": "setup.sh"
 },
 {
-"size": 56158651,
-"digest": "38d718f20a8fa9218e22ade312e724e6c9cdd7c6650e023cfdc21b5505fe7aa3743ae41c0abd717a1bbccec4c4271be2fa82d0e2f96c91e693d70e33b4dc00d6",
+"size": 56115091,
+"digest": "d7188264f28d6f6a84fab9737520cad22fe3d575917a87fc110d0b9a2033617c35da83530ea20553f5c55a996459f750fa2d0c49288c1fb9671f6252a92cf4c9",
 "algorithm": "sha512",
 "filename": "clang.tar.bz2"
 }
 ]
--- a/b2g/config/unagi/config.json
+++ b/b2g/config/unagi/config.json
@@ -2,17 +2,16 @@
     "config_version": 1,
     "tooltool_manifest": "releng-unagi.tt",
     "mock_target": "mozilla-centos6-i386",
     "mock_packages": ["ccache", "make", "bison", "flex", "gcc", "g++", "mpfr", "zlib-devel", "ncurses-devel", "zip", "autoconf213", "glibc-static", "perl-Digest-SHA", "wget", "alsa-lib", "atk", "cairo", "dbus-glib", "fontconfig", "freetype", "glib2", "gtk2", "libXRender", "libXt", "pango", "mozilla-python27-mercurial", "openssh-clients", "nss-devel"],
     "mock_files": [["/home/cltbld/.ssh", "/home/mock_mozilla/.ssh"]],
     "build_targets": [],
     "upload_files": [
         "{objdir}/dist/b2g-update/*.mar",
-        "{objdir}/dist/b2g-*.tar.gz",
         "{objdir}/dist/b2g-*.crashreporter-symbols.zip",
         "{workdir}/sources.xml"
     ],
     "zip_files": [
         ["{workdir}/out/target/product/unagi/*.img", "out/target/product/unagi/"],
         "{workdir}/boot.img",
         "{workdir}/flash.sh",
         "{workdir}/load-config.sh",
--- a/browser/base/content/browser-plugins.js
+++ b/browser/base/content/browser-plugins.js
@@ -246,16 +246,17 @@ var gPluginHandler = {
     // Hide the in-content UI if it's too big. The crashed plugin handler already did this.
     if (eventType != "PluginCrashed") {
       let overlay = doc.getAnonymousElementByAttribute(plugin, "class", "mainBox");
       if (overlay != null && self.isTooSmall(plugin, overlay))
           overlay.style.visibility = "hidden";
     }
   },
 
+  _notificationDisplayedOnce: false,
   handlePluginScripted: function PH_handlePluginScripted(aBrowser) {
     let contentWindow = aBrowser.contentWindow;
     if (!contentWindow)
       return;
 
     let cwu = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                             .getInterface(Ci.nsIDOMWindowUtils);
     let haveVisibleCTPPlugin = cwu.plugins.some(function(plugin) {
@@ -273,19 +274,20 @@ var gPluginHandler = {
       let isInvisible = ((computedStyle.width == "240px" &&
                           computedStyle.height == "200px") ||
                          gPluginHandler.isTooSmall(plugin, overlay));
       return (!isInvisible &&
               gPluginHandler.canActivatePlugin(objLoadingContent));
     });
 
     let notification = PopupNotifications.getNotification("click-to-play-plugins", aBrowser);
-    if (notification && !haveVisibleCTPPlugin) {
+    if (notification && !haveVisibleCTPPlugin && !this._notificationDisplayedOnce) {
       notification.dismissed = false;
       PopupNotifications._update(notification.anchorElement);
+      this._notificationDisplayedOnce = true;
     }
 
     aBrowser._pluginScriptedState = PLUGIN_SCRIPTED_STATE_DONE;
   },
 
   isKnownPlugin: function PH_isKnownPlugin(objLoadingContent) {
     return (objLoadingContent.getContentTypeForMIMEType(objLoadingContent.actualType) ==
             Ci.nsIObjectLoadingContent.TYPE_PLUGIN);
@@ -638,18 +640,19 @@ var gPluginHandler = {
         if (notification)
           notification.remove();
         gPluginHandler._removeClickToPlayOverlays(contentWindow);
       }
     }];
     let notification = PopupNotifications.getNotification("click-to-play-plugins", aBrowser);
     let dismissed = notification ? notification.dismissed : true;
     let options = { dismissed: dismissed, centerActions: centerActions };
+    let icon = haveVulnerablePlugin ? "blocked-plugins-notification-icon" : "plugins-notification-icon"
     PopupNotifications.show(aBrowser, "click-to-play-plugins",
-                            messageString, "plugins-notification-icon",
+                            messageString, icon,
                             mainAction, secondaryActions, options);
   },
 
   _removeClickToPlayOverlays: function PH_removeClickToPlayOverlays(aContentWindow) {
     let doc = aContentWindow.document;
     let cwu = aContentWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                             .getInterface(Ci.nsIDOMWindowUtils);
     for (let plugin of cwu.plugins) {
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -552,16 +552,17 @@
             <image id="default-notification-icon" class="notification-anchor-icon" role="button"/>
             <image id="identity-notification-icon" class="notification-anchor-icon" role="button"/>
             <image id="geo-notification-icon" class="notification-anchor-icon" role="button"/>
             <image id="addons-notification-icon" class="notification-anchor-icon" role="button"/>
             <image id="indexedDB-notification-icon" class="notification-anchor-icon" role="button"/>
             <image id="password-notification-icon" class="notification-anchor-icon" role="button"/>
             <image id="webapps-notification-icon" class="notification-anchor-icon" role="button"/>
             <image id="plugins-notification-icon" class="notification-anchor-icon" role="button"/>
+            <image id="blocked-plugins-notification-icon" class="notification-anchor-icon" role="button"/>
           </box>
           <!-- Use onclick instead of normal popup= syntax since the popup
                code fires onmousedown, and hence eats our favicon drag events.
                We only add the identity-box button to the tab order when the location bar
                has focus, otherwise pressing F6 focuses it instead of the location bar -->
           <box id="identity-box" role="button"
                align="center"
                onclick="gIdentityHandler.handleIdentityButtonEvent(event);"
--- a/browser/base/content/test/Makefile.in
+++ b/browser/base/content/test/Makefile.in
@@ -5,16 +5,17 @@
 DEPTH		= @DEPTH@
 topsrcdir	= @top_srcdir@
 srcdir		= @srcdir@
 VPATH		= @srcdir@
 relativesrcdir  = @relativesrcdir@
 
 DIRS += \
 		newtab \
+		social \
 		$(NULL)
 
 include $(DEPTH)/config/autoconf.mk
 
 MOCHITEST_FILES = \
 		head.js \
 		test_feed_discovery.html \
 		feed_discovery.html \
@@ -281,32 +282,16 @@ endif
                  browser_bug734076.js \
                  browser_bug812562.js \
                  browser_bug818009.js \
                  browser_bug818118.js \
                  blockPluginVulnerableUpdatable.xml \
                  blockPluginVulnerableNoUpdate.xml \
                  blockNoPlugins.xml \
                  browser_utilityOverlay.js \
-                 browser_social.js \
-                 browser_social_toolbar.js \
-                 browser_social_shareButton.js \
-                 browser_social_sidebar.js \
-                 browser_social_flyout.js \
-                 browser_social_mozSocial_API.js \
-                 browser_social_isVisible.js \
-                 browser_social_chatwindow.js \
-                 browser_social_multiprovider.js \
-                 social_panel.html \
-                 social_share_image.png \
-                 social_sidebar.html \
-                 social_chat.html \
-                 social_flyout.html \
-                 social_window.html \
-                 social_worker.js \
                  browser_bug676619.js \
                  download_page.html \
                  $(NULL)
 
 ifneq (cocoa,$(MOZ_WIDGET_TOOLKIT))
 _BROWSER_FILES += \
 		browser_bug462289.js \
 		$(NULL)
--- a/browser/base/content/test/browser_clickToPlayPluginScriptAccessPopup.js
+++ b/browser/base/content/test/browser_clickToPlayPluginScriptAccessPopup.js
@@ -18,21 +18,25 @@ function test() {
   });
   Services.prefs.setBoolPref("plugins.click_to_play", true);
 
   gBrowser.selectedTab = gBrowser.addTab();
   gTestBrowser = gBrowser.selectedBrowser;
   gTestBrowser.addEventListener("load", pageLoad, true);
   gTestBrowser.addEventListener("PluginScripted", pluginScripted, true);
 
+  // This list is iterated in reverse order, since it uses Array.pop to get the next test.
   gNextTestList = [
-    { func: testExpectPopupPart1,
+    // Doesn't show a popup since not the first instance of a small plugin
+    { func: testExpectNoPopupPart1,
       url: gHttpTestRoot + "plugin_test_scriptedPopup1.html" },
-    { func: testExpectPopupPart1,
+    // Doesn't show a popup since not the first instance of a small plugin
+    { func: testExpectNoPopupPart1,
       url: gHttpTestRoot + "plugin_test_scriptedPopup2.html" },
+    // Shows a popup since it is the first instance of a small plugin
     { func: testExpectPopupPart1,
       url: gHttpTestRoot + "plugin_test_scriptedPopup3.html" },
     { func: testExpectNoPopupPart1,
       url: gHttpTestRoot + "plugin_test_scriptedNoPopup1.html" },
     { func: testExpectNoPopupPart1,
       url: gHttpTestRoot + "plugin_test_scriptedNoPopup2.html" },
     { func: testExpectNoPopupPart1,
       url: gHttpTestRoot + "plugin_test_scriptedNoPopup3.html" }
deleted file mode 100644
--- a/browser/base/content/test/browser_social_multiprovider.js
+++ /dev/null
@@ -1,104 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-function test() {
-  waitForExplicitFinish();
-
-  runSocialTestWithProvider(gProviders, function (finishcb) {
-    runSocialTests(tests, undefined, undefined, finishcb);
-  });
-}
-
-let gProviders = [
-  {
-    name: "provider 1",
-    origin: "https://example.com",
-    sidebarURL: "https://example.com/browser/browser/base/content/test/social_sidebar.html?provider1",
-    workerURL: "https://example.com/browser/browser/base/content/test/social_worker.js",
-    iconURL: "chrome://branding/content/icon48.png"
-  },
-  {
-    name: "provider 2",
-    origin: "https://test1.example.com",
-    sidebarURL: "https://test1.example.com/browser/browser/base/content/test/social_sidebar.html?provider2",
-    workerURL: "https://test1.example.com/browser/browser/base/content/test/social_worker.js",
-    iconURL: "chrome://branding/content/icon48.png"
-  }
-];
-
-var tests = {
-  testProviderSwitch: function(next) {
-    function checkProviderMenu(selectedProvider) {
-      let menu = document.getElementById("social-statusarea-popup");
-      let menuProviders = menu.querySelectorAll(".social-provider-menuitem");
-      is(menuProviders.length, gProviders.length, "correct number of providers listed in the menu");
-      // Find the selectedProvider's menu item
-      let el = menu.getElementsByAttribute("origin", selectedProvider.origin);
-      is(el.length, 1, "selected provider menu item exists");
-      is(el[0].getAttribute("checked"), "true", "selected provider menu item is checked");
-    }
-
-    checkProviderMenu(gProviders[0]);
-
-    // Now wait for the initial provider profile to be set
-    waitForProviderLoad(function() {
-      checkUIStateMatchesProvider(gProviders[0]);
-
-      // Now activate "provider 2"
-      observeProviderSet(function () {
-        waitForProviderLoad(function() {
-          checkUIStateMatchesProvider(gProviders[1]);
-          next();
-        });
-      });
-      Social.activateFromOrigin("https://test1.example.com");
-    });
-  }
-}
-
-function checkUIStateMatchesProvider(provider) {
-  let profileData = getExpectedProfileData(provider);
-  // Bug 789863 - share button uses 'displayName', toolbar uses 'userName'
-  // Check the "share button"
-  let displayNameEl = document.getElementById("socialUserDisplayName");
-  is(displayNameEl.getAttribute("label"), profileData.displayName, "display name matches provider profile");
-  // The toolbar
-  let loginStatus = document.getElementsByClassName("social-statusarea-loggedInStatus");
-  for (let label of loginStatus) {
-    is(label.value, profileData.userName, "username name matches provider profile");
-  }
-  // Sidebar
-  is(document.getElementById("social-sidebar-browser").getAttribute("src"), provider.sidebarURL, "side bar URL is set");
-}
-
-function getExpectedProfileData(provider) {
-  // This data is defined in social_worker.js
-  if (provider.origin == "https://test1.example.com") {
-    return {
-      displayName: "Test1 User",
-      userName: "tester"
-    };
-  }
-
-  return {
-    displayName: "Kuma Lisa",
-    userName: "trickster"
-  };
-}
-
-function observeProviderSet(cb) {
-  Services.obs.addObserver(function providerSet(subject, topic, data) {
-    Services.obs.removeObserver(providerSet, "social:provider-set");
-    info("social:provider-set observer was notified");
-    // executeSoon to let the browser UI observers run first
-    executeSoon(cb);
-  }, "social:provider-set", false);
-}
-
-function waitForProviderLoad(cb) {
-  waitForCondition(function() {
-    return Social.provider.profile &&
-           Social.provider.profile.displayName;
-  }, cb, "waitForProviderLoad: provider profile was not set");
-}
--- a/browser/base/content/test/head.js
+++ b/browser/base/content/test/head.js
@@ -83,141 +83,29 @@ function waitForCondition(condition, nex
     if (condition()) {
       moveOn();
     }
     tries++;
   }, 100);
   var moveOn = function() { clearInterval(interval); nextTest(); };
 }
 
-// Check that a specified (string) URL hasn't been "remembered" (ie, is not
-// in history, will not appear in about:newtab or auto-complete, etc.)
-function ensureSocialUrlNotRemembered(url) {
-  let gh = Cc["@mozilla.org/browser/global-history;2"]
-           .getService(Ci.nsIGlobalHistory2);
-  let uri = Services.io.newURI(url, null, null);
-  ok(!gh.isVisited(uri), "social URL " + url + " should not be in global history");
-}
-
 function getTestPlugin() {
   var ph = Cc["@mozilla.org/plugin/host;1"].getService(Ci.nsIPluginHost);
   var tags = ph.getPluginTags();
 
   // Find the test plugin
   for (var i = 0; i < tags.length; i++) {
     if (tags[i].name == "Test Plug-in")
       return tags[i];
   }
   ok(false, "Unable to find plugin");
   return null;
 }
 
-function runSocialTestWithProvider(manifest, callback) {
-  let SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
-
-  let manifests = Array.isArray(manifest) ? manifest : [manifest];
-
-  // Check that none of the provider's content ends up in history.
-  registerCleanupFunction(function () {
-    manifests.forEach(function (m) {
-      for (let what of ['sidebarURL', 'workerURL', 'iconURL']) {
-        if (m[what]) {
-          ensureSocialUrlNotRemembered(m[what]);
-        }
-      }
-    });
-  });
-
-  info("runSocialTestWithProvider: " + manifests.toSource());
-
-  let providersAdded = 0;
-  let firstProvider;
-  manifests.forEach(function (m) {
-    SocialService.addProvider(m, function(provider) {
-      provider.active = true;
-
-      providersAdded++;
-      info("runSocialTestWithProvider: provider added");
-
-      // we want to set the first specified provider as the UI's provider
-      if (provider.origin == manifests[0].origin) {
-        firstProvider = provider;
-      }
-
-      // If we've added all the providers we need, call the callback to start
-      // the tests (and give it a callback it can call to finish them)
-      if (providersAdded == manifests.length) {
-        // Set the UI's provider and enable the feature
-        Social.provider = firstProvider;
-        Social.enabled = true;
-
-        registerCleanupFunction(function () {
-          // disable social before removing the providers to avoid providers
-          // being activated immediately before we get around to removing it.
-          Services.prefs.clearUserPref("social.enabled");
-          // if one test happens to fail, it is likely finishSocialTest will not
-          // be called, causing most future social tests to also fail as they
-          // attempt to add a provider which already exists - so work
-          // around that by also attempting to remove the test provider.
-          manifests.forEach(function (m) {
-            try {
-              SocialService.removeProvider(m.origin, finish);
-            } catch (ex) {}
-          });
-        });
-        function finishSocialTest() {
-          SocialService.removeProvider(provider.origin, finish);
-        }
-        callback(finishSocialTest);
-      }
-    });
-  });
-}
-
-
-function runSocialTests(tests, cbPreTest, cbPostTest, cbFinish) {
-  let testIter = Iterator(tests);
-
-  if (cbPreTest === undefined) {
-    cbPreTest = function(cb) {cb()};
-  }
-  if (cbPostTest === undefined) {
-    cbPostTest = function(cb) {cb()};
-  }
-
-  function runNextTest() {
-    let name, func;
-    try {
-      [name, func] = testIter.next();
-    } catch (err if err instanceof StopIteration) {
-      // out of items:
-      (cbFinish || finish)();
-      return;
-    }
-    // We run on a timeout as the frameworker also makes use of timeouts, so
-    // this helps keep the debug messages sane.
-    executeSoon(function() {
-      function cleanupAndRunNextTest() {
-        info("sub-test " + name + " complete");
-        cbPostTest(runNextTest);
-      }
-      cbPreTest(function() {
-        info("sub-test " + name + " starting");
-        try {
-          func.call(tests, cleanupAndRunNextTest);
-        } catch (ex) {
-          ok(false, "sub-test " + name + " failed: " + ex.toString() +"\n"+ex.stack);
-          cleanupAndRunNextTest();
-        }
-      })
-    });
-  }
-  runNextTest();
-}
-
 function updateBlocklist(aCallback) {
   var blocklistNotifier = Cc["@mozilla.org/extensions/blocklist;1"]
                           .getService(Ci.nsITimerCallback);
   var observer = function() {
     aCallback();
     Services.obs.removeObserver(observer, "blocklist-updated");
   };
   Services.obs.addObserver(observer, "blocklist-updated", false);
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/social/Makefile.in
@@ -0,0 +1,36 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+DEPTH		= @DEPTH@
+topsrcdir	= @top_srcdir@
+srcdir		= @srcdir@
+VPATH		= @srcdir@
+relativesrcdir  = @relativesrcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+_BROWSER_FILES = \
+                 head.js \
+                 browser_social.js \
+                 browser_social_toolbar.js \
+                 browser_social_shareButton.js \
+                 browser_social_sidebar.js \
+                 browser_social_flyout.js \
+                 browser_social_mozSocial_API.js \
+                 browser_social_isVisible.js \
+                 browser_social_chatwindow.js \
+                 browser_social_multiprovider.js \
+                 social_panel.html \
+                 social_share_image.png \
+                 social_sidebar.html \
+                 social_chat.html \
+                 social_flyout.html \
+                 social_window.html \
+                 social_worker.js \
+                 $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
+libs::	$(_BROWSER_FILES)
+	$(INSTALL) $(foreach f,$^,"$f") $(DEPTH)/_tests/testing/mochitest/browser/$(relativesrcdir)
rename from browser/base/content/test/browser_social.js
rename to browser/base/content/test/social/browser_social.js
--- a/browser/base/content/test/browser_social.js
+++ b/browser/base/content/test/social/browser_social.js
@@ -25,18 +25,18 @@ function portClosed(port) {
 }
 
 function test() {
   waitForExplicitFinish();
 
   let manifest = { // normal provider
     name: "provider 1",
     origin: "https://example.com",
-    sidebarURL: "https://example.com/browser/browser/base/content/test/social_sidebar.html",
-    workerURL: "https://example.com/browser/browser/base/content/test/social_worker.js",
+    sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html",
+    workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js",
     iconURL: "https://example.com/browser/browser/base/content/test/moz.png"
   };
   runSocialTestWithProvider(manifest, function (finishcb) {
     runSocialTests(tests, undefined, undefined, finishcb);
   });
 }
 
 var tests = {
@@ -48,29 +48,31 @@ var tests = {
       let topic = e.data.topic;
       switch (topic) {
         case "got-sidebar-message":
           ok(true, "got sidebar message");
           port.close();
           togglePrivateBrowsing(function () {
             ok(!Social.enabled, "Social shuts down during private browsing");
             togglePrivateBrowsing(function () {
+              ok(Social.provider.getWorkerPort(), "port still obtainable after PB")
               ok(Social.enabled, "Social enabled after private browsing");
               next();
             });
           });
           break;
       }
     };
   },
 
   testPrivateBrowsingSocialDisabled: function(next) {
     // test PB from the perspective of entering PB without social enabled
     // we expect social to be enabled at the start of the test, we need
     // to disable it before testing PB transitions.
+    ok(Social.enabled, "social is still enabled");
     let port = Social.provider.getWorkerPort();
     ok(port, "provider has a port");
     port.postMessage({topic: "test-init"});
     port.onmessage = function (e) {
       let topic = e.data.topic;
       switch (topic) {
         case "got-sidebar-message":
           ok(true, "got sidebar message");
rename from browser/base/content/test/browser_social_chatwindow.js
rename to browser/base/content/test/social/browser_social_chatwindow.js
--- a/browser/base/content/test/browser_social_chatwindow.js
+++ b/browser/base/content/test/social/browser_social_chatwindow.js
@@ -3,18 +3,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 function test() {
   waitForExplicitFinish();
 
   let manifest = { // normal provider
     name: "provider 1",
     origin: "https://example.com",
-    sidebarURL: "https://example.com/browser/browser/base/content/test/social_sidebar.html",
-    workerURL: "https://example.com/browser/browser/base/content/test/social_worker.js",
+    sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html",
+    workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js",
     iconURL: "https://example.com/browser/browser/base/content/test/moz.png"
   };
   let oldwidth = window.outerWidth; // we futz with this, so we restore it
   runSocialTestWithProvider(manifest, function (finishcb) {
     runSocialTests(tests, undefined, undefined, function () {
       let chats = document.getElementById("pinnedchats");
       ok(chats.children.length == 0, "no chatty children left behind");
       window.resizeTo(oldwidth, window.outerHeight);
@@ -97,17 +97,17 @@ var tests = {
       }
     }
     port.postMessage({topic: "test-init", data: { id: 1 }});
   },
   // In this case the *worker* opens a chat (so minimized is specified).
   // The worker then makes the same call again - as that second call also
   // specifies "minimized" the chat should *not* be restored.
   testWorkerChatWindowMinimized: function(next) {
-    const chatUrl = "https://example.com/browser/browser/base/content/test/social_chat.html";
+    const chatUrl = "https://example.com/browser/browser/base/content/test/social/social_chat.html";
     let port = Social.provider.getWorkerPort();
     let seen_opened = false;
     ok(port, "provider has a port");
     port.postMessage({topic: "test-init"});
     port.onmessage = function (e) {
       let topic = e.data.topic;
       switch (topic) {
         case "got-chatbox-message":
@@ -170,17 +170,17 @@ var tests = {
       }
     }
     let num = numToOpen;
     while (num-- > 0) {
       port.postMessage({topic: "test-chatbox-open", data: { id: num }});
     }
   },
   testWorkerChatWindow: function(next) {
-    const chatUrl = "https://example.com/browser/browser/base/content/test/social_chat.html";
+    const chatUrl = "https://example.com/browser/browser/base/content/test/social/social_chat.html";
     let port = Social.provider.getWorkerPort();
     ok(port, "provider has a port");
     port.postMessage({topic: "test-init"});
     port.onmessage = function (e) {
       let topic = e.data.topic;
       switch (topic) {
         case "got-chatbox-message":
           ok(true, "got a chat window opened");
@@ -409,17 +409,17 @@ var tests = {
           });
       }
     }
     port.postMessage({topic: "test-init", data: { id: 1 }});
   },
 
   testSecondTopLevelWindow: function(next) {
     // Bug 817782 - check chats work in new top-level windows.
-    const chatUrl = "https://example.com/browser/browser/base/content/test/social_chat.html";
+    const chatUrl = "https://example.com/browser/browser/base/content/test/social/social_chat.html";
     let port = Social.provider.getWorkerPort();
     let secondWindow;
     port.onmessage = function(e) {
       if (e.data.topic == "test-init-done") {
         secondWindow = OpenBrowserWindow();
         secondWindow.addEventListener("load", function loadListener() {
           secondWindow.removeEventListener("load", loadListener);
           port.postMessage({topic: "test-worker-chat", data: chatUrl});
@@ -432,17 +432,17 @@ var tests = {
       }
     }
     port.postMessage({topic: "test-init"});
   },
 
   testChatWindowChooser: function(next) {
     // Tests that when a worker creates a chat, it is opened in the correct
     // window.
-    const chatUrl = "https://example.com/browser/browser/base/content/test/social_chat.html";
+    const chatUrl = "https://example.com/browser/browser/base/content/test/social/social_chat.html";
     let chatId = 1;
     let port = Social.provider.getWorkerPort();
     port.postMessage({topic: "test-init"});
 
     function openChat(callback) {
       port.onmessage = function(e) {
         if (e.data.topic == "got-chatbox-message")
           callback();
@@ -476,17 +476,17 @@ var tests = {
         });
       })
     });
   },
 
   // XXX - note this must be the last test until we restore the login state
   // between tests...
   testCloseOnLogout: function(next) {
-    const chatUrl = "https://example.com/browser/browser/base/content/test/social_chat.html";
+    const chatUrl = "https://example.com/browser/browser/base/content/test/social/social_chat.html";
     let port = Social.provider.getWorkerPort();
     ok(port, "provider has a port");
     port.postMessage({topic: "test-init"});
     port.onmessage = function (e) {
       let topic = e.data.topic;
       switch (topic) {
         case "got-chatbox-message":
           ok(true, "got a chat window opened");
@@ -547,17 +547,17 @@ function get3ChatsForCollapsing(mode, cb
           cb(first, second, third);
         }, mode);
       }, mode);
     });
   }, mode);
 }
 
 function makeChat(mode, uniqueid, cb) {
-  const chatUrl = "https://example.com/browser/browser/base/content/test/social_chat.html";
+  const chatUrl = "https://example.com/browser/browser/base/content/test/social/social_chat.html";
   let provider = Social.provider;
   window.SocialChatBar.openChat(provider, chatUrl + "?id=" + uniqueid, function(chat) {
     // we can't callback immediately or we might close the chat during
     // this event which upsets the implementation - it is only 1/2 way through
     // handling the load event.
     chat.document.title = uniqueid;
     executeSoon(cb);
   }, mode);
rename from browser/base/content/test/browser_social_flyout.js
rename to browser/base/content/test/social/browser_social_flyout.js
--- a/browser/base/content/test/browser_social_flyout.js
+++ b/browser/base/content/test/social/browser_social_flyout.js
@@ -3,18 +3,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 function test() {
   waitForExplicitFinish();
 
   let manifest = { // normal provider
     name: "provider 1",
     origin: "https://example.com",
-    sidebarURL: "https://example.com/browser/browser/base/content/test/social_sidebar.html",
-    workerURL: "https://example.com/browser/browser/base/content/test/social_worker.js",
+    sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html",
+    workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js",
     iconURL: "https://example.com/browser/browser/base/content/test/moz.png"
   };
   runSocialTestWithProvider(manifest, function (finishcb) {
     runSocialTests(tests, undefined, undefined, finishcb);
   });
 }
 
 var tests = {
rename from browser/base/content/test/browser_social_isVisible.js
rename to browser/base/content/test/social/browser_social_isVisible.js
--- a/browser/base/content/test/browser_social_isVisible.js
+++ b/browser/base/content/test/social/browser_social_isVisible.js
@@ -3,18 +3,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 function test() {
   waitForExplicitFinish();
 
   let manifest = { // normal provider
     name: "provider 1",
     origin: "https://example.com",
-    sidebarURL: "https://example.com/browser/browser/base/content/test/social_sidebar.html",
-    workerURL: "https://example.com/browser/browser/base/content/test/social_worker.js",
+    sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html",
+    workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js",
     iconURL: "https://example.com/browser/browser/base/content/test/moz.png"
   };
   runSocialTestWithProvider(manifest, function (finishcb) {
     runSocialTests(tests, undefined, undefined, finishcb);
   });
 }
 
 var tests = {
rename from browser/base/content/test/browser_social_mozSocial_API.js
rename to browser/base/content/test/social/browser_social_mozSocial_API.js
--- a/browser/base/content/test/browser_social_mozSocial_API.js
+++ b/browser/base/content/test/social/browser_social_mozSocial_API.js
@@ -3,18 +3,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 function test() {
   waitForExplicitFinish();
 
   let manifest = { // normal provider
     name: "provider 1",
     origin: "https://example.com",
-    sidebarURL: "https://example.com/browser/browser/base/content/test/social_sidebar.html",
-    workerURL: "https://example.com/browser/browser/base/content/test/social_worker.js",
+    sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html",
+    workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js",
     iconURL: "https://example.com/browser/browser/base/content/test/moz.png"
   };
   runSocialTestWithProvider(manifest, function (finishcb) {
     runSocialTests(tests, undefined, undefined, finishcb);
   });
 }
 
 var tests = {
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/social/browser_social_multiprovider.js
@@ -0,0 +1,104 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+function test() {
+  waitForExplicitFinish();
+
+  runSocialTestWithProvider(gProviders, function (finishcb) {
+    runSocialTests(tests, undefined, undefined, finishcb);
+  });
+}
+
+let gProviders = [
+  {
+    name: "provider 1",
+    origin: "https://example.com",
+    sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html?provider1",
+    workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js",
+    iconURL: "chrome://branding/content/icon48.png"
+  },
+  {
+    name: "provider 2",
+    origin: "https://test1.example.com",
+    sidebarURL: "https://test1.example.com/browser/browser/base/content/test/social/social_sidebar.html?provider2",
+    workerURL: "https://test1.example.com/browser/browser/base/content/test/social/social_worker.js",
+    iconURL: "chrome://branding/content/icon48.png"
+  }
+];
+
+var tests = {
+  testProviderSwitch: function(next) {
+    function checkProviderMenu(selectedProvider) {
+      let menu = document.getElementById("social-statusarea-popup");
+      let menuProviders = menu.querySelectorAll(".social-provider-menuitem");
+      is(menuProviders.length, gProviders.length, "correct number of providers listed in the menu");
+      // Find the selectedProvider's menu item
+      let el = menu.getElementsByAttribute("origin", selectedProvider.origin);
+      is(el.length, 1, "selected provider menu item exists");
+      is(el[0].getAttribute("checked"), "true", "selected provider menu item is checked");
+    }
+
+    checkProviderMenu(gProviders[0]);
+
+    // Now wait for the initial provider profile to be set
+    waitForProviderLoad(function() {
+      checkUIStateMatchesProvider(gProviders[0]);
+
+      // Now activate "provider 2"
+      observeProviderSet(function () {
+        waitForProviderLoad(function() {
+          checkUIStateMatchesProvider(gProviders[1]);
+          next();
+        });
+      });
+      Social.activateFromOrigin("https://test1.example.com");
+    });
+  }
+}
+
+function checkUIStateMatchesProvider(provider) {
+  let profileData = getExpectedProfileData(provider);
+  // Bug 789863 - share button uses 'displayName', toolbar uses 'userName'
+  // Check the "share button"
+  let displayNameEl = document.getElementById("socialUserDisplayName");
+  is(displayNameEl.getAttribute("label"), profileData.displayName, "display name matches provider profile");
+  // The toolbar
+  let loginStatus = document.getElementsByClassName("social-statusarea-loggedInStatus");
+  for (let label of loginStatus) {
+    is(label.value, profileData.userName, "username name matches provider profile");
+  }
+  // Sidebar
+  is(document.getElementById("social-sidebar-browser").getAttribute("src"), provider.sidebarURL, "side bar URL is set");
+}
+
+function getExpectedProfileData(provider) {
+  // This data is defined in social_worker.js
+  if (provider.origin == "https://test1.example.com") {
+    return {
+      displayName: "Test1 User",
+      userName: "tester"
+    };
+  }
+
+  return {
+    displayName: "Kuma Lisa",
+    userName: "trickster"
+  };
+}
+
+function observeProviderSet(cb) {
+  Services.obs.addObserver(function providerSet(subject, topic, data) {
+    Services.obs.removeObserver(providerSet, "social:provider-set");
+    info("social:provider-set observer was notified");
+    // executeSoon to let the browser UI observers run first
+    executeSoon(cb);
+  }, "social:provider-set", false);
+}
+
+function waitForProviderLoad(cb) {
+  waitForCondition(function() {
+    return Social.provider.profile &&
+           Social.provider.profile.displayName;
+  }, cb, "waitForProviderLoad: provider profile was not set");
+}
rename from browser/base/content/test/browser_social_shareButton.js
rename to browser/base/content/test/social/browser_social_shareButton.js
--- a/browser/base/content/test/browser_social_shareButton.js
+++ b/browser/base/content/test/social/browser_social_shareButton.js
@@ -22,18 +22,18 @@ function test() {
 }
 
 function tabLoaded() {
   ok(Social, "Social module loaded");
 
   let manifest = { // normal provider
     name: "provider 1",
     origin: "https://example.com",
-    sidebarURL: "https://example.com/browser/browser/base/content/test/social_sidebar.html",
-    workerURL: "https://example.com/browser/browser/base/content/test/social_worker.js",
+    sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html",
+    workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js",
     iconURL: "https://example.com/browser/browser/base/content/test/moz.png"
   };
   runSocialTestWithProvider(manifest, function (finishcb) {
     gFinishCB = finishcb;
     testInitial();
   });
 }
 
@@ -63,26 +63,26 @@ function testInitial(finishcb) {
     let displayName = document.getElementById("socialUserDisplayName");
     is(displayName.label, profile.displayName, "display name is set");
     ok(!document.getElementById("unsharePopupHeader").hidden, "user profile is visible");
 
     // Check the strings from our worker actually ended up on the button.
     is(shareButton.getAttribute("tooltiptext"), "Share this page", "check tooltip text is correct");
     is(shareStatusLabel.getAttribute("value"), "", "check status label text is blank");
     // Check the relative URL was resolved correctly (note this image has offsets of zero...)
-    is(shareButton.src, 'https://example.com/browser/browser/base/content/test/social_share_image.png', "check image url is correct");
+    is(shareButton.src, 'https://example.com/browser/browser/base/content/test/social/social_share_image.png', "check image url is correct");
 
     // Test clicking the share button
     shareButton.addEventListener("click", function listener() {
       shareButton.removeEventListener("click", listener);
       is(shareButton.hasAttribute("shared"), true, "Share button should have 'shared' attribute after share button is clicked");
       is(shareButton.getAttribute("tooltiptext"), "Unshare this page", "check tooltip text is correct");
       is(shareStatusLabel.getAttribute("value"), "This page has been shared", "check status label text is correct");
       // Check the URL and offsets were applied correctly
-      is(shareButton.src, 'https://example.com/browser/browser/base/content/test/social_share_image.png', "check image url is correct");
+      is(shareButton.src, 'https://example.com/browser/browser/base/content/test/social/social_share_image.png', "check image url is correct");
       executeSoon(testSecondClick.bind(window, testPopupOKButton));
     });
     shareButton.click();
   }, "provider didn't provide user-recommend-prompt response");
 }
 
 function testSecondClick(nextTest) {
   let {shareButton, unsharePopup} = SocialShareButton;
rename from browser/base/content/test/browser_social_sidebar.js
rename to browser/base/content/test/social/browser_social_sidebar.js
--- a/browser/base/content/test/browser_social_sidebar.js
+++ b/browser/base/content/test/social/browser_social_sidebar.js
@@ -3,18 +3,18 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 function test() {
   waitForExplicitFinish();
 
   let manifest = { // normal provider
     name: "provider 1",
     origin: "https://example.com",
-    sidebarURL: "https://example.com/browser/browser/base/content/test/social_sidebar.html",
-    workerURL: "https://example.com/browser/browser/base/content/test/social_worker.js",
+    sidebarURL: "https://example.com/browser/browser/base/content/test/social/social_sidebar.html",
+    workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js",
     iconURL: "https://example.com/browser/browser/base/content/test/moz.png"
   };
   runSocialTestWithProvider(manifest, doTest);
 }
 
 function doTest(finishcb) {
   ok(SocialSidebar.canShow, "social sidebar should be able to be shown");
   ok(SocialSidebar.opened, "social sidebar should be open by default");
rename from browser/base/content/test/browser_social_toolbar.js
rename to browser/base/content/test/social/browser_social_toolbar.js
--- a/browser/base/content/test/browser_social_toolbar.js
+++ b/browser/base/content/test/social/browser_social_toolbar.js
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 function test() {
   waitForExplicitFinish();
 
   let manifest = { // normal provider
     name: "provider 1",
     origin: "https://example.com",
-    workerURL: "https://example.com/browser/browser/base/content/test/social_worker.js",
+    workerURL: "https://example.com/browser/browser/base/content/test/social/social_worker.js",
     iconURL: "https://example.com/browser/browser/base/content/test/moz.png"
   };
   runSocialTestWithProvider(manifest, function (finishcb) {
     runSocialTests(tests, undefined, undefined, finishcb);
   });
 }
 
 var tests = {
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/social/head.js
@@ -0,0 +1,129 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+function waitForCondition(condition, nextTest, errorMsg) {
+  var tries = 0;
+  var interval = setInterval(function() {
+    if (tries >= 30) {
+      ok(false, errorMsg);
+      moveOn();
+    }
+    if (condition()) {
+      moveOn();
+    }
+    tries++;
+  }, 100);
+  var moveOn = function() { clearInterval(interval); nextTest(); };
+}
+
+// Check that a specified (string) URL hasn't been "remembered" (ie, is not
+// in history, will not appear in about:newtab or auto-complete, etc.)
+function ensureSocialUrlNotRemembered(url) {
+  let gh = Cc["@mozilla.org/browser/global-history;2"]
+           .getService(Ci.nsIGlobalHistory2);
+  let uri = Services.io.newURI(url, null, null);
+  ok(!gh.isVisited(uri), "social URL " + url + " should not be in global history");
+}
+
+function runSocialTestWithProvider(manifest, callback) {
+  let SocialService = Cu.import("resource://gre/modules/SocialService.jsm", {}).SocialService;
+
+  let manifests = Array.isArray(manifest) ? manifest : [manifest];
+
+  // Check that none of the provider's content ends up in history.
+  registerCleanupFunction(function () {
+    manifests.forEach(function (m) {
+      for (let what of ['sidebarURL', 'workerURL', 'iconURL']) {
+        if (m[what]) {
+          ensureSocialUrlNotRemembered(m[what]);
+        }
+      }
+    });
+  });
+
+  info("runSocialTestWithProvider: " + manifests.toSource());
+
+  let providersAdded = 0;
+  let firstProvider;
+  manifests.forEach(function (m) {
+    SocialService.addProvider(m, function(provider) {
+      provider.active = true;
+
+      providersAdded++;
+      info("runSocialTestWithProvider: provider added");
+
+      // we want to set the first specified provider as the UI's provider
+      if (provider.origin == manifests[0].origin) {
+        firstProvider = provider;
+      }
+
+      // If we've added all the providers we need, call the callback to start
+      // the tests (and give it a callback it can call to finish them)
+      if (providersAdded == manifests.length) {
+        // Set the UI's provider and enable the feature
+        Social.provider = firstProvider;
+        Social.enabled = true;
+
+        registerCleanupFunction(function () {
+          // disable social before removing the providers to avoid providers
+          // being activated immediately before we get around to removing it.
+          Services.prefs.clearUserPref("social.enabled");
+          // if one test happens to fail, it is likely finishSocialTest will not
+          // be called, causing most future social tests to also fail as they
+          // attempt to add a provider which already exists - so work
+          // around that by also attempting to remove the test provider.
+          manifests.forEach(function (m) {
+            try {
+              SocialService.removeProvider(m.origin, finish);
+            } catch (ex) {}
+          });
+        });
+        function finishSocialTest() {
+          SocialService.removeProvider(provider.origin, finish);
+        }
+        callback(finishSocialTest);
+      }
+    });
+  });
+}
+
+function runSocialTests(tests, cbPreTest, cbPostTest, cbFinish) {
+  let testIter = Iterator(tests);
+
+  if (cbPreTest === undefined) {
+    cbPreTest = function(cb) {cb()};
+  }
+  if (cbPostTest === undefined) {
+    cbPostTest = function(cb) {cb()};
+  }
+
+  function runNextTest() {
+    let name, func;
+    try {
+      [name, func] = testIter.next();
+    } catch (err if err instanceof StopIteration) {
+      // out of items:
+      (cbFinish || finish)();
+      return;
+    }
+    // We run on a timeout as the frameworker also makes use of timeouts, so
+    // this helps keep the debug messages sane.
+    executeSoon(function() {
+      function cleanupAndRunNextTest() {
+        info("sub-test " + name + " complete");
+        cbPostTest(runNextTest);
+      }
+      cbPreTest(function() {
+        info("sub-test " + name + " starting");
+        try {
+          func.call(tests, cleanupAndRunNextTest);
+        } catch (ex) {
+          ok(false, "sub-test " + name + " failed: " + ex.toString() +"\n"+ex.stack);
+          cleanupAndRunNextTest();
+        }
+      })
+    });
+  }
+  runNextTest();
+}
rename from browser/base/content/test/social_chat.html
rename to browser/base/content/test/social/social_chat.html
rename from browser/base/content/test/social_flyout.html
rename to browser/base/content/test/social/social_flyout.html
rename from browser/base/content/test/social_panel.html
rename to browser/base/content/test/social/social_panel.html
rename from browser/base/content/test/social_share_image.png
rename to browser/base/content/test/social/social_share_image.png
rename from browser/base/content/test/social_sidebar.html
rename to browser/base/content/test/social/social_sidebar.html
rename from browser/base/content/test/social_window.html
rename to browser/base/content/test/social/social_window.html
rename from browser/base/content/test/social_worker.js
rename to browser/base/content/test/social/social_worker.js
--- a/browser/base/content/test/social_worker.js
+++ b/browser/base/content/test/social/social_worker.js
@@ -100,36 +100,36 @@ onconnect = function(e) {
           };
         }
         port.postMessage({topic: "social.user-profile", data: profile});
         break;
       case "test-ambient-notification":
         let icon = {
           name: "testIcon",
           iconURL: "chrome://browser/skin/Info.png",
-          contentPanel: "https://example.com/browser/browser/base/content/test/social_panel.html",
+          contentPanel: "https://example.com/browser/browser/base/content/test/social/social_panel.html",
           counter: 1
         };
         apiPort.postMessage({topic: "social.ambient-notification", data: icon});
         break;
       case "test-isVisible":
         sidebarPort.postMessage({topic: "test-isVisible"});
         break;
       case "test-isVisible-response":
         testPort.postMessage({topic: "got-isVisible-response", result: event.data.result});
         break;
       case "social.user-recommend-prompt":
         port.postMessage({
           topic: "social.user-recommend-prompt-response",
           data: {
             images: {
               // this one is relative to test we handle relative ones.
-              share: "browser/browser/base/content/test/social_share_image.png",
+              share: "browser/browser/base/content/test/social/social_share_image.png",
               // absolute to check we handle them too.
-              unshare: "https://example.com/browser/browser/base/content/test/social_share_image.png"
+              unshare: "https://example.com/browser/browser/base/content/test/social/social_share_image.png"
             },
             messages: {
               shareTooltip: "Share this page",
               unshareTooltip: "Unshare this page",
               sharedLabel: "This page has been shared",
               unsharedLabel: "This page is no longer shared",
               unshareLabel: "You have already shared this page",
               portraitLabel: "Your pretty face",
--- a/browser/components/places/tests/unit/test_browserGlue_prefs.js
+++ b/browser/components/places/tests/unit/test_browserGlue_prefs.js
@@ -22,17 +22,17 @@ function waitForImportAndSmartBookmarks(
     Services.obs.removeObserver(waitImport, "bookmarks-restore-success");
     // Delay to test eventual smart bookmarks creation.
     do_execute_soon(function () {
       promiseAsyncUpdates().then(aCallback);
     });
   }, "bookmarks-restore-success", false);
 }
 
-let gTests = [
+[
 
   // This test must be the first one.
   function test_checkPreferences() {
     // Initialize Places through the History Service and check that a new
     // database has been created.
     do_check_eq(PlacesUtils.history.databaseStatus,
                 PlacesUtils.history.DATABASE_STATUS_CREATE);
 
@@ -258,17 +258,17 @@ let gTests = [
     });
     // Force nsBrowserGlue::_initPlaces()
     do_log_info("Simulate Places init");
     bg.QueryInterface(Ci.nsIObserver).observe(null,
                                               TOPIC_BROWSERGLUE_TEST,
                                               TOPICDATA_FORCE_PLACES_INIT);
   }
 
-];
+].forEach(add_test);
 
 do_register_cleanup(function () {
   remove_all_bookmarks();
   remove_bookmarks_html();
   remove_all_JSON_backups();
 });
 
 function run_test()
--- a/browser/config/tooltool-manifests/linux32/clang.manifest
+++ b/browser/config/tooltool-manifests/linux32/clang.manifest
@@ -1,17 +1,17 @@
 [
 {
-"clang_version": "r169139"
+"clang_version": "r169730"
 },
 {
 "size": 47,
 "digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa",
 "algorithm": "sha512",
 "filename": "setup.sh"
 },
 {
-"size": 62513298,
-"digest": "1c9dfc75d4a06438da4d079282178274054e07d814ec6bc8e45c9e62589293df11858c74ce301c53b5bd758c56dc1c593a97cd5034b47ea753c518fd9af69ea4",
+"size": 61875575,
+"digest": "7098e1cc85a8ae45672333320c7673c284023366fbe6d4fab3e9276960b7f92fd74ee63d0ad6c43a86fd96a1b886408993479260ac897fa6fe101c4a9fb807b1",
 "algorithm": "sha512",
 "filename": "clang.tar.bz2"
 }
 ]
--- a/browser/config/tooltool-manifests/linux64/clang.manifest
+++ b/browser/config/tooltool-manifests/linux64/clang.manifest
@@ -1,17 +1,17 @@
 [
 {
-"clang_version": "r169139"
+"clang_version": "r169730"
 },
 {
 "size": 47,
 "digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa",
 "algorithm": "sha512",
 "filename": "setup.sh"
 },
 {
-"size": 62856551,
-"digest": "3542a25815f89555f2e2b4c67fbffa432c341d824395b452698d8d90ee0216e045531adcad14bf7071be1a41c016b4652cf955270b652bcdbd7b04a02cc3c9f9",
+"size": 62279267,
+"digest": "0c9f87e3d7675feaa79b6d5d0997c8f370785901b8668f51da3339ae674291b3946e9d76629adb1c4ccd15aa851d84e4cd39ddd9032c916cc75233fe73c68f2e",
 "algorithm": "sha512",
 "filename": "clang.tar.bz2"
 }
 ]
--- a/browser/config/tooltool-manifests/macosx32/releng.manifest
+++ b/browser/config/tooltool-manifests/macosx32/releng.manifest
@@ -1,17 +1,17 @@
 [
 {
-"clang_version": "r169139"
+"clang_version": "r169730"
 },
 {
 "size": 47,
 "digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa",
 "algorithm": "sha512",
 "filename": "setup.sh"
 },
 {
-"size": 56158651,
-"digest": "38d718f20a8fa9218e22ade312e724e6c9cdd7c6650e023cfdc21b5505fe7aa3743ae41c0abd717a1bbccec4c4271be2fa82d0e2f96c91e693d70e33b4dc00d6",
+"size": 56115091,
+"digest": "d7188264f28d6f6a84fab9737520cad22fe3d575917a87fc110d0b9a2033617c35da83530ea20553f5c55a996459f750fa2d0c49288c1fb9671f6252a92cf4c9",
 "algorithm": "sha512",
 "filename": "clang.tar.bz2"
 }
 ]
--- a/browser/config/tooltool-manifests/macosx64/releng.manifest
+++ b/browser/config/tooltool-manifests/macosx64/releng.manifest
@@ -1,17 +1,17 @@
 [
 {
-"clang_version": "r169139"
+"clang_version": "r169730"
 },
 {
 "size": 47,
 "digest": "2005a41fe97a5e00997063705f39d42b6a43b1cf7ba306cbc7b1513de34cdcd050fc6326efa2107f19ba0cc67914745dbf13154fa748010a93cf072481ef4aaa",
 "algorithm": "sha512",
 "filename": "setup.sh"
 },
 {
-"size": 56158651,
-"digest": "38d718f20a8fa9218e22ade312e724e6c9cdd7c6650e023cfdc21b5505fe7aa3743ae41c0abd717a1bbccec4c4271be2fa82d0e2f96c91e693d70e33b4dc00d6",
+"size": 56115091,
+"digest": "d7188264f28d6f6a84fab9737520cad22fe3d575917a87fc110d0b9a2033617c35da83530ea20553f5c55a996459f750fa2d0c49288c1fb9671f6252a92cf4c9",
 "algorithm": "sha512",
 "filename": "clang.tar.bz2"
 }
 ]
--- a/browser/devtools/inspector/test/Makefile.in
+++ b/browser/devtools/inspector/test/Makefile.in
@@ -23,17 +23,17 @@ include $(topsrcdir)/config/rules.mk
 		browser_inspector_invalidate.js \
 		browser_inspector_menu.js \
 		browser_inspector_pseudoClass_menu.js \
 		browser_inspector_destroyselection.html \
 		browser_inspector_destroyselection.js \
 		browser_inspector_bug_699308_iframe_navigation.js \
 		browser_inspector_bug_672902_keyboard_shortcuts.js \
 		browser_inspector_bug_566084_location_changed.js \
-		browser_inspector_sidebarstate.js \
+		$(filter disabled-temporarily--bug-816990, browser_inspector_sidebarstate.js) \
 		browser_inspector_pseudoclass_lock.js \
 		browser_inspector_cmd_inspect.js \
 		browser_inspector_cmd_inspect.html \
 		browser_inspector_highlighter_autohide.js \
 		browser_inspector_changes.js \
 		browser_inspector_bug_674871.js \
 		head.js \
 		helpers.js \
--- a/browser/makefiles.sh
+++ b/browser/makefiles.sh
@@ -94,16 +94,17 @@ else
     browser/themes/winstripe/communicator/Makefile
   "
 fi
 
 if [ "$ENABLE_TESTS" ]; then
   add_makefiles "
     browser/base/content/test/Makefile
     browser/base/content/test/newtab/Makefile
+    browser/base/content/test/social/Makefile
     browser/components/certerror/test/Makefile
     browser/components/dirprovider/tests/Makefile
     browser/components/downloads/test/Makefile
     browser/components/downloads/test/browser/Makefile
     browser/components/preferences/tests/Makefile
     browser/components/search/test/Makefile
     browser/components/sessionstore/test/Makefile
     browser/components/shell/test/Makefile
--- a/browser/themes/gnomestripe/browser.css
+++ b/browser/themes/gnomestripe/browser.css
@@ -1266,16 +1266,33 @@ toolbar[iconsize="small"] #feed-button {
 #webapps-notification-icon {
   list-style-image: url(chrome://browser/skin/webapps-16.png);
 }
 
 #plugins-notification-icon {
   list-style-image: url(chrome://mozapps/skin/plugins/pluginGeneric-16.png);
 }
 
+#blocked-plugins-notification-icon {
+  list-style-image: url(chrome://mozapps/skin/plugins/notifyPluginBlocked.png);
+}
+
+#blocked-plugins-notification-icon[showing] {
+  animation: pluginBlockedNotification 500ms ease 0s 5 alternate both;
+}
+
+@keyframes pluginBlockedNotification {
+  from {
+    opacity: 0;
+  }
+  to {
+    opacity: 1;
+  }
+}
+
 #webRTC-notification-icon {
   list-style-image: url(chrome://browser/skin/webRTC-shareDevice-16.png);
 }
 
 #treecolAutoCompleteImage {
   max-width : 36px;
 }
 
--- a/browser/themes/pinstripe/browser.css
+++ b/browser/themes/pinstripe/browser.css
@@ -3044,16 +3044,40 @@ toolbarbutton.chevron > .toolbarbutton-m
   #webapps-notification-icon {
     list-style-image: url(chrome://browser/skin/webapps-16@2x.png);
   }
 }
 
 #plugins-notification-icon {
   list-style-image: url(chrome://mozapps/skin/plugins/pluginGeneric-16.png);
 }
+
+#blocked-plugins-notification-icon {
+  list-style-image: url(chrome://mozapps/skin/plugins/notifyPluginBlocked.png);
+}
+
+@media (min-resolution: 2dppx) {
+  #blocked-plugins-notification-icon {
+    list-style-image: url(chrome://mozapps/skin/plugins/pluginBlocked.png);
+  }
+}
+
+#blocked-plugins-notification-icon[showing] {
+  animation: pluginBlockedNotification 500ms ease 0s 5 alternate both;
+}
+
+@keyframes pluginBlockedNotification {
+  from {
+    opacity: 0;
+  }
+  to {
+    opacity: 1;
+  }
+}
+
 @media (min-resolution: 2dppx) {
   #plugins-notification-icon {
     list-style-image: url(chrome://mozapps/skin/plugins/pluginGeneric.png);
   }
 }
 
 #webRTC-notification-icon {
   list-style-image: url(chrome://browser/skin/webRTC-shareDevice-16.png);
--- a/browser/themes/winstripe/browser.css
+++ b/browser/themes/winstripe/browser.css
@@ -2395,16 +2395,33 @@ toolbarbutton.bookmark-item[dragover="tr
 #webapps-notification-icon {
   list-style-image: url(chrome://browser/skin/webapps-16.png);
 }
 
 #plugins-notification-icon {
   list-style-image: url(chrome://mozapps/skin/plugins/pluginGeneric-16.png);
 }
 
+#blocked-plugins-notification-icon {
+  list-style-image: url(chrome://mozapps/skin/plugins/notifyPluginBlocked.png);
+}
+
+#blocked-plugins-notification-icon[showing] {
+  animation: pluginBlockedNotification 500ms ease 0s 5 alternate both;
+}
+
+@keyframes pluginBlockedNotification {
+  from {
+    opacity: 0;
+  }
+  to {
+    opacity: 1;
+  }
+}
+
 #webRTC-notification-icon {
   list-style-image: url(chrome://browser/skin/webRTC-shareDevice-16.png);
 }
 
 #identity-popup-container {
   min-width: 280px;
 }
 
--- a/build/Makefile.in
+++ b/build/Makefile.in
@@ -170,18 +170,16 @@ libs:: $(topsrcdir)/tools/rb/fix_stack_u
 	$(INSTALL) $< $(DIST)/bin
 
 # Unit tests for ManifestParser
 check::
 	$(PYTHON) $(topsrcdir)/config/pythonpath.py -I$(srcdir) \
 	  $(srcdir)/tests/test.py
 
 ifeq ($(OS_ARCH),Darwin)
-libs:: $(topsrcdir)/tools/rb/fix-macosx-stack.pl
-	$(INSTALL) $< $(DIST)/bin
 libs:: $(topsrcdir)/tools/rb/fix_macosx_stack.py
 	$(INSTALL) $< $(DIST)/bin
 
 # Basic unit tests for some stuff in the unify script
 check::
 # build x64/i386 binaries, and unify them
 	rm -f unify-test-x64 unify-test-i386 unify-test-universal
 	$(HOST_CC) -arch x86_64 $(srcdir)/unify-test.c -o unify-test-x64
--- a/build/unix/build-clang/build-clang.py
+++ b/build/unix/build-clang/build-clang.py
@@ -1,14 +1,14 @@
 #!/usr/bin/python
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
-llvm_revision = "169139"
+llvm_revision = "169730"
 moz_version = "moz0"
 
 ##############################################
 
 import os
 import os.path
 import shutil
 import tarfile
@@ -27,22 +27,23 @@ def run_in(path, args):
     check_run(args)
     os.chdir(d)
 
 def patch(patch, plevel, srcdir):
     patch = os.path.realpath(patch)
     check_run(['patch', '-d', srcdir, '-p%s' % plevel, '-i', patch, '--fuzz=0',
                '-s'])
 
-def build_package(package_source_dir, package_build_dir, configure_args):
+def build_package(package_source_dir, package_build_dir, configure_args,
+                  make_args):
     if not os.path.exists(package_build_dir):
         os.mkdir(package_build_dir)
     run_in(package_build_dir,
            ["%s/configure" % package_source_dir] + configure_args)
-    run_in(package_build_dir, ["make", "-j8"])
+    run_in(package_build_dir, ["make", "-j8"] + make_args)
     run_in(package_build_dir, ["make", "install"])
 
 def with_env(env, f):
     old_env = os.environ.copy()
     os.environ.update(env)
     f()
     os.environ.clear()
     os.environ.update(old_env)
@@ -106,17 +107,18 @@ def build_one_stage_aux(stage_dir, is_st
     build_dir = stage_dir + "/build"
     inst_dir = stage_dir + "/clang"
 
     configure_opts = ["--enable-optimized",
                       "--enable-targets=x86,x86_64,arm",
                       "--disable-assertions",
                       "--prefix=%s" % inst_dir,
                       "--with-gcc-toolchain=/tools/gcc-4.5-0moz3"]
-    build_package(llvm_source_dir, build_dir, configure_opts)
+    build_package(llvm_source_dir, build_dir, configure_opts,
+                  ["CLANG_IS_PRODUCTION=1"])
 
 if isDarwin:
     os.environ['MACOSX_DEPLOYMENT_TARGET'] = '10.7'
 
 if not os.path.exists(source_dir):
     os.makedirs(source_dir)
     svn_co("http://llvm.org/svn/llvm-project/llvm/branches/release_32",
            llvm_source_dir, llvm_revision)
--- a/content/html/content/public/nsHTMLMediaElement.h
+++ b/content/html/content/public/nsHTMLMediaElement.h
@@ -582,16 +582,23 @@ protected:
    */
   void ProcessMediaFragmentURI();
 
   /**
    * Mute or unmute the audio, without changing the value that |muted| reports.
    */
   void SetMutedInternal(bool aMuted);
 
+  /**
+   * Suspend (if aPauseForInactiveDocument) or resume element playback and
+   * resource download.  If aSuspendEvents is true, event delivery is
+   * suspended (and events queued) until the element is resumed.
+   */
+  void SuspendOrResumeElement(bool aPauseElement, bool aSuspendEvents);
+
   // Get the nsHTMLMediaElement object if the decoder is being used from an
   // HTML media element, and null otherwise.
   virtual nsHTMLMediaElement* GetMediaElement() MOZ_FINAL MOZ_OVERRIDE
   {
     return this;
   }
 
   // Return true if decoding should be paused
@@ -806,18 +813,22 @@ protected:
   bool mAudioCaptured;
 
   // If TRUE then the media element was actively playing before the currently
   // in progress seeking. If FALSE then the media element is either not seeking
   // or was not actively playing before the current seek. Used to decide whether
   // to raise the 'waiting' event as per 4.7.1.8 in HTML 5 specification.
   bool mPlayingBeforeSeek;
 
-  // True iff this element is paused because the document is inactive
-  bool mPausedForInactiveDocument;
+  // True iff this element is paused because the document is inactive or has
+  // been suspended by the audio channel service.
+  bool mPausedForInactiveDocumentOrChannel;
+
+  // True iff event delivery is suspended (mPausedForInactiveDocumentOrChannel must also be true).
+  bool mEventDeliveryPaused;
 
   // True if we've reported a "waiting" event since the last
   // readyState change to HAVE_CURRENT_DATA.
   bool mWaitingFired;
 
   // True if we're running the "load()" method.
   bool mIsRunningLoadMethod;
 
@@ -881,18 +892,18 @@ protected:
   // information to give it as a hint to the channel for it to bypass the
   // sniffing phase, that would fail because sniffing only works when applied to
   // the first bytes of the stream.
   nsCString mMimeType;
 
   // Audio Channel Type.
   mozilla::dom::AudioChannelType mAudioChannelType;
 
-  // The audiochannel has been muted
-  bool mChannelMuted;
+  // The audiochannel has been suspended.
+  bool mChannelSuspended;
 
   // Is this media element playing?
   bool mPlayingThroughTheAudioChannel;
 
   // An agent used to join audio channel service.
   nsCOMPtr<nsIAudioChannelAgent> mAudioChannelAgent;
 };
 
--- a/content/html/content/src/nsHTMLMediaElement.cpp
+++ b/content/html/content/src/nsHTMLMediaElement.cpp
@@ -1551,17 +1551,17 @@ NS_IMETHODIMP nsHTMLMediaElement::GetMut
 {
   *aMuted = mMuted;
 
   return NS_OK;
 }
 
 void nsHTMLMediaElement::SetMutedInternal(bool aMuted)
 {
-  float effectiveVolume = aMuted || mChannelMuted ? 0.0f : float(mVolume);
+  float effectiveVolume = aMuted ? 0.0f : float(mVolume);
 
   if (mDecoder) {
     mDecoder->SetVolume(effectiveVolume);
   } else if (mAudioStream) {
     mAudioStream->SetVolume(effectiveVolume);
   } else if (mSrcStream) {
     GetSrcMediaStream()->SetAudioOutputVolume(this, effectiveVolume);
   }
@@ -1748,17 +1748,18 @@ nsHTMLMediaElement::nsHTMLMediaElement(a
     mBegun(false),
     mLoadedFirstFrame(false),
     mAutoplaying(true),
     mAutoplayEnabled(true),
     mPaused(true),
     mMuted(false),
     mAudioCaptured(false),
     mPlayingBeforeSeek(false),
-    mPausedForInactiveDocument(false),
+    mPausedForInactiveDocumentOrChannel(false),
+    mEventDeliveryPaused(false),
     mWaitingFired(false),
     mIsRunningLoadMethod(false),
     mIsLoadingFromSourceChildren(false),
     mDelayingLoadEvent(false),
     mIsRunningSelectResource(false),
     mHaveQueuedSelectResource(false),
     mSuspendedAfterFirstFrame(false),
     mAllowSuspendAfterFirstFrame(true),
@@ -1766,17 +1767,17 @@ nsHTMLMediaElement::nsHTMLMediaElement(a
     mHasSelfReference(false),
     mShuttingDown(false),
     mSuspendedForPreloadNone(false),
     mMediaSecurityVerified(false),
     mCORSMode(CORS_NONE),
     mHasAudio(false),
     mDownloadSuspendedByCache(false),
     mAudioChannelType(AUDIO_CHANNEL_NORMAL),
-    mChannelMuted(false),
+    mChannelSuspended(false),
     mPlayingThroughTheAudioChannel(false)
 {
 #ifdef PR_LOGGING
   if (!gMediaElementLog) {
     gMediaElementLog = PR_NewLogModule("nsMediaElement");
   }
   if (!gMediaElementEventsLog) {
     gMediaElementEventsLog = PR_NewLogModule("nsMediaElementEvents");
@@ -1872,17 +1873,17 @@ NS_IMETHODIMP nsHTMLMediaElement::Play()
     ResumeLoad(PRELOAD_ENOUGH);
   }
   // Even if we just did Load() or ResumeLoad(), we could already have a decoder
   // here if we managed to clone an existing decoder.
   if (mDecoder) {
     if (mDecoder->IsEnded()) {
       SetCurrentTime(0);
     }
-    if (!mPausedForInactiveDocument) {
+    if (!mPausedForInactiveDocumentOrChannel) {
       nsresult rv = mDecoder->Play();
       NS_ENSURE_SUCCESS(rv, rv);
     }
   }
 
   if (mCurrentPlayRangeStart == -1.0) {
     GetCurrentTime(&mCurrentPlayRangeStart);
   }
@@ -2298,17 +2299,19 @@ nsresult nsHTMLMediaElement::FinishDecod
                                                 MediaDecoder* aCloneDonor)
 {
   mNetworkState = nsIDOMHTMLMediaElement::NETWORK_LOADING;
 
   // Force a same-origin check before allowing events for this media resource.
   mMediaSecurityVerified = false;
 
   // The new stream has not been suspended by us.
-  mPausedForInactiveDocument = false;
+  mPausedForInactiveDocumentOrChannel = false;
+  mPendingEvents.Clear();
+  mEventDeliveryPaused = false;
 
   aDecoder->SetAudioChannelType(mAudioChannelType);
   aDecoder->SetAudioCaptured(mAudioCaptured);
   aDecoder->SetVolume(mMuted ? 0.0 : mVolume);
   for (uint32_t i = 0; i < mOutputStreams.Length(); ++i) {
     OutputMediaStream* ms = &mOutputStreams[i];
     aDecoder->AddOutputStream(ms->mStream->GetStream()->AsProcessedStream(),
         ms->mFinishWhenEnded);
@@ -2329,17 +2332,17 @@ nsresult nsHTMLMediaElement::FinishDecod
   NotifyDecoderPrincipalChanged();
 
   // We may want to suspend the new stream now.
   // This will also do an AddRemoveSelfReference.
   NotifyOwnerDocumentActivityChanged();
 
   if (!mPaused) {
     SetPlayedOrSeeked(true);
-    if (!mPausedForInactiveDocument) {
+    if (!mPausedForInactiveDocumentOrChannel) {
       rv = mDecoder->Play();
     }
   }
 
   if (OwnerDoc()->HasAudioAvailableListeners()) {
     NotifyAudioAvailableListener();
   }
 
@@ -2475,17 +2478,17 @@ void nsHTMLMediaElement::SetupSrcMediaSt
   mSrcStream = aStream;
   // XXX if we ever support capturing the output of a media element which is
   // playing a stream, we'll need to add a CombineWithPrincipal call here.
   mSrcStreamListener = new StreamListener(this);
   GetSrcMediaStream()->AddListener(mSrcStreamListener);
   if (mPaused) {
     GetSrcMediaStream()->ChangeExplicitBlockerCount(1);
   }
-  if (mPausedForInactiveDocument) {
+  if (mPausedForInactiveDocumentOrChannel) {
     GetSrcMediaStream()->ChangeExplicitBlockerCount(1);
   }
   ChangeDelayLoadStatus(false);
   GetSrcMediaStream()->AddAudioOutput(this);
   GetSrcMediaStream()->SetAudioOutputVolume(this, float(mMuted ? 0.0 : mVolume));
   VideoFrameContainer* container = GetVideoFrameContainer();
   if (container) {
     GetSrcMediaStream()->AddVideoOutput(container);
@@ -2510,17 +2513,17 @@ void nsHTMLMediaElement::EndSrcMediaStre
   VideoFrameContainer* container = GetVideoFrameContainer();
   if (container) {
     GetSrcMediaStream()->RemoveVideoOutput(container);
     container->ClearCurrentFrame();
   }
   if (mPaused) {
     GetSrcMediaStream()->ChangeExplicitBlockerCount(-1);
   }
-  if (mPausedForInactiveDocument) {
+  if (mPausedForInactiveDocumentOrChannel) {
     GetSrcMediaStream()->ChangeExplicitBlockerCount(-1);
   }
   mSrcStream = nullptr;
 }
 
 nsresult nsHTMLMediaElement::NewURIFromString(const nsAutoString& aURISpec, nsIURI** aURI)
 {
   NS_ENSURE_ARG_POINTER(aURI);
@@ -2850,25 +2853,25 @@ static const char* gReadyStateToString[]
 };
 #endif
 
 void nsHTMLMediaElement::ChangeReadyState(nsMediaReadyState aState)
 {
   nsMediaReadyState oldState = mReadyState;
   mReadyState = aState;
 
-  UpdateAudioChannelPlayingState();
-
   if (mNetworkState == nsIDOMHTMLMediaElement::NETWORK_EMPTY ||
       oldState == mReadyState) {
     return;
   }
 
   LOG(PR_LOG_DEBUG, ("%p Ready state changed to %s", this, gReadyStateToString[aState]));
 
+  UpdateAudioChannelPlayingState();
+
   // Handle raising of "waiting" event during seek (see 4.8.10.9)
   if (mPlayingBeforeSeek &&
       oldState < nsIDOMHTMLMediaElement::HAVE_FUTURE_DATA) {
     DispatchAsyncEvent(NS_LITERAL_STRING("waiting"));
   }
 
   if (oldState < nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA &&
       mReadyState >= nsIDOMHTMLMediaElement::HAVE_CURRENT_DATA &&
@@ -2985,17 +2988,17 @@ nsresult nsHTMLMediaElement::DispatchAud
 
 nsresult nsHTMLMediaElement::DispatchEvent(const nsAString& aName)
 {
   LOG_EVENT(PR_LOG_DEBUG, ("%p Dispatching event %s", this,
                           NS_ConvertUTF16toUTF8(aName).get()));
 
   // Save events that occur while in the bfcache. These will be dispatched
   // if the page comes out of the bfcache.
-  if (mPausedForInactiveDocument) {
+  if (mEventDeliveryPaused) {
     mPendingEvents.AppendElement(aName);
     return NS_OK;
   }
 
   return nsContentUtils::DispatchTrustedEvent(OwnerDoc(),
                                               static_cast<nsIContent*>(this),
                                               aName,
                                               false,
@@ -3009,17 +3012,17 @@ nsresult nsHTMLMediaElement::DispatchAsy
 
   nsCOMPtr<nsIRunnable> event = new nsAsyncEventRunner(aName, this);
   NS_DispatchToMainThread(event, NS_DISPATCH_NORMAL);
   return NS_OK;
 }
 
 nsresult nsHTMLMediaElement::DispatchPendingMediaEvents()
 {
-  NS_ASSERTION(!mPausedForInactiveDocument,
+  NS_ASSERTION(!mEventDeliveryPaused,
                "Must not be in bfcache when dispatching pending media events");
 
   uint32_t count = mPendingEvents.Length();
   for (uint32_t i = 0; i < count; ++i) {
     DispatchAsyncEvent(mPendingEvents[i]);
   }
   mPendingEvents.Clear();
 
@@ -3068,52 +3071,63 @@ void nsHTMLMediaElement::NotifyDecoderPr
   }
 }
 
 void nsHTMLMediaElement::UpdateMediaSize(nsIntSize size)
 {
   mMediaSize = size;
 }
 
-void nsHTMLMediaElement::NotifyOwnerDocumentActivityChanged()
+void nsHTMLMediaElement::SuspendOrResumeElement(bool aPauseElement, bool aSuspendEvents)
 {
-  nsIDocument* ownerDoc = OwnerDoc();
-  bool pauseForInactiveDocument =
-    !ownerDoc->IsActive() || !ownerDoc->IsVisible();
-
-  if (pauseForInactiveDocument != mPausedForInactiveDocument) {
-    mPausedForInactiveDocument = pauseForInactiveDocument;
-    if (pauseForInactiveDocument) {
+  if (aPauseElement != mPausedForInactiveDocumentOrChannel) {
+    mPausedForInactiveDocumentOrChannel = aPauseElement;
+    if (aPauseElement) {
       if (mDecoder) {
         mDecoder->Pause();
         mDecoder->Suspend();
       } else if (mSrcStream) {
         GetSrcMediaStream()->ChangeExplicitBlockerCount(1);
       }
+      mEventDeliveryPaused = aSuspendEvents;
     } else {
       if (mDecoder) {
         mDecoder->Resume(false);
         if (!mPaused && !mDecoder->IsEnded()) {
           mDecoder->Play();
         }
       } else if (mSrcStream) {
         GetSrcMediaStream()->ChangeExplicitBlockerCount(-1);
       }
-      DispatchPendingMediaEvents();
+      if (mEventDeliveryPaused) {
+        DispatchPendingMediaEvents();
+        mEventDeliveryPaused = false;
+      }
     }
   }
-
-  if (mPlayingThroughTheAudioChannel && mAudioChannelAgent) {
+}
+
+void nsHTMLMediaElement::NotifyOwnerDocumentActivityChanged()
+{
+  nsIDocument* ownerDoc = OwnerDoc();
+#ifdef MOZ_B2G
+  nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(OwnerDoc());
+  if (domDoc) {
     bool hidden = false;
-    nsCOMPtr<nsIDOMDocument> domDoc = do_QueryInterface(ownerDoc);
-    if (domDoc) {
-      domDoc->GetHidden(&hidden);
+    domDoc->GetHidden(&hidden);
+    // SetVisibilityState will update mChannelSuspended via the CanPlayChanged callback.
+    if (mPlayingThroughTheAudioChannel && mAudioChannelAgent) {
       mAudioChannelAgent->SetVisibilityState(!hidden);
     }
   }
+#endif
+  bool suspendEvents = !ownerDoc->IsActive() || !ownerDoc->IsVisible();
+  bool pauseElement = suspendEvents || mChannelSuspended;
+
+  SuspendOrResumeElement(pauseElement, suspendEvents);
 
   AddRemoveSelfReference();
 }
 
 void nsHTMLMediaElement::AddRemoveSelfReference()
 {
   // XXX we could release earlier here in many situations if we examined
   // which event listeners are attached. Right now we assume there is a
@@ -3517,25 +3531,25 @@ ImageContainer* nsHTMLMediaElement::GetI
 }
 
 nsresult nsHTMLMediaElement::UpdateChannelMuteState(bool aCanPlay)
 {
   // Only on B2G we mute the nsHTMLMediaElement following the rules of
   // AudioChannelService.
 #ifdef MOZ_B2G
   // We have to mute this channel:
-  if (!aCanPlay && !mChannelMuted) {
-    mChannelMuted = true;
+  if (!aCanPlay && !mChannelSuspended) {
+    mChannelSuspended = true;
     DispatchAsyncEvent(NS_LITERAL_STRING("mozinterruptbegin"));
-  } else if (aCanPlay && mChannelMuted) {
-    mChannelMuted = false;
+  } else if (aCanPlay && mChannelSuspended) {
+    mChannelSuspended = false;
     DispatchAsyncEvent(NS_LITERAL_STRING("mozinterruptend"));
   }
 
-  SetMutedInternal(mMuted);
+  SuspendOrResumeElement(mChannelSuspended, false);
 #endif
 
   return NS_OK;
 }
 
 void nsHTMLMediaElement::UpdateAudioChannelPlayingState()
 {
   // The nsHTMLMediaElement is registered to the AudioChannelService only on B2G.
@@ -3547,17 +3561,17 @@ void nsHTMLMediaElement::UpdateAudioChan
     mPlayingThroughTheAudioChannel = playingThroughTheAudioChannel;
 
     if (!mAudioChannelAgent) {
       nsresult rv;
       mAudioChannelAgent = do_CreateInstance("@mozilla.org/audiochannelagent;1", &rv);
       if (!mAudioChannelAgent) {
         return;
       }
-      mAudioChannelAgent->Init( mAudioChannelType, this);
+      mAudioChannelAgent->Init(mAudioChannelType, this);
     }
 
     if (mPlayingThroughTheAudioChannel) {
       bool canPlay;
       mAudioChannelAgent->StartPlaying(&canPlay);
     } else {
       mAudioChannelAgent->StopPlaying();
       mAudioChannelAgent = nullptr;
@@ -3567,9 +3581,8 @@ void nsHTMLMediaElement::UpdateAudioChan
 }
 
 /* void canPlayChanged (in boolean canPlay); */
 NS_IMETHODIMP nsHTMLMediaElement::CanPlayChanged(bool canPlay)
 {
   UpdateChannelMuteState(canPlay);
   return NS_OK;
 }
-
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -8498,16 +8498,22 @@ nsGlobalWindow::GetIndexedDB(nsIIDBFacto
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
   nsCOMPtr<nsIIDBFactory> request(mIndexedDB);
   request.forget(_retval);
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsGlobalWindow::GetMozIndexedDB(nsIIDBFactory** _retval)
+{
+  return GetIndexedDB(_retval);
+}
+
 //*****************************************************************************
 // nsGlobalWindow::nsIInterfaceRequestor
 //*****************************************************************************
 
 NS_IMETHODIMP
 nsGlobalWindow::GetInterface(const nsIID & aIID, void **aSink)
 {
   NS_ENSURE_ARG_POINTER(aSink);
--- a/dom/bluetooth/BluetoothOppManager.cpp
+++ b/dom/bluetooth/BluetoothOppManager.cpp
@@ -41,19 +41,19 @@ public:
 
   BluetoothOppManagerObserver()
   {
   }
 
   bool Init()
   {
     nsCOMPtr<nsIObserverService> obs = services::GetObserverService();
-    if (NS_FAILED(obs->AddObserver(this,
-                                   NS_XPCOM_SHUTDOWN_OBSERVER_ID,
-                                   false))) {
+    if (!obs || NS_FAILED(obs->AddObserver(this,
+                                           NS_XPCOM_SHUTDOWN_OBSERVER_ID,
+                                           false))) {
       NS_WARNING("Failed to add shutdown observer!");
       return false;
     }
 
     return true;
   }
 
   bool Shutdown()
@@ -477,16 +477,36 @@ BluetoothOppManager::CreateFile()
 
   /*
    * The function CreateUnique() may create a file with a different file
    * name from the original sFileName. Therefore we have to retrieve
    * the file name again.
    */
   f->GetLeafName(sFileName);
 
+  mDsFile = nullptr;
+
+  nsCOMPtr<nsIMIMEService> mimeSvc = do_GetService(NS_MIMESERVICE_CONTRACTID);
+  if (mimeSvc) {
+    nsCString mimeType;
+    nsresult rv = mimeSvc->GetTypeFromFile(f, mimeType);
+
+    if (NS_SUCCEEDED(rv)) {
+      if (StringBeginsWith(mimeType, NS_LITERAL_CSTRING("image/"))) {
+        mDsFile = new DeviceStorageFile(NS_LITERAL_STRING("pictures"), f);
+      } else if (StringBeginsWith(mimeType, NS_LITERAL_CSTRING("video/"))) {
+        mDsFile = new DeviceStorageFile(NS_LITERAL_STRING("movies"), f);
+      } else if (StringBeginsWith(mimeType, NS_LITERAL_CSTRING("audio/"))) {
+        mDsFile = new DeviceStorageFile(NS_LITERAL_STRING("music"), f);
+      } else {
+        NS_WARNING("Couldn't recognize the mimetype of received file.");
+      }
+    }
+  }
+
   NS_NewLocalFileOutputStream(getter_AddRefs(mOutputStream), f);
   if (!mOutputStream) {
     NS_WARNING("Couldn't new an output stream");
     return false;
   }
 
   return true;
 }
@@ -1235,22 +1255,34 @@ BluetoothOppManager::OnDisconnect()
   /**
    * It is valid for a bluetooth device which is transfering file via OPP
    * closing socket without sending OBEX disconnect request first. So we
    * delete the broken file when we failed to receive a file from the remote,
    * and notify the transfer has been completed (but failed). We also call
    * AfterOppDisconnected here to ensure all variables will be cleaned.
    */
   if (mSocketStatus == SocketConnectionStatus::SOCKET_CONNECTED) {
+    if (mTransferMode) {
+      if (!mSuccessFlag) {
+        DeleteReceivedFile();
+      } else if (mDsFile) {
+        nsString data;
+        CopyASCIItoUTF16("modified", data);
+
+        nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+        if (obs) {
+          obs->NotifyObservers(mDsFile, "file-watcher-update", data.get());
+        }
+      }
+    }
+
     if (!mSuccessFlag) {
-      if (mTransferMode) {
-        DeleteReceivedFile();
-      }
       FileTransferComplete();
     }
+
     Listen();
   } else if (mSocketStatus == SocketConnectionStatus::SOCKET_CONNECTING) {
     NS_WARNING("BluetoothOppManager got unexpected socket status!");
   }
 
   AfterOppDisconnected();
   mConnectedDeviceAddress.AssignLiteral("00:00:00:00:00:00");
   mSuccessFlag = false;
--- a/dom/bluetooth/BluetoothOppManager.h
+++ b/dom/bluetooth/BluetoothOppManager.h
@@ -5,16 +5,17 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_bluetooth_bluetoothoppmanager_h__
 #define mozilla_dom_bluetooth_bluetoothoppmanager_h__
 
 #include "BluetoothCommon.h"
 #include "mozilla/dom/ipc/Blob.h"
 #include "mozilla/ipc/UnixSocket.h"
+#include "DeviceStorage.h"
 
 class nsIOutputStream;
 class nsIInputStream;
 
 BEGIN_BLUETOOTH_NAMESPACE
 
 class BluetoothReplyRunnable;
 class ObexHeaderSet;
@@ -160,13 +161,14 @@ private:
   nsAutoPtr<uint8_t> mReceivedDataBuffer;
 
   nsCOMPtr<nsIDOMBlob> mBlob;
   nsCOMPtr<nsIThread> mReadFileThread;
   nsCOMPtr<nsIOutputStream> mOutputStream;
   nsCOMPtr<nsIInputStream> mInputStream;
 
   nsRefPtr<BluetoothReplyRunnable> mRunnable;
+  nsRefPtr<DeviceStorageFile> mDsFile;
 };
 
 END_BLUETOOTH_NAMESPACE
 
 #endif
--- a/dom/browser-element/BrowserElementScrolling.js
+++ b/dom/browser-element/BrowserElementScrolling.js
@@ -1,117 +1,207 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 const ContentPanning = {
   init: function cp_init() {
-    ['mousedown', 'mouseup', 'mousemove'].forEach(function(type) {
+    ['mousedown', 'mouseup', 'mousemove', 'touchstart', 'touchend', 'touchmove'].forEach(function(type) {
       addEventListener(type, ContentPanning, false);
     });
 
     addMessageListener("Viewport:Change", this._recvViewportChange.bind(this));
     addMessageListener("Gesture:DoubleTap", this._recvDoubleTap.bind(this));
   },
 
+  evtFilter: '',
+  _filterEvent: function cp_filterEvent(evt) {
+    switch (this.evtFilter) {
+      case 'mouse':
+        if (evt.type == 'touchstart' || evt.type == 'touchend' || evt.type == 'touchmove') {
+          return false;
+        }
+        break;
+      case 'touch':
+        if (evt.type == 'mousedown' || evt.type == 'mouseup' || evt.type == 'mousemove') {
+          return false;
+        }
+        break;
+    }
+    return true;
+  },
   handleEvent: function cp_handleEvent(evt) {
+    // determine scrolling detection is based on touch or mouse event at runtime
+    if (!this.evtFilter) {
+      if (evt.type == 'touchstart') this.evtFilter = 'touch';
+      else if (evt.type == 'mousedown') this.evtFilter = 'mouse';
+    }
+    if (evt.defaultPrevented || !this._filterEvent(evt)) return;
+
     switch (evt.type) {
       case 'mousedown':
+      case 'touchstart':
         this.onTouchStart(evt);
         break;
       case 'mousemove':
+      case 'touchmove':
         this.onTouchMove(evt);
         break;
       case 'mouseup':
+      case 'touchend':
         this.onTouchEnd(evt);
         break;
       case 'click':
         evt.stopPropagation();
         evt.preventDefault();
 
         let target = evt.target;
         let view = target.ownerDocument ? target.ownerDocument.defaultView
                                         : target;
         view.removeEventListener('click', this, true, true);
         break;
     }
   },
 
   position: new Point(0 , 0),
 
+  findFirstTouch: function cp_findFirstTouch(touches) {
+    if (!('trackingId' in this)) return undefined;
+
+    for (let i = 0; i < touches.length; i++) {
+      if (touches[i].identifier === this.trackingId)
+        return touches[i];
+    }
+    return undefined;
+  },
+
   onTouchStart: function cp_onTouchStart(evt) {
+    let target, screenX, screenY;
+    if (this.evtFilter == 'touch') {
+      if ('trackingId' in this) {
+        return;
+      }
+
+      let firstTouch = evt.changedTouches[0];
+      this.trackingId = firstTouch.identifier;
+      target = firstTouch.target;
+      screenX = firstTouch.screenX;
+      screenY = firstTouch.screenY;
+    } else {
+      target = evt.target;
+      screenX = evt.screenX;
+      screenY = evt.screenY;
+    }
+
     this.dragging = true;
     this.panning = false;
 
     let oldTarget = this.target;
-    [this.target, this.scrollCallback] = this.getPannable(evt.target);
+    [this.target, this.scrollCallback] = this.getPannable(target);
 
     // If we found a target, that means we have found a scrollable subframe. In
     // this case, and if we are using async panning and zooming on the parent
     // frame, inform the pan/zoom controller that it should not attempt to
     // handle any touch events it gets until the next batch (meaning the next
     // time we get a touch end).
     if (this.target != null && ContentPanning._asyncPanZoomForViewportFrame) {
       var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
-      os.notifyObservers(docShell, 'cancel-default-pan-zoom', null);
+      os.notifyObservers(docShell, 'detect-scrollable-subframe', null);
     }
 
     // If there is a pan animation running (from a previous pan gesture) and
     // the user touch back the screen, stop this animation immediatly and
     // prevent the possible click action if the touch happens on the same
     // target.
     this.preventNextClick = false;
     if (KineticPanning.active) {
       KineticPanning.stop();
 
       if (oldTarget && oldTarget == this.target)
         this.preventNextClick = true;
     }
 
 
-    this.position.set(evt.screenX, evt.screenY);
+    this.position.set(screenX, screenY);
     KineticPanning.record(new Point(0, 0), evt.timeStamp);
   },
 
   onTouchEnd: function cp_onTouchEnd(evt) {
+    if (this.evtFilter == 'touch' && !this.findFirstTouch(evt.changedTouches))
+      return;
+
     if (!this.dragging)
       return;
     this.dragging = false;
+    this.isScrolling = false;
 
     this.onTouchMove(evt);
 
-    let click = evt.detail;
+    delete this.trackingId;
+
+    let click = (this.evtFilter == 'touch') ? true : evt.detail;
     if (this.target && click && (this.panning || this.preventNextClick)) {
       let target = this.target;
       let view = target.ownerDocument ? target.ownerDocument.defaultView
                                       : target;
       view.addEventListener('click', this, true, true);
     }
 
     if (this.panning)
       KineticPanning.start(this);
   },
 
+  isScrolling: false, // Scrolling gesture is executed in BrowserElementScrolling
   onTouchMove: function cp_onTouchMove(evt) {
     if (!this.dragging || !this.scrollCallback)
       return;
 
+    let screenX, screenY;
+    if (this.evtFilter == 'touch') {
+      let firstTouch = this.findFirstTouch(evt.changedTouches);
+      if (evt.touches.length > 1 || !firstTouch)
+        return;
+      screenX = firstTouch.screenX;
+      screenY = firstTouch.screenY;
+    } else {
+      screenX = evt.screenX;
+      screenY = evt.screenY;
+    }
+
     let current = this.position;
-    let delta = new Point(evt.screenX - current.x, evt.screenY - current.y);
-    current.set(evt.screenX, evt.screenY);
+    let delta = new Point(screenX - current.x, screenY - current.y);
+    current.set(screenX, screenY);
 
     KineticPanning.record(delta, evt.timeStamp);
-    this.scrollCallback(delta.scale(-1));
+    let success = this.scrollCallback(delta.scale(-1));
 
+    // Stop async-pan-zooming if the subframe is really scrolled.
+    if (!this.isScrolling && ContentPanning._asyncPanZoomForViewportFrame) {
+      if (success) {
+        var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService);
+        os.notifyObservers(docShell, 'cancel-default-pan-zoom', null);
+      } else {
+        // Let AsyncPanZoomController handle the scrolling gesture.
+        delete this.trackingId;
+        return;
+      }
+    }
+
+    // Successfully scroll the inner scrollable region.
+    if (success && !this.isScrolling) {
+      this.isScrolling = true;
+    }
+      
     // If a pan action happens, cancel the active state of the
     // current target.
     if (!this.panning && KineticPanning.isPan()) {
       this.panning = true;
       this._resetActive();
     }
+
     evt.stopPropagation();
     evt.preventDefault();
   },
 
 
   onKineticBegin: function cp_onKineticBegin(evt) {
   },
 
--- a/dom/interfaces/storage/nsIDOMStorageIndexedDB.idl
+++ b/dom/interfaces/storage/nsIDOMStorageIndexedDB.idl
@@ -10,16 +10,17 @@
  * http://www.whatwg.org/specs/web-apps/current-work/#scs-client-side and
  * http://www.w3.org/TR/IndexedDB/ for more information.
  *
  * Allows access to contextual storage areas.
  */
 
 interface nsIIDBFactory;
 
-[scriptable, uuid(c5982775-3f65-4d3e-b5f0-2400c987a900)]
+[scriptable, uuid(94ca74e8-9cff-456e-a7a4-a4071a32ff58)]
 interface nsIDOMStorageIndexedDB : nsISupports
 {
   /**
    * Indexed Databases for the current browsing context.
    */
   readonly attribute nsIIDBFactory indexedDB;
+  readonly attribute nsIIDBFactory mozIndexedDB;
 };
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -91,16 +91,17 @@ using namespace mozilla::widget;
 
 NS_IMPL_ISUPPORTS1(ContentListener, nsIDOMEventListener)
 
 static const nsIntSize kDefaultViewportSize(980, 480);
 
 static const char CANCEL_DEFAULT_PAN_ZOOM[] = "cancel-default-pan-zoom";
 static const char BROWSER_ZOOM_TO_RECT[] = "browser-zoom-to-rect";
 static const char BEFORE_FIRST_PAINT[] = "before-first-paint";
+static const char DETECT_SCROLLABLE_SUBFRAME[] = "detect-scrollable-subframe";
 
 NS_IMETHODIMP
 ContentListener::HandleEvent(nsIDOMEvent* aEvent)
 {
   RemoteDOMEvent remoteEvent;
   remoteEvent.mEvent = do_QueryInterface(aEvent);
   NS_ENSURE_STATE(remoteEvent.mEvent);
   mTabChild->SendEvent(remoteEvent);
@@ -236,16 +237,22 @@ TabChild::Observe(nsISupports *aSubject,
           AsyncPanZoomController::CalculateResolution(mLastMetrics);
         mLastMetrics.mScrollOffset = gfx::Point(0, 0);
         utils->SetResolution(mLastMetrics.mResolution.width,
                              mLastMetrics.mResolution.height);
 
         HandlePossibleViewportChange();
       }
     }
+  } else if (!strcmp(aTopic, DETECT_SCROLLABLE_SUBFRAME)) {
+    nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aSubject));
+    nsCOMPtr<nsITabChild> tabChild(GetTabChildFrom(docShell));
+    if (tabChild == this) {
+      mRemoteFrame->DetectScrollableSubframe();
+    }
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 TabChild::OnStateChange(nsIWebProgress* aWebProgress,
                         nsIRequest* aRequest,
@@ -1671,16 +1678,17 @@ TabChild::RecvDestroy()
   }
 
   nsCOMPtr<nsIObserverService> observerService =
     do_GetService(NS_OBSERVERSERVICE_CONTRACTID);
 
   observerService->RemoveObserver(this, CANCEL_DEFAULT_PAN_ZOOM);
   observerService->RemoveObserver(this, BROWSER_ZOOM_TO_RECT);
   observerService->RemoveObserver(this, BEFORE_FIRST_PAINT);
+  observerService->RemoveObserver(this, DETECT_SCROLLABLE_SUBFRAME);
 
   const InfallibleTArray<PIndexedDBChild*>& idbActors =
     ManagedPIndexedDBChild();
   for (uint32_t i = 0; i < idbActors.Length(); ++i) {
     static_cast<IndexedDBChild*>(idbActors[i])->Disconnect();
   }
 
   // XXX what other code in ~TabChild() should we be running here?
@@ -1798,16 +1806,19 @@ TabChild::InitRenderingState()
                                      CANCEL_DEFAULT_PAN_ZOOM,
                                      false);
         observerService->AddObserver(this,
                                      BROWSER_ZOOM_TO_RECT,
                                      false);
         observerService->AddObserver(this,
                                      BEFORE_FIRST_PAINT,
                                      false);
+        observerService->AddObserver(this,
+                                     DETECT_SCROLLABLE_SUBFRAME,
+                                     false);
     }
 
     return true;
 }
 
 void
 TabChild::SetBackgroundColor(const nscolor& aColor)
 {
--- a/dom/wifi/wifi_worker.js
+++ b/dom/wifi/wifi_worker.js
@@ -40,21 +40,32 @@ self.onmessage = function(e) {
   var cmd = data.cmd;
 
   switch (cmd) {
   case "command":
     len.value = 4096;
     var ret = libhardware_legacy.command(data.request, cbuf, len.address());
     var reply = "";
     if (!ret) {
+      // The return value from libhardware_legacy.command is not guaranteed to
+      // be null-terminated. At the same time we want to make sure that we
+      // don't return a response with a trailing newline, so handle both cases
+      // here. Note that if we wrote 4096 characters to cbuf, we don't have to
+      // null-terminate the buffer, as ctypes has the maximum size already.
       var reply_len = len.value;
-      var str = cbuf.readString();
-      if (str[reply_len-1] == "\n")
-        --reply_len;
-      reply = str.substr(0, reply_len);
+      if (reply_len !== 0) {
+        if (cbuf[reply_len - 1] === 10)
+          cbuf[--reply_len] = 0;
+        else if (reply_len !== 4096)
+          cbuf[reply_len] = 0;
+
+        reply = cbuf.readString();
+      }
+
+      // Else if reply_len was 0, use the empty reply, set above.
     }
     postMessage({ id: id, status: ret, reply: reply });
     break;
   case "wait_for_event":
     var ret = libhardware_legacy.wait_for_event(cbuf, 4096);
     var event = cbuf.readString().substr(0, ret.value);
     postMessage({ id: id, event: event });
     break;
--- a/gfx/layers/Layers.cpp
+++ b/gfx/layers/Layers.cpp
@@ -589,16 +589,36 @@ Layer::SnapTransform(const gfx3DMatrix& 
       *aResidualTransform = matrix2D * snappedMatrixInverse;
     }
   } else {
     result = aTransform;
   }
   return result;
 }
 
+static bool
+AncestorLayerMayChangeTransform(Layer* aLayer)
+{
+  for (Layer* l = aLayer; l; l = l->GetParent()) {
+    if (l->GetContentFlags() & Layer::CONTENT_MAY_CHANGE_TRANSFORM) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool
+Layer::MayResample()
+{
+  gfxMatrix transform2d;
+  return !GetEffectiveTransform().Is2D(&transform2d) ||
+         transform2d.HasNonIntegerTranslation() ||
+         AncestorLayerMayChangeTransform(this);
+}
+
 nsIntRect
 Layer::CalculateScissorRect(const nsIntRect& aCurrentScissorRect,
                             const gfxMatrix* aWorldTransform)
 {
   ContainerLayer* container = GetParent();
   NS_ASSERTION(container, "This can't be called on the root!");
 
   // Establish initial clip rect: it's either the one passed in, or
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -571,17 +571,23 @@ public:
      * This should never be set at the same time as CONTENT_OPAQUE.
      */
     CONTENT_COMPONENT_ALPHA = 0x02,
 
     /**
      * If this is set then this layer is part of a preserve-3d group, and should
      * be sorted with sibling layers that are also part of the same group.
      */
-    CONTENT_PRESERVE_3D = 0x04
+    CONTENT_PRESERVE_3D = 0x04,
+    /**
+     * This indicates that the transform may be changed on during an empty
+     * transaction where there is no possibility of redrawing the content, so the
+     * implementation should be ready for that.
+     */
+    CONTENT_MAY_CHANGE_TRANSFORM = 0x08
   };
   /**
    * CONSTRUCTION PHASE ONLY
    * This lets layout make some promises about what will be drawn into the
    * visible region of the ThebesLayer. This enables internal quality
    * and performance optimizations.
    */
   void SetContentFlags(uint32_t aFlags)
@@ -1078,16 +1084,24 @@ protected:
    * transform matrix
    * @param aResidualTransform a transform to apply before mEffectiveTransform
    * in order to get the results to completely match aTransform
    */
   gfx3DMatrix SnapTransform(const gfx3DMatrix& aTransform,
                             const gfxRect& aSnapRect,
                             gfxMatrix* aResidualTransform);
 
+  /**
+   * Returns true if this layer's effective transform is not just
+   * a translation by integers, or if this layer or some ancestor layer
+   * is marked as having a transform that may change without a full layer
+   * transaction.
+   */
+  bool MayResample();
+
   LayerManager* mManager;
   ContainerLayer* mParent;
   Layer* mNextSibling;
   Layer* mPrevSibling;
   void* mImplData;
   nsRefPtr<Layer> mMaskLayer;
   gfx::UserData mUserData;
   nsIntRegion mVisibleRegion;
--- a/gfx/layers/basic/BasicThebesLayer.cpp
+++ b/gfx/layers/basic/BasicThebesLayer.cpp
@@ -155,19 +155,17 @@ BasicThebesLayer::PaintThebes(gfxContext
 
   {
     uint32_t flags = 0;
 #ifndef MOZ_WIDGET_ANDROID
     if (BasicManager()->CompositorMightResample()) {
       flags |= ThebesLayerBuffer::PAINT_WILL_RESAMPLE;
     }
     if (!(flags & ThebesLayerBuffer::PAINT_WILL_RESAMPLE)) {
-      gfxMatrix transform;
-      if (!GetEffectiveTransform().CanDraw2D(&transform) ||
-          transform.HasNonIntegerTranslation()) {
+      if (MayResample()) {
         flags |= ThebesLayerBuffer::PAINT_WILL_RESAMPLE;
       }
     }
 #endif
     if (mDrawAtomically) {
       flags |= ThebesLayerBuffer::PAINT_NO_ROTATION;
     }
     Buffer::PaintState state =
--- a/gfx/layers/d3d10/ThebesLayerD3D10.cpp
+++ b/gfx/layers/d3d10/ThebesLayerD3D10.cpp
@@ -160,19 +160,17 @@ ThebesLayerD3D10::Validate(ReadbackProce
   // If we have a transform that requires resampling of our texture, then
   // we need to make sure we don't sample pixels that haven't been drawn.
   // We clamp sample coordinates to the texture rect, but when the visible region
   // doesn't fill the entire texture rect we need to make sure we draw all the
   // pixels in the texture rect anyway in case they get sampled.
   nsIntRegion neededRegion = mVisibleRegion;
   if (!neededRegion.GetBounds().IsEqualInterior(newTextureRect) ||
       neededRegion.GetNumRects() > 1) {
-    gfxMatrix transform2d;
-    if (!GetEffectiveTransform().Is2D(&transform2d) ||
-        transform2d.HasNonIntegerTranslation()) {
+    if (MayResample()) {
       neededRegion = newTextureRect;
       if (mode == SURFACE_OPAQUE) {
         // We're going to paint outside the visible region, but layout hasn't
         // promised that it will paint opaquely there, so we'll have to
         // treat this layer as transparent.
         mode = SURFACE_SINGLE_CHANNEL_ALPHA;
       }
     }
--- a/gfx/layers/d3d9/ThebesLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ThebesLayerD3D9.cpp
@@ -187,19 +187,17 @@ ThebesLayerD3D9::RenderThebesLayer(Readb
   // If we have a transform that requires resampling of our texture, then
   // we need to make sure we don't sample pixels that haven't been drawn.
   // We clamp sample coordinates to the texture rect, but when the visible region
   // doesn't fill the entire texture rect we need to make sure we draw all the
   // pixels in the texture rect anyway in case they get sampled.
   nsIntRegion neededRegion = mVisibleRegion;
   if (!neededRegion.GetBounds().IsEqualInterior(newTextureRect) ||
       neededRegion.GetNumRects() > 1) {
-    gfxMatrix transform2d;
-    if (!GetEffectiveTransform().Is2D(&transform2d) ||
-        transform2d.HasNonIntegerTranslation()) {
+    if (MayResample()) {
       neededRegion = newTextureRect;
       if (mode == SURFACE_OPAQUE) {
         // We're going to paint outside the visible region, but layout hasn't
         // promised that it will paint opaquely there, so we'll have to
         // treat this layer as transparent.
         mode = SURFACE_SINGLE_CHANNEL_ALPHA;
       }
     }
--- a/gfx/layers/ipc/AsyncPanZoomController.cpp
+++ b/gfx/layers/ipc/AsyncPanZoomController.cpp
@@ -232,16 +232,36 @@ nsEventStatus AsyncPanZoomController::Ha
   nsEventStatus rv = nsEventStatus_eIgnore;
 
   if (mGestureEventListener && !mDisableNextTouchBatch) {
     rv = mGestureEventListener->HandleInputEvent(aEvent);
     if (rv == nsEventStatus_eConsumeNoDefault)
       return rv;
   }
 
+  if (mDelayPanning && aEvent.mInputType == MULTITOUCH_INPUT) {
+    const MultiTouchInput& multiTouchInput = aEvent.AsMultiTouchInput();
+    if (multiTouchInput.mType == MultiTouchInput::MULTITOUCH_MOVE) {
+      // Let BrowserElementScrolling perform panning gesture first.
+      SetState(WAITING_LISTENERS);
+      mTouchQueue.AppendElement(multiTouchInput);
+
+      if (!mTouchListenerTimeoutTask) {
+        mTouchListenerTimeoutTask =
+          NewRunnableMethod(this, &AsyncPanZoomController::TimeoutTouchListeners);
+
+        MessageLoop::current()->PostDelayedTask(
+          FROM_HERE,
+          mTouchListenerTimeoutTask,
+          TOUCH_LISTENER_TIMEOUT);
+      }
+      return nsEventStatus_eConsumeNoDefault;
+    }
+  }
+
   switch (aEvent.mInputType) {
   case MULTITOUCH_INPUT: {
     const MultiTouchInput& multiTouchInput = aEvent.AsMultiTouchInput();
     switch (multiTouchInput.mType) {
       case MultiTouchInput::MULTITOUCH_START: rv = OnTouchStart(multiTouchInput); break;
       case MultiTouchInput::MULTITOUCH_MOVE: rv = OnTouchMove(multiTouchInput); break;
       case MultiTouchInput::MULTITOUCH_END: rv = OnTouchEnd(multiTouchInput); break;
       case MultiTouchInput::MULTITOUCH_CANCEL: rv = OnTouchCancel(multiTouchInput); break;
@@ -1084,16 +1104,17 @@ bool AsyncPanZoomController::SampleConte
 
 void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aViewportFrame, bool aIsFirstPaint) {
   MonitorAutoLock monitor(mMonitor);
 
   mPaintThrottler.TaskComplete();
 
   mLastContentPaintMetrics = aViewportFrame;
 
+  mFrameMetrics.mMayHaveTouchListeners = aViewportFrame.mMayHaveTouchListeners;
   if (mWaitingForContentToPaint) {
     // Remove the oldest sample we have if adding a new sample takes us over our
     // desired number of samples.
     if (mPreviousPaintDurations.Length() >= NUM_PAINT_DURATION_SAMPLES) {
       mPreviousPaintDurations.RemoveElementAt(0);
     }
 
     mPreviousPaintDurations.AppendElement(
@@ -1177,16 +1198,20 @@ void AsyncPanZoomController::UpdateCompo
 
 void AsyncPanZoomController::CancelDefaultPanZoom() {
   mDisableNextTouchBatch = true;
   if (mGestureEventListener) {
     mGestureEventListener->CancelGesture();
   }
 }
 
+void AsyncPanZoomController::DetectScrollableSubframe() {
+  mDelayPanning = true;
+}
+
 void AsyncPanZoomController::ZoomToRect(const gfxRect& aRect) {
   gfx::Rect zoomToRect(gfx::Rect(aRect.x, aRect.y, aRect.width, aRect.height));
 
   SetState(ANIMATING_ZOOM);
 
   {
     MonitorAutoLock mon(mMonitor);
 
@@ -1263,34 +1288,43 @@ void AsyncPanZoomController::ZoomToRect(
 
     mAnimationStartTime = TimeStamp::Now();
 
     ScheduleComposite();
   }
 }
 
 void AsyncPanZoomController::ContentReceivedTouch(bool aPreventDefault) {
-  if (!mFrameMetrics.mMayHaveTouchListeners) {
+  if (!mFrameMetrics.mMayHaveTouchListeners && !mDelayPanning) {
     mTouchQueue.Clear();
     return;
   }
 
   if (mTouchListenerTimeoutTask) {
     mTouchListenerTimeoutTask->Cancel();
     mTouchListenerTimeoutTask = nullptr;
   }
 
   if (mState == WAITING_LISTENERS) {
     if (!aPreventDefault) {
-      SetState(NOTHING);
+      // Delayed scrolling gesture is pending at TOUCHING state.
+      if (mDelayPanning) {
+        SetState(TOUCHING);
+      } else {
+        SetState(NOTHING);
+      }
     }
 
     mHandlingTouchQueue = true;
 
     while (!mTouchQueue.IsEmpty()) {
+      // we need to reset mDelayPanning before handling scrolling gesture.
+      if (mTouchQueue[0].mType == MultiTouchInput::MULTITOUCH_MOVE) {
+        mDelayPanning = false;
+      }
       if (!aPreventDefault) {
         HandleInputEvent(mTouchQueue[0]);
       }
 
       if (mTouchQueue[0].mType == MultiTouchInput::MULTITOUCH_END ||
           mTouchQueue[0].mType == MultiTouchInput::MULTITOUCH_CANCEL) {
         mTouchQueue.RemoveElementAt(0);
         break;
--- a/gfx/layers/ipc/AsyncPanZoomController.h
+++ b/gfx/layers/ipc/AsyncPanZoomController.h
@@ -103,26 +103,32 @@ public:
    * the frame this is tied to during composition onto, in device pixels. In
    * general, this will just be:
    * { x = 0, y = 0, width = surface.width, height = surface.height }, however
    * there is no hard requirement for this.
    */
   void UpdateCompositionBounds(const nsIntRect& aCompositionBounds);
 
   /**
-   * We have found a scrollable subframe, so disable our machinery until we hit
+   * We are scrolling a subframe, so disable our machinery until we hit
    * a touch end or a new touch start. This prevents us from accidentally
    * panning both the subframe and the parent frame.
    *
    * XXX/bug 775452: We should eventually be supporting async scrollable
    * subframes.
    */
   void CancelDefaultPanZoom();
 
   /**
+   * We have found a scrollable subframe, so we need to delay the scrolling
+   * gesture executed and let subframe do the scrolling first.
+   */
+  void DetectScrollableSubframe();
+
+  /**
    * Kicks an animation to zoom to a rect. This may be either a zoom out or zoom
    * in. The actual animation is done on the compositor thread after being set
    * up. |aRect| must be given in CSS pixels, relative to the document.
    */
   void ZoomToRect(const gfxRect& aRect);
 
   /**
    * If we have touch listeners, this should always be called when we know
@@ -544,15 +550,21 @@ private:
   bool mDisableNextTouchBatch;
 
   // Flag used to determine whether or not we should try to enter the
   // WAITING_LISTENERS state. This is used in the case that we are processing a
   // queued up event block. If set, this means that we are handling this queue
   // and we don't want to queue the events back up again.
   bool mHandlingTouchQueue;
 
+  // Flag used to determine whether or not we should try scrolling by
+  // BrowserElementScrolling first. If set, this means we should pend touch move
+  // event, which not be cosumed by GestureListener. This flag will be reset
+  // after touch move event has been handled by content process.
+  bool mDelayPanning;
+
   friend class Axis;
 };
 
 }
 }
 
 #endif // mozilla_layers_PanZoomController_h
--- a/gfx/layers/opengl/ThebesLayerOGL.cpp
+++ b/gfx/layers/opengl/ThebesLayerOGL.cpp
@@ -852,22 +852,17 @@ ThebesLayerOGL::RenderLayer(int aPreviou
   gl()->fActiveTexture(LOCAL_GL_TEXTURE0);
 
   TextureImage::ContentType contentType =
     CanUseOpaqueSurface() ? gfxASurface::CONTENT_COLOR :
                             gfxASurface::CONTENT_COLOR_ALPHA;
 
   uint32_t flags = 0;
 #ifndef MOZ_GFX_OPTIMIZE_MOBILE
-  gfxMatrix transform2d;
-  if (GetEffectiveTransform().Is2D(&transform2d)) {
-    if (transform2d.HasNonIntegerTranslation()) {
-      flags |= ThebesLayerBufferOGL::PAINT_WILL_RESAMPLE;
-    }
-  } else {
+  if (MayResample()) {
     flags |= ThebesLayerBufferOGL::PAINT_WILL_RESAMPLE;
   }
 #endif
 
   Buffer::PaintState state = mBuffer->BeginPaint(contentType, flags);
   mValidRegion.Sub(mValidRegion, state.mRegionToInvalidate);
 
   if (state.mContext) {
--- a/image/test/mochitest/test_bug733553.html
+++ b/image/test/mochitest/test_bug733553.html
@@ -64,17 +64,20 @@ function readyForNext() {
 
 function imageLoad(aEvent) {
   var [width, fileName] = testParts[testIndex];
   is(aEvent.target.width, width,
      "Test " + testIndex + " " + fileName + " width correct");
 
   // Always call readyForNext here, as it's the closest we have to a cleanup
   readyForNext();
-  if ((testParts.length - 1) == testIndex) {
+  if (testParts.length == testIndex) {
+    var firstimg = document.getElementsByTagName('img')[0];
+    firstimg.removeEventListener("load", imageLoad, false);
+    firstimg.removeEventListener("error", imageLoad, false);
     SimpleTest.finish();
   }
 }
 
 </script>
 </pre>
 <div id="content"> <!-- style="display: none" -->
 <iframe id="loader"></iframe>
--- a/intl/lwbrk/public/nsILineBreaker.h
+++ b/intl/lwbrk/public/nsILineBreaker.h
@@ -50,21 +50,23 @@ public:
 NS_DEFINE_STATIC_IID_ACCESSOR(nsILineBreaker, NS_ILINEBREAKER_IID)
 
 static inline bool
 NS_IsSpace(PRUnichar u)
 {
   return u == 0x0020 ||                  // SPACE
          u == 0x0009 ||                  // CHARACTER TABULATION
          u == 0x000D ||                  // CARRIAGE RETURN
+         u == 0x1680 ||                  // OGHAM SPACE MARK
          (0x2000 <= u && u <= 0x2006) || // EN QUAD, EM QUAD, EN SPACE,
                                          // EM SPACE, THREE-PER-EM SPACE,
                                          // FOUR-PER-SPACE, SIX-PER-EM SPACE,
-         (0x2008 <= u && u <= 0x200B);   // PUNCTUATION SPACE, THIN SPACE,
+         (0x2008 <= u && u <= 0x200B) || // PUNCTUATION SPACE, THIN SPACE,
                                          // HAIR SPACE, ZERO WIDTH SPACE
+         u == 0x205F;                    // MEDIUM MATHEMATICAL SPACE 
 }
 
 static inline bool
 NS_NeedsPlatformNativeHandling(PRUnichar aChar)
 {
   return (0x0e01 <= aChar && aChar <= 0x0fff); // Thai, Lao, Tibetan
 }
 
--- a/intl/lwbrk/src/jisx4501class.h
+++ b/intl/lwbrk/src/jisx4501class.h
@@ -48,17 +48,17 @@ 0x777277B7, // U+2010 - U+2017
 0x77A777A7, // U+2018 - U+201F
 0xAAAA7777, // U+2020 - U+2027
 0xB7777777, // U+2028 - U+202F
 0x77744444, // U+2030 - U+2037
 0x7A115107, // U+2038 - U+203F
 0x11017777, // U+2040 - U+2047
 0x77777711, // U+2048 - U+204F
 0x77777777, // U+2050 - U+2057
-0x77777777, // U+2058 - U+205F
+0x57777777, // U+2058 - U+205F
 0x77777777, // U+2060 - U+2067
 0x77777777, // U+2068 - U+206F
 0x77777777, // U+2070 - U+2077
 0x77777777, // U+2078 - U+207F
 0x77777777, // U+2080 - U+2087
 0x77777777, // U+2088 - U+208F
 0x77777777, // U+2090 - U+2097
 0x77777777, // U+2098 - U+209F
--- a/intl/lwbrk/src/nsJISx4501LineBreaker.cpp
+++ b/intl/lwbrk/src/nsJISx4501LineBreaker.cpp
@@ -486,16 +486,22 @@ GetClass(PRUnichar u)
        c = CLASS_NON_BREAKABLE;
      else
        c = CLASS_CHARACTER;
    } else if (0x1800 == h) {
      if (0x0E == l)
        c = CLASS_NON_BREAKABLE;
      else
        c = CLASS_CHARACTER;
+   } else if (0x1600 == h) {
+     if (0x80 == l) { // U+1680 OGHAM SPACE MARK
+       c = CLASS_BREAKABLE;
+     } else {
+       c = CLASS_CHARACTER;
+     }
    } else {
      c = CLASS_CHARACTER; // others
    }
    return c;
 }
 
 static bool
 GetPair(int8_t c1, int8_t c2)
--- a/intl/lwbrk/tools/anzx4501.html
+++ b/intl/lwbrk/tools/anzx4501.html
@@ -249,18 +249,18 @@ Analysis of JIS X 4051 to Unicode Genera
 </TR>
 <TR><TH>05_[b]<TH>
 <TD>33</TD>
 <TD>153</TD>
 <TD></TD>
 <TD>33</TD>
 <TD>2</TD>
 <TD>5</TD>
-<TD>12</TD>
-<TD BGCOLOR=white>238</TD>
+<TD>13</TD>
+<TD BGCOLOR=white>239</TD>
 <TD>32</TD>
 <TD>1</TD>
 <TD></TD>
 <TD></TD>
 <TD></TD>
 <TD></TD>
 <TD>153</TD>
 <TD></TD>
@@ -279,17 +279,17 @@ Analysis of JIS X 4051 to Unicode Genera
 <TD>2</TD>
 <TD></TD>
 <TD></TD>
 <TD></TD>
 <TD></TD>
 <TD>5</TD>
 <TD></TD>
 <TD></TD>
-<TD>12</TD>
+<TD>13</TD>
 </TR>
 <TR><TH>06_15<TH>
 <TD></TD>
 <TD></TD>
 <TD></TD>
 <TD>30</TD>
 <TD></TD>
 <TD></TD>
@@ -322,52 +322,52 @@ Analysis of JIS X 4051 to Unicode Genera
 <TD></TD>
 <TD></TD>
 <TD></TD>
 <TD></TD>
 <TD></TD>
 </TR>
 <TR><TH>07_18<TH>
 <TD>19</TD>
-<TD>156</TD>
+<TD>157</TD>
 <TD></TD>
 <TD>33</TD>
 <TD>56</TD>
-<TD>126</TD>
-<TD>3</TD>
-<TD BGCOLOR=white>393</TD>
+<TD>125</TD>
+<TD>2</TD>
+<TD BGCOLOR=white>392</TD>
 <TD></TD>
 <TD>19</TD>
 <TD></TD>
 <TD></TD>
-<TD>67</TD>
+<TD>64</TD>
+<TD>7</TD>
 <TD>5</TD>
-<TD>4</TD>
 <TD></TD>
-<TD>80</TD>
+<TD>81</TD>
 <TD></TD>
 <TD></TD>
 <TD></TD>
 <TD></TD>
 <TD>3</TD>
 <TD>30</TD>
 <TD>4</TD>
 <TD>5</TD>
 <TD>2</TD>
 <TD></TD>
 <TD>5</TD>
 <TD>36</TD>
 <TD>4</TD>
 <TD></TD>
 <TD>3</TD>
-<TD>23</TD>
-<TD>100</TD>
+<TD>24</TD>
+<TD>98</TD>
 <TD>1</TD>
 <TD>1</TD>
-<TD>1</TD>
+<TD></TD>
 </TR>
 <TR><TH>08_COMPLEX<TH>
 <TD></TD>
 <TD></TD>
 <TD></TD>
 <TD></TD>
 <TD></TD>
 <TD></TD>
@@ -442,46 +442,46 @@ Analysis of JIS X 4051 to Unicode Genera
 <TD></TD>
 <TD></TD>
 </TR>
 <TR><TH>0A_[d]<TH>
 <TD>1</TD>
 <TD>2</TD>
 <TD></TD>
 <TD>6</TD>
-<TD>26</TD>
-<TD>16</TD>
+<TD>28</TD>
+<TD>14</TD>
 <TD></TD>
 <TD BGCOLOR=white>51</TD>
 <TD></TD>
 <TD>1</TD>
 <TD></TD>
 <TD></TD>
-<TD>2</TD>
+<TD>1</TD>
 <TD></TD>
-<TD></TD>
+<TD>1</TD>
 <TD></TD>
 <TD></TD>
 <TD></TD>
 <TD></TD>
 <TD></TD>
 <TD></TD>
 <TD></TD>
 <TD>6</TD>
 <TD></TD>
 <TD></TD>
 <TD>3</TD>
 <TD>3</TD>
 <TD></TD>
-<TD>20</TD>
+<TD>22</TD>
 <TD></TD>
 <TD>2</TD>
 <TD>3</TD>
 <TD>7</TD>
-<TD>4</TD>
+<TD>2</TD>
 <TD></TD>
 <TD></TD>
 <TD></TD>
 </TR>
 <TR><TH>0B_[e]<TH>
 <TD></TD>
 <TD></TD>
 <TD></TD>
@@ -607,19 +607,19 @@ Analysis of JIS X 4051 to Unicode Genera
 <TD></TD>
 </TR>
 <TR><TH>20<TH>
 <TD>2</TD>
 <TD>8</TD>
 <TD>1</TD>
 <TD></TD>
 <TD>5</TD>
-<TD>12</TD>
+<TD>13</TD>
 <TD></TD>
-<TD>102</TD>
+<TD>101</TD>
 <TD></TD>
 <TD></TD>
 <TD>7</TD>
 <TD>3</TD>
 <TD></TD>
 </TR>
 <TR><TH>21<TH>
 <TD></TD>
--- a/intl/lwbrk/tools/anzx4501.pl
+++ b/intl/lwbrk/tools/anzx4501.pl
@@ -54,16 +54,20 @@ open ( HEADER , "> ../src/jisx4501class.
   || die "cannot open output ../src/jisx4501class.h file";
 
 ######################################################################
 #
 # Generate license and header
 #
 ######################################################################
 $hthmlheader = <<END_OF_HTML;
+<!-- This Source Code Form is subject to the terms of the Mozilla Public
+   - License, v. 2.0. If a copy of the MPL was not distributed with this
+   - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
+
 <HTML>
 <HEAD>
 <TITLE>
 Analysis of JIS X 4051 to Unicode General Category Mapping
 </TITLE>
 </HEAD>
 <BODY>
 <H1>
--- a/intl/lwbrk/tools/jisx4501class.txt
+++ b/intl/lwbrk/tools/jisx4501class.txt
@@ -65,17 +65,19 @@ 203A;;2
 203B;;12
 203C;203D;3
 203E;;23
 203F;2043;18
 2044;;3
 2045;;1
 2046;;2
 2047;2049;3
-204A;2063;18
+204A;205E;18
+205F;;17
+2060;2063;18
 206A;206F;18
 2070;2071;18
 2074;208E;18
 2090;2094;18
 2116;;8
 2160;217F;12
 2190;21EA;a12
 2126;;18
--- a/js/src/ion/Bailouts.cpp
+++ b/js/src/ion/Bailouts.cpp
@@ -591,19 +591,20 @@ ion::CachedShapeGuardFailure()
 }
 
 uint32_t
 ion::ThunkToInterpreter(Value *vp)
 {
     JSContext *cx = GetIonContext()->cx;
     IonActivation *activation = cx->runtime->ionActivation;
     BailoutClosure *br = activation->takeBailout();
+    InterpMode resumeMode = JSINTERP_BAILOUT;
 
     if (!EnsureHasScopeObjects(cx, cx->fp()))
-        return Interpret_Error;
+        resumeMode = JSINTERP_RETHROW;
 
     // By default we set the forbidOsr flag on the ion script, but if a GC
     // happens just after we re-enter the interpreter, the ion script get
     // invalidated and we do not see the forbidOsr flag.  This may cause a loop
     // which apear with eager compilation and gc zeal enabled.  This code is a
     // workaround to avoid recompiling with OSR just after a bailout followed by
     // a GC. (see Bug 746691 & Bug 751383)
     jsbytecode *pc = cx->regs().pc;
@@ -626,18 +627,20 @@ ion::ThunkToInterpreter(Value *vp)
             fp = iter.interpFrame();
             script = iter.script();
             if (script->needsArgsObj()) {
                 // Currently IonMonkey does not compile if the script needs an
                 // arguments object, so the frame should not have any argument
                 // object yet.
                 JS_ASSERT(!fp->hasArgsObj());
                 ArgumentsObject *argsobj = ArgumentsObject::createExpected(cx, fp);
-                if (!argsobj)
-                    return Interpret_Error;
+                if (!argsobj) {
+                    resumeMode = JSINTERP_RETHROW;
+                    break;
+                }
                 InternalBindingsHandle bindings(script, &script->bindings);
                 const unsigned var = Bindings::argumentsVarIndex(cx, bindings);
                 // The arguments is a local binding and needsArgsObj does not
                 // check if it is clobbered. Ensure that the local binding
                 // restored during bailout before storing the arguments object
                 // to the slot.
                 if (fp->unaliasedLocal(var).isMagic(JS_OPTIMIZED_ARGUMENTS))
                     fp->unaliasedLocal(var) = ObjectValue(*argsobj);
@@ -648,20 +651,21 @@ ion::ThunkToInterpreter(Value *vp)
 
     if (activation->entryfp() == br->entryfp()) {
         // If the bailout entry fp is the same as the activation entryfp, then
         // there are no scripted frames below us. In this case, just shortcut
         // out with a special return code, and resume interpreting in the
         // original Interpret activation.
         vp->setMagic(JS_ION_BAILOUT);
         js_delete(br);
-        return Interpret_Ok;
+        return resumeMode == JSINTERP_RETHROW ? Interpret_Error : Interpret_Ok;
     }
 
-    InterpretStatus status = Interpret(cx, br->entryfp(), JSINTERP_BAILOUT);
+    InterpretStatus status = Interpret(cx, br->entryfp(), resumeMode);
+    JS_ASSERT_IF(resumeMode == JSINTERP_RETHROW, status == Interpret_Error);
 
     if (status == Interpret_OSR) {
         // The interpreter currently does not ask to perform inline OSR, so
         // this path is unreachable.
         JS_NOT_REACHED("invalid");
 
         IonSpew(IonSpew_Bailouts, "Performing inline OSR %s:%d",
                 cx->fp()->script()->filename,
--- a/js/src/ion/MCallOptimize.cpp
+++ b/js/src/ion/MCallOptimize.cpp
@@ -708,17 +708,18 @@ IonBuilder::inlineStrCharCodeAt(uint32_t
 {
     if (argc != 1 || constructing)
         return InliningStatus_NotInlined;
 
     if (getInlineReturnType() != MIRType_Int32)
         return InliningStatus_NotInlined;
     if (getInlineArgType(argc, 0) != MIRType_String)
         return InliningStatus_NotInlined;
-    if (getInlineArgType(argc, 1) != MIRType_Int32)
+    MIRType argType = getInlineArgType(argc, 1);
+    if (argType != MIRType_Int32 && argType != MIRType_Double)
         return InliningStatus_NotInlined;
 
     MDefinitionVector argv;
     if (!discardCall(argc, argv, current))
         return InliningStatus_Error;
 
     MInstruction *index = MToInt32::New(argv[1]);
     current->add(index);
@@ -763,17 +764,18 @@ IonBuilder::inlineStrCharAt(uint32_t arg
 {
     if (argc != 1 || constructing)
         return InliningStatus_NotInlined;
 
     if (getInlineReturnType() != MIRType_String)
         return InliningStatus_NotInlined;
     if (getInlineArgType(argc, 0) != MIRType_String)
         return InliningStatus_NotInlined;
-    if (getInlineArgType(argc, 1) != MIRType_Int32)
+    MIRType argType = getInlineArgType(argc, 1);
+    if (argType != MIRType_Int32 && argType != MIRType_Double)
         return InliningStatus_NotInlined;
 
     MDefinitionVector argv;
     if (!discardCall(argc, argv, current))
         return InliningStatus_Error;
 
     MInstruction *index = MToInt32::New(argv[1]);
     current->add(index);
--- a/js/src/ion/TypeOracle.cpp
+++ b/js/src/ion/TypeOracle.cpp
@@ -343,24 +343,25 @@ TypeInferenceOracle::elementReadIsTypedA
     }
 
     return true;
 }
 
 bool
 TypeInferenceOracle::elementReadIsString(JSScript *script, jsbytecode *pc)
 {
-    // Check for string[int32].
+    // Check for string[index].
     StackTypeSet *value = script->analysis()->poppedTypes(pc, 1);
     StackTypeSet *id = script->analysis()->poppedTypes(pc, 0);
 
     if (value->getKnownTypeTag() != JSVAL_TYPE_STRING)
         return false;
 
-    if (id->getKnownTypeTag() != JSVAL_TYPE_INT32)
+    JSValueType idType = id->getKnownTypeTag();
+    if (idType != JSVAL_TYPE_INT32 && idType != JSVAL_TYPE_DOUBLE)
         return false;
 
     // This function is used for jsop_getelem_string which should return
     // undefined if this is out-side the string bounds. Currently we just
     // fallback to a CallGetElement.
     StackTypeSet *pushed = script->analysis()->pushedTypes(pc, 0);
     if (pushed->getKnownTypeTag() != JSVAL_TYPE_STRING)
         return false;
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -802,16 +802,19 @@ JSRuntime::JSRuntime(JSUseHelperThreads 
     gcSweepingCompartments(NULL),
     gcCompartmentGroupIndex(0),
     gcCompartmentGroups(NULL),
     gcCurrentCompartmentGroup(NULL),
     gcSweepPhase(0),
     gcSweepCompartment(NULL),
     gcSweepKindIndex(0),
     gcArenasAllocatedDuringSweep(NULL),
+#ifdef DEBUG
+    gcMarkingValidator(NULL),
+#endif
     gcInterFrameGC(0),
     gcSliceBudget(SliceBudget::Unlimited),
     gcIncrementalEnabled(true),
     gcExactScanningEnabled(true),
     gcManipulatingDeadCompartments(false),
     gcObjectsMarkedInDeadCompartments(0),
     gcPoke(false),
     heapState(Idle),
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -445,16 +445,20 @@ class PerThreadData : public js::PerThre
      */
     int32_t             suppressGC;
 
     PerThreadData(JSRuntime *runtime);
 
     bool associatedWith(const JSRuntime *rt) { return runtime_ == rt; }
 };
 
+namespace gc {
+class MarkingValidator;
+} // namespace gc
+
 } // namespace js
 
 struct JSRuntime : js::RuntimeFriendFields
 {
     /* Per-thread data for the main thread that is associated with
      * this JSRuntime, as opposed to any worker threads used in
      * parallel sections.  See definition of |PerThreadData| struct
      * above for more details.
@@ -724,16 +728,20 @@ struct JSRuntime : js::RuntimeFriendFiel
     JSCompartment       *gcSweepCompartment;
     int                 gcSweepKindIndex;
 
     /*
      * List head of arenas allocated during the sweep phase.
      */
     js::gc::ArenaHeader *gcArenasAllocatedDuringSweep;
 
+#ifdef DEBUG
+    js::gc::MarkingValidator *gcMarkingValidator;
+#endif
+
     /*
      * Indicates that a GC slice has taken place in the middle of an animation
      * frame, rather than at the beginning. In this case, the next slice will be
      * delayed so that we don't get back-to-back slices.
      */
     volatile uintptr_t  gcInterFrameGC;
 
     /* Default budget for incremental GC slice. See SliceBudget in jsgc.h. */
--- a/js/src/jsgc.cpp
+++ b/js/src/jsgc.cpp
@@ -2693,43 +2693,58 @@ BeginMarkPhase(JSRuntime *rt)
         if (!c->maybeAlive)
             c->scheduledForDestruction = true;
     }
     rt->gcFoundBlackGrayEdges = false;
 
     return true;
 }
 
-void
+template <class CompartmentIter>
+static void
 MarkWeakReferences(JSRuntime *rt, gcstats::Phase phase)
 {
     GCMarker *gcmarker = &rt->gcMarker;
     JS_ASSERT(gcmarker->isDrained());
 
     gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP_MARK);
     gcstats::AutoPhase ap1(rt->gcStats, phase);
 
     for (;;) {
         bool markedAny = false;
-        for (GCCompartmentGroupIter c(rt); !c.done(); c.next()) {
+        for (CompartmentIter c(rt); !c.done(); c.next()) {
             markedAny |= WatchpointMap::markCompartmentIteratively(c, gcmarker);
             markedAny |= WeakMapBase::markCompartmentIteratively(c, gcmarker);
         }
         markedAny |= Debugger::markAllIteratively(gcmarker);
 
         if (!markedAny)
             break;
 
         SliceBudget budget;
         gcmarker->drainMarkStack(budget);
     }
     JS_ASSERT(gcmarker->isDrained());
 }
 
 static void
+MarkWeakReferencesInCurrentGroup(JSRuntime *rt, gcstats::Phase phase)
+{
+    MarkWeakReferences<GCCompartmentGroupIter>(rt, phase);
+}
+
+#ifdef DEBUG
+static void
+MarkAllWeakReferences(JSRuntime *rt, gcstats::Phase phase)
+{
+    MarkWeakReferences<GCCompartmentsIter>(rt, phase);
+}
+#endif
+
+static void
 MarkGrayReferences(JSRuntime *rt)
 {
     GCMarker *gcmarker = &rt->gcMarker;
 
     {
         gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP_MARK);
         gcstats::AutoPhase ap1(rt->gcStats, gcstats::PHASE_SWEEP_MARK_GRAY);
         gcmarker->setMarkColorGray();
@@ -2738,135 +2753,235 @@ MarkGrayReferences(JSRuntime *rt)
         } else {
             if (JSTraceDataOp op = rt->gcGrayRootsTraceOp)
                 (*op)(gcmarker, rt->gcGrayRootsData);
         }
         SliceBudget budget;
         gcmarker->drainMarkStack(budget);
     }
 
-    MarkWeakReferences(rt, gcstats::PHASE_SWEEP_MARK_GRAY_WEAK);
+    MarkWeakReferencesInCurrentGroup(rt, gcstats::PHASE_SWEEP_MARK_GRAY_WEAK);
 
     JS_ASSERT(gcmarker->isDrained());
 
     gcmarker->setMarkColorBlack();
 }
 
-#if 0
 #ifdef DEBUG
-static void
-ValidateIncrementalMarking(JSRuntime *rt)
+
+class js::gc::MarkingValidator
 {
-    typedef HashMap<Chunk *, uintptr_t *, GCChunkHasher, SystemAllocPolicy> BitmapMap;
+  public:
+    MarkingValidator(JSRuntime *rt);
+    ~MarkingValidator();
+    void nonIncrementalMark();
+    void validate();
+
+  private:
+    JSRuntime *runtime;
+    bool initialized;
+
+    typedef HashMap<Chunk *, ChunkBitmap *, GCChunkHasher, SystemAllocPolicy> BitmapMap;
     BitmapMap map;
+};
+
+js::gc::MarkingValidator::MarkingValidator(JSRuntime *rt)
+  : runtime(rt),
+    initialized(false)
+{}
+
+js::gc::MarkingValidator::~MarkingValidator()
+{
+    if (!map.initialized())
+        return;
+
+    for (BitmapMap::Range r(map.all()); !r.empty(); r.popFront())
+        js_delete(r.front().value);
+}
+
+void
+js::gc::MarkingValidator::nonIncrementalMark()
+{
+    /*
+     * Perform a non-incremental mark for all collecting compartments and record
+     * the results for later comparison.
+     *
+     * Currently this does not validate gray marking.
+     */
+
     if (!map.init())
         return;
 
-    GCMarker *gcmarker = &rt->gcMarker;
+    GCMarker *gcmarker = &runtime->gcMarker;
 
     /* Save existing mark bits. */
-    for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront()) {
+    for (GCChunkSet::Range r(runtime->gcChunkSet.all()); !r.empty(); r.popFront()) {
         ChunkBitmap *bitmap = &r.front()->bitmap;
-        uintptr_t *entry = (uintptr_t *)js_malloc(sizeof(bitmap->bitmap));
+	ChunkBitmap *entry = js_new<ChunkBitmap>();
         if (!entry)
             return;
 
-        memcpy(entry, bitmap->bitmap, sizeof(bitmap->bitmap));
+        memcpy(entry->bitmap, bitmap->bitmap, sizeof(bitmap->bitmap));
         if (!map.putNew(r.front(), entry))
             return;
     }
 
-    /* Save and reset the lists of live weakmaps for the compartments we are collecting. */
+    /*
+     * Save the lists of live weakmaps and array buffers for the compartments we
+     * are collecting.
+     */
     WeakMapVector weakmaps;
-    for (GCCompartmentsIter c(rt); !c.done(); c.next()) {
-        if (!WeakMapBase::saveCompartmentWeakMapList(c, weakmaps))
+    ArrayBufferVector arrayBuffers;
+    for (GCCompartmentsIter c(runtime); !c.done(); c.next()) {
+        if (!WeakMapBase::saveCompartmentWeakMapList(c, weakmaps) ||
+            !ArrayBufferObject::saveArrayBufferList(c, arrayBuffers))
+        {
             return;
+        }
     }
-    for (GCCompartmentsIter c(rt); !c.done(); c.next())
-        WeakMapBase::resetCompartmentWeakMapList(c);
 
     /*
      * After this point, the function should run to completion, so we shouldn't
      * do anything fallible.
      */
+    initialized = true;
+
+    /*
+     * Reset the lists of live weakmaps and array buffers for the compartments we
+     * are collecting.
+     */
+    for (GCCompartmentsIter c(runtime); !c.done(); c.next()) {
+        WeakMapBase::resetCompartmentWeakMapList(c);
+        ArrayBufferObject::resetArrayBufferList(c);
+    }
 
     /* Re-do all the marking, but non-incrementally. */
-    js::gc::State state = rt->gcIncrementalState;
-    rt->gcIncrementalState = MARK_ROOTS;
+    js::gc::State state = runtime->gcIncrementalState;
+    runtime->gcIncrementalState = MARK_ROOTS;
 
     JS_ASSERT(gcmarker->isDrained());
     gcmarker->reset();
 
-    for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront())
+    for (GCChunkSet::Range r(runtime->gcChunkSet.all()); !r.empty(); r.popFront())
         r.front()->bitmap.clear();
 
-    MarkRuntime(gcmarker, true);
+    {
+        gcstats::AutoPhase ap1(runtime->gcStats, gcstats::PHASE_MARK);
+        gcstats::AutoPhase ap2(runtime->gcStats, gcstats::PHASE_MARK_ROOTS);
+        MarkRuntime(gcmarker, true);
+    }
 
     SliceBudget budget;
-    rt->gcIncrementalState = MARK;
-    rt->gcMarker.drainMarkStack(budget);
-    MarkWeakReferences(rt, gcstats::PHASE_SWEEP_MARK_WEAK);
-    MarkGrayReferences(rt);
-
-    /* Now verify that we have the same mark bits as before. */
-    for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront()) {
+    runtime->gcIncrementalState = MARK;
+    runtime->gcMarker.drainMarkStack(budget);
+
+    {
+        gcstats::AutoPhase ap(runtime->gcStats, gcstats::PHASE_SWEEP);
+        MarkAllWeakReferences(runtime, gcstats::PHASE_SWEEP_MARK_WEAK);
+    }
+
+    /* Take a copy of the non-incremental mark state and restore the original. */
+    for (GCChunkSet::Range r(runtime->gcChunkSet.all()); !r.empty(); r.popFront()) {
         Chunk *chunk = r.front();
         ChunkBitmap *bitmap = &chunk->bitmap;
-        uintptr_t *entry = map.lookup(r.front())->value;
-        ChunkBitmap incBitmap;
-
-        memcpy(incBitmap.bitmap, entry, sizeof(incBitmap.bitmap));
-        js_free(entry);
+        ChunkBitmap *entry = map.lookup(chunk)->value;
+        js::Swap(*entry, *bitmap);
+    }
+
+    /* Restore the weak map and array buffer lists. */
+    for (GCCompartmentsIter c(runtime); !c.done(); c.next()) {
+        WeakMapBase::resetCompartmentWeakMapList(c);
+        ArrayBufferObject::resetArrayBufferList(c);
+    }
+    WeakMapBase::restoreCompartmentWeakMapLists(weakmaps);
+    ArrayBufferObject::restoreArrayBufferLists(arrayBuffers);
+
+    runtime->gcIncrementalState = state;
+}
+
+void
+js::gc::MarkingValidator::validate()
+{
+    /*
+     * Validates the incremental marking for a single compartment by comparing
+     * the mark bits to those previously recorded for a non-incremental mark.
+     */
+
+    if (!initialized)
+        return;
+
+    for (GCChunkSet::Range r(runtime->gcChunkSet.all()); !r.empty(); r.popFront()) {
+        Chunk *chunk = r.front();
+        BitmapMap::Ptr ptr = map.lookup(chunk);
+        if (!ptr)
+            continue;  /* Allocated after we did the non-incremental mark. */
+
+        ChunkBitmap *bitmap = ptr->value;
+        ChunkBitmap *incBitmap = &chunk->bitmap;
 
         for (size_t i = 0; i < ArenasPerChunk; i++) {
             if (chunk->decommittedArenas.get(i))
                 continue;
             Arena *arena = &chunk->arenas[i];
             if (!arena->aheader.allocated())
                 continue;
-            if (!arena->aheader.compartment->isCollecting())
+            if (!arena->aheader.compartment->isGCSweeping())
                 continue;
             if (arena->aheader.allocatedDuringIncremental)
                 continue;
 
             AllocKind kind = arena->aheader.getAllocKind();
             uintptr_t thing = arena->thingsStart(kind);
             uintptr_t end = arena->thingsEnd();
             while (thing < end) {
                 Cell *cell = (Cell *)thing;
 
                 /*
                  * If a non-incremental GC wouldn't have collected a cell, then
                  * an incremental GC won't collect it.
                  */
-                JS_ASSERT_IF(bitmap->isMarked(cell, BLACK), incBitmap.isMarked(cell, BLACK));
-
-                /*
-                 * If the cycle collector isn't allowed to collect an object
-                 * after a non-incremental GC has run, then it isn't allowed to
-                 * collected it after an incremental GC.
-                 */
-                JS_ASSERT_IF(!bitmap->isMarked(cell, GRAY), !incBitmap.isMarked(cell, GRAY));
+                JS_ASSERT_IF(bitmap->isMarked(cell, BLACK), incBitmap->isMarked(cell, BLACK));
 
                 thing += Arena::thingSize(kind);
             }
         }
-
-        memcpy(bitmap->bitmap, incBitmap.bitmap, sizeof(incBitmap.bitmap));
     }
-
-    /* Restore the weak map lists. */
-    for (GCCompartmentsIter c(rt); !c.done(); c.next())
-        WeakMapBase::resetCompartmentWeakMapList(c);
-    WeakMapBase::restoreCompartmentWeakMapLists(weakmaps);
-
-    rt->gcIncrementalState = state;
+}
+
+#endif
+
+static void
+ComputeNonIncrementalMarkingForValidation(JSRuntime *rt)
+{
+#ifdef DEBUG
+    JS_ASSERT(!rt->gcMarkingValidator);
+    if (rt->gcIsIncremental && rt->gcValidate)
+        rt->gcMarkingValidator = js_new<MarkingValidator>(rt);
+    if (rt->gcMarkingValidator)
+        rt->gcMarkingValidator->nonIncrementalMark();
+#endif
 }
+
+static void
+ValidateIncrementalMarking(JSRuntime *rt)
+{
+#ifdef DEBUG
+    if (rt->gcMarkingValidator)
+        rt->gcMarkingValidator->validate();
 #endif
+}
+
+static void
+FinishMarkingValidation(JSRuntime *rt)
+{
+#ifdef DEBUG
+    js_delete(rt->gcMarkingValidator);
+    rt->gcMarkingValidator = NULL;
 #endif
+}
 
 static void
 DropStringWrappers(JSRuntime *rt)
 {
     /*
      * String "wrappers" are dropped on GC because their presence would require
      * us to sweep the wrappers in all compartments every time we sweep a
      * compartment group.
@@ -3201,17 +3316,17 @@ EndMarkingCompartmentGroup(JSRuntime *rt
 {
     /*
      * Mark any incoming black pointers from previously swept compartments
      * whose referents are not marked. This can occur when gray cells become
      * black by the action of UnmarkGray.
      */
     MarkIncomingCrossCompartmentPointers(rt, BLACK);
 
-    MarkWeakReferences(rt, gcstats::PHASE_SWEEP_MARK_WEAK);
+    MarkWeakReferencesInCurrentGroup(rt, gcstats::PHASE_SWEEP_MARK_WEAK);
 
     /*
      * Change state of current group to MarkGray to restrict marking to this
      * group.  Note that there may be pointers to the atoms compartment, and
      * these will be marked through, as they are not marked with
      * MarkCrossCompartmentXXX.
      */
     for (GCCompartmentGroupIter c(rt); !c.done(); c.next()) {
@@ -3252,16 +3367,18 @@ BeginSweepingCompartmentGroup(JSRuntime 
 
         /* Purge the ArenaLists before sweeping. */
         c->arenas.purge();
 
         if (c == rt->atomsCompartment)
             sweepingAtoms = true;
     }
 
+    ValidateIncrementalMarking(rt);
+
     FreeOp fop(rt, rt->gcSweepOnBackgroundThread);
 
     {
         gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_FINALIZE_START);
         if (rt->gcFinalizeCallback)
             rt->gcFinalizeCallback(&fop, JSFINALIZE_GROUP_START, !rt->gcIsFull /* unused */);
     }
 
@@ -3353,16 +3470,19 @@ BeginSweepPhase(JSRuntime *rt)
 {
     /*
      * Sweep phase.
      *
      * Finalize as we sweep, outside of rt->gcLock but with rt->isHeapBusy()
      * true so that any attempt to allocate a GC-thing from a finalizer will
      * fail, rather than nest badly and leave the unmarked newborn to be swept.
      */
+
+    ComputeNonIncrementalMarkingForValidation(rt);
+
     gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP);
 
 #ifdef JS_THREADSAFE
     rt->gcSweepOnBackgroundThread = rt->hasContexts() && rt->useHelperThreads();
 #endif
 
 #ifdef DEBUG
     for (CompartmentsIter c(rt); !c.done(); c.next()) {
@@ -3562,16 +3682,18 @@ EndSweepPhase(JSRuntime *rt, JSGCInvocat
         for (unsigned i = 0 ; i < FINALIZE_LIMIT ; ++i) {
             JS_ASSERT_IF(!IsBackgroundFinalized(AllocKind(i)) ||
                          !rt->gcSweepOnBackgroundThread,
                          !c->arenas.arenaListsToSweep[i]);
         }
 #endif
     }
 
+    FinishMarkingValidation(rt);
+
     rt->gcLastGCTime = PRMJ_Now();
 }
 
 /* ...while this class is to be used only for garbage collection. */
 class AutoGCSession : AutoTraceSession {
   public:
     explicit AutoGCSession(JSRuntime *rt);
     ~AutoGCSession();
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -1224,16 +1224,23 @@ js::Interpret(JSContext *cx, StackFrame 
         }
     }
 
     /* The REJOIN mode acts like the normal mode, except the prologue is skipped. */
     if (interpMode == JSINTERP_REJOIN)
         interpMode = JSINTERP_NORMAL;
 
     /*
+     * The RETHROW mode acts like a bailout mode, except that it resume an
+     * exception instead of resuming the script.
+     */
+    if (interpMode == JSINTERP_RETHROW)
+        goto error;
+
+    /*
      * It is important that "op" be initialized before calling DO_OP because
      * it is possible for "op" to be specially assigned during the normal
      * processing of an opcode while looping. We rely on DO_NEXT_OP to manage
      * "op" correctly in all other cases.
      */
     JSOp op;
     int32_t len;
     len = 0;
--- a/js/src/jsinterp.h
+++ b/js/src/jsinterp.h
@@ -167,17 +167,18 @@ extern bool
 Execute(JSContext *cx, HandleScript script, JSObject &scopeChain, Value *rval);
 
 /* Flags to toggle js::Interpret() execution. */
 enum InterpMode
 {
     JSINTERP_NORMAL    = 0, /* interpreter is running normally */
     JSINTERP_REJOIN    = 1, /* as normal, but the frame has already started */
     JSINTERP_SKIP_TRAP = 2, /* as REJOIN, but skip trap at first opcode */
-    JSINTERP_BAILOUT   = 3  /* interpreter is running from an Ion bailout */
+    JSINTERP_BAILOUT   = 3, /* interpreter is running from an Ion bailout */
+    JSINTERP_RETHROW   = 4  /* as BAILOUT, but unwind all frames */
 };
 
 enum InterpretStatus
 {
     Interpret_Error    = 0, /* interpreter had an error */
     Interpret_Ok       = 1, /* interpreter executed successfully */
     Interpret_OSR      = 2  /* when mode=BAILOUT and we should OSR into Ion */
 };
--- a/js/src/jsinterpinlines.h
+++ b/js/src/jsinterpinlines.h
@@ -785,21 +785,21 @@ GetObjectElementOperation(JSContext *cx,
 
 static JS_ALWAYS_INLINE bool
 GetElementOperation(JSContext *cx, JSOp op, HandleValue lref, HandleValue rref,
                     MutableHandleValue res)
 {
     AssertCanGC();
     JS_ASSERT(op == JSOP_GETELEM || op == JSOP_CALLELEM);
 
-    if (lref.isString() && rref.isInt32()) {
+    uint32_t index;
+    if (lref.isString() && IsDefinitelyIndex(rref, &index)) {
         JSString *str = lref.toString();
-        int32_t i = rref.toInt32();
-        if (size_t(i) < str->length()) {
-            str = cx->runtime->staticStrings.getUnitStringForElement(cx, str, size_t(i));
+        if (index < str->length()) {
+            str = cx->runtime->staticStrings.getUnitStringForElement(cx, str, index);
             if (!str)
                 return false;
             res.setString(str);
             return true;
         }
     }
 
     StackFrame *fp = cx->fp();
--- a/js/src/jsscript.h
+++ b/js/src/jsscript.h
@@ -374,16 +374,18 @@ struct JSScript : public js::gc::Cell
 
     /* Persistent type information retained across GCs. */
     js::types::TypeScript *types;
 
   private:
     js::ScriptSource *scriptSource_; /* source code */
 #ifdef JS_METHODJIT
     JITScriptSet *mJITInfo;
+#else
+    void         *mJITInfoPad;
 #endif
     js::HeapPtrFunction function_;
     js::HeapPtrObject   enclosingScope_;
 
     // 32-bit fields.
 
   public:
     uint32_t        length;     /* length of code vector */
@@ -474,19 +476,24 @@ struct JSScript : public js::gc::Cell
                                                    script */
     bool            hasSingletons:1;  /* script has singleton objects */
     bool            isActiveEval:1;   /* script came from eval(), and is still active */
     bool            isCachedEval:1;   /* script came from eval(), and is in eval cache */
     bool            uninlineable:1;   /* script is considered uninlineable by analysis */
 #ifdef JS_METHODJIT
     bool            debugMode:1;      /* script was compiled in debug mode */
     bool            failedBoundsCheck:1; /* script has had hoisted bounds checks fail */
+#else
+    bool            debugModePad:1;
+    bool            failedBoundsCheckPad:1;
 #endif
 #ifdef JS_ION
     bool            failedShapeGuard:1; /* script has had hoisted shape guard fail */
+#else
+    bool            failedShapeGuardPad:1;
 #endif
     bool            invalidatedIdempotentCache:1; /* idempotent cache has triggered invalidation */
     bool            isGenerator:1;    /* is a generator */
     bool            isGeneratorExp:1; /* is a generator expression */
     bool            hasScriptCounts:1;/* script has an entry in
                                          JSCompartment::scriptCountsMap */
     bool            hasDebugScript:1; /* script has an entry in
                                          JSCompartment::debugScriptMap */
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -589,34 +589,66 @@ ArrayBufferObject::sweep(JSCompartment *
         }
         *views = prevLiveView;
 
         buffer = nextBuffer;
     }
 }
 
 void
-ArrayBufferObject::resetArrayBufferList(JSCompartment *compartment)
+ArrayBufferObject::resetArrayBufferList(JSCompartment *comp)
 {
-    JSObject *buffer = compartment->gcLiveArrayBuffers;
+    JSObject *buffer = comp->gcLiveArrayBuffers;
     JS_ASSERT(buffer != UNSET_BUFFER_LINK);
-    compartment->gcLiveArrayBuffers = NULL;
+    comp->gcLiveArrayBuffers = NULL;
 
     while (buffer) {
         JSObject *view = *GetViewList(&buffer->asArrayBuffer());
         JS_ASSERT(view);
 
         JSObject *nextBuffer = BufferLink(view);
         JS_ASSERT(nextBuffer != UNSET_BUFFER_LINK);
 
         SetBufferLink(view, UNSET_BUFFER_LINK);
         buffer = nextBuffer;
     }
 }
 
+/* static */ bool
+ArrayBufferObject::saveArrayBufferList(JSCompartment *comp, ArrayBufferVector &vector)
+{
+    JSObject *obj = comp->gcLiveArrayBuffers;
+    while (obj) {
+        JS_ASSERT(obj != UNSET_BUFFER_LINK);
+        ArrayBufferObject *buffer = &obj->asArrayBuffer();
+        if (!vector.append(buffer))
+            return false;
+
+        JSObject *view = *GetViewList(buffer);
+        JS_ASSERT(view);
+        obj = BufferLink(view);
+    }
+    return true;
+}
+
+/* static */ void
+ArrayBufferObject::restoreArrayBufferLists(ArrayBufferVector &vector)
+{
+    for (ArrayBufferObject **p = vector.begin(); p != vector.end(); p++) {
+        ArrayBufferObject *buffer = *p;
+        JSCompartment *comp = buffer->compartment();
+        JSObject *firstView = *GetViewList(&buffer->asArrayBuffer());
+        JS_ASSERT(firstView);
+        JS_ASSERT(firstView->compartment() == comp);
+        JS_ASSERT(BufferLink(firstView) == UNSET_BUFFER_LINK);
+        SetBufferLink(firstView, comp->gcLiveArrayBuffers);
+        comp->gcLiveArrayBuffers = buffer;
+    }
+}
+
 JSBool
 ArrayBufferObject::obj_lookupGeneric(JSContext *cx, HandleObject obj, HandleId id,
                                      MutableHandleObject objp, MutableHandleShape propp)
 {
     RootedObject delegate(cx, ArrayBufferDelegate(cx, obj));
     if (!delegate)
         return false;
 
--- a/js/src/jstypedarray.h
+++ b/js/src/jstypedarray.h
@@ -12,16 +12,18 @@
 #include "jsobj.h"
 
 #include "gc/Barrier.h"
 
 typedef struct JSProperty JSProperty;
 
 namespace js {
 
+typedef Vector<ArrayBufferObject *, 0, SystemAllocPolicy> ArrayBufferVector;
+
 /*
  * ArrayBufferObject
  *
  * This class holds the underlying raw buffer that the various ArrayBufferView
  * subclasses (DataView and the TypedArrays) access. It can be created
  * explicitly and passed to an ArrayBufferView subclass, or can be created
  * implicitly by constructing a TypedArray with a size.
  */
@@ -128,16 +130,18 @@ class ArrayBufferObject : public JSObjec
                                     JSBool strict);
 
     static JSBool obj_enumerate(JSContext *cx, HandleObject obj, JSIterateOp enum_op,
                                 MutableHandleValue statep, MutableHandleId idp);
 
     static void sweep(JSCompartment *rt);
 
     static void resetArrayBufferList(JSCompartment *rt);
+    static bool saveArrayBufferList(JSCompartment *c, ArrayBufferVector &vector);
+    static void restoreArrayBufferLists(ArrayBufferVector &vector);
 
     static bool stealContents(JSContext *cx, JSObject *obj, void **contents,
                               uint8_t **data);
 
     static inline void setElementsHeader(js::ObjectElements *header, uint32_t bytes);
 
     void addView(RawObject view);
 
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -2778,20 +2778,21 @@ ChooseScaleAndSetTransform(FrameLayerBui
     gfxMatrix frameTransform;
     if (aContainerFrame->AreLayersMarkedActive(nsChangeHint_UpdateTransformLayer) &&
         aTransform &&
         (!aTransform->Is2D(&frameTransform) || frameTransform.HasNonTranslationOrFlip())) {
       // Don't clamp the scale factor when the new desired scale factor matches the old one
       // or it was previously unscaled.
       bool clamp = true;
       gfxMatrix oldFrameTransform2d;
-      if (aLayer->GetTransform().Is2D(&oldFrameTransform2d)) {
+      if (aLayer->GetBaseTransform().Is2D(&oldFrameTransform2d)) {
         gfxSize oldScale = oldFrameTransform2d.ScaleFactors(true);
-        if (oldScale == scale || oldScale == gfxSize(1.0, 1.0))
+        if (oldScale == scale || oldScale == gfxSize(1.0, 1.0)) {
           clamp = false;
+        }
       }
       if (clamp) {
         scale.width = gfxUtils::ClampToScaleFactor(scale.width);
         scale.height = gfxUtils::ClampToScaleFactor(scale.height);
       }
     } else {
       // XXX Do we need to move nearly-integer values to integers here?
     }
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -3917,25 +3917,29 @@ already_AddRefed<Layer> nsDisplayTransfo
   nsRefPtr<ContainerLayer> container = aManager->GetLayerBuilder()->
     BuildContainerLayerFor(aBuilder, aManager, mFrame, this, *mStoredList.GetChildren(),
                            aContainerParameters, &newTransformMatrix);
 
   // Add the preserve-3d flag for this layer, BuildContainerLayerFor clears all flags,
   // so we never need to explicitely unset this flag.
   if (mFrame->Preserves3D() || mFrame->Preserves3DChildren()) {
     container->SetContentFlags(container->GetContentFlags() | Layer::CONTENT_PRESERVE_3D);
+  } else {
+    container->SetContentFlags(container->GetContentFlags() & ~Layer::CONTENT_PRESERVE_3D);
   }
 
   AddAnimationsAndTransitionsToLayer(container, aBuilder,
                                      this, eCSSProperty_transform);
   if (ShouldPrerenderTransformedContent(aBuilder, mFrame, false)) {
     container->SetUserData(nsIFrame::LayerIsPrerenderedDataKey(),
                            /*the value is irrelevant*/nullptr);
+    container->SetContentFlags(container->GetContentFlags() | Layer::CONTENT_MAY_CHANGE_TRANSFORM);
   } else {
     container->RemoveUserData(nsIFrame::LayerIsPrerenderedDataKey());
+    container->SetContentFlags(container->GetContentFlags() & ~Layer::CONTENT_MAY_CHANGE_TRANSFORM);
   }
   return container.forget();
 }
 
 nsDisplayItem::LayerState
 nsDisplayTransform::GetLayerState(nsDisplayListBuilder* aBuilder,
                                   LayerManager* aManager,
                                   const ContainerParameters& aParameters) {
--- a/layout/forms/nsComboboxControlFrame.cpp
+++ b/layout/forms/nsComboboxControlFrame.cpp
@@ -307,17 +307,17 @@ NS_QUERYFRAME_HEAD(nsComboboxControlFram
   NS_QUERYFRAME_ENTRY(nsISelectControlFrame)
   NS_QUERYFRAME_ENTRY(nsIStatefulFrame)
 NS_QUERYFRAME_TAIL_INHERITING(nsBlockFrame)
 
 #ifdef ACCESSIBILITY
 a11y::AccType
 nsComboboxControlFrame::AccessibleType()
 {
-  return a11y::eHTMLComboboxAccessible;
+  return a11y::eHTMLCombobox;
 }
 #endif
 
 void
 nsComboboxControlFrame::SetFocus(bool aOn, bool aRepaint)
 {
   nsWeakFrame weakFrame(this);
   if (aOn) {
--- a/layout/forms/nsFieldSetFrame.cpp
+++ b/layout/forms/nsFieldSetFrame.cpp
@@ -620,17 +620,17 @@ nsFieldSetFrame::RemoveFrame(ChildListID
   NS_ASSERTION(aOldFrame != mLegendFrame, "Cannot remove mLegendFrame here");
   return mContentFrame->RemoveFrame(aListID, aOldFrame);
 }
 
 #ifdef ACCESSIBILITY
 a11y::AccType
 nsFieldSetFrame::AccessibleType()
 {
-  return a11y::eHTMLGroupboxAccessible;
+  return a11y::eHTMLGroupbox;
 }
 #endif
 
 void
 nsFieldSetFrame::ReparentFrameList(const nsFrameList& aFrameList)
 {
   nsFrameManager* frameManager = PresContext()->FrameManager();
   for (nsFrameList::Enumerator e(aFrameList); !e.AtEnd(); e.Next()) {
--- a/layout/forms/nsFileControlFrame.cpp
+++ b/layout/forms/nsFileControlFrame.cpp
@@ -626,17 +626,17 @@ nsFileControlFrame::BuildDisplayList(nsD
 
   return DisplaySelectionOverlay(aBuilder, aLists.Content());
 }
 
 #ifdef ACCESSIBILITY
 a11y::AccType
 nsFileControlFrame::AccessibleType()
 {
-  return a11y::eHTMLFileInputAccessible;
+  return a11y::eHTMLFileInput;
 }
 #endif
 
 uint32_t
 nsFileControlFrame::GetCaptureMode(const CaptureCallbackData& aData)
 {
   int32_t filters = nsHTMLInputElement::FromContent(mContent)->GetFilterFromAccept();
   nsresult rv;
--- a/layout/forms/nsGfxCheckboxControlFrame.cpp
+++ b/layout/forms/nsGfxCheckboxControlFrame.cpp
@@ -85,17 +85,17 @@ nsGfxCheckboxControlFrame::nsGfxCheckbox
 nsGfxCheckboxControlFrame::~nsGfxCheckboxControlFrame()
 {
 }
 
 #ifdef ACCESSIBILITY
 a11y::AccType
 nsGfxCheckboxControlFrame::AccessibleType()
 {
-  return a11y::eHTMLCheckboxAccessible;
+  return a11y::eHTMLCheckbox;
 }
 #endif
 
 //------------------------------------------------------------
 NS_IMETHODIMP
 nsGfxCheckboxControlFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                             const nsRect&           aDirtyRect,
                                             const nsDisplayListSet& aLists)
--- a/layout/forms/nsGfxRadioControlFrame.cpp
+++ b/layout/forms/nsGfxRadioControlFrame.cpp
@@ -31,17 +31,17 @@ nsGfxRadioControlFrame::nsGfxRadioContro
 nsGfxRadioControlFrame::~nsGfxRadioControlFrame()
 {
 }
 
 #ifdef ACCESSIBILITY
 a11y::AccType
 nsGfxRadioControlFrame::AccessibleType()
 {
-  return a11y::eHTMLRadioButtonAccessible;
+  return a11y::eHTMLRadioButton;
 }
 #endif
 
 //--------------------------------------------------------------
 // Draw the dot for a non-native radio button in the checked state.
 static void
 PaintCheckedRadioButton(nsIFrame* aFrame,
                         nsRenderingContext* aCtx,
--- a/layout/forms/nsHTMLButtonControlFrame.cpp
+++ b/layout/forms/nsHTMLButtonControlFrame.cpp
@@ -73,17 +73,17 @@ nsHTMLButtonControlFrame::Init(
 NS_QUERYFRAME_HEAD(nsHTMLButtonControlFrame)
   NS_QUERYFRAME_ENTRY(nsIFormControlFrame)
 NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
 
 #ifdef ACCESSIBILITY
 a11y::AccType
 nsHTMLButtonControlFrame::AccessibleType()
 {
-  return a11y::eHTMLButtonAccessible;
+  return a11y::eHTMLButton;
 }
 #endif
 
 nsIAtom*
 nsHTMLButtonControlFrame::GetType() const
 {
   return nsGkAtoms::HTMLButtonControlFrame;
 }
--- a/layout/forms/nsImageControlFrame.cpp
+++ b/layout/forms/nsImageControlFrame.cpp
@@ -128,20 +128,20 @@ NS_QUERYFRAME_HEAD(nsImageControlFrame)
 NS_QUERYFRAME_TAIL_INHERITING(nsImageControlFrameSuper)
 
 #ifdef ACCESSIBILITY
 a11y::AccType
 nsImageControlFrame::AccessibleType()
 {
   if (mContent->Tag() == nsGkAtoms::button ||
       mContent->Tag() == nsGkAtoms::input) {
-    return a11y::eHTMLButtonAccessible;
+    return a11y::eHTMLButton;
   }
 
-  return a11y::eNoAccessible;
+  return a11y::eNoType;
 }
 #endif
 
 nsIAtom*
 nsImageControlFrame::GetType() const
 {
   return nsGkAtoms::imageControlFrame; 
 }
--- a/layout/forms/nsListControlFrame.cpp
+++ b/layout/forms/nsListControlFrame.cpp
@@ -262,17 +262,17 @@ NS_QUERYFRAME_HEAD(nsListControlFrame)
   NS_QUERYFRAME_ENTRY(nsIListControlFrame)
   NS_QUERYFRAME_ENTRY(nsISelectControlFrame)
 NS_QUERYFRAME_TAIL_INHERITING(nsHTMLScrollFrame)
 
 #ifdef ACCESSIBILITY
 a11y::AccType
 nsListControlFrame::AccessibleType()
 {
-  return a11y::eHTMLSelectListAccessible;
+  return a11y::eHTMLSelectList;
 }
 #endif
 
 static nscoord
 GetMaxOptionHeight(nsIFrame* aContainer)
 {
   nscoord result = 0;
   for (nsIFrame* option = aContainer->GetFirstPrincipalChild();
--- a/layout/forms/nsTextControlFrame.cpp
+++ b/layout/forms/nsTextControlFrame.cpp
@@ -90,17 +90,17 @@ NS_QUERYFRAME_HEAD(nsTextControlFrame)
   NS_QUERYFRAME_ENTRY(nsITextControlFrame)
   NS_QUERYFRAME_ENTRY(nsIStatefulFrame)
 NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
 
 #ifdef ACCESSIBILITY
 a11y::AccType
 nsTextControlFrame::AccessibleType()
 {
-  return a11y::eHTMLTextFieldAccessible;
+  return a11y::eHTMLTextField;
 }
 #endif
 
 #ifdef DEBUG
 class EditorInitializerEntryTracker {
 public:
   explicit EditorInitializerEntryTracker(nsTextControlFrame &frame)
     : mFrame(frame)
--- a/layout/generic/nsBRFrame.cpp
+++ b/layout/generic/nsBRFrame.cpp
@@ -249,15 +249,15 @@ BRFrame::PeekOffsetWord(bool aForward, b
 a11y::AccType
 BRFrame::AccessibleType()
 {
   nsIContent *parent = mContent->GetParent();
   if (parent && parent->IsRootOfNativeAnonymousSubtree() &&
       parent->GetChildCount() == 1) {
     // This <br> is the only node in a text control, therefore it is the hacky
     // "bogus node" used when there is no text in the control
-    return a11y::eNoAccessible;
+    return a11y::eNoType;
   }
 
-  return a11y::eHTMLBRAccessible;
+  return a11y::eHTMLBR;
 }
 #endif
 
--- a/layout/generic/nsBlockFrame.cpp
+++ b/layout/generic/nsBlockFrame.cpp
@@ -6245,44 +6245,44 @@ nsBlockFrame::BuildDisplayList(nsDisplay
 }
 
 #ifdef ACCESSIBILITY
 a11y::AccType
 nsBlockFrame::AccessibleType()
 {
   // block frame may be for <hr>
   if (mContent->Tag() == nsGkAtoms::hr) {
-    return a11y::eHTMLHRAccessible;
+    return a11y::eHTMLHR;
   }
 
   if (!HasBullet() || !PresContext()) {
     if (!mContent->GetParent()) {
       // Don't create accessible objects for the root content node, they are redundant with
       // the nsDocAccessible object created with the document node
-      return a11y::eNoAccessible;
+      return a11y::eNoType;
     }
     
     nsCOMPtr<nsIDOMHTMLDocument> htmlDoc =
       do_QueryInterface(mContent->GetDocument());
     if (htmlDoc) {
       nsCOMPtr<nsIDOMHTMLElement> body;
       htmlDoc->GetBody(getter_AddRefs(body));
       if (SameCOMIdentity(body, mContent)) {
         // Don't create accessible objects for the body, they are redundant with
         // the nsDocAccessible object created with the document node
-        return a11y::eNoAccessible;
+        return a11y::eNoType;
       }
     }
 
     // Not a bullet, treat as normal HTML container
-    return a11y::eHyperTextAccessible;
+    return a11y::eHyperText;
   }
 
   // Create special list bullet accessible
-  return a11y::eHTMLLiAccessible;
+  return a11y::eHTMLLi;
 }
 #endif
 
 void nsBlockFrame::ClearLineCursor()
 {
   if (!(GetStateBits() & NS_BLOCK_HAS_LINE_CURSOR)) {
     return;
   }
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -3027,16 +3027,24 @@ NS_IMETHODIMP nsFrame::HandleDrag(nsPres
 
   nsRefPtr<nsFrameSelection> frameselection = GetFrameSelection();
   bool mouseDown = frameselection->GetMouseDownState();
   if (!mouseDown)
     return NS_OK;
 
   frameselection->StopAutoScrollTimer();
 
+#ifdef MOZ_B2G
+  // We only check touch move event since mouse move event is not cancelable.
+  if (aEvent->message == NS_TOUCH_MOVE &&
+      nsEventStatus_eConsumeNoDefault == *aEventStatus) {
+    return NS_OK;
+  }
+#endif // MOZ_B2G
+
   // Check if we are dragging in a table cell
   nsCOMPtr<nsIContent> parentContent;
   int32_t contentOffset;
   int32_t target;
   nsMouseEvent *me = (nsMouseEvent *)aEvent;
   nsresult result;
   result = GetDataForTableSelection(frameselection, presShell, me,
                                     getter_AddRefs(parentContent),
@@ -6770,17 +6778,17 @@ nsFrame::ChildIsDirty(nsIFrame* aChild)
                 "nsContainerFrame");
 }
 
 
 #ifdef ACCESSIBILITY
 a11y::AccType
 nsFrame::AccessibleType()
 {
-  return a11y::eNoAccessible;
+  return a11y::eNoType;
 }
 #endif
 
 NS_DECLARE_FRAME_PROPERTY(OverflowAreasProperty,
                           nsIFrame::DestroyOverflowAreas)
 
 bool
 nsIFrame::ClearOverflowRects()
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -856,20 +856,20 @@ nsHTMLScrollFrame::GetFrameName(nsAStrin
 a11y::AccType
 nsHTMLScrollFrame::AccessibleType()
 {
   // Create an accessible regardless of focusable state because the state can be
   // changed during frame life cycle without any notifications to accessibility.
   if (mContent->IsRootOfNativeAnonymousSubtree() ||
       GetScrollbarStyles() == nsIScrollableFrame::
         ScrollbarStyles(NS_STYLE_OVERFLOW_HIDDEN, NS_STYLE_OVERFLOW_HIDDEN) ) {
-    return a11y::eNoAccessible;
+    return a11y::eNoType;
   }
 
-  return a11y::eHyperTextAccessible;
+  return a11y::eHyperText;
 }
 #endif
 
 NS_QUERYFRAME_HEAD(nsHTMLScrollFrame)
   NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
   NS_QUERYFRAME_ENTRY(nsIScrollableFrame)
   NS_QUERYFRAME_ENTRY(nsIStatefulFrame)
 NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
--- a/layout/generic/nsHTMLCanvasFrame.cpp
+++ b/layout/generic/nsHTMLCanvasFrame.cpp
@@ -331,17 +331,17 @@ nsHTMLCanvasFrame::GetContinuationOffset
   }
   return offset;
 }
 
 #ifdef ACCESSIBILITY
 a11y::AccType
 nsHTMLCanvasFrame::AccessibleType()
 {
-  return a11y::eHTMLCanvasAccessible;
+  return a11y::eHTMLCanvas;
 }
 #endif
 
 #ifdef DEBUG
 NS_IMETHODIMP
 nsHTMLCanvasFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("HTMLCanvas"), aResult);
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -158,20 +158,20 @@ NS_QUERYFRAME_HEAD(nsImageFrame)
 NS_QUERYFRAME_TAIL_INHERITING(ImageFrameSuper)
 
 #ifdef ACCESSIBILITY
 a11y::AccType
 nsImageFrame::AccessibleType()
 {
   // Don't use GetImageMap() to avoid reentrancy into accessibility.
   if (HasImageMap()) {
-    return a11y::eHTMLImageMapAccessible;
+    return a11y::eHTMLImageMap;
   }
 
-  return a11y::eImageAccessible;
+  return a11y::eImage;
 }
 #endif
 
 void
 nsImageFrame::DisconnectMap()
 {
   if (mImageMap) {
     mImageMap->Destroy();
--- a/layout/generic/nsInlineFrame.cpp
+++ b/layout/generic/nsInlineFrame.cpp
@@ -890,23 +890,23 @@ nsInlineFrame::GetBaseline() const
 #ifdef ACCESSIBILITY
 a11y::AccType
 nsInlineFrame::AccessibleType()
 {
   // Broken image accessibles are created here, because layout
   // replaces the image or image control frame with an inline frame
   nsIAtom *tagAtom = mContent->Tag();
   if (tagAtom == nsGkAtoms::input)  // Broken <input type=image ... />
-    return a11y::eHTMLButtonAccessible;
+    return a11y::eHTMLButton;
   if (tagAtom == nsGkAtoms::img)  // Create accessible for broken <img>
-    return a11y::eImageAccessible;
+    return a11y::eImage;
   if (tagAtom == nsGkAtoms::label)  // Creat accessible for <label>
-    return a11y::eHTMLLabelAccessible;
+    return a11y::eHTMLLabel;
 
-  return a11y::eNoAccessible;
+  return a11y::eNoType;
 }
 #endif
 
 //////////////////////////////////////////////////////////////////////
 
 // nsLineFrame implementation
 
 nsIFrame*
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -270,17 +270,17 @@ NS_QUERYFRAME_HEAD(nsObjectFrame)
   NS_QUERYFRAME_ENTRY(nsObjectFrame)
   NS_QUERYFRAME_ENTRY(nsIObjectFrame)
 NS_QUERYFRAME_TAIL_INHERITING(nsObjectFrameSuper)
 
 #ifdef ACCESSIBILITY
 a11y::AccType
 nsObjectFrame::AccessibleType()
 {
-  return a11y::eHTMLObjectFrameAccessible;
+  return a11y::ePlugin;
 }
 
 #ifdef XP_WIN
 NS_IMETHODIMP nsObjectFrame::GetPluginPort(HWND *aPort)
 {
   *aPort = (HWND) mInstanceOwner->GetPluginPortFromWidget();
   return NS_OK;
 }
--- a/layout/generic/nsSubDocumentFrame.cpp
+++ b/layout/generic/nsSubDocumentFrame.cpp
@@ -80,17 +80,17 @@ nsSubDocumentFrame::nsSubDocumentFrame(n
   , mCallingShow(false)
 {
 }
 
 #ifdef ACCESSIBILITY
 a11y::AccType
 nsSubDocumentFrame::AccessibleType()
 {
-  return a11y::eOuterDocAccessible;
+  return a11y::eOuterDoc;
 }
 #endif
 
 NS_QUERYFRAME_HEAD(nsSubDocumentFrame)
   NS_QUERYFRAME_ENTRY(nsSubDocumentFrame)
 NS_QUERYFRAME_TAIL_INHERITING(nsLeafFrame)
 
 class AsyncFrameInit : public nsRunnable
--- a/layout/generic/nsTextFrameThebes.cpp
+++ b/layout/generic/nsTextFrameThebes.cpp
@@ -3893,21 +3893,21 @@ nsTextPaintStyle::GetResolvedForeColor(n
 #ifdef ACCESSIBILITY
 a11y::AccType
 nsTextFrame::AccessibleType()
 {
   if (IsEmpty()) {
     nsAutoString renderedWhitespace;
     GetRenderedText(&renderedWhitespace, nullptr, nullptr, 0, 1);
     if (renderedWhitespace.IsEmpty()) {
-      return a11y::eNoAccessible;
-    }
-  }
-
-  return a11y::eTextLeafAccessible;
+      return a11y::eNoType;
+    }
+  }
+
+  return a11y::eTextLeaf;
 }
 #endif
 
 
 //-----------------------------------------------------------------------------
 NS_IMETHODIMP
 nsTextFrame::Init(nsIContent*      aContent,
                   nsIFrame*        aParent,
--- a/layout/generic/nsVideoFrame.cpp
+++ b/layout/generic/nsVideoFrame.cpp
@@ -413,17 +413,17 @@ nsVideoFrame::GetType() const
 {
   return nsGkAtoms::HTMLVideoFrame;
 }
 
 #ifdef ACCESSIBILITY
 a11y::AccType
 nsVideoFrame::AccessibleType()
 {
-  return a11y::eHTMLMediaAccessible;
+  return a11y::eHTMLMedia;
 }
 #endif
 
 #ifdef DEBUG
 NS_IMETHODIMP
 nsVideoFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("HTMLVideo"), aResult);
--- a/layout/ipc/PRenderFrame.ipdl
+++ b/layout/ipc/PRenderFrame.ipdl
@@ -37,16 +37,17 @@ parent:
      * |id| is set to 0 in the "direct" case, and to a whole number
      * in the "indirect" case.
      */
     async PLayers();
 
     async NotifyCompositorTransaction();
 
     async CancelDefaultPanZoom();
+    async DetectScrollableSubframe();
 
     async __delete__();
 
 state EMPTY_OR_DIRECT_COMPOSITOR:
     recv PLayers goto HAVE_CONTENT;
     recv NotifyCompositorTransaction goto EMPTY_OR_DIRECT_COMPOSITOR;
     recv __delete__;
 
--- a/layout/ipc/RenderFrameChild.cpp
+++ b/layout/ipc/RenderFrameChild.cpp
@@ -33,16 +33,22 @@ RenderFrameChild::Destroy()
 }
 
 void
 RenderFrameChild::CancelDefaultPanZoom()
 {
   SendCancelDefaultPanZoom();
 }
 
+void
+RenderFrameChild::DetectScrollableSubframe()
+{
+  SendDetectScrollableSubframe();
+}
+
 PLayersChild*
 RenderFrameChild::AllocPLayers()
 {
   return new ShadowLayersChild();
 }
 
 bool
 RenderFrameChild::DeallocPLayers(PLayersChild* aLayers)
--- a/layout/ipc/RenderFrameChild.h
+++ b/layout/ipc/RenderFrameChild.h
@@ -15,16 +15,17 @@ namespace layout {
 
 class RenderFrameChild : public PRenderFrameChild
 {
 public:
   RenderFrameChild() {}
   virtual ~RenderFrameChild() {}
 
   void CancelDefaultPanZoom();
+  void DetectScrollableSubframe();
 
   void Destroy();
 
 protected:
   virtual PLayersChild* AllocPLayers() MOZ_OVERRIDE;
   virtual bool DeallocPLayers(PLayersChild* aLayers) MOZ_OVERRIDE;
 };
 
--- a/layout/ipc/RenderFrameParent.cpp
+++ b/layout/ipc/RenderFrameParent.cpp
@@ -805,16 +805,25 @@ bool
 RenderFrameParent::RecvCancelDefaultPanZoom()
 {
   if (mPanZoomController) {
     mPanZoomController->CancelDefaultPanZoom();
   }
   return true;
 }
 
+bool
+RenderFrameParent::RecvDetectScrollableSubframe()
+{
+  if (mPanZoomController) {
+    mPanZoomController->DetectScrollableSubframe();
+  }
+  return true;
+}
+
 PLayersParent*
 RenderFrameParent::AllocPLayers()
 {
   if (!mFrameLoader || mFrameLoaderDestroyed) {
     return nullptr;
   }
   nsRefPtr<LayerManager> lm = GetFrom(mFrameLoader);
   return new ShadowLayersParent(lm->AsShadowManager(), this, 0);
--- a/layout/ipc/RenderFrameParent.h
+++ b/layout/ipc/RenderFrameParent.h
@@ -104,16 +104,17 @@ public:
   void UpdateZoomConstraints(bool aAllowZoom, float aMinZoom, float aMaxZoom);
 
 protected:
   void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
 
   virtual bool RecvNotifyCompositorTransaction() MOZ_OVERRIDE;
 
   virtual bool RecvCancelDefaultPanZoom() MOZ_OVERRIDE;
+  virtual bool RecvDetectScrollableSubframe() MOZ_OVERRIDE;
 
   virtual PLayersParent* AllocPLayers() MOZ_OVERRIDE;
   virtual bool DeallocPLayers(PLayersParent* aLayers) MOZ_OVERRIDE;
 
 private:
   void BuildViewMap();
   void TriggerRepaint();
   void DispatchEventForPanZoomController(const InputEvent& aEvent);
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text/820255-ref.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html>
+<html>
+  <head>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <title>Test - Bug 820255</title>
+  </head>
+  <body>
+    <div>A&#x1680;<br>B</div>
+    <div>A&#x205F;<br>B</div>
+  </body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/text/820255.html
@@ -0,0 +1,14 @@
+<!DOCTYPE html>
+<html>
+  <head>
+  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
+  <style type="text/css">
+    div { width: 0px; }
+  </style>
+  <title>Test - Bug 820255</title>
+  </head>
+  <body>
+    <div>A&#x1680;B</div>
+    <div>A&#x205F;B</div>
+  </body>
+</html>
--- a/layout/reftests/text/reftest.list
+++ b/layout/reftests/text/reftest.list
@@ -157,16 +157,17 @@ fails-if(cocoaWidget) HTTP(..) == arabic
 fails-if(cocoaWidget) HTTP(..) == arabic-fallback-3.html arabic-fallback-3-ref.html
 fails-if(!cocoaWidget) HTTP(..) != arabic-fallback-4.html arabic-fallback-4-notref.html
 
 == 726392-1.html 726392-1-ref.html
 == 726392-2.html 726392-2-ref.html
 == 726392-3.html 726392-3-ref.html
 == 745555-1.html 745555-1-ref.html
 == 745555-2.html 745555-2-ref.html
+== 820255.html 820255-ref.html
 
 # ensure emoji chars don't render blank (bug 715798, bug 779042);
 # should at least render hexboxes if there's no font support
 != emoji-01.html emoji-01-notref.html
 != emoji-02.html emoji-02-notref.html
 
 # tests to compare graphite to opentype (will trivially pass when graphite not enabled)
 HTTP(..) == graphite-05-ot-only.html graphite-05-ref.html
--- a/layout/tables/nsTableCellFrame.cpp
+++ b/layout/tables/nsTableCellFrame.cpp
@@ -980,17 +980,17 @@ NS_QUERYFRAME_HEAD(nsTableCellFrame)
   NS_QUERYFRAME_ENTRY(nsITableCellLayout)
   NS_QUERYFRAME_ENTRY(nsIPercentHeightObserver)
 NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
 
 #ifdef ACCESSIBILITY
 a11y::AccType
 nsTableCellFrame::AccessibleType()
 {
-  return a11y::eHTMLTableCellAccessible;
+  return a11y::eHTMLTableCell;
 }
 #endif
 
 /* This is primarily for editor access via nsITableLayout */
 NS_IMETHODIMP
 nsTableCellFrame::GetCellIndexes(int32_t &aRowIndex, int32_t &aColIndex)
 {
   nsresult res = GetRowIndex(aRowIndex);
--- a/layout/tables/nsTableOuterFrame.cpp
+++ b/layout/tables/nsTableOuterFrame.cpp
@@ -110,20 +110,20 @@ nsTableCaptionFrame::GetParentStyleConte
   return nsBlockFrame::GetParentStyleContextFrame();
 }
 
 #ifdef ACCESSIBILITY
 a11y::AccType
 nsTableCaptionFrame::AccessibleType()
 {
   if (!GetRect().IsEmpty()) {
-    return a11y::eHTMLCaptionAccessible;
+    return a11y::eHTMLCaption;
   }
 
-  return a11y::eNoAccessible;
+  return a11y::eNoType;
 }
 #endif
 
 #ifdef DEBUG
 NS_IMETHODIMP
 nsTableCaptionFrame::GetFrameName(nsAString& aResult) const
 {
   return MakeFrameName(NS_LITERAL_STRING("Caption"), aResult);
@@ -152,17 +152,17 @@ nsTableOuterFrame::~nsTableOuterFrame()
 NS_QUERYFRAME_HEAD(nsTableOuterFrame)
   NS_QUERYFRAME_ENTRY(nsITableLayout)
 NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
 
 #ifdef ACCESSIBILITY
 a11y::AccType
 nsTableOuterFrame::AccessibleType()
 {
-  return a11y::eHTMLTableAccessible;
+  return a11y::eHTMLTable;
 }
 #endif
 
 void
 nsTableOuterFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   DestroyAbsoluteFrames(aDestructRoot);
   mCaptionFrames.DestroyFramesFrom(aDestructRoot);
--- a/layout/tables/nsTableRowFrame.cpp
+++ b/layout/tables/nsTableRowFrame.cpp
@@ -1352,17 +1352,17 @@ void nsTableRowFrame::SetContinuousBCBor
     default:
       NS_ERROR("invalid NS_SIDE arg");
   }
 }
 #ifdef ACCESSIBILITY
 a11y::AccType
 nsTableRowFrame::AccessibleType()
 {
-  return a11y::eHTMLTableRowAccessible;
+  return a11y::eHTMLTableRow;
 }
 #endif
 /**
  * Sets the NS_ROW_HAS_CELL_WITH_STYLE_HEIGHT bit to indicate whether
  * this row has any cells that have non-auto-height.  (Row-spanning
  * cells are ignored.)
  */
 void nsTableRowFrame::InitHasCellWithStyleHeight(nsTableFrame* aTableFrame)
--- a/memory/replace/dmd/DMD.cpp
+++ b/memory/replace/dmd/DMD.cpp
@@ -556,18 +556,18 @@ StackTrace::Print(const Writer& aWriter)
     return;
   }
 
   for (uint32_t i = 0; i < mLength; i++) {
     nsCodeAddressDetails details;
     void* pc = mPcs[i];
     PcInfo(pc, &details);
     if (details.function[0]) {
-      W("   %14p %s[%s +0x%X]\n", pc, details.function, details.library,
-        details.loffset);
+      W("   %s[%s +0x%X] %p\n", details.function, details.library,
+        details.loffset, pc);
     }
   }
 }
 
 /* static */ const StackTrace*
 StackTrace::Get(Thread* aT)
 {
   MOZ_ASSERT(gStateLock->IsLocked());
@@ -1259,18 +1259,18 @@ FrameGroup::Print(const Writer& aWriter,
     Show(mCombinedSize.mSlop,    gBuf3, kBufLen, showTilde));
 
   W(" %4.2f%% of the heap;  %4.2f%% of %s\n",
     Percent(mCombinedSize.Usable(), aTotalUsableSize),
     Percent(mCombinedSize.Usable(), aCategoryUsableSize),
     astr);
 
   W(" PC is\n");
-  W("   %14p %s[%s +0x%X]\n\n", mPc, details.function, details.library,
-    details.loffset);
+  W("   %s[%s +0x%X] %p\n\n", details.function, details.library,
+    details.loffset, mPc);
 }
 
 //---------------------------------------------------------------------------
 // DMD start-up
 //---------------------------------------------------------------------------
 
 static void RunTestMode(FILE* fp);
 static void RunStressMode();
@@ -1443,20 +1443,20 @@ Init(const malloc_table_t* aMallocTable)
       StatusMsg("can't create test file %s: %s\n", filename, strerror(errno));
       exit(1);
     }
   }
 
   DMD_CREATE_TLS_INDEX(gTlsIndex);
 
   gStackTraceTable = InfallibleAllocPolicy::new_<StackTraceTable>();
-  gStackTraceTable->init(65536);
+  gStackTraceTable->init(8192);
 
   gLiveBlockTable = InfallibleAllocPolicy::new_<BlockTable>();
-  gLiveBlockTable->init(65536);
+  gLiveBlockTable->init(8192);
 
   gDoubleReportBlockGroupTable = InfallibleAllocPolicy::new_<BlockGroupTable>();
   gDoubleReportBlockGroupTable->init(0);
 
   // Set this as late as possible, so that allocations during initialization
   // aren't intercepted.  Once this is set, we are intercepting malloc et al.
   // in earnest.
   gIsDMDRunning = true;
@@ -1662,45 +1662,38 @@ PrintSortedBlockAndFrameGroups(const Wri
 
 // This is only needed because of the |const void*| vs |void*| arg mismatch.
 static size_t
 MallocSizeOf(const void* aPtr)
 {
   return gMallocTable->malloc_usable_size(const_cast<void*>(aPtr));
 }
 
-static void
-ShowExecutionMeasurements(const Writer& aWriter)
+// Note that, unlike most SizeOf* functions, this function does not take a
+// |nsMallocSizeOfFun| argument.  That's because those arguments are primarily
+// to aid DMD track heap blocks... but DMD deliberately doesn't track heap
+// blocks it allocated for itself!
+MOZ_EXPORT void
+SizeOf(Sizes* aSizes)
 {
-  // Stats are non-deterministic, so don't show it in test mode.
-  if (gMode == Test) {
-    return;
-  }
-
-  WriteTitle("Execution measurements\n");
-
-  size_t sizeOfStackTraceTable =
-    gStackTraceTable->sizeOfIncludingThis(MallocSizeOf);
+  aSizes->mStackTraces = 0;
   for (StackTraceTable::Range r = gStackTraceTable->all();
        !r.empty();
        r.popFront()) {
     StackTrace* const& st = r.front();
-    sizeOfStackTraceTable += MallocSizeOf(st);
+    aSizes->mStackTraces += MallocSizeOf(st);
   }
-  W("Stack trace table: %s of %s entries used, taking up %s bytes\n",
-    Show(gStackTraceTable->count(),    gBuf1, kBufLen),
-    Show(gStackTraceTable->capacity(), gBuf2, kBufLen),
-    Show(sizeOfStackTraceTable, gBuf3, kBufLen));
 
-  W("Live block table:  %s of %s entries used, taking up %s bytes\n",
-    Show(gLiveBlockTable->count(),    gBuf1, kBufLen),
-    Show(gLiveBlockTable->capacity(), gBuf2, kBufLen),
-    Show(gLiveBlockTable->sizeOfIncludingThis(MallocSizeOf), gBuf3, kBufLen));
+  aSizes->mStackTraceTable =
+    gStackTraceTable->sizeOfIncludingThis(MallocSizeOf);
 
-  W("\n");
+  aSizes->mLiveBlockTable = gLiveBlockTable->sizeOfIncludingThis(MallocSizeOf);
+
+  aSizes->mDoubleReportTable =
+    gDoubleReportBlockGroupTable->sizeOfIncludingThis(MallocSizeOf);
 }
 
 static void
 ClearState()
 {
   // Unreport all blocks, except those that were reported on allocation,
   // because they need to keep their reported marking.
   for (BlockTable::Range r = gLiveBlockTable->all(); !r.empty(); r.popFront()) {
@@ -1726,21 +1719,21 @@ Dump(Writer aWriter)
   AutoLockState lock;
 
   static int dumpCount = 1;
   StatusMsg("Dump %d {\n", dumpCount++);
 
   StatusMsg("  gathering live block groups...\n");
 
   BlockGroupTable unreportedBlockGroupTable;
-  (void)unreportedBlockGroupTable.init(2048);
+  (void)unreportedBlockGroupTable.init(1024);
   size_t unreportedUsableSize = 0;
 
   BlockGroupTable reportedBlockGroupTable;
-  (void)reportedBlockGroupTable.init(2048);
+  (void)reportedBlockGroupTable.init(1024);
   size_t reportedUsableSize = 0;
 
   bool anyBlocksSampled = false;
 
   for (BlockTable::Range r = gLiveBlockTable->all(); !r.empty(); r.popFront()) {
     const Block& b = r.front().value;
     if (!b.IsReported()) {
       unreportedUsableSize += b.mBlockSize.Usable();
@@ -1776,17 +1769,61 @@ Dump(Writer aWriter)
     Show(reportedUsableSize, gBuf1, kBufLen, showTilde),
     Percent(reportedUsableSize, totalUsableSize));
   W("Unreported: %s bytes (%5.2f%%)\n",
     Show(unreportedUsableSize, gBuf1, kBufLen, showTilde),
     Percent(unreportedUsableSize, totalUsableSize));
 
   W("\n");
 
-  ShowExecutionMeasurements(aWriter);
+  // Stats are non-deterministic, so don't show them in test mode.
+  if (gMode != Test) {
+    Sizes sizes;
+    SizeOf(&sizes);
+
+    WriteTitle("Execution measurements\n");
+
+    W("Data structures that persist after Dump() ends:\n");
+
+    W("  Stack traces:        %10s bytes\n",
+      Show(sizes.mStackTraces, gBuf1, kBufLen));
+
+    W("  Stack trace table:   %10s bytes (%s entries, %s used)\n",
+      Show(sizes.mStackTraceTable,       gBuf1, kBufLen),
+      Show(gStackTraceTable->capacity(), gBuf2, kBufLen),
+      Show(gStackTraceTable->count(),    gBuf3, kBufLen));
+
+    W("  Live block table:    %10s bytes (%s entries, %s used)\n",
+      Show(sizes.mLiveBlockTable,       gBuf1, kBufLen),
+      Show(gLiveBlockTable->capacity(), gBuf2, kBufLen),
+      Show(gLiveBlockTable->count(),    gBuf3, kBufLen));
+
+    W("\nData structures that are cleared after Dump() ends:\n");
+
+    W("  Double-report table: %10s bytes (%s entries, %s used)\n",
+      Show(sizes.mDoubleReportTable,                 gBuf1, kBufLen),
+      Show(gDoubleReportBlockGroupTable->capacity(), gBuf2, kBufLen),
+      Show(gDoubleReportBlockGroupTable->count(),    gBuf3, kBufLen));
+
+    size_t unreportedSize =
+      unreportedBlockGroupTable.sizeOfIncludingThis(MallocSizeOf);
+    W("  Unreported table:    %10s bytes (%s entries, %s used)\n",
+      Show(unreportedSize,                       gBuf1, kBufLen),
+      Show(unreportedBlockGroupTable.capacity(), gBuf2, kBufLen),
+      Show(unreportedBlockGroupTable.count(),    gBuf3, kBufLen));
+
+    size_t reportedSize =
+      reportedBlockGroupTable.sizeOfIncludingThis(MallocSizeOf);
+    W("  Reported table:      %10s bytes (%s entries, %s used)\n",
+      Show(reportedSize,                       gBuf1, kBufLen),
+      Show(reportedBlockGroupTable.capacity(), gBuf2, kBufLen),
+      Show(reportedBlockGroupTable.count(),    gBuf3, kBufLen));
+
+    W("\n");
+  }
 
   ClearState();
 
   StatusMsg("}\n");
 }
 
 //---------------------------------------------------------------------------
 // Testing
--- a/memory/replace/dmd/DMD.h
+++ b/memory/replace/dmd/DMD.h
@@ -3,16 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef DMD_h___
 #define DMD_h___
 
 #include <stdarg.h>
+#include <string.h>
 
 #include "mozilla/Types.h"
 
 namespace mozilla {
 namespace dmd {
 
 // Mark a heap block as reported by a memory reporter.
 MOZ_EXPORT void
@@ -44,12 +45,27 @@ private:
 MOZ_EXPORT void
 Dump(Writer aWriter);
 
 // A useful |WriterFun|.  If |fp| is a FILE* you want |Dump|'s output to be
 // written to, call |Dump(FpWrite, fp)|.
 MOZ_EXPORT void
 FpWrite(void* aFp, const char* aFmt, va_list aAp);
 
+struct Sizes
+{
+  size_t mStackTraces;
+  size_t mStackTraceTable;
+  size_t mLiveBlockTable;
+  size_t mDoubleReportTable;
+
+  Sizes() { memset(this, 0, sizeof(Sizes)); }
+};
+
+// Gets the size of various data structures.  Used to implement a memory
+// reporter for DMD.
+MOZ_EXPORT void
+SizeOf(Sizes* aSizes);
+
 } // namespace mozilla
 } // namespace dmd
 
 #endif /* DMD_h___ */
--- a/parser/html/jArray.h
+++ b/parser/html/jArray.h
@@ -96,18 +96,18 @@ class autoJArray {
       return newArray;
     }
     void operator=(const jArray<T,L>& other) {
       delete[] arr;
       arr = other.arr;
       length = other.length;
     }
 #if defined(MOZ_HAVE_CXX11_NULLPTR)
-#  if defined(__clang__) || defined(__ANDROID__)
-    // clang on OS X 10.7 and gcc-4.6 on android does not have std::nullptr_t
+#  if defined(__clang__) || defined(_STLPORT_VERSION)
+    // clang on OS X 10.7 and Android's STLPort do not have std::nullptr_t
     typedef decltype(nullptr) jArray_nullptr_t;
 #  else
     // decltype(nullptr) does not evaluate to std::nullptr_t on GCC 4.6.3
     typedef std::nullptr_t jArray_nullptr_t;
 #  endif
 #elif defined(__GNUC__)
     typedef void* jArray_nullptr_t;
 #elif defined(_WIN64)
--- a/security/build/Makefile.in
+++ b/security/build/Makefile.in
@@ -137,17 +137,22 @@ DEFAULT_GMAKE_FLAGS += NSS_ENABLE_ECC=1
 DEFAULT_GMAKE_FLAGS += NSINSTALL="$(NSINSTALL)"
 ifndef MOZ_NATIVE_SQLITE
 DEFAULT_GMAKE_FLAGS += SQLITE_LIB_NAME=mozsqlite3
 DEFAULT_GMAKE_FLAGS += SQLITE_INCLUDE_DIR=$(ABS_DIST)/include
 endif
 ifdef NSS_DISABLE_DBM 
 DEFAULT_GMAKE_FLAGS += NSS_DISABLE_DBM=1
 endif
-ABS_topsrcdir   := $(call core_abspath,$(topsrcdir))
+ABS_topsrcdir   := $(shell cd $(topsrcdir); pwd)
+ifeq ($(HOST_OS_ARCH),WINNT)
+ifdef .PYMAKE
+ABS_topsrcdir   := $(shell cd $(topsrcdir); pwd -W)
+endif
+endif
 # Hack to force NSS build system to use "normal" object directories
 DEFAULT_GMAKE_FLAGS += BUILD='$(MOZ_BUILD_ROOT)/security/$$(subst $(ABS_topsrcdir)/security/,,$$(CURDIR))'
 DEFAULT_GMAKE_FLAGS += BUILD_TREE='$$(BUILD)' OBJDIR='$$(BUILD)' DEPENDENCIES='$$(BUILD)/.deps' SINGLE_SHLIB_DIR='$$(BUILD)'
 DEFAULT_GMAKE_FLAGS += SOURCE_XP_DIR=$(ABS_DIST)
 ifndef MOZ_DEBUG
 DEFAULT_GMAKE_FLAGS += BUILD_OPT=1 OPT_CODE_SIZE=1
 endif
 ifdef GNU_CC
--- a/testing/xpcshell/head.js
+++ b/testing/xpcshell/head.js
@@ -870,49 +870,103 @@ function run_test_in_child(testFile, opt
  * Add a test function to the list of tests that are to be run asynchronously.
  *
  * Each test function must call run_next_test() when it's done. Test files
  * should call run_next_test() in their run_test function to execute all
  * async tests.
  *
  * @return the test function that was passed in.
  */
-let gTests = [];
+let _gTests = [];
 function add_test(func) {
-  gTests.push(func);
+  _gTests.push([false, func]);
   return func;
 }
 
+// We lazy import Task.jsm so we don't incur a run-time penalty for all tests.
+let _Task;
+
+/**
+ * Add a test function which is a Task function.
+ *
+ * Task functions are functions fed into Task.jsm's Task.spawn(). They are
+ * generators that emit promises.
+ *
+ * If an exception is thrown, a do_check_* comparison fails, or if a rejected
+ * promise is yielded, the test function aborts immediately and the test is
+ * reported as a failure.
+ *
+ * Unlike add_test(), there is no need to call run_next_test(). The next test
+ * will run automatically as soon the task function is exhausted. To trigger
+ * premature (but successful) termination of the function, simply return or
+ * throw a Task.Result instance.
+ *
+ * Example usage:
+ *
+ * add_task(function test() {
+ *   let result = yield Promise.resolve(true);
+ *
+ *   do_check_true(result);
+ *
+ *   let secondary = yield someFunctionThatReturnsAPromise(result);
+ *   do_check_eq(secondary, "expected value");
+ * });
+ *
+ * add_task(function test_early_return() {
+ *   let result = yield somethingThatReturnsAPromise();
+ *
+ *   if (!result) {
+ *     // Test is ended immediately, with success.
+ *     return;
+ *   }
+ *
+ *   do_check_eq(result, "foo");
+ * });
+ */
+function add_task(func) {
+  if (!_Task) {
+    let ns = {};
+    _Task = Components.utils.import("resource://gre/modules/Task.jsm", ns).Task;
+  }
+
+  _gTests.push([true, func]);
+}
+
 /**
  * Runs the next test function from the list of async tests.
  */
-let gRunningTest = null;
-let gTestIndex = 0; // The index of the currently running test.
+let _gRunningTest = null;
+let _gTestIndex = 0; // The index of the currently running test.
 function run_next_test()
 {
   function _run_next_test()
   {
-    if (gTestIndex < gTests.length) {
+    if (_gTestIndex < _gTests.length) {
       do_test_pending();
-      gRunningTest = gTests[gTestIndex++];
-      print("TEST-INFO | " + _TEST_FILE + " | Starting " +
-            gRunningTest.name);
-      // Exceptions do not kill asynchronous tests, so they'll time out.
-      try {
-        gRunningTest();
-      }
-      catch (e) {
-        do_throw(e);
+      let _isTask;
+      [_isTask, _gRunningTest] = _gTests[_gTestIndex++];
+      print("TEST-INFO | " + _TEST_FILE + " | Starting " + _gRunningTest.name);
+
+      if (_isTask) {
+        _Task.spawn(_gRunningTest)
+             .then(run_next_test, do_report_unexpected_exception);
+      } else {
+        // Exceptions do not kill asynchronous tests, so they'll time out.
+        try {
+          _gRunningTest();
+        } catch (e) {
+          do_throw(e);
+        }
       }
     }
   }
 
   // For sane stacks during failures, we execute this code soon, but not now.
   // We do this now, before we call do_test_finished(), to ensure the pending
   // counter (_tests_pending) never reaches 0 while we still have tests to run
   // (do_execute_soon bumps that counter).
   do_execute_soon(_run_next_test);
 
-  if (gRunningTest !== null) {
+  if (_gRunningTest !== null) {
     // Close the previous test do_test_pending call.
     do_test_finished();
   }
 }
--- a/testing/xpcshell/selftest.py
+++ b/testing/xpcshell/selftest.py
@@ -14,16 +14,81 @@ from runxpcshelltests import XPCShellTes
 objdir = os.path.abspath(os.environ["OBJDIR"])
 xpcshellBin = os.path.join(objdir, "dist", "bin", "xpcshell")
 if sys.platform == "win32":
     xpcshellBin += ".exe"
 
 SIMPLE_PASSING_TEST = "function run_test() { do_check_true(true); }"
 SIMPLE_FAILING_TEST = "function run_test() { do_check_true(false); }"
 
+ADD_TEST_SIMPLE = '''
+function run_test() { run_next_test(); }
+
+add_test(function test_simple() {
+  do_check_true(true);
+  run_next_test();
+});
+'''
+
+ADD_TEST_FAILING = '''
+function run_test() { run_next_test(); }
+
+add_test(function test_failing() {
+  do_check_true(false);
+  run_next_test();
+});
+'''
+
+ADD_TASK_SINGLE = '''
+Components.utils.import("resource://gre/modules/commonjs/promise/core.js");
+
+function run_test() { run_next_test(); }
+
+add_task(function test_task() {
+  yield Promise.resolve(true);
+  yield Promise.resolve(false);
+});
+'''
+
+ADD_TASK_MULTIPLE = '''
+Components.utils.import("resource://gre/modules/commonjs/promise/core.js");
+
+function run_test() { run_next_test(); }
+
+add_task(function test_task() {
+  yield Promise.resolve(true);
+});
+
+add_task(function test_2() {
+  yield Promise.resolve(true);
+});
+'''
+
+ADD_TASK_REJECTED = '''
+Components.utils.import("resource://gre/modules/commonjs/promise/core.js");
+
+function run_test() { run_next_test(); }
+
+add_task(function test_failing() {
+  yield Promise.reject(new Error("I fail."));
+});
+'''
+
+ADD_TASK_FAILURE_INSIDE = '''
+Components.utils.import("resource://gre/modules/commonjs/promise/core.js");
+
+function run_test() { run_next_test(); }
+
+add_task(function test() {
+  let result = yield Promise.resolve(false);
+
+  do_check_true(result);
+});
+'''
+
 class XPCShellTestsTests(unittest.TestCase):
     """
     Yes, these are unit tests for a unit test harness.
     """
     def setUp(self):
         self.log = StringIO()
         self.tempdir = tempfile.mkdtemp()
         self.x = XPCShellTests(log=self.log)
@@ -207,16 +272,91 @@ tail =
         self.assertTestResult(False)
         self.assertEquals(1, self.x.testCount)
         self.assertEquals(0, self.x.passCount)
         self.assertEquals(1, self.x.failCount)
         self.assertEquals(0, self.x.todoCount)
         self.assertInLog("TEST-UNEXPECTED-FAIL")
         self.assertNotInLog("TEST-PASS")
 
+    def testAddTestSimple(self):
+        """
+        Ensure simple add_test() works.
+        """
+        self.writeFile("test_add_test_simple.js", ADD_TEST_SIMPLE)
+        self.writeManifest(["test_add_test_simple.js"])
+
+        self.assertTestResult(True)
+        self.assertEquals(1, self.x.testCount)
+        self.assertEquals(1, self.x.passCount)
+        self.assertEquals(0, self.x.failCount)
+
+    def testAddTestFailing(self):
+        """
+        Ensure add_test() with a failing test is reported.
+        """
+        self.writeFile("test_add_test_failing.js", ADD_TEST_FAILING)
+        self.writeManifest(["test_add_test_failing.js"])
+
+        self.assertTestResult(False)
+        self.assertEquals(1, self.x.testCount)
+        self.assertEquals(0, self.x.passCount)
+        self.assertEquals(1, self.x.failCount)
+
+    def testAddTaskTestSingle(self):
+        """
+        Ensure add_test_task() with a single passing test works.
+        """
+        self.writeFile("test_add_task_simple.js", ADD_TASK_SINGLE)
+        self.writeManifest(["test_add_task_simple.js"])
+
+        self.assertTestResult(True)
+        self.assertEquals(1, self.x.testCount)
+        self.assertEquals(1, self.x.passCount)
+        self.assertEquals(0, self.x.failCount)
+
+    def testAddTaskTestMultiple(self):
+        """
+        Ensure multiple calls to add_test_task() work as expected.
+        """
+        self.writeFile("test_add_task_multiple.js",
+            ADD_TASK_MULTIPLE)
+        self.writeManifest(["test_add_task_multiple.js"])
+
+        self.assertTestResult(True)
+        self.assertEquals(1, self.x.testCount)
+        self.assertEquals(1, self.x.passCount)
+        self.assertEquals(0, self.x.failCount)
+
+    def testAddTaskTestRejected(self):
+        """
+        Ensure rejected task reports as failure.
+        """
+        self.writeFile("test_add_task_rejected.js",
+            ADD_TASK_REJECTED)
+        self.writeManifest(["test_add_task_rejected.js"])
+
+        self.assertTestResult(False)
+        self.assertEquals(1, self.x.testCount)
+        self.assertEquals(0, self.x.passCount)
+        self.assertEquals(1, self.x.failCount)
+
+    def testAddTaskTestFailureInside(self):
+        """
+        Ensure tests inside task are reported as failures.
+        """
+        self.writeFile("test_add_task_failure_inside.js",
+            ADD_TASK_FAILURE_INSIDE)
+        self.writeManifest(["test_add_task_failure_inside.js"])
+
+        self.assertTestResult(False)
+        self.assertEquals(1, self.x.testCount)
+        self.assertEquals(0, self.x.passCount)
+        self.assertEquals(1, self.x.failCount)
+
     def testMissingHeadFile(self):
         """
         Ensure that missing head file results in fatal error.
         """
         self.writeFile("test_basic.js", SIMPLE_PASSING_TEST)
         self.writeManifest([("test_basic.js", "head = missing.js")])
 
         raised = False
--- a/toolkit/components/filepicker/nsFileView.cpp
+++ b/toolkit/components/filepicker/nsFileView.cpp
@@ -209,23 +209,23 @@ public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIFILEVIEW
   NS_DECL_NSITREEVIEW
   
 protected:
   virtual ~nsFileView();
   
   void FilterFiles();
-  void ReverseArray(nsISupportsArray* aArray);
-  void SortArray(nsISupportsArray* aArray);
+  void ReverseArray(nsTArray<nsCOMPtr<nsIFile> >& aArray);
+  void SortArray(nsTArray<nsCOMPtr<nsIFile> >& aArray);
   void SortInternal();
 
-  nsCOMPtr<nsISupportsArray> mFileList;
-  nsCOMPtr<nsISupportsArray> mDirList;
-  nsCOMPtr<nsISupportsArray> mFilteredFiles;
+  nsTArray<nsCOMPtr<nsIFile> > mFileList;
+  nsTArray<nsCOMPtr<nsIFile> > mDirList;
+  nsTArray<nsCOMPtr<nsIFile> > mFilteredFiles;
 
   nsCOMPtr<nsIFile> mDirectoryPath;
   nsCOMPtr<nsITreeBoxObject> mTree;
   nsCOMPtr<nsITreeSelection> mSelection;
   nsCOMPtr<nsIAtom> mDirectoryAtom;
   nsCOMPtr<nsIAtom> mFileAtom;
   nsCOMPtr<nsIDateTimeFormat> mDateFormatter;
 
@@ -287,28 +287,16 @@ nsFileView::Init()
   mDirectoryAtom = do_GetAtom("directory");
   if (!mDirectoryAtom)
     return NS_ERROR_OUT_OF_MEMORY;
 
   mFileAtom = do_GetAtom("file");
   if (!mFileAtom)
     return NS_ERROR_OUT_OF_MEMORY;
 
-  NS_NewISupportsArray(getter_AddRefs(mFileList));
-  if (!mFileList)
-    return NS_ERROR_OUT_OF_MEMORY;
-
-  NS_NewISupportsArray(getter_AddRefs(mDirList));
-  if (!mDirList)
-    return NS_ERROR_OUT_OF_MEMORY;
-
-  NS_NewISupportsArray(getter_AddRefs(mFilteredFiles));
-  if (!mFilteredFiles)
-    return NS_ERROR_OUT_OF_MEMORY;
-
   mDateFormatter = do_CreateInstance(NS_DATETIMEFORMAT_CONTRACTID);
   if (!mDateFormatter)
     return NS_ERROR_OUT_OF_MEMORY;
 
   return NS_OK;
 }
 
 // nsISupports implementation
@@ -340,22 +328,21 @@ nsFileView::GetShowHiddenFiles(bool* aSh
 
 NS_IMETHODIMP
 nsFileView::SetShowOnlyDirectories(bool aOnlyDirs)
 {
   if (aOnlyDirs == mDirectoryFilter)
     return NS_OK;
 
   mDirectoryFilter = aOnlyDirs;
-  uint32_t dirCount;
-  mDirList->Count(&dirCount);
+  uint32_t dirCount = mDirList.Length();
   if (mDirectoryFilter) {
     int32_t rowDiff = mTotalRows - dirCount;
 
-    mFilteredFiles->Clear();
+    mFilteredFiles.Clear();
     mTotalRows = dirCount;
     if (mTree)
       mTree->RowCountChanged(mTotalRows, -rowDiff);
   } else {
     // Run the filter again to get the file list back
     FilterFiles();
 
     SortArray(mFilteredFiles);
@@ -422,39 +409,39 @@ nsFileView::SetDirectory(nsIFile* aDirec
 
   if (!dirEntries) {
     // Couldn't read in the directory, this can happen if the user does not
     // have permission to list it.
     return NS_ERROR_FAILURE;
   }
 
   mDirectoryPath = aDirectory;
-  mFileList->Clear();
-  mDirList->Clear();
+  mFileList.Clear();
+  mDirList.Clear();
 
   bool hasMore = false;
 
   while (NS_SUCCEEDED(dirEntries->HasMoreElements(&hasMore)) && hasMore) {
     nsCOMPtr<nsISupports> nextItem;
     dirEntries->GetNext(getter_AddRefs(nextItem));
     nsCOMPtr<nsIFile> theFile = do_QueryInterface(nextItem);
 
     bool isDirectory = false;
     if (theFile) {
       theFile->IsDirectory(&isDirectory);
 
       if (isDirectory) {
         bool isHidden;
         theFile->IsHidden(&isHidden);
         if (mShowHiddenFiles || !isHidden) {
-          mDirList->AppendElement(theFile);
+          mDirList.AppendElement(theFile);
         }
       }
       else {
-        mFileList->AppendElement(theFile);
+        mFileList.AppendElement(theFile);
       }
     }
   }
 
   if (mTree) {
     mTree->BeginUpdateBatch();
     mTree->RowCountChanged(0, -mTotalRows);
   }
@@ -511,22 +498,21 @@ nsFileView::SetFilter(const nsAString& a
     if (iter == end)
       break;
 
     ++iter; // we know this is either ';' or ' ', skip to next char
   }
 
   if (mTree) {
     mTree->BeginUpdateBatch();
-    uint32_t count;
-    mDirList->Count(&count);
+    uint32_t count = mDirList.Length();
     mTree->RowCountChanged(count, count - mTotalRows);
   }
 
-  mFilteredFiles->Clear();
+  mFilteredFiles.Clear();
 
   FilterFiles();
 
   SortArray(mFilteredFiles);
   if (mReverseSort)
     ReverseArray(mFilteredFiles);
 
   if (mTree)
@@ -540,35 +526,33 @@ nsFileView::GetSelectedFiles(nsIArray** 
 {
   *aFiles = nullptr;
   if (!mSelection)
     return NS_OK;
 
   int32_t numRanges;
   mSelection->GetRangeCount(&numRanges);
 
-  uint32_t dirCount;
-  mDirList->Count(&dirCount);
-
+  uint32_t dirCount = mDirList.Length();
   nsCOMPtr<nsIMutableArray> fileArray =
     do_CreateInstance(NS_ARRAY_CONTRACTID);
   NS_ENSURE_STATE(fileArray);
 
   for (int32_t range = 0; range < numRanges; ++range) {
     int32_t rangeBegin, rangeEnd;
     mSelection->GetRangeAt(range, &rangeBegin, &rangeEnd);
 
     for (int32_t itemIndex = rangeBegin; itemIndex <= rangeEnd; ++itemIndex) {
-      nsCOMPtr<nsIFile> curFile;
+      nsIFile* curFile = nullptr;
 
       if (itemIndex < (int32_t) dirCount)
-        curFile = do_QueryElementAt(mDirList, itemIndex);
+        curFile = mDirList[itemIndex];
       else {
         if (itemIndex < mTotalRows)
-          curFile = do_QueryElementAt(mFilteredFiles, itemIndex - dirCount);
+          curFile = mFilteredFiles[itemIndex - dirCount];
       }
 
       if (curFile)
         fileArray->AppendElement(curFile, false);
     }
   }
 
   NS_ADDREF(*aFiles = fileArray);
@@ -606,18 +590,17 @@ nsFileView::GetRowProperties(int32_t aIn
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFileView::GetCellProperties(int32_t aRow, nsITreeColumn* aCol,
                               nsISupportsArray* aProperties)
 {
-  uint32_t dirCount;
-  mDirList->Count(&dirCount);
+  uint32_t dirCount = mDirList.Length();
 
   if (aRow < (int32_t) dirCount)
     aProperties->AppendElement(mDirectoryAtom);
   else if (aRow < mTotalRows)
     aProperties->AppendElement(mFileAtom);
 
   return NS_OK;
 }
@@ -720,29 +703,26 @@ nsFileView::GetCellValue(int32_t aRow, n
 {
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFileView::GetCellText(int32_t aRow, nsITreeColumn* aCol,
                         nsAString& aCellText)
 {
-  uint32_t dirCount, fileCount;
-  mDirList->Count(&dirCount);
-  mFilteredFiles->Count(&fileCount);
-
+  uint32_t dirCount = mDirList.Length();
   bool isDirectory;
-  nsCOMPtr<nsIFile> curFile;
+  nsIFile* curFile = nullptr;
 
   if (aRow < (int32_t) dirCount) {
     isDirectory = true;
-    curFile = do_QueryElementAt(mDirList, aRow);
+    curFile = mDirList[aRow];
   } else if (aRow < mTotalRows) {
     isDirectory = false;
-    curFile = do_QueryElementAt(mFilteredFiles, aRow - dirCount);
+    curFile = mFilteredFiles[aRow - dirCount];
   } else {
     // invalid row
     aCellText.SetCapacity(0);
     return NS_OK;
   }
 
   const PRUnichar* colID;
   aCol->GetIdConst(&colID);
@@ -850,26 +830,24 @@ nsFileView::PerformActionOnCell(const PR
   return NS_OK;
 }
 
 // Private methods
 
 void
 nsFileView::FilterFiles()
 {
-  uint32_t count = 0;
-  mDirList->Count(&count);
+  uint32_t count = mDirList.Length();
   mTotalRows = count;
-  mFileList->Count(&count);
-  mFilteredFiles->Clear();
+  count = mFileList.Length();
+  mFilteredFiles.Clear();
   uint32_t filterCount = mCurrentFilters.Length();
 
-  nsCOMPtr<nsIFile> file;
   for (uint32_t i = 0; i < count; ++i) {
-    file = do_QueryElementAt(mFileList, i);
+    nsIFile* file = mFileList[i];
     bool isHidden = false;
     if (!mShowHiddenFiles)
       file->IsHidden(&isHidden);
     
     nsAutoString ucsLeafName;
     if(NS_FAILED(file->GetLeafName(ucsLeafName))) {
       // need to check return value for GetLeafName()
       continue;
@@ -883,35 +861,35 @@ nsFileView::FilterFiles()
         {
           file->IsExecutable(&matched);
         } else
           matched = (NS_WildCardMatch(ucsLeafName.get(),
                                       mCurrentFilters.ElementAt(j),
                                       true) == MATCH);
 
         if (matched) {
-          mFilteredFiles->AppendElement(file);
+          mFilteredFiles.AppendElement(file);
           ++mTotalRows;
           break;
         }
       }
     }
   }
 }
 
 void
-nsFileView::ReverseArray(nsISupportsArray* aArray)
+nsFileView::ReverseArray(nsTArray<nsCOMPtr<nsIFile> >& aArray)
 {
-  uint32_t count;
-  aArray->Count(&count);
+  uint32_t count = aArray.Length();
   for (uint32_t i = 0; i < count/2; ++i) {
-    nsCOMPtr<nsISupports> element = dont_AddRef(aArray->ElementAt(i));
-    nsCOMPtr<nsISupports> element2 = dont_AddRef(aArray->ElementAt(count-i-1));
-    aArray->ReplaceElementAt(element2, i);
-    aArray->ReplaceElementAt(element, count-i-1);
+    // If we get references to the COMPtrs in the array, and then .swap() them
+    // we avoid AdRef() / Release() calls.
+    nsCOMPtr<nsIFile>& element = aArray[i];
+    nsCOMPtr<nsIFile>& element2 = aArray[count - i - 1];
+    element.swap(element2);
   }
 }
 
 static int
 SortNameCallback(const void* aElement1, const void* aElement2, void* aContext)
 {
   nsIFile* file1 = *static_cast<nsIFile* const *>(aElement1);
   nsIFile* file2 = *static_cast<nsIFile* const *>(aElement2);
@@ -951,17 +929,17 @@ SortDateCallback(const void* aElement1, 
 
   if (time1 == time2)
     return 0;
 
   return time1 < time2 ? -1 : 1;
 }
 
 void
-nsFileView::SortArray(nsISupportsArray* aArray)
+nsFileView::SortArray(nsTArray<nsCOMPtr<nsIFile> >& aArray)
 {
   // We assume the array to be in filesystem order, which
   // for our purposes, is completely unordered.
 
   int (*compareFunc)(const void*, const void*, void*);
 
   switch (mSortType) {
   case sortName:
@@ -972,31 +950,28 @@ nsFileView::SortArray(nsISupportsArray* 
     break;
   case sortDate:
     compareFunc = SortDateCallback;
     break;
   default:
     return;
   }
 
-  uint32_t count;
-  aArray->Count(&count);
+  uint32_t count = aArray.Length();
 
-  // each item will have an additional refcount while
-  // the array is alive.
   nsIFile** array = new nsIFile*[count];
-  uint32_t i;
-  for (i = 0; i < count; ++i)
-    aArray->QueryElementAt(i, NS_GET_IID(nsIFile), (void**)&(array[i]));
+  for (uint32_t i = 0; i < count; ++i) {
+    array[i] = aArray[i];
+  }
 
   NS_QuickSort(array, count, sizeof(nsIFile*), compareFunc, nullptr);
 
-  for (i = 0; i < count; ++i) {
-    aArray->ReplaceElementAt(array[i], i);
-    NS_RELEASE(array[i]);
+  for (uint32_t i = 0; i < count; ++i) {
+    // Use swap() to avoid refcounting.
+    aArray[i].swap(array[i]);
   }
 
   delete[] array;
 }
 
 void
 nsFileView::SortInternal()
 {
--- a/toolkit/components/places/tests/unit/test_sql_guid_functions.js
+++ b/toolkit/components/places/tests/unit/test_sql_guid_functions.js
@@ -9,18 +9,17 @@
 /**
  * Checks all our invariants about our guids for a given result.
  *
  * @param aGuid
  *        The guid to check.
  */
 function check_invariants(aGuid)
 {
-  print("TEST-INFO | " + gRunningTest.name + " | Checking guid '" +
-        aGuid + "'");
+  do_print("Checking guid '" + aGuid + "'");
 
   do_check_valid_places_guid(aGuid);
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 //// Test Functions
 
 function test_guid_invariants()
--- a/toolkit/components/satchel/nsFormFillController.cpp
+++ b/toolkit/components/satchel/nsFormFillController.cpp
@@ -52,18 +52,16 @@ nsFormFillController::nsFormFillControll
   mMaxRows(0),
   mDisableAutoComplete(false),
   mCompleteDefaultIndex(false),
   mCompleteSelectedIndex(false),
   mForceComplete(false),
   mSuppressOnInput(false)
 {
   mController = do_GetService("@mozilla.org/autocomplete/controller;1");
-  mDocShells = do_CreateInstance("@mozilla.org/supports-array;1");
-  mPopups = do_CreateInstance("@mozilla.org/supports-array;1");
   mPwmgrInputs.Init();
 }
 
 struct PwmgrInputsEnumData
 {
   PwmgrInputsEnumData(nsFormFillController* aFFC, nsIDocument* aDoc)
   : mFFC(aFFC), mDoc(aDoc) {}
 
@@ -81,22 +79,19 @@ nsFormFillController::~nsFormFillControl
     MaybeRemoveMutationObserver(mFocusedInputNode);
     mFocusedInputNode = nullptr;
     mFocusedInput = nullptr;
   }
   PwmgrInputsEnumData ed(this, nullptr);
   mPwmgrInputs.Enumerate(RemoveForDocumentEnumerator, &ed);
 
   // Remove ourselves as a focus listener from all cached docShells
-  uint32_t count;
-  mDocShells->Count(&count);
+  uint32_t count = mDocShells.Length();
   for (uint32_t i = 0; i < count; ++i) {
-    nsCOMPtr<nsIDocShell> docShell;
-    mDocShells->GetElementAt(i, getter_AddRefs(docShell));
-    nsCOMPtr<nsIDOMWindow> domWindow = GetWindowForDocShell(docShell);
+    nsCOMPtr<nsIDOMWindow> domWindow = GetWindowForDocShell(mDocShells[i]);
     RemoveWindowListeners(domWindow);
   }
 }
 
 ////////////////////////////////////////////////////////////////////////
 //// nsIMutationObserver
 //
 
@@ -199,40 +194,39 @@ nsFormFillController::MaybeRemoveMutatio
 ////////////////////////////////////////////////////////////////////////
 //// nsIFormFillController
 
 NS_IMETHODIMP
 nsFormFillController::AttachToBrowser(nsIDocShell *aDocShell, nsIAutoCompletePopup *aPopup)
 {
   NS_ENSURE_TRUE(aDocShell && aPopup, NS_ERROR_ILLEGAL_VALUE);
 
-  mDocShells->AppendElement(aDocShell);
-  mPopups->AppendElement(aPopup);
+  mDocShells.AppendElement(aDocShell);
+  mPopups.AppendElement(aPopup);
 
   // Listen for focus events on the domWindow of the docShell
   nsCOMPtr<nsIDOMWindow> domWindow = GetWindowForDocShell(aDocShell);
   AddWindowListeners(domWindow);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsFormFillController::DetachFromBrowser(nsIDocShell *aDocShell)
 {
   int32_t index = GetIndexOfDocShell(aDocShell);
   NS_ENSURE_TRUE(index >= 0, NS_ERROR_FAILURE);
 
   // Stop listening for focus events on the domWindow of the docShell
-  nsCOMPtr<nsIDocShell> docShell;
-  mDocShells->GetElementAt(index, getter_AddRefs(docShell));
-  nsCOMPtr<nsIDOMWindow> domWindow = GetWindowForDocShell(docShell);
+  nsCOMPtr<nsIDOMWindow> domWindow =
+    GetWindowForDocShell(mDocShells.SafeElementAt(index));
   RemoveWindowListeners(domWindow);
 
-  mDocShells->RemoveElementAt(index);
-  mPopups->RemoveElementAt(index);
+  mDocShells.RemoveElementAt(index);
+  mPopups.RemoveElementAt(index);
 
   return NS_OK;
 }
 
 
 NS_IMETHODIMP
 nsFormFillController::MarkAsLoginManagerField(nsIDOMHTMLInputElement *aInput)
 {
@@ -1055,17 +1049,17 @@ nsFormFillController::StartControllingIn
 
   // Find the currently focused docShell
   nsCOMPtr<nsIDocShell> docShell = GetDocShellForInput(aInput);
   int32_t index = GetIndexOfDocShell(docShell);
   if (index < 0)
     return;
 
   // Cache the popup for the focused docShell
-  mPopups->GetElementAt(index, getter_AddRefs(mFocusedPopup));
+  mFocusedPopup = mPopups.SafeElementAt(index);
 
   nsCOMPtr<nsINode> node = do_QueryInterface(aInput);
   if (!node) {
     return;
   }
 
   AddKeyListener(aInput);
   
@@ -1140,22 +1134,19 @@ nsFormFillController::GetWindowForDocShe
 
 int32_t
 nsFormFillController::GetIndexOfDocShell(nsIDocShell *aDocShell)
 {
   if (!aDocShell)
     return -1;
 
   // Loop through our cached docShells looking for the given docShell
-  uint32_t count;
-  mDocShells->Count(&count);
+  uint32_t count = mDocShells.Length();
   for (uint32_t i = 0; i < count; ++i) {
-    nsCOMPtr<nsIDocShell> docShell;
-    mDocShells->GetElementAt(i, getter_AddRefs(docShell));
-    if (docShell == aDocShell)
+    if (mDocShells[i] == aDocShell)
       return i;
   }
 
   // Recursively check the parent docShell of this one
   nsCOMPtr<nsIDocShellTreeItem> treeItem = do_QueryInterface(aDocShell);
   nsCOMPtr<nsIDocShellTreeItem> parentItem;
   treeItem->GetParent(getter_AddRefs(parentItem));
   if (parentItem) {
--- a/toolkit/components/satchel/nsFormFillController.h
+++ b/toolkit/components/satchel/nsFormFillController.h
@@ -8,23 +8,23 @@
 
 #include "nsIFormFillController.h"
 #include "nsIAutoCompleteInput.h"
 #include "nsIAutoCompleteSearch.h"
 #include "nsIAutoCompleteController.h"
 #include "nsIAutoCompletePopup.h"
 #include "nsIDOMEventListener.h"
 #include "nsCOMPtr.h"
-#include "nsISupportsArray.h"
 #include "nsDataHashtable.h"
 #include "nsIDocShell.h"
 #include "nsIDOMWindow.h"
 #include "nsIDOMHTMLInputElement.h"
 #include "nsILoginManager.h"
 #include "nsIMutationObserver.h"
+#include "nsTArray.h"
 
 // X.h defines KeyPress
 #ifdef KeyPress
 #undef KeyPress
 #endif
 
 class nsFormHistory;
 class nsINode;
@@ -77,18 +77,18 @@ protected:
 
   nsCOMPtr<nsIAutoCompleteController> mController;
   nsCOMPtr<nsILoginManager> mLoginManager;
   nsIDOMHTMLInputElement* mFocusedInput;
   nsINode* mFocusedInputNode;
   nsINode* mListNode;
   nsCOMPtr<nsIAutoCompletePopup> mFocusedPopup;
 
-  nsCOMPtr<nsISupportsArray> mDocShells;
-  nsCOMPtr<nsISupportsArray> mPopups;
+  nsTArray<nsCOMPtr<nsIDocShell> > mDocShells;
+  nsTArray<nsCOMPtr<nsIAutoCompletePopup> > mPopups;
 
   //these are used to dynamically update the autocomplete
   nsCOMPtr<nsIAutoCompleteResult> mLastSearchResult;
   nsCOMPtr<nsIAutoCompleteObserver> mLastListener;
   nsString mLastSearchString;
 
   nsDataHashtable<nsPtrHashKey<const nsINode>, bool> mPwmgrInputs;
 
--- a/toolkit/content/Makefile.in
+++ b/toolkit/content/Makefile.in
@@ -61,23 +61,23 @@ EXTRA_JS_MODULES = \
   DeferredTask.jsm \
   Dict.jsm \
   Geometry.jsm \
   InlineSpellChecker.jsm \
   PageMenu.jsm \
   PopupNotifications.jsm \
   PropertyListUtils.jsm \
   Task.jsm \
-  UpdateChannel.jsm \
   $(NULL)
 
 EXTRA_PP_JS_MODULES = \
   PrivateBrowsingUtils.jsm \
   Services.jsm \
   WindowDraggingUtils.jsm \
   Troubleshoot.jsm \
+  UpdateChannel.jsm \
   $(NULL)
 
 ifneq (Android,$(OS_TARGET))
 EXTRA_PP_JS_MODULES += LightweightThemeConsumer.jsm
 endif
 
 include $(topsrcdir)/config/rules.mk
--- a/toolkit/content/UpdateChannel.jsm
+++ b/toolkit/content/UpdateChannel.jsm
@@ -1,8 +1,10 @@
+#filter substitution
+
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 this.EXPORTED_SYMBOLS = ["UpdateChannel"];
 
 const Cu = Components.utils;
 
@@ -10,22 +12,22 @@ Cu.import("resource://gre/modules/Servic
 
 this.UpdateChannel = {
   /**
    * Read the update channel from defaults only.  We do this to ensure that
    * the channel is tightly coupled with the application and does not apply
    * to other instances of the application that may use the same profile.
    */
   get: function UpdateChannel_get() {
-    let channel = "default";
+    let channel = "@MOZ_UPDATE_CHANNEL@";
     let defaults = Services.prefs.getDefaultBranch(null);
     try {
       channel = defaults.getCharPref("app.update.channel");
     } catch (e) {
-      // use default when pref not found
+      // use default value when pref not found
     }
 
     try {
       let partners = Services.prefs.getChildList("app.partner.").sort();
       if (partners.length) {
         channel += "-cck";
         partners.forEach(function (prefName) {
           channel += "-" + Services.prefs.getCharPref(prefName);
--- a/toolkit/themes/pinstripe/mozapps/jar.mn
+++ b/toolkit/themes/pinstripe/mozapps/jar.mn
@@ -55,17 +55,17 @@ toolkit.jar:
   skin/classic/mozapps/passwordmgr/key-16@2x.png                  (passwordmgr/key-16@2x.png)
   skin/classic/mozapps/passwordmgr/key-64.png                     (passwordmgr/key-64.png)
   skin/classic/mozapps/plugins/contentPluginBlocked.png           (plugins/contentPluginBlocked.png)
   skin/classic/mozapps/plugins/contentPluginCrashed.png           (plugins/contentPluginCrashed.png)
   skin/classic/mozapps/plugins/contentPluginDisabled.png          (plugins/contentPluginDisabled.png)
   skin/classic/mozapps/plugins/contentPluginDownload.png          (plugins/contentPluginDownload.png)
   skin/classic/mozapps/plugins/contentPluginMissing.png           (plugins/contentPluginMissing.png)
   skin/classic/mozapps/plugins/contentPluginClickToPlay.png       (plugins/contentPluginClickToPlay.png)
-  skin/classic/mozapps/plugins/notifyPluginBlocked.png            (plugins/notifyPluginGeneric.png)
+  skin/classic/mozapps/plugins/notifyPluginBlocked.png            (plugins/pluginBlocked-16.png)
   skin/classic/mozapps/plugins/notifyPluginCrashed.png            (plugins/notifyPluginGeneric.png)
   skin/classic/mozapps/plugins/notifyPluginGeneric.png            (plugins/notifyPluginGeneric.png)
   skin/classic/mozapps/plugins/notifyPluginOutdated.png           (plugins/notifyPluginGeneric.png)
   skin/classic/mozapps/plugins/pluginProblem.css                  (plugins/pluginProblem.css)
   skin/classic/mozapps/plugins/pluginGeneric.png                  (plugins/pluginGeneric.png)
   skin/classic/mozapps/plugins/pluginDisabled.png                 (plugins/pluginDisabled.png)
   skin/classic/mozapps/plugins/pluginBlocked.png                  (plugins/pluginBlocked.png)
   skin/classic/mozapps/plugins/pluginBlocked-64.png               (plugins/pluginBlocked-64.png)
deleted file mode 100755
--- a/tools/rb/fix-macosx-stack.pl
+++ /dev/null
@@ -1,226 +0,0 @@
-#!/usr/bin/perl
-# vim:sw=4:ts=4:et:
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at http://mozilla.org/MPL/2.0/.
-
-# $Id: fix-macosx-stack.pl,v 1.6 2007/08/17 06:26:09 dbaron%dbaron.org Exp $
-#
-# This script processes the output of nsTraceRefcnt's Mac OS X stack
-# walking code.  This is useful for two things:
-#  (1) Getting line number information out of
-#      |nsTraceRefcntImpl::WalkTheStack|'s output in debug builds.
-#  (2) Getting function names out of |nsTraceRefcntImpl::WalkTheStack|'s
-#      output on all builds (where it mostly prints UNKNOWN because only
-#      a handful of symbols are exported from component libraries).
-#
-# Use the script by piping output containing stacks (such as raw stacks
-# or make-tree.pl balance trees) through this script.
-
-use strict;
-use IPC::Open2;
-
-sub separate_debug_file_for($) {
-    my ($file) = @_;
-    return '';
-}
-
-my %address_adjustments;
-sub address_adjustment($) {
-    my ($file) = @_;
-    unless (exists $address_adjustments{$file}) {
-        my $result = -1;
-
-        open(OTOOL, '-|', 'otool', '-l', $file);
-        while (<OTOOL>) {
-            if (/^  segname __TEXT$/) {
-                if (<OTOOL> =~ /^   vmaddr (0x[0-9a-f]{8})$/) {
-                    $result = hex($1);
-                    last;
-                } else {
-                    die "Bad output from otool";
-                }
-            }
-        }
-        close(OTOOL);
-
-        $result >= 0 || die "Bad output from otool";
-
-        $address_adjustments{$file} = $result;
-    }
-
-    return $address_adjustments{$file};
-}
-
-sub add_info($$$) {
-    my ($array, $address, $data) = @_;
-
-    # only remember the last item at a given address
-    pop @{$array} if ($#{$array} >= 0 && $array->[$#{$array}]->[0] == $address);
-
-    push @{$array}, [ $address, $data ];
-}
-
-sub sort_by_address() {
-    return $a->[0] <=> $b->[0];
-}
-
-# Return a reference to a hash whose {read} and {write} entries are a
-# bidirectional pipe to an addr2line process that gives symbol
-# information for a file.
-my %nmstructs;
-sub nmstruct_for($) {
-    my ($file) = @_;
-    my $nmstruct;
-    my $curdir;
-    unless (exists $nmstructs{$file}) {
-        $nmstruct = { symbols => [], files => [], lines => [] };
-
-        my $debug_file = separate_debug_file_for($file);
-        $debug_file = $file if ($debug_file eq '');
-
-        open(NM, '-|', 'nm', '-an', $debug_file);
-        while (<NM>) {
-            chomp;
-            my ($addr, $ty, $rest) = ($_ =~ /^([0-9a-f ]{8}) (.) (.*)$/);
-            $addr = hex($addr);
-            if ($ty eq 't' || $ty eq 'T') {
-                my $sym = $rest;
-                if (substr($sym, 0, 1) eq '_') {
-                    # symbols on Mac have an extra leading _
-                    $sym = substr($sym, 1);
-                }
-                add_info($nmstruct->{symbols}, $addr, $sym);
-            } elsif ($ty eq '-') {
-                # nm gives us stabs debugging information
-                my ($n1, $n2, $ty2, $rest2) =
-                    ($rest =~ /^([0-9a-f]{2}) ([0-9a-f]{4}) (.{5}) (.*)$/);
-                # ignore $ty2 == '  FUN'
-                if ($ty2 eq 'SLINE') {
-                    add_info($nmstruct->{lines}, $addr, hex($n2));
-                } elsif ($ty2 eq '  SOL') {
-                    # We get SOL lines within the code for a source
-                    # file.  They always have file names.
-                    my $file = $rest2;
-                    if (!($file =~ /^\//)) {
-                        # resolve relative paths
-                        $file = $curdir . $file;
-                    }
-                    add_info($nmstruct->{files}, $addr, $file);
-                } elsif ($ty2 eq '   SO') {
-                    # We get SO lines at the beginning of the code for a
-                    # source file, for:
-                    #  * the directory of the compilation
-                    #  * the file
-                    #  * sometimes a blank line
-                    if ($rest2 =~ /\/$/) {
-                        $curdir = $rest2;
-                    } elsif ($rest2 ne '') {
-                        add_info($nmstruct->{files}, $addr, $rest2);
-                    }
-                }
-            }
-        }
-        close(NM);
-
-        # nm -n Doesn't sort across .o files.
-        @{$nmstruct->{symbols}} = sort sort_by_address @{$nmstruct->{symbols}};
-        @{$nmstruct->{lines}} = sort sort_by_address @{$nmstruct->{lines}};
-        @{$nmstruct->{files}} = sort sort_by_address @{$nmstruct->{files}};
-
-        $nmstructs{$file} = $nmstruct;
-    } else {
-        $nmstruct = $nmstructs{$file};
-    }
-    return $nmstruct;
-}
-
-my $cxxfilt_pipe;
-sub cxxfilt($) {
-    my ($sym) = @_;
-
-    unless($cxxfilt_pipe) {
-        my $pid = open2($cxxfilt_pipe->{read}, $cxxfilt_pipe->{write},
-                        'c++filt', '--no-strip-underscores',
-                                   '--format', 'gnu-v3');
-    }
-    my $out = $cxxfilt_pipe->{write};
-    my $in = $cxxfilt_pipe->{read};
-    print {$out} $sym . "\n";
-    chomp(my $fixedsym = <$in>);
-    return $fixedsym;
-}
-
-# binary search the array for the address
-sub array_lookup($$) {
-    my ($array, $address) = @_;
-
-    my $start = 0;
-    my $end = $#{$array};
-
-    return [ -1 , "" ] if ($end == -1);
-
-    while ($start != $end) {
-        my $test = int(($start + $end + 1) / 2); # may equal $end
-        # Since we're processing stack traces, and the addresses in
-        # stack traces are the instructions to return to, and we really
-        # want the instruction that made the call (the previous
-        # instruction), use > instead of >=.
-        if ($address > $array->[$test]->[0]) {
-            $start = $test;
-        } else {
-            $end = $test - 1;
-        }
-    }
-
-    return $array->[$start];
-}
-
-sub nm_lookup($$) {
-    my ($nmstruct, $address) = @_;
-    my $sym = array_lookup($nmstruct->{symbols}, $address);
-    return {
-             symbol => cxxfilt($sym->[1]),
-             symbol_offset => ($address - $sym->[0]),
-             file => array_lookup($nmstruct->{files}, $address)->[1],
-             line => array_lookup($nmstruct->{lines}, $address)->[1]
-           };
-}
-
-select STDOUT; $| = 1; # make STDOUT unbuffered
-while (<>) {
-    my $line = $_;
-    if ($line =~ /^([ \|0-9-]*)(.*) ?\[([^ ]*) \+(0x[0-9A-F]{1,8})\](.*)$/) {
-        my $before = $1; # allow preservation of balance trees
-        my $badsymbol = $2;
-        my $file = $3;
-        my $address = hex($4);
-        my $after = $5; # allow preservation of counts
-
-        if (-f $file) {
-            my $nmstruct = nmstruct_for($file);
-            $address += address_adjustment($file);
-
-            my $info = nm_lookup($nmstruct, $address);
-            my $symbol = $info->{symbol};
-            my $fileandline = $info->{file} . ':' . $info->{line};
-
-            # I'm not sure if it's possible for dlsym to have gotten
-            # better information, but just in case:
-            if (my ($offset) = ($badsymbol =~ /\+0x([0-9A-F]{8})/)) { # FIXME: add $
-                if (hex($offset) < $info->{symbol_offset}) {
-                    $symbol = $badsymbol;
-                }
-            }
-
-            if ($fileandline eq ':') { $fileandline = $file; }
-            print "$before$symbol ($fileandline)$after\n";
-        } else {
-            print STDERR "Warning: File \"$file\" does not exist.\n";
-            print $line;
-        }
-
-    } else {
-        print $line;
-    }
-}
--- a/view/src/nsView.cpp
+++ b/view/src/nsView.cpp
@@ -278,29 +278,29 @@ void nsView::DoResetWidgetBounds(bool aM
   // hidpi/lodpi screens to overlap each other and result in bad placement
   // (bug 814434).
   nsRefPtr<nsDeviceContext> dx;
   mViewManager->GetDeviceContext(*getter_AddRefs(dx));
   double invScale = dx->UnscaledAppUnitsPerDevPixel() / 60.0;
 
   if (changedPos) {
     if (changedSize && !aMoveOnly) {
-      mWindow->ResizeClient(NSToIntRound(newBounds.x * invScale),
-                            NSToIntRound(newBounds.y * invScale),
-                            NSToIntRound(newBounds.width * invScale),
-                            NSToIntRound(newBounds.height * invScale),
+      mWindow->ResizeClient(newBounds.x * invScale,
+                            newBounds.y * invScale,
+                            newBounds.width * invScale,
+                            newBounds.height * invScale,
                             aInvalidateChangedSize);
     } else {
-      mWindow->MoveClient(NSToIntRound(newBounds.x * invScale),
-                          NSToIntRound(newBounds.y * invScale));
+      mWindow->MoveClient(newBounds.x * invScale,
+                          newBounds.y * invScale);
     }
   } else {
     if (changedSize && !aMoveOnly) {
-      mWindow->ResizeClient(NSToIntRound(newBounds.width * invScale),
-                            NSToIntRound(newBounds.height * invScale),
+      mWindow->ResizeClient(newBounds.width * invScale,
+                            newBounds.height * invScale,
                             aInvalidateChangedSize);
     } // else do nothing!
   }
 }
 
 void nsView::SetDimensions(const nsRect& aRect, bool aPaint, bool aResizeWidget)
 {
   nsRect dims = aRect;
--- a/widget/android/nsWindow.cpp
+++ b/widget/android/nsWindow.cpp
@@ -401,56 +401,56 @@ nsWindow::ConstrainPosition(bool aAllowS
         *aX = 0;
         *aY = 0;
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsWindow::Move(int32_t aX,
-               int32_t aY)
+nsWindow::Move(double aX,
+               double aY)
 {
     if (IsTopLevel())
         return NS_OK;
 
     return Resize(aX,
                   aY,
                   mBounds.width,
                   mBounds.height,
                   true);
 }
 
 NS_IMETHODIMP
-nsWindow::Resize(int32_t aWidth,
-                 int32_t aHeight,
+nsWindow::Resize(double aWidth,
+                 double aHeight,
                  bool aRepaint)
 {
     return Resize(mBounds.x,
                   mBounds.y,
                   aWidth,
                   aHeight,
                   aRepaint);
 }
 
 NS_IMETHODIMP
-nsWindow::Resize(int32_t aX,
-                 int32_t aY,
-                 int32_t aWidth,
-                 int32_t aHeight,
+nsWindow::Resize(double aX,
+                 double aY,
+                 double aWidth,
+                 double aHeight,
                  bool aRepaint)
 {
-    ALOG("nsWindow[%p]::Resize [%d %d %d %d] (repaint %d)", (void*)this, aX, aY, aWidth, aHeight, aRepaint);
+    ALOG("nsWindow[%p]::Resize [%f %f %f %f] (repaint %d)", (void*)this, aX, aY, aWidth, aHeight, aRepaint);
 
     bool needSizeDispatch = aWidth != mBounds.width || aHeight != mBounds.height;
 
-    mBounds.x = aX;
-    mBounds.y = aY;
-    mBounds.width = aWidth;
-    mBounds.height = aHeight;
+    mBounds.x = NSToIntRound(aX);
+    mBounds.y = NSToIntRound(aY);
+    mBounds.width = NSToIntRound(aWidth);
+    mBounds.height = NSToIntRound(aHeight);
 
     if (needSizeDispatch)
         OnSizeChanged(gfxIntSize(aWidth, aHeight));
 
     // Should we skip honoring aRepaint here?
     if (aRepaint && FindTopLevel() == nsWindow::TopWindow())
         RedrawAll();
 
--- a/widget/android/nsWindow.h
+++ b/widget/android/nsWindow.h
@@ -74,25 +74,25 @@ public:
     virtual nsIWidget *GetParent(void);
     virtual float GetDPI();
     NS_IMETHOD Show(bool aState);
     NS_IMETHOD SetModal(bool aModal);
     virtual bool IsVisible() const;
     NS_IMETHOD ConstrainPosition(bool aAllowSlop,
                                  int32_t *aX,
                                  int32_t *aY);
-    NS_IMETHOD Move(int32_t aX,
-                    int32_t aY);
-    NS_IMETHOD Resize(int32_t aWidth,
-                      int32_t aHeight,
-                      bool    aRepaint);
-    NS_IMETHOD Resize(int32_t aX,
-                      int32_t aY,
-                      int32_t aWidth,
-                      int32_t aHeight,
+    NS_IMETHOD Move(double aX,
+                    double aY);
+    NS_IMETHOD Resize(double aWidth,
+                      double aHeight,
+                      bool   aRepaint);
+    NS_IMETHOD Resize(double aX,
+                      double aY,
+                      double aWidth,
+                      double aHeight,
                       bool aRepaint);
     NS_IMETHOD SetZIndex(int32_t aZIndex);
     NS_IMETHOD PlaceBehind(nsTopLevelWidgetZPlacement aPlacement,
                            nsIWidget *aWidget,
                            bool aActivate);
     NS_IMETHOD SetSizeMode(int32_t aMode);
     NS_IMETHOD Enable(bool aState);
     virtual bool IsEnabled() const;
--- a/widget/cocoa/nsChildView.h
+++ b/widget/cocoa/nsChildView.h
@@ -374,19 +374,20 @@ public:
   virtual bool            IsVisible() const;
 
   NS_IMETHOD              SetParent(nsIWidget* aNewParent);
   virtual nsIWidget*      GetParent(void);
   virtual float           GetDPI();
 
   NS_IMETHOD              ConstrainPosition(bool aAllowSlop,
                                             int32_t *aX, int32_t *aY);
-  NS_IMETHOD              Move(int32_t aX, int32_t aY);
-  NS_IMETHOD              Resize(int32_t aWidth,int32_t aHeight, bool aRepaint);
-  NS_IMETHOD              Resize(int32_t aX, int32_t aY,int32_t aWidth,int32_t aHeight, bool aRepaint);
+  NS_IMETHOD              Move(double aX, double aY);
+  NS_IMETHOD              Resize(double aWidth, double aHeight, bool aRepaint);
+  NS_IMETHOD              Resize(double aX, double aY,
+                                 double aWidth, double aHeight, bool aRepaint);
 
   NS_IMETHOD              Enable(bool aState);
   virtual bool            IsEnabled() const;
   NS_IMETHOD              SetFocus(bool aRaise);
   NS_IMETHOD              GetBounds(nsIntRect &aRect);
 
   // Returns the "backing scale factor" of the view's window, which is the
   // ratio of pixels in the window's backing store to Cocoa points. Prior to
--- a/widget/cocoa/nsChildView.mm
+++ b/widget/cocoa/nsChildView.mm
@@ -791,78 +791,90 @@ nsChildView::BackingScaleFactorChanged()
 
 NS_IMETHODIMP nsChildView::ConstrainPosition(bool aAllowSlop,
                                              int32_t *aX, int32_t *aY)
 {
   return NS_OK;
 }
 
 // Move this component, aX and aY are in the parent widget coordinate system
-NS_IMETHODIMP nsChildView::Move(int32_t aX, int32_t aY)
+NS_IMETHODIMP nsChildView::Move(double aX, double aY)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
-  if (!mView || (mBounds.x == aX && mBounds.y == aY))
+  int32_t x = NSToIntRound(aX);
+  int32_t y = NSToIntRound(aY);
+
+  if (!mView || (mBounds.x == x && mBounds.y == y))
     return NS_OK;
 
-  mBounds.x = aX;
-  mBounds.y = aY;
+  mBounds.x = x;
+  mBounds.y = y;
 
   [mView setFrame:DevPixelsToCocoaPoints(mBounds)];
 
   if (mVisible)
     [mView setNeedsDisplay:YES];
 
   NotifyRollupGeometryChange();
   ReportMoveEvent();
 
   return NS_OK;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
 }
 
-NS_IMETHODIMP nsChildView::Resize(int32_t aWidth, int32_t aHeight, bool aRepaint)
+NS_IMETHODIMP nsChildView::Resize(double aWidth, double aHeight, bool aRepaint)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
-  if (!mView || (mBounds.width == aWidth && mBounds.height == aHeight))
+  int32_t width = NSToIntRound(aWidth);
+  int32_t height = NSToIntRound(aHeight);
+
+  if (!mView || (mBounds.width == width && mBounds.height == height))
     return NS_OK;
 
-  mBounds.width  = aWidth;
-  mBounds.height = aHeight;
+  mBounds.width  = width;
+  mBounds.height = height;
 
   [mView setFrame:DevPixelsToCocoaPoints(mBounds)];
 
   if (mVisible && aRepaint)
     [mView setNeedsDisplay:YES];
 
   NotifyRollupGeometryChange();
   ReportSizeEvent();
 
   return NS_OK;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
 }
 
-NS_IMETHODIMP nsChildView::Resize(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight, bool aRepaint)
+NS_IMETHODIMP nsChildView::Resize(double aX, double aY,
+                                  double aWidth, double aHeight, bool aRepaint)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
-  BOOL isMoving = (mBounds.x != aX || mBounds.y != aY);
-  BOOL isResizing = (mBounds.width != aWidth || mBounds.height != aHeight);
+  int32_t x = NSToIntRound(aX);
+  int32_t y = NSToIntRound(aY);
+  int32_t width = NSToIntRound(aWidth);
+  int32_t height = NSToIntRound(aHeight);
+
+  BOOL isMoving = (mBounds.x != x || mBounds.y != y);
+  BOOL isResizing = (mBounds.width != width || mBounds.height != height);
   if (!mView || (!isMoving && !isResizing))
     return NS_OK;
 
   if (isMoving) {
-    mBounds.x = aX;
-    mBounds.y = aY;
+    mBounds.x = x;
+    mBounds.y = y;
   }
   if (isResizing) {
-    mBounds.width  = aWidth;
-    mBounds.height = aHeight;
+    mBounds.width  = width;
+    mBounds.height = height;
   }
 
   [mView setFrame:DevPixelsToCocoaPoints(mBounds)];
 
   if (mVisible && aRepaint)
     [mView setNeedsDisplay:YES];
 
   NotifyRollupGeometryChange();
--- a/widget/cocoa/nsCocoaWindow.h
+++ b/widget/cocoa/nsCocoaWindow.h
@@ -221,25 +221,25 @@ public:
     virtual nsIntPoint GetClientOffset();
     virtual nsIntSize ClientToWindowSize(const nsIntSize& aClientSize);
 
     virtual void* GetNativeData(uint32_t aDataType) ;
 
     NS_IMETHOD              ConstrainPosition(bool aAllowSlop,
                                               int32_t *aX, int32_t *aY);
     virtual void            SetSizeConstraints(const SizeConstraints& aConstraints);
-    NS_IMETHOD              Move(int32_t aX, int32_t aY);
+    NS_IMETHOD              Move(double aX, double aY);
     NS_IMETHOD              PlaceBehind(nsTopLevelWidgetZPlacement aPlacement,
                                         nsIWidget *aWidget, bool aActivate);
     NS_IMETHOD              SetSizeMode(int32_t aMode);
     NS_IMETHOD              HideWindowChrome(bool aShouldHide);
     void                    EnteredFullScreen(bool aFullScreen);
     NS_IMETHOD              MakeFullScreen(bool aFullScreen);
-    NS_IMETHOD              Resize(int32_t aWidth,int32_t aHeight, bool aRepaint);
-    NS_IMETHOD              Resize(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight, bool aRepaint);
+    NS_IMETHOD              Resize(double aWidth, double aHeight, bool aRepaint);
+    NS_IMETHOD              Resize(double aX, double aY, double aWidth, double aHeight, bool aRepaint);
     NS_IMETHOD              GetClientBounds(nsIntRect &aRect);
     NS_IMETHOD              GetScreenBounds(nsIntRect &aRect);
     void                    ReportMoveEvent();
     void                    ReportSizeEvent();
     NS_IMETHOD              SetCursor(nsCursor aCursor);
     NS_IMETHOD              SetCursor(imgIContainer* aCursor, uint32_t aHotspotX, uint32_t aHotspotY);
 
     CGFloat                 BackingScaleFactor();
@@ -320,17 +320,17 @@ protected:
   nsresult             CreatePopupContentView(const nsIntRect &aRect,
                                               nsDeviceContext *aContext);
   void                 DestroyNativeWindow();
   void                 AdjustWindowShadow();
   void                 SetUpWindowFilter();
   void                 CleanUpWindowFilter();
   void                 UpdateBounds();
 
-  nsresult             DoResize(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight,
+  nsresult             DoResize(double aX, double aY, double aWidth, double aHeight,
                                 bool aRepaint, bool aConstrainToCurrentScreen);
 
   virtual already_AddRefed<nsIWidget>
   AllocateChildPopupWidget()
   {
     static NS_DEFINE_IID(kCPopUpCID, NS_POPUP_CID);
     nsCOMPtr<nsIWidget> widget = do_CreateInstance(kCPopUpCID);
     return widget.forget();
--- a/widget/cocoa/nsCocoaWindow.mm
+++ b/widget/cocoa/nsCocoaWindow.mm
@@ -1120,27 +1120,27 @@ void nsCocoaWindow::SetSizeConstraints(c
   [mWindow setMaxSize:maxSize];
 
   nsBaseWidget::SetSizeConstraints(c);
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
 // Coordinates are global display pixels
-NS_IMETHODIMP nsCocoaWindow::Move(int32_t aX, int32_t aY)
+NS_IMETHODIMP nsCocoaWindow::Move(double aX, double aY)
 {
   if (!mWindow) {
     return NS_OK;
   }
 
   // The point we have is in Gecko coordinates (origin top-left). Convert
   // it to Cocoa ones (origin bottom-left).
   NSPoint coord = {
     static_cast<float>(aX),
-    static_cast<float>(nsCocoaUtils::FlippedScreenY(aY))
+    static_cast<float>(nsCocoaUtils::FlippedScreenY(NSToIntRound(aY)))
   };
 
   NSRect frame = [mWindow frame];
   if (frame.origin.x != coord.x ||
       frame.origin.y + frame.size.height != coord.y) {
     [mWindow setFrameTopLeftPoint:coord];
   }
 
@@ -1303,37 +1303,37 @@ NS_METHOD nsCocoaWindow::MakeFullScreen(
   }
 
   return NS_OK;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
 }
 
 // Coordinates are global display pixels
-nsresult nsCocoaWindow::DoResize(int32_t aX, int32_t aY,
-                                 int32_t aWidth, int32_t aHeight,
+nsresult nsCocoaWindow::DoResize(double aX, double aY,
+                                 double aWidth, double aHeight,
                                  bool aRepaint,
                                  bool aConstrainToCurrentScreen)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
   if (!mWindow) {
     return NS_OK;
   }
 
   // ConstrainSize operates in device pixels, so we need to convert using
   // the backing scale factor here
   CGFloat scale = BackingScaleFactor();
-  aWidth *= scale;
-  aHeight *= scale;
-  ConstrainSize(&aWidth, &aHeight);
-  aWidth = NSToIntRound(aWidth / scale);
-  aHeight = NSToIntRound(aHeight / scale);
-
-  nsIntRect newBounds(aX, aY, aWidth, aHeight);
+  int32_t width = NSToIntRound(aWidth * scale);
+  int32_t height = NSToIntRound(aHeight * scale);
+  ConstrainSize(&width, &height);
+
+  nsIntRect newBounds(aX, aY,
+                      NSToIntRound(width / scale),
+                      NSToIntRound(height / scale));
 
   // constrain to the screen that contains the largest area of the new rect
   FitRectToVisibleAreaForScreen(newBounds, aConstrainToCurrentScreen ?
                                            [mWindow screen] : nullptr);
 
   // convert requested bounds into Cocoa coordinate system
   NSRect newFrame = nsCocoaUtils::GeckoRectToCocoaRect(newBounds);
 
@@ -1353,29 +1353,28 @@ nsresult nsCocoaWindow::DoResize(int32_t
   [mWindow setFrame:newFrame display:YES];
 
   return NS_OK;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
 }
 
 // Coordinates are global display pixels
-NS_IMETHODIMP nsCocoaWindow::Resize(int32_t aX, int32_t aY,
-                                    int32_t aWidth, int32_t aHeight,
+NS_IMETHODIMP nsCocoaWindow::Resize(double aX, double aY,
+                                    double aWidth, double aHeight,
                                     bool aRepaint)
 {
   return DoResize(aX, aY, aWidth, aHeight, aRepaint, false);
 }
 
 // Coordinates are global display pixels
-NS_IMETHODIMP nsCocoaWindow::Resize(int32_t aWidth, int32_t aHeight, bool aRepaint)
+NS_IMETHODIMP nsCocoaWindow::Resize(double aWidth, double aHeight, bool aRepaint)
 {
   double invScale = 1.0 / GetDefaultScale();
-  return DoResize(NSToIntRound(mBounds.x * invScale),
-                  NSToIntRound(mBounds.y * invScale),
+  return DoResize(mBounds.x * invScale, mBounds.y * invScale,
                   aWidth, aHeight, aRepaint, true);
 }
 
 NS_IMETHODIMP nsCocoaWindow::GetClientBounds(nsIntRect &aRect)
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_NSRESULT;
 
   CGFloat scaleFactor = BackingScaleFactor();
--- a/widget/gonk/nsWindow.cpp
+++ b/widget/gonk/nsWindow.cpp
@@ -368,40 +368,41 @@ NS_IMETHODIMP
 nsWindow::ConstrainPosition(bool aAllowSlop,
                             int32_t *aX,
                             int32_t *aY)
 {
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsWindow::Move(int32_t aX,
-               int32_t aY)
+nsWindow::Move(double aX,
+               double aY)
 {
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsWindow::Resize(int32_t aWidth,
-                 int32_t aHeight,
-                 bool    aRepaint)
+nsWindow::Resize(double aWidth,
+                 double aHeight,
+                 bool   aRepaint)
 {
     return Resize(0, 0, aWidth, aHeight, aRepaint);
 }
 
 NS_IMETHODIMP
-nsWindow::Resize(int32_t aX,
-                 int32_t aY,
-                 int32_t aWidth,
-                 int32_t aHeight,
-                 bool    aRepaint)
+nsWindow::Resize(double aX,
+                 double aY,
+                 double aWidth,
+                 double aHeight,
+                 bool   aRepaint)
 {
-    mBounds = nsIntRect(aX, aY, aWidth, aHeight);
+    mBounds = nsIntRect(NSToIntRound(aX), NSToIntRound(aY),
+                        NSToIntRound(aWidth), NSToIntRound(aHeight));
     if (mWidgetListener)
-        mWidgetListener->WindowResized(this, aWidth, aHeight);
+        mWidgetListener->WindowResized(this, mBounds.width, mBounds.height);
 
     if (aRepaint && gWindowToRedraw)
         gWindowToRedraw->Invalidate(sVirtualBounds);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
--- a/widget/gonk/nsWindow.h
+++ b/widget/gonk/nsWindow.h
@@ -56,25 +56,25 @@ public:
                       nsWidgetInitData *aInitData);
     NS_IMETHOD Destroy(void);
 
     NS_IMETHOD Show(bool aState);
     virtual bool IsVisible() const;
     NS_IMETHOD ConstrainPosition(bool aAllowSlop,
                                  int32_t *aX,
                                  int32_t *aY);
-    NS_IMETHOD Move(int32_t aX,
-                    int32_t aY);
-    NS_IMETHOD Resize(int32_t aWidth,
-                      int32_t aHeight,
+    NS_IMETHOD Move(double aX,
+                    double aY);
+    NS_IMETHOD Resize(double aWidth,
+                      double aHeight,
                       bool  aRepaint);
-    NS_IMETHOD Resize(int32_t aX,
-                      int32_t aY,
-                      int32_t aWidth,
-                      int32_t aHeight,
+    NS_IMETHOD Resize(double aX,
+                      double aY,
+                      double aWidth,
+                      double aHeight,
                       bool aRepaint);
     NS_IMETHOD Enable(bool aState);
     virtual bool IsEnabled() const;
     NS_IMETHOD SetFocus(bool aRaise = false);
     NS_IMETHOD ConfigureChildren(const nsTArray<nsIWidget::Configuration>&);
     NS_IMETHOD Invalidate(const nsIntRect &aRect);
     virtual void* GetNativeData(uint32_t aDataType);
     NS_IMETHOD SetTitle(const nsAString& aTitle)
--- a/widget/gtk2/nsWindow.cpp
+++ b/widget/gtk2/nsWindow.cpp
@@ -1007,25 +1007,27 @@ nsWindow::Show(bool aState)
 #endif
 
     NativeShow(aState);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsWindow::Resize(int32_t aWidth, int32_t aHeight, bool aRepaint)
-{
-    ConstrainSize(&aWidth, &aHeight);
+nsWindow::Resize(double aWidth, double aHeight, bool aRepaint)
+{
+    int32_t width = NSToIntRound(aWidth);
+    int32_t height = NSToIntRound(aHeight);
+    ConstrainSize(&width, &height);
 
     // For top-level windows, aWidth and aHeight should possibly be
     // interpreted as frame bounds, but NativeResize treats these as window
     // bounds (Bug 581866).
 
-    mBounds.SizeTo(aWidth, aHeight);
+    mBounds.SizeTo(width, height);
 
     if (!mCreated)
         return NS_OK;
 
     // There are several cases here that we need to handle, based on a
     // matrix of the visibility of the widget, the sanity of this resize
     // and whether or not the widget was previously sane.
 
@@ -1065,58 +1067,62 @@ nsWindow::Resize(int32_t aWidth, int32_t
     }
     // If the widget hasn't been shown, mark the widget as needing to be
     // resized before it is shown.
     else {
         if (AreBoundsSane() && mListenForResizes) {
             // For widgets that we listen for resizes for (widgets created
             // with native parents) we apparently _always_ have to resize.  I
             // dunno why, but apparently we're lame like that.
-            NativeResize(aWidth, aHeight, aRepaint);
+            NativeResize(width, height, aRepaint);
         }
         else {
             mNeedsResize = true;
         }
     }
 
     NotifyRollupGeometryChange();
 
     // send a resize notification if this is a toplevel
     if (mIsTopLevel || mListenForResizes) {
-        DispatchResized(aWidth, aHeight);
+        DispatchResized(width, height);
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsWindow::Resize(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight,
-                       bool aRepaint)
-{
-    ConstrainSize(&aWidth, &aHeight);
-
-    mBounds.x = aX;
-    mBounds.y = aY;
-    mBounds.SizeTo(aWidth, aHeight);
+nsWindow::Resize(double aX, double aY, double aWidth, double aHeight,
+                 bool aRepaint)
+{
+    int32_t width = NSToIntRound(aWidth);
+    int32_t height = NSToIntRound(aHeight);
+    ConstrainSize(&width, &height);
+
+    int32_t x = NSToIntRound(aX);
+    int32_t y = NSToIntRound(aY);
+    mBounds.x = x;
+    mBounds.y = y;
+    mBounds.SizeTo(width, height);
 
     mNeedsMove = true;
 
     if (!mCreated)
         return NS_OK;
 
     // There are several cases here that we need to handle, based on a
     // matrix of the visibility of the widget, the sanity of this resize
     // and whether or not the widget was previously sane.
 
     // Has this widget been set to visible?
     if (mIsShown) {
         // Are the bounds sane?
         if (AreBoundsSane()) {
             // Yep?  Resize the window
-            NativeResize(aX, aY, aWidth, aHeight, aRepaint);
+            NativeResize(x, y, width, height, aRepaint);
             // Does it need to be shown because it was previously insane?
             if (mNeedsShow)
                 NativeShow(true);
         }
         else {
             // If someone has set this so that the needs show flag is false
             // and it needs to be hidden, update the flag and hide the
             // window.  This flag will be cleared the next time someone
@@ -1131,27 +1137,27 @@ nsWindow::Resize(int32_t aX, int32_t aY,
     }
     // If the widget hasn't been shown, mark the widget as needing to be
     // resized before it is shown
     else {
         if (AreBoundsSane() && mListenForResizes){
             // For widgets that we listen for resizes for (widgets created
             // with native parents) we apparently _always_ have to resize.  I
             // dunno why, but apparently we're lame like that.
-            NativeResize(aX, aY, aWidth, aHeight, aRepaint);
+            NativeResize(x, y, width, height, aRepaint);
         }
         else {
             mNeedsResize = true;
         }
     }
 
     NotifyRollupGeometryChange();
 
     if (mIsTopLevel || mListenForResizes) {
-        DispatchResized(aWidth, aHeight);
+        DispatchResized(width, height);
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWindow::Enable(bool aState)
 {
@@ -1164,48 +1170,51 @@ bool
 nsWindow::IsEnabled() const
 {
     return mEnabled;
 }
 
 
 
 NS_IMETHODIMP
-nsWindow::Move(int32_t aX, int32_t aY)
-{
-    LOG(("nsWindow::Move [%p] %d %d\n", (void *)this,
+nsWindow::Move(double aX, double aY)
+{
+    LOG(("nsWindow::Move [%p] %f %f\n", (void *)this,
          aX, aY));
 
+    int32_t x = NSToIntRound(aX);
+    int32_t y = NSToIntRound(aY);
+
     if (mWindowType == eWindowType_toplevel ||
         mWindowType == eWindowType_dialog) {
         SetSizeMode(nsSizeMode_Normal);
     }
 
     // Since a popup window's x/y coordinates are in relation to to
     // the parent, the parent might have moved so we always move a
     // popup window.
-    if (aX == mBounds.x && aY == mBounds.y &&
+    if (x == mBounds.x && y == mBounds.y &&
         mWindowType != eWindowType_popup)
         return NS_OK;
 
     // XXX Should we do some AreBoundsSane check here?
 
-    mBounds.x = aX;
-    mBounds.y = aY;
+    mBounds.x = x;
+    mBounds.y = y;
 
     if (!mCreated)
         return NS_OK;
 
     mNeedsMove = false;
 
     if (mIsTopLevel) {
-        gtk_window_move(GTK_WINDOW(mShell), aX, aY);
+        gtk_window_move(GTK_WINDOW(mShell), x, y);
     }
     else if (mGdkWindow) {
-        gdk_window_move(mGdkWindow, aX, aY);
+        gdk_window_move(mGdkWindow, x, y);
     }
 
     NotifyRollupGeometryChange();
     return NS_OK;
 }
 
 NS_IMETHODIMP
 nsWindow::PlaceBehind(nsTopLevelWidgetZPlacement  aPlacement,
--- a/widget/gtk2/nsWindow.h
+++ b/widget/gtk2/nsWindow.h
@@ -101,27 +101,27 @@ public:
     virtual float      GetDPI();
     virtual nsresult   SetParent(nsIWidget* aNewParent);
     NS_IMETHOD         SetModal(bool aModal);
     virtual bool       IsVisible() const;
     NS_IMETHOD         ConstrainPosition(bool aAllowSlop,
                                          int32_t *aX,
                                          int32_t *aY);
     virtual void       SetSizeConstraints(const SizeConstraints& aConstraints);
-    NS_IMETHOD         Move(int32_t aX,
-                            int32_t aY);
+    NS_IMETHOD         Move(double aX,
+                            double aY);
     NS_IMETHOD         Show             (bool aState);
-    NS_IMETHOD         Resize           (int32_t aWidth,
-                                         int32_t aHeight,
-                                         bool    aRepaint);
-    NS_IMETHOD         Resize           (int32_t aX,
-                                         int32_t aY,
-                                         int32_t aWidth,
-                                         int32_t aHeight,
-                                         bool     aRepaint);
+    NS_IMETHOD         Resize           (double aWidth,
+                                         double aHeight,
+                                         bool   aRepaint);
+    NS_IMETHOD         Resize           (double aX,
+                                         double aY,
+                                         double aWidth,
+                                         double aHeight,
+                                         bool   aRepaint);
     virtual bool       IsEnabled() const;
 
 
     NS_IMETHOD         PlaceBehind(nsTopLevelWidgetZPlacement  aPlacement,
                                    nsIWidget                  *aWidget,
                                    bool                        aActivate);
     NS_IMETHOD         SetZIndex(int32_t aZIndex);
     NS_IMETHOD         SetSizeMode(int32_t aMode);
--- a/widget/nsIWidget.h
+++ b/widget/nsIWidget.h
@@ -87,18 +87,18 @@ typedef nsEventStatus (* EVENT_CALLBACK)
 #ifdef XP_WIN
 #define NS_NATIVE_TSF_THREAD_MGR       100
 #define NS_NATIVE_TSF_CATEGORY_MGR     101
 #define NS_NATIVE_TSF_DISPLAY_ATTR_MGR 102
 #define NS_NATIVE_ICOREWINDOW          103 // winrt specific
 #endif
 
 #define NS_IWIDGET_IID \
-  { 0xdb9b0931, 0xebf9, 0x4e0d, \
-    { 0xb2, 0x0a, 0xf7, 0x5f, 0xcb, 0x17, 0xe6, 0xe1 } }
+  { 0x476D5716, 0xE225, 0x4497, \
+    { 0x80, 0x41, 0x92, 0xF8, 0x67, 0x59, 0xC4, 0x38 } }
 
 /*
  * Window shadow styles
  * Also used for the -moz-window-shadow CSS property
  */
 
 #define NS_STYLE_WINDOW_SHADOW_NONE             0
 #define NS_STYLE_WINDOW_SHADOW_DEFAULT          1
@@ -692,88 +692,94 @@ class nsIWidget : public nsISupports {
      * NOTE:
      *
      * For a top-level window widget, the "parent's coordinate system" is the
      * "global" display pixel coordinate space, *not* device pixels (which
      * may be inconsistent between multiple screens, at least in the Mac OS
      * case with mixed hi-dpi and lo-dpi displays). This applies to all the
      * following Move and Resize widget APIs.
      *
-     * Currently, only Mac OS X implements a display-/device-pixel distinction;
-     * this may change in future, however.
+     * The display-/device-pixel distinction becomes important for (at least)
+     * Mac OS X with Hi-DPI (retina) displays, and Windows when the UI scale
+     * factor is set to other than 100%.
+     *
+     * The Move and Resize methods take floating-point parameters, rather than
+     * integer ones. This is important when manipulating top-level widgets,
+     * where the coordinate system may not be an integral multiple of the
+     * device-pixel space.
      **/
 
     /**
      * Move this widget.
      *
      * Coordinates refer to the top-left of the widget.  For toplevel windows
      * with decorations, this is the top-left of the titlebar and frame .
      *
      * @param aX the new x position expressed in the parent's coordinate system
      * @param aY the new y position expressed in the parent's coordinate system
      *
      **/
-    NS_IMETHOD Move(int32_t aX, int32_t aY) = 0;
+    NS_IMETHOD Move(double aX, double aY) = 0;
 
     /**
      * Reposition this widget so that the client area has the given offset.
      *
      * @param aX       the new x offset of the client area expressed as an
      *                 offset from the origin of the client area of the parent
      *                 widget (for root widgets and popup widgets it is in
      *                 screen coordinates)
      * @param aY       the new y offset of the client area expressed as an
      *                 offset from the origin of the client area of the parent
      *                 widget (for root widgets and popup widgets it is in
      *                 screen coordinates)
      *
      **/
-    NS_IMETHOD MoveClient(int32_t aX, int32_t aY) = 0;
+    NS_IMETHOD MoveClient(double aX, double aY) = 0;
 
     /**
      * Resize this widget. Any size constraints set for the window by a
      * previous call to SetSizeConstraints will be applied.
      *
      * @param aWidth  the new width expressed in the parent's coordinate system
      * @param aHeight the new height expressed in the parent's coordinate system
      * @param aRepaint whether the widget should be repainted
      *
      */
-    NS_IMETHOD Resize(int32_t aWidth,
-                      int32_t aHeight,
-                      bool     aRepaint) = 0;
+    NS_IMETHOD Resize(double aWidth,
+                      double aHeight,
+                      bool   aRepaint) = 0;
 
     /**
      * Move or resize this widget. Any size constraints set for the window by
      * a previous call to SetSizeConstraints will be applied.
      *
      * @param aX       the new x position expressed in the parent's coordinate system
      * @param aY       the new y position expressed in the parent's coordinate system
      * @param aWidth   the new width expressed in the parent's coordinate system
      * @param aHeight  the new height expressed in the parent's coordinate system
      * @param aRepaint whether the widget should be repainted if the size changes
      *
      */
-    NS_IMETHOD Resize(int32_t aX,
-                      int32_t aY,
-                      int32_t aWidth,
-                      int32_t aHeight,
-                      bool     aRepaint) = 0;
+    NS_IMETHOD Resize(double aX,
+                      double aY,
+                      double aWidth,
+                      double aHeight,
+                      bool   aRepaint) = 0;
 
     /**
      * Resize the widget so that the inner client area has the given size.
      *
      * @param aWidth   the new width of the client area.
      * @param aHeight  the new height of the client area.
      * @param aRepaint whether the widget should be repainted
      *
      */
-    NS_IMETHOD ResizeClient(int32_t aWidth,
-                            int32_t aHeight,
-                            bool  aRepaint) = 0;
+    NS_IMETHOD ResizeClient(double aWidth,
+                            double aHeight,
+                            bool   aRepaint) = 0;
 
     /**
      * Resize and reposition the widget so tht inner client area has the given
      * offset and size.
      *
      * @param aX       the new x offset of the client area expressed as an
      *                 offset from the origin of the client area of the parent
      *                 widget (for root widgets and popup widgets it is in
@@ -782,21 +788,21 @@ class nsIWidget : public nsISupports {
      *                 offset from the origin of the client area of the parent
      *                 widget (for root widgets and popup widgets it is in
      *                 screen coordinates)
      * @param aWidth   the new width of the client area.
      * @param aHeight  the new height of the client area.
      * @param aRepaint whether the widget should be repainted
      *
      */
-    NS_IMETHOD ResizeClient(int32_t aX,
-                            int32_t aY,
-                            int32_t aWidth,
-                            int32_t aHeight,
-                            bool    aRepaint) = 0;
+    NS_IMETHOD ResizeClient(double aX,
+                            double aY,
+                            double aWidth,
+                            double aHeight,
+                            bool   aRepaint) = 0;
 
     /**
      * Sets the widget's z-index.
      */
     NS_IMETHOD SetZIndex(int32_t aZIndex) = 0;
 
     /**
      * Gets the widget's z-index. 
--- a/widget/os2/nsWindow.cpp
+++ b/widget/os2/nsWindow.cpp
@@ -798,81 +798,87 @@ void nsWindow::NS2PM_PARENT(POINTL& ptl)
     SWP  swp;
     WinQueryWindowPos(hParent, &swp);
     ptl.y = swp.cy - ptl.y - 1;
   }
 }
 
 //-----------------------------------------------------------------------------
 
-NS_METHOD nsWindow::Move(int32_t aX, int32_t aY)
+NS_METHOD nsWindow::Move(double aX, double aY)
 {
   if (mFrame) {
-    nsresult rv = mFrame->Move(aX, aY);
+    nsresult rv = mFrame->Move(NSToIntRound(aX), NSToIntRound(aY));
     NotifyRollupGeometryChange();
     return rv;
   }
   Resize(aX, aY, mBounds.width, mBounds.height, false);
   return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 
-NS_METHOD nsWindow::Resize(int32_t aWidth, int32_t aHeight, bool aRepaint)
+NS_METHOD nsWindow::Resize(double aWidth, double aHeight, bool aRepaint)
 {
   if (mFrame) {
-    nsresult rv = mFrame->Resize(aWidth, aHeight, aRepaint);
+    nsresult rv = mFrame->Resize(NSToIntRound(aWidth), NSToIntRound(aHeight),
+                                 aRepaint);
     NotifyRollupGeometryChange();
     return rv;
   }
   Resize(mBounds.x, mBounds.y, aWidth, aHeight, aRepaint);
   return NS_OK;
 }
 
 //-----------------------------------------------------------------------------
 
-NS_METHOD nsWindow::Resize(int32_t aX, int32_t aY,
-                           int32_t aWidth, int32_t aHeight, bool aRepaint)
+NS_METHOD nsWindow::Resize(double aX, double aY,
+                           double aWidth, double aHeight, bool aRepaint)
 {
+  int32_t x = NSToIntRound(aX);
+  int32_t y = NSToIntRound(aY);
+  int32_t width = NSToIntRound(aWidth);
+  int32_t height = NSToIntRound(aHeight);
+
   if (mFrame) {
-    nsresult rv = mFrame->Resize(aX, aY, aWidth, aHeight, aRepaint);
+    nsresult rv = mFrame->Resize(x, y, width, height, aRepaint);
     NotifyRollupGeometryChange();
     return rv;
   }
 
   // For mWnd & eWindowType_child set the cached values upfront, see bug 286555.
   // For other mWnd types we defer transfer of values to mBounds to
   // WinSetWindowPos(), see bug 391421.
 
   if (!mWnd ||
       mWindowType == eWindowType_child ||
       mWindowType == eWindowType_plugin) {
-    mBounds.x      = aX;
-    mBounds.y      = aY;
-    mBounds.width  = aWidth;
-    mBounds.height = aHeight;
+    mBounds.x      = x;
+    mBounds.y      = y;
+    mBounds.width  = width;
+    mBounds.height = height;
   }
 
   // To keep top-left corner in the same place, use the new height
   // to calculate the coordinates for the top & bottom left corners.
   if (mWnd) {
-    POINTL ptl = { aX, aY };
+    POINTL ptl = { x, y };
     NS2PM_PARENT(ptl);
-    ptl.y -= aHeight - 1;
+    ptl.y -= height - 1;
 
     // For popups, aX already gives the correct position.
     if (mWindowType == eWindowType_popup) {
-      ptl.y = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN) - aHeight - 1 - aY;
+      ptl.y = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN) - height - 1 - y;
     }
     else if (mParent) {
       WinMapWindowPoints(mParent->mWnd, WinQueryWindow(mWnd, QW_PARENT),
                          &ptl, 1);
     }
 
-    if (!WinSetWindowPos(mWnd, 0, ptl.x, ptl.y, aWidth, aHeight,
+    if (!WinSetWindowPos(mWnd, 0, ptl.x, ptl.y, width, height,
                          SWP_MOVE | SWP_SIZE) && aRepaint) {
       WinInvalidateRect(mWnd, 0, FALSE);
     }
   }
 
   NotifyRollupGeometryChange();
   return NS_OK;
 }
--- a/widget/os2/nsWindow.h
+++ b/widget/os2/nsWindow.h
@@ -146,21 +146,21 @@ public:
   gfxASurface*          GetThebesSurface();
   virtual void*         GetNativeData(uint32_t aDataType);
   virtual void          FreeNativeData(void* aDatum, uint32_t aDataType);
   NS_IMETHOD            CaptureMouse(bool aCapture);
   virtual bool          HasPendingInputEvent();
   NS_IMETHOD            GetBounds(nsIntRect& aRect);
   NS_IMETHOD            GetClientBounds(nsIntRect& aRect);
   virtual nsIntPoint    WidgetToScreenOffset();
-  NS_IMETHOD            Move(int32_t aX, int32_t aY);
-  NS_IMETHOD            Resize(int32_t aWidth, int32_t aHeight,
+  NS_IMETHOD            Move(double aX, double aY);
+  NS_IMETHOD            Resize(double aWidth, double aHeight,
                                bool    aRepaint);
-  NS_IMETHOD            Resize(int32_t aX, int32_t aY,
-                               int32_t aWidth, int32_t aHeight,
+  NS_IMETHOD            Resize(double aX, double aY,
+                               double aWidth, double aHeight,
                                bool    aRepaint);
   NS_IMETHOD            PlaceBehind(nsTopLevelWidgetZPlacement aPlacement,
                                     nsIWidget* aWidget, bool aActivate);
   NS_IMETHOD            SetZIndex(int32_t aZIndex);
   virtual nsresult      ConfigureChildren(const nsTArray<Configuration>& aConfigurations);
   NS_IMETHOD            SetSizeMode(int32_t aMode);
   NS_IMETHOD            HideWindowChrome(bool aShouldHide);
   NS_IMETHOD            SetTitle(const nsAString& aTitle); 
--- a/widget/qt/nsWindow.cpp
+++ b/widget/qt/nsWindow.cpp
@@ -540,36 +540,39 @@ nsWindow::ConstrainPosition(bool aAllowS
                 *aY = screenHeight - mBounds.height;
         }
     }
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsWindow::Move(int32_t aX, int32_t aY)
+nsWindow::Move(double aX, double aY)
 {
-    LOG(("nsWindow::Move [%p] %d %d\n", (void *)this,
+    LOG(("nsWindow::Move [%p] %f %f\n", (void *)this,
          aX, aY));
 
+    int32_t x = NSToIntRound(aX);
+    int32_t y = NSToIntRound(aY);
+
     if (mIsTopLevel) {
         SetSizeMode(nsSizeMode_Normal);
     }
 
-    if (aX == mBounds.x && aY == mBounds.y)
+    if (x == mBounds.x && y == mBounds.y)
         return NS_OK;
 
     mNeedsMove = false;
 
     // update the bounds
-    QPointF pos( aX, aY );
+    QPointF pos( x, y );
     if (mIsTopLevel) {
         QWidget *widget = GetViewWidget();
         NS_ENSURE_TRUE(widget, NS_OK);
-        widget->move(aX, aY);
+        widget->move(x, y);
     }
     else if (mWidget) {
         // the position of the widget is set relative to the parent
         // so we map the coordinates accordingly
         pos = mWidget->mapFromScene(pos);
         pos = mWidget->mapToParent(pos);
         mWidget->setPos(pos);
     }
@@ -2947,20 +2950,20 @@ nsWindow::Show(bool aState)
         mNeedsShow = false;
 
     NativeShow(aState);
 
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsWindow::Resize(int32_t aWidth, int32_t aHeight, bool aRepaint)
+nsWindow::Resize(double aWidth, int32_t double, bool aRepaint)
 {
-    mBounds.width = aWidth;
-    mBounds.height = aHeight;
+    mBounds.width = NSToIntRound(aWidth);
+    mBounds.height = NSToIntRound(aHeight);
 
     if (!mWidget)
         return NS_OK;
 
     if (mIsShown) {
         if (AreBoundsSane()) {
             if (mIsTopLevel || mNeedsShow)
                 NativeResize(mBounds.x, mBounds.y,
@@ -2984,53 +2987,53 @@ nsWindow::Resize(int32_t aWidth, int32_t
                 NativeShow(false);
             }
         }
     }
     else if (AreBoundsSane() && mListenForResizes) {
         // For widgets that we listen for resizes for (widgets created
         // with native parents) we apparently _always_ have to resize.  I
         // dunno why, but apparently we're lame like that.
-        NativeResize(aWidth, aHeight, aRepaint);
+        NativeResize(mBounds.width, mBounds.height, aRepaint);
     }
     else {
         mNeedsResize = true;
     }
 
     // synthesize a resize event if this isn't a toplevel
     if (mIsTopLevel || mListenForResizes) {
-        nsIntRect rect(mBounds.x, mBounds.y, aWidth, aHeight);
         nsEventStatus status;
-        DispatchResizeEvent(rect, status);
+        DispatchResizeEvent(mBounds, status);
     }
 
     NotifyRollupGeometryChange();
     return NS_OK;
 }
 
 NS_IMETHODIMP
-nsWindow::Resize(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight,
+nsWindow::Resize(double aX, double aY, double aWidth, double aHeight,
                  bool aRepaint)
 {
-    mBounds.x = aX;
-    mBounds.y = aY;
-    mBounds.width = aWidth;
-    mBounds.height = aHeight;
+    mBounds.x = NSToIntRound(aX);
+    mBounds.y = NSToIntRound(aY);
+    mBounds.width = NSToIntRound(aWidth);
+    mBounds.height = NSToIntRound(aHeight);
 
     mPlaced = true;
 
     if (!mWidget)
         return NS_OK;
 
     // Has this widget been set to visible?
     if (mIsShown) {
         // Are the bounds sane?
         if (AreBoundsSane()) {
             // Yep?  Resize the window
-            NativeResize(aX, aY, aWidth, aHeight, aRepaint);
+            NativeResize(mBounds.x, mBounds.y, mBounds.width, mBounds.height,
+                         aRepaint);
             // Does it need to be shown because it was previously insane?
             if (mNeedsShow)
                 NativeShow(true);
         }
         else {
             // If someone has set this so that the needs show flag is false
             // and it needs to be hidden, update the flag and hide the
             // window.  This flag will be cleared the next time someone
@@ -3044,28 +3047,28 @@ nsWindow::Resize(int32_t aX, int32_t aY,
         }
     }
     // If the widget hasn't been shown, mark the widget as needing to be
     // resized before it is shown
     else if (AreBoundsSane() && mListenForResizes) {
         // For widgets that we listen for resizes for (widgets created
         // with native parents) we apparently _always_ have to resize.  I
         // dunno why, but apparently we're lame like that.
-        NativeResize(aX, aY, aWidth, aHeight, aRepaint);
+        NativeResize(mBounds.x, mBounds.y, mBounds.width, mBounds.height,
+                     aRepaint);
     }
     else {
         mNeedsResize = true;
         mNeedsMove = true;
     }
 
     if (mIsTopLevel || mListenForResizes) {
         // synthesize a resize event
-        nsIntRect rect(aX, aY, aWidth, aHeight);
         nsEventStatus status;
-        DispatchResizeEvent(rect, status);
+        DispatchResizeEvent(mBounds, status);
     }
 
     if (aRepaint)
         mWidget->update();
 
     NotifyRollupGeometryChange();
     return NS_OK;
 }
--- a/widget/qt/nsWindow.h
+++ b/widget/qt/nsWindow.h
@@ -111,26 +111,26 @@ public:
     virtual nsIWidget *GetParent(void);
     virtual float      GetDPI();
     NS_IMETHOD         Show(bool aState);
     NS_IMETHOD         SetModal(bool aModal);
     virtual bool       IsVisible() const;
     NS_IMETHOD         ConstrainPosition(bool aAllowSlop,
                                          int32_t *aX,
                                          int32_t *aY);
-    NS_IMETHOD         Move(int32_t aX,
-                            int32_t aY);
-    NS_IMETHOD         Resize(int32_t aWidth,
-                              int32_t aHeight,
-                              bool    aRepaint);
-    NS_IMETHOD         Resize(int32_t aX,
-                              int32_t aY,
-                              int32_t aWidth,
-                              int32_t aHeight,
-                              bool     aRepaint);
+    NS_IMETHOD         Move(double aX,
+                            double aY);
+    NS_IMETHOD         Resize(double aWidth,
+                              double aHeight,
+                              bool   aRepaint);
+    NS_IMETHOD         Resize(double aX,
+                              double aY,
+                              double aWidth,
+                              double aHeight,
+                              bool   aRepaint);
     NS_IMETHOD         PlaceBehind(nsTopLevelWidgetZPlacement  aPlacement,
                                    nsIWidget                  *aWidget,
                                    bool                        aActivate);
     NS_IMETHOD         SetSizeMode(int32_t aMode);
     NS_IMETHOD         Enable(bool aState);
     NS_IMETHOD         SetFocus(bool aRaise = false);
     NS_IMETHOD         GetScreenBounds(nsIntRect &aRect);
     NS_IMETHOD         SetForegroundColor(const nscolor &aColor);
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -1317,17 +1317,17 @@ nsWindow::SetSizeConstraints(const SizeC
     c.mMinSize.width = NS_MAX(int32_t(::GetSystemMetrics(SM_CXMINTRACK)), c.mMinSize.width);
     c.mMinSize.height = NS_MAX(int32_t(::GetSystemMetrics(SM_CYMINTRACK)), c.mMinSize.height);
   }
 
   nsBaseWidget::SetSizeConstraints(c);
 }
 
 // Move this component
-NS_METHOD nsWindow::Move(int32_t aX, int32_t aY)
+NS_METHOD nsWindow::Move(double aX, double aY)
 {
   if (mWindowType == eWindowType_toplevel ||
       mWindowType == eWindowType_dialog) {
     SetSizeMode(nsSizeMode_Normal);
   }
   // Check to see if window needs to be moved first
   // to avoid a costly call to SetWindowPos. This check
   // can not be moved to the calling code in nsView, because
@@ -1337,32 +1337,35 @@ NS_METHOD nsWindow::Move(int32_t aX, int
   // in fact change even when the x/y do not.  We always need to perform the
   // check. See bug #97805 for details.
   if (mWindowType != eWindowType_popup && (mBounds.x == aX) && (mBounds.y == aY))
   {
     // Nothing to do, since it is already positioned correctly.
     return NS_OK;
   }
 
-  mBounds.x = aX;
-  mBounds.y = aY;
+  int32_t x = NSToIntRound(aX * GetDefaultScale());
+  int32_t y = NSToIntRound(aY * GetDefaultScale());
+
+  mBounds.x = x;
+  mBounds.y = y;
 
   if (mWnd) {
 #ifdef DEBUG
     // complain if a window is moved offscreen (legal, but potentially worrisome)
     if (mIsTopWidgetWindow) { // only a problem for top-level windows
       // Make sure this window is actually on the screen before we move it
       // XXX: Needs multiple monitor support
       HDC dc = ::GetDC(mWnd);
       if (dc) {
         if (::GetDeviceCaps(dc, TECHNOLOGY) == DT_RASDISPLAY) {
           RECT workArea;
           ::SystemParametersInfo(SPI_GETWORKAREA, 0, &workArea, 0);
           // no annoying assertions. just mention the issue.
-          if (aX < 0 || aX >= workArea.right || aY < 0 || aY >= workArea.bottom) {
+          if (x < 0 || x >= workArea.right || y < 0 || y >= workArea.bottom) {
             PR_LOG(gWindowsLog, PR_LOG_ALWAYS,
                    ("window moved to offscreen position\n"));
           }
         }
       ::ReleaseDC(mWnd, dc);
       }
     }
 #endif
@@ -1373,102 +1376,113 @@ NS_METHOD nsWindow::Move(int32_t aX, int
     // region, some drivers or OSes may incorrectly copy into the clipped-out
     // area.
     if (mWindowType == eWindowType_plugin &&
         (!mLayerManager || mLayerManager->GetBackendType() == LAYERS_D3D9) &&
         mClipRects &&
         (mClipRectCount != 1 || !mClipRects[0].IsEqualInterior(nsIntRect(0, 0, mBounds.width, mBounds.height)))) {
       flags |= SWP_NOCOPYBITS;
     }
-    VERIFY(::SetWindowPos(mWnd, NULL, aX, aY, 0, 0, flags));
+    VERIFY(::SetWindowPos(mWnd, NULL, x, y, 0, 0, flags));
 
     SetThemeRegion();
   }
   NotifyRollupGeometryChange();
   return NS_OK;
 }
 
 // Resize this component
-NS_METHOD nsWindow::Resize(int32_t aWidth, int32_t aHeight, bool aRepaint)
-{
-  NS_ASSERTION((aWidth >=0 ) , "Negative width passed to nsWindow::Resize");
-  NS_ASSERTION((aHeight >=0 ), "Negative height passed to nsWindow::Resize");
-  ConstrainSize(&aWidth, &aHeight);
+NS_METHOD nsWindow::Resize(double aWidth, double aHeight, bool aRepaint)
+{
+  int32_t width = NSToIntRound(aWidth * GetDefaultScale());
+  int32_t height = NSToIntRound(aHeight * GetDefaultScale());
+
+  NS_ASSERTION((width >= 0) , "Negative width passed to nsWindow::Resize");
+  NS_ASSERTION((height >= 0), "Negative height passed to nsWindow::Resize");
+
+  ConstrainSize(&width, &height);
 
   // Avoid unnecessary resizing calls
-  if (mBounds.width == aWidth && mBounds.height == aHeight) {
+  if (mBounds.width == width && mBounds.height == height) {
     if (aRepaint) {
       Invalidate();
     }
     return NS_OK;
   }
 
 #ifdef MOZ_XUL
   if (eTransparencyTransparent == mTransparencyMode)
-    ResizeTranslucentWindow(aWidth, aHeight);
+    ResizeTranslucentWindow(width, height);
 #endif
 
   // Set cached value for lightweight and printing
-  mBounds.width  = aWidth;
-  mBounds.height = aHeight;
+  mBounds.width  = width;
+  mBounds.height = height;
 
   if (mWnd) {
     UINT  flags = SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOMOVE;
 
     if (!aRepaint) {
       flags |= SWP_NOREDRAW;
     }
 
     ClearThemeRegion();
-    VERIFY(::SetWindowPos(mWnd, NULL, 0, 0, aWidth, GetHeight(aHeight), flags));
+    VERIFY(::SetWindowPos(mWnd, NULL, 0, 0, width, GetHeight(height), flags));
     SetThemeRegion();
   }
 
   if (aRepaint)
     Invalidate();
 
   NotifyRollupGeometryChange();
   return NS_OK;
 }
 
 // Resize this component
-NS_METHOD nsWindow::Resize(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight, bool aRepaint)
-{
-  NS_ASSERTION((aWidth >=0 ),  "Negative width passed to nsWindow::Resize");
-  NS_ASSERTION((aHeight >=0 ), "Negative height passed to nsWindow::Resize");
-  ConstrainSize(&aWidth, &aHeight);
+NS_METHOD nsWindow::Resize(double aX, double aY, double aWidth, double aHeight, bool aRepaint)
+{
+  double scale = GetDefaultScale();
+  int32_t x = NSToIntRound(aX * scale);
+  int32_t y = NSToIntRound(aY * scale);
+  int32_t width = NSToIntRound(aWidth * scale);
+  int32_t height = NSToIntRound(aHeight * scale);
+
+  NS_ASSERTION((width >= 0),  "Negative width passed to nsWindow::Resize");
+  NS_ASSERTION((height >= 0), "Negative height passed to nsWindow::Resize");
+
+  ConstrainSize(&width, &height);
 
   // Avoid unnecessary resizing calls
-  if (mBounds.x == aX && mBounds.y == aY &&
-      mBounds.width == aWidth && mBounds.height == aHeight) {
+  if (mBounds.x == x && mBounds.y == y &&
+      mBounds.width == width && mBounds.height == height) {
     if (aRepaint) {
       Invalidate();
     }
     return NS_OK;
   }
 
 #ifdef MOZ_XUL
   if (eTransparencyTransparent == mTransparencyMode)
-    ResizeTranslucentWindow(aWidth, aHeight);
+    ResizeTranslucentWindow(width, height);
 #endif
 
   // Set cached value for lightweight and printing
-  mBounds.x      = aX;
-  mBounds.y      = aY;
-  mBounds.width  = aWidth;
-  mBounds.height = aHeight;
+  mBounds.x      = x;
+  mBounds.y      = y;
+  mBounds.width  = width;
+  mBounds.height = height;
 
   if (mWnd) {
     UINT  flags = SWP_NOZORDER | SWP_NOACTIVATE;
     if (!aRepaint) {
       flags |= SWP_NOREDRAW;
     }
 
     ClearThemeRegion();
-    VERIFY(::SetWindowPos(mWnd, NULL, aX, aY, aWidth, GetHeight(aHeight), flags));
+    VERIFY(::SetWindowPos(mWnd, NULL, x, y, width, GetHeight(height), flags));
     SetThemeRegion();
   }
 
   if (aRepaint)
     Invalidate();
 
   NotifyRollupGeometryChange();
   return NS_OK;
--- a/widget/windows/nsWindow.h
+++ b/widget/windows/nsWindow.h
@@ -90,19 +90,19 @@ public:
   NS_IMETHOD              SetParent(nsIWidget *aNewParent);
   virtual nsIWidget*      GetParent(void);
   virtual float           GetDPI();
   virtual double          GetDefaultScaleInternal();
   NS_IMETHOD              Show(bool bState);
   virtual bool            IsVisible() const;
   NS_IMETHOD              ConstrainPosition(bool aAllowSlop, int32_t *aX, int32_t *aY);
   virtual void            SetSizeConstraints(const SizeConstraints& aConstraints);
-  NS_IMETHOD              Move(int32_t aX, int32_t aY);
-  NS_IMETHOD              Resize(int32_t aWidth, int32_t aHeight, bool aRepaint);
-  NS_IMETHOD              Resize(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight, bool aRepaint);
+  NS_IMETHOD              Move(double aX, double aY);
+  NS_IMETHOD              Resize(double aWidth, double aHeight, bool aRepaint);
+  NS_IMETHOD              Resize(double aX, double aY, double aWidth, double aHeight, bool aRepaint);
   NS_IMETHOD              BeginResizeDrag(nsGUIEvent* aEvent, int32_t aHorizontal, int32_t aVertical);
   NS_IMETHOD              PlaceBehind(nsTopLevelWidgetZPlacement aPlacement, nsIWidget *aWidget, bool aActivate);
   NS_IMETHOD              SetSizeMode(int32_t aMode);
   NS_IMETHOD              Enable(bool aState);
   virtual bool            IsEnabled() const;
   NS_IMETHOD              SetFocus(bool aRaise);
   NS_IMETHOD              GetBounds(nsIntRect &aRect);
   NS_IMETHOD              GetScreenBounds(nsIntRect &aRect);
--- a/widget/xpwidgets/PuppetWidget.cpp
+++ b/widget/xpwidgets/PuppetWidget.cpp
@@ -174,22 +174,22 @@ PuppetWidget::Show(bool aState)
     Resize(mBounds.width, mBounds.height, false);
     Invalidate(mBounds);
   }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
-PuppetWidget::Resize(int32_t aWidth,
-                     int32_t aHeight,
-                     bool    aRepaint)
+PuppetWidget::Resize(double aWidth,
+                     double aHeight,
+                     bool   aRepaint)
 {
   nsIntRect oldBounds = mBounds;
-  mBounds.SizeTo(nsIntSize(aWidth, aHeight));
+  mBounds.SizeTo(nsIntSize(NSToIntRound(aWidth), NSToIntRound(aHeight)));
 
   if (mChild) {
     return mChild->Resize(aWidth, aHeight, aRepaint);
   }
 
   // XXX: roc says that |aRepaint| dictates whether or not to
   // invalidate the expanded area
   if (oldBounds.Size() < mBounds.Size() && aRepaint) {
--- a/widget/xpwidgets/PuppetWidget.h
+++ b/widget/xpwidgets/PuppetWidget.h
@@ -68,27 +68,27 @@ public:
   { return mVisible; }
 
   NS_IMETHOD ConstrainPosition(bool     /*ignored aAllowSlop*/,
                                int32_t* aX,
                                int32_t* aY)
   { *aX = kMaxDimension;  *aY = kMaxDimension;  return NS_OK; }
 
   // We're always at <0, 0>, and so ignore move requests.
-  NS_IMETHOD Move(int32_t aX, int32_t aY)
+  NS_IMETHOD Move(double aX, double aY)
   { return NS_OK; }
 
-  NS_IMETHOD Resize(int32_t aWidth,
-                    int32_t aHeight,
-                    bool    aRepaint);
-  NS_IMETHOD Resize(int32_t aX,
-                    int32_t aY,
-                    int32_t aWidth,
-                    int32_t aHeight,
-                    bool    aRepaint)
+  NS_IMETHOD Resize(double aWidth,
+                    double aHeight,
+                    bool   aRepaint);
+  NS_IMETHOD Resize(double aX,
+                    double aY,
+                    double aWidth,
+                    double aHeight,
+                    bool   aRepaint)
   // (we're always at <0, 0>)
   { return Resize(aWidth, aHeight, aRepaint); }
 
   // XXX/cjones: copying gtk behavior here; unclear what disabling a
   // widget is supposed to entail
   NS_IMETHOD Enable(bool aState)
   { mEnabled = aState;  return NS_OK; }
   virtual bool IsEnabled() const
--- a/widget/xpwidgets/nsBaseWidget.cpp
+++ b/widget/xpwidgets/nsBaseWidget.cpp
@@ -985,43 +985,43 @@ void nsBaseWidget::OnDestroy()
   NS_IF_RELEASE(mContext);
 }
 
 NS_METHOD nsBaseWidget::SetWindowClass(const nsAString& xulWinType)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
-NS_METHOD nsBaseWidget::MoveClient(int32_t aX, int32_t aY)
+NS_METHOD nsBaseWidget::MoveClient(double aX, double aY)
 {
   nsIntPoint clientOffset(GetClientOffset());
   aX -= clientOffset.x;
   aY -= clientOffset.y;
   return Move(aX, aY);
 }
 
-NS_METHOD nsBaseWidget::ResizeClient(int32_t aWidth,
-                                     int32_t aHeight,
+NS_METHOD nsBaseWidget::ResizeClient(double aWidth,
+                                     double aHeight,
                                      bool aRepaint)
 {
   NS_ASSERTION((aWidth >=0) , "Negative width passed to ResizeClient");
   NS_ASSERTION((aHeight >=0), "Negative height passed to ResizeClient");
 
   nsIntRect clientBounds;
   GetClientBounds(clientBounds);
   aWidth = mBounds.width + (aWidth - clientBounds.width);
   aHeight = mBounds.height + (aHeight - clientBounds.height);
 
   return Resize(aWidth, aHeight, aRepaint);
 }
 
-NS_METHOD nsBaseWidget::ResizeClient(int32_t aX,
-                                     int32_t aY,
-                                     int32_t aWidth,
-                                     int32_t aHeight,
+NS_METHOD nsBaseWidget::ResizeClient(double aX,
+                                     double aY,
+                                     double aWidth,
+                                     double aHeight,
                                      bool aRepaint)
 {
   NS_ASSERTION((aWidth >=0) , "Negative width passed to ResizeClient");
   NS_ASSERTION((aHeight >=0), "Negative height passed to ResizeClient");
 
   nsIntRect clientBounds;
   GetClientBounds(clientBounds);
   aWidth = mBounds.width + (aWidth - clientBounds.width);
--- a/widget/xpwidgets/nsBaseWidget.h
+++ b/widget/xpwidgets/nsBaseWidget.h
@@ -111,19 +111,19 @@ public:
 
   virtual void            CreateCompositor();
   virtual void            DrawWindowUnderlay(LayerManager* aManager, nsIntRect aRect) {}
   virtual void            DrawWindowOverlay(LayerManager* aManager, nsIntRect aRect) {}
   virtual void            UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) {}
   virtual gfxASurface*    GetThebesSurface();
   NS_IMETHOD              SetModal(bool aModal); 
   NS_IMETHOD              SetWindowClass(const nsAString& xulWinType);
-  NS_IMETHOD              MoveClient(int32_t aX, int32_t aY);
-  NS_IMETHOD              ResizeClient(int32_t aWidth, int32_t aHeight, bool aRepaint);
-  NS_IMETHOD              ResizeClient(int32_t aX, int32_t aY, int32_t aWidth, int32_t aHeight, bool aRepaint);
+  NS_IMETHOD              MoveClient(double aX, double aY);
+  NS_IMETHOD              ResizeClient(double aWidth, double aHeight, bool aRepaint);
+  NS_IMETHOD              ResizeClient(double aX, double aY, double aWidth, double aHeight, bool aRepaint);
   NS_IMETHOD              GetBounds(nsIntRect &aRect);
   NS_IMETHOD              GetClientBounds(nsIntRect &aRect);
   NS_IMETHOD              GetScreenBounds(nsIntRect &aRect);
   NS_IMETHOD              GetNonClientMargins(nsIntMargin &margins);
   NS_IMETHOD              SetNonClientMargins(nsIntMargin &margins);
   virtual nsIntPoint      GetClientOffset();
   NS_IMETHOD              EnableDragDrop(bool aEnable);
   NS_IMETHOD              GetAttention(int32_t aCycleCount);
--- a/xpcom/base/nsMemoryReporterManager.cpp
+++ b/xpcom/base/nsMemoryReporterManager.cpp
@@ -556,16 +556,88 @@ static int64_t GetAtomTableSize() {
 // NS_RegisterMemoryReporter call fails.  So instead we do it here.
 NS_MEMORY_REPORTER_IMPLEMENT(AtomTable,
     "explicit/atom-tables",
     KIND_HEAP,
     UNITS_BYTES,
     GetAtomTableSize,
     "Memory used by the dynamic and static atoms tables.")
 
+#ifdef MOZ_DMD
+
+namespace mozilla {
+namespace dmd {
+
+class MemoryReporter MOZ_FINAL : public nsIMemoryMultiReporter
+{
+public:
+  MemoryReporter()
+  {}
+
+  NS_DECL_ISUPPORTS
+
+  NS_IMETHOD GetName(nsACString &name)
+  {
+    name.Assign("dmd");
+    return NS_OK;
+  }
+
+  NS_IMETHOD CollectReports(nsIMemoryMultiReporterCallback *callback,
+                            nsISupports *closure)
+  {
+    dmd::Sizes sizes;
+    dmd::SizeOf(&sizes);
+
+#define REPORT(_path, _amount, _desc)                                         \
+    do {                                                                      \
+      nsresult rv;                                                            \
+      rv = callback->Callback(EmptyCString(), NS_LITERAL_CSTRING(_path),      \
+                              nsIMemoryReporter::KIND_HEAP,                   \
+                              nsIMemoryReporter::UNITS_BYTES, _amount,        \
+                              NS_LITERAL_CSTRING(_desc), closure);            \
+      NS_ENSURE_SUCCESS(rv, rv);                                              \
+    } while (0)
+
+    REPORT("explicit/dmd/stack-traces",
+           sizes.mStackTraces,
+           "Memory used by DMD's stack traces.");
+
+    REPORT("explicit/dmd/stack-trace-table",
+           sizes.mStackTraceTable,
+           "Memory used by DMD's stack trace table.");
+
+    REPORT("explicit/dmd/live-block-table",
+           sizes.mLiveBlockTable,
+           "Memory used by DMD's live block table.");
+
+    REPORT("explicit/dmd/double-report-table",
+           sizes.mDoubleReportTable,
+           "Memory used by DMD's double-report table.");
+
+#undef REPORT
+
+    return NS_OK;
+  }
+
+  NS_IMETHOD GetExplicitNonHeap(int64_t *n)
+  {
+    // No non-heap allocations.
+    *n = 0;
+    return NS_OK;
+  }
+
+};
+
+NS_IMPL_ISUPPORTS1(MemoryReporter, nsIMemoryMultiReporter)
+
+} // namespace dmd
+} // namespace mozilla
+
+#endif  // MOZ_DMD
+
 /**
  ** nsMemoryReporterManager implementation
  **/
 
 NS_IMPL_THREADSAFE_ISUPPORTS1(nsMemoryReporterManager, nsIMemoryReporterManager)
 
 NS_IMETHODIMP
 nsMemoryReporterManager::Init()
@@ -596,18 +668,21 @@ nsMemoryReporterManager::Init()
     REGISTER(PageFaultsSoft);
     REGISTER(PageFaultsHard);
 #endif
 
 #ifdef HAVE_PRIVATE_REPORTER
     REGISTER(Private);
 #endif
 
+    REGISTER(AtomTable);
 
-    REGISTER(AtomTable);
+#ifdef MOZ_DMD
+    RegisterMultiReporter(new mozilla::dmd::MemoryReporter);
+#endif
 
 #if defined(XP_LINUX)
     nsMemoryInfoDumper::Initialize();
 #endif
 
     return NS_OK;
 }
 
--- a/xpfe/appshell/src/nsXULWindow.cpp
+++ b/xpfe/appshell/src/nsXULWindow.cpp
@@ -530,18 +530,17 @@ NS_IMETHODIMP nsXULWindow::GetUnscaledDe
   return NS_OK;
 }
 
 NS_IMETHODIMP nsXULWindow::SetPosition(int32_t aX, int32_t aY)
 {
   // Don't reset the window's size mode here - platforms that don't want to move
   // maximized windows should reset it in their respective Move implementation.
   double invScale = 1.0 / mWindow->GetDefaultScale();
-  nsresult rv = mWindow->Move(NSToIntRound(aX * invScale),
-                              NSToIntRound(aY * invScale));
+  nsresult rv = mWindow->Move(aX * invScale, aY * invScale);
   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
   if (!mChromeLoaded) {
     // If we're called before the chrome is loaded someone obviously wants this
     // window at this position. We don't persist this one-time position.
     mIgnoreXULPosition = true;
     return NS_OK;
   }
   PersistentAttributesDirty(PAD_POSITION);
@@ -559,19 +558,17 @@ NS_IMETHODIMP nsXULWindow::SetSize(int32
   /* any attempt to set the window's size or position overrides the window's
      zoom state. this is important when these two states are competing while
      the window is being opened. but it should probably just always be so. */
   mWindow->SetSizeMode(nsSizeMode_Normal);
 
   mIntrinsicallySized = false;
 
   double invScale = 1.0 / mWindow->GetDefaultScale();
-  nsresult rv = mWindow->Resize(NSToIntRound(aCX * invScale),
-                                NSToIntRound(aCY * invScale),
-                                aRepaint);
+  nsresult rv = mWindow->Resize(aCX * invScale, aCY * invScale, aRepaint);
   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
   if (!mChromeLoaded) {
     // If we're called before the chrome is loaded someone obviously wants this
     // window at this size & in the normal size mode (since it is the only mode
     // in which setting dimensions makes sense). We don't persist this one-time
     // size.
     mIgnoreXULSize = true;
     mIgnoreXULSizeMode = true;
@@ -593,20 +590,18 @@ NS_IMETHODIMP nsXULWindow::SetPositionAn
   /* any attempt to set the window's size or position overrides the window's
      zoom state. this is important when these two states are competing while
      the window is being opened. but it should probably just always be so. */
   mWindow->SetSizeMode(nsSizeMode_Normal);
 
   mIntrinsicallySized = false;
 
   double invScale = 1.0 / mWindow->GetDefaultScale();
-  nsresult rv = mWindow->Resize(NSToIntRound(aX * invScale),
-                                NSToIntRound(aY * invScale),
-                                NSToIntRound(aCX * invScale),
-                                NSToIntRound(aCY * invScale),
+  nsresult rv = mWindow->Resize(aX * invScale, aY * invScale,
+                                aCX * invScale, aCY * invScale,
                                 aRepaint);
   NS_ENSURE_SUCCESS(rv, NS_ERROR_FAILURE);
   if (!mChromeLoaded) {
     // If we're called before the chrome is loaded someone obviously wants this
     // window at this size and position. We don't persist this one-time setting.
     mIgnoreXULPosition = true;
     mIgnoreXULSize = true;
     mIgnoreXULSizeMode = true;