1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
9 } = require("resource://devtools/server/devtools-server.js");
12 } = require("resource://devtools/client/devtools-client.js");
15 } = require("resource://devtools/client/shared/remote-debugging/remote-client-manager.js");
18 } = require("resource://devtools/shared/commands/commands-factory.js");
21 * Construct a commands object for a given URL with various query parameters:
23 * - host, port & ws: See the documentation for clientFromURL
25 * - type: "tab", "extension", "worker" or "process"
26 * {String} The type of target to connect to.
30 * {Number} the tab browserId
32 * If type == "extension":
34 * {String} the addonID of the webextension to debug.
36 * If type == "worker":
38 * {String} the unique Worker id of the Worker to debug.
40 * If type == "process":
42 * {Number} the process id to debug. Default to 0, which is the parent process.
46 * The url to fetch query params from.
48 * @return A commands object
50 exports.commandsFromURL = async function commandsFromURL(url) {
51 const client = await clientFromURL(url);
52 const params = url.searchParams;
54 // Clients retrieved from the remote-client-manager are already connected.
55 const isCachedClient = params.get("remoteId");
56 if (!isCachedClient) {
57 // Connect any other client.
58 await client.connect();
61 const id = params.get("id");
62 const type = params.get("type");
66 commands = await _commandsFromURL(client, id, type);
68 if (!isCachedClient) {
69 // If the client was not cached, then the client was created here. If the target
70 // creation failed, we should close the client.
76 // When opening about:debugging's toolboxes for remote runtimes,
77 // we create a new commands using a shared and cached client.
78 // Prevent closing the DevToolsClient on toolbox close and Commands destruction
79 // as this can be used by about:debugging and other toolboxes.
81 commands.shouldCloseClient = false;
87 async function _commandsFromURL(client, id, type) {
89 throw new Error("commandsFromURL, missing type parameter");
94 // Fetch target for a remote tab
95 id = parseInt(id, 10);
98 `commandsFromURL, wrong tab id '${id}', should be a number`
102 commands = await CommandsFactory.forRemoteTab(id, { client });
104 if (ex.message.startsWith("Protocol error (noTab)")) {
106 `commandsFromURL, tab with browserId '${id}' doesn't exist`
111 } else if (type === "extension") {
112 commands = await CommandsFactory.forAddon(id, { client });
116 `commandsFromURL, extension with id '${id}' doesn't exist`
119 } else if (type === "worker") {
120 commands = await CommandsFactory.forWorker(id, { client });
123 throw new Error(`commandsFromURL, worker with id '${id}' doesn't exist`);
125 } else if (type == "process") {
126 // When debugging firefox itself, force the server to accept debugging processes.
127 DevToolsServer.allowChromeProcess = true;
128 commands = await CommandsFactory.forMainProcess({ client });
130 throw new Error(`commandsFromURL, unsupported type '${type}' parameter`);
137 * Create a DevToolsClient for a given URL object having various query parameters:
140 * {String} The hostname or IP address to connect to.
142 * {Number} The TCP port to connect to, to use with `host` argument.
144 * {String} Remote client id, for runtimes from the remote-client-manager
146 * {Boolean} If true, connect via websocket instead of regular TCP connection.
149 * The url to fetch query params from.
150 * @return a promise that resolves a DevToolsClient object
152 async function clientFromURL(url) {
153 const params = url.searchParams;
155 // If a remote id was provided we should already have a connected client available.
156 const remoteId = params.get("remoteId");
158 const client = remoteClientManager.getClientByRemoteId(remoteId);
160 throw new Error(`Could not find client with remote id: ${remoteId}`);
165 const host = params.get("host");
166 const port = params.get("port");
167 const webSocket = !!params.get("ws");
171 transport = await DevToolsClient.socketConnect({ host, port, webSocket });
173 // Setup a server if we don't have one already running
174 DevToolsServer.init();
175 DevToolsServer.registerAllActors();
176 transport = DevToolsServer.connectPipe();
178 return new DevToolsClient(transport);