diff --git a/dom/base/Element.cpp b/dom/base/Element.cpp index 740b1abaad48..39ac376b076f 100644 --- a/dom/base/Element.cpp +++ b/dom/base/Element.cpp @@ -3573,6 +3573,7 @@ GetFullscreenError(CallerType aCallerType) void Element::RequestFullscreen(CallerType aCallerType, ErrorResult& aError) { + auto request = FullscreenRequest::Create(this, aCallerType); // Only grant fullscreen requests if this is called from inside a trusted // event handler (i.e. inside an event handler for a user initiated event). // This stops the fullscreen from being abused similar to the popups of old, @@ -3581,11 +3582,9 @@ Element::RequestFullscreen(CallerType aCallerType, ErrorResult& aError) // Note that requests for fullscreen inside a web app's origin are exempt // from this restriction. if (const char* error = GetFullscreenError(aCallerType)) { - OwnerDoc()->DispatchFullscreenError(error, this); + request->Reject(error); return; } - - auto request = FullscreenRequest::Create(this, aCallerType); OwnerDoc()->AsyncRequestFullscreen(std::move(request)); } diff --git a/dom/base/FullscreenRequest.h b/dom/base/FullscreenRequest.h index 959a1220323e..e1fd8584a4ba 100644 --- a/dom/base/FullscreenRequest.h +++ b/dom/base/FullscreenRequest.h @@ -12,9 +12,11 @@ #define mozilla_FullscreenRequest_h #include "mozilla/LinkedList.h" +#include "mozilla/PendingFullscreenEvent.h" #include "mozilla/UniquePtr.h" #include "mozilla/dom/Element.h" #include "nsIDocument.h" +#include "nsIScriptError.h" namespace mozilla { @@ -42,6 +44,23 @@ struct FullscreenRequest : public LinkedListElement dom::Element* Element() const { return mElement; } nsIDocument* Document() const { return mDocument; } + // Reject the fullscreen request with the given reason. + // It will dispatch the fullscreenerror event. + void Reject(const char* aReason) const + { + if (nsPresContext* presContext = mDocument->GetPresContext()) { + auto pendingEvent = MakeUnique( + FullscreenEventType::Error, mDocument, mElement); + presContext->RefreshDriver()-> + ScheduleFullscreenEvent(std::move(pendingEvent)); + } + nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, + NS_LITERAL_CSTRING("DOM"), + mDocument, + nsContentUtils::eDOM_PROPERTIES, + aReason); + } + private: RefPtr mElement; RefPtr mDocument; diff --git a/dom/base/nsDocument.cpp b/dom/base/nsDocument.cpp index b28c74bd8929..a748d51f9002 100644 --- a/dom/base/nsDocument.cpp +++ b/dom/base/nsDocument.cpp @@ -10929,21 +10929,6 @@ nsIDocument::AsyncRequestFullscreen(UniquePtr aRequest) Dispatch(TaskCategory::Other, event.forget()); } -void -nsIDocument::DispatchFullscreenError(const char* aMessage, nsINode* aTarget) -{ - if (nsPresContext* presContext = GetPresContext()) { - auto pendingEvent = MakeUnique( - FullscreenEventType::Error, this, aTarget); - presContext->RefreshDriver()-> - ScheduleFullscreenEvent(std::move(pendingEvent)); - } - nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, - NS_LITERAL_CSTRING("DOM"), this, - nsContentUtils::eDOM_PROPERTIES, - aMessage); -} - static void UpdateViewportScrollbarOverrideForFullscreen(nsIDocument* aDoc) { @@ -11157,50 +11142,48 @@ GetFullscreenError(nsIDocument* aDoc, CallerType aCallerType) } bool -nsIDocument::FullscreenElementReadyCheck(Element* aElement, - CallerType aCallerType) +nsIDocument::FullscreenElementReadyCheck(const FullscreenRequest& aRequest) { - NS_ASSERTION(aElement, - "Must pass non-null element to nsDocument::RequestFullscreen"); - if (!aElement || aElement == FullscreenStackTop()) { + Element* elem = aRequest.Element(); + if (elem == FullscreenStackTop()) { return false; } - if (!aElement->IsInComposedDoc()) { - DispatchFullscreenError("FullscreenDeniedNotInDocument", aElement); + if (!elem->IsInComposedDoc()) { + aRequest.Reject("FullscreenDeniedNotInDocument"); return false; } - if (aElement->OwnerDoc() != this) { - DispatchFullscreenError("FullscreenDeniedMovedDocument", aElement); + if (elem->OwnerDoc() != this) { + aRequest.Reject("FullscreenDeniedMovedDocument"); return false; } if (!GetWindow()) { - DispatchFullscreenError("FullscreenDeniedLostWindow", aElement); + aRequest.Reject("FullscreenDeniedLostWindow"); return false; } - if (const char* msg = GetFullscreenError(this, aCallerType)) { - DispatchFullscreenError(msg, aElement); + if (const char* msg = GetFullscreenError(this, aRequest.mCallerType)) { + aRequest.Reject(msg); return false; } if (!IsVisible()) { - DispatchFullscreenError("FullscreenDeniedHidden", aElement); + aRequest.Reject("FullscreenDeniedHidden"); return false; } if (HasFullscreenSubDocument(this)) { - DispatchFullscreenError("FullscreenDeniedSubDocFullScreen", aElement); + aRequest.Reject("FullscreenDeniedSubDocFullScreen"); return false; } //XXXsmaug Note, we don't follow the latest fullscreen spec here. // This whole check could be probably removed. if (FullscreenStackTop() && - !nsContentUtils::ContentIsHostIncludingDescendantOf(aElement, + !nsContentUtils::ContentIsHostIncludingDescendantOf(elem, FullscreenStackTop())) { // If this document is fullscreen, only grant fullscreen requests from // a descendant of the current fullscreen element. - DispatchFullscreenError("FullscreenDeniedNotDescendant", aElement); + aRequest.Reject("FullscreenDeniedNotDescendant"); return false; } if (!nsContentUtils::IsChromeDoc(this) && !IsInActiveTab(this)) { - DispatchFullscreenError("FullscreenDeniedNotFocusedTab", aElement); + aRequest.Reject("FullscreenDeniedNotFocusedTab"); return false; } // Deny requests when a windowed plugin is focused. @@ -11210,7 +11193,7 @@ nsIDocument::FullscreenElementReadyCheck(Element* aElement, return false; } if (nsContentUtils::HasPluginWithUncontrolledEventDispatch(fm->GetFocusedElement())) { - DispatchFullscreenError("FullscreenDeniedFocusedPlugin", aElement); + aRequest.Reject("FullscreenDeniedFocusedPlugin"); return false; } return true; @@ -11377,13 +11360,13 @@ nsIDocument::RequestFullscreen(UniquePtr aRequest) if (!elem->IsHTMLElement() && !elem->IsXULElement() && !elem->IsSVGElement(nsGkAtoms::svg) && !elem->IsMathMLElement(nsGkAtoms::math)) { - DispatchFullscreenError("FullscreenDeniedNotHTMLSVGOrMathML", elem); + aRequest->Reject("FullscreenDeniedNotHTMLSVGOrMathML"); return; } // We don't need to check element ready before this point, because // if we called ApplyFullscreen, it would check that for us. - if (!FullscreenElementReadyCheck(elem, aRequest->mCallerType)) { + if (!FullscreenElementReadyCheck(*aRequest)) { return; } @@ -11430,7 +11413,7 @@ bool nsIDocument::ApplyFullscreen(const FullscreenRequest& aRequest) { Element* elem = aRequest.Element(); - if (!FullscreenElementReadyCheck(elem, aRequest.mCallerType)) { + if (!FullscreenElementReadyCheck(aRequest)) { return false; } diff --git a/dom/base/nsIDocument.h b/dom/base/nsIDocument.h index c662b39854f2..898513baebe4 100644 --- a/dom/base/nsIDocument.h +++ b/dom/base/nsIDocument.h @@ -1756,8 +1756,8 @@ public: // 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, - mozilla::dom::CallerType aCallerType); + // It is responsive to dispatch "fullscreenerror" event when necessary. + bool FullscreenElementReadyCheck(const FullscreenRequest&); // This is called asynchronously by nsIDocument::AsyncRequestFullscreen() // to move this document into fullscreen mode if allowed. @@ -1854,12 +1854,6 @@ public: */ static bool HandlePendingFullscreenRequests(nsIDocument* aDocument); - /** - * Dispatch fullscreenerror event and report the failure message to - * the console. - */ - void DispatchFullscreenError(const char* aMessage, nsINode* aTarget); - void RequestPointerLock(Element* aElement, mozilla::dom::CallerType); bool SetPointerLock(Element* aElement, int aCursorStyle);