Merge mozilla-central to fx-team

--HG--
extra : rebase_source : 40dc0b4141079cd2fc66ae3e39e66e5fde1ae10c
This commit is contained in:
Carsten "Tomcat" Book 2015-07-20 12:07:51 +02:00
commit 509202f339
227 changed files with 3645 additions and 1587 deletions

View File

@ -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

View File

@ -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"/>

View File

@ -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"/>

View File

@ -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"/>

View File

@ -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 -->

View File

@ -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"/>

View File

@ -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"/>

View File

@ -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"/>

View File

@ -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"/>

View File

@ -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"
}

View File

@ -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 -->

View File

@ -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"/>

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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]

View 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);
});
});

View File

@ -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;
}

View File

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

View File

@ -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();

View File

@ -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

View 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

View 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

View File

@ -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',

View File

@ -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.

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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

View File

@ -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);
}
}

View File

@ -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

View File

@ -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);

View File

@ -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 |

View File

@ -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

View File

@ -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;
}
},

View File

@ -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;
}

View File

@ -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);

View File

@ -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.

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -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;
};

View File

@ -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);
};
/**

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -163,7 +163,7 @@ parent:
bool aSizeSpecified,
nsString aURI,
nsString aName,
nsString aFeatures,
nsCString aFeatures,
nsString aBaseURI)
returns (nsresult rv,
bool windowOpened,

View File

@ -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,

View File

@ -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

View File

@ -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,

View File

@ -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()
{

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -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',

View 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;
}

View 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___ */

View File

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

View File

@ -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
{

View File

@ -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;

View File

@ -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) {

View File

@ -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();
}

View File

@ -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;
}
}
}

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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"
};

View File

@ -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

View File

@ -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);
}

View File

@ -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.

View File

@ -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;
};

View File

@ -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

View File

@ -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

View File

@ -71,7 +71,7 @@ GrallocTextureClientOGL::ToSurfaceDescriptor(SurfaceDescriptor& aOutDescriptor)
return false;
}
aOutDescriptor = NewSurfaceDescriptorGralloc(mGrallocHandle, mSize, mIsOpaque);
aOutDescriptor = NewSurfaceDescriptorGralloc(mGrallocHandle, mIsOpaque);
return true;
}

View File

@ -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;

View File

@ -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)
{

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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 */)
{

View File

@ -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

View File

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

View File

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

View File

@ -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;

View File

@ -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

View File

@ -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");

View File

@ -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

View File

@ -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) {

View File

@ -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);

View File

@ -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