forked from mirrors/gecko-dev
Bug 1717899 - [remote] Extend the lifetime of the Remote Agent to the Firefox session. r=webdriver-reviewers,jdescottes
Differential Revision: https://phabricator.services.mozilla.com/D144338
This commit is contained in:
parent
4d5eb6f009
commit
dcdabedb93
21 changed files with 80 additions and 196 deletions
|
|
@ -9,7 +9,6 @@ with Files("**"):
|
|||
|
||||
BROWSER_CHROME_MANIFESTS += [
|
||||
"test/browser/browser.ini",
|
||||
"test/browser/component/browser.ini",
|
||||
"test/browser/dom/browser.ini",
|
||||
"test/browser/emulation/browser.ini",
|
||||
"test/browser/fetch/browser.ini",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
[DEFAULT]
|
||||
tags = remote
|
||||
subsuite = remote
|
||||
args =
|
||||
--remote-debugging-port
|
||||
--remote-allow-origins=null
|
||||
prefs = # Bug 1600054: Make CDP Fission compatible
|
||||
fission.bfcacheInParent=false
|
||||
fission.webContentIsolationStrategy=0
|
||||
|
|
@ -8,6 +11,7 @@ support-files =
|
|||
chrome-remote-interface.js
|
||||
head.js
|
||||
|
||||
[browser_agent.js]
|
||||
[browser_cdp.js]
|
||||
[browser_httpd.js]
|
||||
[browser_main_target.js]
|
||||
|
|
|
|||
14
remote/cdp/test/browser/browser_agent.js
Normal file
14
remote/cdp/test/browser/browser_agent.js
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
// To fully test the Remote Agent's capabilities an instance of the interface
|
||||
// also needs to be used.
|
||||
const remoteAgentInstance = Cc["@mozilla.org/remote/agent;1"].createInstance(
|
||||
Ci.nsIRemoteAgent
|
||||
);
|
||||
|
||||
add_task(async function listening() {
|
||||
is(remoteAgentInstance.listening, true, "Agent is listening");
|
||||
});
|
||||
|
|
@ -4,8 +4,6 @@
|
|||
"use strict";
|
||||
|
||||
add_task(async function json_version() {
|
||||
await RemoteAgent.listen(`http://localhost:0`);
|
||||
|
||||
const { userAgent } = Cc[
|
||||
"@mozilla.org/network/protocol;1?name=http"
|
||||
].getService(Ci.nsIHttpProtocolHandler);
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
[DEFAULT]
|
||||
tags = remote
|
||||
subsuite = remote
|
||||
support-files =
|
||||
!/remote/cdp/test/browser/chrome-remote-interface.js
|
||||
!/remote/cdp/test/browser/head.js
|
||||
head.js
|
||||
|
||||
# These tests need to start and close RemoteAgent several times.
|
||||
# It should be the only tests in this suite to avoid side-effects with
|
||||
# regular tests which reuse a shared RemoteAgent instance.
|
||||
[browser_agent.js]
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const URL = "http://localhost:0";
|
||||
|
||||
add_agent_task(async function debuggerAddress() {
|
||||
const port = getNonAtomicFreePort();
|
||||
|
||||
await RemoteAgent.listen(`http://localhost:${port}`);
|
||||
is(
|
||||
remoteAgentInstance.debuggerAddress,
|
||||
`localhost:${port}`,
|
||||
"debuggerAddress set"
|
||||
);
|
||||
});
|
||||
|
||||
add_agent_task(async function listening() {
|
||||
is(remoteAgentInstance.listening, false, "Agent is not listening");
|
||||
await RemoteAgent.listen(URL);
|
||||
is(remoteAgentInstance.listening, true, "Agent is listening");
|
||||
});
|
||||
|
||||
add_agent_task(async function remoteListeningNotification() {
|
||||
let active;
|
||||
const port = getNonAtomicFreePort();
|
||||
|
||||
function observer(subject, topic, data) {
|
||||
Services.obs.removeObserver(observer, topic);
|
||||
|
||||
active = data;
|
||||
}
|
||||
|
||||
Services.obs.addObserver(observer, "remote-listening");
|
||||
await RemoteAgent.listen("http://localhost:" + port);
|
||||
is(active, "true", "remote-listening observer notified enabled state");
|
||||
|
||||
Services.obs.addObserver(observer, "remote-listening");
|
||||
await RemoteAgent.close();
|
||||
is(active, null, "remote-listening observer notified disabled state");
|
||||
});
|
||||
|
||||
// TODO(ato): https://bugzil.la/1590829
|
||||
add_agent_task(async function listenTakesString() {
|
||||
await RemoteAgent.listen("http://localhost:0");
|
||||
await RemoteAgent.close();
|
||||
});
|
||||
|
||||
// TODO(ato): https://bugzil.la/1590829
|
||||
add_agent_task(async function listenNonURL() {
|
||||
try {
|
||||
await RemoteAgent.listen("foobar");
|
||||
fail("listen() did not reject non-URL");
|
||||
} catch (e) {
|
||||
is(e.result, Cr.NS_ERROR_MALFORMED_URI);
|
||||
}
|
||||
});
|
||||
|
||||
add_agent_task(async function listenRestrictedToLoopbackDevice() {
|
||||
try {
|
||||
await RemoteAgent.listen("http://0.0.0.0:9222");
|
||||
fail("listen() did not reject non-loopback device");
|
||||
} catch (e) {
|
||||
is(e.result, Cr.NS_ERROR_ILLEGAL_VALUE);
|
||||
is(e.message, "Restricted to loopback devices");
|
||||
}
|
||||
});
|
||||
|
||||
add_agent_task(async function test_close() {
|
||||
await RemoteAgent.listen(URL);
|
||||
await RemoteAgent.close();
|
||||
// no-op when not listening
|
||||
await RemoteAgent.close();
|
||||
});
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
/* import-globals-from ../head.js */
|
||||
|
||||
Services.scriptloader.loadSubScript(
|
||||
"chrome://mochitests/content/browser/remote/cdp/test/browser/head.js",
|
||||
this
|
||||
);
|
||||
|
||||
// To fully test the Remote Agent's capabilities an instance of the interface
|
||||
// also needs to be used.
|
||||
const remoteAgentInstance = Cc["@mozilla.org/remote/agent;1"].createInstance(
|
||||
Ci.nsIRemoteAgent
|
||||
);
|
||||
|
||||
// set up test conditions and clean up
|
||||
function add_agent_task(originalTask) {
|
||||
const task = async function() {
|
||||
await RemoteAgent.close();
|
||||
await originalTask();
|
||||
};
|
||||
Object.defineProperty(task, "name", {
|
||||
value: originalTask.name,
|
||||
writable: false,
|
||||
});
|
||||
add_plain_task(task);
|
||||
}
|
||||
|
||||
function getNonAtomicFreePort() {
|
||||
const so = Cc["@mozilla.org/network/server-socket;1"].createInstance(
|
||||
Ci.nsIServerSocket
|
||||
);
|
||||
try {
|
||||
so.init(-1, true /* aLoopbackOnly */, -1 /* aBackLog */);
|
||||
return so.port;
|
||||
} finally {
|
||||
so.close();
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,9 @@
|
|||
[DEFAULT]
|
||||
tags = remote
|
||||
subsuite = remote
|
||||
args =
|
||||
--remote-debugging-port
|
||||
--remote-allow-origins=null
|
||||
prefs = # Bug 1600054: Make CDP Fission compatible
|
||||
fission.bfcacheInParent=false
|
||||
fission.webContentIsolationStrategy=0
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
[DEFAULT]
|
||||
tags = remote
|
||||
subsuite = remote
|
||||
args =
|
||||
--remote-debugging-port
|
||||
--remote-allow-origins=null
|
||||
prefs = # Bug 1600054: Make CDP Fission compatible
|
||||
fission.bfcacheInParent=false
|
||||
fission.webContentIsolationStrategy=0
|
||||
|
|
|
|||
|
|
@ -1,7 +1,12 @@
|
|||
[DEFAULT]
|
||||
tags = remote
|
||||
subsuite = remote
|
||||
skip-if = fission # Bug 1600054: Make cdp Fission compatible
|
||||
args =
|
||||
--remote-debugging-port
|
||||
--remote-allow-origins=null
|
||||
prefs = # Bug 1600054: Make CDP Fission compatible
|
||||
fission.bfcacheInParent=false
|
||||
fission.webContentIsolationStrategy=0
|
||||
support-files =
|
||||
!/remote/cdp/test/browser/chrome-remote-interface.js
|
||||
!/remote/cdp/test/browser/head.js
|
||||
|
|
|
|||
|
|
@ -15,16 +15,6 @@ const { TabManager } = ChromeUtils.import(
|
|||
"chrome://remote/content/shared/TabManager.jsm"
|
||||
);
|
||||
|
||||
const { allowNullOrigin } = ChromeUtils.import(
|
||||
"chrome://remote/content/server/WebSocketHandshake.jsm"
|
||||
);
|
||||
|
||||
// The handshake request created by the browser mochitests contains an origin
|
||||
// header, which is currently not supported. This origin is a string "null".
|
||||
// Explicitly allow such an origin for the duration of the test.
|
||||
allowNullOrigin(true);
|
||||
registerCleanupFunction(() => allowNullOrigin(false));
|
||||
|
||||
const TIMEOUT_MULTIPLIER = SpecialPowers.isDebugBuild ? 4 : 1;
|
||||
const TIMEOUT_EVENTS = 1000 * TIMEOUT_MULTIPLIER;
|
||||
|
||||
|
|
@ -52,16 +42,6 @@ setup and teardown described above.
|
|||
|
||||
const add_plain_task = add_task.bind(this);
|
||||
|
||||
// Start RemoteAgent lazily and reuse it for all the tests in the suite.
|
||||
// Starting and stopping RemoteAgent for every test would trigger race conditions
|
||||
// in httpd.js. See Bug 1609162.
|
||||
async function startRemoteAgent() {
|
||||
if (!RemoteAgent.listening) {
|
||||
await RemoteAgent.listen(Services.io.newURI("http://localhost:9222"));
|
||||
info("Remote agent started");
|
||||
}
|
||||
}
|
||||
|
||||
this.add_task = function(taskFn, opts = {}) {
|
||||
const {
|
||||
createTab = true, // By default run each test in its own tab
|
||||
|
|
@ -70,8 +50,6 @@ this.add_task = function(taskFn, opts = {}) {
|
|||
const fn = async function() {
|
||||
let client, tab, target;
|
||||
|
||||
await startRemoteAgent();
|
||||
|
||||
try {
|
||||
const CDP = await getCDP();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
[DEFAULT]
|
||||
tags = remote
|
||||
subsuite = remote
|
||||
args =
|
||||
--remote-debugging-port
|
||||
--remote-allow-origins=null
|
||||
prefs = # Bug 1600054: Make CDP Fission compatible
|
||||
fission.bfcacheInParent=false
|
||||
fission.webContentIsolationStrategy=0
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
[DEFAULT]
|
||||
tags = remote
|
||||
subsuite = remote
|
||||
args =
|
||||
--remote-debugging-port
|
||||
--remote-allow-origins=null
|
||||
prefs = # Bug 1600054: Make CDP Fission compatible
|
||||
fission.bfcacheInParent=false
|
||||
fission.webContentIsolationStrategy=0
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
[DEFAULT]
|
||||
tags = remote
|
||||
subsuite = remote
|
||||
args =
|
||||
--remote-debugging-port
|
||||
--remote-allow-origins=null
|
||||
prefs = # Bug 1600054: Make CDP Fission compatible
|
||||
fission.bfcacheInParent=false
|
||||
fission.webContentIsolationStrategy=0
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
[DEFAULT]
|
||||
tags = remote
|
||||
subsuite = remote
|
||||
args =
|
||||
--remote-debugging-port
|
||||
--remote-allow-origins=null
|
||||
prefs = # Bug 1600054: Make CDP Fission compatible
|
||||
fission.bfcacheInParent=false
|
||||
fission.webContentIsolationStrategy=0
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
[DEFAULT]
|
||||
tags = remote
|
||||
subsuite = remote
|
||||
args =
|
||||
--remote-debugging-port
|
||||
--remote-allow-origins=null
|
||||
prefs = # Bug 1600054: Make CDP Fission compatible
|
||||
fission.bfcacheInParent=false
|
||||
fission.webContentIsolationStrategy=0
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
[DEFAULT]
|
||||
tags = remote
|
||||
subsuite = remote
|
||||
args =
|
||||
--remote-debugging-port
|
||||
--remote-allow-origins=null
|
||||
prefs = # Bug 1600054: Make CDP Fission compatible
|
||||
fission.bfcacheInParent=false
|
||||
fission.webContentIsolationStrategy=0
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
[DEFAULT]
|
||||
tags = remote
|
||||
subsuite = remote
|
||||
args =
|
||||
--remote-debugging-port
|
||||
--remote-allow-origins=null
|
||||
prefs = # Bug 1600054: Make CDP Fission compatible
|
||||
fission.bfcacheInParent=false
|
||||
fission.webContentIsolationStrategy=0
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
[DEFAULT]
|
||||
tags = remote
|
||||
subsuite = remote
|
||||
args =
|
||||
--remote-debugging-port
|
||||
--remote-allow-origins=null
|
||||
prefs = # Bug 1600054: Make CDP Fission compatible
|
||||
fission.bfcacheInParent=false
|
||||
fission.webContentIsolationStrategy=0
|
||||
|
|
|
|||
|
|
@ -180,7 +180,7 @@ class RemoteAgentClass {
|
|||
}
|
||||
}
|
||||
|
||||
async listen(url) {
|
||||
async #listen(url) {
|
||||
if (Services.appinfo.processType != Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT) {
|
||||
throw Components.Exception(
|
||||
"May only be instantiated in parent process",
|
||||
|
|
@ -217,12 +217,12 @@ class RemoteAgentClass {
|
|||
|
||||
await Promise.all([this.webDriverBiDi?.start(), this.cdp?.start()]);
|
||||
} catch (e) {
|
||||
await this.close();
|
||||
await this.#stop();
|
||||
logger.error(`Unable to start remote agent: ${e.message}`, e);
|
||||
}
|
||||
}
|
||||
|
||||
async close() {
|
||||
async #stop() {
|
||||
if (!this.listening) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -315,37 +315,30 @@ class RemoteAgentClass {
|
|||
|
||||
this.#allowHosts = this.handleAllowHostsFlag(subject);
|
||||
this.#allowOrigins = this.handleAllowOriginsFlag(subject);
|
||||
}
|
||||
|
||||
// Ideally we should only initialize the Remote Agent when the command
|
||||
// line argument has been specified. But to allow Browser Chrome tests
|
||||
// to run certain states have to be set and listeners registered.
|
||||
// Once bug 1762647 is fixed all the next lines can be moved to
|
||||
// "final-ui-startup".
|
||||
Services.obs.addObserver(this, "sessionstore-windows-restored");
|
||||
Services.obs.addObserver(this, "quit-application");
|
||||
|
||||
Services.obs.addObserver(this, "sessionstore-windows-restored");
|
||||
Services.obs.addObserver(this, "quit-application");
|
||||
// With Bug 1717899 we will extend the lifetime of the Remote Agent to
|
||||
// the whole Firefox session, which will be identical to Marionette. For
|
||||
// now prevent logging if the component is not enabled during startup.
|
||||
if (
|
||||
(activeProtocols & WEBDRIVER_BIDI_ACTIVE) ===
|
||||
WEBDRIVER_BIDI_ACTIVE
|
||||
) {
|
||||
this.#webDriverBiDi = new WebDriverBiDi(this);
|
||||
if (this.enabled) {
|
||||
logger.debug("WebDriver BiDi enabled");
|
||||
}
|
||||
}
|
||||
|
||||
// With Bug 1717899 we will extend the lifetime of the Remote Agent to
|
||||
// the whole Firefox session, which will be identical to Marionette. For
|
||||
// now prevent logging if the component is not enabled during startup.
|
||||
if (
|
||||
(activeProtocols & WEBDRIVER_BIDI_ACTIVE) ===
|
||||
WEBDRIVER_BIDI_ACTIVE
|
||||
) {
|
||||
this.#webDriverBiDi = new WebDriverBiDi(this);
|
||||
if (this.enabled) {
|
||||
logger.debug("WebDriver BiDi enabled");
|
||||
if ((activeProtocols & CDP_ACTIVE) === CDP_ACTIVE) {
|
||||
this.#cdp = new CDP(this);
|
||||
if (this.enabled) {
|
||||
logger.debug("CDP enabled");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((activeProtocols & CDP_ACTIVE) === CDP_ACTIVE) {
|
||||
this.#cdp = new CDP(this);
|
||||
if (this.enabled) {
|
||||
logger.debug("CDP enabled");
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "final-ui-startup":
|
||||
|
|
@ -353,7 +346,7 @@ class RemoteAgentClass {
|
|||
|
||||
try {
|
||||
let address = Services.io.newURI(`http://localhost:${this.#port}`);
|
||||
await this.listen(address);
|
||||
await this.#listen(address);
|
||||
} catch (e) {
|
||||
throw Error(`Unable to start remote agent: ${e}`);
|
||||
}
|
||||
|
|
@ -372,7 +365,7 @@ class RemoteAgentClass {
|
|||
case "quit-application":
|
||||
Services.obs.removeObserver(this, "quit-application");
|
||||
|
||||
this.close();
|
||||
this.#stop();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
var EXPORTED_SYMBOLS = ["allowNullOrigin", "WebSocketHandshake"];
|
||||
var EXPORTED_SYMBOLS = ["WebSocketHandshake"];
|
||||
|
||||
// This file is an XPCOM service-ified copy of ../devtools/server/socket/websocket-server.js.
|
||||
|
||||
|
|
@ -32,14 +32,6 @@ XPCOMUtils.defineLazyGetter(this, "threadManager", () => {
|
|||
return Cc["@mozilla.org/thread-manager;1"].getService();
|
||||
});
|
||||
|
||||
// This should only be used by the CDP browser mochitests which create a
|
||||
// websocket handshake with a non-null origin. It can be removed once
|
||||
// Mochitest supports custom arguments in browser.ini (bug 1762647)
|
||||
let nullOriginAllowed = false;
|
||||
function allowNullOrigin(allowed) {
|
||||
nullOriginAllowed = allowed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allowed origins are exposed through 2 separate getters because while most
|
||||
* of the values should be valid URIs, `null` is also a valid origin and cannot
|
||||
|
|
@ -154,7 +146,7 @@ function isOriginValid(originHeader) {
|
|||
|
||||
// Special case "null" origins, used for privacy sensitive or opaque origins.
|
||||
if (originHeader === "null") {
|
||||
return allowedOrigins.includes("null") || nullOriginAllowed;
|
||||
return allowedOrigins.includes("null");
|
||||
}
|
||||
|
||||
try {
|
||||
|
|
|
|||
Loading…
Reference in a new issue