Title: [255162] trunk
Revision
255162
Author
[email protected]
Date
2020-01-27 12:54:54 -0800 (Mon, 27 Jan 2020)

Log Message

Support 'allow="fullscreen"' feature policy
https://bugs.webkit.org/show_bug.cgi?id=206806
<rdar://problem/55640448>

Patch by Jer Noble <[email protected]> on 2020-01-27
Reviewed by Youenn Fablet.

Source/WebCore:

Test: http/tests/fullscreen/fullscreen-feature-policy.html

The unprefixed version of the Fullscreen API has deprecated the 'allowfullscreen' iframe
attribute in favor of the 'allow="fullscreen"' style attribute used by Feature Policy.
Add support for such, including the specified handling for the legacy 'allowfullscreen'
attribute.

Note: this patch will (intentionally) change the default behavior of <iframe>s. Previously
any <iframe> without the "allowfullscreen" attribute would not be allowed to enter fullscreen
mode. After this patch, <iframes> without the legacy attribute or an explicit fullscreen
Feature Policy will be allowed to enter fullscreen so long as their origin is the same as
the top document (and that all parent iframes are also allowed to enter fullscreen).

* dom/FullscreenManager.cpp:
(WebCore::FullscreenManager::requestFullscreenForElement):
(WebCore::FullscreenManager::isFullscreenEnabled const):
(WebCore::isAttributeOnAllOwners): Deleted.
(WebCore::FullscreenManager::fullscreenIsAllowedForElement const): Deleted.
* dom/FullscreenManager.h:
* html/FeaturePolicy.cpp:
(WebCore::isFeaturePolicyAllowedByDocumentAndAllOwners):
(WebCore::FeaturePolicy::parse):
(WebCore::FeaturePolicy::allows const):
* html/FeaturePolicy.h:
* html/HTMLIFrameElement.cpp:
(WebCore::HTMLIFrameElement::parseAttribute):
(WebCore::HTMLIFrameElement::featurePolicy const):
* xml/XMLHttpRequest.cpp:
(WebCore::XMLHttpRequest::createRequest):
(WebCore::isSyncXHRAllowedByFeaturePolicy): Deleted.

LayoutTests:

* fullscreen/full-screen-enabled-prefixed.html:
* fullscreen/full-screen-enabled.html:
* fullscreen/full-screen-frameset-expected.txt: Removed.
* fullscreen/full-screen-frameset.html: Removed.
* fullscreen/full-screen-iframe-not-allowed.html:
* fullscreen/full-screen-restrictions.html:
* http/tests/fullscreen/fullscreen-feature-policy-expected.txt: Added.
* http/tests/fullscreen/fullscreen-feature-policy.html: Added.

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (255161 => 255162)


--- trunk/LayoutTests/ChangeLog	2020-01-27 20:29:14 UTC (rev 255161)
+++ trunk/LayoutTests/ChangeLog	2020-01-27 20:54:54 UTC (rev 255162)
@@ -1,3 +1,20 @@
+2020-01-27  Jer Noble  <[email protected]>
+
+        Support 'allow="fullscreen"' feature policy
+        https://bugs.webkit.org/show_bug.cgi?id=206806
+        <rdar://problem/55640448>
+
+        Reviewed by Youenn Fablet.
+
+        * fullscreen/full-screen-enabled-prefixed.html:
+        * fullscreen/full-screen-enabled.html:
+        * fullscreen/full-screen-frameset-expected.txt: Removed.
+        * fullscreen/full-screen-frameset.html: Removed.
+        * fullscreen/full-screen-iframe-not-allowed.html:
+        * fullscreen/full-screen-restrictions.html:
+        * http/tests/fullscreen/fullscreen-feature-policy-expected.txt: Added.
+        * http/tests/fullscreen/fullscreen-feature-policy.html: Added.
+
 2020-01-27  Said Abou-Hallawa  <[email protected]>
 
         Throttling requestAnimationFrame should be controlled by RenderingUpdateScheduler

Modified: trunk/LayoutTests/fullscreen/full-screen-enabled-prefixed.html (255161 => 255162)


--- trunk/LayoutTests/fullscreen/full-screen-enabled-prefixed.html	2020-01-27 20:29:14 UTC (rev 255161)
+++ trunk/LayoutTests/fullscreen/full-screen-enabled-prefixed.html	2020-01-27 20:54:54 UTC (rev 255162)
@@ -6,6 +6,7 @@
     var iframe = document.documentElement.appendChild(document.createElement('iframe'));
     iframe.setAttribute('webkitallowfullscreen', 'true');
     var iframe2 = document.documentElement.appendChild(document.createElement('iframe'));
+    iframe2.setAttribute('allow', "fullscreen 'none'");
     testExpected('iframe.contentDocument.webkitFullscreenEnabled', true);
     testExpected('iframe2.contentDocument.webkitFullscreenEnabled', false);
     endTest();

Modified: trunk/LayoutTests/fullscreen/full-screen-enabled.html (255161 => 255162)


--- trunk/LayoutTests/fullscreen/full-screen-enabled.html	2020-01-27 20:29:14 UTC (rev 255161)
+++ trunk/LayoutTests/fullscreen/full-screen-enabled.html	2020-01-27 20:54:54 UTC (rev 255162)
@@ -6,6 +6,7 @@
     var iframe = document.documentElement.appendChild(document.createElement('iframe'));
     iframe.setAttribute('allowfullscreen', 'true');
     var iframe2 = document.documentElement.appendChild(document.createElement('iframe'));
+    iframe2.setAttribute('allow', "fullscreen 'none'");
     testExpected('iframe.contentDocument.webkitFullscreenEnabled', true);
     testExpected('iframe2.contentDocument.webkitFullscreenEnabled', false);
     endTest();

Deleted: trunk/LayoutTests/fullscreen/full-screen-frameset-expected.txt (255161 => 255162)


--- trunk/LayoutTests/fullscreen/full-screen-frameset-expected.txt	2020-01-27 20:29:14 UTC (rev 255161)
+++ trunk/LayoutTests/fullscreen/full-screen-frameset-expected.txt	2020-01-27 20:54:54 UTC (rev 255162)
@@ -1,17 +0,0 @@
-
-
---------
-Frame: 'header'
---------
-Test for bug 58638: Do not allow fullscreen from within a <frame> element, even with the webkitallowfullscreen attribute set.
-
-To test manually, click the "Go full screen" button - the page should not enter full screen mode.
-
-SUCCEED - did not enter full screen!
-END OF TEST
-
-
---------
-Frame: 'frame'
---------
-Go full screen

Deleted: trunk/LayoutTests/fullscreen/full-screen-frameset.html (255161 => 255162)


--- trunk/LayoutTests/fullscreen/full-screen-frameset.html	2020-01-27 20:29:14 UTC (rev 255161)
+++ trunk/LayoutTests/fullscreen/full-screen-frameset.html	2020-01-27 20:54:54 UTC (rev 255162)
@@ -1,35 +0,0 @@
-<script src=""
-<script>
-if (window.testRunner)
-    testRunner.dumpChildFramesAsText();
-
-var waitingFor = 2;
-function runTest() {
-    if (--waitingFor)
-        return;
-    var frame = document.getElementById('frame');
-
-    waitForEvent(frame.contentDocument, 'webkitfullscreenchange', function() { 
-            consoleWrite("FAIL - entered full screen!");
-            endTest(); 
-            if (testRunner)
-                testRunner.notifyDone();     
-    });
-
-    runWithKeyDown(function() {
-
-        setTimeout(function() { 
-            consoleWrite("SUCCEED - did not enter full screen!"); 
-            endTest();
-            if (testRunner)
-                testRunner.notifyDone();     
-        }, 50);
-
-        frame.contentDocument.documentElement.webkitRequestFullScreen();
-    });
-}
-</script>
-<frameset rows="150,*">
-    <frame name="header" src="" webkitfullscreenallowed _onload_="runTest()">
-    <frame id="frame" name="frame" src="" _onload_="runTest()">
-</frameset>

Modified: trunk/LayoutTests/fullscreen/full-screen-iframe-not-allowed.html (255161 => 255162)


--- trunk/LayoutTests/fullscreen/full-screen-iframe-not-allowed.html	2020-01-27 20:29:14 UTC (rev 255161)
+++ trunk/LayoutTests/fullscreen/full-screen-iframe-not-allowed.html	2020-01-27 20:54:54 UTC (rev 255162)
@@ -20,5 +20,5 @@
     });
 }
 </script>
-<iframe id="frame" src="" _onload_="runTest()">
+<iframe id="frame" src="" _onload_="runTest()" allow="fullscreen 'none'">
 </iframe>

Modified: trunk/LayoutTests/fullscreen/full-screen-restrictions.html (255161 => 255162)


--- trunk/LayoutTests/fullscreen/full-screen-restrictions.html	2020-01-27 20:29:14 UTC (rev 255161)
+++ trunk/LayoutTests/fullscreen/full-screen-restrictions.html	2020-01-27 20:54:54 UTC (rev 255162)
@@ -18,6 +18,7 @@
         var step2 = function() {
             consoleWrite('"The context object\'s node document, or an ancestor browsing context\'s document does not have the fullscreen enabled flag set."')
             var iframe = document.documentElement.appendChild(document.createElement('iframe'));
+            iframe.setAttribute('allow', "fullscreen 'none'");
             var div = iframe.contentDocument.documentElement.appendChild(iframe.contentDocument.createElement('div'));
 
             waitForEventOnce(iframe.contentDocument, 'webkitfullscreenerror', step3);

Added: trunk/LayoutTests/http/tests/fullscreen/fullscreen-feature-policy-expected.txt (0 => 255162)


--- trunk/LayoutTests/http/tests/fullscreen/fullscreen-feature-policy-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/http/tests/fullscreen/fullscreen-feature-policy-expected.txt	2020-01-27 20:54:54 UTC (rev 255162)
@@ -0,0 +1,25 @@
+PASS iframe with src="" should have document.webkitFullscreenEnabled === false.
+PASS iframe with src="" should have document.webkitFullscreenEnabled === true.
+PASS iframe with allow="fullscreen", src="" should have document.webkitFullscreenEnabled === true.
+PASS iframe with allow="fullscreen", src="" should have document.webkitFullscreenEnabled === true.
+PASS iframe with allow="fullscreen *", src="" should have document.webkitFullscreenEnabled === true.
+PASS iframe with allow="fullscreen *", src="" should have document.webkitFullscreenEnabled === true.
+PASS iframe with allow="fullscreen 'none'", src="" should have document.webkitFullscreenEnabled === false.
+PASS iframe with allow="fullscreen 'none'", src="" should have document.webkitFullscreenEnabled === false.
+PASS iframe with allow="fullscreen 'self'", src="" should have document.webkitFullscreenEnabled === false.
+PASS iframe with allow="fullscreen 'self'", src="" should have document.webkitFullscreenEnabled === true.
+PASS iframe with allow="fullscreen http://localhost:8000", src="" should have document.webkitFullscreenEnabled === true.
+PASS iframe with allow="fullscreen http://localhost:8000", src="" should have document.webkitFullscreenEnabled === false.
+PASS iframe with allowfullscreen, src="" should have document.webkitFullscreenEnabled === true.
+PASS iframe with allowfullscreen, src="" should have document.webkitFullscreenEnabled === true.
+PASS iframe with allow="fullscreen 'none'", allowfullscreen, src="" should have document.webkitFullscreenEnabled === false.
+PASS iframe with allow="fullscreen 'none'", allowfullscreen, src="" should have document.webkitFullscreenEnabled === false.
+PASS iframe with allow="fullscreen 'self'", allowfullscreen, src="" should have document.webkitFullscreenEnabled === false.
+PASS iframe with allow="fullscreen 'self'", allowfullscreen, src="" should have document.webkitFullscreenEnabled === true.
+PASS iframe with webkitallowfullscreen, src="" should have document.webkitFullscreenEnabled === true.
+PASS iframe with webkitallowfullscreen, src="" should have document.webkitFullscreenEnabled === true.
+PASS iframe with allow="fullscreen 'none'", webkitallowfullscreen, src="" should have document.webkitFullscreenEnabled === false.
+PASS iframe with allow="fullscreen 'none'", webkitallowfullscreen, src="" should have document.webkitFullscreenEnabled === false.
+PASS iframe with allow="fullscreen 'self'", webkitallowfullscreen, src="" should have document.webkitFullscreenEnabled === false.
+PASS iframe with allow="fullscreen 'self'", webkitallowfullscreen, src="" should have document.webkitFullscreenEnabled === true.
+

Added: trunk/LayoutTests/http/tests/fullscreen/fullscreen-feature-policy.html (0 => 255162)


--- trunk/LayoutTests/http/tests/fullscreen/fullscreen-feature-policy.html	                        (rev 0)
+++ trunk/LayoutTests/http/tests/fullscreen/fullscreen-feature-policy.html	2020-01-27 20:54:54 UTC (rev 255162)
@@ -0,0 +1,75 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+    <style>iframe { display: none; }</style>
+    <script src=""
+    <script>
+    if (window.testRunner) {
+        testRunner.dumpAsText();
+        testRunner.waitUntilDone();
+    }
+
+    function waitFor(element, type) {
+        return new Promise(resolve => {
+            element.addEventListener(type, event => {
+                resolve(event);
+            }, { once: true });
+        });
+    }
+
+    window.addEventListener('load', async event => {
+        try {
+            let attributeFilter = attribute => { return attribute.name !== 'data-enabled'; };
+            let attributeMap = attribute => {
+                if (attribute.value === '')
+                    return attribute.name;
+                if (attribute.name === 'src')
+                    return `${attribute.name}="${attribute.value.substring(0, 10)}..."`;
+                return `${attribute.name}="${attribute.value}"`;
+            }
+
+            for (var frame of document.querySelectorAll('iframe')) {
+                frame.contentWindow.postMessage(["eval", 'parent.postMessage(document.webkitFullscreenEnabled, "*")'], "*");
+                let messageEvent = await waitFor(window, 'message');
+                let expectedMessage = frame.getAttribute('data-enabled');
+                let frameAttributes = Array.prototype.filter.call(frame.attributes, attributeFilter).map(attributeMap);
+                let testDescription = `iframe with ${ frameAttributes.join(', ') } should have document.webkitFullscreenEnabled === ${ expectedMessage }`;
+                if (String(messageEvent.data) === expectedMessage)
+                    testPassed(`${testDescription}.`);
+                else
+                    testFailed(`${testDescription}, was ${ messageEvent.data }`);
+            }
+        } catch(e) {
+            testFailed(`Should not throw. Threw exception ${ e }.`)
+        }
+        if (window.testRunner)
+            testRunner.notifyDone();
+    });
+    </script>
+</head>
+<body>
+    <iframe data-enabled="false" src=""
+    <iframe data-enabled="true" src=""
+    <iframe allow="fullscreen" data-enabled="true" src=""
+    <iframe allow="fullscreen" data-enabled="true" src=""
+    <iframe allow="fullscreen *" data-enabled="true" src=""
+    <iframe allow="fullscreen *" data-enabled="true" src=""
+    <iframe allow="fullscreen 'none'" data-enabled="false" src=""
+    <iframe allow="fullscreen 'none'" data-enabled="false" src=""
+    <iframe allow="fullscreen 'self'" data-enabled="false" src=""
+    <iframe allow="fullscreen 'self'" data-enabled="true" src=""
+    <iframe allow="fullscreen http://localhost:8000" data-enabled="true" src=""
+    <iframe allow="fullscreen http://localhost:8000" data-enabled="false" src=""
+    <iframe allowfullscreen data-enabled="true"  src=""
+    <iframe allowfullscreen data-enabled="true" src=""
+    <iframe allow="fullscreen 'none'" allowfullscreen data-enabled="false" src=""
+    <iframe allow="fullscreen 'none'" allowfullscreen data-enabled="false" src=""
+    <iframe allow="fullscreen 'self'" allowfullscreen data-enabled="false" src=""
+    <iframe allow="fullscreen 'self'" allowfullscreen data-enabled="true" src=""
+    <iframe webkitallowfullscreen data-enabled="true" src=""
+    <iframe webkitallowfullscreen data-enabled="true" src=""
+    <iframe allow="fullscreen 'none'" webkitallowfullscreen data-enabled="false" src=""
+    <iframe allow="fullscreen 'none'" webkitallowfullscreen data-enabled="false" src=""
+    <iframe allow="fullscreen 'self'" webkitallowfullscreen data-enabled="false" src=""
+    <iframe allow="fullscreen 'self'" webkitallowfullscreen data-enabled="true" src=""
+</body>

Modified: trunk/Source/WebCore/ChangeLog (255161 => 255162)


--- trunk/Source/WebCore/ChangeLog	2020-01-27 20:29:14 UTC (rev 255161)
+++ trunk/Source/WebCore/ChangeLog	2020-01-27 20:54:54 UTC (rev 255162)
@@ -1,3 +1,42 @@
+2020-01-27  Jer Noble  <[email protected]>
+
+        Support 'allow="fullscreen"' feature policy
+        https://bugs.webkit.org/show_bug.cgi?id=206806
+        <rdar://problem/55640448>
+
+        Reviewed by Youenn Fablet.
+
+        Test: http/tests/fullscreen/fullscreen-feature-policy.html
+
+        The unprefixed version of the Fullscreen API has deprecated the 'allowfullscreen' iframe
+        attribute in favor of the 'allow="fullscreen"' style attribute used by Feature Policy.
+        Add support for such, including the specified handling for the legacy 'allowfullscreen'
+        attribute.
+
+        Note: this patch will (intentionally) change the default behavior of <iframe>s. Previously
+        any <iframe> without the "allowfullscreen" attribute would not be allowed to enter fullscreen
+        mode. After this patch, <iframes> without the legacy attribute or an explicit fullscreen
+        Feature Policy will be allowed to enter fullscreen so long as their origin is the same as
+        the top document (and that all parent iframes are also allowed to enter fullscreen).
+
+        * dom/FullscreenManager.cpp:
+        (WebCore::FullscreenManager::requestFullscreenForElement):
+        (WebCore::FullscreenManager::isFullscreenEnabled const):
+        (WebCore::isAttributeOnAllOwners): Deleted.
+        (WebCore::FullscreenManager::fullscreenIsAllowedForElement const): Deleted.
+        * dom/FullscreenManager.h:
+        * html/FeaturePolicy.cpp:
+        (WebCore::isFeaturePolicyAllowedByDocumentAndAllOwners):
+        (WebCore::FeaturePolicy::parse):
+        (WebCore::FeaturePolicy::allows const):
+        * html/FeaturePolicy.h:
+        * html/HTMLIFrameElement.cpp:
+        (WebCore::HTMLIFrameElement::parseAttribute):
+        (WebCore::HTMLIFrameElement::featurePolicy const):
+        * xml/XMLHttpRequest.cpp:
+        (WebCore::XMLHttpRequest::createRequest):
+        (WebCore::isSyncXHRAllowedByFeaturePolicy): Deleted.
+
 2020-01-27  Peng Liu  <[email protected]>
 
         Crash in WebCore::HTMLMediaElement::detachMediaSource()

Modified: trunk/Source/WebCore/dom/FullscreenManager.cpp (255161 => 255162)


--- trunk/Source/WebCore/dom/FullscreenManager.cpp	2020-01-27 20:29:14 UTC (rev 255161)
+++ trunk/Source/WebCore/dom/FullscreenManager.cpp	2020-01-27 20:54:54 UTC (rev 255162)
@@ -32,7 +32,7 @@
 #include "ChromeClient.h"
 #include "EventNames.h"
 #include "Frame.h"
-#include "HTMLFrameOwnerElement.h"
+#include "HTMLIFrameElement.h"
 #include "HTMLMediaElement.h"
 #include "Page.h"
 #include "QualifiedName.h"
@@ -44,17 +44,6 @@
 
 using namespace HTMLNames;
 
-static bool isAttributeOnAllOwners(const QualifiedName& attribute, const QualifiedName& prefixedAttribute, const HTMLFrameOwnerElement* owner)
-{
-    if (!owner)
-        return true;
-    do {
-        if (!(owner->hasAttribute(attribute) || owner->hasAttribute(prefixedAttribute)))
-            return false;
-    } while ((owner = owner->document().ownerElement()));
-    return true;
-}
-
 FullscreenManager::FullscreenManager(Document& document)
     : m_document { document }
 {
@@ -62,11 +51,6 @@
 
 FullscreenManager::~FullscreenManager() = default;
 
-bool FullscreenManager::fullscreenIsAllowedForElement(Element& element) const
-{
-    return isAttributeOnAllOwners(allowfullscreenAttr, webkitallowfullscreenAttr, element.document().ownerElement());
-}
-
 void FullscreenManager::requestFullscreenForElement(Element* element, FullscreenCheckType checkType)
 {
     if (!element)
@@ -142,7 +126,7 @@
 
         // The context object's node document, or an ancestor browsing context's document does not have
         // the fullscreen enabled flag set.
-        if (checkType == EnforceIFrameAllowFullscreenRequirement && !fullscreenIsAllowedForElement(*element)) {
+        if (checkType == EnforceIFrameAllowFullscreenRequirement && !isFeaturePolicyAllowedByDocumentAndAllOwners(FeaturePolicy::Type::Fullscreen, document())) {
             failedPreflights(WTFMove(element));
             return;
         }
@@ -345,7 +329,7 @@
     // browsing context's documents have their fullscreen enabled flag set, or false otherwise.
 
     // Top-level browsing contexts are implied to have their allowFullscreen attribute set.
-    return isAttributeOnAllOwners(allowfullscreenAttr, webkitallowfullscreenAttr, document().ownerElement());
+    return isFeaturePolicyAllowedByDocumentAndAllOwners(FeaturePolicy::Type::Fullscreen, document());
 }
 
 static void unwrapFullscreenRenderer(RenderFullScreen* fullscreenRenderer, Element* fullscreenElement)

Modified: trunk/Source/WebCore/dom/FullscreenManager.h (255161 => 255162)


--- trunk/Source/WebCore/dom/FullscreenManager.h	2020-01-27 20:29:14 UTC (rev 255161)
+++ trunk/Source/WebCore/dom/FullscreenManager.h	2020-01-27 20:54:54 UTC (rev 255162)
@@ -83,7 +83,6 @@
     RenderFullScreen* fullscreenRenderer() const;
 
     void dispatchFullscreenChangeEvents();
-    bool fullscreenIsAllowedForElement(Element&) const;
     void fullscreenElementRemoved();
 
     void adjustFullscreenElementOnNodeRemoval(Node&, Document::NodeRemoval = Document::NodeRemoval::Node);

Modified: trunk/Source/WebCore/html/FeaturePolicy.cpp (255161 => 255162)


--- trunk/Source/WebCore/html/FeaturePolicy.cpp	2020-01-27 20:29:14 UTC (rev 255161)
+++ trunk/Source/WebCore/html/FeaturePolicy.cpp	2020-01-27 20:54:54 UTC (rev 255162)
@@ -27,11 +27,36 @@
 #include "FeaturePolicy.h"
 
 #include "Document.h"
+#include "HTMLIFrameElement.h"
+#include "HTMLNames.h"
 #include "HTMLParserIdioms.h"
 #include "SecurityOrigin.h"
 
 namespace WebCore {
 
+using namespace HTMLNames;
+
+bool isFeaturePolicyAllowedByDocumentAndAllOwners(FeaturePolicy::Type type, const Document& document)
+{
+    auto& topDocument = document.topDocument();
+    auto ancestorDocument = &document;
+    while (ancestorDocument != &topDocument) {
+        if (!ancestorDocument)
+            return false;
+
+        auto ownerElement = ancestorDocument->ownerElement();
+        if (is<HTMLIFrameElement>(ownerElement)) {
+            auto featurePolicy = downcast<HTMLIFrameElement>(ownerElement)->featurePolicy();
+            if (!featurePolicy.allows(type, ancestorDocument->securityOrigin().data()))
+                return false;
+        }
+
+        ancestorDocument = ancestorDocument->parentDocument();
+    }
+
+    return true;
+}
+
 static bool isAllowedByFeaturePolicy(const FeaturePolicy::AllowRule& rule, const SecurityOriginData& origin)
 {
     switch (rule.type) {
@@ -94,7 +119,7 @@
     }
 }
 
-FeaturePolicy FeaturePolicy::parse(Document& document, StringView allowAttributeValue)
+FeaturePolicy FeaturePolicy::parse(Document& document, const HTMLIFrameElement& iframe, StringView allowAttributeValue)
 {
     FeaturePolicy policy;
     bool isCameraInitialized = false;
@@ -101,6 +126,7 @@
     bool isMicrophoneInitialized = false;
     bool isDisplayCaptureInitialized = false;
     bool isSyncXHRInitialized = false;
+    bool isFullscreenInitialized = false;
     for (auto allowItem : allowAttributeValue.split(';')) {
         auto item = allowItem.stripLeadingAndTrailingMatchedCharacters(isHTMLSpace<UChar>);
         if (item.startsWith("camera")) {
@@ -123,9 +149,14 @@
             updateList(document, policy.m_syncXHRRule, item.substring(8));
             continue;
         }
+        if (item.startsWith("fullscreen")) {
+            isFullscreenInitialized = true;
+            updateList(document, policy.m_fullscreenRule, item.substring(11));
+            continue;
+        }
     }
 
-    // By default, camera, microphone and display-capture policy is 'self'
+    // By default, camera, microphone, display-capture, and fullscreen policy is 'self'
     if (!isCameraInitialized)
         policy.m_cameraRule.allowedList.add(document.securityOrigin().data());
     if (!isMicrophoneInitialized)
@@ -133,6 +164,21 @@
     if (!isDisplayCaptureInitialized)
         policy.m_displayCaptureRule.allowedList.add(document.securityOrigin().data());
 
+    // https://w3c.github.io/webappsec-feature-policy/#process-feature-policy-attributes
+    // 9.5 Process Feature Policy Attributes
+    // 3.1 If element’s allowfullscreen attribute is specified, and container policy does
+    //     not contain an allowlist for fullscreen,
+    if (!isFullscreenInitialized) {
+        if (iframe.hasAttribute(allowfullscreenAttr) || iframe.hasAttribute(webkitallowfullscreenAttr)) {
+            // 3.1.1 Construct a new declaration for fullscreen, whose allowlist is the special value *.
+            policy.m_fullscreenRule.type = FeaturePolicy::AllowRule::Type::All;
+        } else {
+            // https://fullscreen.spec.whatwg.org/#feature-policy-integration
+            // The default allowlist is 'self'.
+            policy.m_fullscreenRule.allowedList.add(document.securityOrigin().data());
+        }
+    }
+
     if (!isSyncXHRInitialized)
         policy.m_syncXHRRule.type = AllowRule::Type::All;
 
@@ -150,6 +196,8 @@
         return isAllowedByFeaturePolicy(m_displayCaptureRule, origin);
     case Type::SyncXHR:
         return isAllowedByFeaturePolicy(m_syncXHRRule, origin);
+    case Type::Fullscreen:
+        return isAllowedByFeaturePolicy(m_fullscreenRule, origin);
     }
     ASSERT_NOT_REACHED();
     return false;

Modified: trunk/Source/WebCore/html/FeaturePolicy.h (255161 => 255162)


--- trunk/Source/WebCore/html/FeaturePolicy.h	2020-01-27 20:29:14 UTC (rev 255161)
+++ trunk/Source/WebCore/html/FeaturePolicy.h	2020-01-27 20:54:54 UTC (rev 255162)
@@ -32,12 +32,13 @@
 namespace WebCore {
 
 class Document;
+class HTMLIFrameElement;
 
 class FeaturePolicy {
 public:
-    static FeaturePolicy parse(Document&, StringView);
+    static FeaturePolicy parse(Document&, const HTMLIFrameElement&, StringView);
 
-    enum class Type { Camera, Microphone, DisplayCapture, SyncXHR };
+    enum class Type { Camera, Microphone, DisplayCapture, SyncXHR, Fullscreen };
     bool allows(Type, const SecurityOriginData&) const;
 
     struct AllowRule {
@@ -51,6 +52,9 @@
     AllowRule m_microphoneRule;
     AllowRule m_displayCaptureRule;
     AllowRule m_syncXHRRule;
+    AllowRule m_fullscreenRule;
 };
 
+extern bool isFeaturePolicyAllowedByDocumentAndAllOwners(FeaturePolicy::Type, const Document&);
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/html/HTMLIFrameElement.cpp (255161 => 255162)


--- trunk/Source/WebCore/html/HTMLIFrameElement.cpp	2020-01-27 20:29:14 UTC (rev 255161)
+++ trunk/Source/WebCore/html/HTMLIFrameElement.cpp	2020-01-27 20:54:54 UTC (rev 255162)
@@ -102,7 +102,7 @@
         setSandboxFlags(value.isNull() ? SandboxNone : SecurityContext::parseSandboxPolicy(value, invalidTokens));
         if (!invalidTokens.isNull())
             document().addConsoleMessage(MessageSource::Other, MessageLevel::Error, "Error while parsing the 'sandbox' attribute: " + invalidTokens);
-    } else if (name == allowAttr)
+    } else if (name == allowAttr || name == allowfullscreenAttr || name == webkitallowfullscreenAttr)
         m_featurePolicy = WTF::nullopt;
     else
         HTMLFrameElementBase::parseAttribute(name, value);
@@ -138,7 +138,7 @@
 const FeaturePolicy& HTMLIFrameElement::featurePolicy() const
 {
     if (!m_featurePolicy)
-        m_featurePolicy = FeaturePolicy::parse(document(), attributeWithoutSynchronization(allowAttr));
+        m_featurePolicy = FeaturePolicy::parse(document(), *this, attributeWithoutSynchronization(allowAttr));
     return *m_featurePolicy;
 }
 

Modified: trunk/Source/WebCore/xml/XMLHttpRequest.cpp (255161 => 255162)


--- trunk/Source/WebCore/xml/XMLHttpRequest.cpp	2020-01-27 20:29:14 UTC (rev 255161)
+++ trunk/Source/WebCore/xml/XMLHttpRequest.cpp	2020-01-27 20:54:54 UTC (rev 255162)
@@ -578,23 +578,6 @@
     return createRequest();
 }
 
-static inline bool isSyncXHRAllowedByFeaturePolicy(Document& document)
-{
-    auto& topDocument = document.topDocument();
-    if (&document != &topDocument) {
-        for (auto* ancestorDocument = &document; ancestorDocument != &topDocument; ancestorDocument = ancestorDocument->parentDocument()) {
-            auto* element = ancestorDocument->ownerElement();
-            ASSERT(element);
-            if (element && is<HTMLIFrameElement>(*element)) {
-                auto& featurePolicy = downcast<HTMLIFrameElement>(*element).featurePolicy();
-                if (!featurePolicy.allows(FeaturePolicy::Type::SyncXHR, ancestorDocument->securityOrigin().data()))
-                    return false;
-            }
-        }
-    }
-    return true;
-}
-
 ExceptionOr<void> XMLHttpRequest::createRequest()
 {
     // Only GET request is supported for blob URL.
@@ -668,7 +651,7 @@
         if (m_loader)
             setPendingActivity(*this);
     } else {
-        if (scriptExecutionContext()->isDocument() && !isSyncXHRAllowedByFeaturePolicy(*document()))
+        if (scriptExecutionContext()->isDocument() && !isFeaturePolicyAllowedByDocumentAndAllOwners(FeaturePolicy::Type::SyncXHR, *document()))
             return Exception { NetworkError };
 
         request.setDomainForCachePartition(scriptExecutionContext()->domainForCachePartition());
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to