Skip to content

Commit 88d3996

Browse files
authored
[js] Add Federated Credential Management support (#15008)
1 parent c4f228b commit 88d3996

File tree

9 files changed

+413
-1
lines changed

9 files changed

+413
-1
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<title>FedCM Example</title>
5+
</head>
6+
<body>
7+
<button id="triggerButton" onclick="triggerFedCm()">Trigger FedCM</button>
8+
<div id="result"></div>
9+
10+
<script>
11+
// Use a relative path for the configURL
12+
let configURL = `http://${location.host}/common/fedcm/config.json`;
13+
console.log(configURL)
14+
let result = null;
15+
16+
async function triggerFedCm() {
17+
console.log("Config URL:", configURL);
18+
try {
19+
let promise = await navigator.credentials.get({
20+
identity: {
21+
providers: [{
22+
configURL: configURL,
23+
clientId: '1',
24+
}]
25+
}
26+
});
27+
result = promise;
28+
29+
console.log("Promised!")
30+
console.log(result)
31+
document.getElementById('result').innerText = JSON.stringify(result);
32+
} catch (error) {
33+
console.error("FedCM Error:", error);
34+
result = { error: error.message };
35+
document.getElementById('result').innerText = JSON.stringify(result);
36+
}
37+
}
38+
</script>
39+
</body>
40+
</html>

javascript/node/selenium-webdriver/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ js_library(
3333
"io/*.js",
3434
"lib/*.js",
3535
"lib/atoms/bidi-mutation-listener.js",
36+
"lib/fedcm/*.js",
3637
"net/*.js",
3738
"remote/*.js",
3839
"testing/*.js",

javascript/node/selenium-webdriver/lib/command.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,17 @@ const Name = {
185185
GET_DOWNLOADABLE_FILES: 'getDownloadableFiles',
186186
DOWNLOAD_FILE: 'downloadFile',
187187
DELETE_DOWNLOADABLE_FILES: 'deleteDownloadableFiles',
188+
189+
// Federated Credential Management API
190+
// https://www.w3.org/TR/fedcm/#automation
191+
CANCEL_DIALOG: 'cancelDialog',
192+
SELECT_ACCOUNT: 'selectAccount',
193+
GET_ACCOUNTS: 'getAccounts',
194+
GET_FEDCM_TITLE: 'getFedCmTitle',
195+
GET_FEDCM_DIALOG_TYPE: 'getFedCmDialogType',
196+
SET_DELAY_ENABLED: 'setDelayEnabled',
197+
RESET_COOLDOWN: 'resetCooldown',
198+
CLICK_DIALOG_BUTTON: 'clickdialogbutton',
188199
}
189200

190201
/**
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Licensed to the Software Freedom Conservancy (SFC) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The SFC licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
class Account {
19+
constructor(
20+
accountId,
21+
email,
22+
name,
23+
givenName,
24+
pictureUrl,
25+
idpConfigUrl,
26+
loginState,
27+
termsOfServiceUrl,
28+
privacyPolicyUrl,
29+
) {
30+
this._accountId = accountId
31+
this._email = email
32+
this._name = name
33+
this._givenName = givenName
34+
this._pictureUrl = pictureUrl
35+
this._idpConfigUrl = idpConfigUrl
36+
this._loginState = loginState
37+
this._termsOfServiceUrl = termsOfServiceUrl
38+
this._privacyPolicyUrl = privacyPolicyUrl
39+
}
40+
41+
get accountId() {
42+
return this._accountId
43+
}
44+
45+
get email() {
46+
return this._email
47+
}
48+
49+
get name() {
50+
return this._name
51+
}
52+
53+
get givenName() {
54+
return this._givenName
55+
}
56+
57+
get pictureUrl() {
58+
return this._pictureUrl
59+
}
60+
61+
get idpConfigUrl() {
62+
return this._idpConfigUrl
63+
}
64+
65+
get loginState() {
66+
return this._loginState
67+
}
68+
69+
get termsOfServiceUrl() {
70+
return this._termsOfServiceUrl
71+
}
72+
73+
get privacyPolicyUrl() {
74+
return this._privacyPolicyUrl
75+
}
76+
}
77+
78+
module.exports = Account
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
// Licensed to the Software Freedom Conservancy (SFC) under one
2+
// or more contributor license agreements. See the NOTICE file
3+
// distributed with this work for additional information
4+
// regarding copyright ownership. The SFC licenses this file
5+
// to you under the Apache License, Version 2.0 (the
6+
// "License"); you may not use this file except in compliance
7+
// with the License. You may obtain a copy of the License at
8+
//
9+
// http://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing,
12+
// software distributed under the License is distributed on an
13+
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
// KIND, either express or implied. See the License for the
15+
// specific language governing permissions and limitations
16+
// under the License.
17+
18+
const command = require('../command')
19+
const Account = require('./account')
20+
21+
class Dialog {
22+
constructor(driver) {
23+
this._driver = driver
24+
}
25+
26+
async title() {
27+
const result = await this._driver.execute(new command.Command(command.Name.GET_FEDCM_TITLE))
28+
29+
return result.title
30+
}
31+
32+
subtitle() {
33+
return this._driver.execute(new command.Command(command.Name.GET_FEDCM_TITLE))
34+
}
35+
36+
type() {
37+
return this._driver.execute(new command.Command(command.Name.GET_FEDCM_DIALOG_TYPE))
38+
}
39+
40+
async accounts() {
41+
const result = await this._driver.execute(new command.Command(command.Name.GET_ACCOUNTS))
42+
43+
const accountArray = []
44+
45+
result.forEach((account) => {
46+
const acc = new Account(
47+
account.accountId,
48+
account.email,
49+
account.name,
50+
account.givenName,
51+
account.pictureUrl,
52+
account.idpConfigUrl,
53+
account.loginState,
54+
account.termsOfServiceUrl,
55+
account.privacyPolicyUrl,
56+
)
57+
accountArray.push(acc)
58+
})
59+
60+
return accountArray
61+
}
62+
63+
selectAccount(index) {
64+
return this._driver.execute(new command.Command(command.Name.SELECT_ACCOUNT).setParameter('accountIndex', index))
65+
}
66+
67+
accept() {
68+
return this._driver.execute(new command.Command(command.Name.CLICK_DIALOG_BUTTON))
69+
}
70+
71+
dismiss() {
72+
return this._driver.execute(new command.Command(command.Name.CANCEL_DIALOG))
73+
}
74+
}
75+
76+
module.exports = Dialog

javascript/node/selenium-webdriver/lib/http.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,16 @@ const W3C_COMMAND_MAP = new Map([
320320
[cmd.Name.GET_DOWNLOADABLE_FILES, get('/session/:sessionId/se/files')],
321321
[cmd.Name.DOWNLOAD_FILE, post(`/session/:sessionId/se/files`)],
322322
[cmd.Name.DELETE_DOWNLOADABLE_FILES, del(`/session/:sessionId/se/files`)],
323+
324+
// Federated Credential Management Command
325+
[cmd.Name.CANCEL_DIALOG, post(`/session/:sessionId/fedcm/canceldialog`)],
326+
[cmd.Name.SELECT_ACCOUNT, post(`/session/:sessionId/fedcm/selectaccount`)],
327+
[cmd.Name.GET_FEDCM_TITLE, get(`/session/:sessionId/fedcm/gettitle`)],
328+
[cmd.Name.GET_FEDCM_DIALOG_TYPE, get('/session/:sessionId/fedcm/getdialogtype')],
329+
[cmd.Name.SET_DELAY_ENABLED, post(`/session/:sessionId/fedcm/setdelayenabled`)],
330+
[cmd.Name.RESET_COOLDOWN, post(`/session/:sessionId/fedcm/resetcooldown`)],
331+
[cmd.Name.CLICK_DIALOG_BUTTON, post(`/session/:sessionId/fedcm/clickdialogbutton`)],
332+
[cmd.Name.GET_ACCOUNTS, get(`/session/:sessionId/fedcm/accountlist`)],
323333
])
324334

325335
/**

javascript/node/selenium-webdriver/lib/test/fileserver.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ const Pages = (function () {
118118
addPage('emptyText', 'bidi/emptyText.txt')
119119
addPage('redirectedHttpEquiv', 'bidi/redirected_http_equiv.html')
120120
addPage('releaseAction', 'bidi/release_action.html')
121-
121+
addPage('fedcm', 'fedcm/fedcm_async_js.html')
122122
return pages
123123
})()
124124

javascript/node/selenium-webdriver/lib/webdriver.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ const { PinnedScript } = require('./pinnedScript')
4545
const JSZip = require('jszip')
4646
const Script = require('./script')
4747
const Network = require('./network')
48+
const Dialog = require('./fedcm/dialog')
4849

4950
// Capability names that are defined in the W3C spec.
5051
const W3C_CAPABILITY_NAMES = new Set([
@@ -1106,6 +1107,18 @@ class WebDriver {
11061107
return this.execute(new command.Command(command.Name.SCREENSHOT))
11071108
}
11081109

1110+
setDelayEnabled(enabled) {
1111+
return this.execute(new command.Command(command.Name.SET_DELAY_ENABLED).setParameter('enabled', enabled))
1112+
}
1113+
1114+
resetCooldown() {
1115+
return this.execute(new command.Command(command.Name.RESET_COOLDOWN))
1116+
}
1117+
1118+
getFederalCredentialManagementDialog() {
1119+
return new Dialog(this)
1120+
}
1121+
11091122
/** @override */
11101123
manage() {
11111124
return new Options(this)

0 commit comments

Comments
 (0)