Files
tubestation/remote/shared/webdriver/UserPromptHandler.sys.mjs
Butkovits Atila 11a5a23896 Backed out 7 changesets (bug 1870226) for causing build bustages. CLOSED TREE
Backed out changeset 619244623dba (bug 1870226)
Backed out changeset e85a5647cae4 (bug 1870226)
Backed out changeset 21ea9baf83ea (bug 1870226)
Backed out changeset a506c0f0ce28 (bug 1870226)
Backed out changeset 77c78201a206 (bug 1870226)
Backed out changeset 7a98dfef087f (bug 1870226)
Backed out changeset f64ad89c2406 (bug 1870226)
2024-08-23 12:22:02 +03:00

308 lines
8.3 KiB
JavaScript

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
const lazy = {};
ChromeUtils.defineESModuleGetters(lazy, {
assert: "chrome://remote/content/shared/webdriver/Assert.sys.mjs",
pprint: "chrome://remote/content/shared/Format.sys.mjs",
});
/**
* @typedef {string} PromptHandlers
*/
/**
* Enum of known prompt handlers.
*
* @readonly
* @enum {PromptHandlers}
*
* @see https://w3c.github.io/webdriver/#dfn-known-prompt-handlers
*/
export const PromptHandlers = {
/** All simple dialogs encountered should be accepted. */
Accept: "accept",
/**
* All simple dialogs encountered should be accepted, and an error
* returned that the dialog was handled.
*/
AcceptAndNotify: "accept and notify",
/** All simple dialogs encountered should be dismissed. */
Dismiss: "dismiss",
/**
* All simple dialogs encountered should be dismissed, and an error
* returned that the dialog was handled.
*/
DismissAndNotify: "dismiss and notify",
/** All simple dialogs encountered should be left to the user to handle. */
Ignore: "ignore",
};
/**
* @typedef {string} PromptTypes
*/
/**
* Enum of valid prompt types.
*
* @readonly
* @enum {PromptTypes}
*
* @see https://w3c.github.io/webdriver/#dfn-valid-prompt-types
*/
export const PromptTypes = {
// A simple alert dialog
Alert: "alert",
// A simple beforeunload dialog. If no handler is set it falls back to the
// `accept` handler to keep backward compatibility with WebDriver classic,
// which doesn't customize this prompt type.
BeforeUnload: "beforeUnload",
// A simple confirm dialog
Confirm: "confirm",
// Default value when no specific handler is configured. Can only be set when
// specifying the unhandlePromptBehavior capability with a map containing a
// "default" entry. See FALLBACK_DEFAULT_PROMPT_TYPE.
Default: "default",
// A simple prompt dialog
Prompt: "prompt",
};
/**
* Internal prompt type used when the unhandledPromptBehavior capability is
* set as a string. The "fallbackDefault" type will apply to "alert", "confirm"
* and "prompt" prompts, but will not apply to "beforeUnload" prompts.
*/
const FALLBACK_DEFAULT_PROMPT_TYPE = "fallbackDefault";
export class PromptHandlerConfiguration {
#handler;
#notify;
/**
* Create an instance of a prompt handler configuration.
*
* @param {string} handler
* Handler to use for the user prompt. One of "accept", "dismiss" or "ignore".
* @param {boolean} notify
* Flag to indicate if the user needs to be notified when the dialog was
* handled.
*
* @see https://w3c.github.io/webdriver/#dfn-prompt-handler-configuration
*/
constructor(handler, notify) {
this.#handler = handler;
this.#notify = notify;
}
get handler() {
return this.#handler;
}
get notify() {
return this.#notify;
}
toString() {
return "[object PromptHandlerConfiguration]";
}
/**
* JSON serialization of the prompt handler configuration object.
*
* @returns {Object<string, ?>} json
*
* @see https://w3c.github.io/webdriver/#dfn-serialize-a-prompt-handler-configuration
*/
toJSON() {
let serialized = this.#handler;
if (["accept", "dismiss"].includes(serialized) && this.#notify) {
serialized += " and notify";
}
return serialized;
}
}
export class UserPromptHandler {
#promptTypeToHandlerMap;
constructor() {
// Note: this map is null until update-the-user-prompt-handler initializes
// it.
this.#promptTypeToHandlerMap = null;
}
get activePromptHandlers() {
return this.#promptTypeToHandlerMap;
}
get PromptHandlers() {
return PromptHandlers;
}
get PromptTypes() {
return PromptTypes;
}
/**
* Unmarshal a JSON object representation of the unhandledPromptBehavior capability.
*
* @param {Object<string, ?>} json
* JSON Object to unmarshal.
*
* @throws {InvalidArgumentError}
* When the value of the unhandledPromptBehavior capability is invalid.
*
* @returns {UserPromptHandler}
*
* @see https://w3c.github.io/webdriver/#dfn-deserialize-as-an-unhandled-prompt-behavior
*/
static fromJSON(json) {
let isStringValue = false;
let value = json;
if (typeof value === "string") {
// A single specified prompt behavior or for WebDriver classic.
value = { [FALLBACK_DEFAULT_PROMPT_TYPE]: value };
isStringValue = true;
}
lazy.assert.object(
value,
lazy.pprint`Expected "unhandledPromptBehavior" to be an object, got ${value}`
);
const userPromptHandlerCapability = new Map();
for (let [promptType, handler] of Object.entries(value)) {
if (!isStringValue) {
const validPromptTypes = Object.values(PromptTypes);
lazy.assert.in(
promptType,
validPromptTypes,
lazy.pprint`Expected "promptType" to be one of ${validPromptTypes}, got ${promptType}`
);
}
const knownPromptHandlers = Object.values(PromptHandlers);
lazy.assert.in(
handler,
knownPromptHandlers,
lazy.pprint`Expected "handler" to be one of ${knownPromptHandlers}, got ${handler}`
);
let notify = false;
switch (handler) {
case PromptHandlers.AcceptAndNotify:
handler = PromptHandlers.Accept;
notify = true;
break;
case PromptHandlers.DismissAndNotify:
handler = PromptHandlers.Dismiss;
notify = true;
break;
case PromptHandlers.Ignore:
notify = true;
break;
}
const configuration = new PromptHandlerConfiguration(handler, notify);
userPromptHandlerCapability.set(promptType, configuration);
}
const userPromptHandler = new UserPromptHandler();
userPromptHandler.update(userPromptHandlerCapability);
return userPromptHandler;
}
/**
* Get the handler for the given prompt type.
*
* @param {string} promptType
* The prompt type to retrieve the handler for.
*
* @returns {PromptHandlerConfiguration}
*
* @see https://w3c.github.io/webdriver/#dfn-get-the-prompt-handler
*/
getPromptHandler(promptType) {
let handlers;
if (this.#promptTypeToHandlerMap === null) {
handlers = new Map();
} else {
handlers = this.#promptTypeToHandlerMap;
}
if (handlers.has(promptType)) {
return handlers.get(promptType);
}
if (handlers.has(PromptTypes.Default)) {
return handlers.get(PromptTypes.Default);
}
if (promptType === PromptTypes.BeforeUnload) {
return new PromptHandlerConfiguration(PromptHandlers.Accept, false);
}
if (handlers.has(FALLBACK_DEFAULT_PROMPT_TYPE)) {
return handlers.get(FALLBACK_DEFAULT_PROMPT_TYPE);
}
return new PromptHandlerConfiguration(PromptHandlers.Dismiss, true);
}
/**
* Updates the prompt handler configuration for a given requested prompt
* handler map.
*
* @param {Map} requestedPromptHandler
* The request prompt handler configuration map.
*
* @see https://w3c.github.io/webdriver/#dfn-update-the-user-prompt-handler
*/
update(requestedPromptHandler) {
if (this.#promptTypeToHandlerMap === null) {
this.#promptTypeToHandlerMap = new Map();
}
for (const [promptType, handler] of requestedPromptHandler) {
this.#promptTypeToHandlerMap.set(promptType, handler);
}
}
/**
* JSON serialization of the user prompt handler object.
*
* @returns {Object<string, ?>} json
*
* @see https://w3c.github.io/webdriver/#dfn-serialize-the-user-prompt-handler
*/
toJSON() {
if (this.#promptTypeToHandlerMap === null) {
// Fallback to "dismiss and notify" if no handler is set
return PromptHandlers.DismissAndNotify;
}
if (
this.#promptTypeToHandlerMap.size === 1 &&
this.#promptTypeToHandlerMap.has(FALLBACK_DEFAULT_PROMPT_TYPE)
) {
return this.#promptTypeToHandlerMap
.get(FALLBACK_DEFAULT_PROMPT_TYPE)
.toJSON();
}
const serialized = {};
for (const [key, value] of this.#promptTypeToHandlerMap.entries()) {
serialized[key] = value.toJSON();
}
return serialized;
}
toString() {
return "[object UserPromptHandler]";
}
}