1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
|
/* 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;
}
}
}
|