Bug 1283526 part 1 - Revert behavior of allowfullscreen attribute for non-sandboxed iframe. r=smaug
authorXidorn Quan <me@upsuper.org>
Mon, 04 Jul 2016 10:19:35 +1000
changeset 304248 04b34bdb471576c61d0d4b2f4c3b6f1d736bd6c3
parent 304247 4287a45df22d86765e15561a8834f6f3d00c24ec
child 304249 64e752c0270c0dfebdf4004e8f7d19029807994d
push id30419
push userphilringnalda@gmail.com
push dateSat, 09 Jul 2016 15:51:15 +0000
treeherdermozilla-central@e3dcf062007e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1283526
milestone50.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 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);