2016-02-17 00:14:53 +00:00
|
|
|
/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
|
|
|
|
/* vim: set ft=javascript ts=2 et sw=2 tw=80: */
|
2013-12-02 08:28:01 +00:00
|
|
|
/* 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/. */
|
2016-02-17 00:14:53 +00:00
|
|
|
|
2013-12-02 08:28:01 +00:00
|
|
|
"use strict";
|
|
|
|
|
2015-10-07 12:03:21 +00:00
|
|
|
var { classes: Cc, interfaces: Ci, utils: Cu } = Components;
|
2013-12-02 08:28:01 +00:00
|
|
|
|
2016-02-10 10:35:00 +00:00
|
|
|
var { loader, require } = Cu.import("resource://devtools/shared/Loader.jsm", {});
|
2016-04-01 12:48:59 +00:00
|
|
|
// Require this module to setup core modules
|
2016-04-14 08:40:43 +00:00
|
|
|
loader.require("devtools/client/framework/devtools-browser");
|
2016-04-01 12:48:59 +00:00
|
|
|
|
2016-02-10 10:35:00 +00:00
|
|
|
var { gDevTools } = require("devtools/client/framework/devtools");
|
2015-09-21 17:04:18 +00:00
|
|
|
var { TargetFactory } = require("devtools/client/framework/target");
|
|
|
|
var { Toolbox } = require("devtools/client/framework/toolbox");
|
2016-02-27 12:51:10 +00:00
|
|
|
var Services = require("Services");
|
2015-09-21 17:04:18 +00:00
|
|
|
var { DebuggerClient } = require("devtools/shared/client/main");
|
2016-03-22 09:17:21 +00:00
|
|
|
var { PrefsHelper } = require("devtools/client/shared/prefs");
|
2016-05-17 19:07:55 +00:00
|
|
|
var { Task } = require("devtools/shared/task");
|
2013-12-02 08:28:01 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Shortcuts for accessing various debugger preferences.
|
|
|
|
*/
|
2016-03-22 09:17:21 +00:00
|
|
|
var Prefs = new PrefsHelper("devtools.debugger", {
|
2013-12-02 08:28:01 +00:00
|
|
|
chromeDebuggingHost: ["Char", "chrome-debugging-host"],
|
2016-08-01 15:00:00 +00:00
|
|
|
chromeDebuggingWebSocket: ["Bool", "chrome-debugging-websocket"],
|
2013-12-02 08:28:01 +00:00
|
|
|
});
|
|
|
|
|
2015-09-15 18:19:45 +00:00
|
|
|
var gToolbox, gClient;
|
2014-03-18 16:30:23 +00:00
|
|
|
|
2017-07-04 15:05:12 +00:00
|
|
|
var connect = Task.async(function* () {
|
2014-03-18 16:30:23 +00:00
|
|
|
window.removeEventListener("load", connect);
|
2017-08-24 17:03:47 +00:00
|
|
|
|
2014-03-18 16:30:23 +00:00
|
|
|
// Initiate the connection
|
2017-08-24 17:03:47 +00:00
|
|
|
const params = new URLSearchParams(window.location.search);
|
|
|
|
|
|
|
|
// A port needs to be passed in from the query string, for instance:
|
|
|
|
// `./mach run -chrome chrome://devtools/content/framework/toolbox-process-window.xul?port=6080`
|
|
|
|
if (!params.get("port")) {
|
|
|
|
throw new Error("Must specify a port on the query string");
|
|
|
|
}
|
|
|
|
|
2014-12-11 02:55:52 +00:00
|
|
|
let transport = yield DebuggerClient.socketConnect({
|
|
|
|
host: Prefs.chromeDebuggingHost,
|
2017-08-24 17:03:47 +00:00
|
|
|
port: params.get("port"),
|
2016-08-01 15:00:00 +00:00
|
|
|
webSocket: Prefs.chromeDebuggingWebSocket,
|
2014-12-11 02:55:52 +00:00
|
|
|
});
|
2014-03-18 16:30:23 +00:00
|
|
|
gClient = new DebuggerClient(transport);
|
2016-08-01 15:00:00 +00:00
|
|
|
yield gClient.connect();
|
2017-08-24 17:03:47 +00:00
|
|
|
let addonID = params.get("addonID");
|
2014-03-25 17:59:14 +00:00
|
|
|
|
2016-08-01 15:00:00 +00:00
|
|
|
if (addonID) {
|
|
|
|
let { addons } = yield gClient.listAddons();
|
|
|
|
let addonActor = addons.filter(addon => addon.id === addonID).pop();
|
Bug 1302702 - Make WebExtension Addon Debugging oop-compatible. r=ochameau
This patch applies all the changes needed to the devtools actors
and the toolbox-process-window, to be able to debug a webextension
running in an extension child process (as well as a webextension
running in the main process).
The devtools actor used to debug a webextension is splitted into
3 actors:
- the WebExtensionActor is the actor that is created when the
"root.listTabs" RDP request is received, it provides the addon
metadata (name, icon and addon id) and two RDP methods:
- reload: used to reload the addon (e.g. from the "about:debugging#addons" page)
- connectAddonDebuggingActor: which provides the actorID of the actor
that is connected to the process where the extension is running
(used by toolbox-process-window.js to connect the toolbox to the needed
devtools actors, e.g. console, inspector etc.)
- the WebExtensionParentActor is the actor that connects to the
process where the extension is running and ensures that a
WebExtensionChildActor instance is created and connected
(this actor is only the entrypoint to reach the WebExtensionChildActor,
and so it does not provide any RDP request on its own, it only connect
itself to its child counterpart and then it returns the RDP "form" of
the child actor, and the client is then connected directly to the
child actor)
- the WebExtensionChildActor is the actor that is running in the same
process of the target extension, and it provides the same requestTypes
of a tab actor.
By splitting the WebExtensionActor from the WebExtensionParentActor, we are
able to prevent the RemoteDebuggingServer to connect (and create
instances of the WebExtensionChildActor) for every addon listed by
a root.listAddons() request.
MozReview-Commit-ID: L1vxhA6xQkD
--HG--
extra : rebase_source : 7ed7735084d9351ff32ab1ad822e53dd0828dace
2017-03-21 14:55:35 +00:00
|
|
|
let isTabActor = addonActor.isWebExtension;
|
|
|
|
openToolbox({form: addonActor, chrome: true, isTabActor});
|
2016-08-01 15:00:00 +00:00
|
|
|
} else {
|
|
|
|
let response = yield gClient.getProcess();
|
Bug 1302702 - Make WebExtension Addon Debugging oop-compatible. r=ochameau
This patch applies all the changes needed to the devtools actors
and the toolbox-process-window, to be able to debug a webextension
running in an extension child process (as well as a webextension
running in the main process).
The devtools actor used to debug a webextension is splitted into
3 actors:
- the WebExtensionActor is the actor that is created when the
"root.listTabs" RDP request is received, it provides the addon
metadata (name, icon and addon id) and two RDP methods:
- reload: used to reload the addon (e.g. from the "about:debugging#addons" page)
- connectAddonDebuggingActor: which provides the actorID of the actor
that is connected to the process where the extension is running
(used by toolbox-process-window.js to connect the toolbox to the needed
devtools actors, e.g. console, inspector etc.)
- the WebExtensionParentActor is the actor that connects to the
process where the extension is running and ensures that a
WebExtensionChildActor instance is created and connected
(this actor is only the entrypoint to reach the WebExtensionChildActor,
and so it does not provide any RDP request on its own, it only connect
itself to its child counterpart and then it returns the RDP "form" of
the child actor, and the client is then connected directly to the
child actor)
- the WebExtensionChildActor is the actor that is running in the same
process of the target extension, and it provides the same requestTypes
of a tab actor.
By splitting the WebExtensionActor from the WebExtensionParentActor, we are
able to prevent the RemoteDebuggingServer to connect (and create
instances of the WebExtensionChildActor) for every addon listed by
a root.listAddons() request.
MozReview-Commit-ID: L1vxhA6xQkD
--HG--
extra : rebase_source : 7ed7735084d9351ff32ab1ad822e53dd0828dace
2017-03-21 14:55:35 +00:00
|
|
|
openToolbox({form: response.form, chrome: true});
|
2016-08-01 15:00:00 +00:00
|
|
|
}
|
2014-12-11 02:55:52 +00:00
|
|
|
});
|
2013-12-02 08:28:01 +00:00
|
|
|
|
2014-08-15 19:33:00 +00:00
|
|
|
// Certain options should be toggled since we can assume chrome debugging here
|
|
|
|
function setPrefDefaults() {
|
|
|
|
Services.prefs.setBoolPref("devtools.inspector.showUserAgentStyles", true);
|
2015-03-31 15:28:43 +00:00
|
|
|
Services.prefs.setBoolPref("devtools.performance.ui.show-platform-data", true);
|
2015-01-09 08:27:00 +00:00
|
|
|
Services.prefs.setBoolPref("devtools.inspector.showAllAnonymousContent", true);
|
2015-03-04 04:47:00 +00:00
|
|
|
Services.prefs.setBoolPref("browser.dom.window.dump.enabled", true);
|
2016-01-28 18:11:31 +00:00
|
|
|
Services.prefs.setBoolPref("devtools.command-button-noautohide.enabled", true);
|
2016-02-04 10:20:55 +00:00
|
|
|
Services.prefs.setBoolPref("devtools.scratchpad.enabled", true);
|
2016-04-19 21:22:41 +00:00
|
|
|
// Bug 1225160 - Using source maps with browser debugging can lead to a crash
|
|
|
|
Services.prefs.setBoolPref("devtools.debugger.source-maps-enabled", false);
|
2017-04-25 20:11:45 +00:00
|
|
|
Services.prefs.setBoolPref("devtools.debugger.new-debugger-frontend", true);
|
2016-10-20 18:16:40 +00:00
|
|
|
Services.prefs.setBoolPref("devtools.debugger.client-source-maps-enabled", true);
|
2017-06-09 16:42:34 +00:00
|
|
|
Services.prefs.setBoolPref("devtools.webconsole.new-frontend-enabled", false);
|
2014-08-15 19:33:00 +00:00
|
|
|
}
|
2017-07-04 15:05:12 +00:00
|
|
|
window.addEventListener("load", function () {
|
2014-05-20 10:55:00 +00:00
|
|
|
let cmdClose = document.getElementById("toolbox-cmd-close");
|
|
|
|
cmdClose.addEventListener("command", onCloseCommand);
|
2014-08-15 19:33:00 +00:00
|
|
|
setPrefDefaults();
|
2015-03-17 18:55:00 +00:00
|
|
|
connect().catch(e => {
|
|
|
|
let errorMessageContainer = document.getElementById("error-message-container");
|
|
|
|
let errorMessage = document.getElementById("error-message");
|
2016-08-01 15:00:00 +00:00
|
|
|
errorMessage.value = e.message || e;
|
2015-03-17 18:55:00 +00:00
|
|
|
errorMessageContainer.hidden = false;
|
2016-05-06 15:29:10 +00:00
|
|
|
console.error(e);
|
2015-03-17 18:55:00 +00:00
|
|
|
});
|
2014-05-20 10:55:00 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
function onCloseCommand(event) {
|
|
|
|
window.close();
|
|
|
|
}
|
2013-12-02 08:28:01 +00:00
|
|
|
|
2015-02-26 02:55:00 +00:00
|
|
|
function openToolbox({ form, chrome, isTabActor }) {
|
2013-12-02 08:28:01 +00:00
|
|
|
let options = {
|
|
|
|
form: form,
|
2014-03-18 16:30:23 +00:00
|
|
|
client: gClient,
|
2015-02-26 02:55:00 +00:00
|
|
|
chrome: chrome,
|
|
|
|
isTabActor: isTabActor
|
2013-12-02 08:28:01 +00:00
|
|
|
};
|
2015-08-06 12:38:10 +00:00
|
|
|
TargetFactory.forRemoteTab(options).then(target => {
|
2013-12-02 08:28:01 +00:00
|
|
|
let frame = document.getElementById("toolbox-iframe");
|
2014-11-26 23:40:00 +00:00
|
|
|
|
2017-03-07 14:29:48 +00:00
|
|
|
// Remember the last panel that was used inside of this profile.
|
|
|
|
// But if we are testing, then it should always open the debugger panel.
|
|
|
|
let selectedTool =
|
|
|
|
Services.prefs.getCharPref("devtools.browsertoolbox.panel",
|
2017-07-04 15:05:12 +00:00
|
|
|
Services.prefs.getCharPref("devtools.toolbox.selectedTool",
|
|
|
|
"jsdebugger"));
|
2014-11-26 23:40:00 +00:00
|
|
|
|
2017-07-04 15:05:12 +00:00
|
|
|
options = { customIframe: frame };
|
2013-12-02 08:28:01 +00:00
|
|
|
gDevTools.showToolbox(target,
|
2014-11-26 23:40:00 +00:00
|
|
|
selectedTool,
|
2015-08-06 12:38:10 +00:00
|
|
|
Toolbox.HostType.CUSTOM,
|
2013-12-02 08:28:01 +00:00
|
|
|
options)
|
|
|
|
.then(onNewToolbox);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function onNewToolbox(toolbox) {
|
2016-02-16 15:23:56 +00:00
|
|
|
gToolbox = toolbox;
|
|
|
|
bindToolboxHandlers();
|
|
|
|
raise();
|
2017-07-04 15:05:12 +00:00
|
|
|
let env = Components.classes["@mozilla.org/process/environment;1"]
|
|
|
|
.getService(Components.interfaces.nsIEnvironment);
|
2016-04-12 20:05:36 +00:00
|
|
|
let testScript = env.get("MOZ_TOOLBOX_TEST_SCRIPT");
|
2016-02-16 15:23:56 +00:00
|
|
|
if (testScript) {
|
|
|
|
// Only allow executing random chrome scripts when a special
|
|
|
|
// test-only pref is set
|
|
|
|
let prefName = "devtools.browser-toolbox.allow-unsafe-script";
|
|
|
|
if (Services.prefs.getPrefType(prefName) == Services.prefs.PREF_BOOL &&
|
|
|
|
Services.prefs.getBoolPref(prefName) === true) {
|
|
|
|
evaluateTestScript(testScript, toolbox);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function evaluateTestScript(script, toolbox) {
|
|
|
|
let sandbox = Cu.Sandbox(window);
|
|
|
|
sandbox.window = window;
|
|
|
|
sandbox.toolbox = toolbox;
|
|
|
|
Cu.evalInSandbox(script, sandbox);
|
2013-12-02 08:28:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function bindToolboxHandlers() {
|
|
|
|
gToolbox.once("destroyed", quitApp);
|
|
|
|
window.addEventListener("unload", onUnload);
|
2014-11-05 21:56:17 +00:00
|
|
|
|
2017-07-04 15:05:12 +00:00
|
|
|
if (Services.appinfo.OS == "Darwin") {
|
|
|
|
// Badge the dock icon to differentiate this process from the main application
|
|
|
|
// process.
|
|
|
|
updateBadgeText(false);
|
2014-11-05 21:56:17 +00:00
|
|
|
|
2017-07-04 15:05:12 +00:00
|
|
|
// Once the debugger panel opens listen for thread pause / resume.
|
|
|
|
gToolbox.getPanelWhenReady("jsdebugger").then(panel => {
|
|
|
|
setupThreadListeners(panel);
|
|
|
|
});
|
|
|
|
}
|
2014-11-05 21:56:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function setupThreadListeners(panel) {
|
2017-05-17 18:50:22 +00:00
|
|
|
updateBadgeText(panel._selectors.getPause(panel._getState()));
|
2014-11-05 21:56:17 +00:00
|
|
|
|
|
|
|
let onPaused = updateBadgeText.bind(null, true);
|
|
|
|
let onResumed = updateBadgeText.bind(null, false);
|
2017-04-25 20:12:30 +00:00
|
|
|
gToolbox.target.on("thread-paused", onPaused);
|
|
|
|
gToolbox.target.on("thread-resumed", onResumed);
|
2014-11-05 21:56:17 +00:00
|
|
|
|
|
|
|
panel.once("destroyed", () => {
|
2017-04-25 20:12:30 +00:00
|
|
|
gToolbox.target.off("thread-paused", onPaused);
|
|
|
|
gToolbox.target.off("thread-resumed", onResumed);
|
2014-11-05 21:56:17 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function updateBadgeText(paused) {
|
2017-07-04 15:05:12 +00:00
|
|
|
let dockSupport = Cc["@mozilla.org/widget/macdocksupport;1"]
|
|
|
|
.getService(Ci.nsIMacDockSupport);
|
2014-11-05 21:56:17 +00:00
|
|
|
dockSupport.badgeText = paused ? "▐▐ " : " ▶";
|
2013-12-02 08:28:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function onUnload() {
|
|
|
|
window.removeEventListener("unload", onUnload);
|
|
|
|
window.removeEventListener("message", onMessage);
|
2014-05-20 10:55:00 +00:00
|
|
|
let cmdClose = document.getElementById("toolbox-cmd-close");
|
|
|
|
cmdClose.removeEventListener("command", onCloseCommand);
|
2013-12-02 08:28:01 +00:00
|
|
|
gToolbox.destroy();
|
|
|
|
}
|
|
|
|
|
|
|
|
function onMessage(event) {
|
|
|
|
try {
|
|
|
|
let json = JSON.parse(event.data);
|
|
|
|
switch (json.name) {
|
|
|
|
case "toolbox-raise":
|
|
|
|
raise();
|
|
|
|
break;
|
|
|
|
case "toolbox-title":
|
|
|
|
setTitle(json.data.value);
|
|
|
|
break;
|
|
|
|
}
|
2017-07-04 15:05:12 +00:00
|
|
|
} catch (e) {
|
|
|
|
console.error(e);
|
|
|
|
}
|
2013-12-02 08:28:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
window.addEventListener("message", onMessage);
|
|
|
|
|
|
|
|
function raise() {
|
|
|
|
window.focus();
|
|
|
|
}
|
|
|
|
|
|
|
|
function setTitle(title) {
|
|
|
|
document.title = title;
|
|
|
|
}
|
|
|
|
|
|
|
|
function quitApp() {
|
|
|
|
let quit = Cc["@mozilla.org/supports-PRBool;1"]
|
|
|
|
.createInstance(Ci.nsISupportsPRBool);
|
2017-04-14 19:51:39 +00:00
|
|
|
Services.obs.notifyObservers(quit, "quit-application-requested");
|
2013-12-02 08:28:01 +00:00
|
|
|
|
|
|
|
let shouldProceed = !quit.data;
|
|
|
|
if (shouldProceed) {
|
|
|
|
Services.startup.quit(Ci.nsIAppStartup.eForceQuit);
|
|
|
|
}
|
|
|
|
}
|