definitions.js (25238B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 "use strict"; 6 7 const osString = Services.appinfo.OS; 8 9 // Panels 10 loader.lazyGetter( 11 this, 12 "OptionsPanel", 13 () => 14 require("resource://devtools/client/framework/toolbox-options.js") 15 .OptionsPanel 16 ); 17 loader.lazyGetter( 18 this, 19 "InspectorPanel", 20 () => require("resource://devtools/client/inspector/panel.js").InspectorPanel 21 ); 22 loader.lazyGetter( 23 this, 24 "WebConsolePanel", 25 () => 26 require("resource://devtools/client/webconsole/panel.js").WebConsolePanel 27 ); 28 loader.lazyGetter( 29 this, 30 "DebuggerPanel", 31 () => require("resource://devtools/client/debugger/panel.js").DebuggerPanel 32 ); 33 loader.lazyGetter( 34 this, 35 "StyleEditorPanel", 36 () => 37 require("resource://devtools/client/styleeditor/panel.js").StyleEditorPanel 38 ); 39 loader.lazyGetter( 40 this, 41 "MemoryPanel", 42 () => require("resource://devtools/client/memory/panel.js").MemoryPanel 43 ); 44 loader.lazyGetter( 45 this, 46 "NewPerformancePanel", 47 () => 48 require("resource://devtools/client/performance-new/panel/panel.js") 49 .PerformancePanel 50 ); 51 loader.lazyGetter( 52 this, 53 "NetMonitorPanel", 54 () => 55 require("resource://devtools/client/netmonitor/panel.js").NetMonitorPanel 56 ); 57 loader.lazyGetter( 58 this, 59 "StoragePanel", 60 () => require("resource://devtools/client/storage/panel.js").StoragePanel 61 ); 62 loader.lazyGetter( 63 this, 64 "DomPanel", 65 () => require("resource://devtools/client/dom/panel.js").DomPanel 66 ); 67 loader.lazyGetter( 68 this, 69 "AccessibilityPanel", 70 () => 71 require("resource://devtools/client/accessibility/panel.js") 72 .AccessibilityPanel 73 ); 74 loader.lazyGetter( 75 this, 76 "ApplicationPanel", 77 () => 78 require("resource://devtools/client/application/panel.js").ApplicationPanel 79 ); 80 loader.lazyGetter( 81 this, 82 "AntiTrackingPanel", 83 () => 84 require("resource://devtools/client/anti-tracking/panel.js") 85 .AntiTrackingPanel 86 ); 87 88 // Other dependencies 89 loader.lazyRequireGetter( 90 this, 91 "ResponsiveUIManager", 92 "resource://devtools/client/responsive/manager.js" 93 ); 94 loader.lazyRequireGetter( 95 this, 96 "TRACER_LOG_METHODS", 97 "resource://devtools/shared/specs/tracer.js", 98 true 99 ); 100 101 const lazy = {}; 102 ChromeUtils.defineESModuleGetters(lazy, { 103 AppConstants: "resource://gre/modules/AppConstants.sys.mjs", 104 }); 105 loader.lazyRequireGetter( 106 this, 107 "DevToolsExperimentalPrefs", 108 "resource://devtools/client/devtools-experimental-prefs.js" 109 ); 110 loader.lazyRequireGetter( 111 this, 112 "captureAndSaveScreenshot", 113 "resource://devtools/client/shared/screenshot.js", 114 true 115 ); 116 loader.lazyRequireGetter( 117 this, 118 "Menu", 119 "resource://devtools/client/framework/menu.js" 120 ); 121 loader.lazyRequireGetter( 122 this, 123 "MenuItem", 124 "resource://devtools/client/framework/menu-item.js" 125 ); 126 127 const { TYPES: HIGHLIGHTER_TYPES } = ChromeUtils.importESModule( 128 "resource://devtools/shared/highlighters.mjs" 129 ); 130 131 const { LocalizationHelper } = require("resource://devtools/shared/l10n.js"); 132 const L10N = new LocalizationHelper( 133 "devtools/client/locales/startup.properties" 134 ); 135 const CommandKeys = new Localization( 136 ["devtools/startup/key-shortcuts.ftl"], 137 true 138 ); 139 140 var Tools = {}; 141 exports.Tools = Tools; 142 143 // Definitions 144 Tools.options = { 145 id: "options", 146 ordinal: 0, 147 url: "chrome://devtools/content/framework/toolbox-options.html", 148 icon: "chrome://devtools/skin/images/settings.svg", 149 bgTheme: "theme-body", 150 label: l10n("options.label"), 151 iconOnly: true, 152 panelLabel: l10n("options.panelLabel"), 153 tooltip: l10n("optionsButton.tooltip"), 154 inMenu: false, 155 156 isToolSupported() { 157 return true; 158 }, 159 160 build(iframeWindow, toolbox, commands) { 161 return new OptionsPanel(iframeWindow, toolbox, commands); 162 }, 163 }; 164 165 Tools.inspector = { 166 id: "inspector", 167 accesskey: l10n("inspector.accesskey"), 168 ordinal: 1, 169 icon: "chrome://devtools/skin/images/tool-inspector.svg", 170 url: "chrome://devtools/content/inspector/index.xhtml", 171 label: l10n("inspector.label"), 172 panelLabel: l10n("inspector.panelLabel"), 173 get tooltip() { 174 const key = commandkey("devtools-commandkey-inspector"); 175 if (osString == "Darwin") { 176 const cmdShiftC = "Cmd+Shift+" + key; 177 const cmdOptC = "Cmd+Opt+" + key; 178 return l10n("inspector.mac.tooltip", cmdShiftC, cmdOptC); 179 } 180 181 const ctrlShiftC = "Ctrl+Shift+" + key; 182 return l10n("inspector.tooltip2", ctrlShiftC); 183 }, 184 inMenu: false, 185 186 preventClosingOnKey: true, 187 // preventRaisingOnKey is used to keep the focus on the content window for shortcuts 188 // that trigger the element picker. 189 preventRaisingOnKey: true, 190 onkey(panel, toolbox) { 191 if ( 192 Services.prefs.getBoolPref("devtools.command-button-pick.enabled", false) 193 ) { 194 toolbox.nodePicker.togglePicker(); 195 } 196 }, 197 198 isToolSupported(toolbox) { 199 return toolbox.target.hasActor("inspector"); 200 }, 201 202 build(iframeWindow, toolbox, commands) { 203 return new InspectorPanel(iframeWindow, toolbox, commands); 204 }, 205 }; 206 Tools.webConsole = { 207 id: "webconsole", 208 accesskey: l10n("webConsoleCmd.accesskey"), 209 ordinal: 2, 210 url: "chrome://devtools/content/webconsole/index.html", 211 icon: "chrome://devtools/skin/images/tool-webconsole.svg", 212 label: l10n("ToolboxTabWebconsole.label"), 213 menuLabel: l10n("MenuWebconsole.label"), 214 panelLabel: l10n("ToolboxWebConsole.panelLabel"), 215 get tooltip() { 216 return l10n( 217 "ToolboxWebconsole.tooltip2", 218 (osString == "Darwin" ? "Cmd+Opt+" : "Ctrl+Shift+") + 219 commandkey("devtools-commandkey-webconsole") 220 ); 221 }, 222 inMenu: false, 223 224 preventClosingOnKey: true, 225 onkey(panel, toolbox) { 226 if (toolbox.splitConsole) { 227 return toolbox.focusConsoleInput(); 228 } 229 230 panel.focusInput(); 231 return undefined; 232 }, 233 234 isToolSupported() { 235 return true; 236 }, 237 build(iframeWindow, toolbox, commands) { 238 return new WebConsolePanel(iframeWindow, toolbox, commands); 239 }, 240 }; 241 242 Tools.jsdebugger = { 243 id: "jsdebugger", 244 accesskey: l10n("debuggerMenu.accesskey"), 245 ordinal: 3, 246 icon: "chrome://devtools/skin/images/tool-debugger.svg", 247 url: "chrome://devtools/content/debugger/index.html", 248 label: l10n("ToolboxDebugger.label"), 249 panelLabel: l10n("ToolboxDebugger.panelLabel"), 250 get tooltip() { 251 return l10n( 252 "ToolboxDebugger.tooltip4", 253 (osString == "Darwin" ? "Cmd+Opt+" : "Ctrl+Shift+") + 254 commandkey("devtools-commandkey-jsdebugger") 255 ); 256 }, 257 inMenu: false, 258 isToolSupported() { 259 return true; 260 }, 261 build(iframeWindow, toolbox, commands) { 262 return new DebuggerPanel(iframeWindow, toolbox, commands); 263 }, 264 }; 265 266 Tools.styleEditor = { 267 id: "styleeditor", 268 ordinal: 5, 269 visibilityswitch: "devtools.styleeditor.enabled", 270 accesskey: l10n("open.accesskey"), 271 icon: "chrome://devtools/skin/images/tool-styleeditor.svg", 272 url: "chrome://devtools/content/styleeditor/index.xhtml", 273 label: l10n("ToolboxStyleEditor.label"), 274 panelLabel: l10n("ToolboxStyleEditor.panelLabel"), 275 get tooltip() { 276 return l10n( 277 "ToolboxStyleEditor.tooltip3", 278 "Shift+" + functionkey(commandkey("devtools-commandkey-styleeditor")) 279 ); 280 }, 281 inMenu: false, 282 isToolSupported(toolbox) { 283 return toolbox.target.hasActor("styleSheets"); 284 }, 285 286 build(iframeWindow, toolbox, commands) { 287 return new StyleEditorPanel(iframeWindow, toolbox, commands); 288 }, 289 }; 290 291 Tools.performance = { 292 id: "performance", 293 ordinal: 6, 294 icon: "chrome://devtools/skin/images/tool-profiler.svg", 295 url: "chrome://devtools/content/performance-new/panel/index.xhtml", 296 visibilityswitch: "devtools.performance.enabled", 297 label: l10n("performance.label"), 298 panelLabel: l10n("performance.panelLabel"), 299 get tooltip() { 300 return l10n( 301 "performance.tooltip", 302 "Shift+" + functionkey(commandkey("devtools-commandkey-performance")) 303 ); 304 }, 305 accesskey: l10n("performance.accesskey"), 306 inMenu: false, 307 isToolSupported(toolbox) { 308 // Only use the new performance panel on local tab toolboxes, as they are guaranteed 309 // to have a performance actor. 310 // Remote tab toolboxes (eg about:devtools-toolbox from about:debugging) should not 311 // use the performance panel; about:debugging provides a "Profile performance" button 312 // which can be used instead, without having the overhead of starting a remote toolbox. 313 // Also accept the Browser Toolbox, so that we can profile its process via a second browser toolbox. 314 return ( 315 toolbox.commands.descriptorFront.isLocalTab || toolbox.isBrowserToolbox 316 ); 317 }, 318 build(frame, toolbox, commands) { 319 return new NewPerformancePanel(frame, toolbox, commands); 320 }, 321 }; 322 323 Tools.memory = { 324 id: "memory", 325 ordinal: 7, 326 icon: "chrome://devtools/skin/images/tool-memory.svg", 327 url: "chrome://devtools/content/memory/index.xhtml", 328 visibilityswitch: "devtools.memory.enabled", 329 label: l10n("memory.label"), 330 panelLabel: l10n("memory.panelLabel"), 331 tooltip: l10n("memory.tooltip"), 332 333 isToolSupported(toolbox) { 334 const { descriptorFront } = toolbox.commands; 335 return ( 336 !descriptorFront.isWebExtensionDescriptor && 337 !descriptorFront.isWorkerDescriptor 338 ); 339 }, 340 341 build(frame, toolbox, commands) { 342 return new MemoryPanel(frame, toolbox, commands); 343 }, 344 }; 345 346 Tools.netMonitor = { 347 id: "netmonitor", 348 accesskey: l10n("netmonitor.accesskey"), 349 ordinal: 4, 350 visibilityswitch: "devtools.netmonitor.enabled", 351 icon: "chrome://devtools/skin/images/tool-network.svg", 352 url: "chrome://devtools/content/netmonitor/index.html", 353 label: l10n("netmonitor.label"), 354 panelLabel: l10n("netmonitor.panelLabel"), 355 get tooltip() { 356 return l10n( 357 "netmonitor.tooltip2", 358 (osString == "Darwin" ? "Cmd+Opt+" : "Ctrl+Shift+") + 359 commandkey("devtools-commandkey-netmonitor") 360 ); 361 }, 362 inMenu: false, 363 364 isToolSupported(toolbox) { 365 return ( 366 toolbox.target.getTrait("networkMonitor") && 367 !toolbox.target.isWorkerTarget 368 ); 369 }, 370 371 build(iframeWindow, toolbox, commands) { 372 return new NetMonitorPanel(iframeWindow, toolbox, commands); 373 }, 374 }; 375 376 Tools.storage = { 377 id: "storage", 378 ordinal: 8, 379 accesskey: l10n("storage.accesskey"), 380 visibilityswitch: "devtools.storage.enabled", 381 icon: "chrome://devtools/skin/images/tool-storage.svg", 382 url: "chrome://devtools/content/storage/index.xhtml", 383 label: l10n("storage.label"), 384 menuLabel: l10n("storage.menuLabel"), 385 panelLabel: l10n("storage.panelLabel"), 386 get tooltip() { 387 return l10n( 388 "storage.tooltip3", 389 "Shift+" + functionkey(commandkey("devtools-commandkey-storage")) 390 ); 391 }, 392 inMenu: false, 393 394 isToolSupported(toolbox) { 395 const { descriptorFront } = toolbox.commands; 396 // Storage is available on all contexts debugging a BrowsingContext. 397 // As of today, this is all but worker toolboxes. 398 return ( 399 descriptorFront.isTabDescriptor || 400 descriptorFront.isParentProcessDescriptor || 401 descriptorFront.isWebExtensionDescriptor 402 ); 403 }, 404 405 build(iframeWindow, toolbox, commands) { 406 return new StoragePanel(iframeWindow, toolbox, commands); 407 }, 408 }; 409 410 Tools.dom = { 411 id: "dom", 412 accesskey: l10n("dom.accesskey"), 413 ordinal: 11, 414 visibilityswitch: "devtools.dom.enabled", 415 icon: "chrome://devtools/skin/images/tool-dom.svg", 416 url: "chrome://devtools/content/dom/index.html", 417 label: l10n("dom.label"), 418 panelLabel: l10n("dom.panelLabel"), 419 get tooltip() { 420 return l10n( 421 "dom.tooltip", 422 (osString == "Darwin" ? "Cmd+Opt+" : "Ctrl+Shift+") + 423 commandkey("devtools-commandkey-dom") 424 ); 425 }, 426 inMenu: false, 427 428 isToolSupported() { 429 return true; 430 }, 431 432 build(iframeWindow, toolbox, commands) { 433 return new DomPanel(iframeWindow, toolbox, commands); 434 }, 435 }; 436 437 Tools.accessibility = { 438 id: "accessibility", 439 accesskey: l10n("accessibility.accesskey"), 440 ordinal: 9, 441 modifiers: osString == "Darwin" ? "accel,alt" : "accel,shift", 442 visibilityswitch: "devtools.accessibility.enabled", 443 icon: "chrome://devtools/skin/images/tool-accessibility.svg", 444 url: "chrome://devtools/content/accessibility/index.html", 445 label: l10n("accessibility.label"), 446 panelLabel: l10n("accessibility.panelLabel"), 447 get tooltip() { 448 return l10n( 449 "accessibility.tooltip3", 450 "Shift+" + 451 functionkey(commandkey("devtools-commandkey-accessibility-f12")) 452 ); 453 }, 454 inMenu: false, 455 456 isToolSupported(toolbox) { 457 return toolbox.target.hasActor("accessibility"); 458 }, 459 460 build(iframeWindow, toolbox, commands) { 461 return new AccessibilityPanel(iframeWindow, toolbox, commands); 462 }, 463 }; 464 465 Tools.application = { 466 id: "application", 467 ordinal: 10, 468 visibilityswitch: "devtools.application.enabled", 469 icon: "chrome://devtools/skin/images/tool-application.svg", 470 url: "chrome://devtools/content/application/index.html", 471 label: l10n("application.label"), 472 panelLabel: l10n("application.panelLabel"), 473 tooltip: l10n("application.tooltip"), 474 inMenu: false, 475 476 isToolSupported(toolbox) { 477 return toolbox.target.hasActor("manifest"); 478 }, 479 480 build(iframeWindow, toolbox, commands) { 481 return new ApplicationPanel(iframeWindow, toolbox, commands); 482 }, 483 }; 484 485 Tools.antitracking = { 486 id: "antitracking", 487 ordinal: 11, 488 visibilityswitch: "devtools.anti-tracking.enabled", 489 icon: "chrome://browser/skin/tracking-protection.svg", 490 url: "chrome://devtools/content/anti-tracking/index.html", 491 label: "Anti tracking", 492 panelLabel: "Anti tracking", 493 tooltip: "Anti tracking", 494 inMenu: false, 495 496 isToolSupported() { 497 return true; 498 }, 499 500 build(iframeWindow, toolbox, commands) { 501 return new AntiTrackingPanel(iframeWindow, toolbox, commands); 502 }, 503 }; 504 505 var defaultTools = [ 506 Tools.options, 507 Tools.webConsole, 508 Tools.inspector, 509 Tools.jsdebugger, 510 Tools.styleEditor, 511 Tools.performance, 512 Tools.netMonitor, 513 Tools.storage, 514 Tools.memory, 515 Tools.dom, 516 Tools.accessibility, 517 Tools.application, 518 ]; 519 520 // The Anti tracking panel is an internal tool, to be enabled manually via about:config 521 if (Services.prefs.getBoolPref("devtools.anti-tracking.enabled", false)) { 522 defaultTools.push(Tools.antitracking); 523 } 524 525 exports.defaultTools = defaultTools; 526 527 Tools.darkTheme = { 528 id: "dark", 529 label: l10n("options.darkTheme.label2"), 530 ordinal: 1, 531 stylesheets: ["chrome://devtools/skin/dark-theme.css"], 532 classList: ["theme-dark"], 533 }; 534 535 Tools.lightTheme = { 536 id: "light", 537 label: l10n("options.lightTheme.label2"), 538 ordinal: 2, 539 stylesheets: ["chrome://devtools/skin/light-theme.css"], 540 classList: ["theme-light"], 541 }; 542 543 exports.defaultThemes = [Tools.darkTheme, Tools.lightTheme]; 544 545 // List buttons that can be toggled to prevent adding prefs for 546 // addons that have manually inserted toolbarbuttons into DOM. 547 // (By default, supported target is only local tab) 548 exports.ToolboxButtons = [ 549 { 550 id: "command-button-experimental-prefs", 551 description: "DevTools Experimental preferences", 552 isToolSupported: () => !lazy.AppConstants.MOZILLA_OFFICIAL, 553 onClick: (event, toolbox) => DevToolsExperimentalPrefs.showTooltip(toolbox), 554 isChecked: () => DevToolsExperimentalPrefs.isAnyPreferenceEnabled(), 555 }, 556 { 557 id: "command-button-responsive", 558 description: l10n( 559 "toolbox.buttons.responsive", 560 osString == "Darwin" ? "Cmd+Opt+M" : "Ctrl+Shift+M" 561 ), 562 isToolSupported: toolbox => toolbox.commands.descriptorFront.isLocalTab, 563 onClick(event, toolbox) { 564 const { localTab } = toolbox.commands.descriptorFront; 565 const browserWindow = localTab.ownerDocument.defaultView; 566 ResponsiveUIManager.toggle(browserWindow, localTab, { 567 trigger: "toolbox", 568 }); 569 }, 570 isChecked(toolbox) { 571 const { localTab } = toolbox.commands.descriptorFront; 572 if (!localTab) { 573 return false; 574 } 575 return ResponsiveUIManager.isActiveForTab(localTab); 576 }, 577 isToggle: true, 578 setup(toolbox, onChange) { 579 ResponsiveUIManager.on("on", onChange); 580 ResponsiveUIManager.on("off", onChange); 581 }, 582 teardown(toolbox, onChange) { 583 ResponsiveUIManager.off("on", onChange); 584 ResponsiveUIManager.off("off", onChange); 585 }, 586 }, 587 { 588 id: "command-button-screenshot", 589 description: l10n("toolbox.buttons.screenshot"), 590 isToolSupported: toolbox => { 591 return ( 592 // @backward-compat { version 87 } We need to check for the screenshot actor as well 593 // when connecting to older server that does not have the screenshotContentActor 594 toolbox.target.hasActor("screenshotContent") || 595 toolbox.target.hasActor("screenshot") 596 ); 597 }, 598 async onClick(event, toolbox) { 599 // Special case for screenshot button to check for clipboard preference 600 const clipboardEnabled = Services.prefs.getBoolPref( 601 "devtools.screenshot.clipboard.enabled" 602 ); 603 604 // When screenshot to clipboard is enabled disabling saving to file 605 const args = { 606 fullpage: true, 607 file: !clipboardEnabled, 608 clipboard: clipboardEnabled, 609 }; 610 611 const messages = await captureAndSaveScreenshot( 612 toolbox.target, 613 toolbox.win, 614 args 615 ); 616 const notificationBox = toolbox.getNotificationBox(); 617 const priorityMap = { 618 error: notificationBox.PRIORITY_CRITICAL_HIGH, 619 warn: notificationBox.PRIORITY_WARNING_HIGH, 620 }; 621 for (const { text, level } of messages) { 622 // captureAndSaveScreenshot returns "saved" messages, that indicate where the 623 // screenshot was saved. In regular toolbox, we don't want to display them as 624 // the download UI can be used to open them. 625 // But in the browser toolbox, we can't see the download UI, so we'll display the 626 // saved message so the user knows there the file was saved. 627 if ( 628 !toolbox.isBrowserToolbox && 629 level !== "warn" && 630 level !== "error" 631 ) { 632 continue; 633 } 634 notificationBox.appendNotification( 635 text, 636 null, 637 null, 638 priorityMap[level] || notificationBox.PRIORITY_INFO_MEDIUM 639 ); 640 } 641 }, 642 }, 643 createHighlightButton( 644 [HIGHLIGHTER_TYPES.RULERS, HIGHLIGHTER_TYPES.VIEWPORT_SIZE], 645 "rulers" 646 ), 647 createHighlightButton([HIGHLIGHTER_TYPES.MEASURING], "measure"), 648 { 649 id: "command-button-jstracer", 650 description: l10n( 651 "toolbox.buttons.jstracer", 652 osString == "Darwin" ? "Cmd+Shift+5" : "Ctrl+Shift+5" 653 ), 654 isToolSupported: () => 655 Services.prefs.getBoolPref( 656 "devtools.debugger.features.javascript-tracing", 657 false 658 ), 659 async onClick(event, toolbox) { 660 await toolbox.commands.tracerCommand.toggle(); 661 }, 662 isChecked(toolbox) { 663 const { tracerCommand } = toolbox.commands; 664 const button = toolbox.doc.getElementById("command-button-jstracer"); 665 if (button) { 666 button.classList.toggle( 667 "pending", 668 tracerCommand.isTracingEnabled && !tracerCommand.isTracingActive 669 ); 670 } 671 return tracerCommand.isTracingEnabled; 672 }, 673 isToggle: true, 674 setup(toolbox, onChange) { 675 toolbox.commands.tracerCommand.on("toggle", onChange); 676 }, 677 teardown(toolbox, onChange) { 678 toolbox.commands.tracerCommand.off("toggle", onChange); 679 }, 680 getContextMenu(toolbox) { 681 const menu = new Menu(); 682 const options = toolbox.commands.tracerCommand.getTracingOptions(); 683 const { logMethod } = options; 684 menu.append( 685 new MenuItem({ 686 id: "jstracer-menu-item-debugger-sidebar", 687 label: l10n( 688 "toolbox.buttons.jstracer.menu-item.trace-to-debugger-sidebar" 689 ), 690 checked: logMethod == TRACER_LOG_METHODS.DEBUGGER_SIDEBAR, 691 type: "radio", 692 click: () => { 693 Services.prefs.setStringPref( 694 "devtools.debugger.javascript-tracing-log-method", 695 TRACER_LOG_METHODS.DEBUGGER_SIDEBAR 696 ); 697 }, 698 }) 699 ); 700 menu.append( 701 new MenuItem({ 702 id: "jstracer-menu-item-console", 703 label: l10n("traceInWebConsole"), 704 checked: logMethod == TRACER_LOG_METHODS.CONSOLE, 705 type: "radio", 706 click: () => { 707 Services.prefs.setStringPref( 708 "devtools.debugger.javascript-tracing-log-method", 709 TRACER_LOG_METHODS.CONSOLE 710 ); 711 }, 712 }) 713 ); 714 menu.append( 715 new MenuItem({ 716 id: "jstracer-menu-item-profiler", 717 label: l10n("traceInProfiler"), 718 checked: logMethod == TRACER_LOG_METHODS.PROFILER, 719 type: "radio", 720 click: () => { 721 Services.prefs.setStringPref( 722 "devtools.debugger.javascript-tracing-log-method", 723 TRACER_LOG_METHODS.PROFILER 724 ); 725 }, 726 }) 727 ); 728 menu.append( 729 new MenuItem({ 730 id: "jstracer-menu-item-stdout", 731 label: l10n("traceInStdout"), 732 type: "radio", 733 checked: logMethod == TRACER_LOG_METHODS.STDOUT, 734 click: () => { 735 Services.prefs.setStringPref( 736 "devtools.debugger.javascript-tracing-log-method", 737 TRACER_LOG_METHODS.STDOUT 738 ); 739 }, 740 }) 741 ); 742 menu.append(new MenuItem({ type: "separator" })); 743 menu.append( 744 new MenuItem({ 745 id: "jstracer-menu-item-next-interaction", 746 label: l10n("traceOnNextInteraction"), 747 type: "checkbox", 748 checked: options.traceOnNextInteraction, 749 click: () => { 750 Services.prefs.setBoolPref( 751 "devtools.debugger.javascript-tracing-on-next-interaction", 752 !options.traceOnNextInteraction 753 ); 754 }, 755 }) 756 ); 757 menu.append( 758 new MenuItem({ 759 id: "jstracer-menu-item-next-load", 760 label: l10n("traceOnNextLoad"), 761 type: "checkbox", 762 checked: options.traceOnNextLoad, 763 click: () => { 764 Services.prefs.setBoolPref( 765 "devtools.debugger.javascript-tracing-on-next-load", 766 !options.traceOnNextLoad 767 ); 768 }, 769 }) 770 ); 771 menu.append(new MenuItem({ type: "separator" })); 772 menu.append( 773 new MenuItem({ 774 id: "jstracer-menu-item-log-values", 775 label: l10n("traceValues"), 776 type: "checkbox", 777 checked: options.traceValues, 778 click: () => { 779 Services.prefs.setBoolPref( 780 "devtools.debugger.javascript-tracing-values", 781 !options.traceValues 782 ); 783 }, 784 }) 785 ); 786 menu.append( 787 new MenuItem({ 788 id: "jstracer-menu-item-function-return", 789 label: l10n("traceFunctionReturn"), 790 type: "checkbox", 791 checked: options.traceFunctionReturn, 792 click: () => { 793 Services.prefs.setBoolPref( 794 "devtools.debugger.javascript-tracing-function-return", 795 !options.traceFunctionReturn 796 ); 797 }, 798 }) 799 ); 800 return menu; 801 }, 802 }, 803 ]; 804 805 function createHighlightButton(highlighters, id) { 806 return { 807 id: `command-button-${id}`, 808 description: l10n(`toolbox.buttons.${id}`), 809 isToolSupported: toolbox => 810 toolbox.commands.descriptorFront.isTabDescriptor, 811 async onClick(event, toolbox) { 812 const inspectorFront = await toolbox.target.getFront("inspector"); 813 814 await Promise.all( 815 highlighters.map(async name => { 816 const highlighter = 817 await inspectorFront.getOrCreateHighlighterByType(name); 818 819 if (highlighter.isShown()) { 820 await highlighter.hide(); 821 } else { 822 await highlighter.show(); 823 } 824 }) 825 ); 826 }, 827 isChecked(toolbox) { 828 // if the inspector doesn't exist, then the highlighter has not yet been connected 829 // to the front end. 830 const inspectorFront = toolbox.target.getCachedFront("inspector"); 831 if (!inspectorFront) { 832 // initialize the inspector front asyncronously. There is a potential for buggy 833 // behavior here, but we need to change how the buttons get data (have them 834 // consume data from reducers rather than writing our own version) in order to 835 // fix this properly. 836 return false; 837 } 838 839 return highlighters.every(name => 840 inspectorFront.getKnownHighlighter(name)?.isShown() 841 ); 842 }, 843 isToggle: true, 844 }; 845 } 846 847 /** 848 * Lookup l10n string from a string bundle. 849 * 850 * @param {string} name 851 * The key to lookup. 852 * @param {...string} args 853 * Optional format argument. 854 * @returns A localized version of the given key. 855 */ 856 function l10n(name, ...args) { 857 try { 858 return args ? L10N.getFormatStr(name, ...args) : L10N.getStr(name); 859 } catch (ex) { 860 console.log("Error reading '" + name + "'"); 861 throw new Error("l10n error with " + name); 862 } 863 } 864 865 function commandkey(name) { 866 try { 867 return CommandKeys.formatValueSync(name); 868 } catch (ex) { 869 console.log("Error reading '" + name + "'"); 870 throw new Error("l10n error with " + name); 871 } 872 } 873 874 function functionkey(shortkey) { 875 return shortkey.split("_")[1]; 876 }