mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 00:01:50 +00:00
Merge mozilla-central to fx-team
--HG-- extra : rebase_source : 40dc0b4141079cd2fc66ae3e39e66e5fde1ae10c
This commit is contained in:
commit
509202f339
2
CLOBBER
2
CLOBBER
@ -22,4 +22,4 @@
|
||||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Bug 1178850 requires clobber for Android JNI header changes
|
||||
Bug 1123386 requires clobber for switching to use a new compiler
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="3fac3ed7b8c887351098ffc677769ddc36abb3d0"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a47e0c58dd1340a17be7cc96ccd90fcad15a922b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c490ae41c67f892232599f4ef049467a922b613e"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
@ -23,7 +23,7 @@
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<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="f48264d4da9680b6e02c9d0459ac273308e21daf"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="cacd27c973f6c84d13a67adaf5d6fce4ae898e9e"/>
|
||||
<!-- 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"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="3fac3ed7b8c887351098ffc677769ddc36abb3d0"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a47e0c58dd1340a17be7cc96ccd90fcad15a922b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c490ae41c67f892232599f4ef049467a922b613e"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
@ -23,7 +23,7 @@
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<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="f48264d4da9680b6e02c9d0459ac273308e21daf"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="cacd27c973f6c84d13a67adaf5d6fce4ae898e9e"/>
|
||||
<!-- 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"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<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="3fac3ed7b8c887351098ffc677769ddc36abb3d0"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a47e0c58dd1340a17be7cc96ccd90fcad15a922b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c490ae41c67f892232599f4ef049467a922b613e"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="8bc59310552179f9a8bc6cdd0188e2475df52fb7"/>
|
||||
|
@ -17,10 +17,10 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="3fac3ed7b8c887351098ffc677769ddc36abb3d0"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a47e0c58dd1340a17be7cc96ccd90fcad15a922b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c490ae41c67f892232599f4ef049467a922b613e"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f48264d4da9680b6e02c9d0459ac273308e21daf"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="cacd27c973f6c84d13a67adaf5d6fce4ae898e9e"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||
<!-- Stock Android things -->
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="3fac3ed7b8c887351098ffc677769ddc36abb3d0"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a47e0c58dd1340a17be7cc96ccd90fcad15a922b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c490ae41c67f892232599f4ef049467a922b613e"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
@ -23,7 +23,7 @@
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<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="f48264d4da9680b6e02c9d0459ac273308e21daf"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="cacd27c973f6c84d13a67adaf5d6fce4ae898e9e"/>
|
||||
<!-- 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"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="3fac3ed7b8c887351098ffc677769ddc36abb3d0"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a47e0c58dd1340a17be7cc96ccd90fcad15a922b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c490ae41c67f892232599f4ef049467a922b613e"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
@ -23,7 +23,7 @@
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<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="f48264d4da9680b6e02c9d0459ac273308e21daf"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="cacd27c973f6c84d13a67adaf5d6fce4ae898e9e"/>
|
||||
<!-- Stock Android things -->
|
||||
<project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
|
||||
<project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" path="prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" revision="337e0ef5e40f02a1ae59b90db0548976c70a7226"/>
|
||||
|
@ -19,7 +19,7 @@
|
||||
<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="3fac3ed7b8c887351098ffc677769ddc36abb3d0"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="a47e0c58dd1340a17be7cc96ccd90fcad15a922b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c490ae41c67f892232599f4ef049467a922b613e"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="8bc59310552179f9a8bc6cdd0188e2475df52fb7"/>
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="3fac3ed7b8c887351098ffc677769ddc36abb3d0"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a47e0c58dd1340a17be7cc96ccd90fcad15a922b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c490ae41c67f892232599f4ef049467a922b613e"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
@ -23,7 +23,7 @@
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<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="f48264d4da9680b6e02c9d0459ac273308e21daf"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="cacd27c973f6c84d13a67adaf5d6fce4ae898e9e"/>
|
||||
<!-- 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"/>
|
||||
@ -125,7 +125,7 @@
|
||||
<!-- Flame specific things -->
|
||||
<project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="1bb28abbc215f45220620af5cd60a8ac1be93722"/>
|
||||
<project name="device/qcom/common" path="device/qcom/common" revision="2501e5940ba69ece7654ff85611c76ae5bda299c"/>
|
||||
<project name="device-flame" path="device/t2m/flame" remote="b2g" revision="a4f6f31d1fe213ac935ca8ede7d05e47324101a4"/>
|
||||
<project name="device-flame" path="device/t2m/flame" remote="b2g" revision="41d3e221039d1c4486fc13ff26793a7a39226423"/>
|
||||
<project name="codeaurora_kernel_msm" path="kernel" remote="b2g" revision="0865bc4134b67220df4058625fba29305d6b10c3"/>
|
||||
<project name="kernel_lk" path="bootable/bootloader/lk" remote="b2g" revision="fda40423ffa573dc6cafd3780515010cb2a086be"/>
|
||||
<project name="platform_bootable_recovery" path="bootable/recovery" remote="b2g" revision="d5e53ed6f22fa06052351dc03510af9473af01ea"/>
|
||||
|
@ -1,9 +1,9 @@
|
||||
{
|
||||
"git": {
|
||||
"git_revision": "3fac3ed7b8c887351098ffc677769ddc36abb3d0",
|
||||
"git_revision": "a47e0c58dd1340a17be7cc96ccd90fcad15a922b",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "1a91ed6e76994d6279bd2cf81ba1416e86aa2014",
|
||||
"revision": "7f94267761d35a844b070ebae11dd667ab0ed68f",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
@ -17,10 +17,10 @@
|
||||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="3fac3ed7b8c887351098ffc677769ddc36abb3d0"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a47e0c58dd1340a17be7cc96ccd90fcad15a922b"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c490ae41c67f892232599f4ef049467a922b613e"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="f48264d4da9680b6e02c9d0459ac273308e21daf"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="cacd27c973f6c84d13a67adaf5d6fce4ae898e9e"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||
<!-- Stock Android things -->
|
||||
|
@ -15,7 +15,7 @@
|
||||
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="3fac3ed7b8c887351098ffc677769ddc36abb3d0"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="a47e0c58dd1340a17be7cc96ccd90fcad15a922b"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="c490ae41c67f892232599f4ef049467a922b613e"/>
|
||||
<project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
|
||||
@ -23,7 +23,7 @@
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<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="f48264d4da9680b6e02c9d0459ac273308e21daf"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="cacd27c973f6c84d13a67adaf5d6fce4ae898e9e"/>
|
||||
<!-- Stock Android things -->
|
||||
<project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
|
||||
<project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" path="prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" revision="337e0ef5e40f02a1ae59b90db0548976c70a7226"/>
|
||||
|
@ -1,10 +1,10 @@
|
||||
[
|
||||
{
|
||||
"clang_version": "r183744"
|
||||
"clang_version": "r241406"
|
||||
},
|
||||
{
|
||||
"size": 70206124,
|
||||
"digest": "a6b8046bd9485f9387dcb1c14b8d442822f02b1caa61b653e8b6cfd96906deadfb4b29809f2cd2b71f919b321d97dd2ebec6020c15f6d485f1641c0f710a762f",
|
||||
"size": 100307285,
|
||||
"digest": "4d147d0072a928945fc1e938f39a5d0a9d3c676399c09e092c8750b2f973cdbbebda8d94d4d05805fae74a5c49c54263dc22b8b443c23c9a0ae830a261d3cf30",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2",
|
||||
"unpack": true,
|
||||
|
@ -1,10 +1,10 @@
|
||||
[
|
||||
{
|
||||
"clang_version": "r183744"
|
||||
"clang_version": "r241406"
|
||||
},
|
||||
{
|
||||
"size": 70350828,
|
||||
"digest": "6cd04e8ec44c6fef159349c22bd0476891e4a2d46479f9586283eaf3305e42f79c720d40dfec0e78d8899c1651189b12e285de60862ffd0612b0dac7a0c336c6",
|
||||
"size": 100307285,
|
||||
"digest": "4d147d0072a928945fc1e938f39a5d0a9d3c676399c09e092c8750b2f973cdbbebda8d94d4d05805fae74a5c49c54263dc22b8b443c23c9a0ae830a261d3cf30",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2",
|
||||
"unpack": true
|
||||
|
@ -1,10 +1,10 @@
|
||||
[
|
||||
{
|
||||
"clang_version": "r183744"
|
||||
"clang_version": "r241406"
|
||||
},
|
||||
{
|
||||
"size": 59602619,
|
||||
"digest": "86662ebc0ef650490559005948c4f0cb015dad72c7cac43732c2bf2995247081e30c139cf8008d19670a0009fc302c4eee2676981ee3f9ff4a15c01af22b783b",
|
||||
"size": 86465808,
|
||||
"digest": "947eaaf11ac8cbe12e11b48c8b052721e018d31fb8ce20f8bf14b117b6623c56513b1422d8d9c8011bc0b0b985ef74d8f181e7200c6d7a05d79a1bce0d75ddee",
|
||||
"algorithm": "sha512",
|
||||
"filename": "clang.tar.bz2",
|
||||
"unpack": true
|
||||
|
@ -336,6 +336,26 @@ nsScriptSecurityManager::GetChannelResultPrincipal(nsIChannel* aChannel,
|
||||
NS_ADDREF(*aPrincipal = loadInfo->TriggeringPrincipal());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsSecurityFlags securityFlags = loadInfo->GetSecurityMode();
|
||||
if (securityFlags == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS ||
|
||||
securityFlags == nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS ||
|
||||
securityFlags == nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) {
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
nsresult rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(uri));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIPrincipal> triggeringPrincipal = loadInfo->TriggeringPrincipal();
|
||||
bool inheritForAboutBlank = loadInfo->GetAboutBlankInherits();
|
||||
|
||||
if (nsContentUtils::ChannelShouldInheritPrincipal(triggeringPrincipal,
|
||||
uri,
|
||||
inheritForAboutBlank,
|
||||
false)) {
|
||||
triggeringPrincipal.forget(aPrincipal);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
return GetChannelURIPrincipal(aChannel, aPrincipal);
|
||||
}
|
||||
|
@ -9715,7 +9715,8 @@ nsDocShell::InternalLoad(nsIURI* aURI,
|
||||
}
|
||||
if (IsFrame() && !isNewDocShell && !isTargetTopLevelDocShell) {
|
||||
NS_ASSERTION(requestingElement, "A frame but no DOM element!?");
|
||||
contentType = nsIContentPolicy::TYPE_SUBDOCUMENT;
|
||||
contentType = requestingElement->IsHTMLElement(nsGkAtoms::iframe) ?
|
||||
nsIContentPolicy::TYPE_INTERNAL_IFRAME : nsIContentPolicy::TYPE_INTERNAL_FRAME;
|
||||
} else {
|
||||
contentType = nsIContentPolicy::TYPE_DOCUMENT;
|
||||
}
|
||||
@ -9836,13 +9837,9 @@ nsDocShell::InternalLoad(nsIURI* aURI,
|
||||
if (aURI) {
|
||||
aURI->GetSpec(spec);
|
||||
}
|
||||
nsAutoString features;
|
||||
if (mInPrivateBrowsing) {
|
||||
features.AssignLiteral("private");
|
||||
}
|
||||
rv = win->OpenNoNavigate(NS_ConvertUTF8toUTF16(spec),
|
||||
name, // window name
|
||||
features,
|
||||
EmptyString(), // Features
|
||||
getter_AddRefs(newWin));
|
||||
|
||||
// In some cases the Open call doesn't actually result in a new
|
||||
|
@ -9,3 +9,4 @@ support-files =
|
||||
|
||||
[browser_bug343515.js]
|
||||
skip-if = e10s # Bug ?????? - test directly touches content (tries to QI the content window)
|
||||
[browser_test-content-chromeflags.js]
|
||||
|
45
docshell/test/navigation/browser_test-content-chromeflags.js
Normal file
45
docshell/test/navigation/browser_test-content-chromeflags.js
Normal file
@ -0,0 +1,45 @@
|
||||
const TEST_PAGE = `data:text/html,<html><body><a href="about:blank" target="_blank">Test</a></body></html>`;
|
||||
const CHROME_ALL = Ci.nsIWebBrowserChrome.CHROME_ALL;
|
||||
const CHROME_REMOTE_WINDOW = Ci.nsIWebBrowserChrome.CHROME_REMOTE_WINDOW;
|
||||
|
||||
/**
|
||||
* Tests that when we open new browser windows from content they
|
||||
* get the full browser chrome.
|
||||
*/
|
||||
add_task(function* () {
|
||||
// Make sure that the window.open call will open a new
|
||||
// window instead of a new tab.
|
||||
yield new Promise(resolve => {
|
||||
SpecialPowers.pushPrefEnv({
|
||||
"set": [
|
||||
["browser.link.open_newwindow", 2],
|
||||
]
|
||||
}, resolve);
|
||||
});
|
||||
|
||||
yield BrowserTestUtils.withNewTab({
|
||||
gBrowser,
|
||||
url: TEST_PAGE
|
||||
}, function*(browser) {
|
||||
let openedPromise = BrowserTestUtils.waitForNewWindow();
|
||||
BrowserTestUtils.synthesizeMouse("a", 0, 0, {}, browser);
|
||||
let win = yield openedPromise;
|
||||
|
||||
let chromeFlags = win.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIDocShellTreeItem)
|
||||
.treeOwner
|
||||
.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIXULWindow)
|
||||
.chromeFlags;
|
||||
|
||||
// In the multi-process case, the new window will have the
|
||||
// CHROME_REMOTE_WINDOW flag set.
|
||||
const EXPECTED = gMultiProcessBrowser ? CHROME_ALL | CHROME_REMOTE_WINDOW
|
||||
: CHROME_ALL;
|
||||
|
||||
is(chromeFlags, EXPECTED, "Window should have opened with all chrome");
|
||||
|
||||
BrowserTestUtils.closeWindow(win);
|
||||
});
|
||||
});
|
@ -521,23 +521,20 @@ AudioChannelService::Observe(nsISupports* aSubject, const char* aTopic,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
struct RefreshAgentsVolumeData
|
||||
{
|
||||
explicit RefreshAgentsVolumeData(nsPIDOMWindow* aWindow)
|
||||
: mWindow(aWindow)
|
||||
{}
|
||||
|
||||
nsPIDOMWindow* mWindow;
|
||||
nsTArray<nsRefPtr<AudioChannelAgent>> mAgents;
|
||||
};
|
||||
|
||||
void
|
||||
AudioChannelService::RefreshAgentsVolume(nsPIDOMWindow* aWindow)
|
||||
{
|
||||
MOZ_ASSERT(aWindow);
|
||||
MOZ_ASSERT(aWindow->IsOuterWindow());
|
||||
|
||||
AudioChannelWindow* winData = GetWindowData(aWindow->WindowID());
|
||||
nsCOMPtr<nsIDOMWindow> topWindow;
|
||||
aWindow->GetScriptableTop(getter_AddRefs(topWindow));
|
||||
nsCOMPtr<nsPIDOMWindow> pTopWindow = do_QueryInterface(topWindow);
|
||||
if (!pTopWindow) {
|
||||
return;
|
||||
}
|
||||
|
||||
AudioChannelWindow* winData = GetWindowData(pTopWindow->WindowID());
|
||||
if (!winData) {
|
||||
return;
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "mozilla/dom/BlobBinding.h"
|
||||
#include "mozilla/dom/Exceptions.h"
|
||||
#include "mozilla/dom/File.h"
|
||||
#include "mozilla/dom/StructuredCloneHelper.h"
|
||||
#include "mozilla/dom/ToJSValue.h"
|
||||
#include "mozilla/Maybe.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
@ -74,87 +75,6 @@ ConsoleStructuredCloneData
|
||||
* It's not the best, but at least we are able to show something.
|
||||
*/
|
||||
|
||||
// This method is called by the Structured Clone Algorithm when some data has
|
||||
// to be read.
|
||||
static JSObject*
|
||||
ConsoleStructuredCloneCallbacksRead(JSContext* aCx,
|
||||
JSStructuredCloneReader* /* unused */,
|
||||
uint32_t aTag, uint32_t aIndex,
|
||||
void* aClosure)
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
ConsoleStructuredCloneData* data =
|
||||
static_cast<ConsoleStructuredCloneData*>(aClosure);
|
||||
MOZ_ASSERT(data);
|
||||
|
||||
if (aTag == CONSOLE_TAG_BLOB) {
|
||||
MOZ_ASSERT(data->mBlobs.Length() > aIndex);
|
||||
|
||||
JS::Rooted<JS::Value> val(aCx);
|
||||
{
|
||||
nsRefPtr<Blob> blob =
|
||||
Blob::Create(data->mParent, data->mBlobs.ElementAt(aIndex));
|
||||
if (!ToJSValue(aCx, blob, &val)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return &val.toObject();
|
||||
}
|
||||
|
||||
MOZ_CRASH("No other tags are supported.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// This method is called by the Structured Clone Algorithm when some data has
|
||||
// to be written.
|
||||
static bool
|
||||
ConsoleStructuredCloneCallbacksWrite(JSContext* aCx,
|
||||
JSStructuredCloneWriter* aWriter,
|
||||
JS::Handle<JSObject*> aObj,
|
||||
void* aClosure)
|
||||
{
|
||||
ConsoleStructuredCloneData* data =
|
||||
static_cast<ConsoleStructuredCloneData*>(aClosure);
|
||||
MOZ_ASSERT(data);
|
||||
|
||||
nsRefPtr<Blob> blob;
|
||||
if (NS_SUCCEEDED(UNWRAP_OBJECT(Blob, aObj, blob)) &&
|
||||
blob->Impl()->MayBeClonedToOtherThreads()) {
|
||||
if (!JS_WriteUint32Pair(aWriter, CONSOLE_TAG_BLOB, data->mBlobs.Length())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
data->mBlobs.AppendElement(blob->Impl());
|
||||
return true;
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> value(aCx, JS::ObjectOrNullValue(aObj));
|
||||
JS::Rooted<JSString*> jsString(aCx, JS::ToString(aCx, value));
|
||||
if (!jsString) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!JS_WriteString(aWriter, jsString)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
ConsoleStructuredCloneCallbacksError(JSContext* /* aCx */,
|
||||
uint32_t /* aErrorId */)
|
||||
{
|
||||
NS_WARNING("Failed to clone data for the Console API in workers.");
|
||||
}
|
||||
|
||||
static const JSStructuredCloneCallbacks gConsoleCallbacks = {
|
||||
ConsoleStructuredCloneCallbacksRead,
|
||||
ConsoleStructuredCloneCallbacksWrite,
|
||||
ConsoleStructuredCloneCallbacksError
|
||||
};
|
||||
|
||||
class ConsoleCallData final
|
||||
{
|
||||
public:
|
||||
@ -274,6 +194,7 @@ private:
|
||||
|
||||
class ConsoleRunnable : public nsRunnable
|
||||
, public WorkerFeature
|
||||
, public StructuredCloneHelperInternal
|
||||
{
|
||||
public:
|
||||
explicit ConsoleRunnable(Console* aConsole)
|
||||
@ -431,10 +352,67 @@ protected:
|
||||
RunConsole(JSContext* aCx, nsPIDOMWindow* aOuterWindow,
|
||||
nsPIDOMWindow* aInnerWindow) = 0;
|
||||
|
||||
virtual JSObject* ReadCallback(JSContext* aCx,
|
||||
JSStructuredCloneReader* aReader,
|
||||
uint32_t aTag,
|
||||
uint32_t aIndex) override
|
||||
{
|
||||
AssertIsOnMainThread();
|
||||
|
||||
if (aTag == CONSOLE_TAG_BLOB) {
|
||||
MOZ_ASSERT(mClonedData.mBlobs.Length() > aIndex);
|
||||
|
||||
JS::Rooted<JS::Value> val(aCx);
|
||||
{
|
||||
nsRefPtr<Blob> blob =
|
||||
Blob::Create(mClonedData.mParent, mClonedData.mBlobs.ElementAt(aIndex));
|
||||
if (!ToJSValue(aCx, blob, &val)) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
return &val.toObject();
|
||||
}
|
||||
|
||||
MOZ_CRASH("No other tags are supported.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
virtual bool WriteCallback(JSContext* aCx,
|
||||
JSStructuredCloneWriter* aWriter,
|
||||
JS::Handle<JSObject*> aObj) override
|
||||
{
|
||||
nsRefPtr<Blob> blob;
|
||||
if (NS_SUCCEEDED(UNWRAP_OBJECT(Blob, aObj, blob)) &&
|
||||
blob->Impl()->MayBeClonedToOtherThreads()) {
|
||||
if (!JS_WriteUint32Pair(aWriter, CONSOLE_TAG_BLOB,
|
||||
mClonedData.mBlobs.Length())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mClonedData.mBlobs.AppendElement(blob->Impl());
|
||||
return true;
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> value(aCx, JS::ObjectOrNullValue(aObj));
|
||||
JS::Rooted<JSString*> jsString(aCx, JS::ToString(aCx, value));
|
||||
if (!jsString) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!JS_WriteString(aWriter, jsString)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
WorkerPrivate* mWorkerPrivate;
|
||||
|
||||
// This must be released on the worker thread.
|
||||
nsRefPtr<Console> mConsole;
|
||||
|
||||
ConsoleStructuredCloneData mClonedData;
|
||||
};
|
||||
|
||||
// This runnable appends a CallData object into the Console queue running on
|
||||
@ -499,7 +477,7 @@ private:
|
||||
|
||||
JS::Rooted<JS::Value> value(aCx, JS::ObjectValue(*arguments));
|
||||
|
||||
if (!mArguments.write(aCx, value, &gConsoleCallbacks, &mData)) {
|
||||
if (!Write(aCx, value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -537,12 +515,12 @@ private:
|
||||
}
|
||||
|
||||
// Now we could have the correct window (if we are not window-less).
|
||||
mData.mParent = aInnerWindow;
|
||||
mClonedData.mParent = aInnerWindow;
|
||||
|
||||
ProcessCallData(aCx);
|
||||
mCallData->CleanupJSObjects();
|
||||
|
||||
mData.mParent = nullptr;
|
||||
mClonedData.mParent = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
@ -552,7 +530,7 @@ private:
|
||||
ClearException ce(aCx);
|
||||
|
||||
JS::Rooted<JS::Value> argumentsValue(aCx);
|
||||
if (!mArguments.read(aCx, &argumentsValue, &gConsoleCallbacks, &mData)) {
|
||||
if (!Read(aCx, &argumentsValue)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -582,9 +560,6 @@ private:
|
||||
}
|
||||
|
||||
nsRefPtr<ConsoleCallData> mCallData;
|
||||
|
||||
JSAutoStructuredCloneBuffer mArguments;
|
||||
ConsoleStructuredCloneData mData;
|
||||
};
|
||||
|
||||
// This runnable calls ProfileMethod() on the console on the main-thread.
|
||||
@ -629,7 +604,7 @@ private:
|
||||
|
||||
JS::Rooted<JS::Value> value(aCx, JS::ObjectValue(*arguments));
|
||||
|
||||
if (!mBuffer.write(aCx, value, &gConsoleCallbacks, &mData)) {
|
||||
if (!Write(aCx, value)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -644,11 +619,11 @@ private:
|
||||
ClearException ce(aCx);
|
||||
|
||||
// Now we could have the correct window (if we are not window-less).
|
||||
mData.mParent = aInnerWindow;
|
||||
mClonedData.mParent = aInnerWindow;
|
||||
|
||||
JS::Rooted<JS::Value> argumentsValue(aCx);
|
||||
bool ok = mBuffer.read(aCx, &argumentsValue, &gConsoleCallbacks, &mData);
|
||||
mData.mParent = nullptr;
|
||||
bool ok = Read(aCx, &argumentsValue);
|
||||
mClonedData.mParent = nullptr;
|
||||
|
||||
if (!ok) {
|
||||
return;
|
||||
@ -682,9 +657,6 @@ private:
|
||||
|
||||
nsString mAction;
|
||||
Sequence<JS::Value> mArguments;
|
||||
|
||||
JSAutoStructuredCloneBuffer mBuffer;
|
||||
ConsoleStructuredCloneData mData;
|
||||
};
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(Console)
|
||||
|
@ -1059,10 +1059,12 @@ Element::CreateShadowRoot(ErrorResult& aError)
|
||||
return shadowRoot.forget();
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION(DestinationInsertionPointList, mParent, mDestinationPoints)
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(DestinationInsertionPointList, mParent,
|
||||
mDestinationPoints)
|
||||
|
||||
NS_INTERFACE_TABLE_HEAD(DestinationInsertionPointList)
|
||||
NS_INTERFACE_TABLE(DestinationInsertionPointList, nsINodeList)
|
||||
NS_WRAPPERCACHE_INTERFACE_TABLE_ENTRY
|
||||
NS_INTERFACE_TABLE(DestinationInsertionPointList, nsINodeList, nsIDOMNodeList)
|
||||
NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(DestinationInsertionPointList)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
@ -1678,7 +1680,7 @@ Element::UnbindFromTree(bool aDeep, bool aNullParent)
|
||||
nsContentUtils::eDOM_PROPERTIES,
|
||||
"RemovedFullScreenElement");
|
||||
// Fully exit full-screen.
|
||||
nsIDocument::ExitFullscreen(OwnerDoc(), /* async */ false);
|
||||
nsIDocument::ExitFullscreenInDocTree(OwnerDoc());
|
||||
}
|
||||
if (HasPointerLock()) {
|
||||
nsIDocument::UnlockPointer();
|
||||
|
@ -1301,7 +1301,7 @@ public:
|
||||
explicit DestinationInsertionPointList(Element* aElement);
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(DestinationInsertionPointList)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DestinationInsertionPointList)
|
||||
|
||||
// nsIDOMNodeList
|
||||
NS_DECL_NSIDOMNODELIST
|
||||
|
158
dom/base/StructuredCloneHelper.cpp
Normal file
158
dom/base/StructuredCloneHelper.cpp
Normal file
@ -0,0 +1,158 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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 "StructuredCloneHelper.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
namespace {
|
||||
|
||||
JSObject*
|
||||
StructuredCloneCallbacksRead(JSContext* aCx,
|
||||
JSStructuredCloneReader* aReader,
|
||||
uint32_t aTag, uint32_t aIndex,
|
||||
void* aClosure)
|
||||
{
|
||||
StructuredCloneHelperInternal* helper =
|
||||
static_cast<StructuredCloneHelperInternal*>(aClosure);
|
||||
MOZ_ASSERT(helper);
|
||||
return helper->ReadCallback(aCx, aReader, aTag, aIndex);
|
||||
}
|
||||
|
||||
bool
|
||||
StructuredCloneCallbacksWrite(JSContext* aCx,
|
||||
JSStructuredCloneWriter* aWriter,
|
||||
JS::Handle<JSObject*> aObj,
|
||||
void* aClosure)
|
||||
{
|
||||
StructuredCloneHelperInternal* helper =
|
||||
static_cast<StructuredCloneHelperInternal*>(aClosure);
|
||||
MOZ_ASSERT(helper);
|
||||
return helper->WriteCallback(aCx, aWriter, aObj);
|
||||
}
|
||||
|
||||
bool
|
||||
StructuredCloneCallbacksReadTransfer(JSContext* aCx,
|
||||
JSStructuredCloneReader* aReader,
|
||||
uint32_t aTag,
|
||||
void* aContent,
|
||||
uint64_t aExtraData,
|
||||
void* aClosure,
|
||||
JS::MutableHandleObject aReturnObject)
|
||||
{
|
||||
StructuredCloneHelperInternal* helper =
|
||||
static_cast<StructuredCloneHelperInternal*>(aClosure);
|
||||
MOZ_ASSERT(helper);
|
||||
return helper->ReadTransferCallback(aCx, aReader, aTag, aContent,
|
||||
aExtraData, aReturnObject);
|
||||
}
|
||||
|
||||
bool
|
||||
StructuredCloneCallbacksWriteTransfer(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aObj,
|
||||
void* aClosure,
|
||||
// Output:
|
||||
uint32_t* aTag,
|
||||
JS::TransferableOwnership* aOwnership,
|
||||
void** aContent,
|
||||
uint64_t* aExtraData)
|
||||
{
|
||||
StructuredCloneHelperInternal* helper =
|
||||
static_cast<StructuredCloneHelperInternal*>(aClosure);
|
||||
MOZ_ASSERT(helper);
|
||||
return helper->WriteTransferCallback(aCx, aObj, aTag, aOwnership, aContent,
|
||||
aExtraData);
|
||||
}
|
||||
|
||||
void
|
||||
StructuredCloneCallbacksFreeTransfer(uint32_t aTag,
|
||||
JS::TransferableOwnership aOwnership,
|
||||
void* aContent,
|
||||
uint64_t aExtraData,
|
||||
void* aClosure)
|
||||
{
|
||||
StructuredCloneHelperInternal* helper =
|
||||
static_cast<StructuredCloneHelperInternal*>(aClosure);
|
||||
MOZ_ASSERT(helper);
|
||||
return helper->FreeTransferCallback(aTag, aOwnership, aContent, aExtraData);
|
||||
}
|
||||
|
||||
void
|
||||
StructuredCloneCallbacksError(JSContext* aCx,
|
||||
uint32_t aErrorId)
|
||||
{
|
||||
NS_WARNING("Failed to clone data for the Console API in workers.");
|
||||
}
|
||||
|
||||
const JSStructuredCloneCallbacks gCallbacks = {
|
||||
StructuredCloneCallbacksRead,
|
||||
StructuredCloneCallbacksWrite,
|
||||
StructuredCloneCallbacksError,
|
||||
StructuredCloneCallbacksReadTransfer,
|
||||
StructuredCloneCallbacksWriteTransfer,
|
||||
StructuredCloneCallbacksFreeTransfer
|
||||
};
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
bool
|
||||
StructuredCloneHelperInternal::Write(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue)
|
||||
{
|
||||
MOZ_ASSERT(!mBuffer, "Double Write is not allowed");
|
||||
|
||||
mBuffer = new JSAutoStructuredCloneBuffer(&gCallbacks, this);
|
||||
return mBuffer->write(aCx, aValue, &gCallbacks, this);
|
||||
}
|
||||
|
||||
bool
|
||||
StructuredCloneHelperInternal::Read(JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aValue)
|
||||
{
|
||||
MOZ_ASSERT(mBuffer, "Read() without Write() is not allowed.");
|
||||
|
||||
bool ok = mBuffer->read(aCx, aValue, &gCallbacks, this);
|
||||
mBuffer = nullptr;
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool
|
||||
StructuredCloneHelperInternal::ReadTransferCallback(JSContext* aCx,
|
||||
JSStructuredCloneReader* aReader,
|
||||
uint32_t aTag,
|
||||
void* aContent,
|
||||
uint64_t aExtraData,
|
||||
JS::MutableHandleObject aReturnObject)
|
||||
{
|
||||
MOZ_CRASH("Nothing to read.");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
StructuredCloneHelperInternal::WriteTransferCallback(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aObj,
|
||||
uint32_t* aTag,
|
||||
JS::TransferableOwnership* aOwnership,
|
||||
void** aContent,
|
||||
uint64_t* aExtraData)
|
||||
{
|
||||
// No transfers are supported by default.
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
StructuredCloneHelperInternal::FreeTransferCallback(uint32_t aTag,
|
||||
JS::TransferableOwnership aOwnership,
|
||||
void* aContent,
|
||||
uint64_t aExtraData)
|
||||
{
|
||||
MOZ_CRASH("Nothing to free.");
|
||||
}
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
75
dom/base/StructuredCloneHelper.h
Normal file
75
dom/base/StructuredCloneHelper.h
Normal file
@ -0,0 +1,75 @@
|
||||
/* -*- 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_StructuredCloneHelper_h
|
||||
#define mozilla_dom_StructuredCloneHelper_h
|
||||
|
||||
#include "js/StructuredClone.h"
|
||||
#include "nsAutoPtr.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class StructuredCloneHelperInternal
|
||||
{
|
||||
public:
|
||||
// These methods should be implemented in order to clone data.
|
||||
// Read more documentation in js/public/StructuredClone.h.
|
||||
|
||||
virtual JSObject* ReadCallback(JSContext* aCx,
|
||||
JSStructuredCloneReader* aReader,
|
||||
uint32_t aTag,
|
||||
uint32_t aIndex) = 0;
|
||||
|
||||
virtual bool WriteCallback(JSContext* aCx,
|
||||
JSStructuredCloneWriter* aWriter,
|
||||
JS::Handle<JSObject*> aObj) = 0;
|
||||
|
||||
// If these 3 methods are not implement, transfering objects will not be
|
||||
// allowed.
|
||||
|
||||
virtual bool
|
||||
ReadTransferCallback(JSContext* aCx,
|
||||
JSStructuredCloneReader* aReader,
|
||||
uint32_t aTag,
|
||||
void* aContent,
|
||||
uint64_t aExtraData,
|
||||
JS::MutableHandleObject aReturnObject);
|
||||
|
||||
virtual bool
|
||||
WriteTransferCallback(JSContext* aCx,
|
||||
JS::Handle<JSObject*> aObj,
|
||||
// Output:
|
||||
uint32_t* aTag,
|
||||
JS::TransferableOwnership* aOwnership,
|
||||
void** aContent,
|
||||
uint64_t* aExtraData);
|
||||
|
||||
virtual void
|
||||
FreeTransferCallback(uint32_t aTag,
|
||||
JS::TransferableOwnership aOwnership,
|
||||
void* aContent,
|
||||
uint64_t aExtraData);
|
||||
|
||||
// These methods are what you should use.
|
||||
|
||||
bool Write(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue);
|
||||
|
||||
bool Write(JSContext* aCx,
|
||||
JS::Handle<JS::Value> aValue,
|
||||
JS::Handle<JS::Value> aTransfer);
|
||||
|
||||
bool Read(JSContext* aCx,
|
||||
JS::MutableHandle<JS::Value> aValue);
|
||||
|
||||
protected:
|
||||
nsAutoPtr<JSAutoStructuredCloneBuffer> mBuffer;
|
||||
};
|
||||
|
||||
} // dom namespace
|
||||
} // mozilla namespace
|
||||
|
||||
#endif // mozilla_dom_StructuredCloneHelper_h
|
@ -195,6 +195,7 @@ EXPORTS.mozilla.dom += [
|
||||
'ScreenOrientation.h',
|
||||
'ScriptSettings.h',
|
||||
'ShadowRoot.h',
|
||||
'StructuredCloneHelper.h',
|
||||
'StructuredCloneTags.h',
|
||||
'StyleSheetList.h',
|
||||
'SubtleCrypto.h',
|
||||
@ -332,6 +333,7 @@ UNIFIED_SOURCES += [
|
||||
'SameProcessMessageQueue.cpp',
|
||||
'ScriptSettings.cpp',
|
||||
'ShadowRoot.cpp',
|
||||
'StructuredCloneHelper.cpp',
|
||||
'StyleSheetList.cpp',
|
||||
'SubtleCrypto.cpp',
|
||||
'Text.cpp',
|
||||
|
@ -902,7 +902,7 @@ nsDOMClassInfo::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMClassInfo::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, jsval *vp,
|
||||
JSObject *obj, jsid id, JS::Value *vp,
|
||||
bool *_retval)
|
||||
{
|
||||
NS_WARNING("nsDOMClassInfo::GetProperty Don't call me!");
|
||||
@ -912,7 +912,7 @@ nsDOMClassInfo::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsDOMClassInfo::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JSObject *obj, jsid id, jsval *vp,
|
||||
JSObject *obj, jsid id, JS::Value *vp,
|
||||
bool *_retval)
|
||||
{
|
||||
NS_WARNING("nsDOMClassInfo::SetProperty Don't call me!");
|
||||
@ -1339,7 +1339,7 @@ public:
|
||||
bool *_retval);
|
||||
|
||||
nsresult HasInstance(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
|
||||
JS::Handle<JSObject*> obj, const jsval &val, bool *bp,
|
||||
JS::Handle<JSObject*> obj, const JS::Value &val, bool *bp,
|
||||
bool *_retval);
|
||||
|
||||
nsresult ResolveInterfaceConstants(JSContext *cx, JS::Handle<JSObject*> obj);
|
||||
@ -1499,7 +1499,7 @@ nsDOMConstructor::Construct(nsIXPConnectWrappedNative *wrapper, JSContext * cx,
|
||||
nsresult
|
||||
nsDOMConstructor::HasInstance(nsIXPConnectWrappedNative *wrapper,
|
||||
JSContext * cx, JS::Handle<JSObject*> obj,
|
||||
const jsval &v, bool *bp, bool *_retval)
|
||||
const JS::Value &v, bool *bp, bool *_retval)
|
||||
|
||||
{
|
||||
// No need to look these up in the hash.
|
||||
|
@ -3212,7 +3212,7 @@ nsDOMWindowUtils::ExitFullscreen()
|
||||
nsCOMPtr<nsIDocument> doc = GetDocument();
|
||||
NS_ENSURE_STATE(doc);
|
||||
|
||||
nsIDocument::ExitFullscreen(doc, /* async */ false);
|
||||
nsIDocument::ExitFullscreenInDocTree(doc);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -9358,7 +9358,7 @@ nsDocument::OnPageHide(bool aPersisted,
|
||||
// doctree by the time OnPageHide() is called, so we must store a
|
||||
// reference to the root (in nsDocument::mFullscreenRoot) since we can't
|
||||
// just traverse the doctree to get the root.
|
||||
nsIDocument::ExitFullscreen(this, /* async */ false);
|
||||
nsIDocument::ExitFullscreenInDocTree(this);
|
||||
|
||||
// Since the document is removed from the doctree before OnPageHide() is
|
||||
// called, ExitFullscreen() can't traverse from the root down to *this*
|
||||
@ -11122,31 +11122,43 @@ SetWindowFullScreen(nsIDocument* aDoc, bool aValue, gfx::VRHMDInfo *aVRHMD = nul
|
||||
nsContentUtils::AddScriptRunner(new nsSetWindowFullScreen(aDoc, aValue, aVRHMD));
|
||||
}
|
||||
|
||||
class nsCallExitFullscreen : public nsRunnable {
|
||||
static void
|
||||
AskWindowToExitFullscreen(nsIDocument* aDoc)
|
||||
{
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Content) {
|
||||
nsContentUtils::DispatchEventOnlyToChrome(
|
||||
aDoc, ToSupports(aDoc), NS_LITERAL_STRING("MozDOMFullscreen:Exit"),
|
||||
/* Bubbles */ true, /* Cancelable */ false,
|
||||
/* DefaultAction */ nullptr);
|
||||
} else {
|
||||
SetWindowFullScreen(aDoc, false);
|
||||
}
|
||||
}
|
||||
|
||||
class nsCallExitFullscreen : public nsRunnable
|
||||
{
|
||||
public:
|
||||
explicit nsCallExitFullscreen(nsIDocument* aDoc)
|
||||
: mDoc(aDoc) {}
|
||||
NS_IMETHOD Run()
|
||||
|
||||
NS_IMETHOD Run() override final
|
||||
{
|
||||
nsDocument::ExitFullscreen(mDoc);
|
||||
if (!mDoc) {
|
||||
FullscreenRoots::ForEach(&AskWindowToExitFullscreen);
|
||||
} else {
|
||||
AskWindowToExitFullscreen(mDoc);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsIDocument> mDoc;
|
||||
};
|
||||
|
||||
/* static */
|
||||
void
|
||||
nsIDocument::ExitFullscreen(nsIDocument* aDoc, bool aRunAsync)
|
||||
/* static */ void
|
||||
nsIDocument::AsyncExitFullscreen(nsIDocument* aDoc)
|
||||
{
|
||||
if (aDoc && !aDoc->IsFullScreenDoc()) {
|
||||
return;
|
||||
}
|
||||
if (aRunAsync) {
|
||||
NS_DispatchToCurrentThread(new nsCallExitFullscreen(aDoc));
|
||||
return;
|
||||
}
|
||||
nsDocument::ExitFullscreen(aDoc);
|
||||
NS_DispatchToCurrentThread(new nsCallExitFullscreen(aDoc));
|
||||
}
|
||||
|
||||
static bool
|
||||
@ -11193,16 +11205,16 @@ ResetFullScreen(nsIDocument* aDocument, void* aData)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
ExitFullscreenInDocTree(nsIDocument* aMaybeNotARootDoc)
|
||||
/* static */ void
|
||||
nsIDocument::ExitFullscreenInDocTree(nsIDocument* aMaybeNotARootDoc)
|
||||
{
|
||||
MOZ_ASSERT(aMaybeNotARootDoc);
|
||||
|
||||
// Unlock the pointer
|
||||
UnlockPointer();
|
||||
|
||||
nsCOMPtr<nsIDocument> root = aMaybeNotARootDoc->GetFullscreenRoot();
|
||||
NS_ASSERTION(root, "Should have root when in fullscreen!");
|
||||
if (!root) {
|
||||
return;
|
||||
}
|
||||
if (!root->IsFullScreenDoc()) {
|
||||
if (!root || !root->IsFullScreenDoc()) {
|
||||
// If a document was detached before exiting from fullscreen, it is
|
||||
// possible that the root had left fullscreen state. In this case,
|
||||
// we would not get anything from the ResetFullScreen() call. Root's
|
||||
@ -11246,24 +11258,6 @@ ExitFullscreenInDocTree(nsIDocument* aMaybeNotARootDoc)
|
||||
SetWindowFullScreen(root, false);
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
nsDocument::ExitFullscreen(nsIDocument* aDoc)
|
||||
{
|
||||
// Unlock the pointer
|
||||
UnlockPointer();
|
||||
|
||||
if (aDoc) {
|
||||
ExitFullscreenInDocTree(aDoc);
|
||||
return;
|
||||
}
|
||||
|
||||
// Clear fullscreen stacks in all fullscreen roots' descendant documents.
|
||||
FullscreenRoots::ForEach(&ExitFullscreenInDocTree);
|
||||
NS_ASSERTION(FullscreenRoots::IsEmpty(),
|
||||
"Should have exited all fullscreen roots from fullscreen");
|
||||
}
|
||||
|
||||
bool
|
||||
GetFullscreenLeaf(nsIDocument* aDoc, void* aData)
|
||||
{
|
||||
@ -11318,14 +11312,7 @@ nsDocument::RestorePreviousFullScreenState()
|
||||
if (exitingFullscreen) {
|
||||
// If we are fully exiting fullscreen, don't touch anything here,
|
||||
// just wait for the window to get out from fullscreen first.
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Content) {
|
||||
nsContentUtils::DispatchEventOnlyToChrome(
|
||||
this, ToSupports(this), NS_LITERAL_STRING("MozDOMFullscreen:Exit"),
|
||||
/* Bubbles */ true, /* Cancelable */ false,
|
||||
/* DefaultAction */ nullptr);
|
||||
} else {
|
||||
SetWindowFullScreen(this, false);
|
||||
}
|
||||
AskWindowToExitFullscreen(this);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1242,8 +1242,6 @@ public:
|
||||
//
|
||||
already_AddRefed<nsSimpleContentList> BlockedTrackingNodes() const;
|
||||
|
||||
static void ExitFullscreen(nsIDocument* aDoc);
|
||||
|
||||
// Do the "fullscreen element ready check" from the fullscreen spec.
|
||||
// It returns true if the given element is allowed to go into fullscreen.
|
||||
bool FullscreenElementReadyCheck(Element* aElement, bool aWasCallerChrome);
|
||||
|
@ -1249,7 +1249,7 @@ nsFocusManager::SetFocusInner(nsIContent* aNewContent, int32_t aFlags,
|
||||
contentToFocus->OwnerDoc(),
|
||||
nsContentUtils::eDOM_PROPERTIES,
|
||||
"FocusedWindowedPluginWhileFullScreen");
|
||||
nsIDocument::ExitFullscreen(contentToFocus->OwnerDoc(), /* async */ true);
|
||||
nsIDocument::AsyncExitFullscreen(contentToFocus->OwnerDoc());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -6308,11 +6308,9 @@ FinishDOMFullscreenChange(nsIDocument* aDoc, bool aInDOMFullscreen)
|
||||
// Ask the document to handle any pending DOM fullscreen change.
|
||||
nsIDocument::HandlePendingFullscreenRequests(aDoc);
|
||||
} else {
|
||||
// Force exit from DOM full-screen mode. This is so that if we're in
|
||||
// DOM full-screen mode and the user exits full-screen mode with
|
||||
// the browser full-screen mode toggle keyboard-shortcut, we'll detect
|
||||
// that and leave DOM API full-screen mode too.
|
||||
nsIDocument::ExitFullscreen(aDoc, /* async */ false);
|
||||
// If the window is leaving fullscreen state, also ask the document
|
||||
// to exit from DOM Fullscreen.
|
||||
nsIDocument::ExitFullscreenInDocTree(aDoc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1165,24 +1165,29 @@ public:
|
||||
virtual void SetApprovedForFullscreen(bool aIsApproved) = 0;
|
||||
|
||||
/**
|
||||
* Exits documents out of DOM fullscreen mode.
|
||||
* Synchronously cleans up the fullscreen state on the given document.
|
||||
*
|
||||
* If aDocument is null, all fullscreen documents in all browser windows
|
||||
* exit fullscreen.
|
||||
* Calling this without performing fullscreen transition could lead
|
||||
* to undesired effect (the transition happens after document state
|
||||
* flips), hence it should only be called either by nsGlobalWindow
|
||||
* when we have performed the transition, or when it is necessary to
|
||||
* clean up the state immediately. Otherwise, AsyncExitFullscreen()
|
||||
* should be called instead.
|
||||
*
|
||||
* If aDocument is non null, all documents from aDocument's fullscreen root
|
||||
* to the fullscreen leaf exit fullscreen.
|
||||
*
|
||||
* Note that the fullscreen leaf is the bottom-most document which is
|
||||
* fullscreen, it may have non-fullscreen child documents. The fullscreen
|
||||
* root is normally the chrome document.
|
||||
*
|
||||
* If aRunAsync is true, fullscreen is executed asynchronously.
|
||||
*
|
||||
* Note if aDocument is not fullscreen this function has no effect, even if
|
||||
* aDocument has fullscreen ancestors.
|
||||
* aDocument must not be null.
|
||||
*/
|
||||
static void ExitFullscreen(nsIDocument* aDocument, bool aRunAsync);
|
||||
static void ExitFullscreenInDocTree(nsIDocument* aDocument);
|
||||
|
||||
/**
|
||||
* Ask the document to exit fullscreen state asynchronously.
|
||||
*
|
||||
* Different from ExitFullscreenInDocTree(), this allows the window
|
||||
* to perform fullscreen transition first if any.
|
||||
*
|
||||
* If aDocument is null, it will exit fullscreen from all documents
|
||||
* in all windows.
|
||||
*/
|
||||
static void AsyncExitFullscreen(nsIDocument* aDocument);
|
||||
|
||||
/**
|
||||
* Handles one single fullscreen request, updates `aHandled` if the request
|
||||
|
@ -1512,6 +1512,15 @@ nsImageLoadingContent::TrackImage(imgIRequest* aImage)
|
||||
nsIDocument* doc = GetOurCurrentDoc();
|
||||
if (doc && (mFrameCreateCalled || GetOurPrimaryFrame()) &&
|
||||
(mVisibleCount > 0)) {
|
||||
|
||||
if (mVisibleCount == 1) {
|
||||
// Since we're becoming visible, request a decode.
|
||||
nsImageFrame* f = do_QueryFrame(GetOurPrimaryFrame());
|
||||
if (f) {
|
||||
f->MaybeDecodeForPredictedSize();
|
||||
}
|
||||
}
|
||||
|
||||
if (aImage == mCurrentRequest && !(mCurrentRequestFlags & REQUEST_IS_TRACKED)) {
|
||||
mCurrentRequestFlags |= REQUEST_IS_TRACKED;
|
||||
doc->AddImage(mCurrentRequest);
|
||||
|
@ -1485,8 +1485,10 @@ nsObjectLoadingContent::CheckLoadPolicy(int16_t *aContentPolicy)
|
||||
|
||||
nsIDocument* doc = thisContent->OwnerDoc();
|
||||
|
||||
nsContentPolicyType contentPolicyType = GetContentPolicyType();
|
||||
|
||||
*aContentPolicy = nsIContentPolicy::ACCEPT;
|
||||
nsresult rv = NS_CheckContentLoadPolicy(nsIContentPolicy::TYPE_OBJECT,
|
||||
nsresult rv = NS_CheckContentLoadPolicy(contentPolicyType,
|
||||
mURI,
|
||||
doc->NodePrincipal(),
|
||||
thisContent,
|
||||
@ -1532,7 +1534,7 @@ nsObjectLoadingContent::CheckProcessPolicy(int16_t *aContentPolicy)
|
||||
objectType = nsIContentPolicy::TYPE_DOCUMENT;
|
||||
break;
|
||||
case eType_Plugin:
|
||||
objectType = nsIContentPolicy::TYPE_OBJECT;
|
||||
objectType = GetContentPolicyType();
|
||||
break;
|
||||
default:
|
||||
NS_NOTREACHED("Calling checkProcessPolicy with a unloadable type");
|
||||
@ -2485,11 +2487,13 @@ nsObjectLoadingContent::OpenChannel()
|
||||
securityFlags |= nsILoadInfo::SEC_SANDBOXED;
|
||||
}
|
||||
|
||||
nsContentPolicyType contentPolicyType = GetContentPolicyType();
|
||||
|
||||
rv = NS_NewChannel(getter_AddRefs(chan),
|
||||
mURI,
|
||||
thisContent,
|
||||
securityFlags,
|
||||
nsIContentPolicy::TYPE_OBJECT,
|
||||
contentPolicyType,
|
||||
group, // aLoadGroup
|
||||
shim, // aCallbacks
|
||||
nsIChannel::LOAD_CALL_CONTENT_SNIFFERS |
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include "nsImageLoadingContent.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsIChannelEventSink.h"
|
||||
#include "nsIContentPolicy.h"
|
||||
#include "nsIObjectLoadingContent.h"
|
||||
#include "nsIRunnable.h"
|
||||
#include "nsIThreadInternal.h"
|
||||
@ -332,6 +333,11 @@ class nsObjectLoadingContent : public nsImageLoadingContent
|
||||
void UnbindFromTree(bool aDeep = true,
|
||||
bool aNullParent = true);
|
||||
|
||||
/**
|
||||
* Return the content policy type used for loading the element.
|
||||
*/
|
||||
virtual nsContentPolicyType GetContentPolicyType() const = 0;
|
||||
|
||||
private:
|
||||
|
||||
// Object parameter changes returned by UpdateObjectParameters
|
||||
|
@ -36,22 +36,10 @@ function getIntPref(prefName, def) {
|
||||
}
|
||||
}
|
||||
|
||||
function visibilityChangeHandler(e) {
|
||||
// The visibilitychange event's target is the document.
|
||||
let win = e.target.defaultView;
|
||||
|
||||
if (!win._browserElementParents) {
|
||||
return;
|
||||
}
|
||||
|
||||
let beps = Cu.nondeterministicGetWeakMapKeys(win._browserElementParents);
|
||||
if (beps.length == 0) {
|
||||
win.removeEventListener('visibilitychange', visibilityChangeHandler);
|
||||
return;
|
||||
}
|
||||
|
||||
for (let i = 0; i < beps.length; i++) {
|
||||
beps[i]._ownerVisibilityChange();
|
||||
function handleWindowEvent(e) {
|
||||
if (this._browserElementParents) {
|
||||
let beps = Cu.nondeterministicGetWeakMapKeys(this._browserElementParents);
|
||||
beps.forEach(bep => bep._handleOwnerEvent(e));
|
||||
}
|
||||
}
|
||||
|
||||
@ -119,10 +107,14 @@ BrowserElementParent.prototype = {
|
||||
// BrowserElementParents.
|
||||
if (!this._window._browserElementParents) {
|
||||
this._window._browserElementParents = new WeakMap();
|
||||
this._window.addEventListener('visibilitychange',
|
||||
visibilityChangeHandler,
|
||||
/* useCapture = */ false,
|
||||
/* wantsUntrusted = */ false);
|
||||
let handler = handleWindowEvent.bind(this._window);
|
||||
let windowEvents = ['visibilitychange', 'mozfullscreenchange'];
|
||||
let els = Cc["@mozilla.org/eventlistenerservice;1"]
|
||||
.getService(Ci.nsIEventListenerService);
|
||||
for (let event of windowEvents) {
|
||||
els.addSystemEventListener(this._window, event, handler,
|
||||
/* useCapture = */ true);
|
||||
}
|
||||
}
|
||||
|
||||
this._window._browserElementParents.set(this, null);
|
||||
@ -131,11 +123,6 @@ BrowserElementParent.prototype = {
|
||||
BrowserElementPromptService.mapFrameToBrowserElementParent(this._frameElement, this);
|
||||
this._setupMessageListener();
|
||||
this._registerAppManifest();
|
||||
|
||||
let els = Cc["@mozilla.org/eventlistenerservice;1"]
|
||||
.getService(Ci.nsIEventListenerService);
|
||||
els.addSystemEventListener(this._window.document, "mozfullscreenchange",
|
||||
this._fullscreenChange.bind(this), true);
|
||||
},
|
||||
|
||||
_runPendingAPICall: function() {
|
||||
@ -1056,14 +1043,19 @@ BrowserElementParent.prototype = {
|
||||
this._windowUtils.remoteFrameFullscreenReverted();
|
||||
},
|
||||
|
||||
_fullscreenChange: function(evt) {
|
||||
if (this._isAlive() && evt.target == this._window.document) {
|
||||
if (!this._window.document.mozFullScreen) {
|
||||
this._sendAsyncMsg("exit-fullscreen");
|
||||
} else if (this._pendingDOMFullscreen) {
|
||||
this._pendingDOMFullscreen = false;
|
||||
this._sendAsyncMsg("entered-fullscreen");
|
||||
}
|
||||
_handleOwnerEvent: function(evt) {
|
||||
switch (evt.type) {
|
||||
case 'visibilitychange':
|
||||
this._ownerVisibilityChange();
|
||||
break;
|
||||
case 'mozfullscreenchange':
|
||||
if (!this._window.document.mozFullScreen) {
|
||||
this._sendAsyncMsg('exit-fullscreen');
|
||||
} else if (this._pendingDOMFullscreen) {
|
||||
this._pendingDOMFullscreen = false;
|
||||
this._sendAsyncMsg('entered-fullscreen');
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -498,31 +498,38 @@ WebGL2Context::ReadBuffer(GLenum mode)
|
||||
if (IsContextLost())
|
||||
return;
|
||||
|
||||
MakeContextCurrent();
|
||||
const bool isColorAttachment = (mode >= LOCAL_GL_COLOR_ATTACHMENT0 &&
|
||||
mode <= LastColorAttachment());
|
||||
|
||||
if (mode != LOCAL_GL_NONE && mode != LOCAL_GL_BACK && !isColorAttachment) {
|
||||
ErrorInvalidEnum("readBuffer: `mode` must be one of NONE, BACK, or "
|
||||
"COLOR_ATTACHMENTi. Was %s",
|
||||
EnumName(mode));
|
||||
return;
|
||||
}
|
||||
|
||||
if (mBoundReadFramebuffer) {
|
||||
bool isColorAttachment = (mode >= LOCAL_GL_COLOR_ATTACHMENT0 &&
|
||||
mode <= LastColorAttachment());
|
||||
if (mode != LOCAL_GL_NONE &&
|
||||
!isColorAttachment)
|
||||
{
|
||||
ErrorInvalidEnumInfo("readBuffer: If READ_FRAMEBUFFER is non-null,"
|
||||
" `mode` must be COLOR_ATTACHMENTN or NONE."
|
||||
" Was:", mode);
|
||||
ErrorInvalidOperation("readBuffer: If READ_FRAMEBUFFER is non-null, `mode` "
|
||||
"must be COLOR_ATTACHMENTi or NONE. Was %s",
|
||||
EnumName(mode));
|
||||
return;
|
||||
}
|
||||
|
||||
MakeContextCurrent();
|
||||
gl->fReadBuffer(mode);
|
||||
return;
|
||||
}
|
||||
|
||||
// Operating on the default framebuffer.
|
||||
|
||||
if (mode != LOCAL_GL_NONE &&
|
||||
mode != LOCAL_GL_BACK)
|
||||
{
|
||||
ErrorInvalidEnumInfo("readBuffer: If READ_FRAMEBUFFER is null, `mode`"
|
||||
" must be BACK or NONE. Was:", mode);
|
||||
ErrorInvalidOperation("readBuffer: If READ_FRAMEBUFFER is null, `mode`"
|
||||
" must be BACK or NONE. Was %s",
|
||||
EnumName(mode));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1403,10 +1403,8 @@ protected:
|
||||
WebGLRefPtr<WebGLProgram> mCurrentProgram;
|
||||
RefPtr<const webgl::LinkedProgramInfo> mActiveProgramLinkInfo;
|
||||
|
||||
uint32_t mMaxFramebufferColorAttachments;
|
||||
|
||||
GLenum LastColorAttachment() const {
|
||||
return LOCAL_GL_COLOR_ATTACHMENT0 + mMaxFramebufferColorAttachments - 1;
|
||||
return LOCAL_GL_COLOR_ATTACHMENT0 + mGLMaxColorAttachments - 1;
|
||||
}
|
||||
|
||||
bool ValidateFramebufferTarget(GLenum target, const char* const info);
|
||||
|
@ -401,15 +401,8 @@ WebGLContext::ValidateFramebufferAttachment(const WebGLFramebuffer* fb, GLenum a
|
||||
return true;
|
||||
}
|
||||
|
||||
GLenum colorAttachCount = 1;
|
||||
if (IsExtensionEnabled(WebGLExtensionID::WEBGL_draw_buffers))
|
||||
colorAttachCount = mGLMaxColorAttachments;
|
||||
|
||||
if (attachment >= LOCAL_GL_COLOR_ATTACHMENT0 &&
|
||||
attachment < GLenum(LOCAL_GL_COLOR_ATTACHMENT0 + colorAttachCount))
|
||||
{
|
||||
if (attachment >= LOCAL_GL_COLOR_ATTACHMENT0 && attachment <= LastColorAttachment())
|
||||
return true;
|
||||
}
|
||||
|
||||
ErrorInvalidEnum("%s: attachment: invalid enum value 0x%x.", funcName,
|
||||
attachment);
|
||||
@ -1885,9 +1878,6 @@ WebGLContext::InitAndValidateGL()
|
||||
}
|
||||
}
|
||||
|
||||
// Always 1 for GLES2
|
||||
mMaxFramebufferColorAttachments = 1;
|
||||
|
||||
if (gl->IsCompatibilityProfile()) {
|
||||
// gl_PointSize is always available in ES2 GLSL, but has to be
|
||||
// specifically enabled on desktop GLSL.
|
||||
|
@ -398,7 +398,8 @@ EventListenerManager::AddEventListenerInternal(
|
||||
}
|
||||
|
||||
if (mIsMainThreadELM && mTarget) {
|
||||
EventListenerService::NotifyAboutMainThreadListenerChange(mTarget);
|
||||
EventListenerService::NotifyAboutMainThreadListenerChange(mTarget,
|
||||
aTypeAtom);
|
||||
}
|
||||
}
|
||||
|
||||
@ -518,7 +519,8 @@ EventListenerManager::RemoveEventListenerInternal(
|
||||
mTarget->EventListenerRemoved(aUserType);
|
||||
}
|
||||
if (mIsMainThreadELM && mTarget) {
|
||||
EventListenerService::NotifyAboutMainThreadListenerChange(mTarget);
|
||||
EventListenerService::NotifyAboutMainThreadListenerChange(mTarget,
|
||||
aUserType);
|
||||
}
|
||||
|
||||
if (!deviceType
|
||||
@ -654,7 +656,7 @@ EventListenerManager::SetEventHandlerInternal(
|
||||
mTarget->EventListenerAdded(aName);
|
||||
}
|
||||
if (mIsMainThreadELM && mTarget) {
|
||||
EventListenerService::NotifyAboutMainThreadListenerChange(mTarget);
|
||||
EventListenerService::NotifyAboutMainThreadListenerChange(mTarget, aName);
|
||||
}
|
||||
}
|
||||
|
||||
@ -784,7 +786,7 @@ EventListenerManager::RemoveEventHandler(nsIAtom* aName,
|
||||
mTarget->EventListenerRemoved(aName);
|
||||
}
|
||||
if (mIsMainThreadELM && mTarget) {
|
||||
EventListenerService::NotifyAboutMainThreadListenerChange(mTarget);
|
||||
EventListenerService::NotifyAboutMainThreadListenerChange(mTarget, aName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,44 @@ namespace mozilla {
|
||||
|
||||
using namespace dom;
|
||||
|
||||
/******************************************************************************
|
||||
* mozilla::EventListenerChange
|
||||
******************************************************************************/
|
||||
|
||||
NS_IMPL_ISUPPORTS(EventListenerChange, nsIEventListenerChange)
|
||||
|
||||
EventListenerChange::~EventListenerChange()
|
||||
{
|
||||
}
|
||||
|
||||
EventListenerChange::EventListenerChange(dom::EventTarget* aTarget) :
|
||||
mTarget(aTarget)
|
||||
{
|
||||
mChangedListenerNames = nsArrayBase::Create();
|
||||
}
|
||||
|
||||
void
|
||||
EventListenerChange::AddChangedListenerName(nsIAtom* aEventName)
|
||||
{
|
||||
mChangedListenerNames->AppendElement(aEventName, false);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
EventListenerChange::GetTarget(nsIDOMEventTarget** aTarget)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aTarget);
|
||||
NS_ADDREF(*aTarget = mTarget);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
EventListenerChange::GetChangedListenerNames(nsIArray** aEventNames)
|
||||
{
|
||||
NS_ENSURE_ARG_POINTER(aEventNames);
|
||||
NS_ADDREF(*aEventNames = mChangedListenerNames);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* mozilla::EventListenerInfo
|
||||
******************************************************************************/
|
||||
@ -323,7 +361,8 @@ EventListenerService::RemoveListenerChangeListener(nsIListenerChangeListener* aL
|
||||
};
|
||||
|
||||
void
|
||||
EventListenerService::NotifyAboutMainThreadListenerChangeInternal(dom::EventTarget* aTarget)
|
||||
EventListenerService::NotifyAboutMainThreadListenerChangeInternal(dom::EventTarget* aTarget,
|
||||
nsIAtom* aName)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
if (mChangeListeners.IsEmpty()) {
|
||||
@ -337,10 +376,13 @@ EventListenerService::NotifyAboutMainThreadListenerChangeInternal(dom::EventTarg
|
||||
NS_DispatchToCurrentThread(runnable);
|
||||
}
|
||||
|
||||
if (!mPendingListenerChangesSet.Get(aTarget)) {
|
||||
mPendingListenerChanges->AppendElement(aTarget, false);
|
||||
mPendingListenerChangesSet.Put(aTarget, true);
|
||||
nsRefPtr<EventListenerChange> changes = mPendingListenerChangesSet.Get(aTarget);
|
||||
if (!changes) {
|
||||
changes = new EventListenerChange(aTarget);
|
||||
mPendingListenerChanges->AppendElement(changes, false);
|
||||
mPendingListenerChangesSet.Put(aTarget, changes);
|
||||
}
|
||||
changes->AddChangedListenerName(aName);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "nsString.h"
|
||||
#include "nsTObserverArray.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsGkAtoms.h"
|
||||
|
||||
class nsIMutableArray;
|
||||
|
||||
@ -27,6 +28,23 @@ class EventTarget;
|
||||
template<typename T>
|
||||
class Maybe;
|
||||
|
||||
class EventListenerChange final : public nsIEventListenerChange
|
||||
{
|
||||
public:
|
||||
explicit EventListenerChange(dom::EventTarget* aTarget);
|
||||
|
||||
void AddChangedListenerName(nsIAtom* aEventName);
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIEVENTLISTENERCHANGE
|
||||
|
||||
protected:
|
||||
virtual ~EventListenerChange();
|
||||
nsCOMPtr<dom::EventTarget> mTarget;
|
||||
nsCOMPtr<nsIMutableArray> mChangedListenerNames;
|
||||
|
||||
};
|
||||
|
||||
class EventListenerInfo final : public nsIEventListenerInfo
|
||||
{
|
||||
public:
|
||||
@ -70,19 +88,21 @@ public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_NSIEVENTLISTENERSERVICE
|
||||
|
||||
static void NotifyAboutMainThreadListenerChange(dom::EventTarget* aTarget)
|
||||
static void NotifyAboutMainThreadListenerChange(dom::EventTarget* aTarget,
|
||||
nsIAtom* aName)
|
||||
{
|
||||
if (sInstance) {
|
||||
sInstance->NotifyAboutMainThreadListenerChangeInternal(aTarget);
|
||||
sInstance->NotifyAboutMainThreadListenerChangeInternal(aTarget, aName);
|
||||
}
|
||||
}
|
||||
|
||||
void NotifyPendingChanges();
|
||||
private:
|
||||
void NotifyAboutMainThreadListenerChangeInternal(dom::EventTarget* aTarget);
|
||||
void NotifyAboutMainThreadListenerChangeInternal(dom::EventTarget* aTarget,
|
||||
nsIAtom* aName);
|
||||
nsTObserverArray<nsCOMPtr<nsIListenerChangeListener>> mChangeListeners;
|
||||
nsCOMPtr<nsIMutableArray> mPendingListenerChanges;
|
||||
nsDataHashtable<nsISupportsHashKey, bool> mPendingListenerChangesSet;
|
||||
nsDataHashtable<nsISupportsHashKey, nsRefPtr<EventListenerChange>> mPendingListenerChangesSet;
|
||||
|
||||
static EventListenerService* sInstance;
|
||||
};
|
||||
|
@ -9,10 +9,21 @@ interface nsIDOMEventListener;
|
||||
interface nsIDOMEventTarget;
|
||||
interface nsIArray;
|
||||
|
||||
[scriptable, function, uuid(8d5b5a6b-dec0-473d-86c4-591801dfaac1)]
|
||||
/**
|
||||
* Contains an event target along with an array of nsIAtom in form "oneventname"
|
||||
* representing changed event listener names.
|
||||
*/
|
||||
[scriptable, uuid(07222b02-da12-4cf4-b2f7-761da007a8d8)]
|
||||
interface nsIEventListenerChange : nsISupports
|
||||
{
|
||||
readonly attribute nsIDOMEventTarget target;
|
||||
readonly attribute nsIArray changedListenerNames;
|
||||
};
|
||||
|
||||
[scriptable, function, uuid(aa7c95f6-d3b5-44b3-9597-1d9f19b9c5f2)]
|
||||
interface nsIListenerChangeListener : nsISupports
|
||||
{
|
||||
void listenersChanged(in nsIArray aEventTargets);
|
||||
void listenersChanged(in nsIArray aEventListenerChanges);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -22,6 +22,8 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=524674
|
||||
var els = Components.classes["@mozilla.org/eventlistenerservice;1"]
|
||||
.getService(Components.interfaces.nsIEventListenerService);
|
||||
|
||||
const Ci = Components.interfaces;
|
||||
|
||||
function dummyListener() {}
|
||||
|
||||
var runningTest = null;
|
||||
@ -35,29 +37,49 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=524674
|
||||
d.addEventListener("foo", dummyListener);
|
||||
d.addEventListener("foo", dummyListener);
|
||||
xhr.addEventListener("foo", dummyListener);
|
||||
tests[0] = [d, xhr];
|
||||
tests[0] = [{target: d, listeners: ["onfoo"]},
|
||||
{target: xhr, listeners: ["onfoo"]}];
|
||||
},
|
||||
function() {
|
||||
d.addEventListener("bar", dummyListener);
|
||||
d.addEventListener("baz", dummyListener);
|
||||
xhr.addEventListener("bar", dummyListener);
|
||||
xhr.addEventListener("baz", dummyListener);
|
||||
tests[0] = [{target: d, listeners: ["onbaz", "onbar"]},
|
||||
{target: xhr, listeners: ["onbaz", "onbar"]}];
|
||||
},
|
||||
function() {
|
||||
d.onclick = dummyListener;
|
||||
d.onclick = dummyListener;
|
||||
xhr.onload = dummyListener;
|
||||
tests[0] = [d, xhr];
|
||||
tests[0] = [{target: d, listeners: ["onclick"]},
|
||||
{target: xhr, listeners: ["onload"]}];
|
||||
},
|
||||
function() {
|
||||
d.onclick = function() {};
|
||||
tests[0] = [d];
|
||||
tests[0] = [{target: d, listeners: ["onclick"]}];
|
||||
},
|
||||
function() {
|
||||
d.removeEventListener("foo", dummyListener);
|
||||
d.removeEventListener("foo", dummyListener);
|
||||
xhr.removeEventListener("foo", dummyListener);
|
||||
tests[0] = [d, xhr];
|
||||
tests[0] = [{target: d, listeners: ["onfoo"]},
|
||||
{target: xhr, listeners: ["onfoo"]}];
|
||||
},
|
||||
function() {
|
||||
d.removeEventListener("bar", dummyListener);
|
||||
d.removeEventListener("baz", dummyListener);
|
||||
xhr.removeEventListener("bar", dummyListener);
|
||||
xhr.removeEventListener("baz", dummyListener);
|
||||
tests[0] = [{target: d, listeners: ["onbar", "onbaz"]},
|
||||
{target: xhr, listeners: ["onbar", "onbaz"]}];
|
||||
},
|
||||
function() {
|
||||
d.onclick = null;
|
||||
d.onclick = null;
|
||||
xhr.onload = null;
|
||||
tests[0] = [d, xhr];
|
||||
tests[0] = [{target: d, listeners: ["onclick"]},
|
||||
{target: xhr, listeners: ["onload"]}];
|
||||
},
|
||||
function() {
|
||||
els.removeListenerChangeListener(changeListener);
|
||||
@ -76,29 +98,43 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=524674
|
||||
if (typeof tests[0] == "function") {
|
||||
return;
|
||||
}
|
||||
var expectedEventTargets = tests[0];
|
||||
var e = array.enumerate();
|
||||
var expectedEventChanges = tests[0];
|
||||
var eventChanges = array.enumerate();
|
||||
var i = 0;
|
||||
while (e.hasMoreElements()) {
|
||||
while (eventChanges.hasMoreElements() && i < expectedEventChanges.length) {
|
||||
var current;
|
||||
try {
|
||||
current = e.getNext();
|
||||
current = eventChanges.getNext().QueryInterface(Ci.nsIEventListenerChange);
|
||||
var expected = expectedEventChanges[i];
|
||||
|
||||
if (current.target == expected.target) {
|
||||
// expected.target.listeners should be a subset of
|
||||
// current.changedListenerNames if all expected listener changes were
|
||||
// sent. We may get random other event listener changes here too, not
|
||||
// just the one from the test.
|
||||
is(current.target, expected.target, current.target + " = " + expected.target);
|
||||
|
||||
var eNames = current.changedListenerNames.enumerate();
|
||||
var listeners = [];
|
||||
while (eNames.hasMoreElements()) {
|
||||
var listenerName = eNames.getNext().QueryInterface(Ci.nsIAtom).toString();
|
||||
listeners.push(listenerName);
|
||||
}
|
||||
var matchAll = expected.listeners.every(function(val)
|
||||
{ return listeners.indexOf(val) >= 0; });
|
||||
if (!matchAll)
|
||||
return;
|
||||
++i;
|
||||
}
|
||||
} catch(ex) {
|
||||
continue;
|
||||
}
|
||||
var expected = expectedEventTargets[i];
|
||||
if (current == expected) {
|
||||
is(current, expected, current + " = " + expected);
|
||||
// We may get random other event listener changes here too, not just the one from the
|
||||
// test.
|
||||
++i
|
||||
}
|
||||
}
|
||||
if (expectedEventTargets.length != i) {
|
||||
if (expectedEventChanges.length != i) {
|
||||
return;
|
||||
}
|
||||
|
||||
is(expectedEventTargets.length, i, "Should have got notification for all the changes.");
|
||||
is(expectedEventChanges.length, i, "Should have got notification for all the changes.");
|
||||
tests.shift();
|
||||
|
||||
ok(tests.length);
|
||||
|
@ -128,15 +128,21 @@ InternalRequest::MapContentPolicyTypeToRequestContext(nsContentPolicyType aConte
|
||||
case nsIContentPolicy::TYPE_STYLESHEET:
|
||||
context = RequestContext::Style;
|
||||
break;
|
||||
case nsIContentPolicy::TYPE_OBJECT:
|
||||
case nsIContentPolicy::TYPE_INTERNAL_OBJECT:
|
||||
context = RequestContext::Object;
|
||||
break;
|
||||
case nsIContentPolicy::TYPE_INTERNAL_EMBED:
|
||||
context = RequestContext::Embed;
|
||||
break;
|
||||
case nsIContentPolicy::TYPE_DOCUMENT:
|
||||
context = RequestContext::Internal;
|
||||
break;
|
||||
case nsIContentPolicy::TYPE_SUBDOCUMENT:
|
||||
case nsIContentPolicy::TYPE_INTERNAL_IFRAME:
|
||||
context = RequestContext::Iframe;
|
||||
break;
|
||||
case nsIContentPolicy::TYPE_INTERNAL_FRAME:
|
||||
context = RequestContext::Frame;
|
||||
break;
|
||||
case nsIContentPolicy::TYPE_REFRESH:
|
||||
context = RequestContext::Internal;
|
||||
break;
|
||||
|
@ -34,22 +34,22 @@ namespace dom {
|
||||
* beacon | TYPE_BEACON
|
||||
* cspreport | TYPE_CSP_REPORT
|
||||
* download |
|
||||
* embed | TYPE_OBJECT
|
||||
* embed | TYPE_INTERNAL_EMBED
|
||||
* eventsource |
|
||||
* favicon |
|
||||
* fetch | TYPE_FETCH
|
||||
* font | TYPE_FONT
|
||||
* form |
|
||||
* frame | TYPE_SUBDOCUMENT
|
||||
* frame | TYPE_INTERNAL_FRAME
|
||||
* hyperlink |
|
||||
* iframe | TYPE_SUBDOCUMENT
|
||||
* iframe | TYPE_INTERNAL_IFRAME
|
||||
* image | TYPE_IMAGE
|
||||
* imageset | TYPE_IMAGESET
|
||||
* import | Not supported by Gecko
|
||||
* internal | TYPE_DOCUMENT, TYPE_XBL, TYPE_OTHER
|
||||
* location |
|
||||
* manifest | TYPE_WEB_MANIFEST
|
||||
* object | TYPE_OBJECT
|
||||
* object | TYPE_INTERNAL_OBJECT
|
||||
* ping | TYPE_PING
|
||||
* plugin | TYPE_OBJECT_SUBREQUEST
|
||||
* prefetch |
|
||||
@ -67,7 +67,6 @@ namespace dom {
|
||||
* TODO: Figure out if TYPE_DTD maps to anything useful
|
||||
* TODO: Split TYPE_XMLHTTPREQUEST and TYPE_DATAREQUEST for EventSource
|
||||
* TODO: Figure out if TYPE_WEBSOCKET maps to anything useful
|
||||
* TODO: Differentiate between frame and iframe
|
||||
* TODO: Add a content type for prefetch
|
||||
* TODO: Use the content type for manifest when it becomes available
|
||||
* TODO: Add a content type for location
|
||||
@ -75,7 +74,6 @@ namespace dom {
|
||||
* TODO: Add a content type for form
|
||||
* TODO: Add a content type for favicon
|
||||
* TODO: Add a content type for download
|
||||
* TODO: Split TYPE_OBJECT into TYPE_EMBED and TYPE_OBJECT
|
||||
*/
|
||||
|
||||
class Request;
|
||||
|
@ -297,10 +297,12 @@ HTMLContentElement::GetDistributedNodes()
|
||||
return list.forget();
|
||||
}
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTION(DistributedContentList, mParent, mDistributedNodes)
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(DistributedContentList, mParent,
|
||||
mDistributedNodes)
|
||||
|
||||
NS_INTERFACE_TABLE_HEAD(DistributedContentList)
|
||||
NS_INTERFACE_TABLE(DistributedContentList, nsINodeList)
|
||||
NS_WRAPPERCACHE_INTERFACE_TABLE_ENTRY
|
||||
NS_INTERFACE_TABLE(DistributedContentList, nsINodeList, nsIDOMNodeList)
|
||||
NS_INTERFACE_TABLE_TO_MAP_SEGUE_CYCLE_COLLECTION(DistributedContentList)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
|
@ -102,7 +102,7 @@ public:
|
||||
explicit DistributedContentList(HTMLContentElement* aHostElement);
|
||||
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_CLASS(DistributedContentList)
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DistributedContentList)
|
||||
|
||||
// nsIDOMNodeList
|
||||
NS_DECL_NSIDOMNODELIST
|
||||
|
@ -1172,25 +1172,6 @@ nsresult HTMLMediaElement::LoadResource()
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(IsAnyOfHTMLElements(nsGkAtoms::audio, nsGkAtoms::video));
|
||||
nsContentPolicyType contentPolicyType = IsHTMLElement(nsGkAtoms::audio) ?
|
||||
nsIContentPolicy::TYPE_INTERNAL_AUDIO : nsIContentPolicy::TYPE_INTERNAL_VIDEO;
|
||||
|
||||
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
|
||||
nsresult rv = NS_CheckContentLoadPolicy(contentPolicyType,
|
||||
mLoadingSrc,
|
||||
NodePrincipal(),
|
||||
static_cast<Element*>(this),
|
||||
EmptyCString(), // mime type
|
||||
nullptr, // extra
|
||||
&shouldLoad,
|
||||
nsContentUtils::GetContentPolicy(),
|
||||
nsContentUtils::GetSecurityManager());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_CP_REJECTED(shouldLoad)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Set the media element's CORS mode only when loading a resource
|
||||
mCORSMode = AttrValueToCORSMode(GetParsedAttr(nsGkAtoms::crossorigin));
|
||||
|
||||
@ -1212,7 +1193,7 @@ nsresult HTMLMediaElement::LoadResource()
|
||||
|
||||
if (IsMediaStreamURI(mLoadingSrc)) {
|
||||
nsRefPtr<DOMMediaStream> stream;
|
||||
rv = NS_GetStreamForMediaStreamURI(mLoadingSrc, getter_AddRefs(stream));
|
||||
nsresult rv = NS_GetStreamForMediaStreamURI(mLoadingSrc, getter_AddRefs(stream));
|
||||
if (NS_FAILED(rv)) {
|
||||
nsAutoString spec;
|
||||
GetCurrentSrc(spec);
|
||||
@ -1240,27 +1221,31 @@ nsresult HTMLMediaElement::LoadResource()
|
||||
return FinishDecoderSetup(decoder, resource, nullptr, nullptr);
|
||||
}
|
||||
|
||||
nsSecurityFlags securityFlags = nsILoadInfo::SEC_NORMAL;
|
||||
if (nsContentUtils::ChannelShouldInheritPrincipal(NodePrincipal(),
|
||||
mLoadingSrc,
|
||||
false, // aInheritForAboutBlank
|
||||
false // aForceInherit
|
||||
)) {
|
||||
securityFlags = nsILoadInfo::SEC_FORCE_INHERIT_PRINCIPAL;
|
||||
// determine what security checks need to be performed in AsyncOpen2().
|
||||
nsSecurityFlags securityFlags =
|
||||
ShouldCheckAllowOrigin() ? nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS :
|
||||
nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS;
|
||||
|
||||
if (GetCORSMode() == CORS_USE_CREDENTIALS) {
|
||||
securityFlags |= nsILoadInfo::SEC_REQUIRE_CORS_WITH_CREDENTIALS;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(IsAnyOfHTMLElements(nsGkAtoms::audio, nsGkAtoms::video));
|
||||
nsContentPolicyType contentPolicyType = IsHTMLElement(nsGkAtoms::audio) ?
|
||||
nsIContentPolicy::TYPE_INTERNAL_AUDIO : nsIContentPolicy::TYPE_INTERNAL_VIDEO;
|
||||
|
||||
nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup();
|
||||
nsCOMPtr<nsIChannel> channel;
|
||||
rv = NS_NewChannel(getter_AddRefs(channel),
|
||||
mLoadingSrc,
|
||||
static_cast<Element*>(this),
|
||||
securityFlags,
|
||||
contentPolicyType,
|
||||
loadGroup,
|
||||
nullptr, // aCallbacks
|
||||
nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY |
|
||||
nsIChannel::LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE |
|
||||
nsIChannel::LOAD_CALL_CONTENT_SNIFFERS);
|
||||
nsresult rv = NS_NewChannel(getter_AddRefs(channel),
|
||||
mLoadingSrc,
|
||||
static_cast<Element*>(this),
|
||||
securityFlags,
|
||||
contentPolicyType,
|
||||
loadGroup,
|
||||
nullptr, // aCallbacks
|
||||
nsICachingChannel::LOAD_BYPASS_LOCAL_CACHE_IF_BUSY |
|
||||
nsIChannel::LOAD_MEDIA_SNIFFER_OVERRIDES_CONTENT_TYPE |
|
||||
nsIChannel::LOAD_CALL_CONTENT_SNIFFERS);
|
||||
|
||||
NS_ENSURE_SUCCESS(rv,rv);
|
||||
|
||||
@ -1274,24 +1259,6 @@ nsresult HTMLMediaElement::LoadResource()
|
||||
|
||||
channel->SetNotificationCallbacks(loadListener);
|
||||
|
||||
nsCOMPtr<nsIStreamListener> listener;
|
||||
if (ShouldCheckAllowOrigin()) {
|
||||
nsRefPtr<nsCORSListenerProxy> corsListener =
|
||||
new nsCORSListenerProxy(loadListener,
|
||||
NodePrincipal(),
|
||||
GetCORSMode() == CORS_USE_CREDENTIALS);
|
||||
rv = corsListener->Init(channel, DataURIHandling::Allow);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
listener = corsListener;
|
||||
} else {
|
||||
rv = nsContentUtils::GetSecurityManager()->
|
||||
CheckLoadURIWithPrincipal(NodePrincipal(),
|
||||
mLoadingSrc,
|
||||
nsIScriptSecurityManager::STANDARD);
|
||||
listener = loadListener;
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> hc = do_QueryInterface(channel);
|
||||
if (hc) {
|
||||
// Use a byte range request from the start of the resource.
|
||||
@ -1304,7 +1271,7 @@ nsresult HTMLMediaElement::LoadResource()
|
||||
SetRequestHeaders(hc);
|
||||
}
|
||||
|
||||
rv = channel->AsyncOpen(listener, nullptr);
|
||||
rv = channel->AsyncOpen2(loadListener);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Else the channel must be open and starting to download. If it encounters
|
||||
|
@ -246,7 +246,12 @@ private:
|
||||
* value. This is used to know the default tabindex value.
|
||||
*/
|
||||
bool IsFocusableForTabIndex();
|
||||
|
||||
|
||||
nsContentPolicyType GetContentPolicyType() const override
|
||||
{
|
||||
return nsIContentPolicy::TYPE_INTERNAL_OBJECT;
|
||||
}
|
||||
|
||||
virtual void GetItemValueText(DOMString& text) override;
|
||||
virtual void SetItemValueText(const nsAString& text) override;
|
||||
|
||||
|
@ -387,5 +387,18 @@ HTMLSharedObjectElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenPr
|
||||
return rootedObj;
|
||||
}
|
||||
|
||||
nsContentPolicyType
|
||||
HTMLSharedObjectElement::GetContentPolicyType() const
|
||||
{
|
||||
if (mNodeInfo->Equals(nsGkAtoms::applet)) {
|
||||
// We use TYPE_INTERNAL_OBJECT for applet too, since it is not exposed
|
||||
// through RequestContext yet.
|
||||
return nsIContentPolicy::TYPE_INTERNAL_OBJECT;
|
||||
} else {
|
||||
MOZ_ASSERT(mNodeInfo->Equals(nsGkAtoms::embed));
|
||||
return nsIContentPolicy::TYPE_INTERNAL_EMBED;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
@ -207,6 +207,8 @@ private:
|
||||
nsGkAtoms::src;
|
||||
}
|
||||
|
||||
nsContentPolicyType GetContentPolicyType() const override;
|
||||
|
||||
// mIsDoneAddingChildren is only really used for <applet>. This boolean is
|
||||
// always true for <embed>, per the documentation in nsIContent.h.
|
||||
bool mIsDoneAddingChildren;
|
||||
|
@ -163,7 +163,7 @@ parent:
|
||||
bool aSizeSpecified,
|
||||
nsString aURI,
|
||||
nsString aName,
|
||||
nsString aFeatures,
|
||||
nsCString aFeatures,
|
||||
nsString aBaseURI)
|
||||
returns (nsresult rv,
|
||||
bool windowOpened,
|
||||
|
@ -1597,16 +1597,12 @@ TabChild::ProvideWindowCommon(nsIDOMWindow* aOpener,
|
||||
nsAutoCString baseURIString;
|
||||
baseURI->GetSpec(baseURIString);
|
||||
|
||||
// We can assume that if content is requesting to open a window from a remote
|
||||
// tab, then we want to enforce that the new window is also a remote tab.
|
||||
features.AppendLiteral(",remote");
|
||||
|
||||
nsresult rv;
|
||||
|
||||
if (!SendCreateWindow(newChild,
|
||||
aChromeFlags, aCalledFromJS, aPositionSpecified,
|
||||
aSizeSpecified, url,
|
||||
name, NS_ConvertUTF8toUTF16(features),
|
||||
name, features,
|
||||
NS_ConvertUTF8toUTF16(baseURIString),
|
||||
&rv,
|
||||
aWindowIsNew,
|
||||
|
@ -612,7 +612,7 @@ TabParent::RecvCreateWindow(PBrowserParent* aNewTab,
|
||||
const bool& aSizeSpecified,
|
||||
const nsString& aURI,
|
||||
const nsString& aName,
|
||||
const nsString& aFeatures,
|
||||
const nsCString& aFeatures,
|
||||
const nsString& aBaseURI,
|
||||
nsresult* aResult,
|
||||
bool* aWindowIsNew,
|
||||
@ -622,6 +622,13 @@ TabParent::RecvCreateWindow(PBrowserParent* aNewTab,
|
||||
// We always expect to open a new window here. If we don't, it's an error.
|
||||
*aWindowIsNew = true;
|
||||
|
||||
// The content process should never be in charge of computing whether or
|
||||
// not a window should be private or remote - the parent will do that.
|
||||
MOZ_ASSERT(!(aChromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW));
|
||||
MOZ_ASSERT(!(aChromeFlags & nsIWebBrowserChrome::CHROME_NON_PRIVATE_WINDOW));
|
||||
MOZ_ASSERT(!(aChromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME));
|
||||
MOZ_ASSERT(!(aChromeFlags & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW));
|
||||
|
||||
if (NS_WARN_IF(IsBrowserOrApp()))
|
||||
return false;
|
||||
|
||||
@ -735,9 +742,11 @@ TabParent::RecvCreateWindow(PBrowserParent* aNewTab,
|
||||
|
||||
AutoUseNewTab aunt(newTab, aWindowIsNew, aURLToLoad);
|
||||
|
||||
const char* features = aFeatures.Length() ? aFeatures.get() : nullptr;
|
||||
|
||||
*aResult = pwwatch->OpenWindow2(parent, finalURIString.get(),
|
||||
NS_ConvertUTF16toUTF8(aName).get(),
|
||||
NS_ConvertUTF16toUTF8(aFeatures).get(), aCalledFromJS,
|
||||
features, aCalledFromJS,
|
||||
false, false, this, nullptr, getter_AddRefs(window));
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(*aResult)))
|
||||
@ -3136,7 +3145,9 @@ public:
|
||||
NS_IMETHOD GetContentLength(int64_t*) NO_IMPL
|
||||
NS_IMETHOD SetContentLength(int64_t) NO_IMPL
|
||||
NS_IMETHOD Open(nsIInputStream**) NO_IMPL
|
||||
NS_IMETHOD Open2(nsIInputStream**) NO_IMPL
|
||||
NS_IMETHOD AsyncOpen(nsIStreamListener*, nsISupports*) NO_IMPL
|
||||
NS_IMETHOD AsyncOpen2(nsIStreamListener*) NO_IMPL
|
||||
NS_IMETHOD GetContentDisposition(uint32_t*) NO_IMPL
|
||||
NS_IMETHOD SetContentDisposition(uint32_t) NO_IMPL
|
||||
NS_IMETHOD GetContentDispositionFilename(nsAString&) NO_IMPL
|
||||
|
@ -142,7 +142,7 @@ public:
|
||||
const bool& aSizeSpecified,
|
||||
const nsString& aURI,
|
||||
const nsString& aName,
|
||||
const nsString& aFeatures,
|
||||
const nsCString& aFeatures,
|
||||
const nsString& aBaseURI,
|
||||
nsresult* aResult,
|
||||
bool* aWindowIsNew,
|
||||
|
@ -50,6 +50,7 @@
|
||||
#include "nsSandboxFlags.h"
|
||||
#include "mozilla/dom/ScriptSettings.h"
|
||||
#include "nsILoadInfo.h"
|
||||
#include "nsContentSecurityManager.h"
|
||||
|
||||
#include "mozilla/ipc/URIUtils.h"
|
||||
|
||||
@ -552,6 +553,15 @@ nsJSChannel::Open(nsIInputStream **aResult)
|
||||
return mStreamChannel->Open(aResult);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJSChannel::Open2(nsIInputStream** aStream)
|
||||
{
|
||||
nsCOMPtr<nsIStreamListener> listener;
|
||||
nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return Open(aStream);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJSChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext)
|
||||
{
|
||||
@ -663,6 +673,15 @@ nsJSChannel::AsyncOpen(nsIStreamListener *aListener, nsISupports *aContext)
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsJSChannel::AsyncOpen2(nsIStreamListener *aListener)
|
||||
{
|
||||
nsCOMPtr<nsIStreamListener> listener = aListener;
|
||||
nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return AsyncOpen(listener, nullptr);
|
||||
}
|
||||
|
||||
void
|
||||
nsJSChannel::EvaluateScript()
|
||||
{
|
||||
|
@ -258,8 +258,9 @@ static gboolean FactoryFilter(GstPluginFeature *aFeature, gpointer)
|
||||
const gchar *className =
|
||||
gst_element_factory_get_klass(GST_ELEMENT_FACTORY_CAST(aFeature));
|
||||
|
||||
if (!strstr(className, "Decoder") && !strstr(className, "Demux") &&
|
||||
!strstr(className, "Parser")) {
|
||||
// NB: We skip filtering parsers here, because adding them to
|
||||
// the list can give false decoder positives to canPlayType().
|
||||
if (!strstr(className, "Decoder") && !strstr(className, "Demux")) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -298,7 +298,11 @@ TrackBuffer::AppendDataToCurrentResource(MediaByteBuffer* aData, uint32_t aDurat
|
||||
nsRefPtr<TrackBuffer::BufferedRangesUpdatedPromise>
|
||||
TrackBuffer::UpdateBufferedRanges(Interval<int64_t> aByteRange, bool aNotifyParent)
|
||||
{
|
||||
if (aByteRange.Length()) {
|
||||
if (!mParentDecoder) {
|
||||
return BufferedRangesUpdatedPromise::CreateAndResolve(true, __func__);
|
||||
}
|
||||
|
||||
if (mCurrentDecoder && aByteRange.Length()) {
|
||||
mCurrentDecoder->GetReader()->NotifyDataArrived(aByteRange);
|
||||
}
|
||||
|
||||
|
@ -19,11 +19,13 @@
|
||||
#include "GfxDriverInfo.h"
|
||||
#include "gfxWindowsPlatform.h"
|
||||
#include "MediaInfo.h"
|
||||
#include "prsystem.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
static bool sIsWMFEnabled = false;
|
||||
static bool sDXVAEnabled = false;
|
||||
static int sNumDecoderThreads = -1;
|
||||
|
||||
WMFDecoderModule::WMFDecoderModule()
|
||||
: mWMFInitialized(false)
|
||||
@ -44,6 +46,25 @@ WMFDecoderModule::DisableHardwareAcceleration()
|
||||
sDXVAEnabled = false;
|
||||
}
|
||||
|
||||
static void
|
||||
SetNumOfDecoderThreads()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Preferences can only be read on main thread");
|
||||
int32_t numCores = PR_GetNumberOfProcessors();
|
||||
|
||||
// If we have more than 4 cores, let the decoder decide how many threads.
|
||||
// On an 8 core machine, WMF chooses 4 decoder threads
|
||||
const int WMF_DECODER_DEFAULT = -1;
|
||||
int32_t prefThreadCount = Preferences::GetInt("media.wmf.decoder.thread-count", -1);
|
||||
if (prefThreadCount != WMF_DECODER_DEFAULT) {
|
||||
sNumDecoderThreads = std::max(prefThreadCount, 1);
|
||||
} else if (numCores > 4) {
|
||||
sNumDecoderThreads = WMF_DECODER_DEFAULT;
|
||||
} else {
|
||||
sNumDecoderThreads = std::max(numCores - 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* static */
|
||||
void
|
||||
WMFDecoderModule::Init()
|
||||
@ -51,6 +72,14 @@ WMFDecoderModule::Init()
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Must be on main thread.");
|
||||
sIsWMFEnabled = Preferences::GetBool("media.windows-media-foundation.enabled", false);
|
||||
sDXVAEnabled = gfxPlatform::GetPlatform()->CanUseHardwareVideoDecoding();
|
||||
SetNumOfDecoderThreads();
|
||||
}
|
||||
|
||||
/* static */
|
||||
int
|
||||
WMFDecoderModule::GetNumDecoderThreads()
|
||||
{
|
||||
return sNumDecoderThreads;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -48,6 +48,9 @@ public:
|
||||
|
||||
// Called on main thread.
|
||||
static void Init();
|
||||
|
||||
// Called from any thread, must call init first
|
||||
static int GetNumDecoderThreads();
|
||||
private:
|
||||
bool ShouldUseDXVA(const VideoInfo& aConfig) const;
|
||||
bool mWMFInitialized;
|
||||
|
@ -198,13 +198,15 @@ WMFVideoMFTManager::InitInternal(bool aForceD3D9)
|
||||
HRESULT hr = decoder->Create(GetMFTGUID());
|
||||
NS_ENSURE_TRUE(SUCCEEDED(hr), nullptr);
|
||||
|
||||
if (useDxva) {
|
||||
RefPtr<IMFAttributes> attr(decoder->GetAttributes());
|
||||
|
||||
UINT32 aware = 0;
|
||||
if (attr) {
|
||||
RefPtr<IMFAttributes> attr(decoder->GetAttributes());
|
||||
UINT32 aware = 0;
|
||||
if (attr) {
|
||||
attr->GetUINT32(MF_SA_D3D_AWARE, &aware);
|
||||
}
|
||||
attr->SetUINT32(CODECAPI_AVDecNumWorkerThreads,
|
||||
WMFDecoderModule::GetNumDecoderThreads());
|
||||
}
|
||||
|
||||
if (useDxva) {
|
||||
if (aware) {
|
||||
// TODO: Test if I need this anywhere... Maybe on Vista?
|
||||
//hr = attr->SetUINT32(CODECAPI_AVDecVideoAcceleration_H264, TRUE);
|
||||
|
@ -7,6 +7,7 @@
|
||||
TEST_DIRS += ['test']
|
||||
|
||||
EXPORTS.mozilla.dom += [
|
||||
'nsContentSecurityManager.h',
|
||||
'nsCSPContext.h',
|
||||
'nsCSPService.h',
|
||||
'nsCSPUtils.h',
|
||||
@ -14,10 +15,12 @@ EXPORTS.mozilla.dom += [
|
||||
]
|
||||
|
||||
EXPORTS += [
|
||||
'nsContentSecurityManager.h',
|
||||
'nsCORSListenerProxy.h'
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
'nsContentSecurityManager.cpp',
|
||||
'nsCORSListenerProxy.cpp',
|
||||
'nsCSPContext.cpp',
|
||||
'nsCSPParser.cpp',
|
||||
|
263
dom/security/nsContentSecurityManager.cpp
Normal file
263
dom/security/nsContentSecurityManager.cpp
Normal file
@ -0,0 +1,263 @@
|
||||
#include "nsContentSecurityManager.h"
|
||||
#include "nsIChannel.h"
|
||||
#include "nsIStreamListener.h"
|
||||
#include "nsILoadInfo.h"
|
||||
#include "nsContentUtils.h"
|
||||
#include "nsCORSListenerProxy.h"
|
||||
#include "nsIStreamListener.h"
|
||||
|
||||
#include "mozilla/dom/Element.h"
|
||||
|
||||
nsresult
|
||||
ValidateSecurityFlags(nsILoadInfo* aLoadInfo)
|
||||
{
|
||||
nsSecurityFlags securityMode = aLoadInfo->GetSecurityMode();
|
||||
|
||||
if (securityMode != nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS &&
|
||||
securityMode != nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED &&
|
||||
securityMode != nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS &&
|
||||
securityMode != nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL &&
|
||||
securityMode != nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) {
|
||||
MOZ_ASSERT(false, "need one securityflag from nsILoadInfo to perform security checks");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// make sure that cors-with-credentials is only used in combination with CORS.
|
||||
if (aLoadInfo->GetRequireCorsWithCredentials() &&
|
||||
securityMode != nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) {
|
||||
MOZ_ASSERT(false, "can not use cors-with-credentials without cors");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
// all good, found the right security flags
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
DoSOPChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo)
|
||||
{
|
||||
nsSecurityFlags securityMode = aLoadInfo->GetSecurityMode();
|
||||
|
||||
// if none of the REQUIRE_SAME_ORIGIN flags are set, then SOP does not apply
|
||||
if ((securityMode != nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS) &&
|
||||
(securityMode != nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_IS_BLOCKED)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIPrincipal* loadingPrincipal = aLoadInfo->LoadingPrincipal();
|
||||
bool sameOriginDataInherits =
|
||||
securityMode == nsILoadInfo::SEC_REQUIRE_SAME_ORIGIN_DATA_INHERITS;
|
||||
return loadingPrincipal->CheckMayLoad(aURI,
|
||||
true, // report to console
|
||||
sameOriginDataInherits);
|
||||
}
|
||||
|
||||
nsresult
|
||||
DoCheckLoadURIChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
nsSecurityFlags securityMode = aLoadInfo->GetSecurityMode();
|
||||
// Please note that checkLoadURIWithPrincipal should only be enforced for
|
||||
// cross origin requests. If the flag SEC_REQUIRE_CORS_DATA_INHERITS is set
|
||||
// within the loadInfo, then then CheckLoadURIWithPrincipal is performed
|
||||
// within nsCorsListenerProxy
|
||||
if ((securityMode != nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_INHERITS) &&
|
||||
(securityMode != nsILoadInfo::SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIPrincipal> loadingPrincipal = aLoadInfo->LoadingPrincipal();
|
||||
// XXX: @arg nsIScriptSecurityManager::STANDARD
|
||||
// lets use STANDARD for now and evaluate on a callsite basis, see also:
|
||||
// http://mxr.mozilla.org/mozilla-central/source/caps/nsIScriptSecurityManager.idl#62
|
||||
rv = nsContentUtils::GetSecurityManager()->
|
||||
CheckLoadURIWithPrincipal(loadingPrincipal,
|
||||
aURI,
|
||||
nsIScriptSecurityManager::STANDARD);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// If the loadingPrincipal and the triggeringPrincipal are different, then make
|
||||
// sure the triggeringPrincipal is allowed to access that URI.
|
||||
nsCOMPtr<nsIPrincipal> triggeringPrincipal = aLoadInfo->TriggeringPrincipal();
|
||||
if (loadingPrincipal != triggeringPrincipal) {
|
||||
rv = nsContentUtils::GetSecurityManager()->
|
||||
CheckLoadURIWithPrincipal(triggeringPrincipal,
|
||||
aURI,
|
||||
nsIScriptSecurityManager::STANDARD);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
DoCORSChecks(nsIChannel* aChannel, nsILoadInfo* aLoadInfo,
|
||||
nsCOMPtr<nsIStreamListener>& aInAndOutListener)
|
||||
{
|
||||
if (aLoadInfo->GetSecurityMode() != nsILoadInfo::SEC_REQUIRE_CORS_DATA_INHERITS) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsIPrincipal* loadingPrincipal = aLoadInfo->LoadingPrincipal();
|
||||
nsRefPtr<nsCORSListenerProxy> corsListener =
|
||||
new nsCORSListenerProxy(aInAndOutListener,
|
||||
loadingPrincipal,
|
||||
aLoadInfo->GetRequireCorsWithCredentials());
|
||||
// XXX: @arg: DataURIHandling::Allow
|
||||
// lets use DataURIHandling::Allow for now and then decide on callsite basis. see also:
|
||||
// http://mxr.mozilla.org/mozilla-central/source/dom/security/nsCORSListenerProxy.h#33
|
||||
nsresult rv = corsListener->Init(aChannel, DataURIHandling::Allow);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
aInAndOutListener = corsListener;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
DoContentSecurityChecks(nsIURI* aURI, nsILoadInfo* aLoadInfo)
|
||||
{
|
||||
nsContentPolicyType contentPolicyType = aLoadInfo->GetContentPolicyType();
|
||||
nsCString mimeTypeGuess;
|
||||
nsCOMPtr<nsISupports> requestingContext = nullptr;
|
||||
|
||||
switch(contentPolicyType) {
|
||||
case nsIContentPolicy::TYPE_OTHER:
|
||||
case nsIContentPolicy::TYPE_SCRIPT:
|
||||
case nsIContentPolicy::TYPE_IMAGE:
|
||||
case nsIContentPolicy::TYPE_STYLESHEET:
|
||||
case nsIContentPolicy::TYPE_OBJECT:
|
||||
case nsIContentPolicy::TYPE_DOCUMENT:
|
||||
case nsIContentPolicy::TYPE_SUBDOCUMENT:
|
||||
case nsIContentPolicy::TYPE_REFRESH:
|
||||
case nsIContentPolicy::TYPE_XBL:
|
||||
case nsIContentPolicy::TYPE_PING:
|
||||
case nsIContentPolicy::TYPE_XMLHTTPREQUEST:
|
||||
// alias nsIContentPolicy::TYPE_DATAREQUEST:
|
||||
case nsIContentPolicy::TYPE_OBJECT_SUBREQUEST:
|
||||
case nsIContentPolicy::TYPE_DTD:
|
||||
case nsIContentPolicy::TYPE_FONT:
|
||||
MOZ_ASSERT(false, "contentPolicyType not supported yet");
|
||||
break;
|
||||
|
||||
case nsIContentPolicy::TYPE_MEDIA:
|
||||
mimeTypeGuess = EmptyCString();
|
||||
requestingContext = aLoadInfo->LoadingNode();
|
||||
#ifdef DEBUG
|
||||
{
|
||||
nsCOMPtr<mozilla::dom::Element> element = do_QueryInterface(requestingContext);
|
||||
NS_ASSERTION(element != nullptr,
|
||||
"type_media requires requestingContext of type Element");
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
|
||||
case nsIContentPolicy::TYPE_WEBSOCKET:
|
||||
case nsIContentPolicy::TYPE_CSP_REPORT:
|
||||
case nsIContentPolicy::TYPE_XSLT:
|
||||
case nsIContentPolicy::TYPE_BEACON:
|
||||
case nsIContentPolicy::TYPE_FETCH:
|
||||
case nsIContentPolicy::TYPE_IMAGESET:
|
||||
MOZ_ASSERT(false, "contentPolicyType not supported yet");
|
||||
break;
|
||||
|
||||
default:
|
||||
// nsIContentPolicy::TYPE_INVALID
|
||||
MOZ_ASSERT(false, "can not perform security check without a valid contentType");
|
||||
}
|
||||
|
||||
int16_t shouldLoad = nsIContentPolicy::ACCEPT;
|
||||
nsresult rv = NS_CheckContentLoadPolicy(contentPolicyType,
|
||||
aURI,
|
||||
aLoadInfo->LoadingPrincipal(),
|
||||
requestingContext,
|
||||
mimeTypeGuess,
|
||||
nullptr, //extra,
|
||||
&shouldLoad,
|
||||
nsContentUtils::GetContentPolicy(),
|
||||
nsContentUtils::GetSecurityManager());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (NS_CP_REJECTED(shouldLoad)) {
|
||||
return NS_ERROR_CONTENT_BLOCKED;
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Based on the security flags provided in the loadInfo of the channel,
|
||||
* doContentSecurityCheck() performs the following content security checks
|
||||
* before opening the channel:
|
||||
*
|
||||
* (1) Same Origin Policy Check (if applicable)
|
||||
* (2) Allow Cross Origin but perform sanity checks whether a principal
|
||||
* is allowed to access the following URL.
|
||||
* (3) Perform CORS check (if applicable)
|
||||
* (4) ContentPolicy checks (Content-Security-Policy, Mixed Content, ...)
|
||||
*
|
||||
* @param aChannel
|
||||
* The channel to perform the security checks on.
|
||||
* @param aInAndOutListener
|
||||
* The streamListener that is passed to channel->AsyncOpen2() that is now potentially
|
||||
* wrappend within nsCORSListenerProxy() and becomes the corsListener that now needs
|
||||
* to be set as new streamListener on the channel.
|
||||
*/
|
||||
nsresult
|
||||
nsContentSecurityManager::doContentSecurityCheck(nsIChannel* aChannel,
|
||||
nsCOMPtr<nsIStreamListener>& aInAndOutListener)
|
||||
{
|
||||
NS_ENSURE_ARG(aChannel);
|
||||
nsCOMPtr<nsILoadInfo> loadInfo = aChannel->GetLoadInfo();
|
||||
|
||||
if (!loadInfo) {
|
||||
MOZ_ASSERT(false, "channel needs to have loadInfo to perform security checks");
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// make sure that only one of the five security flags is set in the loadinfo
|
||||
// e.g. do not require same origin and allow cross origin at the same time
|
||||
nsresult rv = ValidateSecurityFlags(loadInfo);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// lets store the initialSecurityCheckDone flag which indicates whether the channel
|
||||
// was initialy evaluated by the contentSecurityManager. Once the inital
|
||||
// asyncOpen() of the channel went through the contentSecurityManager then
|
||||
// redirects do not have perform all the security checks, e.g. no reason
|
||||
// to setup CORS again.
|
||||
bool initialSecurityCheckDone = loadInfo->GetInitialSecurityCheckDone();
|
||||
|
||||
// now lets set the initalSecurityFlag for subsequent calls
|
||||
rv = loadInfo->SetInitialSecurityCheckDone(true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// since aChannel was openend using asyncOpen2() we have to make sure
|
||||
// that redirects of that channel also get openend using asyncOpen2()
|
||||
// please note that some implementations of ::AsyncOpen2 might already
|
||||
// have set that flag to true (e.g. nsViewSourceChannel) in which case
|
||||
// we just set the flag again.
|
||||
rv = loadInfo->SetEnforceSecurity(true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsIURI> finalChannelURI;
|
||||
rv = NS_GetFinalChannelURI(aChannel, getter_AddRefs(finalChannelURI));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Perform Same Origin Policy check
|
||||
rv = DoSOPChecks(finalChannelURI, loadInfo);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// if dealing with a redirected channel then we only enforce SOP
|
||||
// and can return at this point.
|
||||
if (initialSecurityCheckDone) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
rv = DoCheckLoadURIChecks(finalChannelURI, loadInfo);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Check if CORS needs to be set up
|
||||
rv = DoCORSChecks(aChannel, loadInfo, aInAndOutListener);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Perform all ContentPolicy checks (MixedContent, CSP, ...)
|
||||
rv = DoContentSecurityChecks(finalChannelURI, loadInfo);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// all security checks passed - lets allow the load
|
||||
return NS_OK;
|
||||
}
|
24
dom/security/nsContentSecurityManager.h
Normal file
24
dom/security/nsContentSecurityManager.h
Normal file
@ -0,0 +1,24 @@
|
||||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* 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/. */
|
||||
|
||||
#ifndef nsContentSecurityManager_h___
|
||||
#define nsContentSecurityManager_h___
|
||||
|
||||
#include "nsIChannel.h"
|
||||
class nsIStreamListener;
|
||||
|
||||
class nsContentSecurityManager
|
||||
{
|
||||
private:
|
||||
nsContentSecurityManager() {}
|
||||
virtual ~nsContentSecurityManager() {}
|
||||
|
||||
public:
|
||||
static nsresult doContentSecurityCheck(nsIChannel* aChannel,
|
||||
nsCOMPtr<nsIStreamListener>& aInAndOutListener);
|
||||
};
|
||||
|
||||
#endif /* nsContentSecurityManager_h___ */
|
@ -435,8 +435,15 @@ PushMessageData::~PushMessageData()
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS0(PushMessageData);
|
||||
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_0(PushMessageData);
|
||||
|
||||
NS_IMPL_CYCLE_COLLECTING_ADDREF(PushMessageData)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(PushMessageData)
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(PushMessageData)
|
||||
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupports)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
||||
void
|
||||
PushMessageData::Json(JSContext* cx, JS::MutableHandle<JSObject*> aRetval)
|
||||
|
@ -163,7 +163,8 @@ class PushMessageData final : public nsISupports,
|
||||
nsString mData;
|
||||
|
||||
public:
|
||||
NS_DECL_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTING_ISUPPORTS
|
||||
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(PushMessageData)
|
||||
|
||||
virtual JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override
|
||||
{
|
||||
|
@ -340,7 +340,7 @@ public:
|
||||
};
|
||||
|
||||
WorkerCrossThreadDispatcher*
|
||||
GetWorkerCrossThreadDispatcher(JSContext* aCx, jsval aWorker);
|
||||
GetWorkerCrossThreadDispatcher(JSContext* aCx, JS::Value aWorker);
|
||||
|
||||
// Random unique constant to facilitate JSPrincipal debugging
|
||||
const uint32_t kJSPrincipalsDebugToken = 0x7e2df9d2;
|
||||
|
@ -46,8 +46,7 @@ self.addEventListener("fetch", function(event) {
|
||||
event.respondWith(fetch("context_test.js"));
|
||||
}
|
||||
} else if (event.request.url.indexOf("frame") >= 0) {
|
||||
// FIXME: Bug 1148044: This should be "frame".
|
||||
if (event.request.context == "iframe") {
|
||||
if (event.request.context == "frame") {
|
||||
event.respondWith(fetch("context_test.js"));
|
||||
}
|
||||
} else if (event.request.url.indexOf("newwindow") >= 0) {
|
||||
|
@ -128,8 +128,7 @@
|
||||
document.documentElement.appendChild(embed);
|
||||
navigator.serviceWorker.addEventListener("message", function onMessage(e) {
|
||||
if (e.data.data == "embed") {
|
||||
// FIXME: Bug 1148030: This should be "embed".
|
||||
is(e.data.context, "object", "Expected the object context on an embed");
|
||||
is(e.data.context, "embed", "Expected the object context on an embed");
|
||||
navigator.serviceWorker.removeEventListener("message", onMessage);
|
||||
resolve();
|
||||
}
|
||||
|
@ -562,7 +562,8 @@ nsWindowWatcher::OpenWindowInternal(nsIDOMWindow* aParent,
|
||||
// security checks.
|
||||
chromeFlags = CalculateChromeFlags(aParent, features.get(), featuresSpecified,
|
||||
aDialog, uriToLoadIsChrome,
|
||||
hasChromeParent, openedFromRemoteTab);
|
||||
hasChromeParent, aCalledFromJS,
|
||||
openedFromRemoteTab);
|
||||
|
||||
// If we are opening a window from a remote browser, the resulting window
|
||||
// should also be remote.
|
||||
@ -1466,8 +1467,8 @@ nsWindowWatcher::URIfromURL(const char* aURL,
|
||||
|
||||
#define NS_CALCULATE_CHROME_FLAG_FOR(feature, flag) \
|
||||
prefBranch->GetBoolPref(feature, &forceEnable); \
|
||||
if (forceEnable && !(aDialog && isCallerChrome) && \
|
||||
!(isCallerChrome && aHasChromeParent) && !aChromeURL) { \
|
||||
if (forceEnable && !(aDialog && !openedFromContentScript) && \
|
||||
!(!openedFromContentScript && aHasChromeParent) && !aChromeURL) { \
|
||||
chromeFlags |= flag; \
|
||||
} else { \
|
||||
chromeFlags |= \
|
||||
@ -1491,26 +1492,30 @@ nsWindowWatcher::CalculateChromeFlags(nsIDOMWindow* aParent,
|
||||
bool aDialog,
|
||||
bool aChromeURL,
|
||||
bool aHasChromeParent,
|
||||
bool aCalledFromJS,
|
||||
bool aOpenedFromRemoteTab)
|
||||
{
|
||||
const bool inContentProcess = XRE_IsContentProcess();
|
||||
uint32_t chromeFlags = 0;
|
||||
bool isCallerChrome =
|
||||
nsContentUtils::IsCallerChrome() && !aOpenedFromRemoteTab;
|
||||
|
||||
bool onlyPrivateFlag = aFeaturesSpecified && aFeatures && isCallerChrome &&
|
||||
nsCRT::strcasecmp(aFeatures, "private") == 0;
|
||||
if (!aFeaturesSpecified || !aFeatures || onlyPrivateFlag) {
|
||||
if (!aFeaturesSpecified || !aFeatures) {
|
||||
chromeFlags = nsIWebBrowserChrome::CHROME_ALL;
|
||||
if (aDialog) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_OPENAS_DIALOG |
|
||||
nsIWebBrowserChrome::CHROME_OPENAS_CHROME;
|
||||
}
|
||||
if (onlyPrivateFlag) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW;
|
||||
|
||||
if (inContentProcess) {
|
||||
return chromeFlags;
|
||||
}
|
||||
return chromeFlags;
|
||||
} else {
|
||||
chromeFlags = nsIWebBrowserChrome::CHROME_WINDOW_BORDERS;
|
||||
}
|
||||
|
||||
bool openedFromContentScript =
|
||||
aOpenedFromRemoteTab ? aCalledFromJS
|
||||
: !nsContentUtils::IsCallerChrome();
|
||||
|
||||
/* This function has become complicated since browser windows and
|
||||
dialogs diverged. The difference is, browser windows assume all
|
||||
chrome not explicitly mentioned is off, if the features string
|
||||
@ -1520,30 +1525,32 @@ nsWindowWatcher::CalculateChromeFlags(nsIDOMWindow* aParent,
|
||||
in the standards-compliant window.(normal)open. */
|
||||
|
||||
bool presenceFlag = false;
|
||||
|
||||
chromeFlags = nsIWebBrowserChrome::CHROME_WINDOW_BORDERS;
|
||||
if (aDialog && WinHasOption(aFeatures, "all", 0, &presenceFlag)) {
|
||||
chromeFlags = nsIWebBrowserChrome::CHROME_ALL;
|
||||
}
|
||||
|
||||
/* Next, allow explicitly named options to override the initial settings */
|
||||
|
||||
// Determine whether the window is a private browsing window
|
||||
if (isCallerChrome) {
|
||||
if (!inContentProcess && !openedFromContentScript) {
|
||||
// Determine whether the window is a private browsing window
|
||||
chromeFlags |= WinHasOption(aFeatures, "private", 0, &presenceFlag) ?
|
||||
nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW : 0;
|
||||
chromeFlags |= WinHasOption(aFeatures, "non-private", 0, &presenceFlag) ?
|
||||
nsIWebBrowserChrome::CHROME_NON_PRIVATE_WINDOW : 0;
|
||||
}
|
||||
|
||||
// Determine whether the window should have remote tabs.
|
||||
if (isCallerChrome || aOpenedFromRemoteTab) {
|
||||
bool remote;
|
||||
if (BrowserTabsRemoteAutostart()) {
|
||||
remote = !WinHasOption(aFeatures, "non-remote", 0, &presenceFlag);
|
||||
} else {
|
||||
remote = WinHasOption(aFeatures, "remote", 0, &presenceFlag);
|
||||
if (!inContentProcess) {
|
||||
// Determine whether the window should have remote tabs.
|
||||
bool remote = BrowserTabsRemoteAutostart();
|
||||
|
||||
if (!openedFromContentScript) {
|
||||
if (remote) {
|
||||
remote = !WinHasOption(aFeatures, "non-remote", 0, &presenceFlag);
|
||||
} else {
|
||||
remote = WinHasOption(aFeatures, "remote", 0, &presenceFlag);
|
||||
}
|
||||
}
|
||||
|
||||
if (remote) {
|
||||
chromeFlags |= nsIWebBrowserChrome::CHROME_REMOTE_WINDOW;
|
||||
}
|
||||
@ -1644,7 +1651,7 @@ nsWindowWatcher::CalculateChromeFlags(nsIDOMWindow* aParent,
|
||||
if (aParent) {
|
||||
aParent->GetFullScreen(&isFullScreen);
|
||||
}
|
||||
if (isFullScreen && !isCallerChrome) {
|
||||
if (isFullScreen && openedFromContentScript) {
|
||||
// If the parent window is in fullscreen & the caller context is content,
|
||||
// dialog feature is disabled. (see bug 803675)
|
||||
disableDialogFeature = true;
|
||||
@ -1671,7 +1678,7 @@ nsWindowWatcher::CalculateChromeFlags(nsIDOMWindow* aParent,
|
||||
*/
|
||||
|
||||
// Check security state for use in determing window dimensions
|
||||
if (!isCallerChrome || !aHasChromeParent) {
|
||||
if (openedFromContentScript || !aHasChromeParent) {
|
||||
// If priv check fails (or if we're called from chrome, but the
|
||||
// parent is not a chrome window), set all elements to minimum
|
||||
// reqs., else leave them alone.
|
||||
@ -2270,12 +2277,19 @@ nsWindowWatcher::GetWindowOpenLocation(nsIDOMWindow* aParent,
|
||||
return nsIBrowserDOMWindow::OPEN_NEWWINDOW;
|
||||
}
|
||||
|
||||
if (restrictionPref == 2 &&
|
||||
// Only continue if there are no size/position features and no special
|
||||
// chrome flags.
|
||||
(aChromeFlags != nsIWebBrowserChrome::CHROME_ALL ||
|
||||
aPositionSpecified || aSizeSpecified)) {
|
||||
return nsIBrowserDOMWindow::OPEN_NEWWINDOW;
|
||||
if (restrictionPref == 2) {
|
||||
// Only continue if there are no size/position features and no special
|
||||
// chrome flags - with the exception of the remoteness and private flags,
|
||||
// which might have been automatically flipped by Gecko.
|
||||
int32_t uiChromeFlags = aChromeFlags;
|
||||
uiChromeFlags &= ~(nsIWebBrowserChrome::CHROME_REMOTE_WINDOW |
|
||||
nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW |
|
||||
nsIWebBrowserChrome::CHROME_NON_PRIVATE_WINDOW |
|
||||
nsIWebBrowserChrome::CHROME_PRIVATE_LIFETIME);
|
||||
if (uiChromeFlags != nsIWebBrowserChrome::CHROME_ALL ||
|
||||
aPositionSpecified || aSizeSpecified) {
|
||||
return nsIBrowserDOMWindow::OPEN_NEWWINDOW;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -96,6 +96,7 @@ protected:
|
||||
bool aDialog,
|
||||
bool aChromeURL,
|
||||
bool aHasChromeParent,
|
||||
bool aCalledFromJS,
|
||||
bool aOpenedFromRemoteTab);
|
||||
static int32_t WinHasOption(const char* aOptions, const char* aName,
|
||||
int32_t aDefault, bool* aPresenceFlag);
|
||||
|
@ -340,92 +340,95 @@ UpgradeHostToOriginAndInsert(const nsACString& aHost, const nsAFlatCString& aTyp
|
||||
// to guess what ports and protocols we want to add permissions for.
|
||||
// We find every URI which they have visited with this host (or a subdomain of this host),
|
||||
// and try to add it as a principal.
|
||||
bool foundHistory = false;
|
||||
|
||||
nsCOMPtr<nsINavHistoryService> histSrv = do_GetService(NS_NAVHISTORYSERVICE_CONTRACTID);
|
||||
|
||||
nsCOMPtr<nsINavHistoryQuery> histQuery;
|
||||
rv = histSrv->GetNewQuery(getter_AddRefs(histQuery));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (histSrv) {
|
||||
nsCOMPtr<nsINavHistoryQuery> histQuery;
|
||||
rv = histSrv->GetNewQuery(getter_AddRefs(histQuery));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// We want to only find history items for this particular host, and subdomains
|
||||
rv = histQuery->SetDomain(aHost);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// We want to only find history items for this particular host, and subdomains
|
||||
rv = histQuery->SetDomain(aHost);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = histQuery->SetDomainIsHost(false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = histQuery->SetDomainIsHost(false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsINavHistoryQueryOptions> histQueryOpts;
|
||||
rv = histSrv->GetNewQueryOptions(getter_AddRefs(histQueryOpts));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsINavHistoryQueryOptions> histQueryOpts;
|
||||
rv = histSrv->GetNewQueryOptions(getter_AddRefs(histQueryOpts));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// We want to get the URIs for every item in the user's history with the given host
|
||||
rv = histQueryOpts->SetResultType(nsINavHistoryQueryOptions::RESULTS_AS_URI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// We want to get the URIs for every item in the user's history with the given host
|
||||
rv = histQueryOpts->SetResultType(nsINavHistoryQueryOptions::RESULTS_AS_URI);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// We only search history, because searching both bookmarks and history
|
||||
// is not supported, and history tends to be more comprehensive.
|
||||
rv = histQueryOpts->SetQueryType(nsINavHistoryQueryOptions::QUERY_TYPE_HISTORY);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// We only search history, because searching both bookmarks and history
|
||||
// is not supported, and history tends to be more comprehensive.
|
||||
rv = histQueryOpts->SetQueryType(nsINavHistoryQueryOptions::QUERY_TYPE_HISTORY);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// We include hidden URIs (such as those visited via iFrames) as they may have permissions too
|
||||
rv = histQueryOpts->SetIncludeHidden(true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// We include hidden URIs (such as those visited via iFrames) as they may have permissions too
|
||||
rv = histQueryOpts->SetIncludeHidden(true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsINavHistoryResult> histResult;
|
||||
rv = histSrv->ExecuteQuery(histQuery, histQueryOpts, getter_AddRefs(histResult));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsINavHistoryResult> histResult;
|
||||
rv = histSrv->ExecuteQuery(histQuery, histQueryOpts, getter_AddRefs(histResult));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsCOMPtr<nsINavHistoryContainerResultNode> histResultContainer;
|
||||
rv = histResult->GetRoot(getter_AddRefs(histResultContainer));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsINavHistoryContainerResultNode> histResultContainer;
|
||||
rv = histResult->GetRoot(getter_AddRefs(histResultContainer));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
rv = histResultContainer->SetContainerOpen(true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = histResultContainer->SetContainerOpen(true);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
uint32_t childCount = 0;
|
||||
rv = histResultContainer->GetChildCount(&childCount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
uint32_t childCount = 0;
|
||||
rv = histResultContainer->GetChildCount(&childCount);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool foundHistory = false;
|
||||
for (uint32_t i = 0; i < childCount; i++) {
|
||||
nsCOMPtr<nsINavHistoryResultNode> child;
|
||||
histResultContainer->GetChild(i, getter_AddRefs(child));
|
||||
if (NS_FAILED(rv)) continue;
|
||||
for (uint32_t i = 0; i < childCount; i++) {
|
||||
nsCOMPtr<nsINavHistoryResultNode> child;
|
||||
histResultContainer->GetChild(i, getter_AddRefs(child));
|
||||
if (NS_FAILED(rv)) continue;
|
||||
|
||||
uint32_t type;
|
||||
rv = child->GetType(&type);
|
||||
if (NS_FAILED(rv) || type != nsINavHistoryResultNode::RESULT_TYPE_URI) {
|
||||
NS_WARNING("Unexpected non-RESULT_TYPE_URI node in "
|
||||
"UpgradeHostToOriginAndInsert()");
|
||||
continue;
|
||||
uint32_t type;
|
||||
rv = child->GetType(&type);
|
||||
if (NS_FAILED(rv) || type != nsINavHistoryResultNode::RESULT_TYPE_URI) {
|
||||
NS_WARNING("Unexpected non-RESULT_TYPE_URI node in "
|
||||
"UpgradeHostToOriginAndInsert()");
|
||||
continue;
|
||||
}
|
||||
|
||||
nsAutoCString uriSpec;
|
||||
rv = child->GetUri(uriSpec);
|
||||
if (NS_FAILED(rv)) continue;
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = NS_NewURI(getter_AddRefs(uri), uriSpec);
|
||||
if (NS_FAILED(rv)) continue;
|
||||
|
||||
// Use the provided host - this URI may be for a subdomain, rather than the host we care about.
|
||||
rv = uri->SetHost(aHost);
|
||||
if (NS_FAILED(rv)) continue;
|
||||
|
||||
// We now have a URI which we can make a nsIPrincipal out of
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
rv = GetPrincipal(uri, aAppId, aIsInBrowserElement, getter_AddRefs(principal));
|
||||
if (NS_FAILED(rv)) continue;
|
||||
|
||||
// Insert it! (The backend should be able to deal with us inserting the same origin repeatedly)
|
||||
foundHistory = true;
|
||||
rv = aHelper->Insert(principal, aType, aPermission,
|
||||
aExpireType, aExpireTime, aModificationTime);
|
||||
NS_WARN_IF(NS_FAILED(rv));
|
||||
}
|
||||
|
||||
nsAutoCString uriSpec;
|
||||
rv = child->GetUri(uriSpec);
|
||||
if (NS_FAILED(rv)) continue;
|
||||
|
||||
nsCOMPtr<nsIURI> uri;
|
||||
rv = NS_NewURI(getter_AddRefs(uri), uriSpec);
|
||||
if (NS_FAILED(rv)) continue;
|
||||
|
||||
// Use the provided host - this URI may be for a subdomain, rather than the host we care about.
|
||||
rv = uri->SetHost(aHost);
|
||||
if (NS_FAILED(rv)) continue;
|
||||
|
||||
// We now have a URI which we can make a nsIPrincipal out of
|
||||
nsCOMPtr<nsIPrincipal> principal;
|
||||
rv = GetPrincipal(uri, aAppId, aIsInBrowserElement, getter_AddRefs(principal));
|
||||
if (NS_FAILED(rv)) continue;
|
||||
|
||||
// Insert it! (The backend should be able to deal with us inserting the same origin repeatedly)
|
||||
foundHistory = true;
|
||||
rv = aHelper->Insert(principal, aType, aPermission,
|
||||
aExpireType, aExpireTime, aModificationTime);
|
||||
NS_WARN_IF(NS_FAILED(rv));
|
||||
rv = histResultContainer->SetContainerOpen(false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
rv = histResultContainer->SetContainerOpen(false);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// If we didn't find any origins for this host in the poermissions database,
|
||||
// we can insert the default http:// and https:// permissions into the database.
|
||||
// This has a relatively high liklihood of applying the permission to the correct
|
||||
|
@ -44,6 +44,12 @@
|
||||
#define LOCAL_GL_ATC_RGBA_EXPLICIT_ALPHA 0x8C93
|
||||
#define LOCAL_GL_ATC_RGBA_INTERPOLATED_ALPHA 0x87EE
|
||||
|
||||
// EGL_ANDROID_image_crop
|
||||
#define LOCAL_EGL_IMAGE_CROP_LEFT_ANDROID 0x3148
|
||||
#define LOCAL_EGL_IMAGE_CROP_TOP_ANDROID 0x3149
|
||||
#define LOCAL_EGL_IMAGE_CROP_RIGHT_ANDROID 0x314A
|
||||
#define LOCAL_EGL_IMAGE_CROP_BOTTOM_ANDROID 0x314B
|
||||
|
||||
// Others
|
||||
#define LOCAL_EGL_PRESERVED_RESOURCES 0x3030
|
||||
#define LOCAL_EGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_EXT 0x3138
|
||||
|
@ -36,6 +36,7 @@ static const char *sEGLExtensionNames[] = {
|
||||
"EGL_KHR_image",
|
||||
"EGL_KHR_fence_sync",
|
||||
"EGL_ANDROID_native_fence_sync",
|
||||
"EGL_ANDROID_image_crop",
|
||||
"ANGLE_platform_angle",
|
||||
"ANGLE_platform_angle_d3d"
|
||||
};
|
||||
|
@ -131,6 +131,7 @@ public:
|
||||
KHR_image,
|
||||
KHR_fence_sync,
|
||||
ANDROID_native_fence_sync,
|
||||
EGL_ANDROID_image_crop,
|
||||
ANGLE_platform_angle,
|
||||
ANGLE_platform_angle_d3d,
|
||||
Extensions_Max
|
||||
|
@ -95,6 +95,9 @@ ImageHost::UseTextureHost(const nsTArray<TimedTexture>& aTextures)
|
||||
img.mTextureSource = mImages.LastElement().mTextureSource;
|
||||
mImages.RemoveElementAt(mImages.Length() - 1);
|
||||
}
|
||||
// SetCropRect() affects only on a specific platform.
|
||||
// If it is not implemented, it does nothing.
|
||||
img.mFrontBuffer->SetCropRect(img.mPictureRect);
|
||||
img.mFrontBuffer->Updated();
|
||||
img.mFrontBuffer->PrepareTextureSource(img.mTextureSource);
|
||||
}
|
||||
|
@ -417,6 +417,11 @@ public:
|
||||
|
||||
virtual gfx::IntSize GetSize() const = 0;
|
||||
|
||||
/**
|
||||
* Should be overridden if TextureHost supports crop rect.
|
||||
*/
|
||||
virtual void SetCropRect(nsIntRect aCropRect) {}
|
||||
|
||||
/**
|
||||
* Debug facility.
|
||||
* XXX - cool kids use Moz2D. See bug 882113.
|
||||
|
@ -84,12 +84,6 @@ struct EGLImageDescriptor {
|
||||
|
||||
struct NewSurfaceDescriptorGralloc {
|
||||
MaybeMagicGrallocBufferHandle buffer;
|
||||
/**
|
||||
* android::GraphicBuffer has a size information. But there are cases
|
||||
* that GraphicBuffer's size and actual video's size are different.
|
||||
* Extra size member is necessary. See Bug 850566.
|
||||
*/
|
||||
IntSize size;
|
||||
bool isOpaque;
|
||||
};
|
||||
|
||||
|
@ -15,17 +15,32 @@ namespace layers {
|
||||
using namespace gl;
|
||||
|
||||
EGLImage
|
||||
EGLImageCreateFromNativeBuffer(GLContext* aGL, void* aBuffer)
|
||||
EGLImageCreateFromNativeBuffer(GLContext* aGL, void* aBuffer, const gfx::IntSize& aCropSize)
|
||||
{
|
||||
EGLint attrs[] = {
|
||||
LOCAL_EGL_IMAGE_PRESERVED, LOCAL_EGL_TRUE,
|
||||
LOCAL_EGL_NONE, LOCAL_EGL_NONE
|
||||
LOCAL_EGL_NONE, LOCAL_EGL_NONE,
|
||||
};
|
||||
|
||||
EGLint cropAttrs[] = {
|
||||
LOCAL_EGL_IMAGE_PRESERVED, LOCAL_EGL_TRUE,
|
||||
LOCAL_EGL_IMAGE_CROP_LEFT_ANDROID, 0,
|
||||
LOCAL_EGL_IMAGE_CROP_TOP_ANDROID, 0,
|
||||
LOCAL_EGL_IMAGE_CROP_RIGHT_ANDROID, aCropSize.width,
|
||||
LOCAL_EGL_IMAGE_CROP_BOTTOM_ANDROID, aCropSize.height,
|
||||
LOCAL_EGL_NONE, LOCAL_EGL_NONE,
|
||||
};
|
||||
|
||||
bool hasCropRect = (aCropSize.width != 0 && aCropSize.height != 0);
|
||||
EGLint* usedAttrs = attrs;
|
||||
if (hasCropRect && sEGLLibrary.IsExtensionSupported(GLLibraryEGL::EGL_ANDROID_image_crop)) {
|
||||
usedAttrs = cropAttrs;
|
||||
}
|
||||
|
||||
return sEGLLibrary.fCreateImage(sEGLLibrary.Display(),
|
||||
EGL_NO_CONTEXT,
|
||||
LOCAL_EGL_NATIVE_BUFFER_ANDROID,
|
||||
aBuffer, attrs);
|
||||
aBuffer, usedAttrs);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -7,6 +7,8 @@
|
||||
#ifndef EGLIMAGEHELPERS_H_
|
||||
#define EGLIMAGEHELPERS_H_
|
||||
|
||||
#include "mozilla/gfx/Point.h"
|
||||
|
||||
typedef void* EGLImage;
|
||||
|
||||
namespace mozilla {
|
||||
@ -16,7 +18,7 @@ namespace gl {
|
||||
|
||||
namespace layers {
|
||||
|
||||
EGLImage EGLImageCreateFromNativeBuffer(gl::GLContext* aGL, void* aBuffer);
|
||||
EGLImage EGLImageCreateFromNativeBuffer(gl::GLContext* aGL, void* aBuffer, const gfx::IntSize& aCropSize);
|
||||
void EGLImageDestroy(gl::GLContext* aGL, EGLImage aImage);
|
||||
|
||||
} // namespace layers
|
||||
|
@ -71,7 +71,7 @@ GrallocTextureClientOGL::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
|
||||
return false;
|
||||
}
|
||||
|
||||
aOutDescriptor = NewSurfaceDescriptorGralloc(mGrallocHandle, mSize, mIsOpaque);
|
||||
aOutDescriptor = NewSurfaceDescriptorGralloc(mGrallocHandle, mIsOpaque);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -139,13 +139,6 @@ protected:
|
||||
|
||||
RefPtr<gfx::DrawTarget> mDrawTarget;
|
||||
|
||||
/**
|
||||
* android::GraphicBuffer has a size information. But there are cases
|
||||
* that GraphicBuffer's size and actual video's size are different.
|
||||
* Extra size member is necessary. See Bug 850566.
|
||||
*/
|
||||
gfx::IntSize mSize;
|
||||
|
||||
android::MediaBuffer* mMediaBuffer;
|
||||
|
||||
bool mIsOpaque;
|
||||
|
@ -103,7 +103,7 @@ GrallocTextureHostOGL::GrallocTextureHostOGL(TextureFlags aFlags,
|
||||
: TextureHost(aFlags)
|
||||
, mGrallocHandle(aDescriptor)
|
||||
, mSize(0, 0)
|
||||
, mDescriptorSize(aDescriptor.size())
|
||||
, mCropSize(0, 0)
|
||||
, mFormat(gfx::SurfaceFormat::UNKNOWN)
|
||||
, mEGLImage(EGL_NO_IMAGE)
|
||||
, mIsOpaque(aDescriptor.isOpaque())
|
||||
@ -116,6 +116,7 @@ GrallocTextureHostOGL::GrallocTextureHostOGL(TextureFlags aFlags,
|
||||
SurfaceFormatForAndroidPixelFormat(graphicBuffer->getPixelFormat(),
|
||||
aFlags & TextureFlags::RB_SWAPPED);
|
||||
mSize = gfx::IntSize(graphicBuffer->getWidth(), graphicBuffer->getHeight());
|
||||
mCropSize = mSize;
|
||||
} else {
|
||||
printf_stderr("gralloc buffer is nullptr");
|
||||
}
|
||||
@ -222,7 +223,7 @@ GrallocTextureHostOGL::GetRenderState()
|
||||
flags |= LayerRenderStateFlags::FORMAT_RB_SWAP;
|
||||
}
|
||||
return LayerRenderState(graphicBuffer,
|
||||
mDescriptorSize,
|
||||
mCropSize,
|
||||
flags,
|
||||
this);
|
||||
}
|
||||
@ -344,8 +345,12 @@ GrallocTextureHostOGL::PrepareTextureSource(CompositableTextureSourceRef& aTextu
|
||||
}
|
||||
|
||||
if (mEGLImage == EGL_NO_IMAGE) {
|
||||
gfx::IntSize cropSize(0, 0);
|
||||
if (mCropSize != mSize) {
|
||||
cropSize = mCropSize;
|
||||
}
|
||||
// Should only happen the first time.
|
||||
mEGLImage = EGLImageCreateFromNativeBuffer(gl, graphicBuffer->getNativeBuffer());
|
||||
mEGLImage = EGLImageCreateFromNativeBuffer(gl, graphicBuffer->getNativeBuffer(), cropSize);
|
||||
}
|
||||
|
||||
GLenum textureTarget = GetTextureTarget(gl, graphicBuffer->getPixelFormat());
|
||||
@ -414,6 +419,23 @@ GrallocTextureHostOGL::WaitAcquireFenceHandleSyncComplete()
|
||||
MOZ_ALWAYS_TRUE( sEGLLibrary.fDestroySync(EGL_DISPLAY(), sync) );
|
||||
}
|
||||
|
||||
void
|
||||
GrallocTextureHostOGL::SetCropRect(nsIntRect aCropRect)
|
||||
{
|
||||
MOZ_ASSERT(aCropRect.TopLeft() == IntPoint(0, 0));
|
||||
MOZ_ASSERT(!aCropRect.IsEmpty());
|
||||
MOZ_ASSERT(aCropRect.width <= mSize.width);
|
||||
MOZ_ASSERT(aCropRect.height <= mSize.height);
|
||||
|
||||
gfx::IntSize cropSize(aCropRect.width, aCropRect.height);
|
||||
if (mCropSize == cropSize) {
|
||||
return;
|
||||
}
|
||||
|
||||
mCropSize = cropSize;
|
||||
mGLTextureSource = nullptr;
|
||||
}
|
||||
|
||||
bool
|
||||
GrallocTextureHostOGL::BindTextureSource(CompositableTextureSourceRef& aTextureSource)
|
||||
{
|
||||
|
@ -38,7 +38,7 @@ public:
|
||||
|
||||
virtual gfx::SurfaceFormat GetFormat() const;
|
||||
|
||||
virtual gfx::IntSize GetSize() const override { return mDescriptorSize; }
|
||||
virtual gfx::IntSize GetSize() const override { return mCropSize; }
|
||||
|
||||
virtual LayerRenderState GetRenderState() override;
|
||||
|
||||
@ -52,6 +52,8 @@ public:
|
||||
|
||||
virtual void WaitAcquireFenceHandleSyncComplete() override;
|
||||
|
||||
virtual void SetCropRect(nsIntRect aCropRect) override;
|
||||
|
||||
bool IsValid() const;
|
||||
|
||||
virtual const char* Name() override { return "GrallocTextureHostOGL"; }
|
||||
@ -68,7 +70,7 @@ private:
|
||||
gfx::IntSize mSize;
|
||||
// Size reported by TextureClient, can be different in some cases (video?),
|
||||
// used by LayerRenderState.
|
||||
gfx::IntSize mDescriptorSize;
|
||||
gfx::IntSize mCropSize;
|
||||
gfx::SurfaceFormat mFormat;
|
||||
EGLImage mEGLImage;
|
||||
bool mIsOpaque;
|
||||
|
@ -273,8 +273,7 @@ FrameAnimator::GetCompositedFrame(uint32_t aFrameNum)
|
||||
|
||||
// If we have a composited version of this frame, return that.
|
||||
if (mLastCompositedFrameIndex == int32_t(aFrameNum)) {
|
||||
return LookupResult(mCompositingFrame->DrawableRef(),
|
||||
/* aIsExactMatch = */ true);
|
||||
return LookupResult(mCompositingFrame->DrawableRef(), MatchType::EXACT);
|
||||
}
|
||||
|
||||
// Otherwise return the raw frame. DoBlend is required to ensure that we only
|
||||
|
@ -18,6 +18,16 @@
|
||||
namespace mozilla {
|
||||
namespace image {
|
||||
|
||||
enum class MatchType : uint8_t
|
||||
{
|
||||
NOT_FOUND, // No matching surface and no placeholder.
|
||||
PENDING, // Found a matching placeholder, but no surface.
|
||||
EXACT, // Found a surface that matches exactly.
|
||||
SUBSTITUTE_BECAUSE_NOT_FOUND, // No exact match, but found a similar one.
|
||||
SUBSTITUTE_BECAUSE_PENDING // Found a similar surface and a placeholder
|
||||
// for an exact match.
|
||||
};
|
||||
|
||||
/**
|
||||
* LookupResult is the return type of SurfaceCache's Lookup*() functions. It
|
||||
* combines a surface with relevant metadata tracked by SurfaceCache.
|
||||
@ -25,25 +35,36 @@ namespace image {
|
||||
class MOZ_STACK_CLASS LookupResult
|
||||
{
|
||||
public:
|
||||
LookupResult()
|
||||
: mIsExactMatch(false)
|
||||
{ }
|
||||
explicit LookupResult(MatchType aMatchType)
|
||||
: mMatchType(aMatchType)
|
||||
{
|
||||
MOZ_ASSERT(mMatchType == MatchType::NOT_FOUND ||
|
||||
mMatchType == MatchType::PENDING,
|
||||
"Only NOT_FOUND or PENDING make sense with no surface");
|
||||
}
|
||||
|
||||
LookupResult(LookupResult&& aOther)
|
||||
: mDrawableRef(Move(aOther.mDrawableRef))
|
||||
, mIsExactMatch(aOther.mIsExactMatch)
|
||||
, mMatchType(aOther.mMatchType)
|
||||
{ }
|
||||
|
||||
LookupResult(DrawableFrameRef&& aDrawableRef, bool aIsExactMatch)
|
||||
LookupResult(DrawableFrameRef&& aDrawableRef, MatchType aMatchType)
|
||||
: mDrawableRef(Move(aDrawableRef))
|
||||
, mIsExactMatch(aIsExactMatch)
|
||||
{ }
|
||||
, mMatchType(aMatchType)
|
||||
{
|
||||
MOZ_ASSERT(!mDrawableRef || !(mMatchType == MatchType::NOT_FOUND ||
|
||||
mMatchType == MatchType::PENDING),
|
||||
"Only NOT_FOUND or PENDING make sense with no surface");
|
||||
MOZ_ASSERT(mDrawableRef || mMatchType == MatchType::NOT_FOUND ||
|
||||
mMatchType == MatchType::PENDING,
|
||||
"NOT_FOUND or PENDING do not make sense with a surface");
|
||||
}
|
||||
|
||||
LookupResult& operator=(LookupResult&& aOther)
|
||||
{
|
||||
MOZ_ASSERT(&aOther != this, "Self-move-assignment is not supported");
|
||||
mDrawableRef = Move(aOther.mDrawableRef);
|
||||
mIsExactMatch = aOther.mIsExactMatch;
|
||||
mMatchType = aOther.mMatchType;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -53,14 +74,14 @@ public:
|
||||
/// @return true if this LookupResult contains a surface.
|
||||
explicit operator bool() const { return bool(mDrawableRef); }
|
||||
|
||||
/// @return true if the surface is an exact match for the Lookup*() arguments.
|
||||
bool IsExactMatch() const { return mIsExactMatch; }
|
||||
/// @return what kind of match this is (exact, substitute, etc.)
|
||||
MatchType Type() const { return mMatchType; }
|
||||
|
||||
private:
|
||||
LookupResult(const LookupResult&) = delete;
|
||||
|
||||
DrawableFrameRef mDrawableRef;
|
||||
bool mIsExactMatch;
|
||||
MatchType mMatchType;
|
||||
};
|
||||
|
||||
} // namespace image
|
||||
|
@ -526,8 +526,12 @@ RasterImage::LookupFrame(uint32_t aFrameNum,
|
||||
return DrawableFrameRef();
|
||||
}
|
||||
|
||||
if (!result || !result.IsExactMatch()) {
|
||||
// The OS threw this frame away. We need to redecode if we can.
|
||||
if (result.Type() == MatchType::NOT_FOUND ||
|
||||
result.Type() == MatchType::SUBSTITUTE_BECAUSE_NOT_FOUND ||
|
||||
((aFlags & FLAG_SYNC_DECODE) && !result)) {
|
||||
// We don't have a copy of this frame, and there's no decoder working on
|
||||
// one. (Or we're sync decoding and the existing decoder hasn't even started
|
||||
// yet.) Trigger decoding so it'll be available next time.
|
||||
MOZ_ASSERT(!mAnim, "Animated frames should be locked");
|
||||
|
||||
Decode(Some(requestedSize), aFlags);
|
||||
@ -1499,6 +1503,19 @@ RasterImage::CreateDecoder(const Maybe<IntSize>& aSize, uint32_t aFlags)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (aSize) {
|
||||
// Add a placeholder for the first frame to the SurfaceCache so we won't
|
||||
// trigger any more decoders with the same parameters.
|
||||
InsertOutcome outcome =
|
||||
SurfaceCache::InsertPlaceholder(ImageKey(this),
|
||||
RasterSurfaceKey(*aSize,
|
||||
decoder->GetDecodeFlags(),
|
||||
/* aFrameNum = */ 0));
|
||||
if (outcome != InsertOutcome::SUCCESS) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (!aSize) {
|
||||
Telemetry::GetHistogramById(
|
||||
Telemetry::IMAGE_DECODE_COUNT)->Subtract(mDecodeCount);
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "mozilla/Likely.h"
|
||||
#include "mozilla/Move.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "mozilla/Pair.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "nsIMemoryReporter.h"
|
||||
@ -67,6 +68,10 @@ static StaticRefPtr<SurfaceCacheImpl> sInstance;
|
||||
*/
|
||||
typedef size_t Cost;
|
||||
|
||||
// Placeholders do not have surfaces, but need to be given a trivial cost for
|
||||
// our invariants to hold.
|
||||
static const Cost sPlaceholderCost = 1;
|
||||
|
||||
static Cost
|
||||
ComputeCost(const IntSize& aSize, uint32_t aBytesPerPixel)
|
||||
{
|
||||
@ -137,17 +142,28 @@ public:
|
||||
, mSurfaceKey(aSurfaceKey)
|
||||
, mLifetime(aLifetime)
|
||||
{
|
||||
MOZ_ASSERT(mSurface, "Must have a valid surface");
|
||||
MOZ_ASSERT(!IsPlaceholder() ||
|
||||
(mCost == sPlaceholderCost && mLifetime == Lifetime::Transient),
|
||||
"Placeholder should have trivial cost and transient lifetime");
|
||||
MOZ_ASSERT(mImageKey, "Must have a valid image key");
|
||||
}
|
||||
|
||||
DrawableFrameRef DrawableRef() const
|
||||
{
|
||||
if (MOZ_UNLIKELY(IsPlaceholder())) {
|
||||
MOZ_ASSERT_UNREACHABLE("Shouldn't call DrawableRef() on a placeholder");
|
||||
return DrawableFrameRef();
|
||||
}
|
||||
|
||||
return mSurface->DrawableRef();
|
||||
}
|
||||
|
||||
void SetLocked(bool aLocked)
|
||||
{
|
||||
if (IsPlaceholder()) {
|
||||
return; // Can't lock a placeholder.
|
||||
}
|
||||
|
||||
if (aLocked && mLifetime == Lifetime::Persistent) {
|
||||
// This may fail, and that's OK. We make no guarantees about whether
|
||||
// locking is successful if you call SurfaceCache::LockImage() after
|
||||
@ -158,6 +174,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
bool IsPlaceholder() const { return !bool(mSurface); }
|
||||
bool IsLocked() const { return bool(mDrawableRef); }
|
||||
|
||||
ImageKey GetImageKey() const { return mImageKey; }
|
||||
@ -165,7 +182,11 @@ public:
|
||||
CostEntry GetCostEntry() { return image::CostEntry(this, mCost); }
|
||||
nsExpirationState* GetExpirationState() { return &mExpirationState; }
|
||||
Lifetime GetLifetime() const { return mLifetime; }
|
||||
bool IsDecoded() const { return mSurface->IsImageComplete(); }
|
||||
|
||||
bool IsDecoded() const
|
||||
{
|
||||
return !IsPlaceholder() && mSurface->IsImageComplete();
|
||||
}
|
||||
|
||||
// A helper type used by SurfaceCacheImpl::CollectSizeOfSurfaces.
|
||||
struct MOZ_STACK_CLASS SurfaceMemoryReport
|
||||
@ -262,21 +283,47 @@ public:
|
||||
return surface.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<CachedSurface>
|
||||
MOZ_WARN_UNUSED_RESULT // See bug 1185044.
|
||||
Pair<already_AddRefed<CachedSurface>, MatchType>
|
||||
LookupBestMatch(const SurfaceKey& aSurfaceKey,
|
||||
const Maybe<uint32_t>& aAlternateFlags)
|
||||
{
|
||||
// Try for a perfect match first.
|
||||
nsRefPtr<CachedSurface> surface;
|
||||
mSurfaces.Get(aSurfaceKey, getter_AddRefs(surface));
|
||||
if (surface && surface->IsDecoded()) {
|
||||
return surface.forget();
|
||||
// Try for an exact match first.
|
||||
nsRefPtr<CachedSurface> exactMatch;
|
||||
mSurfaces.Get(aSurfaceKey, getter_AddRefs(exactMatch));
|
||||
if (exactMatch && exactMatch->IsDecoded()) {
|
||||
return MakePair(exactMatch.forget(), MatchType::EXACT);
|
||||
}
|
||||
|
||||
// There's no perfect match, so find the best match we can.
|
||||
MatchContext matchContext(aSurfaceKey, aAlternateFlags);
|
||||
ForEach(TryToImproveMatch, &matchContext);
|
||||
return matchContext.mBestMatch.forget();
|
||||
|
||||
MatchType matchType;
|
||||
if (matchContext.mBestMatch) {
|
||||
if (!exactMatch) {
|
||||
// No exact match, but we found a substitute.
|
||||
matchType = MatchType::SUBSTITUTE_BECAUSE_NOT_FOUND;
|
||||
} else if (exactMatch != matchContext.mBestMatch) {
|
||||
// The exact match is still decoding, but we found a substitute.
|
||||
matchType = MatchType::SUBSTITUTE_BECAUSE_PENDING;
|
||||
} else {
|
||||
// The exact match is still decoding, but it's the best we've got.
|
||||
matchType = MatchType::EXACT;
|
||||
}
|
||||
} else {
|
||||
if (exactMatch) {
|
||||
// We found an "exact match", but since TryToImproveMatch didn't return
|
||||
// it, it must have been a placeholder.
|
||||
MOZ_ASSERT(exactMatch->IsPlaceholder());
|
||||
matchType = MatchType::PENDING;
|
||||
} else {
|
||||
// We couldn't find an exact match *or* a substitute.
|
||||
matchType = MatchType::NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
return MakePair(matchContext.mBestMatch.forget(), matchType);
|
||||
}
|
||||
|
||||
void ForEach(SurfaceTable::EnumReadFunction aFunction, void* aData)
|
||||
@ -308,6 +355,11 @@ private:
|
||||
auto context = static_cast<MatchContext*>(aContext);
|
||||
const SurfaceKey& idealKey = context->mIdealKey;
|
||||
|
||||
// We never match a placeholder.
|
||||
if (aSurface->IsPlaceholder()) {
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
// Matching the animation time and SVG context is required.
|
||||
if (aSurfaceKey.AnimationTime() != idealKey.AnimationTime() ||
|
||||
aSurfaceKey.SVGContext() != idealKey.SVGContext()) {
|
||||
@ -425,10 +477,21 @@ public:
|
||||
Lifetime aLifetime)
|
||||
{
|
||||
// If this is a duplicate surface, refuse to replace the original.
|
||||
if (MOZ_UNLIKELY(Lookup(aImageKey, aSurfaceKey, /* aMarkUsed = */ false))) {
|
||||
// XXX(seth): Calling Lookup() and then RemoveSurface() does the lookup
|
||||
// twice. We'll make this more efficient in bug 1185137.
|
||||
LookupResult result = Lookup(aImageKey, aSurfaceKey, /* aMarkUsed = */ false);
|
||||
if (MOZ_UNLIKELY(result)) {
|
||||
return InsertOutcome::FAILURE_ALREADY_PRESENT;
|
||||
}
|
||||
|
||||
if (result.Type() == MatchType::PENDING) {
|
||||
RemoveSurface(aImageKey, aSurfaceKey);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(result.Type() == MatchType::NOT_FOUND ||
|
||||
result.Type() == MatchType::PENDING,
|
||||
"A LookupResult with no surface should be NOT_FOUND or PENDING");
|
||||
|
||||
// If this is bigger than we can hold after discarding everything we can,
|
||||
// refuse to cache it.
|
||||
if (MOZ_UNLIKELY(!CanHoldAfterDiscarding(aCost))) {
|
||||
@ -458,6 +521,7 @@ public:
|
||||
// We require that locking succeed if the image is locked and the surface is
|
||||
// persistent; the caller may need to know this to handle errors correctly.
|
||||
if (cache->IsLocked() && aLifetime == Lifetime::Persistent) {
|
||||
MOZ_ASSERT(!surface->IsPlaceholder(), "Placeholders should be transient");
|
||||
surface->SetLocked(true);
|
||||
if (!surface->IsLocked()) {
|
||||
return InsertOutcome::FAILURE;
|
||||
@ -550,12 +614,18 @@ public:
|
||||
{
|
||||
nsRefPtr<ImageSurfaceCache> cache = GetImageCache(aImageKey);
|
||||
if (!cache) {
|
||||
return LookupResult(); // No cached surfaces for this image.
|
||||
// No cached surfaces for this image.
|
||||
return LookupResult(MatchType::NOT_FOUND);
|
||||
}
|
||||
|
||||
nsRefPtr<CachedSurface> surface = cache->Lookup(aSurfaceKey);
|
||||
if (!surface) {
|
||||
return LookupResult(); // Lookup in the per-image cache missed.
|
||||
// Lookup in the per-image cache missed.
|
||||
return LookupResult(MatchType::NOT_FOUND);
|
||||
}
|
||||
|
||||
if (surface->IsPlaceholder()) {
|
||||
return LookupResult(MatchType::PENDING);
|
||||
}
|
||||
|
||||
DrawableFrameRef ref = surface->DrawableRef();
|
||||
@ -563,14 +633,16 @@ public:
|
||||
// The surface was released by the operating system. Remove the cache
|
||||
// entry as well.
|
||||
Remove(surface);
|
||||
return LookupResult();
|
||||
return LookupResult(MatchType::NOT_FOUND);
|
||||
}
|
||||
|
||||
if (aMarkUsed) {
|
||||
MarkUsed(surface, cache);
|
||||
}
|
||||
|
||||
return LookupResult(Move(ref), /* aIsExactMatch = */ true);
|
||||
MOZ_ASSERT(surface->GetSurfaceKey() == aSurfaceKey,
|
||||
"Lookup() not returning an exact match?");
|
||||
return LookupResult(Move(ref), MatchType::EXACT);
|
||||
}
|
||||
|
||||
LookupResult LookupBestMatch(const ImageKey aImageKey,
|
||||
@ -579,7 +651,8 @@ public:
|
||||
{
|
||||
nsRefPtr<ImageSurfaceCache> cache = GetImageCache(aImageKey);
|
||||
if (!cache) {
|
||||
return LookupResult(); // No cached surfaces for this image.
|
||||
// No cached surfaces for this image.
|
||||
return LookupResult(MatchType::NOT_FOUND);
|
||||
}
|
||||
|
||||
// Repeatedly look up the best match, trying again if the resulting surface
|
||||
@ -590,10 +663,16 @@ public:
|
||||
|
||||
nsRefPtr<CachedSurface> surface;
|
||||
DrawableFrameRef ref;
|
||||
MatchType matchType = MatchType::NOT_FOUND;
|
||||
while (true) {
|
||||
surface = cache->LookupBestMatch(aSurfaceKey, aAlternateFlags);
|
||||
// XXX(seth): This code is begging for std::tie. See bug 1184385.
|
||||
Pair<already_AddRefed<CachedSurface>, MatchType> lookupResult =
|
||||
cache->LookupBestMatch(aSurfaceKey, aAlternateFlags);
|
||||
surface = lookupResult.first();
|
||||
matchType = lookupResult.second();
|
||||
|
||||
if (!surface) {
|
||||
return LookupResult(); // Lookup in the per-image cache missed.
|
||||
return LookupResult(matchType); // Lookup in the per-image cache missed.
|
||||
}
|
||||
|
||||
ref = surface->DrawableRef();
|
||||
@ -606,20 +685,18 @@ public:
|
||||
Remove(surface);
|
||||
}
|
||||
|
||||
SurfaceKey key = surface->GetSurfaceKey();
|
||||
const bool isExactMatch = key.Size() == aSurfaceKey.Size();
|
||||
|
||||
MOZ_ASSERT(isExactMatch ==
|
||||
(key == aSurfaceKey ||
|
||||
(aAlternateFlags && key == aSurfaceKey.WithNewFlags(*aAlternateFlags))),
|
||||
MOZ_ASSERT((matchType == MatchType::EXACT) ==
|
||||
(surface->GetSurfaceKey() == aSurfaceKey ||
|
||||
(aAlternateFlags &&
|
||||
surface->GetSurfaceKey() ==
|
||||
aSurfaceKey.WithNewFlags(*aAlternateFlags))),
|
||||
"Result differs in a way other than size or alternate flags");
|
||||
|
||||
|
||||
if (isExactMatch) {
|
||||
if (matchType == MatchType::EXACT) {
|
||||
MarkUsed(surface, cache);
|
||||
}
|
||||
|
||||
return LookupResult(Move(ref), isExactMatch);
|
||||
return LookupResult(Move(ref), matchType);
|
||||
}
|
||||
|
||||
void RemoveSurface(const ImageKey aImageKey,
|
||||
@ -992,7 +1069,7 @@ SurfaceCache::Lookup(const ImageKey aImageKey,
|
||||
const Maybe<uint32_t>& aAlternateFlags /* = Nothing() */)
|
||||
{
|
||||
if (!sInstance) {
|
||||
return LookupResult();
|
||||
return LookupResult(MatchType::NOT_FOUND);
|
||||
}
|
||||
|
||||
MutexAutoLock lock(sInstance->GetMutex());
|
||||
@ -1013,7 +1090,7 @@ SurfaceCache::LookupBestMatch(const ImageKey aImageKey,
|
||||
/* = Nothing() */)
|
||||
{
|
||||
if (!sInstance) {
|
||||
return LookupResult();
|
||||
return LookupResult(MatchType::NOT_FOUND);
|
||||
}
|
||||
|
||||
MutexAutoLock lock(sInstance->GetMutex());
|
||||
@ -1040,6 +1117,19 @@ SurfaceCache::Insert(imgFrame* aSurface,
|
||||
return sInstance->Insert(aSurface, cost, aImageKey, aSurfaceKey, aLifetime);
|
||||
}
|
||||
|
||||
/* static */ InsertOutcome
|
||||
SurfaceCache::InsertPlaceholder(const ImageKey aImageKey,
|
||||
const SurfaceKey& aSurfaceKey)
|
||||
{
|
||||
if (!sInstance) {
|
||||
return InsertOutcome::FAILURE;
|
||||
}
|
||||
|
||||
MutexAutoLock lock(sInstance->GetMutex());
|
||||
return sInstance->Insert(nullptr, sPlaceholderCost, aImageKey, aSurfaceKey,
|
||||
Lifetime::Transient);
|
||||
}
|
||||
|
||||
/* static */ bool
|
||||
SurfaceCache::CanHold(const IntSize& aSize, uint32_t aBytesPerPixel /* = 4 */)
|
||||
{
|
||||
|
@ -230,6 +230,7 @@ struct SurfaceCache
|
||||
/**
|
||||
* Insert a surface into the cache. If a surface with the same ImageKey and
|
||||
* SurfaceKey is already in the cache, Insert returns FAILURE_ALREADY_PRESENT.
|
||||
* If a matching placeholder is already present, the placeholder is removed.
|
||||
*
|
||||
* Each surface in the cache has a lifetime, either Transient or Persistent.
|
||||
* Transient surfaces can expire from the cache at any time. Persistent
|
||||
@ -280,6 +281,33 @@ struct SurfaceCache
|
||||
const SurfaceKey& aSurfaceKey,
|
||||
Lifetime aLifetime);
|
||||
|
||||
/**
|
||||
* Insert a placeholder for a surface into the cache. If a surface with the
|
||||
* same ImageKey and SurfaceKey is already in the cache, InsertPlaceholder()
|
||||
* returns FAILURE_ALREADY_PRESENT.
|
||||
*
|
||||
* Placeholders exist to allow lazy allocation of surfaces. The Lookup*()
|
||||
* methods will report whether a placeholder for an exactly matching surface
|
||||
* existed by returning a MatchType of PENDING or SUBSTITUTE_BECAUSE_PENDING,
|
||||
* but they will never return a placeholder directly. (They couldn't, since
|
||||
* placeholders don't have an associated surface.)
|
||||
*
|
||||
* Once inserted, placeholders can be removed using RemoveSurface() or
|
||||
* RemoveImage(), just like a surface. They're automatically removed when a
|
||||
* real surface that matches the placeholder is inserted with Insert().
|
||||
*
|
||||
* @param aImageKey Key data identifying which image the placeholder
|
||||
* belongs to.
|
||||
* @param aSurfaceKey Key data which uniquely identifies the surface the
|
||||
* placeholder stands in for.
|
||||
* @return SUCCESS if the placeholder was inserted successfully.
|
||||
* FAILURE if the placeholder could not be inserted for some reason.
|
||||
* FAILURE_ALREADY_PRESENT if a surface with the same ImageKey and
|
||||
* SurfaceKey already exists in the cache.
|
||||
*/
|
||||
static InsertOutcome InsertPlaceholder(const ImageKey aImageKey,
|
||||
const SurfaceKey& aSurfaceKey);
|
||||
|
||||
/**
|
||||
* Checks if a surface of a given size could possibly be stored in the cache.
|
||||
* If CanHold() returns false, Insert() will always fail to insert the
|
||||
@ -362,8 +390,8 @@ struct SurfaceCache
|
||||
static void UnlockSurfaces(const ImageKey aImageKey);
|
||||
|
||||
/**
|
||||
* Removes a surface from the cache, if it's present. If it's not present,
|
||||
* RemoveSurface() has no effect.
|
||||
* Removes a surface or placeholder from the cache, if it's present. If it's
|
||||
* not present, RemoveSurface() has no effect.
|
||||
*
|
||||
* Use this function to remove individual surfaces that have become invalid.
|
||||
* Prefer RemoveImage() or DiscardAll() when they're applicable, as they have
|
||||
@ -378,8 +406,9 @@ struct SurfaceCache
|
||||
const SurfaceKey& aSurfaceKey);
|
||||
|
||||
/**
|
||||
* Removes all cached surfaces associated with the given image from the cache.
|
||||
* If the image is locked, it is automatically unlocked.
|
||||
* Removes all cached surfaces and placeholders associated with the given
|
||||
* image from the cache. If the image is locked, it is automatically
|
||||
* unlocked.
|
||||
*
|
||||
* This MUST be called, at a minimum, when an Image which could be storing
|
||||
* surfaces in the surface cache is destroyed. If another image were allocated
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "nsTArray.h"
|
||||
#include "nsObjCExceptions.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "nsContentSecurityManager.h"
|
||||
|
||||
#include <Cocoa/Cocoa.h>
|
||||
|
||||
@ -177,6 +178,15 @@ nsIconChannel::Open(nsIInputStream** _retval)
|
||||
return MakeInputStream(_retval, false);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::Open2(nsIInputStream** aStream)
|
||||
{
|
||||
nsCOMPtr<nsIStreamListener> listener;
|
||||
nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return Open(aStream);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsIconChannel::ExtractIconInfoFromUrl(nsIFile** aLocalFile,
|
||||
uint32_t* aDesiredImageSize,
|
||||
@ -236,6 +246,15 @@ nsIconChannel::AsyncOpen(nsIStreamListener* aListener,
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::AsyncOpen2(nsIStreamListener* aListener)
|
||||
{
|
||||
nsCOMPtr<nsIStreamListener> listener = aListener;
|
||||
nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return AsyncOpen(listener, nullptr);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsIconChannel::MakeInputStream(nsIInputStream** _retval,
|
||||
bool aNonBlocking)
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "nsCExternalHandlerService.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsProxyRelease.h"
|
||||
#include "nsContentSecurityManager.h"
|
||||
|
||||
#ifdef _WIN32_WINNT
|
||||
#undef _WIN32_WINNT
|
||||
@ -198,6 +199,15 @@ nsIconChannel::Open(nsIInputStream** _retval)
|
||||
return MakeInputStream(_retval, false);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::Open2(nsIInputStream** aStream)
|
||||
{
|
||||
nsCOMPtr<nsIStreamListener> listener;
|
||||
nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return Open(aStream);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsIconChannel::ExtractIconInfoFromUrl(nsIFile** aLocalFile,
|
||||
uint32_t* aDesiredImageSize, nsCString& aContentType,
|
||||
@ -253,6 +263,15 @@ nsIconChannel::AsyncOpen(nsIStreamListener* aListener,
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsIconChannel::AsyncOpen2(nsIStreamListener* aListener)
|
||||
{
|
||||
nsCOMPtr<nsIStreamListener> listener = aListener;
|
||||
nsresult rv = nsContentSecurityManager::doContentSecurityCheck(this, listener);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return AsyncOpen(listener, nullptr);
|
||||
}
|
||||
|
||||
static DWORD
|
||||
GetSpecialFolderIcon(nsIFile* aFile, int aFolder,
|
||||
SHFILEINFOW* aSFI, UINT aInfoFlags)
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "nsNullPrincipal.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsString.h"
|
||||
#include "nsTArray.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace net {
|
||||
@ -244,6 +245,12 @@ LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo,
|
||||
rv = PrincipalToPrincipalInfo(aLoadInfo->TriggeringPrincipal(),
|
||||
&triggeringPrincipalInfo);
|
||||
|
||||
nsTArray<PrincipalInfo> redirectChain;
|
||||
for (const nsCOMPtr<nsIPrincipal>& principal : aLoadInfo->RedirectChain()) {
|
||||
rv = PrincipalToPrincipalInfo(principal, redirectChain.AppendElement());
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
|
||||
*aOptionalLoadInfoArgs =
|
||||
LoadInfoArgs(
|
||||
requestingPrincipalInfo,
|
||||
@ -253,7 +260,10 @@ LoadInfoToLoadInfoArgs(nsILoadInfo *aLoadInfo,
|
||||
aLoadInfo->GetUpgradeInsecureRequests(),
|
||||
aLoadInfo->GetInnerWindowID(),
|
||||
aLoadInfo->GetOuterWindowID(),
|
||||
aLoadInfo->GetParentOuterWindowID());
|
||||
aLoadInfo->GetParentOuterWindowID(),
|
||||
aLoadInfo->GetEnforceSecurity(),
|
||||
aLoadInfo->GetInitialSecurityCheckDone(),
|
||||
redirectChain);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -278,6 +288,14 @@ LoadInfoArgsToLoadInfo(const OptionalLoadInfoArgs& aOptionalLoadInfoArgs,
|
||||
PrincipalInfoToPrincipal(loadInfoArgs.triggeringPrincipalInfo(), &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
nsTArray<nsCOMPtr<nsIPrincipal>> redirectChain;
|
||||
for (const PrincipalInfo& principalInfo : loadInfoArgs.redirectChain()) {
|
||||
nsCOMPtr<nsIPrincipal> redirectedPrincipal =
|
||||
PrincipalInfoToPrincipal(principalInfo, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
redirectChain.AppendElement(redirectedPrincipal.forget());
|
||||
}
|
||||
|
||||
nsCOMPtr<nsILoadInfo> loadInfo =
|
||||
new mozilla::LoadInfo(requestingPrincipal,
|
||||
triggeringPrincipal,
|
||||
@ -286,7 +304,10 @@ LoadInfoArgsToLoadInfo(const OptionalLoadInfoArgs& aOptionalLoadInfoArgs,
|
||||
loadInfoArgs.upgradeInsecureRequests(),
|
||||
loadInfoArgs.innerWindowID(),
|
||||
loadInfoArgs.outerWindowID(),
|
||||
loadInfoArgs.parentOuterWindowID());
|
||||
loadInfoArgs.parentOuterWindowID(),
|
||||
loadInfoArgs.enforceSecurity(),
|
||||
loadInfoArgs.initialSecurityCheckDone(),
|
||||
redirectChain);
|
||||
|
||||
loadInfo.forget(outLoadInfo);
|
||||
return NS_OK;
|
||||
|
@ -508,6 +508,69 @@ class MOZ_STACK_CLASS MutableHandle : public js::MutableHandleBase<T>
|
||||
|
||||
namespace js {
|
||||
|
||||
/*
|
||||
* InternalHandle is a handle to an internal pointer into a gcthing. Use
|
||||
* InternalHandle when you have a pointer to a direct field of a gcthing, or
|
||||
* when you need a parameter type for something that *may* be a pointer to a
|
||||
* direct field of a gcthing.
|
||||
*/
|
||||
template <typename T>
|
||||
class InternalHandle {};
|
||||
|
||||
template <typename T>
|
||||
class InternalHandle<T*>
|
||||
{
|
||||
void * const* holder;
|
||||
size_t offset;
|
||||
|
||||
public:
|
||||
/*
|
||||
* Create an InternalHandle using a Handle to the gcthing containing the
|
||||
* field in question, and a pointer to the field.
|
||||
*/
|
||||
template<typename H>
|
||||
InternalHandle(const JS::Handle<H>& handle, T* field)
|
||||
: holder((void**)handle.address()), offset(uintptr_t(field) - uintptr_t(handle.get()))
|
||||
{}
|
||||
|
||||
/*
|
||||
* Create an InternalHandle to a field within a Rooted<>.
|
||||
*/
|
||||
template<typename R>
|
||||
InternalHandle(const JS::Rooted<R>& root, T* field)
|
||||
: holder((void**)root.address()), offset(uintptr_t(field) - uintptr_t(root.get()))
|
||||
{}
|
||||
|
||||
InternalHandle(const InternalHandle<T*>& other)
|
||||
: holder(other.holder), offset(other.offset) {}
|
||||
|
||||
T* get() const { return reinterpret_cast<T*>(uintptr_t(*holder) + offset); }
|
||||
|
||||
const T& operator*() const { return *get(); }
|
||||
T* operator->() const { return get(); }
|
||||
|
||||
static InternalHandle<T*> fromMarkedLocation(T* fieldPtr) {
|
||||
return InternalHandle(fieldPtr);
|
||||
}
|
||||
|
||||
private:
|
||||
/*
|
||||
* Create an InternalHandle to something that is not a pointer to a
|
||||
* gcthing, and so does not need to be rooted in the first place. Use these
|
||||
* InternalHandles to pass pointers into functions that also need to accept
|
||||
* regular InternalHandles to gcthing fields.
|
||||
*
|
||||
* Make this private to prevent accidental misuse; this is only for
|
||||
* fromMarkedLocation().
|
||||
*/
|
||||
explicit InternalHandle(T* field)
|
||||
: holder(&js::ConstNullValue),
|
||||
offset(uintptr_t(field))
|
||||
{}
|
||||
|
||||
void operator=(InternalHandle<T*> other) = delete;
|
||||
};
|
||||
|
||||
/*
|
||||
* By default, things should use the inheritance hierarchy to find their
|
||||
* ThingRootKind. Some pointer types are explicitly set in jspubtd.h so that
|
||||
|
@ -1940,13 +1940,6 @@ static_assert(sizeof(LayoutAlignmentTester) == 16,
|
||||
|
||||
} // namespace JS
|
||||
|
||||
/*
|
||||
* JS::Value and jsval are the same type; jsval is the old name, kept around
|
||||
* for backwards compatibility along with all the JSVAL_* operations below.
|
||||
* jsval_layout is an implementation detail and should not be used externally.
|
||||
*/
|
||||
typedef JS::Value jsval;
|
||||
|
||||
static_assert(sizeof(jsval_layout) == sizeof(JS::Value),
|
||||
"jsval_layout and JS::Value must have identical layouts");
|
||||
|
||||
|
@ -17,7 +17,7 @@ class AtomicsObject : public JSObject
|
||||
public:
|
||||
static const Class class_;
|
||||
static JSObject* initClass(JSContext* cx, Handle<GlobalObject*> global);
|
||||
static bool toString(JSContext* cx, unsigned int argc, jsval* vp);
|
||||
static bool toString(JSContext* cx, unsigned int argc, Value* vp);
|
||||
|
||||
// Defined return values for futexWait.
|
||||
// The error values must be negative because APIs such as futexWaitOrRequeue
|
||||
|
@ -229,7 +229,7 @@ struct RequiredStringArg {
|
||||
};
|
||||
|
||||
static bool
|
||||
StartProfiling(JSContext* cx, unsigned argc, jsval* vp)
|
||||
StartProfiling(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
if (args.length() == 0) {
|
||||
@ -256,7 +256,7 @@ StartProfiling(JSContext* cx, unsigned argc, jsval* vp)
|
||||
}
|
||||
|
||||
static bool
|
||||
StopProfiling(JSContext* cx, unsigned argc, jsval* vp)
|
||||
StopProfiling(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
if (args.length() == 0) {
|
||||
@ -272,7 +272,7 @@ StopProfiling(JSContext* cx, unsigned argc, jsval* vp)
|
||||
}
|
||||
|
||||
static bool
|
||||
PauseProfilers(JSContext* cx, unsigned argc, jsval* vp)
|
||||
PauseProfilers(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
if (args.length() == 0) {
|
||||
@ -288,7 +288,7 @@ PauseProfilers(JSContext* cx, unsigned argc, jsval* vp)
|
||||
}
|
||||
|
||||
static bool
|
||||
ResumeProfilers(JSContext* cx, unsigned argc, jsval* vp)
|
||||
ResumeProfilers(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
if (args.length() == 0) {
|
||||
@ -305,7 +305,7 @@ ResumeProfilers(JSContext* cx, unsigned argc, jsval* vp)
|
||||
|
||||
/* Usage: DumpProfile([filename[, profileName]]) */
|
||||
static bool
|
||||
DumpProfile(JSContext* cx, unsigned argc, jsval* vp)
|
||||
DumpProfile(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
bool ret;
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
@ -332,7 +332,7 @@ DumpProfile(JSContext* cx, unsigned argc, jsval* vp)
|
||||
}
|
||||
|
||||
static bool
|
||||
GetMaxGCPauseSinceClear(JSContext* cx, unsigned argc, jsval* vp)
|
||||
GetMaxGCPauseSinceClear(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
args.rval().setNumber(uint32_t(cx->runtime()->gc.stats.getMaxGCPauseSinceClear()));
|
||||
@ -340,7 +340,7 @@ GetMaxGCPauseSinceClear(JSContext* cx, unsigned argc, jsval* vp)
|
||||
}
|
||||
|
||||
static bool
|
||||
ClearMaxGCPauseAccumulator(JSContext* cx, unsigned argc, jsval* vp)
|
||||
ClearMaxGCPauseAccumulator(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
args.rval().setNumber(uint32_t(cx->runtime()->gc.stats.clearMaxGCPauseAccumulator()));
|
||||
@ -350,7 +350,7 @@ ClearMaxGCPauseAccumulator(JSContext* cx, unsigned argc, jsval* vp)
|
||||
#if defined(MOZ_SHARK) || defined(MOZ_INSTRUMENTS)
|
||||
|
||||
static bool
|
||||
IgnoreAndReturnTrue(JSContext* cx, unsigned argc, jsval* vp)
|
||||
IgnoreAndReturnTrue(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
args.rval().setBoolean(true);
|
||||
@ -361,7 +361,7 @@ IgnoreAndReturnTrue(JSContext* cx, unsigned argc, jsval* vp)
|
||||
|
||||
#ifdef MOZ_CALLGRIND
|
||||
static bool
|
||||
StartCallgrind(JSContext* cx, unsigned argc, jsval* vp)
|
||||
StartCallgrind(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
args.rval().setBoolean(js_StartCallgrind());
|
||||
@ -369,7 +369,7 @@ StartCallgrind(JSContext* cx, unsigned argc, jsval* vp)
|
||||
}
|
||||
|
||||
static bool
|
||||
StopCallgrind(JSContext* cx, unsigned argc, jsval* vp)
|
||||
StopCallgrind(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
args.rval().setBoolean(js_StopCallgrind());
|
||||
@ -377,7 +377,7 @@ StopCallgrind(JSContext* cx, unsigned argc, jsval* vp)
|
||||
}
|
||||
|
||||
static bool
|
||||
DumpCallgrind(JSContext* cx, unsigned argc, jsval* vp)
|
||||
DumpCallgrind(JSContext* cx, unsigned argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
if (args.length() == 0) {
|
||||
|
@ -3621,7 +3621,7 @@ ASTSerializer::functionBody(ParseNode* pn, TokenPos* pos, MutableHandleValue dst
|
||||
}
|
||||
|
||||
static bool
|
||||
reflect_parse(JSContext* cx, uint32_t argc, jsval* vp)
|
||||
reflect_parse(JSContext* cx, uint32_t argc, Value* vp)
|
||||
{
|
||||
CallArgs args = CallArgsFromVp(argc, vp);
|
||||
|
||||
|
@ -416,11 +416,12 @@ static bool
|
||||
FillLanes(JSContext* cx, Handle<TypedObject*> result, const CallArgs& args)
|
||||
{
|
||||
typedef typename T::Elem Elem;
|
||||
InternalHandle<Elem*> mem(result, reinterpret_cast<Elem*>(result->typedMem()));
|
||||
Elem tmp;
|
||||
for (unsigned i = 0; i < T::lanes; i++) {
|
||||
if (!T::toType(cx, args.get(i), &tmp))
|
||||
return false;
|
||||
reinterpret_cast<Elem*>(result->typedMem())[i] = tmp;
|
||||
mem.get()[i] = tmp;
|
||||
}
|
||||
args.rval().setObject(*result);
|
||||
return true;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user