Merge m-c to fx-team
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Tue, 07 Oct 2014 15:05:29 +0200
changeset 209121 32122cb5118daeacb1fb58d3775a5f8783962983
parent 209120 4af29b25a7bff2e9b52ec704c47836855aad265c (current diff)
parent 209107 25a98bac926420e5fcca88d79b400c1b1c10faa5 (diff)
child 209122 22f1131e66e39df39eba618a8a78c854df2f5c36
child 209199 4fa74ef900c52830e0990d20aa4a91b0b8043353
push id1
push userroot
push dateMon, 20 Oct 2014 17:29:22 +0000
milestone35.0a1
Merge m-c to fx-team
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -10,25 +10,25 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="83de447d9ae9a59459d7a445f9348a254c661850"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="9306e431d5b559035d9656902e413816b6ca3c26"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9eec93462df6d01fe33a737bb4a185e9ad6cee15"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f9bc14c28aed7b2571e641bfeeca81876ec48ec"/>
   <!-- Stock Android things -->
   <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="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
   <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="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
   <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="8b880805d454664b3eed11d0f053cdeafa1ff06e"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="a1e239a0bb5cd1d69680bf1075883aa9a7bf2429"/>
   <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="c7931763d41be602407ed9d71e2c0292c6597e00"/>
   <project groups="linux,x86" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="83760d213fb3bec7b4117d266fcfbf6fe2ba14ab"/>
   <project name="device/common" path="device/common" revision="6a2995683de147791e516aae2ccb31fdfbe2ad30"/>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,23 +14,23 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="84923f1940625c47ff4c1fdf01b10fde3b7d909e">
     <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="83de447d9ae9a59459d7a445f9348a254c661850"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="9306e431d5b559035d9656902e413816b6ca3c26"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c058843242068d0df7c107e09da31b53d2e08fa6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9eec93462df6d01fe33a737bb4a185e9ad6cee15"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f9bc14c28aed7b2571e641bfeeca81876ec48ec"/>
   <!-- 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
@@ -12,20 +12,20 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8986df0f82e15ac2798df0b6c2ee3435400677ac">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="83de447d9ae9a59459d7a445f9348a254c661850"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="9306e431d5b559035d9656902e413816b6ca3c26"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9eec93462df6d01fe33a737bb4a185e9ad6cee15"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f9bc14c28aed7b2571e641bfeeca81876ec48ec"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <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-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -10,25 +10,25 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="83de447d9ae9a59459d7a445f9348a254c661850"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="9306e431d5b559035d9656902e413816b6ca3c26"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9eec93462df6d01fe33a737bb4a185e9ad6cee15"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f9bc14c28aed7b2571e641bfeeca81876ec48ec"/>
   <!-- Stock Android things -->
   <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="f92a936f2aa97526d4593386754bdbf02db07a12"/>
   <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="6e47ff2790f5656b5b074407829ceecf3e6188c4"/>
   <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="1950e4760fa14688b83cdbb5acaa1af9f82ef434"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="ac6eb97a37035c09fb5ede0852f0881e9aadf9ad"/>
   <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="737f591c5f95477148d26602c7be56cbea0cdeb9"/>
   <project groups="linux,x86" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="51da9b1981be481b92a59a826d4d78dc73d0989a"/>
   <project name="device/common" path="device/common" revision="798a3664597e6041985feab9aef42e98d458bc3d"/>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,23 +14,23 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="84923f1940625c47ff4c1fdf01b10fde3b7d909e">
     <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="83de447d9ae9a59459d7a445f9348a254c661850"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="9306e431d5b559035d9656902e413816b6ca3c26"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="cd88d860656c31c7da7bb310d6a160d0011b0961"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="c058843242068d0df7c107e09da31b53d2e08fa6"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9eec93462df6d01fe33a737bb4a185e9ad6cee15"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f9bc14c28aed7b2571e641bfeeca81876ec48ec"/>
   <!-- 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/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -10,25 +10,25 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="3a2947df41a480de1457a6dcdbf46ad0af70d8e0">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="83de447d9ae9a59459d7a445f9348a254c661850"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="9306e431d5b559035d9656902e413816b6ca3c26"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9eec93462df6d01fe33a737bb4a185e9ad6cee15"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f9bc14c28aed7b2571e641bfeeca81876ec48ec"/>
   <!-- Stock Android things -->
   <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="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
   <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="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
   <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="8b880805d454664b3eed11d0f053cdeafa1ff06e"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="a1e239a0bb5cd1d69680bf1075883aa9a7bf2429"/>
   <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="c7931763d41be602407ed9d71e2c0292c6597e00"/>
   <project groups="linux,x86" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="a32003194f707f66a2d8cdb913ed1869f1926c5d"/>
   <project name="device/common" path="device/common" revision="96d4d2006c4fcb2f19a3fa47ab10cb409faa017b"/>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -12,20 +12,20 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8986df0f82e15ac2798df0b6c2ee3435400677ac">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="83de447d9ae9a59459d7a445f9348a254c661850"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="9306e431d5b559035d9656902e413816b6ca3c26"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9eec93462df6d01fe33a737bb4a185e9ad6cee15"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f9bc14c28aed7b2571e641bfeeca81876ec48ec"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="e95b4ce22c825da44d14299e1190ea39a5260bde"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/>
   <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="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
   <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="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
   <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="8b880805d454664b3eed11d0f053cdeafa1ff06e"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
         "git_revision": "", 
         "remote": "", 
         "branch": ""
     }, 
-    "revision": "1e5360b21cca807b2ea63ea8fb878b451131c9bd", 
+    "revision": "25a5d3c030a5ece82a1114882575560b58fe185f", 
     "repo_path": "/integration/gaia-central"
 }
--- a/b2g/config/hamachi/sources.xml
+++ b/b2g/config/hamachi/sources.xml
@@ -12,22 +12,22 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="84923f1940625c47ff4c1fdf01b10fde3b7d909e">
     <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="83de447d9ae9a59459d7a445f9348a254c661850"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="9306e431d5b559035d9656902e413816b6ca3c26"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9eec93462df6d01fe33a737bb4a185e9ad6cee15"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f9bc14c28aed7b2571e641bfeeca81876ec48ec"/>
   <!-- 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
@@ -10,17 +10,17 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <default remote="caf" revision="b2g/ics_strawberry" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="84923f1940625c47ff4c1fdf01b10fde3b7d909e">
     <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="83de447d9ae9a59459d7a445f9348a254c661850"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="9306e431d5b559035d9656902e413816b6ca3c26"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
   <project name="gonk-patches" path="patches" remote="b2g" revision="223a2421006e8f5da33f516f6891c87cae86b0f6"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="6426040f1be4a844082c9769171ce7f5341a5528"/>
   <project name="platform/bionic" path="bionic" revision="d2eb6c7b6e1bc7643c17df2d9d9bcb1704d0b9ab"/>
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,20 +12,20 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="8986df0f82e15ac2798df0b6c2ee3435400677ac">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="83de447d9ae9a59459d7a445f9348a254c661850"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="9306e431d5b559035d9656902e413816b6ca3c26"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9eec93462df6d01fe33a737bb4a185e9ad6cee15"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f9bc14c28aed7b2571e641bfeeca81876ec48ec"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <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
@@ -12,22 +12,22 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="ics_chocolate_rb4.2" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="84923f1940625c47ff4c1fdf01b10fde3b7d909e">
     <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="83de447d9ae9a59459d7a445f9348a254c661850"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="9306e431d5b559035d9656902e413816b6ca3c26"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="5883a99b6528ced9dafaed8d3ca2405fb285537e"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="827214fcf38d6569aeb5c6d6f31cb296d1f09272"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="891e5069c0ad330d8191bf8c7b879c814258c89f"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="562d357b72279a9e35d4af5aeecc8e1ffa2f44f1"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9eec93462df6d01fe33a737bb4a185e9ad6cee15"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="9f9bc14c28aed7b2571e641bfeeca81876ec48ec"/>
   <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/build/automationutils.py
+++ b/build/automationutils.py
@@ -304,41 +304,51 @@ def processSingleLeakFile(leakLogFileNam
 
   if logAsWarning:
     log.warning("%s | leakcheck | %s %d bytes leaked (%s)"
                 % (prefix, processString, totalBytesLeaked, leakedObjectSummary))
   else:
     log.info("%s | leakcheck | %s %d bytes leaked (%s)"
              % (prefix, processString, totalBytesLeaked, leakedObjectSummary))
 
-def processLeakLog(leakLogFile, leakThresholds, ignoreMissingLeaks):
+def processLeakLog(leakLogFile, options):
   """Process the leak log, including separate leak logs created
   by child processes.
 
   Use this function if you want an additional PASS/FAIL summary.
   It must be used with the |XPCOM_MEM_BLOAT_LOG| environment variable.
 
   The base of leakLogFile for a non-default process needs to end with
     _proctype_pid12345.log
   "proctype" is a string denoting the type of the process, which should
   be the result of calling XRE_ChildProcessTypeToString(). 12345 is
   a series of digits that is the pid for the process. The .log is
   optional.
 
   All other file names are treated as being for default processes.
 
+  The options argument is checked for two optional attributes,
+  leakThresholds and ignoreMissingLeaks.
+
   leakThresholds should be a dict mapping process types to leak thresholds,
   in bytes. If a process type is not present in the dict the threshold
   will be 0.
+
+  ignoreMissingLeaks should be a list of process types. If a process
+  creates a leak log without a TOTAL, then we report an error if it isn't
+  in the list ignoreMissingLeaks.
   """
 
   if not os.path.exists(leakLogFile):
     log.info("WARNING | leakcheck | refcount logging is off, so leaks can't be detected!")
     return
 
+  leakThresholds = getattr(options, 'leakThresholds', {})
+  ignoreMissingLeaks = getattr(options, 'ignoreMissingLeaks', [])
+
   # This list is based on kGeckoProcessTypeString. ipdlunittest processes likely
   # are not going to produce leak logs we will ever see.
   knownProcessTypes = ["default", "plugin", "tab", "geckomediaplugin"]
 
   for processType in knownProcessTypes:
     log.info("TEST-INFO | leakcheck | %s process: leak threshold set at %d bytes"
              % (processType, leakThresholds.get(processType, 0)))
 
--- a/content/base/src/nsFrameMessageManager.cpp
+++ b/content/base/src/nsFrameMessageManager.cpp
@@ -1723,17 +1723,17 @@ public:
     if (!cc) {
       return true;
     }
     ClonedMessageData data;
     if (!BuildClonedMessageDataForChild(cc, aData, data)) {
       return false;
     }
     InfallibleTArray<mozilla::jsipc::CpowEntry> cpows;
-    if (!cc->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
+    if (aCpows && !cc->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
       return false;
     }
     if (aIsSync) {
       return cc->SendSyncMessage(PromiseFlatString(aMessage), data, cpows,
                                  IPC::Principal(aPrincipal), aJSONRetVal);
     }
     return cc->CallRpcMessage(PromiseFlatString(aMessage), data, cpows,
                               IPC::Principal(aPrincipal), aJSONRetVal);
@@ -1750,17 +1750,17 @@ public:
     if (!cc) {
       return true;
     }
     ClonedMessageData data;
     if (!BuildClonedMessageDataForChild(cc, aData, data)) {
       return false;
     }
     InfallibleTArray<mozilla::jsipc::CpowEntry> cpows;
-    if (!cc->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
+    if (aCpows && !cc->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
       return false;
     }
     return cc->SendAsyncMessage(PromiseFlatString(aMessage), data, cpows,
                                 IPC::Principal(aPrincipal));
   }
 
 };
 
--- a/dom/bindings/Errors.msg
+++ b/dom/bindings/Errors.msg
@@ -55,8 +55,10 @@ MSG_DEF(MSG_INVALID_URL, 1, "{0} is not 
 MSG_DEF(MSG_METADATA_NOT_CONFIGURED, 0, "Either size or lastModified should be true.")
 MSG_DEF(MSG_INVALID_READ_SIZE, 0, "0 (Zero) is not a valid read size.")
 MSG_DEF(MSG_HEADERS_IMMUTABLE, 0, "Headers are immutable and cannot be modified.")
 MSG_DEF(MSG_INVALID_HEADER_NAME, 1, "{0} is an invalid header name.")
 MSG_DEF(MSG_INVALID_HEADER_VALUE, 1, "{0} is an invalid header value.")
 MSG_DEF(MSG_INVALID_HEADER_SEQUENCE, 0, "Headers require name/value tuples when being initialized by a sequence.")
 MSG_DEF(MSG_PERMISSION_DENIED_TO_PASS_ARG, 1, "Permission denied to pass cross-origin object as {0}.")
 MSG_DEF(MSG_MISSING_REQUIRED_DICTIONARY_MEMBER, 1, "Missing required {0}.")
+MSG_DEF(MSG_INVALID_REQUEST_METHOD, 1, "Invalid request method {0}.")
+MSG_DEF(MSG_REQUEST_BODY_CONSUMED_ERROR, 0, "Request body has already been consumed.")
new file mode 100644
--- /dev/null
+++ b/dom/fetch/Fetch.cpp
@@ -0,0 +1,100 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "Fetch.h"
+
+#include "nsIStringStream.h"
+#include "nsIUnicodeEncoder.h"
+
+#include "nsStringStream.h"
+
+#include "mozilla/dom/EncodingUtils.h"
+#include "mozilla/dom/URLSearchParams.h"
+
+namespace mozilla {
+namespace dom {
+
+nsresult
+ExtractByteStreamFromBody(const OwningArrayBufferOrArrayBufferViewOrScalarValueStringOrURLSearchParams& aBodyInit,
+                          nsIInputStream** aStream,
+                          nsCString& aContentType)
+{
+  MOZ_ASSERT(aStream);
+
+  nsresult rv;
+  nsCOMPtr<nsIInputStream> byteStream;
+  if (aBodyInit.IsArrayBuffer()) {
+    const ArrayBuffer& buf = aBodyInit.GetAsArrayBuffer();
+    buf.ComputeLengthAndData();
+    //XXXnsm reinterpret_cast<> is used in DOMParser, should be ok.
+    rv = NS_NewByteInputStream(getter_AddRefs(byteStream),
+                               reinterpret_cast<char*>(buf.Data()),
+                               buf.Length(), NS_ASSIGNMENT_COPY);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+  } else if (aBodyInit.IsArrayBufferView()) {
+    const ArrayBufferView& buf = aBodyInit.GetAsArrayBufferView();
+    buf.ComputeLengthAndData();
+    //XXXnsm reinterpret_cast<> is used in DOMParser, should be ok.
+    rv = NS_NewByteInputStream(getter_AddRefs(byteStream),
+                               reinterpret_cast<char*>(buf.Data()),
+                               buf.Length(), NS_ASSIGNMENT_COPY);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+  } else if (aBodyInit.IsScalarValueString()) {
+    nsString str = aBodyInit.GetAsScalarValueString();
+
+    nsCOMPtr<nsIUnicodeEncoder> encoder = EncodingUtils::EncoderForEncoding("UTF-8");
+    if (!encoder) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
+
+    int32_t destBufferLen;
+    rv = encoder->GetMaxLength(str.get(), str.Length(), &destBufferLen);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+
+    nsCString encoded;
+    if (!encoded.SetCapacity(destBufferLen, fallible_t())) {
+      return NS_ERROR_OUT_OF_MEMORY;
+    }
+
+    char* destBuffer = encoded.BeginWriting();
+    int32_t srcLen = (int32_t) str.Length();
+    int32_t outLen = destBufferLen;
+    rv = encoder->Convert(str.get(), &srcLen, destBuffer, &outLen);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+
+    MOZ_ASSERT(outLen <= destBufferLen);
+    encoded.SetLength(outLen);
+    rv = NS_NewCStringInputStream(getter_AddRefs(byteStream), encoded);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+
+    aContentType = NS_LITERAL_CSTRING("text/plain;charset=UTF-8");
+  } else if (aBodyInit.IsURLSearchParams()) {
+    URLSearchParams& params = aBodyInit.GetAsURLSearchParams();
+    nsString serialized;
+    params.Stringify(serialized);
+    rv = NS_NewStringInputStream(getter_AddRefs(byteStream), serialized);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+    aContentType = NS_LITERAL_CSTRING("application/x-www-form-urlencoded;charset=UTF-8");
+  }
+
+  MOZ_ASSERT(byteStream);
+  byteStream.forget(aStream);
+  return NS_OK;
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/fetch/Fetch.h
@@ -0,0 +1,29 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_Fetch_h
+#define mozilla_dom_Fetch_h
+
+#include "mozilla/dom/UnionTypes.h"
+
+class nsIInputStream;
+
+namespace mozilla {
+namespace dom {
+
+/*
+ * Creates an nsIInputStream based on the fetch specifications 'extract a byte
+ * stream algorithm' - http://fetch.spec.whatwg.org/#concept-bodyinit-extract.
+ * Stores content type in out param aContentType.
+ */
+nsresult
+ExtractByteStreamFromBody(const OwningArrayBufferOrArrayBufferViewOrScalarValueStringOrURLSearchParams& aBodyInit,
+                          nsIInputStream** aStream,
+                          nsCString& aContentType);
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_Fetch_h
--- a/dom/fetch/Headers.cpp
+++ b/dom/fetch/Headers.cpp
@@ -2,17 +2,16 @@
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "mozilla/dom/Headers.h"
 
 #include "mozilla/ErrorResult.h"
-#include "mozilla/dom/UnionTypes.h"
 #include "mozilla/dom/WorkerPrivate.h"
 #include "mozilla/Preferences.h"
 
 #include "nsCharSeparatedTokenizer.h"
 #include "nsContentUtils.h"
 #include "nsDOMString.h"
 #include "nsNetUtil.h"
 #include "nsPIDOMWindow.h"
@@ -78,16 +77,49 @@ Headers::Constructor(const GlobalObject&
 
   if (aRv.Failed()) {
     return nullptr;
   }
 
   return headers.forget();
 }
 
+// static
+already_AddRefed<Headers>
+Headers::Constructor(const GlobalObject& aGlobal,
+                     const OwningHeadersOrByteStringSequenceSequenceOrByteStringMozMap& aInit,
+                     ErrorResult& aRv)
+{
+  nsRefPtr<Headers> headers = new Headers(aGlobal.GetAsSupports());
+
+  if (aInit.IsHeaders()) {
+    headers->Fill(aInit.GetAsHeaders(), aRv);
+  } else if (aInit.IsByteStringSequenceSequence()) {
+    headers->Fill(aInit.GetAsByteStringSequenceSequence(), aRv);
+  } else if (aInit.IsByteStringMozMap()) {
+    headers->Fill(aInit.GetAsByteStringMozMap(), aRv);
+  }
+
+  if (NS_WARN_IF(aRv.Failed())) {
+    return nullptr;
+  }
+
+  return headers.forget();
+}
+
+Headers::Headers(const Headers& aOther)
+  : mOwner(aOther.mOwner)
+  , mGuard(aOther.mGuard)
+{
+  SetIsDOMBinding();
+  ErrorResult result;
+  Fill(aOther, result);
+  MOZ_ASSERT(!result.Failed());
+}
+
 void
 Headers::Append(const nsACString& aName, const nsACString& aValue,
                 ErrorResult& aRv)
 {
   nsAutoCString lowerName;
   ToLowerCase(aName, lowerName);
 
   if (IsInvalidMutableHeader(lowerName, &aValue, aRv)) {
@@ -198,16 +230,22 @@ Headers::Set(const nsACString& aName, co
     entry->mName = lowerName;
     entry->mValue = aValue;
   } else {
     mList.AppendElement(Entry(lowerName, aValue));
   }
 }
 
 void
+Headers::Clear()
+{
+  mList.Clear();
+}
+
+void
 Headers::SetGuard(HeadersGuardEnum aGuard, ErrorResult& aRv)
 {
   // Rather than re-validate all current headers, just require code to set
   // this prior to populating the Headers object.  Allow setting immutable
   // late, though, as that is pretty much required to have a  useful, immutable
   // headers object.
   if (aGuard != HeadersGuardEnum::Immutable && mList.Length() > 0) {
     aRv.Throw(NS_ERROR_FAILURE);
@@ -323,11 +361,10 @@ void
 Headers::Fill(const MozMap<nsCString>& aInit, ErrorResult& aRv)
 {
   nsTArray<nsString> keys;
   aInit.GetKeys(keys);
   for (uint32_t i = 0; i < keys.Length() && !aRv.Failed(); ++i) {
     Append(NS_ConvertUTF16toUTF8(keys[i]), aInit.Get(keys[i]), aRv);
   }
 }
-
 } // namespace dom
 } // namespace mozilla
--- a/dom/fetch/Headers.h
+++ b/dom/fetch/Headers.h
@@ -3,16 +3,18 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_Headers_h
 #define mozilla_dom_Headers_h
 
 #include "mozilla/dom/HeadersBinding.h"
+#include "mozilla/dom/UnionTypes.h"
+
 #include "nsClassHashtable.h"
 #include "nsWrapperCache.h"
 
 class nsPIDOMWindow;
 
 namespace mozilla {
 
 class ErrorResult;
@@ -37,53 +39,67 @@ private:
     { }
 
     Entry() { }
 
     nsCString mName;
     nsCString mValue;
   };
 
-  nsRefPtr<nsISupports> mOwner;
+  nsCOMPtr<nsISupports> mOwner;
   HeadersGuardEnum mGuard;
   nsTArray<Entry> mList;
 
 public:
   explicit Headers(nsISupports* aOwner, HeadersGuardEnum aGuard = HeadersGuardEnum::None)
     : mOwner(aOwner)
     , mGuard(aGuard)
   {
     SetIsDOMBinding();
   }
 
+  explicit Headers(const Headers& aOther);
+
   static bool PrefEnabled(JSContext* cx, JSObject* obj);
 
   static already_AddRefed<Headers>
   Constructor(const GlobalObject& aGlobal,
               const Optional<HeadersOrByteStringSequenceSequenceOrByteStringMozMap>& aInit,
               ErrorResult& aRv);
 
+  static already_AddRefed<Headers>
+  Constructor(const GlobalObject& aGlobal,
+              const OwningHeadersOrByteStringSequenceSequenceOrByteStringMozMap& aInit,
+              ErrorResult& aRv);
+
   void Append(const nsACString& aName, const nsACString& aValue,
               ErrorResult& aRv);
   void Delete(const nsACString& aName, ErrorResult& aRv);
   void Get(const nsACString& aName, nsCString& aValue, ErrorResult& aRv) const;
   void GetAll(const nsACString& aName, nsTArray<nsCString>& aResults,
               ErrorResult& aRv) const;
   bool Has(const nsACString& aName, ErrorResult& aRv) const;
   void Set(const nsACString& aName, const nsACString& aValue, ErrorResult& aRv);
 
+  void Clear();
+
   // ChromeOnly
   HeadersGuardEnum Guard() const { return mGuard; }
   void SetGuard(HeadersGuardEnum aGuard, ErrorResult& aRv);
 
   virtual JSObject* WrapObject(JSContext* aCx);
   nsISupports* GetParentObject() const { return mOwner; }
 
+  void Fill(const Headers& aInit, ErrorResult& aRv);
 private:
-  Headers(const Headers& aOther) MOZ_DELETE;
+  // Since Headers is also an nsISupports, the above constructor can
+  // accidentally be invoked as new Headers(Headers*[, implied None guard]) when
+  // the intention is to use the copy constructor. Explicitly disallow it.
+  Headers(Headers* aOther) MOZ_DELETE;
+
   virtual ~Headers();
 
   static bool IsSimpleHeader(const nsACString& aName,
                              const nsACString* aValue = nullptr);
   static bool IsInvalidName(const nsACString& aName, ErrorResult& aRv);
   static bool IsInvalidValue(const nsACString& aValue, ErrorResult& aRv);
   bool IsImmutable(ErrorResult& aRv) const;
   bool IsForbiddenRequestHeader(const nsACString& aName) const;
@@ -98,17 +114,16 @@ private:
     return IsInvalidName(aName, aRv) ||
            (aValue && IsInvalidValue(*aValue, aRv)) ||
            IsImmutable(aRv) ||
            IsForbiddenRequestHeader(aName) ||
            IsForbiddenRequestNoCorsHeader(aName, aValue) ||
            IsForbiddenResponseHeader(aName);
   }
 
-  void Fill(const Headers& aInit, ErrorResult& aRv);
   void Fill(const Sequence<Sequence<nsCString>>& aInit, ErrorResult& aRv);
   void Fill(const MozMap<nsCString>& aInit, ErrorResult& aRv);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_Headers_h
new file mode 100644
--- /dev/null
+++ b/dom/fetch/InternalRequest.cpp
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "InternalRequest.h"
+
+#include "nsIContentPolicy.h"
+#include "nsIDocument.h"
+
+#include "mozilla/ErrorResult.h"
+#include "mozilla/dom/ScriptSettings.h"
+#include "mozilla/dom/workers/Workers.h"
+
+#include "WorkerPrivate.h"
+
+namespace mozilla {
+namespace dom {
+
+// The global is used to extract the principal.
+already_AddRefed<InternalRequest>
+InternalRequest::GetRequestConstructorCopy(nsIGlobalObject* aGlobal, ErrorResult& aRv) const
+{
+  nsRefPtr<InternalRequest> copy = new InternalRequest();
+  copy->mURL.Assign(mURL);
+  copy->SetMethod(mMethod);
+  copy->mHeaders = new Headers(*mHeaders);
+
+  copy->mBodyStream = mBodyStream;
+  copy->mPreserveContentCodings = true;
+
+  if (NS_IsMainThread()) {
+    nsIPrincipal* principal = aGlobal->PrincipalOrNull();
+    MOZ_ASSERT(principal);
+    aRv = nsContentUtils::GetASCIIOrigin(principal, copy->mOrigin);
+    if (NS_WARN_IF(aRv.Failed())) {
+      return nullptr;
+    }
+  } else {
+    workers::WorkerPrivate* worker = workers::GetCurrentThreadWorkerPrivate();
+    MOZ_ASSERT(worker);
+    worker->AssertIsOnWorkerThread();
+
+    workers::WorkerPrivate::LocationInfo& location = worker->GetLocationInfo();
+    copy->mOrigin = NS_ConvertUTF16toUTF8(location.mOrigin);
+  }
+
+  copy->mMode = mMode;
+  copy->mCredentialsMode = mCredentialsMode;
+  // FIXME(nsm): Add ContentType fetch to nsIContentPolicy and friends.
+  // Then set copy's mContext to that.
+  return copy.forget();
+}
+
+InternalRequest::~InternalRequest()
+{
+}
+
+} // namespace dom
+} // namespace mozilla
new file mode 100644
--- /dev/null
+++ b/dom/fetch/InternalRequest.h
@@ -0,0 +1,264 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_InternalRequest_h
+#define mozilla_dom_InternalRequest_h
+
+#include "mozilla/dom/Headers.h"
+#include "mozilla/dom/RequestBinding.h"
+#include "mozilla/dom/UnionTypes.h"
+
+#include "nsIContentPolicy.h"
+#include "nsIInputStream.h"
+#include "nsISupportsImpl.h"
+
+class nsIDocument;
+class nsPIDOMWindow;
+
+namespace mozilla {
+namespace dom {
+
+class FetchBodyStream;
+class Request;
+
+class InternalRequest MOZ_FINAL
+{
+  friend class Request;
+
+public:
+  NS_INLINE_DECL_THREADSAFE_REFCOUNTING(InternalRequest)
+
+  enum ContextFrameType
+  {
+    FRAMETYPE_AUXILIARY = 0,
+    FRAMETYPE_TOP_LEVEL,
+    FRAMETYPE_NESTED,
+    FRAMETYPE_NONE,
+  };
+
+  // Since referrer type can be none, client or a URL.
+  enum ReferrerType
+  {
+    REFERRER_NONE = 0,
+    REFERRER_CLIENT,
+    REFERRER_URL,
+  };
+
+  enum ResponseTainting
+  {
+    RESPONSETAINT_BASIC,
+    RESPONSETAINT_CORS,
+    RESPONSETAINT_OPAQUE,
+  };
+
+  explicit InternalRequest()
+    : mMethod("GET")
+    , mHeaders(new Headers(nullptr, HeadersGuardEnum::None))
+    , mContextFrameType(FRAMETYPE_NONE)
+    , mReferrerType(REFERRER_CLIENT)
+    , mMode(RequestMode::No_cors)
+    , mCredentialsMode(RequestCredentials::Omit)
+    , mResponseTainting(RESPONSETAINT_BASIC)
+    , mRedirectCount(0)
+    , mAuthenticationFlag(false)
+    , mForceOriginHeader(false)
+    , mManualRedirect(false)
+    , mPreserveContentCodings(false)
+    , mSameOriginDataURL(false)
+    , mSkipServiceWorker(false)
+    , mSynchronous(false)
+    , mUnsafeRequest(false)
+    , mUseURLCredentials(false)
+  {
+  }
+
+  explicit InternalRequest(const InternalRequest& aOther)
+    : mMethod(aOther.mMethod)
+    , mURL(aOther.mURL)
+    , mHeaders(aOther.mHeaders)
+    , mBodyStream(aOther.mBodyStream)
+    , mContext(aOther.mContext)
+    , mOrigin(aOther.mOrigin)
+    , mContextFrameType(aOther.mContextFrameType)
+    , mReferrerType(aOther.mReferrerType)
+    , mReferrerURL(aOther.mReferrerURL)
+    , mMode(aOther.mMode)
+    , mCredentialsMode(aOther.mCredentialsMode)
+    , mResponseTainting(aOther.mResponseTainting)
+    , mRedirectCount(aOther.mRedirectCount)
+    , mAuthenticationFlag(aOther.mAuthenticationFlag)
+    , mForceOriginHeader(aOther.mForceOriginHeader)
+    , mManualRedirect(aOther.mManualRedirect)
+    , mPreserveContentCodings(aOther.mPreserveContentCodings)
+    , mSameOriginDataURL(aOther.mSameOriginDataURL)
+    , mSandboxedStorageAreaURLs(aOther.mSandboxedStorageAreaURLs)
+    , mSkipServiceWorker(aOther.mSkipServiceWorker)
+    , mSynchronous(aOther.mSynchronous)
+    , mUnsafeRequest(aOther.mUnsafeRequest)
+    , mUseURLCredentials(aOther.mUseURLCredentials)
+  {
+  }
+
+  void
+  GetMethod(nsCString& aMethod) const
+  {
+    aMethod.Assign(mMethod);
+  }
+
+  void
+  SetMethod(const nsACString& aMethod)
+  {
+    mMethod.Assign(aMethod);
+  }
+
+  void
+  GetURL(nsCString& aURL) const
+  {
+    aURL.Assign(mURL);
+  }
+
+  bool
+  ReferrerIsNone() const
+  {
+    return mReferrerType == REFERRER_NONE;
+  }
+
+  bool
+  ReferrerIsURL() const
+  {
+    return mReferrerType == REFERRER_URL;
+  }
+
+  bool
+  ReferrerIsClient() const
+  {
+    return mReferrerType == REFERRER_CLIENT;
+  }
+
+  nsCString
+  ReferrerAsURL() const
+  {
+    MOZ_ASSERT(ReferrerIsURL());
+    return mReferrerURL;
+  }
+
+  void
+  SetReferrer(const nsACString& aReferrer)
+  {
+    // May be removed later.
+    MOZ_ASSERT(!ReferrerIsNone());
+    mReferrerType = REFERRER_URL;
+    mReferrerURL.Assign(aReferrer);
+  }
+
+  bool
+  IsSynchronous() const
+  {
+    return mSynchronous;
+  }
+
+  void
+  SetMode(RequestMode aMode)
+  {
+    mMode = aMode;
+  }
+
+  void
+  SetCredentialsMode(RequestCredentials aCredentialsMode)
+  {
+    mCredentialsMode = aCredentialsMode;
+  }
+
+  nsContentPolicyType
+  GetContext() const
+  {
+    return mContext;
+  }
+
+  Headers*
+  Headers_()
+  {
+    return mHeaders;
+  }
+
+  bool
+  ForceOriginHeader()
+  {
+    return mForceOriginHeader;
+  }
+
+  void
+  GetOrigin(nsCString& aOrigin) const
+  {
+    aOrigin.Assign(mOrigin);
+  }
+
+  void
+  SetBody(nsIInputStream* aStream)
+  {
+    mBodyStream = aStream;
+  }
+
+  // Will return the original stream!
+  // Use a tee or copy if you don't want to erase the original.
+  void
+  GetBody(nsIInputStream** aStream)
+  {
+    nsCOMPtr<nsIInputStream> s = mBodyStream;
+    s.forget(aStream);
+  }
+
+  // The global is used as the client for the new object.
+  already_AddRefed<InternalRequest>
+  GetRequestConstructorCopy(nsIGlobalObject* aGlobal, ErrorResult& aRv) const;
+
+private:
+  ~InternalRequest();
+
+  void
+  SetURL(const nsACString& aURL)
+  {
+    mURL.Assign(aURL);
+  }
+
+  nsCString mMethod;
+  nsCString mURL;
+  nsRefPtr<Headers> mHeaders;
+  nsCOMPtr<nsIInputStream> mBodyStream;
+
+  // nsContentPolicyType does not cover the complete set defined in the spec,
+  // but it is a good start.
+  nsContentPolicyType mContext;
+
+  nsCString mOrigin;
+
+  ContextFrameType mContextFrameType;
+  ReferrerType mReferrerType;
+
+  // When mReferrerType is REFERRER_URL.
+  nsCString mReferrerURL;
+
+  RequestMode mMode;
+  RequestCredentials mCredentialsMode;
+  ResponseTainting mResponseTainting;
+
+  uint32_t mRedirectCount;
+
+  bool mAuthenticationFlag;
+  bool mForceOriginHeader;
+  bool mManualRedirect;
+  bool mPreserveContentCodings;
+  bool mSameOriginDataURL;
+  bool mSandboxedStorageAreaURLs;
+  bool mSkipServiceWorker;
+  bool mSynchronous;
+  bool mUnsafeRequest;
+  bool mUseURLCredentials;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_InternalRequest_h
--- a/dom/fetch/Request.cpp
+++ b/dom/fetch/Request.cpp
@@ -1,118 +1,443 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "Request.h"
 
+#include "nsIUnicodeDecoder.h"
+#include "nsIURI.h"
+
+#include "nsDOMFile.h"
 #include "nsDOMString.h"
-#include "nsISupportsImpl.h"
-#include "nsIURI.h"
+#include "nsNetUtil.h"
 #include "nsPIDOMWindow.h"
+#include "nsStreamUtils.h"
+#include "nsStringStream.h"
 
 #include "mozilla/ErrorResult.h"
+#include "mozilla/dom/EncodingUtils.h"
 #include "mozilla/dom/Headers.h"
+#include "mozilla/dom/Fetch.h"
 #include "mozilla/dom/Promise.h"
+#include "mozilla/dom/URL.h"
+#include "mozilla/dom/workers/bindings/URL.h"
+
+// dom/workers
+#include "File.h"
+#include "WorkerPrivate.h"
 
 namespace mozilla {
 namespace dom {
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(Request)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(Request)
-NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Request, mOwner, mHeaders)
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Request, mOwner)
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Request)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
-Request::Request(nsISupports* aOwner)
+Request::Request(nsIGlobalObject* aOwner, InternalRequest* aRequest)
   : mOwner(aOwner)
-  , mHeaders(new Headers(aOwner))
+  , mRequest(aRequest)
+  , mBodyUsed(false)
 {
   SetIsDOMBinding();
 }
 
 Request::~Request()
 {
 }
 
+already_AddRefed<InternalRequest>
+Request::GetInternalRequest()
+{
+  nsRefPtr<InternalRequest> r = mRequest;
+  return r.forget();
+}
+
 /*static*/ already_AddRefed<Request>
-Request::Constructor(const GlobalObject& global,
+Request::Constructor(const GlobalObject& aGlobal,
                      const RequestOrScalarValueString& aInput,
-                     const RequestInit& aInit, ErrorResult& rv)
+                     const RequestInit& aInit, ErrorResult& aRv)
 {
-  nsRefPtr<Request> request = new Request(global.GetAsSupports());
-  return request.forget();
+  nsRefPtr<InternalRequest> request;
+
+  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
+
+  if (aInput.IsRequest()) {
+    nsRefPtr<Request> inputReq = &aInput.GetAsRequest();
+    if (inputReq->BodyUsed()) {
+      aRv.ThrowTypeError(MSG_REQUEST_BODY_CONSUMED_ERROR);
+      return nullptr;
+    }
+
+    inputReq->SetBodyUsed();
+    request = inputReq->GetInternalRequest();
+  } else {
+    request = new InternalRequest();
+  }
+
+  request = request->GetRequestConstructorCopy(global, aRv);
+  if (NS_WARN_IF(aRv.Failed())) {
+    return nullptr;
+  }
+
+  RequestMode fallbackMode = RequestMode::EndGuard_;
+  RequestCredentials fallbackCredentials = RequestCredentials::EndGuard_;
+  if (aInput.IsScalarValueString()) {
+    nsString input;
+    input.Assign(aInput.GetAsScalarValueString());
+
+    nsString requestURL;
+    if (NS_IsMainThread()) {
+      nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(global);
+      MOZ_ASSERT(window);
+      nsCOMPtr<nsIURI> docURI = window->GetDocumentURI();
+      nsCString spec;
+      aRv = docURI->GetSpec(spec);
+      if (NS_WARN_IF(aRv.Failed())) {
+        return nullptr;
+      }
+
+      nsRefPtr<mozilla::dom::URL> url =
+        dom::URL::Constructor(aGlobal, input, NS_ConvertUTF8toUTF16(spec), aRv);
+      if (aRv.Failed()) {
+        return nullptr;
+      }
+
+      url->Stringify(requestURL, aRv);
+      if (aRv.Failed()) {
+        return nullptr;
+      }
+    } else {
+      workers::WorkerPrivate* worker = workers::GetCurrentThreadWorkerPrivate();
+      MOZ_ASSERT(worker);
+      worker->AssertIsOnWorkerThread();
+
+      nsString baseURL = NS_ConvertUTF8toUTF16(worker->GetLocationInfo().mHref);
+      nsRefPtr<workers::URL> url =
+        workers::URL::Constructor(aGlobal, input, baseURL, aRv);
+      if (aRv.Failed()) {
+        return nullptr;
+      }
+
+      url->Stringify(requestURL, aRv);
+      if (aRv.Failed()) {
+        return nullptr;
+      }
+    }
+    request->SetURL(NS_ConvertUTF16toUTF8(requestURL));
+    fallbackMode = RequestMode::Cors;
+    fallbackCredentials = RequestCredentials::Omit;
+  }
+
+  RequestMode mode = aInit.mMode.WasPassed() ? aInit.mMode.Value() : fallbackMode;
+  RequestCredentials credentials =
+    aInit.mCredentials.WasPassed() ? aInit.mCredentials.Value()
+                                   : fallbackCredentials;
+
+  if (mode != RequestMode::EndGuard_) {
+    request->SetMode(mode);
+  }
+
+  if (credentials != RequestCredentials::EndGuard_) {
+    request->SetCredentialsMode(credentials);
+  }
+
+  if (aInit.mMethod.WasPassed()) {
+    nsCString method = aInit.mMethod.Value();
+    ToLowerCase(method);
+
+    if (!method.EqualsASCII("options") &&
+        !method.EqualsASCII("get") &&
+        !method.EqualsASCII("head") &&
+        !method.EqualsASCII("post") &&
+        !method.EqualsASCII("put") &&
+        !method.EqualsASCII("delete")) {
+      NS_ConvertUTF8toUTF16 label(method);
+      aRv.ThrowTypeError(MSG_INVALID_REQUEST_METHOD, &label);
+      return nullptr;
+    }
+
+    ToUpperCase(method);
+    request->SetMethod(method);
+  }
+
+  nsRefPtr<Request> domRequest = new Request(global, request);
+  nsRefPtr<Headers> domRequestHeaders = domRequest->Headers_();
+
+  nsRefPtr<Headers> headers;
+  if (aInit.mHeaders.WasPassed()) {
+    headers = Headers::Constructor(aGlobal, aInit.mHeaders.Value(), aRv);
+    if (aRv.Failed()) {
+      return nullptr;
+    }
+  } else {
+    headers = new Headers(*domRequestHeaders);
+  }
+
+  domRequestHeaders->Clear();
+
+  if (domRequest->Mode() == RequestMode::No_cors) {
+    nsCString method;
+    domRequest->GetMethod(method);
+    ToLowerCase(method);
+    if (!method.EqualsASCII("get") &&
+        !method.EqualsASCII("head") &&
+        !method.EqualsASCII("post")) {
+      NS_ConvertUTF8toUTF16 label(method);
+      aRv.ThrowTypeError(MSG_INVALID_REQUEST_METHOD, &label);
+      return nullptr;
+    }
+
+    domRequestHeaders->SetGuard(HeadersGuardEnum::Request_no_cors, aRv);
+    if (aRv.Failed()) {
+      return nullptr;
+    }
+  }
+
+  domRequestHeaders->Fill(*headers, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
+
+  if (aInit.mBody.WasPassed()) {
+    const OwningArrayBufferOrArrayBufferViewOrScalarValueStringOrURLSearchParams& bodyInit = aInit.mBody.Value();
+    nsCOMPtr<nsIInputStream> stream;
+    nsCString contentType;
+    aRv = ExtractByteStreamFromBody(bodyInit,
+                                    getter_AddRefs(stream), contentType);
+    if (NS_WARN_IF(aRv.Failed())) {
+      return nullptr;
+    }
+    request->SetBody(stream);
+
+    if (!contentType.IsVoid() &&
+        !domRequestHeaders->Has(NS_LITERAL_CSTRING("Content-Type"), aRv)) {
+      domRequestHeaders->Append(NS_LITERAL_CSTRING("Content-Type"),
+                                contentType, aRv);
+    }
+
+    if (aRv.Failed()) {
+      return nullptr;
+    }
+  }
+
+  // Extract mime type.
+  nsTArray<nsCString> contentTypeValues;
+  domRequestHeaders->GetAll(NS_LITERAL_CSTRING("Content-Type"),
+                            contentTypeValues, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
+
+  // HTTP ABNF states Content-Type may have only one value.
+  // This is from the "parse a header value" of the fetch spec.
+  if (contentTypeValues.Length() == 1) {
+    domRequest->mMimeType = contentTypeValues[0];
+    ToLowerCase(domRequest->mMimeType);
+  }
+
+  return domRequest.forget();
 }
 
 already_AddRefed<Request>
 Request::Clone() const
 {
-  nsRefPtr<Request> request = new Request(mOwner);
+  // FIXME(nsm): Bug 1073231. This is incorrect, but the clone method isn't
+  // well defined yet.
+  nsRefPtr<Request> request = new Request(mOwner,
+                                          new InternalRequest(*mRequest));
   return request.forget();
 }
 
+namespace {
+nsresult
+DecodeUTF8(const nsCString& aBuffer, nsString& aDecoded)
+{
+  nsCOMPtr<nsIUnicodeDecoder> decoder =
+    EncodingUtils::DecoderForEncoding("UTF-8");
+  if (!decoder) {
+    return NS_ERROR_FAILURE;
+  }
+
+  int32_t destBufferLen;
+  nsresult rv =
+    decoder->GetMaxLength(aBuffer.get(), aBuffer.Length(), &destBufferLen);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  if (!aDecoded.SetCapacity(destBufferLen, fallible_t())) {
+    return NS_ERROR_OUT_OF_MEMORY;
+  }
+
+  char16_t* destBuffer = aDecoded.BeginWriting();
+  int32_t srcLen = (int32_t) aBuffer.Length();
+  int32_t outLen = destBufferLen;
+  rv = decoder->Convert(aBuffer.get(), &srcLen, destBuffer, &outLen);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  MOZ_ASSERT(outLen <= destBufferLen);
+  aDecoded.SetLength(outLen);
+  return NS_OK;
+}
+}
+
+already_AddRefed<Promise>
+Request::ConsumeBody(ConsumeType aType, ErrorResult& aRv)
+{
+  nsRefPtr<Promise> promise = Promise::Create(mOwner, aRv);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
+
+  if (BodyUsed()) {
+    aRv.ThrowTypeError(MSG_REQUEST_BODY_CONSUMED_ERROR);
+    return nullptr;
+  }
+
+  SetBodyUsed();
+
+  // While the spec says to do this asynchronously, all the body constructors
+  // right now only accept bodies whose streams are backed by an in-memory
+  // buffer that can be read without blocking. So I think this is fine.
+  nsCOMPtr<nsIInputStream> stream;
+  mRequest->GetBody(getter_AddRefs(stream));
+
+  if (!stream) {
+    aRv = NS_NewByteInputStream(getter_AddRefs(stream), "", 0,
+                                NS_ASSIGNMENT_COPY);
+    if (aRv.Failed()) {
+      return nullptr;
+    }
+  }
+
+  AutoJSAPI api;
+  api.Init(mOwner);
+  JSContext* cx = api.cx();
+
+  // We can make this assertion because for now we only support memory backed
+  // structures for the body argument for a Request.
+  MOZ_ASSERT(NS_InputStreamIsBuffered(stream));
+  nsCString buffer;
+  uint64_t len;
+  aRv = stream->Available(&len);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
+
+  aRv = NS_ReadInputStreamToString(stream, buffer, len);
+  if (aRv.Failed()) {
+    return nullptr;
+  }
+
+  buffer.SetLength(len);
+
+  switch (aType) {
+    case CONSUME_ARRAYBUFFER: {
+      JS::Rooted<JSObject*> arrayBuffer(cx);
+      arrayBuffer =
+        ArrayBuffer::Create(cx, buffer.Length(),
+                            reinterpret_cast<const uint8_t*>(buffer.get()));
+      JS::Rooted<JS::Value> val(cx);
+      val.setObjectOrNull(arrayBuffer);
+      promise->MaybeResolve(cx, val);
+      return promise.forget();
+    }
+    case CONSUME_BLOB: {
+      // XXXnsm it is actually possible to avoid these duplicate allocations
+      // for the Blob case by having the Blob adopt the stream's memory
+      // directly, but I've not added a special case for now.
+      //
+      // This is similar to nsContentUtils::CreateBlobBuffer, but also deals
+      // with worker wrapping.
+      uint32_t blobLen = buffer.Length();
+      void* blobData = moz_malloc(blobLen);
+      nsCOMPtr<nsIDOMBlob> blob;
+      if (blobData) {
+        memcpy(blobData, buffer.BeginReading(), blobLen);
+        blob = DOMFile::CreateMemoryFile(blobData, blobLen,
+                                         NS_ConvertUTF8toUTF16(mMimeType));
+      } else {
+        aRv = NS_ERROR_OUT_OF_MEMORY;
+        return nullptr;
+      }
+
+      JS::Rooted<JS::Value> jsBlob(cx);
+      if (NS_IsMainThread()) {
+        aRv = nsContentUtils::WrapNative(cx, blob, &jsBlob);
+        if (aRv.Failed()) {
+          return nullptr;
+        }
+      } else {
+        jsBlob.setObject(*workers::file::CreateBlob(cx, blob));
+      }
+      promise->MaybeResolve(cx, jsBlob);
+      return promise.forget();
+    }
+    case CONSUME_JSON: {
+      nsString decoded;
+      aRv = DecodeUTF8(buffer, decoded);
+      if (aRv.Failed()) {
+        return nullptr;
+      }
+
+      JS::Rooted<JS::Value> json(cx);
+      if (!JS_ParseJSON(cx, decoded.get(), decoded.Length(), &json)) {
+        JS::Rooted<JS::Value> exn(cx);
+        if (JS_GetPendingException(cx, &exn)) {
+          JS_ClearPendingException(cx);
+          promise->MaybeReject(cx, exn);
+        }
+      }
+      promise->MaybeResolve(cx, json);
+      return promise.forget();
+    }
+    case CONSUME_TEXT: {
+      nsString decoded;
+      aRv = DecodeUTF8(buffer, decoded);
+      if (aRv.Failed()) {
+        return nullptr;
+      }
+
+      promise->MaybeResolve(decoded);
+      return promise.forget();
+    }
+  }
+
+  NS_NOTREACHED("Unexpected consume body type");
+  // Silence warnings.
+  return nullptr;
+}
+
 already_AddRefed<Promise>
 Request::ArrayBuffer(ErrorResult& aRv)
 {
-  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
-  MOZ_ASSERT(global);
-  nsRefPtr<Promise> promise = Promise::Create(global, aRv);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-
-  promise->MaybeReject(NS_ERROR_NOT_AVAILABLE);
-  return promise.forget();
+  return ConsumeBody(CONSUME_ARRAYBUFFER, aRv);
 }
 
 already_AddRefed<Promise>
 Request::Blob(ErrorResult& aRv)
 {
-  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
-  MOZ_ASSERT(global);
-  nsRefPtr<Promise> promise = Promise::Create(global, aRv);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-
-  promise->MaybeReject(NS_ERROR_NOT_AVAILABLE);
-  return promise.forget();
+  return ConsumeBody(CONSUME_BLOB, aRv);
 }
 
 already_AddRefed<Promise>
 Request::Json(ErrorResult& aRv)
 {
-  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
-  MOZ_ASSERT(global);
-  nsRefPtr<Promise> promise = Promise::Create(global, aRv);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-
-  promise->MaybeReject(NS_ERROR_NOT_AVAILABLE);
-  return promise.forget();
+  return ConsumeBody(CONSUME_JSON, aRv);
 }
 
 already_AddRefed<Promise>
 Request::Text(ErrorResult& aRv)
 {
-  nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(GetParentObject());
-  MOZ_ASSERT(global);
-  nsRefPtr<Promise> promise = Promise::Create(global, aRv);
-  if (aRv.Failed()) {
-    return nullptr;
-  }
-
-  promise->MaybeReject(NS_ERROR_NOT_AVAILABLE);
-  return promise.forget();
-}
-
-bool
-Request::BodyUsed()
-{
-  return false;
+  return ConsumeBody(CONSUME_TEXT, aRv);
 }
 } // namespace dom
 } // namespace mozilla
--- a/dom/fetch/Request.h
+++ b/dom/fetch/Request.h
@@ -4,74 +4,82 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_Request_h
 #define mozilla_dom_Request_h
 
 #include "nsISupportsImpl.h"
 #include "nsWrapperCache.h"
 
+#include "mozilla/dom/InternalRequest.h"
+// Required here due to certain WebIDL enums/classes being declared in both
+// files.
 #include "mozilla/dom/RequestBinding.h"
 #include "mozilla/dom/UnionTypes.h"
 
-
 class nsPIDOMWindow;
 
 namespace mozilla {
 namespace dom {
 
 class Headers;
 class Promise;
 
 class Request MOZ_FINAL : public nsISupports
                         , public nsWrapperCache
 {
   NS_DECL_CYCLE_COLLECTING_ISUPPORTS
   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(Request)
 
 public:
-  Request(nsISupports* aOwner);
+  Request(nsIGlobalObject* aOwner, InternalRequest* aRequest);
 
   JSObject*
   WrapObject(JSContext* aCx)
   {
     return RequestBinding::Wrap(aCx, this);
   }
 
   void
   GetUrl(DOMString& aUrl) const
   {
-    aUrl.AsAString() = EmptyString();
+    aUrl.AsAString() = NS_ConvertUTF8toUTF16(mRequest->mURL);
   }
 
   void
   GetMethod(nsCString& aMethod) const
   {
-    aMethod = EmptyCString();
+    aMethod = mRequest->mMethod;
   }
 
   RequestMode
   Mode() const
   {
-    return RequestMode::Same_origin;
+    return mRequest->mMode;
   }
 
   RequestCredentials
   Credentials() const
   {
-    return RequestCredentials::Omit;
+    return mRequest->mCredentialsMode;
   }
 
   void
   GetReferrer(DOMString& aReferrer) const
   {
-    aReferrer.AsAString() = EmptyString();
+    if (mRequest->ReferrerIsNone()) {
+      aReferrer.AsAString() = EmptyString();
+      return;
+    }
+
+    // FIXME(nsm): Spec doesn't say what to do if referrer is client.
+    aReferrer.AsAString() = NS_ConvertUTF8toUTF16(mRequest->mReferrerURL);
   }
 
-  Headers* Headers_() const { return mHeaders; }
+  Headers* Headers_() const { return mRequest->Headers_(); }
 
   static already_AddRefed<Request>
   Constructor(const GlobalObject& aGlobal, const RequestOrScalarValueString& aInput,
               const RequestInit& aInit, ErrorResult& rv);
 
   nsISupports* GetParentObject() const
   {
     return mOwner;
@@ -88,20 +96,46 @@ public:
 
   already_AddRefed<Promise>
   Json(ErrorResult& aRv);
 
   already_AddRefed<Promise>
   Text(ErrorResult& aRv);
 
   bool
-  BodyUsed();
+  BodyUsed() const
+  {
+    return mBodyUsed;
+  }
+
+  already_AddRefed<InternalRequest>
+  GetInternalRequest();
 private:
+  enum ConsumeType
+  {
+    CONSUME_ARRAYBUFFER,
+    CONSUME_BLOB,
+    // FormData not supported right now,
+    CONSUME_JSON,
+    CONSUME_TEXT,
+  };
+
   ~Request();
 
-  nsCOMPtr<nsISupports> mOwner;
-  nsRefPtr<Headers> mHeaders;
+  already_AddRefed<Promise>
+  ConsumeBody(ConsumeType aType, ErrorResult& aRv);
+
+  void
+  SetBodyUsed()
+  {
+    mBodyUsed = true;
+  }
+
+  nsCOMPtr<nsIGlobalObject> mOwner;
+  nsRefPtr<InternalRequest> mRequest;
+  bool mBodyUsed;
+  nsCString mMimeType;
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_Request_h
--- a/dom/fetch/moz.build
+++ b/dom/fetch/moz.build
@@ -1,22 +1,26 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 EXPORTS.mozilla.dom += [
+    'Fetch.h',
     'Headers.h',
+    'InternalRequest.h',
     'Request.h',
     'Response.h',
 ]
 
 UNIFIED_SOURCES += [
+    'Fetch.cpp',
     'Headers.cpp',
+    'InternalRequest.cpp',
     'Request.cpp',
     'Response.cpp',
 ]
 
 LOCAL_INCLUDES += [
     '../workers',
 ]
 
new file mode 100644
--- /dev/null
+++ b/dom/ipc/CPOWManagerGetter.h
@@ -0,0 +1,26 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_CPOWManagerGetter_h
+#define mozilla_dom_CPOWManagerGetter_h
+
+namespace mozilla {
+
+namespace jsipc {
+class JavaScriptShared;
+} /* namespace jsipc */
+
+namespace dom {
+class CPOWManagerGetter
+{
+public:
+  virtual mozilla::jsipc::JavaScriptShared* GetCPOWManager() = 0;
+};
+} /* namespace dom */
+
+} /* namespace mozilla */
+
+#endif /* mozilla_dom_CPOWManagerGetter_h */
--- a/dom/ipc/ContentBridgeChild.cpp
+++ b/dom/ipc/ContentBridgeChild.cpp
@@ -93,17 +93,17 @@ ContentBridgeChild::SendPBrowserConstruc
                                                       aID,
                                                       aIsForApp,
                                                       aIsForBrowser);
 }
 
 // This implementation is identical to ContentChild::GetCPOWManager but we can't
 // move it to nsIContentChild because it calls ManagedPJavaScriptChild() which
 // only exists in PContentChild and PContentBridgeChild.
-jsipc::JavaScriptChild *
+jsipc::JavaScriptShared*
 ContentBridgeChild::GetCPOWManager()
 {
   if (ManagedPJavaScriptChild().Length()) {
     return static_cast<JavaScriptChild*>(ManagedPJavaScriptChild()[0]);
   }
   JavaScriptChild* actor = static_cast<JavaScriptChild*>(SendPJavaScriptConstructor());
   return actor;
 }
--- a/dom/ipc/ContentBridgeChild.h
+++ b/dom/ipc/ContentBridgeChild.h
@@ -31,17 +31,17 @@ public:
                                 const ClonedMessageData& aData,
                                 const InfallibleTArray<jsipc::CpowEntry>& aCpows,
                                 const IPC::Principal& aPrincipal) MOZ_OVERRIDE;
 
   virtual PBlobChild*
   SendPBlobConstructor(PBlobChild* actor,
                        const BlobConstructorParams& params);
 
-  jsipc::JavaScriptChild* GetCPOWManager();
+  jsipc::JavaScriptShared* GetCPOWManager() MOZ_OVERRIDE;
 
   virtual bool SendPBrowserConstructor(PBrowserChild* aActor,
                                        const IPCTabContext& aContext,
                                        const uint32_t& aChromeFlags,
                                        const uint64_t& aID,
                                        const bool& aIsForApp,
                                        const bool& aIsForBrowser) MOZ_OVERRIDE;
 
--- a/dom/ipc/ContentBridgeParent.cpp
+++ b/dom/ipc/ContentBridgeParent.cpp
@@ -143,17 +143,17 @@ bool
 ContentBridgeParent::DeallocPBrowserParent(PBrowserParent* aParent)
 {
   return nsIContentParent::DeallocPBrowserParent(aParent);
 }
 
 // This implementation is identical to ContentParent::GetCPOWManager but we can't
 // move it to nsIContentParent because it calls ManagedPJavaScriptParent() which
 // only exists in PContentParent and PContentBridgeParent.
-jsipc::JavaScriptParent*
+jsipc::JavaScriptShared*
 ContentBridgeParent::GetCPOWManager()
 {
   if (ManagedPJavaScriptParent().Length()) {
     return static_cast<JavaScriptParent*>(ManagedPJavaScriptParent()[0]);
   }
   JavaScriptParent* actor = static_cast<JavaScriptParent*>(SendPJavaScriptConstructor());
   return actor;
 }
--- a/dom/ipc/ContentBridgeParent.h
+++ b/dom/ipc/ContentBridgeParent.h
@@ -34,17 +34,17 @@ public:
   virtual PBrowserParent*
   SendPBrowserConstructor(PBrowserParent* aActor,
                           const IPCTabContext& aContext,
                           const uint32_t& aChromeFlags,
                           const uint64_t& aID,
                           const bool& aIsForApp,
                           const bool& aIsForBrowser) MOZ_OVERRIDE;
 
-  jsipc::JavaScriptParent* GetCPOWManager();
+  jsipc::JavaScriptShared* GetCPOWManager() MOZ_OVERRIDE;
 
   virtual uint64_t ChildID() MOZ_OVERRIDE
   {
     return mChildID;
   }
   virtual bool IsForApp() MOZ_OVERRIDE
   {
     return mIsForApp;
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -1241,17 +1241,17 @@ ContentChild::AllocPTestShellChild()
 
 bool
 ContentChild::DeallocPTestShellChild(PTestShellChild* shell)
 {
     delete shell;
     return true;
 }
 
-jsipc::JavaScriptChild *
+jsipc::JavaScriptShared*
 ContentChild::GetCPOWManager()
 {
     if (ManagedPJavaScriptChild().Length()) {
         return static_cast<JavaScriptChild*>(ManagedPJavaScriptChild()[0]);
     }
     JavaScriptChild* actor = static_cast<JavaScriptChild*>(SendPJavaScriptConstructor());
     return actor;
 }
@@ -1726,17 +1726,17 @@ bool
 ContentChild::RecvAsyncMessage(const nsString& aMsg,
                                const ClonedMessageData& aData,
                                const InfallibleTArray<CpowEntry>& aCpows,
                                const IPC::Principal& aPrincipal)
 {
     nsRefPtr<nsFrameMessageManager> cpm = nsFrameMessageManager::sChildProcessManager;
     if (cpm) {
         StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForChild(aData);
-        CpowIdHolder cpows(GetCPOWManager(), aCpows);
+        CpowIdHolder cpows(this, aCpows);
         cpm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(cpm.get()),
                             aMsg, false, &cloneData, &cpows, aPrincipal, nullptr);
     }
     return true;
 }
 
 bool
 ContentChild::RecvGeolocationUpdate(const GeoPosition& somewhere)
--- a/dom/ipc/ContentChild.h
+++ b/dom/ipc/ContentChild.h
@@ -29,17 +29,17 @@ class RemoteSpellcheckEngineChild;
 
 namespace ipc {
 class OptionalURIParams;
 class PFileDescriptorSetChild;
 class URIParams;
 }// namespace ipc
 
 namespace jsipc {
-class JavaScriptChild;
+class JavaScriptShared;
 }
 
 namespace layers {
 class PCompositorChild;
 } // namespace layers
 
 namespace dom {
 
@@ -189,17 +189,17 @@ public:
 
     virtual bool
     RecvDataStoreNotify(const uint32_t& aAppId, const nsString& aName,
                         const nsString& aManifestURL) MOZ_OVERRIDE;
 
     virtual PTestShellChild* AllocPTestShellChild() MOZ_OVERRIDE;
     virtual bool DeallocPTestShellChild(PTestShellChild*) MOZ_OVERRIDE;
     virtual bool RecvPTestShellConstructor(PTestShellChild*) MOZ_OVERRIDE;
-    jsipc::JavaScriptChild *GetCPOWManager();
+    jsipc::JavaScriptShared* GetCPOWManager() MOZ_OVERRIDE;
 
     PMobileConnectionChild*
     SendPMobileConnectionConstructor(PMobileConnectionChild* aActor,
                                      const uint32_t& aClientId);
     virtual PMobileConnectionChild*
     AllocPMobileConnectionChild(const uint32_t& aClientId) MOZ_OVERRIDE;
     virtual bool
     DeallocPMobileConnectionChild(PMobileConnectionChild* aActor) MOZ_OVERRIDE;
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -1772,17 +1772,17 @@ ContentParent::NotifyTabDestroyed(PBrows
     if (ManagedPBrowserParent().Length() == 1) {
         MessageLoop::current()->PostTask(
             FROM_HERE,
             NewRunnableMethod(this, &ContentParent::ShutDownProcess,
                               /* force */ false));
     }
 }
 
-jsipc::JavaScriptParent*
+jsipc::JavaScriptShared*
 ContentParent::GetCPOWManager()
 {
     if (ManagedPJavaScriptParent().Length()) {
         return static_cast<JavaScriptParent*>(ManagedPJavaScriptParent()[0]);
     }
     return nullptr;
 }
 
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -40,17 +40,17 @@ class PRemoteSpellcheckEngineParent;
 namespace ipc {
 class OptionalURIParams;
 class PFileDescriptorSetParent;
 class URIParams;
 class TestShellParent;
 } // namespace ipc
 
 namespace jsipc {
-class JavaScriptParent;
+class JavaScriptShared;
 class PJavaScriptParent;
 }
 
 namespace layers {
 class PCompositorParent;
 class PSharedBufferManagerParent;
 } // namespace layers
 
@@ -172,17 +172,17 @@ public:
     void NotifyTabDestroying(PBrowserParent* aTab);
     /** Notify that a tab was destroyed during normal operation. */
     void NotifyTabDestroyed(PBrowserParent* aTab,
                             bool aNotifiedDestroying);
 
     TestShellParent* CreateTestShell();
     bool DestroyTestShell(TestShellParent* aTestShell);
     TestShellParent* GetTestShellSingleton();
-    jsipc::JavaScriptParent *GetCPOWManager();
+    jsipc::JavaScriptShared* GetCPOWManager() MOZ_OVERRIDE;
 
     void ReportChildAlreadyBlocked();
     bool RequestRunToCompletion();
 
     bool IsAlive();
     virtual bool IsForApp() MOZ_OVERRIDE;
     virtual bool IsForBrowser() MOZ_OVERRIDE
     {
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -2569,17 +2569,17 @@ TabChild::RecvAsyncMessage(const nsStrin
                            const InfallibleTArray<CpowEntry>& aCpows,
                            const IPC::Principal& aPrincipal)
 {
   if (mTabChildGlobal) {
     nsCOMPtr<nsIXPConnectJSObjectHolder> kungFuDeathGrip(GetGlobal());
     StructuredCloneData cloneData = UnpackClonedMessageDataForChild(aData);
     nsRefPtr<nsFrameMessageManager> mm =
       static_cast<nsFrameMessageManager*>(mTabChildGlobal->mMessageManager.get());
-    CpowIdHolder cpows(Manager()->GetCPOWManager(), aCpows);
+    CpowIdHolder cpows(Manager(), aCpows);
     mm->ReceiveMessage(static_cast<EventTarget*>(mTabChildGlobal),
                        aMessage, false, &cloneData, &cpows, aPrincipal, nullptr);
   }
   return true;
 }
 
 class UnloadScriptEvent : public nsRunnable
 {
@@ -2905,17 +2905,17 @@ TabChild::DoSendBlockingMessage(JSContex
                                 InfallibleTArray<nsString>* aJSONRetVal,
                                 bool aIsSync)
 {
   ClonedMessageData data;
   if (!BuildClonedMessageDataForChild(Manager(), aData, data)) {
     return false;
   }
   InfallibleTArray<CpowEntry> cpows;
-  if (!Manager()->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
+  if (aCpows && !Manager()->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
     return false;
   }
   if (aIsSync) {
     return SendSyncMessage(PromiseFlatString(aMessage), data, cpows,
                            Principal(aPrincipal), aJSONRetVal);
   }
 
   return CallRpcMessage(PromiseFlatString(aMessage), data, cpows,
@@ -2929,17 +2929,17 @@ TabChild::DoSendAsyncMessage(JSContext* 
                              JS::Handle<JSObject *> aCpows,
                              nsIPrincipal* aPrincipal)
 {
   ClonedMessageData data;
   if (!BuildClonedMessageDataForChild(Manager(), aData, data)) {
     return false;
   }
   InfallibleTArray<CpowEntry> cpows;
-  if (!Manager()->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
+  if (aCpows && !Manager()->GetCPOWManager()->Wrap(aCx, aCpows, &cpows)) {
     return false;
   }
   return SendAsyncMessage(PromiseFlatString(aMessage), data, cpows,
                           Principal(aPrincipal));
 }
 
 TabChild*
 TabChild::GetFrom(nsIPresShell* aPresShell)
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -1109,17 +1109,17 @@ TabParent::RecvSyncMessage(const nsStrin
     ContentParent* parent = Manager()->AsContentParent();
     if (!ContentParent::IgnoreIPCPrincipal() &&
         parent && principal && !AssertAppPrincipal(parent, principal)) {
       return false;
     }
   }
 
   StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData);
-  CpowIdHolder cpows(Manager()->GetCPOWManager(), aCpows);
+  CpowIdHolder cpows(Manager(), aCpows);
   return ReceiveMessage(aMessage, true, &cloneData, &cpows, aPrincipal, aJSONRetVal);
 }
 
 bool
 TabParent::AnswerRpcMessage(const nsString& aMessage,
                             const ClonedMessageData& aData,
                             const InfallibleTArray<CpowEntry>& aCpows,
                             const IPC::Principal& aPrincipal,
@@ -1131,17 +1131,17 @@ TabParent::AnswerRpcMessage(const nsStri
     ContentParent* parent = Manager()->AsContentParent();
     if (!ContentParent::IgnoreIPCPrincipal() &&
         parent && principal && !AssertAppPrincipal(parent, principal)) {
       return false;
     }
   }
 
   StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData);
-  CpowIdHolder cpows(Manager()->GetCPOWManager(), aCpows);
+  CpowIdHolder cpows(Manager(), aCpows);
   return ReceiveMessage(aMessage, true, &cloneData, &cpows, aPrincipal, aJSONRetVal);
 }
 
 bool
 TabParent::RecvAsyncMessage(const nsString& aMessage,
                             const ClonedMessageData& aData,
                             const InfallibleTArray<CpowEntry>& aCpows,
                             const IPC::Principal& aPrincipal)
@@ -1152,17 +1152,17 @@ TabParent::RecvAsyncMessage(const nsStri
     ContentParent* parent = Manager()->AsContentParent();
     if (!ContentParent::IgnoreIPCPrincipal() &&
         parent && principal && !AssertAppPrincipal(parent, principal)) {
       return false;
     }
   }
 
   StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData);
-  CpowIdHolder cpows(Manager()->GetCPOWManager(), aCpows);
+  CpowIdHolder cpows(Manager(), aCpows);
   return ReceiveMessage(aMessage, false, &cloneData, &cpows, aPrincipal, nullptr);
 }
 
 bool
 TabParent::RecvSetCursor(const uint32_t& aCursor, const bool& aForce)
 {
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (widget) {
--- a/dom/ipc/moz.build
+++ b/dom/ipc/moz.build
@@ -15,16 +15,17 @@ EXPORTS.mozilla.dom.ipc += [
 ]
 
 EXPORTS.mozilla.dom += [
     'ContentBridgeChild.h',
     'ContentBridgeParent.h',
     'ContentChild.h',
     'ContentParent.h',
     'ContentProcess.h',
+    'CPOWManagerGetter.h',
     'CrashReporterChild.h',
     'CrashReporterParent.h',
     'FilePickerParent.h',
     'nsIContentChild.h',
     'nsIContentParent.h',
     'PermissionMessageUtils.h',
     'StructuredCloneUtils.h',
     'TabChild.h',
--- a/dom/ipc/nsIContentChild.cpp
+++ b/dom/ipc/nsIContentChild.cpp
@@ -115,17 +115,17 @@ bool
 nsIContentChild::RecvAsyncMessage(const nsString& aMsg,
                                   const ClonedMessageData& aData,
                                   const InfallibleTArray<CpowEntry>& aCpows,
                                   const IPC::Principal& aPrincipal)
 {
   nsRefPtr<nsFrameMessageManager> cpm = nsFrameMessageManager::sChildProcessManager;
   if (cpm) {
     StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForChild(aData);
-    CpowIdHolder cpows(GetCPOWManager(), aCpows);
+    CpowIdHolder cpows(this, aCpows);
     cpm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(cpm.get()),
                         aMsg, false, &cloneData, &cpows, aPrincipal, nullptr);
   }
   return true;
 }
 
 } // dom
 } // mozilla
--- a/dom/ipc/nsIContentChild.h
+++ b/dom/ipc/nsIContentChild.h
@@ -4,46 +4,47 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_nsIContentChild_h
 #define mozilla_dom_nsIContentChild_h
 
 #include "nsISupports.h"
 #include "nsTArrayForwardDeclare.h"
+#include "mozilla/dom/CPOWManagerGetter.h"
 
 #define NS_ICONTENTCHILD_IID                                    \
   { 0x4eed2e73, 0x94ba, 0x48a8,                                 \
     { 0xa2, 0xd1, 0xa5, 0xed, 0x86, 0xd7, 0xbb, 0xe4 } }
 
 class nsIDOMBlob;
 class nsString;
 
 namespace IPC {
 class Principal;
 } // IPC
 
 namespace mozilla {
 
 namespace jsipc {
 class PJavaScriptChild;
-class JavaScriptChild;
 class CpowEntry;
 } // jsipc
 
 namespace dom {
 
 class BlobChild;
 class BlobConstructorParams;
 class ClonedMessageData;
 class IPCTabContext;
 class PBlobChild;
 class PBrowserChild;
 
 class nsIContentChild : public nsISupports
+                      , public CPOWManagerGetter
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICONTENTCHILD_IID)
 
   BlobChild* GetOrCreateActorForBlob(nsIDOMBlob* aBlob);
 
   virtual PBlobChild* SendPBlobConstructor(
     PBlobChild* aActor,
@@ -51,17 +52,16 @@ public:
 
   virtual bool
   SendPBrowserConstructor(PBrowserChild* aActor,
                           const IPCTabContext& aContext,
                           const uint32_t& aChromeFlags,
                           const uint64_t& aID,
                           const bool& aIsForApp,
                           const bool& aIsForBrowser) = 0;
-  virtual jsipc::JavaScriptChild* GetCPOWManager() = 0;
 protected:
   virtual jsipc::PJavaScriptChild* AllocPJavaScriptChild();
   virtual bool DeallocPJavaScriptChild(jsipc::PJavaScriptChild*);
 
   virtual PBrowserChild* AllocPBrowserChild(const IPCTabContext& aContext,
                                             const uint32_t& aChromeFlags,
                                             const uint64_t& aID,
                                             const bool& aIsForApp,
--- a/dom/ipc/nsIContentParent.cpp
+++ b/dom/ipc/nsIContentParent.cpp
@@ -180,18 +180,17 @@ nsIContentParent::RecvSyncMessage(const 
         parent && principal && !AssertAppPrincipal(parent, principal)) {
       return false;
     }
   }
 
   nsRefPtr<nsFrameMessageManager> ppm = mMessageManager;
   if (ppm) {
     StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData);
-    CpowIdHolder cpows(GetCPOWManager(), aCpows);
-
+    CpowIdHolder cpows(this, aCpows);
     ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
                         aMsg, true, &cloneData, &cpows, aPrincipal, aRetvals);
   }
   return true;
 }
 
 bool
 nsIContentParent::AnswerRpcMessage(const nsString& aMsg,
@@ -208,17 +207,17 @@ nsIContentParent::AnswerRpcMessage(const
         parent && principal && !AssertAppPrincipal(parent, principal)) {
       return false;
     }
   }
 
   nsRefPtr<nsFrameMessageManager> ppm = mMessageManager;
   if (ppm) {
     StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData);
-    CpowIdHolder cpows(GetCPOWManager(), aCpows);
+    CpowIdHolder cpows(this, aCpows);
     ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
                         aMsg, true, &cloneData, &cpows, aPrincipal, aRetvals);
   }
   return true;
 }
 
 bool
 nsIContentParent::RecvAsyncMessage(const nsString& aMsg,
@@ -234,17 +233,17 @@ nsIContentParent::RecvAsyncMessage(const
         parent && principal && !AssertAppPrincipal(parent, principal)) {
       return false;
     }
   }
 
   nsRefPtr<nsFrameMessageManager> ppm = mMessageManager;
   if (ppm) {
     StructuredCloneData cloneData = ipc::UnpackClonedMessageDataForParent(aData);
-    CpowIdHolder cpows(GetCPOWManager(), aCpows);
+    CpowIdHolder cpows(this, aCpows);
     ppm->ReceiveMessage(static_cast<nsIContentFrameMessageManager*>(ppm.get()),
                         aMsg, false, &cloneData, &cpows, aPrincipal, nullptr);
   }
   return true;
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/ipc/nsIContentParent.h
+++ b/dom/ipc/nsIContentParent.h
@@ -4,47 +4,48 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_dom_nsIContentParent_h
 #define mozilla_dom_nsIContentParent_h
 
 #include "nsFrameMessageManager.h"
 #include "nsISupports.h"
+#include "mozilla/dom/CPOWManagerGetter.h"
 
 #define NS_ICONTENTPARENT_IID                                   \
   { 0xeeec9ebf, 0x8ecf, 0x4e38,                                 \
     { 0x81, 0xda, 0xb7, 0x34, 0x13, 0x7e, 0xac, 0xf3 } }
 
 class nsFrameMessageManager;
 class nsIDOMBlob;
 
 namespace IPC {
 class Principal;
 } // namespace IPC
 
 namespace mozilla {
 
 namespace jsipc {
 class PJavaScriptParent;
-class JavaScriptParent;
 class CpowEntry;
 } // namespace jsipc
 
 namespace dom {
 
 class BlobConstructorParams;
 class BlobParent;
 class ContentParent;
 class IPCTabContext;
 class PBlobParent;
 class PBrowserParent;
 
 class nsIContentParent : public nsISupports
                        , public mozilla::dom::ipc::MessageManagerCallback
+                       , public CPOWManagerGetter
 {
 public:
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_ICONTENTPARENT_IID)
 
   nsIContentParent();
 
   BlobParent* GetOrCreateActorForBlob(nsIDOMBlob* aBlob);
 
@@ -59,18 +60,16 @@ public:
   virtual PBrowserParent* SendPBrowserConstructor(
     PBrowserParent* actor,
     const IPCTabContext& context,
     const uint32_t& chromeFlags,
     const uint64_t& aId,
     const bool& aIsForApp,
     const bool& aIsForBrowser) NS_WARN_UNUSED_RESULT = 0;
 
-  virtual jsipc::JavaScriptParent *GetCPOWManager() = 0;
-
   virtual bool IsContentParent() { return false; }
   ContentParent* AsContentParent();
 
 protected: // methods
   bool CanOpenBrowser(const IPCTabContext& aContext);
 
 protected: // IPDL methods
   virtual mozilla::jsipc::PJavaScriptParent* AllocPJavaScriptParent();
--- a/dom/workers/WorkerPrivate.h
+++ b/dom/workers/WorkerPrivate.h
@@ -17,17 +17,17 @@
 #include "mozilla/dom/BindingDeclarations.h"
 #include "nsCycleCollectionParticipant.h"
 #include "nsDataHashtable.h"
 #include "nsHashKeys.h"
 #include "nsRefPtrHashtable.h"
 #include "nsString.h"
 #include "nsTArray.h"
 #include "nsThreadUtils.h"
-#include "StructuredCloneTags.h"
+#include "mozilla/dom/StructuredCloneTags.h"
 
 #include "Queue.h"
 #include "WorkerFeature.h"
 
 class JSAutoStructuredCloneBuffer;
 class nsIChannel;
 class nsIDocument;
 class nsIEventTarget;
--- a/dom/workers/test/fetch/mochitest.ini
+++ b/dom/workers/test/fetch/mochitest.ini
@@ -1,5 +1,7 @@
 [DEFAULT]
 support-files =
   worker_interfaces.js
+  worker_test_request.js
 
 [test_interfaces.html]
+[test_request.html]
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/fetch/test_request.html
@@ -0,0 +1,48 @@
+<!--
+  Any copyright is dedicated to the Public Domain.
+  http://creativecommons.org/publicdomain/zero/1.0/
+-->
+<!DOCTYPE HTML>
+<html>
+<head>
+  <title>Bug XXXXXX - Test Request object in worker</title>
+  <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="display: none"></div>
+<pre id="test"></pre>
+<script class="testbody" type="text/javascript">
+
+  function checkEnabled() {
+    var worker = new Worker("worker_test_request.js");
+    worker.onmessage = function(event) {
+
+      if (event.data.type == 'finish') {
+        SimpleTest.finish();
+      } else if (event.data.type == 'status') {
+        ok(event.data.status, event.data.msg);
+      }
+    }
+
+    worker.onerror = function(event) {
+      ok(false, "Worker had an error: " + event.message + " at " + event.lineno);
+      SimpleTest.finish();
+    };
+
+    worker.postMessage(true);
+  }
+
+  SimpleTest.waitForExplicitFinish();
+
+  SpecialPowers.pushPrefEnv({"set": [
+    ["dom.fetch.enabled", true]
+  ]}, function() {
+    checkEnabled();
+  });
+</script>
+</pre>
+</body>
+</html>
+
new file mode 100644
--- /dev/null
+++ b/dom/workers/test/fetch/worker_test_request.js
@@ -0,0 +1,215 @@
+function ok(a, msg) {
+  dump("OK: " + !!a + "  =>  " + a + " " + msg + "\n");
+  postMessage({type: 'status', status: !!a, msg: a + ": " + msg });
+}
+
+function is(a, b, msg) {
+  dump("IS: " + (a===b) + "  =>  " + a + " | " + b + " " + msg + "\n");
+  postMessage({type: 'status', status: a === b, msg: a + " === " + b + ": " + msg });
+}
+
+function testDefaultCtor() {
+  var req = new Request("");
+  is(req.method, "GET", "Default Request method is GET");
+  ok(req.headers instanceof Headers, "Request should have non-null Headers object");
+  is(req.url, self.location.href, "URL should be resolved with entry settings object's API base URL");
+  is(req.referrer, "", "Default referrer is `client` which serializes to empty string.");
+  is(req.mode, "cors", "Request mode for string input is cors");
+  is(req.credentials, "omit", "Default Request credentials is omit");
+
+  var req = new Request(req);
+  is(req.method, "GET", "Default Request method is GET");
+  ok(req.headers instanceof Headers, "Request should have non-null Headers object");
+  is(req.url, self.location.href, "URL should be resolved with entry settings object's API base URL");
+  is(req.referrer, "", "Default referrer is `client` which serializes to empty string.");
+  is(req.mode, "cors", "Request mode string input is cors");
+  is(req.credentials, "omit", "Default Request credentials is omit");
+}
+
+function testClone() {
+  var req = (new Request("./cloned_request.txt", {
+              method: 'POST',
+              headers: { "Content-Length": 5 },
+              body: "Sample body",
+              mode: "same-origin",
+              credentials: "same-origin",
+            })).clone();
+  ok(req.method === "POST", "Request method is POST");
+  ok(req.headers instanceof Headers, "Request should have non-null Headers object");
+  is(req.headers.get('content-length'), "5", "Request content-length should be 5.");
+  ok(req.url === (new URL("./cloned_request.txt", self.location.href)).href,
+       "URL should be resolved with entry settings object's API base URL");
+  ok(req.referrer === "", "Default referrer is `client` which serializes to empty string.");
+  ok(req.mode === "same-origin", "Request mode is same-origin");
+  ok(req.credentials === "same-origin", "Default credentials is same-origin");
+}
+
+function testUsedRequest() {
+  // Passing a used request should fail.
+  var req = new Request("", { body: "This is foo" });
+  var p1 = req.text().then(function(v) {
+    try {
+      var req2 = new Request(req);
+      ok(false, "Used Request cannot be passed to new Request");
+    } catch(e) {
+      ok(true, "Used Request cannot be passed to new Request");
+    }
+  });
+
+  // Passing a request should set the request as used.
+  var reqA = new Request("", { body: "This is foo" });
+  var reqB = new Request(reqA);
+  is(reqA.bodyUsed, true, "Passing a Request to another Request should set the former as used");
+  return p1;
+}
+
+function testSimpleUrlParse() {
+  // Just checks that the URL parser is actually being used.
+  var req = new Request("/file.html");
+  is(req.url, (new URL("/file.html", self.location.href)).href, "URL parser should be used to resolve Request URL");
+}
+
+function testMethod() {
+  var allowed = ["delete", "get", "head", "options", "post", "put"];
+  for (var i = 0; i < allowed.length; ++i) {
+    try {
+      var r = new Request("", { method: allowed[i] });
+      ok(true, "Method " + allowed[i] + " should be allowed");
+    } catch(e) {
+      ok(false, "Method " + allowed[i] + " should be allowed");
+    }
+  }
+
+  var forbidden = ["aardvark", "connect", "trace", "track"];
+  for (var i = 0; i < forbidden.length; ++i) {
+    try {
+      var r = new Request("", { method: forbidden[i] });
+      ok(false, "Method " + forbidden[i] + " should be forbidden");
+    } catch(e) {
+      ok(true, "Method " + forbidden[i] + " should be forbidden");
+    }
+  }
+
+  var allowedNoCors = ["get", "head", "post"];
+  for (var i = 0; i < allowedNoCors.length; ++i) {
+    try {
+      var r = new Request("", { method: allowedNoCors[i], mode: "no-cors" });
+      ok(true, "Method " + allowedNoCors[i] + " should be allowed in no-cors mode");
+    } catch(e) {
+      ok(false, "Method " + allowedNoCors[i] + " should be allowed in no-cors mode");
+    }
+  }
+
+  var forbiddenNoCors = ["aardvark", "delete", "options", "put"];
+  for (var i = 0; i < forbiddenNoCors.length; ++i) {
+    try {
+      var r = new Request("", { method: forbiddenNoCors[i], mode: "no-cors" });
+      ok(false, "Method " + forbiddenNoCors[i] + " should be forbidden in no-cors mode");
+    } catch(e) {
+      ok(true, "Method " + forbiddenNoCors[i] + " should be forbidden in no-cors mode");
+    }
+  }
+}
+
+function testUrlFragment() {
+  var req = new Request("./request#withfragment");
+  ok(req.url, (new URL("./request", self.location.href)).href, "request.url should be serialized with exclude fragment flag set");
+}
+
+function testBodyUsed() {
+  var req = new Request("./bodyused", { body: "Sample body" });
+  is(req.bodyUsed, false, "bodyUsed is initially false.");
+  return req.text().then((v) => {
+    is(v, "Sample body", "Body should match");
+    is(req.bodyUsed, true, "After reading body, bodyUsed should be true.");
+  }).then((v) => {
+    return req.blob().then((v) => {
+      ok(false, "Attempting to read body again should fail.");
+    }, (e) => {
+      ok(true, "Attempting to read body again should fail.");
+    })
+  });
+}
+
+// FIXME(nsm): Bug 1071290: We can't use Blobs as the body yet.
+function testBodyCreation() {
+  var text = "κόσμε";
+  var req1 = new Request("", { body: text });
+  var p1 = req1.text().then(function(v) {
+    ok(typeof v === "string", "Should resolve to string");
+    is(text, v, "Extracted string should match");
+  });
+
+  var req2 = new Request("", { body: new Uint8Array([72, 101, 108, 108, 111]) });
+  var p2 = req2.text().then(function(v) {
+    is("Hello", v, "Extracted string should match");
+  });
+
+  var req2b = new Request("", { body: (new Uint8Array([72, 101, 108, 108, 111])).buffer });
+  var p2b = req2b.text().then(function(v) {
+    is("Hello", v, "Extracted string should match");
+  });
+
+  var params = new URLSearchParams();
+  params.append("item", "Geckos");
+  params.append("feature", "stickyfeet");
+  params.append("quantity", "700");
+  var req3 = new Request("", { body: params });
+  var p3 = req3.text().then(function(v) {
+    var extracted = new URLSearchParams(v);
+    is(extracted.get("item"), "Geckos", "Param should match");
+    is(extracted.get("feature"), "stickyfeet", "Param should match");
+    is(extracted.get("quantity"), "700", "Param should match");
+  });
+
+  return Promise.all([p1, p2, p2b, p3]);
+}
+
+function testBodyExtraction() {
+  var text = "κόσμε";
+  var newReq = function() { return new Request("", { body: text }); }
+  return newReq().text().then(function(v) {
+    ok(typeof v === "string", "Should resolve to string");
+    is(text, v, "Extracted string should match");
+  }).then(function() {
+    return newReq().blob().then(function(v) {
+      ok(v instanceof Blob, "Should resolve to Blob");
+      var fs = new FileReaderSync();
+      is(fs.readAsText(v), text, "Decoded Blob should match original");
+    });
+  }).then(function() {
+    return newReq().json().then(function(v) {
+      ok(false, "Invalid json should reject");
+    }, function(e) {
+      ok(true, "Invalid json should reject");
+    })
+  }).then(function() {
+    return newReq().arrayBuffer().then(function(v) {
+      ok(v instanceof ArrayBuffer, "Should resolve to ArrayBuffer");
+      var dec = new TextDecoder();
+      is(dec.decode(new Uint8Array(v)), text, "UTF-8 decoded ArrayBuffer should match original");
+    });
+  })
+}
+
+onmessage = function() {
+  var done = function() { postMessage({ type: 'finish' }) }
+
+  testDefaultCtor();
+  testClone();
+  testSimpleUrlParse();
+  testUrlFragment();
+  testMethod();
+
+  Promise.resolve()
+    .then(testBodyCreation)
+    .then(testBodyUsed)
+    .then(testBodyExtraction)
+    .then(testUsedRequest)
+    // Put more promise based tests here.
+    .then(done)
+    .catch(function(e) {
+      ok(false, "Some Request tests failed " + e);
+      done();
+    })
+}
--- a/gfx/layers/Compositor.h
+++ b/gfx/layers/Compositor.h
@@ -8,16 +8,17 @@
 
 #include "Units.h"                      // for ScreenPoint
 #include "mozilla/Assertions.h"         // for MOZ_ASSERT, etc
 #include "mozilla/RefPtr.h"             // for TemporaryRef, RefCounted
 #include "mozilla/gfx/Point.h"          // for IntSize, Point
 #include "mozilla/gfx/Rect.h"           // for Rect, IntRect
 #include "mozilla/gfx/Types.h"          // for Float
 #include "mozilla/layers/CompositorTypes.h"  // for DiagnosticTypes, etc
+#include "mozilla/layers/FenceUtils.h"  // for FenceHandle
 #include "mozilla/layers/LayersTypes.h"  // for LayersBackend
 #include "nsISupportsImpl.h"            // for MOZ_COUNT_CTOR, etc
 #include "nsRegion.h"
 #include <vector>
 #include "mozilla/WidgetUtils.h"
 
 /**
  * Different elements of a web pages are rendered into separate "layers" before
@@ -348,16 +349,21 @@ public:
 
   /**
    * Flush the current frame to the screen and tidy up.
    */
   virtual void EndFrame() = 0;
 
   virtual void SetFBAcquireFence(Layer* aLayer) {}
 
+  virtual FenceHandle GetReleaseFence()
+  {
+    return FenceHandle();
+  }
+
   /**
    * Post-rendering stuff if the rendering is done outside of this Compositor
    * e.g., by Composer2D.
    * aTransform is the transform from user space to window space.
    */
   virtual void EndFrameForExternalComposition(const gfx::Matrix& aTransform) = 0;
 
   /**
--- a/gfx/layers/client/TextureClient.h
+++ b/gfx/layers/client/TextureClient.h
@@ -353,17 +353,17 @@ public:
    * If the texture flags contain TextureFlags::DEALLOCATE_CLIENT, the destruction
    * will be synchronously coordinated with the compositor side, otherwise it
    * will be done asynchronously.
    */
   void ForceRemove();
 
   virtual void SetReleaseFenceHandle(FenceHandle aReleaseFenceHandle)
   {
-    mReleaseFenceHandle = aReleaseFenceHandle;
+    mReleaseFenceHandle.Merge(aReleaseFenceHandle);
   }
 
   const FenceHandle& GetReleaseFenceHandle() const
   {
     return mReleaseFenceHandle;
   }
 
   virtual void SetAcquireFenceHandle(FenceHandle aAcquireFenceHandle)
--- a/gfx/layers/composite/TextureHost.cpp
+++ b/gfx/layers/composite/TextureHost.cpp
@@ -75,18 +75,16 @@ public:
 
   ~TextureParent();
 
   bool Init(const SurfaceDescriptor& aSharedData,
             const TextureFlags& aFlags);
 
   void CompositorRecycle();
 
-  void SendFenceHandleIfPresent();
-
   virtual bool RecvClientRecycle() MOZ_OVERRIDE;
 
   virtual bool RecvClearTextureHostSync() MOZ_OVERRIDE;
 
   virtual bool RecvRemoveTexture() MOZ_OVERRIDE;
 
   TextureHost* GetTextureHost() { return mTextureHost; }
 
@@ -142,24 +140,16 @@ TextureHost::AsTextureHost(PTextureParen
 }
 
 PTextureParent*
 TextureHost::GetIPDLActor()
 {
   return mActor;
 }
 
-// static
-void
-TextureHost::SendFenceHandleIfPresent(PTextureParent* actor)
-{
-  TextureParent* parent = static_cast<TextureParent*>(actor);
-  parent->SendFenceHandleIfPresent();
-}
-
 FenceHandle
 TextureHost::GetAndResetReleaseFenceHandle()
 {
 #if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
   TextureHostOGL* hostOGL = this->AsHostOGL();
   if (!hostOGL) {
     return FenceHandle();
   }
@@ -709,48 +699,25 @@ static void RecycleCallback(TextureHost*
   TextureParent* tp = reinterpret_cast<TextureParent*>(aClosure);
   tp->CompositorRecycle();
 }
 
 void
 TextureParent::CompositorRecycle()
 {
   mTextureHost->ClearRecycleCallback();
-  SendFenceHandleIfPresent();
 
   if (mTextureHost->GetFlags() & TextureFlags::RECYCLE) {
     mozilla::unused << SendCompositorRecycle();
     // Don't forget to prepare for the next reycle
     // if TextureClient request it.
     mWaitForClientRecycle = mTextureHost;
   }
 }
 
-void
-TextureParent::SendFenceHandleIfPresent()
-{
-#if defined(MOZ_WIDGET_GONK) && ANDROID_VERSION >= 17
-  if (mTextureHost) {
-    TextureHostOGL* hostOGL = mTextureHost->AsHostOGL();
-    if (!hostOGL) {
-      return;
-    }
-    android::sp<android::Fence> fence = hostOGL->GetAndResetReleaseFence();
-    if (fence.get() && fence->isValid()) {
-      // HWC might not provide Fence.
-      // In this case, HWC implicitly handles buffer's fence.
-
-      FenceHandle handle = FenceHandle(fence);
-      RefPtr<FenceDeliveryTracker> tracker = new FenceDeliveryTracker(handle);
-      mCompositableManager->SendFenceHandle(tracker, this, handle);
-    }
-  }
-#endif
-}
-
 bool
 TextureParent::RecvClientRecycle()
 {
   // This will allow the RecycleCallback to be called once the compositor
   // releases any external references to TextureHost.
   mTextureHost->SetRecycleCallback(RecycleCallback, this);
   if (!mWaitForClientRecycle) {
     RECYCLE_LOG("Not a recycable tile");
--- a/gfx/layers/composite/TextureHost.h
+++ b/gfx/layers/composite/TextureHost.h
@@ -416,18 +416,16 @@ public:
   /**
    * Return a pointer to the IPDLActor.
    *
    * This is to be used with IPDL messages only. Do not store the returned
    * pointer.
    */
   PTextureParent* GetIPDLActor();
 
-  static void SendFenceHandleIfPresent(PTextureParent* actor);
-
   FenceHandle GetAndResetReleaseFenceHandle();
 
   /**
    * Specific to B2G's Composer2D
    * XXX - more doc here
    */
   virtual LayerRenderState GetRenderState()
   {
--- a/gfx/layers/ipc/CompositableTransactionParent.cpp
+++ b/gfx/layers/ipc/CompositableTransactionParent.cpp
@@ -157,45 +157,46 @@ CompositableParentManager::ReceiveCompos
     case CompositableOperation::TOpRemoveTexture: {
       const OpRemoveTexture& op = aEdit.get_OpRemoveTexture();
       CompositableHost* compositable = AsCompositable(op);
       RefPtr<TextureHost> tex = TextureHost::AsTextureHost(op.textureParent());
 
       MOZ_ASSERT(tex.get());
       compositable->RemoveTextureHost(tex);
       // send FenceHandle if present.
-      TextureHost::SendFenceHandleIfPresent(op.textureParent());
+      SendFenceHandleIfPresent(op.textureParent(), compositable);
       break;
     }
     case CompositableOperation::TOpRemoveTextureAsync: {
       const OpRemoveTextureAsync& op = aEdit.get_OpRemoveTextureAsync();
       CompositableHost* compositable = AsCompositable(op);
       RefPtr<TextureHost> tex = TextureHost::AsTextureHost(op.textureParent());
 
       MOZ_ASSERT(tex.get());
       compositable->RemoveTextureHost(tex);
 
       if (!IsAsync() && GetChildProcessId()) {
         // send FenceHandle if present via ImageBridge.
         ImageBridgeParent::SendFenceHandleToTrackerIfPresent(
                              GetChildProcessId(),
                              op.holderId(),
                              op.transactionId(),
-                             op.textureParent());
+                             op.textureParent(),
+                             compositable);
 
         // If the message is recievied via PLayerTransaction,
         // Send message back via PImageBridge.
         ImageBridgeParent::ReplyRemoveTexture(
                              GetChildProcessId(),
                              OpReplyRemoveTexture(true, // isMain
                                                   op.holderId(),
                                                   op.transactionId()));
       } else {
         // send FenceHandle if present.
-        TextureHost::SendFenceHandleIfPresent(op.textureParent());
+        SendFenceHandleIfPresent(op.textureParent(), compositable);
 
         ReplyRemoveTexture(OpReplyRemoveTexture(false, // isMain
                                                 op.holderId(),
                                                 op.transactionId()));
       }
       break;
     }
     case CompositableOperation::TOpUseTexture: {
@@ -253,11 +254,47 @@ CompositableParentManager::ReceiveCompos
     default: {
       MOZ_ASSERT(false, "bad type");
     }
   }
 
   return true;
 }
 
+void
+CompositableParentManager::SendPendingAsyncMessges()
+{
+  if (mPendingAsyncMessage.empty()) {
+    return;
+  }
+
+  // Some type of AsyncParentMessageData message could have
+  // one file descriptor (e.g. OpDeliverFence).
+  // A number of file descriptors per gecko ipc message have a limitation
+  // on OS_POSIX (MACOSX or LINUX).
+#if defined(OS_POSIX)
+  static const uint32_t kMaxMessageNumber = FileDescriptorSet::MAX_DESCRIPTORS_PER_MESSAGE;
+#else
+  // default number that works everywhere else
+  static const uint32_t kMaxMessageNumber = 250;
+#endif
+
+  InfallibleTArray<AsyncParentMessageData> messages;
+  messages.SetCapacity(mPendingAsyncMessage.size());
+  for (size_t i = 0; i < mPendingAsyncMessage.size(); i++) {
+    messages.AppendElement(mPendingAsyncMessage[i]);
+    // Limit maximum number of messages.
+    if (messages.Length() >= kMaxMessageNumber) {
+      SendAsyncMessage(messages);
+      // Initialize Messages.
+      messages.Clear();
+    }
+  }
+
+  if (messages.Length() > 0) {
+    SendAsyncMessage(messages);
+  }
+  mPendingAsyncMessage.clear();
+}
+
 } // namespace
 } // namespace
 
--- a/gfx/layers/ipc/CompositableTransactionParent.h
+++ b/gfx/layers/ipc/CompositableTransactionParent.h
@@ -25,22 +25,27 @@ typedef std::vector<mozilla::layers::Edi
 // Since PCompositble has two potential manager protocols, we can't just call
 // the Manager() method usually generated when there's one manager protocol,
 // so both manager protocols implement this and we keep a reference to them
 // through this interface.
 class CompositableParentManager : public ISurfaceAllocator
                                 , public AsyncTransactionTrackersHolder
 {
 public:
+  virtual void SendFenceHandleIfPresent(PTextureParent* aTexture,
+                                        CompositableHost* aCompositableHost) = 0;
+
   virtual void SendFenceHandle(AsyncTransactionTracker* aTracker,
                                PTextureParent* aTexture,
                                const FenceHandle& aFence) = 0;
 
   virtual void SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage) = 0;
 
+  void SendPendingAsyncMessges();
+
   /**
    * Get child side's process Id.
    */
   virtual base::ProcessId GetChildProcessId() = 0;
 
 protected:
   /**
    * Handle the IPDL messages that affect PCompositable actors.
@@ -52,14 +57,15 @@ protected:
   /**
    * Return true if this protocol is asynchronous with respect to the content
    * thread (ImageBridge for instance).
    */
   virtual bool IsAsync() const { return false; }
 
   virtual void ReplyRemoveTexture(const OpReplyRemoveTexture& aReply) {}
 
+  std::vector<AsyncParentMessageData> mPendingAsyncMessage;
 };
 
 } // namespace
 } // namespace
 
 #endif
--- a/gfx/layers/ipc/FenceUtils.h
+++ b/gfx/layers/ipc/FenceUtils.h
@@ -21,16 +21,17 @@ namespace layers {
 
 struct FenceHandleFromChild;
 
 struct FenceHandle {
   FenceHandle() {}
   explicit FenceHandle(const FenceHandleFromChild& aFenceHandle) {}
   bool operator==(const FenceHandle&) const { return false; }
   bool IsValid() const { return false; }
+  void Merge(const FenceHandle& aFenceHandle) {}
 };
 
 struct FenceHandleFromChild {
   FenceHandleFromChild() {}
   explicit FenceHandleFromChild(const FenceHandle& aFence) {}
   bool operator==(const FenceHandle&) const { return false; }
   bool operator==(const FenceHandleFromChild&) const { return false; }
   bool IsValid() const { return false; }
--- a/gfx/layers/ipc/FenceUtilsGonk.cpp
+++ b/gfx/layers/ipc/FenceUtilsGonk.cpp
@@ -44,38 +44,45 @@ ParamTraits<FenceHandle>::Write(Message*
   // which returned by getFlattenedSize() and getFdCount() are not changed.
   // So we change nbytes and nfds back by call corresponding calls.
   nbytes = flattenable->getFlattenedSize();
   nfds = flattenable->getFdCount();
 #else
   flattenable->flatten(data, nbytes, fds, nfds);
 #endif
   aMsg->WriteSize(nbytes);
+  aMsg->WriteSize(nfds);
   aMsg->WriteBytes(data, nbytes);
   for (size_t n = 0; n < nfds; ++n) {
     // These buffers can't die in transit because they're created
     // synchonously and the parent-side buffer can only be dropped if
     // there's a crash.
     aMsg->WriteFileDescriptor(FileDescriptor(fds[n], false));
   }
 }
 
 bool
 ParamTraits<FenceHandle>::Read(const Message* aMsg,
                                void** aIter, paramType* aResult)
 {
   size_t nbytes;
+  size_t nfds;
   const char* data;
 
   if (!aMsg->ReadSize(aIter, &nbytes) ||
+      !aMsg->ReadSize(aIter, &nfds) ||
       !aMsg->ReadBytes(aIter, &data, nbytes)) {
     return false;
   }
 
-  size_t nfds = aMsg->num_fds();
+  // Check if nfds is correct.
+  // aMsg->num_fds() could include fds of another ParamTraits<>s.
+  if (nfds > aMsg->num_fds()) {
+    return false;
+  }
   int fds[nfds];
 
   for (size_t n = 0; n < nfds; ++n) {
     FileDescriptor fd;
     if (!aMsg->ReadFileDescriptor(aIter, &fd)) {
       return false;
     }
     // If the GraphicBuffer was shared cross-process, SCM_RIGHTS does
@@ -133,16 +140,17 @@ ParamTraits<FenceHandleFromChild>::Write
   // which returned by getFlattenedSize() and getFdCount() are not changed.
   // So we change nbytes and nfds back by call corresponding calls.
   nbytes = flattenable->getFlattenedSize();
   nfds = flattenable->getFdCount();
 #else
   flattenable->flatten(data, nbytes, fds, nfds);
 #endif
   aMsg->WriteSize(nbytes);
+  aMsg->WriteSize(nfds);
   aMsg->WriteBytes(data, nbytes);
   for (size_t n = 0; n < nfds; ++n) {
     // If the Fence was shared cross-process, SCM_RIGHTS does
     // the right thing and dup's the fd.  If it's shared cross-thread,
     // SCM_RIGHTS doesn't dup the fd.  That's surprising, but we just
     // deal with it here.  NB: only the "default" (master) process can
     // alloc gralloc buffers.
     bool sameProcess = (XRE_GetProcessType() == GeckoProcessType_Default);
@@ -156,24 +164,30 @@ ParamTraits<FenceHandleFromChild>::Write
   }
 }
 
 bool
 ParamTraits<FenceHandleFromChild>::Read(const Message* aMsg,
                                         void** aIter, paramType* aResult)
 {
   size_t nbytes;
+  size_t nfds;
   const char* data;
 
   if (!aMsg->ReadSize(aIter, &nbytes) ||
+      !aMsg->ReadSize(aIter, &nfds) ||
       !aMsg->ReadBytes(aIter, &data, nbytes)) {
     return false;
   }
 
-  size_t nfds = aMsg->num_fds();
+  // Check if nfds is correct.
+  // aMsg->num_fds() could include fds of another ParamTraits<>s.
+  if (nfds > aMsg->num_fds()) {
+    return false;
+  }
   int fds[nfds];
 
   for (size_t n = 0; n < nfds; ++n) {
     FileDescriptor fd;
     if (!aMsg->ReadFileDescriptor(aIter, &fd)) {
       return false;
     }
     fds[n] = fd.fd;
@@ -206,15 +220,39 @@ FenceHandle::FenceHandle(const sp<Fence>
   : mFence(aFence)
 {
 }
 
 FenceHandle::FenceHandle(const FenceHandleFromChild& aFenceHandle) {
   mFence = aFenceHandle.mFence;
 }
 
+void
+FenceHandle::Merge(const FenceHandle& aFenceHandle)
+{
+  if (!aFenceHandle.IsValid()) {
+    return;
+  }
+
+  if (!IsValid()) {
+    mFence = aFenceHandle.mFence;
+  } else {
+    android::sp<android::Fence> mergedFence = android::Fence::merge(
+                  android::String8::format("FenceHandle"),
+                  mFence, aFenceHandle.mFence);
+    if (!mergedFence.get()) {
+      // synchronization is broken, the best we can do is hope fences
+      // signal in order so the new fence will act like a union.
+      // This error handling is same as android::ConsumerBase does.
+      mFence = aFenceHandle.mFence;
+      return;
+    }
+    mFence = mergedFence;
+  }
+}
+
 FenceHandleFromChild::FenceHandleFromChild(const sp<Fence>& aFence)
   : mFence(aFence)
 {
 }
 
 } // namespace layers
 } // namespace mozilla
--- a/gfx/layers/ipc/FenceUtilsGonk.h
+++ b/gfx/layers/ipc/FenceUtilsGonk.h
@@ -18,40 +18,42 @@ namespace layers {
 
 struct FenceHandleFromChild;
 
 struct FenceHandle {
   typedef android::Fence Fence;
 
   FenceHandle()
   { }
-  FenceHandle(const android::sp<Fence>& aFence);
+  explicit FenceHandle(const android::sp<Fence>& aFence);
 
-  FenceHandle(const FenceHandleFromChild& aFenceHandle);
+  explicit FenceHandle(const FenceHandleFromChild& aFenceHandle);
 
   bool operator==(const FenceHandle& aOther) const {
     return mFence.get() == aOther.mFence.get();
   }
 
   bool IsValid() const
   {
     return mFence.get() && mFence->isValid();
   }
 
+  void Merge(const FenceHandle& aFenceHandle);
+
   android::sp<Fence> mFence;
 };
 
 struct FenceHandleFromChild {
   typedef android::Fence Fence;
 
   FenceHandleFromChild()
   { }
-  FenceHandleFromChild(const android::sp<Fence>& aFence);
+  explicit FenceHandleFromChild(const android::sp<Fence>& aFence);
 
-  FenceHandleFromChild(const FenceHandle& aFence) {
+  explicit FenceHandleFromChild(const FenceHandle& aFence) {
     mFence = aFence.mFence;
   }
 
   bool operator==(const FenceHandle& aOther) const {
     return mFence.get() == aOther.mFence.get();
   }
 
   bool operator==(const FenceHandleFromChild& aOther) const {
--- a/gfx/layers/ipc/ImageBridgeParent.cpp
+++ b/gfx/layers/ipc/ImageBridgeParent.cpp
@@ -91,19 +91,35 @@ ImageBridgeParent::GetCompositorBackendT
 void
 ImageBridgeParent::ActorDestroy(ActorDestroyReason aWhy)
 {
   MessageLoop::current()->PostTask(
     FROM_HERE,
     NewRunnableMethod(this, &ImageBridgeParent::DeferredDestroy));
 }
 
+class MOZ_STACK_CLASS AutoImageBridgeParentAsyncMessageSender
+{
+public:
+  explicit AutoImageBridgeParentAsyncMessageSender(ImageBridgeParent* aImageBridge)
+    : mImageBridge(aImageBridge) {}
+
+  ~AutoImageBridgeParentAsyncMessageSender()
+  {
+    mImageBridge->SendPendingAsyncMessges();
+  }
+private:
+  ImageBridgeParent* mImageBridge;
+};
+
 bool
 ImageBridgeParent::RecvUpdate(const EditArray& aEdits, EditReplyArray* aReply)
 {
+  AutoImageBridgeParentAsyncMessageSender autoAsyncMessageSender(this);
+
   // If we don't actually have a compositor, then don't bother
   // creating any textures.
   if (Compositor::GetBackend() == LayersBackend::LAYERS_NONE) {
     return true;
   }
 
   EditReplyVector replyv;
   for (EditArray::index_type i = 0; i < aEdits.Length(); ++i) {
@@ -331,66 +347,121 @@ ImageBridgeParent::CloneToplevel(const I
 bool ImageBridgeParent::IsSameProcess() const
 {
   return OtherProcess() == ipc::kInvalidProcessHandle;
 }
 
 void
 ImageBridgeParent::ReplyRemoveTexture(const OpReplyRemoveTexture& aReply)
 {
-  InfallibleTArray<AsyncParentMessageData> messages;
-  messages.AppendElement(aReply);
-  mozilla::unused << SendParentAsyncMessages(messages);
+  mPendingAsyncMessage.push_back(aReply);
 }
 
 /*static*/ void
 ImageBridgeParent::ReplyRemoveTexture(base::ProcessId aChildProcessId,
                                       const OpReplyRemoveTexture& aReply)
 {
   ImageBridgeParent* imageBridge = ImageBridgeParent::GetInstance(aChildProcessId);
   if (!imageBridge) {
     return;
   }
   imageBridge->ReplyRemoveTexture(aReply);
 }
 
-/*static*/ void
-ImageBridgeParent::SendFenceHandleToTrackerIfPresent(uint64_t aDestHolderId,
-                                                     uint64_t aTransactionId,
-                                                     PTextureParent* aTexture)
+void
+ImageBridgeParent::SendFenceHandleIfPresent(PTextureParent* aTexture,
+                                            CompositableHost* aCompositableHost)
 {
   RefPtr<TextureHost> texture = TextureHost::AsTextureHost(aTexture);
   if (!texture) {
     return;
   }
+
+  // Send a ReleaseFence of CompositorOGL.
+  if (aCompositableHost && aCompositableHost->GetCompositor()) {
+    FenceHandle fence = aCompositableHost->GetCompositor()->GetReleaseFence();
+    if (fence.IsValid()) {
+      RefPtr<FenceDeliveryTracker> tracker = new FenceDeliveryTracker(fence);
+      HoldUntilComplete(tracker);
+      mPendingAsyncMessage.push_back(OpDeliverFence(tracker->GetId(),
+                                                    aTexture, nullptr,
+                                                    fence));
+    }
+  }
+
+  // Send a ReleaseFence that is set by HwcComposer2D.
   FenceHandle fence = texture->GetAndResetReleaseFenceHandle();
-  if (!fence.IsValid()) {
+  if (fence.IsValid()) {
+    RefPtr<FenceDeliveryTracker> tracker = new FenceDeliveryTracker(fence);
+    HoldUntilComplete(tracker);
+    mPendingAsyncMessage.push_back(OpDeliverFence(tracker->GetId(),
+                                                  aTexture, nullptr,
+                                                  fence));
+  }
+}
+
+void
+ImageBridgeParent::SendFenceHandleToTrackerIfPresent(uint64_t aDestHolderId,
+                                                     uint64_t aTransactionId,
+                                                     PTextureParent* aTexture,
+                                                     CompositableHost* aCompositableHost)
+{
+  RefPtr<TextureHost> texture = TextureHost::AsTextureHost(aTexture);
+  if (!texture) {
     return;
   }
 
-  RefPtr<FenceDeliveryTracker> tracker = new FenceDeliveryTracker(fence);
-  HoldUntilComplete(tracker);
-  InfallibleTArray<AsyncParentMessageData> messages;
-  messages.AppendElement(OpDeliverFenceToTracker(tracker->GetId(),
-                                                 aDestHolderId,
-                                                 aTransactionId,
-                                                 fence));
-  mozilla::unused << SendParentAsyncMessages(messages);
+  // Send a ReleaseFence of CompositorOGL.
+  if (aCompositableHost && aCompositableHost->GetCompositor()) {
+    FenceHandle fence = aCompositableHost->GetCompositor()->GetReleaseFence();
+    if (fence.IsValid()) {
+      RefPtr<FenceDeliveryTracker> tracker = new FenceDeliveryTracker(fence);
+      HoldUntilComplete(tracker);
+      mPendingAsyncMessage.push_back(OpDeliverFenceToTracker(tracker->GetId(),
+                                                             aDestHolderId,
+                                                             aTransactionId,
+                                                             fence));
+    }
+  }
+
+  // Send a ReleaseFence that is set by HwcComposer2D.
+  FenceHandle fence = texture->GetAndResetReleaseFenceHandle();
+  if (fence.IsValid()) {
+    RefPtr<FenceDeliveryTracker> tracker = new FenceDeliveryTracker(fence);
+    HoldUntilComplete(tracker);
+    mPendingAsyncMessage.push_back(OpDeliverFenceToTracker(tracker->GetId(),
+                                                           aDestHolderId,
+                                                           aTransactionId,
+                                                           fence));
+  }
 }
 
 /*static*/ void
 ImageBridgeParent::SendFenceHandleToTrackerIfPresent(base::ProcessId aChildProcessId,
                                                      uint64_t aDestHolderId,
                                                      uint64_t aTransactionId,
-                                                     PTextureParent* aTexture)
+                                                     PTextureParent* aTexture,
+                                                     CompositableHost* aCompositableHost)
 {
   ImageBridgeParent* imageBridge = ImageBridgeParent::GetInstance(aChildProcessId);
   if (!imageBridge) {
     return;
   }
   imageBridge->SendFenceHandleToTrackerIfPresent(aDestHolderId,
                                                  aTransactionId,
-                                                 aTexture);
+                                                 aTexture,
+                                                 aCompositableHost);
 }
 
+/*static*/ void
+ImageBridgeParent::SendPendingAsyncMessges(base::ProcessId aChildProcessId)
+{
+#ifdef MOZ_WIDGET_GONK
+  ImageBridgeParent* imageBridge = ImageBridgeParent::GetInstance(aChildProcessId);
+  if (!imageBridge) {
+    return;
+  }
+  imageBridge->SendPendingAsyncMessges();
+#endif
+}
 
 } // layers
 } // mozilla
--- a/gfx/layers/ipc/ImageBridgeParent.h
+++ b/gfx/layers/ipc/ImageBridgeParent.h
@@ -51,16 +51,19 @@ public:
   virtual LayersBackend GetCompositorBackendType() const MOZ_OVERRIDE;
 
   virtual void ActorDestroy(ActorDestroyReason aWhy) MOZ_OVERRIDE;
 
   static PImageBridgeParent*
   Create(Transport* aTransport, ProcessId aChildProcessId);
 
   // CompositableParentManager
+  virtual void SendFenceHandleIfPresent(PTextureParent* aTexture,
+                                        CompositableHost* aCompositableHost) MOZ_OVERRIDE;
+
   virtual void SendFenceHandle(AsyncTransactionTracker* aTracker,
                                PTextureParent* aTexture,
                                const FenceHandle& aFence) MOZ_OVERRIDE;
 
   virtual void SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage) MOZ_OVERRIDE;
 
   virtual base::ProcessId GetChildProcessId() MOZ_OVERRIDE
   {
@@ -117,22 +120,27 @@ public:
 
   virtual void ReplyRemoveTexture(const OpReplyRemoveTexture& aReply) MOZ_OVERRIDE;
 
   static void ReplyRemoveTexture(base::ProcessId aChildProcessId,
                                  const OpReplyRemoveTexture& aReply);
 
   void SendFenceHandleToTrackerIfPresent(uint64_t aDestHolderId,
                                          uint64_t aTransactionId,
-                                         PTextureParent* aTexture);
+                                         PTextureParent* aTexture,
+                                         CompositableHost* aCompositableHost);
 
   static void SendFenceHandleToTrackerIfPresent(base::ProcessId aChildProcessId,
                                                 uint64_t aDestHolderId,
                                                 uint64_t aTransactionId,
-                                                PTextureParent* aTexture);
+                                                PTextureParent* aTexture,
+                                                CompositableHost* aCompositableHost);
+
+  using CompositableParentManager::SendPendingAsyncMessges;
+  static void SendPendingAsyncMessges(base::ProcessId aChildProcessId);
 
   static ImageBridgeParent* GetInstance(ProcessId aId);
 
   // Overriden from IToplevelProtocol
   IToplevelProtocol*
   CloneToplevel(const InfallibleTArray<ProtocolFdMapping>& aFds,
                 base::ProcessHandle aPeerProcess,
                 mozilla::ipc::ProtocolCloneContext* aCtx) MOZ_OVERRIDE;
--- a/gfx/layers/ipc/LayerTransactionParent.cpp
+++ b/gfx/layers/ipc/LayerTransactionParent.cpp
@@ -13,16 +13,17 @@
 #include "ShadowLayerParent.h"          // for ShadowLayerParent
 #include "CompositableTransactionParent.h"  // for EditReplyVector
 #include "ShadowLayersManager.h"        // for ShadowLayersManager
 #include "mozilla/gfx/BasePoint3D.h"    // for BasePoint3D
 #include "mozilla/layers/CanvasLayerComposite.h"
 #include "mozilla/layers/ColorLayerComposite.h"
 #include "mozilla/layers/Compositor.h"  // for Compositor
 #include "mozilla/layers/ContainerLayerComposite.h"
+#include "mozilla/layers/ImageBridgeParent.h" // for ImageBridgeParent
 #include "mozilla/layers/ImageLayerComposite.h"
 #include "mozilla/layers/LayerManagerComposite.h"
 #include "mozilla/layers/LayersMessages.h"  // for EditReply, etc
 #include "mozilla/layers/LayersSurfaces.h"  // for PGrallocBufferParent
 #include "mozilla/layers/LayersTypes.h"  // for MOZ_LAYERS_LOG
 #include "mozilla/layers/PCompositableParent.h"
 #include "mozilla/layers/PLayerParent.h"  // for PLayerParent
 #include "mozilla/layers/TextureHostOGL.h"  // for TextureHostOGL
@@ -187,16 +188,31 @@ LayerTransactionParent::RecvUpdateNoSwap
                                          const bool& isRepeatTransaction,
                                          const mozilla::TimeStamp& aTransactionStart)
 {
   return RecvUpdate(cset, aTransactionId, targetConfig, isFirstPaint,
       scheduleComposite, paintSequenceNumber, isRepeatTransaction,
       aTransactionStart, nullptr);
 }
 
+class MOZ_STACK_CLASS AutoLayerTransactionParentAsyncMessageSender
+{
+public:
+  explicit AutoLayerTransactionParentAsyncMessageSender(LayerTransactionParent* aLayerTransaction)
+    : mLayerTransaction(aLayerTransaction) {}
+
+  ~AutoLayerTransactionParentAsyncMessageSender()
+  {
+    mLayerTransaction->SendPendingAsyncMessges();
+    ImageBridgeParent::SendPendingAsyncMessges(mLayerTransaction->GetChildProcessId());
+  }
+private:
+  LayerTransactionParent* mLayerTransaction;
+};
+
 bool
 LayerTransactionParent::RecvUpdate(const InfallibleTArray<Edit>& cset,
                                    const uint64_t& aTransactionId,
                                    const TargetConfig& targetConfig,
                                    const bool& isFirstPaint,
                                    const bool& scheduleComposite,
                                    const uint32_t& paintSequenceNumber,
                                    const bool& isRepeatTransaction,
@@ -218,16 +234,17 @@ LayerTransactionParent::RecvUpdate(const
   }
 
   if (mLayerManager && mLayerManager->GetCompositor() &&
       !targetConfig.naturalBounds().IsEmpty()) {
     mLayerManager->GetCompositor()->SetScreenRotation(targetConfig.rotation());
   }
 
   EditReplyVector replyv;
+  AutoLayerTransactionParentAsyncMessageSender autoAsyncMessageSender(this);
 
   {
     AutoResolveRefLayers resolve(mShadowLayersManager->GetCompositionManager(this));
     layer_manager()->BeginTransaction();
   }
 
   for (EditArray::index_type i = 0; i < cset.Length(); ++i) {
     const Edit& edit = cset[i];
@@ -886,16 +903,48 @@ LayerTransactionParent::ActorDestroy(Act
 }
 
 bool LayerTransactionParent::IsSameProcess() const
 {
   return OtherProcess() == ipc::kInvalidProcessHandle;
 }
 
 void
+LayerTransactionParent::SendFenceHandleIfPresent(PTextureParent* aTexture,
+                                                 CompositableHost* aCompositableHost)
+{
+  RefPtr<TextureHost> texture = TextureHost::AsTextureHost(aTexture);
+  if (!texture) {
+    return;
+  }
+
+  // Send a ReleaseFence of CompositorOGL.
+  if (aCompositableHost && aCompositableHost->GetCompositor()) {
+    FenceHandle fence = aCompositableHost->GetCompositor()->GetReleaseFence();
+    if (fence.IsValid()) {
+      RefPtr<FenceDeliveryTracker> tracker = new FenceDeliveryTracker(fence);
+      HoldUntilComplete(tracker);
+      mPendingAsyncMessage.push_back(OpDeliverFence(tracker->GetId(),
+                                                    aTexture, nullptr,
+                                                    fence));
+    }
+  }
+
+  // Send a ReleaseFence that is set by HwcComposer2D.
+  FenceHandle fence = texture->GetAndResetReleaseFenceHandle();
+  if (fence.IsValid()) {
+    RefPtr<FenceDeliveryTracker> tracker = new FenceDeliveryTracker(fence);
+    HoldUntilComplete(tracker);
+    mPendingAsyncMessage.push_back(OpDeliverFence(tracker->GetId(),
+                                                  aTexture, nullptr,
+                                                  fence));
+  }
+}
+
+void
 LayerTransactionParent::SendFenceHandle(AsyncTransactionTracker* aTracker,
                                         PTextureParent* aTexture,
                                         const FenceHandle& aFence)
 {
   HoldUntilComplete(aTracker);
   InfallibleTArray<AsyncParentMessageData> messages;
   messages.AppendElement(OpDeliverFence(aTracker->GetId(),
                                         aTexture, nullptr,
--- a/gfx/layers/ipc/LayerTransactionParent.h
+++ b/gfx/layers/ipc/LayerTransactionParent.h
@@ -81,16 +81,19 @@ public:
   virtual LayersBackend GetCompositorBackendType() const MOZ_OVERRIDE;
 
   virtual bool IsSameProcess() const MOZ_OVERRIDE;
 
   const uint64_t& GetPendingTransactionId() { return mPendingTransaction; }
   void SetPendingTransactionId(uint64_t aId) { mPendingTransaction = aId; }
 
   // CompositableParentManager
+  virtual void SendFenceHandleIfPresent(PTextureParent* aTexture,
+                                        CompositableHost* aCompositableHost) MOZ_OVERRIDE;
+
   virtual void SendFenceHandle(AsyncTransactionTracker* aTracker,
                                PTextureParent* aTexture,
                                const FenceHandle& aFence) MOZ_OVERRIDE;
 
   virtual void SendAsyncMessage(const InfallibleTArray<AsyncParentMessageData>& aMessage) MOZ_OVERRIDE;
 
   virtual base::ProcessId GetChildProcessId() MOZ_OVERRIDE
   {
--- a/gfx/layers/opengl/CompositorOGL.cpp
+++ b/gfx/layers/opengl/CompositorOGL.cpp
@@ -1393,59 +1393,43 @@ CompositorOGL::SetFBAcquireFence(Layer* 
   // FBAcquireFence is FramebufferSurface's AcquireFence.
   // AcquireFence will be signaled when a buffer's content is available.
   // See Bug 974152.
 
   if (!aLayer) {
     return;
   }
 
-  const nsIntRegion& visibleRegion = aLayer->GetEffectiveVisibleRegion();
-  if (visibleRegion.IsEmpty()) {
-      return;
+  android::sp<android::Fence> fence = new android::Fence(GetGonkDisplay()->GetPrevFBAcquireFd());
+  if (fence.get() && fence->isValid()) {
+    FenceHandle handle = FenceHandle(fence);
+    mReleaseFenceHandle.Merge(handle);
   }
-
-  // Set FBAcquireFence on ContainerLayer's childs
-  ContainerLayer* container = aLayer->AsContainerLayer();
-  if (container) {
-    for (Layer* child = container->GetFirstChild(); child; child = child->GetNextSibling()) {
-      SetFBAcquireFence(child);
-    }
-    return;
-  }
+}
 
-  // Set FBAcquireFence as tiles' ReleaseFence on TiledLayerComposer.
-  TiledLayerComposer* composer = nullptr;
-  LayerComposite* shadow = aLayer->AsLayerComposite();
-  // Only ask for the composer if we have a compositable host. Timing
-  // may make it so that we don't - see bug 1000634.
-  if (shadow && shadow->GetCompositableHost()) {
-    composer = shadow->GetTiledLayerComposer();
-    if (composer) {
-      composer->SetReleaseFence(new android::Fence(GetGonkDisplay()->GetPrevFBAcquireFd()));
-      return;
-    }
+FenceHandle
+CompositorOGL::GetReleaseFence()
+{
+  if (!mReleaseFenceHandle.IsValid()) {
+    return FenceHandle();
   }
+  return FenceHandle(new android::Fence(mReleaseFenceHandle.mFence->dup()));
+}
 
-  // Set FBAcquireFence as layer buffer's ReleaseFence
-  LayerRenderState state = aLayer->GetRenderState();
-  if (!state.mTexture) {
-    return;
-  }
-  TextureHostOGL* texture = state.mTexture->AsHostOGL();
-  if (!texture) {
-    return;
-  }
-  texture->SetReleaseFence(new android::Fence(GetGonkDisplay()->GetPrevFBAcquireFd()));
-}
 #else
 void
 CompositorOGL::SetFBAcquireFence(Layer* aLayer)
 {
 }
+
+FenceHandle
+CompositorOGL::GetReleaseFence()
+{
+  return FenceHandle();
+}
 #endif
 
 void
 CompositorOGL::EndFrameForExternalComposition(const gfx::Matrix& aTransform)
 {
   // This lets us reftest and screenshot content rendered externally
   if (mTarget) {
     MakeCurrent();
--- a/gfx/layers/opengl/CompositorOGL.h
+++ b/gfx/layers/opengl/CompositorOGL.h
@@ -204,16 +204,17 @@ public:
   virtual void DrawQuad(const gfx::Rect& aRect,
                         const gfx::Rect& aClipRect,
                         const EffectChain &aEffectChain,
                         gfx::Float aOpacity,
                         const gfx::Matrix4x4 &aTransform) MOZ_OVERRIDE;
 
   virtual void EndFrame() MOZ_OVERRIDE;
   virtual void SetFBAcquireFence(Layer* aLayer) MOZ_OVERRIDE;
+  virtual FenceHandle GetReleaseFence() MOZ_OVERRIDE;
   virtual void EndFrameForExternalComposition(const gfx::Matrix& aTransform) MOZ_OVERRIDE;
   virtual void AbortFrame() MOZ_OVERRIDE;
 
   virtual bool SupportsPartialTextureUpdate() MOZ_OVERRIDE;
 
   virtual bool CanUseCanvasLayerForSize(const gfx::IntSize &aSize) MOZ_OVERRIDE
   {
     if (!mGLContext)
@@ -388,14 +389,16 @@ private:
 
   bool mDestroyed;
 
   /**
    * Height of the OpenGL context's primary framebuffer in pixels. Used by
    * FlipY for the y-flipping calculation.
    */
   GLint mHeight;
+
+  FenceHandle mReleaseFenceHandle;
 };
 
 }
 }
 
 #endif /* MOZILLA_GFX_COMPOSITOROGL_H */
--- a/js/ipc/JavaScriptShared.cpp
+++ b/js/ipc/JavaScriptShared.cpp
@@ -2,16 +2,17 @@
  * vim: set ts=4 sw=4 et tw=80:
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "JavaScriptShared.h"
 #include "mozilla/dom/BindingUtils.h"
+#include "mozilla/dom/CPOWManagerGetter.h"
 #include "mozilla/dom/TabChild.h"
 #include "jsfriendapi.h"
 #include "xpcprivate.h"
 #include "WrapperFactory.h"
 #include "mozilla/Preferences.h"
 
 using namespace js;
 using namespace JS;
@@ -510,19 +511,31 @@ JavaScriptShared::toDescriptor(JSContext
             out.setSetter(JS_StrictPropertyStub);
         else
             out.setSetter(UnknownStrictPropertyStub);
     }
 
     return true;
 }
 
+CpowIdHolder::CpowIdHolder(dom::CPOWManagerGetter *managerGetter, const InfallibleTArray<CpowEntry> &cpows)
+  : js_(nullptr),
+    cpows_(cpows)
+{
+    // Only instantiate the CPOW manager if we might need it later.
+    if (cpows.Length())
+        js_ = managerGetter->GetCPOWManager();
+}
+
 bool
 CpowIdHolder::ToObject(JSContext *cx, JS::MutableHandleObject objp)
 {
+    if (!cpows_.Length())
+        return true;
+
     return js_->Unwrap(cx, cpows_, objp);
 }
 
 bool
 JavaScriptShared::Unwrap(JSContext *cx, const InfallibleTArray<CpowEntry> &aCpows,
                          JS::MutableHandleObject objp)
 {
     objp.set(nullptr);
--- a/js/ipc/JavaScriptShared.h
+++ b/js/ipc/JavaScriptShared.h
@@ -9,16 +9,21 @@
 #define mozilla_jsipc_JavaScriptShared_h__
 
 #include "mozilla/dom/DOMTypes.h"
 #include "mozilla/jsipc/PJavaScript.h"
 #include "nsJSUtils.h"
 #include "nsFrameMessageManager.h"
 
 namespace mozilla {
+
+namespace dom {
+class CPOWManagerGetter;
+}
+
 namespace jsipc {
 
 class ObjectId {
   public:
     // Use 47 bits at most, to be safe, since jsval privates are encoded as
     // doubles. See bug 1065811 comment 12 for an explanation.
     static const size_t SERIAL_NUMBER_BITS = 47;
     static const size_t FLAG_BITS = 1;
@@ -58,21 +63,17 @@ class ObjectId {
     bool hasXrayWaiver_ : 1;
 };
 
 class JavaScriptShared;
 
 class CpowIdHolder : public CpowHolder
 {
   public:
-    CpowIdHolder(JavaScriptShared *js, const InfallibleTArray<CpowEntry> &cpows)
-      : js_(js),
-        cpows_(cpows)
-    {
-    }
+    CpowIdHolder(dom::CPOWManagerGetter *managerGetter, const InfallibleTArray<CpowEntry> &cpows);
 
     bool ToObject(JSContext *cx, JS::MutableHandleObject objp);
 
   private:
     JavaScriptShared *js_;
     const InfallibleTArray<CpowEntry> &cpows_;
 };
 
--- a/layout/tools/reftest/remotereftest.py
+++ b/layout/tools/reftest/remotereftest.py
@@ -157,20 +157,16 @@ class RemoteOptions(ReftestOptions):
             f.close()
 
         # httpd-path is specified by standard makefile targets and may be specified
         # on the command line to select a particular version of httpd.js. If not
         # specified, try to select the one from hostutils.zip, as required in bug 882932.
         if not options.httpdPath:
             options.httpdPath = os.path.join(options.utilityPath, "components")
 
-        # Android does not run leak tests, but set some reasonable defaults to avoid errors.
-        options.leakThresholds = {}
-        options.ignoreMissingLeaks = []
-
         # TODO: Copied from main, but I think these are no longer used in a post xulrunner world
         #options.xrePath = options.remoteTestRoot + self.automation._product + '/xulrunner'
         #options.utilityPath = options.testRoot + self.automation._product + '/bin'
         return options
 
 class ReftestServer:
     """ Web server used to serve Reftests, for closer fidelity to the real web.
         It is virtually identical to the server used in mochitest and will only
--- a/layout/tools/reftest/runreftest.py
+++ b/layout/tools/reftest/runreftest.py
@@ -339,17 +339,17 @@ class RefTest(object):
                                  cmdlineArgs,
                                  utilityPath = options.utilityPath,
                                  xrePath=options.xrePath,
                                  debuggerInfo=debuggerInfo,
                                  symbolsPath=options.symbolsPath,
                                  # give the JS harness 30 seconds to deal
                                  # with its own timeouts
                                  timeout=options.timeout + 30.0)
-      processLeakLog(self.leakLogFile, options.leakThresholds, options.ignoreMissingLeaks)
+      processLeakLog(self.leakLogFile, options)
       self.automation.log.info("\nREFTEST INFO | runreftest.py | Running tests: end.")
     finally:
       self.cleanup(profileDir)
     return status
 
   def copyExtraFilesToProfile(self, options, profile):
     "Copy extra files or dirs specified on the command line to the testing profile."
     profileDir = profile.profile
@@ -507,17 +507,16 @@ class ReftestOptions(OptionParser):
       if options.totalChunks is not None and options.thisChunk is None:
         self.error("cannot specify thisChunk or totalChunks with parallel tests")
       if options.focusFilterMode != "all":
         self.error("cannot specify focusFilterMode with parallel tests")
       if options.debugger is not None:
         self.error("cannot specify a debugger with parallel tests")
 
     options.leakThresholds = {"default": options.defaultLeakThreshold}
-    options.ignoreMissingLeaks = []
 
     return options
 
 def main():
   automation = Automation()
   parser = ReftestOptions(automation)
   reftest = RefTest(automation)
 
--- a/layout/tools/reftest/runreftestb2g.py
+++ b/layout/tools/reftest/runreftestb2g.py
@@ -198,20 +198,16 @@ class B2GOptions(ReftestOptions):
             f.close()
 
         # httpd-path is specified by standard makefile targets and may be specified
         # on the command line to select a particular version of httpd.js. If not
         # specified, try to select the one from from the xre bundle, as required in bug 882932.
         if not options.httpdPath:
             options.httpdPath = os.path.join(options.xrePath, "components")
 
-        # B2G reftests do not do leak checking, but set some reasonable defaults to avoid errors.
-        options.leakThresholds = {}
-        options.ignoreMissingLeaks = []
-
         return options
 
 
 class ProfileConfigParser(ConfigParser.RawConfigParser):
     """Subclass of RawConfigParser that outputs .ini files in the exact
        format expected for profiles.ini, which is slightly different
        than the default format.
     """
new file mode 100644
--- /dev/null
+++ b/mozglue/linker/BaseElf.cpp
@@ -0,0 +1,55 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "BaseElf.h"
+#include "Elfxx.h"
+#include "Logging.h"
+
+using namespace Elf;
+
+unsigned long
+BaseElf::Hash(const char *symbol)
+{
+  const unsigned char *sym = reinterpret_cast<const unsigned char *>(symbol);
+  unsigned long h = 0, g;
+  while (*sym) {
+    h = (h << 4) + *sym++;
+    g = h & 0xf0000000;
+    h ^= g;
+    h ^= g >> 24;
+  }
+  return h;
+}
+
+void *
+BaseElf::GetSymbolPtr(const char *symbol, unsigned long hash) const
+{
+  const Sym *sym = GetSymbol(symbol, hash);
+  void *ptr = nullptr;
+  if (sym && sym->st_shndx != SHN_UNDEF)
+    ptr = GetPtr(sym->st_value);
+  DEBUG_LOG("BaseElf::GetSymbolPtr(%p [\"%s\"], \"%s\") = %p",
+            reinterpret_cast<const void *>(this), GetPath(), symbol, ptr);
+  return ptr;
+}
+
+const Sym *
+BaseElf::GetSymbol(const char *symbol, unsigned long hash) const
+{
+  /* Search symbol with the buckets and chains tables.
+   * The hash computed from the symbol name gives an index in the buckets
+   * table. The corresponding value in the bucket table is an index in the
+   * symbols table and in the chains table.
+   * If the corresponding symbol in the symbols table matches, we're done.
+   * Otherwise, the corresponding value in the chains table is a new index
+   * in both tables, which corresponding symbol is tested and so on and so
+   * forth */
+  size_t bucket = hash % buckets.numElements();
+  for (size_t y = buckets[bucket]; y != STN_UNDEF; y = chains[y]) {
+    if (strcmp(symbol, strtab.GetStringAt(symtab[y].st_name)))
+      continue;
+    return &symtab[y];
+  }
+  return nullptr;
+}
new file mode 100644
--- /dev/null
+++ b/mozglue/linker/BaseElf.h
@@ -0,0 +1,93 @@
+/* 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 BaseElf_h
+#define BaseElf_h
+
+#include "ElfLoader.h"
+#include "Elfxx.h"
+
+
+/**
+ * Base class for ELF libraries. This class includes things that will be
+ * common between SystemElfs and CustomElfs.
+ */
+class BaseElf: public LibHandle
+{
+public:
+  /**
+   * Hash function for symbol lookup, as defined in ELF standard for System V.
+   */
+  static unsigned long Hash(const char *symbol);
+
+  /**
+   * Returns the address corresponding to the given symbol name (with a
+   * pre-computed hash).
+   */
+  void *GetSymbolPtr(const char *symbol, unsigned long hash) const;
+
+  /**
+   * Returns a pointer to the Elf Symbol in the Dynamic Symbol table
+   * corresponding to the given symbol name (with a pre-computed hash).
+   */
+  const Elf::Sym *GetSymbol(const char *symbol, unsigned long hash) const;
+
+  BaseElf(const char *path)
+  : LibHandle(path) { }
+
+protected:
+   /**
+    * Inherited from LibHandle. Those are temporary and are not supposed to
+    * be used.
+    */
+   virtual void *GetSymbolPtr(const char *symbol) const { return NULL; };
+   virtual bool Contains(void *addr) const { return false; };
+   virtual void *GetBase() const { return GetPtr(0); }
+
+#ifdef __ARM_EABI__
+  virtual const void *FindExidx(int *pcount) const { return NULL; };
+#endif
+
+  virtual Mappable *GetMappable() const { return NULL; };
+
+public:
+/* private: */
+  /**
+   * Returns a pointer relative to the base address where the library is
+   * loaded.
+   */
+  void *GetPtr(const Elf::Addr offset) const
+  {
+    if (reinterpret_cast<void *>(offset) > base)
+      return reinterpret_cast<void *>(offset);
+    return base + offset;
+  }
+
+  /**
+   * Like the above, but returns a typed (const) pointer
+   */
+  template <typename T>
+  const T *GetPtr(const Elf::Addr offset) const
+  {
+    if (reinterpret_cast<void *>(offset) > base)
+      return reinterpret_cast<const T *>(offset);
+    return reinterpret_cast<const T *>(base + offset);
+  }
+
+  /* Base address where the library is loaded */
+  MappedPtr base;
+
+  /* Buckets and chains for the System V symbol hash table */
+  Array<Elf::Word> buckets;
+  UnsizedArray<Elf::Word> chains;
+
+/* protected: */
+  /* String table */
+  Elf::Strtab strtab;
+
+  /* Symbol table */
+  UnsizedArray<Elf::Sym> symtab;
+};
+
+#endif /* BaseElf_h */
--- a/mozglue/linker/CustomElf.cpp
+++ b/mozglue/linker/CustomElf.cpp
@@ -2,17 +2,19 @@
  * 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 <cstring>
 #include <sys/mman.h>
 #include <vector>
 #include <dlfcn.h>
 #include <signal.h>
+#include <string.h>
 #include "CustomElf.h"
+#include "BaseElf.h"
 #include "Mappable.h"
 #include "Logging.h"
 
 using namespace Elf;
 using namespace mozilla;
 
 /* TODO: Fill ElfLoader::Singleton.lastError on errors. */
 
@@ -274,53 +276,20 @@ CustomElf::~CustomElf()
   CallFini();
   /* Normally, __cxa_finalize is called by the .fini function. However,
    * Android NDK before r6b doesn't do that. Our wrapped cxa_finalize only
    * calls destructors once, so call it in all cases. */
   ElfLoader::__wrap_cxa_finalize(this);
   ElfLoader::Singleton.Forget(this);
 }
 
-namespace {
-
-/**
- * Hash function for symbol lookup, as defined in ELF standard for System V
- */
-unsigned long
-ElfHash(const char *symbol)
-{
-  const unsigned char *sym = reinterpret_cast<const unsigned char *>(symbol);
-  unsigned long h = 0, g;
-  while (*sym) {
-    h = (h << 4) + *sym++;
-    if ((g = h & 0xf0000000))
-      h ^= g >> 24;
-    h &= ~g;
-  }
-  return h;
-}
-
-} /* anonymous namespace */
-
 void *
 CustomElf::GetSymbolPtr(const char *symbol) const
 {
-  return GetSymbolPtr(symbol, ElfHash(symbol));
-}
-
-void *
-CustomElf::GetSymbolPtr(const char *symbol, unsigned long hash) const
-{
-  const Sym *sym = GetSymbol(symbol, hash);
-  void *ptr = nullptr;
-  if (sym && sym->st_shndx != SHN_UNDEF)
-    ptr = GetPtr(sym->st_value);
-  DEBUG_LOG("CustomElf::GetSymbolPtr(%p [\"%s\"], \"%s\") = %p",
-            reinterpret_cast<const void *>(this), GetPath(), symbol, ptr);
-  return ptr;
+  return BaseElf::GetSymbolPtr(symbol, Hash(symbol));
 }
 
 void *
 CustomElf::GetSymbolPtrInDeps(const char *symbol) const
 {
   /* Resolve dlopen and related functions to point to ours */
   if (symbol[0] == 'd' && symbol[1] == 'l') {
     if (strcmp(symbol + 2, "open") == 0)
@@ -367,69 +336,48 @@ CustomElf::GetSymbolPtrInDeps(const char
   // so stub those out here
   if (strncmp(symbol,
               MISSING_FLASH_SYMNAME_START,
               sizeof(MISSING_FLASH_SYMNAME_START) - 1) == 0) {
     return FunctionPtr(__void_stub);
   }
 
   void *sym;
-  /* Search the symbol in the main program. Note this also tries all libraries
-   * the system linker will have loaded RTLD_GLOBAL. Unfortunately, that doesn't
-   * work with bionic, but its linker doesn't normally search the main binary
-   * anyways. Moreover, on android, the main binary is dalvik. */
-#ifdef __GLIBC__
-  sym = dlsym(RTLD_DEFAULT, symbol);
-  DEBUG_LOG("dlsym(RTLD_DEFAULT, \"%s\") = %p", symbol, sym);
-  if (sym)
-    return sym;
-#endif
+
+  unsigned long hash = Hash(symbol);
+
+  /* self_elf should never be NULL, but better safe than sorry. */
+  if (ElfLoader::Singleton.self_elf) {
+    /* We consider the library containing this code a permanent LD_PRELOAD,
+     * so, check if the symbol exists here first. */
+    sym = ElfLoader::Singleton.self_elf->GetSymbolPtr(symbol, hash);
+    if (sym)
+      return sym;
+  }
 
   /* Then search the symbol in our dependencies. Since we already searched in
    * libraries the system linker loaded, skip those (on glibc systems). We
    * also assume the symbol is to be found in one of the dependent libraries
    * directly, not in their own dependent libraries. Building libraries with
    * --no-allow-shlib-undefined ensures such indirect symbol dependency don't
    * happen. */
-  unsigned long hash = ElfHash(symbol);
   for (std::vector<RefPtr<LibHandle> >::const_iterator it = dependencies.begin();
        it < dependencies.end(); ++it) {
     if (!(*it)->IsSystemElf()) {
-      sym = reinterpret_cast<CustomElf *>((*it).get())->GetSymbolPtr(symbol, hash);
-#ifndef __GLIBC__
+      sym = static_cast<BaseElf *>(
+        static_cast<CustomElf *>((*it).get()))->GetSymbolPtr(symbol, hash);
     } else {
       sym = (*it)->GetSymbolPtr(symbol);
-#endif
     }
     if (sym)
       return sym;
   }
   return nullptr;
 }
 
-const Sym *
-CustomElf::GetSymbol(const char *symbol, unsigned long hash) const
-{
-  /* Search symbol with the buckets and chains tables.
-   * The hash computed from the symbol name gives an index in the buckets
-   * table. The corresponding value in the bucket table is an index in the
-   * symbols table and in the chains table.
-   * If the corresponding symbol in the symbols table matches, we're done.
-   * Otherwise, the corresponding value in the chains table is a new index
-   * in both tables, which corresponding symbol is tested and so on and so
-   * forth */
-  size_t bucket = hash % buckets.numElements();
-  for (size_t y = buckets[bucket]; y != STN_UNDEF; y = chains[y]) {
-    if (strcmp(symbol, strtab.GetStringAt(symtab[y].st_name)))
-      continue;
-    return &symtab[y];
-  }
-  return nullptr;
-}
-
 bool
 CustomElf::Contains(void *addr) const
 {
   return base.Contains(addr);
 }
 
 #ifdef __ARM_EABI__
 const void *
--- a/mozglue/linker/CustomElf.h
+++ b/mozglue/linker/CustomElf.h
@@ -1,24 +1,25 @@
 /* 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 CustomElf_h
 #define CustomElf_h
 
 #include "ElfLoader.h"
+#include "BaseElf.h"
 #include "Logging.h"
 #include "Elfxx.h"
 
 /**
  * Library Handle class for ELF libraries we don't let the system linker
  * handle.
  */
-class CustomElf: public LibHandle, private ElfLoader::link_map
+class CustomElf: public BaseElf, private ElfLoader::link_map
 {
   friend class ElfLoader;
   friend class SEGVHandler;
 public:
   /**
    * Returns a new CustomElf using the given file descriptor to map ELF
    * content. The file descriptor ownership is stolen, and it will be closed
    * in CustomElf's destructor if an instance is created, or by the Load
@@ -26,17 +27,17 @@ public:
    * are the same kind of flags that would be given to dlopen(), though
    * currently, none are supported and the behaviour is more or less that of
    * RTLD_GLOBAL | RTLD_BIND_NOW.
    */
   static mozilla::TemporaryRef<LibHandle> Load(Mappable *mappable,
                                                const char *path, int flags);
 
   /**
-   * Inherited from LibHandle
+   * Inherited from LibHandle/BaseElf
    */
   virtual ~CustomElf();
   virtual void *GetSymbolPtr(const char *symbol) const;
   virtual bool Contains(void *addr) const;
   virtual void *GetBase() const { return GetPtr(0); }
 
 #ifdef __ARM_EABI__
   virtual const void *FindExidx(int *pcount) const;
@@ -50,65 +51,35 @@ public:
    * Shows some stats about the Mappable instance. The when argument is to be
    * used by the caller to give an identifier of the when the stats call is
    * made.
    */
   void stats(const char *when) const;
 
 private:
   /**
-   * Returns a pointer to the Elf Symbol in the Dynamic Symbol table
-   * corresponding to the given symbol name (with a pre-computed hash).
-   */
-  const Elf::Sym *GetSymbol(const char *symbol, unsigned long hash) const;
-
-  /**
-   * Returns the address corresponding to the given symbol name (with a
-   * pre-computed hash).
-   */
-  void *GetSymbolPtr(const char *symbol, unsigned long hash) const;
-
-  /**
    * Scan dependent libraries to find the address corresponding to the
    * given symbol name. This is used to find symbols that are undefined
    * in the Elf object.
    */
   void *GetSymbolPtrInDeps(const char *symbol) const;
 
   /**
    * Private constructor
    */
   CustomElf(Mappable *mappable, const char *path)
-  : LibHandle(path)
+  : BaseElf(path)
   , mappable(mappable)
   , init(0)
   , fini(0)
   , initialized(false)
   , has_text_relocs(false)
   { }
 
   /**
-   * Returns a pointer relative to the base address where the library is
-   * loaded.
-   */
-  void *GetPtr(const Elf::Addr offset) const
-  {
-    return base + offset;
-  }
-
-  /**
-   * Like the above, but returns a typed (const) pointer
-   */
-  template <typename T>
-  const T *GetPtr(const Elf::Addr offset) const
-  {
-    return reinterpret_cast<const T *>(base + offset);
-  }
-
-  /**
    * Loads an Elf segment defined by the given PT_LOAD header.
    * Returns whether this succeeded or failed.
    */
   bool LoadSegment(const Elf::Phdr *pt_load) const;
 
   /**
    * Initializes the library according to information found in the given
    * PT_DYNAMIC header.
@@ -162,29 +133,16 @@ private:
   void CallFunction(Elf::Addr addr) const
   {
     return CallFunction(GetPtr(addr));
   }
 
   /* Appropriated Mappable */
   mozilla::RefPtr<Mappable> mappable;
 
-  /* Base address where the library is loaded */
-  MappedPtr base;
-
-  /* String table */
-  Elf::Strtab strtab;
-
-  /* Symbol table */
-  UnsizedArray<Elf::Sym> symtab;
-
-  /* Buckets and chains for the System V symbol hash table */
-  Array<Elf::Word> buckets;
-  UnsizedArray<Elf::Word> chains;
-
   /* List of dependent libraries */
   std::vector<mozilla::RefPtr<LibHandle> > dependencies;
 
   /* List of .rel.dyn/.rela.dyn relocations */
   Array<Elf::Reloc> relocations;
 
   /* List of .rel.plt/.rela.plt relocation */
   Array<Elf::Reloc> jumprels;
--- a/mozglue/linker/ElfLoader.cpp
+++ b/mozglue/linker/ElfLoader.cpp
@@ -6,16 +6,17 @@
 #include <cstring>
 #include <cstdlib>
 #include <cstdio>
 #include <dlfcn.h>
 #include <unistd.h>
 #include <algorithm>
 #include <fcntl.h>
 #include "ElfLoader.h"
+#include "BaseElf.h"
 #include "CustomElf.h"
 #include "Mappable.h"
 #include "Logging.h"
 #include <inttypes.h>
 
 #if defined(ANDROID)
 #include <sys/syscall.h>
 
@@ -33,16 +34,20 @@ inline int sigaltstack(const stack_t *ss
 #endif /* __ANDROID_API__ */
 #endif /* ANDROID */
 
 #ifdef __ARM_EABI__
 extern "C" MOZ_EXPORT const void *
 __gnu_Unwind_Find_exidx(void *pc, int *pcount) __attribute__((weak));
 #endif
 
+/* Pointer to the PT_DYNAMIC section of the executable or library
+ * containing this code. */
+extern "C" Elf::Dyn _DYNAMIC[];
+
 using namespace mozilla;
 
 /**
  * dlfcn.h replacements functions
  */
 
 void *
 __wrap_dlopen(const char *path, int flags)
@@ -326,16 +331,20 @@ SystemElf::FindExidx(int *pcount) const
 ElfLoader ElfLoader::Singleton;
 
 TemporaryRef<LibHandle>
 ElfLoader::Load(const char *path, int flags, LibHandle *parent)
 {
   /* Ensure logging is initialized or refresh if environment changed. */
   Logging::Init();
 
+  /* Ensure self_elf initialization. */
+  if (!self_elf)
+    Init();
+
   RefPtr<LibHandle> handle;
 
   /* Handle dlopen(nullptr) directly. */
   if (!path) {
     handle = SystemElf::Load(nullptr, flags);
     return handle;
   }
 
@@ -461,16 +470,64 @@ ElfLoader::Forget(LibHandle *handle)
       dbg.Remove(static_cast<CustomElf *>(handle));
     handles.erase(it);
   } else {
     DEBUG_LOG("ElfLoader::Forget(%p [\"%s\"]): Handle not found",
               reinterpret_cast<void *>(handle), handle->GetPath());
   }
 }
 
+void
+ElfLoader::Init()
+{
+  Dl_info info;
+  /* On Android < 4.1 can't reenter dl* functions. So when the library
+   * containing this code is dlopen()ed, it can't call dladdr from a
+   * static initializer. */
+  if (dladdr(_DYNAMIC, &info) != 0) {
+    /* Ideally, we wouldn't be initializing self_elf this way, but until
+     * SystemElf actually inherits from BaseElf, we'll just do it this
+     * (gross) way. */
+    UniquePtr<BaseElf> elf = mozilla::MakeUnique<BaseElf>(info.dli_fname);
+    elf->base.Assign(info.dli_fbase, -1);
+    size_t symnum = 0;
+    for (const Elf::Dyn *dyn = _DYNAMIC; dyn->d_tag; dyn++) {
+      switch (dyn->d_tag) {
+        case DT_HASH:
+          {
+            DEBUG_LOG("%s 0x%08" PRIxAddr, "DT_HASH", dyn->d_un.d_val);
+            const Elf::Word *hash_table_header = \
+              elf->GetPtr<Elf::Word>(dyn->d_un.d_ptr);
+            symnum = hash_table_header[1];
+            elf->buckets.Init(&hash_table_header[2], hash_table_header[0]);
+            elf->chains.Init(&*elf->buckets.end());
+          }
+          break;
+        case DT_STRTAB:
+          DEBUG_LOG("%s 0x%08" PRIxAddr, "DT_STRTAB", dyn->d_un.d_val);
+          elf->strtab.Init(elf->GetPtr(dyn->d_un.d_ptr));
+          break;
+        case DT_SYMTAB:
+          DEBUG_LOG("%s 0x%08" PRIxAddr, "DT_SYMTAB", dyn->d_un.d_val);
+          elf->symtab.Init(elf->GetPtr(dyn->d_un.d_ptr));
+          break;
+      }
+    }
+    if (!elf->buckets || !symnum) {
+      ERROR("%s: Missing or broken DT_HASH", info.dli_fname);
+    } else if (!elf->strtab) {
+      ERROR("%s: Missing DT_STRTAB", info.dli_fname);
+    } else if (!elf->symtab) {
+      ERROR("%s: Missing DT_SYMTAB", info.dli_fname);
+    } else {
+      self_elf = Move(elf);
+    }
+  }
+}
+
 ElfLoader::~ElfLoader()
 {
   LibHandleList list;
   /* Build up a list of all library handles with direct (external) references.
    * We actually skip system library handles because we want to keep at least
    * some of these open. Most notably, Mozilla codebase keeps a few libgnome
    * libraries deliberately open because of the mess that libORBit destruction
    * is. dlclose()ing these libraries actually leads to problems. */
@@ -502,16 +559,20 @@ ElfLoader::~ElfLoader()
                   "[%d direct refs, %d refs total]", (*it)->GetPath(),
                   (*it)->DirectRefCount(), (*it)->refCount());
         /* Not removing, since it could have references to other libraries,
          * destroying them as a side effect, and possibly leaving dangling
          * pointers in the handle list we're scanning */
       }
     }
   }
+  /* Avoid self_elf->base destructor unmapping something that doesn't actually
+   * belong to it. */
+  if (self_elf)
+    self_elf->base.release();
 }
 
 void
 ElfLoader::stats(const char *when)
 {
   for (LibHandleList::iterator it = Singleton.handles.begin();
        it < Singleton.handles.end(); ++it)
     if (!(*it)->IsSystemElf())
--- a/mozglue/linker/ElfLoader.h
+++ b/mozglue/linker/ElfLoader.h
@@ -4,16 +4,17 @@
 
 #ifndef ElfLoader_h
 #define ElfLoader_h
 
 #include <vector>
 #include <dlfcn.h>
 #include <signal.h>
 #include "mozilla/RefPtr.h"
+#include "mozilla/UniquePtr.h"
 #include "Zip.h"
 #include "Elfxx.h"
 #include "Mappable.h"
 
 /**
  * dlfcn.h replacement functions
  */
 extern "C" {
@@ -58,16 +59,19 @@ MFBT_API void *
 MFBT_API void
 __dl_munmap(void *handle, void *addr, size_t length);
 
 MFBT_API bool
 IsSignalHandlingBroken();
 
 }
 
+/* Forward declaration because BaseElf.h includes ElfLoader.h */
+class BaseElf;
+
 /**
  * Specialize RefCounted template for LibHandle. We may get references to
  * LibHandles during the execution of their destructor, so we need
  * RefCounted<LibHandle>::Release to support some reentrancy. See further
  * below.
  */
 class LibHandle;
 
@@ -434,16 +438,23 @@ protected:
   friend const char *__wrap_dlerror(void);
   friend void *__wrap_dlsym(void *handle, const char *symbol);
   friend int __wrap_dlclose(void *handle);
   const char *lastError;
 
 private:
   ~ElfLoader();
 
+  /* Initialization code that can't run during static initialization. */
+  void Init();
+
+  /* System loader handle for the library/program containing our code. This
+   * is used to resolve wrapped functions. */
+  mozilla::UniquePtr<BaseElf> self_elf;
+
   /* Bookkeeping */
   typedef std::vector<LibHandle *> LibHandleList;
   LibHandleList handles;
 
 protected:
   friend class CustomElf;
   /**
    * Show some stats about Mappables in CustomElfs. The when argument is to
@@ -552,23 +563,31 @@ private:
      * is in when the function above is called. */
     enum {
       RT_CONSISTENT, /* Changes are complete */
       RT_ADD,        /* Beginning to add a new object */
       RT_DELETE      /* Beginning to remove an object */
     } r_state;
   };
 
+  /* Memory representation of ELF Auxiliary Vectors */
+  struct AuxVector {
+    Elf::Addr type;
+    Elf::Addr value;
+  };
+
   /* Helper class used to integrate libraries loaded by this linker in
    * r_debug */
   class DebuggerHelper
   {
   public:
     DebuggerHelper();
 
+    void Init(AuxVector *auvx);
+
     operator bool()
     {
       return dbg;
     }
 
     /* Make the debugger aware of a new loaded object */
     void Add(link_map *map);
 
--- a/mozglue/linker/Utils.h
+++ b/mozglue/linker/Utils.h
@@ -285,16 +285,20 @@ public:
   }
 
   ~GenericMappedPtr()
   {
     if (get() != MAP_FAILED)
       static_cast<T *>(this)->munmap(get(), GetLength());
   }
 
+  void release()
+  {
+    MemoryRange::Assign(MAP_FAILED, 0);
+  }
 };
 
 struct MappedPtr: public GenericMappedPtr<MappedPtr>
 {
   MappedPtr(void *buf, size_t length)
   : GenericMappedPtr<MappedPtr>(buf, length) { }
   MappedPtr(const MemoryRange& other)
   : GenericMappedPtr<MappedPtr>(other) { }
--- a/mozglue/linker/moz.build
+++ b/mozglue/linker/moz.build
@@ -1,15 +1,16 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 SOURCES += [
+    'BaseElf.cpp',
     'CustomElf.cpp',
     'ElfLoader.cpp',
     'Mappable.cpp',
     'SeekableZStream.cpp',
     'Zip.cpp',
 ]
 
 Library('linker')
--- a/python/mach/mach/base.py
+++ b/python/mach/mach/base.py
@@ -72,39 +72,34 @@ class MethodHandler(object):
         'name',
 
         # String category this command belongs to.
         'category',
 
         # Description of the purpose of this command.
         'description',
 
-        # Whether to allow all arguments from the parser.
-        'allow_all_arguments',
-
         # Functions used to 'skip' commands if they don't meet the conditions
         # in a given context.
         'conditions',
 
         # argparse.ArgumentParser instance to use as the basis for command
         # arguments.
         'parser',
 
         # Arguments added to this command's parser. This is a 2-tuple of
         # positional and named arguments, respectively.
         'arguments',
     )
 
     def __init__(self, cls, method, name, category=None, description=None,
-        allow_all_arguments=False, conditions=None, parser=None, arguments=None,
-        pass_context=False):
+        conditions=None, parser=None, arguments=None, pass_context=False):
 
         self.cls = cls
         self.method = method
         self.name = name
         self.category = category
         self.description = description
-        self.allow_all_arguments = allow_all_arguments
         self.conditions = conditions or []
         self.parser = parser
         self.arguments = arguments or []
         self.pass_context = pass_context
 
--- a/python/mach/mach/decorators.py
+++ b/python/mach/mach/decorators.py
@@ -1,14 +1,15 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 from __future__ import unicode_literals
 
+import argparse
 import collections
 import inspect
 import types
 
 from .base import (
     MachError,
     MethodHandler
 )
@@ -51,18 +52,18 @@ def CommandProvider(cls):
     # define commands multiple times. We also sort keys so commands defined in
     # the same class are grouped in a sane order.
     for attr in sorted(cls.__dict__.keys()):
         value = cls.__dict__[attr]
 
         if not isinstance(value, types.FunctionType):
             continue
 
-        command_name, category, description, allow_all, conditions, parser = getattr(
-            value, '_mach_command', (None, None, None, None, None, None))
+        command_name, category, description, conditions, parser = getattr(
+            value, '_mach_command', (None, None, None, None, None))
 
         if command_name is None:
             continue
 
         if conditions is None and Registrar.require_conditions:
             continue
 
         msg = 'Mach command \'%s\' implemented incorrectly. ' + \
@@ -77,19 +78,18 @@ def CommandProvider(cls):
         for c in conditions:
             if not hasattr(c, '__call__'):
                 msg = msg % (command_name, type(c))
                 raise MachError(msg)
 
         arguments = getattr(value, '_mach_command_args', None)
 
         handler = MethodHandler(cls, attr, command_name, category=category,
-            description=description, allow_all_arguments=allow_all,
-            conditions=conditions, parser=parser, arguments=arguments,
-            pass_context=pass_context)
+            description=description, conditions=conditions, parser=parser,
+            arguments=arguments, pass_context=pass_context)
 
         Registrar.register_command_handler(handler)
 
     return cls
 
 
 class Command(object):
     """Decorator for functions or methods that provide a mach subcommand.
@@ -97,40 +97,36 @@ class Command(object):
     The decorator accepts arguments that define basic attributes of the
     command. The following arguments are recognized:
 
          category -- The string category to which this command belongs. Mach's
              help will group commands by category.
 
          description -- A brief description of what the command does.
 
-         allow_all_args -- Bool indicating whether to allow unknown arguments
-             through to the command.
-
          parser -- an optional argparse.ArgumentParser instance to use as
              the basis for the command arguments.
 
     For example:
 
         @Command('foo', category='misc', description='Run the foo action')
         def foo(self):
             pass
     """
-    def __init__(self, name, category=None, description=None,
-                 allow_all_args=False, conditions=None, parser=None):
+    def __init__(self, name, category=None, description=None, conditions=None,
+                 parser=None):
         self._name = name
         self._category = category
         self._description = description
-        self._allow_all_args = allow_all_args
         self._conditions = conditions
         self._parser = parser
 
     def __call__(self, func):
         func._mach_command = (self._name, self._category, self._description,
-                              self._allow_all_args, self._conditions, self._parser)
+                              self._conditions, self._parser)
 
         return func
 
 
 class CommandArgument(object):
     """Decorator for additional arguments to mach subcommands.
 
     This decorator should be used to add arguments to mach commands. Arguments
@@ -140,16 +136,21 @@ class CommandArgument(object):
 
         @Command('foo', help='Run the foo action')
         @CommandArgument('-b', '--bar', action='store_true', default=False,
             help='Enable bar mode.')
         def foo(self):
             pass
     """
     def __init__(self, *args, **kwargs):
+        if kwargs.get('nargs') == argparse.REMAINDER:
+            # These are the assertions we make in dispatcher.py about
+            # those types of CommandArguments.
+            assert len(args) == 1
+            assert all(k in ('default', 'nargs', 'help') for k in kwargs)
         self._command_args = (args, kwargs)
 
     def __call__(self, func):
         command_args = getattr(func, '_mach_command_args', [])
 
         command_args.insert(0, self._command_args)
 
         func._mach_command_args = command_args
--- a/python/mach/mach/dispatcher.py
+++ b/python/mach/mach/dispatcher.py
@@ -130,38 +130,71 @@ class CommandAction(argparse.Action):
         # We create a new parser, populate it with the command's arguments,
         # then feed all remaining arguments to it, merging the results
         # with ourselves. This is essentially what argparse subparsers
         # do.
 
         parser_args = {
             'add_help': False,
             'usage': '%(prog)s [global arguments] ' + command +
-                ' command arguments]',
+                ' [command arguments]',
         }
 
-        if handler.allow_all_arguments:
-            parser_args['prefix_chars'] = '+'
-
         if handler.parser:
             subparser = handler.parser
         else:
             subparser = argparse.ArgumentParser(**parser_args)
 
+        remainder = None
+
         for arg in handler.arguments:
-            subparser.add_argument(*arg[0], **arg[1])
+            if arg[1].get('nargs') == argparse.REMAINDER:
+                # parse_known_args expects all argparse.REMAINDER ('...')
+                # arguments to be all stuck together. Instead, we want them to
+                # pick any extra argument, wherever they are.
+                # Assume a limited CommandArgument for those arguments.
+                assert len(arg[0]) == 1
+                assert all(k in ('default', 'nargs', 'help') for k in arg[1])
+                remainder = arg
+            else:
+                subparser.add_argument(*arg[0], **arg[1])
 
         # We define the command information on the main parser result so as to
         # not interfere with arguments passed to the command.
         setattr(namespace, 'mach_handler', handler)
         setattr(namespace, 'command', command)
 
         command_namespace, extra = subparser.parse_known_args(args)
         setattr(namespace, 'command_args', command_namespace)
-        if extra:
+        if remainder:
+            (name,), options = remainder
+            # parse_known_args usefully puts all arguments after '--' in
+            # extra, but also puts '--' there. We don't want to pass it down
+            # to the command handler. Note that if multiple '--' are on the
+            # command line, only the first one is removed, so that subsequent
+            # ones are passed down.
+            if '--' in extra:
+                extra.remove('--')
+
+            # Commands with argparse.REMAINDER arguments used to force the
+            # other arguments to be '+' prefixed. If a user now passes such
+            # an argument, if will silently end up in extra. So, check if any
+            # of the allowed arguments appear in a '+' prefixed form, and error
+            # out if that's the case.
+            for args, _ in handler.arguments:
+                for arg in args:
+                    arg = arg.replace('-', '+', 1)
+                    if arg in extra:
+                        raise UnrecognizedArgumentError(command, [arg])
+
+            if extra:
+                setattr(command_namespace, name, extra)
+            else:
+                setattr(command_namespace, name, options.get('default', []))
+        elif extra:
             raise UnrecognizedArgumentError(command, extra)
 
     def _handle_main_help(self, parser, verbose):
         # Since we don't need full sub-parser support for the main help output,
         # we create groups in the ArgumentParser and populate each group with
         # arguments corresponding to command names. This has the side-effect
         # that argparse renders it nicely.
         r = self._mach_registrar
@@ -229,19 +262,16 @@ class CommandAction(argparse.Action):
         # just the command data then supplement the main help's output with
         # this 2nd parser's. We use a custom formatter class to ignore some of
         # the help output.
         parser_args = {
             'formatter_class': CommandFormatter,
             'add_help': False,
         }
 
-        if handler.allow_all_arguments:
-            parser_args['prefix_chars'] = '+'
-
         if handler.parser:
             c_parser = handler.parser
             c_parser.formatter_class = NoUsageFormatter
             # Accessing _action_groups is a bit shady. We are highly dependent
             # on the argparse implementation not changing. We fail fast to
             # detect upstream changes so we can intelligently react to them.
             group = c_parser._action_groups[1]
 
--- a/python/mach_commands.py
+++ b/python/mach_commands.py
@@ -20,17 +20,16 @@ from mach.decorators import (
     CommandProvider,
     Command,
 )
 
 
 @CommandProvider
 class MachCommands(MachCommandBase):
     @Command('python', category='devenv',
-        allow_all_args=True,
         description='Run Python.')
     @CommandArgument('args', nargs=argparse.REMAINDER)
     def python(self, args):
         # Avoid logging the command
         self.log_manager.terminal_handler.setLevel(logging.CRITICAL)
 
         self._activate_virtualenv()
 
--- a/python/mozbuild/mozbuild/mach_commands.py
+++ b/python/mozbuild/mozbuild/mach_commands.py
@@ -805,75 +805,72 @@ def get_run_args(mach_command, params, r
         if not os.path.isdir(path):
             os.makedirs(path)
         args.append('-profile')
         args.append(path)
 
     if params:
         args.extend(params)
 
-    if '--' in args:
-        args.remove('--')
-
     return args
 
 @CommandProvider
 class RunProgram(MachCommandBase):
     """Launch the compiled binary"""
 
-    @Command('run', category='post-build', allow_all_args=True,
+    @Command('run', category='post-build',
         description='Run the compiled program.')
-    @CommandArgument('params', default=None, nargs='...',
+    @CommandArgument('params', nargs='...',
         help='Command-line arguments to be passed through to the program. Not specifying a -profile or -P option will result in a temporary profile being used.')
-    @CommandArgument('+remote', '+r', action='store_true',
+    @CommandArgument('-remote', '-r', action='store_true',
         help='Do not pass the -no-remote argument by default.')
-    @CommandArgument('+background', '+b', action='store_true',
+    @CommandArgument('-background', '-b', action='store_true',
         help='Do not pass the -foreground argument by default on Mac')
-    @CommandArgument('+noprofile', '+n', action='store_true',
+    @CommandArgument('-noprofile', '-n', action='store_true',
         help='Do not pass the -profile argument by default.')
     def run(self, params, remote, background, noprofile):
         args = get_run_args(self, params, remote, background, noprofile)
         if not args:
             return 1
 
         return self.run_process(args=args, ensure_exit_code=False,
             pass_thru=True)
 
 @CommandProvider
 class DebugProgram(MachCommandBase):
     """Debug the compiled binary"""
 
-    @Command('debug', category='post-build', allow_all_args=True,
+    @Command('debug', category='post-build',
         description='Debug the compiled program.')
-    @CommandArgument('params', default=None, nargs='...',
+    @CommandArgument('params', nargs='...',
         help='Command-line arguments to be passed through to the program. Not specifying a -profile or -P option will result in a temporary profile being used.')
-    @CommandArgument('+remote', '+r', action='store_true',
+    @CommandArgument('-remote', '-r', action='store_true',
         help='Do not pass the -no-remote argument by default')
-    @CommandArgument('+background', '+b', action='store_true',
+    @CommandArgument('-background', '-b', action='store_true',
         help='Do not pass the -foreground argument by default on Mac')
-    @CommandArgument('+debugger', default=None, type=str,
+    @CommandArgument('-debugger', default=None, type=str,
         help='Name of debugger to launch')
-    @CommandArgument('+debugparams', default=None, metavar='params', type=str,
+    @CommandArgument('-debugparams', default=None, metavar='params', type=str,
         help='Command-line arguments to pass to the debugger itself; split as the Bourne shell would.')
     # Bug 933807 introduced JS_DISABLE_SLOW_SCRIPT_SIGNALS to avoid clever
     # segfaults induced by the slow-script-detecting logic for Ion/Odin JITted
     # code.  If we don't pass this, the user will need to periodically type
     # "continue" to (safely) resume execution.  There are ways to implement
     # automatic resuming; see the bug.
-    @CommandArgument('+slowscript', action='store_true',
+    @CommandArgument('-slowscript', action='store_true',
         help='Do not set the JS_DISABLE_SLOW_SCRIPT_SIGNALS env variable; when not set, recoverable but misleading SIGSEGV instances may occur in Ion/Odin JIT code')
-    @CommandArgument('+noprofile', '+n', action='store_true',
+    @CommandArgument('-noprofile', '-n', action='store_true',
         help='Do not pass the -profile argument by default.')
     def debug(self, params, remote, background, debugger, debugparams, slowscript, noprofile):
         # Parameters come from the CLI. We need to convert them before their use.
         if debugparams:
             import pymake.process
             argv, badchar = pymake.process.clinetoargv(debugparams, os.getcwd())
             if badchar:
-                print("The +debugparams you passed require a real shell to parse them.")
+                print("The -debugparams you passed require a real shell to parse them.")
                 print("(We can't handle the %r character.)" % (badchar,))
                 return 1
             debugparams = argv;
 
         import mozdebug
 
         if not debugger:
             # No debugger name was provided. Look for the default ones on current OS.
@@ -920,17 +917,17 @@ class DebugProgram(MachCommandBase):
             ensure_exit_code=False, pass_thru=True)
 
 @CommandProvider
 class RunDmd(MachCommandBase):
     """Launch the compiled binary with DMD enabled"""
 
     @Command('dmd', category='post-build',
         description='Run the compiled program with DMD enabled.')
-    @CommandArgument('params', default=None, nargs='...',
+    @CommandArgument('params', nargs='...',
         help=('Command-line arguments to be passed through to the program. '
               'Not specifying a -profile or -P option will result in a '
               'temporary profile being used. If passing -params use a "--" to '
               'indicate the start of params to pass to firefox.'))
     @CommandArgument('--remote', '-r', action='store_true',
         help='Do not pass the -no-remote argument by default.')
     @CommandArgument('--background', '-b', action='store_true',
         help='Do not pass the -foreground argument by default on Mac')
--- a/testing/marionette/client/marionette/tests/unit-tests.ini
+++ b/testing/marionette/client/marionette/tests/unit-tests.ini
@@ -10,29 +10,13 @@ b2g = true
 
 ; true if the test should be skipped
 skip = false
 
 ; marionette unit tests
 [include:unit/unit-tests.ini]
 test_container = true
 
-; webapi tests
-[include:../../../../../dom/bluetooth/tests/marionette/manifest.ini]
-[include:../../../../../dom/telephony/test/marionette/manifest.ini]
-[include:../../../../../dom/voicemail/test/marionette/manifest.ini]
-[include:../../../../../dom/battery/test/marionette/manifest.ini]
-[include:../../../../../dom/mobilemessage/tests/marionette/manifest.ini]
-[include:../../../../../dom/mobileconnection/tests/marionette/manifest.ini]
-[include:../../../../../dom/system/gonk/tests/marionette/manifest.ini]
-[include:../../../../../dom/icc/tests/marionette/manifest.ini]
-[include:../../../../../dom/system/tests/marionette/manifest.ini]
-[include:../../../../../dom/nfc/tests/marionette/manifest.ini]
-[include:../../../../../dom/events/test/marionette/manifest.ini]
-[include:../../../../../dom/wifi/test/marionette/manifest.ini]
-[include:../../../../../dom/cellbroadcast/tests/marionette/manifest.ini]
-[include:../../../../../dom/tethering/tests/marionette/manifest.ini]
-
 ; layout tests
 [include:../../../../../layout/base/tests/marionette/manifest.ini]
 
 ; loop tests
 [include:../../../../../browser/components/loop/manifest.ini]
--- a/testing/mochitest/runtests.py
+++ b/testing/mochitest/runtests.py
@@ -1840,17 +1840,17 @@ class Mochitest(MochitestUtilsMixin):
         self.log.error("Automation Error: Received unexpected exception while running application\n")
         status = 1
 
     finally:
       if options.vmwareRecording:
         self.stopVMwareRecording();
       self.stopServers()
 
-    processLeakLog(self.leak_report_file, options.leakThresholds, options.ignoreMissingLeaks)
+    processLeakLog(self.leak_report_file, options)
 
     if self.nsprLogs:
       with zipfile.ZipFile("%s/nsprlog.zip" % browserEnv["MOZ_UPLOAD_DIR"], "w", zipfile.ZIP_DEFLATED) as logzip:
         for logfile in glob.glob("%s/nspr*.log*" % tempfile.gettempdir()):
           logzip.write(logfile)
           os.remove(logfile)
 
     self.log.info("runtests.py | Running tests: end.")
--- a/testing/mochitest/runtestsb2g.py
+++ b/testing/mochitest/runtestsb2g.py
@@ -197,17 +197,17 @@ class B2GMochitest(MochitestUtilsMixin):
             if status is None:
                 # the runner has timed out
                 status = 124
 
             local_leak_file = tempfile.NamedTemporaryFile()
             self.app_ctx.dm.getFile(self.leak_report_file, local_leak_file.name)
             self.app_ctx.dm.removeFile(self.leak_report_file)
 
-            processLeakLog(local_leak_file.name, options.leakThresholds, options.ignoreMissingLeaks)
+            processLeakLog(local_leak_file.name, options)
         except KeyboardInterrupt:
             self.log.info("runtests.py | Received keyboard interrupt.\n");
             status = -1
         except:
             traceback.print_exc()
             self.log.error("Automation Error: Received unexpected exception while running application\n")
             if hasattr(self, 'runner'):
                 self.runner.check_for_crashes()
--- a/testing/testsuite-targets.mk
+++ b/testing/testsuite-targets.mk
@@ -545,16 +545,21 @@ stage-marionette: make-stage-dir
 	$(NSINSTALL) -D $(MARIONETTE_DIR)/transport
 	@(cd $(topsrcdir)/testing/marionette/client && tar --exclude marionette/tests $(TAR_CREATE_FLAGS) - *) | (cd $(MARIONETTE_DIR)/ && tar -xf -)
 	@(cd $(topsrcdir)/testing/marionette/transport && tar $(TAR_CREATE_FLAGS) - *) | (cd $(MARIONETTE_DIR)/transport && tar -xf -)
 	$(PYTHON) $(topsrcdir)/testing/marionette/client/marionette/tests/print-manifest-dirs.py \
           $(topsrcdir) \
           $(topsrcdir)/testing/marionette/client/marionette/tests/unit-tests.ini \
           | (cd $(topsrcdir) && xargs tar $(TAR_CREATE_FLAGS) -) \
           | (cd $(MARIONETTE_DIR)/tests && tar -xf -)
+	$(PYTHON) $(topsrcdir)/testing/marionette/client/marionette/tests/print-manifest-dirs.py \
+          $(topsrcdir) \
+          $(topsrcdir)/testing/marionette/client/marionette/tests/webapi-tests.ini \
+          | (cd $(topsrcdir) && xargs tar $(TAR_CREATE_FLAGS) -) \
+          | (cd $(MARIONETTE_DIR)/tests && tar -xf -)
 
 stage-mozbase: make-stage-dir
 	$(MAKE) -C $(DEPTH)/testing/mozbase stage-package
 
 stage-web-platform-tests: make-stage-dir
 	$(MAKE) -C $(DEPTH)/testing/web-platform stage-package
 
 stage-instrumentation-tests: make-stage-dir
--- a/tools/mach_commands.py
+++ b/tools/mach_commands.py
@@ -289,17 +289,17 @@ class PastebinProvider(object):
         except urllib2.URLError:
             print('ERROR. Could not connect to pastebin.mozilla.org.')
             return 1
         return 0
 
 
 @CommandProvider
 class ReviewboardToolsProvider(MachCommandBase):
-    @Command('rbt', category='devenv', allow_all_args=True,
+    @Command('rbt', category='devenv',
         description='Run Reviewboard Tools')
     @CommandArgument('args', nargs='...', help='Arguments to rbt tool')
     def rbt(self, args):
         if not args:
             args = ['help']
 
         self._activate_virtualenv()
         self.virtualenv_manager.install_pip_package('RBTools==0.6')