зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to fx-team, a=merge
This commit is contained in:
Коммит
cfc64d6694
2
CLOBBER
2
CLOBBER
|
@ -22,4 +22,4 @@
|
|||
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
|
||||
# don't change CLOBBER for WebIDL changes any more.
|
||||
|
||||
Bug 1171344 requires a clobber due to renaming of a test file.
|
||||
Bug 1164310 requires a clobber due to bug 1177844
|
||||
|
|
|
@ -30,16 +30,16 @@ DocAccessibleParent::RecvShowEvent(const ShowEventData& aData)
|
|||
// required show events.
|
||||
if (!parent) {
|
||||
NS_ERROR("adding child to unknown accessible");
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t newChildIdx = aData.Idx();
|
||||
if (newChildIdx > parent->ChildrenCount()) {
|
||||
NS_ERROR("invalid index to add child at");
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t consumed = AddSubtree(parent, aData.NewTree(), 0, newChildIdx);
|
||||
DebugOnly<uint32_t> consumed = AddSubtree(parent, aData.NewTree(), 0, newChildIdx);
|
||||
MOZ_ASSERT(consumed == aData.NewTree().Length());
|
||||
#ifdef DEBUG
|
||||
for (uint32_t i = 0; i < consumed; i++) {
|
||||
|
@ -48,7 +48,7 @@ DocAccessibleParent::RecvShowEvent(const ShowEventData& aData)
|
|||
}
|
||||
#endif
|
||||
|
||||
return consumed != 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
|
@ -140,8 +140,10 @@ DocAccessibleParent::RecvStateChangeEvent(const uint64_t& aID,
|
|||
const bool& aEnabled)
|
||||
{
|
||||
ProxyAccessible* target = GetAccessible(aID);
|
||||
if (!target)
|
||||
return false;
|
||||
if (!target) {
|
||||
NS_ERROR("we don't know about the target of a state change event!");
|
||||
return true;
|
||||
}
|
||||
|
||||
ProxyStateChangeEvent(target, aState, aEnabled);
|
||||
return true;
|
||||
|
@ -151,8 +153,10 @@ bool
|
|||
DocAccessibleParent::RecvCaretMoveEvent(const uint64_t& aID, const int32_t& aOffset)
|
||||
{
|
||||
ProxyAccessible* proxy = GetAccessible(aID);
|
||||
if (!proxy)
|
||||
return false;
|
||||
if (!proxy) {
|
||||
NS_ERROR("unknown caret move event target!");
|
||||
return true;
|
||||
}
|
||||
|
||||
ProxyCaretMoveEvent(proxy, aOffset);
|
||||
return true;
|
||||
|
@ -167,8 +171,10 @@ DocAccessibleParent::RecvTextChangeEvent(const uint64_t& aID,
|
|||
const bool& aFromUser)
|
||||
{
|
||||
ProxyAccessible* target = GetAccessible(aID);
|
||||
if (!target)
|
||||
return false;
|
||||
if (!target) {
|
||||
NS_ERROR("text change event target is unknown!");
|
||||
return true;
|
||||
}
|
||||
|
||||
ProxyTextChangeEvent(target, aStr, aStart, aLen, aIsInsert, aFromUser);
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
#filter substitution
|
||||
|
||||
// For the all MOZ_MULET ifdef conditions in this file: see bug 1174234
|
||||
|
||||
#ifndef MOZ_MULET
|
||||
pref("toolkit.defaultChromeURI", "chrome://b2g/content/shell.html");
|
||||
pref("browser.chromeURL", "chrome://b2g/content/");
|
||||
|
@ -457,7 +459,9 @@ pref("dom.ipc.processCount", 100000);
|
|||
|
||||
pref("dom.ipc.browser_frames.oop_by_default", false);
|
||||
|
||||
#ifndef MOZ_MULET
|
||||
pref("dom.meta-viewport.enabled", true);
|
||||
#endif
|
||||
|
||||
// SMS/MMS
|
||||
pref("dom.sms.enabled", true);
|
||||
|
|
|
@ -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="805cf546729ba742bf23febda52970fcb35c0e8f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="84c3bf622e211046d905803b34de5d331761f22d"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
|
||||
<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="62682dcee5368fe43284efa4e90f22cb1c88b79e"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="11b6bfa7620f31b9c2bc2e537b66233daf5e192f"/>
|
||||
<!-- Stock Android things -->
|
||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
|
||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="805cf546729ba742bf23febda52970fcb35c0e8f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="84c3bf622e211046d905803b34de5d331761f22d"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
|
||||
<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="62682dcee5368fe43284efa4e90f22cb1c88b79e"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="11b6bfa7620f31b9c2bc2e537b66233daf5e192f"/>
|
||||
<!-- Stock Android things -->
|
||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
|
||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="805cf546729ba742bf23febda52970fcb35c0e8f"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="84c3bf622e211046d905803b34de5d331761f22d"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="8bc59310552179f9a8bc6cdd0188e2475df52fb7"/>
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="805cf546729ba742bf23febda52970fcb35c0e8f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="84c3bf622e211046d905803b34de5d331761f22d"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="62682dcee5368fe43284efa4e90f22cb1c88b79e"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="11b6bfa7620f31b9c2bc2e537b66233daf5e192f"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||
<!-- Stock Android things -->
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="805cf546729ba742bf23febda52970fcb35c0e8f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="84c3bf622e211046d905803b34de5d331761f22d"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
|
||||
<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="62682dcee5368fe43284efa4e90f22cb1c88b79e"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="11b6bfa7620f31b9c2bc2e537b66233daf5e192f"/>
|
||||
<!-- Stock Android things -->
|
||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
|
||||
<project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="6e47ff2790f5656b5b074407829ceecf3e6188c4"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="805cf546729ba742bf23febda52970fcb35c0e8f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="84c3bf622e211046d905803b34de5d331761f22d"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
|
||||
<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="62682dcee5368fe43284efa4e90f22cb1c88b79e"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="11b6bfa7620f31b9c2bc2e537b66233daf5e192f"/>
|
||||
<!-- Stock Android things -->
|
||||
<project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
|
||||
<project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" path="prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" revision="337e0ef5e40f02a1ae59b90db0548976c70a7226"/>
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="805cf546729ba742bf23febda52970fcb35c0e8f"/>
|
||||
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="84c3bf622e211046d905803b34de5d331761f22d"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="8bc59310552179f9a8bc6cdd0188e2475df52fb7"/>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="805cf546729ba742bf23febda52970fcb35c0e8f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="84c3bf622e211046d905803b34de5d331761f22d"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
|
||||
<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="62682dcee5368fe43284efa4e90f22cb1c88b79e"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="11b6bfa7620f31b9c2bc2e537b66233daf5e192f"/>
|
||||
<!-- 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"/>
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
{
|
||||
"git": {
|
||||
"git_revision": "805cf546729ba742bf23febda52970fcb35c0e8f",
|
||||
"git_revision": "84c3bf622e211046d905803b34de5d331761f22d",
|
||||
"remote": "https://git.mozilla.org/releases/gaia.git",
|
||||
"branch": ""
|
||||
},
|
||||
"revision": "669a688b25adf51474f17cc6febdf2a4ba626b93",
|
||||
"revision": "86ee685954005405682f78d7b3009dd61ac2e1ec",
|
||||
"repo_path": "integration/gaia-central"
|
||||
}
|
||||
|
|
|
@ -17,10 +17,10 @@
|
|||
</project>
|
||||
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="805cf546729ba742bf23febda52970fcb35c0e8f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="84c3bf622e211046d905803b34de5d331761f22d"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
|
||||
<project name="moztt" path="external/moztt" remote="b2g" revision="657894b4a1dc0a926117f4812e0940229f9f676f"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="62682dcee5368fe43284efa4e90f22cb1c88b79e"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="11b6bfa7620f31b9c2bc2e537b66233daf5e192f"/>
|
||||
<project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
|
||||
<project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
|
||||
<!-- Stock Android things -->
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
|
||||
<copyfile dest="Makefile" src="core/root.mk"/>
|
||||
</project>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="805cf546729ba742bf23febda52970fcb35c0e8f"/>
|
||||
<project name="gaia" path="gaia" remote="mozillaorg" revision="84c3bf622e211046d905803b34de5d331761f22d"/>
|
||||
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
|
||||
<project name="gonk-misc" path="gonk-misc" remote="b2g" revision="9f45c1988fe72749f0659409e6e3320fabf7b79a"/>
|
||||
<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="62682dcee5368fe43284efa4e90f22cb1c88b79e"/>
|
||||
<project name="apitrace" path="external/apitrace" remote="apitrace" revision="11b6bfa7620f31b9c2bc2e537b66233daf5e192f"/>
|
||||
<!-- 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"/>
|
||||
|
|
|
@ -1701,11 +1701,6 @@ pref("browser.newtabpage.directory.ping", "https://tiles.services.mozilla.com/v3
|
|||
// Enable the DOM fullscreen API.
|
||||
pref("full-screen-api.enabled", true);
|
||||
|
||||
// True if the fullscreen API requires approval upon a domain entering fullscreen.
|
||||
// Domains that have already had fullscreen permission granted won't re-request
|
||||
// approval.
|
||||
pref("full-screen-api.approval-required", true);
|
||||
|
||||
// Startup Crash Tracking
|
||||
// number of startup crashes that can occur before starting into safe mode automatically
|
||||
// (this pref has no effect if more than 6 hours have passed since the last crash)
|
||||
|
|
|
@ -334,68 +334,18 @@ var FullScreen = {
|
|||
|
||||
this.warningBox.setAttribute("hidden", true);
|
||||
this.warningBox.removeAttribute("fade-warning-out");
|
||||
this.warningBox.removeAttribute("obscure-browser");
|
||||
this.warningBox = null;
|
||||
},
|
||||
|
||||
setFullscreenAllowed: function(isApproved) {
|
||||
// The "remember decision" checkbox is hidden when showing for documents that
|
||||
// the permission manager can't handle (documents with URIs without a host).
|
||||
// We simply require those to be approved every time instead.
|
||||
let rememberCheckbox = document.getElementById("full-screen-remember-decision");
|
||||
let uri = BrowserUtils.makeURI(this.fullscreenOrigin);
|
||||
if (!rememberCheckbox.hidden) {
|
||||
if (rememberCheckbox.checked)
|
||||
Services.perms.add(uri,
|
||||
"fullscreen",
|
||||
isApproved ? Services.perms.ALLOW_ACTION : Services.perms.DENY_ACTION,
|
||||
Services.perms.EXPIRE_NEVER);
|
||||
else if (isApproved) {
|
||||
// The user has only temporarily approved fullscren for this fullscreen
|
||||
// session only. Add the permission (so Gecko knows to approve any further
|
||||
// fullscreen requests for this host in this fullscreen session) but add
|
||||
// a listener to revoke the permission when the chrome document exits
|
||||
// fullscreen.
|
||||
Services.perms.add(uri,
|
||||
"fullscreen",
|
||||
Services.perms.ALLOW_ACTION,
|
||||
Services.perms.EXPIRE_SESSION);
|
||||
var onFullscreenchange = function onFullscreenchange(event) {
|
||||
if (event.target == document && document.mozFullScreenElement == null) {
|
||||
// The chrome document has left fullscreen. Remove the temporary permission grant.
|
||||
Services.perms.remove(uri, "fullscreen");
|
||||
document.removeEventListener("mozfullscreenchange", onFullscreenchange);
|
||||
}
|
||||
}
|
||||
document.addEventListener("mozfullscreenchange", onFullscreenchange);
|
||||
}
|
||||
}
|
||||
if (this.warningBox)
|
||||
this.warningBox.setAttribute("fade-warning-out", "true");
|
||||
// If the document has been granted fullscreen, notify Gecko so it can resume
|
||||
// any pending pointer lock requests, otherwise exit fullscreen; the user denied
|
||||
// the fullscreen request.
|
||||
if (isApproved) {
|
||||
gBrowser.selectedBrowser
|
||||
.messageManager
|
||||
.sendAsyncMessage("DOMFullscreen:Approved");
|
||||
} else {
|
||||
document.mozCancelFullScreen();
|
||||
}
|
||||
},
|
||||
|
||||
warningBox: null,
|
||||
warningFadeOutTimeout: null,
|
||||
|
||||
// Shows the fullscreen approval UI, or if the domain has already been approved
|
||||
// for fullscreen, shows a warning that the site has entered fullscreen for a short
|
||||
// duration.
|
||||
// Shows a warning that the site has entered fullscreen for a short duration.
|
||||
showWarning: function(aOrigin) {
|
||||
if (!document.mozFullScreen ||
|
||||
!gPrefService.getBoolPref("full-screen-api.approval-required"))
|
||||
if (!document.mozFullScreen)
|
||||
return;
|
||||
|
||||
// Set the strings on the fullscreen approval UI.
|
||||
// Set the strings on the fullscreen warning UI.
|
||||
this.fullscreenOrigin = aOrigin;
|
||||
let uri = BrowserUtils.makeURI(aOrigin);
|
||||
let host = null;
|
||||
|
@ -403,8 +353,6 @@ var FullScreen = {
|
|||
host = uri.host;
|
||||
} catch (e) { }
|
||||
let hostLabel = document.getElementById("full-screen-domain-text");
|
||||
let rememberCheckbox = document.getElementById("full-screen-remember-decision");
|
||||
let isApproved = false;
|
||||
if (host) {
|
||||
// Document's principal's URI has a host. Display a warning including the hostname and
|
||||
// show UI to enable the user to permanently grant this host permission to enter fullscreen.
|
||||
|
@ -415,17 +363,8 @@ var FullScreen = {
|
|||
|
||||
hostLabel.textContent = bundle.formatStringFromName("fullscreen.entered", [displayHost], 1);
|
||||
hostLabel.removeAttribute("hidden");
|
||||
|
||||
rememberCheckbox.label = bundle.formatStringFromName("fullscreen.rememberDecision", [displayHost], 1);
|
||||
rememberCheckbox.checked = false;
|
||||
rememberCheckbox.removeAttribute("hidden");
|
||||
|
||||
// Note we only allow documents whose principal's URI has a host to
|
||||
// store permission grants.
|
||||
isApproved = Services.perms.testPermission(uri, "fullscreen") == Services.perms.ALLOW_ACTION;
|
||||
} else {
|
||||
hostLabel.setAttribute("hidden", "true");
|
||||
rememberCheckbox.setAttribute("hidden", "true");
|
||||
}
|
||||
|
||||
// Note: the warning box can be non-null if the warning box from the previous request
|
||||
|
@ -443,32 +382,12 @@ var FullScreen = {
|
|||
this.warningBox.removeAttribute("fade-warning-out");
|
||||
}
|
||||
|
||||
// If fullscreen mode has not yet been approved for the fullscreen
|
||||
// document's domain, show the approval UI and don't auto fade out the
|
||||
// fullscreen warning box. Otherwise, we're just notifying of entry into
|
||||
// fullscreen mode. Note if the resource's host is null, we must be
|
||||
// showing a local file or a local data URI, and we require explicit
|
||||
// approval every time.
|
||||
let authUI = document.getElementById("full-screen-approval-pane");
|
||||
if (isApproved) {
|
||||
authUI.setAttribute("hidden", "true");
|
||||
this.warningBox.removeAttribute("obscure-browser");
|
||||
} else {
|
||||
// Partially obscure the <browser> element underneath the approval UI.
|
||||
this.warningBox.setAttribute("obscure-browser", "true");
|
||||
authUI.removeAttribute("hidden");
|
||||
}
|
||||
|
||||
// If we're not showing the fullscreen approval UI, we're just notifying the user
|
||||
// of the transition, so set a timeout to fade the warning out after a few moments.
|
||||
if (isApproved)
|
||||
this.warningFadeOutTimeout =
|
||||
setTimeout(
|
||||
function() {
|
||||
if (this.warningBox)
|
||||
this.warningBox.setAttribute("fade-warning-out", "true");
|
||||
}.bind(this),
|
||||
3000);
|
||||
// Set a timeout to fade the warning out after a few moments.
|
||||
this.warningFadeOutTimeout = setTimeout(() => {
|
||||
if (this.warningBox) {
|
||||
this.warningBox.setAttribute("fade-warning-out", "true");
|
||||
}
|
||||
}, 3000);
|
||||
},
|
||||
|
||||
showNavToolbox: function(trackMouse = true) {
|
||||
|
|
|
@ -655,6 +655,7 @@ window[chromehidden~="toolbar"] toolbar:not(#nav-bar):not(#TabsToolbar):not(#pri
|
|||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 2147483647 !important;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#full-screen-warning-container[fade-warning-out] {
|
||||
|
@ -663,22 +664,13 @@ window[chromehidden~="toolbar"] toolbar:not(#nav-bar):not(#TabsToolbar):not(#pri
|
|||
opacity: 0.0;
|
||||
}
|
||||
|
||||
/* When the modal fullscreen approval UI is showing, don't allow interaction
|
||||
with the page, but when we're just showing the warning upon entering
|
||||
fullscreen on an already approved page, do allow interaction with the page.
|
||||
*/
|
||||
#full-screen-warning-container:not([obscure-browser]) {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
#full-screen-warning-message {
|
||||
/* We must specify a max-width, otherwise word-wrap:break-word doesn't
|
||||
work in descendant <description> and <label> elements. Bug 630864. */
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
#full-screen-domain-text,
|
||||
#full-screen-remember-decision > .checkbox-label-box > .checkbox-label {
|
||||
#full-screen-domain-text {
|
||||
word-wrap: break-word;
|
||||
/* We must specify a min-width, otherwise word-wrap:break-word doesn't work. Bug 630864. */
|
||||
min-width: 1px;
|
||||
|
|
|
@ -1196,26 +1196,6 @@
|
|||
<vbox id="full-screen-warning-message" align="center">
|
||||
<description id="full-screen-domain-text"/>
|
||||
<description class="full-screen-description" value="&fullscreenExitHint2.value;"/>
|
||||
<vbox id="full-screen-approval-pane" align="center">
|
||||
<hbox>
|
||||
#ifdef XP_UNIX
|
||||
<button label="&fullscreenExitButton.label;"
|
||||
oncommand="FullScreen.setFullscreenAllowed(false);"
|
||||
class="full-screen-approval-button"/>
|
||||
<button label="&fullscreenAllowButton.label;"
|
||||
oncommand="FullScreen.setFullscreenAllowed(true);"
|
||||
class="full-screen-approval-button"/>
|
||||
#else
|
||||
<button label="&fullscreenAllowButton.label;"
|
||||
oncommand="FullScreen.setFullscreenAllowed(true);"
|
||||
class="full-screen-approval-button"/>
|
||||
<button label="&fullscreenExitButton.label;"
|
||||
oncommand="FullScreen.setFullscreenAllowed(false);"
|
||||
class="full-screen-approval-button"/>
|
||||
#endif
|
||||
</hbox>
|
||||
<checkbox id="full-screen-remember-decision"/>
|
||||
</vbox>
|
||||
</vbox>
|
||||
</hbox>
|
||||
</hbox>
|
||||
|
|
|
@ -593,7 +593,6 @@ let DOMFullscreenHandler = {
|
|||
|
||||
init: function() {
|
||||
addMessageListener("DOMFullscreen:Entered", this);
|
||||
addMessageListener("DOMFullscreen:Approved", this);
|
||||
addMessageListener("DOMFullscreen:CleanUp", this);
|
||||
addEventListener("MozDOMFullscreen:Request", this);
|
||||
addEventListener("MozDOMFullscreen:Entered", this);
|
||||
|
@ -619,14 +618,6 @@ let DOMFullscreenHandler = {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case "DOMFullscreen:Approved": {
|
||||
if (this._fullscreenDoc) {
|
||||
Services.obs.notifyObservers(this._fullscreenDoc,
|
||||
"fullscreen-approved",
|
||||
"");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "DOMFullscreen:CleanUp": {
|
||||
this._windowUtils.exitFullscreen();
|
||||
this._fullscreenDoc = null;
|
||||
|
|
|
@ -505,7 +505,6 @@ function runTest(testNum) {
|
|||
openContextMenuFor(dom_full_screen, true); // Invoke context menu for next test.
|
||||
}
|
||||
subwindow.addEventListener("mozfullscreenchange", openDomFullScreen, false);
|
||||
SpecialPowers.setBoolPref("full-screen-api.approval-required", false);
|
||||
SpecialPowers.setBoolPref("full-screen-api.allow-trusted-requests-only", false);
|
||||
SpecialPowers.setCharPref("full-screen-api.transition-duration.enter", "0 0");
|
||||
SpecialPowers.setCharPref("full-screen-api.transition-duration.leave", "0 0");
|
||||
|
@ -534,8 +533,9 @@ function runTest(testNum) {
|
|||
var full_screen_element = subwindow.document.getElementById("test-dom-full-screen");
|
||||
var openPagemenu = function() {
|
||||
subwindow.removeEventListener("mozfullscreenchange", openPagemenu, false);
|
||||
SpecialPowers.clearUserPref("full-screen-api.approval-required");
|
||||
SpecialPowers.clearUserPref("full-screen-api.allow-trusted-requests-only");
|
||||
SpecialPowers.clearUserPref("full-screen-api.transition-duration.enter", "0 0");
|
||||
SpecialPowers.clearUserPref("full-screen-api.transition-duration.leave", "0 0");
|
||||
openContextMenuFor(pagemenu, true); // Invoke context menu for next test.
|
||||
}
|
||||
subwindow.addEventListener("mozfullscreenchange", openPagemenu, false);
|
||||
|
|
|
@ -8,6 +8,7 @@ support-files =
|
|||
[browser_referrer_open_link_in_private.js]
|
||||
skip-if = os == 'linux' # Bug 1145199
|
||||
[browser_referrer_open_link_in_tab.js]
|
||||
skip-if = os == 'linux' # Bug 1144816
|
||||
[browser_referrer_open_link_in_window.js]
|
||||
skip-if = os == 'linux' # Bug 1145199
|
||||
[browser_referrer_simple_click.js]
|
||||
|
|
|
@ -321,16 +321,6 @@ let PermissionDefaults = {
|
|||
Services.prefs.setBoolPref("dom.disable_open_during_load", value);
|
||||
},
|
||||
|
||||
get fullscreen() {
|
||||
if (!Services.prefs.getBoolPref("full-screen-api.enabled")) {
|
||||
return this.DENY;
|
||||
}
|
||||
return this.UNKNOWN;
|
||||
},
|
||||
set fullscreen(aValue) {
|
||||
let value = (aValue != this.DENY);
|
||||
Services.prefs.setBoolPref("full-screen-api.enabled", value);
|
||||
},
|
||||
get push() {
|
||||
if (!Services.prefs.getBoolPref("dom.push.enabled")) {
|
||||
return this.DENY;
|
||||
|
@ -382,12 +372,12 @@ let AboutPermissions = {
|
|||
* Potential future additions: "sts/use", "sts/subd"
|
||||
*/
|
||||
_supportedPermissions: ["password", "cookie", "geo", "indexedDB", "popup",
|
||||
"fullscreen", "camera", "microphone", "push"],
|
||||
"camera", "microphone", "push"],
|
||||
|
||||
/**
|
||||
* Permissions that don't have a global "Allow" option.
|
||||
*/
|
||||
_noGlobalAllow: ["geo", "indexedDB", "fullscreen", "camera", "microphone", "push"],
|
||||
_noGlobalAllow: ["geo", "indexedDB", "camera", "microphone", "push"],
|
||||
|
||||
/**
|
||||
* Permissions that don't have a global "Deny" option.
|
||||
|
@ -415,7 +405,6 @@ let AboutPermissions = {
|
|||
Services.prefs.addObserver("dom.push.enabled", this, false);
|
||||
Services.prefs.addObserver("dom.indexedDB.enabled", this, false);
|
||||
Services.prefs.addObserver("dom.disable_open_during_load", this, false);
|
||||
Services.prefs.addObserver("full-screen-api.enabled", this, false);
|
||||
Services.prefs.addObserver("dom.push.enabled", this, false);
|
||||
|
||||
Services.obs.addObserver(this, "perm-changed", false);
|
||||
|
@ -438,7 +427,6 @@ let AboutPermissions = {
|
|||
Services.prefs.removeObserver("dom.push.enabled", this, false);
|
||||
Services.prefs.removeObserver("dom.indexedDB.enabled", this, false);
|
||||
Services.prefs.removeObserver("dom.disable_open_during_load", this, false);
|
||||
Services.prefs.removeObserver("full-screen-api.enabled", this, false);
|
||||
Services.prefs.removeObserver("dom.push.enabled", this, false);
|
||||
|
||||
Services.obs.removeObserver(this, "perm-changed");
|
||||
|
|
|
@ -235,27 +235,6 @@
|
|||
</vbox>
|
||||
</hbox>
|
||||
|
||||
<!-- Fullscreen -->
|
||||
<hbox id="fullscreen-pref-item"
|
||||
class="pref-item" align="top">
|
||||
<image class="pref-icon" type="fullscreen"/>
|
||||
<vbox>
|
||||
<label class="pref-title" value="&fullscreen.label;"/>
|
||||
<hbox align="center">
|
||||
<menulist id="fullscreen-menulist"
|
||||
class="pref-menulist"
|
||||
type="fullscreen"
|
||||
oncommand="AboutPermissions.onPermissionCommand(event);">
|
||||
<menupopup>
|
||||
<menuitem id="fullscreen-0" value="0" label="&permission.alwaysAsk;"/>
|
||||
<menuitem id="fullscreen-1" value="1" label="&permission.allow;"/>
|
||||
<menuitem id="fullscreen-2" value="2" label="&permission.block;"/>
|
||||
</menupopup>
|
||||
</menulist>
|
||||
</hbox>
|
||||
</vbox>
|
||||
</hbox>
|
||||
|
||||
<!-- Push Notifications -->
|
||||
<hbox id="push-pref-item"
|
||||
class="pref-item" align="top">
|
||||
|
|
|
@ -26,7 +26,6 @@ const TEST_PERMS = {
|
|||
"push": PERM_DENY,
|
||||
"indexedDB": PERM_UNKNOWN,
|
||||
"popup": PERM_DENY,
|
||||
"fullscreen" : PERM_UNKNOWN,
|
||||
"camera": PERM_UNKNOWN,
|
||||
"microphone": PERM_UNKNOWN
|
||||
};
|
||||
|
@ -34,11 +33,10 @@ const TEST_PERMS = {
|
|||
const NO_GLOBAL_ALLOW = [
|
||||
"geo",
|
||||
"indexedDB",
|
||||
"fullscreen"
|
||||
];
|
||||
|
||||
// number of managed permissions in the interface
|
||||
const TEST_PERMS_COUNT = 9;
|
||||
const TEST_PERMS_COUNT = 8;
|
||||
|
||||
function test() {
|
||||
waitForExplicitFinish();
|
||||
|
|
|
@ -7,34 +7,11 @@ XPCOMUtils.defineLazyModuleGetter(this, "PlacesTestUtils",
|
|||
|
||||
function whenNewWindowLoaded(aOptions, aCallback) {
|
||||
let win = OpenBrowserWindow(aOptions);
|
||||
let gotLoad = false;
|
||||
let gotActivate = Services.focus.activeWindow == win;
|
||||
|
||||
function maybeRunCallback() {
|
||||
if (gotLoad && gotActivate) {
|
||||
executeSoon(function() { aCallback(win); });
|
||||
}
|
||||
}
|
||||
|
||||
if (!gotActivate) {
|
||||
win.addEventListener("activate", function onActivate() {
|
||||
info("Got activate.");
|
||||
win.removeEventListener("activate", onActivate, false);
|
||||
gotActivate = true;
|
||||
maybeRunCallback();
|
||||
}, false);
|
||||
} else {
|
||||
info("Was activated.");
|
||||
}
|
||||
|
||||
Services.obs.addObserver(function observer(aSubject, aTopic) {
|
||||
if (win == aSubject) {
|
||||
info("Delayed startup finished");
|
||||
Services.obs.removeObserver(observer, aTopic);
|
||||
gotLoad = true;
|
||||
maybeRunCallback();
|
||||
}
|
||||
}, "browser-delayed-startup-finished", false);
|
||||
let focused = SimpleTest.promiseFocus(win);
|
||||
let startupFinished = TestUtils.topicObserved("browser-delayed-startup-finished",
|
||||
subject => subject == win).then(() => win);
|
||||
Promise.all([focused, startupFinished])
|
||||
.then(results => executeSoon(() => aCallback(results[1])));
|
||||
|
||||
return win;
|
||||
}
|
||||
|
|
|
@ -127,8 +127,6 @@ These should match what Safari and other Apple applications use on OS X Lion. --
|
|||
<!ENTITY fullScreenAutohide.accesskey "H">
|
||||
<!ENTITY fullScreenExit.label "Exit Full Screen Mode">
|
||||
<!ENTITY fullScreenExit.accesskey "F">
|
||||
<!ENTITY fullscreenAllowButton.label "Allow">
|
||||
<!ENTITY fullscreenExitButton.label "Deny">
|
||||
|
||||
<!ENTITY fullscreenExitHint2.value "Press ESC at any time to exit.">
|
||||
<!ENTITY leaveDOMFullScreen.label "Exit Full Screen">
|
||||
|
|
|
@ -505,8 +505,6 @@ webapps.requestUninstall = Do you want to uninstall “%1$S”?
|
|||
|
||||
# LOCALIZATION NOTE (fullscreen.entered): displayed when we enter HTML5 fullscreen mode, %S is the domain name of the focused website (e.g. mozilla.com).
|
||||
fullscreen.entered=%S is now fullscreen.
|
||||
# LOCALIZATION NOTE (fullscreen.rememberDecision): displayed when we enter HTML5 fullscreen mode, %S is the domain name of the focused website (e.g. mozilla.com).
|
||||
fullscreen.rememberDecision=Remember decision for %S
|
||||
|
||||
# LOCALIZATION NOTE (fullscreenButton.tooltip): %S is the keyboard shortcut for full screen
|
||||
fullscreenButton.tooltip=Display the window in full screen (%S)
|
||||
|
|
|
@ -41,8 +41,6 @@
|
|||
|
||||
<!ENTITY popup.label "Open Pop-up Windows">
|
||||
|
||||
<!ENTITY fullscreen.label "Fullscreen">
|
||||
|
||||
<!ENTITY push.label "Receive Push Notifications">
|
||||
<!ENTITY camera.label "Use the Camera">
|
||||
<!ENTITY microphone.label "Use the Microphone">
|
||||
|
|
|
@ -16,6 +16,5 @@ permission.install.label = Install Add-ons
|
|||
permission.popup.label = Open Pop-up Windows
|
||||
permission.geo.label = Access Your Location
|
||||
permission.indexedDB.label = Maintain Offline Storage
|
||||
permission.fullscreen.label = Enter Fullscreen
|
||||
permission.pointerLock.label = Hide the Mouse Pointer
|
||||
permission.push.label = Receive Push Notifications
|
||||
|
|
|
@ -186,8 +186,6 @@ let gPermissionObject = {
|
|||
|
||||
"indexedDB": {},
|
||||
|
||||
"fullscreen": {},
|
||||
|
||||
"pointerLock": {
|
||||
exactHostMatch: true
|
||||
},
|
||||
|
|
|
@ -1795,10 +1795,6 @@ toolbarbutton.chevron > .toolbarbutton-icon {
|
|||
box-shadow: 0 0 2px white;
|
||||
}
|
||||
|
||||
#full-screen-warning-container[obscure-browser] {
|
||||
background-color: rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
.full-screen-description {
|
||||
font-size: 150%;
|
||||
}
|
||||
|
@ -1807,11 +1803,6 @@ toolbarbutton.chevron > .toolbarbutton-icon {
|
|||
font-size: 300%;
|
||||
}
|
||||
|
||||
.full-screen-approval-button,
|
||||
#full-screen-remember-decision {
|
||||
font-size: 120%;
|
||||
}
|
||||
|
||||
%include ../shared/devtools/responsivedesign.inc.css
|
||||
%include ../shared/devtools/commandline.inc.css
|
||||
%include ../shared/plugin-doorhanger.inc.css
|
||||
|
|
|
@ -112,9 +112,6 @@
|
|||
.pref-icon[type="plugins"] {
|
||||
list-style-image: url(chrome://mozapps/skin/plugins/pluginGeneric.png);
|
||||
}
|
||||
.pref-icon[type="fullscreen"] {
|
||||
list-style-image: url(chrome://global/skin/icons/question-64.png);
|
||||
}
|
||||
.pref-icon[type="camera"] {
|
||||
list-style-image: url(chrome://global/skin/icons/question-64.png);
|
||||
}
|
||||
|
|
|
@ -3390,10 +3390,6 @@ notification[value="loop-sharing-notification"] .messageImage {
|
|||
box-shadow: 0 0 2px white;
|
||||
}
|
||||
|
||||
#full-screen-warning-container[obscure-browser] {
|
||||
background-color: rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
.full-screen-description {
|
||||
font-size: 150%;
|
||||
}
|
||||
|
@ -3402,11 +3398,6 @@ notification[value="loop-sharing-notification"] .messageImage {
|
|||
font-size: 300%;
|
||||
}
|
||||
|
||||
.full-screen-approval-button,
|
||||
#full-screen-remember-decision {
|
||||
font-size: 120%;
|
||||
}
|
||||
|
||||
%include ../shared/devtools/responsivedesign.inc.css
|
||||
%include ../shared/devtools/commandline.inc.css
|
||||
%include ../shared/plugin-doorhanger.inc.css
|
||||
|
|
|
@ -122,9 +122,6 @@
|
|||
.pref-icon[type="plugins"] {
|
||||
list-style-image: url(chrome://mozapps/skin/plugins/pluginGeneric.png);
|
||||
}
|
||||
.pref-icon[type="fullscreen"] {
|
||||
list-style-image: url(chrome://global/skin/icons/question-64.png);
|
||||
}
|
||||
.pref-icon[type="camera"] {
|
||||
list-style-image: url(chrome://global/skin/icons/question-64.png);
|
||||
}
|
||||
|
|
|
@ -2618,10 +2618,6 @@ notification[value="loop-sharing-notification"] .messageImage {
|
|||
box-shadow: 0 0 2px white;
|
||||
}
|
||||
|
||||
#full-screen-warning-container[obscure-browser] {
|
||||
background-color: rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
.full-screen-description {
|
||||
font-size: 150%;
|
||||
}
|
||||
|
@ -2630,11 +2626,6 @@ notification[value="loop-sharing-notification"] .messageImage {
|
|||
font-size: 300%;
|
||||
}
|
||||
|
||||
.full-screen-approval-button,
|
||||
#full-screen-remember-decision {
|
||||
font-size: 120%;
|
||||
}
|
||||
|
||||
%include ../shared/devtools/responsivedesign.inc.css
|
||||
%include ../shared/devtools/commandline.inc.css
|
||||
%include ../shared/plugin-doorhanger.inc.css
|
||||
|
|
|
@ -116,9 +116,6 @@
|
|||
.pref-icon[type="plugins"] {
|
||||
list-style-image: url(chrome://mozapps/skin/plugins/pluginGeneric.png);
|
||||
}
|
||||
.pref-icon[type="fullscreen"] {
|
||||
list-style-image: url(chrome://global/skin/icons/question-64.png);
|
||||
}
|
||||
.pref-icon[type="camera"] {
|
||||
list-style-image: url(chrome://global/skin/icons/question-64.png);
|
||||
}
|
||||
|
|
|
@ -324,13 +324,7 @@ private:
|
|||
|
||||
AutoSafeJSContext cx;
|
||||
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> sandbox =
|
||||
mConsole->GetOrCreateSandbox(cx, wp->GetPrincipal());
|
||||
if (NS_WARN_IF(!sandbox)) {
|
||||
return;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> global(cx, sandbox->GetJSObject());
|
||||
JS::Rooted<JSObject*> global(cx, mConsole->GetOrCreateSandbox(cx, wp->GetPrincipal()));
|
||||
if (NS_WARN_IF(!global)) {
|
||||
return;
|
||||
}
|
||||
|
@ -661,7 +655,7 @@ private:
|
|||
|
||||
NS_IMPL_CYCLE_COLLECTION_CLASS(Console)
|
||||
|
||||
// We don't need to traverse/unlink mStorage and mSanbox because they are not
|
||||
// We don't need to traverse/unlink mStorage and mSandbox because they are not
|
||||
// CCed objects and they are only used on the main thread, even when this
|
||||
// Console object is used on workers.
|
||||
|
||||
|
@ -715,19 +709,12 @@ Console::Console(nsPIDOMWindow* aWindow)
|
|||
Console::~Console()
|
||||
{
|
||||
if (!NS_IsMainThread()) {
|
||||
nsCOMPtr<nsIThread> mainThread;
|
||||
NS_GetMainThread(getter_AddRefs(mainThread));
|
||||
|
||||
if (mStorage) {
|
||||
nsIConsoleAPIStorage* storage;
|
||||
mStorage.forget(&storage);
|
||||
NS_ProxyRelease(mainThread, storage, false);
|
||||
NS_ReleaseOnMainThread(mStorage);
|
||||
}
|
||||
|
||||
if (mSandbox) {
|
||||
nsIXPConnectJSObjectHolder* sandbox;
|
||||
mSandbox.forget(&sandbox);
|
||||
NS_ProxyRelease(mainThread, sandbox, false);
|
||||
NS_ReleaseOnMainThread(mSandbox);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1876,7 +1863,7 @@ Console::ShouldIncludeStackTrace(MethodName aMethodName)
|
|||
}
|
||||
}
|
||||
|
||||
nsIXPConnectJSObjectHolder*
|
||||
JSObject*
|
||||
Console::GetOrCreateSandbox(JSContext* aCx, nsIPrincipal* aPrincipal)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
@ -1885,14 +1872,16 @@ Console::GetOrCreateSandbox(JSContext* aCx, nsIPrincipal* aPrincipal)
|
|||
nsIXPConnect* xpc = nsContentUtils::XPConnect();
|
||||
MOZ_ASSERT(xpc, "This should never be null!");
|
||||
|
||||
nsresult rv = xpc->CreateSandbox(aCx, aPrincipal,
|
||||
getter_AddRefs(mSandbox));
|
||||
JS::Rooted<JSObject*> sandbox(aCx);
|
||||
nsresult rv = xpc->CreateSandbox(aCx, aPrincipal, sandbox.address());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mSandbox = new JSObjectHolder(aCx, sandbox);
|
||||
}
|
||||
|
||||
return mSandbox;
|
||||
return mSandbox->GetJSObject();
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/JSObjectHolder.h"
|
||||
#include "nsCycleCollectionParticipant.h"
|
||||
#include "nsDataHashtable.h"
|
||||
#include "nsHashKeys.h"
|
||||
|
@ -20,7 +21,6 @@
|
|||
class nsIConsoleAPIStorage;
|
||||
class nsIPrincipal;
|
||||
class nsIProfiler;
|
||||
class nsIXPConnectJSObjectHolder;
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -199,12 +199,12 @@ private:
|
|||
bool
|
||||
ShouldIncludeStackTrace(MethodName aMethodName);
|
||||
|
||||
nsIXPConnectJSObjectHolder*
|
||||
JSObject*
|
||||
GetOrCreateSandbox(JSContext* aCx, nsIPrincipal* aPrincipal);
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> mWindow;
|
||||
nsCOMPtr<nsIConsoleAPIStorage> mStorage;
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> mSandbox;
|
||||
nsRefPtr<JSObjectHolder> mSandbox;
|
||||
#ifdef MOZ_ENABLE_PROFILER_SPS
|
||||
nsCOMPtr<nsIProfiler> mProfiler;
|
||||
#endif
|
||||
|
|
|
@ -3117,10 +3117,6 @@ GetFullScreenError(nsIDocument* aDoc)
|
|||
return "FullScreenDeniedNotInputDriven";
|
||||
}
|
||||
|
||||
if (nsContentUtils::IsSitePermDeny(aDoc->NodePrincipal(), "fullscreen")) {
|
||||
return "FullScreenDeniedBlocked";
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
|
@ -387,6 +387,7 @@ public:
|
|||
* calling IsDirectory will MOZ_ASSERT.
|
||||
*/
|
||||
virtual void LookupAndCacheIsDirectory() = 0;
|
||||
virtual void SetIsDirectory(bool aIsDir) = 0;
|
||||
virtual bool IsDirectory() const = 0;
|
||||
|
||||
/**
|
||||
|
@ -565,6 +566,14 @@ public:
|
|||
MOZ_ASSERT(false, "Why is this being called on a non-BlobImplFile?");
|
||||
}
|
||||
|
||||
virtual void SetIsDirectory(bool aIsDir) override
|
||||
{
|
||||
MOZ_ASSERT(mIsFile,
|
||||
"This should only be called when this object has been created "
|
||||
"from an nsIFile to note that the nsIFile is a directory");
|
||||
mDirState = aIsDir ? BlobDirState::eIsDir : BlobDirState::eIsNotDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the nsIFile that this object wraps is a directory.
|
||||
*/
|
||||
|
@ -572,7 +581,8 @@ public:
|
|||
{
|
||||
MOZ_ASSERT(mDirState != BlobDirState::eUnknownIfDir,
|
||||
"Must only be used by callers for whom the code paths are "
|
||||
"know to call LookupAndCacheIsDirectory()");
|
||||
"know to call LookupAndCacheIsDirectory() or "
|
||||
"SetIsDirectory()");
|
||||
return mDirState == BlobDirState::eIsDir;
|
||||
}
|
||||
|
||||
|
|
|
@ -7464,8 +7464,11 @@ nsContentUtils::TransferableToIPCTransferable(nsITransferable* aTransferable,
|
|||
if (file) {
|
||||
blobImpl = new BlobImplFile(file, false);
|
||||
ErrorResult rv;
|
||||
// Ensure that file data is cached no that the content process
|
||||
// has this data available to it when passed over:
|
||||
blobImpl->GetSize(rv);
|
||||
blobImpl->GetLastModified(rv);
|
||||
blobImpl->LookupAndCacheIsDirectory();
|
||||
} else {
|
||||
blobImpl = do_QueryInterface(data);
|
||||
}
|
||||
|
|
|
@ -11349,9 +11349,7 @@ nsDocument::RestorePreviousFullScreenState()
|
|||
// a fullscreen element in a parent document. If this document isn't
|
||||
// approved for fullscreen, or if it's cross origin, dispatch an
|
||||
// event to chrome so it knows to show the authorization/warning UI.
|
||||
if (!nsContentUtils::HaveEqualPrincipals(fullScreenDoc, doc) ||
|
||||
(!nsContentUtils::IsSitePermAllow(doc->NodePrincipal(), "fullscreen") &&
|
||||
!static_cast<nsDocument*>(doc)->mIsApprovedForFullscreen)) {
|
||||
if (!nsContentUtils::HaveEqualPrincipals(fullScreenDoc, doc)) {
|
||||
DispatchCustomEventWithFlush(
|
||||
doc, NS_LITERAL_STRING("MozDOMFullscreen:NewOrigin"),
|
||||
/* Bubbles */ true, /* ChromeOnly */ true);
|
||||
|
@ -11419,41 +11417,6 @@ LogFullScreenDenied(bool aLogFailure, const char* aMessage, nsIDocument* aDoc)
|
|||
aMessage);
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocument::AddFullscreenApprovedObserver()
|
||||
{
|
||||
if (mHasFullscreenApprovedObserver) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
|
||||
NS_ENSURE_TRUE(os, NS_ERROR_FAILURE);
|
||||
|
||||
nsresult res = os->AddObserver(this, "fullscreen-approved", true);
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
mHasFullscreenApprovedObserver = true;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsDocument::RemoveFullscreenApprovedObserver()
|
||||
{
|
||||
if (!mHasFullscreenApprovedObserver) {
|
||||
return NS_OK;
|
||||
}
|
||||
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
|
||||
NS_ENSURE_TRUE(os, NS_ERROR_FAILURE);
|
||||
|
||||
nsresult res = os->RemoveObserver(this, "fullscreen-approved");
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
|
||||
mHasFullscreenApprovedObserver = false;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::CleanupFullscreenState()
|
||||
{
|
||||
|
@ -11471,8 +11434,6 @@ nsDocument::CleanupFullscreenState()
|
|||
}
|
||||
mFullScreenStack.Clear();
|
||||
}
|
||||
SetApprovedForFullscreen(false);
|
||||
RemoveFullscreenApprovedObserver();
|
||||
mFullscreenRoot = nullptr;
|
||||
}
|
||||
|
||||
|
@ -11817,8 +11778,6 @@ nsDocument::ApplyFullscreen(const FullscreenRequest& aRequest)
|
|||
// to detect if the origin which is fullscreen has changed.
|
||||
nsCOMPtr<nsIDocument> previousFullscreenDoc = GetFullscreenLeaf(this);
|
||||
|
||||
AddFullscreenApprovedObserver();
|
||||
|
||||
// Stores a list of documents which we must dispatch "mozfullscreenchange"
|
||||
// too. We're required by the spec to dispatch the events in root-to-leaf
|
||||
// order, but we traverse the doctree in a leaf-to-root order, so we save
|
||||
|
@ -11875,25 +11834,13 @@ nsDocument::ApplyFullscreen(const FullscreenRequest& aRequest)
|
|||
}
|
||||
}
|
||||
|
||||
// If this document hasn't already been approved in this session,
|
||||
// check to see if the user has granted the fullscreen access
|
||||
// to the document's principal's host, if it has one. Note that documents
|
||||
// in web apps which are the same origin as the web app are considered
|
||||
// trusted and so are automatically approved.
|
||||
if (!mIsApprovedForFullscreen) {
|
||||
mIsApprovedForFullscreen =
|
||||
!Preferences::GetBool("full-screen-api.approval-required") ||
|
||||
NodePrincipal()->GetAppStatus() >= nsIPrincipal::APP_STATUS_INSTALLED ||
|
||||
nsContentUtils::IsSitePermAllow(NodePrincipal(), "fullscreen");
|
||||
}
|
||||
|
||||
FullscreenRoots::Add(this);
|
||||
|
||||
// If it is the first entry of the fullscreen, trigger an event so
|
||||
// that the UI can response to this change, e.g. hide chrome, or
|
||||
// notifying parent process to enter fullscreen. Note that chrome
|
||||
// code may also want to listen to MozDOMFullscreen:NewOrigin event
|
||||
// to pop up warning/approval UI.
|
||||
// to pop up warning UI.
|
||||
if (!previousFullscreenDoc) {
|
||||
nsContentUtils::DispatchEventOnlyToChrome(
|
||||
this, ToSupports(elem), NS_LITERAL_STRING("MozDOMFullscreen:Entered"),
|
||||
|
@ -11901,7 +11848,7 @@ nsDocument::ApplyFullscreen(const FullscreenRequest& aRequest)
|
|||
}
|
||||
|
||||
// The origin which is fullscreen gets changed. Trigger an event so
|
||||
// that the chrome knows to pop up a warning/approval UI. Note that
|
||||
// that the chrome knows to pop up a warning UI. Note that
|
||||
// previousFullscreenDoc == nullptr upon first entry, so we always
|
||||
// take this path on the first entry. Also note that, in a multi-
|
||||
// process browser, the code in content process is responsible for
|
||||
|
@ -12090,15 +12037,13 @@ public:
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// We're about to enter fullscreen mode.
|
||||
nsDocument* doc = static_cast<nsDocument*>(d.get());
|
||||
if (doc->mPendingFullscreenRequests > 0 ||
|
||||
(doc->mHasFullscreenApprovedObserver && !doc->mIsApprovedForFullscreen)) {
|
||||
// We're still waiting for approval.
|
||||
if (doc->mPendingFullscreenRequests > 0) {
|
||||
// We're still entering fullscreen.
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (doc->mIsApprovedForFullscreen || doc->mAllowRelocking) {
|
||||
if (doc->IsFullScreenDoc() || doc->mAllowRelocking) {
|
||||
Allow(JS::UndefinedHandleValue);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -12203,8 +12148,7 @@ nsPointerLockPermissionRequest::Allow(JS::HandleValue aChoices)
|
|||
nsCOMPtr<nsIDocument> doc = do_QueryReferent(mDocument);
|
||||
nsDocument* d = static_cast<nsDocument*>(doc.get());
|
||||
if (!e || !d || gPendingPointerLockRequest != this ||
|
||||
e->GetUncomposedDoc() != d ||
|
||||
(!mUserInputOrChromeCaller && !d->mIsApprovedForFullscreen)) {
|
||||
e->GetUncomposedDoc() != d) {
|
||||
Handled();
|
||||
DispatchPointerLockError(d);
|
||||
return NS_OK;
|
||||
|
@ -12253,12 +12197,6 @@ nsPointerLockPermissionRequest::GetRequester(nsIContentPermissionRequester** aRe
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsDocument::SetApprovedForFullscreen(bool aIsApproved)
|
||||
{
|
||||
mIsApprovedForFullscreen = aIsApproved;
|
||||
}
|
||||
|
||||
static void
|
||||
RedispatchPendingPointerLockRequest(nsIDocument* aDocument)
|
||||
{
|
||||
|
@ -12278,7 +12216,7 @@ RedispatchPendingPointerLockRequest(nsIDocument* aDocument)
|
|||
}
|
||||
|
||||
// We have a request pending on the document which may previously be
|
||||
// blocked for fullscreen approval. Create a clone and re-dispatch it
|
||||
// blocked for fullscreen change. Create a clone and re-dispatch it
|
||||
// to guarantee that Run() method gets called again.
|
||||
bool userInputOrChromeCaller =
|
||||
gPendingPointerLockRequest->mUserInputOrChromeCaller;
|
||||
|
@ -12293,14 +12231,7 @@ nsDocument::Observe(nsISupports *aSubject,
|
|||
const char *aTopic,
|
||||
const char16_t *aData)
|
||||
{
|
||||
if (strcmp("fullscreen-approved", aTopic) == 0) {
|
||||
nsCOMPtr<nsIDocument> subject(do_QueryInterface(aSubject));
|
||||
if (subject != this) {
|
||||
return NS_OK;
|
||||
}
|
||||
SetApprovedForFullscreen(true);
|
||||
RedispatchPendingPointerLockRequest(this);
|
||||
} else if (strcmp("app-theme-changed", aTopic) == 0) {
|
||||
if (strcmp("app-theme-changed", aTopic) == 0) {
|
||||
if (!nsContentUtils::IsSystemPrincipal(NodePrincipal()) &&
|
||||
!IsUnstyledDocument()) {
|
||||
// We don't want to style the chrome window, only app ones.
|
||||
|
|
|
@ -1208,7 +1208,6 @@ public:
|
|||
virtual void RestorePreviousFullScreenState() override;
|
||||
virtual bool IsFullscreenLeaf() override;
|
||||
virtual bool IsFullScreenDoc() override;
|
||||
virtual void SetApprovedForFullscreen(bool aIsApproved) override;
|
||||
virtual nsresult
|
||||
RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement) override;
|
||||
|
||||
|
@ -1254,13 +1253,6 @@ public:
|
|||
// styles from the top element in the stack.
|
||||
void CleanupFullscreenState();
|
||||
|
||||
// Add/remove "fullscreen-approved" observer service notification listener.
|
||||
// Chrome sends us a notification when fullscreen is approved for a
|
||||
// document, with the notification subject as the document that was approved.
|
||||
// We maintain this listener while in fullscreen mode.
|
||||
nsresult AddFullscreenApprovedObserver();
|
||||
nsresult RemoveFullscreenApprovedObserver();
|
||||
|
||||
// Pushes aElement onto the full-screen stack, and removes full-screen styles
|
||||
// from the former full-screen stack top, and its ancestors, and applies the
|
||||
// styles to aElement. aElement becomes the new "full-screen element".
|
||||
|
@ -1661,26 +1653,6 @@ public:
|
|||
// terminated instead of letting it finish at its own pace.
|
||||
bool mParserAborted:1;
|
||||
|
||||
// Whether this document has been approved for fullscreen, either by explicit
|
||||
// approval via the fullscreen-approval UI, or because it received
|
||||
// approval because its document's host already had the "fullscreen"
|
||||
// permission granted when the document requested fullscreen.
|
||||
//
|
||||
// Note if a document's principal doesn't have a host, the permission manager
|
||||
// can't store permissions for it, so we can only manage approval using this
|
||||
// flag.
|
||||
//
|
||||
// Note we must track this separately from the "fullscreen" permission,
|
||||
// so that pending pointer lock requests can determine whether documents
|
||||
// whose principal doesn't have a host (i.e. those which can't store
|
||||
// permissions in the permission manager) have been approved for fullscreen.
|
||||
bool mIsApprovedForFullscreen:1;
|
||||
|
||||
// Whether this document has a fullscreen approved observer. Only documents
|
||||
// which request fullscreen and which don't have a pre-existing approval for
|
||||
// fullscreen will have an observer.
|
||||
bool mHasFullscreenApprovedObserver:1;
|
||||
|
||||
friend class nsPointerLockPermissionRequest;
|
||||
friend class nsCallRequestFullScreen;
|
||||
// When set, trying to lock the pointer doesn't require permission from the
|
||||
|
|
|
@ -152,8 +152,8 @@ typedef CallbackObjectHolder<NodeFilter, nsIDOMNodeFilter> NodeFilterHolder;
|
|||
} // namespace mozilla
|
||||
|
||||
#define NS_IDOCUMENT_IID \
|
||||
{ 0x21bbd52a, 0xc2d2, 0x4b2f, \
|
||||
{ 0xbc, 0x6c, 0xc9, 0x52, 0xbe, 0x23, 0x6b, 0x19 } }
|
||||
{ 0xbbce44c8, 0x22fe, 0x404f, \
|
||||
{ 0x9e, 0x71, 0x23, 0x1d, 0xf4, 0xcc, 0x8e, 0x34 } }
|
||||
|
||||
// Enum for requesting a particular type of document when creating a doc
|
||||
enum DocumentFlavor {
|
||||
|
@ -1156,14 +1156,6 @@ public:
|
|||
*/
|
||||
virtual void SetFullscreenRoot(nsIDocument* aRoot) = 0;
|
||||
|
||||
/**
|
||||
* Sets whether this document is approved for fullscreen mode.
|
||||
* Documents aren't approved for fullscreen until chrome has sent a
|
||||
* "fullscreen-approved" notification with a subject which is a pointer
|
||||
* to the approved document.
|
||||
*/
|
||||
virtual void SetApprovedForFullscreen(bool aIsApproved) = 0;
|
||||
|
||||
/**
|
||||
* Synchronously cleans up the fullscreen state on the given document.
|
||||
*
|
||||
|
|
|
@ -113,18 +113,12 @@ DataStoreDB::CreateFactoryIfNeeded()
|
|||
MOZ_ASSERT(xpc);
|
||||
|
||||
AutoSafeJSContext cx;
|
||||
|
||||
nsCOMPtr<nsIXPConnectJSObjectHolder> globalHolder;
|
||||
rv = xpc->CreateSandbox(cx, principal, getter_AddRefs(globalHolder));
|
||||
JS::Rooted<JSObject*> global(cx);
|
||||
rv = xpc->CreateSandbox(cx, principal, global.address());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
JS::Rooted<JSObject*> global(cx, globalHolder->GetJSObject());
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// The CreateSandbox call returns a proxy to the actual sandbox object. We
|
||||
// don't need a proxy here.
|
||||
global = js::UncheckedUnwrap(global);
|
||||
|
|
|
@ -26,8 +26,10 @@
|
|||
#include "nsIScriptGlobalObject.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/DataTransferBinding.h"
|
||||
#include "mozilla/dom/Directory.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/BindingUtils.h"
|
||||
#include "mozilla/dom/OSFileSystem.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -295,6 +297,13 @@ DataTransfer::GetFiles(ErrorResult& aRv)
|
|||
|
||||
nsRefPtr<File> domFile;
|
||||
if (file) {
|
||||
#ifdef DEBUG
|
||||
if (XRE_GetProcessType() == GeckoProcessType_Default) {
|
||||
bool isDir;
|
||||
file->IsDirectory(&isDir);
|
||||
MOZ_ASSERT(!isDir, "How did we get here?");
|
||||
}
|
||||
#endif
|
||||
domFile = File::CreateFromFile(GetParentObject(), file);
|
||||
} else {
|
||||
nsCOMPtr<BlobImpl> blobImpl = do_QueryInterface(supports);
|
||||
|
@ -814,6 +823,92 @@ DataTransfer::SetDragImage(nsIDOMElement* aImage, int32_t aX, int32_t aY)
|
|||
return rv.StealNSResult();
|
||||
}
|
||||
|
||||
static already_AddRefed<OSFileSystem>
|
||||
MakeOrReuseFileSystem(const nsAString& aNewLocalRootPath,
|
||||
OSFileSystem* aFS,
|
||||
nsPIDOMWindow* aWindow)
|
||||
{
|
||||
MOZ_ASSERT(aWindow);
|
||||
|
||||
nsRefPtr<OSFileSystem> fs;
|
||||
if (aFS) {
|
||||
const nsAString& prevLocalRootPath = aFS->GetLocalRootPath();
|
||||
if (aNewLocalRootPath == prevLocalRootPath) {
|
||||
fs = aFS;
|
||||
}
|
||||
}
|
||||
if (!fs) {
|
||||
fs = new OSFileSystem(aNewLocalRootPath);
|
||||
fs->Init(aWindow);
|
||||
}
|
||||
return fs.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
DataTransfer::GetFilesAndDirectories(ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsINode> parentNode = do_QueryInterface(mParent);
|
||||
if (!parentNode) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIGlobalObject> global = parentNode->OwnerDoc()->GetScopeObject();
|
||||
MOZ_ASSERT(global);
|
||||
if (!global) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<Promise> p = Promise::Create(global, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!mFiles) {
|
||||
ErrorResult dummy;
|
||||
GetFiles(dummy);
|
||||
if (!mFiles) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
Sequence<OwningFileOrDirectory> filesAndDirsSeq;
|
||||
|
||||
if (!filesAndDirsSeq.SetLength(mFiles->Length(), mozilla::fallible_t())) {
|
||||
p->MaybeReject(NS_ERROR_OUT_OF_MEMORY);
|
||||
return p.forget();
|
||||
}
|
||||
|
||||
nsPIDOMWindow* window = parentNode->OwnerDoc()->GetInnerWindow();
|
||||
|
||||
nsRefPtr<OSFileSystem> fs;
|
||||
for (uint32_t i = 0; i < mFiles->Length(); ++i) {
|
||||
if (mFiles->Item(i)->Impl()->IsDirectory()) {
|
||||
#if defined(ANDROID) || defined(MOZ_B2G)
|
||||
MOZ_ASSERT(false,
|
||||
"Directory picking should have been redirected to normal "
|
||||
"file picking for platforms that don't have a directory "
|
||||
"picker");
|
||||
#endif
|
||||
nsAutoString path;
|
||||
mFiles->Item(i)->GetMozFullPathInternal(path, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
int32_t leafSeparatorIndex = path.RFind(FILE_PATH_SEPARATOR);
|
||||
nsDependentSubstring dirname = Substring(path, 0, leafSeparatorIndex);
|
||||
nsDependentSubstring basename = Substring(path, leafSeparatorIndex);
|
||||
fs = MakeOrReuseFileSystem(dirname, fs, window);
|
||||
filesAndDirsSeq[i].SetAsDirectory() = new Directory(fs, basename);
|
||||
} else {
|
||||
filesAndDirsSeq[i].SetAsFile() = mFiles->Item(i);
|
||||
}
|
||||
}
|
||||
|
||||
p->MaybeResolve(filesAndDirsSeq);
|
||||
|
||||
return p.forget();
|
||||
}
|
||||
|
||||
void
|
||||
DataTransfer::AddElement(Element& aElement, ErrorResult& aRv)
|
||||
{
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "nsAutoPtr.h"
|
||||
#include "mozilla/Attributes.h"
|
||||
#include "mozilla/dom/File.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
|
||||
class nsINode;
|
||||
class nsITransferable;
|
||||
|
@ -145,6 +146,9 @@ public:
|
|||
void ClearData(const mozilla::dom::Optional<nsAString>& aFormat,
|
||||
mozilla::ErrorResult& aRv);
|
||||
FileList* GetFiles(mozilla::ErrorResult& aRv);
|
||||
|
||||
already_AddRefed<Promise> GetFilesAndDirectories(ErrorResult& aRv);
|
||||
|
||||
void AddElement(Element& aElement, mozilla::ErrorResult& aRv);
|
||||
uint32_t MozItemCount()
|
||||
{
|
||||
|
|
|
@ -36,8 +36,8 @@ DeviceStorageFileSystem::DeviceStorageFileSystem(
|
|||
mString.Append('-');
|
||||
mString.Append(mStorageName);
|
||||
|
||||
mIsTesting =
|
||||
mozilla::Preferences::GetBool("device.storage.prompt.testing", false);
|
||||
mRequiresPermissionChecks =
|
||||
!mozilla::Preferences::GetBool("device.storage.prompt.testing", false);
|
||||
|
||||
// Get the permission name required to access the file system.
|
||||
nsresult rv =
|
||||
|
@ -97,45 +97,10 @@ DeviceStorageFileSystem::GetWindow() const
|
|||
return mDeviceStorage->GetOwner();
|
||||
}
|
||||
|
||||
already_AddRefed<nsIFile>
|
||||
DeviceStorageFileSystem::GetLocalFile(const nsAString& aRealPath) const
|
||||
void
|
||||
DeviceStorageFileSystem::GetRootName(nsAString& aRetval) const
|
||||
{
|
||||
MOZ_ASSERT(XRE_IsParentProcess(),
|
||||
"Should be on parent process!");
|
||||
nsAutoString localPath;
|
||||
FileSystemUtils::NormalizedPathToLocalPath(aRealPath, localPath);
|
||||
localPath = mLocalRootPath + localPath;
|
||||
nsCOMPtr<nsIFile> file;
|
||||
nsresult rv = NS_NewLocalFile(localPath, false, getter_AddRefs(file));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
return file.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
DeviceStorageFileSystem::GetRealPath(BlobImpl* aFile, nsAString& aRealPath) const
|
||||
{
|
||||
MOZ_ASSERT(XRE_IsParentProcess(),
|
||||
"Should be on parent process!");
|
||||
MOZ_ASSERT(aFile, "aFile Should not be null.");
|
||||
|
||||
aRealPath.Truncate();
|
||||
|
||||
nsAutoString filePath;
|
||||
ErrorResult rv;
|
||||
aFile->GetMozFullPathInternal(filePath, rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return LocalPathToRealPath(filePath, aRealPath);
|
||||
}
|
||||
|
||||
const nsAString&
|
||||
DeviceStorageFileSystem::GetRootName() const
|
||||
{
|
||||
return mStorageName;
|
||||
aRetval = mStorageName;
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -172,19 +137,5 @@ DeviceStorageFileSystem::IsSafeDirectory(Directory* aDir) const
|
|||
return fs->ToString() == mString;
|
||||
}
|
||||
|
||||
bool
|
||||
DeviceStorageFileSystem::LocalPathToRealPath(const nsAString& aLocalPath,
|
||||
nsAString& aRealPath) const
|
||||
{
|
||||
nsAutoString path;
|
||||
FileSystemUtils::LocalPathToNormalizedPath(aLocalPath, path);
|
||||
if (!FileSystemUtils::IsDescendantPath(mNormalizedLocalRootPath, path)) {
|
||||
aRealPath.Truncate();
|
||||
return false;
|
||||
}
|
||||
aRealPath = Substring(path, mNormalizedLocalRootPath.Length());
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -33,14 +33,8 @@ public:
|
|||
virtual nsPIDOMWindow*
|
||||
GetWindow() const override;
|
||||
|
||||
virtual already_AddRefed<nsIFile>
|
||||
GetLocalFile(const nsAString& aRealPath) const override;
|
||||
|
||||
virtual bool
|
||||
GetRealPath(BlobImpl* aFile, nsAString& aRealPath) const override;
|
||||
|
||||
virtual const nsAString&
|
||||
GetRootName() const override;
|
||||
virtual void
|
||||
GetRootName(nsAString& aRetval) const override;
|
||||
|
||||
virtual bool
|
||||
IsSafeFile(nsIFile* aFile) const override;
|
||||
|
@ -51,16 +45,9 @@ private:
|
|||
virtual
|
||||
~DeviceStorageFileSystem();
|
||||
|
||||
bool
|
||||
LocalPathToRealPath(const nsAString& aLocalPath, nsAString& aRealPath) const;
|
||||
|
||||
nsString mStorageType;
|
||||
nsString mStorageName;
|
||||
|
||||
// The local path of the root. Only available in the parent process.
|
||||
// In the child process, we don't use it and its value should be empty.
|
||||
nsString mLocalRootPath;
|
||||
nsString mNormalizedLocalRootPath;
|
||||
nsDOMDeviceStorage* mDeviceStorage;
|
||||
};
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ Directory::GetName(nsAString& aRetval) const
|
|||
aRetval.Truncate();
|
||||
|
||||
if (mPath.IsEmpty()) {
|
||||
aRetval = mFileSystem->GetRootName();
|
||||
mFileSystem->GetRootName(aRetval);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "DeviceStorageFileSystem.h"
|
||||
#include "nsCharSeparatedTokenizer.h"
|
||||
#include "OSFileSystem.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
@ -37,12 +38,12 @@ FileSystemBase::FromString(const nsAString& aString)
|
|||
new DeviceStorageFileSystem(storageType, storageName);
|
||||
return f.forget();
|
||||
}
|
||||
return nullptr;
|
||||
return nsRefPtr<OSFileSystem>(new OSFileSystem(aString)).forget();
|
||||
}
|
||||
|
||||
FileSystemBase::FileSystemBase()
|
||||
: mShutdown(false)
|
||||
, mIsTesting(false)
|
||||
, mRequiresPermissionChecks(true)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -62,6 +63,41 @@ FileSystemBase::GetWindow() const
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIFile>
|
||||
FileSystemBase::GetLocalFile(const nsAString& aRealPath) const
|
||||
{
|
||||
MOZ_ASSERT(XRE_IsParentProcess(),
|
||||
"Should be on parent process!");
|
||||
nsAutoString localPath;
|
||||
FileSystemUtils::NormalizedPathToLocalPath(aRealPath, localPath);
|
||||
localPath = mLocalRootPath + localPath;
|
||||
nsCOMPtr<nsIFile> file;
|
||||
nsresult rv = NS_NewLocalFile(localPath, false, getter_AddRefs(file));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return nullptr;
|
||||
}
|
||||
return file.forget();
|
||||
}
|
||||
|
||||
bool
|
||||
FileSystemBase::GetRealPath(BlobImpl* aFile, nsAString& aRealPath) const
|
||||
{
|
||||
MOZ_ASSERT(XRE_IsParentProcess(),
|
||||
"Should be on parent process!");
|
||||
MOZ_ASSERT(aFile, "aFile Should not be null.");
|
||||
|
||||
aRealPath.Truncate();
|
||||
|
||||
nsAutoString filePath;
|
||||
ErrorResult rv;
|
||||
aFile->GetMozFullPathInternal(filePath, rv);
|
||||
if (NS_WARN_IF(rv.Failed())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return LocalPathToRealPath(filePath, aRealPath);
|
||||
}
|
||||
|
||||
bool
|
||||
FileSystemBase::IsSafeFile(nsIFile* aFile) const
|
||||
{
|
||||
|
@ -74,5 +110,19 @@ FileSystemBase::IsSafeDirectory(Directory* aDir) const
|
|||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
FileSystemBase::LocalPathToRealPath(const nsAString& aLocalPath,
|
||||
nsAString& aRealPath) const
|
||||
{
|
||||
nsAutoString path;
|
||||
FileSystemUtils::LocalPathToNormalizedPath(aLocalPath, path);
|
||||
if (!FileSystemUtils::IsDescendantPath(mNormalizedLocalRootPath, path)) {
|
||||
aRealPath.Truncate();
|
||||
return false;
|
||||
}
|
||||
aRealPath = Substring(path, mNormalizedLocalRootPath.Length());
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -42,18 +42,24 @@ public:
|
|||
virtual nsPIDOMWindow*
|
||||
GetWindow() const;
|
||||
|
||||
/*
|
||||
* Create nsIFile object with the given real path (absolute DOM path).
|
||||
/**
|
||||
* Create nsIFile object from the given real path (absolute DOM path).
|
||||
*/
|
||||
virtual already_AddRefed<nsIFile>
|
||||
GetLocalFile(const nsAString& aRealPath) const = 0;
|
||||
already_AddRefed<nsIFile>
|
||||
GetLocalFile(const nsAString& aRealPath) const;
|
||||
|
||||
/*
|
||||
* Get the virtual name of the root directory. This name will be exposed to
|
||||
* the content page.
|
||||
*/
|
||||
virtual const nsAString&
|
||||
GetRootName() const = 0;
|
||||
virtual void
|
||||
GetRootName(nsAString& aRetval) const = 0;
|
||||
|
||||
const nsAString&
|
||||
GetLocalRootPath() const
|
||||
{
|
||||
return mLocalRootPath;
|
||||
}
|
||||
|
||||
bool
|
||||
IsShutdown() const
|
||||
|
@ -72,8 +78,8 @@ public:
|
|||
* If succeeded, returns true. Otherwise, returns false and set aRealPath to
|
||||
* empty string.
|
||||
*/
|
||||
virtual bool
|
||||
GetRealPath(BlobImpl* aFile, nsAString& aRealPath) const = 0;
|
||||
bool
|
||||
GetRealPath(BlobImpl* aFile, nsAString& aRealPath) const;
|
||||
|
||||
/*
|
||||
* Get the permission name required to access this file system.
|
||||
|
@ -85,13 +91,25 @@ public:
|
|||
}
|
||||
|
||||
bool
|
||||
IsTesting() const
|
||||
RequiresPermissionChecks() const
|
||||
{
|
||||
return mIsTesting;
|
||||
return mRequiresPermissionChecks;
|
||||
}
|
||||
protected:
|
||||
virtual ~FileSystemBase();
|
||||
|
||||
bool
|
||||
LocalPathToRealPath(const nsAString& aLocalPath, nsAString& aRealPath) const;
|
||||
|
||||
// The local path of the root (i.e. the OS path, with OS path separators, of
|
||||
// the OS directory that acts as the root of this OSFileSystem).
|
||||
// Only available in the parent process.
|
||||
// In the child process, we don't use it and its value should be empty.
|
||||
nsString mLocalRootPath;
|
||||
|
||||
// The same, but with path separators normalized to "/".
|
||||
nsString mNormalizedLocalRootPath;
|
||||
|
||||
// The string representation of the file system.
|
||||
nsString mString;
|
||||
|
||||
|
@ -100,7 +118,7 @@ protected:
|
|||
// The permission name required to access the file system.
|
||||
nsCString mPermission;
|
||||
|
||||
bool mIsTesting;
|
||||
bool mRequiresPermissionChecks;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
|
|
|
@ -122,7 +122,7 @@ FileSystemPermissionRequest::Run()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
if (filesystem->IsTesting()) {
|
||||
if (!filesystem->RequiresPermissionChecks()) {
|
||||
Allow(JS::UndefinedHandleValue);
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ FileSystemRequestParent::Dispatch(ContentParent* aParent,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!mFileSystem->IsTesting()) {
|
||||
if (mFileSystem->RequiresPermissionChecks()) {
|
||||
// Check the content process permission.
|
||||
|
||||
nsCString access;
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
/* -*- 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 "mozilla/dom/OSFileSystem.h"
|
||||
|
||||
#include "mozilla/dom/Directory.h"
|
||||
#include "mozilla/dom/File.h"
|
||||
#include "mozilla/dom/FileSystemUtils.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsDebug.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsPIDOMWindow.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
OSFileSystem::OSFileSystem(const nsAString& aRootDir)
|
||||
{
|
||||
mLocalRootPath = aRootDir;
|
||||
FileSystemUtils::LocalPathToNormalizedPath(mLocalRootPath,
|
||||
mNormalizedLocalRootPath);
|
||||
|
||||
// Non-mobile devices don't have the concept of separate permissions to
|
||||
// access different parts of devices storage like Pictures, or Videos, etc.
|
||||
mRequiresPermissionChecks = false;
|
||||
|
||||
mString = mLocalRootPath;
|
||||
|
||||
#ifdef DEBUG
|
||||
mPermission.AssignLiteral("never-used");
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
OSFileSystem::Init(nsPIDOMWindow* aWindow)
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
|
||||
MOZ_ASSERT(!mWindow, "No duple Init() calls");
|
||||
MOZ_ASSERT(aWindow);
|
||||
mWindow = aWindow;
|
||||
}
|
||||
|
||||
nsPIDOMWindow*
|
||||
OSFileSystem::GetWindow() const
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Only call on main thread!");
|
||||
return mWindow;
|
||||
}
|
||||
|
||||
void
|
||||
OSFileSystem::GetRootName(nsAString& aRetval) const
|
||||
{
|
||||
return aRetval.AssignLiteral("/");
|
||||
}
|
||||
|
||||
bool
|
||||
OSFileSystem::IsSafeFile(nsIFile* aFile) const
|
||||
{
|
||||
// The concept of "safe files" is specific to the Device Storage API where
|
||||
// files are only "safe" if they're of a type that is appropriate for the
|
||||
// area of device storage that is being used.
|
||||
MOZ_CRASH("Don't use OSFileSystem with the Device Storage API");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
OSFileSystem::IsSafeDirectory(Directory* aDir) const
|
||||
{
|
||||
// The concept of "safe directory" is specific to the Device Storage API
|
||||
// where a directory is only "safe" if it belongs to the area of device
|
||||
// storage that it is being used with.
|
||||
MOZ_CRASH("Don't use OSFileSystem with the Device Storage API");
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
|
@ -0,0 +1,46 @@
|
|||
/* -*- 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 mozilla_dom_OSFileSystem_h
|
||||
#define mozilla_dom_OSFileSystem_h
|
||||
|
||||
#include "mozilla/dom/FileSystemBase.h"
|
||||
|
||||
namespace mozilla {
|
||||
namespace dom {
|
||||
|
||||
class OSFileSystem : public FileSystemBase
|
||||
{
|
||||
public:
|
||||
explicit OSFileSystem(const nsAString& aRootDir);
|
||||
|
||||
void
|
||||
Init(nsPIDOMWindow* aWindow);
|
||||
|
||||
// Overrides FileSystemBase
|
||||
|
||||
virtual nsPIDOMWindow*
|
||||
GetWindow() const override;
|
||||
|
||||
virtual void
|
||||
GetRootName(nsAString& aRetval) const override;
|
||||
|
||||
virtual bool
|
||||
IsSafeFile(nsIFile* aFile) const override;
|
||||
|
||||
virtual bool
|
||||
IsSafeDirectory(Directory* aDir) const override;
|
||||
|
||||
private:
|
||||
virtual ~OSFileSystem() {}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindow> mWindow;
|
||||
};
|
||||
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
#endif // mozilla_dom_OSFileSystem_h
|
|
@ -11,6 +11,7 @@ EXPORTS.mozilla.dom += [
|
|||
'FileSystemRequestParent.h',
|
||||
'FileSystemTaskBase.h',
|
||||
'FileSystemUtils.h',
|
||||
'OSFileSystem.h',
|
||||
]
|
||||
|
||||
UNIFIED_SOURCES += [
|
||||
|
@ -25,6 +26,7 @@ UNIFIED_SOURCES += [
|
|||
'FileSystemUtils.cpp',
|
||||
'GetDirectoryListingTask.cpp',
|
||||
'GetFileOrDirectoryTask.cpp',
|
||||
'OSFileSystem.cpp',
|
||||
'RemoveTask.cpp',
|
||||
]
|
||||
|
||||
|
|
|
@ -10,7 +10,11 @@
|
|||
#include "mozilla/AsyncEventDispatcher.h"
|
||||
#include "mozilla/DebugOnly.h"
|
||||
#include "mozilla/dom/Date.h"
|
||||
#include "mozilla/dom/Directory.h"
|
||||
#include "mozilla/dom/FileSystemUtils.h"
|
||||
#include "mozilla/dom/OSFileSystem.h"
|
||||
#include "nsAttrValueInlines.h"
|
||||
#include "nsCRTGlue.h"
|
||||
|
||||
#include "nsIDOMHTMLInputElement.h"
|
||||
#include "nsITextControlElement.h"
|
||||
|
@ -373,7 +377,8 @@ HTMLInputElement::nsFilePickerShownCallback::Done(int16_t aResult)
|
|||
|
||||
// Collect new selected filenames
|
||||
nsTArray<nsRefPtr<File>> newFiles;
|
||||
if (mode == static_cast<int16_t>(nsIFilePicker::modeOpenMultiple)) {
|
||||
if (mode == static_cast<int16_t>(nsIFilePicker::modeOpenMultiple) ||
|
||||
mode == static_cast<int16_t>(nsIFilePicker::modeGetFolder)) {
|
||||
nsCOMPtr<nsISimpleEnumerator> iter;
|
||||
nsresult rv = mFilePicker->GetDomfiles(getter_AddRefs(iter));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -2876,7 +2881,9 @@ HTMLInputElement::Focus(ErrorResult& aError)
|
|||
return;
|
||||
}
|
||||
|
||||
// For file inputs, focus the button instead.
|
||||
// For file inputs, focus the first button instead. In the case of there
|
||||
// being two buttons (when the picker is a directory picker) the user can
|
||||
// tab to the next one.
|
||||
nsIFrame* frame = GetPrimaryFrame();
|
||||
if (frame) {
|
||||
for (nsIFrame* childFrame = frame->GetFirstPrincipalChild();
|
||||
|
@ -3544,7 +3551,21 @@ HTMLInputElement::MaybeInitPickers(EventChainPostVisitor& aVisitor)
|
|||
return NS_OK;
|
||||
}
|
||||
if (mType == NS_FORM_INPUT_FILE) {
|
||||
return InitFilePicker(FILE_PICKER_FILE);
|
||||
// If the user clicked on the "Choose folder..." button we open the
|
||||
// directory picker, else we open the file picker.
|
||||
FilePickerType type = FILE_PICKER_FILE;
|
||||
nsCOMPtr<nsIContent> target =
|
||||
do_QueryInterface(aVisitor.mEvent->originalTarget);
|
||||
if (target &&
|
||||
target->GetParent() == this &&
|
||||
target->IsRootOfNativeAnonymousSubtree() &&
|
||||
target->HasAttr(kNameSpaceID_None, nsGkAtoms::directory)) {
|
||||
MOZ_ASSERT(Preferences::GetBool("dom.input.dirpicker", false),
|
||||
"No API or UI should have been exposed to allow this code to "
|
||||
"be reached");
|
||||
type = FILE_PICKER_DIRECTORY;
|
||||
}
|
||||
return InitFilePicker(type);
|
||||
}
|
||||
if (mType == NS_FORM_INPUT_COLOR) {
|
||||
return InitColorPicker();
|
||||
|
@ -4752,7 +4773,10 @@ HTMLInputElement::GetAttributeChangeHint(const nsIAtom* aAttribute,
|
|||
{
|
||||
nsChangeHint retval =
|
||||
nsGenericHTMLFormElementWithState::GetAttributeChangeHint(aAttribute, aModType);
|
||||
if (aAttribute == nsGkAtoms::type) {
|
||||
if (aAttribute == nsGkAtoms::type ||
|
||||
// The presence or absence of the 'directory' attribute determines what
|
||||
// buttons we show for type=file.
|
||||
aAttribute == nsGkAtoms::directory) {
|
||||
NS_UpdateHint(retval, NS_STYLE_HINT_FRAMECHANGE);
|
||||
} else if (mType == NS_FORM_INPUT_IMAGE &&
|
||||
(aAttribute == nsGkAtoms::alt ||
|
||||
|
@ -4797,6 +4821,110 @@ HTMLInputElement::GetAttributeMappingFunction() const
|
|||
}
|
||||
|
||||
|
||||
// Directory picking methods:
|
||||
|
||||
bool
|
||||
HTMLInputElement::IsFilesAndDirectoriesSupported() const
|
||||
{
|
||||
// This method is supposed to return true if a file and directory picker
|
||||
// supports the selection of both files and directories *at the same time*.
|
||||
// Only Mac currently supports that. We could implement it for Mac, but
|
||||
// currently we do not.
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
HTMLInputElement::ChooseDirectory(ErrorResult& aRv)
|
||||
{
|
||||
if (mType != NS_FORM_INPUT_FILE) {
|
||||
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
|
||||
return;
|
||||
}
|
||||
InitFilePicker(
|
||||
#if defined(ANDROID) || defined(MOZ_B2G)
|
||||
// No native directory picker - redirect to plain file picker
|
||||
FILE_PICKER_FILE
|
||||
#else
|
||||
FILE_PICKER_DIRECTORY
|
||||
#endif
|
||||
);
|
||||
}
|
||||
|
||||
static already_AddRefed<OSFileSystem>
|
||||
MakeOrReuseFileSystem(const nsAString& aNewLocalRootPath,
|
||||
OSFileSystem* aFS,
|
||||
nsPIDOMWindow* aWindow)
|
||||
{
|
||||
MOZ_ASSERT(aWindow);
|
||||
|
||||
nsRefPtr<OSFileSystem> fs;
|
||||
if (aFS) {
|
||||
const nsAString& prevLocalRootPath = aFS->GetLocalRootPath();
|
||||
if (aNewLocalRootPath == prevLocalRootPath) {
|
||||
fs = aFS;
|
||||
}
|
||||
}
|
||||
if (!fs) {
|
||||
fs = new OSFileSystem(aNewLocalRootPath);
|
||||
fs->Init(aWindow);
|
||||
}
|
||||
return fs.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise>
|
||||
HTMLInputElement::GetFilesAndDirectories(ErrorResult& aRv)
|
||||
{
|
||||
nsCOMPtr<nsIGlobalObject> global = OwnerDoc()->GetScopeObject();
|
||||
MOZ_ASSERT(global);
|
||||
if (!global) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
nsRefPtr<Promise> p = Promise::Create(global, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const nsTArray<nsRefPtr<File>>& filesAndDirs = GetFilesInternal();
|
||||
|
||||
Sequence<OwningFileOrDirectory> filesAndDirsSeq;
|
||||
|
||||
if (!filesAndDirsSeq.SetLength(filesAndDirs.Length(), mozilla::fallible_t())) {
|
||||
p->MaybeReject(NS_ERROR_OUT_OF_MEMORY);
|
||||
return p.forget();
|
||||
}
|
||||
|
||||
nsPIDOMWindow* window = OwnerDoc()->GetInnerWindow();
|
||||
nsRefPtr<OSFileSystem> fs;
|
||||
for (uint32_t i = 0; i < filesAndDirs.Length(); ++i) {
|
||||
if (filesAndDirs[i]->IsDirectory()) {
|
||||
#if defined(ANDROID) || defined(MOZ_B2G)
|
||||
MOZ_ASSERT(false,
|
||||
"Directory picking should have been redirected to normal "
|
||||
"file picking for platforms that don't have a directory "
|
||||
"picker");
|
||||
#endif
|
||||
nsAutoString path;
|
||||
filesAndDirs[i]->GetMozFullPathInternal(path, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
int32_t leafSeparatorIndex = path.RFind(FILE_PATH_SEPARATOR);
|
||||
nsDependentSubstring dirname = Substring(path, 0, leafSeparatorIndex);
|
||||
nsDependentSubstring basename = Substring(path, leafSeparatorIndex);
|
||||
fs = MakeOrReuseFileSystem(dirname, fs, window);
|
||||
filesAndDirsSeq[i].SetAsDirectory() = new Directory(fs, basename);
|
||||
} else {
|
||||
filesAndDirsSeq[i].SetAsFile() = filesAndDirs[i];
|
||||
}
|
||||
}
|
||||
|
||||
p->MaybeResolve(filesAndDirsSeq);
|
||||
|
||||
return p.forget();
|
||||
}
|
||||
|
||||
|
||||
// Controllers Methods
|
||||
|
||||
nsIControllers*
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "nsIConstraintValidation.h"
|
||||
#include "mozilla/dom/HTMLFormElement.h" // for HasEverTriedInvalidSubmit()
|
||||
#include "mozilla/dom/HTMLInputElementBinding.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "nsIFilePicker.h"
|
||||
#include "nsIContentPrefService2.h"
|
||||
#include "mozilla/Decimal.h"
|
||||
|
@ -685,6 +686,22 @@ public:
|
|||
ErrorResult& aRv, int32_t aSelectionStart = -1,
|
||||
int32_t aSelectionEnd = -1);
|
||||
|
||||
bool DirectoryAttr() const
|
||||
{
|
||||
return HasAttr(kNameSpaceID_None, nsGkAtoms::directory);
|
||||
}
|
||||
|
||||
void SetDirectoryAttr(bool aValue, ErrorResult& aRv)
|
||||
{
|
||||
SetHTMLBoolAttr(nsGkAtoms::directory, aValue, aRv);
|
||||
}
|
||||
|
||||
bool IsFilesAndDirectoriesSupported() const;
|
||||
|
||||
already_AddRefed<Promise> GetFilesAndDirectories(ErrorResult& aRv);
|
||||
|
||||
void ChooseDirectory(ErrorResult& aRv);
|
||||
|
||||
// XPCOM GetAlign() is OK
|
||||
void SetAlign(const nsAString& aValue, ErrorResult& aRv)
|
||||
{
|
||||
|
|
|
@ -56,9 +56,7 @@ function begin() {
|
|||
ok(contextMenu, "Got context menu XUL");
|
||||
|
||||
addFullscreenChangeContinuation("enter", fullscreenEntered);
|
||||
SpecialPowers.pushPrefEnv({"set":[["full-screen-api.approval-required", false]]}, function() {
|
||||
document.body.mozRequestFullScreen();
|
||||
});
|
||||
document.body.mozRequestFullScreen();
|
||||
}
|
||||
|
||||
function finish() {
|
||||
|
|
|
@ -2154,6 +2154,9 @@ public:
|
|||
virtual void
|
||||
LookupAndCacheIsDirectory() override;
|
||||
|
||||
virtual void
|
||||
SetIsDirectory(bool aIsDir) override;
|
||||
|
||||
virtual bool
|
||||
IsDirectory() const override;
|
||||
|
||||
|
@ -2944,6 +2947,13 @@ RemoteBlobImpl::LookupAndCacheIsDirectory()
|
|||
return mBlobImpl->LookupAndCacheIsDirectory();
|
||||
}
|
||||
|
||||
void
|
||||
BlobParent::
|
||||
RemoteBlobImpl::SetIsDirectory(bool aIsDir)
|
||||
{
|
||||
return mBlobImpl->SetIsDirectory(aIsDir);
|
||||
}
|
||||
|
||||
bool
|
||||
BlobParent::
|
||||
RemoteBlobImpl::IsDirectory() const
|
||||
|
|
|
@ -2612,6 +2612,18 @@ ContentChild::RecvStopProfiler()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::RecvPauseProfiler(const bool& aPause)
|
||||
{
|
||||
if (aPause) {
|
||||
profiler_pause();
|
||||
} else {
|
||||
profiler_resume();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
ContentChild::RecvGatherProfile()
|
||||
{
|
||||
|
|
|
@ -393,6 +393,7 @@ public:
|
|||
const double& aInterval,
|
||||
nsTArray<nsCString>&& aFeatures,
|
||||
nsTArray<nsCString>&& aThreadNameFilters) override;
|
||||
virtual bool RecvPauseProfiler(const bool& aPause) override;
|
||||
virtual bool RecvStopProfiler() override;
|
||||
virtual bool RecvGatherProfile() override;
|
||||
virtual bool RecvDomainSetChanged(const uint32_t& aSetType, const uint32_t& aChangeType,
|
||||
|
|
|
@ -669,6 +669,8 @@ static const char* sObserverTopics[] = {
|
|||
#ifdef MOZ_ENABLE_PROFILER_SPS
|
||||
"profiler-started",
|
||||
"profiler-stopped",
|
||||
"profiler-paused",
|
||||
"profiler-resumed",
|
||||
"profiler-subprocess-gather",
|
||||
"profiler-subprocess",
|
||||
#endif
|
||||
|
@ -3113,6 +3115,12 @@ ContentParent::Observe(nsISupports* aSubject,
|
|||
else if (!strcmp(aTopic, "profiler-stopped")) {
|
||||
unused << SendStopProfiler();
|
||||
}
|
||||
else if (!strcmp(aTopic, "profiler-paused")) {
|
||||
unused << SendPauseProfiler(true);
|
||||
}
|
||||
else if (!strcmp(aTopic, "profiler-resumed")) {
|
||||
unused << SendPauseProfiler(false);
|
||||
}
|
||||
else if (!strcmp(aTopic, "profiler-subprocess-gather")) {
|
||||
mGatherer = static_cast<ProfileGatherer*>(aSubject);
|
||||
mGatherer->WillGatherOOPProfile();
|
||||
|
|
|
@ -91,6 +91,7 @@ FilePickerParent::FileSizeAndDateRunnable::Run()
|
|||
ErrorResult rv;
|
||||
mBlobs[i]->GetSize(rv);
|
||||
mBlobs[i]->GetLastModified(rv);
|
||||
mBlobs[i]->LookupAndCacheIsDirectory();
|
||||
}
|
||||
|
||||
// Dispatch ourselves back on the main thread.
|
||||
|
@ -138,7 +139,8 @@ FilePickerParent::Done(int16_t aResult)
|
|||
}
|
||||
|
||||
nsTArray<nsRefPtr<BlobImpl>> blobs;
|
||||
if (mMode == nsIFilePicker::modeOpenMultiple) {
|
||||
if (mMode == nsIFilePicker::modeOpenMultiple ||
|
||||
mMode == nsIFilePicker::modeGetFolder) {
|
||||
nsCOMPtr<nsISimpleEnumerator> iter;
|
||||
NS_ENSURE_SUCCESS_VOID(mFilePicker->GetFiles(getter_AddRefs(iter)));
|
||||
|
||||
|
@ -164,6 +166,7 @@ FilePickerParent::Done(int16_t aResult)
|
|||
|
||||
MOZ_ASSERT(!mRunnable);
|
||||
mRunnable = new FileSizeAndDateRunnable(this, blobs);
|
||||
// Dispatch to background thread to do I/O:
|
||||
if (!mRunnable->Dispatch()) {
|
||||
unused << Send__delete__(this, void_t(), nsIFilePicker::returnCancel);
|
||||
}
|
||||
|
|
|
@ -622,6 +622,7 @@ child:
|
|||
async StartProfiler(uint32_t aEntries, double aInterval, nsCString[] aFeatures,
|
||||
nsCString[] aThreadNameFilters);
|
||||
async StopProfiler();
|
||||
async PauseProfiler(bool aPause);
|
||||
|
||||
async GatherProfile();
|
||||
|
||||
|
|
|
@ -165,8 +165,7 @@ NS_IMPL_ISUPPORTS(TabChild::DelayedFireContextMenuEvent,
|
|||
nsITimerCallback)
|
||||
|
||||
TabChildBase::TabChildBase()
|
||||
: mContentDocumentIsDisplayed(false)
|
||||
, mTabChildGlobal(nullptr)
|
||||
: mTabChildGlobal(nullptr)
|
||||
{
|
||||
mozilla::HoldJSObjects(this);
|
||||
}
|
||||
|
@ -206,280 +205,6 @@ NS_INTERFACE_MAP_END
|
|||
NS_IMPL_CYCLE_COLLECTING_ADDREF(TabChildBase)
|
||||
NS_IMPL_CYCLE_COLLECTING_RELEASE(TabChildBase)
|
||||
|
||||
// For the root frame, Screen and ParentLayer pixels are interchangeable.
|
||||
// nsViewportInfo stores zoom values as CSSToScreenScale (because it's a
|
||||
// data structure specific to the root frame), while FrameMetrics and
|
||||
// ZoomConstraints store zoom values as CSSToParentLayerScale (because they
|
||||
// are not specific to the root frame). We define convenience functions for
|
||||
// converting between the two. As the name suggests, they should only be used
|
||||
// when dealing with the root frame!
|
||||
CSSToScreenScale ConvertScaleForRoot(CSSToParentLayerScale aScale)
|
||||
{
|
||||
return ViewTargetAs<ScreenPixel>(aScale, PixelCastJustification::ScreenIsParentLayerForRoot);
|
||||
}
|
||||
CSSToParentLayerScale ConvertScaleForRoot(CSSToScreenScale aScale)
|
||||
{
|
||||
return ViewTargetAs<ParentLayerPixel>(aScale, PixelCastJustification::ScreenIsParentLayerForRoot);
|
||||
}
|
||||
|
||||
// Calculate the scale needed to fit the given viewport into the given display.
|
||||
CSSToScreenScale CalculateIntrinsicScale(const ScreenIntSize& aDisplaySize, const CSSSize& aViewportSize)
|
||||
{
|
||||
return MaxScaleRatio(ScreenSize(aDisplaySize), aViewportSize);
|
||||
}
|
||||
|
||||
void
|
||||
TabChildBase::InitializeRootMetrics()
|
||||
{
|
||||
// Calculate a really simple resolution that we probably won't
|
||||
// be keeping, as well as putting the scroll offset back to
|
||||
// the top-left of the page.
|
||||
mLastRootMetrics.SetViewport(CSSRect(CSSPoint(), kDefaultViewportSize));
|
||||
mLastRootMetrics.SetCompositionBounds(ParentLayerRect(
|
||||
ParentLayerPoint(),
|
||||
ParentLayerSize(
|
||||
ViewAs<ParentLayerPixel>(GetInnerSize(),
|
||||
PixelCastJustification::ScreenIsParentLayerForRoot))));
|
||||
mLastRootMetrics.SetZoom(CSSToParentLayerScale2D(
|
||||
ConvertScaleForRoot(CalculateIntrinsicScale(GetInnerSize(), kDefaultViewportSize))));
|
||||
mLastRootMetrics.SetDevPixelsPerCSSPixel(WebWidget()->GetDefaultScale());
|
||||
// We use ParentLayerToLayerScale(1) below in order to turn the
|
||||
// async zoom amount into the gecko zoom amount.
|
||||
mLastRootMetrics.SetCumulativeResolution(mLastRootMetrics.GetZoom() / mLastRootMetrics.GetDevPixelsPerCSSPixel() * ParentLayerToLayerScale(1));
|
||||
// This is the root layer, so the cumulative resolution is the same
|
||||
// as the resolution.
|
||||
mLastRootMetrics.SetPresShellResolution(mLastRootMetrics.GetCumulativeResolution().ToScaleFactor().scale);
|
||||
|
||||
nsCOMPtr<nsIPresShell> shell = GetPresShell();
|
||||
if (shell && shell->GetRootScrollFrameAsScrollable()) {
|
||||
// The session history code might restore a scroll position when navigating
|
||||
// back or forward, and we don't want to clobber that.
|
||||
nsPoint pos = shell->GetRootScrollFrameAsScrollable()->GetScrollPosition();
|
||||
mLastRootMetrics.SetScrollOffset(CSSPoint::FromAppUnits(pos));
|
||||
} else {
|
||||
mLastRootMetrics.SetScrollOffset(CSSPoint(0, 0));
|
||||
}
|
||||
|
||||
TABC_LOG("After InitializeRootMetrics, mLastRootMetrics is %s\n",
|
||||
Stringify(mLastRootMetrics).c_str());
|
||||
}
|
||||
|
||||
void
|
||||
TabChildBase::SetCSSViewport(const CSSSize& aSize)
|
||||
{
|
||||
mOldViewportSize = aSize;
|
||||
TABC_LOG("Setting CSS viewport to %s\n", Stringify(aSize).c_str());
|
||||
|
||||
if (mContentDocumentIsDisplayed) {
|
||||
if (nsCOMPtr<nsIPresShell> shell = GetPresShell()) {
|
||||
nsLayoutUtils::SetCSSViewport(shell, aSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CSSSize
|
||||
TabChildBase::GetPageSize(nsCOMPtr<nsIDocument> aDocument, const CSSSize& aViewport)
|
||||
{
|
||||
nsCOMPtr<Element> htmlDOMElement = aDocument->GetHtmlElement();
|
||||
HTMLBodyElement* bodyDOMElement = aDocument->GetBodyElement();
|
||||
|
||||
if (!htmlDOMElement && !bodyDOMElement) {
|
||||
// For non-HTML content (e.g. SVG), just assume page size == viewport size.
|
||||
return aViewport;
|
||||
}
|
||||
|
||||
int32_t htmlWidth = 0, htmlHeight = 0;
|
||||
if (htmlDOMElement) {
|
||||
htmlWidth = htmlDOMElement->ScrollWidth();
|
||||
htmlHeight = htmlDOMElement->ScrollHeight();
|
||||
}
|
||||
int32_t bodyWidth = 0, bodyHeight = 0;
|
||||
if (bodyDOMElement) {
|
||||
bodyWidth = bodyDOMElement->ScrollWidth();
|
||||
bodyHeight = bodyDOMElement->ScrollHeight();
|
||||
}
|
||||
return CSSSize(std::max(htmlWidth, bodyWidth),
|
||||
std::max(htmlHeight, bodyHeight));
|
||||
}
|
||||
|
||||
bool
|
||||
TabChildBase::HandlePossibleViewportChange(const ScreenIntSize& aOldScreenSize)
|
||||
{
|
||||
PuppetWidget* widget = WebWidget();
|
||||
if (!widget || !widget->AsyncPanZoomEnabled()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TABC_LOG("HandlePossibleViewportChange aOldScreenSize=%s mInnerSize=%s\n",
|
||||
Stringify(aOldScreenSize).c_str(), Stringify(GetInnerSize()).c_str());
|
||||
|
||||
nsCOMPtr<nsIDocument> document(GetDocument());
|
||||
if (!document) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsViewportInfo viewportInfo = nsContentUtils::GetViewportInfo(document, GetInnerSize());
|
||||
uint32_t presShellId = 0;
|
||||
mozilla::layers::FrameMetrics::ViewID viewId = FrameMetrics::NULL_SCROLL_ID;
|
||||
APZCCallbackHelper::GetOrCreateScrollIdentifiers(
|
||||
document->GetDocumentElement(), &presShellId, &viewId);
|
||||
|
||||
float screenW = GetInnerSize().width;
|
||||
float screenH = GetInnerSize().height;
|
||||
CSSSize viewport(viewportInfo.GetSize());
|
||||
|
||||
// We're not being displayed in any way; don't bother doing anything because
|
||||
// that will just confuse future adjustments.
|
||||
if (!screenW || !screenH) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TABC_LOG("HandlePossibleViewportChange mOldViewportSize=%s viewport=%s\n",
|
||||
Stringify(mOldViewportSize).c_str(), Stringify(viewport).c_str());
|
||||
CSSSize oldBrowserSize = mOldViewportSize;
|
||||
mLastRootMetrics.SetViewport(CSSRect(
|
||||
mLastRootMetrics.GetViewport().TopLeft(), viewport));
|
||||
if (oldBrowserSize == CSSSize()) {
|
||||
oldBrowserSize = kDefaultViewportSize;
|
||||
}
|
||||
SetCSSViewport(viewport);
|
||||
|
||||
// If this page has not been painted yet, then this must be getting run
|
||||
// because a meta-viewport element was added (via the DOMMetaAdded handler).
|
||||
// in this case, we should not do anything that forces a reflow (see bug
|
||||
// 759678) such as requesting the page size or sending a viewport update. this
|
||||
// code will get run again in the before-first-paint handler and that point we
|
||||
// will run though all of it. the reason we even bother executing up to this
|
||||
// point on the DOMMetaAdded handler is so that scripts that use
|
||||
// window.innerWidth before they are painted have a correct value (bug
|
||||
// 771575).
|
||||
if (!mContentDocumentIsDisplayed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ScreenIntSize oldScreenSize = aOldScreenSize;
|
||||
if (oldScreenSize == ScreenIntSize()) {
|
||||
oldScreenSize = GetInnerSize();
|
||||
}
|
||||
|
||||
FrameMetrics metrics(mLastRootMetrics);
|
||||
metrics.SetViewport(CSSRect(CSSPoint(), viewport));
|
||||
|
||||
// Calculate the composition bounds based on the inner size, excluding the sizes
|
||||
// of the scrollbars if they are not overlay scrollbars.
|
||||
ScreenSize compositionSize(GetInnerSize());
|
||||
nsCOMPtr<nsIPresShell> shell = GetPresShell();
|
||||
if (shell) {
|
||||
nsMargin scrollbarsAppUnits =
|
||||
nsLayoutUtils::ScrollbarAreaToExcludeFromCompositionBoundsFor(shell->GetRootScrollFrame());
|
||||
// Scrollbars are not subject to scaling, so CSS pixels = screen pixels for them.
|
||||
ScreenMargin scrollbars = CSSMargin::FromAppUnits(scrollbarsAppUnits)
|
||||
* CSSToScreenScale(1.0f);
|
||||
compositionSize.width -= scrollbars.LeftRight();
|
||||
compositionSize.height -= scrollbars.TopBottom();
|
||||
}
|
||||
|
||||
metrics.SetCompositionBounds(ParentLayerRect(
|
||||
ParentLayerPoint(),
|
||||
ParentLayerSize(
|
||||
ViewAs<ParentLayerPixel>(GetInnerSize(),
|
||||
PixelCastJustification::ScreenIsParentLayerForRoot))));
|
||||
metrics.SetRootCompositionSize(
|
||||
ScreenSize(compositionSize) * ScreenToLayoutDeviceScale(1.0f) / metrics.GetDevPixelsPerCSSPixel());
|
||||
|
||||
// This change to the zoom accounts for all types of changes I can conceive:
|
||||
// 1. screen size changes, CSS viewport does not (pages with no meta viewport
|
||||
// or a fixed size viewport)
|
||||
// 2. screen size changes, CSS viewport also does (pages with a device-width
|
||||
// viewport)
|
||||
// 3. screen size remains constant, but CSS viewport changes (meta viewport
|
||||
// tag is added or removed)
|
||||
// 4. neither screen size nor CSS viewport changes
|
||||
//
|
||||
// In all of these cases, we maintain how much actual content is visible
|
||||
// within the screen width. Note that "actual content" may be different with
|
||||
// respect to CSS pixels because of the CSS viewport size changing.
|
||||
CSSToScreenScale oldIntrinsicScale = CalculateIntrinsicScale(oldScreenSize, oldBrowserSize);
|
||||
CSSToScreenScale newIntrinsicScale = CalculateIntrinsicScale(GetInnerSize(), viewport);
|
||||
metrics.ZoomBy(newIntrinsicScale.scale / oldIntrinsicScale.scale);
|
||||
|
||||
// Changing the zoom when we're not doing a first paint will get ignored
|
||||
// by AsyncPanZoomController and causes a blurry flash.
|
||||
bool isFirstPaint = true;
|
||||
if (shell) {
|
||||
isFirstPaint = shell->GetIsFirstPaint();
|
||||
}
|
||||
if (isFirstPaint) {
|
||||
// FIXME/bug 799585(?): GetViewportInfo() returns a defaultZoom of
|
||||
// 0.0 to mean "did not calculate a zoom". In that case, we default
|
||||
// it to the intrinsic scale.
|
||||
if (viewportInfo.GetDefaultZoom().scale < 0.01f) {
|
||||
viewportInfo.SetDefaultZoom(newIntrinsicScale);
|
||||
}
|
||||
|
||||
CSSToScreenScale defaultZoom = viewportInfo.GetDefaultZoom();
|
||||
MOZ_ASSERT(viewportInfo.GetMinZoom() <= defaultZoom &&
|
||||
defaultZoom <= viewportInfo.GetMaxZoom());
|
||||
metrics.SetZoom(CSSToParentLayerScale2D(ConvertScaleForRoot(defaultZoom)));
|
||||
|
||||
metrics.SetPresShellId(presShellId);
|
||||
metrics.SetScrollId(viewId);
|
||||
}
|
||||
|
||||
if (shell) {
|
||||
if (nsPresContext* context = shell->GetPresContext()) {
|
||||
metrics.SetDevPixelsPerCSSPixel(CSSToLayoutDeviceScale(
|
||||
(float)nsPresContext::AppUnitsPerCSSPixel() / context->AppUnitsPerDevPixel()));
|
||||
}
|
||||
}
|
||||
|
||||
metrics.SetCumulativeResolution(metrics.GetZoom()
|
||||
/ metrics.GetDevPixelsPerCSSPixel()
|
||||
* ParentLayerToLayerScale(1));
|
||||
// This is the root layer, so the cumulative resolution is the same
|
||||
// as the resolution.
|
||||
metrics.SetPresShellResolution(metrics.GetCumulativeResolution().ToScaleFactor().scale);
|
||||
if (shell) {
|
||||
nsLayoutUtils::SetResolutionAndScaleTo(shell, metrics.GetPresShellResolution());
|
||||
nsLayoutUtils::SetScrollPositionClampingScrollPortSize(shell,
|
||||
metrics.CalculateCompositedSizeInCssPixels());
|
||||
}
|
||||
|
||||
// The call to GetPageSize forces a resize event to content, so we need to
|
||||
// make sure that we have the right CSS viewport and
|
||||
// scrollPositionClampingScrollPortSize set up before that happens.
|
||||
|
||||
CSSSize pageSize = GetPageSize(document, viewport);
|
||||
if (!pageSize.width) {
|
||||
// Return early rather than divide by 0.
|
||||
return false;
|
||||
}
|
||||
metrics.SetScrollableRect(CSSRect(CSSPoint(), pageSize));
|
||||
|
||||
// Calculate a display port _after_ having a scrollable rect because the
|
||||
// display port is clamped to the scrollable rect.
|
||||
metrics.SetDisplayPortMargins(APZCTreeManager::CalculatePendingDisplayPort(
|
||||
// The page must have been refreshed in some way such as a new document or
|
||||
// new CSS viewport, so we know that there's no velocity, acceleration, and
|
||||
// we have no idea how long painting will take.
|
||||
metrics, ParentLayerPoint(0.0f, 0.0f), 0.0));
|
||||
metrics.SetUseDisplayPortMargins();
|
||||
|
||||
// Force a repaint with these metrics. This, among other things, sets the
|
||||
// displayport, so we start with async painting.
|
||||
mLastRootMetrics = ProcessUpdateFrame(metrics);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDOMWindowUtils>
|
||||
TabChildBase::GetDOMWindowUtils()
|
||||
{
|
||||
nsCOMPtr<nsPIDOMWindow> window = do_GetInterface(WebNavigation());
|
||||
nsCOMPtr<nsIDOMWindowUtils> utils = do_GetInterface(window);
|
||||
return utils.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<nsIDocument>
|
||||
TabChildBase::GetDocument() const
|
||||
{
|
||||
|
@ -535,7 +260,7 @@ TabChildBase::UpdateFrameHandler(const FrameMetrics& aFrameMetrics)
|
|||
// Guard against stale updates (updates meant for a pres shell which
|
||||
// has since been torn down and destroyed).
|
||||
if (aFrameMetrics.GetPresShellId() == shell->GetPresShellId()) {
|
||||
mLastRootMetrics = ProcessUpdateFrame(aFrameMetrics);
|
||||
ProcessUpdateFrame(aFrameMetrics);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -549,11 +274,11 @@ TabChildBase::UpdateFrameHandler(const FrameMetrics& aFrameMetrics)
|
|||
return true;
|
||||
}
|
||||
|
||||
FrameMetrics
|
||||
void
|
||||
TabChildBase::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics)
|
||||
{
|
||||
if (!mGlobal || !mTabChildGlobal) {
|
||||
return aFrameMetrics;
|
||||
return;
|
||||
}
|
||||
|
||||
FrameMetrics newMetrics = aFrameMetrics;
|
||||
|
@ -591,7 +316,6 @@ TabChildBase::ProcessUpdateFrame(const FrameMetrics& aFrameMetrics)
|
|||
data.AppendLiteral(" }");
|
||||
|
||||
DispatchMessageManagerMessage(NS_LITERAL_STRING("Viewport:Change"), data);
|
||||
return newMetrics;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -909,22 +633,6 @@ TabChild::TabChild(nsIContentChild* aManager,
|
|||
}
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TabChild::HandleEvent(nsIDOMEvent* aEvent)
|
||||
{
|
||||
nsAutoString eventType;
|
||||
aEvent->GetType(eventType);
|
||||
if (eventType.EqualsLiteral("DOMMetaAdded")) {
|
||||
// This meta data may or may not have been a meta viewport tag. If it was,
|
||||
// we should handle it immediately.
|
||||
HandlePossibleViewportChange(GetInnerSize());
|
||||
} else if (eventType.EqualsLiteral("FullZoomChange")) {
|
||||
HandlePossibleViewportChange(GetInnerSize());
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TabChild::Observe(nsISupports *aSubject,
|
||||
const char *aTopic,
|
||||
|
@ -957,19 +665,7 @@ TabChild::Observe(nsISupports *aSubject,
|
|||
shell->SetIsFirstPaint(true);
|
||||
}
|
||||
|
||||
mContentDocumentIsDisplayed = true;
|
||||
|
||||
// In some cases before-first-paint gets called before
|
||||
// RecvUpdateDimensions is called and therefore before we have an
|
||||
// inner size value set. In such cases defer initializing the viewport
|
||||
// until we we get an inner size.
|
||||
if (HasValidInnerSize()) {
|
||||
InitializeRootMetrics();
|
||||
if (shell) {
|
||||
nsLayoutUtils::SetResolutionAndScaleTo(shell, mLastRootMetrics.GetPresShellResolution());
|
||||
}
|
||||
HandlePossibleViewportChange(GetInnerSize());
|
||||
}
|
||||
APZCCallbackHelper::InitializeRootDisplayport(shell);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1027,100 +723,6 @@ TabChild::Observe(nsISupports *aSubject,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TabChild::OnStateChange(nsIWebProgress* aWebProgress,
|
||||
nsIRequest* aRequest,
|
||||
uint32_t aStateFlags,
|
||||
nsresult aStatus)
|
||||
{
|
||||
NS_NOTREACHED("not implemented in TabChild");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TabChild::OnProgressChange(nsIWebProgress* aWebProgress,
|
||||
nsIRequest* aRequest,
|
||||
int32_t aCurSelfProgress,
|
||||
int32_t aMaxSelfProgress,
|
||||
int32_t aCurTotalProgress,
|
||||
int32_t aMaxTotalProgress)
|
||||
{
|
||||
NS_NOTREACHED("not implemented in TabChild");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TabChild::OnLocationChange(nsIWebProgress* aWebProgress,
|
||||
nsIRequest* aRequest,
|
||||
nsIURI *aLocation,
|
||||
uint32_t aFlags)
|
||||
{
|
||||
if (!AsyncPanZoomEnabled()) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMWindow> window;
|
||||
aWebProgress->GetDOMWindow(getter_AddRefs(window));
|
||||
if (!window) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> progressDoc;
|
||||
window->GetDocument(getter_AddRefs(progressDoc));
|
||||
if (!progressDoc) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIDOMDocument> domDoc;
|
||||
WebNavigation()->GetDocument(getter_AddRefs(domDoc));
|
||||
if (!domDoc || !SameCOMIdentity(domDoc, progressDoc)) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURIFixup> urifixup(do_GetService(NS_URIFIXUP_CONTRACTID));
|
||||
if (!urifixup) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIURI> exposableURI;
|
||||
urifixup->CreateExposableURI(aLocation, getter_AddRefs(exposableURI));
|
||||
if (!exposableURI) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
if (!(aFlags & nsIWebProgressListener::LOCATION_CHANGE_SAME_DOCUMENT)) {
|
||||
mContentDocumentIsDisplayed = false;
|
||||
} else if (mLastURI != nullptr) {
|
||||
bool exposableEqualsLast, exposableEqualsNew;
|
||||
exposableURI->Equals(mLastURI.get(), &exposableEqualsLast);
|
||||
exposableURI->Equals(aLocation, &exposableEqualsNew);
|
||||
if (exposableEqualsLast && !exposableEqualsNew) {
|
||||
mContentDocumentIsDisplayed = false;
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TabChild::OnStatusChange(nsIWebProgress* aWebProgress,
|
||||
nsIRequest* aRequest,
|
||||
nsresult aStatus,
|
||||
const char16_t* aMessage)
|
||||
{
|
||||
NS_NOTREACHED("not implemented in TabChild");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
TabChild::OnSecurityChange(nsIWebProgress* aWebProgress,
|
||||
nsIRequest* aRequest,
|
||||
uint32_t aState)
|
||||
{
|
||||
NS_NOTREACHED("not implemented in TabChild");
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
TabChild::DoUpdateZoomConstraints(const uint32_t& aPresShellId,
|
||||
const ViewID& aViewId,
|
||||
|
@ -1201,10 +803,6 @@ TabChild::Init()
|
|||
loadContext->SetRemoteTabs(
|
||||
mChromeFlags & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW);
|
||||
|
||||
nsCOMPtr<nsIWebProgress> webProgress = do_GetInterface(docShell);
|
||||
NS_ENSURE_TRUE(webProgress, NS_ERROR_FAILURE);
|
||||
webProgress->AddProgressListener(this, nsIWebProgress::NOTIFY_LOCATION);
|
||||
|
||||
// Few lines before, baseWindow->Create() will end up creating a new
|
||||
// window root in nsGlobalWindow::SetDocShell.
|
||||
// Then this chrome event handler, will be inherited to inner windows.
|
||||
|
@ -1249,8 +847,6 @@ NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(TabChild)
|
|||
NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChromeFocus)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIWindowProvider)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIDOMEventListener)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIWebProgressListener)
|
||||
NS_INTERFACE_MAP_ENTRY(nsITabChild)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIObserver)
|
||||
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
|
||||
|
@ -1651,12 +1247,6 @@ TabChild::ProvideWindowCommon(nsIDOMWindow* aOpener,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
TabChild::HasValidInnerSize()
|
||||
{
|
||||
return mHasValidInnerSize;
|
||||
}
|
||||
|
||||
void
|
||||
TabChild::DestroyWindow()
|
||||
{
|
||||
|
@ -2116,40 +1706,25 @@ TabChild::RecvUpdateDimensions(const CSSRect& rect, const CSSSize& size,
|
|||
mUnscaledOuterRect = rect;
|
||||
mChromeDisp = chromeDisp;
|
||||
|
||||
bool initialSizing = !HasValidInnerSize()
|
||||
&& (size.width != 0 && size.height != 0);
|
||||
|
||||
mOrientation = orientation;
|
||||
ScreenIntSize oldScreenSize = GetInnerSize();
|
||||
SetUnscaledInnerSize(size);
|
||||
ScreenIntSize screenSize = GetInnerSize();
|
||||
bool sizeChanged = true;
|
||||
if (initialSizing) {
|
||||
if (!mHasValidInnerSize && size.width != 0 && size.height != 0) {
|
||||
mHasValidInnerSize = true;
|
||||
} else if (screenSize == oldScreenSize) {
|
||||
sizeChanged = false;
|
||||
}
|
||||
|
||||
ScreenIntSize screenSize = GetInnerSize();
|
||||
ScreenIntRect screenRect = GetOuterRect();
|
||||
mPuppetWidget->Resize(screenRect.x + chromeDisp.x,
|
||||
screenRect.y + chromeDisp.y,
|
||||
screenSize.width, screenSize.height, true);
|
||||
|
||||
// Set the size on the document viewer before we update the widget and
|
||||
// trigger a reflow. Otherwise the MobileViewportManager reads the stale
|
||||
// size from the content viewer when it computes a new CSS viewport.
|
||||
nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(WebNavigation());
|
||||
baseWin->SetPositionAndSize(0, 0, screenSize.width, screenSize.height,
|
||||
true);
|
||||
|
||||
if (initialSizing && mContentDocumentIsDisplayed) {
|
||||
// If this is the first time we're getting a valid inner size, and the
|
||||
// before-first-paint event has already been handled, then we need to set
|
||||
// up our default viewport here. See the corresponding call to
|
||||
// InitializeRootMetrics in the before-first-paint handler.
|
||||
InitializeRootMetrics();
|
||||
}
|
||||
|
||||
if (sizeChanged) {
|
||||
HandlePossibleViewportChange(oldScreenSize);
|
||||
}
|
||||
mPuppetWidget->Resize(screenRect.x + chromeDisp.x,
|
||||
screenRect.y + chromeDisp.y,
|
||||
screenSize.width, screenSize.height, true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -2990,9 +2565,6 @@ TabChild::InitTabChildGlobal(FrameScriptLoading aScriptLoading)
|
|||
nsCOMPtr<nsPIWindowRoot> root = do_QueryInterface(chromeHandler);
|
||||
NS_ENSURE_TRUE(root, false);
|
||||
root->SetParentTarget(scope);
|
||||
|
||||
chromeHandler->AddEventListener(NS_LITERAL_STRING("DOMMetaAdded"), this, false);
|
||||
chromeHandler->AddEventListener(NS_LITERAL_STRING("FullZoomChange"), this, false);
|
||||
}
|
||||
|
||||
if (aScriptLoading != DONT_LOAD_SCRIPTS && !mTriedBrowserInit) {
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include "nsIDocShell.h"
|
||||
#include "nsIInterfaceRequestorUtils.h"
|
||||
#include "nsFrameMessageManager.h"
|
||||
#include "nsIWebProgressListener.h"
|
||||
#include "nsIPresShell.h"
|
||||
#include "nsIScriptObjectPrincipal.h"
|
||||
#include "nsWeakReference.h"
|
||||
|
@ -183,12 +182,6 @@ public:
|
|||
virtual nsIWebNavigation* WebNavigation() const = 0;
|
||||
virtual PuppetWidget* WebWidget() = 0;
|
||||
nsIPrincipal* GetPrincipal() { return mPrincipal; }
|
||||
// Recalculates the display state, including the CSS
|
||||
// viewport. This should be called whenever we believe the
|
||||
// viewport data on a document may have changed. If it didn't
|
||||
// change, this function doesn't do anything. However, it should
|
||||
// not be called all the time as it is fairly expensive.
|
||||
bool HandlePossibleViewportChange(const ScreenIntSize& aOldScreenSize);
|
||||
virtual bool DoUpdateZoomConstraints(const uint32_t& aPresShellId,
|
||||
const mozilla::layers::FrameMetrics::ViewID& aViewId,
|
||||
const Maybe<mozilla::layers::ZoomConstraints>& aConstraints) = 0;
|
||||
|
@ -197,19 +190,12 @@ public:
|
|||
|
||||
protected:
|
||||
virtual ~TabChildBase();
|
||||
CSSSize GetPageSize(nsCOMPtr<nsIDocument> aDocument, const CSSSize& aViewport);
|
||||
|
||||
// Get the DOMWindowUtils for the top-level window in this tab.
|
||||
already_AddRefed<nsIDOMWindowUtils> GetDOMWindowUtils();
|
||||
// Get the Document for the top-level window in this tab.
|
||||
already_AddRefed<nsIDocument> GetDocument() const;
|
||||
// Get the pres-shell of the document for the top-level window in this tab.
|
||||
already_AddRefed<nsIPresShell> GetPresShell() const;
|
||||
|
||||
// Wrapper for nsIDOMWindowUtils.setCSSViewport(). This updates some state
|
||||
// variables local to this class before setting it.
|
||||
void SetCSSViewport(const CSSSize& aSize);
|
||||
|
||||
// Wraps up a JSON object as a structured clone and sends it to the browser
|
||||
// chrome script.
|
||||
//
|
||||
|
@ -218,17 +204,12 @@ protected:
|
|||
void DispatchMessageManagerMessage(const nsAString& aMessageName,
|
||||
const nsAString& aJSONData);
|
||||
|
||||
void InitializeRootMetrics();
|
||||
|
||||
mozilla::layers::FrameMetrics ProcessUpdateFrame(const mozilla::layers::FrameMetrics& aFrameMetrics);
|
||||
void ProcessUpdateFrame(const mozilla::layers::FrameMetrics& aFrameMetrics);
|
||||
|
||||
bool UpdateFrameHandler(const mozilla::layers::FrameMetrics& aFrameMetrics);
|
||||
|
||||
protected:
|
||||
CSSSize mOldViewportSize;
|
||||
bool mContentDocumentIsDisplayed;
|
||||
nsRefPtr<TabChildGlobal> mTabChildGlobal;
|
||||
mozilla::layers::FrameMetrics mLastRootMetrics;
|
||||
nsCOMPtr<nsIWebBrowserChrome3> mWebBrowserChrome;
|
||||
};
|
||||
|
||||
|
@ -239,8 +220,6 @@ class TabChild final : public TabChildBase,
|
|||
public nsIWebBrowserChromeFocus,
|
||||
public nsIInterfaceRequestor,
|
||||
public nsIWindowProvider,
|
||||
public nsIDOMEventListener,
|
||||
public nsIWebProgressListener,
|
||||
public nsSupportsWeakReference,
|
||||
public nsITabChild,
|
||||
public nsIObserver,
|
||||
|
@ -288,8 +267,6 @@ public:
|
|||
NS_DECL_NSIWEBBROWSERCHROMEFOCUS
|
||||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
NS_DECL_NSIWINDOWPROVIDER
|
||||
NS_DECL_NSIDOMEVENTLISTENER
|
||||
NS_DECL_NSIWEBPROGRESSLISTENER
|
||||
NS_DECL_NSITABCHILD
|
||||
NS_DECL_NSIOBSERVER
|
||||
NS_DECL_NSITOOLTIPLISTENER
|
||||
|
|
|
@ -65,7 +65,6 @@ nsIJSONDecodeDeprecatedWarning=nsIJSON.decode is deprecated. Please use JSON.pa
|
|||
nsIJSONEncodeDeprecatedWarning=nsIJSON.encode is deprecated. Please use JSON.stringify instead.
|
||||
nsIDOMWindowInternalWarning=Use of nsIDOMWindowInternal is deprecated. Use nsIDOMWindow instead.
|
||||
InputEncodingWarning=Use of inputEncoding is deprecated.
|
||||
FullScreenDeniedBlocked=Request for full-screen was denied because this domain has been blocked from full-screen by user.
|
||||
FullScreenDeniedDisabled=Request for full-screen was denied because full-screen API is disabled by user preference.
|
||||
FullScreenDeniedFocusedPlugin=Request for full-screen was denied because a windowed plugin is focused.
|
||||
FullScreenDeniedHidden=Request for full-screen was denied because the document is no longer visible.
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
Reset=Reset
|
||||
Submit=Submit Query
|
||||
Browse=Browse…
|
||||
ChooseFiles=Choose files…
|
||||
ChooseDirs=Choose folder…
|
||||
FileUpload=File Upload
|
||||
# LOCALIZATION NOTE (IsIndexPromptWithSpace): The last character of the string
|
||||
# should be a space (U+0020) in most locales. The prompt is followed by an
|
||||
|
|
|
@ -66,7 +66,6 @@
|
|||
#include "AppleMP3Reader.h"
|
||||
#endif
|
||||
#ifdef MOZ_FMP4
|
||||
#include "MP4Reader.h"
|
||||
#include "MP4Decoder.h"
|
||||
#include "MP4Demuxer.h"
|
||||
#endif
|
||||
|
@ -654,9 +653,7 @@ MediaDecoderReader* DecoderTraits::CreateReader(const nsACString& aType, Abstrac
|
|||
}
|
||||
#ifdef MOZ_FMP4
|
||||
if (IsMP4SupportedType(aType)) {
|
||||
decoderReader = Preferences::GetBool("media.format-reader.mp4", true) ?
|
||||
static_cast<MediaDecoderReader*>(new MediaFormatReader(aDecoder, new MP4Demuxer(aDecoder->GetResource()))) :
|
||||
static_cast<MediaDecoderReader*>(new MP4Reader(aDecoder));
|
||||
decoderReader = new MediaFormatReader(aDecoder, new MP4Demuxer(aDecoder->GetResource()));
|
||||
} else
|
||||
#endif
|
||||
if (IsMP3SupportedType(aType)) {
|
||||
|
|
|
@ -100,13 +100,6 @@ MediaShutdownManager::Observe(nsISupports *aSubjet,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
ShutdownMediaDecoder(nsRefPtrHashKey<MediaDecoder>* aEntry, void*)
|
||||
{
|
||||
aEntry->GetKey()->Shutdown();
|
||||
return PL_DHASH_REMOVE;
|
||||
}
|
||||
|
||||
void
|
||||
MediaShutdownManager::Shutdown()
|
||||
{
|
||||
|
@ -122,7 +115,10 @@ MediaShutdownManager::Shutdown()
|
|||
|
||||
// Iterate over the decoders and shut them down, and remove them from the
|
||||
// hashtable.
|
||||
mDecoders.EnumerateEntries(ShutdownMediaDecoder, nullptr);
|
||||
for (auto iter = mDecoders.Iter(); !iter.Done(); iter.Next()) {
|
||||
iter.Get()->GetKey()->Shutdown();
|
||||
iter.Remove();
|
||||
}
|
||||
|
||||
// Ensure all media shared thread pools are shutdown. This joins with all
|
||||
// threads in the state machine thread pool, the decoder thread pool, and
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "MP4Decoder.h"
|
||||
#include "MP4Reader.h"
|
||||
#include "MediaDecoderStateMachine.h"
|
||||
#include "MediaFormatReader.h"
|
||||
#include "MP4Demuxer.h"
|
||||
|
@ -42,11 +41,7 @@ MP4Decoder::MP4Decoder()
|
|||
|
||||
MediaDecoderStateMachine* MP4Decoder::CreateStateMachine()
|
||||
{
|
||||
bool useFormatDecoder =
|
||||
Preferences::GetBool("media.format-reader.mp4", true);
|
||||
nsRefPtr<MediaDecoderReader> reader = useFormatDecoder ?
|
||||
static_cast<MediaDecoderReader*>(new MediaFormatReader(this, new MP4Demuxer(GetResource()))) :
|
||||
static_cast<MediaDecoderReader*>(new MP4Reader(this));
|
||||
MediaDecoderReader* reader = new MediaFormatReader(this, new MP4Demuxer(GetResource()));
|
||||
|
||||
return new MediaDecoderStateMachine(this, reader);
|
||||
}
|
||||
|
@ -58,8 +53,8 @@ MP4Decoder::SetCDMProxy(CDMProxy* aProxy)
|
|||
nsresult rv = MediaDecoder::SetCDMProxy(aProxy);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
if (aProxy) {
|
||||
// The MP4Reader can't decrypt EME content until it has a CDMProxy,
|
||||
// and the CDMProxy knows the capabilities of the CDM. The MP4Reader
|
||||
// The MediaFormatReader can't decrypt EME content until it has a CDMProxy,
|
||||
// and the CDMProxy knows the capabilities of the CDM. The MediaFormatReader
|
||||
// remains in "waiting for resources" state until then.
|
||||
CDMCaps::AutoLock caps(aProxy->Capabilites());
|
||||
nsCOMPtr<nsIRunnable> task(
|
||||
|
|
|
@ -20,6 +20,14 @@
|
|||
#include "mp4_demuxer/AnnexB.h"
|
||||
#include "mp4_demuxer/H264.h"
|
||||
|
||||
PRLogModuleInfo* GetDemuxerLog() {
|
||||
static PRLogModuleInfo* log = nullptr;
|
||||
if (!log) {
|
||||
log = PR_NewLogModule("MP4Demuxer");
|
||||
}
|
||||
return log;
|
||||
}
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// Returns true if no SPS was found and search for it should continue.
|
||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -1,280 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim:set ts=2 sw=2 sts=2 et cindent: */
|
||||
/* 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/. */
|
||||
|
||||
#if !defined(MP4Reader_h_)
|
||||
#define MP4Reader_h_
|
||||
|
||||
#include "mozilla/Monitor.h"
|
||||
#include "mozilla/TaskQueue.h"
|
||||
|
||||
#include "MediaDecoderReader.h"
|
||||
#include "nsAutoPtr.h"
|
||||
#include "PlatformDecoderModule.h"
|
||||
#include "mp4_demuxer/mp4_demuxer.h"
|
||||
#include "demuxer/TrackDemuxer.h"
|
||||
|
||||
#include <deque>
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
typedef std::deque<nsRefPtr<MediaRawData>> MediaSampleQueue;
|
||||
|
||||
class MP4Stream;
|
||||
|
||||
class MP4Reader final : public MediaDecoderReader
|
||||
{
|
||||
typedef TrackInfo::TrackType TrackType;
|
||||
|
||||
public:
|
||||
explicit MP4Reader(AbstractMediaDecoder* aDecoder, TaskQueue* aBorrowedTaskQueue = nullptr);
|
||||
|
||||
virtual ~MP4Reader();
|
||||
|
||||
virtual nsresult Init(MediaDecoderReader* aCloneDonor) override;
|
||||
|
||||
virtual size_t SizeOfVideoQueueInFrames() override;
|
||||
virtual size_t SizeOfAudioQueueInFrames() override;
|
||||
|
||||
virtual nsRefPtr<VideoDataPromise>
|
||||
RequestVideoData(bool aSkipToNextKeyframe, int64_t aTimeThreshold, bool aForceDecodeAhead) override;
|
||||
|
||||
virtual nsRefPtr<AudioDataPromise> RequestAudioData() override;
|
||||
|
||||
virtual bool HasAudio() override;
|
||||
virtual bool HasVideo() override;
|
||||
|
||||
virtual nsresult ReadMetadata(MediaInfo* aInfo,
|
||||
MetadataTags** aTags) override;
|
||||
|
||||
virtual void ReadUpdatedMetadata(MediaInfo* aInfo) override;
|
||||
|
||||
virtual nsRefPtr<SeekPromise>
|
||||
Seek(int64_t aTime, int64_t aEndTime) override;
|
||||
|
||||
virtual bool IsMediaSeekable() override;
|
||||
|
||||
virtual int64_t GetEvictionOffset(double aTime) override;
|
||||
|
||||
protected:
|
||||
virtual void NotifyDataArrivedInternal(uint32_t aLength, int64_t aOffset) override;
|
||||
public:
|
||||
|
||||
virtual media::TimeIntervals GetBuffered() override;
|
||||
|
||||
// For Media Resource Management
|
||||
virtual void SetIdle() override;
|
||||
virtual void ReleaseMediaResources() override;
|
||||
virtual void SetSharedDecoderManager(SharedDecoderManager* aManager)
|
||||
override;
|
||||
|
||||
virtual nsresult ResetDecode() override;
|
||||
|
||||
virtual nsRefPtr<ShutdownPromise> Shutdown() override;
|
||||
|
||||
virtual bool IsAsync() const override { return true; }
|
||||
|
||||
virtual bool VideoIsHardwareAccelerated() const override;
|
||||
|
||||
virtual void DisableHardwareAcceleration() override;
|
||||
|
||||
private:
|
||||
|
||||
bool InitDemuxer();
|
||||
void ReturnOutput(MediaData* aData, TrackType aTrack);
|
||||
|
||||
bool EnsureDecodersSetup();
|
||||
|
||||
// Sends input to decoder for aTrack, and output to the state machine,
|
||||
// if necessary.
|
||||
void Update(TrackType aTrack);
|
||||
|
||||
// Enqueues a task to call Update(aTrack) on the decoder task queue.
|
||||
// Lock for corresponding track must be held.
|
||||
void ScheduleUpdate(TrackType aTrack);
|
||||
|
||||
void ExtractCryptoInitData(nsTArray<uint8_t>& aInitData);
|
||||
|
||||
// Initializes mLayersBackendType if possible.
|
||||
void InitLayersBackendType();
|
||||
|
||||
// Blocks until the demuxer produces an sample of specified type.
|
||||
// Returns nullptr on error on EOS. Caller must delete sample.
|
||||
already_AddRefed<MediaRawData> PopSample(TrackType aTrack);
|
||||
already_AddRefed<MediaRawData> PopSampleLocked(TrackType aTrack);
|
||||
|
||||
bool SkipVideoDemuxToNextKeyFrame(int64_t aTimeThreshold, uint32_t& parsed);
|
||||
|
||||
// DecoderCallback proxies the MediaDataDecoderCallback calls to these
|
||||
// functions.
|
||||
void Output(TrackType aType, MediaData* aSample);
|
||||
void InputExhausted(TrackType aTrack);
|
||||
void Error(TrackType aTrack);
|
||||
void Flush(TrackType aTrack);
|
||||
void DrainComplete(TrackType aTrack);
|
||||
void UpdateIndex();
|
||||
bool IsSupportedAudioMimeType(const nsACString& aMimeType);
|
||||
bool IsSupportedVideoMimeType(const nsACString& aMimeType);
|
||||
virtual bool IsWaitingOnCDMResource() override;
|
||||
|
||||
mp4_demuxer::Microseconds GetNextKeyframeTime();
|
||||
bool ShouldSkip(bool aSkipToNextKeyframe, int64_t aTimeThreshold);
|
||||
|
||||
size_t SizeOfQueue(TrackType aTrack);
|
||||
|
||||
nsRefPtr<MP4Stream> mStream;
|
||||
nsRefPtr<mp4_demuxer::MP4Demuxer> mDemuxer;
|
||||
nsRefPtr<PlatformDecoderModule> mPlatform;
|
||||
mp4_demuxer::CryptoFile mCrypto;
|
||||
|
||||
class DecoderCallback : public MediaDataDecoderCallback {
|
||||
public:
|
||||
DecoderCallback(MP4Reader* aReader, TrackType aType)
|
||||
: mReader(aReader)
|
||||
, mType(aType)
|
||||
{
|
||||
}
|
||||
virtual void Output(MediaData* aSample) override {
|
||||
mReader->Output(mType, aSample);
|
||||
}
|
||||
virtual void InputExhausted() override {
|
||||
mReader->InputExhausted(mType);
|
||||
}
|
||||
virtual void Error() override {
|
||||
mReader->Error(mType);
|
||||
}
|
||||
virtual void DrainComplete() override {
|
||||
mReader->DrainComplete(mType);
|
||||
}
|
||||
virtual void ReleaseMediaResources() override {
|
||||
mReader->ReleaseMediaResources();
|
||||
}
|
||||
virtual bool OnReaderTaskQueue() override {
|
||||
return mReader->OnTaskQueue();
|
||||
}
|
||||
private:
|
||||
MP4Reader* mReader;
|
||||
TrackType mType;
|
||||
};
|
||||
|
||||
struct DecoderData {
|
||||
DecoderData(MediaData::Type aType,
|
||||
uint32_t aDecodeAhead)
|
||||
: mType(aType)
|
||||
, mMonitor(aType == MediaData::AUDIO_DATA ? "MP4 audio decoder data"
|
||||
: "MP4 video decoder data")
|
||||
, mNumSamplesInput(0)
|
||||
, mNumSamplesOutput(0)
|
||||
, mDecodeAhead(aDecodeAhead)
|
||||
, mForceDecodeAhead(false)
|
||||
, mActive(false)
|
||||
, mInputExhausted(false)
|
||||
, mError(false)
|
||||
, mIsFlushing(false)
|
||||
, mUpdateScheduled(false)
|
||||
, mDemuxEOS(false)
|
||||
, mDrainComplete(false)
|
||||
, mDiscontinuity(false)
|
||||
{
|
||||
}
|
||||
|
||||
nsAutoPtr<TrackDemuxer> mTrackDemuxer;
|
||||
// The platform decoder.
|
||||
nsRefPtr<MediaDataDecoder> mDecoder;
|
||||
// TaskQueue on which decoder can choose to decode.
|
||||
// Only non-null up until the decoder is created.
|
||||
nsRefPtr<FlushableTaskQueue> mTaskQueue;
|
||||
// Callback that receives output and error notifications from the decoder.
|
||||
nsAutoPtr<DecoderCallback> mCallback;
|
||||
// Decoded samples returned my mDecoder awaiting being returned to
|
||||
// state machine upon request.
|
||||
nsTArray<nsRefPtr<MediaData> > mOutput;
|
||||
// Disambiguate Audio vs Video.
|
||||
MediaData::Type mType;
|
||||
|
||||
// These get overriden in the templated concrete class.
|
||||
virtual bool HasPromise() = 0;
|
||||
virtual void RejectPromise(MediaDecoderReader::NotDecodedReason aReason,
|
||||
const char* aMethodName) = 0;
|
||||
|
||||
// Monitor that protects all non-threadsafe state; the primitives
|
||||
// that follow.
|
||||
Monitor mMonitor;
|
||||
uint64_t mNumSamplesInput;
|
||||
uint64_t mNumSamplesOutput;
|
||||
uint32_t mDecodeAhead;
|
||||
bool mForceDecodeAhead;
|
||||
// Whether this stream exists in the media.
|
||||
bool mActive;
|
||||
bool mInputExhausted;
|
||||
bool mError;
|
||||
bool mIsFlushing;
|
||||
bool mUpdateScheduled;
|
||||
bool mDemuxEOS;
|
||||
bool mDrainComplete;
|
||||
bool mDiscontinuity;
|
||||
};
|
||||
|
||||
template<typename PromiseType>
|
||||
struct DecoderDataWithPromise : public DecoderData {
|
||||
DecoderDataWithPromise(MediaData::Type aType, uint32_t aDecodeAhead) :
|
||||
DecoderData(aType, aDecodeAhead)
|
||||
{
|
||||
mPromise.SetMonitor(&mMonitor);
|
||||
}
|
||||
|
||||
MozPromiseHolder<PromiseType> mPromise;
|
||||
|
||||
bool HasPromise() override { return !mPromise.IsEmpty(); }
|
||||
void RejectPromise(MediaDecoderReader::NotDecodedReason aReason,
|
||||
const char* aMethodName) override
|
||||
{
|
||||
mPromise.Reject(aReason, aMethodName);
|
||||
}
|
||||
};
|
||||
|
||||
DecoderDataWithPromise<AudioDataPromise> mAudio;
|
||||
DecoderDataWithPromise<VideoDataPromise> mVideo;
|
||||
|
||||
// Queued samples extracted by the demuxer, but not yet sent to the platform
|
||||
// decoder.
|
||||
nsRefPtr<MediaRawData> mQueuedVideoSample;
|
||||
|
||||
// Returns true when the decoder for this track needs input.
|
||||
// aDecoder.mMonitor must be locked.
|
||||
bool NeedInput(DecoderData& aDecoder);
|
||||
|
||||
// The last number of decoded output frames that we've reported to
|
||||
// MediaDecoder::NotifyDecoded(). We diff the number of output video
|
||||
// frames every time that DecodeVideoData() is called, and report the
|
||||
// delta there.
|
||||
uint64_t mLastReportedNumDecodedFrames;
|
||||
|
||||
DecoderData& GetDecoderData(TrackType aTrack);
|
||||
|
||||
layers::LayersBackend mLayersBackendType;
|
||||
|
||||
// For use with InvokeAndRetry as an already_refed can't be converted to bool
|
||||
nsRefPtr<MediaRawData> DemuxVideoSample();
|
||||
nsRefPtr<MediaRawData> DemuxAudioSample();
|
||||
|
||||
// True if we've read the streams' metadata.
|
||||
bool mDemuxerInitialized;
|
||||
|
||||
// True if we've gathered telemetry from an SPS.
|
||||
bool mFoundSPSForTelemetry;
|
||||
|
||||
// Synchronized by decoder monitor.
|
||||
bool mIsEncrypted;
|
||||
|
||||
bool mIndexReady;
|
||||
int64_t mLastSeenEnd;
|
||||
Monitor mDemuxerMonitor;
|
||||
nsRefPtr<SharedDecoderManager> mSharedDecoderManager;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif
|
|
@ -7,7 +7,7 @@
|
|||
#ifndef MP4_STREAM_H_
|
||||
#define MP4_STREAM_H_
|
||||
|
||||
#include "mp4_demuxer/mp4_demuxer.h"
|
||||
#include "mp4_demuxer/Stream.h"
|
||||
|
||||
#include "MediaResource.h"
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
EXPORTS += [
|
||||
'MP4Decoder.h',
|
||||
'MP4Demuxer.h',
|
||||
'MP4Reader.h',
|
||||
'MP4Stream.h',
|
||||
]
|
||||
|
||||
|
@ -18,7 +17,6 @@ UNIFIED_SOURCES += [
|
|||
|
||||
SOURCES += [
|
||||
'MP4Demuxer.cpp',
|
||||
'MP4Reader.cpp',
|
||||
]
|
||||
|
||||
FINAL_LIBRARY = 'xul'
|
||||
|
|
|
@ -70,21 +70,17 @@ GMPTimerParent::Shutdown()
|
|||
LOGD(("%s::%s: %p mIsOpen=%d", __CLASS__, __FUNCTION__, this, mIsOpen));
|
||||
|
||||
MOZ_ASSERT(mGMPThread == NS_GetCurrentThread());
|
||||
mTimers.EnumerateEntries(GMPTimerParent::CancelTimers, nullptr);
|
||||
|
||||
for (auto iter = mTimers.Iter(); !iter.Done(); iter.Next()) {
|
||||
Context* context = iter.Get()->GetKey();
|
||||
context->mTimer->Cancel();
|
||||
delete context;
|
||||
}
|
||||
|
||||
mTimers.Clear();
|
||||
mIsOpen = false;
|
||||
}
|
||||
|
||||
/*static */
|
||||
PLDHashOperator
|
||||
GMPTimerParent::CancelTimers(nsPtrHashKey<Context>* aContext, void* aClosure)
|
||||
{
|
||||
auto context = aContext->GetKey();
|
||||
context->mTimer->Cancel();
|
||||
delete context;
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
GMPTimerParent::ActorDestroy(ActorDestroyReason aWhy)
|
||||
{
|
||||
|
|
|
@ -47,9 +47,6 @@ private:
|
|||
uint32_t mId;
|
||||
};
|
||||
|
||||
static PLDHashOperator
|
||||
CancelTimers(nsPtrHashKey<Context>* aContext, void* aClosure);
|
||||
|
||||
void TimerExpired(Context* aContext);
|
||||
|
||||
nsTHashtable<nsPtrHashKey<Context>> mTimers;
|
||||
|
|
|
@ -4,32 +4,151 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "mp4_demuxer/mp4_demuxer.h"
|
||||
#include "MP4Demuxer.h"
|
||||
#include "MP4Stream.h"
|
||||
#include "MozPromise.h"
|
||||
#include "MediaDataDemuxer.h"
|
||||
#include "SharedThreadPool.h"
|
||||
#include "TaskQueue.h"
|
||||
#include "mozilla/ArrayUtils.h"
|
||||
#include "MockMediaResource.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mp4_demuxer;
|
||||
|
||||
class AutoTaskQueue;
|
||||
|
||||
#define DO_FAIL []()->void { EXPECT_TRUE(false); }
|
||||
|
||||
class MP4DemuxerBinding
|
||||
{
|
||||
public:
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MP4DemuxerBinding);
|
||||
|
||||
nsRefPtr<MockMediaResource> resource;
|
||||
Monitor mMonitor;
|
||||
nsRefPtr<MP4Demuxer> demuxer;
|
||||
nsRefPtr<MP4Demuxer> mDemuxer;
|
||||
nsRefPtr<TaskQueue> mTaskQueue;
|
||||
nsRefPtr<MediaTrackDemuxer> mAudioTrack;
|
||||
nsRefPtr<MediaTrackDemuxer> mVideoTrack;
|
||||
uint32_t mIndex;
|
||||
nsTArray<nsRefPtr<MediaRawData>> mSamples;
|
||||
nsTArray<int64_t> mKeyFrameTimecodes;
|
||||
MozPromiseHolder<GenericPromise> mCheckTrackKeyFramePromise;
|
||||
MozPromiseHolder<GenericPromise> mCheckTrackSamples;
|
||||
|
||||
explicit MP4DemuxerBinding(const char* aFileName = "dash_dashinit.mp4")
|
||||
: resource(new MockMediaResource(aFileName))
|
||||
, mMonitor("TestMP4Demuxer monitor")
|
||||
, demuxer(new MP4Demuxer(new MP4Stream(resource), &mMonitor))
|
||||
, mDemuxer(new MP4Demuxer(resource))
|
||||
, mTaskQueue(new TaskQueue(GetMediaThreadPool(MediaThreadType::PLAYBACK)))
|
||||
, mIndex(0)
|
||||
{
|
||||
EXPECT_EQ(NS_OK, resource->Open(nullptr));
|
||||
}
|
||||
|
||||
template<typename Function>
|
||||
void RunTestAndWait(const Function& aFunction)
|
||||
{
|
||||
Function func(aFunction);
|
||||
mDemuxer->Init()->Then(mTaskQueue, __func__, Move(func), DO_FAIL);
|
||||
mTaskQueue->AwaitShutdownAndIdle();
|
||||
}
|
||||
|
||||
nsRefPtr<GenericPromise>
|
||||
CheckTrackKeyFrame(MediaTrackDemuxer* aTrackDemuxer)
|
||||
{
|
||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||
|
||||
nsRefPtr<MediaTrackDemuxer> track = aTrackDemuxer;
|
||||
nsRefPtr<MP4DemuxerBinding> self = this;
|
||||
|
||||
int64_t time = -1;
|
||||
while (mIndex < mSamples.Length()) {
|
||||
uint32_t i = mIndex++;
|
||||
if (mSamples[i]->mKeyframe) {
|
||||
time = mSamples[i]->mTime;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nsRefPtr<GenericPromise> p = mCheckTrackKeyFramePromise.Ensure(__func__);
|
||||
|
||||
if (time == -1) {
|
||||
mCheckTrackKeyFramePromise.Resolve(true, __func__);
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
DispatchTask(
|
||||
[track, time, self] () {
|
||||
track->Seek(media::TimeUnit::FromMicroseconds(time))->Then(self->mTaskQueue, __func__,
|
||||
[track, time, self] () {
|
||||
track->GetSamples()->Then(self->mTaskQueue, __func__,
|
||||
[track, time, self] (nsRefPtr<MediaTrackDemuxer::SamplesHolder> aSamples) {
|
||||
EXPECT_EQ(time, aSamples->mSamples[0]->mTime);
|
||||
self->CheckTrackKeyFrame(track);
|
||||
},
|
||||
DO_FAIL
|
||||
);
|
||||
},
|
||||
DO_FAIL
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
nsRefPtr<GenericPromise>
|
||||
CheckTrackSamples(MediaTrackDemuxer* aTrackDemuxer)
|
||||
{
|
||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||
|
||||
nsRefPtr<MediaTrackDemuxer> track = aTrackDemuxer;
|
||||
nsRefPtr<MP4DemuxerBinding> self = this;
|
||||
|
||||
nsRefPtr<GenericPromise> p = mCheckTrackSamples.Ensure(__func__);
|
||||
|
||||
DispatchTask(
|
||||
[track, self] () {
|
||||
track->GetSamples()->Then(self->mTaskQueue, __func__,
|
||||
[track, self] (nsRefPtr<MediaTrackDemuxer::SamplesHolder> aSamples) {
|
||||
if (aSamples->mSamples.Length()) {
|
||||
self->mSamples.AppendElements(aSamples->mSamples);
|
||||
self->CheckTrackSamples(track);
|
||||
}
|
||||
},
|
||||
[self] (DemuxerFailureReason aReason) {
|
||||
if (aReason == DemuxerFailureReason::DEMUXER_ERROR) {
|
||||
EXPECT_TRUE(false);
|
||||
self->mCheckTrackSamples.Reject(NS_ERROR_FAILURE, __func__);
|
||||
} else if (aReason == DemuxerFailureReason::END_OF_STREAM) {
|
||||
EXPECT_TRUE(self->mSamples.Length() > 1);
|
||||
for (uint32_t i = 0; i < (self->mSamples.Length() - 1); i++) {
|
||||
EXPECT_LT(self->mSamples[i]->mTimecode, self->mSamples[i + 1]->mTimecode);
|
||||
if (self->mSamples[i]->mKeyframe) {
|
||||
self->mKeyFrameTimecodes.AppendElement(self->mSamples[i]->mTimecode);
|
||||
}
|
||||
}
|
||||
self->mCheckTrackSamples.Resolve(true, __func__);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
template<typename FunctionType>
|
||||
void
|
||||
DispatchTask(FunctionType aFun)
|
||||
{
|
||||
nsRefPtr<nsRunnable> r = NS_NewRunnableFunction(aFun);
|
||||
mTaskQueue->Dispatch(r.forget());
|
||||
}
|
||||
|
||||
virtual ~MP4DemuxerBinding()
|
||||
{
|
||||
}
|
||||
|
@ -37,30 +156,20 @@ private:
|
|||
|
||||
TEST(MP4Demuxer, Seek)
|
||||
{
|
||||
nsRefPtr<MP4DemuxerBinding> b = new MP4DemuxerBinding();
|
||||
MonitorAutoLock mon(b->mMonitor);
|
||||
MP4Demuxer* d = b->demuxer;
|
||||
nsRefPtr<MP4DemuxerBinding> binding = new MP4DemuxerBinding();
|
||||
|
||||
EXPECT_TRUE(d->Init());
|
||||
|
||||
nsTArray<nsRefPtr<MediaRawData>> samples;
|
||||
nsRefPtr<MediaRawData> sample;
|
||||
while (!!(sample = d->DemuxVideoSample())) {
|
||||
samples.AppendElement(sample);
|
||||
if (samples.Length() >= 2) {
|
||||
EXPECT_LT(samples[samples.Length() - 2]->mTimecode,
|
||||
samples[samples.Length() - 1]->mTimecode);
|
||||
}
|
||||
}
|
||||
Microseconds keyFrame = 0;
|
||||
for (size_t i = 0; i < samples.Length(); i++) {
|
||||
if (samples[i]->mKeyframe) {
|
||||
keyFrame = samples[i]->mTimecode;
|
||||
}
|
||||
d->SeekVideo(samples[i]->mTime);
|
||||
sample = d->DemuxVideoSample();
|
||||
EXPECT_EQ(keyFrame, sample->mTimecode);
|
||||
}
|
||||
binding->RunTestAndWait([binding] () {
|
||||
binding->mVideoTrack = binding->mDemuxer->GetTrackDemuxer(TrackInfo::kVideoTrack, 0);
|
||||
binding->CheckTrackSamples(binding->mVideoTrack)
|
||||
->Then(binding->mTaskQueue, __func__,
|
||||
[binding] () {
|
||||
binding->CheckTrackKeyFrame(binding->mVideoTrack)
|
||||
->Then(binding->mTaskQueue, __func__,
|
||||
[binding] () {
|
||||
binding->mTaskQueue->BeginShutdown();
|
||||
}, DO_FAIL);
|
||||
}, DO_FAIL);
|
||||
});
|
||||
}
|
||||
|
||||
static nsCString
|
||||
|
@ -87,14 +196,10 @@ ToCryptoString(const CryptoSample& aCrypto)
|
|||
return res;
|
||||
}
|
||||
|
||||
#ifndef XP_WIN // VC2013 doesn't support C++11 array initialization.
|
||||
|
||||
TEST(MP4Demuxer, CENCFrag)
|
||||
{
|
||||
nsRefPtr<MP4DemuxerBinding> b = new MP4DemuxerBinding("gizmo-frag.mp4");
|
||||
MonitorAutoLock mon(b->mMonitor);
|
||||
MP4Demuxer* d = b->demuxer;
|
||||
|
||||
EXPECT_TRUE(d->Init());
|
||||
|
||||
const char* video[] = {
|
||||
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000000000 5,684 5,16980",
|
||||
"1 16 7e571d037e571d037e571d037e571d03 00000000000000000000000000000450 5,1826",
|
||||
|
@ -158,13 +263,22 @@ TEST(MP4Demuxer, CENCFrag)
|
|||
"1 16 7e571d037e571d037e571d037e571d03 000000000000000000000000000019cd 5,2392",
|
||||
};
|
||||
|
||||
nsRefPtr<MediaRawData> sample;
|
||||
size_t i = 0;
|
||||
while (!!(sample = d->DemuxVideoSample())) {
|
||||
nsCString text = ToCryptoString(sample->mCrypto);
|
||||
EXPECT_STREQ(video[i++], text.get());
|
||||
}
|
||||
EXPECT_EQ(ArrayLength(video), i);
|
||||
nsRefPtr<MP4DemuxerBinding> binding = new MP4DemuxerBinding("gizmo-frag.mp4");
|
||||
|
||||
binding->RunTestAndWait([binding, video] () {
|
||||
// grab all video samples.
|
||||
binding->mVideoTrack = binding->mDemuxer->GetTrackDemuxer(TrackInfo::kVideoTrack, 0);
|
||||
binding->CheckTrackSamples(binding->mVideoTrack)
|
||||
->Then(binding->mTaskQueue, __func__,
|
||||
[binding, video] () {
|
||||
for (uint32_t i = 0; i < binding->mSamples.Length(); i++) {
|
||||
nsCString text = ToCryptoString(binding->mSamples[i]->mCrypto);
|
||||
EXPECT_STREQ(video[i++], text.get());
|
||||
}
|
||||
EXPECT_EQ(ArrayLength(video), binding->mSamples.Length());
|
||||
binding->mTaskQueue->BeginShutdown();
|
||||
}, DO_FAIL);
|
||||
});
|
||||
|
||||
const char* audio[] = {
|
||||
"1 16 7e571d047e571d047e571d047e571d04 00000000000000000000000000000000 0,281",
|
||||
|
@ -262,42 +376,52 @@ TEST(MP4Demuxer, CENCFrag)
|
|||
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000008cd 0,433",
|
||||
"1 16 7e571d047e571d047e571d047e571d04 000000000000000000000000000008e9 0,481",
|
||||
};
|
||||
nsRefPtr<MP4DemuxerBinding> audiobinding = new MP4DemuxerBinding("gizmo-frag.mp4");
|
||||
|
||||
i = 0;
|
||||
while (!!(sample = d->DemuxAudioSample())) {
|
||||
nsCString text = ToCryptoString(sample->mCrypto);
|
||||
EXPECT_STREQ(audio[i++], text.get());
|
||||
}
|
||||
EXPECT_EQ(ArrayLength(audio), i);
|
||||
audiobinding->RunTestAndWait([audiobinding, audio] () {
|
||||
// grab all audio samples.
|
||||
audiobinding->mAudioTrack = audiobinding->mDemuxer->GetTrackDemuxer(TrackInfo::kAudioTrack, 0);
|
||||
audiobinding->CheckTrackSamples(audiobinding->mAudioTrack)
|
||||
->Then(audiobinding->mTaskQueue, __func__,
|
||||
[audiobinding, audio] () {
|
||||
EXPECT_TRUE(audiobinding->mSamples.Length() > 1);
|
||||
for (uint32_t i = 0; i < audiobinding->mSamples.Length(); i++) {
|
||||
nsCString text = ToCryptoString(audiobinding->mSamples[i]->mCrypto);
|
||||
EXPECT_STREQ(audio[i++], text.get());
|
||||
}
|
||||
EXPECT_EQ(ArrayLength(audio), audiobinding->mSamples.Length());
|
||||
audiobinding->mTaskQueue->BeginShutdown();
|
||||
}, DO_FAIL);
|
||||
});
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
TEST(MP4Demuxer, GetNextKeyframe)
|
||||
{
|
||||
nsRefPtr<MP4DemuxerBinding> b = new MP4DemuxerBinding("gizmo-frag.mp4");
|
||||
MonitorAutoLock mon(b->mMonitor);
|
||||
MP4Demuxer* d = b->demuxer;
|
||||
nsRefPtr<MP4DemuxerBinding> binding = new MP4DemuxerBinding("gizmo-frag.mp4");
|
||||
|
||||
EXPECT_TRUE(d->Init());
|
||||
binding->RunTestAndWait([binding] () {
|
||||
// Insert a [0,end] buffered range, to simulate Moof's being buffered
|
||||
// via MSE.
|
||||
auto len = binding->resource->GetLength();
|
||||
binding->resource->MockAddBufferedRange(0, len);
|
||||
|
||||
// Insert a [0,end] buffered range, to simulate Moof's being buffered
|
||||
// via MSE.
|
||||
auto len = b->resource->GetLength();
|
||||
b->resource->MockAddBufferedRange(0, len);
|
||||
|
||||
// Rebuild the index so that it can be used to find the keyframes.
|
||||
nsTArray<MediaByteRange> ranges;
|
||||
EXPECT_TRUE(NS_SUCCEEDED(b->resource->GetCachedRanges(ranges)));
|
||||
d->UpdateIndex(ranges);
|
||||
|
||||
// gizmp-frag has two keyframes; one at dts=cts=0, and another at
|
||||
// dts=cts=1000000. Verify we get expected results.
|
||||
|
||||
nsRefPtr<MediaRawData> sample;
|
||||
size_t i = 0;
|
||||
const int64_t keyframe = 1000000;
|
||||
while (!!(sample = d->DemuxVideoSample())) {
|
||||
int64_t expected = (sample->mTimecode < keyframe) ? keyframe : -1;
|
||||
EXPECT_EQ(d->GetNextKeyframeTime(), expected);
|
||||
i++;
|
||||
}
|
||||
// gizmp-frag has two keyframes; one at dts=cts=0, and another at
|
||||
// dts=cts=1000000. Verify we get expected results.
|
||||
media::TimeUnit time;
|
||||
binding->mVideoTrack = binding->mDemuxer->GetTrackDemuxer(TrackInfo::kVideoTrack, 0);
|
||||
binding->mVideoTrack->Reset();
|
||||
binding->mVideoTrack->GetNextRandomAccessPoint(&time);
|
||||
EXPECT_EQ(time.ToMicroseconds(), 0);
|
||||
binding->mVideoTrack->GetSamples()->Then(binding->mTaskQueue, __func__,
|
||||
[binding] () {
|
||||
media::TimeUnit time;
|
||||
binding->mVideoTrack->GetNextRandomAccessPoint(&time);
|
||||
EXPECT_EQ(time.ToMicroseconds(), 1000000);
|
||||
binding->mTaskQueue->BeginShutdown();
|
||||
},
|
||||
DO_FAIL
|
||||
);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include "SharedDecoderManager.h"
|
||||
#include "MP4Decoder.h"
|
||||
#include "MP4Demuxer.h"
|
||||
#include "MP4Reader.h"
|
||||
#endif
|
||||
|
||||
#ifdef MOZ_WEBM
|
||||
|
@ -701,18 +700,15 @@ CreateReaderForType(const nsACString& aType, AbstractMediaDecoder* aDecoder,
|
|||
TaskQueue* aBorrowedTaskQueue)
|
||||
{
|
||||
#ifdef MOZ_FMP4
|
||||
// The MP4Reader that supports fragmented MP4 and uses
|
||||
// The MediaFormatReader that supports fragmented MP4 and uses
|
||||
// PlatformDecoderModules is hidden behind prefs for regular video
|
||||
// elements, but we always want to use it for MSE, so instantiate it
|
||||
// directly here.
|
||||
if ((aType.LowerCaseEqualsLiteral("video/mp4") ||
|
||||
aType.LowerCaseEqualsLiteral("audio/mp4")) &&
|
||||
MP4Decoder::IsEnabled() && aDecoder) {
|
||||
bool useFormatDecoder =
|
||||
Preferences::GetBool("media.mediasource.format-reader.mp4", true);
|
||||
MediaDecoderReader* reader = useFormatDecoder ?
|
||||
static_cast<MediaDecoderReader*>(new MediaFormatReader(aDecoder, new MP4Demuxer(aDecoder->GetResource()), aBorrowedTaskQueue)) :
|
||||
static_cast<MediaDecoderReader*>(new MP4Reader(aDecoder, aBorrowedTaskQueue));
|
||||
MediaDecoderReader* reader =
|
||||
new MediaFormatReader(aDecoder, new MP4Demuxer(aDecoder->GetResource()), aBorrowedTaskQueue);
|
||||
return reader;
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "AppleUtils.h"
|
||||
#include "MP4Reader.h"
|
||||
#include "MP4Decoder.h"
|
||||
#include "mp4_demuxer/Adts.h"
|
||||
#include "MediaInfo.h"
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
#include "PlatformDecoderModule.h"
|
||||
#include "mozilla/ReentrantMonitor.h"
|
||||
#include "MP4Reader.h"
|
||||
#include "MP4Decoder.h"
|
||||
#include "nsIThread.h"
|
||||
#include "ReorderQueue.h"
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include "PlatformDecoderModule.h"
|
||||
#include "FFmpegLibs.h"
|
||||
#include "mozilla/StaticMutex.h"
|
||||
#include "mp4_demuxer/mp4_demuxer.h"
|
||||
|
||||
namespace mozilla
|
||||
{
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#define WMFAudioOutputSource_h_
|
||||
|
||||
#include "WMF.h"
|
||||
#include "MP4Reader.h"
|
||||
#include "MFTDecoder.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "WMFMediaDataDecoder.h"
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
|
||||
|
||||
#include "WMF.h"
|
||||
#include "MP4Reader.h"
|
||||
#include "MFTDecoder.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "PlatformDecoderModule.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#define WMFVideoMFTManager_h_
|
||||
|
||||
#include "WMF.h"
|
||||
#include "MP4Reader.h"
|
||||
#include "MFTDecoder.h"
|
||||
#include "nsRect.h"
|
||||
#include "WMFMediaDataDecoder.h"
|
||||
|
|
|
@ -24,8 +24,6 @@
|
|||
PRLogModuleInfo* GetDemuxerLog();
|
||||
#define LOG(...) MOZ_LOG(GetDemuxerLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||
|
||||
using namespace mp4_demuxer;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
using layers::Image;
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include "PlatformDecoderModule.h"
|
||||
#include "mozilla/Monitor.h"
|
||||
|
||||
#include "mp4_demuxer/mp4_demuxer.h"
|
||||
#include "MediaInfo.h"
|
||||
#include "MediaData.h"
|
||||
|
||||
|
|
|
@ -1959,9 +1959,39 @@ struct CompareFilesByTime
|
|||
|
||||
} // namespace
|
||||
|
||||
bool
|
||||
nsPluginHost::ShouldAddPlugin(nsPluginTag* aPluginTag)
|
||||
{
|
||||
#if defined(XP_WIN) && (defined(__x86_64__) || defined(_M_X64))
|
||||
// On 64-bit windows, the only plugin we should load is flash. Use library
|
||||
// filename and MIME type to check.
|
||||
if (StringBeginsWith(aPluginTag->mFileName, NS_LITERAL_CSTRING("NPSWF"), nsCaseInsensitiveCStringComparator()) &&
|
||||
(aPluginTag->HasMimeType(NS_LITERAL_CSTRING("application/x-shockwave-flash")) ||
|
||||
aPluginTag->HasMimeType(NS_LITERAL_CSTRING("application/x-shockwave-flash-test")))) {
|
||||
return true;
|
||||
}
|
||||
// Accept the test plugin MIME types, so mochitests still work.
|
||||
if (aPluginTag->HasMimeType(NS_LITERAL_CSTRING("application/x-test")) ||
|
||||
aPluginTag->HasMimeType(NS_LITERAL_CSTRING("application/x-Second-Test")) ||
|
||||
aPluginTag->HasMimeType(NS_LITERAL_CSTRING("application/x-java-test"))) {
|
||||
return true;
|
||||
}
|
||||
#ifdef PLUGIN_LOGGING
|
||||
PLUGIN_LOG(PLUGIN_LOG_NORMAL,
|
||||
("ShouldAddPlugin : Ignoring non-flash plugin library %s\n", aPluginTag->mFileName.get()));
|
||||
#endif // PLUGIN_LOGGING
|
||||
return false;
|
||||
#else
|
||||
return true;
|
||||
#endif // defined(XP_WIN) && (defined(__x86_64__) || defined(_M_X64))
|
||||
}
|
||||
|
||||
void
|
||||
nsPluginHost::AddPluginTag(nsPluginTag* aPluginTag)
|
||||
{
|
||||
if (!ShouldAddPlugin(aPluginTag)) {
|
||||
return;
|
||||
}
|
||||
aPluginTag->mNext = mPlugins;
|
||||
mPlugins = aPluginTag;
|
||||
|
||||
|
@ -3119,6 +3149,11 @@ nsPluginHost::ReadPluginInfo()
|
|||
|
||||
MOZ_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_BASIC,
|
||||
("LoadCachedPluginsInfo : Loading Cached plugininfo for %s\n", tag->mFileName.get()));
|
||||
|
||||
if (!ShouldAddPlugin(tag)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
tag->mNext = mCachedPlugins;
|
||||
mCachedPlugins = tag;
|
||||
}
|
||||
|
|
|
@ -340,6 +340,10 @@ private:
|
|||
uint32_t ChromeEpochForContent();
|
||||
void SetChromeEpochForContent(uint32_t aEpoch);
|
||||
|
||||
// On certain platforms, we only want to load certain plugins. This function
|
||||
// centralizes loading rules.
|
||||
bool ShouldAddPlugin(nsPluginTag* aPluginTag);
|
||||
|
||||
nsRefPtr<nsPluginTag> mPlugins;
|
||||
nsRefPtr<nsPluginTag> mCachedPlugins;
|
||||
nsRefPtr<nsInvalidPluginTag> mInvalidPlugins;
|
||||
|
|
|
@ -3806,39 +3806,6 @@ PluginInstanceChild::PostChildAsyncCall(ChildAsyncCall* aTask)
|
|||
ProcessChild::message_loop()->PostTask(FROM_HERE, aTask);
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
InvalidateObject(DeletingObjectEntry* e, void* userArg)
|
||||
{
|
||||
NPObject* o = e->GetKey();
|
||||
if (!e->mDeleted && o->_class && o->_class->invalidate)
|
||||
o->_class->invalidate(o);
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
static PLDHashOperator
|
||||
DeleteObject(DeletingObjectEntry* e, void* userArg)
|
||||
{
|
||||
NPObject* o = e->GetKey();
|
||||
if (!e->mDeleted) {
|
||||
e->mDeleted = true;
|
||||
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
{
|
||||
int32_t refcnt = o->referenceCount;
|
||||
while (refcnt) {
|
||||
--refcnt;
|
||||
NS_LOG_RELEASE(o, refcnt, "NPObject");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
PluginModuleChild::DeallocNPObject(o);
|
||||
}
|
||||
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
void
|
||||
PluginInstanceChild::SwapSurfaces()
|
||||
{
|
||||
|
@ -3946,6 +3913,42 @@ PluginInstanceChild::ClearAllSurfaces()
|
|||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
InvalidateObjects(nsTHashtable<DeletingObjectEntry>& aEntries)
|
||||
{
|
||||
for (auto iter = aEntries.Iter(); !iter.Done(); iter.Next()) {
|
||||
DeletingObjectEntry* e = iter.Get();
|
||||
NPObject* o = e->GetKey();
|
||||
if (!e->mDeleted && o->_class && o->_class->invalidate) {
|
||||
o->_class->invalidate(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
DeleteObjects(nsTHashtable<DeletingObjectEntry>& aEntries)
|
||||
{
|
||||
for (auto iter = aEntries.Iter(); !iter.Done(); iter.Next()) {
|
||||
DeletingObjectEntry* e = iter.Get();
|
||||
NPObject* o = e->GetKey();
|
||||
if (!e->mDeleted) {
|
||||
e->mDeleted = true;
|
||||
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
{
|
||||
int32_t refcnt = o->referenceCount;
|
||||
while (refcnt) {
|
||||
--refcnt;
|
||||
NS_LOG_RELEASE(o, refcnt, "NPObject");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
PluginModuleChild::DeallocNPObject(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
PluginInstanceChild::Destroy()
|
||||
{
|
||||
|
@ -4000,8 +4003,8 @@ PluginInstanceChild::Destroy()
|
|||
mDeletingHash = new nsTHashtable<DeletingObjectEntry>;
|
||||
PluginScriptableObjectChild::NotifyOfInstanceShutdown(this);
|
||||
|
||||
mDeletingHash->EnumerateEntries(InvalidateObject, nullptr);
|
||||
mDeletingHash->EnumerateEntries(DeleteObject, nullptr);
|
||||
InvalidateObjects(*mDeletingHash);
|
||||
DeleteObjects(*mDeletingHash);
|
||||
|
||||
// Null out our cached actors as they should have been killed in the
|
||||
// PluginInstanceDestroyed call above.
|
||||
|
|
|
@ -1266,22 +1266,19 @@ PluginScriptableObjectChild::GetInstanceForNPObject(NPObject* aObject)
|
|||
return d->instance;
|
||||
}
|
||||
|
||||
/* static */ PLDHashOperator
|
||||
PluginScriptableObjectChild::CollectForInstance(NPObjectData* d, void* userArg)
|
||||
{
|
||||
PluginInstanceChild* instance = static_cast<PluginInstanceChild*>(userArg);
|
||||
if (d->instance == instance) {
|
||||
NPObject* o = d->GetKey();
|
||||
instance->mDeletingHash->PutEntry(o);
|
||||
}
|
||||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
PluginScriptableObjectChild::NotifyOfInstanceShutdown(PluginInstanceChild* aInstance)
|
||||
{
|
||||
AssertPluginThread();
|
||||
if (sObjectMap) {
|
||||
sObjectMap->EnumerateEntries(CollectForInstance, aInstance);
|
||||
if (!sObjectMap) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto iter = sObjectMap->Iter(); !iter.Done(); iter.Next()) {
|
||||
NPObjectData* d = iter.Get();
|
||||
if (d->instance == aInstance) {
|
||||
NPObject* o = d->GetKey();
|
||||
aInstance->mDeletingHash->PutEntry(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -329,8 +329,6 @@ private:
|
|||
PluginScriptableObjectChild* actor;
|
||||
};
|
||||
|
||||
static PLDHashOperator CollectForInstance(NPObjectData* d, void* userArg);
|
||||
|
||||
/**
|
||||
* mObjectMap contains all the currently active NPObjects (from NPN_CreateObject until the
|
||||
* final release/dealloc, whether or not an actor is currently associated with the object.
|
||||
|
|
|
@ -120,3 +120,5 @@ skip-if = os != "win"
|
|||
skip-if = toolkit == "cocoa"
|
||||
[test_zero_opacity.html]
|
||||
skip-if = e10s
|
||||
[test_bug1165981.html]
|
||||
skip-if = !(os == "win" && processor == "x86_64")
|
||||
|
|
|
@ -0,0 +1,64 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Bug 1165981 Test</title>
|
||||
|
||||
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript" src="utils.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
|
||||
<body onload="run()">
|
||||
<script class="testbody" type="application/javascript">
|
||||
"use strict";
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
ok(SpecialPowers.setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED, "Flash Test Plug-in"), "Should find allowed test flash plugin");
|
||||
ok(!SpecialPowers.setTestPluginEnabledState(SpecialPowers.Ci.nsIPluginTag.STATE_ENABLED, "Third Test Plug-in"), "Should not find disallowed plugin");
|
||||
|
||||
function findPlugin(pluginName) {
|
||||
for (var i = 0; i < navigator.plugins.length; i++) {
|
||||
var plugin = navigator.plugins[i];
|
||||
if (plugin.name === pluginName) {
|
||||
return plugin;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function findMimeType(mimeTypeType) {
|
||||
for (var i = 0; i < navigator.mimeTypes.length; i++) {
|
||||
var mimeType = navigator.mimeTypes[i];
|
||||
if (mimeType.type === mimeTypeType) {
|
||||
return mimeType;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function run() {
|
||||
var pluginElement = document.getElementById("plugin");
|
||||
is(pluginElement.identifierToStringTest("foo"), "foo", "Should be able to call a function provided by the plugin");
|
||||
|
||||
pluginElement = document.getElementById("disallowedPlugin");
|
||||
is(typeof pluginElement.identifierToStringTest, "undefined", "Should NOT be able to call a function on a disallowed plugin");
|
||||
|
||||
ok(navigator.plugins["Flash Test Plug-in"], "Should have queried a plugin named 'Test Plug-in'");
|
||||
ok(!navigator.plugins["Third Test Plug-in"], "Should NOT have queried a disallowed plugin named 'Third Test Plug-in'");
|
||||
|
||||
ok(findPlugin("Flash Test Plug-in"), "Should have found a plugin named 'Test Plug-in'");
|
||||
ok(!findPlugin("Third Test Plug-in"), "Should NOT found a disallowed plugin named 'Third Test Plug-in'");
|
||||
|
||||
ok(navigator.mimeTypes["application/x-shockwave-flash-test"], "Should have queried a MIME type named 'application/x-shockwave-flash-test'");
|
||||
ok(!navigator.mimeTypes["application/x-third-test"], "Should NOT have queried a disallowed type named 'application/x-third-test'");
|
||||
|
||||
ok(findMimeType("application/x-shockwave-flash-test"), "Should have found a MIME type named 'application/x-shockwave-flash-test'");
|
||||
ok(!findMimeType("application/x-third-test"), "Should NOT have found a disallowed MIME type named 'application/x-third-test'");
|
||||
|
||||
SimpleTest.finish();
|
||||
}
|
||||
</script>
|
||||
|
||||
<object id="plugin" type="application/x-shockwave-flash-test" width=200 height=200></object>
|
||||
<object id="disallowedPlugin" type="application/x-third-test" width=200 height=200></object>
|
||||
</body>
|
||||
</html>
|
|
@ -5,10 +5,10 @@
|
|||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
|
||||
plugin_file_names = Test.plugin SecondTest.plugin
|
||||
plugin_file_names = Test.plugin SecondTest.plugin ThirdTest.plugin npswftest.plugin
|
||||
addon_file_name = testaddon_$(TARGET_XPCOM_ABI).xpi
|
||||
else
|
||||
plugin_file_names = $(DLL_PREFIX)nptest$(DLL_SUFFIX) $(DLL_PREFIX)npsecondtest$(DLL_SUFFIX)
|
||||
plugin_file_names = $(DLL_PREFIX)nptest$(DLL_SUFFIX) $(DLL_PREFIX)npsecondtest$(DLL_SUFFIX) $(DLL_PREFIX)npthirdtest$(DLL_SUFFIX) $(DLL_PREFIX)npswftest$(DLL_SUFFIX)
|
||||
addon_file_name = testaddon.xpi
|
||||
endif
|
||||
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>English</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>libnpswftest.dylib</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>org.mozilla.FlashTestPlugin</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BRPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0.0.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>FLASHTEST</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0.0.0</string>
|
||||
<key>WebPluginName</key>
|
||||
<string>Flash Test Plug-in</string>
|
||||
<key>WebPluginDescription</key>
|
||||
<string>Flash plug-in for testing purposes.</string>
|
||||
<key>WebPluginMIMETypes</key>
|
||||
<dict>
|
||||
<key>application/x-shockwave-flash-test</key>
|
||||
<dict>
|
||||
<key>WebPluginExtensions</key>
|
||||
<array>
|
||||
<string>swf</string>
|
||||
</array>
|
||||
<key>WebPluginTypeDescription</key>
|
||||
<string>Flash test type</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
|
@ -0,0 +1,9 @@
|
|||
#
|
||||
# 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/.
|
||||
|
||||
RELATIVE_PATH=..
|
||||
COCOA_NAME=npswftest
|
||||
include @srcdir@/../testplugin.mk
|
||||
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче