Merge m-c to fx-team
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Fri, 12 Sep 2014 15:24:48 +0200
changeset 205147 3b16c8fd53e89a9c1341931049c571898c438467
parent 205146 3932a0c7f8e54c9586b6a410ee578d1a5a5c6d14 (current diff)
parent 205061 59d4326311e07f7118794857c77435e06b874acb (diff)
child 205148 9f4de6f4b71b83fc354f4342199ba98e88bffb07
push id49106
push userphilringnalda@gmail.com
push dateSat, 13 Sep 2014 17:12:34 +0000
treeherdermozilla-inbound@ab04d0f2665f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone35.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 m-c to fx-team
browser/base/content/test/general/browser.ini
security/manager/ssl/public/nsICertificatePrincipal.idl
security/manager/ssl/src/nsCertificatePrincipal.cpp
security/manager/ssl/src/nsCertificatePrincipal.h
--- a/accessible/tests/mochitest/common.js
+++ b/accessible/tests/mochitest/common.js
@@ -234,17 +234,17 @@ function getAccessible(aAccOrElmOrID, aI
   if (!acc) {
     try {
       acc = gAccRetrieval.getAccessibleFor(elm);
     } catch (e) {
     }
 
     if (!acc) {
       if (!(aDoNotFailIf & DONOTFAIL_IF_NO_ACC))
-        ok(false, "Can't get accessible for " + aAccOrElmOrID);
+        ok(false, "Can't get accessible for " + prettyName(aAccOrElmOrID));
 
       return null;
     }
   }
 
   if (!aInterfaces)
     return acc;
 
--- a/accessible/tests/mochitest/relations/test_embeds.xul
+++ b/accessible/tests/mochitest/relations/test_embeds.xul
@@ -54,17 +54,21 @@
 
     function browserReorderChecker()
     {
       this.type = EVENT_REORDER;
 
       this.match = function browserReorderChecker_match(aEvent)
       {
         // Reorder event might be duped because of temporary document creation.
-        if (aEvent.accessible == getAccessible(currentBrowser())) {
+        var browserAcc = getAccessible(currentBrowser());
+        if (!browserAcc)
+          ok(false, "opa opa sralslasya");
+
+        if (aEvent.accessible == browserAcc) {
           this.cnt++;
           return this.cnt != 2;
         }
 
         return false;
       }
 
       this.cnt = 0;
@@ -78,18 +82,21 @@
       }
 
       this.eventSeq = [
         new browserReorderChecker()
       ];
 
       this.finalCheck = function loadURI_finalCheck()
       {
-        testRelation(browserDocument(), RELATION_EMBEDS,
-                     getAccessible(currentTabDocument()));
+        var acc = getAccessible(currentTabDocument());
+        if (!acc)
+          ok(false, "ahahahaha");
+
+        testRelation(browserDocument(), RELATION_EMBEDS, acc);
       }
 
       this.getID = function loadOneTab_getID()
       {
         return "load uri '" + aURI + "' in new tab";
       }
     }
 
--- a/b2g/components/B2GAppMigrator.js
+++ b/b2g/components/B2GAppMigrator.js
@@ -10,16 +10,19 @@ function debug(s) {
 const DEBUG = false;
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cu = Components.utils;
 
 const kMigrationMessageName = "webapps-before-update-merge";
 
+const kIDBDirType = "indexedDBPDir";
+const kProfileDirType = "ProfD";
+
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/FileUtils.jsm");
 
 XPCOMUtils.defineLazyServiceGetter(this, "appsService",
                                    "@mozilla.org/AppsService;1",
                                    "nsIAppsService");
 
@@ -37,36 +40,70 @@ B2GAppMigrator.prototype = {
     // should be the same on all systems. We should be able to just
     // hardcode it.
     let browserDBFileName = "2959517650brreosw.sqlite";
 
     // Storage directories need to be prefixed with the local id of
     // the app
     let browserLocalAppId = appsService.getAppLocalIdByManifestURL("app://browser.gaiamobile.org/manifest.webapp");
     let browserAppStorageDirName = browserLocalAppId + "+f+app+++browser.gaiamobile.org";
-    let browserDBFile = FileUtils.getFile("ProfD",
-                                          ["storage",
-                                           "persistent",
-                                           browserAppStorageDirName,
-                                           "idb",
-                                           browserDBFileName], true);
+
+    // On the phone, the browser db will only be in the old IDB
+    // directory, since it only existed up until v2.0. On desktop, it
+    // will exist in the profile directory.
+    //
+    // Uses getDir with filename appending to make sure we don't
+    // create extra directories along the way if they don't already
+    // exist.
+    let browserDBFile = FileUtils.getDir(kIDBDirType,
+                                         ["storage",
+                                          "persistent",
+                                          browserAppStorageDirName,
+                                          "idb"], false, true);
+    browserDBFile.append(browserDBFileName);
 
     if (!browserDBFile.exists()) {
-      if (DEBUG) debug("Browser DB file does not exist, nothing to copy");
-      return;
+      if (DEBUG) debug("Browser DB directory " + browserDBFile.path + " does not exist, trying profile location");
+      browserDBFile = FileUtils.getDir(kProfileDirType,
+                                        ["storage",
+                                         "persistent",
+                                         browserAppStorageDirName,
+                                         "idb"], false, true);
+      browserDBFile.append(browserDBFileName);
+      if (!browserDBFile.exists()) {
+        if (DEBUG) debug("Browser DB directory " + browserDBFile.path + " does not exist. Cannot copy browser db.");
+        return;
+      }
     }
 
     let systemLocalAppId = appsService.getAppLocalIdByManifestURL("app://system.gaiamobile.org/manifest.webapp");
     let systemAppStorageDirName = systemLocalAppId + "+f+app+++system.gaiamobile.org";
-    let systemDBDir = FileUtils.getDir("ProfD",
+
+    // This check futureproofs the system DB storage directory. It
+    // currently exists outside of the profile but will most likely
+    // move into the profile at some point.
+    let systemDBDir = FileUtils.getDir(kIDBDirType,
                                        ["storage",
                                         "persistent",
                                         systemAppStorageDirName,
                                         "idb"], false, true);
 
+    if (!systemDBDir.exists()) {
+      if (DEBUG) debug("System DB directory " + systemDBDir.path + " does not exist, trying profile location");
+      systemDBDir = FileUtils.getDir(kProfileDirType,
+                                     ["storage",
+                                      "persistent",
+                                      systemAppStorageDirName,
+                                      "idb"], false, true);
+      if (!systemDBDir.exists()) {
+        if (DEBUG) debug("System DB directory " + systemDBDir.path + " does not exist. Cannot copy browser db.");
+        return;
+      }
+    }
+
     if (DEBUG) {
       debug("Browser DB file exists, copying");
       debug("Browser local id: " + browserLocalAppId + "");
       debug("System local id: " + systemLocalAppId + "");
       debug("Browser DB file path: " + browserDBFile.path + "");
       debug("System DB directory path: " + systemDBDir.path + "");
     }
 
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="fe92ddd450e03b38edb2d465de7897971d68ac68">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="6cb5e0100d70313e4922c8d34bf20dcdd66ef616"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="b72909030e214175144342f7e5df7e88a2b52fd4"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7c22462206967693ab96b6af1627ba6925f5723f"/>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="4d1e85908d792d9468c4da7040acd191fbb51b40">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="6cb5e0100d70313e4922c8d34bf20dcdd66ef616"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="b72909030e214175144342f7e5df7e88a2b52fd4"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c058843242068d0df7c107e09da31b53d2e08fa6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7c22462206967693ab96b6af1627ba6925f5723f"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8986df0f82e15ac2798df0b6c2ee3435400677ac">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="6cb5e0100d70313e4922c8d34bf20dcdd66ef616"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="b72909030e214175144342f7e5df7e88a2b52fd4"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7c22462206967693ab96b6af1627ba6925f5723f"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="fe92ddd450e03b38edb2d465de7897971d68ac68">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="6cb5e0100d70313e4922c8d34bf20dcdd66ef616"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="b72909030e214175144342f7e5df7e88a2b52fd4"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7c22462206967693ab96b6af1627ba6925f5723f"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,17 +14,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="4d1e85908d792d9468c4da7040acd191fbb51b40">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="6cb5e0100d70313e4922c8d34bf20dcdd66ef616"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="b72909030e214175144342f7e5df7e88a2b52fd4"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c058843242068d0df7c107e09da31b53d2e08fa6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7c22462206967693ab96b6af1627ba6925f5723f"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="fe92ddd450e03b38edb2d465de7897971d68ac68">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="6cb5e0100d70313e4922c8d34bf20dcdd66ef616"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="b72909030e214175144342f7e5df7e88a2b52fd4"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7c22462206967693ab96b6af1627ba6925f5723f"/>
@@ -148,11 +148,11 @@
   <project name="platform/hardware/qcom/gps" path="hardware/qcom/gps" revision="9883ea57b0668d8f60dba025d4522dfa69a1fbfa"/>
   <project name="platform/hardware/qcom/media" path="hardware/qcom/media" revision="a558dc844bf5144fc38603fd8f4df8d9557052a5"/>
   <project name="platform/hardware/qcom/wlan" path="hardware/qcom/wlan" revision="57ee1320ed7b4a1a1274d8f3f6c177cd6b9becb2"/>
   <project name="platform/hardware/ril" path="hardware/ril" revision="12b1977cc704b35f2e9db2bb423fa405348bc2f3"/>
   <project name="platform/system/bluetooth" path="system/bluetooth" revision="985bf15264d865fe7b9c5b45f61c451cbaafa43d"/>
   <project name="platform/system/core" path="system/core" revision="350eac5403124dacb2a5fd9e28ac290a59fc3b8e"/>
   <project name="platform_system_nfcd" path="system/nfcd" remote="b2g" revision="54a712b46fe937dacdaed9b1261c63847129a719"/>
   <project name="platform/system/qcom" path="system/qcom" revision="63e3f6f176caad587d42bba4c16b66d953fb23c2"/>
-  <project name="platform/vendor/qcom-opensource/wlan/prima" path="vendor/qcom/opensource/wlan/prima" revision="6ada483cf7ff87eec2a9496941352606db73291e"/>
+  <project name="platform/vendor/qcom-opensource/wlan/prima" path="vendor/qcom/opensource/wlan/prima" revision="d8952a42771045fca73ec600e2b42a4c7129d723"/>
   <project name="platform/vendor/qcom/msm8610" path="device/qcom/msm8610" revision="5d1dbc698de7294697373b436dd44e240f40e1ac"/>
 </manifest>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8986df0f82e15ac2798df0b6c2ee3435400677ac">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="6cb5e0100d70313e4922c8d34bf20dcdd66ef616"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="b72909030e214175144342f7e5df7e88a2b52fd4"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7c22462206967693ab96b6af1627ba6925f5723f"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="e95b4ce22c825da44d14299e1190ea39a5260bde"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
         "git_revision": "", 
         "remote": "", 
         "branch": ""
     }, 
-    "revision": "62c1693326443d61bfa405d41d95d05281053cfa", 
+    "revision": "51bb0dde2b9800784dc6b4688eb8108aa18de765", 
     "repo_path": "/integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="4d1e85908d792d9468c4da7040acd191fbb51b40">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="6cb5e0100d70313e4922c8d34bf20dcdd66ef616"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="b72909030e214175144342f7e5df7e88a2b52fd4"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7c22462206967693ab96b6af1627ba6925f5723f"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -10,17 +10,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="4d1e85908d792d9468c4da7040acd191fbb51b40">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="6cb5e0100d70313e4922c8d34bf20dcdd66ef616"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="b72909030e214175144342f7e5df7e88a2b52fd4"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8986df0f82e15ac2798df0b6c2ee3435400677ac">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="6cb5e0100d70313e4922c8d34bf20dcdd66ef616"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="b72909030e214175144342f7e5df7e88a2b52fd4"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7c22462206967693ab96b6af1627ba6925f5723f"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -12,17 +12,17 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="4d1e85908d792d9468c4da7040acd191fbb51b40">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="6cb5e0100d70313e4922c8d34bf20dcdd66ef616"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="b72909030e214175144342f7e5df7e88a2b52fd4"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="6969df171e5295f855f12d12db0382048e6892e7"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="7c22462206967693ab96b6af1627ba6925f5723f"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -181,17 +181,17 @@ skip-if = e10s # Bug 918663 - DOMLinkAdd
 [browser_bug533232.js]
 [browser_bug537013.js]
 skip-if = buildapp == 'mulet' || e10s # Bug 918634 - swapFrameLoaders not implemented for e10s (test calls replaceTabWithWindow)
 [browser_bug537474.js]
 skip-if = e10s # Bug ?????? - test doesn't wait for document to be created before it checks it
 [browser_bug550565.js]
 skip-if = e10s # Bug 918663 - DOMLinkAdded events don't make their way to chrome (which is how gBrowser.getIcon works)
 [browser_bug553455.js]
-skip-if = buildapp == 'mulet' || e10s # Bug ????? - I don't think either popup notifications nor addon install stuff works?
+skip-if = buildapp == 'mulet' || e10s # Bug 1066070 - I don't think either popup notifications nor addon install stuff works?
 [browser_bug555224.js]
 skip-if = e10s # Bug 691614 - no e10s zoom support yet
 [browser_bug555767.js]
 skip-if = e10s # Bug 916974 - Session history doesn't work in e10s
 [browser_bug556061.js]
 skip-if = e10s # Bug 932651 - getClipboardData in specialpowersAPI.js not e10s friendly
 [browser_bug559991.js]
 skip-if = e10s # Bug 691614 - no e10s zoom support yet
--- a/browser/base/content/test/general/mochitest.ini
+++ b/browser/base/content/test/general/mochitest.ini
@@ -30,9 +30,11 @@ support-files =
 [test_bug364677.html]
 [test_bug395533.html]
 [test_contextmenu.html]
 skip-if = toolkit == "gtk2" || toolkit == "gtk3" # disabled on Linux due to bug 513558
 [test_contextmenu_input.html]
 skip-if = toolkit == "gtk2" || toolkit == "gtk3" # disabled on Linux due to bug 513558
 [test_feed_discovery.html]
 [test_offlineNotification.html]
+skip-if = buildapp == 'mulet' # Bug 1066070 - I don't think either popup notifications nor addon install stuff works?
 [test_offline_gzip.html]
+skip-if = buildapp == 'mulet' # Bug 1066070 - I don't think either popup notifications nor addon install stuff works?
--- a/build/autoconf/frameptr.m4
+++ b/build/autoconf/frameptr.m4
@@ -23,18 +23,19 @@ AC_DEFUN([MOZ_SET_FRAMEPTR_FLAGS], [
     case "$target" in
     *-mingw*)
       MOZ_ENABLE_FRAME_PTR="-Oy-"
       MOZ_DISABLE_FRAME_PTR="-Oy"
     ;;
     esac
   fi
 
-  # if we are debugging, profiling or using ASAN, we want a frame pointer.
+  # if we are debugging, profiling or using sanitizers, we want a frame pointer.
   if test -z "$MOZ_OPTIMIZE" -o \
           -n "$MOZ_PROFILING" -o \
           -n "$MOZ_DEBUG" -o \
+          -n "$MOZ_MSAN" -o \
           -n "$MOZ_ASAN"; then
     MOZ_FRAMEPTR_FLAGS="$MOZ_ENABLE_FRAME_PTR"
   else
     MOZ_FRAMEPTR_FLAGS="$MOZ_DISABLE_FRAME_PTR"
   fi
 ])
--- a/build/automationutils.py
+++ b/build/automationutils.py
@@ -18,18 +18,16 @@ import zipfile
 import mozinfo
 
 __all__ = [
   "ZipFileReader",
   "addCommonOptions",
   "dumpLeakLog",
   "isURL",
   "processLeakLog",
-  "getDebuggerInfo",
-  "DEBUGGER_INFO",
   "replaceBackSlashes",
   'KeyValueParseError',
   'parseKeyValue',
   'systemMemory',
   'environment',
   'dumpScreen',
   "ShutdownLeaks",
   "setAutomationLog",
@@ -43,64 +41,16 @@ def resetGlobalLog():
   log.setLevel(logging.INFO)
   log.addHandler(handler)
 resetGlobalLog()
 
 def setAutomationLog(alt_logger):
   global log
   log = alt_logger
 
-# Map of debugging programs to information about them, like default arguments
-# and whether or not they are interactive.
-DEBUGGER_INFO = {
-  # gdb requires that you supply the '--args' flag in order to pass arguments
-  # after the executable name to the executable.
-  "gdb": {
-    "interactive": True,
-    "args": "-q --args"
-  },
-
-  "cgdb": {
-    "interactive": True,
-    "args": "-q --args"
-  },
-
-  "lldb": {
-    "interactive": True,
-    "args": "--",
-    "requiresEscapedArgs": True
-  },
-
-  # Visual Studio Debugger Support
-  "devenv.exe": {
-    "interactive": True,
-    "args": "-debugexe"
-  },
-
-  # Visual C++ Express Debugger Support
-  "wdexpress.exe": {
-    "interactive": True,
-    "args": "-debugexe"
-  },
-
-  # valgrind doesn't explain much about leaks unless you set the
-  # '--leak-check=full' flag. But there are a lot of objects that are
-  # semi-deliberately leaked, so we set '--show-possibly-lost=no' to avoid
-  # uninteresting output from those objects. We set '--smc-check==all-non-file'
-  # and '--vex-iropt-register-updates=allregs-at-mem-access' so that valgrind
-  # deals properly with JIT'd JavaScript code.
-  "valgrind": {
-    "interactive": False,
-    "args": " ".join(["--leak-check=full",
-                      "--show-possibly-lost=no",
-                      "--smc-check=all-non-file",
-                      "--vex-iropt-register-updates=allregs-at-mem-access"])
-  }
-}
-
 class ZipFileReader(object):
   """
   Class to read zip files in Python 2.5 and later. Limited to only what we
   actually use.
   """
 
   def __init__(self, filename):
     self._zipfile = zipfile.ZipFile(filename, "r")
@@ -219,68 +169,16 @@ def addCommonOptions(parser, defaults={}
                     action = "store", dest = "debuggerArgs",
                     help = "pass the given args to the debugger _before_ "
                            "the application on the command line")
   parser.add_option("--debugger-interactive",
                     action = "store_true", dest = "debuggerInteractive",
                     help = "prevents the test harness from redirecting "
                         "stdout and stderr for interactive debuggers")
 
-def getFullPath(directory, path):
-  "Get an absolute path relative to 'directory'."
-  return os.path.normpath(os.path.join(directory, os.path.expanduser(path)))
-
-def searchPath(directory, path):
-  "Go one step beyond getFullPath and try the various folders in PATH"
-  # Try looking in the current working directory first.
-  newpath = getFullPath(directory, path)
-  if os.path.isfile(newpath):
-    return newpath
-
-  # At this point we have to fail if a directory was given (to prevent cases
-  # like './gdb' from matching '/usr/bin/./gdb').
-  if not os.path.dirname(path):
-    for dir in os.environ['PATH'].split(os.pathsep):
-      newpath = os.path.join(dir, path)
-      if os.path.isfile(newpath):
-        return newpath
-  return None
-
-def getDebuggerInfo(directory, debugger, debuggerArgs, debuggerInteractive = False):
-
-  debuggerInfo = None
-
-  if debugger:
-    debuggerPath = searchPath(directory, debugger)
-    if not debuggerPath:
-      print "Error: Path %s doesn't exist." % debugger
-      sys.exit(1)
-
-    debuggerName = os.path.basename(debuggerPath).lower()
-
-    def getDebuggerInfo(type, default):
-      if debuggerName in DEBUGGER_INFO and type in DEBUGGER_INFO[debuggerName]:
-        return DEBUGGER_INFO[debuggerName][type]
-      return default
-
-    debuggerInfo = {
-      "path": debuggerPath,
-      "interactive" : getDebuggerInfo("interactive", False),
-      "args": getDebuggerInfo("args", "").split(),
-      "requiresEscapedArgs": getDebuggerInfo("requiresEscapedArgs", False)
-    }
-
-    if debuggerArgs:
-      debuggerInfo["args"] = debuggerArgs.split()
-    if debuggerInteractive:
-      debuggerInfo["interactive"] = debuggerInteractive
-
-  return debuggerInfo
-
-
 def dumpLeakLog(leakLogFile, filter = False):
   """Process the leak log, without parsing it.
 
   Use this function if you want the raw log only.
   Use it preferably with the |XPCOM_MEM_LEAK_LOG| environment variable.
   """
 
   # Don't warn (nor "info") if the log file is not there.
--- a/build/mach_bootstrap.py
+++ b/build/mach_bootstrap.py
@@ -44,16 +44,17 @@ SEARCH_PATHS = [
     'testing',
     'testing/xpcshell',
     'testing/web-platform',
     'testing/web-platform/harness',
     'testing/marionette/client',
     'testing/marionette/client/marionette',
     'testing/marionette/transport',
     'testing/mozbase/mozcrash',
+    'testing/mozbase/mozdebug',
     'testing/mozbase/mozdevice',
     'testing/mozbase/mozfile',
     'testing/mozbase/mozhttpd',
     'testing/mozbase/mozlog',
     'testing/mozbase/moznetwork',
     'testing/mozbase/mozprocess',
     'testing/mozbase/mozprofile',
     'testing/mozbase/mozrunner',
--- a/configure.in
+++ b/configure.in
@@ -1259,16 +1259,32 @@ MOZ_ARG_ENABLE_BOOL(address-sanitizer,
     MOZ_ASAN=1,
     MOZ_ASAN= )
 if test -n "$MOZ_ASAN"; then
     MOZ_LLVM_HACKS=1
     AC_DEFINE(MOZ_ASAN)
     MOZ_PATH_PROG(LLVM_SYMBOLIZER, llvm-symbolizer)
 fi
 AC_SUBST(MOZ_ASAN)
+
+dnl ========================================================
+dnl = Use Memory Sanitizer
+dnl ========================================================
+MOZ_ARG_ENABLE_BOOL(memory-sanitizer,
+[  --enable-memory-sanitizer       Enable Memory Sanitizer (default=no)],
+    MOZ_MSAN=1,
+    MOZ_MSAN= )
+if test -n "$MOZ_MSAN"; then
+    MOZ_LLVM_HACKS=1
+    AC_DEFINE(MOZ_MSAN)
+    MOZ_PATH_PROG(LLVM_SYMBOLIZER, llvm-symbolizer)
+fi
+AC_SUBST(MOZ_MSAN)
+
+# The LLVM symbolizer is used by all sanitizers
 AC_SUBST(LLVM_SYMBOLIZER)
 
 dnl ========================================================
 dnl = Enable hacks required for LLVM instrumentations
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(llvm-hacks,
 [  --enable-llvm-hacks       Enable workarounds required for several LLVM instrumentations (default=no)],
     MOZ_LLVM_HACKS=1,
--- a/content/html/document/test/mochitest.ini
+++ b/content/html/document/test/mochitest.ini
@@ -66,17 +66,17 @@ skip-if = toolkit == 'android'
 [test_bug486741.html]
 [test_bug489532.html]
 [test_bug497242.xhtml]
 [test_bug499092.html]
 [test_bug512367.html]
 [test_bug677495.html]
 [test_bug677495-1.html]
 [test_bug741266.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s # b2g(needs control of popup window size) b2g-debug(needs control of popup window size) b2g-desktop(needs control of popup window size)
+skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e10s # b2g(needs control of popup window size) b2g-debug(needs control of popup window size) b2g-desktop(needs control of popup window size)
 [test_non-ascii-cookie.html]
 skip-if = buildapp == 'b2g' || e10s
 [test_bug765780.html]
 [test_bug871161.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') || e10s #Bug 931116, b2g desktop specific, initial triage
 support-files = file_bug871161-1.html file_bug871161-2.html
 
 [test_bug1013316.html]
--- a/content/media/mediasource/MediaSource.cpp
+++ b/content/media/mediasource/MediaSource.cpp
@@ -502,16 +502,30 @@ MediaSource::InitializationEvent()
 {
   MOZ_ASSERT(NS_IsMainThread());
   MSE_DEBUG("MediaSource(%p)::InitializationEvent()", this);
   if (mDecoder) {
     mDecoder->PrepareReaderInitialization();
   }
 }
 
+#if defined(DEBUG)
+void
+MediaSource::Dump(const char* aPath)
+{
+  char buf[255];
+  PR_snprintf(buf, sizeof(buf), "%s/mediasource-%p", aPath, this);
+  PR_MkDir(buf, 0700);
+
+  if (mSourceBuffers) {
+    mSourceBuffers->Dump(buf);
+  }
+}
+#endif
+
 nsPIDOMWindow*
 MediaSource::GetParentObject() const
 {
   return GetOwner();
 }
 
 JSObject*
 MediaSource::WrapObject(JSContext* aCx)
--- a/content/media/mediasource/MediaSource.h
+++ b/content/media/mediasource/MediaSource.h
@@ -93,16 +93,22 @@ public:
   // Queue InitializationEvent to run on the main thread.  Called when a
   // SourceBuffer has an initialization segment appended, but only
   // dispatched the first time (using mFirstSourceBufferInitialization).
   // Demarcates the point in time at which only currently registered
   // TrackBuffers are treated as essential by the MediaSourceReader for
   // initialization.
   void QueueInitializationEvent();
 
+#if defined(DEBUG)
+  // Dump the contents of each SourceBuffer to a series of files under aPath.
+  // aPath must exist.  Debug only, invoke from your favourite debugger.
+  void Dump(const char* aPath);
+#endif
+
 private:
   ~MediaSource();
 
   explicit MediaSource(nsPIDOMWindow* aWindow);
 
   friend class AsyncEventRunner<MediaSource>;
   void DispatchSimpleEvent(const char* aName);
   void QueueAsyncSimpleEvent(const char* aName);
--- a/content/media/mediasource/ResourceQueue.h
+++ b/content/media/mediasource/ResourceQueue.h
@@ -129,16 +129,33 @@ public:
     for (uint32_t i = 0; i < uint32_t(GetSize()); ++i) {
       const ResourceItem* item = ResourceAt(i);
       size += item->SizeOfIncludingThis(aMallocSizeOf);
     }
 
     return size;
   }
 
+#if defined(DEBUG)
+  void Dump(const char* aPath) {
+    for (uint32_t i = 0; i < uint32_t(GetSize()); ++i) {
+      ResourceItem* item = ResourceAt(i);
+
+      char buf[255];
+      PR_snprintf(buf, sizeof(buf), "%s/%08u.bin", aPath, i);
+      FILE* fp = fopen(buf, "wb");
+      if (!fp) {
+        return;
+      }
+      fwrite(item->mData.Elements(), item->mData.Length(), 1, fp);
+      fclose(fp);
+    }
+  }
+#endif
+
 private:
   ResourceItem* ResourceAt(uint32_t aIndex) const {
     return static_cast<ResourceItem*>(ObjectAt(aIndex));
   }
 
   // Returns the index of the resource that contains the given
   // logical offset. aResourceOffset will contain the offset into
   // the resource at the given index returned if it is not null.  If
@@ -168,11 +185,10 @@ private:
 
   // Logical length of the resource.
   uint64_t mLogicalLength;
 
   // Logical offset into the resource of the first element in the queue.
   uint64_t mOffset;
 };
 
-
 } // namespace mozilla
 #endif /* MOZILLA_RESOURCEQUEUE_H_ */
--- a/content/media/mediasource/SourceBuffer.cpp
+++ b/content/media/mediasource/SourceBuffer.cpp
@@ -1,8 +1,9 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
 
 #include "SourceBuffer.h"
 
 #include "AsyncEventRunner.h"
@@ -682,16 +683,26 @@ SourceBuffer::Evict(double aStart, doubl
   double evictTime = aEnd;
   const double safety_threshold = 5;
   if (currentTime + safety_threshold >= evictTime) {
     evictTime -= safety_threshold;
   }
   mTrackBuffer->EvictBefore(evictTime);
 }
 
+#if defined(DEBUG)
+void
+SourceBuffer::Dump(const char* aPath)
+{
+  if (mTrackBuffer) {
+    mTrackBuffer->Dump(aPath);
+  }
+}
+#endif
+
 NS_IMPL_CYCLE_COLLECTION_INHERITED(SourceBuffer, DOMEventTargetHelper,
                                    mMediaSource)
 
 NS_IMPL_ADDREF_INHERITED(SourceBuffer, DOMEventTargetHelper)
 NS_IMPL_RELEASE_INHERITED(SourceBuffer, DOMEventTargetHelper)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(SourceBuffer)
 NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
--- a/content/media/mediasource/SourceBuffer.h
+++ b/content/media/mediasource/SourceBuffer.h
@@ -104,16 +104,20 @@ public:
   void Ended();
 
   // Evict data in the source buffer in the given time range.
   void Evict(double aStart, double aEnd);
 
   double GetBufferedStart();
   double GetBufferedEnd();
 
+#if defined(DEBUG)
+  void Dump(const char* aPath);
+#endif
+
 private:
   ~SourceBuffer();
 
   friend class AsyncEventRunner<SourceBuffer>;
   void DispatchSimpleEvent(const char* aName);
   void QueueAsyncSimpleEvent(const char* aName);
 
   // Create a new decoder for mType, and store the result in mDecoder.
--- a/content/media/mediasource/SourceBufferDecoder.cpp
+++ b/content/media/mediasource/SourceBufferDecoder.cpp
@@ -1,8 +1,9 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
 
 #include "SourceBufferDecoder.h"
 #include "prlog.h"
 #include "AbstractMediaDecoder.h"
--- a/content/media/mediasource/SourceBufferList.cpp
+++ b/content/media/mediasource/SourceBufferList.cpp
@@ -162,16 +162,26 @@ SourceBufferList::DispatchSimpleEvent(co
 void
 SourceBufferList::QueueAsyncSimpleEvent(const char* aName)
 {
   MSE_DEBUG("SourceBufferList(%p) Queuing event '%s'", this, aName);
   nsCOMPtr<nsIRunnable> event = new AsyncEventRunner<SourceBufferList>(this, aName);
   NS_DispatchToMainThread(event);
 }
 
+#if defined(DEBUG)
+void
+SourceBufferList::Dump(const char* aPath)
+{
+  for (uint32_t i = 0; i < mSourceBuffers.Length(); ++i) {
+    mSourceBuffers[i]->Dump(aPath);
+  }
+}
+#endif
+
 SourceBufferList::SourceBufferList(MediaSource* aMediaSource)
   : DOMEventTargetHelper(aMediaSource->GetParentObject())
   , mMediaSource(aMediaSource)
 {
   MOZ_ASSERT(aMediaSource);
 }
 
 MediaSource*
--- a/content/media/mediasource/SourceBufferList.h
+++ b/content/media/mediasource/SourceBufferList.h
@@ -74,16 +74,20 @@ public:
   void Ended();
 
   // Evicts data for the given time range from each SourceBuffer in the list.
   void Evict(double aStart, double aEnd);
 
   // Returns the highest end time of any of the Sourcebuffers.
   double GetHighestBufferedEndTime();
 
+#if defined(DEBUG)
+  void Dump(const char* aPath);
+#endif
+
 private:
   ~SourceBufferList();
 
   friend class AsyncEventRunner<SourceBufferList>;
   void DispatchSimpleEvent(const char* aName);
   void QueueAsyncSimpleEvent(const char* aName);
 
   nsRefPtr<MediaSource> mMediaSource;
--- a/content/media/mediasource/SourceBufferResource.h
+++ b/content/media/mediasource/SourceBufferResource.h
@@ -115,16 +115,22 @@ public:
   void Ended();
   // Remove data from resource if it holds more than the threshold
   // number of bytes. Returns true if some data was evicted.
   bool EvictData(uint32_t aThreshold);
 
   // Remove data from resource before the given offset.
   void EvictBefore(uint64_t aOffset);
 
+#if defined(DEBUG)
+  void Dump(const char* aPath) {
+    mInputBuffer.Dump(aPath);
+  }
+#endif
+
 private:
   ~SourceBufferResource();
   nsresult SeekInternal(int64_t aOffset);
 
   const nsCString mType;
 
   // Provides synchronization between SourceBuffers and InputAdapters.
   // Protects all of the member variables below.  Read() will await a
--- a/content/media/mediasource/TrackBuffer.cpp
+++ b/content/media/mediasource/TrackBuffer.cpp
@@ -1,8 +1,9 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* 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/. */
 
 #include "TrackBuffer.h"
 
 #include "MediaSourceDecoder.h"
@@ -14,16 +15,21 @@
 #include "mozilla/FloatingPoint.h"
 #include "mozilla/dom/MediaSourceBinding.h"
 #include "mozilla/dom/TimeRanges.h"
 #include "nsError.h"
 #include "nsIRunnable.h"
 #include "nsThreadUtils.h"
 #include "prlog.h"
 
+#if defined(DEBUG)
+#include <sys/stat.h>
+#include <sys/types.h>
+#endif
+
 struct JSContext;
 class JSObject;
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* GetMediaSourceLog();
 extern PRLogModuleInfo* GetMediaSourceAPILog();
 
 #define MSE_DEBUG(...) PR_LOG(GetMediaSourceLog(), PR_LOG_DEBUG, (__VA_ARGS__))
@@ -344,9 +350,27 @@ TrackBuffer::ResetDecode()
 
 const nsTArray<nsRefPtr<SourceBufferDecoder>>&
 TrackBuffer::Decoders()
 {
   // XXX assert OnDecodeThread
   return mInitializedDecoders;
 }
 
+#if defined(DEBUG)
+void
+TrackBuffer::Dump(const char* aPath)
+{
+  char path[255];
+  PR_snprintf(path, sizeof(path), "%s/trackbuffer-%p", aPath, this);
+  PR_MkDir(path, 0700);
+
+  for (uint32_t i = 0; i < mDecoders.Length(); ++i) {
+    char buf[255];
+    PR_snprintf(buf, sizeof(buf), "%s/reader-%p", path, mDecoders[i]->GetReader());
+    PR_MkDir(buf, 0700);
+
+    mDecoders[i]->GetResource()->Dump(buf);
+  }
+}
+#endif
+
 } // namespace mozilla
--- a/content/media/mediasource/TrackBuffer.h
+++ b/content/media/mediasource/TrackBuffer.h
@@ -77,16 +77,20 @@ public:
   // Call ResetDecode() on each decoder in mDecoders.
   void ResetDecode();
 
   // Returns a reference to mInitializedDecoders, used by MediaSourceReader
   // to select decoders.
   // TODO: Refactor to a cleaner interface between TrackBuffer and MediaSourceReader.
   const nsTArray<nsRefPtr<SourceBufferDecoder>>& Decoders();
 
+#if defined(DEBUG)
+  void Dump(const char* aPath);
+#endif
+
 private:
   ~TrackBuffer();
 
   // Queue execution of InitializeDecoder on mTaskQueue.
   bool QueueInitializeDecoder(nsRefPtr<SourceBufferDecoder> aDecoder);
 
   // Runs decoder initialization including calling ReadMetadata.  Runs as an
   // event on the decode thread pool.
--- a/content/media/omx/MediaCodecProxy.cpp
+++ b/content/media/omx/MediaCodecProxy.cpp
@@ -13,16 +13,72 @@
 #include "stagefright/MediaErrors.h"
 
 #define LOG_TAG "MediaCodecProxy"
 #include <android/log.h>
 #define ALOG(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
 #define TIMEOUT_DEQUEUE_INPUTBUFFER_MS 1000000ll
 namespace android {
 
+// General Template: MediaCodec::getOutputGraphicBufferFromIndex(...)
+template <typename T, bool InterfaceSupported>
+struct OutputGraphicBufferStub
+{
+  static status_t GetOutputGraphicBuffer(T *aMediaCodec,
+                                         size_t aIndex,
+                                         sp<GraphicBuffer> *aGraphicBuffer)
+  {
+    return ERROR_UNSUPPORTED;
+  }
+};
+
+// Class Template Specialization: MediaCodec::getOutputGraphicBufferFromIndex(...)
+template <typename T>
+struct OutputGraphicBufferStub<T, true>
+{
+  static status_t GetOutputGraphicBuffer(T *aMediaCodec,
+                                         size_t aIndex,
+                                         sp<GraphicBuffer> *aGraphicBuffer)
+  {
+    if (aMediaCodec == nullptr || aGraphicBuffer == nullptr) {
+      return BAD_VALUE;
+    }
+    *aGraphicBuffer = aMediaCodec->getOutputGraphicBufferFromIndex(aIndex);
+    return OK;
+  }
+};
+
+// Wrapper class to handle interface-difference of MediaCodec.
+struct MediaCodecInterfaceWrapper
+{
+  typedef int8_t Supported;
+  typedef int16_t Unsupported;
+
+  template <typename T>
+  static auto TestOutputGraphicBuffer(T *aMediaCodec) -> decltype(aMediaCodec->getOutputGraphicBufferFromIndex(0), Supported());
+
+  template <typename T>
+  static auto TestOutputGraphicBuffer(...) -> Unsupported;
+
+  // SFINAE: Substitution Failure Is Not An Error
+  static const bool OutputGraphicBufferSupported = sizeof(TestOutputGraphicBuffer<MediaCodec>(nullptr)) == sizeof(Supported);
+
+  // Class Template Specialization
+  static OutputGraphicBufferStub<MediaCodec, OutputGraphicBufferSupported> sOutputGraphicBufferStub;
+
+  // Wrapper Function
+  static status_t GetOutputGraphicBuffer(MediaCodec *aMediaCodec,
+                                         size_t aIndex,
+                                         sp<GraphicBuffer> *aGraphicBuffer)
+  {
+    return sOutputGraphicBufferStub.GetOutputGraphicBuffer(aMediaCodec, aIndex, aGraphicBuffer);
+  }
+
+};
+
 sp<MediaCodecProxy>
 MediaCodecProxy::CreateByType(sp<ALooper> aLooper,
                               const char *aMime,
                               bool aEncoder,
                               bool aAsync,
                               wp<CodecResourceListener> aListener)
 {
   sp<MediaCodecProxy> codec = new MediaCodecProxy(aLooper, aMime, aEncoder, aAsync, aListener);
@@ -358,16 +414,47 @@ MediaCodecProxy::requestActivityNotifica
   RWLock::AutoRLock arl(mCodecLock);
 
   if (mCodec == nullptr) {
     return;
   }
   mCodec->requestActivityNotification(aNotify);
 }
 
+status_t
+MediaCodecProxy::getOutputGraphicBufferFromIndex(size_t aIndex,
+                                                 sp<GraphicBuffer> *aGraphicBuffer)
+{
+  // Read Lock for mCodec
+  RWLock::AutoRLock arl(mCodecLock);
+
+  if (mCodec == nullptr) {
+    return NO_INIT;
+  }
+  return MediaCodecInterfaceWrapper::GetOutputGraphicBuffer(mCodec.get(), aIndex, aGraphicBuffer);
+}
+
+status_t
+MediaCodecProxy::getCapability(uint32_t *aCapability)
+{
+  if (aCapability == nullptr) {
+    return BAD_VALUE;
+  }
+
+  uint32_t capability = kEmptyCapability;
+
+  if (MediaCodecInterfaceWrapper::OutputGraphicBufferSupported) {
+    capability |= kCanExposeGraphicBuffer;
+  }
+
+  *aCapability = capability;
+
+  return OK;
+}
+
 // Called on a Binder thread
 void
 MediaCodecProxy::resourceReserved()
 {
   // Create MediaCodec
   releaseCodec();
   if (!allocateCodec()) {
     cancelResource();
--- a/content/media/omx/MediaCodecProxy.h
+++ b/content/media/omx/MediaCodecProxy.h
@@ -35,19 +35,25 @@ public:
     virtual void codecReserved() = 0;
     /* The codec resource is not reserved any more.
      * The client should release the resource as soon as possible if the
      * resource is still being held.
      */
     virtual void codecCanceled() = 0;
   };
 
+  enum Capability {
+    kEmptyCapability        = 0x00000000,
+    kCanExposeGraphicBuffer = 0x00000001,
+  };
+
   enum {
     kKeyBufferIndex = 'bfin',
   };
+
   // Check whether MediaCodec has been allocated.
   bool allocated() const;
 
   // Static MediaCodec methods
   // Only support MediaCodec::CreateByType()
   static sp<MediaCodecProxy> CreateByType(sp<ALooper> aLooper,
                                           const char *aMime,
                                           bool aEncoder,
@@ -107,24 +113,33 @@ public:
   status_t getInputBuffers(Vector<sp<ABuffer>> *aBuffers) const;
 
   status_t getOutputBuffers(Vector<sp<ABuffer>> *aBuffers) const;
 
   // Notification will be posted once there "is something to do", i.e.
   // an input/output buffer has become available, a format change is
   // pending, an error is pending.
   void requestActivityNotification(const sp<AMessage> &aNotify);
+
+  status_t getOutputGraphicBufferFromIndex(size_t aIndex,
+                                           sp<GraphicBuffer> *aGraphicBuffer);
+
+  status_t getCapability(uint32_t *aCapability);
+
+  // Utility functions
+
   // If aData is null, will notify decoder input EOS
   status_t Input(const uint8_t* aData, uint32_t aDataSize,
                  int64_t aTimestampUsecs, uint64_t flags);
   status_t Output(MediaBuffer** aBuffer, int64_t aTimeoutUs);
   bool Prepare();
   bool IsWaitingResources();
   bool IsDormantNeeded();
   void ReleaseMediaResources();
+
 protected:
   virtual ~MediaCodecProxy();
 
   // MediaResourceHandler::EventListener::resourceReserved()
   virtual void resourceReserved();
   // MediaResourceHandler::EventListener::resourceCanceled()
   virtual void resourceCanceled();
 
@@ -160,16 +175,17 @@ private:
   wp<CodecResourceListener> mListener;
 
   // Media Resource Management
   sp<MediaResourceHandler> mResourceHandler;
 
   // MediaCodec instance
   mutable RWLock mCodecLock;
   sp<MediaCodec> mCodec;
+
   //MediaCodec buffers to hold input/output data.
   Vector<sp<ABuffer> > mInputBuffers;
   Vector<sp<ABuffer> > mOutputBuffers;
 
 };
 
 } // namespace android
 
--- a/docshell/test/navigation/mochitest.ini
+++ b/docshell/test/navigation/mochitest.ini
@@ -24,17 +24,17 @@ support-files =
 skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #RANDOM
 [test_bug270414.html]
 skip-if = buildapp == 'b2g' || toolkit == "android" || e10s
 [test_bug278916.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_bug279495.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_bug344861.html]
-skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'android' || e10s
+skip-if = buildapp == 'mulet' || (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'android' || e10s
 [test_bug386782.html]
 skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
 [test_bug430624.html]
 [test_bug430723.html]
 skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'android' #TIMED_OUT # b2g-debug(bug 874423) b2g-desktop(Bug 931116, b2g desktop specific, initial triage)
 [test_child.html]
 [test_grandchild.html]
 [test_not-opener.html]
--- a/dom/audiochannel/tests/mochitest.ini
+++ b/dom/audiochannel/tests/mochitest.ini
@@ -1,11 +1,11 @@
 [DEFAULT]
 support-files =
   audio.ogg
   file_audio.html
   file_telephonyPolicy.html
   AudioChannelChromeScript.js
 
 [test_telephonyPolicy.html]
-skip-if = buildapp == 'mulet' || (toolkit == 'gonk' || e10s)
+skip-if = buildapp == 'mulet' || (toolkit == 'gonk' || e10s) || os == "android"
 [test_audioChannelChange.html]
 skip-if = (toolkit != 'gonk')
--- a/dom/base/ImageEncoder.cpp
+++ b/dom/base/ImageEncoder.cpp
@@ -411,22 +411,21 @@ ImageEncoder::ExtractDataInternal(const 
   } else {
     // no context, so we have to encode an empty image
     // note that if we didn't have a current context, the spec says we're
     // supposed to just return transparent black pixels of the canvas
     // dimensions.
     RefPtr<DataSourceSurface> emptyCanvas =
       Factory::CreateDataSourceSurfaceWithStride(IntSize(aSize.width, aSize.height),
                                                  SurfaceFormat::B8G8R8A8,
-                                                 4 * aSize.width);
+                                                 4 * aSize.width, true);
     if (NS_WARN_IF(!emptyCanvas)) {
       return NS_ERROR_INVALID_ARG;
     }
 
-    ClearDataSourceSurface(emptyCanvas);
     DataSourceSurface::MappedSurface map;
     if (!emptyCanvas->Map(DataSourceSurface::MapType::WRITE, &map)) {
       return NS_ERROR_INVALID_ARG;
     }
     rv = aEncoder->InitFromData(map.mData,
                                 aSize.width * aSize.height * 4,
                                 aSize.width,
                                 aSize.height,
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -86,16 +86,20 @@
 # entry, just make it not a list.
 
 DOMInterfaces = {
 
 'MozActivity': {
     'nativeType': 'mozilla::dom::Activity',
 },
 
+'MozAbortablePromise': {
+    'nativeType': 'mozilla::dom::AbortablePromise',
+},
+
 'AbstractWorker': {
     'concrete': False
 },
 
 'ArchiveReader': {
     'nativeType': 'mozilla::dom::archivereader::ArchiveReader',
 },
 
--- a/dom/canvas/CanvasRenderingContext2D.cpp
+++ b/dom/canvas/CanvasRenderingContext2D.cpp
@@ -892,51 +892,40 @@ CanvasRenderingContext2D::CheckSizeForSk
   // absolute max size threshold
   if (maxsize > 0) {
     return size.width <= maxsize && size.height <= maxsize;
   }
 
   // Cache the number of pixels on the primary screen
   static int32_t gScreenPixels = -1;
   if (gScreenPixels < 0) {
-    // Default to historical mobile screen size of 980x480.  In addition,
-    // allow skia use up to this size even if the screen is smaller.  A lot
-    // content expects this size to work well.
-    gScreenPixels = 980 * 480;
+    // Default to historical mobile screen size of 980x480, like FishIEtank.
+    // In addition, allow skia use up to this size even if the screen is smaller.
+    // A lot content expects this size to work well.
+    // See Bug 999841
+    if (gfxPlatform::GetPlatform()->HasEnoughTotalSystemMemoryForSkiaGL()) {
+      gScreenPixels = 980 * 480;
+    }
 
     nsCOMPtr<nsIScreenManager> screenManager =
       do_GetService("@mozilla.org/gfx/screenmanager;1");
     if (screenManager) {
       nsCOMPtr<nsIScreen> primaryScreen;
       screenManager->GetPrimaryScreen(getter_AddRefs(primaryScreen));
       if (primaryScreen) {
         int32_t x, y, width, height;
         primaryScreen->GetRect(&x, &y, &width, &height);
 
         gScreenPixels = std::max(gScreenPixels, width * height);
       }
     }
   }
 
-  // On high DPI devices the screen pixels may be scaled up.  Make
-  // sure to apply that scaling here as well if we are hooked up
-  // to a widget.
-  static double gDefaultScale = 0.0;
-  if (gDefaultScale < 1.0) {
-    nsIPresShell* ps = GetPresShell();
-    if (ps) {
-      nsIFrame* frame = ps->GetRootFrame();
-      if (frame) {
-        nsIWidget* widget = frame->GetNearestWidget();
-        if (widget) {
-          gDefaultScale = widget->GetDefaultScale().scale;
-        }
-      }
-    }
-  }
+  // Just always use a scale of 1.0. It can be changed if a lot of contents need it.
+  static double gDefaultScale = 1.0;
 
   double scale = gDefaultScale > 0 ? gDefaultScale : 1.0;
   int32_t threshold = ceil(scale * scale * gScreenPixels);
 
   // screen size acts as max threshold
   return threshold < 0 || (size.width * size.height) <= threshold;
 }
 
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -1870,16 +1870,19 @@ TabChild::RecvAcknowledgeScrollUpdate(co
 {
   APZCCallbackHelper::AcknowledgeScrollUpdate(aScrollId, aScrollGeneration);
   return true;
 }
 
 bool
 TabChild::RecvHandleDoubleTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
 {
+    TABC_LOG("Handling double tap at %s with %p %p\n",
+      Stringify(aPoint).c_str(), mGlobal.get(), mTabChildGlobal.get());
+
     if (!mGlobal || !mTabChildGlobal) {
         return true;
     }
 
     CSSPoint point = APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid);
     nsString data;
     data.AppendLiteral("{ \"x\" : ");
     data.AppendFloat(point.x);
@@ -1890,16 +1893,19 @@ TabChild::RecvHandleDoubleTap(const CSSP
     DispatchMessageManagerMessage(NS_LITERAL_STRING("Gesture:DoubleTap"), data);
 
     return true;
 }
 
 bool
 TabChild::RecvHandleSingleTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
 {
+  TABC_LOG("Handling single tap at %s with %p %p %d\n",
+    Stringify(aPoint).c_str(), mGlobal.get(), mTabChildGlobal.get(), mTouchEndCancelled);
+
   if (!mGlobal || !mTabChildGlobal) {
     return true;
   }
 
   if (mTouchEndCancelled) {
     return true;
   }
 
@@ -1919,45 +1925,53 @@ TabChild::RecvHandleSingleTap(const CSSP
 }
 
 void
 TabChild::FireSingleTapEvent(LayoutDevicePoint aPoint)
 {
   if (mDestroyed) {
     return;
   }
+  TABC_LOG("Dispatching single-tap component events to %s\n",
+    Stringify(aPoint).c_str());
   int time = 0;
   DispatchSynthesizedMouseEvent(NS_MOUSE_MOVE, time, aPoint, mWidget);
   DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_DOWN, time, aPoint, mWidget);
   DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_UP, time, aPoint, mWidget);
 }
 
 bool
 TabChild::RecvHandleLongTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid)
 {
+  TABC_LOG("Handling long tap at %s with %p %p\n",
+    Stringify(aPoint).c_str(), mGlobal.get(), mTabChildGlobal.get());
+
   if (!mGlobal || !mTabChildGlobal) {
     return true;
   }
 
   SendPendingTouchPreventedResponse(false, aGuid);
 
   bool eventHandled =
       DispatchMouseEvent(NS_LITERAL_STRING("contextmenu"),
                          APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid),
                          2, 1, 0, true,
                          nsIDOMMouseEvent::MOZ_SOURCE_TOUCH);
 
+  TABC_LOG("Contextmenu event handled: %d\n", eventHandled);
+
   // If no one handle context menu, fire MOZLONGTAP event
   if (!eventHandled) {
     LayoutDevicePoint currentPoint =
       APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid) * mWidget->GetDefaultScale();
     int time = 0;
     nsEventStatus status =
       DispatchSynthesizedMouseEvent(NS_MOUSE_MOZLONGTAP, time, currentPoint, mWidget);
     eventHandled = (status == nsEventStatus_eConsumeNoDefault);
+    TABC_LOG("MOZLONGTAP event handled: %d\n", eventHandled);
   }
 
   SendContentReceivedTouch(aGuid, eventHandled);
 
   return true;
 }
 
 bool
@@ -2221,16 +2235,18 @@ TabChild::CancelTapTracking()
   }
   mTapHoldTimer = nullptr;
 }
 
 bool
 TabChild::RecvRealTouchEvent(const WidgetTouchEvent& aEvent,
                              const ScrollableLayerGuid& aGuid)
 {
+  TABC_LOG("Receiving touch event of type %d\n", aEvent.message);
+
   WidgetTouchEvent localEvent(aEvent);
   localEvent.widget = mWidget;
   for (size_t i = 0; i < localEvent.touches.Length(); i++) {
     aEvent.touches[i]->mRefPoint = APZCCallbackHelper::ApplyCallbackTransform(aEvent.touches[i]->mRefPoint, aGuid, mWidget->GetDefaultScale());
   }
 
   nsEventStatus status = DispatchWidgetEvent(localEvent);
 
new file mode 100644
--- /dev/null
+++ b/dom/promise/AbortablePromise.cpp
@@ -0,0 +1,118 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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/. */
+
+#include "mozilla/dom/AbortablePromise.h"
+
+#include "mozilla/dom/AbortablePromiseBinding.h"
+#include "mozilla/dom/PromiseNativeAbortCallback.h"
+#include "mozilla/ErrorResult.h"
+#include "nsThreadUtils.h"
+#include "PromiseCallback.h"
+
+namespace mozilla {
+namespace dom {
+
+NS_IMPL_CYCLE_COLLECTING_ADDREF(PromiseNativeAbortCallback)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(PromiseNativeAbortCallback)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PromiseNativeAbortCallback)
+  NS_INTERFACE_MAP_ENTRY(nsISupports)
+NS_INTERFACE_MAP_END
+NS_IMPL_CYCLE_COLLECTION_0(PromiseNativeAbortCallback)
+
+NS_IMPL_ADDREF_INHERITED(AbortablePromise, Promise)
+NS_IMPL_RELEASE_INHERITED(AbortablePromise, Promise)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(AbortablePromise)
+NS_INTERFACE_MAP_END_INHERITING(Promise)
+NS_IMPL_CYCLE_COLLECTION_INHERITED(AbortablePromise, Promise, mAbortCallback)
+
+AbortablePromise::AbortablePromise(nsIGlobalObject* aGlobal,
+                                   PromiseNativeAbortCallback& aAbortCallback)
+  : Promise(aGlobal)
+  , mAbortCallback(&aAbortCallback)
+{
+}
+
+AbortablePromise::AbortablePromise(nsIGlobalObject* aGlobal)
+  : Promise(aGlobal)
+{
+}
+
+AbortablePromise::~AbortablePromise()
+{
+}
+
+/* static */ already_AddRefed<AbortablePromise>
+AbortablePromise::Create(nsIGlobalObject* aGlobal,
+                         PromiseNativeAbortCallback& aAbortCallback,
+                         ErrorResult& aRv)
+{
+  nsRefPtr<AbortablePromise> p = new AbortablePromise(aGlobal, aAbortCallback);
+  p->CreateWrapper(aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
+  return p.forget();
+}
+
+JSObject*
+AbortablePromise::WrapObject(JSContext* aCx)
+{
+  return MozAbortablePromiseBinding::Wrap(aCx, this);
+}
+
+/* static */ already_AddRefed<AbortablePromise>
+AbortablePromise::Constructor(const GlobalObject& aGlobal, PromiseInit& aInit,
+                              AbortCallback& aAbortCallback, ErrorResult& aRv)
+{
+  nsCOMPtr<nsIGlobalObject> global;
+  global = do_QueryInterface(aGlobal.GetAsSupports());
+  if (!global) {
+    aRv.Throw(NS_ERROR_UNEXPECTED);
+    return nullptr;
+  }
+
+  nsRefPtr<AbortablePromise> promise = new AbortablePromise(global);
+  promise->CreateWrapper(aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
+
+  promise->CallInitFunction(aGlobal, aInit, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
+
+  promise->mAbortCallback = &aAbortCallback;
+
+  return promise.forget();
+}
+
+void
+AbortablePromise::Abort()
+{
+  if (IsPending()) {
+    return;
+  }
+  MaybeReject(NS_ERROR_ABORT);
+
+  nsCOMPtr<nsIRunnable> runnable =
+    NS_NewRunnableMethod(this, &AbortablePromise::DoAbort);
+  Promise::DispatchToMainOrWorkerThread(runnable);
+}
+
+void
+AbortablePromise::DoAbort()
+{
+  if (mAbortCallback.HasWebIDLCallback()) {
+    ErrorResult rv;
+    mAbortCallback.GetWebIDLCallback()->Call(rv);
+    return;
+  }
+  mAbortCallback.GetXPCOMCallback()->Call();
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/promise/AbortablePromise.h
@@ -0,0 +1,66 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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 mozilla_dom_AbortablePromise_h__
+#define mozilla_dom_AbortablePromise_h__
+
+#include "js/TypeDecls.h"
+#include "mozilla/dom/Promise.h"
+#include "mozilla/dom/CallbackObject.h"
+
+namespace mozilla {
+namespace dom {
+
+class AbortCallback;
+class PromiseNativeAbortCallback;
+
+class AbortablePromise
+  : public Promise
+{
+public:
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(AbortablePromise, Promise)
+
+public:
+  // It is the same as Promise::Create except that this takes an extra
+  // aAbortCallback parameter to set the abort callback handler.
+  static already_AddRefed<AbortablePromise>
+  Create(nsIGlobalObject* aGlobal, PromiseNativeAbortCallback& aAbortCallback,
+         ErrorResult& aRv);
+
+protected:
+  // Constructor used to create native AbortablePromise with C++.
+  AbortablePromise(nsIGlobalObject* aGlobal,
+                   PromiseNativeAbortCallback& aAbortCallback);
+
+  // Constructor used to create AbortablePromise for JavaScript. It should be
+  // called by the static AbortablePromise::Constructor.
+  AbortablePromise(nsIGlobalObject* aGlobal);
+
+  virtual ~AbortablePromise();
+
+public:
+  virtual JSObject*
+  WrapObject(JSContext* aCx) MOZ_OVERRIDE;
+
+  static already_AddRefed<AbortablePromise>
+  Constructor(const GlobalObject& aGlobal, PromiseInit& aInit,
+              AbortCallback& aAbortCallback, ErrorResult& aRv);
+
+  void Abort();
+
+private:
+  void DoAbort();
+
+  // The callback functions to abort the promise.
+  CallbackObjectHolder<AbortCallback,
+                       PromiseNativeAbortCallback> mAbortCallback;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_AbortablePromise_h__
--- a/dom/promise/Promise.cpp
+++ b/dom/promise/Promise.cpp
@@ -320,36 +320,43 @@ JSObject*
 Promise::WrapObject(JSContext* aCx)
 {
   return PromiseBinding::Wrap(aCx, this);
 }
 
 already_AddRefed<Promise>
 Promise::Create(nsIGlobalObject* aGlobal, ErrorResult& aRv)
 {
+  nsRefPtr<Promise> p = new Promise(aGlobal);
+  p->CreateWrapper(aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
+  return p.forget();
+}
+
+void
+Promise::CreateWrapper(ErrorResult& aRv)
+{
   AutoJSAPI jsapi;
-  if (!jsapi.Init(aGlobal)) {
+  if (!jsapi.Init(mGlobal)) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
-    return nullptr;
+    return;
   }
   JSContext* cx = jsapi.cx();
 
-  nsRefPtr<Promise> p = new Promise(aGlobal);
-
   JS::Rooted<JS::Value> ignored(cx);
-  if (!WrapNewBindingObject(cx, p, &ignored)) {
+  if (!WrapNewBindingObject(cx, this, &ignored)) {
     JS_ClearPendingException(cx);
     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
-    return nullptr;
+    return;
   }
 
   // Need the .get() bit here to get template deduction working right
-  dom::PreserveWrapper(p.get());
-
-  return p.forget();
+  dom::PreserveWrapper(this);
 }
 
 void
 Promise::MaybeResolve(JSContext* aCx,
                       JS::Handle<JS::Value> aValue)
 {
   MaybeResolveInternal(aCx, aValue);
 }
@@ -478,64 +485,74 @@ Promise::CreateThenableFunction(JSContex
 
   return obj;
 }
 
 /* static */ already_AddRefed<Promise>
 Promise::Constructor(const GlobalObject& aGlobal,
                      PromiseInit& aInit, ErrorResult& aRv)
 {
-  JSContext* cx = aGlobal.Context();
-
   nsCOMPtr<nsIGlobalObject> global;
   global = do_QueryInterface(aGlobal.GetAsSupports());
   if (!global) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
     return nullptr;
   }
 
   nsRefPtr<Promise> promise = Create(global, aRv);
   if (aRv.Failed()) {
     return nullptr;
   }
 
+  promise->CallInitFunction(aGlobal, aInit, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
+
+  return promise.forget();
+}
+
+void
+Promise::CallInitFunction(const GlobalObject& aGlobal,
+                          PromiseInit& aInit, ErrorResult& aRv)
+{
+  JSContext* cx = aGlobal.Context();
+
   JS::Rooted<JSObject*> resolveFunc(cx,
-                                    CreateFunction(cx, aGlobal.Get(), promise,
+                                    CreateFunction(cx, aGlobal.Get(), this,
                                                    PromiseCallback::Resolve));
   if (!resolveFunc) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
-    return nullptr;
+    return;
   }
 
   JS::Rooted<JSObject*> rejectFunc(cx,
-                                   CreateFunction(cx, aGlobal.Get(), promise,
+                                   CreateFunction(cx, aGlobal.Get(), this,
                                                   PromiseCallback::Reject));
   if (!rejectFunc) {
     aRv.Throw(NS_ERROR_UNEXPECTED);
-    return nullptr;
+    return;
   }
 
   aInit.Call(resolveFunc, rejectFunc, aRv, CallbackObject::eRethrowExceptions);
   aRv.WouldReportJSException();
 
   if (aRv.IsJSException()) {
     JS::Rooted<JS::Value> value(cx);
     aRv.StealJSException(cx, &value);
 
     // we want the same behavior as this JS implementation:
     // function Promise(arg) { try { arg(a, b); } catch (e) { this.reject(e); }}
     if (!JS_WrapValue(cx, &value)) {
       aRv.Throw(NS_ERROR_UNEXPECTED);
-      return nullptr;
+      return;
     }
 
-    promise->MaybeRejectInternal(cx, value);
+    MaybeRejectInternal(cx, value);
   }
-
-  return promise.forget();
 }
 
 /* static */ already_AddRefed<Promise>
 Promise::Resolve(const GlobalObject& aGlobal,
                  JS::Handle<JS::Value> aValue, ErrorResult& aRv)
 {
   // If a Promise was passed, just return it.
   if (aValue.isObject()) {
--- a/dom/promise/Promise.h
+++ b/dom/promise/Promise.h
@@ -45,33 +45,31 @@ public:
   {
     MOZ_ASSERT(mPromise);
   }
 
   virtual bool
   Notify(JSContext* aCx, workers::Status aStatus) MOZ_OVERRIDE;
 };
 
-class Promise MOZ_FINAL : public nsISupports,
-                          public nsWrapperCache,
-                          public SupportsWeakPtr<Promise>
+class Promise : public nsISupports,
+                public nsWrapperCache,
+                public SupportsWeakPtr<Promise>
 {
   friend class NativePromiseCallback;
   friend class PromiseResolverTask;
   friend class PromiseTask;
   friend class PromiseReportRejectFeature;
   friend class PromiseWorkerProxy;
   friend class PromiseWorkerProxyRunnable;
   friend class RejectPromiseCallback;
   friend class ResolvePromiseCallback;
   friend class ThenableResolverTask;
   friend class WrapperPromiseCallback;
 
-  ~Promise();
-
 public:
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Promise)
   MOZ_DECLARE_REFCOUNTED_TYPENAME(Promise)
 
   // Promise creation tries to create a JS reflector for the Promise, so is
   // fallible.  Furthermore, we don't want to do JS-wrapping on a 0-refcount
   // object, so we addref before doing that and return the addrefed pointer
@@ -154,21 +152,42 @@ public:
       const Sequence<JS::Value>& aIterable, ErrorResult& aRv);
 
   static already_AddRefed<Promise>
   Race(const GlobalObject& aGlobal,
        const Sequence<JS::Value>& aIterable, ErrorResult& aRv);
 
   void AppendNativeHandler(PromiseNativeHandler* aRunnable);
 
-private:
+protected:
   // Do NOT call this unless you're Promise::Create.  I wish we could enforce
   // that from inside this class too, somehow.
   explicit Promise(nsIGlobalObject* aGlobal);
 
+  virtual ~Promise();
+
+  // Queue an async task to current main or worker thread.
+  static void
+  DispatchToMainOrWorkerThread(nsIRunnable* aRunnable);
+
+  // Do JS-wrapping after Promise creation.
+  void CreateWrapper(ErrorResult& aRv);
+
+  // Create the JS resolving functions of resolve() and reject(). And provide
+  // references to the two functions by calling PromiseInit passed from Promise
+  // constructor.
+  void CallInitFunction(const GlobalObject& aGlobal, PromiseInit& aInit,
+                        ErrorResult& aRv);
+
+  bool IsPending()
+  {
+    return mResolvePending;
+  }
+
+private:
   friend class PromiseDebugging;
 
   enum PromiseState {
     Pending,
     Resolved,
     Rejected
   };
 
@@ -184,20 +203,16 @@ private:
     mState = aState;
   }
 
   void SetResult(JS::Handle<JS::Value> aValue)
   {
     mResult = aValue;
   }
 
-  // Queue an async task to current main or worker thread.
-  static void
-  DispatchToMainOrWorkerThread(nsIRunnable* aRunnable);
-
   // This method processes promise's resolve/reject callbacks with promise's
   // result. It's executed when the resolver.resolve() or resolver.reject() is
   // called or when the promise already has a result and new callbacks are
   // appended by then(), catch() or done().
   void RunTask();
 
   void RunResolveTask(JS::Handle<JS::Value> aValue,
                       Promise::PromiseState aState,
--- a/dom/promise/PromiseCallback.cpp
+++ b/dom/promise/PromiseCallback.cpp
@@ -15,23 +15,17 @@ namespace dom {
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(PromiseCallback)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(PromiseCallback)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PromiseCallback)
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
-NS_IMPL_CYCLE_COLLECTION_CLASS(PromiseCallback)
-
-NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(PromiseCallback)
-NS_IMPL_CYCLE_COLLECTION_UNLINK_END
-
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(PromiseCallback)
-NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+NS_IMPL_CYCLE_COLLECTION_0(PromiseCallback)
 
 PromiseCallback::PromiseCallback()
 {
 }
 
 PromiseCallback::~PromiseCallback()
 {
 }
new file mode 100644
--- /dev/null
+++ b/dom/promise/PromiseNativeAbortCallback.h
@@ -0,0 +1,36 @@
+/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* 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 mozilla_dom_PromiseNativeAbortCallback_h
+#define mozilla_dom_PromiseNativeAbortCallback_h
+
+#include "nsISupports.h"
+
+namespace mozilla {
+namespace dom {
+
+/*
+ * PromiseNativeAbortCallback allows C++ to react to an AbortablePromise being
+ * aborted.
+ */
+class PromiseNativeAbortCallback : public nsISupports
+{
+protected:
+  virtual ~PromiseNativeAbortCallback()
+  { }
+
+public:
+  // Implemented in AbortablePromise.cpp.
+  NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+  NS_DECL_CYCLE_COLLECTION_CLASS(PromiseNativeAbortCallback)
+
+  virtual void Call() = 0;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_PromiseNativeAbortCallback_h
--- a/dom/promise/moz.build
+++ b/dom/promise/moz.build
@@ -1,22 +1,25 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=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/.
 
 EXPORTS.mozilla.dom += [
+    'AbortablePromise.h',
     'Promise.h',
     'PromiseDebugging.h',
+    'PromiseNativeAbortCallback.h',
     'PromiseNativeHandler.h',
     'PromiseWorkerProxy.h',
 ]
 
 UNIFIED_SOURCES += [
+    'AbortablePromise.cpp',
     'Promise.cpp',
     'PromiseCallback.cpp',
     'PromiseDebugging.cpp'
 ]
 
 FAIL_ON_WARNINGS = True
 
 LOCAL_INCLUDES += [
--- a/dom/promise/tests/mochitest.ini
+++ b/dom/promise/tests/mochitest.ini
@@ -1,6 +1,7 @@
 [DEFAULT]
 
 [test_bug883683.html]
 [test_promise.html]
 [test_promise_utils.html]
 [test_resolve.html]
+[test_abortable_promise.html]
new file mode 100644
--- /dev/null
+++ b/dom/promise/tests/test_abortable_promise.html
@@ -0,0 +1,115 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<html>
+<head>
+  <title>Promise.resolve(anything) Test</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script type="application/javascript"><!--
+
+SimpleTest.waitForExplicitFinish();
+SpecialPowers.pushPrefEnv({"set": [["dom.abortablepromise.enabled", true]]},
+                          runTest);
+var gTests = [testPending, testResolved, testRejected];
+
+function runTest() {
+   if (gTests.length == 0) {
+     SimpleTest.finish();
+     return;
+   }
+   new Promise(gTests.shift()).then(runTest, SimpleTest.finish);
+}
+
+// Aborting pending promise should first reject the promise and then call the
+// abortable callback.
+// The test succeeds once both the rejection handler and the abort handler have
+// been called.
+function testPending(succeed, fail) {
+  var rejected = false;
+  var aborted = false;
+
+  var p = new MozAbortablePromise(function(resolve, reject) {
+    // Wait for a while so that the promise can be aborted before resolved.
+    SimpleTest.executeSoon(function() {
+      resolve(0);
+    });
+  }, function abortable() {
+    aborted = true;
+    ok(true, "Promise aborted.");
+    if (rejected) {
+      succeed();
+    }
+  });
+
+  p.then(function() {
+    ok(false, "Failed to abort pending promise.");
+    fail();
+  }, function(what) {
+    rejected = true;
+    var isAbortException = (what && what.name) == "NS_ERROR_ABORT";
+    ok(isAbortException, "Should have NS_ERROR_ABORT exception");
+    if (!isAbortException) {
+      fail();
+    }
+    if (aborted) {
+      succeed();
+    }
+  });
+
+  // Abort the promise on creation.
+  p.abort();
+}
+
+// Do nothing when aborting resolved promise.
+function testResolved(succeed, fail) {
+  var p = new MozAbortablePromise(function(resolve, reject) {
+    resolve();
+  }, function abortable() {
+    ok(false, "Should not abort a resolved promise.");
+    fail();
+  });
+  p.then(function() {
+    ok(true, "Promise resolved.");
+    // Wait for a while to ensure abort handle won't be called.
+    setTimeout(succeed, 1000);
+  }, function(what) {
+    ok(false, "Failed to resolve promise: " + what);
+    fail();
+  });
+  p.abort();
+}
+
+// Do nothing when aborting rejected promise.
+function testRejected(succeed, fail) {
+  var p = new MozAbortablePromise(function(resolve, reject) {
+    reject(0);
+  }, function abortable() {
+    ok(false, "Should not abort a rejected promise.");
+    fail();
+  });
+
+  p.then(function() {
+    ok(false, "Failed to reject promise.");
+    fail();
+  }, function(what) {
+    is(what, 0, "promise rejected: " + what);
+    // Wait for a while to ensure abort handle won't be called.
+    setTimeout(succeed, 1000);
+  });
+  p.abort();
+}
+// -->
+</script>
+</pre>
+</body>
+</html>
+
--- a/dom/system/NetworkGeolocationProvider.js
+++ b/dom/system/NetworkGeolocationProvider.js
@@ -411,31 +411,30 @@ WifiGeoPositionProvider.prototype = {
                     .getService(Ci.nsIRadioInterfaceLayer);
       let service = Cc["@mozilla.org/mobileconnection/mobileconnectionservice;1"]
                     .getService(Ci.nsIMobileConnectionService);
 
       let numInterfaces = radioService.numRadioInterfaces;
       let result = [];
       for (let i = 0; i < numInterfaces; i++) {
         LOG("Looking for SIM in slot:" + i + " of " + numInterfaces);
-        let radio = radioService.getRadioInterface(i);
-        let iccInfo = radio.rilContext.iccInfo;
         let voice = service.getVoiceConnectionInfo(i);
         let cell = voice.cell;
         let type = voice.type;
+        let network = voice.network;
 
-        if (iccInfo && cell && type) {
+        if (network && cell && type) {
           if (type === "gsm" || type === "gprs" || type === "edge") {
             type = "gsm";
           } else {
             type = "wcdma";
           }
           result.push({ radio: type,
-                      mobileCountryCode: iccInfo.mcc,
-                      mobileNetworkCode: iccInfo.mnc,
+                      mobileCountryCode: voice.network.mcc,
+                      mobileNetworkCode: voice.network.mnc,
                       locationAreaCode: cell.gsmLocationAreaCode,
                       cellId: cell.gsmCellId });
         }
       }
       return result;
     } catch (e) {
       return null;
     }
--- a/dom/tests/mochitest/bugs/mochitest.ini
+++ b/dom/tests/mochitest/bugs/mochitest.ini
@@ -52,17 +52,17 @@ skip-if = buildapp == 'mulet' || buildap
 [test_bug335976.xhtml]
 skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug))
 [test_bug342448.html]
 [test_bug345521.html]
 [test_bug346659.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_bug351601.html]
 [test_bug369306.html]
-skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'android' || e10s #TIMED_OUT # b2g-debug(test timed out, can't focus back from popup window to opener?) b2g-desktop(test timed out, can't focus back from popup window to opener?)
+skip-if = buildapp == 'mulet' || (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'android' || e10s #TIMED_OUT # b2g-debug(test timed out, can't focus back from popup window to opener?) b2g-desktop(test timed out, can't focus back from popup window to opener?)
 [test_bug370098.html]
 [test_bug377539.html]
 [test_bug384122.html]
 [test_bug389366.html]
 [test_bug38959.html]
 skip-if = (buildapp == 'b2g' && toolkit != 'gonk') #Bug 931116, b2g desktop specific, initial triage
 [test_bug393974.html]
 [test_bug394769.html]
@@ -158,10 +158,10 @@ skip-if = toolkit == 'android' || e10s #
 [test_onerror_message.html]
 [test_protochains.html]
 [test_resize_move_windows.html]
 skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e10s #Windows can't change size and position on Android # b2g(Windows can't change size and position on B2G) b2g-debug(Windows can't change size and position on B2G) b2g-desktop(Windows can't change size and position on B2G)
 [test_sizetocontent_clamp.html]
 skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e10s #Windows can't change size on Android # b2g(Windows can't change size on B2G) b2g-debug(Windows can't change size on B2G) b2g-desktop(Windows can't change size on B2G)
 [test_toJSON.html]
 [test_window_bar.html]
-skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s
+skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e10s
 [test_bug1022869.html]
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -114,16 +114,18 @@ var legacyMozPrefixedInterfaces =
   ];
 // IMPORTANT: Do not change the list above without review from a DOM peer,
 //            except to remove items from it!
 
 // IMPORTANT: Do not change the list below without review from a DOM peer!
 var interfaceNamesInGlobalScope =
   [
 // IMPORTANT: Do not change this list without review from a DOM peer!
+    {name: "MozAbortablePromise", pref: "dom.abortablepromise.enabled"},
+// IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "AlarmsManager", pref: "dom.mozAlarms.enabled"},
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "AnalyserNode",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "AnimationEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     {name: "Animation", pref: "dom.animations-api.core.enabled"},
 // IMPORTANT: Do not change this list without review from a DOM peer!
new file mode 100644
--- /dev/null
+++ b/dom/webidl/AbortablePromise.webidl
@@ -0,0 +1,19 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/.
+ */
+
+callback AbortCallback = void ();
+
+[Constructor(PromiseInit init, AbortCallback abortCallback),
+ Pref="dom.abortablepromise.enabled"]
+interface MozAbortablePromise : _Promise {
+  /*
+   * Aborts the promise.
+   * If the promise has not been resolved or rejected, it should be rejected
+   * with an Exception of type abort and then AbortCallback is called
+   * asynchronously. Otherwise, nothing should be done.
+   */
+  void abort();
+};
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -11,16 +11,17 @@ GENERATED_WEBIDL_FILES = [
 PREPROCESSED_WEBIDL_FILES = [
     'Crypto.webidl',
     'HTMLMediaElement.webidl',
     'Navigator.webidl',
     'Window.webidl',
 ]
 
 WEBIDL_FILES = [
+    'AbortablePromise.webidl',
     'AbstractWorker.webidl',
     'ActivityRequestHandler.webidl',
     'AlarmsManager.webidl',
     'AnalyserNode.webidl',
     'Animatable.webidl',
     'Animation.webidl',
     'AnimationEffect.webidl',
     'AnimationEvent.webidl',
--- a/dom/workers/ServiceWorkerRegistration.cpp
+++ b/dom/workers/ServiceWorkerRegistration.cpp
@@ -103,17 +103,17 @@ namespace {
 
 class UnregisterCallback MOZ_FINAL : public nsIServiceWorkerUnregisterCallback
 {
   nsRefPtr<Promise> mPromise;
 
 public:
   NS_DECL_ISUPPORTS
 
-  UnregisterCallback(Promise* aPromise)
+  explicit UnregisterCallback(Promise* aPromise)
     : mPromise(aPromise)
   {
     MOZ_ASSERT(mPromise);
   }
 
   NS_IMETHODIMP
   UnregisterSucceeded(bool aState)
   {
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -1112,30 +1112,30 @@ public:
    */
   static TemporaryRef<ScaledFont>
     CreateScaledFontWithCairo(const NativeFont &aNativeFont, Float aSize, cairo_scaled_font_t* aScaledFont);
 
   /**
    * This creates a simple data source surface for a certain size. It allocates
    * new memory for the surface. This memory is freed when the surface is
    * destroyed.  The caller is responsible for handing the case where nullptr
-   * is returned.
+   * is returned. The surface is not zeroed unless requested.
    */
   static TemporaryRef<DataSourceSurface>
-    CreateDataSourceSurface(const IntSize &aSize, SurfaceFormat aFormat);
+    CreateDataSourceSurface(const IntSize &aSize, SurfaceFormat aFormat, bool aZero = false);
 
   /**
    * This creates a simple data source surface for a certain size with a
    * specific stride, which must be large enough to fit all pixels.
    * It allocates new memory for the surface. This memory is freed when
    * the surface is destroyed.  The caller is responsible for handling the case
-   * where nullptr is returned.
+   * where nullptr is returned. The surface is not zeroed unless requested.
    */
   static TemporaryRef<DataSourceSurface>
-    CreateDataSourceSurfaceWithStride(const IntSize &aSize, SurfaceFormat aFormat, int32_t aStride);
+    CreateDataSourceSurfaceWithStride(const IntSize &aSize, SurfaceFormat aFormat, int32_t aStride, bool aZero = false);
 
   /**
    * This creates a simple data source surface for some existing data. It will
    * wrap this data and the data for this source surface. The caller is
    * responsible for deallocating the memory only after destruction of the
    * surface.
    */
   static TemporaryRef<DataSourceSurface>
--- a/gfx/2d/DataSurfaceHelpers.h
+++ b/gfx/2d/DataSurfaceHelpers.h
@@ -43,16 +43,18 @@ SurfaceToPackedBGRA(DataSourceSurface *a
  * color components).
  */
 uint8_t*
 SurfaceToPackedBGR(DataSourceSurface *aSurface);
 
 /**
  * Clears all the bytes in a DataSourceSurface's data array to zero (so to
  * transparent black for SurfaceFormat::B8G8R8A8, for example).
+ * Note that DataSourceSurfaces can be initialized to zero, which is
+ * more efficient than zeroing the surface after initialization.
  */
 void
 ClearDataSourceSurface(DataSourceSurface *aSurface);
 
 /**
  * Multiplies aStride and aHeight and makes sure the result is limited to
  * something sane. To keep things consistent, this should always be used
  * wherever we allocate a buffer based on surface stride and height.
--- a/gfx/2d/DrawTargetCG.cpp
+++ b/gfx/2d/DrawTargetCG.cpp
@@ -1353,19 +1353,18 @@ DrawTargetCG::Init(BackendType aType,
     size_t bufLen = BufferSizeFromStrideAndHeight(aStride, aSize.height);
     if (bufLen == 0) {
       mColorSpace = nullptr;
       mCg = nullptr;
       return false;
     }
     static_assert(sizeof(decltype(mData[0])) == 1,
                   "mData.Realloc() takes an object count, so its objects must be 1-byte sized if we use bufLen");
-    mData.Realloc(/* actually an object count */ bufLen);
+    mData.Realloc(/* actually an object count */ bufLen, true);
     aData = static_cast<unsigned char*>(mData);
-    memset(aData, 0, bufLen);
   }
 
   mSize = aSize;
 
   if (aType == BackendType::COREGRAPHICS_ACCELERATED) {
     RefPtr<MacIOSurface> ioSurface = MacIOSurface::CreateIOSurface(aSize.width, aSize.height);
     mCg = ioSurface->CreateIOSurfaceContext();
     // If we don't have the symbol for 'CreateIOSurfaceContext' mCg will be null
--- a/gfx/2d/Factory.cpp
+++ b/gfx/2d/Factory.cpp
@@ -695,44 +695,46 @@ Factory::CreateWrappingDataSourceSurface
     return newSurf.forget();
   }
 
   return nullptr;
 }
 
 TemporaryRef<DataSourceSurface>
 Factory::CreateDataSourceSurface(const IntSize &aSize,
-                                 SurfaceFormat aFormat)
+                                 SurfaceFormat aFormat,
+                                 bool aZero)
 {
   if (!CheckSurfaceSize(aSize)) {
     gfxWarning() << "CreateDataSourceSurface failed with bad size";
     return nullptr;
   }
 
   RefPtr<SourceSurfaceAlignedRawData> newSurf = new SourceSurfaceAlignedRawData();
-  if (newSurf->Init(aSize, aFormat)) {
+  if (newSurf->Init(aSize, aFormat, aZero)) {
     return newSurf.forget();
   }
 
   gfxWarning() << "CreateDataSourceSurface failed in init";
   return nullptr;
 }
 
 TemporaryRef<DataSourceSurface>
 Factory::CreateDataSourceSurfaceWithStride(const IntSize &aSize,
                                            SurfaceFormat aFormat,
-                                           int32_t aStride)
+                                           int32_t aStride,
+                                           bool aZero)
 {
   if (aStride < aSize.width * BytesPerPixel(aFormat)) {
     gfxWarning() << "CreateDataSourceSurfaceWithStride failed with bad stride";
     return nullptr;
   }
 
   RefPtr<SourceSurfaceAlignedRawData> newSurf = new SourceSurfaceAlignedRawData();
-  if (newSurf->InitWithStride(aSize, aFormat, aStride)) {
+  if (newSurf->InitWithStride(aSize, aFormat, aStride, aZero)) {
     return newSurf.forget();
   }
 
   gfxWarning() << "CreateDataSourceSurfaceWithStride failed to initialize";
   return nullptr;
 }
 
 TemporaryRef<DrawEventRecorder>
--- a/gfx/2d/FilterNodeSoftware.cpp
+++ b/gfx/2d/FilterNodeSoftware.cpp
@@ -487,26 +487,23 @@ GetDataSurfaceInRect(SourceSurface *aSur
     return aSurface ? aSurface->GetDataSurface() : nullptr;
   }
 
   IntRect intersect = sourceRect.Intersect(aDestRect);
   IntRect intersectInSourceSpace = intersect - sourceRect.TopLeft();
   IntRect intersectInDestSpace = intersect - aDestRect.TopLeft();
   SurfaceFormat format = aSurface ? aSurface->GetFormat() : SurfaceFormat(SurfaceFormat::B8G8R8A8);
 
+  bool clear = aEdgeMode == EDGE_MODE_NONE && !aSurfaceRect.Contains(aDestRect);
   RefPtr<DataSourceSurface> target =
-    Factory::CreateDataSourceSurface(aDestRect.Size(), format);
+    Factory::CreateDataSourceSurface(aDestRect.Size(), format, clear);
   if (MOZ2D_WARN_IF(!target)) {
     return nullptr;
   }
 
-  if (aEdgeMode == EDGE_MODE_NONE && !aSurfaceRect.Contains(aDestRect)) {
-    ClearDataSourceSurface(target);
-  }
-
   if (!aSurface) {
     return target.forget();
   }
 
   RefPtr<DataSourceSurface> dataSource = aSurface->GetDataSurface();
   MOZ_ASSERT(dataSource);
 
   if (aEdgeMode == EDGE_MODE_WRAP) {
@@ -2366,21 +2363,20 @@ FilterNodeConvolveMatrixSoftware::DoRend
 
   if (!input) {
     return nullptr;
   }
 
   DebugOnlyAutoColorSamplingAccessControl accessControl(input);
 
   RefPtr<DataSourceSurface> target =
-    Factory::CreateDataSourceSurface(aRect.Size(), SurfaceFormat::B8G8R8A8);
+    Factory::CreateDataSourceSurface(aRect.Size(), SurfaceFormat::B8G8R8A8, true);
   if (MOZ2D_WARN_IF(!target)) {
     return nullptr;
   }
-  ClearDataSourceSurface(target);
 
   IntPoint offset = aRect.TopLeft() - srcRect.TopLeft();
 
   uint8_t* sourceData = DataAtOffset(input, offset);
   int32_t sourceStride = input->Stride();
   uint8_t* targetData = target->GetData();
   int32_t targetStride = target->Stride();
 
@@ -2771,25 +2767,23 @@ FilterNodeCompositeSoftware::SetAttribut
 }
 
 TemporaryRef<DataSourceSurface>
 FilterNodeCompositeSoftware::Render(const IntRect& aRect)
 {
   RefPtr<DataSourceSurface> start =
     GetInputDataSourceSurface(IN_COMPOSITE_IN_START, aRect, NEED_COLOR_CHANNELS);
   RefPtr<DataSourceSurface> dest =
-    Factory::CreateDataSourceSurface(aRect.Size(), SurfaceFormat::B8G8R8A8);
+    Factory::CreateDataSourceSurface(aRect.Size(), SurfaceFormat::B8G8R8A8, !start);
   if (MOZ2D_WARN_IF(!dest)) {
     return nullptr;
   }
 
   if (start) {
     CopyRect(start, dest, aRect - aRect.TopLeft(), IntPoint());
-  } else {
-    ClearDataSourceSurface(dest);
   }
 
   for (size_t inputIndex = 1; inputIndex < NumberOfSetInputs(); inputIndex++) {
     RefPtr<DataSourceSurface> input =
       GetInputDataSourceSurface(IN_COMPOSITE_IN_START + inputIndex, aRect, NEED_COLOR_CHANNELS);
     if (input) {
       FilterProcessing::ApplyComposition(input, dest, mOperator);
     } else {
--- a/gfx/2d/SourceSurfaceRawData.cpp
+++ b/gfx/2d/SourceSurfaceRawData.cpp
@@ -39,48 +39,50 @@ SourceSurfaceRawData::GuaranteePersistan
   mRawData = new uint8_t[mStride * mSize.height];
 
   memcpy(mRawData, oldData, mStride * mSize.height);
   mOwnData = true;
 }
 
 bool
 SourceSurfaceAlignedRawData::Init(const IntSize &aSize,
-                                  SurfaceFormat aFormat)
+                                  SurfaceFormat aFormat,
+                                  bool aZero)
 {
   mFormat = aFormat;
   mStride = GetAlignedStride<16>(aSize.width * BytesPerPixel(aFormat));
 
   size_t bufLen = BufferSizeFromStrideAndHeight(mStride, aSize.height);
   if (bufLen > 0) {
     static_assert(sizeof(decltype(mArray[0])) == 1,
                   "mArray.Realloc() takes an object count, so its objects must be 1-byte sized if we use bufLen");
-    mArray.Realloc(/* actually an object count */ bufLen);
+    mArray.Realloc(/* actually an object count */ bufLen, aZero);
     mSize = aSize;
   } else {
     mArray.Dealloc();
     mSize.SizeTo(0, 0);
   }
 
   return mArray != nullptr;
 }
 
 bool
 SourceSurfaceAlignedRawData::InitWithStride(const IntSize &aSize,
                                             SurfaceFormat aFormat,
-                                            int32_t aStride)
+                                            int32_t aStride,
+                                            bool aZero)
 {
   mFormat = aFormat;
   mStride = aStride;
 
   size_t bufLen = BufferSizeFromStrideAndHeight(mStride, aSize.height);
   if (bufLen > 0) {
     static_assert(sizeof(decltype(mArray[0])) == 1,
                   "mArray.Realloc() takes an object count, so its objects must be 1-byte sized if we use bufLen");
-    mArray.Realloc(/* actually an object count */ bufLen);
+    mArray.Realloc(/* actually an object count */ bufLen, aZero);
     mSize = aSize;
   } else {
     mArray.Dealloc();
     mSize.SizeTo(0, 0);
   }
 
   return mArray != nullptr;
 }
--- a/gfx/2d/SourceSurfaceRawData.h
+++ b/gfx/2d/SourceSurfaceRawData.h
@@ -51,20 +51,22 @@ public:
   virtual uint8_t *GetData() { return mArray; }
   virtual int32_t Stride() { return mStride; }
 
   virtual SurfaceType GetType() const { return SurfaceType::DATA; }
   virtual IntSize GetSize() const { return mSize; }
   virtual SurfaceFormat GetFormat() const { return mFormat; }
 
   bool Init(const IntSize &aSize,
-            SurfaceFormat aFormat);
+            SurfaceFormat aFormat,
+            bool aZero);
   bool InitWithStride(const IntSize &aSize,
                       SurfaceFormat aFormat,
-                      int32_t aStride);
+                      int32_t aStride,
+                      bool aZero);
 
 private:
   AlignedArray<uint8_t> mArray;
   int32_t mStride;
   SurfaceFormat mFormat;
   IntSize mSize;
 };
 
--- a/gfx/2d/Tools.h
+++ b/gfx/2d/Tools.h
@@ -98,21 +98,21 @@ struct AlignedArray
   typedef T value_type;
 
   AlignedArray()
     : mPtr(nullptr)
     , mStorage(nullptr)
   {
   }
 
-  explicit MOZ_ALWAYS_INLINE AlignedArray(size_t aCount)
+  explicit MOZ_ALWAYS_INLINE AlignedArray(size_t aCount, bool aZero = false)
     : mStorage(nullptr)
     , mCount(0)
   {
-    Realloc(aCount);
+    Realloc(aCount, aZero);
   }
 
   MOZ_ALWAYS_INLINE ~AlignedArray()
   {
     Dealloc();
   }
 
   void Dealloc()
@@ -133,30 +133,34 @@ struct AlignedArray
     }
 #endif
 
     delete [] mStorage;
     mStorage = nullptr;
     mPtr = nullptr;
   }
 
-  MOZ_ALWAYS_INLINE void Realloc(size_t aCount)
+  MOZ_ALWAYS_INLINE void Realloc(size_t aCount, bool aZero = false)
   {
     delete [] mStorage;
     CheckedInt32 storageByteCount =
       CheckedInt32(sizeof(T)) * aCount + (alignment - 1);
     if (!storageByteCount.isValid()) {
       mStorage = nullptr;
       mPtr = nullptr;
       mCount = 0;
       return;
     }
     // We don't create an array of T here, since we don't want ctors to be
     // invoked at the wrong places if we realign below.
-    mStorage = new (std::nothrow) uint8_t[storageByteCount.value()];
+    if (aZero) {
+      mStorage = static_cast<uint8_t *>(calloc(1, storageByteCount.value()));
+    } else {
+      mStorage = new (std::nothrow) uint8_t[storageByteCount.value()];
+    }
     if (!mStorage) {
       mStorage = nullptr;
       mPtr = nullptr;
       mCount = 0;
       return;
     }
     if (uintptr_t(mStorage) % alignment) {
       // Our storage does not start at a <alignment>-byte boundary. Make sure mPtr does!
--- a/gfx/layers/apz/src/AsyncPanZoomController.cpp
+++ b/gfx/layers/apz/src/AsyncPanZoomController.cpp
@@ -809,16 +809,24 @@ AsyncPanZoomController::AssertOnControll
     // If the assertion below fires, it is possible that it is because
     // sControllerThread is not actually the controller thread.
     sControllerThread = PR_GetCurrentThread();
     sControllerThreadDetermined = true;
   }
   MOZ_ASSERT(sControllerThread == PR_GetCurrentThread());
 }
 
+void
+AsyncPanZoomController::AssertOnCompositorThread()
+{
+  if (GetThreadAssertionsEnabled()) {
+    Compositor::AssertOnCompositorThread();
+  }
+}
+
 /*static*/ void
 AsyncPanZoomController::InitializeGlobalState()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   static bool sInitialized = false;
   if (sInitialized)
     return;
@@ -865,19 +873,17 @@ AsyncPanZoomController::AsyncPanZoomCont
 
 AsyncPanZoomController::~AsyncPanZoomController() {
   MOZ_COUNT_DTOR(AsyncPanZoomController);
 }
 
 PCompositorParent*
 AsyncPanZoomController::GetSharedFrameMetricsCompositor()
 {
-  if (GetThreadAssertionsEnabled()) {
-    Compositor::AssertOnCompositorThread();
-  }
+  AssertOnCompositorThread();
 
   if (mSharingFrameMetricsAcrossProcesses) {
     const CompositorParent::LayerTreeState* state = CompositorParent::GetIndirectShadowTree(mLayersId);
     // |state| may be null here if the CrossProcessCompositorParent has already been destroyed.
     return state ? state->mCrossProcessParent : nullptr;
   }
   return mCompositorParent.get();
 }
@@ -894,16 +900,18 @@ AsyncPanZoomController::GetGestureEventL
   MonitorAutoLock lock(mRefPtrMonitor);
   nsRefPtr<GestureEventListener> listener = mGestureEventListener;
   return listener.forget();
 }
 
 void
 AsyncPanZoomController::Destroy()
 {
+  AssertOnCompositorThread();
+
   CancelAnimation();
 
   mTouchBlockQueue.Clear();
 
   { // scope the lock
     MonitorAutoLock lock(mRefPtrMonitor);
     mGeckoContentController = nullptr;
     mGestureEventListener = nullptr;
@@ -2352,16 +2360,18 @@ AsyncPanZoomController::FireAsyncScrollO
     SendAsyncScrollEvent();
   }
   mAsyncScrollTimeoutTask = nullptr;
 }
 
 bool AsyncPanZoomController::UpdateAnimation(const TimeStamp& aSampleTime,
                                              Vector<Task*>* aOutDeferredTasks)
 {
+  AssertOnCompositorThread();
+
   // This function may get called multiple with the same sample time, because
   // there may be multiple layers with this APZC, and each layer invokes this
   // function during composition. However we only want to do one animation step
   // per composition so we need to deduplicate these calls first.
   if (mLastSampleTime == aSampleTime) {
     return false;
   }
   TimeDuration sampleTimeDelta = aSampleTime - mLastSampleTime;
@@ -2424,16 +2434,18 @@ void AsyncPanZoomController::GetOverscro
   // Combine the transformations into a matrix.
   ScreenPoint screenTranslation = translation * mFrameMetrics.GetZoom();
   *aTransform = Matrix4x4().Scale(scaleX, scaleY, 1)
                            .PostTranslate(screenTranslation.x, screenTranslation.y, 0);
 }
 
 bool AsyncPanZoomController::AdvanceAnimations(const TimeStamp& aSampleTime)
 {
+  AssertOnCompositorThread();
+
   // The eventual return value of this function. The compositor needs to know
   // whether or not to advance by a frame as soon as it can. For example, if a
   // fling is happening, it has to keep compositing so that the animation is
   // smooth. If an animation frame is requested, it is the compositor's
   // responsibility to schedule a composite.
   mAsyncTransformAppliedToContent = false;
   bool requestAnimationFrame = false;
   Vector<Task*> deferredTasks;
@@ -2569,16 +2581,18 @@ Matrix4x4 AsyncPanZoomController::GetTra
 
   float zoomChange = mLastContentPaintMetrics.GetZoom().scale / mLastDispatchedPaintMetrics.GetZoom().scale;
 
   return Matrix4x4().Translate(scrollChange.x, scrollChange.y, 0) *
          Matrix4x4().Scale(zoomChange, zoomChange, 1);
 }
 
 void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aLayerMetrics, bool aIsFirstPaint) {
+  AssertOnCompositorThread();
+
   ReentrantMonitorAutoEnter lock(mMonitor);
   bool isDefault = mFrameMetrics.IsDefault();
 
   mLastContentPaintMetrics = aLayerMetrics;
   UpdateTransformScale();
 
   mFrameMetrics.mMayHaveTouchListeners = aLayerMetrics.mMayHaveTouchListeners;
   mFrameMetrics.mMayHaveTouchCaret = aLayerMetrics.mMayHaveTouchCaret;
--- a/gfx/layers/apz/src/AsyncPanZoomController.h
+++ b/gfx/layers/apz/src/AsyncPanZoomController.h
@@ -1100,21 +1100,27 @@ public:
    * In the gtest environment everything runs on one thread, so we
    * shouldn't assert that we're on a particular thread. This enables
    * that behaviour.
    */
   static void SetThreadAssertionsEnabled(bool aEnabled);
   static bool GetThreadAssertionsEnabled();
   /**
    * This can be used to assert that the current thread is the
-   * controller/UI thread (on which input events are received.
+   * controller/UI thread (on which input events are received).
    * This does nothing if thread assertions are disabled.
    */
   static void AssertOnControllerThread();
   /**
+   * This can be used to assert that the current thread is the
+   * compositor thread (which applies the async transform).
+   * This does nothing if thread assertions are disabled.
+   */
+  static void AssertOnCompositorThread();
+  /**
    * Set an extra offset for testing async scrolling.
    */
   void SetTestAsyncScrollOffset(const CSSPoint& aPoint)
   {
     mTestAsyncScrollOffset = aPoint;
   }
 
   void MarkAsyncTransformAppliedToContent()
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -144,16 +144,22 @@ CompositorThreadHolder::CreateCompositor
   /* Timeout values are powers-of-two to enable us get better data.
      128ms is chosen for transient hangs because 8Hz should be the minimally
      acceptable goal for Compositor responsiveness (normal goal is 60Hz). */
   options.transient_hang_timeout = 128; // milliseconds
   /* 2048ms is chosen for permanent hangs because it's longer than most
    * Compositor hangs seen in the wild, but is short enough to not miss getting
    * native hang stacks. */
   options.permanent_hang_timeout = 2048; // milliseconds
+#if defined(_WIN32)
+  /* With d3d9 the compositor thread creates native ui, see DeviceManagerD3D9. As
+   * such the thread is a gui thread, and must process a windows message queue or
+   * risk deadlocks. Chromium message loop TYPE_UI does exactly what we need. */
+  options.message_loop_type = MessageLoop::TYPE_UI;
+#endif
 
   if (!compositorThread->StartWithOptions(options)) {
     delete compositorThread;
     return nullptr;
   }
 
   CreateCompositorMap();
 
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -273,16 +273,17 @@ gfxPlatform::gfxPlatform()
     mBidiNumeralOption = UNINITIALIZED_VALUE;
 
     mSkiaGlue = nullptr;
 
     uint32_t canvasMask = BackendTypeBit(BackendType::CAIRO) | BackendTypeBit(BackendType::SKIA);
     uint32_t contentMask = BackendTypeBit(BackendType::CAIRO);
     InitBackendPrefs(canvasMask, BackendType::CAIRO,
                      contentMask, BackendType::CAIRO);
+    mTotalSystemMemory = mozilla::hal::GetTotalSystemMemory();
 }
 
 gfxPlatform*
 gfxPlatform::GetPlatform()
 {
     if (!gPlatform) {
         Init();
     }
@@ -847,24 +848,22 @@ gfxPlatform::InitializeSkiaCacheLimits()
     bool usingDynamicCache = gfxPrefs::CanvasSkiaGLDynamicCache();
     int cacheItemLimit = gfxPrefs::CanvasSkiaGLCacheItems();
     int cacheSizeLimit = gfxPrefs::CanvasSkiaGLCacheSize();
 
     // Prefs are in megabytes, but we want the sizes in bytes
     cacheSizeLimit *= 1024*1024;
 
     if (usingDynamicCache) {
-      uint32_t totalMemory = mozilla::hal::GetTotalSystemMemory();
-
-      if (totalMemory < 512*1024*1024) {
+      if (mTotalSystemMemory < 512*1024*1024) {
         // We need a very minimal cache on anything smaller than 512mb.
         // Note the large jump as we cross 512mb (from 2mb to 32mb).
         cacheSizeLimit = 2*1024*1024;
-      } else if (totalMemory > 0) {
-        cacheSizeLimit = totalMemory / 16;
+      } else if (mTotalSystemMemory > 0) {
+        cacheSizeLimit = mTotalSystemMemory / 16;
       }
     }
 
   #ifdef DEBUG
     printf_stderr("Determined SkiaGL cache limits: Size %i, Items: %i\n", cacheSizeLimit, cacheItemLimit);
   #endif
 
 #ifdef USE_SKIA_GPU
@@ -907,16 +906,27 @@ gfxPlatform::PurgeSkiaCache()
 
   mSkiaGlue->GetGrContext()->freeGpuResources();
   // GrContext::flush() doesn't call glFlush. Call it here.
   mSkiaGlue->GetGLContext()->MakeCurrent();
   mSkiaGlue->GetGLContext()->fFlush();
 #endif
 }
 
+bool
+gfxPlatform::HasEnoughTotalSystemMemoryForSkiaGL()
+{
+#ifdef MOZ_WIDGET_GONK
+  if (mTotalSystemMemory < 250*1024*1024) {
+    return false;
+  }
+#endif
+  return true;
+}
+
 TemporaryRef<DrawTarget>
 gfxPlatform::CreateDrawTargetForBackend(BackendType aBackend, const IntSize& aSize, SurfaceFormat aFormat)
 {
   // There is a bunch of knowledge in the gfxPlatform heirarchy about how to
   // create the best offscreen surface for the current system and situation. We
   // can easily take advantage of this for the Cairo backend, so that's what we
   // do.
   // mozilla::gfx::Factory can get away without having all this knowledge for
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -542,16 +542,17 @@ public:
 
     mozilla::gl::SkiaGLGlue* GetSkiaGLGlue();
     void PurgeSkiaCache();
 
     virtual bool IsInGonkEmulator() const { return false; }
 
     static bool UsesOffMainThreadCompositing();
 
+    bool HasEnoughTotalSystemMemoryForSkiaGL();
 protected:
     gfxPlatform();
     virtual ~gfxPlatform();
 
     void AppendCJKPrefLangs(eFontPrefLang aPrefLangs[], uint32_t &aLen, 
                             eFontPrefLang aCharLang, eFontPrefLang aPageLang);
 
     /**
@@ -611,16 +612,18 @@ protected:
     int8_t  mFallbackUsesCmaps;
 
     // max character limit for words in word cache
     int32_t mWordCacheCharLimit;
 
     // max number of entries in word cache
     int32_t mWordCacheMaxEntries;
 
+    uint32_t mTotalSystemMemory;
+
 private:
     /**
      * Start up Thebes.
      */
     static void Init();
 
     static void CreateCMSOutputProfile();
 
--- a/image/src/RasterImage.cpp
+++ b/image/src/RasterImage.cpp
@@ -32,16 +32,17 @@
 #include "nsBMPDecoder.h"
 #include "nsICODecoder.h"
 #include "nsIconDecoder.h"
 
 #include "gfxContext.h"
 
 #include "mozilla/gfx/2D.h"
 #include "mozilla/RefPtr.h"
+#include "mozilla/Move.h"
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Services.h"
 #include "mozilla/Preferences.h"
 #include <stdint.h>
 #include "mozilla/Telemetry.h"
 #include "mozilla/TimeStamp.h"
 #include "mozilla/ClearOnShutdown.h"
 #include "mozilla/gfx/Scale.h"
@@ -183,133 +184,123 @@ DiscardingEnabled()
   return enabled;
 }
 
 class ScaleRequest
 {
 public:
   ScaleRequest(RasterImage* aImage,
                const nsIntSize& aSize,
-               imgFrame* aSrcFrame)
-    : dstSize(aSize)
-    , dstLocked(false)
+               RawAccessFrameRef&& aSrcRef)
+    : weakImage(aImage)
+    , srcRef(Move(aSrcRef))
+    , srcRect(srcRef->GetRect())
+    , dstSize(aSize)
     , done(false)
     , stopped(false)
   {
-    MOZ_ASSERT(!aSrcFrame->GetIsPaletted());
+    MOZ_ASSERT(NS_IsMainThread());
+    MOZ_ASSERT(!srcRef->GetIsPaletted());
     MOZ_ASSERT(aSize.width > 0 && aSize.height > 0);
-
-    weakImage = aImage;
-    srcRect = aSrcFrame->GetRect();
   }
 
   // This can only be called on the main thread.
-  bool GetSurfaces(imgFrame* srcFrame)
+  bool AcquireResources()
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     nsRefPtr<RasterImage> image = weakImage.get();
     if (!image) {
       return false;
     }
 
-    bool success = false;
-    if (!dstLocked) {
+    if (!dstFrame) {
       // We need to hold a lock onto the RasterImage object itself so that
       // it (and its associated imgFrames) aren't marked as discardable.
-      bool imgLocked = NS_SUCCEEDED(image->LockImage());
-      bool srcLocked = NS_SUCCEEDED(srcFrame->LockImageData());
-      srcSurface = srcFrame->GetSurface();
-
-      dstLocked = NS_SUCCEEDED(dstFrame->LockImageData());
-      dstSurface = dstFrame->GetSurface();
-
-      success = imgLocked && srcLocked && dstLocked && srcSurface && dstSurface;
-
-      if (success) {
-        srcData = srcFrame->GetImageData();
-        dstData = dstFrame->GetImageData();
-        srcStride = srcFrame->GetImageBytesPerRow();
-        dstStride = dstFrame->GetImageBytesPerRow();
-        srcFormat = srcFrame->GetFormat();
+      if (NS_FAILED(image->LockImage())) {
+        return false;
+      }
+
+      // We'll need a destination frame. It's unconditionally ARGB32 because
+      // that's what the scaler outputs.
+      nsRefPtr<imgFrame> tentativeDstFrame = new imgFrame();
+      nsresult rv =
+        tentativeDstFrame->Init(0, 0, dstSize.width, dstSize.height,
+                                SurfaceFormat::B8G8R8A8);
+      if (NS_FAILED(rv)) {
+        return false;
       }
 
-      // We have references to the surfaces, so we don't need to leave
-      // the source frame (that we don't own) locked. We'll unlock the
-      // destination frame in ReleaseSurfaces(), below.
-      if (srcLocked) {
-        success = NS_SUCCEEDED(srcFrame->UnlockImageData()) && success;
+      // We need a strong reference to the raw data for the destination frame.
+      // (We already got one for the source frame in the constructor.)
+      RawAccessFrameRef tentativeDstRef = tentativeDstFrame->RawAccessRef();
+      if (!tentativeDstRef) {
+        return false;
       }
+
+      dstFrame = tentativeDstFrame.forget();
+      dstRef = Move(tentativeDstRef);
     }
 
-    return success;
+    return true;
   }
 
   // This can only be called on the main thread.
-  bool ReleaseSurfaces()
+  void ReleaseResources()
   {
     MOZ_ASSERT(NS_IsMainThread());
 
     nsRefPtr<RasterImage> image = weakImage.get();
-    if (!image) {
-      return false;
+    if (image) {
+      image->UnlockImage();
+    }
+
+    if (DiscardingEnabled() && dstFrame) {
+      dstFrame->SetDiscardable();
     }
 
-    bool success = false;
-    if (dstLocked) {
-      if (DiscardingEnabled())
-        dstFrame->SetDiscardable();
-      success = NS_SUCCEEDED(dstFrame->UnlockImageData());
-      success = success && NS_SUCCEEDED(image->UnlockImage());
-
-      dstLocked = false;
-      srcData = nullptr;
-      dstData = nullptr;
-      srcSurface = nullptr;
-      dstSurface = nullptr;
-    }
-    return success;
+    // Release everything except dstFrame, which we keep around for RasterImage
+    // to retrieve.
+    srcRef.reset();
+    dstRef.reset();
   }
 
-  // These values may only be touched on the main thread.
+  // These values may only be modified on the main thread.
   WeakPtr<RasterImage> weakImage;
   nsRefPtr<imgFrame> dstFrame;
-  RefPtr<SourceSurface> srcSurface;
-  RefPtr<SourceSurface> dstSurface;
-
-  // Below are the values that may be touched on the scaling thread.
-  uint8_t* srcData;
-  uint8_t* dstData;
+  RawAccessFrameRef srcRef;
+  RawAccessFrameRef dstRef;
+
+  // Below are the values that may be modified on the scaling thread.
   nsIntRect srcRect;
   nsIntSize dstSize;
-  uint32_t srcStride;
-  uint32_t dstStride;
-  SurfaceFormat srcFormat;
-  bool dstLocked;
   bool done;
+
   // This boolean is accessed from both threads simultaneously without locking.
   // That's safe because stopping a ScaleRequest is strictly an optimization;
   // if we're not cache-coherent, at worst we'll do extra work.
   bool stopped;
 };
 
 class DrawRunner : public nsRunnable
 {
 public:
   explicit DrawRunner(ScaleRequest* request)
    : mScaleRequest(request)
   {}
 
   NS_IMETHOD Run()
   {
-    // ScaleWorker is finished with this request, so we can unlock the data now.
-    mScaleRequest->ReleaseSurfaces();
-
+    // Grab the weak image pointer before the request releases it.
     nsRefPtr<RasterImage> image = mScaleRequest->weakImage.get();
 
+    // ScaleWorker is finished with this request, so release everything that we
+    // don't need anymore.
+    mScaleRequest->ReleaseResources();
+
     if (image) {
       RasterImage::ScaleStatus status;
       if (mScaleRequest->done) {
         status = RasterImage::SCALE_DONE;
       } else {
         status = RasterImage::SCALE_INVALID;
       }
 
@@ -323,46 +314,46 @@ private: /* members */
   nsAutoPtr<ScaleRequest> mScaleRequest;
 };
 
 class ScaleRunner : public nsRunnable
 {
 public:
   ScaleRunner(RasterImage* aImage,
               const nsIntSize& aSize,
-              imgFrame* aSrcFrame)
+              RawAccessFrameRef&& aSrcRef)
   {
-    nsAutoPtr<ScaleRequest> request(new ScaleRequest(aImage, aSize, aSrcFrame));
-
-    // Destination is unconditionally ARGB32 because that's what the scaler
-    // outputs.
-    request->dstFrame = new imgFrame();
-    nsresult rv = request->dstFrame->Init(0, 0, request->dstSize.width, request->dstSize.height,
-                                          SurfaceFormat::B8G8R8A8);
-
-    if (NS_FAILED(rv) || !request->GetSurfaces(aSrcFrame)) {
+    nsAutoPtr<ScaleRequest> req(new ScaleRequest(aImage, aSize, Move(aSrcRef)));
+    if (!req->AcquireResources()) {
       return;
     }
 
-    aImage->ScalingStart(request);
-
-    mScaleRequest = request;
+    aImage->ScalingStart(req);
+    mScaleRequest = req;
   }
 
   NS_IMETHOD Run()
   {
-    // An alias just for ease of typing
-    ScaleRequest* request = mScaleRequest;
-
-    if (!request->stopped) {
-      request->done = gfx::Scale(request->srcData, request->srcRect.width, request->srcRect.height, request->srcStride,
-                                 request->dstData, request->dstSize.width, request->dstSize.height, request->dstStride,
-                                 request->srcFormat);
+    ScaleRequest* req = mScaleRequest.get();
+
+    if (!req->stopped) {
+      // Collect information from the frames that we need to scale.
+      uint8_t* srcData = req->srcRef->GetImageData();
+      uint8_t* dstData = req->dstRef->GetImageData();
+      uint32_t srcStride = req->srcRef->GetImageBytesPerRow();
+      uint32_t dstStride = req->dstRef->GetImageBytesPerRow();
+      SurfaceFormat srcFormat = req->srcRef->GetFormat();
+
+      // Actually do the scaling.
+      req->done =
+        gfx::Scale(srcData, req->srcRect.width, req->srcRect.height, srcStride,
+                   dstData, req->dstSize.width, req->dstSize.height, dstStride,
+                   srcFormat);
     } else {
-      request->done = false;
+      req->done = false;
     }
 
     // OK, we've got a new scaled image. Let's get the main thread to unlock and
     // redraw it.
     nsRefPtr<DrawRunner> runner = new DrawRunner(mScaleRequest.forget());
     NS_DispatchToMainThread(runner);
 
     return NS_OK;
@@ -858,17 +849,19 @@ RasterImage::CopyFrame(uint32_t aWhichFr
     return nullptr;
   }
 
   // Create a 32-bit image surface of our size, but draw using the frame's
   // rect, implicitly padding the frame out to the image's size.
 
   IntSize size(mSize.width, mSize.height);
   RefPtr<DataSourceSurface> surf =
-    Factory::CreateDataSourceSurface(size, SurfaceFormat::B8G8R8A8);
+    Factory::CreateDataSourceSurface(size,
+                                     SurfaceFormat::B8G8R8A8,
+                                     /* aZero = */ true);
   if (NS_WARN_IF(!surf)) {
     return nullptr;
   }
 
   DataSourceSurface::MappedSurface mapping;
   DebugOnly<bool> success =
     surf->Map(DataSourceSurface::MapType::WRITE, &mapping);
   NS_ASSERTION(success, "Failed to map surface");
@@ -2617,37 +2610,35 @@ RasterImage::RequestScale(imgFrame* aFra
 {
   // We can't store more than one scaled version of an image right now, so if
   // there's more than one instance of this image, bail.
   if (mLockCount != 1) {
     return;
   }
 
   // We also can't scale if we can't lock the image data for this frame.
-  if (NS_FAILED(aFrame->LockImageData())) {
-    aFrame->UnlockImageData();
+  RawAccessFrameRef frameRef = aFrame->RawAccessRef();
+  if (!frameRef) {
     return;
   }
 
   // If we have an outstanding request, signal it to stop (if it can).
   if (mScaleRequest) {
     mScaleRequest->stopped = true;
   }
 
-  nsRefPtr<ScaleRunner> runner = new ScaleRunner(this, aSize, aFrame);
+  nsRefPtr<ScaleRunner> runner = new ScaleRunner(this, aSize, Move(frameRef));
   if (runner->IsOK()) {
     if (!sScaleWorkerThread) {
       NS_NewNamedThread("Image Scaler", getter_AddRefs(sScaleWorkerThread));
       ClearOnShutdown(&sScaleWorkerThread);
     }
 
     sScaleWorkerThread->Dispatch(runner, NS_DISPATCH_NORMAL);
   }
-
-  aFrame->UnlockImageData();
 }
 
 bool
 RasterImage::DrawWithPreDownscaleIfNeeded(imgFrame *aFrame,
                                           gfxContext *aContext,
                                           const nsIntSize& aSize,
                                           const ImageRegion& aRegion,
                                           GraphicsFilter aFilter,
--- a/image/src/imgFrame.cpp
+++ b/image/src/imgFrame.cpp
@@ -737,25 +737,27 @@ bool imgFrame::ImageComplete() const
 {
   MutexAutoLock lock(mDecodedMutex);
 
   return mDecoded.IsEqualInterior(nsIntRect(mOffset.x, mOffset.y,
                                             mSize.width, mSize.height));
 }
 
 // A hint from the image decoders that this image has no alpha, even
-// though we created is ARGB32.  This changes our format to RGB24,
-// which in turn will cause us to Optimize() to RGB24.  Has no effect
-// after Optimize() is called, though in all cases it will be just a
-// performance win -- the pixels are still correct and have the A byte
-// set to 0xff.
+// though we're decoding it as B8G8R8A8. 
+// Since this is only called during decoding, there is a mImageSurface
+// that should be updated to use B8G8R8X8. This doesn't change the
+// underlying data at all, but allows DrawTargets to avoid blending
+// when drawing known opaque images.
 void imgFrame::SetHasNoAlpha()
 {
   if (mFormat == SurfaceFormat::B8G8R8A8) {
     mFormat = SurfaceFormat::B8G8R8X8;
+    MOZ_ASSERT(mImageSurface);
+    mImageSurface = CreateLockedSurface(mVBuf, mSize, mFormat);
   }
 }
 
 void imgFrame::SetAsNonPremult(bool aIsNonPremult)
 {
   mNonPremult = aIsNonPremult;
 }
 
--- a/image/src/imgTools.cpp
+++ b/image/src/imgTools.cpp
@@ -269,17 +269,18 @@ NS_IMETHODIMP imgTools::EncodeCroppedIma
   }
 
   // Check that the given crop rectangle is within image bounds.
   NS_ENSURE_ARG(frameWidth >= aOffsetX + aWidth &&
                 frameHeight >= aOffsetY + aHeight);
 
   RefPtr<DataSourceSurface> dataSurface =
     Factory::CreateDataSourceSurface(IntSize(aWidth, aHeight),
-                                     SurfaceFormat::B8G8R8A8);
+                                     SurfaceFormat::B8G8R8A8,
+                                     /* aZero = */ true);
   if (NS_WARN_IF(!dataSurface)) {
     return NS_ERROR_FAILURE;
   }
 
   DataSourceSurface::MappedSurface map;
   if (!dataSurface->Map(DataSourceSurface::MapType::WRITE, &map)) {
     return NS_ERROR_FAILURE;
   }
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -1072,16 +1072,32 @@ MOZ_ARG_ENABLE_BOOL(address-sanitizer,
     MOZ_ASAN=1,
     MOZ_ASAN= )
 if test -n "$MOZ_ASAN"; then
     MOZ_LLVM_HACKS=1
     AC_DEFINE(MOZ_ASAN)
     MOZ_PATH_PROG(LLVM_SYMBOLIZER, llvm-symbolizer)
 fi
 AC_SUBST(MOZ_ASAN)
+
+dnl ========================================================
+dnl = Use Memory Sanitizer
+dnl ========================================================
+MOZ_ARG_ENABLE_BOOL(memory-sanitizer,
+[  --enable-memory-sanitizer       Enable Memory Sanitizer (default=no)],
+    MOZ_MSAN=1,
+    MOZ_MSAN= )
+if test -n "$MOZ_MSAN"; then
+    MOZ_LLVM_HACKS=1
+    AC_DEFINE(MOZ_MSAN)
+    MOZ_PATH_PROG(LLVM_SYMBOLIZER, llvm-symbolizer)
+fi
+AC_SUBST(MOZ_MSAN)
+
+# The LLVM symbolizer is used by all sanitizers
 AC_SUBST(LLVM_SYMBOLIZER)
 
 dnl ========================================================
 dnl = Enable hacks required for LLVM instrumentations
 dnl ========================================================
 MOZ_ARG_ENABLE_BOOL(llvm-hacks,
 [  --enable-llvm-hacks       Enable workarounds required for several LLVM instrumentations (default=no)],
     MOZ_LLVM_HACKS=1,
@@ -1963,17 +1979,17 @@ dnl ====================================
 dnl = Flags to strip unused symbols from .so components
 dnl ========================================================
 case "$target" in
     *-linux*|*-kfreebsd*-gnu|*-gnu*)
         MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS='-Wl,--version-script -Wl,$(BUILD_TOOLS)/gnu-ld-scripts/components-version-script'
         ;;
     *-solaris*)
         if test -z "$GNU_CC"; then
-         eOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS='-M $(BUILD_TOOLS)/gnu-ld-scripts/components-mapfile'
+         MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS='-M $(BUILD_TOOLS)/gnu-ld-scripts/components-mapfile'
         else
          if test -z "$GCC_USE_GNU_LD"; then
           MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS='-Wl,-M -Wl,$(BUILD_TOOLS)/gnu-ld-scripts/components-mapfile'
          else
           MOZ_COMPONENTS_VERSION_SCRIPT_LDFLAGS='-Wl,--version-script -Wl,$(BUILD_TOOLS)/gnu-ld-scripts/components-version-script'
          fi
         fi
         ;;
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -2029,17 +2029,18 @@ IonCompile(JSContext *cx, JSScript *scri
 
     types::CompilerConstraintList *constraints = types::NewCompilerConstraintList(*temp);
     if (!constraints)
         return AbortReason_Alloc;
 
     const OptimizationInfo *optimizationInfo = js_IonOptimizations.get(optimizationLevel);
     const JitCompileOptions options(cx);
 
-    IonBuilder *builder = alloc->new_<IonBuilder>(CompileCompartment::get(cx->compartment()),
+    IonBuilder *builder = alloc->new_<IonBuilder>((JSContext *) nullptr,
+                                                  CompileCompartment::get(cx->compartment()),
                                                   options, temp, graph, constraints,
                                                   inspector, info, optimizationInfo,
                                                   baselineFrameInspector);
     if (!builder)
         return AbortReason_Alloc;
 
     JS_ASSERT(recompile == HasIonScript(builder->script(), executionMode));
     JS_ASSERT(CanIonCompile(builder->script(), executionMode));
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -2787,17 +2787,17 @@ jit::AnalyzeNewScriptDefiniteProperties(
     if (!constraints) {
         js_ReportOutOfMemory(cx);
         return false;
     }
 
     BaselineInspector inspector(script);
     const JitCompileOptions options(cx);
 
-    IonBuilder builder(CompileCompartment::get(cx->compartment()), options, &temp, &graph, constraints,
+    IonBuilder builder(cx, CompileCompartment::get(cx->compartment()), options, &temp, &graph, constraints,
                        &inspector, &info, optimizationInfo, /* baselineFrame = */ nullptr);
 
     if (!builder.build()) {
         if (builder.abortReason() == AbortReason_Alloc)
             return false;
         return true;
     }
 
@@ -3014,17 +3014,17 @@ jit::AnalyzeArgumentsUsage(JSContext *cx
 
     types::CompilerConstraintList *constraints = types::NewCompilerConstraintList(temp);
     if (!constraints)
         return false;
 
     BaselineInspector inspector(script);
     const JitCompileOptions options(cx);
 
-    IonBuilder builder(CompileCompartment::get(cx->compartment()), options, &temp, &graph, constraints,
+    IonBuilder builder(nullptr, CompileCompartment::get(cx->compartment()), options, &temp, &graph, constraints,
                        &inspector, &info, optimizationInfo, /* baselineFrame = */ nullptr);
 
     if (!builder.build()) {
         if (builder.abortReason() == AbortReason_Alloc)
             return false;
         return true;
     }
 
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -101,25 +101,26 @@ jit::NewBaselineFrameInspector(TempAlloc
             types::Type type = types::GetMaybeOptimizedOutValueType(frame->unaliasedLocal(i));
             inspector->varTypes.infallibleAppend(type);
         }
     }
 
     return inspector;
 }
 
-IonBuilder::IonBuilder(CompileCompartment *comp,
+IonBuilder::IonBuilder(JSContext *analysisContext, CompileCompartment *comp,
                        const JitCompileOptions &options, TempAllocator *temp,
                        MIRGraph *graph, types::CompilerConstraintList *constraints,
                        BaselineInspector *inspector, CompileInfo *info,
                        const OptimizationInfo *optimizationInfo,
                        BaselineFrameInspector *baselineFrame, size_t inliningDepth,
                        uint32_t loopDepth)
   : MIRGenerator(comp, options, temp, graph, info, optimizationInfo),
     backgroundCodegen_(nullptr),
+    analysisContext(analysisContext),
     baselineFrame_(baselineFrame),
     constraints_(constraints),
     analysis_(*temp, info->script()),
     thisTypes(nullptr),
     argTypes(nullptr),
     typeArray(nullptr),
     typeArrayHint(0),
     bytecodeTypeMap(nullptr),
@@ -141,24 +142,26 @@ IonBuilder::IonBuilder(CompileCompartmen
     lazyArguments_(nullptr),
     inlineCallInfo_(nullptr)
 {
     script_ = info->script();
     pc = info->startPC();
     abortReason_ = AbortReason_Disable;
 
     JS_ASSERT(script()->hasBaselineScript() == (info->executionMode() != ArgumentsUsageAnalysis));
+    JS_ASSERT(!!analysisContext == (info->executionMode() == DefinitePropertiesAnalysis));
 
     if (!info->executionModeIsAnalysis())
         script()->baselineScript()->setIonCompiledOrInlined();
 }
 
 void
 IonBuilder::clearForBackEnd()
 {
+    JS_ASSERT(!analysisContext);
     baselineFrame_ = nullptr;
 
     // The caches below allocate data from the malloc heap. Release this before
     // later phases of compilation to avoid leaks, as the top level IonBuilder
     // is not explicitly destroyed. Note that builders for inner scripts are
     // constructed on the stack and will release this memory on destruction.
     gsn.purge();
     scopeCoordinateNameCache.purge();
@@ -341,16 +344,32 @@ IonBuilder::InliningDecision
 IonBuilder::canInlineTarget(JSFunction *target, CallInfo &callInfo)
 {
     if (!optimizationInfo().inlineInterpreted())
         return InliningDecision_DontInline;
 
     if (!target->isInterpreted())
         return DontInline(nullptr, "Non-interpreted target");
 
+    // Allow constructing lazy scripts when performing the definite properties
+    // analysis, as baseline has not been used to warm the caller up yet.
+    if (target->isInterpreted() && info().executionMode() == DefinitePropertiesAnalysis) {
+        RootedScript script(analysisContext, target->getOrCreateScript(analysisContext));
+        if (!script)
+            return InliningDecision_Error;
+
+        if (!script->hasBaselineScript() && script->canBaselineCompile()) {
+            MethodStatus status = BaselineCompile(analysisContext, script);
+            if (status == Method_Error)
+                return InliningDecision_Error;
+            if (status != Method_Compiled)
+                return InliningDecision_DontInline;
+        }
+    }
+
     if (!target->hasScript())
         return DontInline(nullptr, "Lazy script");
 
     JSScript *inlineScript = target->nonLazyScript();
     if (callInfo.constructing() && !target->isInterpretedConstructor())
         return DontInline(inlineScript, "Callee is not a constructor");
 
     ExecutionMode executionMode = info().executionMode();
@@ -4179,20 +4198,26 @@ IonBuilder::inlineScriptedCall(CallInfo 
                                                      inlineScriptTree);
     if (!info)
         return false;
 
     MIRGraphReturns returns(alloc());
     AutoAccumulateReturns aar(graph(), returns);
 
     // Build the graph.
-    IonBuilder inlineBuilder(compartment, options, &alloc(), &graph(), constraints(),
+    IonBuilder inlineBuilder(analysisContext, compartment, options, &alloc(), &graph(), constraints(),
                              &inspector, info, &optimizationInfo(), nullptr, inliningDepth_ + 1,
                              loopDepth_);
     if (!inlineBuilder.buildInline(this, outerResumePoint, callInfo)) {
+        if (analysisContext && analysisContext->isExceptionPending()) {
+            JitSpew(JitSpew_Abort, "Inline builder raised exception.");
+            abortReason_ = AbortReason_Error;
+            return false;
+        }
+
         // Inlining the callee failed. Mark the callee as uninlineable only if
         // the inlining was aborted for a non-exception reason.
         if (inlineBuilder.abortReason_ == AbortReason_Disable) {
             calleeScript->setUninlineable();
             abortReason_ = AbortReason_Inlining;
         } else if (inlineBuilder.abortReason_ == AbortReason_Inlining) {
             abortReason_ = AbortReason_Inlining;
         } else if (inlineBuilder.abortReason_ == AbortReason_NewScriptProperties) {
@@ -6413,16 +6438,18 @@ IonBuilder::testSingletonProperty(JSObje
     // reconfigured as a getter/setter then the type information for the
     // property will change and trigger invalidation.
 
     while (obj) {
         if (!ClassHasEffectlessLookup(obj->getClass(), name))
             return nullptr;
 
         types::TypeObjectKey *objType = types::TypeObjectKey::get(obj);
+        if (analysisContext)
+            objType->ensureTrackedProperty(analysisContext, NameToId(name));
 
         if (objType->unknownProperties())
             return nullptr;
 
         types::HeapTypeSetKey property = objType->property(NameToId(name));
         if (property.isOwnProperty(constraints())) {
             if (obj->hasSingletonType())
                 return property.singleton(constraints());
@@ -6494,16 +6521,18 @@ IonBuilder::testSingletonPropertyTypes(M
 
         // For property accesses which may be on many objects, we just need to
         // find a prototype common to all the objects; if that prototype
         // has the singleton property, the access will not be on a missing property.
         for (unsigned i = 0; i < types->getObjectCount(); i++) {
             types::TypeObjectKey *object = types->getObject(i);
             if (!object)
                 continue;
+            if (analysisContext)
+                object->ensureTrackedProperty(analysisContext, NameToId(name));
 
             const Class *clasp = object->clasp();
             if (!ClassHasEffectlessLookup(clasp, name) || ClassHasResolveHook(compartment, clasp, name))
                 return false;
             if (object->unknownProperties())
                 return false;
             types::HeapTypeSetKey property = object->property(NameToId(name));
             if (property.isOwnProperty(constraints()))
@@ -6701,16 +6730,18 @@ IonBuilder::getStaticName(JSObject *stat
             return pushConstant(UndefinedValue());
         if (name == names().NaN)
             return pushConstant(compartment->runtime()->NaNValue());
         if (name == names().Infinity)
             return pushConstant(compartment->runtime()->positiveInfinityValue());
     }
 
     types::TypeObjectKey *staticType = types::TypeObjectKey::get(staticObject);
+    if (analysisContext)
+        staticType->ensureTrackedProperty(analysisContext, NameToId(name));
 
     if (staticType->unknownProperties()) {
         *psucceeded = false;
         return true;
     }
 
     types::HeapTypeSetKey property = staticType->property(id);
     if (!property.maybeTypes() ||
@@ -6719,17 +6750,17 @@ IonBuilder::getStaticName(JSObject *stat
     {
         // The property has been reconfigured as non-configurable, non-enumerable
         // or non-writable.
         *psucceeded = false;
         return true;
     }
 
     types::TemporaryTypeSet *types = bytecodeTypes(pc);
-    BarrierKind barrier = PropertyReadNeedsTypeBarrier(constraints(), staticType,
+    BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(), staticType,
                                                        name, types, /* updateObserved = */ true);
 
     JSObject *singleton = types->getSingleton();
 
     MIRType knownType = types->getKnownMIRType();
     if (barrier == BarrierKind::NoBarrier) {
         // Try to inline properties holding a known constant object.
         if (singleton) {
@@ -7535,17 +7566,18 @@ IonBuilder::getElemTryCache(bool *emitte
     // of this getelem.
     bool nonNativeGetElement = inspector->hasSeenNonNativeGetElement(pc);
     if (index->mightBeType(MIRType_Int32) && nonNativeGetElement)
         return true;
 
     // Emit GetElementCache.
 
     types::TemporaryTypeSet *types = bytecodeTypes(pc);
-    BarrierKind barrier = PropertyReadNeedsTypeBarrier(constraints(), obj, nullptr, types);
+    BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(), obj,
+                                                       nullptr, types);
 
     // Always add a barrier if the index might be a string or symbol, so that
     // the cache can attach stubs for particular properties.
     if (index->mightBeType(MIRType_String) || index->mightBeType(MIRType_Symbol))
         barrier = BarrierKind::TypeSet;
 
     // See note about always needing a barrier in jsop_getprop.
     if (needsToMonitorMissingProperties(types))
@@ -7583,17 +7615,18 @@ IonBuilder::jsop_getelem_dense(MDefiniti
     MOZ_ASSERT(index->type() == MIRType_Int32 || index->type() == MIRType_Double);
     if (JSOp(*pc) == JSOP_CALLELEM) {
         // Indexed call on an element of an array. Populate the observed types
         // with any objects that could be in the array, to avoid extraneous
         // type barriers.
         AddObjectsForPropertyRead(obj, nullptr, types);
     }
 
-    BarrierKind barrier = PropertyReadNeedsTypeBarrier(constraints(), obj, nullptr, types);
+    BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(), obj,
+                                                       nullptr, types);
     bool needsHoleCheck = !ElementAccessIsPacked(constraints(), obj);
 
     // Reads which are on holes in the object do not have to bail out if
     // undefined values have been observed at this access site and the access
     // cannot hit another indexed property on the object or its prototypes.
     bool readOutOfBounds =
         types->hasType(types::Type::UndefinedType()) &&
         !ElementAccessHasExtraIndexedProperty(constraints(), obj);
@@ -8899,17 +8932,18 @@ IonBuilder::jsop_getprop(PropertyName *n
     // Try to optimize arguments.length.
     if (!getPropTryArgumentsLength(&emitted, obj) || emitted)
         return emitted;
 
     // Try to optimize arguments.callee.
     if (!getPropTryArgumentsCallee(&emitted, obj, name) || emitted)
         return emitted;
 
-    BarrierKind barrier = PropertyReadNeedsTypeBarrier(constraints(), obj, name, types);
+    BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(),
+                                                       obj, name, types);
 
     // Always use a call if we are performing analysis and
     // not actually emitting code, to simplify later analysis. Also skip deeper
     // analysis if there are no known types for this operation, as it will
     // always invalidate when executing.
     if (info().executionModeIsAnalysis() || types->empty()) {
         MCallGetProperty *call = MCallGetProperty::New(alloc(), obj, name, *pc == JSOP_CALLPROP);
         current->add(call);
@@ -9581,17 +9615,18 @@ IonBuilder::getPropTryInnerize(bool *emi
     if (!getPropTryConstant(emitted, inner, name, types) || *emitted)
         return *emitted;
 
     if (!getStaticName(&script()->global(), name, emitted) || *emitted)
         return *emitted;
 
     // Passing the inner object to GetProperty IC is safe, see the
     // needsOuterizedThisObject check in IsCacheableGetPropCallNative.
-    BarrierKind barrier = PropertyReadNeedsTypeBarrier(constraints(), inner, name, types);
+    BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(),
+                                                       inner, name, types);
     if (!getPropTryCache(emitted, inner, name, barrier, types) || *emitted)
         return *emitted;
 
     MOZ_ASSERT(*emitted == false);
     return true;
 }
 
 bool
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -209,17 +209,17 @@ class IonBuilder
         static CFGState CondSwitch(IonBuilder *builder, jsbytecode *exitpc, jsbytecode *defaultTarget);
         static CFGState Label(jsbytecode *exitpc);
         static CFGState Try(jsbytecode *exitpc, MBasicBlock *successor);
     };
 
     static int CmpSuccessors(const void *a, const void *b);
 
   public:
-    IonBuilder(CompileCompartment *comp,
+    IonBuilder(JSContext *analysisContext, CompileCompartment *comp,
                const JitCompileOptions &options, TempAllocator *temp,
                MIRGraph *graph, types::CompilerConstraintList *constraints,
                BaselineInspector *inspector, CompileInfo *info,
                const OptimizationInfo *optimizationInfo, BaselineFrameInspector *baselineFrame,
                size_t inliningDepth = 0, uint32_t loopDepth = 0);
 
     bool build();
     bool buildInline(IonBuilder *callerBuilder, MResumePoint *callerResumePoint,
@@ -860,16 +860,17 @@ class IonBuilder
         return callerBuilder_ != nullptr;
     }
 
     const JSAtomState &names() { return compartment->runtime()->names(); }
 
   private:
     bool init();
 
+    JSContext *analysisContext;
     BaselineFrameInspector *baselineFrame_;
 
     // Constraints for recording dependencies on type information.
     types::CompilerConstraintList *constraints_;
 
     // Basic analysis information about the script.
     BytecodeAnalysis analysis_;
     BytecodeAnalysis &analysis() {
--- a/js/src/jit/MCallOptimize.cpp
+++ b/js/src/jit/MCallOptimize.cpp
@@ -428,17 +428,18 @@ IonBuilder::inlineArrayPopShift(CallInfo
     callInfo.setImplicitlyUsedUnchecked();
 
     obj = addMaybeCopyElementsForWrite(obj);
 
     types::TemporaryTypeSet *returnTypes = getInlineReturnTypeSet();
     bool needsHoleCheck = thisTypes->hasObjectFlags(constraints(), types::OBJECT_FLAG_NON_PACKED);
     bool maybeUndefined = returnTypes->hasType(types::Type::UndefinedType());
 
-    BarrierKind barrier = PropertyReadNeedsTypeBarrier(constraints(), obj, nullptr, returnTypes);
+    BarrierKind barrier = PropertyReadNeedsTypeBarrier(analysisContext, constraints(),
+                                                       obj, nullptr, returnTypes);
     if (barrier != BarrierKind::NoBarrier)
         returnType = MIRType_Value;
 
     MArrayPopShift *ins = MArrayPopShift::New(alloc(), obj, mode, needsHoleCheck, maybeUndefined);
     current->add(ins);
     current->push(ins);
     ins->setResultType(returnType);
 
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -3662,17 +3662,18 @@ PropertyReadNeedsTypeBarrier(types::Comp
         }
     }
 
     property.freeze(constraints);
     return BarrierKind::NoBarrier;
 }
 
 BarrierKind
-jit::PropertyReadNeedsTypeBarrier(types::CompilerConstraintList *constraints,
+jit::PropertyReadNeedsTypeBarrier(JSContext *propertycx,
+                                  types::CompilerConstraintList *constraints,
                                   types::TypeObjectKey *object, PropertyName *name,
                                   types::TemporaryTypeSet *observed, bool updateObserved)
 {
     // If this access has never executed, try to add types to the observed set
     // according to any property which exists on the object or its prototype.
     if (updateObserved && observed->empty() && name) {
         JSObject *obj;
         if (object->singleton())
@@ -3682,16 +3683,18 @@ jit::PropertyReadNeedsTypeBarrier(types:
         else
             obj = nullptr;
 
         while (obj) {
             if (!obj->getClass()->isNative())
                 break;
 
             types::TypeObjectKey *typeObj = types::TypeObjectKey::get(obj);
+            if (propertycx)
+                typeObj->ensureTrackedProperty(propertycx, NameToId(name));
 
             if (!typeObj->unknownProperties()) {
                 types::HeapTypeSetKey property = typeObj->property(NameToId(name));
                 if (property.maybeTypes()) {
                     types::TypeSet::TypeList types;
                     if (!property.maybeTypes()->enumerateTypes(&types))
                         break;
                     if (types.length()) {
@@ -3707,34 +3710,35 @@ jit::PropertyReadNeedsTypeBarrier(types:
             obj = obj->getProto();
         }
     }
 
     return PropertyReadNeedsTypeBarrier(constraints, object, name, observed);
 }
 
 BarrierKind
-jit::PropertyReadNeedsTypeBarrier(types::CompilerConstraintList *constraints,
+jit::PropertyReadNeedsTypeBarrier(JSContext *propertycx,
+                                  types::CompilerConstraintList *constraints,
                                   MDefinition *obj, PropertyName *name,
                                   types::TemporaryTypeSet *observed)
 {
     if (observed->unknown())
         return BarrierKind::NoBarrier;
 
     types::TypeSet *types = obj->resultTypeSet();
     if (!types || types->unknownObject())
         return BarrierKind::TypeSet;
 
     BarrierKind res = BarrierKind::NoBarrier;
 
     bool updateObserved = types->getObjectCount() == 1;
     for (size_t i = 0; i < types->getObjectCount(); i++) {
         types::TypeObjectKey *object = types->getObject(i);
         if (object) {
-            BarrierKind kind = PropertyReadNeedsTypeBarrier(constraints, object, name,
+            BarrierKind kind = PropertyReadNeedsTypeBarrier(propertycx, constraints, object, name,
                                                             observed, updateObserved);
             if (kind == BarrierKind::TypeSet)
                 return BarrierKind::TypeSet;
 
             if (kind == BarrierKind::TypeTagOnly) {
                 MOZ_ASSERT(res == BarrierKind::NoBarrier || res == BarrierKind::TypeTagOnly);
                 res = BarrierKind::TypeTagOnly;
             } else {
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -11767,20 +11767,22 @@ MControlInstruction *MDefinition::toCont
 bool ElementAccessIsDenseNative(MDefinition *obj, MDefinition *id);
 bool ElementAccessIsTypedArray(MDefinition *obj, MDefinition *id,
                                Scalar::Type *arrayType);
 bool ElementAccessIsPacked(types::CompilerConstraintList *constraints, MDefinition *obj);
 bool ElementAccessMightBeCopyOnWrite(types::CompilerConstraintList *constraints, MDefinition *obj);
 bool ElementAccessHasExtraIndexedProperty(types::CompilerConstraintList *constraints,
                                           MDefinition *obj);
 MIRType DenseNativeElementType(types::CompilerConstraintList *constraints, MDefinition *obj);
-BarrierKind PropertyReadNeedsTypeBarrier(types::CompilerConstraintList *constraints,
+BarrierKind PropertyReadNeedsTypeBarrier(JSContext *propertycx,
+                                         types::CompilerConstraintList *constraints,
                                          types::TypeObjectKey *object, PropertyName *name,
                                          types::TemporaryTypeSet *observed, bool updateObserved);
-BarrierKind PropertyReadNeedsTypeBarrier(types::CompilerConstraintList *constraints,
+BarrierKind PropertyReadNeedsTypeBarrier(JSContext *propertycx,
+                                         types::CompilerConstraintList *constraints,
                                          MDefinition *obj, PropertyName *name,
                                          types::TemporaryTypeSet *observed);
 BarrierKind PropertyReadOnPrototypeNeedsTypeBarrier(types::CompilerConstraintList *constraints,
                                                     MDefinition *obj, PropertyName *name,
                                                     types::TemporaryTypeSet *observed);
 bool PropertyReadIsIdempotent(types::CompilerConstraintList *constraints,
                               MDefinition *obj, PropertyName *name);
 void AddObjectsForPropertyRead(MDefinition *obj, PropertyName *name,
--- a/js/src/jsinfer.cpp
+++ b/js/src/jsinfer.cpp
@@ -1086,16 +1086,31 @@ TypeObjectKey::property(jsid id)
     property.object_ = this;
     property.id_ = id;
     if (TypeObject *type = maybeType())
         property.maybeTypes_ = type->maybeGetProperty(id);
 
     return property;
 }
 
+void
+TypeObjectKey::ensureTrackedProperty(JSContext *cx, jsid id)
+{
+    // If we are accessing a lazily defined property which actually exists in
+    // the VM and has not been instantiated yet, instantiate it now if we are
+    // on the main thread and able to do so.
+    if (!JSID_IS_VOID(id) && !JSID_IS_EMPTY(id)) {
+        JS_ASSERT(CurrentThreadCanAccessRuntime(cx->runtime()));
+        if (JSObject *obj = singleton()) {
+            if (obj->isNative() && obj->nativeLookupPure(id))
+                EnsureTrackPropertyTypes(cx, obj, id);
+        }
+    }
+}
+
 bool
 HeapTypeSetKey::instantiate(JSContext *cx)
 {
     if (maybeTypes())
         return true;
     if (object()->isSingleObject() && !object()->asSingleObject()->getType(cx)) {
         cx->clearPendingException();
         return false;
--- a/js/src/jsinfer.h
+++ b/js/src/jsinfer.h
@@ -1460,16 +1460,17 @@ struct TypeObjectKey
     JSObject *singleton();
     TypeNewScript *newScript();
 
     bool unknownProperties();
     bool hasFlags(CompilerConstraintList *constraints, TypeObjectFlags flags);
     void watchStateChangeForInlinedCall(CompilerConstraintList *constraints);
     void watchStateChangeForTypedArrayData(CompilerConstraintList *constraints);
     HeapTypeSetKey property(jsid id);
+    void ensureTrackedProperty(JSContext *cx, jsid id);
 
     TypeObject *maybeType();
 };
 
 // Representation of a heap type property which may or may not be instantiated.
 // Heap properties for singleton types are instantiated lazily as they are used
 // by the compiler, but this is only done on the main thread. If we are
 // compiling off thread and use a property which has not yet been instantiated,
--- a/js/src/vm/Compression.cpp
+++ b/js/src/vm/Compression.cpp
@@ -101,16 +101,22 @@ Compressor::compressMore()
     JS_ASSERT_IF(done, ret == Z_STREAM_END);
     return done ? DONE : CONTINUE;
 }
 
 bool
 js::DecompressString(const unsigned char *inp, size_t inplen, unsigned char *out, size_t outlen)
 {
     JS_ASSERT(inplen <= UINT32_MAX);
+
+    // Mark the memory we pass to zlib as initialized for MSan.
+#ifdef MOZ_MSAN
+    __msan_unpoison(out, outlen);
+#endif
+
     z_stream zs;
     zs.zalloc = zlib_alloc;
     zs.zfree = zlib_free;
     zs.opaque = nullptr;
     zs.next_in = (Bytef *)inp;
     zs.avail_in = inplen;
     zs.next_out = out;
     JS_ASSERT(outlen);
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -2230,17 +2230,17 @@ nsDisplayBackgroundImage::GetInsideClipR
     switch (aClip) {
     case NS_STYLE_BG_CLIP_BORDER:
       clipRect = nsRect(aItem->ToReferenceFrame(), frame->GetSize());
       break;
     case NS_STYLE_BG_CLIP_PADDING:
       clipRect = frame->GetPaddingRect() - frame->GetPosition() + aItem->ToReferenceFrame();
       break;
     case NS_STYLE_BG_CLIP_CONTENT:
-      clipRect = frame->GetContentRect() - frame->GetPosition() + aItem->ToReferenceFrame();
+      clipRect = frame->GetContentRectRelativeToSelf() + aItem->ToReferenceFrame();
       break;
     default:
       NS_NOTREACHED("Unknown clip type");
       return result;
     }
   }
 
   return clipRect.Intersect(aRect);
--- a/layout/forms/test/mochitest.ini
+++ b/layout/forms/test/mochitest.ini
@@ -18,25 +18,25 @@ skip-if = toolkit == 'android' #TIMED_OU
 [test_bug402198.html]
 [test_bug411236.html]
 [test_bug446663.html]
 skip-if = buildapp == 'b2g' || toolkit == 'android' # b2g(needs copy support) b2g-debug(needs copy support) b2g-desktop(needs copy support)
 [test_bug476308.html]
 [test_bug477531.html]
 [test_bug477700.html]
 [test_bug478219.xhtml]
-skip-if = buildapp == 'b2g' || toolkit == 'android' || e10s #window.closed not working, bug 907795 # b2g(window.closed not working, bug 907795) b2g-debug(window.closed not working, bug 907795) b2g-desktop(window.closed not working, bug 907795)
+skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' || e10s #window.closed not working, bug 907795 # b2g(window.closed not working, bug 907795) b2g-debug(window.closed not working, bug 907795) b2g-desktop(window.closed not working, bug 907795)
 [test_bug534785.html]
 [test_bug542914.html]
 skip-if = (toolkit == 'gonk' && debug) #debug-only failure
 [test_bug549170.html]
 [test_bug562447.html]
 [test_bug563642.html]
 [test_bug564115.html]
-skip-if = (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'android' || e10s #TIMED_OUT # b2g-debug(times out on window.open and focus event) b2g-desktop(times out on window.open and focus event)
+skip-if = buildapp == 'mulet' || (buildapp == 'b2g' && (toolkit != 'gonk' || debug)) || toolkit == 'android' || e10s #TIMED_OUT # b2g-debug(times out on window.open and focus event) b2g-desktop(times out on window.open and focus event)
 [test_bug571352.html]
 skip-if = buildapp == 'mulet' || buildapp == 'b2g' || toolkit == 'android' #TIMED_OUT # b2g(shift-click multi-select not working?) b2g-debug(shift-click multi-select not working?) b2g-desktop(shift-click multi-select not working?)
 [test_bug572406.html]
 [test_bug572649.html]
 skip-if = toolkit == 'android' #TIMED_OUT
 [test_bug595310.html]
 [test_bug620936.html]
 [test_bug644542.html]
--- a/layout/generic/Selection.h
+++ b/layout/generic/Selection.h
@@ -210,17 +210,17 @@ public:
   SelectionType GetType(){return mType;}
   void          SetType(SelectionType aType){mType = aType;}
 
   nsresult     NotifySelectionListeners();
 
   friend struct AutoApplyUserSelectStyle;
   struct MOZ_STACK_CLASS AutoApplyUserSelectStyle
   {
-    AutoApplyUserSelectStyle(Selection* aSelection
+    explicit AutoApplyUserSelectStyle(Selection* aSelection
                              MOZ_GUARD_OBJECT_NOTIFIER_PARAM)
       : mSavedValue(aSelection->mApplyUserSelectStyle)
     {
       MOZ_GUARD_OBJECT_NOTIFIER_INIT;
       aSelection->mApplyUserSelectStyle = true;
     }
     AutoRestore<bool> mSavedValue;
     MOZ_DECL_USE_GUARD_OBJECT_NOTIFIER
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -5868,17 +5868,17 @@ nsIFrame::IsFrameSelected() const
   return nsRange::IsNodeSelected(GetContent(), 0,
                                  GetContent()->GetChildCount());
 }
 
 nsresult
 nsFrame::GetPointFromOffset(int32_t inOffset, nsPoint* outPoint)
 {
   NS_PRECONDITION(outPoint != nullptr, "Null parameter");
-  nsRect contentRect = GetContentRect() - GetPosition();
+  nsRect contentRect = GetContentRectRelativeToSelf();
   nsPoint pt = contentRect.TopLeft();
   if (mContent)
   {
     nsIContent* newContent = mContent->GetParent();
     if (newContent){
       int32_t newOffset = newContent->IndexOf(mContent);
 
       bool isRTL = (NS_GET_EMBEDDING_LEVEL(this) & 1) == 1;
--- a/layout/generic/nsHTMLCanvasFrame.cpp
+++ b/layout/generic/nsHTMLCanvasFrame.cpp
@@ -236,16 +236,18 @@ nsHTMLCanvasFrame::Reflow(nsPresContext*
   NS_FRAME_TRACE(NS_FRAME_TRACE_CALLS,
                   ("exit nsHTMLCanvasFrame::Reflow: size=%d,%d",
                    aMetrics.ISize(wm), aMetrics.BSize(wm)));
   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aMetrics);
 }
 
 // FIXME taken from nsImageFrame, but then had splittable frame stuff
 // removed.  That needs to be fixed.
+// XXXdholbert As in nsImageFrame, this function's clients should probably
+// just be calling GetContentRectRelativeToSelf().
 nsRect 
 nsHTMLCanvasFrame::GetInnerArea() const
 {
   nsMargin bp = mBorderPadding.GetPhysicalMargin(GetWritingMode());
   nsRect r;
   r.x = bp.left;
   r.y = bp.top;
   r.width = mRect.width - bp.left - bp.right;
@@ -254,17 +256,17 @@ nsHTMLCanvasFrame::GetInnerArea() const
 }
 
 already_AddRefed<Layer>
 nsHTMLCanvasFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
                               LayerManager* aManager,
                               nsDisplayItem* aItem,
                               const ContainerLayerParameters& aContainerParameters)
 {
-  nsRect area = GetContentRect() - GetPosition() + aItem->ToReferenceFrame();
+  nsRect area = GetContentRectRelativeToSelf() + aItem->ToReferenceFrame();
   HTMLCanvasElement* element = static_cast<HTMLCanvasElement*>(GetContent());
   nsIntSize canvasSize = GetCanvasSize();
 
   nsPresContext* presContext = PresContext();
   element->HandlePrintCallback(presContext->Type());
 
   if (canvasSize.width <= 0 || canvasSize.height <= 0 || area.IsEmpty())
     return nullptr;
--- a/layout/generic/nsImageFrame.cpp
+++ b/layout/generic/nsImageFrame.cpp
@@ -807,20 +807,22 @@ nsImageFrame::ComputeSize(nsRenderingCon
                             aRenderingContext, this,
                             intrinsicSize, mIntrinsicRatio,
                             aCBSize,
                             aMargin,
                             aBorder,
                             aPadding);
 }
 
+// XXXdholbert This function's clients should probably just be calling
+// GetContentRectRelativeToSelf() directly.
 nsRect 
 nsImageFrame::GetInnerArea() const
 {
-  return GetContentRect() - GetPosition();
+  return GetContentRectRelativeToSelf();
 }
 
 Element*
 nsImageFrame::GetMapElement() const
 {
   nsAutoString usemap;
   if (mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::usemap, usemap)) {
     return mContent->OwnerDoc()->FindImageMap(usemap);
--- a/layout/generic/nsVideoFrame.cpp
+++ b/layout/generic/nsVideoFrame.cpp
@@ -169,17 +169,17 @@ CorrectForAspectRatio(const gfxRect& aRe
 }
 
 already_AddRefed<Layer>
 nsVideoFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
                          LayerManager* aManager,
                          nsDisplayItem* aItem,
                          const ContainerLayerParameters& aContainerParameters)
 {
-  nsRect area = GetContentRect() - GetPosition() + aItem->ToReferenceFrame();
+  nsRect area = GetContentRectRelativeToSelf() + aItem->ToReferenceFrame();
   HTMLVideoElement* element = static_cast<HTMLVideoElement*>(GetContent());
   nsIntSize videoSize;
   if (NS_FAILED(element->GetVideoSize(&videoSize)) || area.IsEmpty()) {
     return nullptr;
   }
 
   nsRefPtr<ImageContainer> container = element->GetImageContainer();
   if (!container)
@@ -388,17 +388,17 @@ public:
   // when we come to paint, the video frame is transparent or has gone
   // away completely (e.g. because of a decoder error). The problem would
   // be especially acute if we have off-main-thread rendering.
 
   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE
   {
     *aSnap = true;
     nsIFrame* f = Frame();
-    return f->GetContentRect() - f->GetPosition() + ToReferenceFrame();
+    return f->GetContentRectRelativeToSelf() + ToReferenceFrame();
   }
 
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerLayerParameters& aContainerParameters) MOZ_OVERRIDE
   {
     return static_cast<nsVideoFrame*>(mFrame)->BuildLayer(aBuilder, aManager, this, aContainerParameters);
   }
--- a/layout/ipc/RenderFrameParent.cpp
+++ b/layout/ipc/RenderFrameParent.cpp
@@ -48,17 +48,17 @@ GetContentRectLayerOffset(nsIFrame* aCon
 {
   nscoord auPerDevPixel = aContainerFrame->PresContext()->AppUnitsPerDevPixel();
 
   // Offset to the content rect in case we have borders or padding
   // Note that aContainerFrame could be a reference frame itself, so
   // we need to be careful here to ensure that we call ToReferenceFrame
   // on aContainerFrame and not its parent.
   nsPoint frameOffset = aBuilder->ToReferenceFrame(aContainerFrame) +
-    (aContainerFrame->GetContentRect().TopLeft() - aContainerFrame->GetPosition());
+    aContainerFrame->GetContentRectRelativeToSelf().TopLeft();
 
   return frameOffset.ToNearestPixels(auPerDevPixel);
 }
 
 // Return true iff |aManager| is a "temporary layer manager".  They're
 // used for small software rendering tasks, like drawWindow.  That's
 // currently implemented by a BasicLayerManager without a backing
 // widget, and hence in non-retained mode.
--- a/layout/style/nsLayoutStylesheetCache.cpp
+++ b/layout/style/nsLayoutStylesheetCache.cpp
@@ -50,195 +50,137 @@ nsLayoutStylesheetCache::Observe(nsISupp
   }
   return NS_OK;
 }
 
 CSSStyleSheet*
 nsLayoutStylesheetCache::ScrollbarsSheet()
 {
   EnsureGlobal();
-  if (!gStyleCache)
-    return nullptr;
 
   if (!gStyleCache->mScrollbarsSheet) {
-    nsCOMPtr<nsIURI> sheetURI;
-    NS_NewURI(getter_AddRefs(sheetURI),
-              NS_LITERAL_CSTRING("chrome://global/skin/scrollbars.css"));
-
     // Scrollbars don't need access to unsafe rules
-    if (sheetURI)
-      LoadSheet(sheetURI, gStyleCache->mScrollbarsSheet, false);
-    NS_ASSERTION(gStyleCache->mScrollbarsSheet, "Could not load scrollbars.css.");
+    LoadSheetURL("chrome://global/skin/scrollbars.css",
+                 gStyleCache->mScrollbarsSheet, false);
   }
 
   return gStyleCache->mScrollbarsSheet;
 }
 
 CSSStyleSheet*
 nsLayoutStylesheetCache::FormsSheet()
 {
   EnsureGlobal();
-  if (!gStyleCache)
-    return nullptr;
 
   if (!gStyleCache->mFormsSheet) {
-    nsCOMPtr<nsIURI> sheetURI;
-      NS_NewURI(getter_AddRefs(sheetURI),
-                NS_LITERAL_CSTRING("resource://gre-resources/forms.css"));
-
     // forms.css needs access to unsafe rules
-    if (sheetURI)
-      LoadSheet(sheetURI, gStyleCache->mFormsSheet, true);
-
-    NS_ASSERTION(gStyleCache->mFormsSheet, "Could not load forms.css.");
+    LoadSheetURL("resource://gre-resources/forms.css",
+                 gStyleCache->mFormsSheet, true);
   }
 
   return gStyleCache->mFormsSheet;
 }
 
 CSSStyleSheet*
 nsLayoutStylesheetCache::NumberControlSheet()
 {
   EnsureGlobal();
-  if (!gStyleCache)
-    return nullptr;
 
   if (!sNumberControlEnabled) {
     return nullptr;
   }
 
   if (!gStyleCache->mNumberControlSheet) {
-    nsCOMPtr<nsIURI> sheetURI;
-    NS_NewURI(getter_AddRefs(sheetURI),
-              NS_LITERAL_CSTRING("resource://gre-resources/number-control.css"));
-
-    if (sheetURI)
-      LoadSheet(sheetURI, gStyleCache->mNumberControlSheet, false);
-
-    NS_ASSERTION(gStyleCache->mNumberControlSheet, "Could not load number-control.css");
+    LoadSheetURL("resource://gre-resources/number-control.css",
+                 gStyleCache->mNumberControlSheet, false);
   }
 
   return gStyleCache->mNumberControlSheet;
 }
 
 CSSStyleSheet*
 nsLayoutStylesheetCache::UserContentSheet()
 {
   EnsureGlobal();
-  if (!gStyleCache)
-    return nullptr;
-
   return gStyleCache->mUserContentSheet;
 }
 
 CSSStyleSheet*
 nsLayoutStylesheetCache::UserChromeSheet()
 {
   EnsureGlobal();
-  if (!gStyleCache)
-    return nullptr;
-
   return gStyleCache->mUserChromeSheet;
 }
 
 CSSStyleSheet*
 nsLayoutStylesheetCache::UASheet()
 {
   EnsureGlobal();
-  if (!gStyleCache)
-    return nullptr;
-
   return gStyleCache->mUASheet;
 }
 
 CSSStyleSheet*
 nsLayoutStylesheetCache::HTMLSheet()
 {
   EnsureGlobal();
-  if (!gStyleCache)
-    return nullptr;
-
   return gStyleCache->mHTMLSheet;
 }
 
 CSSStyleSheet*
 nsLayoutStylesheetCache::MinimalXULSheet()
 {
   EnsureGlobal();
-  if (!gStyleCache)
-    return nullptr;
-
   return gStyleCache->mMinimalXULSheet;
 }
 
 CSSStyleSheet*
 nsLayoutStylesheetCache::XULSheet()
 {
   EnsureGlobal();
-  if (!gStyleCache)
-    return nullptr;
-
   return gStyleCache->mXULSheet;
 }
 
 CSSStyleSheet*
 nsLayoutStylesheetCache::QuirkSheet()
 {
   EnsureGlobal();
-  if (!gStyleCache)
-    return nullptr;
-
   return gStyleCache->mQuirkSheet;
 }
 
 CSSStyleSheet*
 nsLayoutStylesheetCache::FullScreenOverrideSheet()
 {
   EnsureGlobal();
-  if (!gStyleCache)
-    return nullptr;
-
   return gStyleCache->mFullScreenOverrideSheet;
 }
 
 CSSStyleSheet*
 nsLayoutStylesheetCache::SVGSheet()
 {
   EnsureGlobal();
-  if (!gStyleCache)
-    return nullptr;
-
   return gStyleCache->mSVGSheet;
 }
 
 CSSStyleSheet*
 nsLayoutStylesheetCache::MathMLSheet()
 {
   EnsureGlobal();
-  if (!gStyleCache)
-    return nullptr;
 
   if (!gStyleCache->mMathMLSheet) {
-    nsCOMPtr<nsIURI> uri;
-    NS_NewURI(getter_AddRefs(uri), "resource://gre-resources/mathml.css");
-    if (uri) {
-      LoadSheet(uri, gStyleCache->mMathMLSheet, true);
-    }
-    NS_ASSERTION(gStyleCache->mMathMLSheet, "Could not load mathml.css");
+    LoadSheetURL("resource://gre-resources/mathml.css",
+                 gStyleCache->mMathMLSheet, true);
   }
 
   return gStyleCache->mMathMLSheet;
 }
 
 CSSStyleSheet*
 nsLayoutStylesheetCache::CounterStylesSheet()
 {
   EnsureGlobal();
-  if (!gStyleCache)
-    return nullptr;
 
   return gStyleCache->mCounterStylesSheet;
 }
 
 void
 nsLayoutStylesheetCache::Shutdown()
 {
   NS_IF_RELEASE(gCSSLoader);
@@ -260,32 +202,30 @@ nsLayoutStylesheetCache::CollectReports(
 
 size_t
 nsLayoutStylesheetCache::SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const
 {
   size_t n = aMallocSizeOf(this);
 
   #define MEASURE(s) n += s ? s->SizeOfIncludingThis(aMallocSizeOf) : 0;
 
-  MEASURE(mScrollbarsSheet);
+  MEASURE(mCounterStylesSheet);
   MEASURE(mFormsSheet);
-  MEASURE(mNumberControlSheet);
-  MEASURE(mUserContentSheet);
-  MEASURE(mUserChromeSheet);
-  MEASURE(mUASheet);
+  MEASURE(mFullScreenOverrideSheet);
   MEASURE(mHTMLSheet);
+  MEASURE(mMathMLSheet);
   MEASURE(mMinimalXULSheet);
-  MEASURE(mXULSheet);
+  MEASURE(mNumberControlSheet);
   MEASURE(mQuirkSheet);
-  MEASURE(mFullScreenOverrideSheet);
   MEASURE(mSVGSheet);
-  MEASURE(mCounterStylesSheet);
-  if (mMathMLSheet) {
-    MEASURE(mMathMLSheet);
-  }
+  MEASURE(mScrollbarsSheet);
+  MEASURE(mUASheet);
+  MEASURE(mUserChromeSheet);
+  MEASURE(mUserContentSheet);
+  MEASURE(mXULSheet);
 
   // Measurement of the following members may be added later if DMD finds it is
   // worthwhile:
   // - gCSSLoader
 
   return n;
 }
 
@@ -301,67 +241,35 @@ nsLayoutStylesheetCache::nsLayoutStylesh
     obsSvc->AddObserver(this, "chrome-flush-skin-caches", false);
     obsSvc->AddObserver(this, "chrome-flush-caches", false);
   }
 
   InitFromProfile();
 
   // And make sure that we load our UA sheets.  No need to do this
   // per-profile, since they're profile-invariant.
-  nsCOMPtr<nsIURI> uri;
-  NS_NewURI(getter_AddRefs(uri), "resource://gre-resources/ua.css");
-  if (uri) {
-    LoadSheet(uri, mUASheet, true);
-  }
-  NS_ASSERTION(mUASheet, "Could not load ua.css");
-
-  NS_NewURI(getter_AddRefs(uri), "resource://gre-resources/html.css");
-  if (uri) {
-    LoadSheet(uri, mHTMLSheet, true);
-  }
-  NS_ASSERTION(mHTMLSheet, "Could not load xul.css");
-
-  NS_NewURI(getter_AddRefs(uri), "chrome://global/content/minimal-xul.css");
-  if (uri) {
-    LoadSheet(uri, mMinimalXULSheet, true);
-  }
-  NS_ASSERTION(mMinimalXULSheet, "Could not load minimal-xul.css");
-
-  NS_NewURI(getter_AddRefs(uri), "chrome://global/content/xul.css");
-  if (uri) {
-    LoadSheet(uri, mXULSheet, true);
-  }
-  NS_ASSERTION(mXULSheet, "Could not load xul.css");
+  LoadSheetURL("resource://gre-resources/counterstyles.css",
+               mCounterStylesSheet, true);
+  LoadSheetURL("resource://gre-resources/full-screen-override.css",
+               mFullScreenOverrideSheet, true);
+  LoadSheetURL("resource://gre-resources/html.css",
+               mHTMLSheet, true);
+  LoadSheetURL("chrome://global/content/minimal-xul.css",
+               mMinimalXULSheet, true);
+  LoadSheetURL("resource://gre-resources/quirk.css",
+               mQuirkSheet, true);
+  LoadSheetURL("resource://gre/res/svg.css",
+               mSVGSheet, true);
+  LoadSheetURL("resource://gre-resources/ua.css",
+               mUASheet, true);
+  LoadSheetURL("chrome://global/content/xul.css",
+               mXULSheet, true);
 
-  NS_NewURI(getter_AddRefs(uri), "resource://gre-resources/quirk.css");
-  if (uri) {
-    LoadSheet(uri, mQuirkSheet, true);
-  }
-  NS_ASSERTION(mQuirkSheet, "Could not load quirk.css");
-
-  NS_NewURI(getter_AddRefs(uri), "resource://gre-resources/full-screen-override.css");
-  if (uri) {
-    LoadSheet(uri, mFullScreenOverrideSheet, true);
-  }
-  NS_ASSERTION(mFullScreenOverrideSheet, "Could not load full-screen-override.css");
-
-  NS_NewURI(getter_AddRefs(uri), "resource://gre/res/svg.css");
-  if (uri) {
-    LoadSheet(uri, mSVGSheet, true);
-  }
-  NS_ASSERTION(mSVGSheet, "Could not load svg.css");
-
-  NS_NewURI(getter_AddRefs(uri), "resource://gre-resources/counterstyles.css");
-  if (uri) {
-    LoadSheet(uri, mCounterStylesSheet, true);
-  }
-  NS_ASSERTION(mCounterStylesSheet, "Could not load counterstyles.css");
-
-  // mMathMLSheet is created on-demand since its use is rare. This helps save
-  // memory for Firefox OS apps.
+  // The remaining sheets are created on-demand since their use is rarer. This
+  // helps save memory for Firefox OS apps.
 }
 
 nsLayoutStylesheetCache::~nsLayoutStylesheetCache()
 {
   mozilla::UnregisterWeakMemoryReporter(this);
   MOZ_ASSERT(!gStyleCache);
 }
 
@@ -369,20 +277,21 @@ void
 nsLayoutStylesheetCache::InitMemoryReporter()
 {
   mozilla::RegisterWeakMemoryReporter(this);
 }
 
 void
 nsLayoutStylesheetCache::EnsureGlobal()
 {
+  MOZ_ASSERT(NS_IsMainThread());
+
   if (gStyleCache) return;
 
   gStyleCache = new nsLayoutStylesheetCache();
-  if (!gStyleCache) return;
 
   gStyleCache->InitMemoryReporter();
 
   Preferences::AddBoolVarCache(&sNumberControlEnabled, NUMBER_CONTROL_PREF,
                                true);
 }
 
 void
@@ -410,16 +319,29 @@ nsLayoutStylesheetCache::InitFromProfile
 
   contentFile->Append(NS_LITERAL_STRING("userContent.css"));
   chromeFile->Append(NS_LITERAL_STRING("userChrome.css"));
 
   LoadSheetFile(contentFile, mUserContentSheet);
   LoadSheetFile(chromeFile, mUserChromeSheet);
 }
 
+/* static */ void
+nsLayoutStylesheetCache::LoadSheetURL(const char* aURL,
+                                      nsRefPtr<CSSStyleSheet>& aSheet,
+                                      bool aEnableUnsafeRules)
+{
+  nsCOMPtr<nsIURI> uri;
+  NS_NewURI(getter_AddRefs(uri), aURL);
+  LoadSheet(uri, aSheet, aEnableUnsafeRules);
+  if (!aSheet) {
+    NS_ERROR(nsPrintfCString("Could not load %s", aURL).get());
+  }
+}
+
 void
 nsLayoutStylesheetCache::LoadSheetFile(nsIFile* aFile, nsRefPtr<CSSStyleSheet>& aSheet)
 {
   bool exists = false;
   aFile->Exists(&exists);
 
   if (!exists) return;
 
--- a/layout/style/nsLayoutStylesheetCache.h
+++ b/layout/style/nsLayoutStylesheetCache.h
@@ -55,32 +55,35 @@ class nsLayoutStylesheetCache MOZ_FINAL
 
 private:
   nsLayoutStylesheetCache();
   ~nsLayoutStylesheetCache();
 
   static void EnsureGlobal();
   void InitFromProfile();
   void InitMemoryReporter();
+  static void LoadSheetURL(const char* aURL,
+                           nsRefPtr<mozilla::CSSStyleSheet>& aSheet,
+                           bool aEnableUnsafeRules);
   static void LoadSheetFile(nsIFile* aFile,
                             nsRefPtr<mozilla::CSSStyleSheet>& aSheet);
   static void LoadSheet(nsIURI* aURI, nsRefPtr<mozilla::CSSStyleSheet>& aSheet,
                         bool aEnableUnsafeRules);
 
   static mozilla::StaticRefPtr<nsLayoutStylesheetCache> gStyleCache;
   static mozilla::css::Loader* gCSSLoader;
-  nsRefPtr<mozilla::CSSStyleSheet> mScrollbarsSheet;
+  nsRefPtr<mozilla::CSSStyleSheet> mCounterStylesSheet;
   nsRefPtr<mozilla::CSSStyleSheet> mFormsSheet;
-  nsRefPtr<mozilla::CSSStyleSheet> mNumberControlSheet;
-  nsRefPtr<mozilla::CSSStyleSheet> mUserContentSheet;
-  nsRefPtr<mozilla::CSSStyleSheet> mUserChromeSheet;
-  nsRefPtr<mozilla::CSSStyleSheet> mUASheet;
+  nsRefPtr<mozilla::CSSStyleSheet> mFullScreenOverrideSheet;
   nsRefPtr<mozilla::CSSStyleSheet> mHTMLSheet;
+  nsRefPtr<mozilla::CSSStyleSheet> mMathMLSheet;
   nsRefPtr<mozilla::CSSStyleSheet> mMinimalXULSheet;
-  nsRefPtr<mozilla::CSSStyleSheet> mXULSheet;
+  nsRefPtr<mozilla::CSSStyleSheet> mNumberControlSheet;
   nsRefPtr<mozilla::CSSStyleSheet> mQuirkSheet;
-  nsRefPtr<mozilla::CSSStyleSheet> mFullScreenOverrideSheet;
   nsRefPtr<mozilla::CSSStyleSheet> mSVGSheet;
-  nsRefPtr<mozilla::CSSStyleSheet> mMathMLSheet;
-  nsRefPtr<mozilla::CSSStyleSheet> mCounterStylesSheet;
+  nsRefPtr<mozilla::CSSStyleSheet> mScrollbarsSheet;
+  nsRefPtr<mozilla::CSSStyleSheet> mUASheet;
+  nsRefPtr<mozilla::CSSStyleSheet> mUserChromeSheet;
+  nsRefPtr<mozilla::CSSStyleSheet> mUserContentSheet;
+  nsRefPtr<mozilla::CSSStyleSheet> mXULSheet;
 };
 
 #endif
--- a/layout/svg/nsSVGEffects.h
+++ b/layout/svg/nsSVGEffects.h
@@ -143,17 +143,17 @@ protected:
     nsSVGIDRenderingObserver* mContainer;
   };
 
   SourceReference mElement;
 };
 
 struct nsSVGFrameReferenceFromProperty
 {
-  nsSVGFrameReferenceFromProperty(nsIFrame* aFrame)
+  explicit nsSVGFrameReferenceFromProperty(nsIFrame* aFrame)
     : mFrame(aFrame)
     , mFramePresShell(aFrame->PresContext()->PresShell())
   {}
 
   // Clear our reference to the frame.
   void Detach();
 
   // null if the frame has become invalid
--- a/layout/tables/nsTableCellFrame.cpp
+++ b/layout/tables/nsTableCellFrame.cpp
@@ -719,17 +719,17 @@ nsTableCellFrame::GetCellBaseline() cons
 {
   // Ignore the position of the inner frame relative to the cell frame
   // since we want the position as though the inner were top-aligned.
   nsIFrame *inner = mFrames.FirstChild();
   nscoord borderPadding = GetUsedBorderAndPadding().top;
   nscoord result;
   if (nsLayoutUtils::GetFirstLineBaseline(GetWritingMode(), inner, &result))
     return result + borderPadding;
-  return inner->GetContentRect().YMost() - inner->GetPosition().y +
+  return inner->GetContentRectRelativeToSelf().YMost() +
          borderPadding;
 }
 
 int32_t nsTableCellFrame::GetRowSpan()
 {
   int32_t rowSpan=1;
   nsGenericHTMLElement *hc = nsGenericHTMLElement::FromContent(mContent);
 
--- a/layout/tools/reftest/runreftest.py
+++ b/layout/tools/reftest/runreftest.py
@@ -18,20 +18,20 @@ import sys
 import threading
 
 SCRIPT_DIRECTORY = os.path.abspath(os.path.realpath(os.path.dirname(sys.argv[0])))
 sys.path.insert(0, SCRIPT_DIRECTORY)
 
 from automation import Automation
 from automationutils import (
         addCommonOptions,
-        getDebuggerInfo,
         isURL,
         processLeakLog
 )
+import mozdebug
 import mozprofile
 
 def categoriesToRegex(categoryList):
   return "\\(" + ', '.join(["(?P<%s>\\d+) %s" % c for c in categoryList]) + "\\)"
 summaryLines = [('Successful', [('pass', 'pass'), ('loadOnly', 'load only')]),
                 ('Unexpected', [('fail', 'unexpected fail'),
                                 ('pass', 'unexpected pass'),
                                 ('asserts', 'unexpected asserts'),
@@ -315,17 +315,17 @@ class RefTest(object):
     print 'REFTEST INFO | Result summary:'
     for (summaryObj, (text, categories)) in zip(summaryObjects, summaryLines):
       details = ', '.join(["%d %s" % (summaryObj[attribute], description) for (attribute, description) in categories])
       print 'REFTEST INFO | ' + text + ': ' + str(summaryObj['total']) + ' (' +  details + ')'
 
     return int(any(t.retcode != 0 for t in threads))
 
   def runSerialTests(self, testPath, options, cmdlineArgs = None):
-    debuggerInfo = getDebuggerInfo(self.oldcwd, options.debugger, options.debuggerArgs,
+    debuggerInfo = mozdebug.get_debugger_info(options.debugger, options.debuggerArgs,
         options.debuggerInteractive);
 
     profileDir = None
     try:
       reftestlist = self.getManifestPath(testPath)
       if cmdlineArgs == None:
         cmdlineArgs = ['-reftest', reftestlist]
       profile = self.createReftestProfile(options, reftestlist)
--- a/mfbt/MemoryChecking.h
+++ b/mfbt/MemoryChecking.h
@@ -49,16 +49,39 @@ void MOZ_EXPORT
   __asan_poison_memory_region((addr), (size))
 
 #define MOZ_MAKE_MEM_UNDEFINED(addr, size) \
   __asan_unpoison_memory_region((addr), (size))
 
 #define MOZ_MAKE_MEM_DEFINED(addr, size) \
   __asan_unpoison_memory_region((addr), (size))
 }
+#elif defined(MOZ_MSAN)
+#include <stddef.h>
+
+#include "mozilla/Types.h"
+
+extern "C" {
+/* These definitions are usually provided through the
+ * sanitizer/msan_interface.h header installed by MSan.
+ */
+void MOZ_EXPORT
+__msan_poison(void const volatile *addr, size_t size);
+void MOZ_EXPORT
+__msan_unpoison(void const volatile *addr, size_t size);
+
+#define MOZ_MAKE_MEM_NOACCESS(addr, size) \
+  __msan_poison((addr), (size))
+
+#define MOZ_MAKE_MEM_UNDEFINED(addr, size) \
+  __msan_poison((addr), (size))
+
+#define MOZ_MAKE_MEM_DEFINED(addr, size) \
+  __msan_unpoison((addr), (size))
+}
 #elif defined(MOZ_VALGRIND)
 #define MOZ_MAKE_MEM_NOACCESS(addr, size) \
   VALGRIND_MAKE_MEM_NOACCESS((addr), (size))
 
 #define MOZ_MAKE_MEM_UNDEFINED(addr, size) \
   VALGRIND_MAKE_MEM_UNDEFINED((addr), (size))
 
 #define MOZ_MAKE_MEM_DEFINED(addr, size) \
--- a/mobile/android/base/EventDispatcher.java
+++ b/mobile/android/base/EventDispatcher.java
@@ -7,16 +7,17 @@ package org.mozilla.gecko;
 import org.mozilla.gecko.GeckoAppShell;
 import org.mozilla.gecko.GeckoEvent;
 import org.mozilla.gecko.mozglue.RobocopTarget;
 import org.mozilla.gecko.util.EventCallback;
 import org.mozilla.gecko.util.GeckoEventListener;
 import org.mozilla.gecko.util.NativeEventListener;
 import org.mozilla.gecko.util.NativeJSContainer;
 import org.mozilla.gecko.util.NativeJSObject;
+import org.mozilla.gecko.util.ThreadUtils;
 
 import org.json.JSONException;
 import org.json.JSONObject;
 
 import android.util.Log;
 
 import java.util.HashMap;
 import java.util.List;
@@ -222,22 +223,28 @@ public final class EventDispatcher {
     @Deprecated
     public static void sendError(JSONObject message, Object response) {
         sendResponseHelper(STATUS_ERROR, message, response);
     }
 
     @Deprecated
     private static void sendResponseHelper(String status, JSONObject message, Object response) {
         try {
+            final String topic = message.getString("type") + ":Response";
             final JSONObject wrapper = new JSONObject();
             wrapper.put(GUID, message.getString(GUID));
             wrapper.put("status", status);
             wrapper.put("response", response);
-            GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent(
-                    message.getString("type") + ":Response", wrapper.toString()));
+
+            if (ThreadUtils.isOnGeckoThread()) {
+                GeckoAppShell.notifyGeckoObservers(topic, wrapper.toString());
+            } else {
+                GeckoAppShell.sendEventToGecko(
+                    GeckoEvent.createBroadcastEvent(topic, wrapper.toString()));
+            }
         } catch (final JSONException e) {
             Log.e(LOGTAG, "Unable to send response", e);
         }
     }
 
     private static class GeckoEventCallback implements EventCallback {
         private final String guid;
         private final String type;
@@ -260,20 +267,26 @@ public final class EventDispatcher {
             if (sent) {
                 throw new IllegalStateException("Callback has already been executed for type=" +
                         type + ", guid=" + guid);
             }
 
             sent = true;
 
             try {
+                final String topic = type + ":Response";
                 final JSONObject wrapper = new JSONObject();
                 wrapper.put(GUID, guid);
                 wrapper.put("status", status);
                 wrapper.put("response", response);
-                GeckoAppShell.sendEventToGecko(GeckoEvent.createBroadcastEvent(type + ":Response",
-                        wrapper.toString()));
+
+                if (ThreadUtils.isOnGeckoThread()) {
+                    GeckoAppShell.notifyGeckoObservers(topic, wrapper.toString());
+                } else {
+                    GeckoAppShell.sendEventToGecko(
+                        GeckoEvent.createBroadcastEvent(topic, wrapper.toString()));
+                }
             } catch (final JSONException e) {
                 Log.e(LOGTAG, "Unable to send response for: " + type, e);
             }
         }
     }
 }
--- a/mobile/android/base/GeckoAppShell.java
+++ b/mobile/android/base/GeckoAppShell.java
@@ -293,17 +293,22 @@ public class GeckoAppShell
                 mScanner = null;
             }
         }
     }
 
     private static LayerView sLayerView;
 
     public static void setLayerView(LayerView lv) {
+        if (sLayerView == lv) {
+            return;
+        }
         sLayerView = lv;
+        // Install new Gecko-to-Java editable listener.
+        editableListener = new GeckoEditable();
     }
 
     @RobocopTarget
     public static LayerView getLayerView() {
         return sLayerView;
     }
 
     public static void runGecko(String apkPath, String args, String url, String type) {
@@ -344,40 +349,26 @@ public class GeckoAppShell
             Log.w(LOGTAG, "STARTUP PERFORMANCE WARNING: un-official build: purging the " +
                           "startup (JavaScript) caches.");
             combinedArgs += " -purgecaches";
         }
 
         DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
         combinedArgs += " -width " + metrics.widthPixels + " -height " + metrics.heightPixels;
 
-        ThreadUtils.postToUiThread(new Runnable() {
-                @Override
-                public void run() {
-                    geckoLoaded();
-                }
-            });
-
         if (!AppConstants.MOZILLA_OFFICIAL) {
             Log.d(LOGTAG, "GeckoLoader.nativeRun " + combinedArgs);
         }
         // and go
         GeckoLoader.nativeRun(combinedArgs);
 
         // Remove pumpMessageLoop() idle handler
         Looper.myQueue().removeIdleHandler(idleHandler);
     }
 
-    // Called on the UI thread after Gecko loads.
-    private static void geckoLoaded() {
-        GeckoEditable editable = new GeckoEditable();
-        // install the gecko => editable listener
-        editableListener = editable;
-    }
-
     static void sendPendingEventsToGecko() {
         try {
             while (!PENDING_EVENTS.isEmpty()) {
                 final GeckoEvent e = PENDING_EVENTS.poll();
                 notifyGeckoOfEvent(e);
             }
         } catch (NoSuchElementException e) {}
     }
@@ -442,16 +433,19 @@ public class GeckoAppShell
         }, responseMessage);
 
         sendEventToGecko(GeckoEvent.createBroadcastEvent(request.getName(), request.getData()));
     }
 
     // Tell the Gecko event loop that an event is available.
     public static native void notifyGeckoOfEvent(GeckoEvent event);
 
+    // Synchronously notify a Gecko observer; must be called from Gecko thread.
+    public static native void notifyGeckoObservers(String subject, String data);
+
     /*
      *  The Gecko-side API: API methods that Gecko calls
      */
 
     @WrapElementForJNI(allowMultithread = true, noThrow = true)
     public static void handleUncaughtException(Thread thread, Throwable e) {
         if (GeckoThread.checkLaunchState(GeckoThread.LaunchState.GeckoExited)) {
             // We've called System.exit. All exceptions after this point are Android
--- a/mobile/android/base/util/ThreadUtils.java
+++ b/mobile/android/base/util/ThreadUtils.java
@@ -177,16 +177,23 @@ public final class ThreadUtils {
         switch (behavior) {
         case THROW:
             throw e;
         default:
             Log.e(LOGTAG, "Method called on wrong thread!", e);
         }
     }
 
+    public static boolean isOnGeckoThread() {
+        if (sGeckoThread != null) {
+            return isOnThread(sGeckoThread);
+        }
+        return false;
+    }
+
     public static boolean isOnUiThread() {
         return isOnThread(getUiThread());
     }
 
     public static boolean isOnBackgroundThread() {
         if (sBackgroundThread == null) {
             return false;
         }
--- a/modules/libjar/nsIZipReader.idl
+++ b/modules/libjar/nsIZipReader.idl
@@ -10,17 +10,17 @@
 struct PRFileDesc;
 %}
 
 [ptr] native PRFileDescStar(PRFileDesc);
 
 interface nsIUTF8StringEnumerator;
 interface nsIInputStream;
 interface nsIFile;
-interface nsICertificatePrincipal;
+interface nsIX509Cert;
 
 [scriptable, uuid(fad6f72f-13d8-4e26-9173-53007a4afe71)]
 interface nsIZipEntry : nsISupports
 {
     /**
      * The type of compression used for the item.  The possible values and
      * their meanings are defined in the zip file specification at
      * http://www.pkware.com/business_and_developers/developer/appnote/
@@ -58,17 +58,17 @@ interface nsIZipEntry : nsISupports
      */
     readonly attribute boolean          isSynthetic;
     /**
      * The UNIX style file permissions of this item.
      */
     readonly attribute unsigned long    permissions;
 };
 
-[scriptable, uuid(38d6d07a-8a58-4fe7-be8b-ef6472fa83ff)]
+[scriptable, uuid(894c8dc0-37c8-11e4-916c-0800200c9a66)]
 interface nsIZipReader : nsISupports
 {
     /**
      * Opens a zip file for reading.
      * It is allowed to open with another file, 
      * but it needs to be closed first with close().
      */
     void open(in nsIFile zipFile);
@@ -185,18 +185,18 @@ interface nsIZipReader : nsISupports
      /**
      * Returns an object describing the entity which signed 
      * an entry. parseManifest must be called first. If aEntryName is an
      * entry in the jar, getInputStream must be called after parseManifest.
      * If aEntryName is an external file which has meta-information 
      * stored in the jar, verifyExternalFile (not yet implemented) must 
      * be called before getPrincipal.
      */
-    nsICertificatePrincipal getCertificatePrincipal(in AUTF8String aEntryName);   
-    
+    nsIX509Cert getSigningCert(in AUTF8String aEntryName);
+
     readonly attribute uint32_t manifestEntriesCount;
 };
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIZipReaderCache
 
 [scriptable, uuid(94ecd586-d405-4801-93d3-8ac7bef81bde)]
 interface nsIZipReaderCache : nsISupports
--- a/modules/libjar/nsJAR.cpp
+++ b/modules/libjar/nsJAR.cpp
@@ -1,17 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* 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/. */
 #include <string.h>
 #include "nsJARInputStream.h"
 #include "nsJAR.h"
 #include "nsIFile.h"
-#include "nsICertificatePrincipal.h"
+#include "nsIX509Cert.h"
 #include "nsIConsoleService.h"
 #include "nsICryptoHash.h"
 #include "nsIDataSignatureVerifier.h"
 #include "prprf.h"
 #include "mozilla/Omnijar.h"
 
 #ifdef XP_UNIX
   #include <sys/stat.h>
@@ -318,22 +318,23 @@ nsJAR::GetInputStreamWithSpec(const nsAC
   }
   if (NS_FAILED(rv)) {
     NS_RELEASE(*result);
   }
   return rv;
 }
 
 NS_IMETHODIMP
-nsJAR::GetCertificatePrincipal(const nsACString &aFilename, nsICertificatePrincipal** aPrincipal)
+nsJAR::GetSigningCert(const nsACString& aFilename, nsIX509Cert** aSigningCert)
 {
   //-- Parameter check
-  if (!aPrincipal)
+  if (!aSigningCert) {
     return NS_ERROR_NULL_POINTER;
-  *aPrincipal = nullptr;
+  }
+  *aSigningCert = nullptr;
 
   // Don't check signatures in the omnijar - this is only
   // interesting for extensions/XPIs.
   nsRefPtr<nsZipArchive> greOmni = mozilla::Omnijar::GetReader(mozilla::Omnijar::GRE);
   nsRefPtr<nsZipArchive> appOmni = mozilla::Omnijar::GetReader(mozilla::Omnijar::APP);
 
   if (mZip == greOmni || mZip == appOmni)
     return NS_OK;
@@ -361,22 +362,21 @@ nsJAR::GetCertificatePrincipal(const nsA
       rv = VerifyEntry(manItem, entryData, entryDataLen);
       if (NS_FAILED(rv)) return rv;
     }
     requestedStatus = manItem->status;
   }
   else // User wants identity of signer w/o verifying any entries
     requestedStatus = mGlobalStatus;
 
-  if (requestedStatus != JAR_VALID_MANIFEST)
+  if (requestedStatus != JAR_VALID_MANIFEST) {
     ReportError(aFilename, requestedStatus);
-  else // Valid signature
-  {
-    *aPrincipal = mPrincipal;
-    NS_IF_ADDREF(*aPrincipal);
+  } else { // Valid signature
+    *aSigningCert = mSigningCert;
+    NS_IF_ADDREF(*aSigningCert);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsJAR::GetManifestEntriesCount(uint32_t* count)
 {
   *count = mTotalItemsInManifest;
@@ -584,24 +584,25 @@ nsJAR::ParseManifest()
     mGlobalStatus = JAR_NO_MANIFEST;
     mParsedManifest = true;
     return NS_OK;
   }
 
   //-- Verify that the signature file is a valid signature of the SF file
   int32_t verifyError;
   rv = verifier->VerifySignature(sigBuffer, sigLen, manifestBuffer, manifestLen,
-                                 &verifyError, getter_AddRefs(mPrincipal));
+                                 &verifyError, getter_AddRefs(mSigningCert));
   if (NS_FAILED(rv)) return rv;
-  if (mPrincipal && verifyError == nsIDataSignatureVerifier::VERIFY_OK)
+  if (mSigningCert && verifyError == nsIDataSignatureVerifier::VERIFY_OK) {
     mGlobalStatus = JAR_VALID_MANIFEST;
-  else if (verifyError == nsIDataSignatureVerifier::VERIFY_ERROR_UNKNOWN_ISSUER)
+  } else if (verifyError == nsIDataSignatureVerifier::VERIFY_ERROR_UNKNOWN_ISSUER) {
     mGlobalStatus = JAR_INVALID_UNKNOWN_CA;
-  else
+  } else {
     mGlobalStatus = JAR_INVALID_SIG;
+  }
 
   //-- Parse the SF file. If the verification above failed, principal
   // is null, and ParseOneFile will mark the relevant entries as invalid.
   // if ParseOneFile fails, then it has no effect, and we can safely
   // continue to the next SF file, or return.
   ParseOneFile(manifestBuffer, JAR_SF);
   mParsedManifest = true;
 
--- a/modules/libjar/nsJAR.h
+++ b/modules/libjar/nsJAR.h
@@ -24,17 +24,17 @@
 #include "nsTHashtable.h"
 #include "nsIZipReader.h"
 #include "nsZipArchive.h"
 #include "nsIObserverService.h"
 #include "nsWeakReference.h"
 #include "nsIObserver.h"
 #include "mozilla/Attributes.h"
 
-class nsICertificatePrincipal;
+class nsIX509Cert;
 class nsIInputStream;
 class nsJARManifestItem;
 class nsZipReaderCache;
 
 /* For mManifestStatus */
 typedef enum
 {
   JAR_MANIFEST_NOT_PARSED = 0,
@@ -101,17 +101,17 @@ class nsJAR MOZ_FINAL : public nsIZipRea
     typedef nsClassHashtable<nsCStringHashKey, nsJARManifestItem> ManifestDataHashtable;
 
     //-- Private data members
     nsCOMPtr<nsIFile>        mZipFile;        // The zip/jar file on disk
     nsCString                mOuterZipEntry;  // The entry in the zip this zip is reading from
     nsRefPtr<nsZipArchive>   mZip;            // The underlying zip archive
     ManifestDataHashtable    mManifestData;   // Stores metadata for each entry
     bool                     mParsedManifest; // True if manifest has been parsed
-    nsCOMPtr<nsICertificatePrincipal> mPrincipal; // The entity which signed this file
+    nsCOMPtr<nsIX509Cert>    mSigningCert;    // The entity which signed this file
     int16_t                  mGlobalStatus;   // Global signature verification status
     PRIntervalTime           mReleaseTime;    // used by nsZipReaderCache for flushing entries
     nsZipReaderCache*        mCache;          // if cached, this points to the cache it's contained in
     mozilla::Mutex           mLock;
     int64_t                  mMtime;
     int32_t                  mTotalItemsInManifest;
     bool                     mOpened;
 
--- a/modules/libjar/test/chrome/test_bug386153.html
+++ b/modules/libjar/test/chrome/test_bug386153.html
@@ -40,38 +40,40 @@ function openZip(path) {
   var zip = Cc["@mozilla.org/libjar/zip-reader;1"].
             createInstance(Ci.nsIZipReader);
   zip.open(resolved);
   return zip;
 }
 
 // Gets the pretty name from the signing cert or null if the zip is unsigned.
 function getSigner(zip) {
-  var principal = zip.getCertificatePrincipal(null);
-  if (principal && principal.hasCertificate)
-    return principal.prettyName;
+  var signingCert = zip.getSigningCert(null);
+  if (signingCert) {
+    return signingCert.organization;
+  }
   return null;
 }
 
 function verifySigning(zip) {
-  var principal = zip.getCertificatePrincipal(null);
+  var signingCert = zip.getSigningCert(null);
   var count = 0;
   var entries = zip.findEntries(null);
   while (entries.hasMore()) {
     var entry = entries.getNext();
     // Nothing in META-INF is in the manifest.
     if (entry.substr(0, 9) == "META-INF/")
       continue;
     // Directory entries aren't in the manifest.
     if (entry.substr(-1) == "/")
       continue;
     count++;
-    var entryPrincipal = zip.getCertificatePrincipal(entry);
-    if (!entryPrincipal || !principal.equals(entryPrincipal))
+    var entryCert = zip.getSigningCert(entry);
+    if (!entryCert || !signingCert.equals(entryCert)) {
       return false;
+    }
   }
   return zip.manifestEntriesCount == count;
 }
 
 var zip = openZip("unsigned.zip");
 is(getSigner(zip), null, "Should not be signed");
 
 zip = openZip("signed.zip");
--- a/modules/libpref/init/all.js
+++ b/modules/libpref/init/all.js
@@ -102,16 +102,19 @@ pref("offline-apps.quota.warn",        5
 
 // zlib compression level used for cache compression:
 // 0 => disable compression
 // 1 => best speed
 // 9 => best compression
 // cache compression turned off for now - see bug #715198
 pref("browser.cache.compression_level", 0);
 
+// Whether or not MozAbortablePromise is enabled.
+pref("dom.abortablepromise.enabled", false);
+
 // Whether or not testing features are enabled.
 pref("dom.quotaManager.testing", false);
 
 // Whether or not indexedDB is enabled.
 pref("dom.indexedDB.enabled", true);
 // Space to allow indexedDB databases before prompting (in MB).
 pref("dom.indexedDB.warningQuota", 50);
 // Whether or not indexedDB experimental features are enabled.
--- a/mozglue/android/jni-stubs.inc
+++ b/mozglue/android/jni-stubs.inc
@@ -357,16 +357,35 @@ Java_org_mozilla_gecko_GeckoAppShell_not
 #endif
 
 #ifdef JNI_BINDINGS
   xul_dlsym("Java_org_mozilla_gecko_GeckoAppShell_notifyGeckoOfEvent", &f_Java_org_mozilla_gecko_GeckoAppShell_notifyGeckoOfEvent);
 #endif
 
 #ifdef JNI_STUBS
 
+typedef void (*Java_org_mozilla_gecko_GeckoAppShell_notifyGeckoObservers_t)(JNIEnv *, jclass, jstring, jstring);
+static Java_org_mozilla_gecko_GeckoAppShell_notifyGeckoObservers_t f_Java_org_mozilla_gecko_GeckoAppShell_notifyGeckoObservers;
+extern "C" NS_EXPORT void JNICALL
+Java_org_mozilla_gecko_GeckoAppShell_notifyGeckoObservers(JNIEnv * arg0, jclass arg1, jstring arg2, jstring arg3) {
+    if (!f_Java_org_mozilla_gecko_GeckoAppShell_notifyGeckoObservers) {
+        arg0->ThrowNew(arg0->FindClass("java/lang/UnsupportedOperationException"),
+                       "JNI Function called before it was loaded");
+        return ;
+    }
+     f_Java_org_mozilla_gecko_GeckoAppShell_notifyGeckoObservers(arg0, arg1, arg2, arg3);
+}
+#endif
+
+#ifdef JNI_BINDINGS
+  xul_dlsym("Java_org_mozilla_gecko_GeckoAppShell_notifyGeckoObservers", &f_Java_org_mozilla_gecko_GeckoAppShell_notifyGeckoObservers);
+#endif
+
+#ifdef JNI_STUBS
+
 typedef jlong (*Java_org_mozilla_gecko_GeckoAppShell_runUiThreadCallback_t)(JNIEnv *, jclass);
 static Java_org_mozilla_gecko_GeckoAppShell_runUiThreadCallback_t f_Java_org_mozilla_gecko_GeckoAppShell_runUiThreadCallback;
 extern "C" NS_EXPORT jlong JNICALL
 Java_org_mozilla_gecko_GeckoAppShell_runUiThreadCallback(JNIEnv * arg0, jclass arg1) {
     if (!f_Java_org_mozilla_gecko_GeckoAppShell_runUiThreadCallback) {
         arg0->ThrowNew(arg0->FindClass("java/lang/UnsupportedOperationException"),
                        "JNI Function called before it was loaded");
         return 0;
--- a/python/mozbuild/mozbuild/mach_commands.py
+++ b/python/mozbuild/mozbuild/mach_commands.py
@@ -819,75 +819,62 @@ class DebugProgram(MachCommandBase):
         help='Command-line arguments to be passed through to the program. Not specifying a -profile or -P option will result in a temporary profile being used.')
     @CommandArgument('+remote', '+r', action='store_true',
         help='Do not pass the -no-remote argument by default')
     @CommandArgument('+background', '+b', action='store_true',
         help='Do not pass the -foreground argument by default on Mac')
     @CommandArgument('+debugger', default=None, type=str,
         help='Name of debugger to launch')
     @CommandArgument('+debugparams', default=None, metavar='params', type=str,
-        help='Command-line arguments to pass to GDB or LLDB itself; split as the Bourne shell would.')
+        help='Command-line arguments to pass to the debugger itself; split as the Bourne shell would.')
     # Bug 933807 introduced JS_DISABLE_SLOW_SCRIPT_SIGNALS to avoid clever
     # segfaults induced by the slow-script-detecting logic for Ion/Odin JITted
     # code.  If we don't pass this, the user will need to periodically type
     # "continue" to (safely) resume execution.  There are ways to implement
     # automatic resuming; see the bug.
     @CommandArgument('+slowscript', action='store_true',
         help='Do not set the JS_DISABLE_SLOW_SCRIPT_SIGNALS env variable; when not set, recoverable but misleading SIGSEGV instances may occur in Ion/Odin JIT code')
     def debug(self, params, remote, background, debugger, debugparams, slowscript):
-        import which
-        if debugger:
-            try:
-                debugger = which.which(debugger)
-            except Exception as e:
-                print("You don't have %s in your PATH" % (debugger))
-                print(e)
-                return 1
-        else:
-            try:
-                debugger = which.which('gdb')
-            except Exception:
-                try:
-                    debugger = which.which('lldb')
-                except Exception as e:
-                    print("You don't have gdb or lldb in your PATH")
-                    print(e)
-                    return 1
-        args = [debugger]
-        extra_env = { 'MOZ_CRASHREPORTER_DISABLE' : '1' }
+        # Parameters come from the CLI. We need to convert them before their use.
         if debugparams:
             import pymake.process
             argv, badchar = pymake.process.clinetoargv(debugparams, os.getcwd())
             if badchar:
                 print("The +debugparams you passed require a real shell to parse them.")
                 print("(We can't handle the %r character.)" % (badchar,))
                 return 1
-            args.extend(argv)
+            debugparams = argv;
+
+        import mozdebug
+
+        if not debugger:
+            # No debugger name was provided. Look for the default ones on current OS.
+            debugger = mozdebug.get_default_debugger_name(mozdebug.DebuggerSearch.KeepLooking)
+
+        self.debuggerInfo = mozdebug.get_debugger_info(debugger, debugparams)
+
+        # We could not find the information about the desired debugger.
+        if not self.debuggerInfo:
+            print("Could not find a suitable debugger in your PATH.")
+            return 1
+
+        extra_env = { 'MOZ_CRASHREPORTER_DISABLE' : '1' }
 
         binpath = None
 
         try:
             binpath = self.get_binary_path('app')
         except Exception as e:
             print("It looks like your program isn't built.",
                 "You can run |mach build| to build it.")
             print(e)
             return 1
 
-        # args added to separate the debugger and process arguments.
-        args_separator = {
-            'gdb': '--args',
-            'ddd': '--args',
-            'cgdb': '--args',
-            'lldb': '--'
-        }
-
-        debugger_name = os.path.basename(debugger)
-        if debugger_name in args_separator:
-            args.append(args_separator[debugger_name])
+        # Build the list of arguments to pass to run_process
+        args = [self.debuggerInfo.path] + self.debuggerInfo.args
         args.append(binpath)
 
         if not remote:
             args.append('-no-remote')
         if not background and sys.platform == 'darwin':
             args.append('-foreground')
         if params:
             args.extend(params)
--- a/security/manager/boot/src/StaticHPKPins.h
+++ b/security/manager/boot/src/StaticHPKPins.h
@@ -1087,9 +1087,9 @@ static const TransportSecurityPreload kP
   { "youtube.com", true, false, false, -1, &kPinset_google_root_pems },
   { "ytimg.com", true, false, false, -1, &kPinset_google_root_pems },
 };
 
 // Pinning Preload List Length = 331;
 
 static const int32_t kUnknownId = -1;
 
-static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1418659817121000);
+static const PRTime kPreloadPKPinsExpirationTime = INT64_C(1418960624394000);
--- a/security/manager/boot/src/nsSTSPreloadList.errors
+++ b/security/manager/boot/src/nsSTSPreloadList.errors
@@ -58,72 +58,75 @@ googleplex.com: could not connect to hos
 googleplex.com: could not connect to host (error ignored - included regardless)
 goto.google.com: did not receive HSTS header (error ignored - included regardless)
 gparent.org: did not receive HSTS header
 greplin.com: did not receive HSTS header
 groups.google.com: did not receive HSTS header (error ignored - included regardless)
 hackerone-user-content.com: could not connect to host
 haste.ch: could not connect to host
 history.google.com: did not receive HSTS header (error ignored - included regardless)
+hoerbuecher-und-hoerspiele.de: did not receive HSTS header
 honeytracks.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 124"  data: no]
 hostedtalkgadget.google.com: did not receive HSTS header (error ignored - included regardless)
 howrandom.org: could not connect to host
 in.xero.com: max-age too low: 3600
 intercom.io: did not receive HSTS header
 iop.intuit.com: max-age too low: 86400
 irccloud.com: did not receive HSTS header
 jitsi.org: did not receive HSTS header
+jonaswitmer.ch: could not connect to host
 jottit.com: could not connect to host
 keymaster.lookout.com: did not receive HSTS header
 kiwiirc.com: max-age too low: 5256000
-klaxn.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 124"  data: no]
 ledgerscope.net: did not receive HSTS header
 liberty.lavabit.com: could not connect to host
 lifeguard.aecom.com: did not receive HSTS header
 lists.mayfirst.org: did not receive HSTS header
 login.corp.google.com: max-age too low: 7776000 (error ignored - included regardless)
 logotype.se: did not receive HSTS header
 ludwig.im: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 124"  data: no]
 lumi.do: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 124"  data: no]
 m.gparent.org: could not connect to host
 mail.google.com: did not receive HSTS header (error ignored - included regardless)
 market.android.com: did not receive HSTS header (error ignored - included regardless)
+matteomarescotti.name: could not connect to host
 mobilethreat.net: could not connect to host
 mobilethreatnetwork.net: could not connect to host
 my.alfresco.com: did not receive HSTS header
 mydigipass.com: did not receive HSTS header
 mykolab.com: did not receive HSTS header
 nachsenden.info: did not receive HSTS header
 neonisi.com: could not connect to host
+netzpolitik.org: did not receive HSTS header
 nexth.de: could not connect to host
 nexth.net: could not connect to host
 nexth.us: could not connect to host
 noexpect.org: could not connect to host
 openshift.redhat.com: did not receive HSTS header
 ottospora.nl: could not connect to host
-passwd.io: could not connect to host
 passwordbox.com: did not receive HSTS header
 paypal.com: max-age too low: 14400
 payroll.xero.com: max-age too low: 3600
 piratenlogin.de: did not receive HSTS header
 platform.lookout.com: could not connect to host
 play.google.com: did not receive HSTS header (error ignored - included regardless)
 prodpad.com: did not receive HSTS header
 profiles.google.com: did not receive HSTS header (error ignored - included regardless)
 promecon-gmbh.de: did not receive HSTS header
 rapidresearch.me: could not connect to host
 riseup.net: did not receive HSTS header
-roddis.net: could not connect to host
 sah3.net: could not connect to host
 saturngames.co.uk: did not receive HSTS header
 script.google.com: did not receive HSTS header (error ignored - included regardless)
 security.google.com: did not receive HSTS header (error ignored - included regardless)
+securityheaders.com: did not receive HSTS header
 semenkovich.com: did not receive HSTS header
 serverdensity.io: did not receive HSTS header
 shops.neonisi.com: could not connect to host
+siammedia.co: did not receive HSTS header
 silentcircle.org: could not connect to host
 simon.butcher.name: max-age too low: 2629743
 sites.google.com: did not receive HSTS header (error ignored - included regardless)
 sol.io: could not connect to host
 souyar.de: could not connect to host
 souyar.net: could not connect to host
 souyar.us: could not connect to host
 spreadsheets.google.com: did not receive HSTS header (error ignored - included regardless)
@@ -135,16 +138,18 @@ sunshinepress.org: could not connect to 
 surfeasy.com: did not receive HSTS header
 talk.google.com: did not receive HSTS header (error ignored - included regardless)
 talkgadget.google.com: did not receive HSTS header (error ignored - included regardless)
 tektoria.de: did not receive HSTS header
 translate.googleapis.com: did not receive HSTS header (error ignored - included regardless)
 uprotect.it: could not connect to host
 wallet.google.com: did not receive HSTS header (error ignored - included regardless)
 webmail.mayfirst.org: did not receive HSTS header
+wf-training-master.appspot.com: could not connect to host
+wf-training-master.appspot.com: could not connect to host (error ignored - included regardless)
 whonix.org: did not receive HSTS header
 www.calyxinstitute.org: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 124"  data: no]
 www.cueup.com: could not connect to host
 www.developer.mydigipass.com: could not connect to host
 www.dropbox.com: max-age too low: 2592000
 www.elanex.biz: did not receive HSTS header
 www.gmail.com: did not receive HSTS header (error ignored - included regardless)
 www.googlemail.com: did not receive HSTS header (error ignored - included regardless)
@@ -152,12 +157,12 @@ www.greplin.com: did not receive HSTS he
 www.jitsi.org: did not receive HSTS header
 www.ledgerscope.net: did not receive HSTS header
 www.logentries.com: did not receive HSTS header
 www.moneybookers.com: did not receive HSTS header
 www.neonisi.com: could not connect to host
 www.paycheckrecords.com: max-age too low: 86400
 www.paypal.com: [Exception... "Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsISiteSecurityService.processHeader]"  nsresult: "0x80004005 (NS_ERROR_FAILURE)"  location: "JS frame :: /builds/slave/m-cen-l64-periodicupdate-00000/getHSTSPreloadList.js :: processStsHeader :: line 124"  data: no]
 www.rme.li: did not receive HSTS header
-www.roddis.net: could not connect to host
+www.roddis.net: did not receive HSTS header
 www.sandbox.mydigipass.com: could not connect to host
 www.surfeasy.com: did not receive HSTS header
 zoo24.de: max-age too low: 2592000
--- a/security/manager/boot/src/nsSTSPreloadList.inc
+++ b/security/manager/boot/src/nsSTSPreloadList.inc
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /*****************************************************************************/
 /* This is an automatically generated file. If you're not                    */
 /* nsSiteSecurityService.cpp, you shouldn't be #including it.     */
 /*****************************************************************************/
 
 #include <stdint.h>
-const PRTime gPreloadListExpirationTime = INT64_C(1420884435199000);
+const PRTime gPreloadListExpirationTime = INT64_C(1421379819168000);
 
 class nsSTSPreload
 {
   public:
     const char *mHost;
     const bool mIncludeSubdomains;
 };
 
@@ -63,17 +63,17 @@ static const nsSTSPreload kSTSPreloadLis
   { "bl4ckb0x.com", true },
   { "bl4ckb0x.de", true },
   { "bl4ckb0x.info", true },
   { "bl4ckb0x.net", true },
   { "bl4ckb0x.org", true },
   { "blacklane.com", true },
   { "blocksatz-medien.de", true },
   { "blog.cyveillance.com", true },
-  { "blog.gparent.org", false },
+  { "blog.gparent.org", true },
   { "blog.linode.com", false },
   { "blog.torproject.org", false },
   { "bohramt.de", true },
   { "boxcryptor.com", true },
   { "brunosouza.org", true },
   { "buddhistische-weisheiten.org", true },
   { "bugzil.la", true },
   { "bugzilla.mozilla.org", true },
@@ -191,17 +191,16 @@ static const nsSTSPreload kSTSPreloadLis
   { "haufschild.de", true },
   { "hausverbrauch.de", true },
   { "heha.co", true },
   { "helichat.de", true },
   { "help.simpletax.ca", false },
   { "helpium.de", true },
   { "hex2013.com", true },
   { "history.google.com", true },
-  { "hoerbuecher-und-hoerspiele.de", true },
   { "hostedtalkgadget.google.com", true },
   { "hostinginnederland.nl", true },
   { "hostix.de", true },
   { "howrandom.org", true },
   { "iban.is", true },
   { "id.atlassian.com", false },
   { "id.mayfirst.org", false },
   { "ihrlotto.de", true },
@@ -295,17 +294,16 @@ static const nsSTSPreload kSTSPreloadLis
   { "mwe.st", true },
   { "my.onlime.ch", false },
   { "my.xero.com", false },
   { "mylookout.com", false },
   { "mynigma.org", true },
   { "neg9.org", false },
   { "neilwynne.com", false },
   { "netzbit.de", true },
-  { "netzpolitik.org", true },
   { "ng-security.com", true },
   { "npw.net", true },
   { "onedrive.com", true },
   { "onedrive.live.com", false },
   { "oplop.appspot.com", true },
   { "opsmate.com", false },
   { "optimus.io", true },
   { "otakuworld.de", true },
@@ -367,23 +365,21 @@ static const nsSTSPreload kSTSPreloadLis
   { "sandbox.mydigipass.com", false },
   { "schokokeks.org", false },
   { "schwarzer.it", true },
   { "scrambl.is", true },
   { "script.google.com", true },
   { "sdsl-speedtest.de", true },
   { "security-carpet.com", true },
   { "security.google.com", true },
-  { "securityheaders.com", true },
   { "secuvera.de", true },
   { "seifried.org", true },
   { "servethecity-karlsruhe.de", true },
   { "sherbers.de", true },
   { "shodan.io", true },
-  { "siammedia.co", true },
   { "silentcircle.com", true },
   { "simbolo.co.uk", false },
   { "simple.com", false },
   { "simpletax.ca", false },
   { "simplystudio.com", true },
   { "sites.google.com", true },
   { "skydrive.live.com", false },
   { "spreadsheets.google.com", true },
--- a/security/manager/ssl/public/moz.build
+++ b/security/manager/ssl/public/moz.build
@@ -6,17 +6,16 @@
 
 XPIDL_SOURCES += [
     'nsIASN1Object.idl',
     'nsIASN1PrintableItem.idl',
     'nsIASN1Sequence.idl',
     'nsIAssociatedContentSecurity.idl',
     'nsIBadCertListener2.idl',
     'nsICertificateDialogs.idl',
-    'nsICertificatePrincipal.idl',
     'nsICertOverrideService.idl',
     'nsICertPickDialogs.idl',
     'nsIClientAuthDialogs.idl',
     'nsIDataSignatureVerifier.idl',
     'nsIDOMCryptoDialogs.idl',
     'nsIGenKeypairInfoDlg.idl',
     'nsIIdentityInfo.idl',
     'nsIKeygenThread.idl',
deleted file mode 100644
--- a/security/manager/ssl/public/nsICertificatePrincipal.idl
+++ /dev/null
@@ -1,33 +0,0 @@
-/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
- *
- * 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/. */
-
-#include "nsISupports.idl"
-
-/*
- * Historically, principals, certificates, and signed JARs were all linked
- * together in one big mess. When that mess was cleaned up, it turned out that
- * the principals used to store certificate information didn't overlap at all
- * with the principals used for security policy. So this interface was created
- * so that real principals wouldn't have to carry around all that baggage.
- *
- * The name here is totally a misnomer. This isn't a principal at all, and would
- * better be called nsICertificateHolder or something. But that would require
- * renaming some APIs, so let's just let this be for now.
- */
-
-[scriptable, uuid(7cd4af5a-64d3-44a8-9700-804a42a6109a)]
-interface nsICertificatePrincipal : nsISupports
-{
-    readonly attribute AUTF8String fingerprint;
-    readonly attribute AUTF8String prettyName;
-    readonly attribute AUTF8String subjectName;
-    readonly attribute nsISupports certificate;
-    readonly attribute boolean     hasCertificate; // For compat; always true.
-
-    bool equals(in nsICertificatePrincipal aOther);
-};
-
-////////////////////////////////////////////////////////////////////////////////
--- a/security/manager/ssl/public/nsIDataSignatureVerifier.idl
+++ b/security/manager/ssl/public/nsIDataSignatureVerifier.idl
@@ -1,23 +1,22 @@
 /* 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/. */
 
 
 #include "nsISupports.idl"
 
-// NB: This isn't actually a principal at all. The naming is just historical.
-interface nsICertificatePrincipal;
+interface nsIX509Cert;
 
 /**
  * An interface for verifying that a given string of data was signed by the
  * private key matching the given public key.
  */
-[scriptable, uuid(577f097f-15e4-4043-bc0e-6d2fadcacae2)]
+[scriptable, uuid(94066a00-37c9-11e4-916c-0800200c9a66)]
 interface nsIDataSignatureVerifier : nsISupports
 {
   /**
    * Verifies that the data matches the data that was used to generate the
    * signature.
    *
    * @param aData      The data to be tested.
    * @param aSignature The signature of the data, base64 encoded.
@@ -27,15 +26,15 @@ interface nsIDataSignatureVerifier : nsI
    */
   boolean verifyData(in ACString aData, in ACString aSignature, in ACString aPublicKey);
 
    /* Sig Verification Error Codes */
   const long VERIFY_OK = 0;
   const long VERIFY_ERROR_UNKNOWN_ISSUER = 1;
   const long VERIFY_ERROR_OTHER = 2;
 
-  nsICertificatePrincipal verifySignature(in string aSignature,
-                                          in unsigned long aSignatureLen,
-                                          in string plaintext,
-                                          in unsigned long plaintextLen,
-                                          out long errorCode);
+  nsIX509Cert verifySignature(in string aSignature,
+                              in unsigned long aSignatureLen,
+                              in string plaintext,
+                              in unsigned long plaintextLen,
+                              out long errorCode);
 
 };
--- a/security/manager/ssl/src/moz.build
+++ b/security/manager/ssl/src/moz.build
@@ -14,17 +14,16 @@ EXPORTS += [
 ]
 
 EXPORTS.mozilla += [
     'PublicSSL.h',
 ]
 
 UNIFIED_SOURCES += [
     'CryptoTask.cpp',
-    'nsCertificatePrincipal.cpp',
     'nsCertOverrideService.cpp',
     'nsCertPicker.cpp',
     'nsCertVerificationThread.cpp',
     'nsClientAuthRemember.cpp',
     'nsCrypto.cpp',
     'nsDataSignatureVerifier.cpp',
     'nsKeygenHandler.cpp',
     'nsKeygenThread.cpp',
deleted file mode 100644
--- a/security/manager/ssl/src/nsCertificatePrincipal.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* 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/. */
-
-#include "nsCertificatePrincipal.h"
-
-NS_IMPL_ISUPPORTS(nsCertificatePrincipal, nsICertificatePrincipal)
-
-NS_IMETHODIMP
-nsCertificatePrincipal::GetFingerprint(nsACString& aFingerprint)
-{
-  aFingerprint = mFingerprint;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsCertificatePrincipal::GetSubjectName(nsACString& aSubjectName)
-{
-  aSubjectName = mSubjectName;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsCertificatePrincipal::GetPrettyName(nsACString& aPrettyName)
-{
-  aPrettyName = mPrettyName;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsCertificatePrincipal::GetCertificate(nsISupports** aCert)
-{
-  nsCOMPtr<nsISupports> cert = mCert;
-  cert.forget(aCert);
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsCertificatePrincipal::GetHasCertificate(bool* rv)
-{
-  *rv = true;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsCertificatePrincipal::Equals(nsICertificatePrincipal* aOther, bool* rv)
-{
-  nsAutoCString str;
-  aOther->GetFingerprint(str);
-  if (!str.Equals(mFingerprint)) {
-    *rv = false;
-    return NS_OK;
-  }
-
-  // If either subject name is empty, just let the result stand, but if they're
-  // both non-empty, only claim equality if they're equal.
-  if (!mSubjectName.IsEmpty()) {
-    // Check the other principal's subject name
-    aOther->GetSubjectName(str);
-    *rv = str.Equals(mSubjectName) || str.IsEmpty();
-    return NS_OK;
-  }
-
-  *rv = true;
-  return NS_OK;
-}
deleted file mode 100644
--- a/security/manager/ssl/src/nsCertificatePrincipal.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* 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 __NS_CERTIFICATEPRINCIPAL_H
-#define __NS_CERTIFICATEPRINCIPAL_H
-
-#include "nsICertificatePrincipal.h"
-#include "nsString.h"
-#include "nsCOMPtr.h"
-
-class nsCertificatePrincipal : public nsICertificatePrincipal
-{
-public:
-  NS_DECL_ISUPPORTS
-  NS_DECL_NSICERTIFICATEPRINCIPAL
-
-  nsCertificatePrincipal(const nsACString& aFingerprint,
-                         const nsACString& aSubjectName,
-                         const nsACString& aPrettyName,
-                         nsISupports* aCert)
-                         : mFingerprint(aFingerprint)
-                         , mSubjectName(aSubjectName)
-                         , mPrettyName(aPrettyName)
-                         , mCert(aCert)
-    {}
-
-protected:
-  virtual ~nsCertificatePrincipal() {}
-
-private:
-  nsCString             mFingerprint;
-  nsCString             mSubjectName;
-  nsCString             mPrettyName;
-  nsCOMPtr<nsISupports> mCert;
-};
-
-#endif /* __NS_CERTIFICATEPRINCIPAL_H */
--- a/security/manager/ssl/src/nsDataSignatureVerifier.cpp
+++ b/security/manager/ssl/src/nsDataSignatureVerifier.cpp
@@ -2,17 +2,16 @@
  * 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/. */
 
 #include "nsDataSignatureVerifier.h"
 
 #include "cms.h"
 #include "cryptohi.h"
 #include "keyhi.h"
-#include "nsCertificatePrincipal.h"
 #include "nsCOMPtr.h"
 #include "nsNSSComponent.h"
 #include "nssb64.h"
 #include "pkix/pkixtypes.h"
 #include "ScopedNSSTypes.h"
 #include "secerr.h"
 #include "SharedCertVerifier.h"
 
@@ -217,17 +216,17 @@ VerifyCMSDetachedSignatureIncludingCerti
 }
 
 } // namespace mozilla
 
 namespace {
 
 struct VerifyCertificateContext
 {
-  nsCOMPtr<nsICertificatePrincipal> principal;
+  nsCOMPtr<nsIX509Cert> signingCert;
   ScopedCERTCertList builtChain;
 };
 
 static nsresult
 VerifyCertificate(CERTCertificate* cert, void* voidContext, void* pinArg)
 {
   // XXX: missing pinArg is tolerated
   if (NS_WARN_IF(!cert) || NS_WARN_IF(!voidContext)) {
@@ -237,37 +236,17 @@ VerifyCertificate(CERTCertificate* cert,
   VerifyCertificateContext* context =
     reinterpret_cast<VerifyCertificateContext*>(voidContext);
 
   nsCOMPtr<nsIX509Cert> xpcomCert(nsNSSCertificate::Create(cert));
   if (!xpcomCert) {
     return NS_ERROR_OUT_OF_MEMORY;
   }
 
-  nsAutoString fingerprint;
-  nsresult rv = xpcomCert->GetSha1Fingerprint(fingerprint);
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-  nsAutoString orgName;
-  rv = xpcomCert->GetOrganization(orgName);
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-  nsAutoString subjectName;
-  rv = xpcomCert->GetSubjectName(subjectName);
-  if (NS_FAILED(rv)) {
-    return rv;
-  }
-
-  context->principal =
-    new nsCertificatePrincipal(NS_ConvertUTF16toUTF8(fingerprint),
-                               NS_ConvertUTF16toUTF8(subjectName),
-                               NS_ConvertUTF16toUTF8(orgName),
-                               xpcomCert);
+  context->signingCert = xpcomCert;
 
   RefPtr<SharedCertVerifier> certVerifier(GetDefaultCertVerifier());
   NS_ENSURE_TRUE(certVerifier, NS_ERROR_UNEXPECTED);
 
   return MapSECStatus(certVerifier->VerifyCert(cert,
                                                certificateUsageObjectSigner,
                                                Now(), pinArg,
                                                nullptr, // hostname
@@ -279,24 +258,24 @@ VerifyCertificate(CERTCertificate* cert,
 } // unnamed namespcae
 
 NS_IMETHODIMP
 nsDataSignatureVerifier::VerifySignature(const char* aRSABuf,
                                          uint32_t aRSABufLen,
                                          const char* aPlaintext,
                                          uint32_t aPlaintextLen,
                                          int32_t* aErrorCode,
-                                         nsICertificatePrincipal** aPrincipal)
+                                         nsIX509Cert** aSigningCert)
 {
-  if (!aPlaintext || !aPrincipal || !aErrorCode) {
+  if (!aPlaintext || !aSigningCert || !aErrorCode) {
     return NS_ERROR_INVALID_ARG;
   }
 
   *aErrorCode = VERIFY_ERROR_OTHER;
-  *aPrincipal = nullptr;
+  *aSigningCert = nullptr;
 
   nsNSSShutDownPreventionLock locker;
 
   Digest digest;
   nsresult rv = digest.DigestBuf(SEC_OID_SHA1,
                                  reinterpret_cast<const uint8_t*>(aPlaintext),
                                  aPlaintextLen);
   if (NS_WARN_IF(NS_FAILED(rv))) {
@@ -320,13 +299,13 @@ nsDataSignatureVerifier::VerifySignature
     if (rv == GetXPCOMFromNSSError(SEC_ERROR_UNKNOWN_ISSUER)) {
       *aErrorCode = VERIFY_ERROR_UNKNOWN_ISSUER;
     } else {
       *aErrorCode = VERIFY_ERROR_OTHER;
     }
     rv = NS_OK;
   }
   if (rv == NS_OK) {
-    context.principal.forget(aPrincipal);
+    context.signingCert.forget(aSigningCert);
   }
 
   return rv;
 }
--- a/services/fxaccounts/FxAccountsProfileClient.jsm
+++ b/services/fxaccounts/FxAccountsProfileClient.jsm
@@ -146,17 +146,17 @@ this.FxAccountsProfileClient.prototype =
  *   @param {number} [details.errno]
  *          Error number
  *   @param {String} [details.error]
  *          Error description
  *   @param {String|null} [details.message]
  *          Error message
  * @constructor
  */
-var FxAccountsProfileClientError = function (details) {
+this.FxAccountsProfileClientError = function(details) {
   details = details || {};
 
   this.name = "FxAccountsProfileClientError";
   this.code = details.code || null;
   this.errno = details.errno || ERRNO_UNKNOWN_ERROR;
   this.error = details.error || ERROR_UNKNOWN;
   this.message = details.message || null;
 };
--- a/testing/config/mozbase_requirements.txt
+++ b/testing/config/mozbase_requirements.txt
@@ -1,10 +1,11 @@
 ../mozbase/manifestparser
 ../mozbase/mozcrash
+../mozbase/mozdebug
 ../mozbase/mozdevice
 ../mozbase/mozfile
 ../mozbase/mozhttpd
 ../mozbase/mozinfo
 ../mozbase/mozinstall
 ../mozbase/mozlog
 ../mozbase/moznetwork
 ../mozbase/mozprocess
--- a/testing/mochitest/runtests.py
+++ b/testing/mochitest/runtests.py
@@ -11,16 +11,17 @@ import os
 import sys
 SCRIPT_DIR = os.path.abspath(os.path.realpath(os.path.dirname(__file__)))
 sys.path.insert(0, SCRIPT_DIR);
 
 import ctypes
 import glob
 import json
 import mozcrash
+import mozdebug
 import mozinfo
 import mozprocess
 import mozrunner
 import optparse
 import re
 import shutil
 import signal
 import subprocess
@@ -29,17 +30,16 @@ import tempfile
 import time
 import traceback
 import urllib2
 import zipfile
 import bisection
 
 from automationutils import (
     environment,
-    getDebuggerInfo,
     isURL,
     KeyValueParseError,
     parseKeyValue,
     processLeakLog,
     dumpScreen,
     ShutdownLeaks,
     printstatus,
     LSANLeaks,
@@ -385,17 +385,17 @@ class WebSocketServer(object):
     # debugger.
     #
     # If we're not in an interactive debugger, the wrapper causes the server to
     # die silently upon receiving a SIGINT.
     scriptPath = 'pywebsocket_wrapper.py'
     script = os.path.join(self._scriptdir, scriptPath)
 
     cmd = [sys.executable, script]
-    if self.debuggerInfo and self.debuggerInfo['interactive']:
+    if self.debuggerInfo and self.debuggerInfo.interactive:
         cmd += ['--interactive']
     cmd += ['-p', str(self.port), '-w', self._scriptdir, '-l',      \
            os.path.join(self._scriptdir, "websock.log"),            \
            '--log-level=debug', '--allow-handlers-outside-root-dir']
     # start the process
     self._process = mozprocess.ProcessHandler(cmd, cwd=SCRIPT_DIR)
     self._process.run()
     pid = self._process.pid
@@ -1372,18 +1372,18 @@ class Mochitest(MochitestUtilsMixin):
 
     # configure the message logger buffering
     self.message_logger.buffering = quiet
 
     # debugger information
     interactive = False
     debug_args = None
     if debuggerInfo:
-        interactive = debuggerInfo['interactive']
-        debug_args = [debuggerInfo['path']] + debuggerInfo['args']
+        interactive = debuggerInfo.interactive
+        debug_args = [debuggerInfo.path] + debuggerInfo.args
 
     # fix default timeout
     if timeout == -1:
       timeout = self.DEFAULT_TIMEOUT
 
     # copy env so we don't munge the caller's environment
     env = env.copy()
 
@@ -1402,17 +1402,17 @@ class Mochitest(MochitestUtilsMixin):
 
       # build command line
       cmd = os.path.abspath(app)
       args = list(extraArgs)
       # TODO: mozrunner should use -foreground at least for mac
       # https://bugzilla.mozilla.org/show_bug.cgi?id=916512
       args.append('-foreground')
       if testUrl:
-        if debuggerInfo and debuggerInfo['requiresEscapedArgs']:
+        if debuggerInfo and debuggerInfo.requiresEscapedArgs:
           testUrl = testUrl.replace("&", "\\&")
         args.append(testUrl)
 
       if detectShutdownLeaks:
         shutdownLeaks = ShutdownLeaks(self.log.info)
       else:
         shutdownLeaks = None
 
@@ -1689,20 +1689,20 @@ class Mochitest(MochitestUtilsMixin):
       self.initializeLooping(options)
 
     # get debugger info, a dict of:
     # {'path': path to the debugger (string),
     #  'interactive': whether the debugger is interactive or not (bool)
     #  'args': arguments to the debugger (list)
     # TODO: use mozrunner.local.debugger_arguments:
     # https://github.com/mozilla/mozbase/blob/master/mozrunner/mozrunner/local.py#L42
-    debuggerInfo = getDebuggerInfo(self.oldcwd,
-                                   options.debugger,
-                                   options.debuggerArgs,
-                                   options.debuggerInteractive)
+
+    debuggerInfo = mozdebug.get_debugger_info(options.debugger,
+                                              options.debuggerArgs,
+                                              options.debuggerInteractive)
 
     if options.useTestMediaDevices:
       devices = findTestMediaDevices(self.log)
       if not devices:
         self.log.error("Could not find test media devices to use")
         return 1
       self.mediaDevices = devices
 
@@ -1711,16 +1711,22 @@ class Mochitest(MochitestUtilsMixin):
     # https://bugzilla.mozilla.org/show_bug.cgi?id=919300
     self.manifest = self.buildProfile(options)
     if self.manifest is None:
       return 1
 
     self.leak_report_file = os.path.join(options.profilePath, "runtests_leaks.log")
 
     self.browserEnv = self.buildBrowserEnv(options, debuggerInfo is not None)
+
+    # If there are any Mulet-specific tests doing remote network access,
+    # we will not be aware since we are explicitely allowing this, as for B2G
+    if mozinfo.info.get('buildapp') == 'mulet' and 'MOZ_DISABLE_NONLOCAL_CONNECTIONS' in self.browserEnv:
+      del self.browserEnv['MOZ_DISABLE_NONLOCAL_CONNECTIONS']
+
     if self.browserEnv is None:
       return 1
 
     try:
       self.startServers(options, debuggerInfo)
 
       # testsToFilter parameter is used to filter out the test list that is sent to buildTestPath
       testURL = self.buildTestPath(options, testsToFilter)
--- a/testing/mozbase/Makefile.in
+++ b/testing/mozbase/Makefile.in
@@ -3,16 +3,17 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 include $(topsrcdir)/config/rules.mk
 
 # Harness packages from the srcdir
 MOZBASE_PACKAGES = \
   manifestparser \
   mozcrash \
+  mozdebug \
   mozfile \
   mozhttpd \
   mozinfo \
   mozinstall \
   mozlog \
   mozprocess \
   mozprofile \
   mozrunner \
new file mode 100644
--- /dev/null
+++ b/testing/mozbase/docs/mozdebug.rst
@@ -0,0 +1,5 @@
+:mod:`mozdebug` --- Configure and launch compatible debuggers.
+======================================================================================
+
+.. automodule:: mozdebug
+   :members: get_debugger_info, get_default_debugger_name, DebuggerSearch
--- a/testing/mozbase/docs/setuprunning.rst
+++ b/testing/mozbase/docs/setuprunning.rst
@@ -9,8 +9,9 @@ correctly handling the case where the sy
 .. toctree::
    :maxdepth: 2
 
    mozfile
    mozprofile
    mozprocess
    mozrunner
    mozcrash
+   mozdebug
new file mode 100644
--- /dev/null
+++ b/testing/mozbase/mozdebug/mozdebug/__init__.py
@@ -0,0 +1,30 @@
+# 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 module contains a set of function to gather information about the
+debugging capabilities of the platform. It allows to look for a specific
+debugger or to query the system for a compatible/default debugger.
+
+The following simple example looks for the default debugger on the
+current platform and launches a debugger process with the correct
+debugger-specific arguments:
+
+::
+
+  import mozdebug
+
+  debugger = mozdebug.get_default_debugger_name()
+  debuggerInfo = mozdebug.get_debugger_info(debugger)
+
+  debuggeePath = "toDebug"
+
+  processArgs = [self.debuggerInfo.path] + self.debuggerInfo.args
+  processArgs.append(debuggeePath)
+
+  run_process(args, ...)
+
+"""
+
+from mozdebug import *
new file mode 100644
--- /dev/null
+++ b/testing/mozbase/mozdebug/mozdebug/mozdebug.py
@@ -0,0 +1,168 @@
+#!/usr/bin/env 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/.
+
+import os
+import mozinfo
+from collections import namedtuple
+from distutils.spawn import find_executable
+
+__all__ = ['get_debugger_info',
+           'get_default_debugger_name',
+           'DebuggerSearch']
+
+'''
+Map of debugging programs to information about them, like default arguments
+and whether or not they are interactive.
+
+To add support for a new debugger, simply add the relative entry in
+_DEBUGGER_INFO and optionally update the _DEBUGGER_PRIORITIES.
+'''
+_DEBUGGER_INFO = {
+    # gdb requires that you supply the '--args' flag in order to pass arguments
+    # after the executable name to the executable.
+    'gdb': {
+        'interactive': True,
+        'args': ['-q', '--args']
+    },
+
+    'cgdb': {
+        'interactive': True,
+        'args': ['-q', '--args']
+    },
+
+    'lldb': {
+        'interactive': True,
+        'args': ['--'],
+        'requiresEscapedArgs': True
+    },
+
+    # Visual Studio Debugger Support.
+    'devenv.exe': {
+        'interactive': True,
+        'args': ['-debugexe']
+    },
+
+    # Visual C++ Express Debugger Support.
+    'wdexpress.exe': {
+        'interactive': True,
+        'args': ['-debugexe']
+    },
+
+    # valgrind doesn't explain much about leaks unless you set the
+    # '--leak-check=full' flag. But there are a lot of objects that are
+    # semi-deliberately leaked, so we set '--show-possibly-lost=no' to avoid
+    # uninteresting output from those objects. We set '--smc-check==all-non-file'
+    # and '--vex-iropt-register-updates=allregs-at-mem-access' so that valgrind
+    # deals properly with JIT'd JavaScript code.
+    'valgrind': {
+        'interactive': False,
+        'args': ['--leak-check=full',
+                '--show-possibly-lost=no',
+                '--smc-check=all-non-file',
+                '--vex-iropt-register-updates=allregs-at-mem-access']
+    }
+}
+
+# Maps each OS platform to the preferred debugger programs found in _DEBUGGER_INFO.
+_DEBUGGER_PRIORITIES = {
+      'win': ['devenv.exe', 'wdexpress.exe'],
+      'linux': ['gdb', 'cgdb', 'lldb'],
+      'mac': ['lldb', 'gdb'],
+      'unknown': ['gdb']
+}
+
+def get_debugger_info(debugger, debuggerArgs = None, debuggerInteractive = False):
+    '''
+    Get the information about the requested debugger.
+
+    Returns a dictionary containing the |path| of the debugger executable,
+    if it will run in |interactive| mode, its arguments and whether it needs
+    to escape arguments it passes to the debugged program (|requiresEscapedArgs|).
+    If the debugger cannot be found in the system, returns |None|.
+
+    :param debugger: The name of the debugger.
+    :param debuggerArgs: If specified, it's the list of arguments to pass to the
+     debugger. A debugger specific separator arguments is appended at the end of
+     that list.
+    :param debuggerInteractive: If specified, forces the debugger to be interactive.
+    '''
+
+    debuggerPath = None
+
+    if debugger:
+        # Append '.exe' to the debugger on Windows if it's not present,
+        # so things like '--debugger=devenv' work.
+        if (os.name == 'nt'
+            and not debugger.lower().endswith('.exe')):
+            debugger += '.exe'
+
+        debuggerPath = find_executable(debugger)
+
+    if not debuggerPath:
+        print 'Error: Could not find debugger %s.' % debugger
+        return None
+
+    debuggerName = os.path.basename(debuggerPath).lower()
+
+    def get_debugger_info(type, default):
+        if debuggerName in _DEBUGGER_INFO and type in _DEBUGGER_INFO[debuggerName]:
+            return _DEBUGGER_INFO[debuggerName][type]
+        return default
+
+    # Define a namedtuple to access the debugger information from the outside world.
+    DebuggerInfo = namedtuple(
+        'DebuggerInfo',
+        ['path', 'interactive', 'args', 'requiresEscapedArgs']
+    )
+
+    debugger_arguments = get_debugger_info('args', '')
+
+    # Extend the default arguments for the chosen debugger with the ones passed in, if any.
+    if debuggerArgs:
+        # Make sure to append the argument separator (if any) after the
+        # provided arguments.
+        debugger_arguments = debuggerArgs + debugger_arguments;
+
+    # Override the default debugger interactive mode if needed.
+    debugger_interactive = get_debugger_info('interactive', False)
+    if debuggerInteractive:
+        debugger_interactive = debuggerInteractive
+
+    d = DebuggerInfo(
+        debuggerPath,
+        debugger_interactive,
+        debugger_arguments,
+        get_debugger_info('requiresEscapedArgs', False)
+    )
+
+    return d
+
+# Defines the search policies to use in get_default_debugger_name.
+class DebuggerSearch:
+  OnlyFirst = 1
+  KeepLooking = 2
+
+def get_default_debugger_name(search=DebuggerSearch.OnlyFirst):
+    '''
+    Get the debugger name for the default debugger on current platform.
+
+    :param search: If specified, stops looking for the debugger if the
+     default one is not found (|DebuggerSearch.OnlyFirst|) or keeps
+     looking for other compatible debuggers (|DebuggerSearch.KeepLooking|).
+    '''
+
+    # Find out which debuggers are preferred for use on this platform.
+    debuggerPriorities = _DEBUGGER_PRIORITIES[mozinfo.os if mozinfo.os in _DEBUGGER_PRIORITIES else 'unknown']
+
+    # Finally get the debugger information.
+    for debuggerName in debuggerPriorities:
+        debuggerPath = find_executable(debuggerName)
+        if debuggerPath:
+            return debuggerName
+        elif not search == DebuggerSearch.KeepLooking:
+            return None
+
+    return None
new file mode 100644
--- /dev/null
+++ b/testing/mozbase/mozdebug/setup.py
@@ -0,0 +1,27 @@
+# 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/.
+
+from setuptools import setup
+
+PACKAGE_VERSION = '0.1'
+
+setup(name='mozdebug',
+      version=PACKAGE_VERSION,
+      description="Utilities for running applications under native code debuggers intended for use in Mozilla testing",
+      long_description="see http://mozbase.readthedocs.org/",
+      classifiers=[], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
+      keywords='mozilla',
+      author='Mozilla Automation and Testing Team',
+      author_email='tools@lists.mozilla.org',
+      url='https://wiki.mozilla.org/Auto-tools/Projects/Mozbase',
+      license='MPL',
+      packages=['mozdebug'],
+      include_package_data=True,
+      zip_safe=False,
+      install_requires=['mozinfo'],
+      entry_points="""
+      # -*- Entry points: -*-
+      """,
+      )
+
--- a/testing/mozbase/mozrunner/setup.py
+++ b/testing/mozbase/mozrunner/setup.py
@@ -1,17 +1,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/.
 
 import sys
 from setuptools import setup, find_packages
 
 PACKAGE_NAME = 'mozrunner'
-PACKAGE_VERSION = '6.2'
+PACKAGE_VERSION = '6.3'
 
 desc = """Reliable start/stop/configuration of Mozilla Applications (Firefox, Thunderbird, etc.)"""
 
 deps = ['mozcrash >= 0.11',
         'mozdevice >= 0.37',
         'mozfile >= 1.0',
         'mozinfo >= 0.7',
         'mozlog >= 1.5',
--- a/testing/mozbase/mozversion/setup.py
+++ b/testing/mozbase/mozversion/setup.py
@@ -1,15 +1,15 @@
 # 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/.
 
 from setuptools import setup
 
-PACKAGE_VERSION = '0.6'
+PACKAGE_VERSION = '0.7'
 
 dependencies = ['mozdevice >= 0.29',
                 'mozfile >= 1.0',
                 'mozlog >= 1.5']
 
 setup(name='mozversion',
       version=PACKAGE_VERSION,
       description='Library to get version information for applications',
--- a/testing/mozbase/packages.txt
+++ b/testing/mozbase/packages.txt
@@ -1,11 +1,12 @@
 manifestparser.pth:testing/mozbase/manifestparser
 mozb2g.pth:testing/mozbase/mozb2g
 mozcrash.pth:testing/mozbase/mozcrash
+mozdebug.pth:testing/mozbase/mozdebug
 mozdevice.pth:testing/mozbase/mozdevice
 mozfile.pth:testing/mozbase/mozfile
 mozhttpd.pth:testing/mozbase/mozhttpd
 mozinfo.pth:testing/mozbase/mozinfo
 mozinstall.pth:testing/mozbase/mozinstall
 mozlog.pth:testing/mozbase/mozlog
 moznetwork.pth:testing/mozbase/moznetwork
 mozprocess.pth:testing/mozbase/mozprocess
--- a/testing/xpcshell/mach_commands.py
+++ b/testing/xpcshell/mach_commands.py
@@ -141,25 +141,19 @@ class XPCShellRunner(MozbuildObject):
         tests_dir = os.path.join(self.topobjdir, '_tests', 'xpcshell')
         modules_dir = os.path.join(self.topobjdir, '_tests', 'modules')
         # We want output from the test to be written immediately if we are only
         # running a single test.
         verbose_output = (test_path is not None or
                           (manifest and len(manifest.test_paths())==1) or
                           verbose)
 
-        # We need to attach the '.exe' extension on Windows for the debugger to
-        # work properly.
-        xpcsExecutable = 'xpcshell'
-        if os.name == 'nt':
-          xpcsExecutable += '.exe'
-
         args = {
             'manifest': manifest,
-            'xpcshell': os.path.join(self.bindir, xpcsExecutable),
+            'xpcshell': self.get_binary_path('xpcshell'),
             'mozInfo': os.path.join(self.topobjdir, 'mozinfo.json'),
             'symbolsPath': os.path.join(self.distdir, 'crashreporter-symbols'),
             'interactive': interactive,
             'keepGoing': keep_going,
             'logfiles': False,
             'sequential': sequential,
             'shuffle': shuffle,
             'testsRootDir': tests_dir,
--- a/testing/xpcshell/runxpcshelltests.py
+++ b/testing/xpcshell/runxpcshelltests.py
@@ -2,16 +2,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/.
 
 import copy
 import json
 import math
+import mozdebug
 import os
 import os.path
 import random
 import re
 import shutil
 import signal
 import socket
 import sys
@@ -392,17 +393,17 @@ class XPCShellTestThread(Thread):
             self.xpcsCmd.extend([
                 '-e',
                 'const _TESTING_MODULES_DIR = "%s";' % sanitized
             ])
 
         self.xpcsCmd.extend(['-f', os.path.join(self.testharnessdir, 'head.js')])
 
         if self.debuggerInfo:
-            self.xpcsCmd = [self.debuggerInfo["path"]] + self.debuggerInfo["args"] + self.xpcsCmd
+            self.xpcsCmd = [self.debuggerInfo.path] + self.debuggerInfo.args + self.xpcsCmd
 
         # Automation doesn't specify a pluginsPath and xpcshell defaults to
         # $APPDIR/plugins. We do the same here so we can carry on with
         # setting up every test with its own plugins directory.
         if not self.pluginsPath:
             self.pluginsPath = os.path.join(self.appPath, 'plugins')
 
         self.pluginsDir = self.setupPluginsDir()
@@ -752,17 +753,16 @@ class XPCShellTestThread(Thread):
                 self.keep_going = False
                 return
 
         self.keep_going = True
 
 class XPCShellTests(object):
 
     log = getGlobalLog()
-    oldcwd = os.getcwd()
 
     def __init__(self, log=None):
         """ Init logging and node status """
         if log:
             resetGlobalLog(log)
 
         # Each method of the underlying logger must acquire the log
         # mutex before writing to stdout.
@@ -899,17 +899,17 @@ class XPCShellTests(object):
         """
           Determine the value of the stdout and stderr for the test.
           Return value is a list (pStdout, pStderr).
         """
         if self.interactive:
             pStdout = None
             pStderr = None
         else:
-            if (self.debuggerInfo and self.debuggerInfo["interactive"]):
+            if (self.debuggerInfo and self.debuggerInfo.interactive):
                 pStdout = None
                 pStderr = None
             else:
                 if sys.platform == 'os2emx':
                     pStdout = None
                 else:
                     pStdout = PIPE
                 pStderr = STDOUT
@@ -1185,18 +1185,21 @@ class XPCShellTests(object):
         |pluginsPath|, if provided, custom plugins directory to be returned from
           the xpcshell dir svc provider for NS_APP_PLUGINS_DIR_LIST.
         |interactive|, if set to True, indicates to provide an xpcshell prompt
           instead of automatically executing the test.
         |verbose|, if set to True, will cause stdout/stderr from tests to
           be printed always
         |logfiles|, if set to False, indicates not to save output to log files.
           Non-interactive only option.
-        |debuggerInfo|, if set, specifies the debugger and debugger arguments
-          that will be used to launch xpcshell.
+        |debugger|, if set, specifies the name of the debugger that will be used
+          to launch xpcshell.
+        |debuggerArgs|, if set, specifies arguments to use with the debugger.
+        |debuggerInteractive|, if set, allows the debugger to be run in interactive
+          mode.
         |profileName|, if set, specifies the name of the application for the profile
           directory if running only a subset of tests.
         |mozInfo|, if set, specifies specifies build configuration information, either as a filename containing JSON, or a dict.
         |shuffle|, if True, execute tests in random order.
         |testsRootDir|, absolute path to root directory of all tests. This is used
           by xUnit generation to determine the package name of the tests.
         |xunitFilename|, if set, specifies the filename to which to write xUnit XML
           results.
@@ -1242,31 +1245,40 @@ class XPCShellTests(object):
             testingModulesDir = os.path.normpath(testingModulesDir)
 
             if not os.path.isabs(testingModulesDir):
                 testingModulesDir = os.path.abspath(testingModulesDir)
 
             if not testingModulesDir.endswith(os.path.sep):
                 testingModulesDir += os.path.sep
 
+        self.debuggerInfo = None
+
+        if debugger:
+            # We need a list of arguments, not a string, to feed into
+            # the debugger
+            if debuggerArgs:
+                debuggerArgs = debuggerArgs.split();
+
+            self.debuggerInfo = mozdebug.get_debugger_info(debugger, debuggerArgs, debuggerInteractive)
+
         self.xpcshell = xpcshell
         self.xrePath = xrePath
         self.appPath = appPath
         self.symbolsPath = symbolsPath
         self.manifest = manifest
         self.testdirs = testdirs
         self.testPath = testPath
         self.interactive = interactive
         self.verbose = verbose
         self.keepGoing = keepGoing
         self.logfiles = logfiles
         self.on_message = on_message
         self.totalChunks = totalChunks
         self.thisChunk = thisChunk
-        self.debuggerInfo = getDebuggerInfo(self.oldcwd, debugger, debuggerArgs, debuggerInteractive)
         self.profileName = profileName or "xpcshell"
         self.mozInfo = mozInfo
         self.testingModulesDir = testingModulesDir
         self.pluginsPath = pluginsPath
         self.sequential = sequential
 
         if not testdirs and not manifest:
             # nothing to test!
@@ -1357,17 +1369,17 @@ class XPCShellTests(object):
             # when we are only running tests sequentially.
             signal.signal(signal.SIGINT, markGotSIGINT)
 
         if self.debuggerInfo:
             # Force a sequential run
             self.sequential = True
 
             # If we have an interactive debugger, disable SIGINT entirely.
-            if self.debuggerInfo["interactive"]:
+            if self.debuggerInfo.interactive:
                 signal.signal(signal.SIGINT, lambda signum, frame: None)
 
         # create a queue of all tests that will run
         tests_queue = deque()
         # also a list for the tests that need to be run sequentially
         sequential_tests = []
         for test_object in self.alltests:
             name = test_object['path']
--- a/testing/xpcshell/xpcshell_b2g.ini
+++ b/testing/xpcshell/xpcshell_b2g.ini
@@ -22,10 +22,11 @@ requesttimeoutfactor = 2
 [include:toolkit/devtools/sourcemap/tests/unit/xpcshell.ini]
 [include:toolkit/mozapps/downloads/tests/unit/xpcshell.ini]
 [include:toolkit/mozapps/update/tests/unit_aus_update/xpcshell.ini]
 [include:toolkit/mozapps/update/tests/unit_base_updater/xpcshell.ini]
 [include:toolkit/mozapps/update/tests/unit_timermanager/xpcshell.ini]
 [include:ipc/testshell/tests/xpcshell.ini]
 [include:b2g/components/test/unit/xpcshell.ini]
 [include:security/manager/ssl/tests/unit/xpcshell.ini]
+[include:services/fxaccounts/tests/xpcshell/xpcshell.ini]
 [include:toolkit/devtools/discovery/tests/unit/xpcshell.ini]
 [include:toolkit/devtools/security/tests/unit/xpcshell.ini]
--- a/toolkit/mozapps/extensions/internal/XPIProvider.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIProvider.jsm
@@ -1192,36 +1192,37 @@ function getTemporaryFile() {
 }
 
 /**
  * Verifies that a zip file's contents are all signed by the same principal.
  * Directory entries and anything in the META-INF directory are not checked.
  *
  * @param  aZip
  *         A nsIZipReader to check
- * @param  aPrincipal
- *         The nsIPrincipal to compare against
+ * @param  aCertificate
+ *         The nsIX509Cert to compare against
  * @return true if all the contents that should be signed were signed by the
  *         principal
  */
-function verifyZipSigning(aZip, aPrincipal) {
+function verifyZipSigning(aZip, aCertificate) {
   var count = 0;
   var entries = aZip.findEntries(null);
   while (entries.hasMore()) {
     var entry = entries.getNext();
     // Nothing in META-INF is in the manifest.
     if (entry.substr(0, 9) == "META-INF/")
       continue;
     // Directory entries aren't in the manifest.
     if (entry.substr(-1) == "/")
       continue;
     count++;
-    var entryPrincipal = aZip.getCertificatePrincipal(entry);
-    if (!entryPrincipal || !aPrincipal.equals(entryPrincipal))
+    var entryCertificate = aZip.getSigningCert(entry);
+    if (!entryCertificate || !aCertificate.equals(entryCertificate)) {
       return false;
+    }
   }
   return aZip.manifestEntriesCount == count;
 }
 
 /**
  * Replaces %...% strings in an addon url (update and updateInfo) with
  * appropriate values.
  *
@@ -5122,29 +5123,27 @@ AddonInstall.prototype = {
     try {
       zipreader.open(this.file);
     }
     catch (e) {
       zipreader.close();
       throw e;
     }
 
-    let principal = zipreader.getCertificatePrincipal(null);
-    if (principal && principal.hasCertificate) {
+    let x509 = zipreader.getSigningCert(null);
+    if (x509) {
       logger.debug("Verifying XPI signature");
-      if (verifyZipSigning(zipreader, principal)) {
-        let x509 = principal.certificate;
-        if (x509 instanceof Ci.nsIX509Cert)
-          this.certificate = x509;
-        if (this.certificate && this.certificate.commonName.length > 0)
+      if (verifyZipSigning(zipreader, x509)) {
+        this.certificate = x509;
+        if (this.certificate.commonName.length > 0) {
           this.certName = this.certificate.commonName;
-        else
-          this.certName = principal.prettyName;
-      }
-      else {
+        } else {
+          this.certName = this.certificate.organization;
+        }
+      } else {
         zipreader.close();
         throw new Error("XPI is incorrectly signed");
       }
     }
 
     try {
       this.addon = loadManifestFromZipReader(zipreader);
     }
--- a/widget/android/AndroidJNI.cpp
+++ b/widget/android/AndroidJNI.cpp
@@ -74,16 +74,39 @@ NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_GeckoAppShell_notifyGeckoOfEvent(JNIEnv *jenv, jclass jc, jobject event)
 {
     // poke the appshell
     if (nsAppShell::gAppShell)
         nsAppShell::gAppShell->PostEvent(AndroidGeckoEvent::MakeFromJavaObject(jenv, event));
 }
 
 NS_EXPORT void JNICALL
+Java_org_mozilla_gecko_GeckoAppShell_notifyGeckoObservers(JNIEnv *aEnv, jclass,
+                                                         jstring aTopic, jstring aData)
+{
+    if (!NS_IsMainThread()) {
+        AndroidBridge::ThrowException(aEnv,
+            "java/lang/IllegalThreadStateException", "Not on Gecko main thread");
+        return;
+    }
+
+    nsCOMPtr<nsIObserverService> obsServ =
+        mozilla::services::GetObserverService();
+    if (!obsServ) {
+        AndroidBridge::ThrowException(aEnv,
+            "java/lang/IllegalStateException", "No observer service");
+        return;
+    }
+
+    const nsJNICString topic(aTopic, aEnv);
+    const nsJNIString data(aData, aEnv);
+    obsServ->NotifyObservers(nullptr, topic.get(), data.get());
+}
+
+NS_EXPORT void JNICALL
 Java_org_mozilla_gecko_GeckoAppShell_processNextNativeEvent(JNIEnv *jenv, jclass, jboolean mayWait)
 {
     // poke the appshell
     if (nsAppShell::gAppShell)
         nsAppShell::gAppShell->ProcessNextNativeEvent(mayWait != JNI_FALSE);
 }
 
 NS_EXPORT jlong JNICALL
--- a/widget/windows/WinUtils.cpp
+++ b/widget/windows/WinUtils.cpp
@@ -617,31 +617,40 @@ WinUtils::GetMessage(LPMSG aMsg, HWND aW
 #endif // #ifdef NS_ENABLE_TSF
   return ::GetMessageW(aMsg, aWnd, aFirstMessage, aLastMessage);
 }
 
 /* static */
 void
 WinUtils::WaitForMessage()
 {
-  DWORD result = ::MsgWaitForMultipleObjectsEx(0, NULL, INFINITE, QS_ALLINPUT,
-                                               MWMO_INPUTAVAILABLE);
-  NS_WARN_IF_FALSE(result != WAIT_FAILED, "Wait failed");
+  while (true) {
+    DWORD result = ::MsgWaitForMultipleObjectsEx(0, NULL, INFINITE,
+                                                 MOZ_QS_ALLEVENT,
+                                                 MWMO_INPUTAVAILABLE);
+    NS_WARN_IF_FALSE(result != WAIT_FAILED, "Wait failed");
 
-  // This idiom is taken from the Chromium ipc code, see
-  // ipc/chromium/src/base/message+puimp_win.cpp:270.
-  // The intent is to avoid a busy wait when MsgWaitForMultipleObjectsEx
-  // returns quickly but PeekMessage would not return a message.
-  if (result == WAIT_OBJECT_0) {
+    // Sent messages (via SendMessage and friends) are processed differently
+    // than queued messages (via PostMessage); the destination window procedure
+    // of the sent message is called during (Get|Peek)Message. Since PeekMessage
+    // does not tell us whether it processed any sent messages, we need to query
+    // this ahead of time.
+    bool haveSentMessagesPending =
+      (HIWORD(::GetQueueStatus(QS_SENDMESSAGE)) & QS_SENDMESSAGE) != 0;
+
     MSG msg = {0};
-    DWORD queue_status = ::GetQueueStatus(QS_MOUSE);
-    if (HIWORD(queue_status) & QS_MOUSE &&
-        !PeekMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST, PM_NOREMOVE)) {
-      ::WaitMessage();
+    if (haveSentMessagesPending ||
+        ::PeekMessageW(&msg, nullptr, 0, 0, PM_NOREMOVE)) {
+      break;
     }
+    // The message is intended for another thread that has been synchronized
+    // with our input queue; yield to give other threads an opportunity to
+    // process the message. This should prevent busy waiting if resumed due
+    // to another thread's message.
+    ::SwitchToThread();
   }
 }
 
 /* static */
 bool
 WinUtils::GetRegistryKey(HKEY aRoot,
                          char16ptr_t aKeyName,
                          char16ptr_t aValueName,
--- a/xpcom/base/nsStackWalk.cpp
+++ b/xpcom/base/nsStackWalk.cpp
@@ -38,20 +38,16 @@ static CriticalAddress gCriticalAddress;
   (defined(XP_MACOSX) && \
    (defined(__i386) || defined(__ppc__) || defined(HAVE__UNWIND_BACKTRACE)))
 
 #define NSSTACKWALK_SUPPORTS_LINUX \
   (defined(linux) && \
    ((defined(__GNUC__) && (defined(__i386) || defined(PPC))) || \
     defined(HAVE__UNWIND_BACKTRACE)))
 
-#define NSSTACKWALK_SUPPORTS_SOLARIS \
-  (defined(__sun) && \
-   (defined(__sparc) || defined(sparc) || defined(__i386) || defined(i386)))
-
 #if NSSTACKWALK_SUPPORTS_MACOSX
 #include <pthread.h>
 #include <CoreServices/CoreServices.h>
 
 typedef void
 malloc_logger_t(uint32_t aType,
                 uintptr_t aArg1, uintptr_t aArg2, uintptr_t aArg3,
                 uintptr_t aResult, uint32_t aNumHotFramesToSkip);
@@ -858,19 +854,18 @@ NS_FormatCodeAddressDetails(void* aPC, c
       aBuffer[len] = '\0';
     }
   }
   aBuffer[aBufferSize - 2] = '\n';
   aBuffer[aBufferSize - 1] = '\0';
   return NS_OK;
 }
 
-// WIN32 x86 stack walking code
-// i386 or PPC Linux stackwalking code or Solaris
-#elif HAVE_DLADDR && (HAVE__UNWIND_BACKTRACE || NSSTACKWALK_SUPPORTS_LINUX || NSSTACKWALK_SUPPORTS_SOLARIS || NSSTACKWALK_SUPPORTS_MACOSX)
+// i386 or PPC Linux stackwalking code
+#elif HAVE_DLADDR && (HAVE__UNWIND_BACKTRACE || NSSTACKWALK_SUPPORTS_LINUX || NSSTACKWALK_SUPPORTS_MACOSX)
 
 #include <stdlib.h>
 #include <string.h>
 #include "nscore.h"
 #include <stdio.h>
 #include "plstr.h"
 
 // On glibc 2.1, the Dl_info api defined in <dlfcn.h> is only exposed
@@ -899,270 +894,16 @@ void DemangleSymbol(const char* aSymbol,
 
   if (demangled) {
     PL_strncpyz(aBuffer, demangled, aBufLen);
     free(demangled);
   }
 #endif // MOZ_DEMANGLE_SYMBOLS
 }
 
-
-#if NSSTACKWALK_SUPPORTS_SOLARIS
-
-/*
- * Stack walking code for Solaris courtesy of Bart Smaalder's "memtrak".
- */
-
-#include <synch.h>
-#include <ucontext.h>
-#include <sys/frame.h>
-#include <sys/regset.h>
-#include <sys/stack.h>
-
-static int    load_address ( void * pc, void * arg );
-static struct bucket * newbucket ( void * pc );
-static struct frame * cs_getmyframeptr ( void );
-static void   cs_walk_stack ( void * (*read_func)(char * address),
-                              struct frame * fp,
-                              int (*operate_func)(void *, void *, void *),
-                              void * usrarg );
-static void   cs_operate ( void (*operate_func)(void *, void *, void *),
-                           void * usrarg );
-
-#ifndef STACK_BIAS
-#define STACK_BIAS 0
-#endif /*STACK_BIAS*/
-
-#define LOGSIZE 4096
-
-/* type of demangling function */
-typedef int demf_t(const char *, char *, size_t);
-
-static demf_t *demf;
-
-static int initialized = 0;
-
-#if defined(sparc) || defined(__sparc)
-#define FRAME_PTR_REGISTER REG_SP
-#endif
-
-#if defined(i386) || defined(__i386)
-#define FRAME_PTR_REGISTER EBP
-#endif
-
-struct bucket {
-  void * pc;
-  int index;
-  struct bucket * next;
-};
-
-struct my_user_args {
-  NS_WalkStackCallback callback;
-  uint32_t skipFrames;
-  uint32_t maxFrames;
-  uint32_t numFrames;
-  void *closure;
-};
-
-
-static void myinit();
-
-#pragma init (myinit)
-
-static void
-myinit()
-{
-
-  if (!initialized) {
-#ifndef __GNUC__
-    void *handle;
-    const char *libdem = "libdemangle.so.1";
-
-    /* load libdemangle if we can and need to (only try this once) */
-    if ((handle = dlopen(libdem, RTLD_LAZY)) != nullptr) {
-      demf = (demf_t *)dlsym(handle,
-                             "cplus_demangle"); /*lint !e611 */
-      /*
-       * lint override above is to prevent lint from
-       * complaining about "suspicious cast".
-       */
-    }
-#endif /*__GNUC__*/
-  }
-  initialized = 1;
-}
-
-
-static int
-load_address(void * pc, void * arg)
-{
-  static struct bucket table[2048];
-  static mutex_t lock;
-  struct bucket * ptr;
-  struct my_user_args * args = (struct my_user_args *) arg;
-
-  unsigned int val = NS_PTR_TO_INT32(pc);
-
-  ptr = table + ((val >> 2)&2047);
-
-  mutex_lock(&lock);
-  while (ptr->next) {
-    if (ptr->next->pc == pc)
-      break;
-    ptr = ptr->next;
-  }
-
-  int stop = 0;
-  if (ptr->next) {
-    mutex_unlock(&lock);
-  } else {
-    (args->callback)(pc, args->closure);
-    args->numFrames++;
-    if (args->maxFrames != 0 && args->numFrames == args->maxFrames)
-      stop = 1;   // causes us to stop getting frames
-
-    ptr->next = newbucket(pc);
-    mutex_unlock(&lock);
-  }
-  return stop;
-}
-
-
-static struct bucket *
-newbucket(void * pc)
-{
-  struct bucket * ptr = (struct bucket *)malloc(sizeof(*ptr));
-  static int index; /* protected by lock in caller */
-
-  ptr->index = index++;
-  ptr->next = nullptr;
-  ptr->pc = pc;
-  return (ptr);
-}
-
-
-static struct frame *
-csgetframeptr()
-{
-  ucontext_t u;
-  struct frame *fp;
-
-  (void) getcontext(&u);
-
-  fp = (struct frame *)
-    ((char *)u.uc_mcontext.gregs[FRAME_PTR_REGISTER] +
-     STACK_BIAS);
-
-  /* make sure to return parents frame pointer.... */
-
-  return ((struct frame *)((ulong_t)fp->fr_savfp + STACK_BIAS));
-}
-
-
-static void
-cswalkstack(struct frame *fp, int (*operate_func)(void *, void *, void *),
-            void *usrarg)
-{
-
-  while (fp != 0 && fp->fr_savpc != 0) {
-
-    if (operate_func((void *)fp->fr_savpc, nullptr, usrarg) != 0)
-      break;
-    /*
-     * watch out - libthread stacks look funny at the top
-     * so they may not have their STACK_BIAS set
-     */
-
-    fp = (struct frame *)((ulong_t)fp->fr_savfp +
-                          (fp->fr_savfp?(ulong_t)STACK_BIAS:0));
-  }
-}
-
-
-static void
-cs_operate(int (*operate_func)(void *, void *, void *), void * usrarg)
-{
-  cswalkstack(csgetframeptr(), operate_func, usrarg);
-}
-
-EXPORT_XPCOM_API(nsresult)
-NS_StackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames,
-             uint32_t aMaxFrames, void* aClosure, uintptr_t aThread,
-             void* aPlatformData)
-{
-  MOZ_ASSERT(!aThread);
-  MOZ_ASSERT(!aPlatformData);
-  struct my_user_args args;
-
-  StackWalkInitCriticalAddress();
-
-  if (!initialized) {
-    myinit();
-  }
-
-  args.callback = aCallback;
-  args.skipFrames = aSkipFrames; /* XXX Not handled! */
-  args.maxFrames = aMaxFrames;
-  args.numFrames = 0;
-  args.closure = aClosure;
-  cs_operate(load_address, &args);
-  return args.numFrames == 0 ? NS_ERROR_FAILURE : NS_OK;
-}
-
-EXPORT_XPCOM_API(nsresult)
-NS_DescribeCodeAddress(void* aPC, nsCodeAddressDetails* aDetails)
-{
-  aDetails->library[0] = '\0';
-  aDetails->loffset = 0;
-  aDetails->filename[0] = '\0';
-  aDetails->lineno = 0;
-  aDetails->function[0] = '\0';
-  aDetails->foffset = 0;
-
-  char dembuff[4096];
-  Dl_info info;
-
-  if (dladdr(aPC, & info)) {
-    if (info.dli_fname) {
-      PL_strncpyz(aDetails->library, info.dli_fname,
-                  sizeof(aDetails->library));
-      aDetails->loffset = (char*)aPC - (char*)info.dli_fbase;
-    }
-    if (info.dli_sname) {
-      aDetails->foffset = (char*)aPC - (char*)info.dli_saddr;
-#ifdef __GNUC__
-      DemangleSymbol(info.dli_sname, dembuff, sizeof(dembuff));
-#else
-      if (!demf || demf(info.dli_sname, dembuff, sizeof(dembuff))) {
-        dembuff[0] = 0;
-      }
-#endif /*__GNUC__*/
-      PL_strncpyz(aDetails->function,
-                  (dembuff[0] != '\0') ? dembuff : info.dli_sname,
-                  sizeof(aDetails->function));
-    }
-  }
-
-  return NS_OK;
-}
-
-EXPORT_XPCOM_API(nsresult)
-NS_FormatCodeAddressDetails(void* aPC, const nsCodeAddressDetails* aDetails,
-                            char* aBuffer, uint32_t aBufferSize)
-{
-  snprintf(aBuffer, aBufferSize, "%p %s:%s+0x%lx\n",
-           aPC,
-           aDetails->library[0] ? aDetails->library : "??",
-           aDetails->function[0] ? aDetails->function : "??",
-           aDetails->foffset);
-  return NS_OK;
-}
-
-#else // not __sun-specific
-
 #if __GLIBC__ > 2 || __GLIBC_MINOR > 1
 #define HAVE___LIBC_STACK_END 1
 #else
 #define HAVE___LIBC_STACK_END 0
 #endif
 
 #if HAVE___LIBC_STACK_END
 extern void* __libc_stack_end; // from ld-linux.so
@@ -1374,18 +1115,16 @@ NS_FormatCodeAddressDetails(void* aPC, c
     snprintf(aBuffer, aBufferSize, "%s+0x%08" PRIXPTR
              " [%s +0x%08" PRIXPTR "]\n",
              aDetails->function, aDetails->foffset,
              aDetails->library, aDetails->loffset);
   }
   return NS_OK;
 }
 
-#endif
-
 #else // unsupported platform.
 
 EXPORT_XPCOM_API(nsresult)
 NS_StackWalk(NS_WalkStackCallback aCallback, uint32_t aSkipFrames,
              uint32_t aMaxFrames, void* aClosure, uintptr_t aThread,
              void* aPlatformData)
 {
   MOZ_ASSERT(!aThread);
--- a/xpcom/glue/nsProxyRelease.h
+++ b/xpcom/glue/nsProxyRelease.h
@@ -149,16 +149,20 @@ public:
     }
     return mRawPtr;
   }
 
   bool operator==(const nsMainThreadPtrHolder<T>& aOther) const
   {
     return mRawPtr == aOther.mRawPtr;
   }
+  bool operator!() const
+  {
+    return !mRawPtr;
+  }
 
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(nsMainThreadPtrHolder<T>)
 
 private:
   // Our wrapped pointer.
   T* mRawPtr;
 
   // Whether to strictly enforce thread invariants in this class.
@@ -220,12 +224,14 @@ public:
   // These are safe to call on other threads with appropriate external locking.
   bool operator==(const nsMainThreadPtrHandle<T>& aOther) const
   {
     if (!mPtr || !aOther.mPtr) {
       return mPtr == aOther.mPtr;
     }
     return *mPtr == *aOther.mPtr;
   }
-  bool operator!() { return !mPtr; }
+  bool operator!() const {
+    return !mPtr || !*mPtr;
+  }
 };
 
 #endif
--- a/xpcom/glue/nsTArray.h
+++ b/xpcom/glue/nsTArray.h
@@ -1874,17 +1874,17 @@ protected:
   // copy-constructors will call nsAutoArrayBase's implicit copy-constructor,
   // which won't call Init() and set up the auto buffer!
   nsAutoArrayBase(const self_type& aOther)
   {
     Init();
     this->AppendElements(aOther);
   }
 
-  nsAutoArrayBase(const TArrayBase &aOther)
+  explicit nsAutoArrayBase(const TArrayBase &aOther)
   {
     Init();
     this->AppendElements(aOther);
   }
 
   template<typename Allocator>
   nsAutoArrayBase(nsTArray_Impl<elem_type, Allocator>&& aOther)
   {