зеркало из https://github.com/mozilla/gecko-dev.git
211 строки
6.9 KiB
JavaScript
211 строки
6.9 KiB
JavaScript
/* vim: set ts=2 sw=2 sts=2 et tw=80: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
"use strict";
|
|
|
|
var EXPORTED_SYMBOLS = ["DOMFullscreenParent"];
|
|
|
|
const { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
|
|
|
|
class DOMFullscreenParent extends JSWindowActorParent {
|
|
waitingForChildFullscreen = false;
|
|
|
|
updateFullscreenWindowReference(aWindow) {
|
|
if (aWindow.document.documentElement.hasAttribute("inDOMFullscreen")) {
|
|
this._fullscreenWindow = aWindow;
|
|
} else {
|
|
delete this._fullscreenWindow;
|
|
}
|
|
}
|
|
|
|
didDestroy() {
|
|
let window = this._fullscreenWindow;
|
|
if (!window) {
|
|
return;
|
|
}
|
|
|
|
if (this.waitingForChildFullscreen) {
|
|
// We were killed while waiting for our DOMFullscreenChild
|
|
// to transition to fullscreen so we abort the entire
|
|
// fullscreen transition to prevent getting stuck in a
|
|
// partial fullscreen state. We need to go through the
|
|
// document since window.Fullscreen could be undefined
|
|
// at this point.
|
|
//
|
|
// This could reject if we're not currently in fullscreen
|
|
// so just ignore rejection.
|
|
window.document.exitFullscreen().catch(() => {});
|
|
return;
|
|
}
|
|
|
|
// Need to resume Chrome UI if the window is still in fullscreen UI
|
|
// to avoid the window stays in fullscreen problem. (See Bug 1620341)
|
|
if (window.document.documentElement.hasAttribute("inDOMFullscreen")) {
|
|
if (window.FullScreen) {
|
|
window.FullScreen.cleanupDomFullscreen(this);
|
|
}
|
|
if (window.windowUtils) {
|
|
window.windowUtils.remoteFrameFullscreenReverted();
|
|
}
|
|
}
|
|
this.updateFullscreenWindowReference(window);
|
|
}
|
|
|
|
receiveMessage(aMessage) {
|
|
let topBrowsingContext = this.browsingContext.top;
|
|
let browser = topBrowsingContext.embedderElement;
|
|
|
|
if (!browser) {
|
|
// No need to go further when the browser is not accessible anymore
|
|
// (which can happen when the tab is closed for instance),
|
|
return;
|
|
}
|
|
|
|
let window = browser.ownerGlobal;
|
|
switch (aMessage.name) {
|
|
case "DOMFullscreen:Request": {
|
|
this.requestOrigin = this;
|
|
this.addListeners(window);
|
|
window.windowUtils.remoteFrameFullscreenChanged(browser);
|
|
break;
|
|
}
|
|
case "DOMFullscreen:NewOrigin": {
|
|
// Don't show the warning if we've already exited fullscreen.
|
|
if (window.document.fullscreen) {
|
|
window.PointerlockFsWarning.showFullScreen(
|
|
aMessage.data.originNoSuffix
|
|
);
|
|
}
|
|
break;
|
|
}
|
|
case "DOMFullscreen:Entered": {
|
|
this.waitingForChildFullscreen = false;
|
|
window.FullScreen.enterDomFullscreen(browser, this);
|
|
this.updateFullscreenWindowReference(window);
|
|
break;
|
|
}
|
|
case "DOMFullscreen:Exit": {
|
|
window.windowUtils.remoteFrameFullscreenReverted();
|
|
break;
|
|
}
|
|
case "DOMFullscreen:Exited": {
|
|
window.FullScreen.cleanupDomFullscreen(this);
|
|
this.updateFullscreenWindowReference(window);
|
|
break;
|
|
}
|
|
case "DOMFullscreen:Painted": {
|
|
Services.obs.notifyObservers(window, "fullscreen-painted");
|
|
this.sendAsyncMessage("DOMFullscreen:Painted", {});
|
|
TelemetryStopwatch.finish("FULLSCREEN_CHANGE_MS");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
handleEvent(aEvent) {
|
|
let window = aEvent.currentTarget.ownerGlobal;
|
|
switch (aEvent.type) {
|
|
case "MozDOMFullscreen:Entered": {
|
|
// The event target is the element which requested the DOM
|
|
// fullscreen. If we were entering DOM fullscreen for a remote
|
|
// browser, the target would be the browser which was the parameter of
|
|
// `remoteFrameFullscreenChanged` call. If the fullscreen
|
|
// request was initiated from an in-process browser, we need
|
|
// to get its corresponding browser here.
|
|
let browser;
|
|
if (aEvent.target.ownerGlobal == window) {
|
|
browser = aEvent.target;
|
|
} else {
|
|
browser = aEvent.target.ownerGlobal.docShell.chromeEventHandler;
|
|
}
|
|
|
|
// Addon installation should be cancelled when entering fullscreen for security and usability reasons.
|
|
// Installation prompts in fullscreen can trick the user into installing unwanted addons.
|
|
// In fullscreen the notification box does not have a clear visual association with its parent anymore.
|
|
if (window.gXPInstallObserver) {
|
|
window.gXPInstallObserver.removeAllNotifications(browser);
|
|
}
|
|
|
|
TelemetryStopwatch.start("FULLSCREEN_CHANGE_MS");
|
|
window.FullScreen.enterDomFullscreen(browser, this);
|
|
this.updateFullscreenWindowReference(window);
|
|
break;
|
|
}
|
|
case "MozDOMFullscreen:Exited": {
|
|
TelemetryStopwatch.start("FULLSCREEN_CHANGE_MS");
|
|
|
|
// Make sure that the actor has not been destroyed before
|
|
// accessing its browsing context. Otherwise, a error may
|
|
// occur and hence cleanupDomFullscreen not executed, resulting
|
|
// in the browser window being in an unstable state.
|
|
// (Bug 1590138).
|
|
if (!this.hasBeenDestroyed() && !this.requestOrigin) {
|
|
this.requestOrigin = this;
|
|
}
|
|
window.FullScreen.cleanupDomFullscreen(this);
|
|
this.updateFullscreenWindowReference(window);
|
|
this.removeListeners(window);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
addListeners(aWindow) {
|
|
aWindow.addEventListener(
|
|
"MozDOMFullscreen:Entered",
|
|
this,
|
|
/* useCapture */ true,
|
|
/* wantsUntrusted */
|
|
false
|
|
);
|
|
aWindow.addEventListener(
|
|
"MozDOMFullscreen:Exited",
|
|
this,
|
|
/* useCapture */ true,
|
|
/* wantsUntrusted */ false
|
|
);
|
|
}
|
|
|
|
removeListeners(aWindow) {
|
|
aWindow.removeEventListener("MozDOMFullscreen:Entered", this, true);
|
|
aWindow.removeEventListener("MozDOMFullscreen:Exited", this, true);
|
|
}
|
|
|
|
/**
|
|
* Get the actor where the original fullscreen
|
|
* enter or exit request comes from.
|
|
*/
|
|
get requestOrigin() {
|
|
let requestOrigin = this.browsingContext.top.fullscreenRequestOrigin;
|
|
return requestOrigin && requestOrigin.get();
|
|
}
|
|
|
|
/**
|
|
* Store the actor where the original fullscreen
|
|
* enter or exit request comes from in the top level
|
|
* browsing context.
|
|
*/
|
|
set requestOrigin(aActor) {
|
|
if (aActor) {
|
|
this.browsingContext.top.fullscreenRequestOrigin = Cu.getWeakReference(
|
|
aActor
|
|
);
|
|
} else {
|
|
delete this.browsingContext.top.fullscreenRequestOrigin;
|
|
}
|
|
}
|
|
|
|
hasBeenDestroyed() {
|
|
// The 'didDestroy' callback is not always getting called.
|
|
// So we can't rely on it here. Instead, we will try to access
|
|
// the browsing context to judge wether the actor has
|
|
// been destroyed or not.
|
|
try {
|
|
return !this.browsingContext;
|
|
} catch {
|
|
return true;
|
|
}
|
|
}
|
|
}
|