diff --git a/LayoutTests/http/tests/identity/allow-attribute.https-expected.txt b/LayoutTests/http/tests/identity/allow-attribute.https-expected.txt new file mode 100644 index 0000000000000..29967b1b6e95b --- /dev/null +++ b/LayoutTests/http/tests/identity/allow-attribute.https-expected.txt @@ -0,0 +1,13 @@ +PASS is allowed to call get() +PASS is not allowed to call get() +PASS is allowed to call get() +PASS is allowed to call get() +PASS is allowed to call get() +PASS is allowed to call get() +PASS is not allowed to call get() +PASS is not allowed to call get() +PASS is not allowed to call get() +PASS is allowed to call get() +PASS is allowed to call get() +PASS is not allowed to call get() + diff --git a/LayoutTests/http/tests/identity/allow-attribute.https.html b/LayoutTests/http/tests/identity/allow-attribute.https.html new file mode 100644 index 0000000000000..183d6b6769915 --- /dev/null +++ b/LayoutTests/http/tests/identity/allow-attribute.https.html @@ -0,0 +1,133 @@ + + + + + Test allow attribute with "digital-credentials-get" and + CredentialsContainer's .get() method + + + + + + diff --git a/LayoutTests/http/tests/identity/resources/iframe.html b/LayoutTests/http/tests/identity/resources/iframe.html new file mode 100644 index 0000000000000..398f9ac4e7603 --- /dev/null +++ b/LayoutTests/http/tests/identity/resources/iframe.html @@ -0,0 +1,33 @@ + + + +

Digital Credentials API

+ diff --git a/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/default-permissions-policy.https.sub-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/default-permissions-policy.https.sub-expected.txt new file mode 100644 index 0000000000000..4eb103f9c0c3f --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/default-permissions-policy.https.sub-expected.txt @@ -0,0 +1,3 @@ + +PASS Permissions-Policy is by default 'self'. + diff --git a/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/default-permissions-policy.https.sub.html b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/default-permissions-policy.https.sub.html new file mode 100644 index 0000000000000..34a40bdcfe746 --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/default-permissions-policy.https.sub.html @@ -0,0 +1,42 @@ + + + + + + + + + + diff --git a/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/disabled-by-permissions-policy.https.sub-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/disabled-by-permissions-policy.https.sub-expected.txt new file mode 100644 index 0000000000000..c9abd2a0657ad --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/disabled-by-permissions-policy.https.sub-expected.txt @@ -0,0 +1,5 @@ + + +FAIL Permissions-Policy header digital-credentials-get=() disallows the top-level document. promise_rejects_dom: function "function() { throw e }" threw object "TypeError: At least one provider must be specified." that is not a DOMException NotAllowedError: property "code" is equal to undefined, expected 0 +FAIL Permissions-Policy header digital-credentials-get=() disallows same-origin iframes. assert_false: Digital Credential API expected false got true + diff --git a/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/disabled-by-permissions-policy.https.sub.html b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/disabled-by-permissions-policy.https.sub.html new file mode 100644 index 0000000000000..65b58066349da --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/disabled-by-permissions-policy.https.sub.html @@ -0,0 +1,36 @@ + + + + + + + + + + diff --git a/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/disabled-by-permissions-policy.https.sub.html.headers b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/disabled-by-permissions-policy.https.sub.html.headers new file mode 100644 index 0000000000000..02a76b7c3f289 --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/disabled-by-permissions-policy.https.sub.html.headers @@ -0,0 +1 @@ +Permissions-Policy: digital-credentials-get=() diff --git a/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/enabled-on-self-origin-by-permissions-policy.https.sub-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/enabled-on-self-origin-by-permissions-policy.https.sub-expected.txt new file mode 100644 index 0000000000000..2a904d018e058 --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/enabled-on-self-origin-by-permissions-policy.https.sub-expected.txt @@ -0,0 +1,6 @@ + +PASS Permissions-Policy header digital-credentials-get=(self) allows the top-level document. +PASS Permissions-Policy header digital-credentials-get=(self) allows same-origin iframes. +PASS Permissions-Policy header digital-credentials-get=(self) disallows cross-origin iframes. +PASS Permissions-Policy header digital-credentials-get=(self) gets overridden by allow attribute. + diff --git a/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/enabled-on-self-origin-by-permissions-policy.https.sub.html b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/enabled-on-self-origin-by-permissions-policy.https.sub.html new file mode 100644 index 0000000000000..019be25fa2d90 --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/enabled-on-self-origin-by-permissions-policy.https.sub.html @@ -0,0 +1,59 @@ + + + + + + + + + + diff --git a/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/enabled-on-self-origin-by-permissions-policy.https.sub.html.headers b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/enabled-on-self-origin-by-permissions-policy.https.sub.html.headers new file mode 100644 index 0000000000000..1207d9e29a111 --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/enabled-on-self-origin-by-permissions-policy.https.sub.html.headers @@ -0,0 +1 @@ +Permissions-Policy: digital-credentials-get=(self) diff --git a/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/override-permissions-policy.https.sub-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/override-permissions-policy.https.sub-expected.txt new file mode 100644 index 0000000000000..889badd382c60 --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/override-permissions-policy.https.sub-expected.txt @@ -0,0 +1,5 @@ + + +PASS Header-set policy is overridden in cross-origin iframe using allow attribute. +FAIL Setting digital-credentials-get=(self) disallows the API in same-origin iframes. assert_false: Digital Credential API expected false got true + diff --git a/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/override-permissions-policy.https.sub.html b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/override-permissions-policy.https.sub.html new file mode 100644 index 0000000000000..393949f4116d2 --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/override-permissions-policy.https.sub.html @@ -0,0 +1,39 @@ + + + + + + + + + + diff --git a/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/override-permissions-policy.https.sub.html.headers b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/override-permissions-policy.https.sub.html.headers new file mode 100644 index 0000000000000..02a76b7c3f289 --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/override-permissions-policy.https.sub.html.headers @@ -0,0 +1 @@ +Permissions-Policy: digital-credentials-get=() diff --git a/LayoutTests/imported/w3c/web-platform-tests/permissions-policy/resources/digital-credentials-get.html b/LayoutTests/imported/w3c/web-platform-tests/permissions-policy/resources/digital-credentials-get.html new file mode 100644 index 0000000000000..4b212756c2291 --- /dev/null +++ b/LayoutTests/imported/w3c/web-platform-tests/permissions-policy/resources/digital-credentials-get.html @@ -0,0 +1,33 @@ + + + + + + + +

Digital Credentials iframe

+ diff --git a/LayoutTests/imported/w3c/web-platform-tests/permissions-policy/resources/permissions-policy.js b/LayoutTests/imported/w3c/web-platform-tests/permissions-policy/resources/permissions-policy.js index d700cb086b362..cfc6d3caab103 100644 --- a/LayoutTests/imported/w3c/web-platform-tests/permissions-policy/resources/permissions-policy.js +++ b/LayoutTests/imported/w3c/web-platform-tests/permissions-policy/resources/permissions-policy.js @@ -30,7 +30,7 @@ function assert_permissions_policy_supported() { // promise. Used by test_feature_availability_with_post_message_result() function test_feature_availability( feature_descriptionOrObject, test, src, expect_feature_available, feature_name, - allowfullscreen, is_promise_test = false) { + allowfullscreen, is_promise_test = false, needs_focus = false) { if (feature_descriptionOrObject && feature_descriptionOrObject instanceof Object) { const { @@ -41,6 +41,7 @@ function test_feature_availability( feature_name, allowfullscreen, is_promise_test, + needs_focus, } = feature_descriptionOrObject; return test_feature_availability( feature_description, @@ -49,7 +50,8 @@ function test_feature_availability( expect_feature_available, feature_name, allowfullscreen, - is_promise_test + is_promise_test, + needs_focus, ); } @@ -84,6 +86,9 @@ function test_feature_availability( window.addEventListener('message', resolve); }).then(expectFeatureAvailable); document.body.appendChild(frame); + if (needs_focus) { + frame.focus(); + } return promise; } diff --git a/LayoutTests/platform/glib/TestExpectations b/LayoutTests/platform/glib/TestExpectations index 08b1954dec2e1..b6ec8c2ff0c16 100644 --- a/LayoutTests/platform/glib/TestExpectations +++ b/LayoutTests/platform/glib/TestExpectations @@ -2805,6 +2805,7 @@ imported/w3c/web-platform-tests/credential-management/ [ Skip ] # Digital Crendentials API http/wpt/identity/ [ Skip ] +http/tests/identity/ [ Skip ] imported/w3c/web-platform-tests/digital-credentials/ [ Skip ] # WebGL2 diff --git a/LayoutTests/platform/mac-site-isolation/TestExpectations b/LayoutTests/platform/mac-site-isolation/TestExpectations index 44577274a23d9..2ae2f6e77f962 100644 --- a/LayoutTests/platform/mac-site-isolation/TestExpectations +++ b/LayoutTests/platform/mac-site-isolation/TestExpectations @@ -5195,6 +5195,7 @@ http/wpt/html/semantics/scripting-1/the-script-element/module/module-meta-url-re http/wpt/html/semantics/scripting-1/the-script-element/module/module-meta-url-with-fragment.html [ Skip ] http/wpt/html/semantics/text-level-semantics/the-a-element/a-download-click-404.html [ Skip ] http/wpt/identity/identitycredentialscontainer-create-basics.https.html [ Skip ] +http/tests/identity/allow-attribute.https.html [ Skip ] http/wpt/identity/identitycredentialscontainer-get-basics.https.html [ Skip ] http/wpt/identity/identitycredentialscontainer-store-basics.https.html [ Skip ] http/wpt/identity/idl.https.html [ Skip ] diff --git a/LayoutTests/platform/mac-wk1/TestExpectations b/LayoutTests/platform/mac-wk1/TestExpectations index bf49b40b02eb9..b5a56d7993cd8 100644 --- a/LayoutTests/platform/mac-wk1/TestExpectations +++ b/LayoutTests/platform/mac-wk1/TestExpectations @@ -1822,6 +1822,7 @@ imported/w3c/web-platform-tests/credential-management/ [ Skip ] # Skip Digital Credentials API http/wpt/identity/ [ Skip ] +http/tests/identity/ [ Skip ] imported/w3c/web-platform-tests/digital-credentials/ [ Skip ] webkit.org/b/182554 transitions/transition-display-property.html [ Pass ImageOnlyFailure ] diff --git a/LayoutTests/platform/win/TestExpectations b/LayoutTests/platform/win/TestExpectations index 680d1957c1b99..6ec62760c4128 100644 --- a/LayoutTests/platform/win/TestExpectations +++ b/LayoutTests/platform/win/TestExpectations @@ -1701,6 +1701,7 @@ http/wpt/css/css-highlight-api [ Skip ] http/wpt/entries-api [ Skip ] http/wpt/geometry [ Skip ] http/wpt/identity [ Skip ] +http/tests/identity [ Skip ] http/wpt/loading/redirect-headers.html [ Skip ] # Failure diff --git a/Source/WebCore/Modules/identity/IdentityCredentialsContainer.cpp b/Source/WebCore/Modules/identity/IdentityCredentialsContainer.cpp index fd61ff72fc4f8..2eeed44c83ec2 100644 --- a/Source/WebCore/Modules/identity/IdentityCredentialsContainer.cpp +++ b/Source/WebCore/Modules/identity/IdentityCredentialsContainer.cpp @@ -51,6 +51,11 @@ void IdentityCredentialsContainer::get(CredentialRequestOptions&& options, Crede return; RefPtr document = this->document(); + if (!PermissionsPolicy::isFeatureEnabled(PermissionsPolicy::Feature::DigitalCredentialsGetRule, *document, PermissionsPolicy::ShouldReportViolation::No)) { + promise.reject(Exception { ExceptionCode::NotAllowedError, "Third-party iframes are not allowed to call .get() unless explicitly allowed via Permissions Policy (digital-credentials-get)"_s }); + return; + } + if (!document->hasFocus()) { promise.reject(Exception { ExceptionCode::NotAllowedError, "The document is not focused."_s }); return; diff --git a/Source/WebCore/html/PermissionsPolicy.cpp b/Source/WebCore/html/PermissionsPolicy.cpp index 0d10bb914d774..ce3c0f64120e7 100644 --- a/Source/WebCore/html/PermissionsPolicy.cpp +++ b/Source/WebCore/html/PermissionsPolicy.cpp @@ -77,6 +77,8 @@ static ASCIILiteral toFeatureNameForLogging(PermissionsPolicy::Feature feature) #if ENABLE(WEB_AUTHN) case PermissionsPolicy::Feature::PublickeyCredentialsGetRule: return "PublickeyCredentialsGet"_s; + case PermissionsPolicy::Feature::DigitalCredentialsGetRule: + return "DigitalCredentialsGet"_s; #endif #if ENABLE(WEBXR) case PermissionsPolicy::Feature::XRSpatialTracking: @@ -117,6 +119,7 @@ static std::pair readFeatureIdentifier(S #endif #if ENABLE(WEB_AUTHN) constexpr auto publickeyCredentialsGetRuleToken { "publickey-credentials-get"_s }; + constexpr auto digitalCredentialsGetRuleToken { "digital-credentials-get"_s }; #endif #if ENABLE(WEBXR) constexpr auto xrSpatialTrackingToken { "xr-spatial-tracking"_s }; @@ -171,6 +174,9 @@ static std::pair readFeatureIdentifier(S } else if (value.startsWith(publickeyCredentialsGetRuleToken)) { feature = PermissionsPolicy::Feature::PublickeyCredentialsGetRule; remainingValue = value.substring(publickeyCredentialsGetRuleToken.length()); + } else if (value.startsWith(digitalCredentialsGetRuleToken)) { + feature = PermissionsPolicy::Feature::DigitalCredentialsGetRule; + remainingValue = value.substring(digitalCredentialsGetRuleToken.length()); #endif #if ENABLE(WEBXR) } else if (value.startsWith(xrSpatialTrackingToken)) { @@ -213,6 +219,7 @@ static ASCIILiteral defaultAllowlistValue(PermissionsPolicy::Feature feature) #endif #if ENABLE(WEB_AUTHN) case PermissionsPolicy::Feature::PublickeyCredentialsGetRule: + case PermissionsPolicy::Feature::DigitalCredentialsGetRule: #endif #if ENABLE(WEBXR) case PermissionsPolicy::Feature::XRSpatialTracking: diff --git a/Source/WebCore/html/PermissionsPolicy.h b/Source/WebCore/html/PermissionsPolicy.h index 331340b332068..577f8a2270878 100644 --- a/Source/WebCore/html/PermissionsPolicy.h +++ b/Source/WebCore/html/PermissionsPolicy.h @@ -63,6 +63,7 @@ class PermissionsPolicy { #endif #if ENABLE(WEB_AUTHN) PublickeyCredentialsGetRule, + DigitalCredentialsGetRule, #endif #if ENABLE(WEBXR) XRSpatialTracking, diff --git a/Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in b/Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in index 2553619355c0b..54bfa4555c6dd 100644 --- a/Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in +++ b/Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in @@ -8320,6 +8320,7 @@ struct WebCore::OwnerPermissionsPolicyData { #endif #if ENABLE(WEB_AUTHN) PublickeyCredentialsGetRule, + DigitalCredentialsGetRule, #endif #if ENABLE(WEBXR) XRSpatialTracking,