Merge m-c to fx-team.
authorRyan VanderMeulen <ryanvm@gmail.com>
Thu, 23 Jan 2014 16:00:27 -0500
changeset 165003 3ba925830469d57a7a08e1857f0f468596e4025f
parent 165002 f63078a8ce74e88025bb8de240fb8e5ce29e17a0 (current diff)
parent 164963 066c526104ef75518dd40e9d4c976b45c7c2269a (diff)
child 165004 9d650c07b5476aec4e12f100e62d7f742548b9e3
child 165012 3e47c6473118e0a6d6d7ec55179b30b59a85b8e1
push id38871
push usercbook@mozilla.com
push dateFri, 24 Jan 2014 08:28:29 +0000
treeherdermozilla-inbound@8be30d3b0b80 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone29.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to fx-team.
dom/tests/mochitest/webapps/test_install_receipts.xul
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -396,16 +396,17 @@ pref("browser.link.open_newwindow.restri
 // work), but make in-process browser frames the default.
 pref("dom.mozBrowserFramesEnabled", true);
 
 // Enable a (virtually) unlimited number of mozbrowser processes.
 // We'll run out of PIDs on UNIX-y systems before we hit this limit.
 pref("dom.ipc.processCount", 100000);
 
 pref("dom.ipc.browser_frames.oop_by_default", false);
+pref("dom.browser_frames.useAsyncPanZoom", false);
 
 // SMS/MMS
 pref("dom.sms.enabled", true);
 
 //The waiting time in network manager.
 pref("network.gonk.ms-release-mms-connection", 30000);
 
 // WebContacts
--- a/b2g/chrome/content/settings.js
+++ b/b2g/chrome/content/settings.js
@@ -646,8 +646,15 @@ SettingsListener.observe("accessibility.
   themingPrefs.forEach(function(pref) {
     SettingsListener.observe('gaia.' + pref, null, function(value) {
       if (value) {
         Services.prefs.setCharPref(pref, value);
       }
     });
   });
 })();
+
+// =================== AsyncPanZoom ======================
+
+SettingsListener.observe('apz.force-enable', false, function(value) {
+  Services.prefs.setBoolPref('dom.browser_frames.useAsyncPanZoom', value);
+});
+
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -7,23 +7,23 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="00d8d05f0d0730a3cbf17635ad6a6b197a2ce7c9"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="290efee3de3a12c9d803f4650d50bc7c7a8e1f2d"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="87aa8679560ce09f6445621d6f370d9de722cdba"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="4addd530e2dc1708745d11d81de21b5d1230ed41"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="425f8b5fadf5889834c5acd27d23c9e0b2129c28"/>
   <project name="device/common" path="device/common" revision="42b808b7e93d0619286ae8e59110b176b7732389"/>
   <project name="device/sample" path="device/sample" revision="237bd668d0f114d801a8d6455ef5e02cc3577587"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
   <project name="platform/external/bluetooth/bluez" path="external/bluetooth/bluez" revision="52a1a862a8bac319652b8f82d9541ba40bfa45ce"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -6,20 +6,20 @@
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="fce1a137746dbd354bca1918f02f96d51c40bad2">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="00d8d05f0d0730a3cbf17635ad6a6b197a2ce7c9"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="290efee3de3a12c9d803f4650d50bc7c7a8e1f2d"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="4addd530e2dc1708745d11d81de21b5d1230ed41"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="905bfa3548eb75cf1792d0d8412b92113bbd4318"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="c3d7efc45414f1b44cd9c479bb2758c91c4707c0"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="b89fda71fcd0fa0cf969310e75be3ea33e048b44"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="2e7d5348f35575870b3c7e567a9a9f6d66f8d6c5"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -7,23 +7,23 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="00d8d05f0d0730a3cbf17635ad6a6b197a2ce7c9"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="290efee3de3a12c9d803f4650d50bc7c7a8e1f2d"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="eda08beb3ba9a159843c70ffde0f9660ec351eb9"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="87aa8679560ce09f6445621d6f370d9de722cdba"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="4addd530e2dc1708745d11d81de21b5d1230ed41"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform/bionic" path="bionic" revision="c72b8f6359de7ed17c11ddc9dfdde3f615d188a9"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="425f8b5fadf5889834c5acd27d23c9e0b2129c28"/>
   <project name="device/common" path="device/common" revision="42b808b7e93d0619286ae8e59110b176b7732389"/>
   <project name="device/sample" path="device/sample" revision="237bd668d0f114d801a8d6455ef5e02cc3577587"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
   <project name="platform/external/bluetooth/bluez" path="external/bluetooth/bluez" revision="52a1a862a8bac319652b8f82d9541ba40bfa45ce"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,4 +1,4 @@
 {
-    "revision": "630d27e5cff74e12e319572dff2b1acd632dc326", 
+    "revision": "9506ca996d28109df7dc8db6e381f54a83aa20ff", 
     "repo_path": "/integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -6,22 +6,22 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="00d8d05f0d0730a3cbf17635ad6a6b197a2ce7c9"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="290efee3de3a12c9d803f4650d50bc7c7a8e1f2d"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="4addd530e2dc1708745d11d81de21b5d1230ed41"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
   <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"/>
   <project name="device/sample" path="device/sample" revision="68b1cb978a20806176123b959cb05d4fa8adaea4"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
--- a/b2g/config/helix/sources.xml
+++ b/b2g/config/helix/sources.xml
@@ -5,17 +5,17 @@
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="00d8d05f0d0730a3cbf17635ad6a6b197a2ce7c9"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="290efee3de3a12c9d803f4650d50bc7c7a8e1f2d"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/inari/sources.xml
+++ b/b2g/config/inari/sources.xml
@@ -7,22 +7,22 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="00d8d05f0d0730a3cbf17635ad6a6b197a2ce7c9"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="290efee3de3a12c9d803f4650d50bc7c7a8e1f2d"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="4addd530e2dc1708745d11d81de21b5d1230ed41"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="cd5dfce80bc3f0139a56b58aca633202ccaee7f8"/>
   <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"/>
   <project name="device/sample" path="device/sample" revision="c328f3d4409db801628861baa8d279fb8855892f"/>
   <project name="platform_external_apriori" path="external/apriori" remote="b2g" revision="11816ad0406744f963537b23d68ed9c2afb412bd"/>
--- a/b2g/config/leo/sources.xml
+++ b/b2g/config/leo/sources.xml
@@ -6,22 +6,22 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="00d8d05f0d0730a3cbf17635ad6a6b197a2ce7c9"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="290efee3de3a12c9d803f4650d50bc7c7a8e1f2d"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="4addd530e2dc1708745d11d81de21b5d1230ed41"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <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"/>
   <project name="device/sample" path="device/sample" revision="68b1cb978a20806176123b959cb05d4fa8adaea4"/>
--- a/b2g/config/mako/sources.xml
+++ b/b2g/config/mako/sources.xml
@@ -6,20 +6,20 @@
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="fce1a137746dbd354bca1918f02f96d51c40bad2">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="00d8d05f0d0730a3cbf17635ad6a6b197a2ce7c9"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="290efee3de3a12c9d803f4650d50bc7c7a8e1f2d"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="4addd530e2dc1708745d11d81de21b5d1230ed41"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="905bfa3548eb75cf1792d0d8412b92113bbd4318"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="c3d7efc45414f1b44cd9c479bb2758c91c4707c0"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="b89fda71fcd0fa0cf969310e75be3ea33e048b44"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="2e7d5348f35575870b3c7e567a9a9f6d66f8d6c5"/>
--- a/b2g/config/wasabi/sources.xml
+++ b/b2g/config/wasabi/sources.xml
@@ -6,22 +6,22 @@
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="59605a7c026ff06cc1613af3938579b1dddc6cfe">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="00d8d05f0d0730a3cbf17635ad6a6b197a2ce7c9"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="290efee3de3a12c9d803f4650d50bc7c7a8e1f2d"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="e9b6626eddbc85873eaa2a9174a9bd5101e5c05f"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="84f2f2fce22605e17d511ff1767e54770067b5b5"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="96d2d00165f4561fbde62d1062706eab74b3a01f"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="4addd530e2dc1708745d11d81de21b5d1230ed41"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="a887bfabaed83c4588b40c845535c0388c8da0f3"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <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"/>
   <project name="device/sample" path="device/sample" revision="c328f3d4409db801628861baa8d279fb8855892f"/>
--- a/config/makefiles/xpidl/Makefile.in
+++ b/config/makefiles/xpidl/Makefile.in
@@ -1,13 +1,12 @@
 # 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/.
 
-SUPPRESS_DEFAULT_RULES := 1
 STANDALONE_MAKEFILE := 1
 
 include $(topsrcdir)/config/rules.mk
 
 # Building XPIDLs effectively consists of two steps:
 #
 #   1) Staging all .idl files to a common directory.
 #   2) Doing everything with the .idl files.
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -587,27 +587,25 @@ export MOZBUILD_BACKEND_CHECKED=1
 endif
 endif
 endif
 
 # The root makefile doesn't want to do a plain export/libs, because
 # of the tiers and because of libxul. Suppress the default rules in favor
 # of something else. Makefiles which use this var *must* provide a sensible
 # default rule before including rules.mk
-ifndef SUPPRESS_DEFAULT_RULES
 default all::
 	$(MAKE) export
 ifdef MOZ_PSEUDO_DERECURSE
 ifdef COMPILE_ENVIRONMENT
 	$(MAKE) compile
 endif
 endif
 	$(MAKE) libs
 	$(MAKE) tools
-endif # SUPPRESS_DEFAULT_RULES
 
 ifeq ($(findstring s,$(filter-out --%, $(MAKEFLAGS))),)
 ECHO := echo
 QUIET :=
 else
 ECHO := true
 QUIET := -q
 endif
--- a/configure.in
+++ b/configure.in
@@ -242,16 +242,17 @@ if test -n "$gonkdir" ; then
 
         MOZ_RTSP=1
         MOZ_NFC=1
         MOZ_B2G_CAMERA=1
         MOZ_OMX_DECODER=1
         AC_SUBST(MOZ_OMX_DECODER)
         MOZ_OMX_ENCODER=1
         AC_SUBST(MOZ_OMX_ENCODER)
+        AC_DEFINE(MOZ_OMX_ENCODER)
         ;;
     19)
         GONK_INCLUDES="-I$gonkdir/frameworks/native/include"
         MOZ_B2G_BT=1
         MOZ_B2G_BT_BLUEDROID=1
         MOZ_NFC=1
 
         ;;
--- a/content/base/src/nsFrameLoader.cpp
+++ b/content/base/src/nsFrameLoader.cpp
@@ -2053,17 +2053,19 @@ nsFrameLoader::TryRemoteBrowser()
   }
 
   PROFILER_LABEL("nsFrameLoader", "CreateRemoteBrowser");
 
   MutableTabContext context;
   nsCOMPtr<mozIApplication> ownApp = GetOwnApp();
   nsCOMPtr<mozIApplication> containingApp = GetContainingApp();
   ScrollingBehavior scrollingBehavior = DEFAULT_SCROLLING;
-  if (mOwnerContent->AttrValueIs(kNameSpaceID_None,
+
+  if (Preferences::GetBool("dom.browser_frames.useAsyncPanZoom", false) ||
+      mOwnerContent->AttrValueIs(kNameSpaceID_None,
                                  nsGkAtoms::mozasyncpanzoom,
                                  nsGkAtoms::_true,
                                  eCaseMatters)) {
     scrollingBehavior = ASYNC_PAN_ZOOM;
   }
 
   bool rv = true;
   if (ownApp) {
--- a/content/canvas/src/CanvasRenderingContext2D.cpp
+++ b/content/canvas/src/CanvasRenderingContext2D.cpp
@@ -2938,17 +2938,18 @@ CanvasRenderingContext2D::SetMozDashOffs
 {
   ContextState& state = CurrentState();
   if (!state.dash.IsEmpty()) {
     state.dashOffset = mozDashOffset;
   }
 }
 
 void
-CanvasRenderingContext2D::SetLineDash(const mozilla::dom::AutoSequence<double>& aSegments) {
+CanvasRenderingContext2D::SetLineDash(const Sequence<double>& aSegments)
+{
   FallibleTArray<mozilla::gfx::Float>& dash = CurrentState().dash;
   dash.Clear();
 
   for (uint32_t x = 0; x < aSegments.Length(); x++) {
     dash.AppendElement(aSegments[x]);
   }
   if (aSegments.Length() % 2) { // If the number of elements is odd, concatenate again
     for (uint32_t x = 0; x < aSegments.Length(); x++) {
--- a/content/canvas/src/CanvasRenderingContext2D.h
+++ b/content/canvas/src/CanvasRenderingContext2D.h
@@ -333,17 +333,17 @@ public:
                                      JS::Handle<JSObject*> currentTransform,
                                      mozilla::ErrorResult& error);
   void GetFillRule(nsAString& fillRule);
   void SetFillRule(const nsAString& fillRule);
   JS::Value GetMozDash(JSContext* cx, mozilla::ErrorResult& error);
   void SetMozDash(JSContext* cx, const JS::Value& mozDash,
                   mozilla::ErrorResult& error);
 
-  void SetLineDash(const mozilla::dom::AutoSequence<double>& mSegments);
+  void SetLineDash(const Sequence<double>& mSegments);
   void GetLineDash(nsTArray<double>& mSegments) const;
 
   void SetLineDashOffset(double mOffset);
   double LineDashOffset() const;
 
   double MozDashOffset()
   {
     return CurrentState().dashOffset;
--- a/content/html/content/src/nsGenericHTMLElement.cpp
+++ b/content/html/content/src/nsGenericHTMLElement.cpp
@@ -3149,17 +3149,17 @@ nsGenericHTMLElement::SetItemValue(JSCon
                                    ErrorResult& aError)
 {
   if (!HasAttr(kNameSpaceID_None, nsGkAtoms::itemprop) ||
       HasAttr(kNameSpaceID_None, nsGkAtoms::itemscope)) {
     aError.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     return;
   }
 
-  FakeDependentString string;
+  binding_detail::FakeDependentString string;
   JS::Rooted<JS::Value> value(aCx, aValue);
   if (!ConvertJSValueToString(aCx, value, &value, eStringify, eStringify, string)) {
     aError.Throw(NS_ERROR_UNEXPECTED);
     return;
   }
   SetItemValueText(string);
 }
 
--- a/content/media/encoder/moz.build
+++ b/content/media/encoder/moz.build
@@ -20,17 +20,16 @@ UNIFIED_SOURCES += [
     'TrackEncoder.cpp',
 ]
 
 if CONFIG['MOZ_OPUS']:
     EXPORTS += ['OpusTrackEncoder.h']
     UNIFIED_SOURCES += ['OpusTrackEncoder.cpp']
 
 if CONFIG['MOZ_OMX_ENCODER']:
-    DEFINES['MOZ_OMX_ENCODER'] = True
     EXPORTS += ['OmxTrackEncoder.h']
     UNIFIED_SOURCES += ['OmxTrackEncoder.cpp']
 
 FAIL_ON_WARNINGS = True
 
 FINAL_LIBRARY = 'gklayout'
 
 include('/ipc/chromium/chromium-config.mozbuild')
--- a/dom/apps/src/Webapps.jsm
+++ b/dom/apps/src/Webapps.jsm
@@ -2013,16 +2013,26 @@ this.DOMApplicationRegistry = {
 
     let sendError = function sendError(aError) {
       aData.error = aError;
       aMm.sendAsyncMessage("Webapps:Install:Return:KO", aData);
       Cu.reportError("Error installing app from: " + app.installOrigin +
                      ": " + aError);
     }.bind(this);
 
+    if (app.receipts.length > 0) {
+      for (let receipt of app.receipts) {
+        let error = this.isReceipt(receipt);
+        if (error) {
+          sendError(error);
+          return;
+        }
+      }
+    }
+
     // Hosted apps can't be trusted or certified, so just check that the
     // manifest doesn't ask for those.
     function checkAppStatus(aManifest) {
       let manifestStatus = aManifest.type || "web";
       return manifestStatus === "web";
     }
 
     let checkManifest = (function() {
@@ -2122,16 +2132,26 @@ this.DOMApplicationRegistry = {
 
     let sendError = function sendError(aError) {
       aData.error = aError;
       aMm.sendAsyncMessage("Webapps:Install:Return:KO", aData);
       Cu.reportError("Error installing packaged app from: " +
                      app.installOrigin + ": " + aError);
     }.bind(this);
 
+    if (app.receipts.length > 0) {
+      for (let receipt of app.receipts) {
+        let error = this.isReceipt(receipt);
+        if (error) {
+          sendError(error);
+          return;
+        }
+      }
+    }
+
     let checkUpdateManifest = (function() {
       let manifest = app.updateManifest;
 
       // Disallow reinstalls from the same manifest URL for now.
       let id = this._appIdForManifestURL(app.manifestURL);
       if (id !== null && this._isLaunchable(this.webapps[id])) {
         sendError("REINSTALL_FORBIDDEN");
         return false;
--- a/dom/apps/tests/mochitest.ini
+++ b/dom/apps/tests/mochitest.ini
@@ -11,8 +11,9 @@ support-files =
 
 [test_app_update.html]
 [test_bug_795164.html]
 [test_packaged_app_common.js]
 [test_packaged_app_install.html]
 [test_packaged_app_update.html]
 [test_uninstall_errors.html]
 [test_receipt_operations.html]
+[test_install_receipts.html]
new file mode 100644
--- /dev/null
+++ b/dom/apps/tests/test_install_receipts.html
@@ -0,0 +1,215 @@
+<!DOCTYPE html>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id={960837}
+-->
+<head>
+  <title>Test for Bug {960837}</title>
+  <script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id={960837}">Mozilla Bug {960837}</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+
+</div>
+<pre id="test">
+<script class="testbody" type="application/javascript;version=1.7">
+
+var gManifestURL = "http://test/tests/dom/apps/tests/file_app.sjs?apptype=hosted&getmanifest=true";
+var gGenerator = runTest();
+
+function debug(aMsg) {
+  //dump("== Tests debug == " + aMsg + "\n");
+}
+
+function go() {
+  SpecialPowers.pushPermissions(
+    [{ "type": "webapps-manage", "allow": 1, "context": document }],
+    function() { gGenerator.next() });
+}
+
+function continueTest() {
+  try {
+    gGenerator.next();
+  } catch (e) {
+    dump("Got exception: " + e + "\n");
+  }
+}
+
+function finish() {
+  SimpleTest.finish();
+}
+
+function cbError(aError) {
+  ok(false, "Error callback invoked " + aError);
+  finish();
+}
+
+SimpleTest.waitForExplicitFinish();
+
+function runTest() {
+  launchableValue = SpecialPowers.setAllAppsLaunchable(true);
+
+  SpecialPowers.autoConfirmAppInstall(continueTest);
+  yield undefined;
+
+  // Test install with three valid receipts
+  let valid_receipt1 = 'eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJwcm9kdWN0IjogeyJ1cmwiOiAiaHR0cHM6Ly93d3cubW96aWxsYS5vcmciLCAic3RvcmVkYXRhIjogIjUxNjkzMTQzNTYifSwgInJlaXNzdWUiOiAiaHR0cDovL21vY2hpLnRlc3Q6ODg4OC9yZWlzc3VlLzUxNjkzMTQzNTYiLCAidXNlciI6IHsidHlwZSI6ICJkaXJlY3RlZC1pZGVudGlmaWVyIiwgInZhbHVlIjogIjRmYjM1MTUxLTJiOWItNGJhMi04MjgzLWM0OWQzODE2NDBiZCJ9LCAidmVyaWZ5IjogImh0dHA6Ly9tb2NoaS50ZXN0Ojg4ODgvdmVyaWZ5LzUxNjkzMTQzNTYiLCAiaXNzIjogImh0dHA6Ly9tb2NoaS50ZXN0Ojg4ODgiLCAiaWF0IjogMTMxMzYwMTg4LCAidHlwIjogInB1cmNoYXNlLXJlY2VpcHQiLCAibmJmIjogMTMxMzYwMTg1LCAiZGV0YWlsIjogImh0dHA6Ly9tb2NoaS50ZXN0Ojg4ODgvcmVjZWlwdC81MTY5MzE0MzU2In0.eZpTEnCLUR3iP3rm9WyJOqx1k66mQaAxqcrvX11r5E0';
+
+  let valid_receipt2 = 'eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJwcm9kdWN0IjogeyJ1cmwiOiAiaHR0cHM6Ly93d3cubW96aWxsYS5vcmciLCAic3RvcmVkYXRhIjogIjUxNjkzMTQzNTcifSwgInJlaXNzdWUiOiAiaHR0cDovL21vY2hpLnRlc3Q6ODg4OC9yZWlzc3VlLzUxNjkzMTQzNTYiLCAidXNlciI6IHsidHlwZSI6ICJkaXJlY3RlZC1pZGVudGlmaWVyIiwgInZhbHVlIjogIjRmYjM1MTUxLTJiOWItNGJhMi04MjgzLWM0OWQzODE2NDBiZCJ9LCAidmVyaWZ5IjogImh0dHA6Ly9tb2NoaS50ZXN0Ojg4ODgvdmVyaWZ5LzUxNjkzMTQzNTYiLCAiaXNzIjogImh0dHA6Ly9tb2NoaS50ZXN0Ojg4ODgiLCAiaWF0IjogMTMxMzYwMTg4LCAidHlwIjogInB1cmNoYXNlLXJlY2VpcHQiLCAibmJmIjogMTMxMzYwMTg1LCAiZGV0YWlsIjogImh0dHA6Ly9tb2NoaS50ZXN0Ojg4ODgvcmVjZWlwdC81MTY5MzE0MzU2In0.k7tI0PTaMJf0w0keAHJR6couypGY-EtA38q2xOtSv6k';
+
+  let valid_receipt3 = 'eyJhbGciOiAiUlMyNTYiLCAidHlwIjogIkpXVCIsICJqa3UiOiAiaHR0cHM6Ly9tYXJrZXRwbGFjZS5jZG4ubW96aWxsYS5uZXQvcHVibGljX2tleXMvbWFya2V0cGxhY2Utcm9vdC1wdWIta2V5Lmp3ayJ9.eyJpc3MiOiAiaHR0cHM6Ly9tYXJrZXRwbGFjZS5jZG4ubW96aWxsYS5uZXQvcHVibGljX2tleXMvbWFya2V0cGxhY2Utcm9vdC1wdWIta2V5Lmp3ayIsICJwcmljZV9saW1pdCI6IDEwMCwgImp3ayI6IFt7ImFsZyI6ICJSU0EiLCAibW9kIjogIkFMYkszek5VQ0lFTEJRZ1QycGUzTEkwdC1sR0w5OElFTnBWOUtuX0F4VGxjLXZzX0ZFMlVyNzU2Z012bHA3a3BWVmFEWVNCdnVCQjgtZEZpU3VJbHdCUFB2bWFIaTFhd0xJMjRRY2JOMVJrN3pZS01SclVfSzdkVEN6MEh6VHoza01YVXp1ci1ySTIxS3BKb0NSZFNxeUl4bHpnUWFna1dUUWxIYUI2VzkzUjBacUxlQk9lUzhjbzNOUlczdjFfY0h4VTE1d0k4T0JHY0tRSXB3VHpONUVfRFdNZ0F1MGFQMHlWY3EzT0FwXy1fa1pjYXBtQnpSTmVMOHBxMjZXN01jMUpJZVBnZVZ5SXExcFBLMU9ldGhmdF9KeTk5R19EWWxQNW15YjFEY1VpbHE3RVNKc1UyeUZPUjJhWmkyYU1lTkRZekwyUmdZSGt2RWxyNDRMM2NZM0UiLCAiZXhwIjogIkFRQUIiLCAia2lkIjogImFwcHN0b3JlLm1vemlsbGEuY29tLTIwMTMtMTEtMjcifV0sICJleHAiOiAxMzg2Nzg4NDAxLCAiaWF0IjogMTM4NTU3ODgwMSwgInR5cCI6ICJjZXJ0aWZpZWQta2V5IiwgIm5iZiI6IDEzODU1Nzg4MDF9.Ne5AffwNIjbQmwY_dSKVXR0R0wdB92sW_BWQWbN2WKa_Ep6V0Fwr2pfcv0KenZcYKdxhhSPBrs5R38EcIqTYYrgIeeJyM_gGzv-ESsUsqbFejAbVH2xfwATZ1lXNPh0VSt33Drf2RY5jeU5PD3usXgOPr8RYAGkMxz_0SUay5WCBVRLkrgtrCUNyIKBwuHlxKK1JkncVXsN0mr_gwbm0EpBgIOEZQj75TE0KcviMUvYn8uhVYEwYMLzMQmUbI5quxH2z5mcK2DDNQGgT6ABJljKWCY-PPuMo9tsgXe6L7MTafulBuSIjs1ztAl4ZnwZjKmxWmhdeiaT41tCFlr4K8Q~eyJqa3UiOiAiaHR0cHM6Ly9tYXJrZXRwbGFjZS5jZG4ubW96aWxsYS5uZXQvcHVibGljX2tleXMvbWFya2V0cGxhY2Utcm9vdC1wdWIta2V5Lmp3ayIsICJ0eXAiOiAiSldUIiwgImFsZyI6ICJSUzI1NiJ9.eyJwcm9kdWN0IjogeyJ1cmwiOiAiaHR0cHM6Ly9tYXJrZXRwbGFjZS5maXJlZm94LmNvbSIsICJzdG9yZWRhdGEiOiAiaWQ9NDM4OTc4In0sICJpc3MiOiAiaHR0cHM6Ly9tYXJrZXRwbGFjZS5maXJlZm94LmNvbSIsICJ2ZXJpZnkiOiAiaHR0cHM6Ly9yZWNlaXB0Y2hlY2subWFya2V0cGxhY2UuZmlyZWZveC5jb20vdmVyaWZ5LyIsICJkZXRhaWwiOiAiaHR0cHM6Ly9tYXJrZXRwbGFjZS5maXJlZm94LmNvbS9hcGkvdjEvcmVjZWlwdHMvcmVpc3N1ZS8iLCAicmVpc3N1ZSI6ICJodHRwczovL21hcmtldHBsYWNlLmZpcmVmb3guY29tL2FwaS92MS9yZWNlaXB0cy9yZWlzc3VlLyIsICJ1c2VyIjogeyJ0eXBlIjogImRpcmVjdGVkLWlkZW50aWZpZXIiLCAidmFsdWUiOiAiMTkzMzI2LTVjMTUzNmQ1LWUxMDQtNDAzYy04NDBlLTQ5YjMyMmQ5Yjg4NSJ9LCAiZXhwIjogMTQwMTgyNTEyOCwgImlhdCI6IDEzODYxMDAzMjgsICJ0eXAiOiAicHVyY2hhc2UtcmVjZWlwdCIsICJuYmYiOiAxMzg2MTAwMzI4fQ.r2DVUpouRDJYqZe61LJBcIwmeF2mI8FmbGMRlfNFcinKAIs8nMVVNX8xSWJ6jXXgZ62VfHJCLHapADX8rCg6NgxFV_FdP7j2H_2Ufo0E0TREifTN6V4v1dCnzDulNhZmO8G-nQJUVOAtNfNC95PY7tVa8WC7dYXnKZsD6NhIxxVEtBGuiiySpWArI-g3pcl41rXNHHpJbRfrOD4QgVNrsV83TWILYRr6PWr3aqOM2XT_x2SzEfhBNvdG8AJmR0MKQytvfcgz3Vt1hMak88nFrzTLiKkuuPAXpwB5q83LZIl4EYG3UAnte4-XWlLb-NJ78vgXa64myy-3fPr7EO6LaQ';
+
+  var request = navigator.mozApps.install(gManifestURL, { receipts: [ valid_receipt1, valid_receipt2, valid_receipt3 ]});
+  request.onerror = cbError;
+  request.onsuccess = continueTest;
+  yield undefined;
+
+  var app = request.result;
+  ok(app, "App is non-null");
+  ok(app.receipts.length == 3, "Three receipts");
+
+  request = navigator.mozApps.mgmt.uninstall(app);
+  request.onerror = cbError;
+  request.onsuccess = continueTest;
+  yield undefined;
+
+  // Test install with a receipt with less than 3 segments
+  let receipt_few_segments = 'eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJwcm9kdWN0IjogeyJ1cmwiOiAiaHR0cHM6Ly93d3cubW96aWxsYS5vcmciLCAic3RvcmVkYXRhIjogIjUxNjkzMTQzNTcifSwgInJlaXNzdWUiOiAiaHR0cDovL21vY2hpLnRlc3Q6ODg4OC9yZWlzc3VlLzUxNjkzMTQzNTYiLCAidXNlciI6IHsidHlwZSI6ICJkaXJlY3RlZC1pZGVudGlmaWVyIiwgInZhbHVlIjogIjRmYjM1MTUxLTJiOWItNGJhMi04MjgzLWM0OWQzODE2NDBiZCJ9LCAidmVyaWZ5IjogImh0dHA6Ly9tb2NoaS50ZXN0Ojg4ODgvdmVyaWZ5LzUxNjkzMTQzNTYiLCAiaXNzIjogImh0dHA6Ly9tb2NoaS50ZXN0Ojg4ODgiLCAiaWF0IjogMTMxMzYwMTg4LCAidHlwIjogInB1cmNoYXNlLXJlY2VpcHQiLCAibmJmIjogMTMxMzYwMTg1LCAiZGV0YWlsIjogImh0dHA6Ly9tb2NoaS50ZXN0Ojg4ODgvcmVjZWlwdC81MTY5MzE0MzU2In0';
+
+  var request = navigator.mozApps.install(gManifestURL, { receipts: [ receipt_few_segments ]});
+  request.onsuccess = function() {
+    ok(false, "Less than 3 segments");
+  }
+  request.onerror = function() {
+    ok(this.error.name == "INVALID_SEGMENTS_NUMBER",
+       "Less than 3 segments");
+    continueTest();
+  }
+  yield undefined;
+
+  // Test install with a receipt without the typ field
+  let receipt_without_typ = "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJwcm9kdWN0IjogeyJ1cmwiOiAiaHR0cHM6Ly93d3cubW96aWxsYS5vcmciLCAic3RvcmVkYXRhIjogIjUxNjkzMTQzNTgifSwgInJlaXNzdWUiOiAiaHR0cDovL21vY2hpLnRlc3Q6ODg4OC9yZWlzc3VlLzUxNjkzMTQzNTYiLCAidXNlciI6IHsidHlwZSI6ICJkaXJlY3RlZC1pZGVudGlmaWVyIiwgInZhbHVlIjogIjRmYjM1MTUxLTJiOWItNGJhMi04MjgzLWM0OWQzODE2NDBiZCJ9LCAidmVyaWZ5IjogImh0dHA6Ly9tb2NoaS50ZXN0Ojg4ODgvdmVyaWZ5LzUxNjkzMTQzNTYiLCAiaXNzIjogImh0dHA6Ly9tb2NoaS50ZXN0Ojg4ODgiLCAiaWF0IjogMTMxMzYwMTg4LCAibmJmIjogMTMxMzYwMTg1LCAiZGV0YWlsIjogImh0dHA6Ly9tb2NoaS50ZXN0Ojg4ODgvcmVjZWlwdC81MTY5MzE0MzU2In0.6NY9DCEwhv9gTo1d7G4SJubZp_wSkaAJWA9iIp0PAQg";
+
+  var request = navigator.mozApps.install(gManifestURL, { receipts: [ receipt_without_typ ]});
+  request.onsuccess = function() {
+    ok(false, "No type field");
+  }
+  request.onerror = function() {
+    ok(this.error.name == "RECEIPT_TYPE_REQUIRED",
+       "No type field");
+    continueTest();
+  }
+  yield undefined;
+
+  // Test install with a receipt without the product field
+  let receipt_without_product = "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJyZWlzc3VlIjogImh0dHA6Ly9tb2NoaS50ZXN0Ojg4ODgvcmVpc3N1ZS81MTY5MzE0MzU2IiwgInVzZXIiOiB7InR5cGUiOiAiZGlyZWN0ZWQtaWRlbnRpZmllciIsICJ2YWx1ZSI6ICI0ZmIzNTE1MS0yYjliLTRiYTItODI4My1jNDlkMzgxNjQwYmQifSwgInZlcmlmeSI6ICJodHRwOi8vbW9jaGkudGVzdDo4ODg4L3ZlcmlmeS81MTY5MzE0MzU2IiwgImlzcyI6ICJodHRwOi8vbW9jaGkudGVzdDo4ODg4IiwgImlhdCI6IDEzMTM2MDE4OCwgInR5cCI6ICJwdXJjaGFzZS1yZWNlaXB0IiwgIm5iZiI6IDEzMTM2MDE4NSwgImRldGFpbCI6ICJodHRwOi8vbW9jaGkudGVzdDo4ODg4L3JlY2VpcHQvNTE2OTMxNDM1NiJ9.TWB8VXM2MhsyHLX3kWdjpSyn5Mz3SfG0oRIn-5p_0ko";
+
+  var request = navigator.mozApps.install(gManifestURL, { receipts: [ receipt_without_product ]});
+  request.onsuccess = function() {
+    ok(false, "No product field");
+  }
+  request.onerror = function() {
+    ok(this.error.name == "RECEIPT_PRODUCT_REQUIRED",
+       "No product field");
+    continueTest();
+  }
+  yield undefined;
+
+  // Test install with a receipt without the user field
+  let receipt_without_user = "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJwcm9kdWN0IjogeyJ1cmwiOiAiaHR0cHM6Ly93d3cubW96aWxsYS5vcmciLCAic3RvcmVkYXRhIjogIjUxNjkzMTQzNTgifSwgInJlaXNzdWUiOiAiaHR0cDovL21vY2hpLnRlc3Q6ODg4OC9yZWlzc3VlLzUxNjkzMTQzNTYiLCAidmVyaWZ5IjogImh0dHA6Ly9tb2NoaS50ZXN0Ojg4ODgvdmVyaWZ5LzUxNjkzMTQzNTYiLCAiaXNzIjogImh0dHA6Ly9tb2NoaS50ZXN0Ojg4ODgiLCAiaWF0IjogMTMxMzYwMTg4LCAidHlwIjogInB1cmNoYXNlLXJlY2VpcHQiLCAibmJmIjogMTMxMzYwMTg1LCAiZGV0YWlsIjogImh0dHA6Ly9tb2NoaS50ZXN0Ojg4ODgvcmVjZWlwdC81MTY5MzE0MzU2In0.eYm4ncnKvYzn-OYam5L55RQ8ShK6UlMrjFQOwByHSew";
+
+  var request = navigator.mozApps.install(gManifestURL, { receipts: [ receipt_without_user ]});
+  request.onsuccess = function() {
+    ok(false, "No user field");
+  }
+  request.onerror = function() {
+    ok(this.error.name == "RECEIPT_USER_REQUIRED",
+       "No user field");
+    continueTest();
+  }
+  yield undefined;
+
+  // Test install with a receipt without the iss field
+  let receipt_without_iss = "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJwcm9kdWN0IjogeyJ1cmwiOiAiaHR0cHM6Ly93d3cubW96aWxsYS5vcmciLCAic3RvcmVkYXRhIjogIjUxNjkzMTQzNTgifSwgInJlaXNzdWUiOiAiaHR0cDovL21vY2hpLnRlc3Q6ODg4OC9yZWlzc3VlLzUxNjkzMTQzNTYiLCAidXNlciI6IHsidHlwZSI6ICJkaXJlY3RlZC1pZGVudGlmaWVyIiwgInZhbHVlIjogIjRmYjM1MTUxLTJiOWItNGJhMi04MjgzLWM0OWQzODE2NDBiZCJ9LCAidmVyaWZ5IjogImh0dHA6Ly9tb2NoaS50ZXN0Ojg4ODgvdmVyaWZ5LzUxNjkzMTQzNTYiLCAiaWF0IjogMTMxMzYwMTg4LCAidHlwIjogInB1cmNoYXNlLXJlY2VpcHQiLCAibmJmIjogMTMxMzYwMTg1LCAiZGV0YWlsIjogImh0dHA6Ly9tb2NoaS50ZXN0Ojg4ODgvcmVjZWlwdC81MTY5MzE0MzU2In0.kvumGJAu8HkJ_utucwHwiOA_jJcqRMXBRQVDZd4KfUw";
+
+  var request = navigator.mozApps.install(gManifestURL, { receipts: [ receipt_without_iss ]});
+  request.onsuccess = function() {
+    ok(false, "No iss field");
+  }
+  request.onerror = function() {
+    ok(this.error.name == "RECEIPT_ISS_REQUIRED",
+       "No iss field");
+    continueTest();
+  }
+  yield undefined;
+
+  // Test install with a receipt without the nbf field
+  let receipt_without_nbf = "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJwcm9kdWN0IjogeyJ1cmwiOiAiaHR0cHM6Ly93d3cubW96aWxsYS5vcmciLCAic3RvcmVkYXRhIjogIjUxNjkzMTQzNTgifSwgInJlaXNzdWUiOiAiaHR0cDovL21vY2hpLnRlc3Q6ODg4OC9yZWlzc3VlLzUxNjkzMTQzNTYiLCAidXNlciI6IHsidHlwZSI6ICJkaXJlY3RlZC1pZGVudGlmaWVyIiwgInZhbHVlIjogIjRmYjM1MTUxLTJiOWItNGJhMi04MjgzLWM0OWQzODE2NDBiZCJ9LCAidmVyaWZ5IjogImh0dHA6Ly9tb2NoaS50ZXN0Ojg4ODgvdmVyaWZ5LzUxNjkzMTQzNTYiLCAiaXNzIjogImh0dHA6Ly9tb2NoaS50ZXN0Ojg4ODgiLCAiaWF0IjogMTMxMzYwMTg4LCAidHlwIjogInB1cmNoYXNlLXJlY2VpcHQiLCAiZGV0YWlsIjogImh0dHA6Ly9tb2NoaS50ZXN0Ojg4ODgvcmVjZWlwdC81MTY5MzE0MzU2In0.TYp6RQDFmyxLrmwAbhwkWLWgqhILR5yGA9CWDKNRU9Q";
+
+  var request = navigator.mozApps.install(gManifestURL, { receipts: [ receipt_without_nbf ]});
+  request.onsuccess = function() {
+    ok(false, "No nbf field");
+  }
+  request.onerror = function() {
+    ok(this.error.name == "RECEIPT_NBF_REQUIRED",
+       "No nbf field");
+    continueTest();
+  }
+  yield undefined;
+
+  // Test install with a receipt without the iat field
+  let receipt_without_iat = "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJwcm9kdWN0IjogeyJ1cmwiOiAiaHR0cHM6Ly93d3cubW96aWxsYS5vcmciLCAic3RvcmVkYXRhIjogIjUxNjkzMTQzNTgifSwgInJlaXNzdWUiOiAiaHR0cDovL21vY2hpLnRlc3Q6ODg4OC9yZWlzc3VlLzUxNjkzMTQzNTYiLCAidXNlciI6IHsidHlwZSI6ICJkaXJlY3RlZC1pZGVudGlmaWVyIiwgInZhbHVlIjogIjRmYjM1MTUxLTJiOWItNGJhMi04MjgzLWM0OWQzODE2NDBiZCJ9LCAiaXNzIjogImh0dHA6Ly9tb2NoaS50ZXN0Ojg4ODgiLCAidmVyaWZ5IjogImh0dHA6Ly9tb2NoaS50ZXN0Ojg4ODgvdmVyaWZ5LzUxNjkzMTQzNTYiLCAidHlwIjogInB1cmNoYXNlLXJlY2VpcHQiLCAibmJmIjogMTMxMzYwMTg1LCAiZGV0YWlsIjogImh0dHA6Ly9tb2NoaS50ZXN0Ojg4ODgvcmVjZWlwdC81MTY5MzE0MzU2In0.EWxAzgfIM1VtwAscajDjqsRt_lysk_Wtj4_d4NbMg3U";
+
+  var request = navigator.mozApps.install(gManifestURL, { receipts: [ receipt_without_iat ]});
+  request.onsuccess = function() {
+    ok(false, "No iat field");
+  }
+  request.onerror = function() {
+    ok(this.error.name == "RECEIPT_IAT_REQUIRED",
+       "No iat field");
+    continueTest();
+  }
+  yield undefined;
+
+  // Test install with a receipt with a not expected type
+  let receipt_with_wrong_typ = "eyJhbGciOiAiSFMyNTYiLCAidHlwIjogIkpXVCJ9.eyJwcm9kdWN0IjogeyJ1cmwiOiAiaHR0cHM6Ly93d3cubW96aWxsYS5vcmciLCAic3RvcmVkYXRhIjogIjUxNjkzMTQzNTgifSwgInJlaXNzdWUiOiAiaHR0cDovL21vY2hpLnRlc3Q6ODg4OC9yZWlzc3VlLzUxNjkzMTQzNTYiLCAidXNlciI6IHsidHlwZSI6ICJkaXJlY3RlZC1pZGVudGlmaWVyIiwgInZhbHVlIjogIjRmYjM1MTUxLTJiOWItNGJhMi04MjgzLWM0OWQzODE2NDBiZCJ9LCAidmVyaWZ5IjogImh0dHA6Ly9tb2NoaS50ZXN0Ojg4ODgvdmVyaWZ5LzUxNjkzMTQzNTYiLCAiaXNzIjogImh0dHA6Ly9tb2NoaS50ZXN0Ojg4ODgiLCAiaWF0IjogMTMxMzYwMTg4LCAidHlwIjogImZha2UiLCAibmJmIjogMTMxMzYwMTg1LCAiZGV0YWlsIjogImh0dHA6Ly9tb2NoaS50ZXN0Ojg4ODgvcmVjZWlwdC81MTY5MzE0MzU2In0.SGF5lCYvGQEoILyq_tVBD_gPYp00dOTvRlgyOs4twmQ";
+
+  var request = navigator.mozApps.install(gManifestURL, { receipts: [ receipt_with_wrong_typ ]});
+  request.onsuccess = function() {
+    ok(false, "Wrong type");
+  }
+  request.onerror = function() {
+    ok(this.error.name == "RECEIPT_TYPE_UNSUPPORTED",
+       "Wrong type");
+    continueTest();
+  }
+  yield undefined;
+
+  // Test install with a valid receipt and a not valid one
+  var request = navigator.mozApps.install(gManifestURL, { receipts: [ receipt_few_segments, valid_receipt1 ]});
+  request.onsuccess = function() {
+    ok(false, "Less than 3 segments");
+  }
+  request.onerror = function() {
+    ok(this.error.name == "INVALID_SEGMENTS_NUMBER",
+       "Less than 3 segments");
+    continueTest();
+  }
+  yield undefined;
+
+  // All done.
+  ok(true, "All done");
+  finish();
+}
+
+addLoadEvent(go);
+
+</script>
+</pre>
+</body>
+</html>
\ No newline at end of file
--- a/dom/bindings/BindingDeclarations.h
+++ b/dom/bindings/BindingDeclarations.h
@@ -317,17 +317,19 @@ public:
   }
 };
 
 // Specialization for strings.
 // XXXbz we can't pull in FakeDependentString here, because it depends on
 // internal strings.  So we just have to forward-declare it and reimplement its
 // ToAStringPtr.
 
+namespace binding_detail {
 struct FakeDependentString;
+} // namespace binding_detail
 
 template<>
 class Optional<nsAString>
 {
 public:
   Optional() : mPassed(false) {}
 
   bool WasPassed() const
@@ -339,17 +341,17 @@ public:
   {
     MOZ_ASSERT(str);
     mStr = str;
     mPassed = true;
   }
 
   // If this code ever goes away, remove the comment pointing to it in the
   // FakeDependentString class in BindingUtils.h.
-  void operator=(const FakeDependentString* str)
+  void operator=(const binding_detail::FakeDependentString* str)
   {
     MOZ_ASSERT(str);
     mStr = reinterpret_cast<const nsDependentString*>(str);
     mPassed = true;
   }
 
   const nsAString& Value() const
   {
--- a/dom/bindings/BindingUtils.h
+++ b/dom/bindings/BindingUtils.h
@@ -1451,16 +1451,18 @@ HasPropertyOnPrototype(JSContext* cx, JS
 // shadowPrototypeProperties is false then skip properties that are also
 // present on the proto chain of proxy.  If shadowPrototypeProperties is true,
 // then the "proxy" argument is ignored.
 bool
 AppendNamedPropertyIds(JSContext* cx, JS::Handle<JSObject*> proxy,
                        nsTArray<nsString>& names,
                        bool shadowPrototypeProperties, JS::AutoIdVector& props);
 
+namespace binding_detail {
+
 // A struct that has the same layout as an nsDependentString but much
 // faster constructor and destructor behavior
 struct FakeDependentString {
   FakeDependentString() :
     mFlags(nsDependentString::F_TERMINATED)
   {
   }
 
@@ -1528,29 +1530,31 @@ private:
                     "Offset of mLength should match");
       static_assert(offsetof(FakeDependentString, mFlags) ==
                       offsetof(DepedentStringAsserter, mFlags),
                     "Offset of mFlags should match");
     }
   };
 };
 
+} // namespace binding_detail
+
 enum StringificationBehavior {
   eStringify,
   eEmpty,
   eNull
 };
 
 // pval must not be null and must point to a rooted JS::Value
 static inline bool
 ConvertJSValueToString(JSContext* cx, JS::Handle<JS::Value> v,
                        JS::MutableHandle<JS::Value> pval,
                        StringificationBehavior nullBehavior,
                        StringificationBehavior undefinedBehavior,
-                       FakeDependentString& result)
+                       binding_detail::FakeDependentString& result)
 {
   JSString *s;
   if (v.isString()) {
     s = v.toString();
   } else {
     StringificationBehavior behavior;
     if (v.isNull()) {
       behavior = nullBehavior;
@@ -1592,29 +1596,33 @@ ConvertJSValueToByteString(JSContext* cx
                            nsACString& result);
 
 template<typename T>
 void DoTraceSequence(JSTracer* trc, FallibleTArray<T>& seq);
 template<typename T>
 void DoTraceSequence(JSTracer* trc, InfallibleTArray<T>& seq);
 
 // Class for simple sequence arguments, only used internally by codegen.
+namespace binding_detail {
+
 template<typename T>
 class AutoSequence : public AutoFallibleTArray<T, 16>
 {
 public:
   AutoSequence() : AutoFallibleTArray<T, 16>()
   {}
 
   // Allow converting to const sequences as needed
   operator const Sequence<T>&() const {
     return *reinterpret_cast<const Sequence<T>*>(this);
   }
 };
 
+} // namespace binding_detail
+
 // Class used to trace sequences, with specializations for various
 // sequence types.
 template<typename T,
          bool isDictionary=IsBaseOf<DictionaryBase, T>::value,
          bool isTypedArray=IsBaseOf<AllTypedArraysBase, T>::value>
 class SequenceTracer
 {
   explicit SequenceTracer() MOZ_DELETE; // Should never be instantiated
@@ -2039,16 +2047,49 @@ T& NonNullHelper(OwningNonNull<T>& aArg)
 }
 
 template<typename T>
 const T& NonNullHelper(const OwningNonNull<T>& aArg)
 {
   return aArg;
 }
 
+inline
+void NonNullHelper(NonNull<binding_detail::FakeDependentString>& aArg)
+{
+  // This overload is here to make sure that we never end up applying
+  // NonNullHelper to a NonNull<binding_detail::FakeDependentString>. If we
+  // try to, it should fail to compile, since presumably the caller will try to
+  // use our nonexistent return value.
+}
+
+inline
+void NonNullHelper(const NonNull<binding_detail::FakeDependentString>& aArg)
+{
+  // This overload is here to make sure that we never end up applying
+  // NonNullHelper to a NonNull<binding_detail::FakeDependentString>. If we
+  // try to, it should fail to compile, since presumably the caller will try to
+  // use our nonexistent return value.
+}
+
+inline
+void NonNullHelper(binding_detail::FakeDependentString& aArg)
+{
+  // This overload is here to make sure that we never end up applying
+  // NonNullHelper to a FakeDependentString before we've constified it.  If we
+  // try to, it should fail to compile, since presumably the caller will try to
+  // use our nonexistent return value.
+}
+
+MOZ_ALWAYS_INLINE
+const nsAString& NonNullHelper(const binding_detail::FakeDependentString& aArg)
+{
+  return aArg;
+}
+
 // Reparent the wrapper of aObj to whatever its native now thinks its
 // parent should be.
 nsresult
 ReparentWrapper(JSContext* aCx, JS::Handle<JSObject*> aObj);
 
 /**
  * Used to implement the hasInstance hook of an interface object.
  *
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -3025,17 +3025,17 @@ def getJSToNativeConversionInfo(type, de
         # optional or nullable complexity going on.  In that situation, we can
         # use an AutoSequence instead.  We have to keep using Sequence in the
         # nullable and optional cases because we don't want to leak the
         # AutoSequence type to consumers, which would be unavoidable with
         # Nullable<AutoSequence> or Optional<AutoSequence>.
         if isMember or isOptional or nullable or isCallbackReturnValue:
             sequenceClass = "Sequence"
         else:
-            sequenceClass = "AutoSequence"
+            sequenceClass = "binding_detail::AutoSequence"
 
         # XXXbz we can't include the index in the the sourceDescription, because
         # we don't really have a way to pass one in dynamically at runtime...
         elementInfo = getJSToNativeConversionInfo(
             elementType, descriptorProvider, isMember="Sequence",
             exceptionCode=exceptionCode, lenientFloatCode=lenientFloatCode,
             isCallbackReturnValue=isCallbackReturnValue,
             sourceDescription="element of %s" % sourceDescription)
@@ -3631,36 +3631,40 @@ for (uint32_t i = 0; i < length; ++i) {
             if isMember == "Variadic":
                 # The string is kept alive by the argument, so we can just
                 # depend on it.
                 assignString = "${declName}.Rebind(str.Data(), str.Length())"
             else:
                 assignString = "${declName} = str"
             return JSToNativeConversionInfo(
                 "{\n"
-                "  FakeDependentString str;\n"
+                "  binding_detail::FakeDependentString str;\n"
                 "%s\n"
                 "  %s;\n"
                 "}\n" % (
                     CGIndenter(CGGeneric(getConversionCode("str"))).define(),
                     assignString),
                 declType=declType, dealWithOptional=isOptional)
 
         if isOptional:
             declType = "Optional<nsAString>"
-        else:
-            declType = "NonNull<nsAString>"
+            holderType = CGGeneric("binding_detail::FakeDependentString")
+            conversionCode = ("%s\n"
+                              "${declName} = &${holderName};" %
+                              getConversionCode("${holderName}"))
+        else:
+            declType = "binding_detail::FakeDependentString"
+            holderType = None
+            conversionCode = getConversionCode("${declName}")
 
         # No need to deal with optional here; we handled it already
         return JSToNativeConversionInfo(
-            ("%s\n"
-             "${declName} = &${holderName};" %
-             getConversionCode("${holderName}")),
+            conversionCode,
             declType=CGGeneric(declType),
-            holderType=CGGeneric("FakeDependentString"))
+            holderType=holderType)
 
     if type.isByteString():
         assert not isEnforceRange and not isClamp
 
         nullable = toStringBool(type.nullable())
 
         conversionCode = (
             "if (!ConvertJSValueToByteString(cx, ${val}, ${mutableVal},"
@@ -3827,17 +3831,17 @@ for (uint32_t i = 0; i < length; ++i) {
         # should be able to assume not isOptional here.
         assert not isOptional
 
         typeName = CGDictionary.makeDictionaryName(type.inner)
         if not isMember and not isCallbackReturnValue:
             # Since we're not a member and not nullable or optional, no one will
             # see our real type, so we can do the fast version of the dictionary
             # that doesn't pre-initialize members.
-            typeName = "dictionary_detail::Fast" + typeName
+            typeName = "binding_detail::Fast" + typeName
 
         declType = CGGeneric(typeName)
 
         # We do manual default value handling here, because we
         # actually do want a jsval, and we only handle null anyway
         # NOTE: if isNullOrUndefined or isDefinitelyObject are true,
         # we know we have a value, so we don't have to worry about the
         # default value.
@@ -4165,17 +4169,17 @@ class CGArgumentConverter(CGThing):
 
         # Variadic arguments get turned into a sequence.
         if typeConversion.dealWithOptional:
             raise TypeError("Shouldn't have optional things in variadics")
         if typeConversion.holderType is not None:
             raise TypeError("Shouldn't need holders for variadics")
 
         replacer = dict(self.argcAndIndex, **self.replacementVariables)
-        replacer["seqType"] = CGTemplatedType("AutoSequence",
+        replacer["seqType"] = CGTemplatedType("binding_detail::AutoSequence",
                                               typeConversion.declType).define()
         if typeNeedsRooting(self.argument.type):
             rooterDecl = ("SequenceRooter<%s> ${holderName}(cx, &${declName});\n" %
                           typeConversion.declType.define())
         else:
             rooterDecl = ""
         replacer["elemType"] = typeConversion.declType.define()
 
@@ -6937,17 +6941,17 @@ class CGUnionStruct(CGThing):
                 if self.ownsMembers:
                     methods.append(vars["setter"])
                     if t.isString():
                         methods.append(
                             ClassMethod("SetStringData", "void",
                                 [Argument("const nsString::char_type*", "aData"),
                                  Argument("nsString::size_type", "aLength")],
                                 inline=True, bodyInHeader=True,
-                                body="mValue.mString.Value().Assign(aData, aLength);"))
+                                body="SetAsString().Assign(aData, aLength);"))
 
             body = string.Template('MOZ_ASSERT(Is${name}(), "Wrong type!");\n'
                                    'mValue.m${name}.Destroy();\n'
                                    'mType = eUninitialized;').substitute(vars)
             methods.append(ClassMethod("Destroy" + vars["name"],
                                        "void",
                                        [],
                                        visibility="private",
@@ -7136,17 +7140,17 @@ class CGUnionConversionStruct(CGThing):
                                            bodyInHeader=True,
                                            body=body,
                                            visibility="private"))
                 if t.isString():
                     methods.append(ClassMethod("SetStringData", "void",
                                      [Argument("const nsDependentString::char_type*", "aData"),
                                       Argument("nsDependentString::size_type", "aLength")],
                                      inline=True, bodyInHeader=True,
-                                     body="mStringHolder.SetData(aData, aLength);"))
+                                     body="SetAsString().SetData(aData, aLength);"))
 
             if vars["holderType"] is not None:
                 members.append(ClassMember("m%sHolder" % vars["name"],
                                            vars["holderType"]))
 
         return CGClass(structName + "Argument",
                        members=members,
                        constructors=[ctor],
@@ -7960,17 +7964,17 @@ class CGProxyNamedOperation(CGProxySpeci
             unwrapString = ("nameVal = %s;\n" % self.value) + unwrapString
 
         # Sadly, we have to set up nameVal even if we have an atom id,
         # because we don't know for sure, and we can end up needing it
         # so it needs to be higher up the stack.  Using a Maybe here
         # seems like probable overkill.
         return ("JS::Rooted<JS::Value> nameVal(cx);\n" +
                 idDecl +
-                ("FakeDependentString %s;\n" % argName) +
+                ("binding_detail::FakeDependentString %s;\n" % argName) +
                 unwrapString +
                 ("\n"
                  "\n"
                  "%s* self = UnwrapProxy(proxy);\n" %
                  self.descriptor.nativeType) +
                 CGProxySpecialOperation.define(self))
 
 class CGProxyNamedGetter(CGProxyNamedOperation):
@@ -9253,17 +9257,17 @@ if (""",
             )
 
         fastStruct = CGClass("Fast" + selfName,
             bases=[ClassBase(selfName)],
             constructors=[fastDictionaryCtor],
             isStruct=True)
 
         return CGList([struct,
-                       CGNamespace.build(['dictionary_detail'],
+                       CGNamespace.build(['binding_detail'],
                                          fastStruct)],
                       "\n")
 
     def deps(self):
         return self.dictionary.getDeps()
 
     @staticmethod
     def makeDictionaryName(dictionary):
@@ -11596,16 +11600,18 @@ struct PrototypeTraits;
         (includes, implincludes,
          declarations, unions) = UnionTypes(config.getDescriptors(),
                                             config.getDictionaries(),
                                             config.getCallbacks(),
                                             config)
         includes.add("mozilla/dom/OwningNonNull.h")
         includes.add("mozilla/dom/UnionMember.h")
         includes.add("mozilla/dom/BindingDeclarations.h")
+        # Need BindingUtils.h for FakeDependentString
+        includes.add("mozilla/dom/BindingUtils.h")
         implincludes.add("mozilla/dom/PrimitiveConversions.h")
 
         # Wrap all of that in our namespaces.
         curr = CGNamespace.build(['mozilla', 'dom'], unions)
 
         curr = CGWrapper(curr, post='\n')
 
         namespaces = []
--- a/dom/browser-element/BrowserElementPanning.js
+++ b/dom/browser-element/BrowserElementPanning.js
@@ -9,16 +9,22 @@
 dump("############################### browserElementPanning.js loaded\n");
 
 let { classes: Cc, interfaces: Ci, results: Cr, utils: Cu }  = Components;
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/Geometry.jsm");
 
 var global = this;
 
+const kObservedEvents = [
+  "BEC:ShownModalPrompt",
+  "Activity:Success",
+  "Activity:Error"
+];
+
 const ContentPanning = {
   // Are we listening to touch or mouse events?
   watchedEventsType: '',
 
   // Are mouse events being delivered to this content along with touch
   // events, in violation of spec?
   hybridEvents: false,
 
@@ -50,22 +56,27 @@ const ContentPanning = {
     events.forEach(function(type) {
       // Using the system group for mouse/touch events to avoid
       // missing events if .stopPropagation() has been called.
       els.addSystemEventListener(global, type,
                                  this.handleEvent.bind(this),
                                  /* useCapture = */ false);
     }.bind(this));
 
+    addEventListener("unload",
+		     this._unloadHandler.bind(this),
+		     /* useCapture = */ false,
+		     /* wantsUntrusted = */ false);
+
     addMessageListener("Viewport:Change", this._recvViewportChange.bind(this));
     addMessageListener("Gesture:DoubleTap", this._recvDoubleTap.bind(this));
     addEventListener("visibilitychange", this._handleVisibilityChange.bind(this));
-    Services.obs.addObserver(this, "BEC:ShownModalPrompt", false);
-    Services.obs.addObserver(this, "Activity:Success", false);
-    Services.obs.addObserver(this, "Activity:Error", false);
+    kObservedEvents.forEach((topic) => {
+      Services.obs.addObserver(this, topic, false);
+    });
   },
 
   handleEvent: function cp_handleEvent(evt) {
     this._tryDelayMouseEvents();
 
     if (evt.defaultPrevented || evt.multipleActionsPrevented) {
       // clean up panning state even if touchend/mouseup has been preventDefault.
       if(evt.type === 'touchend' || evt.type === 'mouseup') {
@@ -591,16 +602,22 @@ const ContentPanning = {
     delete this.primaryPointerId;
     this._activationTimer.cancel();
 
     // If there is a scroll action but the application is not managed by
     // the AsyncPanZoom controller, let's do a manual kinetic panning action.
     if (this.panning && docShell.asyncPanZoomEnabled === false) {
       KineticPanning.start(this);
     }
+  },
+
+  _unloadHandler: function() {
+    kObservedEvents.forEach((topic) => {
+      Services.obs.removeObserver(this, topic);
+    });
   }
 };
 
 // Min/max velocity of kinetic panning. This is in pixels/millisecond.
 const kMinVelocity = 0.2;
 const kMaxVelocity = 6;
 
 // Constants that affect the "friction" of the scroll pane.
--- a/dom/events/nsJSEventListener.cpp
+++ b/dom/events/nsJSEventListener.cpp
@@ -168,17 +168,17 @@ nsJSEventListener::HandleEvent(nsIDOMEve
 
     NS_ENSURE_TRUE(aEvent, NS_ERROR_UNEXPECTED);
     InternalScriptErrorEvent* scriptEvent =
       aEvent->GetInternalNSEvent()->AsScriptErrorEvent();
     if (scriptEvent &&
         (scriptEvent->message == NS_LOAD_ERROR ||
          scriptEvent->typeString.EqualsLiteral("error"))) {
       errorMsg = scriptEvent->errorMsg;
-      msgOrEvent.SetAsString() = static_cast<nsAString*>(&errorMsg);
+      msgOrEvent.SetAsString().SetData(errorMsg.Data(), errorMsg.Length());
 
       file = scriptEvent->fileName;
       fileName = &file;
 
       lineNumber.Construct();
       lineNumber.Value() = scriptEvent->lineNr;
     } else {
       msgOrEvent.SetAsEvent() = aEvent->InternalDOMEvent();
--- a/dom/media/MediaManager.cpp
+++ b/dom/media/MediaManager.cpp
@@ -873,16 +873,17 @@ public:
     MOZ_ASSERT(mSuccess.mRawPtr);
     MOZ_ASSERT(mError.mRawPtr);
 
     // We add a disabled listener to the StreamListeners array until accepted
     // If this was the only active MediaStream, remove the window from the list.
     if (NS_IsMainThread()) {
       // This is safe since we're on main-thread, and the window can only
       // be invalidated from the main-thread (see OnNavigation)
+      nsCOMPtr<nsIDOMGetUserMediaSuccessCallback> success(mSuccess);
       nsCOMPtr<nsIDOMGetUserMediaErrorCallback> error(mError);
       error->OnError(aErrorMsg);
 
       // Should happen *after* error runs for consistency, but may not matter
       nsRefPtr<MediaManager> manager(MediaManager::GetInstance());
       manager->RemoveFromWindowList(mWindowID, mListener);
     } else {
       // This will re-check the window being alive on main-thread
new file mode 100644
--- /dev/null
+++ b/dom/media/tests/mochitest/NetworkPreparationChromeScript.js
@@ -0,0 +1,65 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+const { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
+const { Services } = Cu.import('resource://gre/modules/Services.jsm');
+
+var browser = Services.wm.getMostRecentWindow('navigator:browser');
+var connection = browser.navigator.mozMobileConnections[0];
+
+// provide a fake APN and enable data connection.
+function enableDataConnection() {
+  let setLock = browser.navigator.mozSettings.createLock();
+  setLock.set({
+    'ril.data.enabled': true,
+    'ril.data.apnSettings': [
+      [
+        {'carrier':'T-Mobile US',
+         'apn':'epc.tmobile.com',
+         'mmsc':'http://mms.msg.eng.t-mobile.com/mms/wapenc',
+         'types':['default','supl','mms']}
+      ]
+    ]
+  });
+}
+
+// enable 3G radio
+function enableRadio() {
+  if (connection.radioState !== 'enabled') {
+    connection.setRadioEnabled(true);
+  }
+}
+
+// disable 3G radio
+function disableRadio() {
+  if (connection.radioState === 'enabled') {
+    connection.setRadioEnabled(false);
+  }
+}
+
+addMessageListener('prepare-network', function(message) {
+  //RIL DOM events will be pending until RIL receiveing system-message-listener-ready event.
+  Services.obs.notifyObservers(null, 'system-message-listener-ready', null);
+
+  connection.addEventListener('datachange', function onDataChange() {
+    if (connection.data.connected) {
+      connection.removeEventListener('datachange', onDataChange);
+      Services.prefs.setIntPref('network.proxy.type', 2);
+      sendAsyncMessage('network-ready', true);
+    }
+  });
+
+  enableRadio();
+  enableDataConnection();
+});
+
+addMessageListener('network-cleanup', function(message) {
+  connection.addEventListener('datachange', function onDataChange() {
+    if (!connection.data.connected) {
+      connection.removeEventListener('datachange', onDataChange);
+      Services.prefs.setIntPref('network.proxy.type', 2);
+      sendAsyncMessage('network-disabled', true);
+    }
+  });
+  disableRadio();
+});
--- a/dom/media/tests/mochitest/mochitest.ini
+++ b/dom/media/tests/mochitest/mochitest.ini
@@ -1,14 +1,15 @@
 [DEFAULT]
 support-files =
   head.js
   mediaStreamPlayback.js
   pc.js
   templates.js
+  NetworkPreparationChromeScript.js
 
 [test_dataChannel_basicAudio.html]
 [test_dataChannel_basicAudioVideo.html]
 # Disabled on OS X for bug 930481 timeouts
 skip-if = os == 'mac'
 [test_dataChannel_basicAudioVideoCombined.html]
 # Disabled on OS X for bug 930481 timeouts
 skip-if = os == 'mac'
@@ -47,8 +48,10 @@ skip-if = os == 'mac'
 [test_peerConnection_setLocalAnswerInHaveLocalOffer.html]
 [test_peerConnection_setLocalAnswerInStable.html]
 [test_peerConnection_setLocalOfferInHaveRemoteOffer.html]
 [test_peerConnection_setRemoteAnswerInHaveRemoteOffer.html]
 [test_peerConnection_setRemoteAnswerInStable.html]
 [test_peerConnection_setRemoteOfferInHaveLocalOffer.html]
 [test_peerConnection_throwInCallbacks.html]
 [test_peerConnection_toJSON.html]
+# Bug950317: Hack for making a cleanup hook after finishing all WebRTC cases
+[test_zmedia_cleanup.html]
--- a/dom/media/tests/mochitest/pc.js
+++ b/dom/media/tests/mochitest/pc.js
@@ -318,16 +318,85 @@ MediaElementChecker.prototype = {
    * state of the media element is HAVE_METADATA.
    */
   checkForNoMediaFlow : function MEC_CheckForNoMediaFlow() {
     ok(this.element.readyState === HTMLMediaElement.HAVE_METADATA,
        'Media element has a ready state of HAVE_METADATA');
   }
 };
 
+/**
+ * Query function for determining if any IP address is available for
+ * generating SDP.
+ *
+ * @return false if required additional network setup.
+ */
+function isNetworkReady() {
+  // for gonk platform
+  if ("nsINetworkInterfaceListService" in SpecialPowers.Ci) {
+    var listService = SpecialPowers.Cc["@mozilla.org/network/interface-list-service;1"]
+                        .getService(SpecialPowers.Ci.nsINetworkInterfaceListService);
+    var itfList = listService.getDataInterfaceList(
+          SpecialPowers.Ci.nsINetworkInterfaceListService.LIST_NOT_INCLUDE_MMS_INTERFACES |
+          SpecialPowers.Ci.nsINetworkInterfaceListService.LIST_NOT_INCLUDE_SUPL_INTERFACES);
+    var num = itfList.getNumberOfInterface();
+    for (var i = 0; i < num; i++) {
+      if (itfList.getInterface(i).ip) {
+        info("Network interface is ready with address: " + itfList.getInterface(i).ip);
+        return true;
+      }
+    }
+    // ip address is not available
+    info("Network interface is not ready, required additional network setup");
+    return false;
+  }
+  info("Network setup is not required");
+  return true;
+}
+
+/**
+ * Network setup utils for Gonk
+ *
+ * @return {object} providing functions for setup/teardown data connection
+ */
+function getNetworkUtils() {
+  var url = SimpleTest.getTestFileURL("NetworkPreparationChromeScript.js");
+  var script = SpecialPowers.loadChromeScript(url);
+
+  var utils = {
+    /**
+     * Utility for setting up data connection.
+     *
+     * @param aCallback callback after data connection is ready.
+     */
+    prepareNetwork: function(aCallback) {
+      script.addMessageListener('network-ready', function (message) {
+        info("Network interface is ready");
+        aCallback();
+      });
+      info("Setup network interface");
+      script.sendAsyncMessage("prepare-network", true);
+    },
+    /**
+     * Utility for tearing down data connection.
+     *
+     * @param aCallback callback after data connection is closed.
+     */
+    tearDownNetwork: function(aCallback) {
+      script.addMessageListener('network-disabled', function (message) {
+        ok(true, 'network-disabled');
+        script.destroy();
+        aCallback();
+      });
+      script.sendAsyncMessage("network-cleanup", true);
+    }
+  };
+
+  return utils;
+}
 
 /**
  * This class handles tests for peer connections.
  *
  * @constructor
  * @param {object} [options={}]
  *        Optional options for the peer connection test
  * @param {object} [options.commands=commandsPeerConnection]
@@ -344,16 +413,37 @@ MediaElementChecker.prototype = {
  */
 function PeerConnectionTest(options) {
   // If no options are specified make it an empty object
   options = options || { };
   options.commands = options.commands || commandsPeerConnection;
   options.is_local = "is_local" in options ? options.is_local : true;
   options.is_remote = "is_remote" in options ? options.is_remote : true;
 
+  var netTeardownCommand = null;
+  if (!isNetworkReady()) {
+    var utils = getNetworkUtils();
+    // Trigger network setup to obtain IP address before creating any PeerConnection.
+    utils.prepareNetwork(function() {
+      ok(isNetworkReady(),'setup network connection successfully');
+    });
+
+    netTeardownCommand = [
+      [
+        'TEARDOWN_NETWORK',
+        function(test) {
+          utils.tearDownNetwork(function() {
+            info('teardown network connection');
+            test.next();
+          });
+        }
+      ]
+    ];
+  }
+
   if (options.is_local)
     this.pcLocal = new PeerConnectionWrapper('pcLocal', options.config_pc1);
   else
     this.pcLocal = null;
 
   if (options.is_remote)
     this.pcRemote = new PeerConnectionWrapper('pcRemote', options.config_pc2 || options.config_pc1);
   else
@@ -365,16 +455,21 @@ function PeerConnectionTest(options) {
   this.chain = new CommandChain(this, options.commands);
   if (!options.is_local) {
     this.chain.filterOut(/^PC_LOCAL/);
   }
   if (!options.is_remote) {
     this.chain.filterOut(/^PC_REMOTE/);
   }
 
+  // Insert network teardown after testcase execution.
+  if (netTeardownCommand) {
+    this.chain.append(netTeardownCommand);
+  }
+
   var self = this;
   this.chain.onFinished = function () {
     self.teardown();
   };
 }
 
 /**
  * Closes the peer connection if it is active
new file mode 100644
--- /dev/null
+++ b/dom/media/tests/mochitest/test_zmedia_cleanup.html
@@ -0,0 +1,29 @@
+<!DOCTYPE HTML>
+<html>
+  <head>
+    <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+    <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  </head>
+<body>
+<pre id="test">
+<script type="application/javascript">
+SimpleTest.waitForExplicitFinish();
+
+if ("nsINetworkInterfaceListService" in SpecialPowers.Ci) {
+  var url = SimpleTest.getTestFileURL("NetworkPreparationChromeScript.js");
+  var script = SpecialPowers.loadChromeScript(url);
+  script.addMessageListener('network-disabled', function (message) {
+    ok(true, 'network-disabled');
+    script.destroy();
+    SimpleTest.finish();
+  });
+  script.sendAsyncMessage("network-cleanup", true);
+} else {
+  ok(true, 'no need to cleanup network interface');
+  SimpleTest.finish();
+}
+
+</script>
+</pre>
+</body>
+</html>
--- a/dom/mobileconnection/src/MobileConnection.cpp
+++ b/dom/mobileconnection/src/MobileConnection.cpp
@@ -102,18 +102,16 @@ MobileConnection::Init(nsPIDOMWindow* aW
 
   mWindow = do_GetWeakReference(aWindow);
   mListener = new Listener(this);
 
   if (CheckPermission("mobileconnection")) {
     DebugOnly<nsresult> rv = mProvider->RegisterMobileConnectionMsg(mClientId, mListener);
     NS_WARN_IF_FALSE(NS_SUCCEEDED(rv),
                      "Failed registering mobile connection messages with provider");
-
-    printf_stderr("MobileConnection initialized");
   }
 }
 
 void
 MobileConnection::Shutdown()
 {
   if (mProvider && mListener) {
     mListener->Disconnect();
--- a/dom/network/tests/unit_stats/test_networkstats_db.js
+++ b/dom/network/tests/unit_stats/test_networkstats_db.js
@@ -168,21 +168,18 @@ add_test(function test_internalSaveStats
       do_check_eq(result[0].rxTotalBytes, stats.rxTotalBytes);
       do_check_eq(result[0].txTotalBytes, stats.txTotalBytes);
       run_next_test();
     });
   });
 });
 
 add_test(function test_internalSaveStats_arraySamples() {
-  var networks = getNetworks();
-
-  netStatsDb.clearStats(networks, function (error, result) {
-    do_check_eq(error, null);
-
+  clearStore('net_stats_store', function() {
+    var networks = getNetworks();
     var network = [networks[0].id, networks[0].type];
 
     var samples = 2;
     var stats = [];
     for (var i = 0; i < samples; i++) {
       stats.push({ appId:         0,
                    serviceType:   "",
                    network:       network,
@@ -198,22 +195,19 @@ add_test(function test_internalSaveStats
     netStatsDb.dbNewTxn("net_stats_store", "readwrite", function(txn, store) {
       netStatsDb._saveStats(txn, store, stats);
     }, function(error, result) {
       do_check_eq(error, null);
 
       netStatsDb.logAllRecords(function(error, result) {
         do_check_eq(error, null);
 
-        // Result has one sample more than samples because clear inserts
-        // an empty sample to keep totalBytes synchronized with netd counters
-        result.shift();
         do_check_eq(result.length, samples);
         var success = true;
-        for (var i = 1; i < samples; i++) {
+        for (var i = 0; i < samples; i++) {
           if (result[i].appId != stats[i].appId ||
               result[i].serviceType != stats[i].serviceType ||
               !compareNetworks(result[i].network, stats[i].network) ||
               result[i].timestamp != stats[i].timestamp ||
               result[i].rxBytes != stats[i].rxBytes ||
               result[i].txBytes != stats[i].txBytes ||
               result[i].rxSystemBytes != stats[i].rxSystemBytes ||
               result[i].txSystemBytes != stats[i].txSystemBytes ||
@@ -226,21 +220,18 @@ add_test(function test_internalSaveStats
         do_check_true(success);
         run_next_test();
       });
     });
   });
 });
 
 add_test(function test_internalRemoveOldStats() {
-  var networks = getNetworks();
-
-  netStatsDb.clearStats(networks, function (error, result) {
-    do_check_eq(error, null);
-
+  clearStore('net_stats_store', function() {
+    var networks = getNetworks();
     var network = [networks[0].id, networks[0].type];
     var samples = 10;
     var stats = [];
     for (var i = 0; i < samples - 1; i++) {
       stats.push({ appId:               0, serviceType: "",
                    network:       network, timestamp:     Date.now() + (10 * i),
                    rxBytes:             0, txBytes:       0,
                    rxSystemBytes:    1234, txSystemBytes: 1234,
@@ -267,18 +258,17 @@ add_test(function test_internalRemoveOld
 
         run_next_test();
       });
     });
   });
 });
 
 function processSamplesDiff(networks, lastStat, newStat, callback) {
-  netStatsDb.clearStats(networks, function (error, result){
-    do_check_eq(error, null);
+  clearStore('net_stats_store', function() {
     netStatsDb.dbNewTxn("net_stats_store", "readwrite", function(txn, store) {
       netStatsDb._saveStats(txn, store, lastStat);
     }, function(error, result) {
       netStatsDb.dbNewTxn("net_stats_store", "readwrite", function(txn, store) {
         let request = store.index("network").openCursor(newStat.network, "prev");
         request.onsuccess = function onsuccess(event) {
           let cursor = event.target.result;
           do_check_neq(cursor, null);
@@ -443,39 +433,33 @@ add_test(function test_saveAppStats() {
                 serviceType:    "",
                 networkId:      networks[0].id,
                 networkType:    networks[0].type,
                 date:           new Date(),
                 rxBytes:        2234,
                 txBytes:        2234,
                 isAccumulative: false };
 
-  netStatsDb.clearStats(networks, function (error, result) {
-    do_check_eq(error, null);
+  clearStore('net_stats_store', function() {
     netStatsDb.saveStats(stats, function(error, result) {
       do_check_eq(error, null);
       netStatsDb.logAllRecords(function(error, result) {
         do_check_eq(error, null);
-        // The clear function clears all records of the datbase but
-        // inserts a new element for each [appId, connectionId, connectionType]
-        // record to keep the track of rxTotalBytes / txTotalBytes.
-        // So at this point, we have two records, one for the appId 0 used in
-        // past tests and the new one for appId 1
-        do_check_eq(result.length, 2);
-        do_check_eq(result[1].appId, stats.appId);
-        do_check_eq(result[1].serviceType, stats.serviceType);
-        do_check_true(compareNetworks(result[1].network, network));
+        do_check_eq(result.length, 1);
+        do_check_eq(result[0].appId, stats.appId);
+        do_check_eq(result[0].serviceType, stats.serviceType);
+        do_check_true(compareNetworks(result[0].network, network));
         let timestamp = filterTimestamp(stats.date);
-        do_check_eq(result[1].timestamp, timestamp);
-        do_check_eq(result[1].rxBytes, stats.rxBytes);
-        do_check_eq(result[1].txBytes, stats.txBytes);
-        do_check_eq(result[1].rxSystemBytes, 0);
-        do_check_eq(result[1].txSystemBytes, 0);
-        do_check_eq(result[1].rxTotalBytes, 0);
-        do_check_eq(result[1].txTotalBytes, 0);
+        do_check_eq(result[0].timestamp, timestamp);
+        do_check_eq(result[0].rxBytes, stats.rxBytes);
+        do_check_eq(result[0].txBytes, stats.txBytes);
+        do_check_eq(result[0].rxSystemBytes, 0);
+        do_check_eq(result[0].txSystemBytes, 0);
+        do_check_eq(result[0].rxTotalBytes, 0);
+        do_check_eq(result[0].txTotalBytes, 0);
         run_next_test();
       });
     });
   });
 });
 
 add_test(function test_saveServiceStats() {
   var networks = getNetworks();
@@ -485,46 +469,41 @@ add_test(function test_saveServiceStats(
                 serviceType:    "FakeType",
                 networkId:      networks[0].id,
                 networkType:    networks[0].type,
                 date:           new Date(),
                 rxBytes:        2234,
                 txBytes:        2234,
                 isAccumulative: false };
 
-  netStatsDb.clearStats(networks, function (error, result) {
-    do_check_eq(error, null);
+  clearStore('net_stats_store', function() {
     netStatsDb.saveStats(stats, function(error, result) {
       do_check_eq(error, null);
       netStatsDb.logAllRecords(function(error, result) {
         do_check_eq(error, null);
-        // Again, at this point, we have two records, one for the appId 0 and 
-        // empty serviceType used in past tests and the new one for appId 0 and
-        // non-empty serviceType.
-        do_check_eq(result.length, 2);
-        do_check_eq(result[1].appId, stats.appId);
-        do_check_eq(result[1].serviceType, stats.serviceType);
-        do_check_true(compareNetworks(result[1].network, network));
+        do_check_eq(result.length, 1);
+        do_check_eq(result[0].appId, stats.appId);
+        do_check_eq(result[0].serviceType, stats.serviceType);
+        do_check_true(compareNetworks(result[0].network, network));
         let timestamp = filterTimestamp(stats.date);
-        do_check_eq(result[1].timestamp, timestamp);
-        do_check_eq(result[1].rxBytes, stats.rxBytes);
-        do_check_eq(result[1].txBytes, stats.txBytes);
-        do_check_eq(result[1].rxSystemBytes, 0);
-        do_check_eq(result[1].txSystemBytes, 0);
-        do_check_eq(result[1].rxTotalBytes, 0);
-        do_check_eq(result[1].txTotalBytes, 0);
+        do_check_eq(result[0].timestamp, timestamp);
+        do_check_eq(result[0].rxBytes, stats.rxBytes);
+        do_check_eq(result[0].txBytes, stats.txBytes);
+        do_check_eq(result[0].rxSystemBytes, 0);
+        do_check_eq(result[0].txSystemBytes, 0);
+        do_check_eq(result[0].rxTotalBytes, 0);
+        do_check_eq(result[0].txTotalBytes, 0);
         run_next_test();
       });
     });
   });
 });
 
-function prepareFind(network, stats, callback) {
-  netStatsDb.clearStats(network, function (error, result) {
-    do_check_eq(error, null);
+function prepareFind(stats, callback) {
+  clearStore('net_stats_store', function() {
     netStatsDb.dbNewTxn("net_stats_store", "readwrite", function(txn, store) {
       netStatsDb._saveStats(txn, store, stats);
     }, function(error, result) {
         callback(error, result);
     });
   });
 }
 
@@ -552,17 +531,17 @@ add_test(function test_find () {
 
     stats.push({ appId:                 appId, serviceType:   serviceType,
                  network:       networkMobile, timestamp:     saveDate + (sampleRate * i),
                  rxBytes:                   0, txBytes:       10,
                  rxSystemBytes:             0, txSystemBytes: 0,
                  rxTotalBytes:              0, txTotalBytes:  0 });
   }
 
-  prepareFind(networks[0], stats, function(error, result) {
+  prepareFind(stats, function(error, result) {
     do_check_eq(error, null);
     netStatsDb.find(function (error, result) {
       do_check_eq(error, null);
       do_check_eq(result.serviceType, serviceType);
       do_check_eq(result.network.id, networks[0].id);
       do_check_eq(result.network.type, networks[0].type);
       do_check_eq(result.start.getTime(), start.getTime());
       do_check_eq(result.end.getTime(), end.getTime());
@@ -596,17 +575,17 @@ add_test(function test_findAppStats () {
                  rxTotalBytes:           0, txTotalBytes: 0 });
 
     stats.push({ appId:                appId, serviceType:  serviceType,
                  network:      networkMobile, timestamp:    saveDate + (sampleRate * i),
                  rxBytes:                  0, txBytes:      10,
                  rxTotalBytes:             0, txTotalBytes: 0 });
   }
 
-  prepareFind(networks[0], stats, function(error, result) {
+  prepareFind(stats, function(error, result) {
     do_check_eq(error, null);
     netStatsDb.find(function (error, result) {
       do_check_eq(error, null);
       do_check_eq(result.serviceType, serviceType);
       do_check_eq(result.network.id, networks[0].id);
       do_check_eq(result.network.type, networks[0].type);
       do_check_eq(result.start.getTime(), start.getTime());
       do_check_eq(result.end.getTime(), end.getTime());
@@ -640,17 +619,17 @@ add_test(function test_findServiceStats 
                  rxTotalBytes:           0, txTotalBytes: 0 });
 
     stats.push({ appId:                appId, serviceType:  serviceType,
                  network:      networkMobile, timestamp:    saveDate + (sampleRate * i),
                  rxBytes:                  0, txBytes:      10,
                  rxTotalBytes:             0, txTotalBytes: 0 });
   }
 
-  prepareFind(networks[0], stats, function(error, result) {
+  prepareFind(stats, function(error, result) {
     do_check_eq(error, null);
     netStatsDb.find(function (error, result) {
       do_check_eq(error, null);
       do_check_eq(result.serviceType, serviceType);
       do_check_eq(result.network.id, networks[0].id);
       do_check_eq(result.network.type, networks[0].type);
       do_check_eq(result.start.getTime(), start.getTime());
       do_check_eq(result.end.getTime(), end.getTime());
@@ -715,31 +694,24 @@ add_test(function test_saveMultipleAppSt
     rxBytes:                  0, txBytes:        10,
     serviceType:             "", isAccumulative: false
   };
 
   let keys = Object.keys(cached);
   let index = 0;
 
   networks.push(networkMobile);
-  netStatsDb.clearStats(networks, function (error, result) {
-    do_check_eq(error, null);
+
+  clearStore('net_stats_store', function() {
     netStatsDb.saveStats(cached[keys[index]],
       function callback(error, result) {
         do_check_eq(error, null);
 
         if (index == keys.length - 1) {
           netStatsDb.logAllRecords(function(error, result) {
-            // Again, result has two samples more than expected samples because
-            // clear inserts one empty sample for each network to keep totalBytes
-            // synchronized with netd counters. so the first two samples have to
-            // be discarted.
-            result.shift();
-            result.shift();
-
             do_check_eq(error, null);
             do_check_eq(result.length, 6);
             do_check_eq(result[0].serviceType, serviceType);
             do_check_eq(result[3].appId, 1);
             do_check_true(compareNetworks(result[0].network, [networkWifi.id, networkWifi.type]));
             do_check_eq(result[0].rxBytes, 0);
             do_check_eq(result[0].txBytes, 10);
             run_next_test();
--- a/dom/system/gonk/RadioInterfaceLayer.js
+++ b/dom/system/gonk/RadioInterfaceLayer.js
@@ -773,17 +773,17 @@ function RadioInterfaceLayer() {
       Services.prefs.getBoolPref(kPrefCellBroadcastDisabled);
   } catch(e) {}
 
   try {
     options.clirMode = Services.prefs.getIntPref(kPrefClirModePreference);
   } catch(e) {}
 
   let numIfaces = this.numRadioInterfaces;
-  debug(numIfaces + " interfaces");
+  if (DEBUG) debug(numIfaces + " interfaces");
   this.radioInterfaces = [];
   for (let clientId = 0; clientId < numIfaces; clientId++) {
     options.clientId = clientId;
     this.radioInterfaces.push(new RadioInterface(options));
   }
 
   // TODO: Move 'ril.data.*' settings handler to DataConnectionManager,
   // see bug 905568.
@@ -1305,17 +1305,17 @@ RadioInterface.prototype = {
    */
   getSupportedNetworkTypes: function() {
     let key = "ro.moz.ril." + this.clientId + ".network_types";
     let supportedNetworkTypes = libcutils.property_get(key, "").split(",");
     for (let type of supportedNetworkTypes) {
       // If the value in system property is not valid, use the default one which
       // is defined in ril_consts.js.
       if (RIL.GECKO_SUPPORTED_NETWORK_TYPES.indexOf(type) < 0) {
-        this.debug("Unknown network type: " + type);
+        if (DEBUG) this.debug("Unknown network type: " + type);
         supportedNetworkTypes =
           RIL.GECKO_SUPPORTED_NETWORK_TYPES_DEFAULT.split(",");
         break;
       }
     }
     if (DEBUG) this.debug("Supported Network Types: " + supportedNetworkTypes);
     return supportedNetworkTypes;
   },
@@ -1951,17 +1951,16 @@ RadioInterface.prototype = {
     let data = this.rilContext.data;
 
     if (this.isInfoChanged(message, operatorInfo)) {
       this.updateInfo(message, operatorInfo);
 
       // Update lastKnownNetwork
       if (message.mcc && message.mnc) {
         this._lastKnownNetwork = message.mcc + "-" + message.mnc;
-        if (DEBUG) this.debug("_lastKnownNetwork: " + this._lastKnownNetwork);
       }
 
       // If the voice is unregistered, no need to send RIL:VoiceInfoChanged.
       if (voice.network && !batch) {
         gMessageManager.sendMobileConnectionMessage("RIL:VoiceInfoChanged",
                                                     this.clientId, voice);
       }
 
@@ -2599,17 +2598,17 @@ RadioInterface.prototype = {
    */
   setClockBySntp: function(offset) {
     // Got the SNTP info.
     this.setClockAutoUpdateAvailable(true);
     if (!this._clockAutoUpdateEnabled) {
       return;
     }
     if (this._lastNitzMessage) {
-      debug("SNTP: NITZ available, discard SNTP");
+      if (DEBUG) debug("SNTP: NITZ available, discard SNTP");
       return;
     }
     gTimeService.set(Date.now() + offset);
   },
 
   handleIccMbdn: function(message) {
     let voicemailInfo = this.voicemailInfo;
 
@@ -2654,17 +2653,16 @@ RadioInterface.prototype = {
         Services.prefs.setCharPref("ril.lastKnownSimMcc",
                                    message.mcc.toString());
       } catch (e) {}
     }
 
     // Update lastKnownHomeNetwork.
     if (message.mcc && message.mnc) {
       this._lastKnownHomeNetwork = message.mcc + "-" + message.mnc;
-      this.debug("_lastKnownHomeNetwork: " + this._lastKnownHomeNetwork);
     }
 
     // If spn becomes available, we should check roaming again.
     if (!oldSpn && message.spn) {
       let voice = this.rilContext.voice;
       let data = this.rilContext.data;
       let voiceRoaming = voice.roaming;
       let dataRoaming = data.roaming;
@@ -2810,17 +2808,19 @@ RadioInterface.prototype = {
   handleSettingsChange: function(aName, aResult, aMessage) {
     // Don't allow any content processes to modify the setting
     // "time.clock.automatic-update.available" except for the chrome process.
     if (aName === kSettingsClockAutoUpdateAvailable &&
         aMessage !== "fromInternalSetting") {
       let isClockAutoUpdateAvailable = this._lastNitzMessage !== null ||
                                        this._sntp.isAvailable();
       if (aResult !== isClockAutoUpdateAvailable) {
-        debug("Content processes cannot modify 'time.clock.automatic-update.available'. Restore!");
+        if (DEBUG) {
+          debug("Content processes cannot modify 'time.clock.automatic-update.available'. Restore!");
+        }
         // Restore the setting to the current value.
         this.setClockAutoUpdateAvailable(isClockAutoUpdateAvailable);
       }
     }
 
     // Don't allow any content processes to modify the setting
     // "time.timezone.automatic-update.available" except for the chrome
     // process.
@@ -3753,18 +3753,22 @@ RadioInterface.prototype = {
         if (DEBUG) {
           this.debug("callback handler for " + name + " threw an exception: " + e);
         }
       }
     }
   },
 
   setupDataCallByType: function(apntype) {
+    if (DEBUG) this.debug("setupDataCallByType: " + apntype);
     let apnSetting = this.apnSettings.byType[apntype];
     if (!apnSetting) {
+      if (DEBUG) {
+        this.debug("No apn setting for type: " + apntype);
+      }
       return;
     }
 
     let dataInfo = this.rilContext.data;
     if (dataInfo.state != RIL.GECKO_MOBILE_CONNECTION_STATE_REGISTERED ||
         dataInfo.type == RIL.GECKO_MOBILE_CONNECTION_STATE_UNKNOWN) {
       return;
     }
@@ -3793,18 +3797,22 @@ RadioInterface.prototype = {
 
       Services.obs.notifyObservers(apnSetting.iface,
                                    kNetworkInterfaceStateChangedTopic,
                                    null);
     }
   },
 
   deactivateDataCallByType: function(apntype) {
+    if (DEBUG) this.debug("deactivateDataCallByType: " + apntype);
     let apnSetting = this.apnSettings.byType[apntype];
     if (!apnSetting) {
+      if (DEBUG) {
+        this.debug("No apn setting for type: " + apntype);
+      }
       return;
     }
 
     apnSetting.iface.disconnect(apntype);
     // We just call disconnect() function, so this interface should be in
     // disconnecting state. If this interface is still in connected state, we
     // are sure that other data call types still need this connection of this
     // interface. In this circumstance, we have to directly update the
@@ -4095,36 +4103,37 @@ RILNetworkInterface.prototype = {
                                      kNetworkInterfaceStateChangedTopic,
                                      null);
       }
       return;
     }
 
     this.state = datacall.state;
 
+    Services.obs.notifyObservers(this,
+                                 kNetworkInterfaceStateChangedTopic,
+                                 null);
+
+    if ((this.state == RIL.GECKO_NETWORK_STATE_UNKNOWN ||
+         this.state == RIL.GECKO_NETWORK_STATE_DISCONNECTED) &&
+        this.registeredAsNetworkInterface) {
+      gNetworkManager.unregisterNetworkInterface(this);
+      this.registeredAsNetworkInterface = false;
+      this.cid = null;
+      this.connectedTypes = [];
+    }
+
     // In case the data setting changed while the datacall was being started or
     // ended, let's re-check the setting and potentially adjust the datacall
     // state again.
     if (this.radioInterface.apnSettings.byType.default &&
         (this.radioInterface.apnSettings.byType.default.apn ==
          this.apnSetting.apn)) {
       this.radioInterface.updateRILNetworkInterface();
     }
-
-    Services.obs.notifyObservers(this,
-                                 kNetworkInterfaceStateChangedTopic,
-                                 null);
-
-    if (this.state == RIL.GECKO_NETWORK_STATE_UNKNOWN &&
-        this.registeredAsNetworkInterface) {
-      gNetworkManager.unregisterNetworkInterface(this);
-      this.registeredAsNetworkInterface = false;
-      this.cid = null;
-      this.connectedTypes = [];
-    }
   },
 
   receiveDataCallList: function(dataCalls, length) {
   },
 
   // Helpers
 
   cid: null,
--- a/dom/system/gonk/ril_worker.js
+++ b/dom/system/gonk/ril_worker.js
@@ -3802,17 +3802,19 @@ let RIL = {
       case DATACALL_ACTIVE_DOWN:
       case DATACALL_ACTIVE_UP:
         datacall.state = GECKO_NETWORK_STATE_CONNECTED;
         break;
     }
   },
 
   _processSuppSvcNotification: function(info) {
-    debug("handle supp svc notification: " + JSON.stringify(info));
+    if (DEBUG) {
+      debug("handle supp svc notification: " + JSON.stringify(info));
+    }
 
     let notification = null;
     let callIndex = -1;
 
     if (info.notificationType === 0) {
       // MO intermediate result code. Refer to code1 defined in 3GPP 27.007
       // 7.17.
     } else if (info.notificationType === 1) {
@@ -4964,17 +4966,17 @@ let RIL = {
     RILQUIRKS_HAVE_QUERY_ICC_LOCK_RETRY_COUNT = quirks.haveQueryIccLockRetryCount;
     RILQUIRKS_SEND_STK_PROFILE_DOWNLOAD = quirks.sendStkProfileDownload;
     RILQUIRKS_DATA_REGISTRATION_ON_DEMAND = quirks.dataRegistrationOnDemand;
   }
 };
 
 RIL.initRILState();
 
-RIL[REQUEST_GET_SIM_STATUS] = function(length, options) {
+RIL[REQUEST_GET_SIM_STATUS] = function REQUEST_GET_SIM_STATUS(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
   let iccStatus = {};
   iccStatus.cardState = Buf.readInt32(); // CARD_STATE_*
   iccStatus.universalPINState = Buf.readInt32(); // CARD_PINSTATE_*
   iccStatus.gsmUmtsSubscriptionAppIndex = Buf.readInt32();
@@ -5006,38 +5008,39 @@ RIL[REQUEST_GET_SIM_STATUS] = function(l
       Buf.readInt32();
       Buf.readInt32();
     }
   }
 
   if (DEBUG) debug("iccStatus: " + JSON.stringify(iccStatus));
   this._processICCStatus(iccStatus);
 };
-RIL[REQUEST_ENTER_SIM_PIN] = function(length, options) {
+RIL[REQUEST_ENTER_SIM_PIN] = function REQUEST_ENTER_SIM_PIN(length, options) {
   this._processEnterAndChangeICCResponses(length, options);
 };
-RIL[REQUEST_ENTER_SIM_PUK] = function(length, options) {
+RIL[REQUEST_ENTER_SIM_PUK] = function REQUEST_ENTER_SIM_PUK(length, options) {
   this._processEnterAndChangeICCResponses(length, options);
 };
-RIL[REQUEST_ENTER_SIM_PIN2] = function(length, options) {
+RIL[REQUEST_ENTER_SIM_PIN2] = function REQUEST_ENTER_SIM_PIN2(length, options) {
   this._processEnterAndChangeICCResponses(length, options);
 };
-RIL[REQUEST_ENTER_SIM_PUK2] = function(length, options) {
+RIL[REQUEST_ENTER_SIM_PUK2] = function REQUEST_ENTER_SIM_PUK(length, options) {
   this._processEnterAndChangeICCResponses(length, options);
 };
-RIL[REQUEST_CHANGE_SIM_PIN] = function(length, options) {
+RIL[REQUEST_CHANGE_SIM_PIN] = function REQUEST_CHANGE_SIM_PIN(length, options) {
   this._processEnterAndChangeICCResponses(length, options);
 };
-RIL[REQUEST_CHANGE_SIM_PIN2] = function(length, options) {
+RIL[REQUEST_CHANGE_SIM_PIN2] = function REQUEST_CHANGE_SIM_PIN2(length, options) {
   this._processEnterAndChangeICCResponses(length, options);
 };
-RIL[REQUEST_ENTER_NETWORK_DEPERSONALIZATION_CODE] = function(length, options) {
+RIL[REQUEST_ENTER_NETWORK_DEPERSONALIZATION_CODE] =
+  function REQUEST_ENTER_NETWORK_DEPERSONALIZATION_CODE(length, options) {
   this._processEnterAndChangeICCResponses(length, options);
 };
-RIL[REQUEST_GET_CURRENT_CALLS] = function(length, options) {
+RIL[REQUEST_GET_CURRENT_CALLS] = function REQUEST_GET_CURRENT_CALLS(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
   let calls_length = 0;
   // The RIL won't even send us the length integer if there are no active calls.
   // So only read this integer if the parcel actually has it.
   if (length) {
@@ -5083,104 +5086,104 @@ RIL[REQUEST_GET_CURRENT_CALLS] = functio
         userData: null //XXX TODO byte array?!?
       };
     }
 
     calls[call.callIndex] = call;
   }
   this._processCalls(calls);
 };
-RIL[REQUEST_DIAL] = function(length, options) {
+RIL[REQUEST_DIAL] = function REQUEST_DIAL(length, options) {
   if (options.rilRequestError) {
     // The connection is not established yet.
     options.callIndex = -1;
     this._sendCallError(options.callIndex,
                         RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError]);
   }
 };
-RIL[REQUEST_GET_IMSI] = function(length, options) {
+RIL[REQUEST_GET_IMSI] = function REQUEST_GET_IMSI(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
   this.iccInfoPrivate.imsi = Buf.readString();
   if (DEBUG) {
     debug("IMSI: " + this.iccInfoPrivate.imsi);
   }
 
   options.rilMessageType = "iccimsi";
   options.imsi = this.iccInfoPrivate.imsi;
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_HANGUP] = function(length, options) {
+RIL[REQUEST_HANGUP] = function REQUEST_HANGUP(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
   this.getCurrentCalls();
 };
-RIL[REQUEST_HANGUP_WAITING_OR_BACKGROUND] = function(length, options) {
+RIL[REQUEST_HANGUP_WAITING_OR_BACKGROUND] = function REQUEST_HANGUP_WAITING_OR_BACKGROUND(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
   this.getCurrentCalls();
 };
-RIL[REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND] = function(length, options) {
+RIL[REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND] = function REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
   this.getCurrentCalls();
 };
-RIL[REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE] = function(length, options) {
+RIL[REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE] = function REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
   this.getCurrentCalls();
 };
-RIL[REQUEST_SWITCH_HOLDING_AND_ACTIVE] = function(length, options) {
+RIL[REQUEST_SWITCH_HOLDING_AND_ACTIVE] = function REQUEST_SWITCH_HOLDING_AND_ACTIVE(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
   // XXX Normally we should get a UNSOLICITED_RESPONSE_CALL_STATE_CHANGED parcel
   // notifying us of call state changes, but sometimes we don't (have no idea why).
   // this.getCurrentCalls() helps update the call state actively.
   this.getCurrentCalls();
 };
-RIL[REQUEST_CONFERENCE] = function(length, options) {
+RIL[REQUEST_CONFERENCE] = function REQUEST_CONFERENCE(length, options) {
   if (options.rilRequestError) {
     this._hasConferenceRequest = false;
     options = {rilMessageType: "conferenceError",
                errorName: "addError",
                errorMsg: RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError]};
     this.sendChromeMessage(options);
     return;
   }
 };
 RIL[REQUEST_UDUB] = null;
-RIL[REQUEST_LAST_CALL_FAIL_CAUSE] = function(length, options) {
+RIL[REQUEST_LAST_CALL_FAIL_CAUSE] = function REQUEST_LAST_CALL_FAIL_CAUSE(length, options) {
   let num = 0;
   if (length) {
     num = Buf.readInt32();
   }
   if (!num) {
     // No response of REQUEST_LAST_CALL_FAIL_CAUSE. Change the call state into
     // 'disconnected' directly.
     this._handleDisconnectedCall(options);
     return;
   }
 
   let failCause = Buf.readInt32();
   options.failCause = RIL_CALL_FAILCAUSE_TO_GECKO_CALL_ERROR[failCause];
   this._handleDisconnectedCall(options);
 };
-RIL[REQUEST_SIGNAL_STRENGTH] = function(length, options) {
+RIL[REQUEST_SIGNAL_STRENGTH] = function REQUEST_SIGNAL_STRENGTH(length, options) {
   this._receivedNetworkInfo(NETWORK_INFO_SIGNAL);
 
   if (options.rilRequestError) {
     return;
   }
 
   let signal = {
     gsmSignalStrength: Buf.readInt32(),
@@ -5199,17 +5202,17 @@ RIL[REQUEST_SIGNAL_STRENGTH] = function(
     signal.lteRSSNR =          Buf.readInt32();
     signal.lteCQI =            Buf.readInt32();
   }
 
   if (DEBUG) debug("signal strength: " + JSON.stringify(signal));
 
   this._processSignalStrength(signal);
 };
-RIL[REQUEST_VOICE_REGISTRATION_STATE] = function(length, options) {
+RIL[REQUEST_VOICE_REGISTRATION_STATE] = function REQUEST_VOICE_REGISTRATION_STATE(length, options) {
   this._receivedNetworkInfo(NETWORK_INFO_VOICE_REGISTRATION_STATE);
 
   if (options.rilRequestError) {
     return;
   }
 
   let state = Buf.readStringList();
   if (DEBUG) debug("voice registration state: " + state);
@@ -5220,55 +5223,55 @@ RIL[REQUEST_VOICE_REGISTRATION_STATE] = 
        (this.voiceRegistrationState.emergencyCallsOnly ||
         this.voiceRegistrationState.connected) &&
       this.voiceRegistrationState.radioTech != NETWORK_CREG_TECH_UNKNOWN) {
     // Radio is ready for making the cached emergency call.
     this.cachedDialRequest.callback();
     this.cachedDialRequest = null;
   }
 };
-RIL[REQUEST_DATA_REGISTRATION_STATE] = function(length, options) {
+RIL[REQUEST_DATA_REGISTRATION_STATE] = function REQUEST_DATA_REGISTRATION_STATE(length, options) {
   this._receivedNetworkInfo(NETWORK_INFO_DATA_REGISTRATION_STATE);
 
   if (options.rilRequestError) {
     return;
   }
 
   let state = Buf.readStringList();
   this._processDataRegistrationState(state);
 };
-RIL[REQUEST_OPERATOR] = function(length, options) {
+RIL[REQUEST_OPERATOR] = function REQUEST_OPERATOR(length, options) {
   this._receivedNetworkInfo(NETWORK_INFO_OPERATOR);
 
   if (options.rilRequestError) {
     return;
   }
 
   let operatorData = Buf.readStringList();
   if (DEBUG) debug("Operator: " + operatorData);
   this._processOperator(operatorData);
 };
-RIL[REQUEST_RADIO_POWER] = function(length, options) {
+RIL[REQUEST_RADIO_POWER] = function REQUEST_RADIO_POWER(length, options) {
   if (options.rilMessageType == null) {
     // The request was made by ril_worker itself.
     if (options.rilRequestError) {
       if (this.cachedDialRequest && options.enabled) {
         // Turning on radio fails. Notify the error of making an emergency call.
         this.cachedDialRequest.onerror(GECKO_ERROR_RADIO_NOT_AVAILABLE);
         this.cachedDialRequest = null;
       }
     }
     return;
   }
 
   options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   this.sendChromeMessage(options);
 };
 RIL[REQUEST_DTMF] = null;
-RIL[REQUEST_SEND_SMS] = function(length, options) {
+RIL[REQUEST_SEND_SMS] = function REQUEST_SEND_SMS(length, options) {
   this._processSmsSendResult(length, options);
 };
 RIL[REQUEST_SEND_SMS_EXPECT_MORE] = null;
 
 RIL.readSetupDataCall_v5 = function readSetupDataCall_v5(options) {
   if (!options) {
     options = {};
   }
@@ -5278,17 +5281,17 @@ RIL.readSetupDataCall_v5 = function read
   options.ipaddr = ipaddr;
   options.dns = dns;
   options.gw = gw;
   options.active = DATACALL_ACTIVE_UNKNOWN;
   options.state = GECKO_NETWORK_STATE_CONNECTING;
   return options;
 };
 
-RIL[REQUEST_SETUP_DATA_CALL] = function(length, options) {
+RIL[REQUEST_SETUP_DATA_CALL] = function REQUEST_SETUP_DATA_CALL(length, options) {
   if (options.rilRequestError) {
     // On Data Call generic errors, we shall notify caller
     this._sendDataCallError(options, options.rilRequestError);
     return;
   }
 
   if (RILQUIRKS_V5_LEGACY) {
     // Populate the `options` object with the data call information. That way
@@ -5301,50 +5304,50 @@ RIL[REQUEST_SETUP_DATA_CALL] = function(
     // or not.
     this.getDataCallList();
     return;
   }
   // Pass `options` along. That way we retain the APN and other info about
   // how the data call was set up.
   this[REQUEST_DATA_CALL_LIST](length, options);
 };
-RIL[REQUEST_SIM_IO] = function(length, options) {
+RIL[REQUEST_SIM_IO] = function REQUEST_SIM_IO(length, options) {
   if (!length) {
     ICCIOHelper.processICCIOError(options);
     return;
   }
 
   // Don't need to read rilRequestError since we can know error status from
   // sw1 and sw2.
   options.sw1 = Buf.readInt32();
   options.sw2 = Buf.readInt32();
   if (options.sw1 != ICC_STATUS_NORMAL_ENDING) {
     ICCIOHelper.processICCIOError(options);
     return;
   }
   ICCIOHelper.processICCIO(options);
 };
-RIL[REQUEST_SEND_USSD] = function(length, options) {
+RIL[REQUEST_SEND_USSD] = function REQUEST_SEND_USSD(length, options) {
   if (DEBUG) {
     debug("REQUEST_SEND_USSD " + JSON.stringify(options));
   }
   options.success = (this._ussdSession = options.rilRequestError === 0);
   options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_CANCEL_USSD] = function(length, options) {
+RIL[REQUEST_CANCEL_USSD] = function REQUEST_CANCEL_USSD(length, options) {
   if (DEBUG) {
     debug("REQUEST_CANCEL_USSD" + JSON.stringify(options));
   }
   options.success = (options.rilRequestError === 0);
   this._ussdSession = !options.success;
   options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_GET_CLIR] = function(length, options) {
+RIL[REQUEST_GET_CLIR] = function REQUEST_GET_CLIR(length, options) {
   options.success = (options.rilRequestError === 0);
   if (!options.success) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
     this.sendChromeMessage(options);
     return;
   }
 
   let bufLength = Buf.readInt32();
@@ -5418,17 +5421,17 @@ RIL[REQUEST_GET_CLIR] = function(length,
         options.success = false;
         options.errorMsg = GECKO_ERROR_GENERIC_FAILURE;
         break;
     }
   }
 
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_SET_CLIR] = function(length, options) {
+RIL[REQUEST_SET_CLIR] = function REQUEST_SET_CLIR(length, options) {
   if (options.rilMessageType == null) {
     // The request was made by ril_worker itself automatically. Don't report.
     return;
   }
   options.success = (options.rilRequestError === 0);
   if (!options.success) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   } else if (options.rilMessageType === "sendMMI") {
@@ -5439,17 +5442,18 @@ RIL[REQUEST_SET_CLIR] = function(length,
       case MMI_PROCEDURE_DEACTIVATION:
         options.statusMessage = MMI_SM_KS_SERVICE_DISABLED;
         break;
     }
   }
   this.sendChromeMessage(options);
 };
 
-RIL[REQUEST_QUERY_CALL_FORWARD_STATUS] = function(length, options) {
+RIL[REQUEST_QUERY_CALL_FORWARD_STATUS] =
+  function REQUEST_QUERY_CALL_FORWARD_STATUS(length, options) {
   options.success = (options.rilRequestError === 0);
   if (!options.success) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
     this.sendChromeMessage(options);
     return;
   }
 
   let rulesLength = 0;
@@ -5478,17 +5482,18 @@ RIL[REQUEST_QUERY_CALL_FORWARD_STATUS] =
     options.statusMessage = MMI_SM_KS_SERVICE_INTERROGATED;
     // MMI query call forwarding options request returns a set of rules that
     // will be exposed in the form of an array of nsIDOMMozMobileCFInfo
     // instances.
     options.additionalInformation = rules;
   }
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_SET_CALL_FORWARD] = function(length, options) {
+RIL[REQUEST_SET_CALL_FORWARD] =
+  function REQUEST_SET_CALL_FORWARD(length, options) {
   options.success = (options.rilRequestError === 0);
   if (!options.success) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   } else if (options.rilMessageType === "sendMMI") {
     switch (options.action) {
       case CALL_FORWARD_ACTION_ENABLE:
         options.statusMessage = MMI_SM_KS_SERVICE_ENABLED;
         break;
@@ -5500,17 +5505,18 @@ RIL[REQUEST_SET_CALL_FORWARD] = function
         break;
       case CALL_FORWARD_ACTION_ERASURE:
         options.statusMessage = MMI_SM_KS_SERVICE_ERASED;
         break;
     }
   }
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_QUERY_CALL_WAITING] = function(length, options) {
+RIL[REQUEST_QUERY_CALL_WAITING] =
+  function REQUEST_QUERY_CALL_WAITING(length, options) {
   options.success = (options.rilRequestError === 0);
   if (!options.success) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
     this.sendChromeMessage(options);
     return;
   }
 
   if (options.callback) {
@@ -5519,68 +5525,68 @@ RIL[REQUEST_QUERY_CALL_WAITING] = functi
   }
 
   options.length = Buf.readInt32();
   options.enabled = ((Buf.readInt32() == 1) &&
                      ((Buf.readInt32() & ICC_SERVICE_CLASS_VOICE) == 0x01));
   this.sendChromeMessage(options);
 };
 
-RIL[REQUEST_SET_CALL_WAITING] = function(length, options) {
+RIL[REQUEST_SET_CALL_WAITING] = function REQUEST_SET_CALL_WAITING(length, options) {
   options.success = (options.rilRequestError === 0);
   if (!options.success) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
     this.sendChromeMessage(options);
     return;
   }
 
   if (options.callback) {
     options.callback.call(this, options);
     return;
   }
 
   this.sendChromeMessage(options);
 };
 RIL[REQUEST_SMS_ACKNOWLEDGE] = null;
-RIL[REQUEST_GET_IMEI] = function(length, options) {
+RIL[REQUEST_GET_IMEI] = function REQUEST_GET_IMEI(length, options) {
   this.IMEI = Buf.readString();
   let rilMessageType = options.rilMessageType;
   // So far we only send the IMEI back to chrome if it was requested via MMI.
   if (rilMessageType !== "sendMMI") {
     return;
   }
 
   options.success = (options.rilRequestError === 0);
   options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   if ((!options.success || this.IMEI == null) && !options.errorMsg) {
     options.errorMsg = GECKO_ERROR_GENERIC_FAILURE;
   }
   options.statusMessage = this.IMEI;
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_GET_IMEISV] = function(length, options) {
+RIL[REQUEST_GET_IMEISV] = function REQUEST_GET_IMEISV(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
   this.IMEISV = Buf.readString();
 };
 RIL[REQUEST_ANSWER] = null;
-RIL[REQUEST_DEACTIVATE_DATA_CALL] = function(length, options) {
+RIL[REQUEST_DEACTIVATE_DATA_CALL] = function REQUEST_DEACTIVATE_DATA_CALL(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
   let datacall = this.currentDataCalls[options.cid];
   delete this.currentDataCalls[options.cid];
   datacall.state = GECKO_NETWORK_STATE_UNKNOWN;
   datacall.rilMessageType = "datacallstatechange";
   this.sendChromeMessage(datacall);
 };
-RIL[REQUEST_QUERY_FACILITY_LOCK] = function(length, options) {
+RIL[REQUEST_QUERY_FACILITY_LOCK] = function REQUEST_QUERY_FACILITY_LOCK(length, options) {
   options.success = (options.rilRequestError === 0);
   if (!options.success) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   }
 
   let services;
   if (length) {
     // Buf.readInt32List()[0] for Call Barring is a bit vector of services.
@@ -5608,17 +5614,17 @@ RIL[REQUEST_QUERY_FACILITY_LOCK] = funct
         }
       }
 
       options.additionalInformation = serviceClass;
     }
   }
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_SET_FACILITY_LOCK] = function(length, options) {
+RIL[REQUEST_SET_FACILITY_LOCK] = function REQUEST_SET_FACILITY_LOCK(length, options) {
   options.success = (options.rilRequestError === 0);
   if (!options.success) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   }
 
   options.retryCount = length ? Buf.readInt32List()[0] : -1;
 
   if (options.success && (options.rilMessageType === "sendMMI")) {
@@ -5628,59 +5634,60 @@ RIL[REQUEST_SET_FACILITY_LOCK] = functio
         break;
       case MMI_PROCEDURE_DEACTIVATION:
         options.statusMessage = MMI_SM_KS_SERVICE_DISABLED;
         break;
     }
   }
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_CHANGE_BARRING_PASSWORD] = function(length, options) {
+RIL[REQUEST_CHANGE_BARRING_PASSWORD] =
+  function REQUEST_CHANGE_BARRING_PASSWORD(length, options) {
   if (options.rilRequestError) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   }
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_SIM_OPEN_CHANNEL] = function(length, options) {
+RIL[REQUEST_SIM_OPEN_CHANNEL] = function REQUEST_SIM_OPEN_CHANNEL(length, options) {
   if (options.rilRequestError) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
     this.sendChromeMessage(options);
     return;
   }
 
   options.channel = Buf.readInt32();
   if (DEBUG) debug("Setting channel number in options: " + options.channel);
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_SIM_CLOSE_CHANNEL] = function(length, options) {
+RIL[REQUEST_SIM_CLOSE_CHANNEL] = function REQUEST_SIM_CLOSE_CHANNEL(length, options) {
   if (options.rilRequestError) {
     options.error = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
     this.sendChromeMessage(options);
     return;
   }
 
   // No return value
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_SIM_ACCESS_CHANNEL] = function(length, options) {
+RIL[REQUEST_SIM_ACCESS_CHANNEL] = function REQUEST_SIM_ACCESS_CHANNEL(length, options) {
   if (options.rilRequestError) {
     options.error = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
     this.sendChromeMessage(options);
   }
 
   options.sw1 = Buf.readInt32();
   options.sw2 = Buf.readInt32();
   options.simResponse = Buf.readString();
   if (DEBUG) {
     debug("Setting return values for RIL[REQUEST_SIM_ACCESS_CHANNEL]: ["
           + options.sw1 + "," + options.sw2 + ", " + options.simResponse + "]");
   }
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_QUERY_NETWORK_SELECTION_MODE] = function(length, options) {
+RIL[REQUEST_QUERY_NETWORK_SELECTION_MODE] = function REQUEST_QUERY_NETWORK_SELECTION_MODE(length, options) {
   this._receivedNetworkInfo(NETWORK_INFO_NETWORK_SELECTION_MODE);
 
   if (options.rilRequestError) {
     return;
   }
 
   let mode = Buf.readInt32List();
   let selectionMode;
@@ -5698,60 +5705,60 @@ RIL[REQUEST_QUERY_NETWORK_SELECTION_MODE
   }
 
   if (this.networkSelectionMode != selectionMode) {
     this.networkSelectionMode = options.mode = selectionMode;
     options.rilMessageType = "networkselectionmodechange";
     this._sendNetworkInfoMessage(NETWORK_INFO_NETWORK_SELECTION_MODE, options);
   }
 };
-RIL[REQUEST_SET_NETWORK_SELECTION_AUTOMATIC] = function(length, options) {
+RIL[REQUEST_SET_NETWORK_SELECTION_AUTOMATIC] = function REQUEST_SET_NETWORK_SELECTION_AUTOMATIC(length, options) {
   if (options.rilRequestError) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   }
 
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_SET_NETWORK_SELECTION_MANUAL] = function(length, options) {
+RIL[REQUEST_SET_NETWORK_SELECTION_MANUAL] = function REQUEST_SET_NETWORK_SELECTION_MANUAL(length, options) {
   if (options.rilRequestError) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   }
 
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_QUERY_AVAILABLE_NETWORKS] = function(length, options) {
+RIL[REQUEST_QUERY_AVAILABLE_NETWORKS] = function REQUEST_QUERY_AVAILABLE_NETWORKS(length, options) {
   if (options.rilRequestError) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   } else {
     options.networks = this._processNetworks();
   }
   this.sendChromeMessage(options);
 };
 RIL[REQUEST_DTMF_START] = null;
 RIL[REQUEST_DTMF_STOP] = null;
-RIL[REQUEST_BASEBAND_VERSION] = function(length, options) {
+RIL[REQUEST_BASEBAND_VERSION] = function REQUEST_BASEBAND_VERSION(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
   this.basebandVersion = Buf.readString();
   if (DEBUG) debug("Baseband version: " + this.basebandVersion);
 };
-RIL[REQUEST_SEPARATE_CONNECTION] = function(length, options) {
+RIL[REQUEST_SEPARATE_CONNECTION] = function REQUEST_SEPARATE_CONNECTION(length, options) {
   if (options.rilRequestError) {
     options = {rilMessageType: "conferenceError",
                errorName: "removeError",
                errorMsg: RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError]};
     this.sendChromeMessage(options);
     return;
   }
 };
 RIL[REQUEST_SET_MUTE] = null;
 RIL[REQUEST_GET_MUTE] = null;
-RIL[REQUEST_QUERY_CLIP] = function(length, options) {
+RIL[REQUEST_QUERY_CLIP] = function REQUEST_QUERY_CLIP(length, options) {
   options.success = (options.rilRequestError === 0);
   if (!options.success) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
     this.sendChromeMessage(options);
     return;
   }
 
   let bufLength = Buf.readInt32();
@@ -5819,17 +5826,17 @@ RIL.readDataCall_v6 = function(options) 
     options.ipaddr = options.ipaddr.split(" ")[0];
   }
   if (options.gw) {
     options.gw = options.gw.split(" ")[0];
   }
   return options;
 };
 
-RIL[REQUEST_DATA_CALL_LIST] = function(length, options) {
+RIL[REQUEST_DATA_CALL_LIST] = function REQUEST_DATA_CALL_LIST(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
   if (!length) {
     this._processDataCallList(null);
     return;
   }
@@ -5856,17 +5863,17 @@ RIL[REQUEST_DATA_CALL_LIST] = function(l
   }
   this._processDataCallList(datacalls, newDataCallOptions);
 };
 RIL[REQUEST_RESET_RADIO] = null;
 RIL[REQUEST_OEM_HOOK_RAW] = null;
 RIL[REQUEST_OEM_HOOK_STRINGS] = null;
 RIL[REQUEST_SCREEN_STATE] = null;
 RIL[REQUEST_SET_SUPP_SVC_NOTIFICATION] = null;
-RIL[REQUEST_WRITE_SMS_TO_SIM] = function(length, options) {
+RIL[REQUEST_WRITE_SMS_TO_SIM] = function REQUEST_WRITE_SMS_TO_SIM(length, options) {
   if (options.rilRequestError) {
     // `The MS shall return a "protocol error, unspecified" error message if
     // the short message cannot be stored in the (U)SIM, and there is other
     // message storage available at the MS` ~ 3GPP TS 23.038 section 4. Here
     // we assume we always have indexed db as another storage.
     this.acknowledgeGsmSms(false, PDU_FCS_PROTOCOL_ERROR);
   } else {
     this.acknowledgeGsmSms(true, PDU_FCS_OK);
@@ -5876,31 +5883,31 @@ RIL[REQUEST_DELETE_SMS_ON_SIM] = null;
 RIL[REQUEST_SET_BAND_MODE] = null;
 RIL[REQUEST_QUERY_AVAILABLE_BAND_MODE] = null;
 RIL[REQUEST_STK_GET_PROFILE] = null;
 RIL[REQUEST_STK_SET_PROFILE] = null;
 RIL[REQUEST_STK_SEND_ENVELOPE_COMMAND] = null;
 RIL[REQUEST_STK_SEND_TERMINAL_RESPONSE] = null;
 RIL[REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM] = null;
 RIL[REQUEST_EXPLICIT_CALL_TRANSFER] = null;
-RIL[REQUEST_SET_PREFERRED_NETWORK_TYPE] = function(length, options) {
+RIL[REQUEST_SET_PREFERRED_NETWORK_TYPE] = function REQUEST_SET_PREFERRED_NETWORK_TYPE(length, options) {
   if (options.networkType == null) {
     // The request was made by ril_worker itself automatically. Don't report.
     return;
   }
 
   if (options.rilRequestError) {
     options.success = false;
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   } else {
     options.success = true;
   }
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_GET_PREFERRED_NETWORK_TYPE] = function(length, options) {
+RIL[REQUEST_GET_PREFERRED_NETWORK_TYPE] = function REQUEST_GET_PREFERRED_NETWORK_TYPE(length, options) {
   if (options.rilRequestError) {
     options.success = false;
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
     this.sendChromeMessage(options);
     return;
   }
 
   let networkType = RIL_PREFERRED_NETWORK_TYPE_TO_GECKO.indexOf(GECKO_PREFERRED_NETWORK_TYPE_DEFAULT);
@@ -5911,127 +5918,127 @@ RIL[REQUEST_GET_PREFERRED_NETWORK_TYPE] 
   options.networkType = networkType;
   options.success = true;
 
   this.sendChromeMessage(options);
 };
 RIL[REQUEST_GET_NEIGHBORING_CELL_IDS] = null;
 RIL[REQUEST_SET_LOCATION_UPDATES] = null;
 RIL[REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE] = null;
-RIL[REQUEST_CDMA_SET_ROAMING_PREFERENCE] = function(length, options) {
+RIL[REQUEST_CDMA_SET_ROAMING_PREFERENCE] = function REQUEST_CDMA_SET_ROAMING_PREFERENCE(length, options) {
   if (options.rilRequestError) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   }
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_CDMA_QUERY_ROAMING_PREFERENCE] = function(length, options) {
+RIL[REQUEST_CDMA_QUERY_ROAMING_PREFERENCE] = function REQUEST_CDMA_QUERY_ROAMING_PREFERENCE(length, options) {
   if (options.rilRequestError) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   } else {
     let mode = Buf.readInt32List();
     options.mode = CDMA_ROAMING_PREFERENCE_TO_GECKO[mode[0]];
   }
   this.sendChromeMessage(options);
 };
 RIL[REQUEST_SET_TTY_MODE] = null;
 RIL[REQUEST_QUERY_TTY_MODE] = null;
-RIL[REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE] = function(length, options) {
+RIL[REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE] = function REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE(length, options) {
   if (options.rilRequestError) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
     this.sendChromeMessage(options);
     return;
   }
 
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE] = function(length, options) {
+RIL[REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE] = function REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE(length, options) {
   if (options.rilRequestError) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
     this.sendChromeMessage(options);
     return;
   }
 
   let enabled = Buf.readInt32List();
   options.enabled = enabled[0] ? true : false;
   this.sendChromeMessage(options);
 };
 RIL[REQUEST_CDMA_FLASH] = null;
 RIL[REQUEST_CDMA_BURST_DTMF] = null;
 RIL[REQUEST_CDMA_VALIDATE_AND_WRITE_AKEY] = null;
-RIL[REQUEST_CDMA_SEND_SMS] = function(length, options) {
+RIL[REQUEST_CDMA_SEND_SMS] = function REQUEST_CDMA_SEND_SMS(length, options) {
   this._processSmsSendResult(length, options);
 };
 RIL[REQUEST_CDMA_SMS_ACKNOWLEDGE] = null;
 RIL[REQUEST_GSM_GET_BROADCAST_SMS_CONFIG] = null;
-RIL[REQUEST_GSM_SET_BROADCAST_SMS_CONFIG] = function(length, options) {
+RIL[REQUEST_GSM_SET_BROADCAST_SMS_CONFIG] = function REQUEST_GSM_SET_BROADCAST_SMS_CONFIG(length, options) {
   if (options.rilRequestError == ERROR_SUCCESS) {
     this.setSmsBroadcastActivation(true);
   }
 };
 RIL[REQUEST_GSM_SMS_BROADCAST_ACTIVATION] = null;
 RIL[REQUEST_CDMA_GET_BROADCAST_SMS_CONFIG] = null;
 RIL[REQUEST_CDMA_SET_BROADCAST_SMS_CONFIG] = null;
 RIL[REQUEST_CDMA_SMS_BROADCAST_ACTIVATION] = null;
-RIL[REQUEST_CDMA_SUBSCRIPTION] = function(length, options) {
+RIL[REQUEST_CDMA_SUBSCRIPTION] = function REQUEST_CDMA_SUBSCRIPTION(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
   let result = Buf.readStringList();
 
   this.iccInfo.mdn = result[0];
   // The result[1] is Home SID. (Already be handled in readCDMAHome())
   // The result[2] is Home NID. (Already be handled in readCDMAHome())
   // The result[3] is MIN.
   // The result[4] is PRL version.
 
   ICCUtilsHelper.handleICCInfoChange();
 };
 RIL[REQUEST_CDMA_WRITE_SMS_TO_RUIM] = null;
 RIL[REQUEST_CDMA_DELETE_SMS_ON_RUIM] = null;
-RIL[REQUEST_DEVICE_IDENTITY] = function(length, options) {
+RIL[REQUEST_DEVICE_IDENTITY] = function REQUEST_DEVICE_IDENTITY(length, options) {
   if (options.rilRequestError) {
     return;
   }
 
   let result = Buf.readStringList();
 
   // The result[0] is for IMEI. (Already be handled in REQUEST_GET_IMEI)
   // The result[1] is for IMEISV. (Already be handled in REQUEST_GET_IMEISV)
   // They are both ignored.
   this.ESN = result[2];
   this.MEID = result[3];
 };
-RIL[REQUEST_EXIT_EMERGENCY_CALLBACK_MODE] = function(length, options) {
+RIL[REQUEST_EXIT_EMERGENCY_CALLBACK_MODE] = function REQUEST_EXIT_EMERGENCY_CALLBACK_MODE(length, options) {
   if (options.internal) {
     return;
   }
 
   options.success = (options.rilRequestError === 0);
   if (!options.success) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   }
   this.sendChromeMessage(options);
 };
-RIL[REQUEST_GET_SMSC_ADDRESS] = function(length, options) {
+RIL[REQUEST_GET_SMSC_ADDRESS] = function REQUEST_GET_SMSC_ADDRESS(length, options) {
   this.SMSC = options.rilRequestError ? null : Buf.readString();
 
   if (!options || options.rilMessageType !== "getSmscAddress") {
     return;
   }
 
   options.smscAddress = this.SMSC;
   options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   this.sendChromeMessage(options);
 };
 RIL[REQUEST_SET_SMSC_ADDRESS] = null;
 RIL[REQUEST_REPORT_SMS_MEMORY_STATUS] = null;
 RIL[REQUEST_REPORT_STK_SERVICE_IS_RUNNING] = null;
 RIL[REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU] = null;
-RIL[REQUEST_STK_SEND_ENVELOPE_WITH_STATUS] = function(length, options) {
+RIL[REQUEST_STK_SEND_ENVELOPE_WITH_STATUS] = function REQUEST_STK_SEND_ENVELOPE_WITH_STATUS(length, options) {
   if (options.rilRequestError) {
     this.acknowledgeGsmSms(false, PDU_FCS_UNSPECIFIED);
     return;
   }
 
   let sw1 = Buf.readInt32();
   let sw2 = Buf.readInt32();
   if ((sw1 == ICC_STATUS_SAT_BUSY) && (sw2 === 0x00)) {
@@ -6047,37 +6054,37 @@ RIL[REQUEST_STK_SEND_ENVELOPE_WITH_STATU
   if (!responsePduLen) {
     this.acknowledgeGsmSms(success, success ? PDU_FCS_OK
                                          : PDU_FCS_USIM_DATA_DOWNLOAD_ERROR);
     return;
   }
 
   this.acknowledgeIncomingGsmSmsWithPDU(success, responsePduLen, options);
 };
-RIL[REQUEST_VOICE_RADIO_TECH] = function(length, options) {
+RIL[REQUEST_VOICE_RADIO_TECH] = function REQUEST_VOICE_RADIO_TECH(length, options) {
   if (options.rilRequestError) {
     if (DEBUG) {
       debug("Error when getting voice radio tech: " + options.rilRequestError);
     }
     return;
   }
   let radioTech = Buf.readInt32List();
   this._processRadioTech(radioTech[0]);
 };
-RIL[REQUEST_GET_UNLOCK_RETRY_COUNT] = function(length, options) {
+RIL[REQUEST_GET_UNLOCK_RETRY_COUNT] = function REQUEST_GET_UNLOCK_RETRY_COUNT(length, options) {
   options.success = (options.rilRequestError === 0);
   if (!options.success) {
     options.errorMsg = RIL_ERROR_TO_GECKO_ERROR[options.rilRequestError];
   }
   options.retryCount = length ? Buf.readInt32List()[0] : -1;
   this.sendChromeMessage(options);
 };
 RIL[RIL_REQUEST_GPRS_ATTACH] = null;
 RIL[RIL_REQUEST_GPRS_DETACH] = null;
-RIL[UNSOLICITED_RESPONSE_RADIO_STATE_CHANGED] = function() {
+RIL[UNSOLICITED_RESPONSE_RADIO_STATE_CHANGED] = function UNSOLICITED_RESPONSE_RADIO_STATE_CHANGED() {
   let radioState = Buf.readInt32();
   let newState;
   if (radioState == RADIO_STATE_UNAVAILABLE) {
     newState = GECKO_RADIOSTATE_UNAVAILABLE;
   } else if (radioState == RADIO_STATE_OFF) {
     newState = GECKO_RADIOSTATE_OFF;
   } else {
     newState = GECKO_RADIOSTATE_READY;
@@ -6147,82 +6154,79 @@ RIL[UNSOLICITED_RESPONSE_RADIO_STATE_CHA
   // If _waitingRadioTech is set, we don't need to get icc status now.
   if (radioState == RADIO_STATE_UNAVAILABLE ||
       radioState == RADIO_STATE_OFF ||
       this._waitingRadioTech) {
     return;
   }
   this.getICCStatus();
 };
-RIL[UNSOLICITED_RESPONSE_CALL_STATE_CHANGED] = function() {
+RIL[UNSOLICITED_RESPONSE_CALL_STATE_CHANGED] = function UNSOLICITED_RESPONSE_CALL_STATE_CHANGED() {
   this.getCurrentCalls();
 };
-RIL[UNSOLICITED_RESPONSE_VOICE_NETWORK_STATE_CHANGED] = function() {
+RIL[UNSOLICITED_RESPONSE_VOICE_NETWORK_STATE_CHANGED] = function UNSOLICITED_RESPONSE_VOICE_NETWORK_STATE_CHANGED() {
   if (DEBUG) debug("Network state changed, re-requesting phone state and ICC status");
   this.getICCStatus();
   this.requestNetworkInfo();
 };
-RIL[UNSOLICITED_RESPONSE_NEW_SMS] = function(length) {
+RIL[UNSOLICITED_RESPONSE_NEW_SMS] = function UNSOLICITED_RESPONSE_NEW_SMS(length) {
   let [message, result] = GsmPDUHelper.processReceivedSms(length);
 
   if (message) {
     result = this._processSmsMultipart(message);
   }
 
   if (result == PDU_FCS_RESERVED || result == MOZ_FCS_WAIT_FOR_EXPLICIT_ACK) {
     return;
   }
 
   // Not reserved FCS values, send ACK now.
   this.acknowledgeGsmSms(result == PDU_FCS_OK, result);
 };
-RIL[UNSOLICITED_RESPONSE_NEW_SMS_STATUS_REPORT] = function(length) {
+RIL[UNSOLICITED_RESPONSE_NEW_SMS_STATUS_REPORT] = function UNSOLICITED_RESPONSE_NEW_SMS_STATUS_REPORT(length) {
   let result = this._processSmsStatusReport(length);
   this.acknowledgeGsmSms(result == PDU_FCS_OK, result);
 };
-RIL[UNSOLICITED_RESPONSE_NEW_SMS_ON_SIM] = function(length) {
+RIL[UNSOLICITED_RESPONSE_NEW_SMS_ON_SIM] = function UNSOLICITED_RESPONSE_NEW_SMS_ON_SIM(length) {
   let recordNumber = Buf.readInt32List()[0];
 
   SimRecordHelper.readSMS(
     recordNumber,
     function onsuccess(message) {
       if (message && message.simStatus === 3) { //New Unread SMS
         this._processSmsMultipart(message);
       }
     }.bind(this),
     function onerror(errorMsg) {
       if (DEBUG) {
         debug("Failed to Read NEW SMS on SIM #" + recordNumber + ", errorMsg: " + errorMsg);
       }
     });
 };
-RIL[UNSOLICITED_ON_USSD] = function() {
+RIL[UNSOLICITED_ON_USSD] = function UNSOLICITED_ON_USSD() {
   let [typeCode, message] = Buf.readStringList();
   if (DEBUG) {
     debug("On USSD. Type Code: " + typeCode + " Message: " + message);
   }
 
   this._ussdSession = (typeCode != "0" && typeCode != "2");
 
   this.sendChromeMessage({rilMessageType: "USSDReceived",
                           message: message,
                           sessionEnded: !this._ussdSession});
 };
-RIL[UNSOLICITED_NITZ_TIME_RECEIVED] = function() {
+RIL[UNSOLICITED_NITZ_TIME_RECEIVED] = function UNSOLICITED_NITZ_TIME_RECEIVED() {
   let dateString = Buf.readString();
 
   // The data contained in the NITZ message is
   // in the form "yy/mm/dd,hh:mm:ss(+/-)tz,dt"
   // for example: 12/02/16,03:36:08-20,00,310410
-
-  // Always print the NITZ info so we can collection what different providers
-  // send down the pipe (see bug XXX).
-  // TODO once data is collected, add in |if (DEBUG)|
-
-  debug("DateTimeZone string " + dateString);
+  // See also bug 714352 - Listen for NITZ updates from rild.
+
+  if (DEBUG) debug("DateTimeZone string " + dateString);
 
   let now = Date.now();
 
   let year = parseInt(dateString.substr(0, 2), 10);
   let month = parseInt(dateString.substr(3, 2), 10);
   let day = parseInt(dateString.substr(6, 2), 10);
   let hours = parseInt(dateString.substr(9, 2), 10);
   let minutes = parseInt(dateString.substr(12, 2), 10);
@@ -6242,68 +6246,68 @@ RIL[UNSOLICITED_NITZ_TIME_RECEIVED] = fu
 
   this.sendChromeMessage({rilMessageType: "nitzTime",
                           networkTimeInMS: timeInMS,
                           networkTimeZoneInMinutes: -(tz * 15),
                           networkDSTInMinutes: -(dst * 60),
                           receiveTimeInMS: now});
 };
 
-RIL[UNSOLICITED_SIGNAL_STRENGTH] = function(length) {
+RIL[UNSOLICITED_SIGNAL_STRENGTH] = function UNSOLICITED_SIGNAL_STRENGTH(length) {
   this[REQUEST_SIGNAL_STRENGTH](length, {rilRequestError: ERROR_SUCCESS});
 };
-RIL[UNSOLICITED_DATA_CALL_LIST_CHANGED] = function(length) {
+RIL[UNSOLICITED_DATA_CALL_LIST_CHANGED] = function UNSOLICITED_DATA_CALL_LIST_CHANGED(length) {
   if (RILQUIRKS_V5_LEGACY) {
     this.getDataCallList();
     return;
   }
   this[REQUEST_DATA_CALL_LIST](length, {rilRequestError: ERROR_SUCCESS});
 };
-RIL[UNSOLICITED_SUPP_SVC_NOTIFICATION] = function(length) {
+RIL[UNSOLICITED_SUPP_SVC_NOTIFICATION] = function UNSOLICITED_SUPP_SVC_NOTIFICATION(length) {
   let info = {};
   info.notificationType = Buf.readInt32();
   info.code = Buf.readInt32();
   info.index = Buf.readInt32();
   info.type = Buf.readInt32();
   info.number = Buf.readString();
 
   this._processSuppSvcNotification(info);
 };
 
-RIL[UNSOLICITED_STK_SESSION_END] = function() {
+RIL[UNSOLICITED_STK_SESSION_END] = function UNSOLICITED_STK_SESSION_END() {
   this.sendChromeMessage({rilMessageType: "stksessionend"});
 };
-RIL[UNSOLICITED_STK_PROACTIVE_COMMAND] = function() {
+RIL[UNSOLICITED_STK_PROACTIVE_COMMAND] = function UNSOLICITED_STK_PROACTIVE_COMMAND() {
   this.processStkProactiveCommand();
 };
-RIL[UNSOLICITED_STK_EVENT_NOTIFY] = function() {
+RIL[UNSOLICITED_STK_EVENT_NOTIFY] = function UNSOLICITED_STK_EVENT_NOTIFY() {
   this.processStkProactiveCommand();
 };
 RIL[UNSOLICITED_STK_CALL_SETUP] = null;
 RIL[UNSOLICITED_SIM_SMS_STORAGE_FULL] = null;
 RIL[UNSOLICITED_SIM_REFRESH] = null;
-RIL[UNSOLICITED_CALL_RING] = function() {
+RIL[UNSOLICITED_CALL_RING] = function UNSOLICITED_CALL_RING() {
   let info = {rilMessageType: "callRing"};
   let isCDMA = false; //XXX TODO hard-code this for now
   if (isCDMA) {
     info.isPresent = Buf.readInt32();
     info.signalType = Buf.readInt32();
     info.alertPitch = Buf.readInt32();
     info.signal = Buf.readInt32();
   }
   // At this point we don't know much other than the fact there's an incoming
   // call, but that's enough to bring up the Phone app already. We'll know
   // details once we get a call state changed notification and can then
   // dispatch DOM events etc.
   this.sendChromeMessage(info);
 };
-RIL[UNSOLICITED_RESPONSE_SIM_STATUS_CHANGED] = function() {
+RIL[UNSOLICITED_RESPONSE_SIM_STATUS_CHANGED] = function UNSOLICITED_RESPONSE_SIM_STATUS_CHANGED() {
   this.getICCStatus();
 };
-RIL[UNSOLICITED_RESPONSE_CDMA_NEW_SMS] = function(length) {
+RIL[UNSOLICITED_RESPONSE_CDMA_NEW_SMS] = function UNSOLICITED_RESPONSE_CDMA_NEW_SMS(length) {
   let [message, result] = CdmaPDUHelper.processReceivedSms(length);
 
   if (message) {
     if (message.teleservice === PDU_CDMA_MSG_TELESERIVCIE_ID_WAP) {
       result = this._processCdmaSmsWapPush(message);
     } else if (message.subMsgType === PDU_CDMA_MSG_TYPE_DELIVER_ACK) {
       result = this._processCdmaSmsStatusReport(message);
     } else {
@@ -6313,17 +6317,17 @@ RIL[UNSOLICITED_RESPONSE_CDMA_NEW_SMS] =
 
   if (result == PDU_FCS_RESERVED || result == MOZ_FCS_WAIT_FOR_EXPLICIT_ACK) {
     return;
   }
 
   // Not reserved FCS values, send ACK now.
   this.acknowledgeCdmaSms(result == PDU_FCS_OK, result);
 };
-RIL[UNSOLICITED_RESPONSE_NEW_BROADCAST_SMS] = function(length) {
+RIL[UNSOLICITED_RESPONSE_NEW_BROADCAST_SMS] = function UNSOLICITED_RESPONSE_NEW_BROADCAST_SMS(length) {
   let message;
   try {
     message = GsmPDUHelper.readCbMessage(Buf.readInt32());
   } catch (e) {
     if (DEBUG) {
       debug("Failed to parse Cell Broadcast message: " + JSON.stringify(e));
     }
     return;
@@ -6334,49 +6338,49 @@ RIL[UNSOLICITED_RESPONSE_NEW_BROADCAST_S
     return;
   }
 
   message.rilMessageType = "cellbroadcast-received";
   this.sendChromeMessage(message);
 };
 RIL[UNSOLICITED_CDMA_RUIM_SMS_STORAGE_FULL] = null;
 RIL[UNSOLICITED_RESTRICTED_STATE_CHANGED] = null;
-RIL[UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE] = function() {
+RIL[UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE] = function UNSOLICITED_ENTER_EMERGENCY_CALLBACK_MODE() {
   this._handleChangedEmergencyCbMode(true);
 };
-RIL[UNSOLICITED_CDMA_CALL_WAITING] = function(length) {
+RIL[UNSOLICITED_CDMA_CALL_WAITING] = function UNSOLICITED_CDMA_CALL_WAITING(length) {
   let call = {};
   call.number              = Buf.readString();
   call.numberPresentation  = Buf.readInt32();
   call.name                = Buf.readString();
   call.namePresentation    = Buf.readInt32();
   call.isPresent           = Buf.readInt32();
   call.signalType          = Buf.readInt32();
   call.alertPitch          = Buf.readInt32();
   call.signal              = Buf.readInt32();
   this.sendChromeMessage({rilMessageType: "cdmaCallWaiting",
                           number: call.number});
 };
-RIL[UNSOLICITED_CDMA_OTA_PROVISION_STATUS] = function() {
+RIL[UNSOLICITED_CDMA_OTA_PROVISION_STATUS] = function UNSOLICITED_CDMA_OTA_PROVISION_STATUS() {
   let status = Buf.readInt32List()[0];
   this.sendChromeMessage({rilMessageType: "otastatuschange",
                           status: status});
 };
-RIL[UNSOLICITED_CDMA_INFO_REC] = function(length) {
+RIL[UNSOLICITED_CDMA_INFO_REC] = function UNSOLICITED_CDMA_INFO_REC(length) {
   let record = CdmaPDUHelper.decodeInformationRecord();
   record.rilMessageType = "cdma-info-rec-received";
   this.sendChromeMessage(record);
 };
 RIL[UNSOLICITED_OEM_HOOK_RAW] = null;
 RIL[UNSOLICITED_RINGBACK_TONE] = null;
 RIL[UNSOLICITED_RESEND_INCALL_MUTE] = null;
-RIL[UNSOLICITED_EXIT_EMERGENCY_CALLBACK_MODE] = function() {
+RIL[UNSOLICITED_EXIT_EMERGENCY_CALLBACK_MODE] = function UNSOLICITED_EXIT_EMERGENCY_CALLBACK_MODE() {
   this._handleChangedEmergencyCbMode(false);
 };
-RIL[UNSOLICITED_RIL_CONNECTED] = function(length) {
+RIL[UNSOLICITED_RIL_CONNECTED] = function UNSOLICITED_RIL_CONNECTED(length) {
   // Prevent response id collision between UNSOLICITED_RIL_CONNECTED and
   // UNSOLICITED_VOICE_RADIO_TECH_CHANGED for Akami on gingerbread branch.
   if (!length) {
     return;
   }
 
   let version = Buf.readInt32List()[0];
   RILQUIRKS_V5_LEGACY = (version < 5);
@@ -13895,10 +13899,10 @@ function onRILMessage(data) {
   Buf.processIncoming(data);
 }
 
 onmessage = function onmessage(event) {
   RIL.handleChromeMessage(event.data);
 };
 
 onerror = function onerror(event) {
-  debug("RIL Worker error" + event.message + "\n");
-};
+  if (DEBUG) debug("RIL Worker error" + event.message + "\n");
+};
--- a/dom/tests/mochitest/webapps/chrome.ini
+++ b/dom/tests/mochitest/webapps/chrome.ini
@@ -6,12 +6,11 @@ support-files =
   apps/*
 
 [test_bug_765063.xul]
 [test_bug_771294.xul]
 [test_cross_origin.xul]
 [test_getNotInstalled.xul]
 [test_install_app.xul]
 [test_install_errors.xul]
-[test_install_receipts.xul]
 [test_install_utf8.xul]
 [test_launch_paths.xul]
 [test_list_api.xul]
deleted file mode 100644
--- a/dom/tests/mochitest/webapps/test_install_receipts.xul
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0"?>
-
-<!-- Any copyright is dedicated to the Public Domain.
-   - http://creativecommons.org/publicdomain/zero/1.0/ -->
-
-<?xml-stylesheet type="text/css" href="chrome://global/skin"?>
-<?xml-stylesheet type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"?>
-
-<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-        title="Mozilla Bug 741549">
-  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"/>
-  <script type="application/javascript" src="head.js"/>
-  <!-- test results are displayed in the html:body -->
-  <body xmlns="http://www.w3.org/1999/xhtml">
-  <a href="https://bugzilla.mozilla.org/show_bug.cgi?id=741549"
-     target="_blank">Mozilla Bug 741549</a>
-  </body>
-
-<script>
-
-SimpleTest.waitForExplicitFinish();
-
-var url = "http://test/chrome/dom/tests/mochitest/webapps/apps/basic.webapp";
-
-var receipts = [
-  "a",
-  0,
-  true,
-  false,
-  null,
-  undefined,
-  { prop: 1 },
-  { nest: { ed: "hi" } },
-  NaN,
-  Infinity,
-];
-
-confirmNextInstall();
-navigator.mozApps.install(url, { receipts: receipts }).onsuccess =
-function onInstall() {
-  is(this.result.receipts[0], "a", "receipts[0]");
-  is(this.result.receipts[1], 0, "receipts[1]");
-  is(this.result.receipts[2], true, "receipts[2]");
-  is(this.result.receipts[3], false, "receipts[3]");
-  is(this.result.receipts[4], null, "receipts[4]");
-  is(this.result.receipts[5], undefined, "receipts[5]");
-  is(this.result.receipts[6].prop, 1, "receipts[6].prop");
-  is(this.result.receipts[7].nest.ed, "hi", "receipts[7].nest.ed");
-  todo_is(this.result.receipts[8], NaN, "receipts[8]");
-  todo_is(this.result.receipts[9], Infinity, "receipts[9]");
-
-  navigator.mozApps.mgmt.uninstall(this.result).onsuccess = function onUninstall() {
-    SimpleTest.finish();
-  }
-};
-
-</script>
-</window>
--- a/gfx/layers/basic/BasicCompositor.cpp
+++ b/gfx/layers/basic/BasicCompositor.cpp
@@ -91,27 +91,36 @@ public:
 
 protected:
   virtual void UpdateImpl(const SurfaceDescriptor& aImage,
                           nsIntRegion *aRegion,
                           nsIntPoint*) MOZ_OVERRIDE
   {
     AutoOpenSurface surf(OPEN_READ_ONLY, aImage);
     nsRefPtr<gfxASurface> surface = ShadowLayerForwarder::OpenDescriptor(OPEN_READ_ONLY, aImage);
+    if (!surface) {
+      if (aImage.type() != SurfaceDescriptor::TShmem &&
+          aImage.type() != SurfaceDescriptor::TMemoryImage &&
+          aImage.type() != SurfaceDescriptor::TRGBImage) {
+        printf_stderr("Unsupported SurfaceDescriptor type: %i\n", static_cast<int>(aImage.type()));
+      }
+      NS_WARNING("Could not open the SurfaceDescriptor");
+      return;
+    }
     nsRefPtr<gfxImageSurface> image = surface->GetAsImageSurface();
     mFormat = ImageFormatToSurfaceFormat(image->Format());
     mSize = IntSize(image->Width(), image->Height());
     mSurface = Factory::CreateWrappingDataSourceSurface(image->Data(),
                                                         image->Stride(),
                                                         mSize,
                                                         mFormat);
   }
 
   virtual bool EnsureSurface() {
-    return true;
+    return mSurface != nullptr;
   }
 
   virtual bool Lock() MOZ_OVERRIDE {
     return EnsureSurface();
   }
 
   virtual TemporaryRef<gfx::DataSourceSurface> GetAsSurface() MOZ_OVERRIDE {
     if (!mSurface) {
--- a/gfx/layers/client/CanvasClient.cpp
+++ b/gfx/layers/client/CanvasClient.cpp
@@ -48,17 +48,17 @@ CanvasClient::CreateCanvasClient(CanvasC
   return new CanvasClient2D(aForwarder, aFlags);
 }
 
 void
 CanvasClient2D::Update(gfx::IntSize aSize, ClientCanvasLayer* aLayer)
 {
   if (mBuffer &&
       (mBuffer->IsImmutable() || mBuffer->GetSize() != aSize)) {
-    mBuffer->ForceRemove();
+    GetForwarder()->AddForceRemovingTexture(mBuffer);
     mBuffer = nullptr;
   }
 
   bool bufferCreated = false;
   if (!mBuffer) {
     bool isOpaque = (aLayer->GetContentFlags() & Layer::CONTENT_OPAQUE);
     gfxContentType contentType = isOpaque
                                                 ? GFX_CONTENT_COLOR
--- a/gfx/layers/client/ClientLayerManager.cpp
+++ b/gfx/layers/client/ClientLayerManager.cpp
@@ -384,16 +384,17 @@ ClientLayerManager::ForwardTransaction(b
 
     if (sent) {
       mNeedsComposite = false;
     }
   } else if (HasShadowManager()) {
     NS_WARNING("failed to forward Layers transaction");
   }
 
+  mForwarder->ForceRemoveTexturesIfNecessary();
   mPhase = PHASE_NONE;
 
   // this may result in Layers being deleted, which results in
   // PLayer::Send__delete__() and DeallocShmem()
   mKeepAlive.Clear();
 }
 
 ShadowableLayer*
--- a/gfx/layers/client/ContentClient.cpp
+++ b/gfx/layers/client/ContentClient.cpp
@@ -142,16 +142,19 @@ ContentClientRemoteBuffer::BeginPaint()
 
 void
 ContentClientRemoteBuffer::EndPaint()
 {
   // XXX: We might still not have a texture client if PaintThebes
   // decided we didn't need one yet because the region to draw was empty.
   SetBufferProvider(nullptr);
   SetBufferProviderOnWhite(nullptr);
+  for (unsigned i = 0; i< mOldTextures.Length(); ++i) {
+    mOldTextures[i]->Unlock();
+  }
   mOldTextures.Clear();
 
   if (mTextureClient) {
     mTextureClient->Unlock();
   }
   if (mTextureClientOnWhite) {
     mTextureClientOnWhite->Unlock();
   }
@@ -232,18 +235,26 @@ ContentClientRemoteBuffer::CreateBuffer(
                                         RefPtr<gfx::DrawTarget>* aBlackDT,
                                         RefPtr<gfx::DrawTarget>* aWhiteDT)
 {
   BuildTextureClients(gfxPlatform::GetPlatform()->Optimal2DFormatForContent(aType), aRect, aFlags);
   if (!mTextureClient) {
     return;
   }
 
+  // We just created the textures and we are about to get their draw targets
+  // so we have to lock them here.
+  DebugOnly<bool> locked = mTextureClient->Lock(OPEN_READ_WRITE);
+  MOZ_ASSERT(locked, "Could not lock the TextureClient");
+
   *aBlackDT = mTextureClient->AsTextureClientDrawTarget()->GetAsDrawTarget();
   if (aFlags & BUFFER_COMPONENT_ALPHA) {
+    locked = mTextureClientOnWhite->Lock(OPEN_READ_WRITE);
+    MOZ_ASSERT(locked, "Could not lock the second TextureClient for component alpha");
+
     *aWhiteDT = mTextureClientOnWhite->AsTextureClientDrawTarget()->GetAsDrawTarget();
   }
 }
 
 nsIntRegion
 ContentClientRemoteBuffer::GetUpdatedRegion(const nsIntRegion& aRegionToDraw,
                                             const nsIntRegion& aVisibleRegion,
                                             bool aDidSelfCopy)
@@ -276,16 +287,19 @@ ContentClientRemoteBuffer::Updated(const
                                    bool aDidSelfCopy)
 {
   nsIntRegion updatedRegion = GetUpdatedRegion(aRegionToDraw,
                                                aVisibleRegion,
                                                aDidSelfCopy);
 
   MOZ_ASSERT(mTextureClient);
   mForwarder->UseTexture(this, mTextureClient);
+  if (mTextureClientOnWhite) {
+    mForwarder->UseTexture(this, mTextureClientOnWhite);
+  }
   mForwarder->UpdateTextureRegion(this,
                                   ThebesBufferData(BufferRect(),
                                                    BufferRotation()),
                                   updatedRegion);
 }
 
 void
 ContentClientRemoteBuffer::SwapBuffers(const nsIntRegion& aFrontUpdatedRegion)
@@ -903,31 +917,43 @@ DeprecatedContentClientDoubleBuffered::U
     ReturnDrawTarget(destDT);
   }
 }
 
 void
 ContentClientSingleBuffered::PrepareFrame()
 {
   if (!mFrontAndBackBufferDiffer) {
+    if (mTextureClient) {
+      DebugOnly<bool> locked = mTextureClient->Lock(OPEN_READ_WRITE);
+      MOZ_ASSERT(locked);
+    }
+    if (mTextureClientOnWhite) {
+      DebugOnly<bool> locked = mTextureClientOnWhite->Lock(OPEN_READ_WRITE);
+      MOZ_ASSERT(locked);
+    }
     return;
   }
 
   RefPtr<DrawTarget> backBuffer = GetDTBuffer();
   if (!backBuffer && mTextureClient) {
+    DebugOnly<bool> locked = mTextureClient->Lock(OPEN_READ_WRITE);
+    MOZ_ASSERT(locked);
     backBuffer = mTextureClient->AsTextureClientDrawTarget()->GetAsDrawTarget();
   }
 
   RefPtr<DrawTarget> oldBuffer;
   oldBuffer = SetDTBuffer(backBuffer,
                           mBufferRect,
                           mBufferRotation);
 
   backBuffer = GetDTBufferOnWhite();
   if (!backBuffer && mTextureClientOnWhite) {
+    DebugOnly<bool> locked = mTextureClientOnWhite->Lock(OPEN_READ_WRITE);
+    MOZ_ASSERT(locked);
     backBuffer = mTextureClientOnWhite->AsTextureClientDrawTarget()->GetAsDrawTarget();
   }
 
   oldBuffer = SetDTBufferOnWhite(backBuffer);
 
   mIsNewBuffer = false;
   mFrontAndBackBufferDiffer = false;
 }
--- a/gfx/layers/client/ImageClient.cpp
+++ b/gfx/layers/client/ImageClient.cpp
@@ -98,30 +98,30 @@ TextureInfo ImageClientSingle::GetTextur
 {
   return TextureInfo(COMPOSITABLE_IMAGE);
 }
 
 void
 ImageClientSingle::FlushAllImages(bool aExceptFront)
 {
   if (!aExceptFront && mFrontBuffer) {
-    mFrontBuffer->ForceRemove();
+    GetForwarder()->AddForceRemovingTexture(mFrontBuffer);
     mFrontBuffer = nullptr;
   }
 }
 
 void
 ImageClientBuffered::FlushAllImages(bool aExceptFront)
 {
   if (!aExceptFront && mFrontBuffer) {
-    mFrontBuffer->ForceRemove();
+    GetForwarder()->AddForceRemovingTexture(mFrontBuffer);
     mFrontBuffer = nullptr;
   }
   if (mBackBuffer) {
-    mBackBuffer->ForceRemove();
+    GetForwarder()->AddForceRemovingTexture(mBackBuffer);
     mBackBuffer = nullptr;
   }
 }
 
 bool
 ImageClientSingle::UpdateImage(ImageContainer* aContainer,
                                uint32_t aContentFlags)
 {
@@ -142,34 +142,34 @@ ImageClientSingle::UpdateImage(ImageCont
 
     if (texture->IsSharedWithCompositor()) {
       // XXX - temporary fix for bug 911941
       // This will be changed with bug 912907
       return false;
     }
 
     if (mFrontBuffer) {
-      mFrontBuffer->ForceRemove();
+      GetForwarder()->AddForceRemovingTexture(mFrontBuffer);
     }
     mFrontBuffer = texture;
     if (!AddTextureClient(texture)) {
       mFrontBuffer = nullptr;
       return false;
     }
     GetForwarder()->UpdatedTexture(this, texture, nullptr);
     GetForwarder()->UseTexture(this, texture);
   } else if (image->GetFormat() == PLANAR_YCBCR) {
     PlanarYCbCrImage* ycbcr = static_cast<PlanarYCbCrImage*>(image);
     const PlanarYCbCrData* data = ycbcr->GetData();
     if (!data) {
       return false;
     }
 
     if (mFrontBuffer && mFrontBuffer->IsImmutable()) {
-      mFrontBuffer->ForceRemove();
+      GetForwarder()->AddForceRemovingTexture(mFrontBuffer);
       mFrontBuffer = nullptr;
     }
 
     bool bufferCreated = false;
     if (!mFrontBuffer) {
       mFrontBuffer = CreateBufferTextureClient(gfx::SurfaceFormat::YUV, TEXTURE_FLAGS_DEFAULT);
       gfx::IntSize ySize(data->mYSize.width, data->mYSize.height);
       gfx::IntSize cbCrSize(data->mCbCrSize.width, data->mCbCrSize.height);
@@ -202,17 +202,17 @@ ImageClientSingle::UpdateImage(ImageCont
     }
 
   } else if (image->GetFormat() == SHARED_TEXTURE) {
     SharedTextureImage* sharedImage = static_cast<SharedTextureImage*>(image);
     const SharedTextureImage::Data *data = sharedImage->GetData();
     gfx::IntSize size = gfx::IntSize(image->GetSize().width, image->GetSize().height);
 
     if (mFrontBuffer) {
-      mFrontBuffer->ForceRemove();
+      GetForwarder()->AddForceRemovingTexture(mFrontBuffer);
       mFrontBuffer = nullptr;
     }
 
     RefPtr<SharedTextureClientOGL> buffer = new SharedTextureClientOGL(mTextureFlags);
     buffer->InitWith(data->mHandle, size, data->mShareType, data->mInverted);
     mFrontBuffer = buffer;
     if (!AddTextureClient(mFrontBuffer)) {
       mFrontBuffer = nullptr;
@@ -223,17 +223,17 @@ ImageClientSingle::UpdateImage(ImageCont
   } else {
     nsRefPtr<gfxASurface> surface = image->DeprecatedGetAsSurface();
     MOZ_ASSERT(surface);
 
     gfx::IntSize size = gfx::IntSize(image->GetSize().width, image->GetSize().height);
 
     if (mFrontBuffer &&
         (mFrontBuffer->IsImmutable() || mFrontBuffer->GetSize() != size)) {
-      mFrontBuffer->ForceRemove();
+      GetForwarder()->AddForceRemovingTexture(mFrontBuffer);
       mFrontBuffer = nullptr;
     }
 
     bool bufferCreated = false;
     if (!mFrontBuffer) {
       gfxImageFormat format
         = gfxPlatform::GetPlatform()->OptimalFormatForContent(surface->GetContentType());
       mFrontBuffer = CreateTextureClientForDrawing(gfx::ImageFormatToSurfaceFormat(format),
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -381,20 +381,20 @@ public:
   virtual size_t GetBufferSize() const MOZ_OVERRIDE;
 
   virtual bool IsAllocated() const MOZ_OVERRIDE { return mAllocated; }
 
   virtual TextureClientData* DropTextureData() MOZ_OVERRIDE;
 
   ISurfaceAllocator* GetAllocator() const;
 
-  ipc::Shmem& GetShmem() { return mShmem; }
+  mozilla::ipc::Shmem& GetShmem() { return mShmem; }
 
 protected:
-  ipc::Shmem mShmem;
+  mozilla::ipc::Shmem mShmem;
   RefPtr<ISurfaceAllocator> mAllocator;
   bool mAllocated;
 };
 
 /**
  * TextureClient that wraps raw memory.
  * The corresponding texture on the host side is MemoryTextureHost.
  * Can obviously not be used in a cross process setup.
--- a/gfx/layers/composite/ContentHost.cpp
+++ b/gfx/layers/composite/ContentHost.cpp
@@ -122,17 +122,17 @@ ContentHostBase::Composite(EffectChain& 
   }
 
   TileIterator* tileIter = source->AsTileIterator();
   TileIterator* iterOnWhite = nullptr;
   if (tileIter) {
     tileIter->BeginTileIteration();
   }
 
-  if (mTextureHostOnWhite) {
+  if (sourceOnWhite) {
     iterOnWhite = sourceOnWhite->AsTileIterator();
     MOZ_ASSERT(!tileIter || tileIter->GetTileCount() == iterOnWhite->GetTileCount(),
                "Tile count mismatch on component alpha texture");
     if (iterOnWhite) {
       iterOnWhite->BeginTileIteration();
     }
   }
 
@@ -216,21 +216,19 @@ ContentHostBase::Composite(EffectChain& 
   GetCompositor()->DrawDiagnostics(diagnostics, *aVisibleRegion, aClipRect, aTransform);
 }
 
 
 void
 ContentHostBase::UseTextureHost(TextureHost* aTexture)
 {
   if (aTexture->GetFlags() & TEXTURE_ON_WHITE) {
-    mTextureHost = nullptr;
     mTextureHostOnWhite = aTexture;
     mTextureHostOnWhite->SetCompositor(GetCompositor());
   } else {
-    mTextureHostOnWhite = nullptr;
     mTextureHost = aTexture;
     mTextureHost->SetCompositor(GetCompositor());
   }
 }
 
 void
 ContentHostBase::SetCompositor(Compositor* aCompositor)
 {
--- a/gfx/layers/composite/TextureHost.cpp
+++ b/gfx/layers/composite/TextureHost.cpp
@@ -714,33 +714,36 @@ TextureParent::RecvRemoveTextureSync()
 
 void
 TextureParent::ActorDestroy(ActorDestroyReason why)
 {
   if (!mTextureHost) {
     return;
   }
 
+  bool isDeffered = mTextureHost->GetFlags() & TEXTURE_DEALLOCATE_DEFERRED;
   switch (why) {
   case AncestorDeletion:
     NS_WARNING("PTexture deleted after ancestor");
     // fall-through to deletion path
   case Deletion:
-    if (!(mTextureHost->GetFlags() & TEXTURE_DEALLOCATE_CLIENT) &&
-        !(mTextureHost->GetFlags() & TEXTURE_DEALLOCATE_DEFERRED)) {
+    if (!(mTextureHost->GetFlags() & TEXTURE_DEALLOCATE_CLIENT) && !isDeffered) {
       mTextureHost->DeallocateSharedData();
     }
     break;
 
   case NormalShutdown:
   case AbnormalShutdown:
     mTextureHost->OnShutdown();
     break;
 
   case FailedConstructor:
     NS_RUNTIMEABORT("FailedConstructor isn't possible in PTexture");
   }
-  mTextureHost->ForgetSharedData();
+
+  if (!isDeffered) {
+    mTextureHost->ForgetSharedData();
+  }
   mTextureHost = nullptr;
 }
 
 } // namespace
 } // namespace
--- a/gfx/layers/ipc/AsyncPanZoomController.cpp
+++ b/gfx/layers/ipc/AsyncPanZoomController.cpp
@@ -1223,17 +1223,17 @@ bool FlingAnimation::Sample(FrameMetrics
 
   // Inversely scale the offset by the resolution (when you're zoomed further in,
   // a larger swipe should move you a shorter distance).
   CSSPoint cssOffset = offset / aFrameMetrics.mZoom;
   aFrameMetrics.mScrollOffset += CSSPoint::FromUnknownPoint(gfx::Point(
     mX.AdjustDisplacement(cssOffset.x, overscroll.x,
                           aFrameMetrics.GetDisableScrollingX()),
     mY.AdjustDisplacement(cssOffset.y, overscroll.y,
-                          aFrameMetrics.GetDisableScrollingX())
+                          aFrameMetrics.GetDisableScrollingY())
   ));
 
   return true;
 }
 
 void AsyncPanZoomController::StartAnimation(AsyncPanZoomAnimation* aAnimation)
 {
   ReentrantMonitorAutoEnter lock(mMonitor);
--- a/gfx/layers/ipc/CompositableForwarder.h
+++ b/gfx/layers/ipc/CompositableForwarder.h
@@ -8,34 +8,33 @@
 #define MOZILLA_LAYERS_COMPOSITABLEFORWARDER
 
 #include <stdint.h>                     // for int32_t, uint64_t
 #include "gfxTypes.h"
 #include "mozilla/Attributes.h"         // for MOZ_OVERRIDE
 #include "mozilla/layers/CompositorTypes.h"
 #include "mozilla/layers/ISurfaceAllocator.h"  // for ISurfaceAllocator
 #include "mozilla/layers/LayersTypes.h"  // for LayersBackend
+#include "mozilla/layers/TextureClient.h"  // for TextureClient
 #include "nsRegion.h"                   // for nsIntRegion
 
 struct nsIntPoint;
 struct nsIntRect;
 
 namespace mozilla {
 namespace layers {
 
 class CompositableClient;
 class TextureFactoryIdentifier;
 class SurfaceDescriptor;
 class SurfaceDescriptorTiles;
 class ThebesBufferData;
 class DeprecatedTextureClient;
-class TextureClient;
 class BasicTiledLayerBuffer;
 class PTextureChild;
-class TextureClientData;
 
 /**
  * A transaction is a set of changes that happenned on the content side, that
  * should be sent to the compositor side.
  * CompositableForwarder is an interface to manage a transaction of
  * compositable objetcs.
  *
  * ShadowLayerForwarder is an example of a CompositableForwarder (that can
@@ -158,16 +157,39 @@ public:
 
   /**
    * Tell the compositor side to delete the TextureHost corresponding to the
    * TextureClient passed in parameter.
    */
   virtual void RemoveTexture(TextureClient* aTexture) = 0;
 
   /**
+   * Forcibly remove texture data from TextureClient
+   * after a tansaction with Compositor.
+   */
+  virtual void AddForceRemovingTexture(TextureClient* aClient)
+  {
+    if (aClient) {
+      mForceRemovingTextures.AppendElement(aClient);
+    }
+  }
+
+  /**
+   * Forcibly remove texture data from TextureClient
+   * This function needs to be called after a tansaction with Compositor.
+   */
+  virtual void ForceRemoveTexturesIfNecessary()
+  {
+    for (uint32_t i = 0; i < mForceRemovingTextures.Length(); i++) {
+       mForceRemovingTextures[i]->ForceRemove();
+    }
+    mForceRemovingTextures.Clear();
+  }
+
+  /**
    * Tell the CompositableHost on the compositor side what texture to use for
    * the next composition.
    */
   virtual void UseTexture(CompositableClient* aCompositable,
                           TextureClient* aClient) = 0;
 
   /**
    * Tell the compositor side that the shared data has been modified so that
@@ -214,14 +236,15 @@ public:
   const TextureFactoryIdentifier& GetTextureFactoryIdentifier() const
   {
     return mTextureFactoryIdentifier;
   }
 
 protected:
   TextureFactoryIdentifier mTextureFactoryIdentifier;
   bool mMultiProcess;
+  nsTArray<RefPtr<TextureClient> > mForceRemovingTextures;
 };
 
 } // namespace
 } // namespace
 
 #endif
--- a/gfx/layers/ipc/ImageBridgeChild.cpp
+++ b/gfx/layers/ipc/ImageBridgeChild.cpp
@@ -438,22 +438,37 @@ void ImageBridgeChild::FlushAllImagesNow
 
 void
 ImageBridgeChild::BeginTransaction()
 {
   MOZ_ASSERT(mTxn->Finished(), "uncommitted txn?");
   mTxn->Begin();
 }
 
+class MOZ_STACK_CLASS AutoForceRemoveTextures
+{
+public:
+  AutoForceRemoveTextures(ImageBridgeChild* aImageBridge)
+    : mImageBridge(aImageBridge) {}
+
+  ~AutoForceRemoveTextures()
+  {
+    mImageBridge->ForceRemoveTexturesIfNecessary();
+  }
+private:
+  ImageBridgeChild* mImageBridge;
+};
+
 void
 ImageBridgeChild::EndTransaction()
 {
   MOZ_ASSERT(!mTxn->Finished(), "forgot BeginTransaction?");
 
   AutoEndTransaction _(mTxn);
+  AutoForceRemoveTextures autoForceRemoveTextures(this);
 
   if (mTxn->IsEmpty()) {
     return;
   }
 
   AutoInfallibleTArray<CompositableOperation, 10> cset;
   cset.SetCapacity(mTxn->mOperations.size());
   if (!mTxn->mOperations.empty()) {
--- a/intl/icu/Makefile.in
+++ b/intl/icu/Makefile.in
@@ -1,14 +1,13 @@
 # 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/.
 
 STANDALONE_MAKEFILE = 1
-SUPPRESS_DEFAULT_RULES = 1
 
 # Ensure that this happens before including rules.mk
 ifdef ENABLE_INTL_API
   ifndef MOZ_NATIVE_ICU
   # Library names: On Windows, ICU uses modified library names for static
   # and debug libraries.
     ifeq ($(OS_ARCH),WINNT)
       ifdef MOZ_DEBUG
--- a/js/public/RootingAPI.h
+++ b/js/public/RootingAPI.h
@@ -133,16 +133,17 @@ class HeapBase {};
  */
 struct NullPtr
 {
     static void * const constNullValue;
 };
 
 namespace gc {
 struct Cell;
+template<typename T>
 struct PersistentRootedMarker;
 } /* namespace gc */
 
 } /* namespace js */
 
 namespace JS {
 
 template <typename T> class Rooted;
@@ -1185,17 +1186,18 @@ MutableHandle<T>::MutableHandle(Persiste
  * TenuredHeap<T> would be better types. It's up to the implementor of the type
  * containing Heap<T> or TenuredHeap<T> members to make sure their referents get
  * marked when the object itself is marked.
  */
 template<typename T>
 class PersistentRooted : private mozilla::LinkedListElement<PersistentRooted<T> > {
     friend class mozilla::LinkedList<PersistentRooted>;
     friend class mozilla::LinkedListElement<PersistentRooted>;
-    friend class js::gc::PersistentRootedMarker;
+
+    friend class js::gc::PersistentRootedMarker<T>;
 
     void registerWithRuntime(JSRuntime *rt) {
         JS::shadow::Runtime *srt = JS::shadow::Runtime::asShadowRuntime(rt);
         srt->getPersistentRootedList<T>().insertBack(this);
     }
 
   public:
     PersistentRooted(JSContext *cx) : ptr(js::GCMethods<T>::initial())
--- a/js/src/gc/Barrier.h
+++ b/js/src/gc/Barrier.h
@@ -366,49 +366,54 @@ class EncapsulatedPtr : public Barriered
  * Not to be confused with JS::Heap<T>.
  */
 template <class T, class Unioned = uintptr_t>
 class HeapPtr : public BarrieredPtr<T, Unioned>
 {
   public:
     HeapPtr() : BarrieredPtr<T, Unioned>(nullptr) {}
     explicit HeapPtr(T *v) : BarrieredPtr<T, Unioned>(v) { post(); }
-    explicit HeapPtr(const HeapPtr<T> &v) : BarrieredPtr<T, Unioned>(v) { post(); }
+    explicit HeapPtr(const HeapPtr<T, Unioned> &v) : BarrieredPtr<T, Unioned>(v) { post(); }
 
     void init(T *v) {
         JS_ASSERT(!IsPoisonedPtr<T>(v));
         this->value = v;
         post();
     }
 
     HeapPtr<T, Unioned> &operator=(T *v) {
         this->pre();
         JS_ASSERT(!IsPoisonedPtr<T>(v));
         this->value = v;
         post();
         return *this;
     }
 
-    HeapPtr<T, Unioned> &operator=(const HeapPtr<T> &v) {
+    HeapPtr<T, Unioned> &operator=(const HeapPtr<T, Unioned> &v) {
         this->pre();
         JS_ASSERT(!IsPoisonedPtr<T>(v.value));
         this->value = v.value;
         post();
         return *this;
     }
 
   protected:
     void post() { T::writeBarrierPost(this->value, (void *)&this->value); }
 
     /* Make this friend so it can access pre() and post(). */
     template <class T1, class T2>
     friend inline void
     BarrieredSetPair(Zone *zone,
                      HeapPtr<T1> &v1, T1 *val1,
                      HeapPtr<T2> &v2, T2 *val2);
+
+  private:
+    /* The default move construction and assignment operators would be incorrect. */
+    HeapPtr(HeapPtr<T> &&) MOZ_DELETE;
+    HeapPtr<T, Unioned> &operator=(HeapPtr<T, Unioned> &&) MOZ_DELETE;
 };
 
 /*
  * FixedHeapPtr is designed for one very narrow case: replacing immutable raw
  * pointers to GC-managed things, implicitly converting to a handle type for
  * ease of use.  Pointers encapsulated by this type must:
  *
  *   be immutable (no incremental write barriers),
@@ -775,16 +780,20 @@ class HeapValue : public BarrieredValue
   private:
     void post() {
         writeBarrierPost(value, &value);
     }
 
     void post(JSRuntime *rt) {
         writeBarrierPost(rt, value, &value);
     }
+
+    /* The default move construction and assignment operators would be incorrect. */
+    HeapValue(HeapValue &&) MOZ_DELETE;
+    HeapValue &operator=(HeapValue &&) MOZ_DELETE;
 };
 
 class RelocatableValue : public BarrieredValue
 {
   public:
     explicit RelocatableValue() : BarrieredValue(UndefinedValue()) {}
 
     explicit RelocatableValue(const Value &v)
@@ -1115,16 +1124,20 @@ class HeapId : public BarrieredId
         post();
         return *this;
     }
 
   private:
     void post() {};
 
     HeapId(const HeapId &v) MOZ_DELETE;
+
+    /* The default move construction and assignment operators would be incorrect. */
+    HeapId(HeapId &&) MOZ_DELETE;
+    HeapId &operator=(HeapId &&) MOZ_DELETE;
 };
 
 /*
  * Incremental GC requires that weak pointers have read barriers. This is mostly
  * an issue for empty shapes stored in JSCompartment. The problem happens when,
  * during an incremental GC, some JS code stores one of the compartment's empty
  * shapes into an object already marked black. Normally, this would not be a
  * problem, because the empty shape would have been part of the initial snapshot
--- a/js/src/gc/Nursery.cpp
+++ b/js/src/gc/Nursery.cpp
@@ -4,20 +4,23 @@
  * 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/. */
 
 #ifdef JSGC_GENERATIONAL
 
 #include "gc/Nursery-inl.h"
 
+#include <inttypes.h>
+
 #include "jscompartment.h"
 #include "jsgc.h"
 #include "jsinfer.h"
 #include "jsutil.h"
+#include "prmjtime.h"
 
 #include "gc/GCInternals.h"
 #include "gc/Memory.h"
 #ifdef JS_ION
 #include "jit/IonFrames.h"
 #endif
 #include "vm/ArrayObject.h"
 #include "vm/Debugger.h"
@@ -27,16 +30,25 @@
 #include "vm/TypedArrayObject.h"
 
 #include "jsgcinlines.h"
 
 using namespace js;
 using namespace gc;
 using namespace mozilla;
 
+//#define PROFILE_NURSERY
+
+#ifdef PROFILE_NURSERY
+/*
+ * Print timing information for minor GCs that take longer than this time in microseconds.
+ */
+static int64_t GCReportThreshold = INT64_MAX;
+#endif
+
 bool
 js::Nursery::init()
 {
     JS_ASSERT(start() == 0);
 
     if (!hugeSlots.init())
         return false;
 
@@ -63,16 +75,22 @@ js::Nursery::init()
     numActiveChunks_ = 1;
     setCurrentChunk(0);
 #ifdef JS_GC_ZEAL
     JS_POISON(heap, FreshNursery, NurserySize);
 #endif
     for (int i = 0; i < NumNurseryChunks; ++i)
         chunk(i).trailer.runtime = rt;
 
+#ifdef PROFILE_NURSERY
+    char *env = getenv("JS_MINORGC_TIME");
+    if (env)
+        GCReportThreshold = atoi(env);
+#endif
+
     JS_ASSERT(isEnabled());
     return true;
 }
 
 js::Nursery::~Nursery()
 {
     if (start())
         UnmapPages(runtime(), (void *)start(), NurserySize);
@@ -621,86 +639,156 @@ CheckHashTablesAfterMovingGC(JSRuntime *
             c->checkWrapperMapAfterMovingGC();
             if (c->debugScopes)
                 c->debugScopes->checkHashTablesAfterMovingGC(rt);
         }
     }
 #endif
 }
 
+#ifdef PROFILE_NURSERY
+#define TIME_START(name) int64_t timstampStart_##name = PRMJ_Now()
+#define TIME_END(name) int64_t timstampEnd_##name = PRMJ_Now()
+#define TIME_TOTAL(name) (timstampEnd_##name - timstampStart_##name)
+#else
+#define TIME_START(name)
+#define TIME_END(name)
+#define TIME_TOTAL(name)
+#endif
+
 void
 js::Nursery::collect(JSRuntime *rt, JS::gcreason::Reason reason, TypeObjectList *pretenureTypes)
 {
     JS_AbortIfWrongThread(rt);
 
     if (rt->mainThread.suppressGC)
         return;
 
     if (!isEnabled())
         return;
 
     if (isEmpty())
         return;
 
+    TIME_START(total);
+
     AutoStopVerifyingBarriers av(rt, false);
 
+    TIME_START(waitBgSweep);
     rt->gcHelperThread.waitBackgroundSweepEnd();
+    TIME_END(waitBgSweep);
 
     /* Move objects pointed to by roots from the nursery to the major heap. */
     MinorCollectionTracer trc(rt, this);
+
+    TIME_START(markStoreBuffer);
     rt->gcStoreBuffer.mark(&trc); // This must happen first.
+    TIME_END(markStoreBuffer);
+
+    TIME_START(checkHashTables);
     CheckHashTablesAfterMovingGC(rt);
+    TIME_END(checkHashTables);
+
+    TIME_START(markRuntime);
     MarkRuntime(&trc);
+    TIME_END(markRuntime);
+
+    TIME_START(markDebugger);
     Debugger::markAll(&trc);
+    TIME_END(markDebugger);
+
+    TIME_START(clearNewObjectCache);
     rt->newObjectCache.clearNurseryObjects(rt);
+    TIME_END(clearNewObjectCache);
 
     /*
      * Most of the work is done here. This loop iterates over objects that have
      * been moved to the major heap. If these objects have any outgoing pointers
      * to the nursery, then those nursery objects get moved as well, until no
      * objects are left to move. That is, we iterate to a fixed point.
      */
+    TIME_START(collectToFP);
     TenureCountCache tenureCounts;
     collectToFixedPoint(&trc, tenureCounts);
+    TIME_END(collectToFP);
 
+    TIME_START(updateJitActivations);
 #ifdef JS_ION
     /* Update any slot or element pointers whose destination has been tenured. */
     js::jit::UpdateJitActivationsForMinorGC(rt, &trc);
 #endif
+    TIME_END(updateJitActivations);
 
     /* Resize the nursery. */
+    TIME_START(resize);
     double promotionRate = trc.tenuredSize / double(allocationEnd() - start());
     if (promotionRate > 0.05)
         growAllocableSpace();
     else if (promotionRate < 0.01)
         shrinkAllocableSpace();
+    TIME_END(resize);
 
+    TIME_START(pretenure);
     // If we are promoting the nursery, or exhausted the store buffer with
     // pointers to nursery things, which will force a collection well before
     // the nursery is full, look for object types that are getting promoted
     // excessively and try to pretenure them.
     if (pretenureTypes && (promotionRate > 0.8 || reason == JS::gcreason::FULL_STORE_BUFFER)) {
         for (size_t i = 0; i < ArrayLength(tenureCounts.entries); i++) {
             const TenureCount &entry = tenureCounts.entries[i];
             if (entry.count >= 3000)
                 pretenureTypes->append(entry.type); // ignore alloc failure
         }
     }
+    TIME_END(pretenure);
 
     /* Sweep. */
+    TIME_START(sweep);
     sweep(rt);
     rt->gcStoreBuffer.clear();
+    TIME_END(sweep);
 
     /*
      * We ignore gcMaxBytes when allocating for minor collection. However, if we
      * overflowed, we disable the nursery. The next time we allocate, we'll fail
      * because gcBytes >= gcMaxBytes.
      */
     if (rt->gcBytes >= rt->gcMaxBytes)
         disable();
+
+    TIME_END(total);
+
+#ifdef PROFILE_NURSERY
+    int64_t totalTime = TIME_TOTAL(total);
+
+    if (totalTime >= GCReportThreshold) {
+        static bool printedHeader = false;
+        if (!printedHeader) {
+            fprintf(stderr,
+                    "MinorGC time: Total   WaitBg  mkStrBf ckHshTb mkRuntm mkDbggr clrNOC  collect updtIon resize  pretnur sweep\n");
+            printedHeader = true;
+        }
+
+#define FMT " %7" PRIu64
+        fprintf(stderr, "MinorGC time:" FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT FMT "\n",
+                totalTime,
+                TIME_TOTAL(waitBgSweep),
+                TIME_TOTAL(markStoreBuffer),
+                TIME_TOTAL(checkHashTables),
+                TIME_TOTAL(markRuntime),
+                TIME_TOTAL(markDebugger),
+                TIME_TOTAL(clearNewObjectCache),
+                TIME_TOTAL(collectToFP),
+                TIME_TOTAL(updateJitActivations),
+                TIME_TOTAL(resize),
+                TIME_TOTAL(pretenure),
+                TIME_TOTAL(sweep));
+#undef FMT
+    }
+#endif
 }
 
 void
 js::Nursery::sweep(JSRuntime *rt)
 {
     /* Free malloced pointers owned by freed things in the nursery. */
     for (HugeSlotsSet::Range r = hugeSlots.all(); !r.empty(); r.popFront())
         rt->defaultFreeOp()->free_(r.front());
--- a/js/src/gc/RootMarking.cpp
+++ b/js/src/gc/RootMarking.cpp
@@ -622,65 +622,65 @@ JSPropertyDescriptor::trace(JSTracer *tr
         JSObject *tmp = JS_FUNC_TO_DATA_PTR(JSObject *, setter);
         MarkObjectRoot(trc, &tmp, "Descriptor::set");
         setter = JS_DATA_TO_FUNC_PTR(JSStrictPropertyOp, tmp);
     }
 }
 
 namespace js {
 namespace gc {
+
+template<typename T>
 struct PersistentRootedMarker
 {
-    template<typename Referent>
+    typedef PersistentRooted<T> Element;
+    typedef mozilla::LinkedList<Element> List;
+    typedef void (*MarkFunc)(JSTracer *trc, T *ref, const char *name);
+
+    template <MarkFunc Mark>
     static void
-    markChainIfNotNull(JSTracer *trc,
-                       mozilla::LinkedList<PersistentRooted<Referent *> > &list,
-                       void (*marker)(JSTracer *trc, Referent **ref, const char *name),
-                       const char *name)
+    markChainIfNotNull(JSTracer *trc, List &list, const char *name)
     {
-        for (PersistentRooted<Referent *> *r = list.getFirst(); r; r = r->getNext()) {
+        for (Element *r = list.getFirst(); r; r = r->getNext()) {
             if (r->get())
-                marker(trc, r->address(), name);
+                Mark(trc, r->address(), name);
         }
     }
 
-    template<typename Referent>
+    template <MarkFunc Mark>
     static void
-    markChain(JSTracer *trc,
-              mozilla::LinkedList<PersistentRooted<Referent> > &list,
-              void (*marker)(JSTracer *trc, Referent *ref, const char *name),
-              const char *name)
+    markChain(JSTracer *trc, List &list, const char *name)
     {
-        for (PersistentRooted<Referent> *r = list.getFirst(); r; r = r->getNext())
-            marker(trc, r->address(), name);
+        for (Element *r = list.getFirst(); r; r = r->getNext())
+            Mark(trc, r->address(), name);
     }
 };
 }
 }
 
 void
 js::gc::MarkPersistentRootedChains(JSTracer *trc)
 {
     JSRuntime *rt = trc->runtime;
 
     // Mark the PersistentRooted chains of types that may be null.
-    PersistentRootedMarker::markChainIfNotNull(trc, rt->functionPersistentRooteds, &MarkObjectRoot,
-                                               "PersistentRooted<JSFunction *>");
-    PersistentRootedMarker::markChainIfNotNull(trc, rt->objectPersistentRooteds, &MarkObjectRoot,
-                                               "PersistentRooted<JSObject *>");
-    PersistentRootedMarker::markChainIfNotNull(trc, rt->scriptPersistentRooteds, &MarkScriptRoot,
-                                               "PersistentRooted<JSScript *>");
-    PersistentRootedMarker::markChainIfNotNull(trc, rt->stringPersistentRooteds, &MarkStringRoot,
-                                               "PersistentRooted<JSString *>");
+    PersistentRootedMarker<JSFunction*>::markChainIfNotNull<MarkObjectRoot>(
+        trc, rt->functionPersistentRooteds, "PersistentRooted<JSFunction *>");
+    PersistentRootedMarker<JSObject*>::markChainIfNotNull<MarkObjectRoot>(
+        trc, rt->objectPersistentRooteds, "PersistentRooted<JSObject *>");
+    PersistentRootedMarker<JSScript*>::markChainIfNotNull<MarkScriptRoot>(
+        trc, rt->scriptPersistentRooteds, "PersistentRooted<JSScript *>");
+    PersistentRootedMarker<JSString*>::markChainIfNotNull<MarkStringRoot>(
+        trc, rt->stringPersistentRooteds, "PersistentRooted<JSString *>");
 
     // Mark the PersistentRooted chains of types that are never null.
-    PersistentRootedMarker::markChain(trc, rt->idPersistentRooteds, &MarkIdRoot,
-                                      "PersistentRooted<jsid>");
-    PersistentRootedMarker::markChain(trc, rt->valuePersistentRooteds, &MarkValueRoot,
-                                      "PersistentRooted<Value>");
+    PersistentRootedMarker<jsid>::markChain<MarkIdRoot>(trc, rt->idPersistentRooteds,
+                                                        "PersistentRooted<jsid>");
+    PersistentRootedMarker<Value>::markChain<MarkValueRoot>(trc, rt->valuePersistentRooteds,
+                                                            "PersistentRooted<Value>");
 }
 
 void
 js::gc::MarkRuntime(JSTracer *trc, bool useSavedRoots)
 {
     JSRuntime *rt = trc->runtime;
     JS_ASSERT(trc->callback != GCMarker::GrayCallback);
 
--- a/js/src/jit/AsmJS.cpp
+++ b/js/src/jit/AsmJS.cpp
@@ -17,16 +17,17 @@
 #include "prmjtime.h"
 
 #include "assembler/assembler/MacroAssembler.h"
 #include "frontend/Parser.h"
 #include "jit/AsmJSLink.h"
 #include "jit/AsmJSModule.h"
 #include "jit/AsmJSSignalHandlers.h"
 #include "jit/CodeGenerator.h"
+#include "jit/CompileWrappers.h"
 #include "jit/MIR.h"
 #include "jit/MIRGraph.h"
 #ifdef JS_ION_PERF
 # include "jit/PerfSpewer.h"
 #endif
 #include "vm/Interpreter.h"
 
 #include "jsinferinlines.h"
@@ -2038,17 +2039,19 @@ class FunctionCompiler
         JS_ASSERT(locals_.count() == argTypes.length() + varInitializers_.length());
 
         alloc_  = lifo_.new_<TempAllocator>(&lifo_);
         ionContext_.construct(m_.cx(), alloc_);
 
         graph_  = lifo_.new_<MIRGraph>(alloc_);
         info_   = lifo_.new_<CompileInfo>(locals_.count(), SequentialExecution);
         const OptimizationInfo *optimizationInfo = js_IonOptimizations.get(Optimization_AsmJS);
-        mirGen_ = lifo_.new_<MIRGenerator>(CompileCompartment::get(cx()->compartment()), alloc_,
+        const JitCompileOptions options;
+        mirGen_ = lifo_.new_<MIRGenerator>(CompileCompartment::get(cx()->compartment()),
+                                           options, alloc_,
                                            graph_, info_, optimizationInfo);
 
         if (!newBlock(/* pred = */ nullptr, &curBlock_, fn_))
             return false;
 
         curBlock_->add(MAsmJSCheckOverRecursed::New(alloc(), &m_.stackOverflowLabel()));
 
         for (ABIArgTypeIter i = argTypes; !i.done(); i++) {
--- a/js/src/jit/BaselineCompiler.cpp
+++ b/js/src/jit/BaselineCompiler.cpp
@@ -1185,19 +1185,43 @@ BaselineCompiler::emit_JSOP_DOUBLE()
 
 bool
 BaselineCompiler::emit_JSOP_STRING()
 {
     frame.push(StringValue(script->getAtom(pc)));
     return true;
 }
 
+typedef JSObject *(*DeepCloneObjectLiteralFn)(JSContext *, HandleObject, NewObjectKind);
+static const VMFunction DeepCloneObjectLiteralInfo =
+    FunctionInfo<DeepCloneObjectLiteralFn>(DeepCloneObjectLiteral);
+
 bool
 BaselineCompiler::emit_JSOP_OBJECT()
 {
+    if (JS::CompartmentOptionsRef(cx).cloneSingletons(cx)) {
+        RootedObject obj(cx, script->getObject(GET_UINT32_INDEX(pc)));
+        if (!obj)
+            return false;
+
+        prepareVMCall();
+
+        pushArg(ImmWord(js::MaybeSingletonObject));
+        pushArg(ImmGCPtr(obj));
+
+        if (!callVM(DeepCloneObjectLiteralInfo))
+            return false;
+
+        // Box and push return value.
+        masm.tagValue(JSVAL_TYPE_OBJECT, ReturnReg, R0);
+        frame.push(R0);
+        return true;
+    }
+
+    JS::CompartmentOptionsRef(cx).setSingletonsAsValues();
     frame.push(ObjectValue(*script->getObject(pc)));
     return true;
 }
 
 typedef JSObject *(*CloneRegExpObjectFn)(JSContext *, JSObject *);
 static const VMFunction CloneRegExpObjectInfo =
     FunctionInfo<CloneRegExpObjectFn>(CloneRegExpObject);
 
--- a/js/src/jit/CodeGenerator.cpp
+++ b/js/src/jit/CodeGenerator.cpp
@@ -1073,16 +1073,28 @@ CodeGenerator::visitTableSwitchV(LTableS
     masm.bind(&unboxInt);
     masm.unboxInt32(value, index);
 
     masm.bind(&isInt);
 
     return emitTableSwitchDispatch(mir, index, ToRegisterOrInvalid(ins->tempPointer()));
 }
 
+typedef JSObject *(*DeepCloneObjectLiteralFn)(JSContext *, HandleObject, NewObjectKind);
+static const VMFunction DeepCloneObjectLiteralInfo =
+    FunctionInfo<DeepCloneObjectLiteralFn>(DeepCloneObjectLiteral);
+
+bool
+CodeGenerator::visitCloneLiteral(LCloneLiteral *lir)
+{
+    pushArg(ImmWord(js::MaybeSingletonObject));
+    pushArg(ToRegister(lir->output()));
+    return callVM(DeepCloneObjectLiteralInfo, lir);
+}
+
 bool
 CodeGenerator::visitParameter(LParameter *lir)
 {
     return true;
 }
 
 bool
 CodeGenerator::visitCallee(LCallee *lir)
--- a/js/src/jit/CodeGenerator.h
+++ b/js/src/jit/CodeGenerator.h
@@ -55,16 +55,17 @@ class CodeGenerator : public CodeGenerat
     bool link(JSContext *cx, types::CompilerConstraintList *constraints);
 
     bool visitLabel(LLabel *lir);
     bool visitNop(LNop *lir);
     bool visitOsiPoint(LOsiPoint *lir);
     bool visitGoto(LGoto *lir);
     bool visitTableSwitch(LTableSwitch *ins);
     bool visitTableSwitchV(LTableSwitchV *ins);
+    bool visitCloneLiteral(LCloneLiteral *lir);
     bool visitParameter(LParameter *lir);
     bool visitCallee(LCallee *lir);
     bool visitStart(LStart *lir);
     bool visitReturn(LReturn *ret);
     bool visitDefVar(LDefVar *lir);
     bool visitDefFun(LDefFun *lir);
     bool visitOsrEntry(LOsrEntry *lir);
     bool visitOsrScopeChain(LOsrScopeChain *lir);
--- a/js/src/jit/CompileWrappers.cpp
+++ b/js/src/jit/CompileWrappers.cpp
@@ -226,16 +226,40 @@ CompileCompartment::jitCompartment()
 }
 
 bool
 CompileCompartment::hasObjectMetadataCallback()
 {
     return compartment()->hasObjectMetadataCallback();
 }
 
+// Note: This function is thread-safe because setSingletonAsValue sets a boolean
+// variable to false, and this boolean variable has no way to be resetted to
+// true. So even if there is a concurrent write, this concurrent write will
+// always have the same value.  If there is a concurrent read, then we will
+// clone a singleton instead of using the value which is baked in the JSScript,
+// and this would be an unfortunate allocation, but this will not change the
+// semantics of the JavaScript code which is executed.
+void
+CompileCompartment::setSingletonsAsValues()
+{
+    return JS::CompartmentOptionsRef(compartment()).setSingletonsAsValues();
+}
+
 #ifdef JS_THREADSAFE
 AutoLockForCompilation::AutoLockForCompilation(CompileCompartment *compartment
                                                MOZ_GUARD_OBJECT_NOTIFIER_PARAM_IN_IMPL)
 {
     MOZ_GUARD_OBJECT_NOTIFIER_INIT;
     init(compartment->compartment()->runtimeFromAnyThread());
 }
 #endif
+
+JitCompileOptions::JitCompileOptions()
+  : cloneSingletons_(false)
+{
+}
+
+JitCompileOptions::JitCompileOptions(JSContext *cx)
+{
+    JS::CompartmentOptions &options = cx->compartment()->options();
+    cloneSingletons_ = options.cloneSingletons(cx);
+}
--- a/js/src/jit/CompileWrappers.h
+++ b/js/src/jit/CompileWrappers.h
@@ -108,16 +108,34 @@ class CompileCompartment
 
     const void *addressOfEnumerators();
 
     const CallsiteCloneTable &callsiteClones();
 
     const JitCompartment *jitCompartment();
 
     bool hasObjectMetadataCallback();
+
+    // Mirror CompartmentOptions.
+    void setSingletonsAsValues();
 };
 
+class JitCompileOptions
+{
+  public:
+    JitCompileOptions();
+    JitCompileOptions(JSContext *cx);
+
+    bool cloneSingletons() const {
+        return cloneSingletons_;
+    }
+
+  private:
+    bool cloneSingletons_;
+};
+
+
 } // namespace jit
 } // namespace js
 
 #endif // JS_ION
 
 #endif // jit_CompileWrappers_h
--- a/js/src/jit/Ion.cpp
+++ b/js/src/jit/Ion.cpp
@@ -1701,20 +1701,21 @@ IonCompile(JSContext *cx, JSScript *scri
     AutoFlushCache afc("IonCompile", cx->runtime()->jitRuntime());
 
     AutoTempAllocatorRooter root(cx, temp);
     types::CompilerConstraintList *constraints = types::NewCompilerConstraintList(*temp);
     if (!constraints)
         return AbortReason_Alloc;
 
     const OptimizationInfo *optimizationInfo = js_IonOptimizations.get(optimizationLevel);
+    const JitCompileOptions options(cx);
 
     IonBuilder *builder = alloc->new_<IonBuilder>((JSContext *) nullptr,
                                                   CompileCompartment::get(cx->compartment()),
-                                                  temp, graph, constraints,
+                                                  options, temp, graph, constraints,
                                                   inspector, info, optimizationInfo,
                                                   baselineFrameInspector);
     if (!builder)
         return AbortReason_Alloc;
 
     JS_ASSERT(recompile == HasIonScript(builder->script(), executionMode));
     JS_ASSERT(CanIonCompile(builder->script(), executionMode));
 
--- a/js/src/jit/IonAnalysis.cpp
+++ b/js/src/jit/IonAnalysis.cpp
@@ -2182,17 +2182,19 @@ jit::AnalyzeNewScriptProperties(JSContex
                      script->needsArgsObj());
 
     AutoTempAllocatorRooter root(cx, &temp);
 
     const OptimizationInfo *optimizationInfo = js_IonOptimizations.get(Optimization_Normal);
 
     types::CompilerConstraintList *constraints = types::NewCompilerConstraintList(temp);
     BaselineInspector inspector(script);
-    IonBuilder builder(cx, CompileCompartment::get(cx->compartment()), &temp, &graph, constraints,
+    const JitCompileOptions options(cx);
+
+    IonBuilder builder(cx, CompileCompartment::get(cx->compartment()), options, &temp, &graph, constraints,
                        &inspector, &info, optimizationInfo, /* baselineFrame = */ nullptr);
 
     if (!builder.build()) {
         if (builder.abortReason() == AbortReason_Alloc)
             return false;
         return true;
     }
 
--- a/js/src/jit/IonBuilder.cpp
+++ b/js/src/jit/IonBuilder.cpp
@@ -98,23 +98,24 @@ jit::NewBaselineFrameInspector(TempAlloc
             inspector->varTypes.infallibleAppend(types::Type::UndefinedType());
         else
             inspector->varTypes.infallibleAppend(types::GetValueType(frame->unaliasedVar(i)));
     }
 
     return inspector;
 }
 
-IonBuilder::IonBuilder(JSContext *analysisContext, CompileCompartment *comp, TempAllocator *temp,
+IonBuilder::IonBuilder(JSContext *analysisContext, CompileCompartment *comp,
+                       const JitCompileOptions &options, TempAllocator *temp,
                        MIRGraph *graph, types::CompilerConstraintList *constraints,
                        BaselineInspector *inspector, CompileInfo *info,
                        const OptimizationInfo *optimizationInfo,
                        BaselineFrameInspector *baselineFrame, size_t inliningDepth,
                        uint32_t loopDepth)
-  : MIRGenerator(comp, temp, graph, info, optimizationInfo),
+  : MIRGenerator(comp, options, temp, graph, info, optimizationInfo),
     backgroundCodegen_(nullptr),
     analysisContext(analysisContext),
     baselineFrame_(baselineFrame),
     abortReason_(AbortReason_Disable),
     reprSetHash_(nullptr),
     constraints_(constraints),
     analysis_(*temp, info->script()),
     thisTypes(nullptr),
@@ -3894,17 +3895,17 @@ IonBuilder::inlineScriptedCall(CallInfo 
         return false;
 
     MIRGraphReturns returns(alloc());
     AutoAccumulateReturns aar(graph(), returns);
 
     unlock();
 
     // Build the graph.
-    IonBuilder inlineBuilder(analysisContext, compartment, &alloc(), &graph(), constraints(),
+    IonBuilder inlineBuilder(analysisContext, compartment, options, &alloc(), &graph(), constraints(),
                              &inspector, info, &optimizationInfo(), nullptr, inliningDepth_ + 1,
                              loopDepth_);
     if (!inlineBuilder.buildInline(this, outerResumePoint, callInfo)) {
         if (analysisContext && analysisContext->isExceptionPending()) {
             IonSpew(IonSpew_Abort, "Inline builder raised exception.");
             abortReason_ = AbortReason_Error;
             return false;
         }
@@ -9100,16 +9101,24 @@ IonBuilder::jsop_regexp(RegExpObject *re
     }
 
     return true;
 }
 
 bool
 IonBuilder::jsop_object(JSObject *obj)
 {
+    if (options.cloneSingletons()) {
+        MCloneLiteral *clone = MCloneLiteral::New(alloc(), constant(ObjectValue(*obj)));
+        current->add(clone);
+        current->push(clone);
+        return resumeAfter(clone);
+    }
+
+    compartment->setSingletonsAsValues();
     pushConstant(ObjectValue(*obj));
     return true;
 }
 
 bool
 IonBuilder::jsop_lambda(JSFunction *fun)
 {
     JS_ASSERT(analysis().usesScopeChain());
--- a/js/src/jit/IonBuilder.h
+++ b/js/src/jit/IonBuilder.h
@@ -207,17 +207,18 @@ class IonBuilder : public MIRGenerator
         static CFGState CondSwitch(IonBuilder *builder, jsbytecode *exitpc, jsbytecode *defaultTarget);
         static CFGState Label(jsbytecode *exitpc);
         static CFGState Try(jsbytecode *exitpc, MBasicBlock *successor);
     };
 
     static int CmpSuccessors(const void *a, const void *b);
 
   public:
-    IonBuilder(JSContext *analysisContext, CompileCompartment *comp, TempAllocator *temp,
+    IonBuilder(JSContext *analysisContext, CompileCompartment *comp,
+               const JitCompileOptions &options, TempAllocator *temp,
                MIRGraph *graph, types::CompilerConstraintList *constraints,
                BaselineInspector *inspector, CompileInfo *info,
                const OptimizationInfo *optimizationInfo, BaselineFrameInspector *baselineFrame,
                size_t inliningDepth = 0, uint32_t loopDepth = 0);
 
     bool build();
     bool buildInline(IonBuilder *callerBuilder, MResumePoint *callerResumePoint,
                      CallInfo &callInfo);
--- a/js/src/jit/LIR-Common.h
+++ b/js/src/jit/LIR-Common.h
@@ -227,16 +227,37 @@ class LValue : public LInstructionHelper
       : v_(v)
     { }
 
     Value value() const {
         return v_;
     }
 };
 
+// Clone an object literal such as we are not modifying the object contained in
+// the sources.
+class LCloneLiteral : public LCallInstructionHelper<1, 1, 0>
+{
+  public:
+    LIR_HEADER(CloneLiteral)
+
+    LCloneLiteral(const LAllocation &obj)
+    {
+        setOperand(0, obj);
+    }
+
+    const LAllocation *getObjectLiteral() {
+        return getOperand(0);
+    }
+
+    MCloneLiteral *mir() const {
+        return mir_->toCloneLiteral();
+    }
+};
+
 // Formal argument for a function, returning a box. Formal arguments are
 // initially read from the stack.
 class LParameter : public LInstructionHelper<BOX_PIECES, 0, 0>
 {
   public:
     LIR_HEADER(Parameter)
 };
 
--- a/js/src/jit/LOpcodes.h
+++ b/js/src/jit/LOpcodes.h
@@ -12,16 +12,17 @@
     _(Nop)                          \
     _(OsiPoint)                     \
     _(MoveGroup)                    \
     _(Integer)                      \
     _(Pointer)                      \
     _(Double)                       \
     _(Float32)                      \
     _(Value)                        \
+    _(CloneLiteral)                 \
     _(Parameter)                    \
     _(Callee)                       \
     _(TableSwitch)                  \
     _(TableSwitchV)                 \
     _(Goto)                         \
     _(NewArray)                     \
     _(NewObject)                    \
     _(NewSlots)                     \
--- a/js/src/jit/Lowering.cpp
+++ b/js/src/jit/Lowering.cpp
@@ -23,16 +23,26 @@
 
 using namespace js;
 using namespace jit;
 
 using mozilla::DebugOnly;
 using JS::GenericNaN;
 
 bool
+LIRGenerator::visitCloneLiteral(MCloneLiteral *ins)
+{
+    JS_ASSERT(ins->type() == MIRType_Object);
+    JS_ASSERT(ins->input()->type() == MIRType_Object);
+
+    LCloneLiteral *lir = new(alloc()) LCloneLiteral(useRegisterAtStart(ins->input()));
+    return defineReturn(lir, ins) && assignSafepoint(lir, ins);
+}
+
+bool
 LIRGenerator::visitParameter(MParameter *param)
 {
     ptrdiff_t offset;
     if (param->index() == MParameter::THIS_SLOT)
         offset = THIS_FRAME_ARGSLOT;
     else
         offset = 1 + param->index();
 
--- a/js/src/jit/Lowering.h
+++ b/js/src/jit/Lowering.h
@@ -56,16 +56,17 @@ class LIRGenerator : public LIRGenerator
     bool lowerCallArguments(MCall *call);
 
   public:
     bool visitInstruction(MInstruction *ins);
     bool visitBlock(MBasicBlock *block);
 
     // Visitor hooks are explicit, to give CPU-specific versions a chance to
     // intercept without a bunch of explicit gunk in the .cpp.
+    bool visitCloneLiteral(MCloneLiteral *ins);
     bool visitParameter(MParameter *param);
     bool visitCallee(MCallee *callee);
     bool visitGoto(MGoto *ins);
     bool visitTableSwitch(MTableSwitch *tableswitch);
     bool visitNewSlots(MNewSlots *ins);
     bool visitNewArray(MNewArray *ins);
     bool visitNewObject(MNewObject *ins);
     bool visitNewDeclEnvObject(MNewDeclEnvObject *ins);
--- a/js/src/jit/MIR.cpp
+++ b/js/src/jit/MIR.cpp
@@ -534,16 +534,22 @@ MConstant::canProduceFloat32() const
 
     if (type() == MIRType_Int32)
         return IsFloat32Representable(static_cast<double>(value_.toInt32()));
     if (type() == MIRType_Double)
         return IsFloat32Representable(value_.toDouble());
     return true;
 }
 
+MCloneLiteral *
+MCloneLiteral::New(TempAllocator &alloc, MDefinition *obj)
+{
+    return new(alloc) MCloneLiteral(obj);
+}
+
 void
 MControlInstruction::printOpcode(FILE *fp) const
 {
     MDefinition::printOpcode(fp);
     for (size_t j = 0; j < numSuccessors(); j++)
         fprintf(fp, " block%d", getSuccessor(j)->id());
 }
 
--- a/js/src/jit/MIR.h
+++ b/js/src/jit/MIR.h
@@ -994,16 +994,37 @@ class MConstant : public MNullaryInstruc
     }
 
     void computeRange(TempAllocator &alloc);
     bool truncate();
 
     bool canProduceFloat32() const;
 };
 
+// Deep clone a constant JSObject.
+class MCloneLiteral
+  : public MUnaryInstruction,
+    public ObjectPolicy<0>
+{
+  protected:
+    MCloneLiteral(MDefinition *obj)
+      : MUnaryInstruction(obj)
+    {
+        setResultType(MIRType_Object);
+    }
+
+  public:
+    INSTRUCTION_HEADER(CloneLiteral)
+    static MCloneLiteral *New(TempAllocator &alloc, MDefinition *obj);
+
+    TypePolicy *typePolicy() {
+        return this;
+    }
+};
+
 class MParameter : public MNullaryInstruction
 {
     int32_t index_;
 
   public:
     static const int32_t THIS_SLOT = -1;
 
     MParameter(int32_t index, types::TemporaryTypeSet *types)
--- a/js/src/jit/MIRGenerator.h
+++ b/js/src/jit/MIRGenerator.h
@@ -29,17 +29,18 @@ namespace jit {
 class MBasicBlock;
 class MIRGraph;
 class MStart;
 class OptimizationInfo;
 
 class MIRGenerator
 {
   public:
-    MIRGenerator(CompileCompartment *compartment, TempAllocator *alloc, MIRGraph *graph,
+    MIRGenerator(CompileCompartment *compartment, const JitCompileOptions &options,
+                 TempAllocator *alloc, MIRGraph *graph,
                  CompileInfo *info, const OptimizationInfo *optimizationInfo);
 
     TempAllocator &alloc() {
         return *alloc_;
     }
     MIRGraph &graph() {
         return *graph_;
     }
@@ -158,14 +159,17 @@ class MIRGenerator
     bool modifiesFrameArguments_;
 
 #if defined(JS_ION_PERF)
     AsmJSPerfSpewer asmJSPerfSpewer_;
 
   public:
     AsmJSPerfSpewer &perfSpewer() { return asmJSPerfSpewer_; }
 #endif
+
+  public:
+    const JitCompileOptions options;
 };
 
 } // namespace jit
 } // namespace js
 
 #endif /* jit_MIRGenerator_h */
--- a/js/src/jit/MIRGraph.cpp
+++ b/js/src/jit/MIRGraph.cpp
@@ -11,32 +11,33 @@
 #include "jit/Ion.h"
 #include "jit/IonSpewer.h"
 #include "jit/MIR.h"
 #include "jit/MIRGenerator.h"
 
 using namespace js;
 using namespace js::jit;
 
-MIRGenerator::MIRGenerator(CompileCompartment *compartment,
+MIRGenerator::MIRGenerator(CompileCompartment *compartment, const JitCompileOptions &options,
                            TempAllocator *alloc, MIRGraph *graph, CompileInfo *info,
                            const OptimizationInfo *optimizationInfo)
   : compartment(compartment),
     info_(info),
     optimizationInfo_(optimizationInfo),
     alloc_(alloc),
     graph_(graph),
     error_(false),
     cancelBuild_(0),
     maxAsmJSStackArgBytes_(0),
     performsAsmJSCall_(false),
     asmJSHeapAccesses_(*alloc),
     asmJSGlobalAccesses_(*alloc),
     minAsmJSHeapLength_(AsmJSAllocationGranularity),
-    modifiesFrameArguments_(false)
+    modifiesFrameArguments_(false),
+    options(options)
 { }
 
 bool
 MIRGenerator::abortFmt(const char *message, va_list ap)
 {
     IonSpewVA(IonSpew_Abort, message, ap);
     error_ = true;
     return false;
--- a/js/src/jit/MOpcodes.h
+++ b/js/src/jit/MOpcodes.h
@@ -7,16 +7,17 @@
 #ifndef jit_MOpcodes_h
 #define jit_MOpcodes_h
 
 namespace js {
 namespace jit {
 
 #define MIR_OPCODE_LIST(_)                                                  \
     _(Constant)                                                             \
+    _(CloneLiteral)                                                         \
     _(Parameter)                                                            \
     _(Callee)                                                               \
     _(TableSwitch)                                                          \
     _(Goto)                                                                 \
     _(Test)                                                                 \
     _(TypeObjectDispatch)                                                   \
     _(FunctionDispatch)                                                     \
     _(Compare)                                                              \
--- a/js/src/jit/ParallelSafetyAnalysis.cpp
+++ b/js/src/jit/ParallelSafetyAnalysis.cpp
@@ -107,16 +107,17 @@ class ParallelSafetyVisitor : public MIn
     }
 
     bool convertToBailout(MBasicBlock *block, MInstruction *ins);
 
     // I am taking the policy of blacklisting everything that's not
     // obviously safe for now.  We can loosen as we need.
 
     SAFE_OP(Constant)
+    UNSAFE_OP(CloneLiteral)
     SAFE_OP(Parameter)
     SAFE_OP(Callee)
     SAFE_OP(TableSwitch)
     SAFE_OP(Goto)
     SAFE_OP(Test)
     SAFE_OP(Compare)
     SAFE_OP(Phi)
     SAFE_OP(Beta)
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -2495,16 +2495,22 @@ JS::CompartmentOptions::ion(JSContext *c
 }
 
 bool
 JS::CompartmentOptions::asmJS(JSContext *cx) const
 {
     return asmJSOverride_.get(cx->options().asmJS());
 }
 
+bool
+JS::CompartmentOptions::cloneSingletons(JSContext *cx) const
+{
+    return cloneSingletonsOverride_.get(cx->options().cloneSingletons());
+}
+
 JS::CompartmentOptions &
 JS::CompartmentOptions::setZone(ZoneSpecifier spec)
 {
     zone_.spec = spec;
     return *this;
 }
 
 JS::CompartmentOptions &
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1457,17 +1457,18 @@ class JS_PUBLIC_API(ContextOptions) {
         privateIsNSISupports_(false),
         dontReportUncaught_(false),
         noDefaultCompartmentObject_(false),
         noScriptRval_(false),
         strictMode_(false),
         baseline_(false),
         typeInference_(false),
         ion_(false),
-        asmJS_(false)
+        asmJS_(false),
+        cloneSingletons_(false)
     {
     }
 
     bool extraWarnings() const { return extraWarnings_; }
     ContextOptions &setExtraWarnings(bool flag) {
         extraWarnings_ = flag;
         return *this;
     }
@@ -1581,29 +1582,40 @@ class JS_PUBLIC_API(ContextOptions) {
         asmJS_ = flag;
         return *this;
     }
     ContextOptions &toggleAsmJS() {
         asmJS_ = !asmJS_;
         return *this;
     }
 
+    bool cloneSingletons() const { return cloneSingletons_; }
+    ContextOptions &setCloneSingletons(bool flag) {
+        cloneSingletons_ = flag;
+        return *this;
+    }
+    ContextOptions &toggleCloneSingletons() {
+        cloneSingletons_ = !cloneSingletons_;
+        return *this;
+    }
+
   private:
     bool extraWarnings_ : 1;
     bool werror_ : 1;
     bool varObjFix_ : 1;
     bool privateIsNSISupports_ : 1;
     bool dontReportUncaught_ : 1;
     bool noDefaultCompartmentObject_ : 1;
     bool noScriptRval_ : 1;
     bool strictMode_ : 1;
     bool baseline_ : 1;
     bool typeInference_ : 1;
     bool ion_ : 1;
     bool asmJS_ : 1;
+    bool cloneSingletons_ : 1;
 };
 
 JS_PUBLIC_API(ContextOptions &)
 ContextOptionsRef(JSContext *cx);
 
 class JS_PUBLIC_API(AutoSaveContextOptions) {
   public:
     AutoSaveContextOptions(JSContext *cx)
@@ -2606,16 +2618,17 @@ class JS_PUBLIC_API(CompartmentOptions)
 
         Mode mode_;
     };
 
     explicit CompartmentOptions()
       : version_(JSVERSION_UNKNOWN)
       , invisibleToDebugger_(false)
       , mergeable_(false)
+      , singletonsAsTemplates_(true)
     {
         zone_.spec = JS::FreshZone;
     }
 
     JSVersion version() const { return version_; }
     CompartmentOptions &setVersion(JSVersion aVersion) {
         MOZ_ASSERT(aVersion != JSVERSION_UNKNOWN);
         version_ = aVersion;
@@ -2649,36 +2662,52 @@ class JS_PUBLIC_API(CompartmentOptions)
     Override &typeInferenceOverride() { return typeInferenceOverride_; }
 
     bool ion(JSContext *cx) const;
     Override &ionOverride() { return ionOverride_; }
 
     bool asmJS(JSContext *cx) const;
     Override &asmJSOverride() { return asmJSOverride_; }
 
+    bool cloneSingletons(JSContext *cx) const;
+    Override &cloneSingletonsOverride() { return cloneSingletonsOverride_; }
+
     void *zonePointer() const {
         JS_ASSERT(uintptr_t(zone_.pointer) > uintptr_t(JS::SystemZone));
         return zone_.pointer;
     }
     ZoneSpecifier zoneSpecifier() const { return zone_.spec; }
     CompartmentOptions &setZone(ZoneSpecifier spec);
     CompartmentOptions &setSameZoneAs(JSObject *obj);
 
+    void setSingletonsAsValues() {
+        singletonsAsTemplates_ = false;
+    }
+    bool getSingletonsAsTemplates() const {
+        return singletonsAsTemplates_;
+    };
+
   private:
     JSVersion version_;
     bool invisibleToDebugger_;
     bool mergeable_;
     Override baselineOverride_;
     Override typeInferenceOverride_;
     Override ionOverride_;
     Override asmJSOverride_;
+    Override cloneSingletonsOverride_;
     union {
         ZoneSpecifier spec;
         void *pointer; // js::Zone* is not exposed in the API.
     } zone_;
+
+    // To XDR singletons, we need to ensure that all singletons are all used as
+    // templates, by making JSOP_OBJECT return a clone of the JSScript
+    // singleton, instead of returning the value which is baked in the JSScript.
+    bool singletonsAsTemplates_;
 };
 
 JS_PUBLIC_API(CompartmentOptions &)
 CompartmentOptionsRef(JSCompartment *compartment);
 
 JS_PUBLIC_API(CompartmentOptions &)
 CompartmentOptionsRef(JSContext *cx);
 
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -1798,16 +1798,17 @@ CopySlots(JSContext *cx, HandleObject fr
 JSObject *
 js::CloneObject(JSContext *cx, HandleObject obj, Handle<js::TaggedProto> proto, HandleObject parent)
 {
     if (!obj->isNative() && !obj->is<ProxyObject>()) {
         JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
                              JSMSG_CANT_CLONE_OBJECT);
         return nullptr;
     }
+
     RootedObject clone(cx, NewObjectWithGivenProto(cx, obj->getClass(), proto, parent));
     if (!clone)
         return nullptr;
     if (obj->isNative()) {
         if (clone->is<JSFunction>() && (obj->compartment() != clone->compartment())) {
             JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr,
                                  JSMSG_CANT_CLONE_OBJECT);
             return nullptr;
@@ -1820,16 +1821,297 @@ js::CloneObject(JSContext *cx, HandleObj
         if (!CopySlots(cx, obj, clone))
             return nullptr;
     }
 
     return clone;
 }
 
 JSObject *
+js::DeepCloneObjectLiteral(JSContext *cx, HandleObject obj, NewObjectKind newKind)
+{
+    /* NB: Keep this in sync with XDRObjectLiteral. */
+    JS_ASSERT(JS::CompartmentOptionsRef(cx).getSingletonsAsTemplates());
+    JS_ASSERT(obj->is<JSObject>() || obj->is<ArrayObject>());
+
+    // Result of the clone function.
+    RootedObject clone(cx);
+
+    // Temporary element/slot which would be stored in the cloned object.
+    RootedValue v(cx);
+    RootedObject deepObj(cx);
+
+    if (obj->getClass() == &ArrayObject::class_) {
+        clone = NewDenseUnallocatedArray(cx, obj->as<ArrayObject>().length(), nullptr, newKind);
+    } else {
+        // Object literals are tenured by default as holded by the JSScript.
+        JS_ASSERT(obj->isTenured());
+        AllocKind kind = obj->tenuredGetAllocKind();
+        Rooted<TypeObject*> typeObj(cx, obj->getType(cx));
+        if (!typeObj)
+            return nullptr;
+        RootedObject parent(cx, obj->getParent());
+        clone = NewObjectWithGivenProto(cx, &JSObject::class_, typeObj->proto().toObject(),
+                                        parent, kind, newKind);
+    }
+
+    // Allocate the same number of slots.
+    if (!clone || !clone->ensureElements(cx, obj->getDenseCapacity()))
+        return nullptr;
+
+    // Copy the number of initialized elements.
+    uint32_t initialized = obj->getDenseInitializedLength();
+    if (initialized)
+        clone->setDenseInitializedLength(initialized);
+
+    // Recursive copy of dense element.
+    for (uint32_t i = 0; i < initialized; ++i) {
+        v = obj->getDenseElement(i);
+        if (v.isObject()) {
+            deepObj = &v.toObject();
+            deepObj = js::DeepCloneObjectLiteral(cx, deepObj, newKind);
+            if (!deepObj) {
+                JS_ReportOutOfMemory(cx);
+                return nullptr;
+            }
+            v.setObject(*deepObj);
+        }
+        clone->initDenseElement(i, v);
+    }
+
+    JS_ASSERT(obj->compartment() == clone->compartment());
+    JS_ASSERT(!obj->hasPrivate());
+    RootedShape shape(cx, obj->lastProperty());
+    size_t span = shape->slotSpan();
+    clone->setLastProperty(cx, clone, shape);
+    for (size_t i = 0; i < span; i++) {
+        v = obj->getSlot(i);
+        if (v.isObject()) {
+            deepObj = &v.toObject();
+            deepObj = js::DeepCloneObjectLiteral(cx, deepObj, newKind);
+            if (!deepObj)
+                return nullptr;
+            v.setObject(*deepObj);
+        }
+        clone->setSlot(i, v);
+    }
+
+    if (obj->getClass() == &ArrayObject::class_)
+        FixArrayType(cx, clone);
+    else
+        FixObjectType(cx, clone);
+
+#ifdef DEBUG
+    Rooted<TypeObject*> typeObj(cx, obj->getType(cx));
+    Rooted<TypeObject*> cloneTypeObj(cx, clone->getType(cx));
+    if (!typeObj || !cloneTypeObj)
+        return nullptr;
+    JS_ASSERT(typeObj == cloneTypeObj);
+#endif
+
+    return clone;
+}
+
+template<XDRMode mode>
+bool
+js::XDRObjectLiteral(XDRState<mode> *xdr, MutableHandleObject obj)
+{
+    /* NB: Keep this in sync with DeepCloneObjectLiteral. */
+
+    JSContext *cx = xdr->cx();
+    JS_ASSERT_IF(mode == XDR_ENCODE, JS::CompartmentOptionsRef(cx).getSingletonsAsTemplates());
+
+    // Distinguish between objects and array classes.
+    uint32_t isArray = 0;
+    {
+        if (mode == XDR_ENCODE) {
+            JS_ASSERT(obj->is<JSObject>() || obj->is<ArrayObject>());
+            isArray = obj->getClass() == &ArrayObject::class_ ? 1 : 0;
+        }
+
+        if (!xdr->codeUint32(&isArray))
+            return false;
+    }
+
+    if (isArray) {
+        uint32_t length;
+
+        if (mode == XDR_ENCODE)
+            length = obj->as<ArrayObject>().length();
+
+        if (!xdr->codeUint32(&length))
+            return false;
+
+        if (mode == XDR_DECODE)
+            obj.set(NewDenseUnallocatedArray(cx, length, NULL, js::MaybeSingletonObject));
+
+    } else {
+        // Code the alloc kind of the object.
+        AllocKind kind;
+        {
+            if (mode == XDR_ENCODE) {
+                JS_ASSERT(obj->getClass() == &JSObject::class_);
+                JS_ASSERT(obj->isTenured());
+                kind = obj->tenuredGetAllocKind();
+            }
+
+            if (!xdr->codeEnum32(&kind))
+                return false;
+
+            if (mode == XDR_DECODE)
+                obj.set(NewBuiltinClassInstance(cx, &JSObject::class_, kind, js::MaybeSingletonObject));
+        }
+    }
+
+    {
+        uint32_t capacity;
+        if (mode == XDR_ENCODE)
+            capacity = obj->getDenseCapacity();
+        if (!xdr->codeUint32(&capacity))
+            return false;
+        if (mode == XDR_DECODE) {
+            if (!obj->ensureElements(cx, capacity)) {
+                JS_ReportOutOfMemory(cx);
+                return false;
+            }
+        }
+    }
+
+    uint32_t initialized;
+    {
+        if (mode == XDR_ENCODE)
+            initialized = obj->getDenseInitializedLength();
+        if (!xdr->codeUint32(&initialized))
+            return false;
+        if (mode == XDR_DECODE) {
+            if (initialized)
+                obj->setDenseInitializedLength(initialized);
+        }
+    }
+
+    RootedValue tmpValue(cx);
+
+    // Recursively copy dense elements.
+    {
+        for (unsigned i = 0; i < initialized; i++) {
+            if (mode == XDR_ENCODE)
+                tmpValue = obj->getDenseElement(i);
+
+            if (!xdr->codeConstValue(&tmpValue))
+                return false;
+
+            if (mode == XDR_DECODE)
+                obj->initDenseElement(i, tmpValue);
+        }
+    }
+
+    JS_ASSERT(!obj->hasPrivate());
+    RootedShape shape(cx, obj->lastProperty());
+
+    // Code the number of slots in the vector.
+    unsigned nslot = 0;
+
+    // Code ids of the object in order. As opposed to DeepCloneObjectLiteral we
+    // cannot just re-use the shape of the original bytecode value and we have
+    // to write down the shape as well as the corresponding values.  Ideally we
+    // would have a mechanism to serialize the shape too.
+    js::AutoIdVector ids(cx);
+    {
+        if (mode == XDR_ENCODE && !shape->isEmptyShape()) {
+            nslot = shape->slotSpan();
+            if (!ids.reserve(nslot))
+                return false;
+
+            for (unsigned i = 0; i < nslot; i++)
+                ids.infallibleAppend(JSID_VOID);
+
+            for (Shape::Range<NoGC> it(shape); !it.empty(); it.popFront()) {
+                // If we have reached the native property of the array class, we
+                // exit as the remaining would only be reserved slots.
+                if (!it.front().hasSlot()) {
+                    JS_ASSERT(isArray);
+                    break;
+                }
+
+                JS_ASSERT(it.front().hasDefaultGetter());
+                ids[it.front().slot()] = it.front().propid();
+            }
+        }
+
+        if (!xdr->codeUint32(&nslot))
+            return false;
+
+        RootedAtom atom(cx);
+        RootedId id(cx);
+        uint32_t idType = 0;
+        for (unsigned i = 0; i < nslot; i++) {
+            if (mode == XDR_ENCODE) {
+                id = ids[i];
+                if (JSID_IS_INT(id))
+                    idType = JSID_TYPE_INT;
+                else if (JSID_IS_ATOM(id))
+                    idType = JSID_TYPE_STRING;
+                else
+                    MOZ_ASSUME_UNREACHABLE("Object property is not yet supported by XDR.");
+
+                tmpValue = obj->getSlot(i);
+            }
+
+            if (!xdr->codeUint32(&idType))
+                return false;
+
+            if (idType == JSID_TYPE_STRING) {
+                if (mode == XDR_ENCODE)
+                    atom = JSID_TO_ATOM(id);
+                if (!XDRAtom(xdr, &atom))
+                    return false;
+                if (mode == XDR_DECODE)
+                    id = AtomToId(atom);
+            } else {
+                JS_ASSERT(idType == JSID_TYPE_INT);
+                uint32_t indexVal;
+                if (mode == XDR_ENCODE)
+                    indexVal = uint32_t(JSID_TO_INT(id));
+                if (!xdr->codeUint32(&indexVal))
+                    return false;
+                if (mode == XDR_DECODE)
+                    id = INT_TO_JSID(int32_t(indexVal));
+            }
+
+            if (!xdr->codeConstValue(&tmpValue))
+                return false;
+
+            if (mode == XDR_DECODE) {
+                if (!DefineNativeProperty(cx, obj, id, tmpValue, NULL, NULL,
+                                          JSPROP_ENUMERATE, 0, 0)) {
+                    return false;
+                }
+            }
+        }
+
+        JS_ASSERT_IF(mode == XDR_DECODE, !obj->inDictionaryMode());
+    }
+
+    if (mode == XDR_DECODE) {
+        if (isArray)
+            FixArrayType(cx, obj);
+        else
+            FixObjectType(cx, obj);
+    }
+
+    return true;
+}
+
+template bool
+js::XDRObjectLiteral(XDRState<XDR_ENCODE> *xdr, MutableHandleObject obj);
+
+template bool
+js::XDRObjectLiteral(XDRState<XDR_DECODE> *xdr, MutableHandleObject obj);
+
+JSObject *
 js::CloneObjectLiteral(JSContext *cx, HandleObject parent, HandleObject srcObj)
 {
     Rooted<TypeObject*> typeObj(cx);
     typeObj = cx->getNewType(&JSObject::class_, cx->global()->getOrCreateObjectPrototype(cx));
 
     JS_ASSERT(srcObj->getClass() == &JSObject::class_);
     AllocKind kind = GetBackgroundAllocKind(GuessObjectGCKind(srcObj->numFixedSlots()));
     JS_ASSERT_IF(srcObj->isTenured(), kind == srcObj->tenuredGetAllocKind());
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -17,16 +17,17 @@
  */
 
 #include "mozilla/MemoryReporting.h"
 
 #include "gc/Marking.h"
 #include "js/GCAPI.h"
 #include "vm/ObjectImpl.h"
 #include "vm/Shape.h"
+#include "vm/Xdr.h"
 
 namespace JS {
 struct ObjectsExtraSizes;
 }
 
 namespace js {
 
 class AutoPropDescArrayRooter;
@@ -1398,16 +1399,19 @@ CreateThisForFunction(JSContext *cx, js:
 
 // Generic call for constructing |this|.
 extern JSObject *
 CreateThis(JSContext *cx, const js::Class *clasp, js::HandleObject callee);
 
 extern JSObject *
 CloneObject(JSContext *cx, HandleObject obj, Handle<js::TaggedProto> proto, HandleObject parent);
 
+extern JSObject *
+DeepCloneObjectLiteral(JSContext *cx, HandleObject obj, NewObjectKind newKind = GenericObject);
+
 /*
  * Flags for the defineHow parameter of js_DefineNativeProperty.
  */
 const unsigned DNP_DONT_PURGE   = 1;   /* suppress js_PurgeScopeChain */
 const unsigned DNP_UNQUALIFIED  = 2;   /* Unqualified property set.  Only used in
                                        the defineHow argument of
                                        js_SetPropertyHelper. */
 
@@ -1573,16 +1577,20 @@ ToObject(JSContext *cx, HandleValue vp)
 JS_ALWAYS_INLINE JSObject *
 ToObjectFromStack(JSContext *cx, HandleValue vp)
 {
     if (vp.isObject())
         return &vp.toObject();
     return ToObjectSlow(cx, vp, true);
 }
 
+template<XDRMode mode>
+bool
+XDRObjectLiteral(XDRState<mode> *xdr, MutableHandleObject obj);
+
 extern JSObject *
 CloneObjectLiteral(JSContext *cx, HandleObject parent, HandleObject srcObj);
 
 } /* namespace js */
 
 extern void
 js_GetObjectSlotName(JSTracer *trc, char *buf, size_t bufsize);
 
--- a/js/src/jsscript.cpp
+++ b/js/src/jsscript.cpp
@@ -17,16 +17,17 @@
 #include <string.h>
 
 #include "jsapi.h"
 #include "jsatom.h"
 #include "jsautooplen.h"
 #include "jscntxt.h"
 #include "jsfun.h"
 #include "jsgc.h"
+#include "jsobj.h"
 #include "jsopcode.h"
 #include "jstypes.h"
 #include "jsutil.h"
 #include "jswrapper.h"
 
 #include "frontend/BytecodeEmitter.h"
 #include "frontend/SharedContext.h"
 #include "gc/Marking.h"
@@ -300,33 +301,39 @@ js::XDRScriptConst(XDRState<mode> *xdr, 
      */
     enum ConstTag {
         SCRIPT_INT     = 0,
         SCRIPT_DOUBLE  = 1,
         SCRIPT_ATOM    = 2,
         SCRIPT_TRUE    = 3,
         SCRIPT_FALSE   = 4,
         SCRIPT_NULL    = 5,
-        SCRIPT_VOID    = 6
+        SCRIPT_OBJECT  = 6,
+        SCRIPT_VOID    = 7,
+        SCRIPT_HOLE    = 8
     };
 
     uint32_t tag;
     if (mode == XDR_ENCODE) {
         if (vp.isInt32()) {
             tag = SCRIPT_INT;
         } else if (vp.isDouble()) {
             tag = SCRIPT_DOUBLE;
         } else if (vp.isString()) {
             tag = SCRIPT_ATOM;
         } else if (vp.isTrue()) {
             tag = SCRIPT_TRUE;
         } else if (vp.isFalse()) {
             tag = SCRIPT_FALSE;
         } else if (vp.isNull()) {
             tag = SCRIPT_NULL;
+        } else if (vp.isObject()) {
+            tag = SCRIPT_OBJECT;
+        } else if (vp.isMagic(JS_ELEMENTS_HOLE)) {
+            tag = SCRIPT_HOLE;
         } else {
             JS_ASSERT(vp.isUndefined());
             tag = SCRIPT_VOID;
         }
     }
 
     if (!xdr->codeUint32(&tag))
         return false;
@@ -369,20 +376,36 @@ js::XDRScriptConst(XDRState<mode> *xdr, 
       case SCRIPT_FALSE:
         if (mode == XDR_DECODE)
             vp.set(BooleanValue(false));
         break;
       case SCRIPT_NULL:
         if (mode == XDR_DECODE)
             vp.set(NullValue());
         break;
+      case SCRIPT_OBJECT: {
+        RootedObject obj(cx);
+        if (mode == XDR_ENCODE)
+            obj = &vp.toObject();
+
+        if (!XDRObjectLiteral(xdr, &obj))
+            return false;
+
+        if (mode == XDR_DECODE)
+            vp.setObject(*obj);
+        break;
+      }
       case SCRIPT_VOID:
         if (mode == XDR_DECODE)
             vp.set(UndefinedValue());
         break;
+      case SCRIPT_HOLE:
+        if (mode == XDR_DECODE)
+            vp.setMagic(JS_ELEMENTS_HOLE);
+        break;
     }
     return true;
 }
 
 template bool
 js::XDRScriptConst(XDRState<XDR_ENCODE> *, MutableHandleValue);
 
 template bool
@@ -400,16 +423,22 @@ FindBlockIndex(JSScript *script, StaticB
     }
 
     MOZ_ASSUME_UNREACHABLE("Block not found");
 }
 
 static bool
 SaveSharedScriptData(ExclusiveContext *, Handle<JSScript *>, SharedScriptData *, uint32_t);
 
+enum XDRClassKind {
+    CK_BlockObject = 0,
+    CK_JSFunction  = 1,
+    CK_JSObject    = 2
+};
+
 template<XDRMode mode>
 bool
 js::XDRScript(XDRState<mode> *xdr, HandleObject enclosingScope, HandleScript enclosingScript,
               HandleFunction fun, MutableHandleScript scriptp)
 {
     /* NB: Keep this in sync with CloneScript. */
 
     enum ScriptBits {
@@ -723,25 +752,63 @@ js::XDRScript(XDRState<mode> *xdr, Handl
 
     /*
      * Here looping from 0-to-length to xdr objects is essential to ensure that
      * all references to enclosing blocks (via FindBlockIndex below) happen
      * after the enclosing block has been XDR'd.
      */
     for (i = 0; i != nobjects; ++i) {
         HeapPtr<JSObject> *objp = &script->objects()->vector[i];
-        uint32_t isBlock;
+        XDRClassKind classk;
+
         if (mode == XDR_ENCODE) {
             JSObject *obj = *objp;
-            JS_ASSERT(obj->is<JSFunction>() || obj->is<StaticBlockObject>());
-            isBlock = obj->is<BlockObject>() ? 1 : 0;
+            if (obj->is<BlockObject>())
+                classk = CK_BlockObject;
+            else if (obj->is<JSFunction>())
+                classk = CK_JSFunction;
+            else if (obj->is<JSObject>() || obj->is<ArrayObject>())
+                classk = CK_JSObject;
+            else
+                MOZ_ASSUME_UNREACHABLE("Cannot encode this class of object.");
         }
-        if (!xdr->codeUint32(&isBlock))
+
+        if (!xdr->codeEnum32(&classk))
             return false;
-        if (isBlock == 0) {
+
+        switch (classk) {
+          case CK_BlockObject: {
+            /* Code the nested block's enclosing scope. */
+            uint32_t blockEnclosingScopeIndex = 0;
+            if (mode == XDR_ENCODE) {
+                if (StaticBlockObject *block = (*objp)->as<StaticBlockObject>().enclosingBlock())
+                    blockEnclosingScopeIndex = FindBlockIndex(script, *block);
+                else
+                    blockEnclosingScopeIndex = UINT32_MAX;
+            }
+            if (!xdr->codeUint32(&blockEnclosingScopeIndex))
+                return false;
+            Rooted<JSObject*> blockEnclosingScope(cx);
+            if (mode == XDR_DECODE) {
+                if (blockEnclosingScopeIndex != UINT32_MAX) {
+                    JS_ASSERT(blockEnclosingScopeIndex < i);
+                    blockEnclosingScope = script->objects()->vector[blockEnclosingScopeIndex];
+                } else {
+                    blockEnclosingScope = fun;
+                }
+            }
+
+            Rooted<StaticBlockObject*> tmp(cx, static_cast<StaticBlockObject *>(objp->get()));
+            if (!XDRStaticBlockObject(xdr, blockEnclosingScope, tmp.address()))
+                return false;
+            *objp = tmp;
+            break;
+          }
+
+          case CK_JSFunction: {
             /* Code the nested function's enclosing scope. */
             uint32_t funEnclosingScopeIndex = 0;
             if (mode == XDR_ENCODE) {
                 JSScript *innerScript = (*objp)->as<JSFunction>().getOrCreateScript(cx);
                 if (!innerScript)
                     return false;
                 RootedObject staticScope(cx, innerScript->enclosingStaticScope());
                 StaticScopeIter<NoGC> ssi(staticScope);
@@ -764,42 +831,32 @@ js::XDRScript(XDRState<mode> *xdr, Handl
                     funEnclosingScope = script->objects()->vector[funEnclosingScopeIndex];
                 }
             }
 
             RootedObject tmp(cx, *objp);
             if (!XDRInterpretedFunction(xdr, funEnclosingScope, script, &tmp))
                 return false;
             *objp = tmp;
-        } else {
-            /* Code the nested block's enclosing scope. */
-            JS_ASSERT(isBlock == 1);
-            uint32_t blockEnclosingScopeIndex = 0;
-            if (mode == XDR_ENCODE) {
-                if (StaticBlockObject *block = (*objp)->as<StaticBlockObject>().enclosingBlock())
-                    blockEnclosingScopeIndex = FindBlockIndex(script, *block);
-                else
-                    blockEnclosingScopeIndex = UINT32_MAX;
-            }
-            if (!xdr->codeUint32(&blockEnclosingScopeIndex))
-                return false;
-            Rooted<JSObject*> blockEnclosingScope(cx);
-            if (mode == XDR_DECODE) {
-                if (blockEnclosingScopeIndex != UINT32_MAX) {
-                    JS_ASSERT(blockEnclosingScopeIndex < i);
-                    blockEnclosingScope = script->objects()->vector[blockEnclosingScopeIndex];
-                } else {
-                    blockEnclosingScope = fun;
-                }
-            }
-
-            Rooted<StaticBlockObject*> tmp(cx, static_cast<StaticBlockObject *>(objp->get()));
-            if (!XDRStaticBlockObject(xdr, blockEnclosingScope, tmp.address()))
+            break;
+          }
+
+          case CK_JSObject: {
+            /* Code object literal. */
+            RootedObject tmp(cx, *objp);
+            if (!XDRObjectLiteral(xdr, &tmp))
                 return false;
             *objp = tmp;
+            break;
+          }
+
+          default: {
+            MOZ_ASSUME_UNREACHABLE("Unknown class kind.");
+            return false;
+          }
         }
     }
 
     for (i = 0; i != nregexps; ++i) {
         if (!XDRScriptRegExpObject(xdr, &script->regexps()->vector[i]))
             return false;
     }
 
--- a/js/src/vm/Interpreter.cpp
+++ b/js/src/vm/Interpreter.cpp
@@ -2767,17 +2767,29 @@ CASE(JSOP_DOUBLE)
 }
 END_CASE(JSOP_DOUBLE)
 
 CASE(JSOP_STRING)
     PUSH_STRING(script->getAtom(REGS.pc));
 END_CASE(JSOP_STRING)
 
 CASE(JSOP_OBJECT)
-    PUSH_OBJECT(*script->getObject(REGS.pc));
+{
+    RootedObject &ref = rootObject0;
+    ref = script->getObject(REGS.pc);
+    if (JS::CompartmentOptionsRef(cx).cloneSingletons(cx)) {
+        JSObject *obj = js::DeepCloneObjectLiteral(cx, ref, js::MaybeSingletonObject);
+        if (!obj)
+            goto error;
+        PUSH_OBJECT(*obj);
+    } else {
+        JS::CompartmentOptionsRef(cx).setSingletonsAsValues();
+        PUSH_OBJECT(*ref);
+    }
+}
 END_CASE(JSOP_OBJECT)
 
 CASE(JSOP_REGEXP)
 {
     /*
      * Push a regexp object cloned from the regexp literal object mapped by the
      * bytecode at pc.
      */
--- a/js/src/vm/Xdr.h
+++ b/js/src/vm/Xdr.h
@@ -3,31 +3,32 @@
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef vm_Xdr_h
 #define vm_Xdr_h
 
 #include "mozilla/Endian.h"
+#include "mozilla/TypeTraits.h"
 
 #include "jsatom.h"
 
 namespace js {
 
 /*
  * Bytecode version number. Increment the subtrahend whenever JS bytecode
  * changes incompatibly.
  *
  * This version number is XDR'd near the front of xdr bytecode and
  * aborts deserialization if there is a mismatch between the current
  * and saved versions. If deserialization fails, the data should be
  * invalidated if possible.
  */
-static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 164);
+static const uint32_t XDR_BYTECODE_VERSION = uint32_t(0xb973c0de - 165);
 
 class XDRBuffer {
   public:
     XDRBuffer(JSContext *cx)
       : context(cx), base(nullptr), cursor(nullptr), limit(nullptr) { }
 
     JSContext *cx() const {
         return context;
@@ -156,16 +157,34 @@ class XDRState {
             mozilla::LittleEndian::writeUint64(ptr, *n);
         } else {
             const uint8_t *ptr = buf.read(sizeof(*n));
             *n = mozilla::LittleEndian::readUint64(ptr);
         }
         return true;
     }
 
+    /*
+     * Use SFINAE to refuse any specialization which is not an enum.  Uses of
+     * this function do not have to specialize the type of the enumerated field
+     * as C++ will extract the parameterized from the argument list.
+     */
+    template <typename T>
+    bool codeEnum32(T *val, typename mozilla::EnableIf<mozilla::IsEnum<T>::value, T>::Type * = NULL)
+    {
+        uint32_t tmp;
+        if (mode == XDR_ENCODE)
+            tmp = *val;
+        if (!codeUint32(&tmp))
+            return false;
+        if (mode == XDR_DECODE)
+            *val = T(tmp);
+        return true;
+    }
+
     bool codeDouble(double *dp) {
         union DoublePun {
             double d;
             uint64_t u;
         } pun;
         if (mode == XDR_ENCODE)
             pun.d = *dp;
         if (!codeUint64(&pun.u))
--- a/media/libtheora/lib/Makefile.in
+++ b/media/libtheora/lib/Makefile.in
@@ -1,15 +1,15 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 
 ifdef GNU_AS
-ifeq ($(findstring arm,$(OS_TEST)), arm)
+ifeq ($(CPU_ARCH),arm)
 
 # These flags are a lie; they're just used to enable the requisite
 # opcodes; actual arch detection is done at runtime.
 ASFLAGS = -march=armv7-a -mfpu=neon
 
 armfrag-gnu.$(ASM_SUFFIX): armopts-gnu.S
 armidct-gnu.$(ASM_SUFFIX): armopts-gnu.S
 armloop-gnu.$(ASM_SUFFIX): armopts-gnu.S
--- a/media/libtheora/lib/moz.build
+++ b/media/libtheora/lib/moz.build
@@ -15,17 +15,17 @@ UNIFIED_SOURCES += [
     'huffdec.c',
     'idct.c',
     'info.c',
     'internal.c',
     'quant.c',
     'state.c',
 ]
 
-if CONFIG['OS_TEST'] == 'arm' and CONFIG['GNU_AS']:
+if CONFIG['CPU_ARCH'] == 'arm' and CONFIG['GNU_AS']:
     GENERATED_SOURCES += [ '%s.%s' % (f, CONFIG['ASM_SUFFIX']) for f in [
         'armbits-gnu',
         'armfrag-gnu',
         'armidct-gnu',
         'armloop-gnu',
     ]]
 
 if '86' in CONFIG['OS_TEST']:
--- a/media/webrtc/signaling/src/callcontrol/CallControlManagerImpl.cpp
+++ b/media/webrtc/signaling/src/callcontrol/CallControlManagerImpl.cpp
@@ -19,19 +19,17 @@
 #include "csf_common.h"
 
 extern "C"
 {
 #include "config_api.h"
 }
 
 
-static const char* logTag = "CallControlManager";
-
-static std::string logDestination = "CallControl.log";
+static const char logTag[] = "CallControlManager";
 
 using namespace std;
 using namespace CSFUnified;
 
 namespace CSF
 {
 
 
--- a/media/webrtc/trunk/webrtc/modules/audio_device/linux/audio_device_alsa_linux.cc
+++ b/media/webrtc/trunk/webrtc/modules/audio_device/linux/audio_device_alsa_linux.cc
@@ -185,23 +185,25 @@ int32_t AudioDeviceLinuxALSA::Init()
         return -1;
     }
 
     if (_initialized)
     {
         return 0;
     }
 
+#ifdef USE_X11
     //Get X display handle for typing detection
     _XDisplay = XOpenDisplay(NULL);
     if (!_XDisplay)
     {
         WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
           "  failed to open X display, typing detection will not work");
     }
+#endif
 
     _playWarning = 0;
     _playError = 0;
     _recWarning = 0;
     _recError = 0;
 
     _initialized = true;
 
@@ -259,21 +261,23 @@ int32_t AudioDeviceLinuxALSA::Terminate(
         {
             WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
                          "  failed to close down the play audio thread");
         }
 
         _critSect.Enter();
     }
 
+#ifdef USE_X11
     if (_XDisplay)
     {
       XCloseDisplay(_XDisplay);
       _XDisplay = NULL;
     }
+#endif
 
     _initialized = false;
     _outputDeviceIsSpecified = false;
     _inputDeviceIsSpecified = false;
 
     return 0;
 }
 
@@ -2365,21 +2369,23 @@ bool AudioDeviceLinuxALSA::RecThreadProc
 
 
 bool AudioDeviceLinuxALSA::KeyPressed() const{
 
   char szKey[32];
   unsigned int i = 0;
   char state = 0;
 
+#ifdef USE_X11
   if (!_XDisplay)
     return false;
 
   // Check key map status
   XQueryKeymap(_XDisplay, szKey);
+#endif
 
   // A bit change in keymap means a key is pressed
   for (i = 0; i < sizeof(szKey); i++)
     state |= (szKey[i] ^ _oldKeyState[i]) & szKey[i];
 
   // Save old state
   memcpy((char*)_oldKeyState, (char*)szKey, sizeof(_oldKeyState));
   return (state != 0);
--- a/media/webrtc/trunk/webrtc/modules/audio_device/linux/audio_device_alsa_linux.h
+++ b/media/webrtc/trunk/webrtc/modules/audio_device/linux/audio_device_alsa_linux.h
@@ -11,17 +11,19 @@
 #ifndef WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_ALSA_LINUX_H
 #define WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_ALSA_LINUX_H
 
 #include "webrtc/modules/audio_device/audio_device_generic.h"
 #include "webrtc/modules/audio_device/linux/audio_mixer_manager_alsa_linux.h"
 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
 
 
+#ifdef USE_X11
 #include <X11/Xlib.h>
+#endif
 #include <alsa/asoundlib.h>
 #include <sys/ioctl.h>
 #include <sys/soundcard.h>
 
 
 namespace webrtc
 {
 class EventWrapper;
@@ -248,14 +250,16 @@ private:
     uint16_t _playError;
     uint16_t _recWarning;
     uint16_t _recError;
 
     uint16_t _playBufDelay;                 // playback delay
     uint16_t _playBufDelayFixed;            // fixed playback delay
 
     char _oldKeyState[32];
+#ifdef USE_X11
     Display* _XDisplay;
+#endif
 };
 
 }
 
 #endif  // MODULES_AUDIO_DEVICE_MAIN_SOURCE_LINUX_AUDIO_DEVICE_ALSA_LINUX_H_
--- a/media/webrtc/trunk/webrtc/modules/audio_device/linux/audio_device_pulse_linux.cc
+++ b/media/webrtc/trunk/webrtc/modules/audio_device/linux/audio_device_pulse_linux.cc
@@ -226,23 +226,25 @@ int32_t AudioDeviceLinuxPulse::Init()
         return -1;
     }
 
     _playWarning = 0;
     _playError = 0;
     _recWarning = 0;
     _recError = 0;
 
+#ifdef USE_X11
     //Get X display handle for typing detection
     _XDisplay = XOpenDisplay(NULL);
     if (!_XDisplay)
     {
         WEBRTC_TRACE(kTraceWarning, kTraceAudioDevice, _id,
           "  failed to open X display, typing detection will not work");
     }
+#endif
 
     // RECORDING
     const char* threadName = "webrtc_audio_module_rec_thread";
     _ptrThreadRec = ThreadWrapper::CreateThread(RecThreadFunc, this,
                                                 kRealtimePriority, threadName);
     if (_ptrThreadRec == NULL)
     {
         WEBRTC_TRACE(kTraceCritical, kTraceAudioDevice, _id,
@@ -347,21 +349,23 @@ int32_t AudioDeviceLinuxPulse::Terminate
     // Terminate PulseAudio
     if (TerminatePulseAudio() < 0)
     {
         WEBRTC_TRACE(kTraceError, kTraceAudioDevice, _id,
                      "  failed to terminate PulseAudio");
         return -1;
     }
 
+#ifdef USE_X11
     if (_XDisplay)
     {
       XCloseDisplay(_XDisplay);
       _XDisplay = NULL;
     }
+#endif
 
     _initialized = false;
     _outputDeviceIsSpecified = false;
     _inputDeviceIsSpecified = false;
 
     return 0;
 }
 
@@ -3110,21 +3114,23 @@ bool AudioDeviceLinuxPulse::RecThreadPro
 }
 
 bool AudioDeviceLinuxPulse::KeyPressed() const{
 
   char szKey[32];
   unsigned int i = 0;
   char state = 0;
 
+#ifdef USE_X11
   if (!_XDisplay)
     return false;
 
   // Check key map status
   XQueryKeymap(_XDisplay, szKey);
+#endif
 
   // A bit change in keymap means a key is pressed
   for (i = 0; i < sizeof(szKey); i++)
     state |= (szKey[i] ^ _oldKeyState[i]) & szKey[i];
 
   // Save old state
   memcpy((char*)_oldKeyState, (char*)szKey, sizeof(_oldKeyState));
   return (state != 0);
--- a/media/webrtc/trunk/webrtc/modules/audio_device/linux/audio_device_pulse_linux.h
+++ b/media/webrtc/trunk/webrtc/modules/audio_device/linux/audio_device_pulse_linux.h
@@ -10,17 +10,19 @@
 
 #ifndef WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_PULSE_LINUX_H
 #define WEBRTC_AUDIO_DEVICE_AUDIO_DEVICE_PULSE_LINUX_H
 
 #include "webrtc/modules/audio_device/audio_device_generic.h"
 #include "webrtc/modules/audio_device/linux/audio_mixer_manager_pulse_linux.h"
 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
 
+#ifdef USE_X11
 #include <X11/Xlib.h>
+#endif
 #include <pulse/pulseaudio.h>
 
 // We define this flag if it's missing from our headers, because we want to be
 // able to compile against old headers but still use PA_STREAM_ADJUST_LATENCY
 // if run against a recent version of the library.
 #ifndef PA_STREAM_ADJUST_LATENCY
 #define PA_STREAM_ADJUST_LATENCY 0x2000U
 #endif
@@ -376,14 +378,16 @@ private:
     pa_stream* _recStream;
     pa_stream* _playStream;
     uint32_t _recStreamFlags;
     uint32_t _playStreamFlags;
     pa_buffer_attr _playBufferAttr;
     pa_buffer_attr _recBufferAttr;
 
     char _oldKeyState[32];
+#ifdef USE_X11
     Display* _XDisplay;
+#endif
 };
 
 }
 
 #endif  // MODULES_AUDIO_DEVICE_MAIN_SOURCE_LINUX_AUDIO_DEVICE_PULSE_LINUX_H_
--- a/netwerk/protocol/http/nsHttpChunkedDecoder.cpp
+++ b/netwerk/protocol/http/nsHttpChunkedDecoder.cpp
@@ -1,16 +1,16 @@
 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 // HttpLog.h should generally be included first
 #include "HttpLog.h"
-
+#include <errno.h>
 #include "nsHttpChunkedDecoder.h"
 #include <algorithm>
 
 namespace mozilla {
 namespace net {
 
 //-----------------------------------------------------------------------------
 // nsHttpChunkedDecoder <public>
@@ -116,22 +116,31 @@ nsHttpChunkedDecoder::ParseChunkRemainin
             }
             else {
                 mWaitEOF = false;
                 mReachedEOF = true;
                 LOG(("reached end of chunked-body\n"));
             }
         }
         else if (*buf) {
+            char *endptr;
+            unsigned long parsedval; // could be 64 bit, could be 32
+
             // ignore any chunk-extensions
             if ((p = PL_strchr(buf, ';')) != nullptr)
                 *p = 0;
 
-            if (!sscanf(buf, "%x", &mChunkRemaining)) {
-                LOG(("sscanf failed parsing hex on string [%s]\n", buf));
+            // mChunkRemaining is an uint32_t!
+            parsedval = strtoul(buf, &endptr, 16);
+            mChunkRemaining = (uint32_t) parsedval;
+
+            if ((endptr == buf) ||
+                ((errno == ERANGE) && (parsedval == ULONG_MAX))  ||
+                (parsedval != mChunkRemaining) ) {
+                LOG(("failed parsing hex on string [%s]\n", buf));
                 return NS_ERROR_UNEXPECTED;
             }
 
             // we've discovered the last chunk
             if (mChunkRemaining == 0)
                 mWaitEOF = true;
         }
 
--- a/netwerk/protocol/http/nsHttpDigestAuth.cpp
+++ b/netwerk/protocol/http/nsHttpDigestAuth.cpp
@@ -499,19 +499,19 @@ nsHttpDigestAuth::CalculateHA1(const nsA
 
 nsresult
 nsHttpDigestAuth::CalculateHA2(const nsAFlatCString & method,
                                const nsAFlatCString & path,
                                uint16_t qop,
                                const char * bodyDigest,
                                char * result)
 {
-  int16_t methodLen = method.Length();
-  int16_t pathLen = path.Length();
-  int16_t len = methodLen + pathLen + 1;
+  uint16_t methodLen = method.Length();
+  uint32_t pathLen = path.Length();
+  uint32_t len = methodLen + pathLen + 1;
 
   if (qop & QOP_AUTH_INT) {
     len += EXPANDED_DIGEST_LENGTH + 1;
   }
 
   nsAutoCString contents;
   contents.SetCapacity(len);
 
new file mode 100644
--- /dev/null
+++ b/netwerk/test/unit/test_chunked_responses.js
@@ -0,0 +1,173 @@
+/*
+ * Test Chunked-Encoded response parsing.
+ */
+
+////////////////////////////////////////////////////////////////////////////////
+// Test infrastructure
+
+Cu.import("resource://testing-common/httpd.js");
+
+XPCOMUtils.defineLazyGetter(this, "URL", function() {
+  return "http://localhost:" + httpserver.identity.primaryPort;
+});
+
+var httpserver = new HttpServer();
+var index = 0;
+var test_flags = new Array();
+var testPathBase = "/chunked_hdrs";
+
+function run_test()
+{
+  httpserver.start(-1);
+
+  do_test_pending();
+  run_test_number(1);
+}
+
+function run_test_number(num)
+{
+  testPath = testPathBase + num;
+  httpserver.registerPathHandler(testPath, eval("handler" + num));
+
+  var channel = setupChannel(testPath);
+  flags = test_flags[num];   // OK if flags undefined for test
+  channel.asyncOpen(new ChannelListener(eval("completeTest" + num),
+                                        channel, flags), null);
+}
+
+function setupChannel(url)
+{
+  var ios = Components.classes["@mozilla.org/network/io-service;1"].
+                       getService(Ci.nsIIOService);
+  var chan = ios.newChannel(URL + url, "", null);
+  var httpChan = chan.QueryInterface(Components.interfaces.nsIHttpChannel);
+  return httpChan;
+}
+
+function endTests()
+{
+  httpserver.stop(do_test_finished);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Test 1: FAIL because of overflowed chunked size. The parser uses long so
+//         the test case uses >64bit to fail on all platforms.
+test_flags[1] = CL_EXPECT_LATE_FAILURE|CL_ALLOW_UNKNOWN_CL;
+
+function handler1(metadata, response)
+{
+  var body = "12345678123456789\r\ndata never reached";
+
+  response.seizePower();
+  response.write("HTTP/1.1 200 OK\r\n");
+  response.write("Content-Type: text/plain\r\n");
+  response.write("Transfer-Encoding: chunked\r\n");
+  response.write("\r\n");
+  response.write(body);
+  response.finish();
+}
+
+function completeTest1(request, data, ctx)
+{
+  do_check_eq(request.status, Components.results.NS_ERROR_UNEXPECTED);
+
+  run_test_number(2);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Test 2: FAIL because of non-hex in chunked length
+
+test_flags[2] = CL_EXPECT_LATE_FAILURE|CL_ALLOW_UNKNOWN_CL;
+
+function handler2(metadata, response)
+{
+  var body = "junkintheway 123\r\ndata never reached";
+
+  response.seizePower();
+  response.write("HTTP/1.1 200 OK\r\n");
+  response.write("Content-Type: text/plain\r\n");
+  response.write("Transfer-Encoding: chunked\r\n");
+  response.write("\r\n");
+  response.write(body);
+  response.finish();
+}
+
+function completeTest2(request, data, ctx)
+{
+  do_check_eq(request.status, Components.results.NS_ERROR_UNEXPECTED);
+  run_test_number(3);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Test 3: OK in spite of non-hex digits after size in the length field
+
+test_flags[3] = CL_ALLOW_UNKNOWN_CL;
+
+function handler3(metadata, response)
+{
+  var body = "c junkafter\r\ndata reached";
+
+  response.seizePower();
+  response.write("HTTP/1.1 200 OK\r\n");
+  response.write("Content-Type: text/plain\r\n");
+  response.write("Transfer-Encoding: chunked\r\n");
+  response.write("\r\n");
+  response.write(body);
+  response.finish();
+}
+
+function completeTest3(request, data, ctx)
+{
+  do_check_eq(request.status, 0);
+  run_test_number(4);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Test 4: Verify a fully compliant chunked response.
+
+test_flags[4] = CL_ALLOW_UNKNOWN_CL;
+
+function handler4(metadata, response)
+{
+  var body = "c\r\ndata reached\r\n\0\r\n\r\n";
+
+  response.seizePower();
+  response.write("HTTP/1.1 200 OK\r\n");
+  response.write("Content-Type: text/plain\r\n");
+  response.write("Transfer-Encoding: chunked\r\n");
+  response.write("\r\n");
+  response.write(body);
+  response.finish();
+}
+
+function completeTest4(request, data, ctx)
+{
+  do_check_eq(request.status, 0);
+  run_test_number(5);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Test 5: A chunk size larger than 32 bit but smaller than 64bit also fails
+// This is probabaly subject to get improved at some point.
+
+test_flags[5] = CL_EXPECT_LATE_FAILURE|CL_ALLOW_UNKNOWN_CL;
+
+function handler5(metadata, response)
+{
+  var body = "123456781\r\ndata never reached";
+
+  response.seizePower();
+  response.write("HTTP/1.1 200 OK\r\n");
+  response.write("Content-Type: text/plain\r\n");
+  response.write("Transfer-Encoding: chunked\r\n");
+  response.write("\r\n");
+  response.write(body);
+  response.finish();
+}
+
+function completeTest5(request, data, ctx)
+{
+  do_check_eq(request.status, Components.results.NS_ERROR_UNEXPECTED);
+  endTests();
+//  run_test_number(6);
+}
--- a/netwerk/test/unit/xpcshell.ini
+++ b/netwerk/test/unit/xpcshell.ini
@@ -179,16 +179,17 @@ skip-if = os == "android"
 [test_content_sniffer.js]
 [test_cookie_header.js]
 [test_cookiejars.js]
 [test_cookiejars_safebrowsing.js]
 [test_data_protocol.js]
 [test_dns_service.js]
 [test_dns_localredirect.js]
 [test_duplicate_headers.js]
+[test_chunked_responses.js]
 [test_event_sink.js]
 [test_extract_charset_from_content_type.js]
 [test_force_sniffing.js]
 [test_fallback_no-cache-entry_canceled.js]
 [test_fallback_no-cache-entry_passing.js]
 [test_fallback_redirect-to-different-origin_canceled.js]
 [test_fallback_redirect-to-different-origin_passing.js]
 [test_fallback_request-error_canceled.js]
new file mode 100644
--- /dev/null
+++ b/netwerk/test/unit_ipc/test_chunked_responses_wrap.js
@@ -0,0 +1,7 @@
+//
+// Run test script in content process instead of chrome (xpcshell's default)
+//
+
+function run_test() {
+  run_test_in_child("../unit/test_chunked_responses.js");
+}
--- a/testing/mochitest/b2g-debug.json
+++ b/testing/mochitest/b2g-debug.json
@@ -296,43 +296,29 @@
     "dom/file/test/test_readonly_lockedfiles.html":"",
     "dom/file/test/test_success_events_after_abort.html":"",
     "dom/file/test/test_truncate.html":"",
     "dom/file/test/test_workers.html":"",
     "dom/file/test/test_write_read_data.html":"",
 
     "dom/imptests/editing/conformancetest/test_runtest.html":"takes too long",
 
-    "dom/media/tests/mochitest/test_dataChannel_basicAudio.html":"bug 908473",
-    "dom/media/tests/mochitest/test_dataChannel_basicAudioVideo.html":"",
-    "dom/media/tests/mochitest/test_dataChannel_basicAudioVideoCombined.html":"",
-    "dom/media/tests/mochitest/test_dataChannel_basicDataOnly.html":"",
-    "dom/media/tests/mochitest/test_dataChannel_basicVideo.html":"",
-    "dom/media/tests/mochitest/test_dataChannel_noOffer.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_addCandidateInHaveLocalOffer.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_basicAudio.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_basicAudioVideo.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_basicAudioVideoCombined.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_basicVideo.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_bug822674.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_bug825703.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_bug827843.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_bug834153.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_bug835370.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_errorCallbacks.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveAudio.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveVideo.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveVideoAudio.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_setLocalAnswerInHaveLocalOffer.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_setLocalAnswerInStable.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_setLocalOfferInHaveRemoteOffer.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_setRemoteAnswerInHaveRemoteOffer.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_setRemoteAnswerInStable.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_setRemoteOfferInHaveLocalOffer.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_throwInCallbacks.html":"",
+    "dom/media/tests/mochitest/test_dataChannel_basicAudio.html":"Bug 962984, test fail on b2g debug build",
+    "dom/media/tests/mochitest/test_dataChannel_basicAudioVideo.html":"Bug 960442, video support for WebRTC is disabled on b2g",
+    "dom/media/tests/mochitest/test_dataChannel_basicAudioVideoCombined.html":"Bug 960442, video support for WebRTC is disabled on b2g",
+    "dom/media/tests/mochitest/test_dataChannel_basicVideo.html":"Bug 960442, video support for WebRTC is disabled on b2g",
+    "dom/media/tests/mochitest/test_peerConnection_basicAudioVideo.html":"Bug 960442, video support for WebRTC is disabled on b2g",
+    "dom/media/tests/mochitest/test_peerConnection_basicAudioVideoCombined.html":"Bug 960442, video support for WebRTC is disabled on b2g",
+    "dom/media/tests/mochitest/test_peerConnection_basicVideo.html":"Bug 960442, video support for WebRTC is disabled on b2g",
+    "dom/media/tests/mochitest/test_peerConnection_bug827843.html":"Bug 960442, video support for WebRTC is disabled on b2g",
+    "dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveAudio.html":"Bug 960442, video support for WebRTC is disabled on b2g",
+    "dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveVideo.html":"Bug 960442, video support for WebRTC is disabled on b2g",
+    "dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveVideoAudio.html":"Bug 960442, video support for WebRTC is disabled on b2g",
+    "dom/media/tests/mochitest/test_peerConnection_throwInCallbacks.html":"Bug 960442, video support for WebRTC is disabled on b2g",
+    "dom/media/tests/ipc/test_ipc.html":"nested ipc not working",
 
     "dom/network/tests/test_networkstats_basics.html":"Will be fixed in bug 858005",
     "dom/permission/tests/test_permission_basics.html":"https not working, bug 907770",
 
     "dom/tests/mochitest/bugs/test_bug335976.xhtml":"",
     "dom/tests/mochitest/bugs/test_bug369306.html":"test timed out, can't focus back from popup window to opener?",
     "dom/tests/mochitest/bugs/test_bug396843.html":"",
     "dom/tests/mochitest/bugs/test_bug406375.html":"",
--- a/testing/mochitest/b2g.json
+++ b/testing/mochitest/b2g.json
@@ -283,43 +283,27 @@
     "dom/file/test/test_readonly_lockedfiles.html":"",
     "dom/file/test/test_success_events_after_abort.html":"",
     "dom/file/test/test_truncate.html":"",
     "dom/file/test/test_workers.html":"",
     "dom/file/test/test_write_read_data.html":"",
 
     "dom/imptests/editing/conformancetest/test_runtest.html":"takes too long",
 
-    "dom/media/tests/mochitest/test_dataChannel_basicAudio.html":"bug 908473",
-    "dom/media/tests/mochitest/test_dataChannel_basicAudioVideo.html":"",
-    "dom/media/tests/mochitest/test_dataChannel_basicAudioVideoCombined.html":"",
-    "dom/media/tests/mochitest/test_dataChannel_basicDataOnly.html":"",
-    "dom/media/tests/mochitest/test_dataChannel_basicVideo.html":"",
-    "dom/media/tests/mochitest/test_dataChannel_noOffer.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_addCandidateInHaveLocalOffer.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_basicAudio.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_basicAudioVideo.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_basicAudioVideoCombined.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_basicVideo.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_bug822674.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_bug825703.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_bug827843.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_bug834153.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_bug835370.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_errorCallbacks.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveAudio.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveVideo.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveVideoAudio.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_setLocalAnswerInHaveLocalOffer.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_setLocalAnswerInStable.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_setLocalOfferInHaveRemoteOffer.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_setRemoteAnswerInHaveRemoteOffer.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_setRemoteAnswerInStable.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_setRemoteOfferInHaveLocalOffer.html":"",
-    "dom/media/tests/mochitest/test_peerConnection_throwInCallbacks.html":"",
+    "dom/media/tests/mochitest/test_dataChannel_basicAudioVideo.html":"Bug 960442, video support for WebRTC is disabled on b2g",
+    "dom/media/tests/mochitest/test_dataChannel_basicAudioVideoCombined.html":"Bug 960442, video support for WebRTC is disabled on b2g",
+    "dom/media/tests/mochitest/test_dataChannel_basicVideo.html":"Bug 960442, video support for WebRTC is disabled on b2g",
+    "dom/media/tests/mochitest/test_peerConnection_basicAudioVideo.html":"Bug 960442, video support for WebRTC is disabled on b2g",
+    "dom/media/tests/mochitest/test_peerConnection_basicAudioVideoCombined.html":"Bug 960442, video support for WebRTC is disabled on b2g",
+    "dom/media/tests/mochitest/test_peerConnection_basicVideo.html":"Bug 960442, video support for WebRTC is disabled on b2g",
+    "dom/media/tests/mochitest/test_peerConnection_bug827843.html":"Bug 960442, video support for WebRTC is disabled on b2g",
+    "dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveAudio.html":"Bug 960442, video support for WebRTC is disabled on b2g",
+    "dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveVideo.html":"Bug 960442, video support for WebRTC is disabled on b2g",
+    "dom/media/tests/mochitest/test_peerConnection_offerRequiresReceiveVideoAudio.html":"Bug 960442, video support for WebRTC is disabled on b2g",
+    "dom/media/tests/mochitest/test_peerConnection_throwInCallbacks.html":"Bug 960442, video support for WebRTC is disabled on b2g",
     "dom/media/tests/ipc/test_ipc.html":"nested ipc not working",
 
     "dom/permission/tests/test_permission_basics.html":"https not working, bug 907770",
 
     "dom/tests/mochitest/bugs/test_bug406375.html":"",
     "dom/tests/mochitest/bugs/test_bug427744.html":"",
     "dom/tests/mochitest/bugs/test_sizetocontent_clamp.html": "Windows can't change size on B2G",
     "dom/tests/mochitest/bugs/test_resize_move_windows.html": "Windows can't change size and position on B2G",
--- a/widget/cocoa/moz.build
+++ b/widget/cocoa/moz.build
@@ -65,16 +65,18 @@ SOURCES += [
     'TextInputHandler.mm',
 ]
 
 if CONFIG['TARGET_CPU'] == 'x86_64':
     UNIFIED_SOURCES += [
         'ComplexTextInputPanel.mm',
     ]
 
+include('/ipc/chromium/chromium-config.mozbuild')
+
 FINAL_LIBRARY = 'xul'
 LOCAL_INCLUDES += [
     '../shared',
     '../xpwidgets',
     '/layout/forms',
     '/layout/generic',
     '/layout/xul',
 ]
--- a/widget/gtk/nsImageToPixbuf.cpp
+++ b/widget/gtk/nsImageToPixbuf.cpp
@@ -3,23 +3,30 @@
  * 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 <gdk-pixbuf/gdk-pixbuf.h>
 
 #include "gfxASurface.h"
 #include "gfxImageSurface.h"
 #include "gfxContext.h"
+#include "gfxPlatform.h"
+#include "mozilla/gfx/2D.h"
+#include "mozilla/RefPtr.h"
 
 #include "imgIContainer.h"
 
 #include "nsAutoPtr.h"
 
 #include "nsImageToPixbuf.h"
 
+using mozilla::gfx::DataSourceSurface;
+using mozilla::gfx::SurfaceFormat;
+using mozilla::RefPtr;
+
 NS_IMPL_ISUPPORTS1(nsImageToPixbuf, nsIImageToPixbuf)
 
 inline unsigned char
 unpremultiply (unsigned char color,
                unsigned char alpha)
 {
     if (alpha == 0)
         return 0;
@@ -31,84 +38,99 @@ NS_IMETHODIMP_(GdkPixbuf*)
 nsImageToPixbuf::ConvertImageToPixbuf(imgIContainer* aImage)
 {
     return ImageToPixbuf(aImage);
 }
 
 GdkPixbuf*
 nsImageToPixbuf::ImageToPixbuf(imgIContainer* aImage)
 {
-    nsRefPtr<gfxASurface> surface =
+    nsRefPtr<gfxASurface> thebesSurface =
       aImage->GetFrame(imgIContainer::FRAME_CURRENT,
                        imgIContainer::FLAG_SYNC_DECODE);
 
     // If the last call failed, it was probably because our call stack originates
     // in an imgINotificationObserver event, meaning that we're not allowed request
     // a sync decode. Presumably the originating event is something sensible like
     // OnStopFrame(), so we can just retry the call without a sync decode.
-    if (!surface)
-        surface = aImage->GetFrame(imgIContainer::FRAME_CURRENT,
-                                   imgIContainer::FLAG_NONE);
+    if (!thebesSurface)
+      thebesSurface = aImage->GetFrame(imgIContainer::FRAME_CURRENT,
+                                       imgIContainer::FLAG_NONE);
 
+    NS_ENSURE_TRUE(thebesSurface, nullptr);
+
+    RefPtr<SourceSurface> surface =
+      gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr,
+                                                             thebesSurface);
     NS_ENSURE_TRUE(surface, nullptr);
 
-    nsRefPtr<gfxImageSurface> frame(surface->GetAsReadableARGB32ImageSurface());
-    NS_ENSURE_TRUE(frame, nullptr);
-
-    return ImgSurfaceToPixbuf(frame, frame->Width(), frame->Height());
+    return SourceSurfaceToPixbuf(surface,
+                                 surface->GetSize().width,
+                                 surface->GetSize().height);
 }
 
 GdkPixbuf*
-nsImageToPixbuf::ImgSurfaceToPixbuf(gfxImageSurface* aImgSurface, int32_t aWidth, int32_t aHeight)
+nsImageToPixbuf::SourceSurfaceToPixbuf(SourceSurface* aSurface,
+                                       int32_t aWidth,
+                                       int32_t aHeight)
 {
+    MOZ_ASSERT(aWidth <= aSurface->GetSize().width &&
+               aHeight <= aSurface->GetSize().height,
+               "Requested rect is bigger than the supplied surface");
+
     GdkPixbuf* pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8,
                                        aWidth, aHeight);
     if (!pixbuf)
         return nullptr;
 
-    uint32_t rowstride = gdk_pixbuf_get_rowstride (pixbuf);
-    guchar* pixels = gdk_pixbuf_get_pixels (pixbuf);
+    uint32_t destStride = gdk_pixbuf_get_rowstride (pixbuf);
+    guchar* destPixels = gdk_pixbuf_get_pixels (pixbuf);
 
-    long cairoStride = aImgSurface->Stride();
-    unsigned char* cairoData = aImgSurface->Data();
+    RefPtr<DataSourceSurface> dataSurface = aSurface->GetDataSurface();
+    DataSourceSurface::MappedSurface map;
+    dataSurface->Map(DataSourceSurface::MapType::READ, &map);
+    uint8_t* srcData = map.mData;
+    int32_t srcStride = map.mStride;
 
-    gfxImageFormat format = aImgSurface->Format();
+    SurfaceFormat format = dataSurface->GetFormat();
 
     for (int32_t row = 0; row < aHeight; ++row) {
         for (int32_t col = 0; col < aWidth; ++col) {
-            guchar* pixel = pixels + row * rowstride + 4 * col;
+            guchar* destPixel = destPixels + row * destStride + 4 * col;
 
-            uint32_t* cairoPixel = reinterpret_cast<uint32_t*>
-                                                   ((cairoData + row * cairoStride + 4 * col));
+            uint32_t* srcPixel =
+                reinterpret_cast<uint32_t*>((srcData + row * srcStride + 4 * col));
 
-            if (format == gfxImageFormatARGB32) {
-                const uint8_t a = (*cairoPixel >> 24) & 0xFF;
-                const uint8_t r = unpremultiply((*cairoPixel >> 16) & 0xFF, a);
-                const uint8_t g = unpremultiply((*cairoPixel >>  8) & 0xFF, a);
-                const uint8_t b = unpremultiply((*cairoPixel >>  0) & 0xFF, a);
+            if (format == SurfaceFormat::B8G8R8A8) {
+                const uint8_t a = (*srcPixel >> 24) & 0xFF;
+                const uint8_t r = unpremultiply((*srcPixel >> 16) & 0xFF, a);
+                const uint8_t g = unpremultiply((*srcPixel >>  8) & 0xFF, a);
+                const uint8_t b = unpremultiply((*srcPixel >>  0) & 0xFF, a);
 
-                *pixel++ = r;
-                *pixel++ = g;
-                *pixel++ = b;
-                *pixel++ = a;
+                *destPixel++ = r;
+                *destPixel++ = g;
+                *destPixel++ = b;
+                *destPixel++ = a;
             } else {
-                NS_ASSERTION(format == gfxImageFormatRGB24,
-                             "unexpected format");
-                const uint8_t r = (*cairoPixel >> 16) & 0xFF;
-                const uint8_t g = (*cairoPixel >>  8) & 0xFF;
-                const uint8_t b = (*cairoPixel >>  0) & 0xFF;
+                MOZ_ASSERT(format == SurfaceFormat::B8G8R8X8);
 
-                *pixel++ = r;
-                *pixel++ = g;
-                *pixel++ = b;
-                *pixel++ = 0xFF; // A
+                const uint8_t r = (*srcPixel >> 16) & 0xFF;
+                const uint8_t g = (*srcPixel >>  8) & 0xFF;
+                const uint8_t b = (*srcPixel >>  0) & 0xFF;
+
+                *destPixel++ = r;
+                *destPixel++ = g;
+                *destPixel++ = b;
+                *destPixel++ = 0xFF; // A
             }
         }
     }
 
+    dataSurface->Unmap();
+
     return pixbuf;
 }
 
 GdkPixbuf*
 nsImageToPixbuf::SurfaceToPixbuf(gfxASurface* aSurface, int32_t aWidth, int32_t aHeight)
 {
     if (aSurface->CairoStatus()) {
         NS_ERROR("invalid surface");
@@ -130,10 +152,14 @@ nsImageToPixbuf::SurfaceToPixbuf(gfxASur
         if (!context)
             return nullptr;
 
         context->SetOperator(gfxContext::OPERATOR_SOURCE);
         context->SetSource(aSurface);
         context->Paint();
     }
 
-    return ImgSurfaceToPixbuf(imgSurface, aWidth, aHeight);
+    RefPtr<SourceSurface> surface =
+        gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr,
+                                                               imgSurface);
+
+    return SourceSurfaceToPixbuf(surface, aWidth, aHeight);
 }
--- a/widget/gtk/nsImageToPixbuf.h
+++ b/widget/gtk/nsImageToPixbuf.h
@@ -8,33 +8,43 @@
 
 #include "nsIImageToPixbuf.h"
 #include "mozilla/Attributes.h"
 
 class gfxASurface;
 class gfxPattern;
 class gfxImageSurface;
 
+namespace mozilla {
+namespace gfx {
+class SourceSurface;
+}
+}
+
 class nsImageToPixbuf MOZ_FINAL : public nsIImageToPixbuf {
+    typedef mozilla::gfx::SourceSurface SourceSurface;
+
     public:
         NS_DECL_ISUPPORTS
         NS_IMETHOD_(GdkPixbuf*) ConvertImageToPixbuf(imgIContainer* aImage);
 
         // Friendlier version of ConvertImageToPixbuf for callers inside of
         // widget
         /**
          * The return value of all these, if not null, should be
          * released as needed by the caller using g_object_unref.
          */
         static GdkPixbuf* ImageToPixbuf(imgIContainer * aImage);
         static GdkPixbuf* SurfaceToPixbuf(gfxASurface* aSurface,
                                           int32_t aWidth, int32_t aHeight);
+        static GdkPixbuf* SourceSurfaceToPixbuf(SourceSurface* aSurface,
+                                                int32_t aWidth,
+                                                int32_t aHeight);
+
     private:
-        static GdkPixbuf* ImgSurfaceToPixbuf(gfxImageSurface* aImgSurface,
-                                             int32_t aWidth, int32_t aHeight);
         ~nsImageToPixbuf() {}
 };
 
 
 // fc2389b8-c650-4093-9e42-b05e5f0685b7
 #define NS_IMAGE_TO_PIXBUF_CID \
 { 0xfc2389b8, 0xc650, 0x4093, \
   { 0x9e, 0x42, 0xb0, 0x5e, 0x5f, 0x06, 0x85, 0xb7 } }
--- a/widget/windows/nsTextStore.cpp
+++ b/widget/windows/nsTextStore.cpp
@@ -520,18 +520,16 @@ nsTextStore::nsTextStore()
  : mContent(mComposition, mSelection)
 {
   mRefCnt = 1;
   mEditCookie = 0;
   mIPProfileCookie = TF_INVALID_COOKIE;
   mSinkMask = 0;
   mLock = 0;
   mLockQueued = 0;
-  mTextChange.acpStart = INT32_MAX;
-  mTextChange.acpOldEnd = mTextChange.acpNewEnd = 0;
   mInputScopeDetected = false;
   mInputScopeRequested = false;
   mIsRecordingActionsWithoutLock = false;
   mNotifySelectionChange = false;
   mIsIMM_IME = IsIMM_IME(::GetKeyboardLayout(0));
   // We hope that 5 or more actions don't occur at once.
   mPendingActions.SetCapacity(5);
 
@@ -675,17 +673,25 @@ nsTextStore::Create(nsWindowBase* aWidge
 
   return true;
 }
 
 bool
 nsTextStore::Destroy(void)
 {
   PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
-    ("TSF: 0x%p nsTextStore::Destroy()", this));
+    ("TSF: 0x%p nsTextStore::Destroy(), mComposition.IsComposing()=%s",
+     this, GetBoolName(mComposition.IsComposing())));
+
+  // If there is composition, TSF keeps the composition even after the text
+  // store destroyed.  So, we should clear the composition here.
+  if (mComposition.IsComposing()) {
+    NS_WARNING("Composition is still alive at destroying the text store");
+    CommitCompositionInternal(false);
+  }
 
   mContent.Clear();
   mSelection.MarkDirty();
 
   if (mWidget) {
     // When blurred, Tablet Input Panel posts "blur" messages
     // and try to insert text when the message is retrieved later.
     // But by that time the text store is already destroyed,
@@ -3063,88 +3069,109 @@ nsTextStore::GetIMEUpdatePreference()
 nsresult
 nsTextStore::OnTextChangeInternal(uint32_t aStart,
                                   uint32_t aOldEnd,
                                   uint32_t aNewEnd)
 {
   PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
          ("TSF: 0x%p nsTextStore::OnTextChangeInternal(aStart=%lu, "
           "aOldEnd=%lu, aNewEnd=%lu), mSink=0x%p, mSinkMask=%s, "
-          "mTextChange={ acpStart=%ld, acpOldEnd=%ld, acpNewEnd=%ld }",
+          "mComposition.IsComposing()=%s",
           this, aStart, aOldEnd, aNewEnd, mSink.get(),
-          GetSinkMaskNameStr(mSinkMask).get(), mTextChange.acpStart,
-          mTextChange.acpOldEnd, mTextChange.acpNewEnd));
+          GetSinkMaskNameStr(mSinkMask).get(),
+          GetBoolName(mComposition.IsComposing())));
 
   if (IsReadLocked()) {
     return NS_OK;
   }
 
-  NS_ASSERTION(!mComposition.IsComposing(), "text changed during composition");
   mSelection.MarkDirty();
 
-  if (mSink && 0 != (mSinkMask & TS_AS_TEXT_CHANGE)) {
-    mTextChange.acpStart = std::min(mTextChange.acpStart, LONG(aStart));
-    mTextChange.acpOldEnd = std::max(mTextChange.acpOldEnd, LONG(aOldEnd));
-    mTextChange.acpNewEnd = std::max(mTextChange.acpNewEnd, LONG(aNewEnd));
-    ::PostMessageW(mWidget->GetWindowHandle(),
-                   WM_USER_TSF_TEXTCHANGE, 0, 0);
+  if (!mSink || !(mSinkMask & TS_AS_TEXT_CHANGE)) {
+    return NS_OK;
+  }
+
+  if (aStart >= INT32_MAX || aOldEnd >= INT32_MAX || aNewEnd >= INT32_MAX) {
+    PR_LOG(sTextStoreLog, PR_LOG_ERROR,
+           ("TSF: 0x%p   nsTextStore::OnTextChangeInternal() FAILED due to "
+            "offset is too big for calling mSink->OnTextChange()...",
+            this));
+    return NS_OK;
   }
+
+  // Some TIPs are confused by text change notification during composition.
+  // Especially, some of them stop working for composition in our process.
+  // For preventing it, let's commit the composition.
+  if (mComposition.IsComposing()) {
+    PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
+           ("TSF: 0x%p   nsTextStore::OnTextChangeInternal(), "
+            "committing the composition for avoiding making TIP confused...",
+            this));
+    CommitCompositionInternal(false);
+    return NS_OK;
+  }
+
+  TS_TEXTCHANGE textChange;
+  textChange.acpStart = static_cast<LONG>(aStart);
+  textChange.acpOldEnd = static_cast<LONG>(aOldEnd);
+  textChange.acpNewEnd = static_cast<LONG>(aNewEnd);
+
+  PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
+         ("TSF: 0x%p   nsTextStore::OnTextChangeInternal(), calling"
+          "mSink->OnTextChange(0, { acpStart=%ld, acpOldEnd=%ld, "
+          "acpNewEnd=%ld })...", this, textChange.acpStart,
+          textChange.acpOldEnd, textChange.acpNewEnd));
+  mSink->OnTextChange(0, &textChange);
+
   return NS_OK;
 }
 
-void
-nsTextStore::OnTextChangeMsg()
-{
-  PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
-         ("TSF: 0x%p nsTextStore::OnTextChangeMsg(), "
-          "mSink=0x%p, mSinkMask=%s, mTextChange={ acpStart=%ld, "
-          "acpOldEnd=%ld, acpNewEnd=%ld }",
-          this, mSink.get(),
-          GetSinkMaskNameStr(mSinkMask).get(), mTextChange.acpStart,
-          mTextChange.acpOldEnd, mTextChange.acpNewEnd));
-
-  if (!mLock && mSink && 0 != (mSinkMask & TS_AS_TEXT_CHANGE) &&
-      INT32_MAX > mTextChange.acpStart) {
-    PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
-           ("TSF: 0x%p   nsTextStore::OnTextChangeMsg(), calling"
-            "mSink->OnTextChange(0, { acpStart=%ld, acpOldEnd=%ld, "
-            "acpNewEnd=%ld })...", this, mTextChange.acpStart,
-            mTextChange.acpOldEnd, mTextChange.acpNewEnd));
-    mSink->OnTextChange(0, &mTextChange);
-    mTextChange.acpStart = INT32_MAX;
-    mTextChange.acpOldEnd = mTextChange.acpNewEnd = 0;
-  }
-}
-
 nsresult
 nsTextStore::OnSelectionChangeInternal(void)
 {
   PR_LOG(sTextStoreLog, PR_LOG_DEBUG,
          ("TSF: 0x%p nsTextStore::OnSelectionChangeInternal(), "
-          "mSink=0x%p, mSinkMask=%s, mIsRecordingActionsWithoutLock=%s",
+          "mSink=0x%p, mSinkMask=%s, mIsRecordingActionsWithoutLock=%s, "
+          "mComposition.IsComposing()=%s",
           this, mSink.get(), GetSinkMaskNameStr(mSinkMask).get(),
-          GetBoolName(mIsRecordingActionsWithoutLock)));
+          GetBoolName(mIsRecordingActionsWithoutLock),
+          GetBoolName(mComposition.IsComposing())));
 
   if (IsReadLocked()) {
     return NS_OK;
   }
 
-  NS_ASSERTION(!mComposition.IsComposing(),
-               "selection changed during composition");
   mSelection.MarkDirty();
 
-  if (mSink && 0 != (mSinkMask & TS_AS_SEL_CHANGE)) {
+  if (!mSink || !(mSinkMask & TS_AS_SEL_CHANGE)) {
+    return NS_OK;
+  }
+
+  // Some TIPs are confused by selection change notification during composition.
+  // Especially, some of them stop working for composition in our process.
+  // For preventing it, let's commit the composition.
+  if (mComposition.IsComposing()) {
+    PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
+           ("TSF: 0x%p   nsTextStore::OnSelectionChangeInternal(), "
+            "committing the composition for avoiding making TIP confused...",
+            this));
+    CommitCompositionInternal(false);
+    return NS_OK;
+  }
+
+  if (!mIsRecordingActionsWithoutLock) {
     PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
            ("TSF: 0x%p   nsTextStore::OnSelectionChangeInternal(), calling "
             "mSink->OnSelectionChange()...", this));
-    if (!mIsRecordingActionsWithoutLock) {
-      mSink->OnSelectionChange();
-    } else {
-      mNotifySelectionChange = true;
-    }
+    mSink->OnSelectionChange();
+  } else {
+    PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
+           ("TSF: 0x%p   nsTextStore::OnSelectionChangeInternal(), pending "
+            "a call of mSink->OnSelectionChange()...", this));
+    mNotifySelectionChange = true;
   }
   return NS_OK;
 }
 
 nsresult
 nsTextStore::OnLayoutChange()
 {
   NS_ENSURE_TRUE(mContext, NS_ERROR_FAILURE);
@@ -3594,22 +3621,16 @@ nsTextStore::ProcessMessage(nsWindowBase
       sTsfTextStore->mIsIMM_IME = IsIMM_IME(::GetKeyboardLayout(0));
 
       PR_LOG(sTextStoreLog, PR_LOG_ALWAYS,
         ("TSF: nsTextStore::ProcessMessage(aWindow=0x%p, "
          "aMessage=WM_INPUTLANGCHANGE, aWParam=0x%08X, aLParam=0x%08X), "
          "mIsIMM_IME=%s", aWindow, aWParam, aLParam,
          GetBoolName(sTsfTextStore->mIsIMM_IME)));
       break;
-
-    case WM_USER_TSF_TEXTCHANGE:
-      NS_ENSURE_TRUE_VOID(sTsfTextStore);
-      sTsfTextStore->OnTextChangeMsg();
-      aResult.mConsumed = true;
-      break;
   }
 }
 
 /******************************************************************/
 /* nsTextStore::Composition                                       */
 /******************************************************************/
 
 void
--- a/widget/windows/nsTextStore.h
+++ b/widget/windows/nsTextStore.h
@@ -39,21 +39,16 @@ class MetroWidget;
 #endif
 
 namespace mozilla {
 namespace widget {
 struct MSGResult;
 } // namespace widget
 } // namespace mozilla
 
-// It doesn't work well when we notify TSF of text change
-// during a mutation observer call because things get broken.
-// So we post a message and notify TSF when we get it later.
-#define WM_USER_TSF_TEXTCHANGE  (WM_USER + 0x100)
-
 /*
  * Text Services Framework text store
  */
 
 class nsTextStore MOZ_FINAL : public ITextStoreACP,
                               public ITfContextOwnerCompositionSink,
                               public ITfInputProcessorProfileActivationSink
 {
@@ -241,17 +236,16 @@ protected:
   // only when this is called from SetSelection.  Because otherwise, the text
   // event should not be sent from here.
   HRESULT  SetSelectionInternal(const TS_SELECTION_ACP*,
                                 bool aDispatchTextEvent = false);
   bool     InsertTextAtSelectionInternal(const nsAString &aInsertStr,
                                          TS_TEXTCHANGE* aTextChange);
   void     CommitCompositionInternal(bool);
   nsresult OnTextChangeInternal(uint32_t, uint32_t, uint32_t);
-  void     OnTextChangeMsg();
   nsresult OnSelectionChangeInternal(void);
   HRESULT  GetDisplayAttribute(ITfProperty* aProperty,
                                ITfRange* aRange,
                                TF_DISPLAYATTRIBUTE* aResult);
   HRESULT  RestartCompositionIfNecessary(ITfRange* pRangeNew = nullptr);
 
   // Following methods record composing action(s) to mPendingActions.
   // They will be flushed FlushPendingActions().
@@ -284,18 +278,16 @@ protected:
   // Currently installed notification sink
   nsRefPtr<ITextStoreACPSink>  mSink;
   // TS_AS_* mask of what events to notify
   DWORD                        mSinkMask;
   // 0 if not locked, otherwise TS_LF_* indicating the current lock
   DWORD                        mLock;
   // 0 if no lock is queued, otherwise TS_LF_* indicating the queue lock
   DWORD                        mLockQueued;
-  // Cumulative text change offsets since the last notification
-  TS_TEXTCHANGE                mTextChange;
 
   class Composition MOZ_FINAL
   {
   public:
     // nullptr if no composition is active, otherwise the current composition
     nsRefPtr<ITfCompositionView> mView;
 
     // Current copy of the active composition string. Only mString is