Skip to content

Commit

Permalink
Add WebDriver commands (#465)
Browse files Browse the repository at this point in the history
* Add WebDriver commands

* review comments

* review comments

* markdown

* add dialog type

* review comments
  • Loading branch information
cbiesinger authored May 16, 2023
1 parent 15ea16e commit 865e7d6
Showing 1 changed file with 272 additions and 7 deletions.
279 changes: 272 additions & 7 deletions spec/index.bs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ spec: credential-management-1; urlPrefix: https://w3c.github.io/webappsec-creden
text: same-origin with its ancestors; url: same-origin-with-its-ancestors
type: dfn
text: requires user mediation; url: origin-requires-user-mediation
spec: webdriver; urlPrefix: https://w3c.github.io/webdriver/
type: dfn
text: getting a property; url: dfn-getting-properties
text: no such alert; url: dfn-no-such-alert
text: error code; url: dfn-error-code
</pre>

<pre class=link-defaults>
Expand All @@ -39,6 +44,7 @@ spec:infra; type:dfn; text:user agent
spec:html; type:dfn; for:environment settings object; text:global object
spec:html; type:dfn; for:html-origin-def; text:origin
spec:webidl; type:dfn; text:resolve
spec:webdriver2; type:dfn; text:error
</pre>

<style>
Expand Down Expand Up @@ -470,7 +476,7 @@ This [=internal method=] accepts three arguments:
The <var ignore="">options</var>.{{CredentialRequestOptions/signal}} is used as an abort signal for the
requests.

<div algorithm>
<div algorithm="[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)">
When the {{IdentityCredential}}'s
<dfn for="IdentityCredential" method>\[[DiscoverFromExternalSource]](origin, options, sameOriginWithAncestors)</dfn>
algorithm is invoked, the user agent MUST execute the following steps. This returns an
Expand Down Expand Up @@ -499,10 +505,14 @@ algorithm is invoked, the user agent MUST execute the following steps. This retu
|options|["{{CredentialRequestOptions/mediation}}"], and |globalObject|.
1. If |credential| is a pair:
1. Let |throwImmediately| be the value of the second element of the pair.
1. If |throwImmediately| is false, the user agent SHOULD wait a random
amount of time before the next step, unless it has implemented
another way to prevent exposing to the RP whether the user has
an account logged in to the RP.
1. The user agent SHOULD wait a random amount of time
before the next step if all of the following conditions hold:
* |throwImmediately| is false
* The <dfn>promise rejection delay</dfn> was not disabled by
[=setdelayenabled|user agent automation=]
* The user agent has not implemented another way to prevent
exposing to the RP whether the user has an account logged
in to the RP

Note: The intention here is as follows. If we resolved the promise immediately,
then an RP could infer that no dialog was shown because the promise was
Expand All @@ -523,7 +533,7 @@ algorithm is invoked, the user agent MUST execute the following steps. This retu
The <a>create an IdentityCredential</a> algorithm invokes the various FedCM fetches, shows the user
agent UI, and creates the {{IdentityCredential}} that is then returned to the [=RP=].

<div algorithm>
<div algorithm="create an IdentityCredential">
To <dfn>create an IdentityCredential</dfn> given an {{IdentityProviderConfig}}
|provider|, a {{CredentialRequestOptions/mediation}} |mediation|, and a
|globalObject|, run the following steps. This returns an {{IdentityCredential}}
Expand Down Expand Up @@ -560,7 +570,7 @@ the exception thrown.
1. Set |account| to |registeredAccount| and |accountState| to the result of running
[=compute the connection status=] algorithm given |provider| and |account|. When doing this,
the user agent MAY show some UI to the user indicating that they are being
auto-reauthenticated.
<dfn>auto-reauthenticated</dfn>.
1. Otherwise, if |mediation| is "{{CredentialMediationRequirement/silent}}", return failure.
1. Otherwise, if |accountsList|'s size is 1:
1. Set |account| to |accountsList|[0].
Expand Down Expand Up @@ -1479,6 +1489,261 @@ occur when there is access to the [=current settings object=]. The [=internal me
modified by this specification do not have such access since they are invoked [=in parallel=]
by {{CredentialsContainer}}'s <a abstract-op>Request a `Credential`</a> abstract operation.

<!-- ============================================================ -->
# User Agent Automation # {#automation}
<!-- ============================================================ -->

For the purposes of user agent automation and website testing, this document
defines the below [[WebDriver2]] [=extension commands=] to interact with any
active FedCM dialogs.

## Cancel dialog ## {#webdriver-canceldialog}

<figure id="table-webdriver-canceldialog" class="table">
<table class="data">
<thead>
<tr>
<th>HTTP Method</th>
<th>URI Template</th>
</tr>
</thead>
<tbody>
<tr>
<td>POST</td>
<td>`/session/{session id}/fedcm/canceldialog`</td>
</tr>
</tbody>
</table>
</figure>

The [=remote end steps=] are:

1. If no FedCM dialog is currently open, return a [=error|WebDriver error=] with
[=error code=] [=no such alert=].

1. Close the dialog and continue the [=create an IdentityCredential=] algorithm
as if the user had canceled the dialog without choosing an account.

1. Return [=success=] with data `null`.

## Select account ## {#webdriver-selectaccount}

<figure id="table-webdriver-selectaccount" class="table">
<table class="data">
<thead>
<tr>
<th>HTTP Method</th>
<th>URI Template</th>
</tr>
</thead>
<tbody>
<tr>
<td>POST</td>
<td>`/session/{session id}/fedcm/selectaccount`</td>
</tr>
</tbody>
</table>
</figure>

The [=remote end steps=] are:

1. If |parameters| is not a JSON [[ECMASCRIPT#sec-json-object|Object]], return a
[=error|WebDriver error=] with [=error code=] [=invalid argument=].

1. If no FedCM dialog is currently open, return a [=error|WebDriver error=] with
[=error code=] [=no such alert=].

1. Let |accountIndex| be the result of [=getting a property=] named `"accountIndex"`
from |parameters|.

1. If |accountIndex| is {{undefined}} or is less than 0 or greater than or
equal to the number of accounts that the user can choose from in the
current flow, return a [=error|WebDriver error=] with [=error code=]
[=invalid argument=].

1. Close the dialog and continue the [=create an IdentityCredential=] algorithm
as if the user had selected the account indicated by |accountIndex| and
[=request permission to sign-up|granted permission to sign-up=], if applicable.

1. Return [=success=] with data `null`.

## Account list ## {#webdriver-accountlist}

<figure id="table-webdriver-accountlist" class="table">
<table class="data">
<thead>
<tr>
<th>HTTP Method</th>
<th>URI Template</th>
</tr>
</thead>
<tbody>
<tr>
<td>GET</td>
<td>`/session/{session id}/fedcm/accountlist`</td>
</tr>
</tbody>
</table>
</figure>

The [=remote end steps=] are:

1. If no FedCM dialog is currently open, return a [=error|WebDriver error=] with
[=error code=] [=no such alert=].

1. Let |accounts| be the list of accounts that the user can or could choose
from in the current flow.

1. Let |list| be an empty list.

1. For each |account| in |accounts|:
1. Let |accountState| be the result of running the [=compute the connection status=]
algorithm given |account| and the {{IdentityProviderConfig}} of the IDP
|account| belongs to
1. [=list/Append=] a [=dictionary=] to |list| with the following properties:
1. `accountId` set to the account's {{IdentityProviderAccount/id}}
1. `email` set to the account's {{IdentityProviderAccount/email}}
1. `name` set to the account's {{IdentityProviderAccount/name}}
1. `givenName` set to the account's {{IdentityProviderAccount/given_name}},
if present
1. `pictureUrl` set to the account's {{IdentityProviderAccount/picture}},
if present
1. `idpConfigUrl` set to the {{IdentityProviderConfig/configURL}} of the
IDP this account belongs to
1. `loginState` to `"SignUp"` if |accountState| is [=compute the connection status/disconnected=]
and `"SignIn"` otherwise
1. `termsOfServiceUrl` to the {{IdentityProviderClientMetadata/terms_of_service_url}}
if one was provided and the `loginState` is `"SignUp"`, otherwise {{undefined}}
1. `privacyPolicyUrl` to the {{IdentityProviderClientMetadata/privacy_policy_url}}
if one was provided and the `loginState` is `"SignUp"`, otherwise {{undefined}}

1. Return [=success=] with data |list|.

## Get title ## {#webdriver-gettitle}

<figure id="table-webdriver-gettitle" class="table">
<table class="data">
<thead>
<tr>
<th>HTTP Method</th>
<th>URI Template</th>
</tr>
</thead>
<tbody>
<tr>
<td>GET</td>
<td>`/session/{session id}/fedcm/gettitle`</td>
</tr>
</tbody>
</table>
</figure>

Note: This command lets automation verify that the
[context api](https://github.com/fedidcg/FedCM/blob/main/proposals/context-api.md)
was applied properly

The [=remote end steps=] are:

1. If no FedCM dialog is currently open, return a [=error|WebDriver error=] with
[=error code=] [=no such alert=].

1. Let |data| be a dictionary with an object with properties as follows:
1. `title` set to the title of the open dialog
1. `subtitle` set to the subtitle of the open dialog, if there is one

1. Return [=success=] with data |data|.

## Get dialog type ## {#webdriver-getdialogtype}

<figure id="table-webdriver-getdialogtype" class="table">
<table class="data">
<thead>
<tr>
<th>HTTP Method</th>
<th>URI Template</th>
</tr>
</thead>
<tbody>
<tr>
<td>GET</td>
<td>`/session/{session id}/fedcm/getdialogtype`</td>
</tr>
</tbody>
</table>
</figure>

The [=remote end steps=] are:

1. If no FedCM dialog is currently open, return a [=error|WebDriver error=] with
[=error code=] [=no such alert=].

1. Let |type| be a string that is "`AutoReauthn`" if the user is being [=auto-reauthenticated=],
or "`AccountChooser`" otherwise.

1. Return [=success=] with data |type|.

## Set delay enabled ## {#webdriver-setdelayenabled}

<figure id="table-webdriver-setdelayenabled" class="table">
<table class="data">
<thead>
<tr>
<th>HTTP Method</th>
<th>URI Template</th>
</tr>
</thead>
<tbody>
<tr>
<td>POST</td>
<td>`/session/{session id}/fedcm/`<dfn>`setdelayenabled`</dfn></td>
</tr>
</tbody>
</table>
</figure>

The [=remote end steps=] are:

1. If |parameters| is not a JSON [[ECMASCRIPT#sec-json-object|Object]], return a
[=error|WebDriver error=] with [=error code=] [=invalid argument=].

1. Let |enabled| be the result of [=getting a property=] named `"enabled"` from
|parameters|.

1. If |enabled| is {{undefined}} or is not a boolean, return a [=error|WebDriver error=]
with [=error code=] [=invalid argument=].

1. If |enabled| is false, disables the [=promise rejection delay=]; otherwise,
re-enables it.

1. Return [=success=] with data `null`.

## Reset cooldown ## {#webdriver-resetcooldown}

<figure id="table-webdriver-resetcooldown" class="table">
<table class="data">
<thead>
<tr>
<th>HTTP Method</th>
<th>URI Template</th>
</tr>
</thead>
<tbody>
<tr>
<td>POST</td>
<td>`/session/{session id}/fedcm/resetcooldown`</td>
</tr>
</tbody>
</table>
</figure>

The [=remote end steps=] are:

1. If the user agent uses a cooldown delay, which disables the API for an
amount of time after the user dismissed the dialog, then this command
resets that cooldown such that the next FedCM call can succeed again.

1. Return [=success=] with data `null`.

<!-- ============================================================ -->
# Security # {#security}
<!-- ============================================================ -->
Expand Down

0 comments on commit 865e7d6

Please sign in to comment.