forked from mirrors/gecko-dev
Bug 1884090 - [remote] Add support for "HTTP flag" in WebDriver Session. r=webdriver-reviewers,jdescottes
Differential Revision: https://phabricator.services.mozilla.com/D211815
This commit is contained in:
parent
9406e9ecd1
commit
9c60f55dee
8 changed files with 263 additions and 129 deletions
|
|
@ -115,6 +115,9 @@ export function GeckoDriver(server) {
|
||||||
// WebDriver Session
|
// WebDriver Session
|
||||||
this._currentSession = null;
|
this._currentSession = null;
|
||||||
|
|
||||||
|
// Flag to indicate a WebDriver HTTP session
|
||||||
|
this._flags = new Set([lazy.WebDriverSession.SESSION_FLAG_HTTP]);
|
||||||
|
|
||||||
// Flag to indicate that the application is shutting down
|
// Flag to indicate that the application is shutting down
|
||||||
this._isShuttingDown = false;
|
this._isShuttingDown = false;
|
||||||
|
|
||||||
|
|
@ -401,14 +404,20 @@ GeckoDriver.prototype.newSession = async function (cmd) {
|
||||||
const { parameters: capabilities } = cmd;
|
const { parameters: capabilities } = cmd;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// If the WebDriver BiDi protocol is active always use the Remote Agent
|
|
||||||
// to handle the WebDriver session. If it's not the case then Marionette
|
|
||||||
// itself needs to handle it, and has to nullify the "webSocketUrl"
|
|
||||||
// capability.
|
|
||||||
if (lazy.RemoteAgent.webDriverBiDi) {
|
if (lazy.RemoteAgent.webDriverBiDi) {
|
||||||
await lazy.RemoteAgent.webDriverBiDi.createSession(capabilities);
|
// If the WebDriver BiDi protocol is active always use the Remote Agent
|
||||||
|
// to handle the WebDriver session.
|
||||||
|
await lazy.RemoteAgent.webDriverBiDi.createSession(
|
||||||
|
capabilities,
|
||||||
|
this._flags
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
this._currentSession = new lazy.WebDriverSession(capabilities);
|
// If it's not the case then Marionette itself needs to handle it, and
|
||||||
|
// has to nullify the "webSocketUrl" capability.
|
||||||
|
this._currentSession = new lazy.WebDriverSession(
|
||||||
|
capabilities,
|
||||||
|
this._flags
|
||||||
|
);
|
||||||
this._currentSession.capabilities.delete("webSocketUrl");
|
this._currentSession.capabilities.delete("webSocketUrl");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ const { error } = ChromeUtils.importESModule(
|
||||||
);
|
);
|
||||||
|
|
||||||
add_task(async function test_execute_missing_command_error() {
|
add_task(async function test_execute_missing_command_error() {
|
||||||
const session = new WebDriverSession();
|
const session = new WebDriverSession({}, new Set());
|
||||||
|
|
||||||
info("Attempt to execute an unknown protocol command");
|
info("Attempt to execute an unknown protocol command");
|
||||||
await Assert.rejects(
|
await Assert.rejects(
|
||||||
|
|
@ -24,7 +24,7 @@ add_task(async function test_execute_missing_command_error() {
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(async function test_execute_missing_internal_command_error() {
|
add_task(async function test_execute_missing_internal_command_error() {
|
||||||
const session = new WebDriverSession();
|
const session = new WebDriverSession({}, new Set());
|
||||||
|
|
||||||
info(
|
info(
|
||||||
"Attempt to execute a protocol command which relies on an unknown internal method"
|
"Attempt to execute a protocol command which relies on an unknown internal method"
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
* 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/. */
|
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
|
||||||
|
|
||||||
const lazy = {};
|
const lazy = {};
|
||||||
|
|
||||||
ChromeUtils.defineESModuleGetters(lazy, {
|
ChromeUtils.defineESModuleGetters(lazy, {
|
||||||
|
|
@ -14,21 +16,45 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
||||||
"chrome://remote/content/shared/webdriver/UserPromptHandler.sys.mjs",
|
"chrome://remote/content/shared/webdriver/UserPromptHandler.sys.mjs",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ChromeUtils.defineLazyGetter(lazy, "debuggerAddress", () => {
|
||||||
|
return lazy.RemoteAgent.running && lazy.RemoteAgent.cdp
|
||||||
|
? lazy.remoteAgent.debuggerAddress
|
||||||
|
: null;
|
||||||
|
});
|
||||||
|
|
||||||
|
ChromeUtils.defineLazyGetter(lazy, "isHeadless", () => {
|
||||||
|
return Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo).isHeadless;
|
||||||
|
});
|
||||||
|
|
||||||
ChromeUtils.defineLazyGetter(lazy, "remoteAgent", () => {
|
ChromeUtils.defineLazyGetter(lazy, "remoteAgent", () => {
|
||||||
return Cc["@mozilla.org/remote/agent;1"].createInstance(Ci.nsIRemoteAgent);
|
return Cc["@mozilla.org/remote/agent;1"].createInstance(Ci.nsIRemoteAgent);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ChromeUtils.defineLazyGetter(lazy, "userAgent", () => {
|
||||||
|
return Cc["@mozilla.org/network/protocol;1?name=http"].getService(
|
||||||
|
Ci.nsIHttpProtocolHandler
|
||||||
|
).userAgent;
|
||||||
|
});
|
||||||
|
|
||||||
|
XPCOMUtils.defineLazyPreferenceGetter(
|
||||||
|
lazy,
|
||||||
|
"shutdownTimeout",
|
||||||
|
"toolkit.asyncshutdown.crash_timeout"
|
||||||
|
);
|
||||||
|
|
||||||
// List of capabilities which are only relevant for Webdriver Classic.
|
// List of capabilities which are only relevant for Webdriver Classic.
|
||||||
export const WEBDRIVER_CLASSIC_CAPABILITIES = [
|
export const WEBDRIVER_CLASSIC_CAPABILITIES = [
|
||||||
"pageLoadStrategy",
|
"pageLoadStrategy",
|
||||||
"timeouts",
|
|
||||||
"strictFileInteractability",
|
"strictFileInteractability",
|
||||||
|
"timeouts",
|
||||||
"unhandledPromptBehavior",
|
"unhandledPromptBehavior",
|
||||||
"webSocketUrl",
|
"webSocketUrl",
|
||||||
"moz:useNonSpecCompliantPointerOrigin",
|
|
||||||
"moz:webdriverClick",
|
// Gecko specific capabilities
|
||||||
"moz:debuggerAddress",
|
"moz:debuggerAddress",
|
||||||
"moz:firefoxOptions",
|
"moz:firefoxOptions",
|
||||||
|
"moz:useNonSpecCompliantPointerOrigin",
|
||||||
|
"moz:webdriverClick",
|
||||||
];
|
];
|
||||||
|
|
||||||
/** Representation of WebDriver session timeouts. */
|
/** Representation of WebDriver session timeouts. */
|
||||||
|
|
@ -90,7 +116,7 @@ export class Timeouts {
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new lazy.error.InvalidArgumentError(
|
throw new lazy.error.InvalidArgumentError(
|
||||||
"Unrecognised timeout: " + type
|
`Unrecognized timeout: ${type}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -407,51 +433,36 @@ export class Proxy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** WebDriver session capabilities representation. */
|
|
||||||
export class Capabilities extends Map {
|
export class Capabilities extends Map {
|
||||||
/** @class */
|
/**
|
||||||
|
* WebDriver session capabilities representation.
|
||||||
|
*/
|
||||||
constructor() {
|
constructor() {
|
||||||
|
// Default values for capabilities supported by both WebDriver protocols
|
||||||
super([
|
super([
|
||||||
// webdriver
|
|
||||||
["browserName", getWebDriverBrowserName()],
|
["browserName", getWebDriverBrowserName()],
|
||||||
["browserVersion", lazy.AppInfo.version],
|
["browserVersion", lazy.AppInfo.version],
|
||||||
["platformName", getWebDriverPlatformName()],
|
["platformName", getWebDriverPlatformName()],
|
||||||
["acceptInsecureCerts", false],
|
["acceptInsecureCerts", false],
|
||||||
["pageLoadStrategy", PageLoadStrategy.Normal],
|
|
||||||
["proxy", new Proxy()],
|
["proxy", new Proxy()],
|
||||||
["setWindowRect", !lazy.AppInfo.isAndroid],
|
|
||||||
["timeouts", new Timeouts()],
|
|
||||||
["strictFileInteractability", false],
|
|
||||||
["unhandledPromptBehavior", new lazy.UserPromptHandler()],
|
["unhandledPromptBehavior", new lazy.UserPromptHandler()],
|
||||||
[
|
["userAgent", lazy.userAgent],
|
||||||
"userAgent",
|
|
||||||
Cc["@mozilla.org/network/protocol;1?name=http"].getService(
|
|
||||||
Ci.nsIHttpProtocolHandler
|
|
||||||
).userAgent,
|
|
||||||
],
|
|
||||||
["webSocketUrl", null],
|
|
||||||
|
|
||||||
// proprietary
|
// HTTP only capabilities
|
||||||
|
["pageLoadStrategy", PageLoadStrategy.Normal],
|
||||||
|
["timeouts", new Timeouts()],
|
||||||
|
["setWindowRect", !lazy.AppInfo.isAndroid],
|
||||||
|
["strictFileInteractability", false],
|
||||||
|
|
||||||
|
// Gecko specific capabilities
|
||||||
["moz:accessibilityChecks", false],
|
["moz:accessibilityChecks", false],
|
||||||
["moz:buildID", lazy.AppInfo.appBuildID],
|
["moz:buildID", lazy.AppInfo.appBuildID],
|
||||||
[
|
["moz:debuggerAddress", lazy.debuggerAddress],
|
||||||
"moz:debuggerAddress",
|
["moz:headless", lazy.isHeadless],
|
||||||
// With bug 1715481 fixed always use the Remote Agent instance
|
|
||||||
lazy.RemoteAgent.running && lazy.RemoteAgent.cdp
|
|
||||||
? lazy.remoteAgent.debuggerAddress
|
|
||||||
: null,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
"moz:headless",
|
|
||||||
Cc["@mozilla.org/gfx/info;1"].getService(Ci.nsIGfxInfo).isHeadless,
|
|
||||||
],
|
|
||||||
["moz:platformVersion", Services.sysinfo.getProperty("version")],
|
["moz:platformVersion", Services.sysinfo.getProperty("version")],
|
||||||
["moz:processID", lazy.AppInfo.processID],
|
["moz:processID", lazy.AppInfo.processID],
|
||||||
["moz:profile", maybeProfile()],
|
["moz:profile", maybeProfile()],
|
||||||
[
|
["moz:shutdownTimeout", lazy.shutdownTimeout],
|
||||||
"moz:shutdownTimeout",
|
|
||||||
Services.prefs.getIntPref("toolkit.asyncshutdown.crash_timeout"),
|
|
||||||
],
|
|
||||||
["moz:webdriverClick", true],
|
["moz:webdriverClick", true],
|
||||||
["moz:windowless", false],
|
["moz:windowless", false],
|
||||||
]);
|
]);
|
||||||
|
|
@ -478,7 +489,7 @@ export class Capabilities extends Map {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JSON serialisation of capabilities object.
|
* JSON serialization of capabilities object.
|
||||||
*
|
*
|
||||||
* @returns {Object<string, ?>}
|
* @returns {Object<string, ?>}
|
||||||
*/
|
*/
|
||||||
|
|
@ -501,11 +512,13 @@ export class Capabilities extends Map {
|
||||||
*
|
*
|
||||||
* @param {Object<string, *>=} json
|
* @param {Object<string, *>=} json
|
||||||
* WebDriver capabilities.
|
* WebDriver capabilities.
|
||||||
|
* @param {boolean=} isHttp
|
||||||
|
* Flag indicating that it is a WebDriver classic session. Defaults to false.
|
||||||
*
|
*
|
||||||
* @returns {Capabilities}
|
* @returns {Capabilities}
|
||||||
* Internal representation of WebDriver capabilities.
|
* Internal representation of WebDriver capabilities.
|
||||||
*/
|
*/
|
||||||
static fromJSON(json) {
|
static fromJSON(json, isHttp = false) {
|
||||||
if (typeof json == "undefined" || json === null) {
|
if (typeof json == "undefined" || json === null) {
|
||||||
json = {};
|
json = {};
|
||||||
}
|
}
|
||||||
|
|
@ -518,6 +531,11 @@ export class Capabilities extends Map {
|
||||||
// TODO: Bug 1823907. We can start using here spec compliant method `validate`,
|
// TODO: Bug 1823907. We can start using here spec compliant method `validate`,
|
||||||
// as soon as `desiredCapabilities` and `requiredCapabilities` are not supported.
|
// as soon as `desiredCapabilities` and `requiredCapabilities` are not supported.
|
||||||
for (let [k, v] of Object.entries(json)) {
|
for (let [k, v] of Object.entries(json)) {
|
||||||
|
if (!isHttp && WEBDRIVER_CLASSIC_CAPABILITIES.includes(k)) {
|
||||||
|
// Ignore any WebDriver classic capability for a WebDriver BiDi session.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
switch (k) {
|
switch (k) {
|
||||||
case "acceptInsecureCerts":
|
case "acceptInsecureCerts":
|
||||||
lazy.assert.boolean(
|
lazy.assert.boolean(
|
||||||
|
|
|
||||||
|
|
@ -32,10 +32,31 @@ ChromeUtils.defineLazyGetter(lazy, "logger", () => lazy.Log.get());
|
||||||
// Global singleton that holds active WebDriver sessions
|
// Global singleton that holds active WebDriver sessions
|
||||||
const webDriverSessions = new Map();
|
const webDriverSessions = new Map();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Set} SessionConfigurationFlags
|
||||||
|
* A set of flags defining the features of a WebDriver session. It can be
|
||||||
|
* empty or contain entries as listed below. External specifications may
|
||||||
|
* define additional flags, or create sessions without the HTTP flag.
|
||||||
|
*
|
||||||
|
* <dl>
|
||||||
|
* <dt><code>"http"</code> (string)
|
||||||
|
* <dd>Flag indicating a WebDriver classic (HTTP) session.
|
||||||
|
* </dl>
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Representation of WebDriver session.
|
* Representation of WebDriver session.
|
||||||
*/
|
*/
|
||||||
export class WebDriverSession {
|
export class WebDriverSession {
|
||||||
|
#capabilities;
|
||||||
|
#connections;
|
||||||
|
#http;
|
||||||
|
#id;
|
||||||
|
#messageHandler;
|
||||||
|
#path;
|
||||||
|
|
||||||
|
static SESSION_FLAG_HTTP = "http";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new WebDriver session.
|
* Construct a new WebDriver session.
|
||||||
*
|
*
|
||||||
|
|
@ -52,23 +73,22 @@ export class WebDriverSession {
|
||||||
* are implicitly trusted on navigation for the duration of the session.
|
* are implicitly trusted on navigation for the duration of the session.
|
||||||
*
|
*
|
||||||
* <dt><code>pageLoadStrategy</code> (string)
|
* <dt><code>pageLoadStrategy</code> (string)
|
||||||
* <dd>The page load strategy to use for the current session. Must be
|
* <dd>(HTTP only) The page load strategy to use for the current session. Must be
|
||||||
* one of "<tt>none</tt>", "<tt>eager</tt>", and "<tt>normal</tt>".
|
* one of "<tt>none</tt>", "<tt>eager</tt>", and "<tt>normal</tt>".
|
||||||
*
|
*
|
||||||
* <dt><code>proxy</code> (Proxy object)
|
* <dt><code>proxy</code> (Proxy object)
|
||||||
* <dd>Defines the proxy configuration.
|
* <dd>Defines the proxy configuration.
|
||||||
*
|
*
|
||||||
* <dt><code>setWindowRect</code> (boolean)
|
* <dt><code>setWindowRect</code> (boolean)
|
||||||
* <dd>Indicates whether the remote end supports all of the resizing
|
* <dd>(HTTP only) Indicates whether the remote end supports all of the resizing
|
||||||
* and repositioning commands.
|
* and repositioning commands.
|
||||||
*
|
*
|
||||||
* <dt><code>strictFileInteractability</code> (boolean)
|
* <dt><code>strictFileInteractability</code> (boolean)
|
||||||
* <dd>Defines the current session’s strict file interactability.
|
* <dd>(HTTP only) Defines the current session’s strict file interactability.
|
||||||
*
|
*
|
||||||
* <dt><code>timeouts</code> (Timeouts object)
|
* <dt><code>timeouts</code> (Timeouts object)
|
||||||
* <dd>Describes the timeouts imposed on certian session operations.
|
* <dd>(HTTP only) Describes the timeouts imposed on certain session operations.
|
||||||
*
|
*
|
||||||
* TODO: update for WebDriver BiDi type
|
|
||||||
* <dt><code>unhandledPromptBehavior</code> (string)
|
* <dt><code>unhandledPromptBehavior</code> (string)
|
||||||
* <dd>Describes the current session’s user prompt handler. Must be one of
|
* <dd>Describes the current session’s user prompt handler. Must be one of
|
||||||
* "<tt>accept</tt>", "<tt>accept and notify</tt>", "<tt>dismiss</tt>",
|
* "<tt>accept</tt>", "<tt>accept and notify</tt>", "<tt>dismiss</tt>",
|
||||||
|
|
@ -76,13 +96,13 @@ export class WebDriverSession {
|
||||||
* "<tt>dismiss and notify</tt>" state.
|
* "<tt>dismiss and notify</tt>" state.
|
||||||
*
|
*
|
||||||
* <dt><code>moz:accessibilityChecks</code> (boolean)
|
* <dt><code>moz:accessibilityChecks</code> (boolean)
|
||||||
* <dd>Run a11y checks when clicking elements.
|
* <dd>(HTTP only) Run a11y checks when clicking elements.
|
||||||
*
|
*
|
||||||
* <dt><code>moz:debuggerAddress</code> (boolean)
|
* <dt><code>moz:debuggerAddress</code> (boolean)
|
||||||
* <dd>Indicate that the Chrome DevTools Protocol (CDP) has to be enabled.
|
* <dd>Indicate that the Chrome DevTools Protocol (CDP) has to be enabled.
|
||||||
*
|
*
|
||||||
* <dt><code>moz:webdriverClick</code> (boolean)
|
* <dt><code>moz:webdriverClick</code> (boolean)
|
||||||
* <dd>Use a WebDriver conforming <i>WebDriver::ElementClick</i>.
|
* <dd>(HTTP only) Use a WebDriver conforming <i>WebDriver::ElementClick</i>.
|
||||||
* </dl>
|
* </dl>
|
||||||
*
|
*
|
||||||
* <h4>WebAuthn</h4>
|
* <h4>WebAuthn</h4>
|
||||||
|
|
@ -140,7 +160,7 @@ export class WebDriverSession {
|
||||||
* <code>proxyType</code> is "<tt>manual</tt>".
|
* <code>proxyType</code> is "<tt>manual</tt>".
|
||||||
*
|
*
|
||||||
* <dt><code>noProxy</code> (string)
|
* <dt><code>noProxy</code> (string)
|
||||||
* <dd>Lists the adress for which the proxy should be bypassed when
|
* <dd>Lists the address for which the proxy should be bypassed when
|
||||||
* the <code>proxyType</code> is "<tt>manual</tt>". Must be a JSON
|
* the <code>proxyType</code> is "<tt>manual</tt>". Must be a JSON
|
||||||
* List containing any number of any of domains, IPv4 addresses, or IPv6
|
* List containing any number of any of domains, IPv4 addresses, or IPv6
|
||||||
* addresses.
|
* addresses.
|
||||||
|
|
@ -168,9 +188,10 @@ export class WebDriverSession {
|
||||||
* </code></pre>
|
* </code></pre>
|
||||||
*
|
*
|
||||||
* @param {Object<string, *>=} capabilities
|
* @param {Object<string, *>=} capabilities
|
||||||
* JSON Object containing any of the recognised capabilities listed
|
* JSON Object containing any of the recognized capabilities listed
|
||||||
* above.
|
* above.
|
||||||
*
|
* @param {SessionConfigurationFlags} flags
|
||||||
|
* Session configuration flags.
|
||||||
* @param {WebDriverBiDiConnection=} connection
|
* @param {WebDriverBiDiConnection=} connection
|
||||||
* An optional existing WebDriver BiDi connection to associate with the
|
* An optional existing WebDriver BiDi connection to associate with the
|
||||||
* new session.
|
* new session.
|
||||||
|
|
@ -178,19 +199,20 @@ export class WebDriverSession {
|
||||||
* @throws {SessionNotCreatedError}
|
* @throws {SessionNotCreatedError}
|
||||||
* If, for whatever reason, a session could not be created.
|
* If, for whatever reason, a session could not be created.
|
||||||
*/
|
*/
|
||||||
constructor(capabilities, connection) {
|
constructor(capabilities, flags, connection) {
|
||||||
// WebSocket connections that use this session. This also accounts for
|
// WebSocket connections that use this session. This also accounts for
|
||||||
// possible disconnects due to network outages, which require clients
|
// possible disconnects due to network outages, which require clients
|
||||||
// to reconnect.
|
// to reconnect.
|
||||||
this._connections = new Set();
|
this.#connections = new Set();
|
||||||
|
|
||||||
this.id = lazy.generateUUID();
|
this.#id = lazy.generateUUID();
|
||||||
|
this.#http = flags.has(WebDriverSession.SESSION_FLAG_HTTP);
|
||||||
|
|
||||||
// Define the HTTP path to query this session via WebDriver BiDi
|
// Define the HTTP path to query this session via WebDriver BiDi
|
||||||
this.path = `/session/${this.id}`;
|
this.#path = `/session/${this.#id}`;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.capabilities = lazy.Capabilities.fromJSON(capabilities, this.path);
|
this.#capabilities = lazy.Capabilities.fromJSON(capabilities, this.#http);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new lazy.error.SessionNotCreatedError(e);
|
throw new lazy.error.SessionNotCreatedError(e);
|
||||||
}
|
}
|
||||||
|
|
@ -201,7 +223,7 @@ export class WebDriverSession {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.capabilities.get("acceptInsecureCerts")) {
|
if (this.acceptInsecureCerts) {
|
||||||
lazy.logger.warn(
|
lazy.logger.warn(
|
||||||
"TLS certificate errors will be ignored for this session"
|
"TLS certificate errors will be ignored for this session"
|
||||||
);
|
);
|
||||||
|
|
@ -219,7 +241,7 @@ export class WebDriverSession {
|
||||||
// immediately register the newly created session for it.
|
// immediately register the newly created session for it.
|
||||||
if (connection) {
|
if (connection) {
|
||||||
connection.registerSession(this);
|
connection.registerSession(this);
|
||||||
this._connections.add(connection);
|
this.#connections.add(connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Maps a Navigable (browsing context or content browser for top-level
|
// Maps a Navigable (browsing context or content browser for top-level
|
||||||
|
|
@ -228,11 +250,11 @@ export class WebDriverSession {
|
||||||
|
|
||||||
lazy.registerProcessDataActor();
|
lazy.registerProcessDataActor();
|
||||||
|
|
||||||
webDriverSessions.set(this.id, this);
|
webDriverSessions.set(this.#id, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
webDriverSessions.delete(this.id);
|
webDriverSessions.delete(this.#id);
|
||||||
|
|
||||||
lazy.unregisterProcessDataActor();
|
lazy.unregisterProcessDataActor();
|
||||||
|
|
||||||
|
|
@ -241,20 +263,20 @@ export class WebDriverSession {
|
||||||
lazy.allowAllCerts.disable();
|
lazy.allowAllCerts.disable();
|
||||||
|
|
||||||
// Close all open connections which unregister themselves.
|
// Close all open connections which unregister themselves.
|
||||||
this._connections.forEach(connection => connection.close());
|
this.#connections.forEach(connection => connection.close());
|
||||||
if (this._connections.size > 0) {
|
if (this.#connections.size > 0) {
|
||||||
lazy.logger.warn(
|
lazy.logger.warn(
|
||||||
`Failed to close ${this._connections.size} WebSocket connections`
|
`Failed to close ${this.#connections.size} WebSocket connections`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destroy the dedicated MessageHandler instance if we created one.
|
// Destroy the dedicated MessageHandler instance if we created one.
|
||||||
if (this._messageHandler) {
|
if (this.#messageHandler) {
|
||||||
this._messageHandler.off(
|
this.#messageHandler.off(
|
||||||
"message-handler-protocol-event",
|
"message-handler-protocol-event",
|
||||||
this._onMessageHandlerProtocolEvent
|
this._onMessageHandlerProtocolEvent
|
||||||
);
|
);
|
||||||
this._messageHandler.destroy();
|
this.#messageHandler.destroy();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -282,46 +304,66 @@ export class WebDriverSession {
|
||||||
}
|
}
|
||||||
|
|
||||||
get a11yChecks() {
|
get a11yChecks() {
|
||||||
return this.capabilities.get("moz:accessibilityChecks");
|
return this.#capabilities.get("moz:accessibilityChecks");
|
||||||
|
}
|
||||||
|
|
||||||
|
get acceptInsecureCerts() {
|
||||||
|
return this.#capabilities.get("acceptInsecureCerts");
|
||||||
|
}
|
||||||
|
|
||||||
|
get capabilities() {
|
||||||
|
return this.#capabilities;
|
||||||
|
}
|
||||||
|
|
||||||
|
get http() {
|
||||||
|
return this.#http;
|
||||||
|
}
|
||||||
|
|
||||||
|
get id() {
|
||||||
|
return this.#id;
|
||||||
}
|
}
|
||||||
|
|
||||||
get messageHandler() {
|
get messageHandler() {
|
||||||
if (!this._messageHandler) {
|
if (!this.#messageHandler) {
|
||||||
this._messageHandler =
|
this.#messageHandler =
|
||||||
lazy.RootMessageHandlerRegistry.getOrCreateMessageHandler(this.id);
|
lazy.RootMessageHandlerRegistry.getOrCreateMessageHandler(this.#id);
|
||||||
this._onMessageHandlerProtocolEvent =
|
this._onMessageHandlerProtocolEvent =
|
||||||
this._onMessageHandlerProtocolEvent.bind(this);
|
this._onMessageHandlerProtocolEvent.bind(this);
|
||||||
this._messageHandler.on(
|
this.#messageHandler.on(
|
||||||
"message-handler-protocol-event",
|
"message-handler-protocol-event",
|
||||||
this._onMessageHandlerProtocolEvent
|
this._onMessageHandlerProtocolEvent
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this._messageHandler;
|
return this.#messageHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
get pageLoadStrategy() {
|
get pageLoadStrategy() {
|
||||||
return this.capabilities.get("pageLoadStrategy");
|
return this.#capabilities.get("pageLoadStrategy");
|
||||||
|
}
|
||||||
|
|
||||||
|
get path() {
|
||||||
|
return this.#path;
|
||||||
}
|
}
|
||||||
|
|
||||||
get proxy() {
|
get proxy() {
|
||||||
return this.capabilities.get("proxy");
|
return this.#capabilities.get("proxy");
|
||||||
}
|
}
|
||||||
|
|
||||||
get strictFileInteractability() {
|
get strictFileInteractability() {
|
||||||
return this.capabilities.get("strictFileInteractability");
|
return this.#capabilities.get("strictFileInteractability");
|
||||||
}
|
}
|
||||||
|
|
||||||
get timeouts() {
|
get timeouts() {
|
||||||
return this.capabilities.get("timeouts");
|
return this.#capabilities.get("timeouts");
|
||||||
}
|
}
|
||||||
|
|
||||||
set timeouts(timeouts) {
|
set timeouts(timeouts) {
|
||||||
this.capabilities.set("timeouts", timeouts);
|
this.#capabilities.set("timeouts", timeouts);
|
||||||
}
|
}
|
||||||
|
|
||||||
get userPromptHandler() {
|
get userPromptHandler() {
|
||||||
return this.capabilities.get("unhandledPromptBehavior");
|
return this.#capabilities.get("unhandledPromptBehavior");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -330,15 +372,15 @@ export class WebDriverSession {
|
||||||
* @param {WebDriverBiDiConnection} connection
|
* @param {WebDriverBiDiConnection} connection
|
||||||
*/
|
*/
|
||||||
removeConnection(connection) {
|
removeConnection(connection) {
|
||||||
if (this._connections.has(connection)) {
|
if (this.#connections.has(connection)) {
|
||||||
this._connections.delete(connection);
|
this.#connections.delete(connection);
|
||||||
} else {
|
} else {
|
||||||
lazy.logger.warn("Trying to remove a connection that doesn't exist.");
|
lazy.logger.warn("Trying to remove a connection that doesn't exist.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
toString() {
|
toString() {
|
||||||
return `[object ${this.constructor.name} ${this.id}]`;
|
return `[object ${this.constructor.name} ${this.#id}]`;
|
||||||
}
|
}
|
||||||
|
|
||||||
// nsIHttpRequestHandler
|
// nsIHttpRequestHandler
|
||||||
|
|
@ -362,12 +404,12 @@ export class WebDriverSession {
|
||||||
response._connection
|
response._connection
|
||||||
);
|
);
|
||||||
conn.registerSession(this);
|
conn.registerSession(this);
|
||||||
this._connections.add(conn);
|
this.#connections.add(conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onMessageHandlerProtocolEvent(eventName, messageHandlerEvent) {
|
_onMessageHandlerProtocolEvent(eventName, messageHandlerEvent) {
|
||||||
const { name, data } = messageHandlerEvent;
|
const { name, data } = messageHandlerEvent;
|
||||||
this._connections.forEach(connection => connection.sendEvent(name, data));
|
this.#connections.forEach(connection => connection.sendEvent(name, data));
|
||||||
}
|
}
|
||||||
|
|
||||||
// XPCOM
|
// XPCOM
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,7 @@ add_task(function test_Timeouts_fromJSON() {
|
||||||
equal(ts.script, json.script);
|
equal(ts.script, json.script);
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(function test_Timeouts_fromJSON_unrecognised_field() {
|
add_task(function test_Timeouts_fromJSON_unrecognized_field() {
|
||||||
let json = {
|
let json = {
|
||||||
sessionId: "foobar",
|
sessionId: "foobar",
|
||||||
};
|
};
|
||||||
|
|
@ -58,7 +58,7 @@ add_task(function test_Timeouts_fromJSON_unrecognised_field() {
|
||||||
Timeouts.fromJSON(json);
|
Timeouts.fromJSON(json);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
equal(e.name, error.InvalidArgumentError.name);
|
equal(e.name, error.InvalidArgumentError.name);
|
||||||
equal(e.message, "Unrecognised timeout: sessionId");
|
equal(e.message, "Unrecognized timeout: sessionId");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -439,27 +439,53 @@ add_task(function test_Capabilities_fromJSON() {
|
||||||
caps = fromJSON({ acceptInsecureCerts: false });
|
caps = fromJSON({ acceptInsecureCerts: false });
|
||||||
equal(false, caps.get("acceptInsecureCerts"));
|
equal(false, caps.get("acceptInsecureCerts"));
|
||||||
|
|
||||||
for (let strategy of Object.values(PageLoadStrategy)) {
|
|
||||||
caps = fromJSON({ pageLoadStrategy: strategy });
|
|
||||||
equal(strategy, caps.get("pageLoadStrategy"));
|
|
||||||
}
|
|
||||||
|
|
||||||
let proxyConfig = { proxyType: "manual" };
|
let proxyConfig = { proxyType: "manual" };
|
||||||
caps = fromJSON({ proxy: proxyConfig });
|
caps = fromJSON({ proxy: proxyConfig });
|
||||||
equal("manual", caps.get("proxy").proxyType);
|
equal("manual", caps.get("proxy").proxyType);
|
||||||
|
|
||||||
|
// HTTP only capabilities
|
||||||
|
for (let strategy of Object.values(PageLoadStrategy)) {
|
||||||
|
caps = fromJSON({ pageLoadStrategy: strategy }, true);
|
||||||
|
equal(strategy, caps.get("pageLoadStrategy"));
|
||||||
|
|
||||||
|
caps = fromJSON({ pageLoadStrategy: strategy });
|
||||||
|
equal("normal", caps.get("pageLoadStrategy"));
|
||||||
|
}
|
||||||
|
|
||||||
let timeoutsConfig = { implicit: 123 };
|
let timeoutsConfig = { implicit: 123 };
|
||||||
caps = fromJSON({ timeouts: timeoutsConfig });
|
caps = fromJSON({ timeouts: timeoutsConfig });
|
||||||
|
equal(0, caps.get("timeouts").implicit);
|
||||||
|
caps = fromJSON({ timeouts: timeoutsConfig }, true);
|
||||||
equal(123, caps.get("timeouts").implicit);
|
equal(123, caps.get("timeouts").implicit);
|
||||||
|
|
||||||
caps = fromJSON({ strictFileInteractability: false });
|
caps = fromJSON({ strictFileInteractability: false }, true);
|
||||||
equal(false, caps.get("strictFileInteractability"));
|
equal(false, caps.get("strictFileInteractability"));
|
||||||
caps = fromJSON({ strictFileInteractability: true });
|
caps = fromJSON({ strictFileInteractability: true }, true);
|
||||||
equal(true, caps.get("strictFileInteractability"));
|
equal(true, caps.get("strictFileInteractability"));
|
||||||
|
|
||||||
caps = fromJSON({ webSocketUrl: true });
|
caps = fromJSON({ webSocketUrl: true }, true);
|
||||||
equal(true, caps.get("webSocketUrl"));
|
equal(true, caps.get("webSocketUrl"));
|
||||||
|
|
||||||
|
// Mozilla specific capabilities
|
||||||
|
caps = fromJSON({ "moz:accessibilityChecks": true });
|
||||||
|
equal(true, caps.get("moz:accessibilityChecks"));
|
||||||
|
caps = fromJSON({ "moz:accessibilityChecks": false });
|
||||||
|
equal(false, caps.get("moz:accessibilityChecks"));
|
||||||
|
|
||||||
|
caps = fromJSON({ "moz:webdriverClick": true }, true);
|
||||||
|
equal(true, caps.get("moz:webdriverClick"));
|
||||||
|
caps = fromJSON({ "moz:webdriverClick": false }, true);
|
||||||
|
equal(false, caps.get("moz:webdriverClick"));
|
||||||
|
|
||||||
|
// capability is always populated with null if remote agent is not listening
|
||||||
|
caps = fromJSON({});
|
||||||
|
equal(null, caps.get("moz:debuggerAddress"));
|
||||||
|
caps = fromJSON({ "moz:debuggerAddress": "foo" });
|
||||||
|
equal(null, caps.get("moz:debuggerAddress"));
|
||||||
|
caps = fromJSON({ "moz:debuggerAddress": true });
|
||||||
|
equal(null, caps.get("moz:debuggerAddress"));
|
||||||
|
|
||||||
|
// Extension capabilities
|
||||||
caps = fromJSON({ "webauthn:virtualAuthenticators": true });
|
caps = fromJSON({ "webauthn:virtualAuthenticators": true });
|
||||||
equal(true, caps.get("webauthn:virtualAuthenticators"));
|
equal(true, caps.get("webauthn:virtualAuthenticators"));
|
||||||
caps = fromJSON({ "webauthn:virtualAuthenticators": false });
|
caps = fromJSON({ "webauthn:virtualAuthenticators": false });
|
||||||
|
|
@ -505,31 +531,13 @@ add_task(function test_Capabilities_fromJSON() {
|
||||||
/InvalidArgumentError/
|
/InvalidArgumentError/
|
||||||
);
|
);
|
||||||
|
|
||||||
caps = fromJSON({ "moz:accessibilityChecks": true });
|
|
||||||
equal(true, caps.get("moz:accessibilityChecks"));
|
|
||||||
caps = fromJSON({ "moz:accessibilityChecks": false });
|
|
||||||
equal(false, caps.get("moz:accessibilityChecks"));
|
|
||||||
|
|
||||||
// capability is always populated with null if remote agent is not listening
|
|
||||||
caps = fromJSON({});
|
|
||||||
equal(null, caps.get("moz:debuggerAddress"));
|
|
||||||
caps = fromJSON({ "moz:debuggerAddress": "foo" });
|
|
||||||
equal(null, caps.get("moz:debuggerAddress"));
|
|
||||||
caps = fromJSON({ "moz:debuggerAddress": true });
|
|
||||||
equal(null, caps.get("moz:debuggerAddress"));
|
|
||||||
|
|
||||||
caps = fromJSON({ "moz:webdriverClick": true });
|
|
||||||
equal(true, caps.get("moz:webdriverClick"));
|
|
||||||
caps = fromJSON({ "moz:webdriverClick": false });
|
|
||||||
equal(false, caps.get("moz:webdriverClick"));
|
|
||||||
|
|
||||||
// No longer supported capabilities
|
// No longer supported capabilities
|
||||||
Assert.throws(
|
Assert.throws(
|
||||||
() => fromJSON({ "moz:useNonSpecCompliantPointerOrigin": false }),
|
() => fromJSON({ "moz:useNonSpecCompliantPointerOrigin": false }, true),
|
||||||
/InvalidArgumentError/
|
/InvalidArgumentError/
|
||||||
);
|
);
|
||||||
Assert.throws(
|
Assert.throws(
|
||||||
() => fromJSON({ "moz:useNonSpecCompliantPointerOrigin": true }),
|
() => fromJSON({ "moz:useNonSpecCompliantPointerOrigin": true }, true),
|
||||||
/InvalidArgumentError/
|
/InvalidArgumentError/
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
const { Capabilities, Timeouts } = ChromeUtils.importESModule(
|
const { Timeouts } = ChromeUtils.importESModule(
|
||||||
"chrome://remote/content/shared/webdriver/Capabilities.sys.mjs"
|
"chrome://remote/content/shared/webdriver/Capabilities.sys.mjs"
|
||||||
);
|
);
|
||||||
const { getWebDriverSessionById, WebDriverSession } =
|
const { getWebDriverSessionById, WebDriverSession } =
|
||||||
|
|
@ -12,26 +12,79 @@ const { getWebDriverSessionById, WebDriverSession } =
|
||||||
"chrome://remote/content/shared/webdriver/Session.sys.mjs"
|
"chrome://remote/content/shared/webdriver/Session.sys.mjs"
|
||||||
);
|
);
|
||||||
|
|
||||||
add_task(function test_WebDriverSession_ctor() {
|
function createSession(options = {}) {
|
||||||
const session = new WebDriverSession();
|
const { capabilities = {}, connection, isHttp = false } = options;
|
||||||
|
|
||||||
|
const flags = new Set();
|
||||||
|
if (isHttp) {
|
||||||
|
flags.add("http");
|
||||||
|
}
|
||||||
|
|
||||||
|
return new WebDriverSession(capabilities, flags, connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
add_task(function test_WebDriverSession_ctor() {
|
||||||
|
Assert.throws(() => new WebDriverSession({}), /TypeError/);
|
||||||
|
|
||||||
|
// Session id and path
|
||||||
|
let session = createSession();
|
||||||
equal(typeof session.id, "string");
|
equal(typeof session.id, "string");
|
||||||
ok(session.capabilities instanceof Capabilities);
|
equal(session.path, `/session/${session.id}`);
|
||||||
|
|
||||||
|
// Sets HTTP flag
|
||||||
|
session = createSession({ isHttp: true });
|
||||||
|
equal(session.http, true);
|
||||||
|
session = createSession({ isHttp: false });
|
||||||
|
equal(session.http, false);
|
||||||
|
|
||||||
|
// Sets capabilities based on session configuration flag.
|
||||||
|
const capabilities = {
|
||||||
|
acceptInsecureCerts: true,
|
||||||
|
unhandledPromptBehavior: "ignore",
|
||||||
|
|
||||||
|
// HTTP only
|
||||||
|
pageLoadStrategy: "eager",
|
||||||
|
strictFileInteractability: true,
|
||||||
|
timeouts: { script: 1000 },
|
||||||
|
};
|
||||||
|
|
||||||
|
// HTTP session
|
||||||
|
session = createSession({ isHttp: true, capabilities });
|
||||||
|
equal(session.acceptInsecureCerts, true);
|
||||||
|
equal(session.pageLoadStrategy, "eager");
|
||||||
|
equal(session.strictFileInteractability, true);
|
||||||
|
equal(session.timeouts.script, 1000);
|
||||||
|
equal(session.userPromptHandler.toJSON(), "ignore");
|
||||||
|
|
||||||
|
// BiDi session (uses default values for HTTP only capabilities)
|
||||||
|
session = createSession({ isHttp: false, capabilities });
|
||||||
|
equal(session.acceptInsecureCerts, true);
|
||||||
|
equal(session.pageLoadStrategy, "normal");
|
||||||
|
equal(session.strictFileInteractability, false);
|
||||||
|
equal(session.timeouts.script, 30000);
|
||||||
|
equal(session.userPromptHandler.toJSON(), "dismiss and notify");
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(function test_WebDriverSession_destroy() {
|
add_task(function test_WebDriverSession_destroy() {
|
||||||
const session = new WebDriverSession();
|
const session = createSession();
|
||||||
|
|
||||||
session.destroy();
|
session.destroy();
|
||||||
|
|
||||||
|
// Calling twice doesn't raise error.
|
||||||
|
session.destroy();
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(function test_WebDriverSession_getters() {
|
add_task(function test_WebDriverSession_getters() {
|
||||||
const session = new WebDriverSession();
|
const session = createSession();
|
||||||
|
|
||||||
equal(
|
equal(
|
||||||
session.a11yChecks,
|
session.a11yChecks,
|
||||||
session.capabilities.get("moz:accessibilityChecks")
|
session.capabilities.get("moz:accessibilityChecks")
|
||||||
);
|
);
|
||||||
|
equal(
|
||||||
|
session.acceptInsecureCerts,
|
||||||
|
session.capabilities.get("acceptInsecureCerts")
|
||||||
|
);
|
||||||
equal(session.pageLoadStrategy, session.capabilities.get("pageLoadStrategy"));
|
equal(session.pageLoadStrategy, session.capabilities.get("pageLoadStrategy"));
|
||||||
equal(session.proxy, session.capabilities.get("proxy"));
|
equal(session.proxy, session.capabilities.get("proxy"));
|
||||||
equal(
|
equal(
|
||||||
|
|
@ -46,7 +99,7 @@ add_task(function test_WebDriverSession_getters() {
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(function test_WebDriverSession_setters() {
|
add_task(function test_WebDriverSession_setters() {
|
||||||
const session = new WebDriverSession();
|
const session = createSession();
|
||||||
|
|
||||||
const timeouts = new Timeouts();
|
const timeouts = new Timeouts();
|
||||||
timeouts.pageLoad = 45;
|
timeouts.pageLoad = 45;
|
||||||
|
|
@ -56,8 +109,8 @@ add_task(function test_WebDriverSession_setters() {
|
||||||
});
|
});
|
||||||
|
|
||||||
add_task(function test_getWebDriverSessionById() {
|
add_task(function test_getWebDriverSessionById() {
|
||||||
const session1 = new WebDriverSession();
|
const session1 = createSession();
|
||||||
const session2 = new WebDriverSession();
|
const session2 = createSession();
|
||||||
|
|
||||||
equal(getWebDriverSessionById(session1.id), session1);
|
equal(getWebDriverSessionById(session1.id), session1);
|
||||||
equal(getWebDriverSessionById(session2.id), session2);
|
equal(getWebDriverSessionById(session2.id), session2);
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,8 @@ export class WebDriverBiDi {
|
||||||
* @param {Object<string, *>=} capabilities
|
* @param {Object<string, *>=} capabilities
|
||||||
* JSON Object containing any of the recognised capabilities as listed
|
* JSON Object containing any of the recognised capabilities as listed
|
||||||
* on the `WebDriverSession` class.
|
* on the `WebDriverSession` class.
|
||||||
*
|
* @param {Set} flags
|
||||||
|
* Session configuration flags.
|
||||||
* @param {WebDriverBiDiConnection=} sessionlessConnection
|
* @param {WebDriverBiDiConnection=} sessionlessConnection
|
||||||
* Optional connection that is not yet accociated with a WebDriver
|
* Optional connection that is not yet accociated with a WebDriver
|
||||||
* session, and has to be associated with the new WebDriver session.
|
* session, and has to be associated with the new WebDriver session.
|
||||||
|
|
@ -80,7 +81,7 @@ export class WebDriverBiDi {
|
||||||
* @throws {SessionNotCreatedError}
|
* @throws {SessionNotCreatedError}
|
||||||
* If, for whatever reason, a session could not be created.
|
* If, for whatever reason, a session could not be created.
|
||||||
*/
|
*/
|
||||||
async createSession(capabilities, sessionlessConnection) {
|
async createSession(capabilities, flags, sessionlessConnection) {
|
||||||
if (this.session) {
|
if (this.session) {
|
||||||
throw new lazy.error.SessionNotCreatedError(
|
throw new lazy.error.SessionNotCreatedError(
|
||||||
"Maximum number of active sessions"
|
"Maximum number of active sessions"
|
||||||
|
|
@ -89,6 +90,7 @@ export class WebDriverBiDi {
|
||||||
|
|
||||||
const session = new lazy.WebDriverSession(
|
const session = new lazy.WebDriverSession(
|
||||||
capabilities,
|
capabilities,
|
||||||
|
flags,
|
||||||
sessionlessConnection
|
sessionlessConnection
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -180,13 +180,15 @@ export class WebDriverBiDiConnection extends WebSocketConnection {
|
||||||
if (module === "session" && command === "new") {
|
if (module === "session" && command === "new") {
|
||||||
const processedCapabilities = lazy.processCapabilities(params);
|
const processedCapabilities = lazy.processCapabilities(params);
|
||||||
|
|
||||||
|
const flags = new Set();
|
||||||
result = await lazy.RemoteAgent.webDriverBiDi.createSession(
|
result = await lazy.RemoteAgent.webDriverBiDi.createSession(
|
||||||
processedCapabilities,
|
processedCapabilities,
|
||||||
|
flags,
|
||||||
this
|
this
|
||||||
);
|
);
|
||||||
|
|
||||||
// Since in Capabilities class we setup default values also for capabilities which are
|
// The Capabilities class sets up default values also for capabilities
|
||||||
// not relevant for bidi, we want to remove them from the payload before returning to a client.
|
// which are not relevant for BiDi, we want to remove those from the payload.
|
||||||
result.capabilities = Array.from(result.capabilities.entries()).reduce(
|
result.capabilities = Array.from(result.capabilities.entries()).reduce(
|
||||||
(object, [key, value]) => {
|
(object, [key, value]) => {
|
||||||
if (!lazy.WEBDRIVER_CLASSIC_CAPABILITIES.includes(key)) {
|
if (!lazy.WEBDRIVER_CLASSIC_CAPABILITIES.includes(key)) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue