1 /* vim: set ts=2 sw=2 sts=2 et tw=80: */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 export class DOMFullscreenChild extends JSWindowActorChild {
7 receiveMessage(aMessage) {
8 let window = this.contentWindow;
9 let windowUtils = window?.windowUtils;
11 switch (aMessage.name) {
12 case "DOMFullscreen:Entered": {
14 // If we are not able to enter fullscreen, tell the parent to just
16 this.sendAsyncMessage("DOMFullscreen:Exit", {});
20 let remoteFrameBC = aMessage.data.remoteFrameBC;
22 let remoteFrame = remoteFrameBC.embedderElement;
24 // This could happen when the page navigate away and trigger a
25 // process switching during fullscreen transition, tell the parent
27 this.sendAsyncMessage("DOMFullscreen:Exit", {});
30 this._isNotTheRequestSource = true;
31 windowUtils.remoteFrameFullscreenChanged(remoteFrame);
33 this._waitForMozAfterPaint = true;
34 this._lastTransactionId = windowUtils.lastTransactionId;
36 !windowUtils.handleFullscreenRequests() &&
37 !this.document.fullscreenElement
39 // If we don't actually have any pending fullscreen request
40 // to handle, neither we have been in fullscreen, tell the
41 // parent to just exit.
42 this.sendAsyncMessage("DOMFullscreen:Exit", {});
47 case "DOMFullscreen:CleanUp": {
48 let isNotTheRequestSource = !!aMessage.data.remoteFrameBC;
49 // If we've exited fullscreen at this point, no need to record
50 // transaction id or call exit fullscreen. This is especially
51 // important for pre-e10s, since in that case, it is possible
52 // that no more paint would be triggered after this point.
53 if (this.document.fullscreenElement) {
54 this._isNotTheRequestSource = isNotTheRequestSource;
55 // Need to wait for the MozAfterPaint after exiting fullscreen if
56 // this is the request source.
57 this._waitForMozAfterPaint = !this._isNotTheRequestSource;
58 // windowUtils could be null if the associated window is not current
59 // active window. In this case, document must be in the process of
60 // exiting fullscreen, it is okay to not ask it to exit fullscreen.
62 this._lastTransactionId = windowUtils.lastTransactionId;
63 windowUtils.exitFullscreen();
65 } else if (isNotTheRequestSource) {
66 // If we are not the request source and have exited fullscreen, reply
67 // Exited to parent as parent is waiting for our reply.
68 this.sendAsyncMessage("DOMFullscreen:Exited", {});
70 // If we've already exited fullscreen, it is possible that no more
71 // paint would be triggered, so don't wait for MozAfterPaint.
72 // TODO: There might be some way to move this code around a bit to
73 // make it easier to follow. Somehow handle the "local" case in
74 // one place and the isNotTheRequestSource case after that.
75 this.sendAsyncMessage("DOMFullscreen:Painted", {});
79 case "DOMFullscreen:Painted": {
80 Services.obs.notifyObservers(window, "fullscreen-painted");
87 if (this.hasBeenDestroyed()) {
88 // Make sure that this actor is alive before going further because
89 // if it's not the case, any attempt to send a message or access
90 // objects such as 'contentWindow' will fail. (See bug 1590138)
94 switch (aEvent.type) {
95 case "MozDOMFullscreen:Request": {
96 this.sendAsyncMessage("DOMFullscreen:Request", {});
99 case "MozDOMFullscreen:NewOrigin": {
100 this.sendAsyncMessage("DOMFullscreen:NewOrigin", {
101 originNoSuffix: aEvent.target.nodePrincipal.originNoSuffix,
105 case "MozDOMFullscreen:Exit": {
106 this.sendAsyncMessage("DOMFullscreen:Exit", {});
109 case "MozDOMFullscreen:Entered":
110 case "MozDOMFullscreen:Exited": {
111 if (this._isNotTheRequestSource) {
112 // Fullscreen change event for a frame in the
113 // middle (content frame embedding the oop frame where the
114 // request comes from)
116 delete this._isNotTheRequestSource;
117 this.sendAsyncMessage(aEvent.type.replace("Moz", ""), {});
121 if (this._waitForMozAfterPaint) {
122 delete this._waitForMozAfterPaint;
123 this._listeningWindow = this.contentWindow.windowRoot;
124 this._listeningWindow.addEventListener("MozAfterPaint", this);
127 if (!this.document || !this.document.fullscreenElement) {
128 // If we receive any fullscreen change event, and find we are
129 // actually not in fullscreen, also ask the parent to exit to
130 // ensure that the parent always exits fullscreen when we do.
131 this.sendAsyncMessage("DOMFullscreen:Exit", {});
135 case "MozAfterPaint": {
136 // Only send Painted signal after we actually finish painting
137 // the transition for the fullscreen change.
138 // Note that this._lastTransactionId is not set when in pre-e10s
139 // mode, so we need to check that explicitly.
141 !this._lastTransactionId ||
142 aEvent.transactionId > this._lastTransactionId
144 this._listeningWindow.removeEventListener("MozAfterPaint", this);
145 delete this._listeningWindow;
146 this.sendAsyncMessage("DOMFullscreen:Painted", {});
154 // The 'didDestroy' callback is not always getting called.
155 // So we can't rely on it here. Instead, we will try to access
156 // the browsing context to judge wether the actor has
157 // been destroyed or not.
159 return !this.browsingContext;