mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-03-05 00:02:37 +00:00

This changeset adds basic remote connection functionality to about:debugging. About:debugging can target a remote firefox instance if the host and port parameters are passed as URL search params. The feature is not explicitly exposed at the moment and there is no UI to connect an instance, and no UI feedback when connected to a remote instance. When connected, about:debugging should correctly list tabs, workers and addons for the target instance of Firefox. Debugging features work for all supported targets. Known limitations: - preferences are read from the local Firefox instance (multiprocess, addon debugging etc...). At the moment the remote instance must be manually correctly configured MozReview-Commit-ID: DOekSCb96XC --HG-- extra : rebase_source : 89b73e885e50bfba4e1888f8791f637a5ba05ca7 extra : intermediate-source : 840e23f2a496e2cec280643fef127095bd67d518 extra : source : 6cc5cc4494e67ae9dd7371420710c3f8afe5b256
150 lines
4.5 KiB
JavaScript
150 lines
4.5 KiB
JavaScript
/* 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 { TargetFactory } = require("devtools/client/framework/target");
|
|
const { DebuggerServer } = require("devtools/server/main");
|
|
const { DebuggerClient } = require("devtools/shared/client/debugger-client");
|
|
|
|
/**
|
|
* Construct a Target for a given URL object having various query parameters:
|
|
*
|
|
* - host, port & ws: See the documentation for clientFromURL
|
|
*
|
|
* - type: tab, process, window
|
|
* {String} The type of target to connect to.
|
|
*
|
|
* If type == "tab":
|
|
* - id:
|
|
* {Number} the tab outerWindowID
|
|
* - chrome: Optional
|
|
* {Boolean} Force the creation of a chrome target. Gives more privileges to
|
|
* the tab actor. Allows chrome execution in the webconsole and see chrome
|
|
* files in the debugger. (handy when contributing to firefox)
|
|
*
|
|
* If type == "process":
|
|
* - id:
|
|
* {Number} the process id to debug. Default to 0, which is the parent process.
|
|
*
|
|
* If type == "window":
|
|
* - id:
|
|
* {Number} the window outerWindowID
|
|
*
|
|
* @param {URL} url
|
|
* The url to fetch query params from.
|
|
*
|
|
* @return A target object
|
|
*/
|
|
exports.targetFromURL = async function targetFromURL(url) {
|
|
let client = await clientFromURL(url);
|
|
await client.connect();
|
|
|
|
let params = url.searchParams;
|
|
let type = params.get("type");
|
|
if (!type) {
|
|
throw new Error("targetFromURL, missing type parameter");
|
|
}
|
|
let id = params.get("id");
|
|
// Allows to spawn a chrome enabled target for any context
|
|
// (handy to debug chrome stuff in a child process)
|
|
let chrome = params.has("chrome");
|
|
|
|
let form, isTabActor;
|
|
if (type === "tab") {
|
|
// Fetch target for a remote tab
|
|
id = parseInt(id, 10);
|
|
if (isNaN(id)) {
|
|
throw new Error(`targetFromURL, wrong tab id '${id}', should be a number`);
|
|
}
|
|
try {
|
|
let response = await client.getTab({ outerWindowID: id });
|
|
form = response.tab;
|
|
} catch (ex) {
|
|
if (ex.error == "noTab") {
|
|
throw new Error(`targetFromURL, tab with outerWindowID '${id}' doesn't exist`);
|
|
}
|
|
throw ex;
|
|
}
|
|
} else if (type == "process") {
|
|
// Fetch target for a remote chrome actor
|
|
DebuggerServer.allowChromeProcess = true;
|
|
try {
|
|
id = parseInt(id, 10);
|
|
if (isNaN(id)) {
|
|
id = 0;
|
|
}
|
|
let response = await client.getProcess(id);
|
|
form = response.form;
|
|
chrome = true;
|
|
if (id != 0) {
|
|
// Child process are not exposing tab actors and only support debugger+console
|
|
isTabActor = false;
|
|
}
|
|
} catch (ex) {
|
|
if (ex.error == "noProcess") {
|
|
throw new Error(`targetFromURL, process with id '${id}' doesn't exist`);
|
|
}
|
|
throw ex;
|
|
}
|
|
} else if (type == "window") {
|
|
// Fetch target for a remote window actor
|
|
DebuggerServer.allowChromeProcess = true;
|
|
try {
|
|
id = parseInt(id, 10);
|
|
if (isNaN(id)) {
|
|
throw new Error("targetFromURL, window requires id parameter");
|
|
}
|
|
let response = await client.mainRoot.getWindow({
|
|
outerWindowID: id,
|
|
});
|
|
form = response.window;
|
|
chrome = true;
|
|
} catch (ex) {
|
|
if (ex.error == "notFound") {
|
|
throw new Error(`targetFromURL, window with id '${id}' doesn't exist`);
|
|
}
|
|
throw ex;
|
|
}
|
|
} else {
|
|
throw new Error(`targetFromURL, unsupported type '${type}' parameter`);
|
|
}
|
|
|
|
return TargetFactory.forRemoteTab({ client, form, chrome, isTabActor });
|
|
};
|
|
|
|
/**
|
|
* Create a DebuggerClient 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.
|
|
* 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 DebuggerClient object
|
|
*/
|
|
async function clientFromURL(url) {
|
|
let params = url.searchParams;
|
|
let host = params.get("host");
|
|
let port = params.get("port");
|
|
let webSocket = !!params.get("ws");
|
|
|
|
let transport;
|
|
if (port) {
|
|
transport = await DebuggerClient.socketConnect({ host, port, webSocket });
|
|
} else {
|
|
// Setup a server if we don't have one already running
|
|
DebuggerServer.init();
|
|
DebuggerServer.registerAllActors();
|
|
transport = DebuggerServer.connectPipe();
|
|
}
|
|
return new DebuggerClient(transport);
|
|
}
|
|
|
|
exports.clientFromURL = clientFromURL;
|