diff options
Diffstat (limited to 'devtools/client/framework/attach-thread.js')
-rw-r--r-- | devtools/client/framework/attach-thread.js | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/devtools/client/framework/attach-thread.js b/devtools/client/framework/attach-thread.js new file mode 100644 index 000000000..db445ce23 --- /dev/null +++ b/devtools/client/framework/attach-thread.js @@ -0,0 +1,115 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ +/* vim: set ft=javascript ts=2 et sw=2 tw=80: */ +/* 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/. */ + +const {Cc, Ci, Cu} = require("chrome"); +const Services = require("Services"); +const defer = require("devtools/shared/defer"); + +const {LocalizationHelper} = require("devtools/shared/l10n"); +const L10N = new LocalizationHelper("devtools/client/locales/toolbox.properties"); + +function handleThreadState(toolbox, event, packet) { + // Suppress interrupted events by default because the thread is + // paused/resumed a lot for various actions. + if (event !== "paused" || packet.why.type !== "interrupted") { + // TODO: Bug 1225492, we continue emitting events on the target + // like we used to, but we should emit these only on the + // threadClient now. + toolbox.target.emit("thread-" + event); + } + + if (event === "paused") { + toolbox.highlightTool("jsdebugger"); + + if (packet.why.type === "debuggerStatement" || + packet.why.type === "breakpoint" || + packet.why.type === "exception") { + toolbox.raise(); + toolbox.selectTool("jsdebugger"); + } + } else if (event === "resumed") { + toolbox.unhighlightTool("jsdebugger"); + } +} + +function attachThread(toolbox) { + let deferred = defer(); + + let target = toolbox.target; + let { form: { chromeDebugger, actor } } = target; + + // Sourcemaps are always turned off when using the new debugger + // frontend. This is because it does sourcemapping on the + // client-side, so the server should not do it. It also does not support + // blackboxing yet. + let useSourceMaps = false; + let autoBlackBox = false; + if(!Services.prefs.getBoolPref("devtools.debugger.new-debugger-frontend")) { + useSourceMaps = Services.prefs.getBoolPref("devtools.debugger.source-maps-enabled"); + autoBlackBox = Services.prefs.getBoolPref("devtools.debugger.auto-black-box"); + } + let threadOptions = { useSourceMaps, autoBlackBox }; + + let handleResponse = (res, threadClient) => { + if (res.error) { + deferred.reject(new Error("Couldn't attach to thread: " + res.error)); + return; + } + threadClient.addListener("paused", handleThreadState.bind(null, toolbox)); + threadClient.addListener("resumed", handleThreadState.bind(null, toolbox)); + + if (!threadClient.paused) { + deferred.reject( + new Error("Thread in wrong state when starting up, should be paused") + ); + } + + // These flags need to be set here because the client sends them + // with the `resume` request. We make sure to do this before + // resuming to avoid another interrupt. We can't pass it in with + // `threadOptions` because the resume request will override them. + threadClient.pauseOnExceptions( + Services.prefs.getBoolPref("devtools.debugger.pause-on-exceptions"), + Services.prefs.getBoolPref("devtools.debugger.ignore-caught-exceptions") + ); + + threadClient.resume(res => { + if (res.error === "wrongOrder") { + const box = toolbox.getNotificationBox(); + box.appendNotification( + L10N.getStr("toolbox.resumeOrderWarning"), + "wrong-resume-order", + "", + box.PRIORITY_WARNING_HIGH + ); + } + + deferred.resolve(threadClient); + }); + }; + + if (target.isTabActor) { + // Attaching a tab, a browser process, or a WebExtensions add-on. + target.activeTab.attachThread(threadOptions, handleResponse); + } else if (target.isAddon) { + // Attaching a legacy addon. + target.client.attachAddon(actor, res => { + target.client.attachThread(res.threadActor, handleResponse); + }); + } else { + // Attaching an old browser debugger or a content process. + target.client.attachThread(chromeDebugger, handleResponse); + } + + return deferred.promise; +} + +function detachThread(threadClient) { + threadClient.removeListener("paused"); + threadClient.removeListener("resumed"); +} + +module.exports = { attachThread, detachThread }; |