Changeset 255162 in webkit


Ignore:
Timestamp:
Jan 27, 2020 12:54:54 PM (4 years ago)
Author:
commit-queue@webkit.org
Message:

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

Patch by Jer Noble <jer.noble@apple.com> 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.
Location:
trunk
Files:
2 added
2 deleted
12 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r255158 r255162  
     12020-01-27  Jer Noble  <jer.noble@apple.com>
     2
     3        Support 'allow="fullscreen"' feature policy
     4        https://bugs.webkit.org/show_bug.cgi?id=206806
     5        <rdar://problem/55640448>
     6
     7        Reviewed by Youenn Fablet.
     8
     9        * fullscreen/full-screen-enabled-prefixed.html:
     10        * fullscreen/full-screen-enabled.html:
     11        * fullscreen/full-screen-frameset-expected.txt: Removed.
     12        * fullscreen/full-screen-frameset.html: Removed.
     13        * fullscreen/full-screen-iframe-not-allowed.html:
     14        * fullscreen/full-screen-restrictions.html:
     15        * http/tests/fullscreen/fullscreen-feature-policy-expected.txt: Added.
     16        * http/tests/fullscreen/fullscreen-feature-policy.html: Added.
     17
    1182020-01-27  Said Abou-Hallawa  <sabouhallawa@apple.com>
    219
  • trunk/LayoutTests/fullscreen/full-screen-enabled-prefixed.html

    r143533 r255162  
    77    iframe.setAttribute('webkitallowfullscreen', 'true');
    88    var iframe2 = document.documentElement.appendChild(document.createElement('iframe'));
     9    iframe2.setAttribute('allow', "fullscreen 'none'");
    910    testExpected('iframe.contentDocument.webkitFullscreenEnabled', true);
    1011    testExpected('iframe2.contentDocument.webkitFullscreenEnabled', false);
  • trunk/LayoutTests/fullscreen/full-screen-enabled.html

    r143533 r255162  
    77    iframe.setAttribute('allowfullscreen', 'true');
    88    var iframe2 = document.documentElement.appendChild(document.createElement('iframe'));
     9    iframe2.setAttribute('allow', "fullscreen 'none'");
    910    testExpected('iframe.contentDocument.webkitFullscreenEnabled', true);
    1011    testExpected('iframe2.contentDocument.webkitFullscreenEnabled', false);
  • trunk/LayoutTests/fullscreen/full-screen-iframe-not-allowed.html

    r104838 r255162  
    2121}
    2222</script>
    23 <iframe id="frame" src="resources/inner.html" onload="runTest()">
     23<iframe id="frame" src="resources/inner.html" onload="runTest()" allow="fullscreen 'none'">
    2424</iframe>
  • trunk/LayoutTests/fullscreen/full-screen-restrictions.html

    r120190 r255162  
    1919            consoleWrite('"The context object\'s node document, or an ancestor browsing context\'s document does not have the fullscreen enabled flag set."')
    2020            var iframe = document.documentElement.appendChild(document.createElement('iframe'));
     21            iframe.setAttribute('allow', "fullscreen 'none'");
    2122            var div = iframe.contentDocument.documentElement.appendChild(iframe.contentDocument.createElement('div'));
    2223
  • trunk/Source/WebCore/ChangeLog

    r255161 r255162  
     12020-01-27  Jer Noble  <jer.noble@apple.com>
     2
     3        Support 'allow="fullscreen"' feature policy
     4        https://bugs.webkit.org/show_bug.cgi?id=206806
     5        <rdar://problem/55640448>
     6
     7        Reviewed by Youenn Fablet.
     8
     9        Test: http/tests/fullscreen/fullscreen-feature-policy.html
     10
     11        The unprefixed version of the Fullscreen API has deprecated the 'allowfullscreen' iframe
     12        attribute in favor of the 'allow="fullscreen"' style attribute used by Feature Policy.
     13        Add support for such, including the specified handling for the legacy 'allowfullscreen'
     14        attribute.
     15
     16        Note: this patch will (intentionally) change the default behavior of <iframe>s. Previously
     17        any <iframe> without the "allowfullscreen" attribute would not be allowed to enter fullscreen
     18        mode. After this patch, <iframes> without the legacy attribute or an explicit fullscreen
     19        Feature Policy will be allowed to enter fullscreen so long as their origin is the same as
     20        the top document (and that all parent iframes are also allowed to enter fullscreen).
     21
     22        * dom/FullscreenManager.cpp:
     23        (WebCore::FullscreenManager::requestFullscreenForElement):
     24        (WebCore::FullscreenManager::isFullscreenEnabled const):
     25        (WebCore::isAttributeOnAllOwners): Deleted.
     26        (WebCore::FullscreenManager::fullscreenIsAllowedForElement const): Deleted.
     27        * dom/FullscreenManager.h:
     28        * html/FeaturePolicy.cpp:
     29        (WebCore::isFeaturePolicyAllowedByDocumentAndAllOwners):
     30        (WebCore::FeaturePolicy::parse):
     31        (WebCore::FeaturePolicy::allows const):
     32        * html/FeaturePolicy.h:
     33        * html/HTMLIFrameElement.cpp:
     34        (WebCore::HTMLIFrameElement::parseAttribute):
     35        (WebCore::HTMLIFrameElement::featurePolicy const):
     36        * xml/XMLHttpRequest.cpp:
     37        (WebCore::XMLHttpRequest::createRequest):
     38        (WebCore::isSyncXHRAllowedByFeaturePolicy): Deleted.
     39
    1402020-01-27  Peng Liu  <peng.liu6@apple.com>
    241
  • trunk/Source/WebCore/dom/FullscreenManager.cpp

    r253923 r255162  
    3333#include "EventNames.h"
    3434#include "Frame.h"
    35 #include "HTMLFrameOwnerElement.h"
     35#include "HTMLIFrameElement.h"
    3636#include "HTMLMediaElement.h"
    3737#include "Page.h"
     
    4545using namespace HTMLNames;
    4646
    47 static bool isAttributeOnAllOwners(const QualifiedName& attribute, const QualifiedName& prefixedAttribute, const HTMLFrameOwnerElement* owner)
    48 {
    49     if (!owner)
    50         return true;
    51     do {
    52         if (!(owner->hasAttribute(attribute) || owner->hasAttribute(prefixedAttribute)))
    53             return false;
    54     } while ((owner = owner->document().ownerElement()));
    55     return true;
    56 }
    57 
    5847FullscreenManager::FullscreenManager(Document& document)
    5948    : m_document { document }
     
    6251
    6352FullscreenManager::~FullscreenManager() = default;
    64 
    65 bool FullscreenManager::fullscreenIsAllowedForElement(Element& element) const
    66 {
    67     return isAttributeOnAllOwners(allowfullscreenAttr, webkitallowfullscreenAttr, element.document().ownerElement());
    68 }
    6953
    7054void FullscreenManager::requestFullscreenForElement(Element* element, FullscreenCheckType checkType)
     
    143127        // The context object's node document, or an ancestor browsing context's document does not have
    144128        // the fullscreen enabled flag set.
    145         if (checkType == EnforceIFrameAllowFullscreenRequirement && !fullscreenIsAllowedForElement(*element)) {
     129        if (checkType == EnforceIFrameAllowFullscreenRequirement && !isFeaturePolicyAllowedByDocumentAndAllOwners(FeaturePolicy::Type::Fullscreen, document())) {
    146130            failedPreflights(WTFMove(element));
    147131            return;
     
    346330
    347331    // Top-level browsing contexts are implied to have their allowFullscreen attribute set.
    348     return isAttributeOnAllOwners(allowfullscreenAttr, webkitallowfullscreenAttr, document().ownerElement());
     332    return isFeaturePolicyAllowedByDocumentAndAllOwners(FeaturePolicy::Type::Fullscreen, document());
    349333}
    350334
  • trunk/Source/WebCore/dom/FullscreenManager.h

    r251220 r255162  
    8484
    8585    void dispatchFullscreenChangeEvents();
    86     bool fullscreenIsAllowedForElement(Element&) const;
    8786    void fullscreenElementRemoved();
    8887
  • trunk/Source/WebCore/html/FeaturePolicy.cpp

    r250288 r255162  
    2828
    2929#include "Document.h"
     30#include "HTMLIFrameElement.h"
     31#include "HTMLNames.h"
    3032#include "HTMLParserIdioms.h"
    3133#include "SecurityOrigin.h"
    3234
    3335namespace WebCore {
     36
     37using namespace HTMLNames;
     38
     39bool isFeaturePolicyAllowedByDocumentAndAllOwners(FeaturePolicy::Type type, const Document& document)
     40{
     41    auto& topDocument = document.topDocument();
     42    auto ancestorDocument = &document;
     43    while (ancestorDocument != &topDocument) {
     44        if (!ancestorDocument)
     45            return false;
     46
     47        auto ownerElement = ancestorDocument->ownerElement();
     48        if (is<HTMLIFrameElement>(ownerElement)) {
     49            auto featurePolicy = downcast<HTMLIFrameElement>(ownerElement)->featurePolicy();
     50            if (!featurePolicy.allows(type, ancestorDocument->securityOrigin().data()))
     51                return false;
     52        }
     53
     54        ancestorDocument = ancestorDocument->parentDocument();
     55    }
     56
     57    return true;
     58}
    3459
    3560static bool isAllowedByFeaturePolicy(const FeaturePolicy::AllowRule& rule, const SecurityOriginData& origin)
     
    95120}
    96121
    97 FeaturePolicy FeaturePolicy::parse(Document& document, StringView allowAttributeValue)
     122FeaturePolicy FeaturePolicy::parse(Document& document, const HTMLIFrameElement& iframe, StringView allowAttributeValue)
    98123{
    99124    FeaturePolicy policy;
     
    102127    bool isDisplayCaptureInitialized = false;
    103128    bool isSyncXHRInitialized = false;
     129    bool isFullscreenInitialized = false;
    104130    for (auto allowItem : allowAttributeValue.split(';')) {
    105131        auto item = allowItem.stripLeadingAndTrailingMatchedCharacters(isHTMLSpace<UChar>);
     
    124150            continue;
    125151        }
    126     }
    127 
    128     // By default, camera, microphone and display-capture policy is 'self'
     152        if (item.startsWith("fullscreen")) {
     153            isFullscreenInitialized = true;
     154            updateList(document, policy.m_fullscreenRule, item.substring(11));
     155            continue;
     156        }
     157    }
     158
     159    // By default, camera, microphone, display-capture, and fullscreen policy is 'self'
    129160    if (!isCameraInitialized)
    130161        policy.m_cameraRule.allowedList.add(document.securityOrigin().data());
     
    133164    if (!isDisplayCaptureInitialized)
    134165        policy.m_displayCaptureRule.allowedList.add(document.securityOrigin().data());
     166
     167    // https://w3c.github.io/webappsec-feature-policy/#process-feature-policy-attributes
     168    // 9.5 Process Feature Policy Attributes
     169    // 3.1 If element’s allowfullscreen attribute is specified, and container policy does
     170    //     not contain an allowlist for fullscreen,
     171    if (!isFullscreenInitialized) {
     172        if (iframe.hasAttribute(allowfullscreenAttr) || iframe.hasAttribute(webkitallowfullscreenAttr)) {
     173            // 3.1.1 Construct a new declaration for fullscreen, whose allowlist is the special value *.
     174            policy.m_fullscreenRule.type = FeaturePolicy::AllowRule::Type::All;
     175        } else {
     176            // https://fullscreen.spec.whatwg.org/#feature-policy-integration
     177            // The default allowlist is 'self'.
     178            policy.m_fullscreenRule.allowedList.add(document.securityOrigin().data());
     179        }
     180    }
    135181
    136182    if (!isSyncXHRInitialized)
     
    151197    case Type::SyncXHR:
    152198        return isAllowedByFeaturePolicy(m_syncXHRRule, origin);
     199    case Type::Fullscreen:
     200        return isAllowedByFeaturePolicy(m_fullscreenRule, origin);
    153201    }
    154202    ASSERT_NOT_REACHED();
  • trunk/Source/WebCore/html/FeaturePolicy.h

    r250288 r255162  
    3333
    3434class Document;
     35class HTMLIFrameElement;
    3536
    3637class FeaturePolicy {
    3738public:
    38     static FeaturePolicy parse(Document&, StringView);
     39    static FeaturePolicy parse(Document&, const HTMLIFrameElement&, StringView);
    3940
    40     enum class Type { Camera, Microphone, DisplayCapture, SyncXHR };
     41    enum class Type { Camera, Microphone, DisplayCapture, SyncXHR, Fullscreen };
    4142    bool allows(Type, const SecurityOriginData&) const;
    4243
     
    5253    AllowRule m_displayCaptureRule;
    5354    AllowRule m_syncXHRRule;
     55    AllowRule m_fullscreenRule;
    5456};
    5557
     58extern bool isFeaturePolicyAllowedByDocumentAndAllOwners(FeaturePolicy::Type, const Document&);
     59
    5660} // namespace WebCore
  • trunk/Source/WebCore/html/HTMLIFrameElement.cpp

    r252392 r255162  
    103103        if (!invalidTokens.isNull())
    104104            document().addConsoleMessage(MessageSource::Other, MessageLevel::Error, "Error while parsing the 'sandbox' attribute: " + invalidTokens);
    105     } else if (name == allowAttr)
     105    } else if (name == allowAttr || name == allowfullscreenAttr || name == webkitallowfullscreenAttr)
    106106        m_featurePolicy = WTF::nullopt;
    107107    else
     
    139139{
    140140    if (!m_featurePolicy)
    141         m_featurePolicy = FeaturePolicy::parse(document(), attributeWithoutSynchronization(allowAttr));
     141        m_featurePolicy = FeaturePolicy::parse(document(), *this, attributeWithoutSynchronization(allowAttr));
    142142    return *m_featurePolicy;
    143143}
  • trunk/Source/WebCore/xml/XMLHttpRequest.cpp

    r254652 r255162  
    579579}
    580580
    581 static inline bool isSyncXHRAllowedByFeaturePolicy(Document& document)
    582 {
    583     auto& topDocument = document.topDocument();
    584     if (&document != &topDocument) {
    585         for (auto* ancestorDocument = &document; ancestorDocument != &topDocument; ancestorDocument = ancestorDocument->parentDocument()) {
    586             auto* element = ancestorDocument->ownerElement();
    587             ASSERT(element);
    588             if (element && is<HTMLIFrameElement>(*element)) {
    589                 auto& featurePolicy = downcast<HTMLIFrameElement>(*element).featurePolicy();
    590                 if (!featurePolicy.allows(FeaturePolicy::Type::SyncXHR, ancestorDocument->securityOrigin().data()))
    591                     return false;
    592             }
    593         }
    594     }
    595     return true;
    596 }
    597 
    598581ExceptionOr<void> XMLHttpRequest::createRequest()
    599582{
     
    669652            setPendingActivity(*this);
    670653    } else {
    671         if (scriptExecutionContext()->isDocument() && !isSyncXHRAllowedByFeaturePolicy(*document()))
     654        if (scriptExecutionContext()->isDocument() && !isFeaturePolicyAllowedByDocumentAndAllOwners(FeaturePolicy::Type::SyncXHR, *document()))
    672655            return Exception { NetworkError };
    673656
Note: See TracChangeset for help on using the changeset viewer.