author | Abdoulaye Oumar Ly <ablayelyfondou@gmail.com> |
Fri, 11 Oct 2019 14:30:28 +0000 | |
changeset 497279 | fcaa0242c20458b719aa356a4d988a97e4ad3a3b |
parent 497278 | 8b47aa47a640e1ac2bb3250d8d1ecbcce7b24a4b |
child 497280 | bd04c04797d0af75173fe7f8f63630ef5b7ec285 |
push id | 36681 |
push user | cbrindusan@mozilla.com |
push date | Fri, 11 Oct 2019 21:50:12 +0000 |
treeherder | mozilla-central@c5e6477c3a24 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | NeilDeakin, smaug |
bugs | 1505916 |
milestone | 71.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/browser/actors/DOMFullscreenChild.jsm +++ b/browser/actors/DOMFullscreenChild.jsm @@ -14,32 +14,44 @@ class DOMFullscreenChild extends JSWindo let windowUtils = window && window.windowUtils; if (!windowUtils) { return; } switch (aMessage.name) { case "DOMFullscreen:Entered": { - this._lastTransactionId = windowUtils.lastTransactionId; - if ( - !windowUtils.handleFullscreenRequests() && - !this.document.fullscreenElement - ) { - // If we don't actually have any pending fullscreen request - // to handle, neither we have been in fullscreen, tell the - // parent to just exit. - this.sendAsyncMessage("DOMFullscreen:Exit", {}); + let remoteFrameBC = aMessage.data.remoteFrameBC; + if (remoteFrameBC) { + let remoteFrame = remoteFrameBC.embedderElement; + this._isNotTheRequestSource = true; + windowUtils.remoteFrameFullscreenChanged(remoteFrame); + } else { + this._lastTransactionId = windowUtils.lastTransactionId; + if ( + !windowUtils.handleFullscreenRequests() && + !this.document.fullscreenElement + ) { + // If we don't actually have any pending fullscreen request + // to handle, neither we have been in fullscreen, tell the + // parent to just exit. + this.sendAsyncMessage("DOMFullscreen:Exit", {}); + } } break; } case "DOMFullscreen:CleanUp": { + let remoteFrameBC = aMessage.data.remoteFrameBC; + if (remoteFrameBC) { + this._isNotTheRequestSource = true; + } + // If we've exited fullscreen at this point, no need to record // transaction id or call exit fullscreen. This is especially - // important for non-e10s, since in that case, it is possible + // important for pre-e10s, since in that case, it is possible // that no more paint would be triggered after this point. if (this.document.fullscreenElement) { this._lastTransactionId = windowUtils.lastTransactionId; windowUtils.exitFullscreen(); } break; } case "DOMFullscreen:Painted": { @@ -62,30 +74,39 @@ class DOMFullscreenChild extends JSWindo break; } case "MozDOMFullscreen:Exit": { this.sendAsyncMessage("DOMFullscreen:Exit", {}); break; } case "MozDOMFullscreen:Entered": case "MozDOMFullscreen:Exited": { - let rootWindow = this.contentWindow.windowRoot; - rootWindow.addEventListener("MozAfterPaint", this); - if (!this.document || !this.document.fullscreenElement) { - // If we receive any fullscreen change event, and find we are - // actually not in fullscreen, also ask the parent to exit to - // ensure that the parent always exits fullscreen when we do. - this.sendAsyncMessage("DOMFullscreen:Exit", {}); + if (this._isNotTheRequestSource) { + // Fullscreen change event for a frame in the + // middle (content frame embedding the oop frame where the + // request comes from) + + delete this._isNotTheRequestSource; + this.sendAsyncMessage(aEvent.type.replace("Moz", ""), {}); + } else { + let rootWindow = this.contentWindow.windowRoot; + rootWindow.addEventListener("MozAfterPaint", this); + if (!this.document || !this.document.fullscreenElement) { + // If we receive any fullscreen change event, and find we are + // actually not in fullscreen, also ask the parent to exit to + // ensure that the parent always exits fullscreen when we do. + this.sendAsyncMessage("DOMFullscreen:Exit", {}); + } } break; } case "MozAfterPaint": { // Only send Painted signal after we actually finish painting // the transition for the fullscreen change. - // Note that this._lastTransactionId is not set when in non-e10s + // Note that this._lastTransactionId is not set when in pre-e10s // mode, so we need to check that explicitly. if ( !this._lastTransactionId || aEvent.transactionId > this._lastTransactionId ) { let rootWindow = this.contentWindow.windowRoot; rootWindow.removeEventListener("MozAfterPaint", this); this.sendAsyncMessage("DOMFullscreen:Painted", {});
--- a/browser/actors/DOMFullscreenParent.jsm +++ b/browser/actors/DOMFullscreenParent.jsm @@ -10,16 +10,17 @@ const { Services } = ChromeUtils.import( class DOMFullscreenParent extends JSWindowActorParent { receiveMessage(aMessage) { let topBrowsingContext = this.browsingContext.top; let browser = topBrowsingContext.embedderElement; 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.fullscreen) { window.PointerlockFsWarning.showFullScreen( @@ -73,16 +74,19 @@ class DOMFullscreenParent extends JSWind window.gXPInstallObserver.removeAllNotifications(browser); TelemetryStopwatch.start("FULLSCREEN_CHANGE_MS"); window.FullScreen.enterDomFullscreen(browser, this); break; } case "MozDOMFullscreen:Exited": TelemetryStopwatch.start("FULLSCREEN_CHANGE_MS"); + if (!this.requestOrigin) { + this.requestOrigin = this; + } window.FullScreen.cleanupDomFullscreen(this); this.removeListeners(window); break; } } addListeners(aWindow) { aWindow.addEventListener( @@ -99,9 +103,33 @@ class DOMFullscreenParent extends JSWind /* 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; + } + } }
--- a/browser/base/content/browser-fullScreenAndPointerLock.js +++ b/browser/base/content/browser-fullScreenAndPointerLock.js @@ -409,35 +409,43 @@ var FullScreen = { ) { this.exitDomFullScreen(); this._logWarningPermissionPromptFS("fullScreenCanceled"); } }, enterDomFullscreen(aBrowser, aActor) { if (!document.fullscreenElement) { + aActor.requestOrigin = null; return; } // If we have a current pointerlock warning shown then hide it // before transition. PointerlockFsWarning.close(); // If it is a remote browser, send a message to ask the content // to enter fullscreen state. We don't need to do so if it is an // in-process browser, since all related document should have // entered fullscreen state at this point. + // Additionally, in Fission world, we may need to notify the + // frames in the middle (content frames that embbed the oop iframe where + // the element requesting fullscreen lives) to enter fullscreen + // first. // This should be done before the active tab check below to ensure // that the content document handles the pending request. Doing so // before the check is fine since we also check the activeness of // the requesting document in content-side handling code. if (this._isRemoteBrowser(aBrowser)) { - aActor.sendAsyncMessage("DOMFullscreen:Entered", {}); + if ( + !this._sendMessageToTheRightContent(aActor, "DOMFullscreen:Entered") + ) { + return; + } } - // If we've received a fullscreen notification, we have to ensure that the // element that's requesting fullscreen belongs to the browser that's currently // active. If not, we exit fullscreen since the "full-screen document" isn't // actually visible now. if ( !aBrowser || gBrowser.selectedBrowser != aBrowser || // The top-level window has lost focus since the request to enter @@ -490,32 +498,83 @@ var FullScreen = { MousePosTracker.removeListener(this); document.removeEventListener("keypress", this._keyToggleCallback); document.removeEventListener("popupshown", this._setPopupOpen); document.removeEventListener("popuphidden", this._setPopupOpen); } }, cleanupDomFullscreen(aActor) { + if (!this._sendMessageToTheRightContent(aActor, "DOMFullscreen:CleanUp")) { + return; + } + PopupNotifications.panel.removeEventListener( "popupshowing", () => this._handlePermPromptShow(), true ); - aActor.sendAsyncMessage("DOMFullscreen:CleanUp", {}); PointerlockFsWarning.close(); gBrowser.tabContainer.removeEventListener( "TabSelect", this.exitDomFullScreen ); document.documentElement.removeAttribute("inDOMFullscreen"); }, + /** + * Search for the first ancestor of aActor that lives in a different process. + * If found, that ancestor is sent the message. Otherwise, the recipient should + * be the actor of the request origin. + * + * @param {JSWindowActorParent} aActor + * The actor that called this function. + * @param {String} message + * Message to be sent. + * + * @return {boolean} + * Return true if the message is sent to the request source + * or false otherwise. + */ + _sendMessageToTheRightContent(aActor, aMessage) { + let childBC = aActor.browsingContext; + let parentBC = childBC.parent; + + while (parentBC) { + let childPid = childBC.currentWindowGlobal.osPid; + let parentPid = parentBC.currentWindowGlobal.osPid; + + if (childPid == parentPid) { + childBC = parentBC; + parentBC = childBC.parent; + } else { + break; + } + } + + if (parentBC) { + let parentActor = parentBC.currentWindowGlobal.getActor("DOMFullscreen"); + parentActor.sendAsyncMessage(aMessage, { + remoteFrameBC: childBC, + }); + return false; + } + + // All content frames living outside the process where + // the element requesting fullscreen lives should + // have entered or exited fullscreen at this point. + // So let's notify the process where the original request + // comes from. + aActor.requestOrigin.sendAsyncMessage(aMessage, {}); + aActor.requestOrigin = null; + return true; + }, + _isRemoteBrowser(aBrowser) { return gMultiProcessBrowser && aBrowser.getAttribute("remote") == "true"; }, getMouseTargetRect() { return this._mouseTargetRect; },
--- a/dom/base/Document.cpp +++ b/dom/base/Document.cpp @@ -13458,17 +13458,17 @@ static bool IsInActiveTab(Document* aDoc return activeWindow == rootWin; } nsresult Document::RemoteFrameFullscreenChanged(Element* aFrameElement) { // Ensure the frame element is the fullscreen element in this document. // If the frame element is already the fullscreen element in this document, // this has no effect. auto request = FullscreenRequest::CreateForRemote(aFrameElement); - RequestFullscreen(std::move(request)); + RequestFullscreen(std::move(request), XRE_IsContentProcess()); return NS_OK; } nsresult Document::RemoteFrameFullscreenReverted() { UniquePtr<FullscreenExit> exit = FullscreenExit::CreateForRemote(this); RestorePreviousFullscreenState(std::move(exit)); return NS_OK; } @@ -13612,24 +13612,25 @@ static bool ShouldApplyFullscreenDirectl // because nsGlobalWindow::SetFullscreenInternal() will do nothing // if it is already in fullscreen. If we do not apply the state but // instead add it to the queue and wait for the window as normal, // we would get stuck. return true; } } -void Document::RequestFullscreen(UniquePtr<FullscreenRequest> aRequest) { +void Document::RequestFullscreen(UniquePtr<FullscreenRequest> aRequest, + bool applyFullScreenDirectly) { nsCOMPtr<nsPIDOMWindowOuter> rootWin = GetRootWindow(this); if (!rootWin) { aRequest->MayRejectPromise(); return; } - if (ShouldApplyFullscreenDirectly(this, rootWin)) { + if (applyFullScreenDirectly || ShouldApplyFullscreenDirectly(this, rootWin)) { ApplyFullscreen(std::move(aRequest)); return; } // Per spec only HTML, <svg>, and <math> should be allowed, but // we also need to allow XUL elements right now. Element* elem = aRequest->Element(); if (!elem->IsHTMLElement() && !elem->IsXULElement() &&
--- a/dom/base/Document.h +++ b/dom/base/Document.h @@ -2145,17 +2145,18 @@ class Document : public nsINode, // Do the "fullscreen element ready check" from the fullscreen spec. // It returns true if the given element is allowed to go into fullscreen. // It is responsive to dispatch "fullscreenerror" event when necessary. bool FullscreenElementReadyCheck(const FullscreenRequest&); // This is called asynchronously by Document::AsyncRequestFullscreen() // to move this document into fullscreen mode if allowed. - void RequestFullscreen(UniquePtr<FullscreenRequest> aRequest); + void RequestFullscreen(UniquePtr<FullscreenRequest> aRequest, + bool applyFullScreenDirectly = false); // Removes all elements from the fullscreen stack, removing full-scren // styles from the top element in the stack. void CleanupFullscreenState(); // Pushes aElement onto the fullscreen stack, and removes fullscreen styles // from the former fullscreen stack top, and its ancestors, and applies the // styles to aElement. aElement becomes the new "fullscreen element".