Bug 1602608: Reject DOM Fullscreen promises with reasonable messages. r=smaug
authorKris Maglione <maglione.k@gmail.com>
Tue, 10 Dec 2019 22:26:23 +0000
changeset 506320 7635669b8d722e90ffd93fea712b60da64085653
parent 506319 0480e575877faf68d5042fa0b7ca45badf1855a5
child 506321 b0ce0ed033e6ed37358f10468c2bd11d7aa3b935
push id36902
push useraciure@mozilla.com
push dateWed, 11 Dec 2019 03:34:51 +0000
treeherdermozilla-central@7635669b8d72 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1602608
milestone73.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
Bug 1602608: Reject DOM Fullscreen promises with reasonable messages. r=smaug Differential Revision: https://phabricator.services.mozilla.com/D56599
dom/base/Document.cpp
dom/base/Document.h
dom/base/FullscreenChange.h
--- a/dom/base/Document.cpp
+++ b/dom/base/Document.cpp
@@ -12720,17 +12720,17 @@ class PendingFullscreenChangeList {
       while (mCurrent) {
         if (mCurrent->Type() == T::kType) {
           nsCOMPtr<nsIDocShellTreeItem> docShell =
               mCurrent->Document()->GetDocShell();
           if (!docShell) {
             // Always automatically drop fullscreen changes which are
             // from a document detached from the doc shell.
             UniquePtr<T> change = TakeAndNextInternal();
-            change->MayRejectPromise();
+            change->MayRejectPromise(u"Document is not active");
             continue;
           }
           while (docShell && docShell != mRootShellForIteration) {
             nsCOMPtr<nsIDocShellTreeItem> parent;
             docShell->GetInProcessParent(getter_AddRefs(parent));
             docShell = parent.forget();
           }
           if (docShell) {
@@ -12959,18 +12959,22 @@ static void DispatchFullscreenNewOriginE
       ChromeOnlyDispatch::eYes);
   asyncDispatcher->PostDOMEvent();
 }
 
 void Document::RestorePreviousFullscreenState(UniquePtr<FullscreenExit> aExit) {
   NS_ASSERTION(!FullscreenStackTop() || !FullscreenRoots::IsEmpty(),
                "Should have at least 1 fullscreen root when fullscreen!");
 
-  if (!FullscreenStackTop() || !GetWindow() || FullscreenRoots::IsEmpty()) {
-    aExit->MayRejectPromise();
+  if (!GetWindow()) {
+    aExit->MayRejectPromise(u"No active window");
+    return;
+  }
+  if (!FullscreenStackTop() || FullscreenRoots::IsEmpty()) {
+    aExit->MayRejectPromise(u"Not in fullscreen mode");
     return;
   }
 
   nsCOMPtr<Document> fullScreenDoc = GetFullscreenLeaf(this);
   AutoTArray<Element*, 8> exitElements;
 
   Document* doc = fullScreenDoc;
   // Collect all subdocuments.
@@ -13275,17 +13279,17 @@ static const char* GetFullscreenError(Do
   // allowfullscreen attribute set.
   nsCOMPtr<nsIDocShell> docShell(aDoc->GetDocShell());
   if (!docShell || !docShell->GetFullscreenAllowed()) {
     return "FullscreenDeniedContainerNotAllowed";
   }
   return nullptr;
 }
 
-bool Document::FullscreenElementReadyCheck(const FullscreenRequest& aRequest) {
+bool Document::FullscreenElementReadyCheck(FullscreenRequest& aRequest) {
   Element* elem = aRequest.Element();
   // Strictly speaking, this isn't part of the fullscreen element ready
   // check in the spec, but per steps in the spec, when an element which
   // is already the fullscreen element requests fullscreen, nothing
   // should change and no event should be dispatched, but we still need
   // to resolve the returned promise.
   if (elem == FullscreenStackTop()) {
     aRequest.MayResolvePromise();
@@ -13324,17 +13328,17 @@ bool Document::FullscreenElementReadyChe
   if (!nsContentUtils::IsChromeDoc(this) && !IsInActiveTab(this)) {
     aRequest.Reject("FullscreenDeniedNotFocusedTab");
     return false;
   }
   // Deny requests when a windowed plugin is focused.
   nsFocusManager* fm = nsFocusManager::GetFocusManager();
   if (!fm) {
     NS_WARNING("Failed to retrieve focus manager in fullscreen request.");
-    aRequest.MayRejectPromise();
+    aRequest.MayRejectPromise(u"An unexpected error occurred");
     return false;
   }
   if (nsContentUtils::HasPluginWithUncontrolledEventDispatch(
           fm->GetFocusedElement())) {
     aRequest.Reject("FullscreenDeniedFocusedPlugin");
     return false;
   }
   return true;
@@ -13380,17 +13384,17 @@ static bool ShouldApplyFullscreenDirectl
     return true;
   }
 }
 
 void Document::RequestFullscreen(UniquePtr<FullscreenRequest> aRequest,
                                  bool applyFullScreenDirectly) {
   nsCOMPtr<nsPIDOMWindowOuter> rootWin = GetRootWindow(this);
   if (!rootWin) {
-    aRequest->MayRejectPromise();
+    aRequest->MayRejectPromise(u"No active window");
     return;
   }
 
   if (applyFullScreenDirectly || ShouldApplyFullscreenDirectly(this, rootWin)) {
     ApplyFullscreen(std::move(aRequest));
     return;
   }
 
@@ -13438,17 +13442,17 @@ bool Document::HandlePendingFullscreenRe
   return handled;
 }
 
 static void ClearPendingFullscreenRequests(Document* aDoc) {
   PendingFullscreenChangeList::Iterator<FullscreenRequest> iter(
       aDoc, PendingFullscreenChangeList::eInclusiveDescendants);
   while (!iter.AtEnd()) {
     UniquePtr<FullscreenRequest> request = iter.TakeAndNext();
-    request->MayRejectPromise();
+    request->MayRejectPromise(u"Fullscreen request aborted");
   }
 }
 
 bool Document::ApplyFullscreen(UniquePtr<FullscreenRequest> aRequest) {
   if (!FullscreenElementReadyCheck(*aRequest)) {
     return false;
   }
 
--- a/dom/base/Document.h
+++ b/dom/base/Document.h
@@ -2174,17 +2174,17 @@ class Document : public nsINode,
    * the <iframe> or <browser> that contains this document is also mode
    * fullscreen. This happens recursively in all ancestor documents.
    */
   void AsyncRequestFullscreen(UniquePtr<FullscreenRequest>);
 
   // 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&);
+  bool FullscreenElementReadyCheck(FullscreenRequest&);
 
   // This is called asynchronously by Document::AsyncRequestFullscreen()
   // to move this document into fullscreen mode if allowed.
   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.
--- a/dom/base/FullscreenChange.h
+++ b/dom/base/FullscreenChange.h
@@ -36,22 +36,26 @@ class FullscreenChange : public LinkedLi
 
   void MayResolvePromise() const {
     if (mPromise) {
       MOZ_ASSERT(mPromise->State() == Promise::PromiseState::Pending);
       mPromise->MaybeResolveWithUndefined();
     }
   }
 
-  void MayRejectPromise() const {
+  void MayRejectPromise(const nsAString& aMessage) {
     if (mPromise) {
       MOZ_ASSERT(mPromise->State() == Promise::PromiseState::Pending);
-      mPromise->MaybeReject(NS_ERROR_DOM_TYPE_ERR);
+      mPromise->MaybeRejectWithTypeError(aMessage);
     }
   }
+  template <int N>
+  void MayRejectPromise(const char16_t (&aMessage)[N]) {
+    MayRejectPromise(nsLiteralString(aMessage));
+  }
 
  protected:
   typedef dom::Promise Promise;
 
   FullscreenChange(ChangeType aType, dom::Document* aDocument,
                    already_AddRefed<Promise> aPromise)
       : mType(aType), mDocument(aDocument), mPromise(aPromise) {
     MOZ_ASSERT(aDocument);
@@ -86,24 +90,24 @@ class FullscreenRequest : public Fullscr
   }
 
   ~FullscreenRequest() { MOZ_COUNT_DTOR(FullscreenRequest); }
 
   dom::Element* Element() const { return mElement; }
 
   // Reject the fullscreen request with the given reason.
   // It will dispatch the fullscreenerror event.
-  void Reject(const char* aReason) const {
+  void Reject(const char* aReason) {
     if (nsPresContext* presContext = Document()->GetPresContext()) {
       auto pendingEvent = MakeUnique<PendingFullscreenEvent>(
           FullscreenEventType::Error, Document(), mElement);
       presContext->RefreshDriver()->ScheduleFullscreenEvent(
           std::move(pendingEvent));
     }
-    MayRejectPromise();
+    MayRejectPromise(u"Fullscreen request denied");
     nsContentUtils::ReportToConsole(nsIScriptError::warningFlag,
                                     NS_LITERAL_CSTRING("DOM"), Document(),
                                     nsContentUtils::eDOM_PROPERTIES, aReason);
   }
 
  private:
   RefPtr<dom::Element> mElement;