From 58fcbbf0528d7eba283f558ff097a28c03fd5666 Mon Sep 17 00:00:00 2001 From: Marcos Caceres Date: Wed, 4 Sep 2024 05:01:13 -0700 Subject: [PATCH] Digital Credentials API: handle mediation requirement https://bugs.webkit.org/show_bug.cgi?id=277322 rdar://133266859 Reviewed by Anne van Kesteren. Make sure mediation is alway required when getting digital credentials as required by the spec: https://github.com/WICG/digital-credentials/pull/149 * LayoutTests/http/wpt/identity/identitycredentialscontainer-get-hidden.https.html: * LayoutTests/imported/w3c/web-platform-tests/digital-credentials/allow-attribute.https.html: * LayoutTests/imported/w3c/web-platform-tests/digital-credentials/dc-types.ts: * LayoutTests/imported/w3c/web-platform-tests/digital-credentials/default-permissions-policy.https.sub.html: * LayoutTests/imported/w3c/web-platform-tests/digital-credentials/disabled-by-permissions-policy.https.sub.html: * LayoutTests/imported/w3c/web-platform-tests/digital-credentials/enabled-on-self-origin-by-permissions-policy.https.sub.html: * LayoutTests/imported/w3c/web-platform-tests/digital-credentials/identity-get.tentative.https-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/digital-credentials/identity-get.tentative.https.html: * LayoutTests/imported/w3c/web-platform-tests/digital-credentials/support/helper.js: (export.makeGetOptions): * LayoutTests/imported/w3c/web-platform-tests/permissions-policy/resources/digital-credentials-get.html: * LayoutTests/platform/ios/imported/w3c/web-platform-tests/digital-credentials/identity-get.tentative.https-expected.txt: * Source/WebCore/Modules/identity/IdentityCredentialsContainer.cpp: (WebCore::IdentityCredentialsContainer::get): Canonical link: https://commits.webkit.org/283148@main --- ...itycredentialscontainer-get-hidden.https.html | 1 + .../allow-attribute.https.html | 1 + .../digital-credentials/dc-types.ts | 16 +++++++++++++--- .../default-permissions-policy.https.sub.html | 6 +++--- ...disabled-by-permissions-policy.https.sub.html | 6 +++--- ...f-origin-by-permissions-policy.https.sub.html | 6 +++--- .../identity-get.tentative.https-expected.txt | 1 + .../identity-get.tentative.https.html | 9 +++++++++ .../digital-credentials/support/helper.js | 8 ++++---- .../resources/digital-credentials-get.html | 9 +++++---- .../identity-get.tentative.https-expected.txt | 1 + .../identity/IdentityCredentialsContainer.cpp | 9 ++++++--- 12 files changed, 50 insertions(+), 23 deletions(-) diff --git a/LayoutTests/http/wpt/identity/identitycredentialscontainer-get-hidden.https.html b/LayoutTests/http/wpt/identity/identitycredentialscontainer-get-hidden.https.html index 6b562ed31365b..430198eee2ab8 100644 --- a/LayoutTests/http/wpt/identity/identitycredentialscontainer-get-hidden.https.html +++ b/LayoutTests/http/wpt/identity/identitycredentialscontainer-get-hidden.https.html @@ -40,6 +40,7 @@ digital: { providers: [], }, + mediation: "required", }); await promise_rejects_dom(t, "NotAllowedError", p); diff --git a/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/allow-attribute.https.html b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/allow-attribute.https.html index a42a3b68f0e88..0d66e28e72076 100644 --- a/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/allow-attribute.https.html +++ b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/allow-attribute.https.html @@ -105,6 +105,7 @@ // Results in TypeError when allowed, NotAllowedError when disallowed providers: [], }, + mediation: "required", }; const { data } = await new Promise((resolve) => { window.addEventListener("message", resolve, { diff --git a/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/dc-types.ts b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/dc-types.ts index f2b7e3a172c35..6ea100c6727d6 100644 --- a/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/dc-types.ts +++ b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/dc-types.ts @@ -1,4 +1,9 @@ export type ProviderType = "default" | "openid4vp"; +export type CredentialMediationRequirement = + | "conditional" + | "optional" + | "required" + | "silent"; /** * @see https://wicg.github.io/digital-credentials/#dom-identityrequestprovider @@ -26,12 +31,17 @@ export interface CredentialRequestOptions { * The digital credential request options. */ digital: DigitalCredentialRequestOptions; + mediation: CredentialMediationRequirement; } /** * The actions that can be performed on the API via the iframe. */ -export type IframeActionType = "create" | "get" | "ping" | "preventSilentAccess" ; +export type IframeActionType = + | "create" + | "get" + | "ping" + | "preventSilentAccess"; /** * If present, when the abort controller should be aborted @@ -53,8 +63,8 @@ export interface EventData { */ options?: object; /** - * If the API needs to blessed before the action is performed. - */ + * If the API needs to blessed before the action is performed. + */ needsUserActivation?: boolean; } 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 index fa3309ac2b403..1d46c53736073 100644 --- 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 @@ -7,8 +7,8 @@ - - - diff --git a/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/support/helper.js b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/support/helper.js index 6bbcdb2cd3eb8..60be755fa0ee9 100644 --- a/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/support/helper.js +++ b/LayoutTests/imported/w3c/web-platform-tests/digital-credentials/support/helper.js @@ -9,16 +9,17 @@ */ /** * @param {ProviderType | ProviderType[]} [providersToUse=["default"]] + * @param {CredentialMediationRequirement} [mediation="required"] * @returns {CredentialRequestOptions} */ -export function makeGetOptions(providersToUse = ["default"]) { +export function makeGetOptions(providersToUse = ["default"], mediation = "required") { if (typeof providersToUse === "string") { if (providersToUse === "default" || providersToUse === "openid4vp"){ return makeGetOptions([providersToUse]); } } if (!Array.isArray(providersToUse) || !providersToUse?.length) { - return { digital: { providers: providersToUse } }; + return { digital: { providers: providersToUse }, mediation }; } const providers = []; for (const provider of providersToUse) { @@ -31,10 +32,9 @@ export function makeGetOptions(providersToUse = ["default"]) { break; default: throw new Error(`Unknown provider type: ${provider}`); - break; } } - return { digital: { providers } }; + return { digital: { providers }, mediation }; } /** * 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 index 4b212756c2291..04f256c2447c6 100644 --- 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 @@ -2,8 +2,8 @@ - - - +

Digital Credentials iframe

diff --git a/LayoutTests/platform/ios/imported/w3c/web-platform-tests/digital-credentials/identity-get.tentative.https-expected.txt b/LayoutTests/platform/ios/imported/w3c/web-platform-tests/digital-credentials/identity-get.tentative.https-expected.txt index e40c7275cbd17..74128a416842d 100644 --- a/LayoutTests/platform/ios/imported/w3c/web-platform-tests/digital-credentials/identity-get.tentative.https-expected.txt +++ b/LayoutTests/platform/ios/imported/w3c/web-platform-tests/digital-credentials/identity-get.tentative.https-expected.txt @@ -11,4 +11,5 @@ PASS navigator.identity.get() promise is rejected if called with an aborted sign PASS navigator.identity.get() promise is rejected if called with an aborted signal in cross-origin iframe. FAIL navigator.identity.get() promise is rejected if abort controller is aborted after call to get(). promise_rejects_dom: function "function() { throw e }" threw object "NotSupportedError: Not implemented" that is not a DOMException AbortError: property "code" is equal to 9, expected 20 FAIL navigator.identity.get() promise is rejected if abort controller is aborted after call to get() in cross-origin iframe. assert_equals: expected "AbortError" but got "NotAllowedError" +PASS Mediation is required to get a DigitalCredential. diff --git a/Source/WebCore/Modules/identity/IdentityCredentialsContainer.cpp b/Source/WebCore/Modules/identity/IdentityCredentialsContainer.cpp index c17afd359e707..bf40be89518bb 100644 --- a/Source/WebCore/Modules/identity/IdentityCredentialsContainer.cpp +++ b/Source/WebCore/Modules/identity/IdentityCredentialsContainer.cpp @@ -37,6 +37,7 @@ #include "JSDOMPromiseDeferred.h" #include "JSDigitalCredential.h" #include "LocalDOMWindow.h" +#include "MediationRequirement.h" #include "Page.h" #include "VisibilityState.h" @@ -56,6 +57,11 @@ void IdentityCredentialsContainer::get(CredentialRequestOptions&& options, Crede return; } + if (options.mediation != MediationRequirement::Required) { + promise.reject(Exception { ExceptionCode::TypeError, "User mediation is required for DigitalCredential."_s }); + return; + } + RefPtr document = this->document(); ASSERT(document); @@ -85,9 +91,6 @@ void IdentityCredentialsContainer::get(CredentialRequestOptions&& options, Crede return; } - // FIXME: mediation requirement, - // which is waiting on https://github.com/WICG/digital-credentials/pull/149 - document->page()->credentialRequestCoordinator().discoverFromExternalSource(*document, WTFMove(options), WTFMove(promise)); }