From cd6132798674ccfe3b21adbf328c9b31a0ecba47 Mon Sep 17 00:00:00 2001 From: Chris Pearce Date: Tue, 31 Jul 2012 14:09:31 +1200 Subject: [PATCH] =?UTF-8?q?Bug=20684620=20-=20Implement=20cross=20process?= =?UTF-8?q?=20fullscreen=20API=20for=20B2G=20apps=20and=20web=20content.?= =?UTF-8?q?=20r=3Djlebar=20*=20*=20*=20Bug=20684620=20-=20Fix=20in-process?= =?UTF-8?q?=20fullscreen=20in=20B2G.=20r=3D=3F?= --- b2g/chrome/content/shell.js | 6 + content/base/public/nsIDocument.h | 25 +++- content/base/src/nsDocument.cpp | 155 ++++++++++++++++++-- content/base/src/nsDocument.h | 18 ++- content/base/src/nsFrameLoader.cpp | 1 + content/base/src/nsGenericElement.cpp | 11 +- dom/base/nsDOMWindowUtils.cpp | 34 +++++ dom/base/nsGlobalWindow.cpp | 36 +++++ dom/base/nsGlobalWindow.h | 4 + dom/base/nsPIDOMWindow.h | 6 + dom/browser-element/BrowserElementChild.js | 41 ++++++ dom/browser-element/BrowserElementParent.js | 47 +++++- dom/interfaces/base/nsIDOMWindowUtils.idl | 25 +++- 13 files changed, 380 insertions(+), 29 deletions(-) diff --git a/b2g/chrome/content/shell.js b/b2g/chrome/content/shell.js index 2b6a5295718f..23f9e8aea2dc 100644 --- a/b2g/chrome/content/shell.js +++ b/b2g/chrome/content/shell.js @@ -383,6 +383,12 @@ Services.obs.addObserver(function onSystemMessage(subject, topic, data) { }); }, 'system-messages-open-app', false); +Services.obs.addObserver(function(aSubject, aTopic, aData) { + shell.sendEvent(shell.contentBrowser.contentWindow, + "mozChromeEvent", { type: "fullscreenoriginchange", + fullscreenorigin: aData } ); +}, "fullscreen-origin-change", false); + (function Repl() { if (!Services.prefs.getBoolPref('b2g.remote-js.enabled')) { return; diff --git a/content/base/public/nsIDocument.h b/content/base/public/nsIDocument.h index 5a21833304d7..094e7f3bd76b 100644 --- a/content/base/public/nsIDocument.h +++ b/content/base/public/nsIDocument.h @@ -92,8 +92,8 @@ class Element; } // namespace mozilla #define NS_IDOCUMENT_IID \ -{ 0x8c6a1e62, 0xd5ad, 0x4297, \ - { 0xb9, 0x41, 0x64, 0x49, 0x22, 0x2e, 0xc4, 0xf0 } } +{ 0xbd70ee06, 0x2a7d, 0x4258, \ + { 0x86, 0x4b, 0xbd, 0x28, 0xad, 0x9f, 0xd1, 0x41 } } // Flag for AddStyleSheet(). #define NS_STYLESHEET_FROM_CATALOG (1 << 0) @@ -723,6 +723,27 @@ public: */ virtual void AsyncRequestFullScreen(Element* aElement) = 0; + /** + * Called when a frame in a child process has entered fullscreen or when a + * fullscreen frame in a child process changes to another origin. + * aFrameElement is the frame element which contains the child-process + * fullscreen document, and aNewOrigin is the origin of the new fullscreen + * document. + */ + virtual nsresult RemoteFrameFullscreenChanged(nsIDOMElement* aFrameElement, + const nsAString& aNewOrigin) = 0; + + /** + * Called when a frame in a remote child document has rolled back fullscreen + * so that all its fullscreen element stacks are empty; we must continue the + * rollback in this parent process' doc tree branch which is fullscreen. + * Note that only one branch of the document tree can have its documents in + * fullscreen state at one time. We're in inconsistent state if the a + * fullscreen document has a parent and that parent isn't fullscreen. We + * preserve this property across process boundaries. + */ + virtual nsresult RemoteFrameFullscreenReverted() = 0; + /** * Restores the previous full-screen element to full-screen status. If there * is no former full-screen element, this exits full-screen, moving the diff --git a/content/base/src/nsDocument.cpp b/content/base/src/nsDocument.cpp index 5ac384fdf04e..62c6ebc5e4b3 100644 --- a/content/base/src/nsDocument.cpp +++ b/content/base/src/nsDocument.cpp @@ -8499,7 +8499,7 @@ nsDocument::MozCancelFullScreen() } // Runnable to set window full-screen mode. Used as a script runner -// to ensure we only call nsGlobalWindow::SetFullScreen() when it's safe to +// to ensure we only call nsGlobalWindow::SetFullScreen() when it's safe to // run script. nsGlobalWindow::SetFullScreen() dispatches a synchronous event // (handled in chome code) which is unsafe to run if this is called in // nsGenericElement::UnbindFromTree(). @@ -8547,13 +8547,54 @@ nsIDocument::ExitFullScreen(bool aRunAsync) nsDocument::ExitFullScreen(); } +// Returns true if the document is a direct child of a cross process parent +// mozbrowser iframe. This is the case when the document has a null parent, +// and its DocShell reports that it is a browser frame. static bool -ResetFullScreen(nsIDocument* aDocument, void* aData) { +HasCrossProcessParent(nsIDocument* aDocument) +{ + if (XRE_GetProcessType() != GeckoProcessType_Content) { + return false; + } + if (aDocument->GetParentDocument() != nullptr) { + return false; + } + nsPIDOMWindow* win = aDocument->GetWindow(); + if (!win) { + return false; + } + nsCOMPtr docShell = win->GetDocShell(); + if (!docShell) { + return false; + } + bool isBrowserElement = false; + docShell->GetIsBrowserElement(&isBrowserElement); + return isBrowserElement; +} + +static bool +ResetFullScreen(nsIDocument* aDocument, void* aData) +{ if (aDocument->IsFullScreenDoc()) { static_cast(aDocument)->CleanupFullscreenState(); NS_ASSERTION(!aDocument->IsFullScreenDoc(), "Should reset full-screen"); nsTArray* changed = reinterpret_cast*>(aData); changed->AppendElement(aDocument); + + if (HasCrossProcessParent(aDocument)) { + // We're at the top of the content-process side doc tree. Ask the parent + // process to exit fullscreen. + nsCOMPtr os = mozilla::services::GetObserverService(); + os->NotifyObservers(aDocument, "ask-parent-to-exit-fullscreen", nullptr); + } + + // Dispatch a notification so that if this document has any + // cross-process subdocuments, they'll be notified to exit fullscreen. + // The BrowserElementParent listens for this event and performs the + // cross process notification if it has a remote child process. + nsCOMPtr os = mozilla::services::GetObserverService(); + os->NotifyObservers(aDocument, "ask-children-to-exit-fullscreen", nullptr); + aDocument->EnumerateSubDocuments(ResetFullScreen, aData); } return true; @@ -8623,8 +8664,15 @@ nsDocument::RestorePreviousFullScreenState() UnlockPointer(); } - // Clear full-screen stacks in all descendant documents, bottom up. nsCOMPtr fullScreenDoc(do_QueryReferent(sFullScreenDoc)); + + // The fullscreen document may contain a