diff --git a/dom/base/DocumentOrShadowRoot.cpp b/dom/base/DocumentOrShadowRoot.cpp index 8647825035..f8f9d5a28c 100644 --- a/dom/base/DocumentOrShadowRoot.cpp +++ b/dom/base/DocumentOrShadowRoot.cpp @@ -160,5 +160,25 @@ DocumentOrShadowRoot::GetPointerLockElement() retargetedPointerLockedElement->AsElement() : nullptr; } +Element* +DocumentOrShadowRoot::GetFullscreenElement() +{ + if (!AsNode().IsInComposedDoc()) { + return nullptr; + } + + Element* element = AsNode().OwnerDoc()->FullScreenStackTop(); + NS_ASSERTION(!element || + element->State().HasState(NS_EVENT_STATE_FULL_SCREEN), + "Fullscreen element should have fullscreen styles applied"); + + nsIContent* retargeted = Retarget(element); + if (retargeted && retargeted->IsElement()) { + return retargeted->AsElement(); + } + + return nullptr; +} + } } diff --git a/dom/base/DocumentOrShadowRoot.h b/dom/base/DocumentOrShadowRoot.h index e622107d03..e056078275 100644 --- a/dom/base/DocumentOrShadowRoot.h +++ b/dom/base/DocumentOrShadowRoot.h @@ -115,6 +115,7 @@ public: ~DocumentOrShadowRoot() = default; Element* GetPointerLockElement(); + Element* GetFullscreenElement(); protected: nsIContent* Retarget(nsIContent* aContent) const; diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index a7af75979f..e158d54d76 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -8603,7 +8603,7 @@ nsDocument::OnPageHide(bool aPersisted, EnumerateActivityObservers(NotifyActivityChanged, nullptr); ClearPendingFullscreenRequests(this); - if (GetFullscreenElement()) { + if (FullScreenStackTop()) { // If this document was fullscreen, we should exit fullscreen in this // doctree branch. This ensures that if the user navigates while in // fullscreen mode we don't leave its still visible ancestor documents @@ -10307,7 +10307,7 @@ nsIDocument::AsyncExitFullscreen(nsIDocument* aDoc) static bool CountFullscreenSubDocuments(nsIDocument* aDoc, void* aData) { - if (aDoc->GetFullscreenElement()) { + if (aDoc->FullScreenStackTop()) { uint32_t* count = static_cast(aData); (*count)++; } @@ -10327,7 +10327,7 @@ nsDocument::IsFullscreenLeaf() { // A fullscreen leaf document is fullscreen, and has no fullscreen // subdocuments. - if (!GetFullscreenElement()) { + if (!FullScreenStackTop()) { return false; } return CountFullscreenSubDocuments(this) == 0; @@ -10336,11 +10336,11 @@ nsDocument::IsFullscreenLeaf() static bool ResetFullScreen(nsIDocument* aDocument, void* aData) { - if (aDocument->GetFullscreenElement()) { + if (aDocument->FullScreenStackTop()) { NS_ASSERTION(CountFullscreenSubDocuments(aDocument) <= 1, "Should have at most 1 fullscreen subdocument."); static_cast(aDocument)->CleanupFullscreenState(); - NS_ASSERTION(!aDocument->GetFullscreenElement(), + NS_ASSERTION(!aDocument->FullScreenStackTop(), "Should reset full-screen"); auto changed = reinterpret_cast*>(aData); changed->AppendElement(aDocument); @@ -10388,7 +10388,7 @@ nsIDocument::ExitFullscreenInDocTree(nsIDocument* aMaybeNotARootDoc) UnlockPointer(); nsCOMPtr root = aMaybeNotARootDoc->GetFullscreenRoot(); - if (!root || !root->GetFullscreenElement()) { + if (!root || !root->FullScreenStackTop()) { // If a document was detached before exiting from fullscreen, it is // possible that the root had left fullscreen state. In this case, // we would not get anything from the ResetFullScreen() call. Root's @@ -10417,7 +10417,7 @@ nsIDocument::ExitFullscreenInDocTree(nsIDocument* aMaybeNotARootDoc) DispatchFullScreenChange(changed[changed.Length() - i - 1]); } - NS_ASSERTION(!root->GetFullscreenElement(), + NS_ASSERTION(!root->FullScreenStackTop(), "Fullscreen root should no longer be a fullscreen doc..."); // Move the top-level window out of fullscreen mode. @@ -10434,7 +10434,7 @@ GetFullscreenLeaf(nsIDocument* aDoc, void* aData) nsIDocument** result = static_cast(aData); *result = aDoc; return false; - } else if (aDoc->GetFullscreenElement()) { + } else if (aDoc->FullScreenStackTop()) { aDoc->EnumerateSubDocuments(GetFullscreenLeaf, aData); } return true; @@ -10453,7 +10453,7 @@ GetFullscreenLeaf(nsIDocument* aDoc) nsIDocument* root = nsContentUtils::GetRootDocument(aDoc); // Check that the root is actually fullscreen so we don't waste time walking // around its descendants. - if (!root->GetFullscreenElement()) { + if (!root->FullScreenStackTop()) { return nullptr; } GetFullscreenLeaf(root, &leaf); @@ -10463,10 +10463,10 @@ GetFullscreenLeaf(nsIDocument* aDoc) void nsDocument::RestorePreviousFullScreenState() { - NS_ASSERTION(!GetFullscreenElement() || !FullscreenRoots::IsEmpty(), + NS_ASSERTION(!FullScreenStackTop() || !FullscreenRoots::IsEmpty(), "Should have at least 1 fullscreen root when fullscreen!"); - if (!GetFullscreenElement() || !GetWindow() || FullscreenRoots::IsEmpty()) { + if (!FullScreenStackTop() || !GetWindow() || FullscreenRoots::IsEmpty()) { return; } @@ -10641,7 +10641,7 @@ nsDocument::FullScreenStackPush(Element* aElement) } EventStateManager::SetFullScreenState(aElement, true); mFullScreenStack.AppendElement(do_GetWeakReference(aElement)); - NS_ASSERTION(GetFullscreenElement() == aElement, "Should match"); + NS_ASSERTION(FullScreenStackTop() == aElement, "Should match"); UpdateViewportScrollbarOverrideForFullscreen(this); return true; } @@ -10689,7 +10689,7 @@ nsDocument::FullScreenStackTop() uint32_t last = mFullScreenStack.Length() - 1; nsCOMPtr element(do_QueryReferent(mFullScreenStack[last])); NS_ASSERTION(element, "Should have full-screen element!"); - NS_ASSERTION(element->IsInUncomposedDoc(), "Full-screen element should be in doc"); + NS_ASSERTION(element->IsInComposedDoc(), "Full-screen element should be in doc"); NS_ASSERTION(element->OwnerDoc() == this, "Full-screen element should be in this doc"); return element; } @@ -10767,7 +10767,7 @@ nsresult nsDocument::RemoteFrameFullscreenReverted() } /* static */ bool -nsDocument::IsUnprefixedFullscreenEnabled(JSContext* aCx, JSObject* aObject) +nsIDocument::IsUnprefixedFullscreenEnabled(JSContext* aCx, JSObject* aObject) { MOZ_ASSERT(NS_IsMainThread()); return nsContentUtils::IsCallerChrome() || @@ -10815,10 +10815,10 @@ nsDocument::FullscreenElementReadyCheck(Element* aElement, { NS_ASSERTION(aElement, "Must pass non-null element to nsDocument::RequestFullScreen"); - if (!aElement || aElement == GetFullscreenElement()) { + if (!aElement || aElement == FullScreenStackTop()) { return false; } - if (!aElement->IsInUncomposedDoc()) { + if (!aElement->IsInComposedDoc()) { DispatchFullscreenError("FullscreenDeniedNotInDocument"); return false; } @@ -10842,8 +10842,11 @@ nsDocument::FullscreenElementReadyCheck(Element* aElement, DispatchFullscreenError("FullscreenDeniedSubDocFullScreen"); return false; } - if (GetFullscreenElement() && - !nsContentUtils::ContentIsDescendantOf(aElement, GetFullscreenElement())) { + //XXXsmaug Note, we don't follow the latest fullscreen spec here. + // This whole check could be probably removed. + if (FullScreenStackTop() && + !nsContentUtils::ContentIsHostIncludingDescendantOf(aElement, + FullScreenStackTop())) { // If this document is full-screen, only grant full-screen requests from // a descendant of the current full-screen element. DispatchFullscreenError("FullscreenDeniedNotDescendant"); @@ -11203,16 +11206,6 @@ nsDocument::GetMozFullScreenElement(nsIDOMElement **aFullScreenElement) return NS_OK; } -Element* -nsDocument::GetFullscreenElement() -{ - Element* element = FullScreenStackTop(); - NS_ASSERTION(!element || - element->State().HasState(NS_EVENT_STATE_FULL_SCREEN), - "Fullscreen element should have fullscreen styles applied"); - return element; -} - NS_IMETHODIMP nsDocument::GetMozFullScreen(bool *aFullScreen) { diff --git a/dom/base/nsDocument.h b/dom/base/nsDocument.h index 010f95ae25..1c10d7b5c3 100644 --- a/dom/base/nsDocument.h +++ b/dom/base/nsDocument.h @@ -896,8 +896,6 @@ public: // already_AddRefed BlockedTrackingNodes() const; - static bool IsUnprefixedFullscreenEnabled(JSContext* aCx, JSObject* aObject); - // Do the "fullscreen element ready check" from the fullscreen spec. // It returns true if the given element is allowed to go into fullscreen. bool FullscreenElementReadyCheck(Element* aElement, bool aWasCallerChrome); @@ -921,11 +919,10 @@ public: void FullScreenStackPop(); // Returns the top element from the full-screen stack. - Element* FullScreenStackTop(); + Element* FullScreenStackTop() override; // DOM-exposed fullscreen API bool FullscreenEnabled() override; - Element* GetFullscreenElement() override; void RequestPointerLock(Element* aElement) override; bool SetPointerLock(Element* aElement, int aCursorStyle); diff --git a/dom/base/nsIDocument.h b/dom/base/nsIDocument.h index 3bdbd0896c..dcaee4fabd 100644 --- a/dom/base/nsIDocument.h +++ b/dom/base/nsIDocument.h @@ -2637,7 +2637,7 @@ public: nsIURI* GetDocumentURIObject() const; // Not const because all the full-screen goop is not const virtual bool FullscreenEnabled() = 0; - virtual Element* GetFullscreenElement() = 0; + virtual Element* FullScreenStackTop() = 0; bool Fullscreen() { return !!GetFullscreenElement(); @@ -2647,6 +2647,7 @@ public: { UnlockPointer(this); } + static bool IsUnprefixedFullscreenEnabled(JSContext* aCx, JSObject* aObject); #ifdef MOZILLA_INTERNAL_API bool Hidden() const { diff --git a/dom/html/test/file_fullscreen-shadowdom.html b/dom/html/test/file_fullscreen-shadowdom.html new file mode 100644 index 0000000000..efc7fe8f5f --- /dev/null +++ b/dom/html/test/file_fullscreen-shadowdom.html @@ -0,0 +1,52 @@ + + + + + Bug 1430305 + + + + + + + Mozilla Bug 1430305 + +
+ +
+      
+    
+ + diff --git a/dom/html/test/mochitest.ini b/dom/html/test/mochitest.ini index dcbb73840a..a0cc7b77f8 100644 --- a/dom/html/test/mochitest.ini +++ b/dom/html/test/mochitest.ini @@ -72,6 +72,7 @@ support-files = file_fullscreen-rollback.html file_fullscreen-scrollbar.html file_fullscreen-selector.html + file_fullscreen-shadowdom.html file_fullscreen-svg-element.html file_fullscreen-top-layer.html file_fullscreen-unprefix-disabled-inner.html diff --git a/dom/html/test/test_fullscreen-api.html b/dom/html/test/test_fullscreen-api.html index 1ac5b3b517..e269c67ad4 100644 --- a/dom/html/test/test_fullscreen-api.html +++ b/dom/html/test/test_fullscreen-api.html @@ -39,6 +39,7 @@ var gTestWindows = [ "file_fullscreen-navigation.html", "file_fullscreen-scrollbar.html", "file_fullscreen-selector.html", + "file_fullscreen-shadowdom.html", "file_fullscreen-top-layer.html", "file_fullscreen-backdrop.html", "file_fullscreen-nested.html", @@ -96,7 +97,8 @@ addLoadEvent(function() { ["full-screen-api.unprefix.enabled", true], ["full-screen-api.allow-trusted-requests-only", false], ["full-screen-api.transition-duration.enter", "0 0"], - ["full-screen-api.transition-duration.leave", "0 0"] + ["full-screen-api.transition-duration.leave", "0 0"], + ["dom.webcomponents.enabled", true] ]}, nextTest); }); SimpleTest.waitForExplicitFinish(); diff --git a/dom/webidl/Document.webidl b/dom/webidl/Document.webidl index 46cb629feb..3bdd4e7962 100644 --- a/dom/webidl/Document.webidl +++ b/dom/webidl/Document.webidl @@ -238,10 +238,6 @@ partial interface Document { readonly attribute boolean fullscreenEnabled; [BinaryName="fullscreenEnabled"] readonly attribute boolean mozFullScreenEnabled; - [LenientSetter, Func="nsDocument::IsUnprefixedFullscreenEnabled"] - readonly attribute Element? fullscreenElement; - [BinaryName="fullscreenElement"] - readonly attribute Element? mozFullScreenElement; [Func="nsDocument::IsUnprefixedFullscreenEnabled"] void exitFullscreen(); diff --git a/dom/webidl/DocumentOrShadowRoot.webidl b/dom/webidl/DocumentOrShadowRoot.webidl index 267f16f23b..eb4a4b666d 100644 --- a/dom/webidl/DocumentOrShadowRoot.webidl +++ b/dom/webidl/DocumentOrShadowRoot.webidl @@ -23,6 +23,8 @@ interface DocumentOrShadowRoot { readonly attribute StyleSheetList styleSheets; readonly attribute Element? pointerLockElement; - // Not implemented yet: bug 1430305. - // readonly attribute Element? fullscreenElement; + [LenientSetter, Func="nsDocument::IsUnprefixedFullscreenEnabled"] + readonly attribute Element? fullscreenElement; + [BinaryName="fullscreenElement"] + readonly attribute Element? mozFullScreenElement; };