Merge m-c to fx-team
authorWes Kocher <wkocher@mozilla.com>
Wed, 14 May 2014 16:35:34 -0700
changeset 183199 e74c91d8a96953fb3be43e945ce4cc1568e381fd
parent 183198 25fa9e0e5b06a72134aa7cd626cea70519b4210e (current diff)
parent 183182 e4843f4f08a77c337ec6cf4e0a6bf44e0e3699d8 (diff)
child 183200 95cc116fac5a4ac195dad18e632519fe5b881c9a
push idunknown
push userunknown
push dateunknown
milestone32.0a1
Merge m-c to fx-team
--- a/b2g/chrome/content/settings.js
+++ b/b2g/chrome/content/settings.js
@@ -629,70 +629,82 @@ SettingsListener.observe("accessibility.
     let setting = {};
     setting[gaiaSettingName] = prefValue;
     window.navigator.mozSettings.createLock().set(setting);
   });
 })();
 
 // =================== Various simple mapping  ======================
 let settingsToObserve = {
-  'ril.mms.retrieval_mode': {
-    prefName: 'dom.mms.retrieval_mode',
-    defaultValue: 'manual'
-  },
-  'ril.sms.strict7BitEncoding.enabled': {
-    prefName: 'dom.sms.strict7BitEncoding',
-    defaultValue: false
-  },
-  'ril.sms.requestStatusReport.enabled': {
-    prefName: 'dom.sms.requestStatusReport',
-    defaultValue: false
+  'app.update.channel': {
+    resetToPref: true
   },
-  'ril.mms.requestStatusReport.enabled': {
-    prefName: 'dom.mms.requestStatusReport',
-    defaultValue: false
+  'app.update.interval': 86400,
+  'app.update.url': {
+    resetToPref: true
   },
-  'ril.mms.requestReadReport.enabled': {
-    prefName: 'dom.mms.requestReadReport',
-    defaultValue: true
-  },
-  'ril.cellbroadcast.disabled': false,
-  'ril.radio.disabled': false,
-  'wap.UAProf.url': '',
-  'wap.UAProf.tagname': 'x-wap-profile',
-  'devtools.eventlooplag.threshold': 100,
-  'privacy.donottrackheader.enabled': false,
   'apz.force-enable': {
     prefName: 'dom.browser_frames.useAsyncPanZoom',
     defaultValue: false
   },
-  'layers.enable-tiles': true,
-  'layers.simple-tiles': false,
-  'layers.draw-tile-borders': false,
-  'layers.dump': false,
   'debug.fps.enabled': {
     prefName: 'layers.acceleration.draw-fps',
     defaultValue: false
   },
+  'debug.log-animations.enabled': {
+    prefName: 'layers.offmainthreadcomposition.log-animations',
+    defaultValue: false
+  },
   'debug.paint-flashing.enabled': {
     prefName: 'nglayout.debug.paint_flashing',
     defaultValue: false
   },
+  'devtools.eventlooplag.threshold': 100,
   'layers.draw-borders': false,
-  'app.update.interval': 86400,
-  'app.update.url': {
+  'layers.draw-tile-borders': false,
+  'layers.dump': false,
+  'layers.enable-tiles': true,
+  'layers.simple-tiles': false,
+  'privacy.donottrackheader.enabled': false,
+  'ril.cellbroadcast.disabled': false,
+  'ril.radio.disabled': false,
+  'ril.mms.requestReadReport.enabled': {
+    prefName: 'dom.mms.requestReadReport',
+    defaultValue: true
+  },
+  'ril.mms.requestStatusReport.enabled': {
+    prefName: 'dom.mms.requestStatusReport',
+    defaultValue: false
+  },
+  'ril.mms.retrieval_mode': {
+    prefName: 'dom.mms.retrieval_mode',
+    defaultValue: 'manual'
+  },
+  'ril.sms.requestStatusReport.enabled': {
+    prefName: 'dom.sms.requestStatusReport',
+    defaultValue: false
+  },
+  'ril.sms.strict7BitEncoding.enabled': {
+    prefName: 'dom.sms.strict7BitEncoding',
+    defaultValue: false
+  },
+  'ui.touch.radius.leftmm': {
     resetToPref: true
   },
-  'app.update.channel': {
+  'ui.touch.radius.topmm': {
+    resetToPref: true
+  },
+  'ui.touch.radius.rightmm': {
     resetToPref: true
   },
-  'debug.log-animations.enabled': {
-    prefName: 'layers.offmainthreadcomposition.log-animations',
-    defaultValue: false
-  }
+  'ui.touch.radius.bottommm': {
+    resetToPref: true
+  },
+  'wap.UAProf.tagname': 'x-wap-profile',
+  'wap.UAProf.url': ''
 };
 
 for (let key in settingsToObserve) {
   let setting = settingsToObserve[key];
 
   // Allow setting to contain flags redefining prefName and defaultValue.
   let prefName = setting.prefName || key;
   let defaultValue = setting.defaultValue;
--- a/b2g/components/FxAccountsMgmtService.jsm
+++ b/b2g/components/FxAccountsMgmtService.jsm
@@ -66,23 +66,28 @@ this.FxAccountsMgmtService = {
           eventName: aTopic.substring(aTopic.indexOf(":") + 1)
         });
         break;
     }
   },
 
   handleEvent: function(aEvent) {
     let msg = aEvent.detail;
-    log.debug("Got content msg " + JSON.stringify(msg));
+    log.debug("MgmtService got content event: " + JSON.stringify(msg));
     let self = FxAccountsMgmtService;
 
     if (!msg.id) {
       return;
     }
 
+    if (msg.error) {
+      self._onReject(msg.id, msg.error);
+      return;
+    }
+
     let data = msg.data;
     if (!data) {
       return;
     }
     // Backwards compatibility: handle accountId coming from Gaia
     if (data.accountId && typeof(data.email === "undefined")) {
       data.email = data.accountId;
       delete data.accountId;
--- a/b2g/components/FxAccountsUIGlue.js
+++ b/b2g/components/FxAccountsUIGlue.js
@@ -33,17 +33,17 @@ FxAccountsUIGlue.prototype = {
       let msg = result.detail;
       if (!msg || !msg.id || msg.id != id) {
         deferred.reject("InternalErrorWrongContentEvent");
         SystemAppProxy.removeEventListener("mozFxAccountsRPContentEvent",
                                            onContentEvent);
         return;
       }
 
-      log.debug("Got content event " + JSON.stringify(msg));
+      log.debug("UIGlue got content event " + JSON.stringify(msg));
 
       if (msg.error) {
         deferred.reject(msg);
       } else {
         deferred.resolve(msg.result);
       }
       SystemAppProxy.removeEventListener("mozFxAccountsRPContentEvent",
                                          onContentEvent);
--- 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="2a165bebfa19b11b697837409f9550dd2917c46c">
     <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="70953f779faf6b1a94861c34ffdc3d5fd1c442e5"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="3a1d67246a79e3632c3b3f2460a25291e7e2714c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="abedd83e1ba61cb83e59c723ad6279ad2a7aa1d1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="ca283b9db2b151d465cfd2e19346cf58fe89e413"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="d5800c36b2d5822fc3fe1899b9280401de466e1e"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="fd4be2909b788b563435fe0addb1bd98dfa75457"/>
   <!-- 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="e6383e6e785cc3ea237e902beb1092f9aa88e29d">
     <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="70953f779faf6b1a94861c34ffdc3d5fd1c442e5"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="3a1d67246a79e3632c3b3f2460a25291e7e2714c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="abedd83e1ba61cb83e59c723ad6279ad2a7aa1d1"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="fd4be2909b788b563435fe0addb1bd98dfa75457"/>
   <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="65fba428f8d76336b33ddd9e15900357953600ba">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="70953f779faf6b1a94861c34ffdc3d5fd1c442e5"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="3a1d67246a79e3632c3b3f2460a25291e7e2714c"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="abedd83e1ba61cb83e59c723ad6279ad2a7aa1d1"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <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="fd4be2909b788b563435fe0addb1bd98dfa75457"/>
   <!-- Stock Android things -->
--- 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="2a165bebfa19b11b697837409f9550dd2917c46c">
     <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="70953f779faf6b1a94861c34ffdc3d5fd1c442e5"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="3a1d67246a79e3632c3b3f2460a25291e7e2714c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="abedd83e1ba61cb83e59c723ad6279ad2a7aa1d1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="ca283b9db2b151d465cfd2e19346cf58fe89e413"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="d5800c36b2d5822fc3fe1899b9280401de466e1e"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="fd4be2909b788b563435fe0addb1bd98dfa75457"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -11,19 +11,19 @@
   <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="e6383e6e785cc3ea237e902beb1092f9aa88e29d">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
-  <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
+  <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="70953f779faf6b1a94861c34ffdc3d5fd1c442e5"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="3a1d67246a79e3632c3b3f2460a25291e7e2714c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="abedd83e1ba61cb83e59c723ad6279ad2a7aa1d1"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="fd4be2909b788b563435fe0addb1bd98dfa75457"/>
   <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"/>
@@ -114,17 +114,17 @@
   <project name="platform/system/media" path="system/media" revision="df2cdd433738a891102873710bdd3c3db7adb0cc"/>
   <project name="platform/system/netd" path="system/netd" revision="ea8103eae5642621ca8202e00620f4ca954ed413"/>
   <project name="platform/system/security" path="system/security" revision="360f51f7af191316cd739f229db1c5f7233be063"/>
   <project name="platform/system/vold" path="system/vold" revision="153df4d067a4149c7d78f1c92fed2ce2bd6a272e"/>
   <default remote="caf" revision="jb_3.2" sync-j="4"/>
   <!-- Flame specific things -->
   <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="e8a318f7690092e639ba88891606f4183e846d3f"/>
   <project name="device/qcom/common" path="device/qcom/common" revision="34ed8345250bb97262d70a052217a92e83444ede"/>
-  <project name="device-flame" path="device/t2m/flame" remote="b2g" revision="7dffe28a30abbcda13b0ba2d7a933d22bd82f9d7"/>
+  <project name="device-flame" path="device/t2m/flame" remote="b2g" revision="b1d23890531de539e47e594e07e06b2dca54a85b"/>
   <project name="kernel/msm" path="kernel" revision="7158567fc83e7475f08db3adedc5df1ad6f54abd"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="f2914eacee9120680a41463708bb6ee8291749fc"/>
   <project name="platform/external/bluetooth/bluedroid" path="external/bluetooth/bluedroid" revision="4b7ae991637a216d745e154cd49b4db6ca55a19e"/>
   <project name="platform/external/bluetooth/bluez" path="external/bluetooth/bluez" revision="f0689ac1914cdbc59e53bdc9edd9013dc157c299"/>
   <project name="platform/external/bluetooth/glib" path="external/bluetooth/glib" revision="dd925f76e4f149c3d5571b80e12f7e24bbe89c59"/>
   <project name="platform/external/dbus" path="external/dbus" revision="ea87119c843116340f5df1d94eaf8275e1055ae8"/>
   <project name="platform/external/libnfc-nci" path="external/libnfc-nci" revision="494c177966fdc31183a5f7af82dc9130f523da4b"/>
   <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="320b05a5761eb2a4816f7529c91ea49422979b55"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
         "git_revision": "", 
         "remote": "", 
         "branch": ""
     }, 
-    "revision": "993067c495a5e0956dfe4169f1f48d9a791304f0", 
+    "revision": "166c0ff9af0ce73ae5665d71715ea2bb96a4bacc", 
     "repo_path": "/integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -12,20 +12,20 @@
   <!--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="2a165bebfa19b11b697837409f9550dd2917c46c">
     <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="70953f779faf6b1a94861c34ffdc3d5fd1c442e5"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="3a1d67246a79e3632c3b3f2460a25291e7e2714c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="abedd83e1ba61cb83e59c723ad6279ad2a7aa1d1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
-  <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
+  <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="fd4be2909b788b563435fe0addb1bd98dfa75457"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="746bc48f34f5060f90801925dcdd964030c1ab6d"/>
   <project name="platform/development" path="development" revision="2460485184bc8535440bb63876d4e63ec1b4770c"/>
   <project name="device/common" path="device/common" revision="0dcc1e03659db33b77392529466f9eb685cdd3c7"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -10,20 +10,20 @@
   <!--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="2a165bebfa19b11b697837409f9550dd2917c46c">
     <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="70953f779faf6b1a94861c34ffdc3d5fd1c442e5"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="3a1d67246a79e3632c3b3f2460a25291e7e2714c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="abedd83e1ba61cb83e59c723ad6279ad2a7aa1d1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
-  <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
+  <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <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"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="575fdbf046e966a5915b1f1e800e5d6ad0ea14c0"/>
   <project name="platform/development" path="development" revision="b1025ec93beeb480caaf3049d171283c3846461d"/>
   <project name="device/common" path="device/common" revision="0dcc1e03659db33b77392529466f9eb685cdd3c7"/>
--- a/b2g/config/inari/sources.xml
+++ b/b2g/config/inari/sources.xml
@@ -14,20 +14,20 @@
   <!--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="2a165bebfa19b11b697837409f9550dd2917c46c">
     <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="70953f779faf6b1a94861c34ffdc3d5fd1c442e5"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="3a1d67246a79e3632c3b3f2460a25291e7e2714c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="abedd83e1ba61cb83e59c723ad6279ad2a7aa1d1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
-  <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
+  <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="fd4be2909b788b563435fe0addb1bd98dfa75457"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="cd5dfce80bc3f0139a56b58aca633202ccaee7f8"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="e0a9ac010df3afaa47ba107192c05ac8b5516435"/>
   <project name="platform/development" path="development" revision="a384622f5fcb1d2bebb9102591ff7ae91fe8ed2d"/>
   <project name="device/common" path="device/common" revision="7c65ea240157763b8ded6154a17d3c033167afb7"/>
--- a/b2g/config/leo/sources.xml
+++ b/b2g/config/leo/sources.xml
@@ -12,20 +12,20 @@
   <!--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="2a165bebfa19b11b697837409f9550dd2917c46c">
     <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="70953f779faf6b1a94861c34ffdc3d5fd1c442e5"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="3a1d67246a79e3632c3b3f2460a25291e7e2714c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="abedd83e1ba61cb83e59c723ad6279ad2a7aa1d1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
-  <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
+  <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="fd4be2909b788b563435fe0addb1bd98dfa75457"/>
   <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"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="575fdbf046e966a5915b1f1e800e5d6ad0ea14c0"/>
   <project name="platform/development" path="development" revision="b1025ec93beeb480caaf3049d171283c3846461d"/>
--- a/b2g/config/mako/sources.xml
+++ b/b2g/config/mako/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="e6383e6e785cc3ea237e902beb1092f9aa88e29d">
     <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="70953f779faf6b1a94861c34ffdc3d5fd1c442e5"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="3a1d67246a79e3632c3b3f2460a25291e7e2714c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="abedd83e1ba61cb83e59c723ad6279ad2a7aa1d1"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="fd4be2909b788b563435fe0addb1bd98dfa75457"/>
   <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,20 +12,20 @@
   <!--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="2a165bebfa19b11b697837409f9550dd2917c46c">
     <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="70953f779faf6b1a94861c34ffdc3d5fd1c442e5"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="3a1d67246a79e3632c3b3f2460a25291e7e2714c"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="abedd83e1ba61cb83e59c723ad6279ad2a7aa1d1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
-  <project name="librecovery" path="librecovery" remote="b2g" revision="1f6a1fe07f81c5bc5e1d079c9b60f7f78ca2bf4f"/>
+  <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="ce95d372e6d285725b96490afdaaf489ad8f9ca9"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="fd4be2909b788b563435fe0addb1bd98dfa75457"/>
   <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="cd5dfce80bc3f0139a56b58aca633202ccaee7f8"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="e0a9ac010df3afaa47ba107192c05ac8b5516435"/>
   <project name="platform/development" path="development" revision="a384622f5fcb1d2bebb9102591ff7ae91fe8ed2d"/>
--- a/configure.in
+++ b/configure.in
@@ -2542,17 +2542,17 @@ AC_LANG_CPLUSPLUS
 
 MOZ_CXX11
 
 AC_LANG_C
 
 dnl Check for .hidden assembler directive and visibility attribute.
 dnl Borrowed from glibc configure.in
 dnl ===============================================================
-if test "$GNU_CC"; then
+if test "$GNU_CC" -a "$OS_TARGET" != WINNT; then
   AC_DEFINE(HAVE_VISIBILITY_HIDDEN_ATTRIBUTE)
   AC_DEFINE(HAVE_VISIBILITY_ATTRIBUTE)
   if test -n "$gonkdir"; then
     visibility_target=Gonk
   else
     visibility_target=$OS_TARGET
   fi
   case "$visibility_target" in
@@ -5801,16 +5801,21 @@ if test -n "$MOZ_ANGLE_RENDERER"; then
       AC_MSG_RESULT([Windows SDK not found.])
     fi
   fi
 
   if test -z "$MOZ_D3DCOMPILER_VISTA_DLL_PATH"; then
     MOZ_D3DCOMPILER_VISTA_DLL=
   fi
 
+  # On mingw, check if headers are provided by toolchain.
+  if test -n "$GNU_CC"; then
+    MOZ_CHECK_HEADER(d3d10.h, MOZ_HAS_WINSDK_WITH_D3D=1)
+  fi
+
   ######################################
   # Find _43 for use by XP.
 
   # Get the SDK path from the registry.
   # First try to get the June 2010 SDK
   MOZ_DIRECTX_SDK_REG_KEY=`reg query 'HKLM\Software\Microsoft\DirectX' //s | grep 'Microsoft DirectX SDK (June 2010)' | head -n 1`
   if test -z "$MOZ_DIRECTX_SDK_REG_KEY" ; then
     # Otherwise just take whatever comes first
--- a/content/base/src/EventSource.cpp
+++ b/content/base/src/EventSource.cpp
@@ -5,16 +5,17 @@
 
 #include "mozilla/dom/EventSource.h"
 
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/DebugOnly.h"
 #include "mozilla/DOMEventTargetHelper.h"
 #include "mozilla/dom/EventSourceBinding.h"
 #include "mozilla/dom/MessageEvent.h"
+#include "mozilla/dom/ScriptSettings.h"
 
 #include "js/OldDebugAPI.h"
 #include "nsNetUtil.h"
 #include "nsMimeTypes.h"
 #include "nsIPromptFactory.h"
 #include "nsIWindowWatcher.h"
 #include "nsPresContext.h"
 #include "nsContentPolicyUtils.h"
@@ -24,17 +25,16 @@
 #include "nsIScriptObjectPrincipal.h"
 #include "nsJSUtils.h"
 #include "nsIAsyncVerifyRedirectCallback.h"
 #include "nsIScriptError.h"
 #include "mozilla/dom/EncodingUtils.h"
 #include "nsIChannelPolicy.h"
 #include "nsIContentSecurityPolicy.h"
 #include "nsContentUtils.h"
-#include "nsCxPusher.h"
 #include "mozilla/Preferences.h"
 #include "xpcpublic.h"
 #include "nsCrossSiteListenerProxy.h"
 #include "nsWrapperCacheInlines.h"
 #include "mozilla/Attributes.h"
 #include "nsError.h"
 
 namespace mozilla {
@@ -1231,25 +1231,25 @@ EventSource::DispatchAllMessageEvents()
 
   mGoingToDispatchAllMessages = false;
 
   nsresult rv = CheckInnerWindowCorrectness();
   if (NS_FAILED(rv)) {
     return;
   }
 
-  // Let's play get the JSContext
-  nsCOMPtr<nsIScriptGlobalObject> sgo = do_QueryInterface(GetOwner());
-  NS_ENSURE_TRUE_VOID(sgo);
+  // We need a parent object so that we can enter its compartment.
+  nsCOMPtr<nsIGlobalObject> parentObject = do_QueryInterface(GetParentObject());
+  if (NS_WARN_IF(!parentObject)) {
+    return;
+  }
 
-  nsIScriptContext* scriptContext = sgo->GetContext();
-  NS_ENSURE_TRUE_VOID(scriptContext);
-
-  AutoPushJSContext cx(scriptContext->GetNativeContext());
-  NS_ENSURE_TRUE_VOID(cx);
+  AutoJSAPI jsapi;
+  JSContext* cx = jsapi.cx();
+  JSAutoCompartment ac(cx, parentObject->GetGlobalJSObject());
 
   while (mMessagesToDispatch.GetSize() > 0) {
     nsAutoPtr<Message>
       message(static_cast<Message*>(mMessagesToDispatch.PopFront()));
 
     // Now we can turn our string into a jsval
     JS::Rooted<JS::Value> jsData(cx);
     {
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -28,17 +28,16 @@
 #include "nsIWebNavigation.h"
 #include "nsIWebProgress.h"
 #include "nsIDocShell.h"
 #include "nsIDocShellTreeOwner.h"
 #include "nsIDocShellLoadInfo.h"
 #include "nsIDOMApplicationRegistry.h"
 #include "nsIBaseWindow.h"
 #include "nsContentUtils.h"
-#include "nsCxPusher.h"
 #include "nsIXPConnect.h"
 #include "nsUnicharUtils.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsIScrollable.h"
 #include "nsFrameLoader.h"
 #include "nsIDOMEventTarget.h"
 #include "nsIFrame.h"
@@ -2418,22 +2417,16 @@ nsFrameLoader::EnsureMessageManager()
 
   if (mMessageManager) {
     if (ShouldUseRemoteProcess() && mRemoteBrowserShown) {
       mMessageManager->InitWithCallback(this);
     }
     return NS_OK;
   }
 
-  nsIScriptContext* sctx = mOwnerContent->GetContextForEventHandlers(&rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-  NS_ENSURE_STATE(sctx);
-  AutoPushJSContext cx(sctx->GetNativeContext());
-  NS_ENSURE_STATE(cx);
-
   nsCOMPtr<nsIDOMChromeWindow> chromeWindow =
     do_QueryInterface(GetOwnerDoc()->GetWindow());
   nsCOMPtr<nsIMessageBroadcaster> parentManager;
   if (chromeWindow) {
     chromeWindow->GetMessageManager(getter_AddRefs(parentManager));
   }
 
   if (ShouldUseRemoteProcess()) {
--- a/content/canvas/src/CanvasRenderingContext2D.cpp
+++ b/content/canvas/src/CanvasRenderingContext2D.cpp
@@ -4281,26 +4281,28 @@ bool
 CanvasRenderingContext2D::ShouldForceInactiveLayer(LayerManager *aManager)
 {
   return !aManager->CanUseCanvasLayerForSize(IntSize(mWidth, mHeight));
 }
 
 NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(CanvasPath, AddRef)
 NS_IMPL_CYCLE_COLLECTION_UNROOT_NATIVE(CanvasPath, Release)
 
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(CanvasPath)
-
-CanvasPath::CanvasPath(nsCOMPtr<nsISupports> aParent) : mParent(aParent)
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(CanvasPath, mParent)
+
+CanvasPath::CanvasPath(nsISupports* aParent)
+  : mParent(aParent)
 {
   SetIsDOMBinding();
 
   mPathBuilder = gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget()->CreatePathBuilder();
 }
 
-CanvasPath::CanvasPath(nsCOMPtr<nsISupports> aParent, RefPtr<PathBuilder> aPathBuilder): mParent(aParent), mPathBuilder(aPathBuilder)
+CanvasPath::CanvasPath(nsISupports* aParent, RefPtr<PathBuilder> aPathBuilder)
+  : mParent(aParent), mPathBuilder(aPathBuilder)
 {
   SetIsDOMBinding();
 
   if (!mPathBuilder) {
     mPathBuilder = gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget()->CreatePathBuilder();
   }
 }
 
--- a/content/canvas/src/CanvasRenderingContext2D.h
+++ b/content/canvas/src/CanvasRenderingContext2D.h
@@ -41,17 +41,17 @@ class ImageData;
 class StringOrCanvasGradientOrCanvasPattern;
 class OwningStringOrCanvasGradientOrCanvasPattern;
 class TextMetrics;
 
 extern const mozilla::gfx::Float SIGMA_MAX;
 
 template<typename T> class Optional;
 
-class CanvasPath :
+class CanvasPath MOZ_FINAL :
   public nsWrapperCache
 {
 public:
   NS_INLINE_DECL_CYCLE_COLLECTING_NATIVE_REFCOUNTING(CanvasPath)
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_NATIVE_CLASS(CanvasPath)
 
   nsCOMPtr<nsISupports> GetParentObject() { return mParent; }
 
@@ -83,18 +83,18 @@ public:
   void LineTo(const gfx::Point& aPoint);
   void BezierTo(const gfx::Point& aCP1,
                 const gfx::Point& aCP2,
                 const gfx::Point& aCP3);
 
   mozilla::RefPtr<mozilla::gfx::Path> GetPath(const CanvasWindingRule& winding,
                                               const mozilla::RefPtr<mozilla::gfx::DrawTarget>& mTarget) const;
 
-  CanvasPath(nsCOMPtr<nsISupports> aParent);
-  CanvasPath(nsCOMPtr<nsISupports> aParent, RefPtr<gfx::PathBuilder> mPathBuilder);
+  explicit CanvasPath(nsISupports* aParent);
+  CanvasPath(nsISupports* aParent, RefPtr<gfx::PathBuilder> mPathBuilder);
   virtual ~CanvasPath() {}
 
 private:
 
   nsCOMPtr<nsISupports> mParent;
   static gfx::Float ToFloat(double aValue) { return gfx::Float(aValue); }
 
   mutable RefPtr<gfx::Path> mPath;
--- a/content/canvas/test/test_canvas_path.html
+++ b/content/canvas/test/test_canvas_path.html
@@ -378,9 +378,13 @@ function runTests() {
   ok(false, "unexpected exception thrown in: test_pathconstructor_canvas");
  }
  SpecialPowers.setBoolPref("canvas.path.enabled", false);
  SimpleTest.finish();
 }
 
 addLoadEvent(runTests);
 
+// Don't leak the world via the Path2D reference to its window.
+document.all;
+window.p = new Path2D();
+
 </script>
--- a/content/html/content/src/HTMLFormElement.h
+++ b/content/html/content/src/HTMLFormElement.h
@@ -421,17 +421,17 @@ protected:
   public:
     FormPasswordEventDispatcher(HTMLFormElement* aEventNode,
                                 const nsAString& aEventType)
       : AsyncEventDispatcher(aEventNode, aEventType, true, true)
     {}
 
     NS_IMETHOD Run() MOZ_OVERRIDE
     {
-      static_cast<HTMLFormElement*>(mEventNode.get())->EventHandled();
+      static_cast<HTMLFormElement*>(mTarget.get())->EventHandled();
       return AsyncEventDispatcher::Run();
     }
   };
 
   nsRefPtr<FormPasswordEventDispatcher> mFormPasswordEventDispatcher;
 
   class RemoveElementRunnable;
   friend class RemoveElementRunnable;
--- a/content/media/webaudio/AudioBuffer.cpp
+++ b/content/media/webaudio/AudioBuffer.cpp
@@ -161,18 +161,17 @@ AudioBuffer::CopyToChannel(JSContext* aJ
     return;
   }
 
   PodMove(JS_GetFloat32ArrayData(mJSChannels[aChannelNumber]) + aStartInChannel,
           aSource.Data(), length);
 }
 
 void
-AudioBuffer::SetRawChannelContents(JSContext* aJSContext, uint32_t aChannel,
-                                   float* aContents)
+AudioBuffer::SetRawChannelContents(uint32_t aChannel, float* aContents)
 {
   PodCopy(JS_GetFloat32ArrayData(mJSChannels[aChannel]), aContents, mLength);
 }
 
 JSObject*
 AudioBuffer::GetChannelData(JSContext* aJSContext, uint32_t aChannel,
                             ErrorResult& aRv)
 {
--- a/content/media/webaudio/AudioBuffer.h
+++ b/content/media/webaudio/AudioBuffer.h
@@ -92,19 +92,17 @@ public:
    * Can return null if there is no data.
    */
   ThreadSharedFloatArrayBufferList* GetThreadSharedChannelsForRate(JSContext* aContext);
 
   // This replaces the contents of the JS array for the given channel.
   // This function needs to be called on an AudioBuffer which has not been
   // handed off to the content yet, and right after the object has been
   // initialized.
-  void SetRawChannelContents(JSContext* aJSContext,
-                             uint32_t aChannel,
-                             float* aContents);
+  void SetRawChannelContents(uint32_t aChannel, float* aContents);
 
 protected:
   bool RestoreJSChannelData(JSContext* aJSContext);
   void ClearJSChannels();
 
   nsRefPtr<AudioContext> mContext;
   // Float32Arrays
   AutoFallibleTArray<JS::Heap<JSObject*>, 2> mJSChannels;
--- a/content/media/webaudio/AudioContext.cpp
+++ b/content/media/webaudio/AudioContext.cpp
@@ -585,31 +585,26 @@ AudioContext::UpdateNodeCount(int32_t aD
   mNodeCount += aDelta;
   MOZ_ASSERT(mNodeCount >= 0);
   // mDestinationNode may be null when we're destroying nodes unlinked by CC
   if (!firstNode && mDestination) {
     mDestination->SetIsOnlyNodeForContext(mNodeCount == 1);
   }
 }
 
-JSContext*
-AudioContext::GetJSContext() const
+JSObject*
+AudioContext::GetGlobalJSObject() const
 {
-  MOZ_ASSERT(NS_IsMainThread());
-
-  nsCOMPtr<nsIScriptGlobalObject> scriptGlobal =
-    do_QueryInterface(GetParentObject());
-  if (!scriptGlobal) {
+  nsCOMPtr<nsIGlobalObject> parentObject = do_QueryInterface(GetParentObject());
+  if (!parentObject) {
     return nullptr;
   }
-  nsIScriptContext* scriptContext = scriptGlobal->GetContext();
-  if (!scriptContext) {
-    return nullptr;
-  }
-  return scriptContext->GetNativeContext();
+
+  // This can also return null.
+  return parentObject->GetGlobalJSObject();
 }
 
 void
 AudioContext::StartRendering(ErrorResult& aRv)
 {
   MOZ_ASSERT(mIsOffline, "This should only be called on OfflineAudioContext");
   if (mIsStarted) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
--- a/content/media/webaudio/AudioContext.h
+++ b/content/media/webaudio/AudioContext.h
@@ -214,17 +214,17 @@ public:
   void UnregisterPannerNode(PannerNode* aNode);
   void UpdatePannerSource();
 
   uint32_t MaxChannelCount() const;
 
   void Mute() const;
   void Unmute() const;
 
-  JSContext* GetJSContext() const;
+  JSObject* GetGlobalJSObject() const;
 
   AudioChannel MozAudioChannelType() const;
   void SetMozAudioChannelType(AudioChannel aValue, ErrorResult& aRv);
 
   void UpdateNodeCount(int32_t aDelta);
 
   double DOMTimeToStreamTime(double aTime) const
   {
--- a/content/media/webaudio/AudioDestinationNode.cpp
+++ b/content/media/webaudio/AudioDestinationNode.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* 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 "AudioDestinationNode.h"
 #include "mozilla/dom/AudioDestinationNodeBinding.h"
+#include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Services.h"
 #include "AudioChannelAgent.h"
 #include "AudioChannelService.h"
 #include "AudioNodeEngine.h"
 #include "AudioNodeStream.h"
 #include "MediaStreamGraph.h"
 #include "OfflineAudioCompletionEvent.h"
@@ -120,31 +121,35 @@ public:
   void FireOfflineCompletionEvent(AudioDestinationNode* aNode)
   {
     AudioContext* context = aNode->Context();
     context->Shutdown();
     // Shutdown drops self reference, but the context is still referenced by aNode,
     // which is strongly referenced by the runnable that called
     // AudioDestinationNode::FireOfflineCompletionEvent.
 
-    AutoPushJSContext cx(context->GetJSContext());
-    if (!cx) {
+    // We need the global for the context so that we can enter its compartment.
+    JSObject* global = context->GetGlobalJSObject();
+    if (NS_WARN_IF(!global)) {
       return;
     }
-    JSAutoRequest ar(cx);
+
+    AutoJSAPI jsapi;
+    JSContext* cx = jsapi.cx();
+    JSAutoCompartment ac(cx, global);
 
     // Create the input buffer
     nsRefPtr<AudioBuffer> renderedBuffer = new AudioBuffer(context,
                                                            mLength,
                                                            mSampleRate);
     if (!renderedBuffer->InitializeBuffers(mInputChannels.Length(), cx)) {
       return;
     }
     for (uint32_t i = 0; i < mInputChannels.Length(); ++i) {
-      renderedBuffer->SetRawChannelContents(cx, i, mInputChannels[i]);
+      renderedBuffer->SetRawChannelContents(i, mInputChannels[i]);
     }
 
     nsRefPtr<OfflineAudioCompletionEvent> event =
         new OfflineAudioCompletionEvent(context, nullptr, nullptr);
     event->InitEvent(renderedBuffer);
     context->DispatchTrustedEvent(event);
   }
 
--- a/content/media/webaudio/AudioProcessingEvent.cpp
+++ b/content/media/webaudio/AudioProcessingEvent.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* 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 "AudioProcessingEvent.h"
 #include "mozilla/dom/AudioProcessingEventBinding.h"
+#include "mozilla/dom/ScriptSettings.h"
 #include "AudioContext.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTION_INHERITED(AudioProcessingEvent, Event,
                                    mInputBuffer, mOutputBuffer, mNode)
 
@@ -35,17 +36,25 @@ AudioProcessingEvent::WrapObject(JSConte
 {
   return AudioProcessingEventBinding::Wrap(aCx, this);
 }
 
 void
 AudioProcessingEvent::LazilyCreateBuffer(nsRefPtr<AudioBuffer>& aBuffer,
                                          uint32_t aNumberOfChannels)
 {
-  AutoPushJSContext cx(mNode->Context()->GetJSContext());
+  // We need the global for the context so that we can enter its compartment.
+  JSObject* global = mNode->Context()->GetGlobalJSObject();
+  if (NS_WARN_IF(!global)) {
+    return;
+  }
+
+  AutoJSAPI jsapi;
+  JSContext* cx = jsapi.cx();
+  JSAutoCompartment ac(cx, global);
 
   aBuffer = new AudioBuffer(mNode->Context(), mNode->BufferSize(),
                             mNode->Context()->SampleRate());
   aBuffer->InitializeBuffers(aNumberOfChannels, cx);
 }
 
 }
 }
--- a/content/media/webaudio/MediaBufferDecoder.cpp
+++ b/content/media/webaudio/MediaBufferDecoder.cpp
@@ -2,28 +2,28 @@
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* 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 "MediaBufferDecoder.h"
 #include "BufferDecoder.h"
 #include "mozilla/dom/AudioContextBinding.h"
+#include "mozilla/dom/ScriptSettings.h"
 #include <speex/speex_resampler.h>
 #include "nsXPCOMCIDInternal.h"
 #include "nsComponentManagerUtils.h"
 #include "MediaDecoderReader.h"
 #include "BufferMediaResource.h"
 #include "DecoderTraits.h"
 #include "AudioContext.h"
 #include "AudioBuffer.h"
 #include "nsIScriptObjectPrincipal.h"
 #include "nsIScriptError.h"
 #include "nsMimeTypes.h"
-#include "nsCxPusher.h"
 #include "WebAudioUtils.h"
 
 namespace mozilla {
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(WebAudioDecodeJob)
 
 NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(WebAudioDecodeJob)
   NS_IMPL_CYCLE_COLLECTION_UNLINK(mContext)
@@ -397,30 +397,34 @@ MediaDecodeTask::CallbackTheResult()
 }
 
 bool
 WebAudioDecodeJob::AllocateBuffer()
 {
   MOZ_ASSERT(!mOutput);
   MOZ_ASSERT(NS_IsMainThread());
 
-  // First, get a JSContext
-  AutoPushJSContext cx(mContext->GetJSContext());
-  if (!cx) {
+  // We need the global for the context so that we can enter its compartment.
+  JSObject* global = mContext->GetGlobalJSObject();
+  if (NS_WARN_IF(!global)) {
     return false;
   }
 
+  AutoJSAPI jsapi;
+  JSContext* cx = jsapi.cx();
+  JSAutoCompartment ac(cx, global);
+
   // Now create the AudioBuffer
   mOutput = new AudioBuffer(mContext, mWriteIndex, mContext->SampleRate());
   if (!mOutput->InitializeBuffers(mChannelBuffers.Length(), cx)) {
     return false;
   }
 
   for (uint32_t i = 0; i < mChannelBuffers.Length(); ++i) {
-    mOutput->SetRawChannelContents(cx, i, mChannelBuffers[i]);
+    mOutput->SetRawChannelContents(i, mChannelBuffers[i]);
   }
 
   return true;
 }
 
 void
 MediaBufferDecoder::AsyncDecodeMedia(const char* aContentType, uint8_t* aBuffer,
                                      uint32_t aLength,
--- a/content/media/webaudio/ScriptProcessorNode.cpp
+++ b/content/media/webaudio/ScriptProcessorNode.cpp
@@ -7,17 +7,17 @@
 #include "ScriptProcessorNode.h"
 #include "mozilla/dom/ScriptProcessorNodeBinding.h"
 #include "AudioBuffer.h"
 #include "AudioDestinationNode.h"
 #include "AudioNodeEngine.h"
 #include "AudioNodeStream.h"
 #include "AudioProcessingEvent.h"
 #include "WebAudioUtils.h"
-#include "nsCxPusher.h"
+#include "mozilla/dom/ScriptSettings.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/PodOperations.h"
 #include <deque>
 
 namespace mozilla {
 namespace dom {
 
 // The maximum latency, in seconds, that we can live with before dropping
@@ -397,54 +397,61 @@ private:
           // this function.
           MutexAutoLock lock(mStream->Engine()->NodeMutex());
           node = static_cast<ScriptProcessorNode*>(mStream->Engine()->Node());
         }
         if (!node || !node->Context()) {
           return NS_OK;
         }
 
-        AutoPushJSContext cx(node->Context()->GetJSContext());
-        if (cx) {
+        // Get the global for the context so that we can enter its compartment.
+        JSObject* global = node->Context()->GetGlobalJSObject();
+        if (NS_WARN_IF(!global)) {
+          return NS_OK;
+        }
 
-          // Create the input buffer
-          nsRefPtr<AudioBuffer> inputBuffer;
-          if (!mNullInput) {
-            inputBuffer = new AudioBuffer(node->Context(),
-                                          node->BufferSize(),
-                                          node->Context()->SampleRate());
-            if (!inputBuffer->InitializeBuffers(mInputChannels.Length(), cx)) {
-              return NS_OK;
-            }
-            // Put the channel data inside it
-            for (uint32_t i = 0; i < mInputChannels.Length(); ++i) {
-              inputBuffer->SetRawChannelContents(cx, i, mInputChannels[i]);
-            }
-          }
+        AutoJSAPI jsapi;
+        JSContext* cx = jsapi.cx();
+        JSAutoCompartment ac(cx, global);
 
-          // Ask content to produce data in the output buffer
-          // Note that we always avoid creating the output buffer here, and we try to
-          // avoid creating the input buffer as well.  The AudioProcessingEvent class
-          // knows how to lazily create them if needed once the script tries to access
-          // them.  Otherwise, we may be able to get away without creating them!
-          nsRefPtr<AudioProcessingEvent> event = new AudioProcessingEvent(node, nullptr, nullptr);
-          event->InitEvent(inputBuffer,
-                           mInputChannels.Length(),
-                           mPlaybackTime);
-          node->DispatchTrustedEvent(event);
+        // Create the input buffer
+        nsRefPtr<AudioBuffer> inputBuffer;
+        if (!mNullInput) {
+          inputBuffer = new AudioBuffer(node->Context(),
+                                        node->BufferSize(),
+                                        node->Context()->SampleRate());
+          if (!inputBuffer->InitializeBuffers(mInputChannels.Length(), cx)) {
+            return NS_OK;
+          }
+          // Put the channel data inside it
+          for (uint32_t i = 0; i < mInputChannels.Length(); ++i) {
+            inputBuffer->SetRawChannelContents(i, mInputChannels[i]);
+          }
+        }
 
-          // Steal the output buffers
-          nsRefPtr<ThreadSharedFloatArrayBufferList> output;
-          if (event->HasOutputBuffer()) {
-            output = event->OutputBuffer()->GetThreadSharedChannelsForRate(cx);
-          }
+        // Ask content to produce data in the output buffer
+        // Note that we always avoid creating the output buffer here, and we try to
+        // avoid creating the input buffer as well.  The AudioProcessingEvent class
+        // knows how to lazily create them if needed once the script tries to access
+        // them.  Otherwise, we may be able to get away without creating them!
+        nsRefPtr<AudioProcessingEvent> event = new AudioProcessingEvent(node, nullptr, nullptr);
+        event->InitEvent(inputBuffer,
+                         mInputChannels.Length(),
+                         mPlaybackTime);
+        node->DispatchTrustedEvent(event);
 
-          // Append it to our output buffer queue
-          node->GetSharedBuffers()->FinishProducingOutputBuffer(output, node->BufferSize());
+        // Steal the output buffers
+        nsRefPtr<ThreadSharedFloatArrayBufferList> output;
+        if (event->HasOutputBuffer()) {
+          output = event->OutputBuffer()->GetThreadSharedChannelsForRate(cx);
         }
+
+        // Append it to our output buffer queue
+        node->GetSharedBuffers()->FinishProducingOutputBuffer(output, node->BufferSize());
+
         return NS_OK;
       }
     private:
       nsRefPtr<AudioNodeStream> mStream;
       InputChannels mInputChannels;
       double mPlaybackTime;
       bool mNullInput;
     };
--- a/dom/base/nsGlobalWindow.cpp
+++ b/dom/base/nsGlobalWindow.cpp
@@ -13447,22 +13447,16 @@ nsGlobalChromeWindow::GetMessageManager(
 
 nsIMessageBroadcaster*
 nsGlobalWindow::GetMessageManager(ErrorResult& aError)
 {
   FORWARD_TO_INNER_OR_THROW(GetMessageManager, (aError), aError, nullptr);
   MOZ_ASSERT(IsChromeWindow());
   nsGlobalChromeWindow* myself = static_cast<nsGlobalChromeWindow*>(this);
   if (!myself->mMessageManager) {
-    nsIScriptContext* scx = GetContextInternal();
-    if (NS_WARN_IF(!scx || !(scx->GetNativeContext()))) {
-      aError.Throw(NS_ERROR_UNEXPECTED);
-      return nullptr;
-    }
-
     nsCOMPtr<nsIMessageBroadcaster> globalMM =
       do_GetService("@mozilla.org/globalmessagemanager;1");
     myself->mMessageManager =
       new nsFrameMessageManager(nullptr,
                                 static_cast<nsFrameMessageManager*>(globalMM.get()),
                                 MM_CHROME | MM_BROADCASTER);
   }
   return myself->mMessageManager;
--- a/dom/bluetooth/bluedroid/BluetoothSocket.cpp
+++ b/dom/bluetooth/bluedroid/BluetoothSocket.cpp
@@ -1,16 +1,17 @@
 /* -*- 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 "BluetoothSocket.h"
 
+#include <fcntl.h>
 #include <hardware/bluetooth.h>
 #include <hardware/bt_sock.h>
 #include <sys/socket.h>
 
 #include "base/message_loop.h"
 #include "BluetoothSocketObserver.h"
 #include "BluetoothUtils.h"
 #include "mozilla/FileUtils.h"
@@ -76,50 +77,47 @@ ReadBdAddress(const uint8_t* aData, size
   sprintf(bdstr, "%02x:%02x:%02x:%02x:%02x:%02x",
           aData[*aOffset], aData[*aOffset + 1], aData[*aOffset + 2],
           aData[*aOffset + 3], aData[*aOffset + 4], aData[*aOffset + 5]);
 
   aDeviceAddress.AssignLiteral(bdstr);
   *aOffset += 6;
 }
 
-class mozilla::dom::bluetooth::DroidSocketImpl
-    : public MessageLoopForIO::Watcher
+class mozilla::dom::bluetooth::DroidSocketImpl : public ipc::UnixFdWatcher
 {
 public:
-  DroidSocketImpl(BluetoothSocket* aConsumer, int aFd)
-    : mConsumer(aConsumer)
+  DroidSocketImpl(MessageLoop* aIOLoop, BluetoothSocket* aConsumer, int aFd)
+    : ipc::UnixFdWatcher(aIOLoop, aFd)
+    , mConsumer(aConsumer)
     , mReadMsgForClientFd(false)
-    , mIOLoop(nullptr)
-    , mFd(aFd)
     , mShuttingDownOnIOThread(false)
     , mChannel(0)
     , mAuth(false)
     , mEncrypt(false)
   {
   }
 
-  DroidSocketImpl(BluetoothSocket* aConsumer,
+  DroidSocketImpl(MessageLoop* aIOLoop, BluetoothSocket* aConsumer,
                   int aChannel, bool aAuth, bool aEncrypt)
-    : mConsumer(aConsumer)
+    : ipc::UnixFdWatcher(aIOLoop)
+    , mConsumer(aConsumer)
     , mReadMsgForClientFd(false)
-    , mIOLoop(nullptr)
-    , mFd(-1)
     , mShuttingDownOnIOThread(false)
     , mChannel(aChannel)
     , mAuth(aAuth)
     , mEncrypt(aEncrypt)
   { }
 
-  DroidSocketImpl(BluetoothSocket* aConsumer, const nsAString& aDeviceAddress,
+  DroidSocketImpl(MessageLoop* aIOLoop, BluetoothSocket* aConsumer,
+                  const nsAString& aDeviceAddress,
                   int aChannel, bool aAuth, bool aEncrypt)
-    : mConsumer(aConsumer)
+    : ipc::UnixFdWatcher(aIOLoop)
+    , mConsumer(aConsumer)
     , mReadMsgForClientFd(false)
-    , mIOLoop(nullptr)
-    , mFd(-1)
     , mShuttingDownOnIOThread(false)
     , mDeviceAddress(aDeviceAddress)
     , mChannel(aChannel)
     , mAuth(aAuth)
     , mEncrypt(aEncrypt)
   {
     MOZ_ASSERT(!mDeviceAddress.IsEmpty());
   }
@@ -127,17 +125,17 @@ public:
   ~DroidSocketImpl()
   {
     MOZ_ASSERT(NS_IsMainThread());
   }
 
   void QueueWriteData(UnixSocketRawData* aData)
   {
     mOutgoingQ.AppendElement(aData);
-    OnFileCanWriteWithoutBlocking(mFd);
+    OnFileCanWriteWithoutBlocking(GetFd());
   }
 
   bool IsShutdownOnMainThread()
   {
     MOZ_ASSERT(NS_IsMainThread());
     return mConsumer == nullptr;
   }
 
@@ -153,53 +151,36 @@ public:
     mConsumer = nullptr;
   }
 
   void ShutdownOnIOThread()
   {
     MOZ_ASSERT(!NS_IsMainThread());
     MOZ_ASSERT(!mShuttingDownOnIOThread);
 
-    mReadWatcher.StopWatchingFileDescriptor();
-    mWriteWatcher.StopWatchingFileDescriptor();
+    RemoveWatchers(READ_WATCHER | WRITE_WATCHER);
 
     mShuttingDownOnIOThread = true;
   }
 
   void Connect();
   void Listen();
 
   void SetUpIO(bool aWrite)
   {
-    MOZ_ASSERT(!mIOLoop);
-    MOZ_ASSERT(mFd >= 0);
-    mIOLoop = MessageLoopForIO::current();
-
-    // Set up a read watch
-    mIOLoop->WatchFileDescriptor(mFd,
-                                 true,
-                                 MessageLoopForIO::WATCH_READ,
-                                 &mReadWatcher,
-                                 this);
-
+    AddWatchers(READ_WATCHER, true);
     if (aWrite) {
-      // Set up a write watch
-      mIOLoop->WatchFileDescriptor(mFd.get(),
-                                   false,
-                                   MessageLoopForIO::WATCH_WRITE,
-                                   &mWriteWatcher,
-                                   this);
+        AddWatchers(WRITE_WATCHER, false);
     }
   }
 
   void ConnectClientFd()
   {
     // Stop current read watch
-    mReadWatcher.StopWatchingFileDescriptor();
-    mIOLoop = nullptr;
+    RemoveWatchers(READ_WATCHER);
 
     // Restart read & write watch on client fd
     SetUpIO(true);
   }
 
   /**
    * Consumer pointer. Non-thread safe RefPtr, so should only be manipulated
    * directly from main thread. All non-main-thread accesses should happen with
@@ -234,43 +215,22 @@ private:
    *
    * @param aFd     [in]  File descriptor to read message from
    * @param aBuffer [out] Data buffer read
    * @param aLength [out] Number of bytes read
    */
   ssize_t ReadMsg(int aFd, void *aBuffer, size_t aLength);
 
   /**
-   * IO Loop pointer. Must be initalized and called from IO thread only.
-   */
-  MessageLoopForIO* mIOLoop;
-
-  /**
    * Raw data queue. Must be pushed/popped from IO thread only.
    */
   typedef nsTArray<UnixSocketRawData* > UnixSocketRawDataQueue;
   UnixSocketRawDataQueue mOutgoingQ;
 
   /**
-   * Read watcher for libevent. Only to be accessed on IO Thread.
-   */
-  MessageLoopForIO::FileDescriptorWatcher mReadWatcher;
-
-  /**
-   * Write watcher for libevent. Only to be accessed on IO Thread.
-   */
-  MessageLoopForIO::FileDescriptorWatcher mWriteWatcher;
-
-  /**
-   * File descriptor to read from/write to. Connection happens on user provided
-   * thread. Read/write/close happens on IO thread.
-   */
-  mozilla::ScopedClose mFd;
-
-  /**
    * If true, do not requeue whatever task we're running
    */
   bool mShuttingDownOnIOThread;
 
   nsString mDeviceAddress;
   int mChannel;
   bool mAuth;
   bool mEncrypt;
@@ -491,33 +451,28 @@ DroidSocketImpl::Connect()
                                        UUID_OBEX_OBJECT_PUSH,
                                        mChannel,
                                        &fd,
                                        (BTSOCK_FLAG_ENCRYPT * mEncrypt) |
                                        (BTSOCK_FLAG_AUTH * mAuth));
   NS_ENSURE_TRUE_VOID(status == BT_STATUS_SUCCESS);
   NS_ENSURE_TRUE_VOID(fd >= 0);
 
-  mFd = fd;
-
-  MOZ_ASSERT(!mIOLoop);
-  mIOLoop = MessageLoopForIO::current();
+  int flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL));
+  NS_ENSURE_TRUE_VOID(flags >= 0);
 
-  // Set up a read watch
-  mIOLoop->WatchFileDescriptor(mFd.get(),
-                               true,
-                               MessageLoopForIO::WATCH_READ,
-                               &mReadWatcher,
-                               this);
-  // Set up a write watch
-  mIOLoop->WatchFileDescriptor(mFd.get(),
-                               false,
-                               MessageLoopForIO::WATCH_WRITE,
-                               &mWriteWatcher,
-                               this);
+  if (!(flags & O_NONBLOCK)) {
+    int res = TEMP_FAILURE_RETRY(fcntl(fd, F_SETFL, flags | O_NONBLOCK));
+    NS_ENSURE_TRUE_VOID(!res);
+  }
+
+  SetFd(fd);
+
+  AddWatchers(READ_WATCHER, true);
+  AddWatchers(WRITE_WATCHER, false);
 }
 
 void
 DroidSocketImpl::Listen()
 {
   MOZ_ASSERT(sBluetoothSocketInterface);
 
   // TODO: uuid and service name as arguments
@@ -529,27 +484,26 @@ DroidSocketImpl::Listen()
                                       UUID_OBEX_OBJECT_PUSH,
                                       mChannel,
                                       &fd,
                                       (BTSOCK_FLAG_ENCRYPT * mEncrypt) |
                                       (BTSOCK_FLAG_AUTH * mAuth));
   NS_ENSURE_TRUE_VOID(status == BT_STATUS_SUCCESS);
   NS_ENSURE_TRUE_VOID(fd >= 0);
 
-  mFd = fd;
-
-  MOZ_ASSERT(!mIOLoop);
-  mIOLoop = MessageLoopForIO::current();
+  int flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL));
+  NS_ENSURE_TRUE_VOID(flags >= 0);
 
-  // Set up a read watch
-  mIOLoop->WatchFileDescriptor(mFd.get(),
-                               true,
-                               MessageLoopForIO::WATCH_READ,
-                               &mReadWatcher,
-                               this);
+  if (!(flags & O_NONBLOCK)) {
+    int res = TEMP_FAILURE_RETRY(fcntl(fd, F_SETFL, flags | O_NONBLOCK));
+    NS_ENSURE_TRUE_VOID(!res);
+  }
+
+  SetFd(fd);
+  AddWatchers(READ_WATCHER, true);
 }
 
 ssize_t
 DroidSocketImpl::ReadMsg(int aFd, void *aBuffer, size_t aLength)
 {
   ssize_t ret;
   struct msghdr msg;
   struct iovec iv;
@@ -561,35 +515,44 @@ DroidSocketImpl::ReadMsg(int aFd, void *
   iv.iov_base = (unsigned char *)aBuffer;
   iv.iov_len = aLength;
 
   msg.msg_iov = &iv;
   msg.msg_iovlen = 1;
   msg.msg_control = cmsgbuf;
   msg.msg_controllen = sizeof(cmsgbuf);
 
-  ret = recvmsg(mFd.get(), &msg, MSG_NOSIGNAL);
+  ret = recvmsg(GetFd(), &msg, MSG_NOSIGNAL);
   if (ret < 0 && errno == EPIPE) {
     // Treat this as an end of stream
     return 0;
   }
 
   NS_ENSURE_FALSE(ret < 0, -1);
   NS_ENSURE_FALSE(msg.msg_flags & (MSG_CTRUNC | MSG_OOB | MSG_ERRQUEUE), -1);
 
   // Extract client fd from message header
   for (struct cmsghdr *cmsgptr = CMSG_FIRSTHDR(&msg);
        cmsgptr != nullptr; cmsgptr = CMSG_NXTHDR(&msg, cmsgptr)) {
     if (cmsgptr->cmsg_level != SOL_SOCKET) {
       continue;
     }
     if (cmsgptr->cmsg_type == SCM_RIGHTS) {
       int *pDescriptors = (int *)CMSG_DATA(cmsgptr);
+
       // Overwrite fd with client fd
-      mFd.reset(pDescriptors[0]);
+      int fd = pDescriptors[0];
+      int flags = TEMP_FAILURE_RETRY(fcntl(fd, F_GETFL));
+      NS_ENSURE_TRUE(flags >= 0, 0);
+      if (!(flags & O_NONBLOCK)) {
+        int res = TEMP_FAILURE_RETRY(fcntl(fd, F_SETFL, flags | O_NONBLOCK));
+        NS_ENSURE_TRUE(!res, 0);
+      }
+      Close();
+      SetFd(fd);
       break;
     }
   }
 
   return ret;
 }
 
 void
@@ -619,18 +582,17 @@ DroidSocketImpl::OnFileCanReadWithoutBlo
         }
 
         BT_WARNING("Cannot read from network");
         // else fall through to error handling on other errno's
       }
 
       // We're done with our descriptors. Ensure that spurious events don't
       // cause us to end up back here.
-      mReadWatcher.StopWatchingFileDescriptor();
-      mWriteWatcher.StopWatchingFileDescriptor();
+      RemoveWatchers(READ_WATCHER | WRITE_WATCHER);
       nsRefPtr<RequestClosingSocketTask> t = new RequestClosingSocketTask(this);
       NS_DispatchToMainThread(t);
       return;
     }
 
     incoming->mSize = ret;
     nsRefPtr<SocketReceiveTask> t =
       new SocketReceiveTask(this, incoming.forget());
@@ -677,23 +639,17 @@ DroidSocketImpl::OnFileCanWriteWithoutBl
         data->mCurrentWriteOffset += written;
       }
       if (written != write_amount) {
         break;
       }
     }
 
     if (data->mCurrentWriteOffset != data->mSize) {
-      MessageLoopForIO::current()->WatchFileDescriptor(
-        aFd,
-        false,
-        MessageLoopForIO::WATCH_WRITE,
-        &mWriteWatcher,
-        this);
-      return;
+      AddWatchers(WRITE_WATCHER, false);
     }
     mOutgoingQ.RemoveElementAt(0);
     delete data;
   }
 }
 
 BluetoothSocket::BluetoothSocket(BluetoothSocketObserver* aObserver,
                                  BluetoothSocketType aType,
@@ -732,31 +688,33 @@ BluetoothSocket::CloseDroidSocket()
 
 bool
 BluetoothSocket::Connect(const nsAString& aDeviceAddress, int aChannel)
 {
   MOZ_ASSERT(NS_IsMainThread());
   NS_ENSURE_FALSE(mImpl, false);
 
   mIsServer = false;
-  mImpl = new DroidSocketImpl(this, aDeviceAddress, aChannel, mAuth, mEncrypt);
+  mImpl = new DroidSocketImpl(XRE_GetIOMessageLoop(), this, aDeviceAddress,
+                              aChannel, mAuth, mEncrypt);
   XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
                                    new SocketConnectTask(mImpl));
 
   return true;
 }
 
 bool
 BluetoothSocket::Listen(int aChannel)
 {
   MOZ_ASSERT(NS_IsMainThread());
   NS_ENSURE_FALSE(mImpl, false);
 
   mIsServer = true;
-  mImpl = new DroidSocketImpl(this, aChannel, mAuth, mEncrypt);
+  mImpl = new DroidSocketImpl(XRE_GetIOMessageLoop(), this, aChannel, mAuth,
+                              mEncrypt);
   XRE_GetIOMessageLoop()->PostTask(FROM_HERE,
                                    new SocketListenTask(mImpl));
   return true;
 }
 
 bool
 BluetoothSocket::SendDroidSocketData(UnixSocketRawData* aData)
 {
--- a/dom/events/AsyncEventDispatcher.cpp
+++ b/dom/events/AsyncEventDispatcher.cpp
@@ -14,76 +14,84 @@
 namespace mozilla {
 
 using namespace dom;
 
 /******************************************************************************
  * mozilla::AsyncEventDispatcher
  ******************************************************************************/
 
-AsyncEventDispatcher::AsyncEventDispatcher(nsINode* aEventNode,
+AsyncEventDispatcher::AsyncEventDispatcher(EventTarget* aTarget,
                                            WidgetEvent& aEvent)
-  : mEventNode(aEventNode)
+  : mTarget(aTarget)
   , mDispatchChromeOnly(false)
 {
-  MOZ_ASSERT(mEventNode);
-  EventDispatcher::CreateEvent(aEventNode, nullptr, &aEvent, EmptyString(),
+  MOZ_ASSERT(mTarget);
+  EventDispatcher::CreateEvent(aTarget, nullptr, &aEvent, EmptyString(),
                                getter_AddRefs(mEvent));
   NS_ASSERTION(mEvent, "Should never fail to create an event");
   mEvent->DuplicatePrivateData();
   mEvent->SetTrusted(aEvent.mFlags.mIsTrusted);
 }
 
 NS_IMETHODIMP
 AsyncEventDispatcher::Run()
 {
   if (mEvent) {
     if (mDispatchChromeOnly) {
       MOZ_ASSERT(mEvent->InternalDOMEvent()->IsTrusted());
 
-      nsCOMPtr<nsIDocument> ownerDoc = mEventNode->OwnerDoc();
-      nsPIDOMWindow* window = ownerDoc->GetWindow();
+      nsCOMPtr<nsINode> node = do_QueryInterface(mTarget);
+      MOZ_ASSERT(node, "ChromeOnly dispatch supported with Node targets only!");
+      nsPIDOMWindow* window = node->OwnerDoc()->GetWindow();
       if (!window) {
         return NS_ERROR_INVALID_ARG;
       }
 
       nsCOMPtr<EventTarget> target = window->GetParentTarget();
       if (!target) {
         return NS_ERROR_INVALID_ARG;
       }
       EventDispatcher::DispatchDOMEvent(target, nullptr, mEvent,
                                         nullptr, nullptr);
     } else {
-      nsCOMPtr<EventTarget> target = mEventNode.get();
       bool defaultActionEnabled; // This is not used because the caller is async
-      target->DispatchEvent(mEvent, &defaultActionEnabled);
+      mTarget->DispatchEvent(mEvent, &defaultActionEnabled);
     }
   } else {
-    nsIDocument* doc = mEventNode->OwnerDoc();
     if (mDispatchChromeOnly) {
-      nsContentUtils::DispatchChromeEvent(doc, mEventNode, mEventType,
+      nsCOMPtr<nsINode> node = do_QueryInterface(mTarget);
+      MOZ_ASSERT(node, "ChromeOnly dispatch supported with Node targets only!");
+      nsContentUtils::DispatchChromeEvent(node->OwnerDoc(), node, mEventType,
                                           mBubbles, false);
     } else {
-      nsContentUtils::DispatchTrustedEvent(doc, mEventNode, mEventType,
-                                           mBubbles, false);
+      nsCOMPtr<nsIDOMEvent> event;
+      NS_NewDOMEvent(getter_AddRefs(event), mTarget, nullptr, nullptr);
+      nsresult rv = event->InitEvent(mEventType, mBubbles, false);
+      NS_ENSURE_SUCCESS(rv, rv);
+      event->SetTrusted(true);
+      bool dummy;
+      mTarget->DispatchEvent(event, &dummy);
     }
   }
 
   return NS_OK;
 }
 
 nsresult
 AsyncEventDispatcher::PostDOMEvent()
 {
+  nsRefPtr<AsyncEventDispatcher> ensureDeletionWhenFailing = this;
   return NS_DispatchToCurrentThread(this);
 }
 
 void
 AsyncEventDispatcher::RunDOMEventWhenSafe()
 {
+  nsRefPtr<AsyncEventDispatcher> ensureDeletionWhenFailing = this;
   nsContentUtils::AddScriptRunner(this);
 }
 
 /******************************************************************************
  * mozilla::LoadBlockingAsyncEventDispatcher
  ******************************************************************************/
 
 LoadBlockingAsyncEventDispatcher::~LoadBlockingAsyncEventDispatcher()
--- a/dom/events/AsyncEventDispatcher.h
+++ b/dom/events/AsyncEventDispatcher.h
@@ -21,39 +21,48 @@ namespace mozilla {
  * For example, you may need to fire an event from within layout, but
  * want to ensure that the event handler doesn't mutate the DOM at
  * the wrong time, in order to avoid resulting instability.
  */
  
 class AsyncEventDispatcher : public nsRunnable
 {
 public:
-  AsyncEventDispatcher(nsINode* aEventNode, const nsAString& aEventType,
+  AsyncEventDispatcher(nsINode* aTarget, const nsAString& aEventType,
                        bool aBubbles, bool aDispatchChromeOnly)
-    : mEventNode(aEventNode)
+    : mTarget(aTarget)
     , mEventType(aEventType)
     , mBubbles(aBubbles)
     , mDispatchChromeOnly(aDispatchChromeOnly)
   {
   }
 
-  AsyncEventDispatcher(nsINode* aEventNode, nsIDOMEvent* aEvent)
-    : mEventNode(aEventNode)
+  AsyncEventDispatcher(dom::EventTarget* aTarget, const nsAString& aEventType,
+                       bool aBubbles)
+    : mTarget(aTarget)
+    , mEventType(aEventType)
+    , mBubbles(aBubbles)
+    , mDispatchChromeOnly(false)
+  {
+  }
+
+  AsyncEventDispatcher(dom::EventTarget* aTarget, nsIDOMEvent* aEvent)
+    : mTarget(aTarget)
     , mEvent(aEvent)
     , mDispatchChromeOnly(false)
   {
   }
 
-  AsyncEventDispatcher(nsINode* aEventNode, WidgetEvent& aEvent);
+  AsyncEventDispatcher(dom::EventTarget* aTarget, WidgetEvent& aEvent);
 
   NS_IMETHOD Run() MOZ_OVERRIDE;
   nsresult PostDOMEvent();
   void RunDOMEventWhenSafe();
 
-  nsCOMPtr<nsINode>     mEventNode;
+  nsCOMPtr<dom::EventTarget> mTarget;
   nsCOMPtr<nsIDOMEvent> mEvent;
   nsString              mEventType;
   bool                  mBubbles;
   bool                  mDispatchChromeOnly;
 };
 
 class LoadBlockingAsyncEventDispatcher MOZ_FINAL : public AsyncEventDispatcher
 {
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -496,16 +496,21 @@ ContentParentsMemoryReporter::CollectRep
     return NS_OK;
 }
 
 nsDataHashtable<nsStringHashKey, ContentParent*>* ContentParent::sAppContentParents;
 nsTArray<ContentParent*>* ContentParent::sNonAppContentParents;
 nsTArray<ContentParent*>* ContentParent::sPrivateContent;
 StaticAutoPtr<LinkedList<ContentParent> > ContentParent::sContentParents;
 
+#ifdef MOZ_NUWA_PROCESS
+// The pref updates sent to the Nuwa process.
+static nsTArray<PrefSetting>* sNuwaPrefUpdates;
+#endif
+
 // This is true when subprocess launching is enabled.  This is the
 // case between StartUp() and ShutDown() or JoinAllSubprocesses().
 static bool sCanLaunchSubprocesses;
 
 // The first content child has ID 1, so the chrome process can have ID 0.
 static uint64_t gContentChildID = 1;
 
 // We want the prelaunched process to know that it's for apps, but not
@@ -1320,16 +1325,24 @@ ContentParent::ActorDestroy(ActorDestroy
 #endif
     if (mgr && isMemoryChild) {
         mgr->DecrementNumChildProcesses();
     }
 
     // remove the global remote preferences observers
     Preferences::RemoveObserver(this, "");
 
+#ifdef MOZ_NUWA_PROCESS
+    // Remove the pref update requests.
+    if (IsNuwaProcess() && sNuwaPrefUpdates) {
+        delete sNuwaPrefUpdates;
+        sNuwaPrefUpdates = nullptr;
+    }
+#endif
+
     RecvRemoveGeolocationListener();
 
     mConsoleService = nullptr;
 
     MarkAsDead();
 
     if (obs) {
         nsRefPtr<nsHashPropertyBag> props = new nsHashPropertyBag();
@@ -2110,16 +2123,23 @@ ContentParent::RecvAddNewProcess(const u
         return false;
     }
     nsRefPtr<ContentParent> content;
     content = new ContentParent(this,
                                 MAGIC_PREALLOCATED_APP_MANIFEST_URL,
                                 aPid,
                                 aFds);
     content->Init();
+
+    size_t numNuwaPrefUpdates = sNuwaPrefUpdates ?
+                                sNuwaPrefUpdates->Length() : 0;
+    // Resend pref updates to the forked child.
+    for (int i = 0; i < numNuwaPrefUpdates; i++) {
+        content->SendPreferenceUpdate(sNuwaPrefUpdates->ElementAt(i));
+    }
     PreallocatedProcessManager::PublishSpareProcess(content);
     return true;
 #else
     NS_ERROR("ContentParent::RecvAddNewProcess() not implemented!");
     return false;
 #endif
 }
 
@@ -2157,19 +2177,32 @@ ContentParent::Observe(nsISupports* aSub
     }
     // listening for remotePrefs...
     else if (!strcmp(aTopic, "nsPref:changed")) {
         // We know prefs are ASCII here.
         NS_LossyConvertUTF16toASCII strData(aData);
 
         PrefSetting pref(strData, null_t(), null_t());
         Preferences::GetPreference(&pref);
+#ifdef MOZ_NUWA_PROCESS
+        if (IsNuwaProcess() && PreallocatedProcessManager::IsNuwaReady()) {
+            // Don't send the pref update to the Nuwa process. Save the update
+            // to send to the forked child.
+            if (!sNuwaPrefUpdates) {
+                sNuwaPrefUpdates = new nsTArray<PrefSetting>();
+            }
+            sNuwaPrefUpdates->AppendElement(pref);
+        } else if (!SendPreferenceUpdate(pref)) {
+            return NS_ERROR_NOT_AVAILABLE;
+        }
+#else
         if (!SendPreferenceUpdate(pref)) {
             return NS_ERROR_NOT_AVAILABLE;
         }
+#endif
     }
     else if (!strcmp(aTopic, NS_IPC_IOSERVICE_SET_OFFLINE_TOPIC)) {
       NS_ConvertUTF16toUTF8 dataStr(aData);
       const char *offline = dataStr.get();
       if (!SendSetOffline(!strcmp(offline, "true") ? true : false))
           return NS_ERROR_NOT_AVAILABLE;
     }
     // listening for alert notifications
--- a/dom/ipc/PreallocatedProcessManager.cpp
+++ b/dom/ipc/PreallocatedProcessManager.cpp
@@ -49,16 +49,17 @@ public:
   already_AddRefed<ContentParent> Take();
 
 #ifdef MOZ_NUWA_PROCESS
 public:
   void ScheduleDelayedNuwaFork();
   void DelayedNuwaFork();
   void PublishSpareProcess(ContentParent* aContent);
   void MaybeForgetSpare(ContentParent* aContent);
+  bool IsNuwaReady();
   void OnNuwaReady();
   bool PreallocatedProcessReady();
   already_AddRefed<ContentParent> GetSpareProcess();
   void RunAfterPreallocatedProcessReady(nsIRunnable* aRunnable);
 
 private:
   void NuwaFork();
 
@@ -335,16 +336,22 @@ PreallocatedProcessManagerImpl::MaybeFor
 
   if (aContent == mPreallocatedAppProcess) {
     mPreallocatedAppProcess = nullptr;
     mIsNuwaReady = false;
     ScheduleDelayedNuwaFork();
   }
 }
 
+bool
+PreallocatedProcessManagerImpl::IsNuwaReady()
+{
+  return mIsNuwaReady;
+}
+
 void
 PreallocatedProcessManagerImpl::OnNuwaReady()
 {
   NS_ASSERTION(!mIsNuwaReady, "Multiple Nuwa processes created!");
   ProcessPriorityManager::SetProcessPriority(mPreallocatedAppProcess,
                                              hal::PROCESS_PRIORITY_MASTER);
   mIsNuwaReady = true;
   if (Preferences::GetBool("dom.ipc.processPriorityManager.testMode")) {
@@ -477,16 +484,22 @@ PreallocatedProcessManager::MaybeForgetS
 }
 
 /* static */ void
 PreallocatedProcessManager::OnNuwaReady()
 {
   GetPPMImpl()->OnNuwaReady();
 }
 
+/* static */ bool
+PreallocatedProcessManager::IsNuwaReady()
+{
+  return GetPPMImpl()->IsNuwaReady();
+}
+
 /*static */ bool
 PreallocatedProcessManager::PreallocatedProcessReady()
 {
   return GetPPMImpl()->PreallocatedProcessReady();
 }
 
 /* static */ void
 PreallocatedProcessManager::RunAfterPreallocatedProcessReady(nsIRunnable* aRequest)
--- a/dom/ipc/PreallocatedProcessManager.h
+++ b/dom/ipc/PreallocatedProcessManager.h
@@ -78,16 +78,17 @@ public:
    * Allocate* functions (or change the dom.ipc.processPrelaunch pref from
    * false to true) before we'll create a new process.
    */
   static already_AddRefed<ContentParent> Take();
 
 #ifdef MOZ_NUWA_PROCESS
   static void PublishSpareProcess(ContentParent* aContent);
   static void MaybeForgetSpare(ContentParent* aContent);
+  static bool IsNuwaReady();
   static void OnNuwaReady();
   static bool PreallocatedProcessReady();
   static void RunAfterPreallocatedProcessReady(nsIRunnable* aRunnable);
 #endif
 
 private:
   PreallocatedProcessManager();
   DISALLOW_EVIL_CONSTRUCTORS(PreallocatedProcessManager);
--- a/gfx/layers/basic/TextureClientX11.cpp
+++ b/gfx/layers/basic/TextureClientX11.cpp
@@ -63,23 +63,16 @@ TextureClientX11::ToSurfaceDescriptor(Su
   if (!mSurface) {
     return false;
   }
 
   aOutDescriptor = SurfaceDescriptorX11(mSurface);
   return true;
 }
 
-TextureClientData*
-TextureClientX11::DropTextureData()
-{
-  MOZ_ASSERT(!(mFlags & TextureFlags::DEALLOCATE_CLIENT));
-  return nullptr;
-}
-
 bool
 TextureClientX11::AllocateForSurface(IntSize aSize, TextureAllocationFlags aTextureFlags)
 {
   MOZ_ASSERT(IsValid());
   //MOZ_ASSERT(mFormat != gfx::FORMAT_YUV, "This TextureClient cannot use YCbCr data");
 
   gfxContentType contentType = ContentForFormat(mFormat);
   nsRefPtr<gfxASurface> surface = gfxPlatform::GetPlatform()->CreateOffscreenSurface(aSize, contentType);
--- a/gfx/layers/basic/TextureClientX11.h
+++ b/gfx/layers/basic/TextureClientX11.h
@@ -24,18 +24,16 @@ class TextureClientX11 : public TextureC
   ~TextureClientX11();
 
   // TextureClient
 
   virtual bool IsAllocated() const MOZ_OVERRIDE;
 
   virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) MOZ_OVERRIDE;
 
-  virtual TextureClientData* DropTextureData() MOZ_OVERRIDE;
-
   virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; }
 
   virtual bool Lock(OpenMode aMode) MOZ_OVERRIDE;
 
   virtual void Unlock() MOZ_OVERRIDE;
 
   virtual bool IsLocked() const MOZ_OVERRIDE { return mLocked; }
 
--- a/gfx/layers/client/CompositableClient.h
+++ b/gfx/layers/client/CompositableClient.h
@@ -22,17 +22,16 @@ namespace layers {
 class AsyncTransactionTracker;
 class CompositableClient;
 class TextureClient;
 class BufferTextureClient;
 class ImageBridgeChild;
 class CompositableForwarder;
 class CompositableChild;
 class SurfaceDescriptor;
-class TextureClientData;
 class PCompositableChild;
 /**
  * CompositableClient manages the texture-specific logic for composite layers,
  * independently of the layer. It is the content side of a CompositableClient/
  * CompositableHost pair.
  *
  * CompositableClient's purpose is to send texture data to the compositor side
  * along with any extra information about how the texture is to be composited.
--- a/gfx/layers/client/TextureClient.cpp
+++ b/gfx/layers/client/TextureClient.cpp
@@ -77,17 +77,16 @@ namespace layers {
  */
 class TextureChild MOZ_FINAL : public PTextureChild
 {
 public:
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TextureChild)
 
   TextureChild()
   : mForwarder(nullptr)
-  , mTextureData(nullptr)
   , mTextureClient(nullptr)
   , mIPCOpen(false)
   {
   }
 
   bool Recv__delete__() MOZ_OVERRIDE;
 
   bool RecvCompositorRecycle()
@@ -99,28 +98,16 @@ public:
 
   void WaitForCompositorRecycle()
   {
     mWaitForRecycle = mTextureClient;
     RECYCLE_LOG("Wait for recycle %p\n", mWaitForRecycle.get());
     SendClientRecycle();
   }
 
-  /**
-   * Only used during the deallocation phase iff we need synchronization between
-   * the client and host side for deallocation (that is, when the data is going
-   * to be deallocated or recycled on the client side).
-   */
-  void SetTextureData(TextureClientData* aData)
-  {
-    mTextureData = aData;
-  }
-
-  void DeleteTextureData();
-
   CompositableForwarder* GetForwarder() { return mForwarder; }
 
   ISurfaceAllocator* GetAllocator() { return mForwarder; }
 
   void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
 
   bool IPCOpen() const { return mIPCOpen; }
 
@@ -138,38 +125,25 @@ private:
   void ReleaseIPDLReference() {
     MOZ_ASSERT(mIPCOpen == true);
     mIPCOpen = false;
     Release();
   }
 
   RefPtr<CompositableForwarder> mForwarder;
   RefPtr<TextureClient> mWaitForRecycle;
-  TextureClientData* mTextureData;
   TextureClient* mTextureClient;
   bool mIPCOpen;
 
   friend class TextureClient;
 };
 
-void
-TextureChild::DeleteTextureData()
-{
-  mWaitForRecycle = nullptr;
-  if (mTextureData) {
-    mTextureData->DeallocateSharedData(GetAllocator());
-    delete mTextureData;
-    mTextureData = nullptr;
-  }
-}
-
 bool
 TextureChild::Recv__delete__()
 {
-  DeleteTextureData();
   return true;
 }
 
 void
 TextureChild::ActorDestroy(ActorDestroyReason why)
 {
   if (mTextureClient) {
     mTextureClient->mActor = nullptr;
@@ -357,90 +331,16 @@ TextureClient::CreateBufferTextureClient
     return result.forget();
   }
   RefPtr<BufferTextureClient> result = new ShmemTextureClient(aAllocator, aFormat,
                                                               aMoz2DBackend,
                                                               aTextureFlags);
   return result.forget();
 }
 
-
-class ShmemTextureClientData : public TextureClientData
-{
-public:
-  ShmemTextureClientData(ipc::Shmem& aShmem)
-  : mShmem(aShmem)
-  {
-    MOZ_COUNT_CTOR(ShmemTextureClientData);
-  }
-
-  ~ShmemTextureClientData()
-  {
-    MOZ_COUNT_CTOR(ShmemTextureClientData);
-  }
-
-  virtual void DeallocateSharedData(ISurfaceAllocator* allocator)
-  {
-    allocator->DeallocShmem(mShmem);
-    mShmem = ipc::Shmem();
-  }
-
-private:
-  ipc::Shmem mShmem;
-};
-
-class MemoryTextureClientData : public TextureClientData
-{
-public:
-  MemoryTextureClientData(uint8_t* aBuffer)
-  : mBuffer(aBuffer)
-  {
-    MOZ_COUNT_CTOR(MemoryTextureClientData);
-  }
-
-  ~MemoryTextureClientData()
-  {
-    MOZ_ASSERT(!mBuffer, "Forgot to deallocate the shared texture data?");
-    MOZ_COUNT_DTOR(MemoryTextureClientData);
-  }
-
-  virtual void DeallocateSharedData(ISurfaceAllocator*)
-  {
-    delete[] mBuffer;
-    mBuffer = nullptr;
-  }
-
-private:
-  uint8_t* mBuffer;
-};
-
-TextureClientData*
-MemoryTextureClient::DropTextureData()
-{
-  if (!mBuffer) {
-    return nullptr;
-  }
-  TextureClientData* result = new MemoryTextureClientData(mBuffer);
-  MarkInvalid();
-  mBuffer = nullptr;
-  return result;
-}
-
-TextureClientData*
-ShmemTextureClient::DropTextureData()
-{
-  if (!mShmem.IsReadable()) {
-    return nullptr;
-  }
-  TextureClientData* result = new ShmemTextureClientData(mShmem);
-  MarkInvalid();
-  mShmem = ipc::Shmem();
-  return result;
-}
-
 TextureClient::TextureClient(TextureFlags aFlags)
   : mFlags(aFlags)
   , mShared(false)
   , mValid(true)
 {}
 
 TextureClient::~TextureClient()
 {
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -76,38 +76,16 @@ public:
    * be painted entirely with opaque content.
    */
   virtual bool AllocateForYCbCr(gfx::IntSize aYSize,
                                 gfx::IntSize aCbCrSize,
                                 StereoMode aStereoMode) = 0;
 };
 
 /**
- * Holds the shared data of a TextureClient, to be destroyed later.
- *
- * TextureClient's destructor initiates the destruction sequence of the
- * texture client/host pair. If the shared data is to be deallocated on the
- * host side, there is nothing to do.
- * On the other hand, if the client data must be deallocated on the client
- * side, the CompositableClient will ask the TextureClient to drop its shared
- * data in the form of a TextureClientData object. This data will be kept alive
- * until the host side confirms that it is not using the data anymore and that
- * it is completely safe to deallocate the shared data.
- *
- * See:
- *  - The PTexture IPDL protocol
- *  - CompositableChild in TextureClient.cpp
- */
-class TextureClientData {
-public:
-  virtual void DeallocateSharedData(ISurfaceAllocator* allocator) = 0;
-  virtual ~TextureClientData() {}
-};
-
-/**
  * TextureClient is a thin abstraction over texture data that need to be shared
  * between the content process and the compositor process. It is the
  * content-side half of a TextureClient/TextureHost pair. A corresponding
  * TextureHost lives on the compositor-side.
  *
  * TextureClient's primary purpose is to present texture data in a way that is
  * understood by the IPC system. There are two ways to use it:
  * - Use it to serialize image data that is not IPC-friendly (most likely
@@ -340,26 +318,16 @@ private:
 protected:
   /**
    * An invalid TextureClient cannot provide access to its shared data
    * anymore. This usually means it will soon be destroyed.
    */
   void MarkInvalid() { mValid = false; }
 
   /**
-   * Drop the shared data into a TextureClientData object and mark this
-   * TextureClient as invalid.
-   *
-   * The TextureClient must not hold any reference to the shared data
-   * after this method has been called.
-   * The TextureClientData is owned by the caller.
-   */
-  virtual TextureClientData* DropTextureData() = 0;
-
-  /**
    * Should only be called *once* per texture, in TextureClient::InitIPDLActor.
    * Some texture implementations rely on the fact that the descriptor will be
    * deserialized.
    * Calling ToSurfaceDescriptor again after it has already returned true,
    * or never constructing a TextureHost with aDescriptor may result in a memory
    * leak (see CairoTextureClientD3D9 for example).
    */
   virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aDescriptor) = 0;
@@ -465,18 +433,16 @@ public:
   virtual bool Allocate(uint32_t aSize) MOZ_OVERRIDE;
 
   virtual uint8_t* GetBuffer() const MOZ_OVERRIDE;
 
   virtual size_t GetBufferSize() const MOZ_OVERRIDE;
 
   virtual bool IsAllocated() const MOZ_OVERRIDE { return mAllocated; }
 
-  virtual TextureClientData* DropTextureData() MOZ_OVERRIDE;
-
   virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return true; }
 
   mozilla::ipc::Shmem& GetShmem() { return mShmem; }
 
 protected:
   mozilla::ipc::Shmem mShmem;
   bool mAllocated;
 };
@@ -501,18 +467,16 @@ public:
   virtual uint8_t* GetBuffer() const MOZ_OVERRIDE { return mBuffer; }
 
   virtual size_t GetBufferSize() const MOZ_OVERRIDE { return mBufSize; }
 
   virtual bool IsAllocated() const MOZ_OVERRIDE { return mBuffer != nullptr; }
 
   virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return true; }
 
-  virtual TextureClientData* DropTextureData() MOZ_OVERRIDE;
-
 protected:
   uint8_t* mBuffer;
   size_t mBufSize;
 };
 
 struct TextureClientAutoUnlock
 {
   TextureClient* mTexture;
--- a/gfx/layers/d3d11/TextureD3D11.h
+++ b/gfx/layers/d3d11/TextureD3D11.h
@@ -45,18 +45,16 @@ public:
   virtual bool ImplementsLocking() const MOZ_OVERRIDE { return true; }
 
   virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return false; }
 
   virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) MOZ_OVERRIDE;
 
   virtual gfx::IntSize GetSize() const MOZ_OVERRIDE { return mSize; }
 
-  virtual TextureClientData* DropTextureData() MOZ_OVERRIDE { return nullptr; }
-
   virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE { return mFormat; }
 
   virtual bool CanExposeDrawTarget() const MOZ_OVERRIDE { return true; }
 
   virtual TemporaryRef<gfx::DrawTarget> GetAsDrawTarget() MOZ_OVERRIDE;
 
   virtual bool AllocateForSurface(gfx::IntSize aSize,
                                   TextureAllocationFlags aFlags = ALLOC_DEFAULT) MOZ_OVERRIDE;
--- a/gfx/layers/d3d9/TextureD3D9.cpp
+++ b/gfx/layers/d3d9/TextureD3D9.cpp
@@ -299,38 +299,16 @@ TextureSourceD3D9::SurfaceToTexture(Devi
   context->SetOperator(gfxContext::OPERATOR_SOURCE);
   context->Paint();
 
   FinishTextures(aDeviceManager, texture, surface);
 
   return texture;
 }
 
-class D3D9TextureClientData : public TextureClientData
-{
-public:
-  D3D9TextureClientData(IDirect3DTexture9* aTexture)
-    : mTexture(aTexture)
-  {}
-
-  D3D9TextureClientData(gfxWindowsSurface* aWindowSurface)
-    : mWindowSurface(aWindowSurface)
-  {}
-
-  virtual void DeallocateSharedData(ISurfaceAllocator*) MOZ_OVERRIDE
-  {
-    mWindowSurface = nullptr;
-    mTexture = nullptr;
-  }
-
-private:
-  RefPtr<IDirect3DTexture9> mTexture;
-  nsRefPtr<gfxWindowsSurface> mWindowSurface;
-};
-
 DataTextureSourceD3D9::DataTextureSourceD3D9(gfx::SurfaceFormat aFormat,
                                              CompositorD3D9* aCompositor,
                                              TextureFlags aFlags,
                                              StereoMode aStereoMode)
   : mFormat(aFormat)
   , mCompositor(aCompositor)
   , mCurrentTile(0)
   , mFlags(aFlags)
@@ -697,25 +675,16 @@ CairoTextureClientD3D9::AllocateForSurfa
   }
 
   mNeedsClear = aFlags & ALLOC_CLEAR_BUFFER;
 
   MOZ_ASSERT(mTexture);
   return true;
 }
 
-TextureClientData*
-CairoTextureClientD3D9::DropTextureData()
-{
-  TextureClientData* data = new D3D9TextureClientData(mTexture);
-  mTexture = nullptr;
-  MarkInvalid();
-  return data;
-}
-
 DIBTextureClientD3D9::DIBTextureClientD3D9(gfx::SurfaceFormat aFormat, TextureFlags aFlags)
   : TextureClient(aFlags)
   , mFormat(aFormat)
   , mIsLocked(false)
 {
   MOZ_COUNT_CTOR(DIBTextureClientD3D9);
 }
 
@@ -788,48 +757,30 @@ DIBTextureClientD3D9::AllocateForSurface
     NS_WARNING("Could not create surface");
     mSurface = nullptr;
     return false;
   }
 
   return true;
 }
 
-TextureClientData*
-DIBTextureClientD3D9::DropTextureData()
-{
-  TextureClientData* data = new D3D9TextureClientData(mSurface);
-  mSurface = nullptr;
-  MarkInvalid();
-  return data;
-}
-
 SharedTextureClientD3D9::SharedTextureClientD3D9(gfx::SurfaceFormat aFormat, TextureFlags aFlags)
   : TextureClient(aFlags)
   , mFormat(aFormat)
   , mHandle(0)
   , mIsLocked(false)
 {
   MOZ_COUNT_CTOR(SharedTextureClientD3D9);
 }
 
 SharedTextureClientD3D9::~SharedTextureClientD3D9()
 {
   MOZ_COUNT_DTOR(SharedTextureClientD3D9);
 }
 
-TextureClientData*
-SharedTextureClientD3D9::DropTextureData()
-{
-  TextureClientData* data = new D3D9TextureClientData(mTexture);
-  mTexture = nullptr;
-  MarkInvalid();
-  return data;
-}
-
 bool
 SharedTextureClientD3D9::Lock(OpenMode)
 {
   MOZ_ASSERT(!mIsLocked);
   if (!IsValid()) {
     return false;
   }
   mIsLocked = true;
--- a/gfx/layers/d3d9/TextureD3D9.h
+++ b/gfx/layers/d3d9/TextureD3D9.h
@@ -202,18 +202,16 @@ public:
   virtual bool IsLocked() const MOZ_OVERRIDE { return mIsLocked; }
 
   virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) MOZ_OVERRIDE;
 
   virtual gfx::IntSize GetSize() const { return mSize; }
 
   virtual gfx::SurfaceFormat GetFormat() const { return mFormat; }
 
-  virtual TextureClientData* DropTextureData() MOZ_OVERRIDE;
-
   virtual bool CanExposeDrawTarget() const MOZ_OVERRIDE { return true; }
 
   virtual TemporaryRef<gfx::DrawTarget> GetAsDrawTarget() MOZ_OVERRIDE;
 
   virtual bool AllocateForSurface(gfx::IntSize aSize,
                                   TextureAllocationFlags aFlags = ALLOC_DEFAULT) MOZ_OVERRIDE;
 
   virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return true; }
@@ -253,18 +251,16 @@ public:
   virtual bool IsLocked() const MOZ_OVERRIDE { return mIsLocked; }
 
   virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) MOZ_OVERRIDE;
 
   virtual gfx::IntSize GetSize() const { return mSize; }
 
   virtual gfx::SurfaceFormat GetFormat() const { return mFormat; }
 
-  virtual TextureClientData* DropTextureData() MOZ_OVERRIDE;
-
   virtual bool CanExposeDrawTarget() const MOZ_OVERRIDE { return true; }
 
   virtual TemporaryRef<gfx::DrawTarget> GetAsDrawTarget() MOZ_OVERRIDE;
 
   virtual bool AllocateForSurface(gfx::IntSize aSize,
                                   TextureAllocationFlags aFlags = ALLOC_DEFAULT) MOZ_OVERRIDE;
 
   virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return true; }
@@ -309,18 +305,16 @@ public:
     mDesc = aDesc;
   }
 
   virtual gfx::IntSize GetSize() const
   {
     return gfx::IntSize(mDesc.Width, mDesc.Height);
   }
 
-  virtual TextureClientData* DropTextureData() MOZ_OVERRIDE;
-
   virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return true; }
 
 private:
   RefPtr<IDirect3DTexture9> mTexture;
   gfx::SurfaceFormat mFormat;
   HANDLE mHandle;
   D3DSURFACE_DESC mDesc;
   bool mIsLocked;
--- a/gfx/layers/opengl/GrallocTextureClient.cpp
+++ b/gfx/layers/opengl/GrallocTextureClient.cpp
@@ -13,45 +13,16 @@
 #include "gfx2DGlue.h"
 
 namespace mozilla {
 namespace layers {
 
 using namespace mozilla::gfx;
 using namespace android;
 
-class GrallocTextureClientData : public TextureClientData {
-public:
-  GrallocTextureClientData(MaybeMagicGrallocBufferHandle aDesc)
-    : mGrallocHandle(aDesc)
-  {
-    MOZ_COUNT_CTOR(GrallocTextureClientData);
-  }
-
-  ~GrallocTextureClientData()
-  {
-    MOZ_COUNT_DTOR(GrallocTextureClientData);
-  }
-
-  virtual void DeallocateSharedData(ISurfaceAllocator* allocator) MOZ_OVERRIDE
-  {
-    allocator->DeallocGrallocBuffer(&mGrallocHandle);
-  }
-
-private:
-  MaybeMagicGrallocBufferHandle mGrallocHandle;
-};
-
-TextureClientData*
-GrallocTextureClientOGL::DropTextureData()
-{
-  TextureClientData* result = new GrallocTextureClientData(mGrallocHandle);
-  return result;
-}
-
 GrallocTextureClientOGL::GrallocTextureClientOGL(MaybeMagicGrallocBufferHandle buffer,
                                                  gfx::IntSize aSize,
                                                  gfx::BackendType aMoz2dBackend,
                                                  TextureFlags aFlags)
 : BufferTextureClient(nullptr, gfx::SurfaceFormat::UNKNOWN, aMoz2dBackend, aFlags)
 , mGrallocHandle(buffer)
 , mMappedBuffer(nullptr)
 , mMediaBuffer(nullptr)
--- a/gfx/layers/opengl/GrallocTextureClient.h
+++ b/gfx/layers/opengl/GrallocTextureClient.h
@@ -55,18 +55,16 @@ public:
   virtual bool ImplementsLocking() const MOZ_OVERRIDE { return true; }
 
   virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return false; }
 
   virtual bool IsAllocated() const MOZ_OVERRIDE;
 
   virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) MOZ_OVERRIDE;
 
-  virtual TextureClientData* DropTextureData() MOZ_OVERRIDE;
-
   virtual void SetReleaseFenceHandle(FenceHandle aReleaseFenceHandle) MOZ_OVERRIDE;
 
   virtual void WaitReleaseFence() MOZ_OVERRIDE;
 
   void InitWith(MaybeMagicGrallocBufferHandle aDesc, gfx::IntSize aSize);
 
   void SetTextureFlags(TextureFlags aFlags) { AddFlags(aFlags); }
 
--- a/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.cpp
+++ b/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.cpp
@@ -60,35 +60,10 @@ MacIOSurfaceTextureClientOGL::ToSurfaceD
 }
 
 gfx::IntSize
 MacIOSurfaceTextureClientOGL::GetSize() const
 {
   return gfx::IntSize(mSurface->GetDevicePixelWidth(), mSurface->GetDevicePixelHeight());
 }
 
-class MacIOSurfaceTextureClientData : public TextureClientData
-{
-public:
-  MacIOSurfaceTextureClientData(MacIOSurface* aSurface)
-    : mSurface(aSurface)
-  {}
-
-  virtual void DeallocateSharedData(ISurfaceAllocator*) MOZ_OVERRIDE
-  {
-    mSurface = nullptr;
-  }
-
-private:
-  RefPtr<MacIOSurface> mSurface;
-};
-
-TextureClientData*
-MacIOSurfaceTextureClientOGL::DropTextureData()
-{
-  TextureClientData* data = new MacIOSurfaceTextureClientData(mSurface);
-  mSurface = nullptr;
-  MarkInvalid();
-  return data;
-}
-
 }
 }
--- a/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.h
+++ b/gfx/layers/opengl/MacIOSurfaceTextureClientOGL.h
@@ -29,21 +29,19 @@ public:
   virtual bool IsLocked() const MOZ_OVERRIDE;
 
   virtual bool IsAllocated() const MOZ_OVERRIDE { return !!mSurface; }
 
   virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) MOZ_OVERRIDE;
 
   virtual gfx::IntSize GetSize() const;
 
-  virtual TextureClientData* DropTextureData() MOZ_OVERRIDE;
-
   virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return false; }
 
 protected:
   RefPtr<MacIOSurface> mSurface;
   bool mIsLocked;
 };
 
 }
 }
 
-#endif // MOZILLA_GFX_MACIOSURFACETEXTURECLIENTOGL_H
\ No newline at end of file
+#endif // MOZILLA_GFX_MACIOSURFACETEXTURECLIENTOGL_H
--- a/gfx/layers/opengl/TextureClientOGL.h
+++ b/gfx/layers/opengl/TextureClientOGL.h
@@ -50,25 +50,16 @@ public:
 
   void InitWith(gl::SharedTextureHandle aHandle,
                 gfx::IntSize aSize,
                 gl::SharedTextureShareType aShareType,
                 bool aInverted = false);
 
   virtual gfx::IntSize GetSize() const { return mSize; }
 
-  virtual TextureClientData* DropTextureData() MOZ_OVERRIDE
-  {
-    // XXX - right now the code paths using this are managing the shared texture
-    // data, although they should use a TextureClientData for this to ensure that
-    // the destruction sequence is race-free.
-    MarkInvalid();
-    return nullptr;
-  }
-
   virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE
   {
     return gfx::SurfaceFormat::UNKNOWN;
   }
 
   virtual bool AllocateForSurface(gfx::IntSize aSize, TextureAllocationFlags aFlags) MOZ_OVERRIDE
   {
     return false;
@@ -97,18 +88,16 @@ public:
   virtual bool Lock(OpenMode mode) MOZ_OVERRIDE;
 
   virtual void Unlock() MOZ_OVERRIDE;
 
   virtual bool IsLocked() const MOZ_OVERRIDE { return mIsLocked; }
 
   virtual bool ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor) MOZ_OVERRIDE;
 
-  virtual TextureClientData* DropTextureData() MOZ_OVERRIDE { return nullptr; }
-
   virtual bool HasInternalBuffer() const MOZ_OVERRIDE { return false; }
 
   void InitWith(gfx::SurfaceStream* aStream);
 
   virtual gfx::IntSize GetSize() const { return gfx::IntSize(); }
 
   virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE
   {
--- a/js/src/configure.in
+++ b/js/src/configure.in
@@ -2088,17 +2088,17 @@ fi
 
 AC_LANG_CPLUSPLUS
 
 MOZ_CXX11
 
 dnl Check for .hidden assembler directive and visibility attribute.
 dnl Borrowed from glibc configure.in
 dnl ===============================================================
-if test "$GNU_CC"; then
+if test "$GNU_CC" -a "$OS_TARGET" != WINNT; then
   AC_DEFINE(HAVE_VISIBILITY_HIDDEN_ATTRIBUTE)
   AC_DEFINE(HAVE_VISIBILITY_ATTRIBUTE)
   if test -n "$gonkdir"; then
     visibility_target=Gonk
   else
     visibility_target=$OS_TARGET
   fi
   case "$visibility_target" in
--- a/js/src/ctypes/libffi-patches/00-base.patch
+++ b/js/src/ctypes/libffi-patches/00-base.patch
@@ -1,13 +1,13 @@
 Modifications to upstream libffi needed for the Mozilla build:
 * Clear INFO_DEPS so that builds don't fail when makeinfo isn't present.
   - This can be removed if https://github.com/atgreen/libffi/issues/111 is fixed.
 * Various workarounds for pymake bugs.
-  - Once pymake support is fully deprecated, hunks 2 & 3 be safely removed.
+  - Once pymake support is fully deprecated, hunks 2-4 be safely removed.
 
 diff --git a/js/src/ctypes/libffi/Makefile.in b/js/src/ctypes/libffi/Makefile.in
 --- a/js/src/ctypes/libffi/Makefile.in
 +++ b/js/src/ctypes/libffi/Makefile.in
 @@ -358,17 +358,17 @@ am__v_TEXI2PDF_1 =
  AM_V_texinfo = $(am__v_texinfo_@AM_V@)
  am__v_texinfo_ = $(am__v_texinfo_@AM_DEFAULT_V@)
  am__v_texinfo_0 = -q
@@ -21,17 +21,40 @@ diff --git a/js/src/ctypes/libffi/Makefi
  am__TEXINFO_TEX_DIR = $(srcdir)
  DVIS = doc/libffi.dvi
  PDFS = doc/libffi.pdf
  PSS = doc/libffi.ps
  HTMLS = doc/libffi.html
  TEXINFOS = doc/libffi.texi
  TEXI2DVI = texi2dvi
  TEXI2PDF = $(TEXI2DVI) --pdf --batch
-@@ -1292,57 +1292,57 @@ distclean-compile:
+@@ -758,18 +758,20 @@ Makefile: $(srcdir)/Makefile.in $(top_bu
+ 
+ $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ 	$(am__cd) $(srcdir) && $(AUTOCONF)
+ $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ 	$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
+ $(am__aclocal_m4_deps):
+ 
+ fficonfig.h: stamp-h1
+-	@test -f $@ || rm -f stamp-h1
+-	@test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1
++	@if test ! -f $@; then \
++	  rm -f stamp-h1; \
++	  $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \
++	else :; fi
+ 
+ stamp-h1: $(srcdir)/fficonfig.h.in $(top_builddir)/config.status
+ 	@rm -f stamp-h1
+ 	cd $(top_builddir) && $(SHELL) ./config.status fficonfig.h
+ $(srcdir)/fficonfig.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) 
+ 	($(am__cd) $(top_srcdir) && $(AUTOHEADER))
+ 	rm -f stamp-h1
+ 	touch $@
+@@ -1292,57 +1294,57 @@ distclean-compile:
  @AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/freebsd.Plo@am__quote@
  @AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/sysv.Plo@am__quote@
  @AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/unix64.Plo@am__quote@
  @AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/win32.Plo@am__quote@
  @AMDEP_TRUE@@am__include@ @am__quote@src/x86/$(DEPDIR)/win64.Plo@am__quote@
  @AMDEP_TRUE@@am__include@ @am__quote@src/xtensa/$(DEPDIR)/ffi.Plo@am__quote@
  @AMDEP_TRUE@@am__include@ @am__quote@src/xtensa/$(DEPDIR)/sysv.Plo@am__quote@
  
@@ -85,17 +108,17 @@ diff --git a/js/src/ctypes/libffi/Makefi
  @am__fastdepCC_TRUE@	$(AM_V_CC)depbase=`echo $@ | sed 's|[^/]*$$|$(DEPDIR)/&|;s|\.lo$$||'`;\
  @am__fastdepCC_TRUE@	$(LTCOMPILE) -MT $@ -MD -MP -MF $$depbase.Tpo -c -o $@ $< &&\
  @am__fastdepCC_TRUE@	$(am__mv) $$depbase.Tpo $$depbase.Plo
  @AMDEP_TRUE@@am__fastdepCC_FALSE@	$(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
  @AMDEP_TRUE@@am__fastdepCC_FALSE@	DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
  @am__fastdepCC_FALSE@	$(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
  
  mostlyclean-libtool:
-@@ -1443,17 +1443,17 @@ doc/libffi.html: doc/libffi.texi $(srcdi
+@@ -1443,17 +1445,17 @@ doc/libffi.html: doc/libffi.texi $(srcdi
  	-@rm -f vti.tmp
  	@cp $(srcdir)/doc/version.texi $@
  
  mostlyclean-vti:
  	-rm -f vti.tmp
  
  maintainer-clean-vti:
  @MAINTAINER_MODE_TRUE@	-rm -f $(srcdir)/doc/stamp-vti $(srcdir)/doc/version.texi
--- a/js/src/ctypes/libffi/Makefile.in
+++ b/js/src/ctypes/libffi/Makefile.in
@@ -758,18 +758,20 @@ Makefile: $(srcdir)/Makefile.in $(top_bu
 
 $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
 	$(am__cd) $(srcdir) && $(AUTOCONF)
 $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
 	$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
 $(am__aclocal_m4_deps):
 
 fficonfig.h: stamp-h1
-	@test -f $@ || rm -f stamp-h1
-	@test -f $@ || $(MAKE) $(AM_MAKEFLAGS) stamp-h1
+	@if test ! -f $@; then \
+	  rm -f stamp-h1; \
+	  $(MAKE) $(AM_MAKEFLAGS) stamp-h1; \
+	else :; fi
 
 stamp-h1: $(srcdir)/fficonfig.h.in $(top_builddir)/config.status
 	@rm -f stamp-h1
 	cd $(top_builddir) && $(SHELL) ./config.status fficonfig.h
 $(srcdir)/fficonfig.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) 
 	($(am__cd) $(top_srcdir) && $(AUTOHEADER))
 	rm -f stamp-h1
 	touch $@
--- a/js/src/jit-test/tests/asm.js/testSource.js
+++ b/js/src/jit-test/tests/asm.js/testSource.js
@@ -232,17 +232,17 @@ if (isAsmJSCompilationAvailable() && isC
     var m = new Function('glob', 'ffi', 'heap', bodyOnly);
     assertEq(isAsmJSModuleLoadedFromCache(m), true);
     assertEq(m.toString(), "function anonymous(glob, ffi, heap) {\n" + bodyOnly + "\n}");
     assertEq(m.toSource(), "(function anonymous(glob, ffi, heap) {\n" + bodyOnly + "\n})");
 }
 
 })();
 
-/* Implicit "use strict" context */
+/* Implicit "use strict" context in modules */
 (function() {
 
 var funcHeader =  'function (glob, ffi, heap) {',
     funcBody = '\n"use asm";\n\
     function g() {}\n\
     return g;\n\n'
     funcFooter = '}',
     funcSource = funcHeader + funcBody + funcFooter
@@ -331,8 +331,38 @@ if (isAsmJSCompilationAvailable() && isC
 
     eval('var x = 42;' + moduleDecl);
     m = g3();
     assertEq(isAsmJSModuleLoadedFromCache(g3), true);
     checkFuncSrc(m);
 }
 
 })();
+
+/* Implicit "use strict" context in functions */
+(function () {
+
+var funcCode = 'function g(x) {\n\
+    x=x|0;\n\
+    return x + 1 | 0;}';
+var moduleCode = 'function () {\n\
+    "use asm";\n' + funcCode + '\n\
+    return g;\n\
+    }',
+    useStrict = '"use strict";';
+
+var f5 = eval(useStrict + ";\n(" + moduleCode + "())");
+
+var expectedToString = funcCode.replace('{', '{\n' + useStrict + '\n')
+var expectedToSource = expectedToString
+
+assertEq(f5.toString(), expectedToString);
+assertEq(f5.toSource(), expectedToSource);
+
+if (isAsmJSCompilationAvailable() && isCachingEnabled()) {
+    var mf5 = eval("\"use strict\";\n(" + moduleCode + ")");
+    assertEq(isAsmJSModuleLoadedFromCache(mf5), true);
+    var f5 = mf5();
+    assertEq(f5.toString(), expectedToString);
+    assertEq(f5.toSource(), expectedToSource);
+}
+
+})();
--- a/js/src/jit/AsmJSLink.cpp
+++ b/js/src/jit/AsmJSLink.cpp
@@ -580,16 +580,17 @@ HandleDynamicLinkFailure(JSContext *cx, 
         formals.infallibleAppend(module.globalArgumentName());
     if (module.importArgumentName())
         formals.infallibleAppend(module.importArgumentName());
     if (module.bufferArgumentName())
         formals.infallibleAppend(module.bufferArgumentName());
 
     CompileOptions options(cx);
     options.setOriginPrincipals(module.scriptSource()->originPrincipals())
+           .setFile(module.scriptSource()->filename())
            .setCompileAndGo(false)
            .setNoScriptRval(false);
 
     SourceBufferHolder srcBuf(src->chars(), end - begin, SourceBufferHolder::NoOwnership);
     if (!frontend::CompileFunctionBody(cx, &fun, options, formals, srcBuf))
         return false;
 
     // Call the function we just recompiled.
@@ -855,16 +856,38 @@ js::IsAsmJSModule(JSContext *cx, unsigne
 }
 
 bool
 js::IsAsmJSModule(HandleFunction fun)
 {
     return fun->isNative() && fun->maybeNative() == LinkAsmJS;
 }
 
+static bool
+AppendUseStrictSource(JSContext *cx, HandleFunction fun, Handle<JSFlatString*> src, StringBuffer &out)
+{
+    // We need to add "use strict" in the body right after the opening
+    // brace.
+    size_t bodyStart = 0, bodyEnd;
+
+    // No need to test for functions created with the Function ctor as
+    // these don't implicitly inherit the "use strict" context. Strict mode is
+    // enabled for functions created with the Function ctor only if they begin with
+    // the "use strict" directive, but these functions won't validate as asm.js
+    // modules.
+
+    ConstTwoByteChars chars(src->chars(), src->length());
+    if (!FindBody(cx, fun, chars, src->length(), &bodyStart, &bodyEnd))
+        return false;
+
+    return out.append(chars, bodyStart) &&
+           out.append("\n\"use strict\";\n") &&
+           out.append(chars + bodyStart, src->length() - bodyStart);
+}
+
 JSString *
 js::AsmJSModuleToString(JSContext *cx, HandleFunction fun, bool addParenToLambda)
 {
     AsmJSModule &module = ModuleFunctionToModuleObject(fun).module();
 
     uint32_t begin = module.funcStart();
     uint32_t end = module.funcEndAfterCurly();
     ScriptSource *source = module.scriptSource();
@@ -904,36 +927,18 @@ js::AsmJSModuleToString(JSContext *cx, H
             return nullptr;
     }
 
     Rooted<JSFlatString*> src(cx, source->substring(cx, begin, end));
     if (!src)
         return nullptr;
 
     if (module.strict()) {
-        // We need to add "use strict" in the body right after the opening
-        // brace.
-        size_t bodyStart = 0, bodyEnd;
-
-        // No need to test for functions created with the Function ctor as
-        // these doesn't implicitly inherit the "use strict" context. Strict mode is
-        // enabled for functions created with the Function ctor only if they begin with
-        // the "use strict" directive, but these functions won't validate as asm.js
-        // modules.
-
-        ConstTwoByteChars chars(src->chars(), src->length());
-        if (!FindBody(cx, fun, chars, src->length(), &bodyStart, &bodyEnd))
+        if (!AppendUseStrictSource(cx, fun, src, out))
             return nullptr;
-
-        if (!out.append(chars, bodyStart) ||
-            !out.append("\n\"use strict\";\n") ||
-            !out.append(chars + bodyStart, src->length() - bodyStart))
-        {
-            return nullptr;
-        }
     } else {
         if (!out.append(src->chars(), src->length()))
             return nullptr;
     }
 
     if (funCtor && !out.append("\n}"))
         return nullptr;
 
@@ -990,17 +995,32 @@ js::AsmJSFunctionToString(JSContext *cx,
 
     // asm.js functions cannot have been created with a Function constructor
     // as they belong within a module.
     JS_ASSERT(!(begin == 0 && end == source->length() && source->argumentsNotIncluded()));
 
     if (!out.append("function "))
         return nullptr;
 
-    Rooted<JSFlatString*> src(cx, source->substring(cx, begin, end));
-    if (!src)
-        return nullptr;
+    if (module.strict()) {
+        // AppendUseStrictSource expects its input to start right after the
+        // function name, so split the source chars from the src into two parts:
+        // the function name and the rest (arguments + body).
+
+        // asm.js functions can't be anonymous
+        JS_ASSERT(fun->atom());
+        if (!out.append(fun->atom()))
+            return nullptr;
 
-    if (!out.append(src->chars(), src->length()))
-        return nullptr;
+        size_t nameEnd = begin + fun->atom()->length();
+        Rooted<JSFlatString*> src(cx, source->substring(cx, nameEnd, end));
+        if (!AppendUseStrictSource(cx, fun, src, out))
+            return nullptr;
+    } else {
+        Rooted<JSFlatString*> src(cx, source->substring(cx, begin, end));
+        if (!src)
+            return nullptr;
+        if (!out.append(src->chars(), src->length()))
+            return nullptr;
+    }
 
     return out.finishString();
 }
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -1562,81 +1562,81 @@ GenerateLIR(MIRGenerator *mir)
         IonSpewPass("Generate LIR");
 
         if (mir->shouldCancel("Generate LIR"))
             return nullptr;
     }
 
     AllocationIntegrityState integrity(*lir);
 
-    TraceLogStartEvent(logger, TraceLogger::RegisterAllocation);
-
-    switch (mir->optimizationInfo().registerAllocator()) {
-      case RegisterAllocator_LSRA: {
+    {
+        AutoTraceLog log(logger, TraceLogger::RegisterAllocation);
+
+        switch (mir->optimizationInfo().registerAllocator()) {
+          case RegisterAllocator_LSRA: {
 #ifdef DEBUG
-        if (!integrity.record())
-            return nullptr;
+            if (!integrity.record())
+                return nullptr;
 #endif
 
-        LinearScanAllocator regalloc(mir, &lirgen, *lir);
-        if (!regalloc.go())
-            return nullptr;
+            LinearScanAllocator regalloc(mir, &lirgen, *lir);
+            if (!regalloc.go())
+                return nullptr;
 
 #ifdef DEBUG
-        if (!integrity.check(false))
-            return nullptr;
+            if (!integrity.check(false))
+                return nullptr;
 #endif
 
-        IonSpewPass("Allocate Registers [LSRA]", &regalloc);
-        break;
-      }
-
-      case RegisterAllocator_Backtracking: {
+            IonSpewPass("Allocate Registers [LSRA]", &regalloc);
+            break;
+          }
+
+          case RegisterAllocator_Backtracking: {
 #ifdef DEBUG
-        if (!integrity.record())
-            return nullptr;
+            if (!integrity.record())
+                return nullptr;
 #endif
 
-        BacktrackingAllocator regalloc(mir, &lirgen, *lir);
-        if (!regalloc.go())
-            return nullptr;
+            BacktrackingAllocator regalloc(mir, &lirgen, *lir);
+            if (!regalloc.go())
+                return nullptr;
 
 #ifdef DEBUG
-        if (!integrity.check(false))
-            return nullptr;
+            if (!integrity.check(false))
+                return nullptr;
 #endif
 
-        IonSpewPass("Allocate Registers [Backtracking]");
-        break;
-      }
-
-      case RegisterAllocator_Stupid: {
-        // Use the integrity checker to populate safepoint information, so
-        // run it in all builds.
-        if (!integrity.record())
+            IonSpewPass("Allocate Registers [Backtracking]");
+            break;
+          }
+
+          case RegisterAllocator_Stupid: {
+            // Use the integrity checker to populate safepoint information, so
+            // run it in all builds.
+            if (!integrity.record())
+                return nullptr;
+
+            StupidAllocator regalloc(mir, &lirgen, *lir);
+            if (!regalloc.go())
+                return nullptr;
+            if (!integrity.check(true))
+                return nullptr;
+            IonSpewPass("Allocate Registers [Stupid]");
+            break;
+          }
+
+          default:
+            MOZ_ASSUME_UNREACHABLE("Bad regalloc");
+        }
+
+        if (mir->shouldCancel("Allocate Registers"))
             return nullptr;
-
-        StupidAllocator regalloc(mir, &lirgen, *lir);
-        if (!regalloc.go())
-            return nullptr;
-        if (!integrity.check(true))
-            return nullptr;
-        IonSpewPass("Allocate Registers [Stupid]");
-        break;
-      }
-
-      default:
-        MOZ_ASSUME_UNREACHABLE("Bad regalloc");
     }
 
-    if (mir->shouldCancel("Allocate Registers"))
-        return nullptr;
-
-    TraceLogStopEvent(logger, TraceLogger::RegisterAllocation);
-
     {
         AutoTraceLog log(logger, TraceLogger::UnsplitEdges);
         // Now that all optimization and register allocation is done, re-introduce
         // critical edges to avoid unnecessary jumps.
         if (!UnsplitEdges(lir))
             return nullptr;
         IonSpewPass("Unsplit Critical Edges");
         AssertBasicGraphCoherency(graph);
--- a/js/src/vm/String-inl.h
+++ b/js/src/vm/String-inl.h
@@ -82,17 +82,17 @@ JSString::validateLength(js::ThreadSafeC
     }
 
     return true;
 }
 
 MOZ_ALWAYS_INLINE void
 JSRope::init(js::ThreadSafeContext *cx, JSString *left, JSString *right, size_t length)
 {
-    d.lengthAndFlags = buildLengthAndFlags(length, ROPE_FLAGS);
+    d.u0.lengthAndFlags = buildLengthAndFlags(length, ROPE_FLAGS);
     d.u1.left = left;
     d.s.u2.right = right;
     js::StringWriteBarrierPost(cx, &d.u1.left);
     js::StringWriteBarrierPost(cx, &d.s.u2.right);
 }
 
 template <js::AllowGC allowGC>
 MOZ_ALWAYS_INLINE JSRope *
@@ -117,17 +117,17 @@ JSRope::markChildren(JSTracer *trc)
     js::gc::MarkStringUnbarriered(trc, &d.s.u2.right, "right child");
 }
 
 MOZ_ALWAYS_INLINE void
 JSDependentString::init(js::ThreadSafeContext *cx, JSLinearString *base, const jschar *chars,
                         size_t length)
 {
     JS_ASSERT(!js::IsPoisonedPtr(base));
-    d.lengthAndFlags = buildLengthAndFlags(length, DEPENDENT_FLAGS);
+    d.u0.lengthAndFlags = buildLengthAndFlags(length, DEPENDENT_FLAGS);
     d.u1.chars = chars;
     d.s.u2.base = base;
     js::StringWriteBarrierPost(cx, reinterpret_cast<JSString **>(&d.s.u2.base));
 }
 
 MOZ_ALWAYS_INLINE JSLinearString *
 JSDependentString::new_(js::ExclusiveContext *cx,
                         JSLinearString *baseArg, const jschar *chars, size_t length)
@@ -180,17 +180,17 @@ JSString::markBase(JSTracer *trc)
 {
     JS_ASSERT(hasBase());
     js::gc::MarkStringUnbarriered(trc, &d.s.u2.base, "base");
 }
 
 MOZ_ALWAYS_INLINE void
 JSFlatString::init(const jschar *chars, size_t length)
 {
-    d.lengthAndFlags = buildLengthAndFlags(length, FIXED_FLAGS);
+    d.u0.lengthAndFlags = buildLengthAndFlags(length, FIXED_FLAGS);
     d.u1.chars = chars;
 }
 
 template <js::AllowGC allowGC>
 MOZ_ALWAYS_INLINE JSFlatString *
 JSFlatString::new_(js::ThreadSafeContext *cx, const jschar *chars, size_t length)
 {
     JS_ASSERT(chars[length] == jschar(0));
@@ -224,42 +224,42 @@ MOZ_ALWAYS_INLINE JSInlineString *
 JSInlineString::new_(js::ThreadSafeContext *cx)
 {
     return (JSInlineString *)js_NewGCString<allowGC>(cx);
 }
 
 MOZ_ALWAYS_INLINE jschar *
 JSInlineString::init(size_t length)
 {
-    d.lengthAndFlags = buildLengthAndFlags(length, FIXED_FLAGS);
+    d.u0.lengthAndFlags = buildLengthAndFlags(length, FIXED_FLAGS);
     d.u1.chars = d.inlineStorage;
     JS_ASSERT(lengthFits(length) || (isFatInline() && JSFatInlineString::lengthFits(length)));
     return d.inlineStorage;
 }
 
 MOZ_ALWAYS_INLINE void
 JSInlineString::resetLength(size_t length)
 {
-    d.lengthAndFlags = buildLengthAndFlags(length, FIXED_FLAGS);
+    d.u0.lengthAndFlags = buildLengthAndFlags(length, FIXED_FLAGS);
     JS_ASSERT(lengthFits(length) || (isFatInline() && JSFatInlineString::lengthFits(length)));
 }
 
 template <js::AllowGC allowGC>
 MOZ_ALWAYS_INLINE JSFatInlineString *
 JSFatInlineString::new_(js::ThreadSafeContext *cx)
 {
     return js_NewGCFatInlineString<allowGC>(cx);
 }
 
 MOZ_ALWAYS_INLINE void
 JSExternalString::init(const jschar *chars, size_t length, const JSStringFinalizer *fin)
 {
     JS_ASSERT(fin);
     JS_ASSERT(fin->finalize);
-    d.lengthAndFlags = buildLengthAndFlags(length, FIXED_FLAGS);
+    d.u0.lengthAndFlags = buildLengthAndFlags(length, FIXED_FLAGS);
     d.u1.chars = chars;
     d.s.u2.externalFinalizer = fin;
 }
 
 MOZ_ALWAYS_INLINE JSExternalString *
 JSExternalString::new_(JSContext *cx, const jschar *chars, size_t length,
                        const JSStringFinalizer *fin)
 {
--- a/js/src/vm/String.cpp
+++ b/js/src/vm/String.cpp
@@ -226,18 +226,17 @@ JSRope::flattenInternal(ExclusiveContext
      * Perform a depth-first dag traversal, splatting each node's characters
      * into a contiguous buffer. Visit each rope node three times:
      *   1. record position in the buffer and recurse into left child;
      *   2. recurse into the right child;
      *   3. transform the node into a dependent string.
      * To avoid maintaining a stack, tree nodes are mutated to indicate how many
      * times they have been visited. Since ropes can be dags, a node may be
      * encountered multiple times during traversal. However, step 3 above leaves
-     * a valid dependent string, so everything works out. This algorithm is
-     * homomorphic to marking code.
+     * a valid dependent string, so everything works out.
      *
      * While ropes avoid all sorts of quadratic cases with string
      * concatenation, they can't help when ropes are immediately flattened.
      * One idiomatic case that we'd like to keep linear (and has traditionally
      * been linear in SM and other JS engines) is:
      *
      *   while (...) {
      *     s += ...
@@ -255,52 +254,60 @@ JSRope::flattenInternal(ExclusiveContext
      * N.B. This optimization can create chains of dependent strings.
      */
     const size_t wholeLength = length();
     size_t wholeCapacity;
     jschar *wholeChars;
     JSString *str = this;
     jschar *pos;
 
+    /*
+     * JSString::flattenData is a tagged pointer to the parent node.
+     * The tag indicates what to do when we return to the parent.
+     */
+    static const uintptr_t Tag_Mask = 0x3;
+    static const uintptr_t Tag_FinishNode = 0x0;
+    static const uintptr_t Tag_VisitRightChild = 0x1;
+
     /* Find the left most string, containing the first string. */
     JSRope *leftMostRope = this;
     while (leftMostRope->leftChild()->isRope())
         leftMostRope = &leftMostRope->leftChild()->asRope();
 
     if (leftMostRope->leftChild()->isExtensible()) {
         JSExtensibleString &left = leftMostRope->leftChild()->asExtensible();
         size_t capacity = left.capacity();
         if (capacity >= wholeLength) {
             /*
              * Simulate a left-most traversal from the root to leftMost->leftChild()
              * via first_visit_node
              */
+            JS_ASSERT(str->isRope());
             while (str != leftMostRope) {
-                JS_ASSERT(str->isRope());
                 if (b == WithIncrementalBarrier) {
                     JSString::writeBarrierPre(str->d.u1.left);
                     JSString::writeBarrierPre(str->d.s.u2.right);
                 }
                 JSString *child = str->d.u1.left;
+                JS_ASSERT(child->isRope());
                 str->d.u1.chars = left.chars();
-                child->d.s.u3.parent = str;
-                child->d.lengthAndFlags = 0x200;
+                child->d.u0.flattenData = uintptr_t(str) | Tag_VisitRightChild;
                 str = child;
             }
             if (b == WithIncrementalBarrier) {
                 JSString::writeBarrierPre(str->d.u1.left);
                 JSString::writeBarrierPre(str->d.s.u2.right);
             }
             str->d.u1.chars = left.chars();
             wholeCapacity = capacity;
             wholeChars = const_cast<jschar *>(left.chars());
-            size_t bits = left.d.lengthAndFlags;
+            size_t bits = left.d.u0.lengthAndFlags;
             pos = wholeChars + (bits >> LENGTH_SHIFT);
             JS_STATIC_ASSERT(!(EXTENSIBLE_FLAGS & DEPENDENT_FLAGS));
-            left.d.lengthAndFlags = bits ^ (EXTENSIBLE_FLAGS | DEPENDENT_FLAGS);
+            left.d.u0.lengthAndFlags = bits ^ (EXTENSIBLE_FLAGS | DEPENDENT_FLAGS);
             left.d.s.u2.base = (JSLinearString *)this;  /* will be true on exit */
             StringWriteBarrierPostRemove(maybecx, &left.d.u1.left);
             StringWriteBarrierPost(maybecx, (JSString **)&left.d.s.u2.base);
             goto visit_right_child;
         }
     }
 
     if (!AllocChars(maybecx, wholeLength, &wholeChars, &wholeCapacity))
@@ -312,56 +319,56 @@ JSRope::flattenInternal(ExclusiveContext
             JSString::writeBarrierPre(str->d.u1.left);
             JSString::writeBarrierPre(str->d.s.u2.right);
         }
 
         JSString &left = *str->d.u1.left;
         str->d.u1.chars = pos;
         StringWriteBarrierPostRemove(maybecx, &str->d.u1.left);
         if (left.isRope()) {
-            left.d.s.u3.parent = str;          /* Return to this when 'left' done, */
-            left.d.lengthAndFlags = 0x200;     /* but goto visit_right_child. */
+            /* Return to this node when 'left' done, then goto visit_right_child. */
+            left.d.u0.flattenData = uintptr_t(str) | Tag_VisitRightChild;
             str = &left;
             goto first_visit_node;
         }
         size_t len = left.length();
         PodCopy(pos, left.d.u1.chars, len);
         pos += len;
     }
     visit_right_child: {
         JSString &right = *str->d.s.u2.right;
         if (right.isRope()) {
-            right.d.s.u3.parent = str;         /* Return to this node when 'right' done, */
-            right.d.lengthAndFlags = 0x300;    /* but goto finish_node. */
+            /* Return to this node when 'right' done, then goto finish_node. */
+            right.d.u0.flattenData = uintptr_t(str) | Tag_FinishNode;
             str = &right;
             goto first_visit_node;
         }
         size_t len = right.length();
         PodCopy(pos, right.d.u1.chars, len);
         pos += len;
     }
     finish_node: {
         if (str == this) {
             JS_ASSERT(pos == wholeChars + wholeLength);
             *pos = '\0';
-            str->d.lengthAndFlags = buildLengthAndFlags(wholeLength, EXTENSIBLE_FLAGS);
+            str->d.u0.lengthAndFlags = buildLengthAndFlags(wholeLength, EXTENSIBLE_FLAGS);
             str->d.u1.chars = wholeChars;
             str->d.s.u2.capacity = wholeCapacity;
             StringWriteBarrierPostRemove(maybecx, &str->d.u1.left);
             StringWriteBarrierPostRemove(maybecx, &str->d.s.u2.right);
             return &this->asFlat();
         }
-        size_t progress = str->d.lengthAndFlags;
-        str->d.lengthAndFlags = buildLengthAndFlags(pos - str->d.u1.chars, DEPENDENT_FLAGS);
+        uintptr_t flattenData = str->d.u0.flattenData;
+        str->d.u0.lengthAndFlags = buildLengthAndFlags(pos - str->d.u1.chars, DEPENDENT_FLAGS);
         str->d.s.u2.base = (JSLinearString *)this;       /* will be true on exit */
         StringWriteBarrierPost(maybecx, (JSString **)&str->d.s.u2.base);
-        str = str->d.s.u3.parent;
-        if (progress == 0x200)
+        str = (JSString *)(flattenData & ~Tag_Mask);
+        if ((flattenData & Tag_Mask) == Tag_VisitRightChild)
             goto visit_right_child;
-        JS_ASSERT(progress == 0x300);
+        JS_ASSERT((flattenData & Tag_Mask) == Tag_FinishNode);
         goto finish_node;
     }
 }
 
 JSFlatString *
 JSRope::flatten(ExclusiveContext *maybecx)
 {
 #if JSGC_INCREMENTAL
@@ -460,17 +467,17 @@ JSDependentString::undepend(ExclusiveCon
     PodCopy(s, chars(), n);
     s[n] = 0;
     d.u1.chars = s;
 
     /*
      * Transform *this into an undepended string so 'base' will remain rooted
      * for the benefit of any other dependent string that depends on *this.
      */
-    d.lengthAndFlags = buildLengthAndFlags(n, UNDEPENDED_FLAGS);
+    d.u0.lengthAndFlags = buildLengthAndFlags(n, UNDEPENDED_FLAGS);
 
     return &this->asFlat();
 }
 
 bool
 JSFlatString::isIndexSlow(uint32_t *indexp) const
 {
     const jschar *s = charsZ();
--- a/js/src/vm/String.h
+++ b/js/src/vm/String.h
@@ -131,34 +131,33 @@ static const size_t UINT32_CHAR_BUFFER_L
 class JSString : public js::gc::BarrieredCell<JSString>
 {
   protected:
     static const size_t NUM_INLINE_CHARS = 2 * sizeof(void *) / sizeof(jschar);
 
     /* Fields only apply to string types commented on the right. */
     struct Data
     {
-        size_t                     lengthAndFlags;      /* JSString */
+        union {
+            size_t                 lengthAndFlags;      /* JSString */
+            uintptr_t              flattenData;         /* JSRope (temporary while flattening) */
+        } u0;
         union {
             const jschar           *chars;              /* JSLinearString */
             JSString               *left;               /* JSRope */
         } u1;
         union {
             jschar                 inlineStorage[NUM_INLINE_CHARS]; /* JS(Inline|FatInline)String */
             struct {
                 union {
                     JSLinearString *base;               /* JS(Dependent|Undepended)String */
                     JSString       *right;              /* JSRope */
                     size_t         capacity;            /* JSFlatString (extensible) */
                     const JSStringFinalizer *externalFinalizer;/* JSExternalString */
                 } u2;
-                union {
-                    JSString       *parent;             /* JSRope (temporary) */
-                    size_t         reserved;            /* may use for bug 615290 */
-                } u3;
             } s;
         };
     } d;
 
   public:
     /* Flags exposed only for jits */
 
     /*
@@ -247,22 +246,22 @@ class JSString : public js::gc::Barriere
     /* Avoid lame compile errors in JSRope::flatten */
     friend class JSRope;
 
   public:
     /* All strings have length. */
 
     MOZ_ALWAYS_INLINE
     size_t length() const {
-        return d.lengthAndFlags >> LENGTH_SHIFT;
+        return d.u0.lengthAndFlags >> LENGTH_SHIFT;
     }
 
     MOZ_ALWAYS_INLINE
     bool empty() const {
-        return d.lengthAndFlags <= FLAGS_MASK;
+        return d.u0.lengthAndFlags <= FLAGS_MASK;
     }
 
     /*
      * All strings have a fallible operation to get an array of chars.
      * getCharsZ additionally ensures the array is null terminated.
      */
 
     inline const jschar *getChars(js::ExclusiveContext *cx);
@@ -294,17 +293,17 @@ class JSString : public js::gc::Barriere
     static bool ensureLinear(js::ExclusiveContext *cx, JSString *str) {
         return str->ensureLinear(cx) != nullptr;
     }
 
     /* Type query and debug-checked casts */
 
     MOZ_ALWAYS_INLINE
     bool isRope() const {
-        return (d.lengthAndFlags & FLAGS_MASK) == ROPE_FLAGS;
+        return (d.u0.lengthAndFlags & FLAGS_MASK) == ROPE_FLAGS;
     }
 
     MOZ_ALWAYS_INLINE
     JSRope &asRope() const {
         JS_ASSERT(isRope());
         return *(JSRope *)this;
     }
 
@@ -316,17 +315,17 @@ class JSString : public js::gc::Barriere
     MOZ_ALWAYS_INLINE
     JSLinearString &asLinear() const {
         JS_ASSERT(JSString::isLinear());
         return *(JSLinearString *)this;
     }
 
     MOZ_ALWAYS_INLINE
     bool isDependent() const {
-        return (d.lengthAndFlags & FLAGS_MASK) == DEPENDENT_FLAGS;
+        return (d.u0.lengthAndFlags & FLAGS_MASK) == DEPENDENT_FLAGS;
     }
 
     MOZ_ALWAYS_INLINE
     JSDependentString &asDependent() const {
         JS_ASSERT(isDependent());
         return *(JSDependentString *)this;
     }
 
@@ -338,17 +337,17 @@ class JSString : public js::gc::Barriere
     MOZ_ALWAYS_INLINE
     JSFlatString &asFlat() const {
         JS_ASSERT(isFlat());
         return *(JSFlatString *)this;
     }
 
     MOZ_ALWAYS_INLINE
     bool isExtensible() const {
-        return (d.lengthAndFlags & FLAGS_MASK) == EXTENSIBLE_FLAGS;
+        return (d.u0.lengthAndFlags & FLAGS_MASK) == EXTENSIBLE_FLAGS;
     }
 
     MOZ_ALWAYS_INLINE
     JSExtensibleString &asExtensible() const {
         JS_ASSERT(isExtensible());
         return *(JSExtensibleString *)this;
     }
 
@@ -371,40 +370,40 @@ class JSString : public js::gc::Barriere
     MOZ_ALWAYS_INLINE
     JSExternalString &asExternal() const {
         JS_ASSERT(isExternal());
         return *(JSExternalString *)this;
     }
 
     MOZ_ALWAYS_INLINE
     bool isUndepended() const {
-        return (d.lengthAndFlags & FLAGS_MASK) == UNDEPENDED_FLAGS;
+        return (d.u0.lengthAndFlags & FLAGS_MASK) == UNDEPENDED_FLAGS;
     }
 
     MOZ_ALWAYS_INLINE
     bool isAtom() const {
-        return d.lengthAndFlags & ATOM_BIT;
+        return d.u0.lengthAndFlags & ATOM_BIT;
     }
 
     MOZ_ALWAYS_INLINE
     bool isPermanentAtom() const {
-        return (d.lengthAndFlags & FLAGS_MASK) == PERMANENT_ATOM_FLAGS;
+        return (d.u0.lengthAndFlags & FLAGS_MASK) == PERMANENT_ATOM_FLAGS;
     }
 
     MOZ_ALWAYS_INLINE
     JSAtom &asAtom() const {
         JS_ASSERT(isAtom());
         return *(JSAtom *)this;
     }
 
     /* Only called by the GC for dependent or undepended strings. */
 
     inline bool hasBase() const {
         JS_STATIC_ASSERT((DEPENDENT_FLAGS | JS_BIT(1)) == UNDEPENDED_FLAGS);
-        return d.lengthAndFlags & HAS_BASE_BIT;
+        return d.u0.lengthAndFlags & HAS_BASE_BIT;
     }
 
     inline JSLinearString *base() const;
 
     inline void markBase(JSTracer *trc);
 
     /* Only called by the GC for strings with the FINALIZE_STRING kind. */
 
@@ -412,17 +411,17 @@ class JSString : public js::gc::Barriere
 
     /* Gets the number of bytes that the chars take on the heap. */
 
     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf);
 
     /* Offsets for direct field from jit code. */
 
     static size_t offsetOfLengthAndFlags() {
-        return offsetof(JSString, d.lengthAndFlags);
+        return offsetof(JSString, d.u0.lengthAndFlags);
     }
 
     static size_t offsetOfChars() {
         return offsetof(JSString, d.u1.chars);
     }
 
     js::gc::AllocKind getAllocKind() const { return tenuredGetAllocKind(); }
 
@@ -589,21 +588,21 @@ class JSFlatString : public JSLinearStri
      */
     inline js::PropertyName *toPropertyName(JSContext *cx);
 
     /*
      * Once a JSFlatString sub-class has been added to the atom state, this
      * operation changes the string to the JSAtom type, in place.
      */
     MOZ_ALWAYS_INLINE JSAtom *morphAtomizedStringIntoAtom() {
-        d.lengthAndFlags = buildLengthAndFlags(length(), ATOM_BIT);
+        d.u0.lengthAndFlags = buildLengthAndFlags(length(), ATOM_BIT);
         return &asAtom();
     }
     MOZ_ALWAYS_INLINE JSAtom *morphAtomizedStringIntoPermanentAtom() {
-        d.lengthAndFlags = buildLengthAndFlags(length(), PERMANENT_ATOM_FLAGS);
+        d.u0.lengthAndFlags = buildLengthAndFlags(length(), PERMANENT_ATOM_FLAGS);
         return &asAtom();
     }
 
     inline void finalize(js::FreeOp *fop);
 };
 
 JS_STATIC_ASSERT(sizeof(JSFlatString) == sizeof(JSString));
 
@@ -735,23 +734,23 @@ class JSAtom : public JSFlatString
   public:
     /* Returns the PropertyName for this.  isIndex() must be false. */
     inline js::PropertyName *asPropertyName();
 
     inline void finalize(js::FreeOp *fop);
 
     MOZ_ALWAYS_INLINE
     bool isPermanent() const {
-        return d.lengthAndFlags & PERMANENT_BIT;
+        return d.u0.lengthAndFlags & PERMANENT_BIT;
     }
 
     // Transform this atom into a permanent atom. This is only done during
     // initialization of the runtime.
     MOZ_ALWAYS_INLINE void morphIntoPermanentAtom() {
-        d.lengthAndFlags = buildLengthAndFlags(length(), PERMANENT_ATOM_FLAGS);
+        d.u0.lengthAndFlags = buildLengthAndFlags(length(), PERMANENT_ATOM_FLAGS);
     }
 
 #ifdef DEBUG
     void dump();
 #endif
 };
 
 JS_STATIC_ASSERT(sizeof(JSAtom) == sizeof(JSString));
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/disabled-1-ref.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Bug 1007278: test button "disabled" text style</title>
+<style>
+  button {
+    color: GrayText;
+    border-width: 0;
+    background: transparent;
+  }
+</style>
+</head>
+<body>
+  <button>Some text</button>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/disabled-1.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Bug 1007278: test button "disabled" text style</title>
+<style>
+  button {
+    border-width: 0;
+    background: transparent;
+  }
+</style>
+</head>
+<body>
+  <button disabled>Some text</button>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/disabled-2-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Bug 1007278: test all types of buttons look similar when disabled</title>
+</head>
+<body>
+  <button>Some text</button>
+  <button>Some text</button>
+  <button>Reset</button>
+  <button>Submit Query</button>
+  <br>
+  <button disabled>Some text</button>
+  <button disabled>Some text</button>
+  <button disabled>Reset</button>
+  <button disabled>Submit Query</button>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/disabled-2.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Bug 1007278: test all types of buttons look similar when disabled</title>
+</head>
+<body>
+  <button>Some text</button>
+  <input type="button" value="Some text">
+  <input type="reset">
+  <input type="submit">
+  <br>
+  <button disabled>Some text</button>
+  <input disabled type="button" value="Some text">
+  <input disabled type="reset">
+  <input disabled type="submit">
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/disabled-3-notref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Bug 1007278: check disabled and non-disabled buttons look different</title>
+</head>
+<body>
+  <button disabled>Some text</button>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/disabled-3.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Bug 1007278: check disabled and non-disabled buttons look different</title>
+</head>
+<body>
+  <button>Some text</button>
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/disabled-4-notref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Bug 1007278: check disabled and non-disabled buttons look different</title>
+</head>
+<body>
+  <input disabled type="button" value="Some text">
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/disabled-4.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Bug 1007278: check disabled and non-disabled buttons look different</title>
+</head>
+<body>
+  <input type="button" value="Some text">
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/disabled-5-notref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Bug 1007278: check disabled and non-disabled buttons look different</title>
+</head>
+<body>
+  <input disabled type="reset">
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/disabled-5.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Bug 1007278: check disabled and non-disabled buttons look different</title>
+</head>
+<body>
+  <input type="reset">
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/disabled-6-notref.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Bug 1007278: check disabled and non-disabled buttons look different</title>
+</head>
+<body>
+  <input disabled type="submit">
+</body>
+</html>
new file mode 100644
--- /dev/null
+++ b/layout/reftests/forms/button/disabled-6.html
@@ -0,0 +1,9 @@
+<!DOCTYPE html>
+<html>
+<head>
+<title>Bug 1007278: check disabled and non-disabled buttons look different</title>
+</head>
+<body>
+  <input type="submit">
+</body>
+</html>
--- a/layout/reftests/forms/button/reftest.list
+++ b/layout/reftests/forms/button/reftest.list
@@ -12,8 +12,20 @@ fuzzy-if(B2G||Android,125,20) == percent
 fuzzy-if(B2G||Android,125,80) == percent-width-child-2.html  percent-width-child-2-ref.html
 
 == vertical-centering.html vertical-centering-ref.html
 
 != line-height-button-0.5.html line-height-button-1.0.html
 != line-height-button-1.5.html line-height-button-1.0.html
 != line-height-input-0.5.html line-height-input-1.0.html
 != line-height-input-1.5.html line-height-input-1.0.html
+
+# Looks like Android and B2G change the text color, but to something slightly
+# different from ColorGray
+fails-if(Android||B2G) == disabled-1.html disabled-1-ref.html
+# While disabled buttons don't look like non-disabled buttons, <button disabled>
+# is different from other disabled buttons for B2G ICS Emulator (see bug 1009714)
+fails-if(B2G) == disabled-2.html disabled-2-ref.html
+
+!= disabled-3.html disabled-3-notref.html
+!= disabled-4.html disabled-4-notref.html
+!= disabled-5.html disabled-5-notref.html
+!= disabled-6.html disabled-6-notref.html
--- a/layout/style/forms.css
+++ b/layout/style/forms.css
@@ -659,16 +659,17 @@ input[type="submit"]:disabled:active,
 input[type="submit"]:disabled {
   /* The sum of border-top, border-bottom, padding-top, padding-bottom
      must be the same here and for text inputs */
   padding: 0px 6px 0px 6px;
   border: 2px outset ButtonFace;
   cursor: inherit; 
 }
 
+button:disabled:active, button:disabled,
 input[type="reset"]:disabled:active,
 input[type="reset"]:disabled,
 input[type="button"]:disabled:active,
 input[type="button"]:disabled,
 select:disabled > button,
 select:disabled > button,
 input[type="submit"]:disabled:active,
 input[type="submit"]:disabled {
--- a/mach
+++ b/mach
@@ -1,9 +1,9 @@
-#!/usr/bin/env python2.7
+#!/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/.
 
 from __future__ import print_function, unicode_literals
 
 import os
 import sys
--- a/netwerk/protocol/http/Http2Session.cpp
+++ b/netwerk/protocol/http/Http2Session.cpp
@@ -121,16 +121,29 @@ Http2Session::Http2Session(nsAHttpTransa
 
     if (!aHttpTransaction->IsNullTransaction())
       AddStream(aHttpTransaction, firstPriority);
     mLastDataReadEpoch = mLastReadEpoch;
 
     mPingThreshold = gHttpHandler->SpdyPingThreshold();
 }
 
+// Copy the 32 bit number into the destination, using network byte order
+// in the destination.
+template<typename charType> static void
+CopyAsNetwork32(charType dest,   // where to store it
+                uint32_t number) // the 32 bit number in native format
+{
+  number = PR_htonl(number);
+  memcpy(dest, &number, sizeof(number));
+}
+
+template void CopyAsNetwork32(char *dest, uint32_t number);
+template void CopyAsNetwork32(uint8_t *dest, uint32_t number);
+
 PLDHashOperator
 Http2Session::ShutdownEnumerator(nsAHttpTransaction *key,
                                  nsAutoPtr<Http2Stream> &stream,
                                  void *closure)
 {
   Http2Session *self = static_cast<Http2Session *>(closure);
 
   // On a clean server hangup the server sets the GoAwayID to be the ID of
@@ -596,22 +609,21 @@ template<typename charType> void
 Http2Session::CreateFrameHeader(charType dest, uint16_t frameLength,
                                 uint8_t frameType, uint8_t frameFlags,
                                 uint32_t streamID)
 {
   MOZ_ASSERT(frameLength <= kMaxFrameData, "framelength too large");
   MOZ_ASSERT(!(streamID & 0x80000000));
 
   frameLength = PR_htons(frameLength);
-  streamID = PR_htonl(streamID);
 
   memcpy(dest, &frameLength, 2);
   dest[2] = frameType;
   dest[3] = frameFlags;
-  memcpy(dest + 4, &streamID, 4);
+  CopyAsNetwork32(dest + 4, streamID);
 }
 
 char *
 Http2Session::EnsureOutputBuffer(uint32_t spaceNeeded)
 {
   // this is an infallible allocation (if an allocation is
   // needed, which is probably isn't)
   EnsureBuffer(mOutputQueueBuffer, mOutputQueueUsed + spaceNeeded,
@@ -705,17 +717,17 @@ Http2Session::GeneratePriority(uint32_t 
   MOZ_ASSERT(PR_GetCurrentThread() == gSocketThread);
   LOG3(("Http2Session::GeneratePriority %p %X %X\n",
         this, aID, aPriorityWeight));
 
   char *packet = EnsureOutputBuffer(13);
   mOutputQueueUsed += 13;
 
   CreateFrameHeader(packet, 5, FRAME_TYPE_PRIORITY, 0, aID);
-  memset(packet + 8, 0, 4);
+  CopyAsNetwork32(packet + 8, 0);
   memcpy(packet + 12, &aPriorityWeight, 1);
   LogIO(this, nullptr, "Generate Priority", packet, 13);
   FlushOutputQueue();
 }
 
 void
 Http2Session::GenerateRstStream(uint32_t aStatusCode, uint32_t aID)
 {
@@ -731,18 +743,17 @@ Http2Session::GenerateRstStream(uint32_t
   }
 
   LOG3(("Http2Session::GenerateRst %p 0x%X %d\n", this, aID, aStatusCode));
 
   char *packet = EnsureOutputBuffer(12);
   mOutputQueueUsed += 12;
   CreateFrameHeader(packet, 4, FRAME_TYPE_RST_STREAM, 0, aID);
 
-  aStatusCode = PR_htonl(aStatusCode);
-  memcpy(packet + 8, &aStatusCode, 4);
+  CopyAsNetwork32(packet + 8, aStatusCode);
 
   LogIO(this, nullptr, "Generate Reset", packet, 12);
   FlushOutputQueue();
 }
 
 void
 Http2Session::GenerateGoAway(uint32_t aStatusCode)
 {
@@ -750,22 +761,20 @@ Http2Session::GenerateGoAway(uint32_t aS
   LOG3(("Http2Session::GenerateGoAway %p code=%X\n", this, aStatusCode));
 
   char *packet = EnsureOutputBuffer(16);
   mOutputQueueUsed += 16;
 
   CreateFrameHeader(packet, 8, FRAME_TYPE_GOAWAY, 0, 0);
 
   // last-good-stream-id are bytes 8-11 reflecting pushes
-  uint32_t goAway = PR_htonl(mOutgoingGoAwayID);
-  memcpy(packet + 8, &goAway, 4);
+  CopyAsNetwork32(packet + 8, mOutgoingGoAwayID);
 
   // bytes 12-15 are the status code.
-  aStatusCode = PR_htonl(aStatusCode);
-  memcpy(packet + 12, &aStatusCode, 4);
+  CopyAsNetwork32(packet + 12, aStatusCode);
 
   LogIO(this, nullptr, "Generate GoAway", packet, 16);
   FlushOutputQueue();
 }
 
 // The Hello is comprised of 24 octets of magic, which are designed to
 // flush out silent but broken intermediaries, followed by a settings
 // frame which sets a small flow control window for pushes and a
@@ -807,18 +816,17 @@ Http2Session::SendHello()
     packet[8 + 5 * numberOfEntries] = SETTINGS_TYPE_MAX_CONCURRENT;
     // The value portion of the setting pair is already initialized to 0
     numberOfEntries++;
   }
 
   // Advertise the Push RWIN for the session, and on each new pull stream
   // send a window update with END_FLOW_CONTROL
   packet[8 + 5 * numberOfEntries] = SETTINGS_TYPE_INITIAL_WINDOW;
-  uint32_t rwin = PR_htonl(mPushAllowance);
-  memcpy(packet + 9 + 5 * numberOfEntries, &rwin, 4);
+  CopyAsNetwork32(packet + 9 + 5 * numberOfEntries, mPushAllowance);
   numberOfEntries++;
 
   // Explicitly signal that we do NOT support compressed data frames, even
   // though the default is to not support anyway.
   packet[8 + 5 * numberOfEntries] = SETTINGS_TYPE_COMPRESS_DATA;
   // The value portion of the setting pair is already initialized to 0
   numberOfEntries++;
 
@@ -830,26 +838,25 @@ Http2Session::SendHello()
   LogIO(this, nullptr, "Generate Settings", packet, 8 + dataLen);
 
   // now bump the local session window from 64KB
   uint32_t sessionWindowBump = ASpdySession::kInitialRwin - kDefaultRwin;
   if (kDefaultRwin >= ASpdySession::kInitialRwin)
     goto sendHello_complete;
 
   // send a window update for the session (Stream 0) for something large
-  sessionWindowBump = PR_htonl(sessionWindowBump);
   mLocalSessionWindow = ASpdySession::kInitialRwin;
 
   packet = mOutputQueueBuffer.get() + mOutputQueueUsed;
   CreateFrameHeader(packet, 4, FRAME_TYPE_WINDOW_UPDATE, 0, 0);
   mOutputQueueUsed += 12;
-  memcpy(packet + 8, &sessionWindowBump, 4);
+  CopyAsNetwork32(packet + 8, sessionWindowBump);
 
   LOG3(("Session Window increase at start of session %p %u\n",
-        this, PR_ntohl(sessionWindowBump)));
+        this, sessionWindowBump));
   LogIO(this, nullptr, "Session Window Bump ", packet, 12);
 
 sendHello_complete:
   FlushOutputQueue();
 }
 
 // perform a bunch of integrity checks on the stream.
 // returns true if passed, false (plus LOG and ABORT) if failed.
@@ -2475,18 +2482,17 @@ Http2Session::UpdateLocalStreamWindow(Ht
   stream->IncrementClientReceiveWindow(toack);
 
   // room for this packet needs to be ensured before calling this function
   char *packet = mOutputQueueBuffer.get() + mOutputQueueUsed;
   mOutputQueueUsed += 12;
   MOZ_ASSERT(mOutputQueueUsed <= mOutputQueueSize);
 
   CreateFrameHeader(packet, 4, FRAME_TYPE_WINDOW_UPDATE, 0, stream->StreamID());
-  toack = PR_htonl(toack);
-  memcpy(packet + 8, &toack, 4);
+  CopyAsNetwork32(packet + 8, toack);
 
   LogIO(this, stream, "Stream Window Update", packet, 12);
   // dont flush here, this write can commonly be coalesced with a
   // session window update to immediately follow.
 }
 
 void
 Http2Session::UpdateLocalSessionWindow(uint32_t bytes)
@@ -2514,18 +2520,17 @@ Http2Session::UpdateLocalSessionWindow(u
   mLocalSessionWindow += toack;
 
   // room for this packet needs to be ensured before calling this function
   char *packet = mOutputQueueBuffer.get() + mOutputQueueUsed;
   mOutputQueueUsed += 12;
   MOZ_ASSERT(mOutputQueueUsed <= mOutputQueueSize);
 
   CreateFrameHeader(packet, 4, FRAME_TYPE_WINDOW_UPDATE, 0, 0);
-  toack = PR_htonl(toack);
-  memcpy(packet + 8, &toack, 4);
+  CopyAsNetwork32(packet + 8, toack);
 
   LogIO(this, nullptr, "Session Window Update", packet, 12);
   // dont flush here, this write can commonly be coalesced with others
 }
 
 void
 Http2Session::UpdateLocalRwin(Http2Stream *stream, uint32_t bytes)
 {
--- a/security/certverifier/OCSPCache.cpp
+++ b/security/certverifier/OCSPCache.cpp
@@ -1,11 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* Copyright 2013 Mozilla Foundation
+/* This code is made available to you under your choice of the following sets
+ * of licensing terms:
+ */
+/* 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/.
+ */
+/* Copyright 2013 Mozilla Contributors
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
--- a/security/certverifier/OCSPCache.h
+++ b/security/certverifier/OCSPCache.h
@@ -1,11 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* Copyright 2013 Mozilla Foundation
+/* This code is made available to you under your choice of the following sets
+ * of licensing terms:
+ */
+/* 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/.
+ */
+/* Copyright 2013 Mozilla Contributors
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
--- a/security/pkix/include/pkix/ScopedPtr.h
+++ b/security/pkix/include/pkix/ScopedPtr.h
@@ -1,11 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* Copyright 2013 Mozilla Foundation
+/* This code is made available to you under your choice of the following sets
+ * of licensing terms:
+ */
+/* 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/.
+ */
+/* Copyright 2013 Mozilla Contributors
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
--- a/security/pkix/include/pkix/bind.h
+++ b/security/pkix/include/pkix/bind.h
@@ -1,11 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* Copyright 2013 Mozilla Foundation
+/* This code is made available to you under your choice of the following sets
+ * of licensing terms:
+ */
+/* 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/.
+ */
+/* Copyright 2013 Mozilla Contributors
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
--- a/security/pkix/include/pkix/enumclass.h
+++ b/security/pkix/include/pkix/enumclass.h
@@ -1,11 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* Copyright 2013 Mozilla Foundation
+/* This code is made available to you under your choice of the following sets
+ * of licensing terms:
+ */
+/* 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/.
+ */
+/* Copyright 2013 Mozilla Contributors
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
--- a/security/pkix/include/pkix/nullptr.h
+++ b/security/pkix/include/pkix/nullptr.h
@@ -1,11 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* Copyright 2013 Mozilla Foundation
+/* This code is made available to you under your choice of the following sets
+ * of licensing terms:
+ */
+/* 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/.
+ */
+/* Copyright 2013 Mozilla Contributors
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
--- a/security/pkix/include/pkix/pkix.h
+++ b/security/pkix/include/pkix/pkix.h
@@ -1,11 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* Copyright 2013 Mozilla Foundation
+/* This code is made available to you under your choice of the following sets
+ * of licensing terms:
+ */
+/* 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/.
+ */
+/* Copyright 2013 Mozilla Contributors
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
--- a/security/pkix/include/pkix/pkixtypes.h
+++ b/security/pkix/include/pkix/pkixtypes.h
@@ -1,11 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* Copyright 2012 Mozilla Foundation
+/* This code is made available to you under your choice of the following sets
+ * of licensing terms:
+ */
+/* 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/.
+ */
+/* Copyright 2013 Mozilla Contributors
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
--- a/security/pkix/lib/pkixbind.cpp
+++ b/security/pkix/lib/pkixbind.cpp
@@ -1,11 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* Copyright 2013 Mozilla Foundation
+/* This code is made available to you under your choice of the following sets
+ * of licensing terms:
+ */
+/* 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/.
+ */
+/* Copyright 2013 Mozilla Contributors
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
--- a/security/pkix/lib/pkixbuild.cpp
+++ b/security/pkix/lib/pkixbuild.cpp
@@ -1,11 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* Copyright 2013 Mozilla Foundation
+/* This code is made available to you under your choice of the following sets
+ * of licensing terms:
+ */
+/* 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/.
+ */
+/* Copyright 2013 Mozilla Contributors
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
--- a/security/pkix/lib/pkixcheck.cpp
+++ b/security/pkix/lib/pkixcheck.cpp
@@ -1,11 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* Copyright 2013 Mozilla Foundation
+/* This code is made available to you under your choice of the following sets
+ * of licensing terms:
+ */
+/* 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/.
+ */
+/* Copyright 2013 Mozilla Contributors
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
--- a/security/pkix/lib/pkixcheck.h
+++ b/security/pkix/lib/pkixcheck.h
@@ -1,11 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* Copyright 2013 Mozilla Foundation
+/* This code is made available to you under your choice of the following sets
+ * of licensing terms:
+ */
+/* 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/.
+ */
+/* Copyright 2013 Mozilla Contributors
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
--- a/security/pkix/lib/pkixder.cpp
+++ b/security/pkix/lib/pkixder.cpp
@@ -1,11 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* Copyright 2013 Mozilla Foundation
+/* This code is made available to you under your choice of the following sets
+ * of licensing terms:
+ */
+/* 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/.
+ */
+/* Copyright 2013 Mozilla Contributors
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
--- a/security/pkix/lib/pkixder.h
+++ b/security/pkix/lib/pkixder.h
@@ -1,11 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* Copyright 2013 Mozilla Foundation
+/* This code is made available to you under your choice of the following sets
+ * of licensing terms:
+ */
+/* 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/.
+ */
+/* Copyright 2013 Mozilla Contributors
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
--- a/security/pkix/lib/pkixkey.cpp
+++ b/security/pkix/lib/pkixkey.cpp
@@ -1,11 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* Copyright 2013 Mozilla Foundation
+/* This code is made available to you under your choice of the following sets
+ * of licensing terms:
+ */
+/* 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/.
+ */
+/* Copyright 2013 Mozilla Contributors
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
--- a/security/pkix/lib/pkixocsp.cpp
+++ b/security/pkix/lib/pkixocsp.cpp
@@ -1,11 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* Copyright 2013 Mozilla Foundation
+/* This code is made available to you under your choice of the following sets
+ * of licensing terms:
+ */
+/* 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/.
+ */
+/* Copyright 2013 Mozilla Contributors
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
--- a/security/pkix/lib/pkixutil.h
+++ b/security/pkix/lib/pkixutil.h
@@ -1,11 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* Copyright 2013 Mozilla Foundation
+/* This code is made available to you under your choice of the following sets
+ * of licensing terms:
+ */
+/* 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/.
+ */
+/* Copyright 2013 Mozilla Contributors
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
--- a/security/pkix/test/gtest/nssgtest.cpp
+++ b/security/pkix/test/gtest/nssgtest.cpp
@@ -1,11 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* Copyright 2013 Mozilla Foundation
+/* This code is made available to you under your choice of the following sets
+ * of licensing terms:
+ */
+/* 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/.
+ */
+/* Copyright 2013 Mozilla Contributors
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
--- a/security/pkix/test/gtest/nssgtest.h
+++ b/security/pkix/test/gtest/nssgtest.h
@@ -1,11 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* Copyright 2013 Mozilla Foundation
+/* This code is made available to you under your choice of the following sets
+ * of licensing terms:
+ */
+/* 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/.
+ */
+/* Copyright 2013 Mozilla Contributors
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
--- a/security/pkix/test/gtest/pkixder_input_tests.cpp
+++ b/security/pkix/test/gtest/pkixder_input_tests.cpp
@@ -1,11 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* Copyright 2013 Mozilla Foundation
+/* This code is made available to you under your choice of the following sets
+ * of licensing terms:
+ */
+/* 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/.
+ */
+/* Copyright 2013 Mozilla Contributors
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
--- a/security/pkix/test/gtest/pkixder_pki_types_tests.cpp
+++ b/security/pkix/test/gtest/pkixder_pki_types_tests.cpp
@@ -1,11 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* Copyright 2013 Mozilla Foundation
+/* This code is made available to you under your choice of the following sets
+ * of licensing terms:
+ */
+/* 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/.
+ */
+/* Copyright 2013 Mozilla Contributors
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
--- a/security/pkix/test/gtest/pkixder_universal_types_tests.cpp
+++ b/security/pkix/test/gtest/pkixder_universal_types_tests.cpp
@@ -1,11 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* Copyright 2013 Mozilla Foundation
+/* This code is made available to you under your choice of the following sets
+ * of licensing terms:
+ */
+/* 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/.
+ */
+/* Copyright 2013 Mozilla Contributors
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
--- a/security/pkix/test/lib/moz.build
+++ b/security/pkix/test/lib/moz.build
@@ -1,10 +1,17 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
-# Copyright 2013 Mozilla Foundation
+# This code is made available to you under your choice of the following sets
+# of licensing terms:
+#
+# 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/.
+#
+# Copyright 2013 Mozilla Contributors
 #
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at
 #
 # http://www.apache.org/licenses/LICENSE-2.0
 #
 # Unless required by applicable law or agreed to in writing, software
--- a/security/pkix/test/lib/pkixtestutil.cpp
+++ b/security/pkix/test/lib/pkixtestutil.cpp
@@ -1,11 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* Copyright 2013 Mozilla Foundation
+/* This code is made available to you under your choice of the following sets
+ * of licensing terms:
+ */
+/* 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/.
+ */
+/* Copyright 2013 Mozilla Contributors
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
--- a/security/pkix/test/lib/pkixtestutil.h
+++ b/security/pkix/test/lib/pkixtestutil.h
@@ -1,11 +1,18 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
-/* Copyright 2013 Mozilla Foundation
+/* This code is made available to you under your choice of the following sets
+ * of licensing terms:
+ */
+/* 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/.
+ */
+/* Copyright 2013 Mozilla Contributors
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
  *
  *     http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
--- a/toolkit/identity/FirefoxAccounts.jsm
+++ b/toolkit/identity/FirefoxAccounts.jsm
@@ -146,16 +146,20 @@ FxAccountsService.prototype = {
 
     this.fxAccountsManager.getAssertion(rp.audience, options).then(
       data => {
         log.debug("got assertion for " + rp.audience + ": " + data);
         this.doLogin(aRPId, data);
       },
       error => {
         log.error("get assertion failed: " + JSON.stringify(error));
+        // Cancellation is passed through an error channel; here we reroute.
+        if (error.details && (error.details.error == "DIALOG_CLOSED_BY_USER")) {
+          return this.doCancel(aRPId);
+        }
         this.doError(aRPId, error);
       }
     );
   },
 
   /**
    * Invoked when a user wishes to logout of a site (for instance, when clicking
    * on an in-content logout button).
@@ -193,57 +197,57 @@ FxAccountsService.prototype = {
         this._rpFlows.delete(key);
       }
     }
   },
 
   doLogin: function doLogin(aRpCallerId, aAssertion) {
     let rp = this._rpFlows.get(aRpCallerId);
     if (!rp) {
-      log.warn("doLogin found no rp to go with callerId " + aRpCallerId + "\n");
+      log.warn("doLogin found no rp to go with callerId " + aRpCallerId);
       return;
     }
 
     rp.doLogin(aAssertion);
   },
 
   doLogout: function doLogout(aRpCallerId) {
     let rp = this._rpFlows.get(aRpCallerId);
     if (!rp) {
-      log.warn("doLogout found no rp to go with callerId " + aRpCallerId + "\n");
+      log.warn("doLogout found no rp to go with callerId " + aRpCallerId);
       return;
     }
 
     rp.doLogout();
   },
 
   doReady: function doReady(aRpCallerId) {
     let rp = this._rpFlows.get(aRpCallerId);
     if (!rp) {
-      log.warn("doReady found no rp to go with callerId " + aRpCallerId + "\n");
+      log.warn("doReady found no rp to go with callerId " + aRpCallerId);
       return;
     }
 
     rp.doReady();
   },
 
   doCancel: function doCancel(aRpCallerId) {
     let rp = this._rpFlows.get(aRpCallerId);
     if (!rp) {
-      log.warn("doCancel found no rp to go with callerId " + aRpCallerId + "\n");
+      log.warn("doCancel found no rp to go with callerId " + aRpCallerId);
       return;
     }
 
     rp.doCancel();
   },
 
   doError: function doError(aRpCallerId, aError) {
     let rp = this._rpFlows.get(aRpCallerId);
     if (!rp) {
-      log.warn("doCancel found no rp to go with callerId " + aRpCallerId + "\n");
+      log.warn("doError found no rp to go with callerId " + aRpCallerId);
       return;
     }
 
     rp.doError(aError);
   }
 };
 
 this.FirefoxAccounts = new FxAccountsService();
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/update/UpdaterHealthProvider.jsm
@@ -0,0 +1,69 @@
+/* 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/. */
+
+"use strict";
+
+this.EXPORTED_SYMBOLS = [
+  "UpdateProvider",
+];
+
+const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
+
+Cu.import("resource://gre/modules/Metrics.jsm", this);
+Cu.import("resource://gre/modules/Task.jsm", this);
+
+const DAILY_COUNTER_FIELD = {type: Metrics.Storage.FIELD_DAILY_COUNTER};
+const DAILY_DISCRETE_NUMERIC_FIELD = {type: Metrics.Storage.FIELD_DAILY_DISCRETE_NUMERIC};
+
+function UpdateMeasurement1() {
+  Metrics.Measurement.call(this);
+}
+
+UpdateMeasurement1.prototype = Object.freeze({
+  __proto__: Metrics.Measurement.prototype,
+
+  name: "update",
+  version: 1,
+
+  fields: {
+    updateCheckStartCount: DAILY_COUNTER_FIELD,
+    updateCheckSuccessCount: DAILY_COUNTER_FIELD,
+    updateCheckFailedCount: DAILY_COUNTER_FIELD,
+    updateCheckFailedStatuses: DAILY_DISCRETE_NUMERIC_FIELD,
+    completeUpdateStartCount: DAILY_COUNTER_FIELD,
+    partialUpdateStartCount: DAILY_COUNTER_FIELD,
+    completeUpdateSuccessCount: DAILY_COUNTER_FIELD,
+    partialUpdateSuccessCount: DAILY_COUNTER_FIELD,
+    updateFailedCount: DAILY_COUNTER_FIELD,
+    updateFailedStatuses: DAILY_DISCRETE_NUMERIC_FIELD,
+  },
+});
+
+this.UpdateProvider = function () {
+  Metrics.Provider.call(this);
+};
+UpdateProvider.prototype = Object.freeze({
+  __proto__: Metrics.Provider.prototype,
+
+  name: "org.mozilla.update",
+
+  measurementTypes: [
+    UpdateMeasurement1,
+  ],
+
+  recordUpdate: function (field, status) {
+    let m = this.getMeasurement(UpdateMeasurement1.prototype.name,
+                                UpdateMeasurement1.prototype.version);
+
+    return this.enqueueStorageOperation(function recordUpdateFields() {
+      return Task.spawn(function recordUpdateFieldsTask() {
+        yield m.incrementDailyCounter(field + "Count");
+
+        if ((field == "updateFailed" || field == "updateCheckFailed") && status) {
+          yield m.addDailyDiscreteNumeric(field + "Statuses", status);
+        }
+      }.bind(this));
+    }.bind(this));
+  },
+});
--- a/toolkit/mozapps/update/moz.build
+++ b/toolkit/mozapps/update/moz.build
@@ -41,9 +41,13 @@ if CONFIG['MOZ_UPDATER']:
         'nsUpdateService.manifest',
     ]
 
     EXTRA_PP_COMPONENTS += [
         'nsUpdateService.js',
         'nsUpdateServiceStub.js',
     ]
 
-JAR_MANIFESTS += ['jar.mn']
\ No newline at end of file
+    EXTRA_JS_MODULES += [
+      'UpdaterHealthProvider.jsm'
+    ]
+
+JAR_MANIFESTS += ['jar.mn']
--- a/toolkit/mozapps/update/nsUpdateService.js
+++ b/toolkit/mozapps/update/nsUpdateService.js
@@ -7,16 +7,17 @@
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */
 
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 Components.utils.import("resource://gre/modules/FileUtils.jsm");
 Components.utils.import("resource://gre/modules/AddonManager.jsm");
 Components.utils.import("resource://gre/modules/Services.jsm");
 Components.utils.import("resource://gre/modules/ctypes.jsm");
+Components.utils.import("resource://gre/modules/UpdaterHealthProvider.jsm");
 
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 const Cr = Components.results;
 const Cu = Components.utils;
 
 const UPDATESERVICE_CID = Components.ID("{B3C290A6-3943-4B89-8BBE-C01EB7B3B311}");
 const UPDATESERVICE_CONTRACTID = "@mozilla.org/updates/update-service;1";
@@ -253,16 +254,28 @@ const PING_BGUC_ADDON_PREF_DISABLED     
 const PING_BGUC_ADDON_SAME_APP_VER           = 27;
 // No incompatible add-ons found during incompatible check (background download)
 const PING_BGUC_CHECK_NO_INCOMPAT            = 28;
 // Incompatible add-ons found and all of them have updates (background download)
 const PING_BGUC_ADDON_UPDATES_FOR_INCOMPAT   = 29;
 // Incompatible add-ons found (update notification)
 const PING_BGUC_ADDON_HAVE_INCOMPAT          = 30;
 
+// Health report field names
+const UpdaterHealthReportFields = {
+  CHECK_START: "updateCheckStart",
+  CHECK_SUCCESS: "updateCheckSuccess",
+  CHECK_FAILED: "updateCheckFailed",
+  COMPLETE_START: "completeUpdateStart",
+  PARTIAL_START: "partialUpdateStart",
+  COMPLETE_SUCCESS: "completeUpdateSuccess",
+  PARTIAL_SUCCESS: "partialUpdateSuccess",
+  FAILED: "updateFailed"
+};
+
 var gLocale = null;
 var gUpdateMutexHandle = null;
 
 #ifdef MOZ_WIDGET_GONK
 var gSDCardMountLock = null;
 
 XPCOMUtils.defineLazyGetter(this, "gExtStorage", function aus_gExtStorage() {
     return Services.env.get("EXTERNAL_STORAGE");
@@ -931,16 +944,47 @@ function getStatusTextFromCode(code, def
     reason = gUpdateBundle.GetStringFromName("check_error-" + defaultCode);
     LOG("getStatusTextFromCode - transfer error: " + reason +
         ", default code: " + defaultCode);
   }
   return reason;
 }
 
 /**
+ * Record count in the health report.
+ * @param field
+ *        The field name to record
+ * @param status
+ *        Status code for errors, 0 otherwise
+ */
+function recordInHealthReport(field, status) {
+#ifdef MOZ_SERVICES_HEALTHREPORT
+  try {
+    LOG("recordInHealthReport - " + field + " - " + status);
+
+    let reporter = Cc["@mozilla.org/datareporting/service;1"]
+                      .getService().wrappedJSObject.healthReporter;
+
+    if (reporter) {
+      reporter.onInit().then(function recordUpdateInHealthReport() {
+        try {
+          reporter.getProvider("org.mozilla.update").recordUpdate(field, status);
+        } catch (ex) {
+          Cu.reportError(ex);
+        }
+      });
+    }
+  // If getting the heath reporter service fails, don't fail updating.
+  } catch (ex) {
+    LOG("recordInHealthReport - could not initialize health reporter");
+  }
+#endif
+}
+
+/**
  * Get the Active Updates directory
  * @return The active updates directory, as a nsIFile object
  */
 function getUpdatesDir() {
   // Right now, we only support downloading one patch at a time, so we always
   // use the same target directory.
   return getUpdateDirCreate([DIR_UPDATES, "0"]);
 }
@@ -3595,16 +3639,18 @@ Checker.prototype = {
       throw Cr.NS_ERROR_NULL_POINTER;
 
     Services.obs.notifyObservers(null, "update-check-start", null);
 
     var url = this.getUpdateURL(force);
     if (!url || (!this.enabled && !force))
       return;
 
+    recordInHealthReport(UpdaterHealthReportFields.CHECK_START, 0);
+
     this._request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
                     createInstance(Ci.nsISupports);
     // This is here to let unit test code override XHR
     if (this._request.wrappedJSObject) {
       this._request = this._request.wrappedJSObject;
     }
     this._request.open("GET", url, true);
     var allowNonBuiltIn = !getPref("getBoolPref",
@@ -3718,16 +3764,18 @@ Checker.prototype = {
       gCertUtils.checkCert(this._request.channel, allowNonBuiltIn, certs);
 
       if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_CERT_ERRORS))
         Services.prefs.clearUserPref(PREF_APP_UPDATE_CERT_ERRORS);
 
       if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_BACKGROUNDERRORS))
         Services.prefs.clearUserPref(PREF_APP_UPDATE_BACKGROUNDERRORS);
 
+      recordInHealthReport(UpdaterHealthReportFields.CHECK_SUCCESS, 0);
+
       // Tell the callback about the updates
       this._callback.onCheckComplete(event.target, updates, updates.length);
     }
     catch (e) {
       LOG("Checker:onLoad - there was a problem checking for updates. " +
           "Exception: " + e);
       var request = event.target;
       var status = this._getChannelStatus(request);
@@ -3738,16 +3786,19 @@ Checker.prototype = {
 
       if (this._isHttpStatusCode(status)) {
         update.errorCode = HTTP_ERROR_OFFSET + status;
       }
       if (e.result == Cr.NS_ERROR_ILLEGAL_VALUE) {
         update.errorCode = updates[0] ? CERT_ATTR_CHECK_FAILED_HAS_UPDATE
                                       : CERT_ATTR_CHECK_FAILED_NO_UPDATE;
       }
+
+      recordInHealthReport(UpdaterHealthReportFields.CHECK_FAILED, update.errorCode);
+
       this._callback.onError(request, update);
     }
 
     this._callback = null;
     this._request = null;
   },
 
   /**
@@ -3769,16 +3820,18 @@ Checker.prototype = {
 
     if (status == Cr.NS_ERROR_OFFLINE) {
       // We use a separate constant here because nsIUpdate.errorCode is signed
       update.errorCode = NETWORK_ERROR_OFFLINE;
     } else if (this._isHttpStatusCode(status)) {
       update.errorCode = HTTP_ERROR_OFFSET + status;
     }
 
+    recordInHealthReport(UpdaterHealthReportFields.CHECK_FAILED, update.errorCode);
+
     this._callback.onError(request, update);
 
     this._request = null;
   },
 
   /**
    * Whether or not we are allowed to do update checking.
    */
@@ -4083,16 +4136,20 @@ Downloader.prototype = {
     // to download.
     this._patch = this._selectPatch(update, updateDir);
     if (!this._patch) {
       LOG("Downloader:downloadUpdate - no patch to download");
       return readStatusFile(updateDir);
     }
     this.isCompleteUpdate = this._patch.type == "complete";
 
+    recordInHealthReport(
+      this.isCompleteUpdate ? UpdaterHealthReportFields.COMPLETE_START :
+                              UpdaterHealthReportFields.PARTIAL_START, 0);
+
     var patchFile = null;
 
 #ifdef MOZ_WIDGET_GONK
     let status = readStatusFile(updateDir);
     if (isInterruptedUpdate(status)) {
       LOG("Downloader:downloadUpdate - interruptted update");
       // The update was interrupted. Try to locate the existing patch file.
       // For an interrupted download, this allows a resume rather than a
@@ -4338,16 +4395,20 @@ Downloader.prototype = {
     var retryTimeout = getPref("getIntPref", PREF_APP_UPDATE_RETRY_TIMEOUT,
                                DEFAULT_UPDATE_RETRY_TIMEOUT);
     var maxFail = getPref("getIntPref", PREF_APP_UPDATE_SOCKET_ERRORS,
                           DEFAULT_SOCKET_MAX_ERRORS);
     LOG("Downloader:onStopRequest - status: " + status + ", " +
         "current fail: " + this.updateService._consecutiveSocketErrors + ", " +
         "max fail: " + maxFail + ", " + "retryTimeout: " + retryTimeout);
     if (Components.isSuccessCode(status)) {
+      recordInHealthReport(
+        this.isCompleteUpdate ? UpdaterHealthReportFields.COMPLETE_SUCCESS :
+                                UpdaterHealthReportFields.PARTIAL_SUCCESS, 0);
+
       if (this._verifyDownload()) {
         state = shouldUseService() ? STATE_PENDING_SVC : STATE_PENDING;
         if (this.background) {
           shouldShowPrompt = !getCanStageUpdates();
         }
 
         // Tell the updater.exe we're ready to apply.
         writeStatusFile(getUpdatesDir(), state);
@@ -4366,59 +4427,63 @@ Downloader.prototype = {
         this._update.statusText = message;
 
         if (this._update.isCompleteUpdate || this._update.patchCount != 2)
           deleteActiveUpdate = true;
 
         // Destroy the updates directory, since we're done with it.
         cleanUpUpdatesDir();
       }
-    } else if (status == Cr.NS_ERROR_OFFLINE) {
-      // Register an online observer to try again.
-      // The online observer will continue the incremental download by
-      // calling downloadUpdate on the active update which continues
-      // downloading the file from where it was.
-      LOG("Downloader:onStopRequest - offline, register online observer: true");
-      shouldRegisterOnlineObserver = true;
-      deleteActiveUpdate = false;
-    // Each of NS_ERROR_NET_TIMEOUT, ERROR_CONNECTION_REFUSED, and
-    // NS_ERROR_NET_RESET can be returned when disconnecting the internet while
-    // a download of a MAR is in progress.  There may be others but I have not
-    // encountered them during testing.
-    } else if ((status == Cr.NS_ERROR_NET_TIMEOUT ||
-                status == Cr.NS_ERROR_CONNECTION_REFUSED ||
-                status == Cr.NS_ERROR_NET_RESET) &&
-               this.updateService._consecutiveSocketErrors < maxFail) {
-      LOG("Downloader:onStopRequest - socket error, shouldRetrySoon: true");
-      shouldRetrySoon = true;
-      deleteActiveUpdate = false;
-    } else if (status != Cr.NS_BINDING_ABORTED &&
-               status != Cr.NS_ERROR_ABORT &&
-               status != Cr.NS_ERROR_DOCUMENT_NOT_CACHED) {
-      LOG("Downloader:onStopRequest - non-verification failure");
-      // Some sort of other failure, log this in the |statusText| property
-      state = STATE_DOWNLOAD_FAILED;
-
-      // XXXben - if |request| (The Incremental Download) provided a means
-      // for accessing the http channel we could do more here.
-
-      this._update.statusText = getStatusTextFromCode(status,
-                                                      Cr.NS_BINDING_FAILED);
+    } else {
+      recordInHealthReport(UpdaterHealthReportFields.FAILED, status);
+
+      if (status == Cr.NS_ERROR_OFFLINE) {
+        // Register an online observer to try again.
+        // The online observer will continue the incremental download by
+        // calling downloadUpdate on the active update which continues
+        // downloading the file from where it was.
+        LOG("Downloader:onStopRequest - offline, register online observer: true");
+        shouldRegisterOnlineObserver = true;
+        deleteActiveUpdate = false;
+      // Each of NS_ERROR_NET_TIMEOUT, ERROR_CONNECTION_REFUSED, and
+      // NS_ERROR_NET_RESET can be returned when disconnecting the internet while
+      // a download of a MAR is in progress.  There may be others but I have not
+      // encountered them during testing.
+      } else if ((status == Cr.NS_ERROR_NET_TIMEOUT ||
+                  status == Cr.NS_ERROR_CONNECTION_REFUSED ||
+                  status == Cr.NS_ERROR_NET_RESET) &&
+                 this.updateService._consecutiveSocketErrors < maxFail) {
+        LOG("Downloader:onStopRequest - socket error, shouldRetrySoon: true");
+        shouldRetrySoon = true;
+        deleteActiveUpdate = false;
+      } else if (status != Cr.NS_BINDING_ABORTED &&
+                 status != Cr.NS_ERROR_ABORT &&
+                 status != Cr.NS_ERROR_DOCUMENT_NOT_CACHED) {
+        LOG("Downloader:onStopRequest - non-verification failure");
+        // Some sort of other failure, log this in the |statusText| property
+        state = STATE_DOWNLOAD_FAILED;
+
+        // XXXben - if |request| (The Incremental Download) provided a means
+        // for accessing the http channel we could do more here.
+
+        this._update.statusText = getStatusTextFromCode(status,
+                                                        Cr.NS_BINDING_FAILED);
 
 #ifdef MOZ_WIDGET_GONK
-      // bug891009: On FirefoxOS, manaully retry OTA download will reuse
-      // the Update object. We need to remove selected patch so that download
-      // can be triggered again successfully.
-      this._update.selectedPatch.selected = false;
+        // bug891009: On FirefoxOS, manaully retry OTA download will reuse
+        // the Update object. We need to remove selected patch so that download
+        // can be triggered again successfully.
+        this._update.selectedPatch.selected = false;
 #endif
 
-      // Destroy the updates directory, since we're done with it.
-      cleanUpUpdatesDir();
-
-      deleteActiveUpdate = true;
+        // Destroy the updates directory, since we're done with it.
+        cleanUpUpdatesDir();
+
+        deleteActiveUpdate = true;
+      }
     }
     LOG("Downloader:onStopRequest - setting state to: " + state);
     this._patch.state = state;
     var um = Cc["@mozilla.org/updates/update-manager;1"].
              getService(Ci.nsIUpdateManager);
     if (deleteActiveUpdate) {
       this._update.installDate = (new Date()).getTime();
       um.activeUpdate = null;
--- a/toolkit/mozapps/update/nsUpdateService.manifest
+++ b/toolkit/mozapps/update/nsUpdateService.manifest
@@ -5,8 +5,11 @@ component {093C2356-4843-4C65-8709-D7DBC
 contract @mozilla.org/updates/update-manager;1 {093C2356-4843-4C65-8709-D7DBCBBE7DFB}
 component {898CDC9B-E43F-422F-9CC4-2F6291B415A3} nsUpdateService.js
 contract @mozilla.org/updates/update-checker;1 {898CDC9B-E43F-422F-9CC4-2F6291B415A3}
 component {27ABA825-35B5-4018-9FDD-F99250A0E722} nsUpdateService.js
 contract @mozilla.org/updates/update-prompt;1 {27ABA825-35B5-4018-9FDD-F99250A0E722}
 component {e43b0010-04ba-4da6-b523-1f92580bc150} nsUpdateServiceStub.js
 contract @mozilla.org/updates/update-service-stub;1 {e43b0010-04ba-4da6-b523-1f92580bc150}
 category profile-after-change nsUpdateServiceStub @mozilla.org/updates/update-service-stub;1
+#ifdef MOZ_SERVICES_HEALTHREPORT
+category healthreport-js-provider-default UpdateProvider resource://gre/modules/UpdaterHealthProvider.jsm
+#endif
new file mode 100644
--- /dev/null
+++ b/toolkit/mozapps/update/tests/unit_aus_update/updateHealthReport.js
@@ -0,0 +1,91 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+const {utils: Cu, classes: Cc, interfaces: Ci} = Components;
+
+
+Cu.import("resource://gre/modules/Metrics.jsm");
+Cu.import("resource://gre/modules/UpdaterHealthProvider.jsm");
+
+// Create a profile
+let gProfile = do_get_profile();
+
+function run_test() {
+  run_next_test();
+}
+
+add_test(function test_constructor() {
+  let provider = new UpdateProvider();
+  run_next_test();
+});
+
+add_task(function test_init() {
+  let storage = yield Metrics.Storage("init");
+  let provider = new UpdateProvider();
+  yield provider.init(storage);
+  yield provider.shutdown();
+
+  yield storage.close();
+});
+
+add_task(function test_collect() {
+  let storage = yield Metrics.Storage("collect");
+  let provider = new UpdateProvider();
+  yield provider.init(storage);
+
+  let now = new Date();
+
+  let m = provider.getMeasurement("update", 1);
+
+  let fieldcount = 0;
+  for (let field of ["updateCheckStart",
+                     "updateCheckSuccess",
+                     "completeUpdateStart",
+                     "partialUpdateStart",
+                     "completeUpdateSuccess",
+                     "partialUpdateSuccess"]) {
+    fieldcount++; // One new day per iteration
+
+    yield provider.recordUpdate(field, 0);
+
+    let data = yield m.getValues();
+    do_check_eq(data.days.size, 1);
+
+    let day = data.days.getDay(now);
+    do_check_eq(day.size, fieldcount);
+    do_check_eq(day.get(field + "Count"), 1);
+
+    yield provider.recordUpdate(field, 0);
+
+    data = yield m.getValues();
+    day = data.days.getDay(now);
+    do_check_eq(day.size, fieldcount);
+    do_check_eq(day.get(field + "Count"), 2);
+  }
+
+  for (let field of ["updateCheckFailed", "updateFailed"]) {
+    fieldcount += 2; // Two fields added per iteration
+
+    yield provider.recordUpdate(field, 500);
+
+    let data = yield m.getValues();
+    let day = data.days.getDay(now);
+    do_check_eq(day.size, fieldcount);
+
+    do_check_eq(day.get(field + "Statuses"), 500);
+
+    yield provider.recordUpdate(field, 800);
+
+    data = yield m.getValues();
+    day = data.days.getDay(now);
+    do_check_eq(day.size, fieldcount);
+    do_check_eq(day.get(field + "Statuses")[0], 500);
+    do_check_eq(day.get(field + "Statuses")[1], 800);
+  }
+
+  yield provider.shutdown();
+  yield storage.close();
+});
+
--- a/toolkit/mozapps/update/tests/unit_aus_update/xpcshell.ini
+++ b/toolkit/mozapps/update/tests/unit_aus_update/xpcshell.ini
@@ -34,8 +34,10 @@ reason = custom nsIUpdatePrompt
 [uiOnlyAllowOneWindow.js]
 skip-if = toolkit == 'gonk'
 reason = custom nsIUpdatePrompt
 [uiUnsupportedAlreadyNotified.js]
 skip-if = toolkit == 'gonk'
 reason = custom nsIUpdatePrompt
 [updateRootDirMigration_win.js]
 run-if = os == 'win'
+[updateHealthReport.js]
+skip-if = ! healthreport
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -3584,16 +3584,25 @@ nsWindow::UpdateThemeGeometries(const ns
   }
 
   nsRefPtr<LayerManager> layerManager = GetLayerManager();
   if (layerManager) {
     layerManager->SetRegionToClear(clearRegion);
   }
 }
 
+uint32_t
+nsWindow::GetMaxTouchPoints() const
+{
+  if (IsWin7OrLater()) {
+    return GetSystemMetrics(SM_MAXIMUMTOUCHES);
+  }
+  return 0;
+}
+
 /**************************************************************
  **************************************************************
  **
  ** BLOCK: Moz Events
  **
  ** Moz GUI event management. 
  **
  **************************************************************
--- a/widget/windows/nsWindow.h
+++ b/widget/windows/nsWindow.h
@@ -192,16 +192,17 @@ public:
   virtual nsIMEUpdatePreference GetIMEUpdatePreference();
   NS_IMETHOD              GetNonClientMargins(nsIntMargin &margins);
   NS_IMETHOD              SetNonClientMargins(nsIntMargin &margins);
   void                    SetDrawsInTitlebar(bool aState);
   mozilla::TemporaryRef<mozilla::gfx::DrawTarget> StartRemoteDrawing() MOZ_OVERRIDE;
   virtual void            EndRemoteDrawing() MOZ_OVERRIDE;
 
   virtual void            UpdateThemeGeometries(const nsTArray<ThemeGeometry>& aThemeGeometries) MOZ_OVERRIDE;
+  virtual uint32_t        GetMaxTouchPoints() const MOZ_OVERRIDE;
 
   /**
    * Event helpers
    */
   virtual bool            DispatchMouseEvent(uint32_t aEventType, WPARAM wParam,
                                              LPARAM lParam,
                                              bool aIsContextMenuKey = false,
                                              int16_t aButton = mozilla::WidgetMouseEvent::eLeftButton,
--- a/widget/windows/nsWindowDefs.h
+++ b/widget/windows/nsWindowDefs.h
@@ -40,16 +40,21 @@
 // Internal message for ensuring the file picker is visible on multi monitor
 // systems, and when the screen resolution changes.
 #define MOZ_WM_ENSUREVISIBLE              (WM_APP+0x374F)
 
 #ifndef SM_CXPADDEDBORDER
 #define SM_CXPADDEDBORDER                 92
 #endif
 
+// require WINVER >= 0x601
+#ifndef SM_MAXIMUMTOUCHES
+#define SM_MAXIMUMTOUCHES                 95
+#endif
+
 #ifndef WM_THEMECHANGED
 #define WM_THEMECHANGED                   0x031A
 #endif
 
 #ifndef WM_GETOBJECT
 #define WM_GETOBJECT                      0x03d
 #endif