attach-thread.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. const {Cc, Ci, Cu} = require("chrome");
  6. const Services = require("Services");
  7. const defer = require("devtools/shared/defer");
  8. const {LocalizationHelper} = require("devtools/shared/l10n");
  9. const L10N = new LocalizationHelper("devtools/client/locales/toolbox.properties");
  10. function handleThreadState(toolbox, event, packet) {
  11. // Suppress interrupted events by default because the thread is
  12. // paused/resumed a lot for various actions.
  13. if (event !== "paused" || packet.why.type !== "interrupted") {
  14. // TODO: Bug 1225492, we continue emitting events on the target
  15. // like we used to, but we should emit these only on the
  16. // threadClient now.
  17. toolbox.target.emit("thread-" + event);
  18. }
  19. if (event === "paused") {
  20. toolbox.highlightTool("jsdebugger");
  21. if (packet.why.type === "debuggerStatement" ||
  22. packet.why.type === "breakpoint" ||
  23. packet.why.type === "exception") {
  24. toolbox.raise();
  25. toolbox.selectTool("jsdebugger");
  26. }
  27. } else if (event === "resumed") {
  28. toolbox.unhighlightTool("jsdebugger");
  29. }
  30. }
  31. function attachThread(toolbox) {
  32. let deferred = defer();
  33. let target = toolbox.target;
  34. let { form: { chromeDebugger, actor } } = target;
  35. // Sourcemaps are always turned off when using the new debugger
  36. // frontend. This is because it does sourcemapping on the
  37. // client-side, so the server should not do it. It also does not support
  38. // blackboxing yet.
  39. let useSourceMaps = false;
  40. let autoBlackBox = false;
  41. if(!Services.prefs.getBoolPref("devtools.debugger.new-debugger-frontend")) {
  42. useSourceMaps = Services.prefs.getBoolPref("devtools.debugger.source-maps-enabled");
  43. autoBlackBox = Services.prefs.getBoolPref("devtools.debugger.auto-black-box");
  44. }
  45. let threadOptions = { useSourceMaps, autoBlackBox };
  46. let handleResponse = (res, threadClient) => {
  47. if (res.error) {
  48. deferred.reject(new Error("Couldn't attach to thread: " + res.error));
  49. return;
  50. }
  51. threadClient.addListener("paused", handleThreadState.bind(null, toolbox));
  52. threadClient.addListener("resumed", handleThreadState.bind(null, toolbox));
  53. if (!threadClient.paused) {
  54. deferred.reject(
  55. new Error("Thread in wrong state when starting up, should be paused")
  56. );
  57. }
  58. // These flags need to be set here because the client sends them
  59. // with the `resume` request. We make sure to do this before
  60. // resuming to avoid another interrupt. We can't pass it in with
  61. // `threadOptions` because the resume request will override them.
  62. threadClient.pauseOnExceptions(
  63. Services.prefs.getBoolPref("devtools.debugger.pause-on-exceptions"),
  64. Services.prefs.getBoolPref("devtools.debugger.ignore-caught-exceptions")
  65. );
  66. threadClient.resume(res => {
  67. if (res.error === "wrongOrder") {
  68. const box = toolbox.getNotificationBox();
  69. box.appendNotification(
  70. L10N.getStr("toolbox.resumeOrderWarning"),
  71. "wrong-resume-order",
  72. "",
  73. box.PRIORITY_WARNING_HIGH
  74. );
  75. }
  76. deferred.resolve(threadClient);
  77. });
  78. };
  79. if (target.isTabActor) {
  80. // Attaching a tab, a browser process, or a WebExtensions add-on.
  81. target.activeTab.attachThread(threadOptions, handleResponse);
  82. } else if (target.isAddon) {
  83. // Attaching a legacy addon.
  84. target.client.attachAddon(actor, res => {
  85. target.client.attachThread(res.threadActor, handleResponse);
  86. });
  87. } else {
  88. // Attaching an old browser debugger or a content process.
  89. target.client.attachThread(chromeDebugger, handleResponse);
  90. }
  91. return deferred.promise;
  92. }
  93. function detachThread(threadClient) {
  94. threadClient.removeListener("paused");
  95. threadClient.removeListener("resumed");
  96. }
  97. module.exports = { attachThread, detachThread };