Merge b-i to m-c
authorPhil Ringnalda <philringnalda@gmail.com>
Sat, 25 Jan 2014 19:58:13 -0800
changeset 181267 611698b4a2469cdd8b589a91d7aa4d67d622f798
parent 181240 ce31e8b8cbbd2ecd8f80940109f17007fbccefcf (current diff)
parent 181266 79ce86d2d0f3e0148d0245b9fc784688ce704b9c (diff)
child 181269 1fd134a0174749342399942abe60e9fa53b70d48
child 181305 05b43154936d3db9ea2c7d6cbb90ab25fbebda65
child 181308 a609b220ec44c121ad0eb9a2bbae14ec4f5b9140
push id3343
push userffxbld
push dateMon, 17 Mar 2014 21:55:32 +0000
treeherdermozilla-beta@2f7d3415f79f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone29.0a1
first release with
nightly linux32
611698b4a246 / 29.0a1 / 20140126030203 / files
nightly linux64
611698b4a246 / 29.0a1 / 20140126030203 / files
nightly mac
611698b4a246 / 29.0a1 / 20140126030203 / files
nightly win32
611698b4a246 / 29.0a1 / 20140126030203 / files
nightly win64
611698b4a246 / 29.0a1 / 20140126030203 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge b-i to m-c
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -860,19 +860,16 @@ pref("b2g.neterror.url", "app://system.g
 
 // Enable Web Speech synthesis API
 pref("media.webspeech.synth.enabled", true);
 
 // Downloads API
 pref("dom.mozDownloads.enabled", true);
 pref("dom.downloads.max_retention_days", 7);
 
-// Downloads API
-pref("dom.mozDownloads.enabled", true);
-
 // Inactivity time in milliseconds after which we shut down the OS.File worker.
 pref("osfile.reset_worker_delay", 5000);
 
 // The URL of the Firefox Accounts auth server backend
 pref("identity.fxaccounts.auth.uri", "https://api-accounts.dev.lcip.org/v1");
 
 // APZC preferences.
 //
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -7,17 +7,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <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="f382061fe95750d584a9078175c421a36892afc9"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="d342388c8c0a33ef72d0ea57707ec5ce89c10242"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="87aa8679560ce09f6445621d6f370d9de722cdba"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
   <!-- 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
@@ -6,17 +6,17 @@
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="fce1a137746dbd354bca1918f02f96d51c40bad2">
     <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="f382061fe95750d584a9078175c421a36892afc9"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="d342388c8c0a33ef72d0ea57707ec5ce89c10242"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="905bfa3548eb75cf1792d0d8412b92113bbd4318"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="c3d7efc45414f1b44cd9c479bb2758c91c4707c0"/>
   <!-- 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/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -7,17 +7,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <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="f382061fe95750d584a9078175c421a36892afc9"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="d342388c8c0a33ef72d0ea57707ec5ce89c10242"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="87aa8679560ce09f6445621d6f370d9de722cdba"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,4 +1,4 @@
 {
-    "revision": "407993cc2cef77f8c8d0415f11996889ed18dc56", 
+    "revision": "0284cd20f5348574b2bbd224ceacc9fb5e5d33da", 
     "repo_path": "/integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -6,17 +6,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <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="f382061fe95750d584a9078175c421a36892afc9"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="d342388c8c0a33ef72d0ea57707ec5ce89c10242"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
   <!-- 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
@@ -5,17 +5,17 @@
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <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="f382061fe95750d584a9078175c421a36892afc9"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="d342388c8c0a33ef72d0ea57707ec5ce89c10242"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
   <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/inari/sources.xml
+++ b/b2g/config/inari/sources.xml
@@ -7,17 +7,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <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="f382061fe95750d584a9078175c421a36892afc9"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="d342388c8c0a33ef72d0ea57707ec5ce89c10242"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="cd5dfce80bc3f0139a56b58aca633202ccaee7f8"/>
--- a/b2g/config/leo/sources.xml
+++ b/b2g/config/leo/sources.xml
@@ -6,17 +6,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <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="f382061fe95750d584a9078175c421a36892afc9"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="d342388c8c0a33ef72d0ea57707ec5ce89c10242"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/b2g/config/mako/sources.xml
+++ b/b2g/config/mako/sources.xml
@@ -6,17 +6,17 @@
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="fce1a137746dbd354bca1918f02f96d51c40bad2">
     <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="f382061fe95750d584a9078175c421a36892afc9"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="d342388c8c0a33ef72d0ea57707ec5ce89c10242"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="905bfa3548eb75cf1792d0d8412b92113bbd4318"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="c3d7efc45414f1b44cd9c479bb2758c91c4707c0"/>
   <!-- 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
@@ -6,17 +6,17 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <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="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <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="f382061fe95750d584a9078175c421a36892afc9"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="d342388c8c0a33ef72d0ea57707ec5ce89c10242"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
--- a/dom/base/IndexedDBHelper.jsm
+++ b/dom/base/IndexedDBHelper.jsm
@@ -51,31 +51,31 @@ IndexedDBHelper.prototype = {
     if (DEBUG) debug("Try to open database:" + self.dbName + " " + self.dbVersion);
     let req = indexedDB.open(this.dbName, this.dbVersion);
     req.onsuccess = function (event) {
       if (DEBUG) debug("Opened database:" + self.dbName + " " + self.dbVersion);
       self._db = event.target.result;
       self._db.onversionchange = function(event) {
         if (DEBUG) debug("WARNING: DB modified from a different window.");
       }
-      aSuccessCb();
+      aSuccessCb && aSuccessCb();
     };
 
     req.onupgradeneeded = function (aEvent) {
       if (DEBUG) {
         debug("Database needs upgrade:" + self.dbName + aEvent.oldVersion + aEvent.newVersion);
         debug("Correct new database version:" + (aEvent.newVersion == this.dbVersion));
       }
 
       let _db = aEvent.target.result;
       self.upgradeSchema(req.transaction, _db, aEvent.oldVersion, aEvent.newVersion);
     };
     req.onerror = function (aEvent) {
       if (DEBUG) debug("Failed to open database: " + self.dbName);
-      aFailureCb(aEvent.target.error.name);
+      aFailureCb && aFailureCb(aEvent.target.error.name);
     };
     req.onblocked = function (aEvent) {
       if (DEBUG) debug("Opening database request is blocked.");
     };
   },
 
   /**
    * Use the cached DB or open a new one.
@@ -83,17 +83,17 @@ IndexedDBHelper.prototype = {
    * @param successCb
    *        Success callback to call.
    * @param failureCb
    *        Error callback to call when an error is encountered.
    */
   ensureDB: function ensureDB(aSuccessCb, aFailureCb) {
     if (this._db) {
       if (DEBUG) debug("ensureDB: already have a database, returning early.");
-      aSuccessCb();
+      aSuccessCb && aSuccessCb();
       return;
     }
     this.open(aSuccessCb, aFailureCb);
   },
 
   /**
    * Start a new transaction.
    *
--- a/dom/base/Navigator.cpp
+++ b/dom/base/Navigator.cpp
@@ -1912,16 +1912,37 @@ Navigator::HasDataStoreSupport(JSContext
   if (NS_FAILED(doc->NodePrincipal()->GetAppStatus(&status))) {
     return false;
   }
 
   return status == nsIPrincipal::APP_STATUS_CERTIFIED;
 }
 
 /* static */
+bool
+Navigator::HasDownloadsSupport(JSContext* aCx, JSObject* aGlobal)
+{
+  // We'll need a rooted object so that GC doesn't make it go away while
+  // we're calling CheckIsChrome.
+  JS::Rooted<JSObject*> global(aCx, aGlobal);
+
+  // Because of the way this API must be implemented, it will interact with
+  // objects attached to a chrome window. We always want to allow this.
+  if (ThreadsafeCheckIsChrome(aCx, global)) {
+    return true;
+  }
+
+  nsCOMPtr<nsPIDOMWindow> win = GetWindowFromGlobal(global);
+
+  return win &&
+         CheckPermission(win, "downloads")  &&
+         Preferences::GetBool("dom.mozDownloads.enabled");
+}
+
+/* static */
 already_AddRefed<nsPIDOMWindow>
 Navigator::GetWindowFromGlobal(JSObject* aGlobal)
 {
   nsCOMPtr<nsPIDOMWindow> win =
     do_QueryInterface(nsJSUtils::GetStaticScriptGlobal(aGlobal));
   MOZ_ASSERT(!win || win->IsInnerWindow());
   return win.forget();
 }
--- a/dom/base/Navigator.h
+++ b/dom/base/Navigator.h
@@ -285,16 +285,18 @@ public:
 
   static bool HasPushNotificationsSupport(JSContext* /* unused */,
                                           JSObject* aGlobal);
 
   static bool HasInputMethodSupport(JSContext* /* unused */, JSObject* aGlobal);
 
   static bool HasDataStoreSupport(JSContext* cx, JSObject* aGlobal);
 
+  static bool HasDownloadsSupport(JSContext* aCx, JSObject* aGlobal);
+
   nsPIDOMWindow* GetParentObject() const
   {
     return GetWindow();
   }
 
   virtual JSObject* WrapObject(JSContext* cx,
                                JS::Handle<JSObject*> scope) MOZ_OVERRIDE;
 
--- a/dom/downloads/src/DownloadsAPI.js
+++ b/dom/downloads/src/DownloadsAPI.js
@@ -201,22 +201,22 @@ function createDOMDownloadObject(aWindow
 function DOMDownloadImpl() {
   debug("DOMDownloadImpl constructor ");
 
   this.wrappedJSObject = this;
   this.totalBytes = 0;
   this.currentBytes = 0;
   this.url = null;
   this.path = null;
-  this.state = "stopped";
   this.contentType = null;
 
   /* fields that require getters/setters */
   this._error = null;
   this._startTime = new Date();
+  this._state = "stopped";
 
   /* private fields */
   this.id = null;
 }
 
 DOMDownloadImpl.prototype = {
 
   createPromise: function(aPromiseInit) {
@@ -265,16 +265,35 @@ DOMDownloadImpl.prototype = {
     if (aStartTime instanceof Date) {
       this._startTime = aStartTime;
     }
     else {
       this._startTime = new Date(aStartTime);
     }
   },
 
+  get state() {
+    return this._state;
+  },
+
+  // We require a setter here to simplify the internals of the Download Manager
+  // since we actually pass dummy JSON objects to the child process and update
+  // them. This is the case for all other setters for read-only attributes
+  // implemented in this object.
+  set state(aState) {
+    // We need to ensure that XPCOM consumers of this API respect the enum
+    // values as well.
+    if (["downloading",
+         "stopped",
+         "succeeded",
+         "finalized"].indexOf(aState) != -1) {
+      this._state = aState;
+    }
+  },
+
   _init: function(aWindow, aDownload) {
     this._window = aWindow;
     this.id = aDownload.id;
     this._update(aDownload);
     Services.obs.addObserver(this, "downloads-state-change-" + this.id,
                              /* ownsWeak */ true);
     debug("observer set for " + this.id);
   },
--- a/dom/downloads/tests/serve_file.sjs
+++ b/dom/downloads/tests/serve_file.sjs
@@ -4,34 +4,48 @@ function getQuery(request) {
   var query = {};
   request.queryString.split('&').forEach(function (val) {
     var [name, value] = val.split('=');
     query[name] = unescape(value);
   });
   return query;
 }
 
-// Timer used to handle the request response.
-var timer = null;
-
 function handleResponse() {
   // Is this a rate limited response?
   if (this.state.rate > 0) {
     // Calculate how many bytes we have left to send.
     var bytesToWrite = this.state.totalBytes - this.state.sentBytes;
 
     // Do we have any bytes left to send? If not we'll just fall thru and
     // cancel our repeating timer and finalize the response.
     if (bytesToWrite > 0) {
       // Figure out how many bytes to send, based on the rate limit.
       bytesToWrite =
         (bytesToWrite > this.state.rate) ? this.state.rate : bytesToWrite;
 
       for (let i = 0; i < bytesToWrite; i++) {
-        this.response.write("0");
+        try {
+          this.response.bodyOutputStream.write("0", 1);
+        } catch (e) {
+          // Connection was closed by client.
+          if (e == Components.results.NS_ERROR_NOT_AVAILABLE) {
+            // There's no harm in calling this multiple times.
+            this.response.finish();
+
+            // It's possible that our timer wasn't cancelled in time
+            // and we'll be called again.
+            if (this.timer) {
+              this.timer.cancel();
+              this.timer = null;
+            }
+
+            return;
+          }
+        }
       }
 
       // Update the number of bytes we've sent to the client.
       this.state.sentBytes += bytesToWrite;
 
       // Wait until the next call to do anything else.
       return;
     }
@@ -42,22 +56,29 @@ function handleResponse() {
       this.response.write("0");
     }
   }
 
   // Finalize the response.
   this.response.finish();
 
   // All done sending, go ahead and cancel our repeating timer.
-  timer.cancel();
+  this.timer.cancel();
+
+  // Clear the timer.
+  this.timer = null;
 }
 
 function handleRequest(request, response) {
   var query = getQuery(request);
 
+  // sending at a specific rate requires our response to be asynchronous so
+  // we handle all requests asynchronously. See handleResponse().
+  response.processAsync();
+
   // Default status when responding.
   var version = "1.1";
   var statusCode = 200;
   var description = "OK";
 
   // Default values for content type, size and rate.
   var contentType = "text/plain";
   var contentRange = null;
@@ -115,36 +136,35 @@ function handleRequest(request, response
   // The context for the responseHandler.
   var context = {
     response: response,
     state: {
       contentType: contentType,
       totalBytes: size,
       sentBytes: 0,
       rate: rate
-    }
+    },
+    timer: null
   };
 
   // The notify implementation for the timer.
   context.notify = handleResponse.bind(context);
 
-  timer =
+  context.timer =
     Components.classes["@mozilla.org/timer;1"]
               .createInstance(Components.interfaces.nsITimer);
 
-  // sending at a specific rate requires our response to be asynchronous so
-  // we handle all requests asynchronously. See handleResponse().
-  response.processAsync();
-
   // generate the content.
   response.setStatusLine(version, statusCode, description);
   response.setHeader("Content-Type", contentType, false);
   if (contentRange) {
     response.setHeader("Content-Range", contentRange, false);
   }
   response.setHeader("Content-Length", size.toString(), false);
 
   // initialize the timer and start writing out the response.
-  timer.initWithCallback(context,
-                         1000,
-                         Components.interfaces.nsITimer.TYPE_REPEATING_SLACK);
+  context.timer.initWithCallback(
+    context,
+    1000,
+    Components.interfaces.nsITimer.TYPE_REPEATING_SLACK
+  );
 
 }
--- a/dom/src/notification/NotificationDB.jsm
+++ b/dom/src/notification/NotificationDB.jsm
@@ -52,16 +52,28 @@ let NotificationDB = {
     var promise = OS.File.read(NOTIFICATION_STORE_PATH);
     promise.then(
       function onSuccess(data) {
         try {
           this.notifications = JSON.parse(gDecoder.decode(data));
         } catch (e) {
           if (DEBUG) { debug("Unable to parse file data " + e); }
         }
+        // populate the list of notifications by tag
+        if (this.notifications) {
+          for (var origin in this.notifications) {
+            this.byTag[origin] = {};
+            for (var id in this.notifications[origin]) {
+              var curNotification = this.notifications[origin][id];
+              if (curNotification.tag) {
+                this.byTag[origin][curNotification.tag] = curNotification;
+              }
+            }
+          }
+        }
         this.loaded = true;
         callback && callback();
       }.bind(this),
 
       // If read failed, we assume we have no notifications to load.
       function onFailure(reason) {
         this.loaded = true;
         this.createStore(callback);
@@ -123,37 +135,47 @@ let NotificationDB = {
     } else {
       callback();
     }
   },
 
   receiveMessage: function(message) {
     if (DEBUG) { debug("Received message:" + message.name); }
 
+    // sendAsyncMessage can fail if the child process exits during a
+    // notification storage operation, so always wrap it in a try/catch.
+    function returnMessage(name, data) {
+      try {
+        message.target.sendAsyncMessage(name, data);
+      } catch (e) {
+        if (DEBUG) { debug("Return message failed, " + name); }
+      }
+    }
+
     switch (message.name) {
       case "Notification:GetAll":
         this.queueTask("getall", message.data, function(notifications) {
-          message.target.sendAsyncMessage("Notification:GetAll:Return:OK", {
+          returnMessage("Notification:GetAll:Return:OK", {
             requestID: message.data.requestID,
             notifications: notifications
           });
         });
         break;
 
       case "Notification:Save":
         this.queueTask("save", message.data, function() {
-          message.target.sendAsyncMessage("Notification:Save:Return:OK", {
+          returnMessage("Notification:Save:Return:OK", {
             requestID: message.data.requestID
           });
         });
         break;
 
       case "Notification:Delete":
         this.queueTask("delete", message.data, function() {
-          message.target.sendAsyncMessage("Notification:Delete:Return:OK", {
+          returnMessage("Notification:Delete:Return:OK", {
             requestID: message.data.requestID
           });
         });
         break;
 
       default:
         if (DEBUG) { debug("Invalid message name" + message.name); }
     }
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -322,22 +322,16 @@ var interfaceNamesInGlobalScope =
     "DOMStringList",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "DOMStringMap",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "DOMTokenList",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "DOMTransactionEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "DOMDownload", b2g: true, pref: "dom.mozDownloads.enabled"},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "DOMDownloadManager", b2g: true, pref: "dom.mozDownloads.enabled"},
-// IMPORTANT: Do not change this list without review from a DOM peer!
-    {name: "DownloadEvent", b2g: true, pref: "dom.mozDownloads.enabled"},
-// IMPORTANT: Do not change this list without review from a DOM peer!
     "DragEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "DynamicsCompressorNode",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "Element",
 // IMPORTANT: Do not change this list without review from a DOM peer!
     "ElementReplaceEvent",
 // IMPORTANT: Do not change this list without review from a DOM peer!
--- a/dom/webidl/DownloadEvent.webidl
+++ b/dom/webidl/DownloadEvent.webidl
@@ -1,16 +1,16 @@
 /* -*- 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/.
  */
 
 [Constructor(DOMString type, optional DownloadEventInit eventInitDict),
- Pref="dom.mozDownloads.enabled"]
+ Func="Navigator::HasDownloadsSupport"]
 interface DownloadEvent : Event
 {
   readonly attribute DOMDownload? download;
 };
 
 dictionary DownloadEventInit : EventInit
 {
   DOMDownload? download = null;
--- a/dom/webidl/Downloads.webidl
+++ b/dom/webidl/Downloads.webidl
@@ -1,15 +1,34 @@
 /* -*- 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/.
  */
 
-[NavigatorProperty="mozDownloadManager",
+// Represents the state of a download.
+// "downloading": The resource is actively transfering.
+// "stopped"    : No network tranfer is happening.
+// "succeeded"  : The resource has been downloaded successfully.
+// "finalized"  : We won't try to download this resource, but the DOM
+//                object is still alive.
+enum DownloadState {
+  "downloading",
+  "stopped",
+  "succeeded",
+  "finalized"
+};
+
+//
+// XXXTODO: When we have a generic way to do feature detection in marketplace
+//          we will *STOP* using the pref and use the function like DOMDownload
+//          and DownloadEvent.
+//
+[NoInterfaceObject,
+ NavigatorProperty="mozDownloadManager",
  JSImplementation="@mozilla.org/downloads/manager;1",
  Pref="dom.mozDownloads.enabled"]
 interface DOMDownloadManager : EventTarget {
   // This promise returns an array of downloads with all the current
   // download objects.
   Promise getDownloads();
 
   // Removes one download from the downloads set. Returns a promise resolved
@@ -19,38 +38,33 @@ interface DOMDownloadManager : EventTarg
   // Removes all the completed downloads from the set.
   Promise clearAllDone();
 
   // Fires when a new download starts.
   attribute EventHandler ondownloadstart;
 };
 
 [JSImplementation="@mozilla.org/downloads/download;1",
- Pref="dom.mozDownloads.enabled"]
+ Func="Navigator::HasDownloadsSupport"]
 interface DOMDownload : EventTarget {
   // The full size of the resource.
   readonly attribute long totalBytes;
 
   // The number of bytes that we have currently downloaded.
   readonly attribute long currentBytes;
 
   // The url of the resource.
   readonly attribute DOMString url;
 
   // The path in local storage where the file will end up once the download
   // is complete.
   readonly attribute DOMString path;
 
-  // The state of the download. Can be any of:
-  // "downloading": The resource is actively transfering.
-  // "stopped"    : No network tranfer is happening.
-  // "succeeded"  : The resource has been downloaded successfully.
-  // "finalized"  : We won't try to download this resource, but the DOM
-  //                object is still alive.
-  readonly attribute DOMString state;
+  // The state of the download.
+  readonly attribute DownloadState state;
 
   // The mime type for this resource.
   readonly attribute DOMString contentType;
 
   // The timestamp this download started.
   readonly attribute Date startTime;
 
   // An opaque identifier for this download. All instances of the same
--- a/testing/mochitest/b2g-debug.json
+++ b/testing/mochitest/b2g-debug.json
@@ -300,16 +300,17 @@
     "dom/file/test/test_write_read_data.html":"",
 
     "dom/imptests/editing/conformancetest/test_runtest.html":"takes too long",
 
     "dom/media/tests/mochitest/test_dataChannel_basicAudio.html":"Bug 962984, test fail on b2g debug build",
     "dom/media/tests/mochitest/test_dataChannel_basicAudioVideo.html":"Bug 960442, video support for WebRTC is disabled on b2g",
     "dom/media/tests/mochitest/test_dataChannel_basicAudioVideoCombined.html":"Bug 960442, video support for WebRTC is disabled on b2g",
     "dom/media/tests/mochitest/test_dataChannel_basicVideo.html":"Bug 960442, video support for WebRTC is disabled on b2g",
+    "dom/media/tests/mochitest/test_peerConnection_basicAudio.html":"Bug 962984, test fail on b2g debug build",
     "dom/media/tests/mochitest/test_peerConnection_basicAudioVideo.html":"Bug 960442, video support for WebRTC is disabled on b2g",
     "dom/media/tests/mochitest/test_peerConnection_basicAudioVideoCombined.html":"Bug 960442, video support for WebRTC is disabled on b2g",
     "dom/media/tests/mochitest/test_peerConnection_basicVideo.html":"Bug 960442, video support for WebRTC is disabled on b2g",
     "dom/media/tests/mochitest/test_peerConnection_bug827843.html":"Bug 960442, video support for WebRTC is disabled on b2g",
     "dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveAudio.html":"Bug 960442, video support for WebRTC is disabled on b2g",
     "dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveVideo.html":"Bug 960442, video support for WebRTC is disabled on b2g",
     "dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveVideoAudio.html":"Bug 960442, video support for WebRTC is disabled on b2g",
     "dom/media/tests/mochitest/test_peerConnection_throwInCallbacks.html":"Bug 960442, video support for WebRTC is disabled on b2g",
--- a/testing/mozbase/mozprocess/mozprocess/processhandler.py
+++ b/testing/mozbase/mozprocess/mozprocess/processhandler.py
@@ -105,46 +105,44 @@ class ProcessHandlerMixin(object):
                         self._internal_poll(_deadstate=_maxint)
                     else:
                         self.poll(_deadstate=sys.maxint)
                 if self._handle or self._job or self._io_port:
                     self._cleanup()
             else:
                 subprocess.Popen.__del__(self)
 
-        def kill(self):
+        def kill(self, sig=None):
             self.returncode = 0
             if isWin:
                 if not self._ignore_children and self._handle and self._job:
                     winprocess.TerminateJobObject(self._job, winprocess.ERROR_CONTROL_C_EXIT)
                     self.returncode = winprocess.GetExitCodeProcess(self._handle)
                 elif self._handle:
                     err = None
                     try:
                         winprocess.TerminateProcess(self._handle, winprocess.ERROR_CONTROL_C_EXIT)
                     except:
                         err = "Could not terminate process"
                     self.returncode = winprocess.GetExitCodeProcess(self._handle)
                     self._cleanup()
                     if err is not None:
                         raise OSError(err)
-                else:
-                    pass
             else:
+                sig = sig or signal.SIGKILL
                 if not self._ignore_children:
                     try:
-                        os.killpg(self.pid, signal.SIGKILL)
+                        os.killpg(self.pid, sig)
                     except BaseException, e:
                         if getattr(e, "errno", None) != 3:
                             # Error 3 is "no such process", which is ok
                             print >> sys.stdout, "Could not kill process, could not find pid: %s, assuming it's already dead" % self.pid
                 else:
-                    os.kill(self.pid, signal.SIGKILL)
-                if self.returncode is None:
-                    self.returncode = subprocess.Popen._internal_poll(self)
+                    os.kill(self.pid, sig)
+                self.returncode = -sig
 
             self._cleanup()
             return self.returncode
 
         def wait(self):
             """ Popen.wait
                 Called to wait for a running process to shut down and return
                 its exit code
@@ -412,17 +410,17 @@ falling back to not using job objects fo
 
                 # Python 2.5 uses isAlive versus is_alive use the proper one
                 threadalive = False
                 if hasattr(self, "_procmgrthread"):
                     if hasattr(self._procmgrthread, 'is_alive'):
                         threadalive = self._procmgrthread.is_alive()
                     else:
                         threadalive = self._procmgrthread.isAlive()
-                if self._job and threadalive: 
+                if self._job and threadalive:
                     # Then we are managing with IO Completion Ports
                     # wait on a signal so we know when we have seen the last
                     # process come through.
                     # We use queues to synchronize between the thread and this
                     # function because events just didn't have robust enough error
                     # handling on pre-2.7 versions
                     err = None
                     try:
@@ -638,30 +636,33 @@ falling back to not using job objects fo
         # build process arguments
         args.update(self.keywordargs)
 
         # launch the process
         self.proc = self.Process([self.cmd] + self.args, **args)
 
         self.processOutput(timeout=timeout, outputTimeout=outputTimeout)
 
-    def kill(self):
+    def kill(self, sig=None):
         """
         Kills the managed process.
 
         If you created the process with 'ignore_children=False' (the
         default) then it will also also kill all child processes spawned by
         it. If you specified 'ignore_children=True' when creating the
         process, only the root process will be killed.
 
         Note that this does not manage any state, save any output etc,
         it immediately kills the process.
+
+        :param sig: Signal used to kill the process, defaults to SIGKILL
+                    (has no effect on Windows)
         """
         try:
-            return self.proc.kill()
+            return self.proc.kill(sig=sig)
         except AttributeError:
             # Try to print a relevant error message.
             if not self.proc:
                 print >> sys.stderr, "Unable to kill Process because call to ProcessHandler constructor failed."
             else:
                 raise
 
     def readWithTimeout(self, f, timeout):
--- a/testing/mozbase/mozprocess/tests/test_mozprocess_kill.py
+++ b/testing/mozbase/mozprocess/tests/test_mozprocess_kill.py
@@ -18,57 +18,61 @@ class ProcTestKill(proctest.ProcTest):
                                           cwd=here)
         p.run()
         p.kill()
 
         detected, output = proctest.check_for_process(self.proclaunch)
         self.determine_status(detected,
                               output,
                               p.proc.returncode,
-                              p.didTimeout)
+                              p.didTimeout,
+                              expectedfail=('returncode',))
 
     def test_process_kill_deep(self):
         """Process is started, we kill it, we use a deep process tree"""
 
         p = processhandler.ProcessHandler([self.python, self.proclaunch, "process_normal_deep_python.ini"],
                                           cwd=here)
         p.run()
         p.kill()
 
         detected, output = proctest.check_for_process(self.proclaunch)
         self.determine_status(detected,
                               output,
                               p.proc.returncode,
-                              p.didTimeout)
+                              p.didTimeout,
+                              expectedfail=('returncode',))
 
     def test_process_kill_deep_wait(self):
         """Process is started, we use a deep process tree, we let it spawn
            for a bit, we kill it"""
 
         p = processhandler.ProcessHandler([self.python, self.proclaunch, "process_normal_deep_python.ini"],
                                           cwd=here)
         p.run()
         # Let the tree spawn a bit, before attempting to kill
         time.sleep(3)
         p.kill()
 
         detected, output = proctest.check_for_process(self.proclaunch)
         self.determine_status(detected,
                               output,
                               p.proc.returncode,
-                              p.didTimeout)
+                              p.didTimeout,
+                              expectedfail=('returncode',))
 
     def test_process_kill_broad(self):
         """Process is started, we kill it, we use a broad process tree"""
 
         p = processhandler.ProcessHandler([self.python, self.proclaunch, "process_normal_broad_python.ini"],
                                           cwd=here)
         p.run()
         p.kill()
 
         detected, output = proctest.check_for_process(self.proclaunch)
         self.determine_status(detected,
                               output,
                               p.proc.returncode,
-                              p.didTimeout)
+                              p.didTimeout,
+                              expectedfail=('returncode',))
 
 if __name__ == '__main__':
     unittest.main()
--- a/testing/mozbase/mozprocess/tests/test_mozprocess_kill_broad_wait.py
+++ b/testing/mozbase/mozprocess/tests/test_mozprocess_kill_broad_wait.py
@@ -24,12 +24,13 @@ class ProcTestKill(proctest.ProcTest):
         # Let the tree spawn a bit, before attempting to kill
         time.sleep(3)
         p.kill()
 
         detected, output = proctest.check_for_process(self.proclaunch)
         self.determine_status(detected,
                               output,
                               p.proc.returncode,
-                              p.didTimeout)
+                              p.didTimeout,
+                              expectedfail=('returncode',))
 
 if __name__ == '__main__':
     unittest.main()
--- a/testing/mozbase/mozrunner/mozrunner/runner.py
+++ b/testing/mozbase/mozrunner/mozrunner/runner.py
@@ -65,49 +65,60 @@ class Runner(object):
             # this run uses the managed processhandler
             self.process_handler = self.process_class(cmd, env=self.env, **self.kp_kwargs)
             self.process_handler.run(timeout, outputTimeout)
 
     def wait(self, timeout=None):
         """
         Wait for the process to exit.
         Returns the process return code if the process exited,
-        returns None otherwise.
+        returns -<signal> if the process was killed (Unix only)
+        returns None if the process is still running.
 
-        If timeout is not None, will return after timeout seconds.
-        Use is_running() to determine whether or not a timeout occured.
-        Timeout is ignored if interactive was set to True.
+        :param timeout: if not None, will return after timeout seconds.
+                        Use is_running() to determine whether or not a
+                        timeout occured. Timeout is ignored if
+                        interactive was set to True.
         """
         if self.process_handler is not None:
             if isinstance(self.process_handler, subprocess.Popen):
                 self.returncode = self.process_handler.wait()
             else:
                 self.process_handler.wait(timeout)
+
+                if not self.process_handler:
+                    # the process was killed by another thread
+                    return self.returncode
+
+                # the process terminated, retrieve the return code
                 self.returncode = self.process_handler.proc.poll()
                 if self.returncode is not None:
                     self.process_handler = None
         elif self.returncode is None:
             raise RunnerNotStartedError("Wait called before runner started")
 
         return self.returncode
 
     def is_running(self):
         """
         Returns True if the process is still running, False otherwise
         """
         return self.process_handler is not None
 
 
-    def stop(self):
+    def stop(self, sig=None):
         """
         Kill the process
+
+        :param sig: Signal used to kill the process, defaults to SIGKILL
+                    (has no effect on Windows).
         """
         if self.process_handler is None:
             return
-        self.process_handler.kill()
+        self.returncode = self.process_handler.kill(sig=sig)
         self.process_handler = None
 
     def reset(self):
         """
         Reset the runner to its default state
         """
         if getattr(self, 'profile', False):
             self.profile.reset()
--- a/widget/gonk/nsWindow.cpp
+++ b/widget/gonk/nsWindow.cpp
@@ -526,17 +526,17 @@ nsWindow::GetDefaultScaleInternal()
     // We'll take the mid-value between these three numbers as the boundary.
     if (dpi < 200.0) {
         return 1.0; // mdpi devices.
     }
     if (dpi < 300.0) {
         return 1.5; // hdpi devices.
     }
     // xhdpi devices and beyond.
-    return floor(dpi / 150.0);
+    return floor(dpi / 150.0 + 0.5);
 }
 
 LayerManager *
 nsWindow::GetLayerManager(PLayerTransactionChild* aShadowManager,
                           LayersBackend aBackendHint,
                           LayerManagerPersistence aPersistence,
                           bool* aAllowRetaining)
 {