Merge m-c to fx-team, a=merge

This commit is contained in:
Wes Kocher 2015-07-21 16:13:57 -07:00
commit e9790127ae
178 changed files with 2409 additions and 3405 deletions

View File

@ -22,4 +22,4 @@
# changes to stick? As of bug 928195, this shouldn't be necessary! Please
# don't change CLOBBER for WebIDL changes any more.
Bug 1171344 requires a clobber due to renaming of a test file.
Bug 1164310 requires a clobber due to bug 1177844

View File

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

View File

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

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="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"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="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"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="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"/>

View File

@ -17,10 +17,10 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="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 -->

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="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"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="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"/>

View File

@ -19,7 +19,7 @@
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
<project name="gaia.git" path="gaia" remote="mozillaorg" revision="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"/>

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="e862ab9177af664f00b4522e2350f4cb13866d73">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="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"/>

View File

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

View File

@ -17,10 +17,10 @@
</project>
<project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
<project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
<project name="gaia" path="gaia" remote="mozillaorg" revision="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 -->

View File

@ -15,7 +15,7 @@
<project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
<copyfile dest="Makefile" src="core/root.mk"/>
</project>
<project name="gaia" path="gaia" remote="mozillaorg" revision="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"/>

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -186,8 +186,6 @@ let gPermissionObject = {
"indexedDB": {},
"fullscreen": {},
"pointerLock": {
exactHostMatch: true
},

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3117,10 +3117,6 @@ GetFullScreenError(nsIDocument* aDoc)
return "FullScreenDeniedNotInputDriven";
}
if (nsContentUtils::IsSitePermDeny(aDoc->NodePrincipal(), "fullscreen")) {
return "FullScreenDeniedBlocked";
}
return nullptr;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -87,7 +87,7 @@ Directory::GetName(nsAString& aRetval) const
aRetval.Truncate();
if (mPath.IsEmpty()) {
aRetval = mFileSystem->GetRootName();
mFileSystem->GetRootName(aRetval);
return;
}

View File

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

View File

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

View File

@ -122,7 +122,7 @@ FileSystemPermissionRequest::Run()
return NS_OK;
}
if (filesystem->IsTesting()) {
if (!filesystem->RequiresPermissionChecks()) {
Allow(JS::UndefinedHandleValue);
return NS_OK;
}

View File

@ -58,7 +58,7 @@ FileSystemRequestParent::Dispatch(ContentParent* aParent,
return false;
}
if (!mFileSystem->IsTesting()) {
if (mFileSystem->RequiresPermissionChecks()) {
// Check the content process permission.
nsCString access;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -622,6 +622,7 @@ child:
async StartProfiler(uint32_t aEntries, double aInterval, nsCString[] aFeatures,
nsCString[] aThreadNameFilters);
async StopProfiler();
async PauseProfiler(bool aPause);
async GatherProfile();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

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

View File

@ -47,9 +47,6 @@ private:
uint32_t mId;
};
static PLDHashOperator
CancelTimers(nsPtrHashKey<Context>* aContext, void* aClosure);
void TimerExpired(Context* aContext);
nsTHashtable<nsPtrHashKey<Context>> mTimers;

View File

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

View File

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

View File

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

View File

@ -9,7 +9,6 @@
#include "PlatformDecoderModule.h"
#include "mozilla/ReentrantMonitor.h"
#include "MP4Reader.h"
#include "MP4Decoder.h"
#include "nsIThread.h"
#include "ReorderQueue.h"

View File

@ -10,7 +10,6 @@
#include "PlatformDecoderModule.h"
#include "FFmpegLibs.h"
#include "mozilla/StaticMutex.h"
#include "mp4_demuxer/mp4_demuxer.h"
namespace mozilla
{

View File

@ -8,7 +8,6 @@
#define WMFAudioOutputSource_h_
#include "WMF.h"
#include "MP4Reader.h"
#include "MFTDecoder.h"
#include "mozilla/RefPtr.h"
#include "WMFMediaDataDecoder.h"

View File

@ -9,9 +9,9 @@
#include "WMF.h"
#include "MP4Reader.h"
#include "MFTDecoder.h"
#include "mozilla/RefPtr.h"
#include "PlatformDecoderModule.h"
namespace mozilla {

View File

@ -8,7 +8,6 @@
#define WMFVideoMFTManager_h_
#include "WMF.h"
#include "MP4Reader.h"
#include "MFTDecoder.h"
#include "nsRect.h"
#include "WMFMediaDataDecoder.h"

View File

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

View File

@ -13,7 +13,6 @@
#include "PlatformDecoderModule.h"
#include "mozilla/Monitor.h"
#include "mp4_demuxer/mp4_demuxer.h"
#include "MediaInfo.h"
#include "MediaData.h"

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

Some files were not shown because too many files have changed in this diff Show More