Bug 1283526 part 1 - Revert behavior of allowfullscreen attribute for non-sandboxed iframe. r?smaug draft
authorXidorn Quan <me@upsuper.org>
Mon, 04 Jul 2016 10:19:35 +1000
changeset 383781 cd9963d08be7c29ac6c63770c9ddb60de448d02b
parent 383780 fcd9b8fb2a5752cc6073a1d974ceeb78588fdba7
child 383782 2fd3450228e53d2b8774db173383c9983b4b927d
push id22093
push userxquan@mozilla.com
push dateMon, 04 Jul 2016 23:47:28 +0000
reviewerssmaug
bugs1283526
milestone50.0a1
Bug 1283526 part 1 - Revert behavior of allowfullscreen attribute for non-sandboxed iframe. r?smaug MozReview-Commit-ID: BayA4tQBsfC
docshell/base/nsDocShell.cpp
docshell/base/nsIDocShell.idl
dom/base/ImportManager.cpp
dom/base/nsDocument.cpp
dom/base/nsIDocument.h
dom/xul/XULDocument.cpp
testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe-allowfullscreen.html
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -2551,20 +2551,16 @@ nsDocShell::GetFullscreenAllowed(bool* a
       if (!frameElement->HasAttr(kNameSpaceID_None,
                                  nsGkAtoms::allowfullscreen)) {
         return NS_OK;
       }
     } else {
       // neither iframe nor embed
       return NS_OK;
     }
-    nsIDocument* doc = frameElement->GetUncomposedDoc();
-    if (!doc || !doc->FullscreenEnabledInternal()) {
-      return NS_OK;
-    }
   }
 
   // If we have no parent then we're the root docshell; no ancestor of the
   // original docshell doesn't have a allowfullscreen attribute, so
   // report fullscreen as allowed.
   RefPtr<nsDocShell> parent = GetParentDocshell();
   if (!parent) {
     *aFullscreenAllowed = true;
@@ -3832,23 +3828,16 @@ nsDocShell::IsSandboxedFrom(nsIDocShell*
       return false;
     }
   }
 
   // Otherwise, we are sandboxed from aTargetDocShell.
   return true;
 }
 
-void
-nsDocShell::ApplySandboxAndFullscreenFlags(nsIDocument* aDoc)
-{
-  aDoc->SetSandboxFlags(mSandboxFlags);
-  aDoc->SetFullscreenEnabled(GetFullscreenAllowed());
-}
-
 NS_IMETHODIMP
 nsDocShell::GetTreeOwner(nsIDocShellTreeOwner** aTreeOwner)
 {
   NS_ENSURE_ARG_POINTER(aTreeOwner);
 
   *aTreeOwner = mTreeOwner;
   NS_IF_ADDREF(*aTreeOwner);
   return NS_OK;
@@ -8057,19 +8046,19 @@ nsDocShell::CreateAboutBlankContentViewe
                                     getter_AddRefs(blankDoc));
     if (blankDoc) {
       // Hack: set the base URI manually, since this document never
       // got Reset() with a channel.
       blankDoc->SetBaseURI(aBaseURI);
 
       blankDoc->SetContainer(this);
 
-      // Apply the sandbox and fullscreen enabled flags to the document.
-      // These are immutable after being set here.
-      ApplySandboxAndFullscreenFlags(blankDoc);
+      // Copy our sandbox flags to the document. These are immutable
+      // after being set here.
+      blankDoc->SetSandboxFlags(mSandboxFlags);
 
       // create a content viewer for us and the new document
       docFactory->CreateInstanceForDocument(
         NS_ISUPPORTS_CAST(nsIDocShell*, this), blankDoc, "view",
         getter_AddRefs(viewer));
 
       // hook 'em up
       if (viewer) {
--- a/docshell/base/nsIDocShell.idl
+++ b/docshell/base/nsIDocShell.idl
@@ -20,17 +20,16 @@ class nsIPresShell;
 [ptr] native nsPresContext(nsPresContext);
 [ptr] native nsIPresShell(nsIPresShell);
 
 interface nsIURI;
 interface nsIChannel;
 interface nsIContentViewer;
 interface nsIDOMEventTarget;
 interface nsIDocShellLoadInfo;
-interface nsIDocument;
 interface nsIEditor;
 interface nsIEditingSession;
 interface nsISimpleEnumerator;
 interface nsIInputStream;
 interface nsIRequest;
 interface nsISHEntry;
 interface nsILayoutHistoryState;
 interface nsISecureBrowserUI;
@@ -897,21 +896,16 @@ interface nsIDocShell : nsIDocShellTreeI
 
   /**
    * Returns true if we are sandboxed from aTargetDocShell.
    * aTargetDocShell - the browsing context we are attempting to navigate.
    */
   [noscript,notxpcom,nostdcall] bool isSandboxedFrom(in nsIDocShell aTargetDocShell);
 
   /**
-   * Apply sandbox flags and fullscreen enabled flag to the given document.
-   */
-  [noscript,notxpcom] void applySandboxAndFullscreenFlags(in nsIDocument aDoc);
-
-  /**
    * This member variable determines whether a document has Mixed Active Content that
    * was initially blocked from loading, but the user has choosen to override the
    * block and allow the content to load. mMixedContentChannel is set to the document's
    * channel when the user allows mixed content. The nsMixedContentBlocker content policy
    * checks if the document's root channel matches the mMixedContentChannel.  If it matches,
    * then Mixed Content is loaded.  If it does match, mixed content is blocked.
    *
    * A match implies that there is definitely mixed active content on a page that was
--- a/dom/base/ImportManager.cpp
+++ b/dom/base/ImportManager.cpp
@@ -596,17 +596,16 @@ ImportLoader::OnStartRequest(nsIRequest*
   // The imported document must know which master document it belongs to.
   mDocument = do_QueryInterface(importDoc);
   nsCOMPtr<nsIDocument> master = mImportParent->MasterDocument();
   mDocument->SetMasterDocument(master);
 
   // We want to inherit the sandbox flags and fullscreen enabled flag
   // from the master document.
   mDocument->SetSandboxFlags(master->GetSandboxFlags());
-  mDocument->SetFullscreenEnabled(master->FullscreenEnabledInternal());
 
   // We have to connect the blank document we created with the channel we opened,
   // and create its own LoadGroup for it.
   nsCOMPtr<nsIStreamListener> listener;
   nsCOMPtr<nsILoadGroup> loadGroup;
   channel->GetLoadGroup(getter_AddRefs(loadGroup));
   nsCOMPtr<nsILoadGroup> newLoadGroup = do_CreateInstance(NS_LOADGROUP_CONTRACTID);
   NS_ENSURE_TRUE(newLoadGroup, NS_ERROR_OUT_OF_MEMORY);
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -1450,17 +1450,16 @@ nsIDocument::nsIDocument()
     // unless we get a window, and in that case the docshell value will get
     // &&-ed in, this is safe.
     mAllowDNSPrefetch(true),
     mIsBeingUsedAsImage(false),
     mHasLinksToUpdate(false),
     mFontFaceSetDirty(true),
     mGetUserFontSetCalled(false),
     mPostedFlushUserFontSet(false),
-    mFullscreenEnabled(false),
     mPartID(0),
     mDidFireDOMContentLoaded(true),
     mHasScrollLinkedEffect(false),
     mUserHasInteracted(false)
 {
   SetInDocument();
 
   PR_INIT_CLIST(&mDOMMediaQueryLists);
@@ -2589,17 +2588,18 @@ nsDocument::StartDocumentLoad(const char
   }
 
   // If this document is being loaded by a docshell, copy its sandbox flags
   // to the document, and store the fullscreen enabled flag. These are
   // immutable after being set here.
   nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(aContainer);
 
   if (docShell) {
-    docShell->ApplySandboxAndFullscreenFlags(this);
+    nsresult rv = docShell->GetSandboxFlags(&mSandboxFlags);
+    NS_ENSURE_SUCCESS(rv, rv);
     WarnIfSandboxIneffective(docShell, mSandboxFlags, GetChannel());
   }
 
   // The CSP directive upgrade-insecure-requests not only applies to the
   // toplevel document, but also to nested documents. Let's propagate that
   // flag from the parent to the nested document.
   nsCOMPtr<nsIDocShellTreeItem> treeItem = this->GetDocShell();
   if (treeItem) {
@@ -11797,17 +11797,21 @@ GetFullscreenError(nsIDocument* aDoc, bo
     // in a Runnable, so don't use GetMozFullScreenEnabled() from a
     // Runnable!
     return nullptr;
   }
 
   if (!nsContentUtils::IsFullScreenApiEnabled()) {
     return "FullscreenDeniedDisabled";
   }
-  if (!aDoc->FullscreenEnabledInternal()) {
+
+  // Ensure that all containing elements are <iframe> and have
+  // allowfullscreen attribute set.
+  nsCOMPtr<nsIDocShell> docShell(aDoc->GetDocShell());
+  if (!docShell || !docShell->GetFullscreenAllowed()) {
     return "FullscreenDeniedContainerNotAllowed";
   }
   return nullptr;
 }
 
 bool
 nsDocument::FullscreenElementReadyCheck(Element* aElement,
                                         bool aWasCallerChrome)
--- a/dom/base/nsIDocument.h
+++ b/dom/base/nsIDocument.h
@@ -2588,21 +2588,16 @@ public:
   // Not const because all the full-screen goop is not const
   virtual bool FullscreenEnabled() = 0;
   virtual Element* GetFullscreenElement() = 0;
   bool Fullscreen()
   {
     return !!GetFullscreenElement();
   }
   void ExitFullscreen();
-  bool FullscreenEnabledInternal() const { return mFullscreenEnabled; }
-  void SetFullscreenEnabled(bool aEnabled)
-  {
-    mFullscreenEnabled = aEnabled;
-  }
   Element* GetMozPointerLockElement();
   void MozExitPointerLock()
   {
     UnlockPointer(this);
   }
   bool Hidden() const
   {
     return mVisibilityState != mozilla::dom::VisibilityState::Visible;
@@ -3054,20 +3049,16 @@ protected:
   bool mFontFaceSetDirty : 1;
 
   // Has GetUserFontSet() been called?
   bool mGetUserFontSetCalled : 1;
 
   // Do we currently have an event posted to call FlushUserFontSet?
   bool mPostedFlushUserFontSet : 1;
 
-  // Whether fullscreen is enabled for this document. This corresponds
-  // to the "fullscreen enabled flag" in the HTML spec.
-  bool mFullscreenEnabled : 1;
-
   enum Type {
     eUnknown, // should never be used
     eHTML,
     eXHTML,
     eGenericXML,
     eSVG,
     eXUL
   };
--- a/dom/xul/XULDocument.cpp
+++ b/dom/xul/XULDocument.cpp
@@ -378,17 +378,16 @@ XULDocument::StartDocumentLoad(const cha
             }
         }
     }
     // NOTE: If this ever starts calling nsDocument::StartDocumentLoad
     // we'll possibly need to reset our content type afterwards.
     mStillWalking = true;
     mMayStartLayout = false;
     mDocumentLoadGroup = do_GetWeakReference(aLoadGroup);
-    mFullscreenEnabled = true;
 
     mChannel = aChannel;
 
     // Get the URI.  Note that this should match nsDocShell::OnLoadingSite
     nsresult rv =
         NS_GetFinalChannelURI(aChannel, getter_AddRefs(mDocumentURI));
     NS_ENSURE_SUCCESS(rv, rv);
     
--- a/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe-allowfullscreen.html
+++ b/testing/web-platform/tests/html/semantics/embedded-content/the-iframe-element/iframe-allowfullscreen.html
@@ -5,95 +5,35 @@
 <link rel="author" title="Mozilla" href="https://www.mozilla.org">
 <link rel="help" href="https://html.spec.whatwg.org/multipage/browsers.html#initialise-the-document-object">
 <link rel="help" href="https://fullscreen.spec.whatwg.org/#fullscreen-enabled-flag">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 
 <div id="log"></div>
 <script>
-  function test_allowfullscreen(t, setup_iframe) {
+  async_test(function(t) {
     var iframe = document.createElement("iframe");
-    setup_iframe(iframe);
     iframe.src = "support/blank.htm";
     var eventWatcher = new EventWatcher(t, iframe, "load");
     document.body.appendChild(iframe);
     t.add_cleanup(function() {
       document.body.removeChild(iframe);
     });
 
     assert_true(document.fullscreenEnabled, "Top level document has fullscreen enabled flag set");
-    eventWatcher.wait_for("load").then(t.step_func(function() {
+    eventWatcher.wait_for("load").then(t.step_func_done(function() {
       assert_false(iframe.contentDocument.fullscreenEnabled, "Document inside iframe without allowfullscreen attribute should not have fullscreen enabled flag set");
       iframe.setAttribute("allowfullscreen", true);
-      assert_false(iframe.contentDocument.fullscreenEnabled, "Setting allowfullscreen attribute after document load should not affect fullscreen enabled flag");
-      iframe.contentWindow.location.reload();
-      return eventWatcher.wait_for("load");
-    })).then(t.step_func(function() {
-      assert_true(iframe.contentDocument.fullscreenEnabled, "Fullscreen enabled flag should be set when a new document is loaded with allowfullscreen attribute present");
+      assert_true(iframe.contentDocument.fullscreenEnabled, "Fullscreen should be allowed when allowfullscreen attribute is set");
       iframe.removeAttribute("allowfullscreen");
-      assert_true(iframe.contentDocument.fullscreenEnabled, "Removing allowfullscreen attribute should not affect fullscreen enabled flag");
-      iframe.contentWindow.location.reload();
-      return eventWatcher.wait_for("load");
-    })).then(t.step_func_done(function() {
-      assert_false(iframe.contentDocument.fullscreenEnabled, "Fullscreen enabled flag should be reset when a new document is loaded with allowfullscreen attribute absent");
+      assert_false(iframe.contentDocument.fullscreenEnabled, "Fullscreen should be denied when allowfullscreen attribute is removed");
     }));
-  }
-
-  async_test(function(t) {
-    test_allowfullscreen(t, function(iframe) {});
   }, "iframe-allowfullscreen");
 
-  async_test(function(t) {
-    test_allowfullscreen(t, function(iframe) {
-      iframe.setAttribute("sandbox", "allow-same-origin");
-    });
-  }, "iframe-sandbox-allowfullscreen");
-
-  /* Fullscreen enabled flag with dialog */
-
-  function test_allowfullscreen_dialog(t, setup_iframe, check) {
-    var iframe = document.createElement("iframe");
-    setup_iframe(iframe);
-    iframe.src = "support/blank.htm";
-    var eventWatcher = new EventWatcher(t, iframe, "load");
-    document.body.appendChild(iframe);
-    t.add_cleanup(function() {
-      document.body.removeChild(iframe);
-    });
-
-    var newWin;
-    assert_true(document.fullscreenEnabled, "Top level document has fullscreen enabled flag set");
-    eventWatcher.wait_for("load").then(t.step_func(function() {
-      assert_false(iframe.contentDocument.fullscreenEnabled, "Document inside iframe without allowfullscreen attribute should not have fullscreen enabled flag set");
-      newWin = iframe.contentWindow.open("support/blank.htm");
-      t.add_cleanup(function() {
-        newWin.close();
-      });
-      var newWinEventWatcher = new EventWatcher(t, newWin, "load");
-      return newWinEventWatcher.wait_for("load");
-    })).then(t.step_func_done(function() {
-      check(newWin);
-    }));
-  }
-
-  async_test(function(t) {
-    test_allowfullscreen_dialog(t, function() {}, function(newWin) {
-      assert_true(newWin.document.fullscreenEnabled, "Document in the new window is a top level document, thus should has fullscreen enabled flag set");
-    });
-  }, "iframe-allowfullscreen-dialog");
-
-  async_test(function(t) {
-    test_allowfullscreen_dialog(t, function(iframe) {
-      iframe.setAttribute("sandbox", "allow-same-origin allow-popups");
-    }, function(newWin) {
-      assert_false(newWin.document.fullscreenEnabled, "Document in the new window should inherit the sandboxed fullscreen flag and should not have fullscreen enabled flag set");
-    });
-  }, "iframe-sandbox-allowfullscreen-dialog");
-
   /* Fullscreen enabled flag with about:blank */
 
   function test_allowfullscreen_noload(setup_iframe, check) {
     var iframe = document.createElement("iframe");
     setup_iframe(iframe);
     document.body.appendChild(iframe);
     check(iframe.contentDocument);
     document.body.removeChild(iframe);