Skip to content

Commit

Permalink
[js] Add Federated Credential Management support (SeleniumHQ#15008)
Browse files Browse the repository at this point in the history
  • Loading branch information
pujagani authored Jan 6, 2025
1 parent c4f228b commit 88d3996
Show file tree
Hide file tree
Showing 9 changed files with 413 additions and 1 deletion.
40 changes: 40 additions & 0 deletions common/src/web/fedcm/fedcm_async_js.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<!DOCTYPE html>
<html>
<head>
<title>FedCM Example</title>
</head>
<body>
<button id="triggerButton" onclick="triggerFedCm()">Trigger FedCM</button>
<div id="result"></div>

<script>
// Use a relative path for the configURL
let configURL = `http://${location.host}/common/fedcm/config.json`;
console.log(configURL)
let result = null;

async function triggerFedCm() {
console.log("Config URL:", configURL);
try {
let promise = await navigator.credentials.get({
identity: {
providers: [{
configURL: configURL,
clientId: '1',
}]
}
});
result = promise;

console.log("Promised!")
console.log(result)
document.getElementById('result').innerText = JSON.stringify(result);
} catch (error) {
console.error("FedCM Error:", error);
result = { error: error.message };
document.getElementById('result').innerText = JSON.stringify(result);
}
}
</script>
</body>
</html>
1 change: 1 addition & 0 deletions javascript/node/selenium-webdriver/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ js_library(
"io/*.js",
"lib/*.js",
"lib/atoms/bidi-mutation-listener.js",
"lib/fedcm/*.js",
"net/*.js",
"remote/*.js",
"testing/*.js",
Expand Down
11 changes: 11 additions & 0 deletions javascript/node/selenium-webdriver/lib/command.js
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,17 @@ const Name = {
GET_DOWNLOADABLE_FILES: 'getDownloadableFiles',
DOWNLOAD_FILE: 'downloadFile',
DELETE_DOWNLOADABLE_FILES: 'deleteDownloadableFiles',

// Federated Credential Management API
// https://www.w3.org/TR/fedcm/#automation
CANCEL_DIALOG: 'cancelDialog',
SELECT_ACCOUNT: 'selectAccount',
GET_ACCOUNTS: 'getAccounts',
GET_FEDCM_TITLE: 'getFedCmTitle',
GET_FEDCM_DIALOG_TYPE: 'getFedCmDialogType',
SET_DELAY_ENABLED: 'setDelayEnabled',
RESET_COOLDOWN: 'resetCooldown',
CLICK_DIALOG_BUTTON: 'clickdialogbutton',
}

/**
Expand Down
78 changes: 78 additions & 0 deletions javascript/node/selenium-webdriver/lib/fedcm/account.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The SFC licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

class Account {
constructor(
accountId,
email,
name,
givenName,
pictureUrl,
idpConfigUrl,
loginState,
termsOfServiceUrl,
privacyPolicyUrl,
) {
this._accountId = accountId
this._email = email
this._name = name
this._givenName = givenName
this._pictureUrl = pictureUrl
this._idpConfigUrl = idpConfigUrl
this._loginState = loginState
this._termsOfServiceUrl = termsOfServiceUrl
this._privacyPolicyUrl = privacyPolicyUrl
}

get accountId() {
return this._accountId
}

get email() {
return this._email
}

get name() {
return this._name
}

get givenName() {
return this._givenName
}

get pictureUrl() {
return this._pictureUrl
}

get idpConfigUrl() {
return this._idpConfigUrl
}

get loginState() {
return this._loginState
}

get termsOfServiceUrl() {
return this._termsOfServiceUrl
}

get privacyPolicyUrl() {
return this._privacyPolicyUrl
}
}

module.exports = Account
76 changes: 76 additions & 0 deletions javascript/node/selenium-webdriver/lib/fedcm/dialog.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
// Licensed to the Software Freedom Conservancy (SFC) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The SFC licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.

const command = require('../command')
const Account = require('./account')

class Dialog {
constructor(driver) {
this._driver = driver
}

async title() {
const result = await this._driver.execute(new command.Command(command.Name.GET_FEDCM_TITLE))

return result.title
}

subtitle() {
return this._driver.execute(new command.Command(command.Name.GET_FEDCM_TITLE))
}

type() {
return this._driver.execute(new command.Command(command.Name.GET_FEDCM_DIALOG_TYPE))
}

async accounts() {
const result = await this._driver.execute(new command.Command(command.Name.GET_ACCOUNTS))

const accountArray = []

result.forEach((account) => {
const acc = new Account(
account.accountId,
account.email,
account.name,
account.givenName,
account.pictureUrl,
account.idpConfigUrl,
account.loginState,
account.termsOfServiceUrl,
account.privacyPolicyUrl,
)
accountArray.push(acc)
})

return accountArray
}

selectAccount(index) {
return this._driver.execute(new command.Command(command.Name.SELECT_ACCOUNT).setParameter('accountIndex', index))
}

accept() {
return this._driver.execute(new command.Command(command.Name.CLICK_DIALOG_BUTTON))
}

dismiss() {
return this._driver.execute(new command.Command(command.Name.CANCEL_DIALOG))
}
}

module.exports = Dialog
10 changes: 10 additions & 0 deletions javascript/node/selenium-webdriver/lib/http.js
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,16 @@ const W3C_COMMAND_MAP = new Map([
[cmd.Name.GET_DOWNLOADABLE_FILES, get('/session/:sessionId/se/files')],
[cmd.Name.DOWNLOAD_FILE, post(`/session/:sessionId/se/files`)],
[cmd.Name.DELETE_DOWNLOADABLE_FILES, del(`/session/:sessionId/se/files`)],

// Federated Credential Management Command
[cmd.Name.CANCEL_DIALOG, post(`/session/:sessionId/fedcm/canceldialog`)],
[cmd.Name.SELECT_ACCOUNT, post(`/session/:sessionId/fedcm/selectaccount`)],
[cmd.Name.GET_FEDCM_TITLE, get(`/session/:sessionId/fedcm/gettitle`)],
[cmd.Name.GET_FEDCM_DIALOG_TYPE, get('/session/:sessionId/fedcm/getdialogtype')],
[cmd.Name.SET_DELAY_ENABLED, post(`/session/:sessionId/fedcm/setdelayenabled`)],
[cmd.Name.RESET_COOLDOWN, post(`/session/:sessionId/fedcm/resetcooldown`)],
[cmd.Name.CLICK_DIALOG_BUTTON, post(`/session/:sessionId/fedcm/clickdialogbutton`)],
[cmd.Name.GET_ACCOUNTS, get(`/session/:sessionId/fedcm/accountlist`)],
])

/**
Expand Down
2 changes: 1 addition & 1 deletion javascript/node/selenium-webdriver/lib/test/fileserver.js
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ const Pages = (function () {
addPage('emptyText', 'bidi/emptyText.txt')
addPage('redirectedHttpEquiv', 'bidi/redirected_http_equiv.html')
addPage('releaseAction', 'bidi/release_action.html')

addPage('fedcm', 'fedcm/fedcm_async_js.html')
return pages
})()

Expand Down
13 changes: 13 additions & 0 deletions javascript/node/selenium-webdriver/lib/webdriver.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ const { PinnedScript } = require('./pinnedScript')
const JSZip = require('jszip')
const Script = require('./script')
const Network = require('./network')
const Dialog = require('./fedcm/dialog')

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

setDelayEnabled(enabled) {
return this.execute(new command.Command(command.Name.SET_DELAY_ENABLED).setParameter('enabled', enabled))
}

resetCooldown() {
return this.execute(new command.Command(command.Name.RESET_COOLDOWN))
}

getFederalCredentialManagementDialog() {
return new Dialog(this)
}

/** @override */
manage() {
return new Options(this)
Expand Down
Loading

0 comments on commit 88d3996

Please sign in to comment.