--- 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')