Bug 1270648 part 5 - Setup the sandboxed fullscreen flag and make it work properly. r?smaug draft
authorXidorn Quan <me@upsuper.org>
Mon, 16 May 2016 10:21:50 +1000
changeset 367719 8dfd78925fe882360ae966f151d241914b5f86bb
parent 367718 69f0f4754620ec47fcb050818d16d95a237f3f0b
child 521093 5d6a5f2dd02e5eca9cb74744177b121f74d6a18a
push id18336
push userxquan@mozilla.com
push dateTue, 17 May 2016 09:32:49 +0000
reviewerssmaug
bugs1270648
milestone49.0a1
Bug 1270648 part 5 - Setup the sandboxed fullscreen flag and make it work properly. r?smaug MozReview-Commit-ID: 3EKRbOyXwNi
docshell/base/nsDocShell.cpp
dom/base/nsSandboxFlags.h
dom/html/HTMLIFrameElement.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
@@ -2497,16 +2497,20 @@ nsDocShell::GetFullscreenAllowed(bool* a
   if (mFullscreenAllowed != CHECK_ATTRIBUTES) {
     *aFullscreenAllowed = (mFullscreenAllowed == PARENT_ALLOWS);
     return NS_OK;
   }
 
   // Assume false until we determine otherwise...
   *aFullscreenAllowed = false;
 
+  // If it is sandboxed, fullscreen is not allowed.
+  if (mSandboxFlags & SANDBOXED_FULLSCREEN) {
+    return NS_OK;
+  }
   nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
   if (!win) {
     return NS_OK;
   }
   nsCOMPtr<Element> frameElement = win->GetFrameElementInternal();
   if (frameElement && !frameElement->IsXULElement()) {
     // We do not allow document inside any containing element other
     // than iframe to enter fullscreen.
--- a/dom/base/nsSandboxFlags.h
+++ b/dom/base/nsSandboxFlags.h
@@ -77,22 +77,17 @@ const unsigned long SANDBOXED_AUTOMATIC_
  * access the origin's data.
  */
 // We don't have an explicit representation of this one, apparently?
 // const unsigned long SANDBOXED_STORAGE_AREA_URLS = 0x200;
 
 /**
  * This flag prevents content from using the requestFullscreen() method.
  */
-// We don't implement this yet.  See represent this as a sandbox flag; instead it's an explicit check for
-// the "allowfullscreen" attribute on the <iframe> that includes us.
-// XXXbz This is wrong in two ways: It can change during the life of the
-// document, and it doesn't get correctly propagated to popups.  See
-// https://bugzilla.mozilla.org/show_bug.cgi?id=1270648
-// const unsigned long SANDBOXED_FULLSCREEN = 0x400;
+const unsigned long SANDBOXED_FULLSCREEN = 0x400;
 
 /**
  * This flag blocks the document from changing document.domain.
  */
 const unsigned long SANDBOXED_DOMAIN = 0x800;
 
 /**
  * This flag prevents content from using window.alert(), window.confirm(),
--- a/dom/html/HTMLIFrameElement.cpp
+++ b/dom/html/HTMLIFrameElement.cpp
@@ -211,17 +211,22 @@ HTMLIFrameElement::SetAttr(int32_t aName
   return NS_OK;
 }
 
 nsresult
 HTMLIFrameElement::AfterSetAttr(int32_t aNameSpaceID, nsIAtom* aName,
                                 const nsAttrValue* aValue,
                                 bool aNotify)
 {
-  if (aName == nsGkAtoms::sandbox && aNameSpaceID == kNameSpaceID_None && mFrameLoader) {
+  if ((aName == nsGkAtoms::sandbox ||
+       // The allowfullscreen attribute affects the sandboxed fullscreen
+       // flag, thus we should also reapply it if that is changed.
+       aName == nsGkAtoms::allowfullscreen ||
+       aName == nsGkAtoms::mozallowfullscreen) &&
+      aNameSpaceID == kNameSpaceID_None && mFrameLoader) {
     // If we have an nsFrameLoader, apply the new sandbox flags.
     // Since this is called after the setter, the sandbox flags have
     // alreay been updated.
     mFrameLoader->ApplySandboxFlags(GetSandboxFlags());
   }
   return nsGenericHTMLFrameElement::AfterSetAttr(aNameSpaceID, aName, aValue,
                                                  aNotify);
 }
@@ -253,21 +258,25 @@ HTMLIFrameElement::GetSandboxFlags()
   }
 
   //  Start off by setting all the restriction flags.
   uint32_t out = SANDBOX_ALL_FLAGS;
 
 // Macro for updating the flag according to the keywords
 #define SANDBOX_KEYWORD(string, atom, flags)                             \
   if (sandboxAttr->Contains(nsGkAtoms::atom, eIgnoreCase)) { out &= ~(flags); }
+#include "IframeSandboxKeywordList.h"
+#undef SANDBOX_KEYWORD
 
-#include "IframeSandboxKeywordList.h"
+  if (GetParsedAttr(nsGkAtoms::allowfullscreen) ||
+      GetParsedAttr(nsGkAtoms::mozallowfullscreen)) {
+    out &= ~SANDBOXED_FULLSCREEN;
+  }
 
   return out;
-#undef SANDBOX_KEYWORD
 }
 
 JSObject*
 HTMLIFrameElement::WrapNode(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return HTMLIFrameElementBinding::Wrap(aCx, this, aGivenProto);
 }
 
--- 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,18 +5,19 @@
 <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>
-  async_test(function(t) {
+  function test_allowfullscreen(t, setup_iframe) {
     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");
@@ -30,20 +31,31 @@
       assert_true(iframe.contentDocument.fullscreenEnabled, "Fullscreen enabled flag should be set when a new document is loaded with allowfullscreen attribute present");
       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");
     }));
+  }
+
+  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");
+
+  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;
@@ -52,12 +64,26 @@
       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() {
-      assert_true(newWin.document.fullscreenEnabled, "Document in the new window is a top level document, thus should has fullscreen enabled flag set");
+      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");
 </script>