Skip to content

Commit

Permalink
Bug 1884090 - [remote] Add support for "HTTP flag" in WebDriver Sessi…
Browse files Browse the repository at this point in the history
…on. r=webdriver-reviewers,jdescottes

Differential Revision: https://phabricator.services.mozilla.com/D211815
  • Loading branch information
whimboo committed May 29, 2024
1 parent c3852c5 commit 86ccdaf
Show file tree
Hide file tree
Showing 8 changed files with 262 additions and 128 deletions.
21 changes: 15 additions & 6 deletions remote/marionette/driver.sys.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,9 @@ export function GeckoDriver(server) {
// WebDriver Session
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
this._isShuttingDown = false;

Expand Down Expand Up @@ -401,14 +404,20 @@ GeckoDriver.prototype.newSession = async function (cmd) {
const { parameters: capabilities } = cmd;

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) {
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 {
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");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const { error } = ChromeUtils.importESModule(
);

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");
await Assert.rejects(
Expand All @@ -24,7 +24,7 @@ add_task(async function test_execute_missing_command_error() {
});

add_task(async function test_execute_missing_internal_command_error() {
const session = new WebDriverSession();
const session = new WebDriverSession({}, new Set());

info(
"Attempt to execute a protocol command which relies on an unknown internal method"
Expand Down
90 changes: 54 additions & 36 deletions remote/shared/webdriver/Capabilities.sys.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
* 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/. */

import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";

const lazy = {};

ChromeUtils.defineESModuleGetters(lazy, {
Expand All @@ -14,21 +16,45 @@ ChromeUtils.defineESModuleGetters(lazy, {
"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", () => {
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.
export const WEBDRIVER_CLASSIC_CAPABILITIES = [
"pageLoadStrategy",
"timeouts",
"strictFileInteractability",
"timeouts",
"unhandledPromptBehavior",
"webSocketUrl",
"moz:useNonSpecCompliantPointerOrigin",
"moz:webdriverClick",

// Gecko specific capabilities
"moz:debuggerAddress",
"moz:firefoxOptions",
"moz:useNonSpecCompliantPointerOrigin",
"moz:webdriverClick",
];

/** Representation of WebDriver session timeouts. */
Expand Down Expand Up @@ -90,7 +116,7 @@ export class Timeouts {

default:
throw new lazy.error.InvalidArgumentError(
"Unrecognised timeout: " + type
`Unrecognized timeout: ${type}`
);
}
}
Expand Down Expand Up @@ -407,51 +433,36 @@ export class Proxy {
}
}

/** WebDriver session capabilities representation. */
export class Capabilities extends Map {
/** @class */
/**
* WebDriver session capabilities representation.
*/
constructor() {
// Default values for capabilities supported by both WebDriver protocols
super([
// webdriver
["browserName", getWebDriverBrowserName()],
["browserVersion", lazy.AppInfo.version],
["platformName", getWebDriverPlatformName()],
["acceptInsecureCerts", false],
["pageLoadStrategy", PageLoadStrategy.Normal],
["proxy", new Proxy()],
["setWindowRect", !lazy.AppInfo.isAndroid],
["unhandledPromptBehavior", new lazy.UserPromptHandler()],
["userAgent", lazy.userAgent],

// HTTP only capabilities
["pageLoadStrategy", PageLoadStrategy.Normal],
["timeouts", new Timeouts()],
["setWindowRect", !lazy.AppInfo.isAndroid],
["strictFileInteractability", false],
["unhandledPromptBehavior", new lazy.UserPromptHandler()],
[
"userAgent",
Cc["@mozilla.org/network/protocol;1?name=http"].getService(
Ci.nsIHttpProtocolHandler
).userAgent,
],
["webSocketUrl", null],

// proprietary

// Gecko specific capabilities
["moz:accessibilityChecks", false],
["moz:buildID", lazy.AppInfo.appBuildID],
[
"moz:debuggerAddress",
// 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:debuggerAddress", lazy.debuggerAddress],
["moz:headless", lazy.isHeadless],
["moz:platformVersion", Services.sysinfo.getProperty("version")],
["moz:processID", lazy.AppInfo.processID],
["moz:profile", maybeProfile()],
[
"moz:shutdownTimeout",
Services.prefs.getIntPref("toolkit.asyncshutdown.crash_timeout"),
],
["moz:shutdownTimeout", lazy.shutdownTimeout],
["moz:webdriverClick", true],
["moz:windowless", false],
]);
Expand All @@ -478,7 +489,7 @@ export class Capabilities extends Map {
}

/**
* JSON serialisation of capabilities object.
* JSON serialization of capabilities object.
*
* @returns {Object<string, ?>}
*/
Expand All @@ -501,11 +512,13 @@ export class Capabilities extends Map {
*
* @param {Object<string, *>=} json
* WebDriver capabilities.
* @param {boolean=} isHttp
* Flag indicating that it is a WebDriver classic session. Defaults to false.
*
* @returns {Capabilities}
* Internal representation of WebDriver capabilities.
*/
static fromJSON(json) {
static fromJSON(json, isHttp = false) {
if (typeof json == "undefined" || json === null) {
json = {};
}
Expand All @@ -518,6 +531,11 @@ export class Capabilities extends Map {
// TODO: Bug 1823907. We can start using here spec compliant method `validate`,
// as soon as `desiredCapabilities` and `requiredCapabilities` are not supported.
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) {
case "acceptInsecureCerts":
lazy.assert.boolean(
Expand Down
Loading

0 comments on commit 86ccdaf

Please sign in to comment.