summaryrefslogtreecommitdiffstats
path: root/devtools/client/framework/commands-from-url.js
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 19:33:14 +0000
commit36d22d82aa202bb199967e9512281e9a53db42c9 (patch)
tree105e8c98ddea1c1e4784a60a5a6410fa416be2de /devtools/client/framework/commands-from-url.js
parentInitial commit. (diff)
downloadfirefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz
firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip
Adding upstream version 115.7.0esr.upstream/115.7.0esrupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'devtools/client/framework/commands-from-url.js')
-rw-r--r--devtools/client/framework/commands-from-url.js179
1 files changed, 179 insertions, 0 deletions
diff --git a/devtools/client/framework/commands-from-url.js b/devtools/client/framework/commands-from-url.js
new file mode 100644
index 0000000000..f9b5cec46c
--- /dev/null
+++ b/devtools/client/framework/commands-from-url.js
@@ -0,0 +1,179 @@
+/* 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/. */
+
+"use strict";
+
+const {
+ DevToolsServer,
+} = require("resource://devtools/server/devtools-server.js");
+const {
+ DevToolsClient,
+} = require("resource://devtools/client/devtools-client.js");
+const {
+ remoteClientManager,
+} = require("resource://devtools/client/shared/remote-debugging/remote-client-manager.js");
+const {
+ CommandsFactory,
+} = require("resource://devtools/shared/commands/commands-factory.js");
+
+/**
+ * Construct a commands object for a given URL with various query parameters:
+ *
+ * - host, port & ws: See the documentation for clientFromURL
+ *
+ * - type: "tab", "extension", "worker" or "process"
+ * {String} The type of target to connect to.
+ *
+ * If type == "tab":
+ * - id:
+ * {Number} the tab browserId
+ *
+ * If type == "extension":
+ * - id:
+ * {String} the addonID of the webextension to debug.
+ *
+ * If type == "worker":
+ * - id:
+ * {String} the unique Worker id of the Worker to debug.
+ *
+ * If type == "process":
+ * - id:
+ * {Number} the process id to debug. Default to 0, which is the parent process.
+ *
+ *
+ * @param {URL} url
+ * The url to fetch query params from.
+ *
+ * @return A commands object
+ */
+exports.commandsFromURL = async function commandsFromURL(url) {
+ const client = await clientFromURL(url);
+ const params = url.searchParams;
+
+ // Clients retrieved from the remote-client-manager are already connected.
+ const isCachedClient = params.get("remoteId");
+ if (!isCachedClient) {
+ // Connect any other client.
+ await client.connect();
+ }
+
+ const id = params.get("id");
+ const type = params.get("type");
+
+ let commands;
+ try {
+ commands = await _commandsFromURL(client, id, type);
+ } catch (e) {
+ if (!isCachedClient) {
+ // If the client was not cached, then the client was created here. If the target
+ // creation failed, we should close the client.
+ await client.close();
+ }
+ throw e;
+ }
+
+ // When opening about:debugging's toolboxes for remote runtimes,
+ // we create a new commands using a shared and cached client.
+ // Prevent closing the DevToolsClient on toolbox close and Commands destruction
+ // as this can be used by about:debugging and other toolboxes.
+ if (isCachedClient) {
+ commands.shouldCloseClient = false;
+ }
+
+ return commands;
+};
+
+async function _commandsFromURL(client, id, type) {
+ if (!type) {
+ throw new Error("commandsFromURL, missing type parameter");
+ }
+
+ let commands;
+ if (type === "tab") {
+ // Fetch target for a remote tab
+ id = parseInt(id, 10);
+ if (isNaN(id)) {
+ throw new Error(
+ `commandsFromURL, wrong tab id '${id}', should be a number`
+ );
+ }
+ try {
+ commands = await CommandsFactory.forRemoteTab(id, { client });
+ } catch (ex) {
+ if (ex.message.startsWith("Protocol error (noTab)")) {
+ throw new Error(
+ `commandsFromURL, tab with browserId '${id}' doesn't exist`
+ );
+ }
+ throw ex;
+ }
+ } else if (type === "extension") {
+ commands = await CommandsFactory.forAddon(id, { client });
+
+ if (!commands) {
+ throw new Error(
+ `commandsFromURL, extension with id '${id}' doesn't exist`
+ );
+ }
+ } else if (type === "worker") {
+ commands = await CommandsFactory.forWorker(id, { client });
+
+ if (!commands) {
+ throw new Error(`commandsFromURL, worker with id '${id}' doesn't exist`);
+ }
+ } else if (type == "process") {
+ // When debugging firefox itself, force the server to accept debugging processes.
+ DevToolsServer.allowChromeProcess = true;
+ commands = await CommandsFactory.forMainProcess({ client });
+ } else {
+ throw new Error(`commandsFromURL, unsupported type '${type}' parameter`);
+ }
+
+ return commands;
+}
+
+/**
+ * Create a DevToolsClient for a given URL object having various query parameters:
+ *
+ * host:
+ * {String} The hostname or IP address to connect to.
+ * port:
+ * {Number} The TCP port to connect to, to use with `host` argument.
+ * remoteId:
+ * {String} Remote client id, for runtimes from the remote-client-manager
+ * ws:
+ * {Boolean} If true, connect via websocket instead of regular TCP connection.
+ *
+ * @param {URL} url
+ * The url to fetch query params from.
+ * @return a promise that resolves a DevToolsClient object
+ */
+async function clientFromURL(url) {
+ const params = url.searchParams;
+
+ // If a remote id was provided we should already have a connected client available.
+ const remoteId = params.get("remoteId");
+ if (remoteId) {
+ const client = remoteClientManager.getClientByRemoteId(remoteId);
+ if (!client) {
+ throw new Error(`Could not find client with remote id: ${remoteId}`);
+ }
+ return client;
+ }
+
+ const host = params.get("host");
+ const port = params.get("port");
+ const webSocket = !!params.get("ws");
+
+ let transport;
+ if (port) {
+ transport = await DevToolsClient.socketConnect({ host, port, webSocket });
+ } else {
+ // Setup a server if we don't have one already running
+ DevToolsServer.init();
+ DevToolsServer.registerAllActors();
+ transport = DevToolsServer.connectPipe();
+ }
+ return new DevToolsClient(transport);
+}