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";
|
|
|
|
|
2018-02-07 09:37:36 +00:00
|
|
|
var { loader, require } = ChromeUtils.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");
|
2017-09-29 13:24:14 +00:00
|
|
|
var { DebuggerClient } = require("devtools/shared/client/debugger-client");
|
2016-03-22 09:17:21 +00:00
|
|
|
var { PrefsHelper } = require("devtools/client/shared/prefs");
|
2013-12-02 08:28:01 +00:00
|
|
|
|
2018-02-23 14:39:50 +00:00
|
|
|
// Timeout to wait before we assume that a connect() timed out without an error.
|
|
|
|
// In milliseconds. (With the Debugger pane open, this has been reported to last
|
|
|
|
// more than 10 seconds!)
|
|
|
|
const STATUS_REVEAL_TIME = 15000;
|
2018-02-21 08:22:49 +00:00
|
|
|
|
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
|
|
|
|
2018-02-21 08:22:49 +00:00
|
|
|
function appendStatusMessage(msg) {
|
2018-06-01 10:36:09 +00:00
|
|
|
const statusMessage = document.getElementById("status-message");
|
2018-02-21 08:22:49 +00:00
|
|
|
statusMessage.value += msg + "\n";
|
|
|
|
if (msg.stack) {
|
|
|
|
statusMessage.value += msg.stack + "\n";
|
|
|
|
}
|
|
|
|
}
|
2017-08-24 17:03:47 +00:00
|
|
|
|
2018-02-23 14:39:50 +00:00
|
|
|
function toggleStatusMessage(visible = true) {
|
2018-06-01 10:36:09 +00:00
|
|
|
const statusMessageContainer = document.getElementById("status-message-container");
|
2018-02-23 14:39:50 +00:00
|
|
|
statusMessageContainer.hidden = !visible;
|
|
|
|
}
|
|
|
|
|
|
|
|
function revealStatusMessage() {
|
|
|
|
toggleStatusMessage(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
function hideStatusMessage() {
|
|
|
|
toggleStatusMessage(false);
|
2018-02-21 08:22:49 +00:00
|
|
|
}
|
|
|
|
|
2018-03-12 18:24:38 +00:00
|
|
|
var connect = async function() {
|
2014-03-18 16:30:23 +00:00
|
|
|
// Initiate the connection
|
2018-06-01 10:36:09 +00:00
|
|
|
const env = Cc["@mozilla.org/process/environment;1"]
|
2018-02-28 17:51:33 +00:00
|
|
|
.getService(Ci.nsIEnvironment);
|
2018-06-01 10:36:09 +00:00
|
|
|
const port = env.get("MOZ_BROWSER_TOOLBOX_PORT");
|
|
|
|
const addonID = env.get("MOZ_BROWSER_TOOLBOX_ADDONID");
|
2017-08-24 17:03:47 +00:00
|
|
|
|
2017-09-18 22:52:11 +00:00
|
|
|
// A port needs to be passed in from the environment, for instance:
|
|
|
|
// MOZ_BROWSER_TOOLBOX_PORT=6080 ./mach run -chrome \
|
|
|
|
// chrome://devtools/content/framework/toolbox-process-window.xul
|
|
|
|
if (!port) {
|
|
|
|
throw new Error("Must pass a port in an env variable with MOZ_BROWSER_TOOLBOX_PORT");
|
2017-08-24 17:03:47 +00:00
|
|
|
}
|
|
|
|
|
2018-06-01 10:36:09 +00:00
|
|
|
const host = Prefs.chromeDebuggingHost;
|
|
|
|
const webSocket = Prefs.chromeDebuggingWebSocket;
|
2018-02-21 08:22:49 +00:00
|
|
|
appendStatusMessage(`Connecting to ${host}:${port}, ws: ${webSocket}`);
|
2018-06-01 10:36:09 +00:00
|
|
|
const transport = await DebuggerClient.socketConnect({
|
2018-02-21 08:22:49 +00:00
|
|
|
host,
|
2017-09-18 22:52:11 +00:00
|
|
|
port,
|
2018-02-21 08:22:49 +00:00
|
|
|
webSocket,
|
2014-12-11 02:55:52 +00:00
|
|
|
});
|
2014-03-18 16:30:23 +00:00
|
|
|
gClient = new DebuggerClient(transport);
|
2018-02-21 08:22:49 +00:00
|
|
|
appendStatusMessage("Start protocol client for connection");
|
2018-02-20 14:11:46 +00:00
|
|
|
await gClient.connect();
|
2014-03-25 17:59:14 +00:00
|
|
|
|
2018-02-21 08:22:49 +00:00
|
|
|
appendStatusMessage("Get root form for toolbox");
|
2016-08-01 15:00:00 +00:00
|
|
|
if (addonID) {
|
2018-06-01 10:36:09 +00:00
|
|
|
const { addons } = await gClient.listAddons();
|
2018-06-04 23:37:02 +00:00
|
|
|
const addonTargetActor = addons.filter(addon => addon.id === addonID).pop();
|
|
|
|
const isBrowsingContext = addonTargetActor.isWebExtension;
|
|
|
|
await openToolbox({form: addonTargetActor, chrome: true, isBrowsingContext});
|
2016-08-01 15:00:00 +00:00
|
|
|
} else {
|
2018-06-01 10:36:09 +00:00
|
|
|
const response = await gClient.getProcess();
|
2018-02-21 08:22:49 +00:00
|
|
|
await openToolbox({form: response.form, chrome: true});
|
2016-08-01 15:00:00 +00:00
|
|
|
}
|
2018-02-20 14:11:46 +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-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);
|
2017-11-08 16:36:43 +00:00
|
|
|
Services.prefs.setBoolPref("devtools.preference.new-panel-enabled", false);
|
2018-01-25 23:09:27 +00:00
|
|
|
Services.prefs.setBoolPref("layout.css.emulate-moz-box-with-flex", false);
|
2018-04-30 16:22:14 +00:00
|
|
|
|
2018-04-30 16:22:17 +00:00
|
|
|
Services.prefs.setBoolPref("devtools.accessibility.enabled", true);
|
2018-04-30 16:22:14 +00:00
|
|
|
Services.prefs.setBoolPref("devtools.performance.enabled", false);
|
2014-08-15 19:33:00 +00:00
|
|
|
}
|
2018-04-30 16:22:14 +00:00
|
|
|
|
2018-03-12 18:24:38 +00:00
|
|
|
window.addEventListener("load", async function() {
|
2018-06-01 10:36:09 +00:00
|
|
|
const cmdClose = document.getElementById("toolbox-cmd-close");
|
2014-05-20 10:55:00 +00:00
|
|
|
cmdClose.addEventListener("command", onCloseCommand);
|
2014-08-15 19:33:00 +00:00
|
|
|
setPrefDefaults();
|
2018-02-23 14:39:50 +00:00
|
|
|
// Reveal status message if connecting is slow or if an error occurs.
|
2018-06-01 10:36:09 +00:00
|
|
|
const delayedStatusReveal = setTimeout(revealStatusMessage, STATUS_REVEAL_TIME);
|
2018-02-20 14:11:46 +00:00
|
|
|
try {
|
|
|
|
await connect();
|
2018-02-21 08:22:49 +00:00
|
|
|
clearTimeout(delayedStatusReveal);
|
2018-02-23 14:39:50 +00:00
|
|
|
hideStatusMessage();
|
2018-02-20 14:11:46 +00:00
|
|
|
} catch (e) {
|
2018-02-23 14:39:50 +00:00
|
|
|
clearTimeout(delayedStatusReveal);
|
2018-02-21 08:22:49 +00:00
|
|
|
appendStatusMessage(e);
|
|
|
|
revealStatusMessage();
|
2016-05-06 15:29:10 +00:00
|
|
|
console.error(e);
|
2018-02-20 14:11:46 +00:00
|
|
|
}
|
2018-02-21 08:22:49 +00:00
|
|
|
}, { once: true });
|
2014-05-20 10:55:00 +00:00
|
|
|
|
|
|
|
function onCloseCommand(event) {
|
|
|
|
window.close();
|
|
|
|
}
|
2013-12-02 08:28:01 +00:00
|
|
|
|
2018-05-25 23:20:28 +00:00
|
|
|
async function openToolbox({ form, chrome, isBrowsingContext }) {
|
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,
|
2018-05-25 23:20:28 +00:00
|
|
|
isBrowsingContext: isBrowsingContext
|
2013-12-02 08:28:01 +00:00
|
|
|
};
|
2018-02-21 08:22:49 +00:00
|
|
|
appendStatusMessage(`Create toolbox target: ${JSON.stringify(arguments, null, 2)}`);
|
2018-06-01 10:36:09 +00:00
|
|
|
const target = await TargetFactory.forRemoteTab(options);
|
|
|
|
const frame = document.getElementById("toolbox-iframe");
|
2018-02-20 14:11:46 +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.
|
2018-06-01 10:36:09 +00:00
|
|
|
const selectedTool =
|
2018-02-20 14:11:46 +00:00
|
|
|
Services.prefs.getCharPref("devtools.browsertoolbox.panel",
|
|
|
|
Services.prefs.getCharPref("devtools.toolbox.selectedTool",
|
|
|
|
"jsdebugger"));
|
|
|
|
|
|
|
|
options = { customIframe: frame };
|
2018-02-21 08:22:49 +00:00
|
|
|
appendStatusMessage(`Show toolbox with ${selectedTool} selected`);
|
2018-06-01 10:36:09 +00:00
|
|
|
const toolbox = await gDevTools.showToolbox(
|
2018-02-20 14:11:46 +00:00
|
|
|
target,
|
|
|
|
selectedTool,
|
|
|
|
Toolbox.HostType.CUSTOM,
|
|
|
|
options
|
|
|
|
);
|
|
|
|
onNewToolbox(toolbox);
|
2013-12-02 08:28:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function onNewToolbox(toolbox) {
|
2016-02-16 15:23:56 +00:00
|
|
|
gToolbox = toolbox;
|
|
|
|
bindToolboxHandlers();
|
|
|
|
raise();
|
2018-06-01 10:36:09 +00:00
|
|
|
const env = Cc["@mozilla.org/process/environment;1"]
|
2018-02-28 17:51:33 +00:00
|
|
|
.getService(Ci.nsIEnvironment);
|
2018-06-01 10:36:09 +00:00
|
|
|
const 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
|
2018-06-01 10:36:09 +00:00
|
|
|
const prefName = "devtools.browser-toolbox.allow-unsafe-script";
|
2016-02-16 15:23:56 +00:00
|
|
|
if (Services.prefs.getPrefType(prefName) == Services.prefs.PREF_BOOL &&
|
|
|
|
Services.prefs.getBoolPref(prefName) === true) {
|
|
|
|
evaluateTestScript(testScript, toolbox);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function evaluateTestScript(script, toolbox) {
|
2018-06-01 10:36:09 +00:00
|
|
|
const sandbox = Cu.Sandbox(window);
|
2016-02-16 15:23:56 +00:00
|
|
|
sandbox.window = window;
|
|
|
|
sandbox.toolbox = toolbox;
|
2018-02-05 16:43:50 +00:00
|
|
|
sandbox.ChromeUtils = ChromeUtils;
|
2016-02-16 15:23:56 +00:00
|
|
|
Cu.evalInSandbox(script, sandbox);
|
2013-12-02 08:28:01 +00:00
|
|
|
}
|
|
|
|
|
2018-02-20 14:11:46 +00:00
|
|
|
async function bindToolboxHandlers() {
|
2013-12-02 08:28:01 +00:00
|
|
|
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.
|
2018-06-01 10:36:09 +00:00
|
|
|
const panel = await gToolbox.getPanelWhenReady("jsdebugger");
|
2018-02-20 14:11:46 +00:00
|
|
|
setupThreadListeners(panel);
|
2017-07-04 15:05:12 +00:00
|
|
|
}
|
2014-11-05 21:56:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function setupThreadListeners(panel) {
|
2018-01-18 15:51:00 +00:00
|
|
|
updateBadgeText(panel.isPaused());
|
2014-11-05 21:56:17 +00:00
|
|
|
|
2018-06-01 10:36:09 +00:00
|
|
|
const onPaused = updateBadgeText.bind(null, true);
|
|
|
|
const 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) {
|
2018-06-01 10:36:09 +00:00
|
|
|
const dockSupport = Cc["@mozilla.org/widget/macdocksupport;1"]
|
2017-07-04 15:05:12 +00:00
|
|
|
.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);
|
2018-06-01 10:36:09 +00:00
|
|
|
const cmdClose = document.getElementById("toolbox-cmd-close");
|
2014-05-20 10:55:00 +00:00
|
|
|
cmdClose.removeEventListener("command", onCloseCommand);
|
2013-12-02 08:28:01 +00:00
|
|
|
gToolbox.destroy();
|
|
|
|
}
|
|
|
|
|
|
|
|
function onMessage(event) {
|
2018-06-19 23:46:49 +00:00
|
|
|
if (!event.data) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
const msg = event.data;
|
|
|
|
switch (msg.name) {
|
|
|
|
case "toolbox-raise":
|
|
|
|
raise();
|
|
|
|
break;
|
|
|
|
case "toolbox-title":
|
|
|
|
setTitle(msg.data.value);
|
|
|
|
break;
|
2017-07-04 15:05:12 +00:00
|
|
|
}
|
2013-12-02 08:28:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
window.addEventListener("message", onMessage);
|
|
|
|
|
|
|
|
function raise() {
|
|
|
|
window.focus();
|
|
|
|
}
|
|
|
|
|
|
|
|
function setTitle(title) {
|
|
|
|
document.title = title;
|
|
|
|
}
|
|
|
|
|
|
|
|
function quitApp() {
|
2018-06-01 10:36:09 +00:00
|
|
|
const quit = Cc["@mozilla.org/supports-PRBool;1"]
|
2013-12-02 08:28:01 +00:00
|
|
|
.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
|
|
|
|
2018-06-01 10:36:09 +00:00
|
|
|
const shouldProceed = !quit.data;
|
2013-12-02 08:28:01 +00:00
|
|
|
if (shouldProceed) {
|
|
|
|
Services.startup.quit(Ci.nsIAppStartup.eForceQuit);
|
|
|
|
}
|
|
|
|
}
|