While the frontend doesn't need passing the isShown state from the actor, the tests require to pass it via highlighter's actor's form. The frontend can derivate the current state by looking at target actor configuration. Differential Revision: https://phabricator.services.mozilla.com/D306098
947 lines
27 KiB
JavaScript
947 lines
27 KiB
JavaScript
/* 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/. */
|
|
|
|
"use strict";
|
|
|
|
const osString = Services.appinfo.OS;
|
|
|
|
// Panels
|
|
loader.lazyGetter(
|
|
this,
|
|
"OptionsPanel",
|
|
() =>
|
|
require("resource://devtools/client/framework/toolbox-options.js")
|
|
.OptionsPanel
|
|
);
|
|
loader.lazyGetter(
|
|
this,
|
|
"InspectorPanel",
|
|
() => require("resource://devtools/client/inspector/panel.js").InspectorPanel
|
|
);
|
|
loader.lazyGetter(
|
|
this,
|
|
"WebConsolePanel",
|
|
() =>
|
|
require("resource://devtools/client/webconsole/panel.js").WebConsolePanel
|
|
);
|
|
loader.lazyGetter(
|
|
this,
|
|
"DebuggerPanel",
|
|
() => require("resource://devtools/client/debugger/panel.js").DebuggerPanel
|
|
);
|
|
loader.lazyGetter(
|
|
this,
|
|
"StyleEditorPanel",
|
|
() =>
|
|
require("resource://devtools/client/styleeditor/panel.js").StyleEditorPanel
|
|
);
|
|
loader.lazyGetter(
|
|
this,
|
|
"MemoryPanel",
|
|
() => require("resource://devtools/client/memory/panel.js").MemoryPanel
|
|
);
|
|
loader.lazyGetter(
|
|
this,
|
|
"NewPerformancePanel",
|
|
() =>
|
|
require("resource://devtools/client/performance-new/panel/panel.js")
|
|
.PerformancePanel
|
|
);
|
|
loader.lazyGetter(
|
|
this,
|
|
"NetMonitorPanel",
|
|
() =>
|
|
require("resource://devtools/client/netmonitor/panel.js").NetMonitorPanel
|
|
);
|
|
loader.lazyGetter(
|
|
this,
|
|
"StoragePanel",
|
|
() => require("resource://devtools/client/storage/panel.js").StoragePanel
|
|
);
|
|
loader.lazyGetter(
|
|
this,
|
|
"DomPanel",
|
|
() => require("resource://devtools/client/dom/panel.js").DomPanel
|
|
);
|
|
loader.lazyGetter(
|
|
this,
|
|
"AccessibilityPanel",
|
|
() =>
|
|
require("resource://devtools/client/accessibility/panel.js")
|
|
.AccessibilityPanel
|
|
);
|
|
loader.lazyGetter(
|
|
this,
|
|
"ApplicationPanel",
|
|
() =>
|
|
require("resource://devtools/client/application/panel.js").ApplicationPanel
|
|
);
|
|
loader.lazyGetter(
|
|
this,
|
|
"AntiTrackingPanel",
|
|
() =>
|
|
require("resource://devtools/client/anti-tracking/panel.js")
|
|
.AntiTrackingPanel
|
|
);
|
|
|
|
// Other dependencies
|
|
loader.lazyRequireGetter(
|
|
this,
|
|
"ResponsiveUIManager",
|
|
"resource://devtools/client/responsive/manager.js"
|
|
);
|
|
loader.lazyRequireGetter(
|
|
this,
|
|
"TRACER_LOG_METHODS",
|
|
"resource://devtools/shared/specs/tracer.js",
|
|
true
|
|
);
|
|
|
|
const lazy = {};
|
|
ChromeUtils.defineESModuleGetters(lazy, {
|
|
AppConstants: "resource://gre/modules/AppConstants.sys.mjs",
|
|
});
|
|
loader.lazyRequireGetter(
|
|
this,
|
|
"DevToolsExperimentalPrefs",
|
|
"resource://devtools/client/devtools-experimental-prefs.js"
|
|
);
|
|
loader.lazyRequireGetter(
|
|
this,
|
|
"captureAndSaveScreenshot",
|
|
"resource://devtools/client/shared/screenshot.js",
|
|
true
|
|
);
|
|
loader.lazyRequireGetter(
|
|
this,
|
|
"Menu",
|
|
"resource://devtools/client/framework/menu.js"
|
|
);
|
|
loader.lazyRequireGetter(
|
|
this,
|
|
"MenuItem",
|
|
"resource://devtools/client/framework/menu-item.js"
|
|
);
|
|
|
|
const { TYPES: HIGHLIGHTER_TYPES } = ChromeUtils.importESModule(
|
|
"resource://devtools/shared/highlighters.mjs"
|
|
);
|
|
|
|
const { LocalizationHelper } = require("resource://devtools/shared/l10n.js");
|
|
const L10N = new LocalizationHelper(
|
|
"devtools/client/locales/startup.properties"
|
|
);
|
|
const CommandKeys = new Localization(
|
|
["devtools/startup/key-shortcuts.ftl"],
|
|
true
|
|
);
|
|
|
|
var Tools = {};
|
|
exports.Tools = Tools;
|
|
|
|
// Definitions
|
|
Tools.options = {
|
|
id: "options",
|
|
ordinal: 0,
|
|
url: "chrome://devtools/content/framework/toolbox-options.html",
|
|
icon: "chrome://devtools/skin/images/settings.svg",
|
|
bgTheme: "theme-body",
|
|
label: l10n("options.label"),
|
|
iconOnly: true,
|
|
panelLabel: l10n("options.panelLabel"),
|
|
tooltip: l10n("optionsButton.tooltip"),
|
|
inMenu: false,
|
|
|
|
isToolSupported() {
|
|
return true;
|
|
},
|
|
|
|
build(iframeWindow, toolbox, commands) {
|
|
return new OptionsPanel(iframeWindow, toolbox, commands);
|
|
},
|
|
};
|
|
|
|
Tools.inspector = {
|
|
id: "inspector",
|
|
accesskey: l10n("inspector.accesskey"),
|
|
ordinal: 1,
|
|
icon: "chrome://devtools/skin/images/tool-inspector.svg",
|
|
url: "chrome://devtools/content/inspector/index.xhtml",
|
|
label: l10n("inspector.label"),
|
|
panelLabel: l10n("inspector.panelLabel"),
|
|
get tooltip() {
|
|
const key = commandkey("devtools-commandkey-inspector");
|
|
if (osString == "Darwin") {
|
|
const cmdShiftC = "Cmd+Shift+" + key;
|
|
const cmdOptC = "Cmd+Opt+" + key;
|
|
return l10n("inspector.mac.tooltip", cmdShiftC, cmdOptC);
|
|
}
|
|
|
|
const ctrlShiftC = "Ctrl+Shift+" + key;
|
|
return l10n("inspector.tooltip2", ctrlShiftC);
|
|
},
|
|
inMenu: false,
|
|
|
|
preventClosingOnKey: true,
|
|
// preventRaisingOnKey is used to keep the focus on the content window for shortcuts
|
|
// that trigger the element picker.
|
|
preventRaisingOnKey: true,
|
|
onkey(panel, toolbox) {
|
|
if (
|
|
Services.prefs.getBoolPref("devtools.command-button-pick.enabled", false)
|
|
) {
|
|
toolbox.nodePicker.togglePicker();
|
|
}
|
|
},
|
|
|
|
isToolSupported(toolbox) {
|
|
return toolbox.target.hasActor("inspector");
|
|
},
|
|
|
|
build(iframeWindow, toolbox, commands) {
|
|
return new InspectorPanel(iframeWindow, toolbox, commands);
|
|
},
|
|
};
|
|
Tools.webConsole = {
|
|
id: "webconsole",
|
|
accesskey: l10n("webConsoleCmd.accesskey"),
|
|
ordinal: 2,
|
|
url: "chrome://devtools/content/webconsole/index.html",
|
|
icon: "chrome://devtools/skin/images/tool-webconsole.svg",
|
|
label: l10n("ToolboxTabWebconsole.label"),
|
|
menuLabel: l10n("MenuWebconsole.label"),
|
|
panelLabel: l10n("ToolboxWebConsole.panelLabel"),
|
|
get tooltip() {
|
|
return l10n(
|
|
"ToolboxWebconsole.tooltip2",
|
|
(osString == "Darwin" ? "Cmd+Opt+" : "Ctrl+Shift+") +
|
|
commandkey("devtools-commandkey-webconsole")
|
|
);
|
|
},
|
|
inMenu: false,
|
|
|
|
preventClosingOnKey: true,
|
|
onkey(panel, toolbox) {
|
|
if (toolbox.splitConsole) {
|
|
return toolbox.focusConsoleInput();
|
|
}
|
|
|
|
panel.focusInput();
|
|
return undefined;
|
|
},
|
|
|
|
isToolSupported() {
|
|
return true;
|
|
},
|
|
build(iframeWindow, toolbox, commands) {
|
|
return new WebConsolePanel(iframeWindow, toolbox, commands);
|
|
},
|
|
};
|
|
|
|
Tools.jsdebugger = {
|
|
id: "jsdebugger",
|
|
accesskey: l10n("debuggerMenu.accesskey"),
|
|
ordinal: 3,
|
|
icon: "chrome://devtools/skin/images/tool-debugger.svg",
|
|
url: "chrome://devtools/content/debugger/index.html",
|
|
label: l10n("ToolboxDebugger.label"),
|
|
panelLabel: l10n("ToolboxDebugger.panelLabel"),
|
|
get tooltip() {
|
|
return l10n(
|
|
"ToolboxDebugger.tooltip4",
|
|
(osString == "Darwin" ? "Cmd+Opt+" : "Ctrl+Shift+") +
|
|
commandkey("devtools-commandkey-jsdebugger")
|
|
);
|
|
},
|
|
inMenu: false,
|
|
isToolSupported() {
|
|
return true;
|
|
},
|
|
build(iframeWindow, toolbox, commands) {
|
|
return new DebuggerPanel(iframeWindow, toolbox, commands);
|
|
},
|
|
};
|
|
|
|
Tools.styleEditor = {
|
|
id: "styleeditor",
|
|
ordinal: 5,
|
|
visibilityswitch: "devtools.styleeditor.enabled",
|
|
accesskey: l10n("open.accesskey"),
|
|
icon: "chrome://devtools/skin/images/tool-styleeditor.svg",
|
|
url: "chrome://devtools/content/styleeditor/index.xhtml",
|
|
label: l10n("ToolboxStyleEditor.label"),
|
|
panelLabel: l10n("ToolboxStyleEditor.panelLabel"),
|
|
get tooltip() {
|
|
return l10n(
|
|
"ToolboxStyleEditor.tooltip3",
|
|
"Shift+" + functionkey(commandkey("devtools-commandkey-styleeditor"))
|
|
);
|
|
},
|
|
inMenu: false,
|
|
isToolSupported(toolbox) {
|
|
return toolbox.target.hasActor("styleSheets");
|
|
},
|
|
|
|
build(iframeWindow, toolbox, commands) {
|
|
return new StyleEditorPanel(iframeWindow, toolbox, commands);
|
|
},
|
|
};
|
|
|
|
Tools.performance = {
|
|
id: "performance",
|
|
ordinal: 6,
|
|
icon: "chrome://devtools/skin/images/tool-profiler.svg",
|
|
url: "chrome://devtools/content/performance-new/panel/index.xhtml",
|
|
visibilityswitch: "devtools.performance.enabled",
|
|
label: l10n("performance.label"),
|
|
panelLabel: l10n("performance.panelLabel"),
|
|
get tooltip() {
|
|
return l10n(
|
|
"performance.tooltip",
|
|
"Shift+" + functionkey(commandkey("devtools-commandkey-performance"))
|
|
);
|
|
},
|
|
accesskey: l10n("performance.accesskey"),
|
|
inMenu: false,
|
|
isToolSupported(toolbox) {
|
|
// Only use the new performance panel on local tab toolboxes, as they are guaranteed
|
|
// to have a performance actor.
|
|
// Remote tab toolboxes (eg about:devtools-toolbox from about:debugging) should not
|
|
// use the performance panel; about:debugging provides a "Profile performance" button
|
|
// which can be used instead, without having the overhead of starting a remote toolbox.
|
|
// Also accept the Browser Toolbox, so that we can profile its process via a second browser toolbox.
|
|
return (
|
|
toolbox.commands.descriptorFront.isLocalTab || toolbox.isBrowserToolbox
|
|
);
|
|
},
|
|
build(frame, toolbox, commands) {
|
|
return new NewPerformancePanel(frame, toolbox, commands);
|
|
},
|
|
};
|
|
|
|
Tools.memory = {
|
|
id: "memory",
|
|
ordinal: 7,
|
|
icon: "chrome://devtools/skin/images/tool-memory.svg",
|
|
url: "chrome://devtools/content/memory/index.xhtml",
|
|
visibilityswitch: "devtools.memory.enabled",
|
|
label: l10n("memory.label"),
|
|
panelLabel: l10n("memory.panelLabel"),
|
|
tooltip: l10n("memory.tooltip"),
|
|
|
|
isToolSupported(toolbox) {
|
|
const { descriptorFront } = toolbox.commands;
|
|
return (
|
|
!descriptorFront.isWebExtensionDescriptor &&
|
|
!descriptorFront.isWorkerDescriptor
|
|
);
|
|
},
|
|
|
|
build(frame, toolbox, commands) {
|
|
return new MemoryPanel(frame, toolbox, commands);
|
|
},
|
|
};
|
|
|
|
Tools.netMonitor = {
|
|
id: "netmonitor",
|
|
accesskey: l10n("netmonitor.accesskey"),
|
|
ordinal: 4,
|
|
visibilityswitch: "devtools.netmonitor.enabled",
|
|
icon: "chrome://devtools/skin/images/tool-network.svg",
|
|
url: "chrome://devtools/content/netmonitor/index.html",
|
|
label: l10n("netmonitor.label"),
|
|
panelLabel: l10n("netmonitor.panelLabel"),
|
|
get tooltip() {
|
|
return l10n(
|
|
"netmonitor.tooltip2",
|
|
(osString == "Darwin" ? "Cmd+Opt+" : "Ctrl+Shift+") +
|
|
commandkey("devtools-commandkey-netmonitor")
|
|
);
|
|
},
|
|
inMenu: false,
|
|
|
|
isToolSupported(toolbox) {
|
|
return (
|
|
toolbox.target.getTrait("networkMonitor") &&
|
|
!toolbox.target.isWorkerTarget
|
|
);
|
|
},
|
|
|
|
build(iframeWindow, toolbox, commands) {
|
|
return new NetMonitorPanel(iframeWindow, toolbox, commands);
|
|
},
|
|
};
|
|
|
|
Tools.storage = {
|
|
id: "storage",
|
|
ordinal: 8,
|
|
accesskey: l10n("storage.accesskey"),
|
|
visibilityswitch: "devtools.storage.enabled",
|
|
icon: "chrome://devtools/skin/images/tool-storage.svg",
|
|
url: "chrome://devtools/content/storage/index.xhtml",
|
|
label: l10n("storage.label"),
|
|
menuLabel: l10n("storage.menuLabel"),
|
|
panelLabel: l10n("storage.panelLabel"),
|
|
get tooltip() {
|
|
return l10n(
|
|
"storage.tooltip3",
|
|
"Shift+" + functionkey(commandkey("devtools-commandkey-storage"))
|
|
);
|
|
},
|
|
inMenu: false,
|
|
|
|
isToolSupported(toolbox) {
|
|
const { descriptorFront } = toolbox.commands;
|
|
// Storage is available on all contexts debugging a BrowsingContext.
|
|
// As of today, this is all but worker toolboxes.
|
|
return (
|
|
descriptorFront.isTabDescriptor ||
|
|
descriptorFront.isParentProcessDescriptor ||
|
|
descriptorFront.isWebExtensionDescriptor
|
|
);
|
|
},
|
|
|
|
build(iframeWindow, toolbox, commands) {
|
|
return new StoragePanel(iframeWindow, toolbox, commands);
|
|
},
|
|
};
|
|
|
|
Tools.dom = {
|
|
id: "dom",
|
|
accesskey: l10n("dom.accesskey"),
|
|
ordinal: 11,
|
|
visibilityswitch: "devtools.dom.enabled",
|
|
icon: "chrome://devtools/skin/images/tool-dom.svg",
|
|
url: "chrome://devtools/content/dom/index.html",
|
|
label: l10n("dom.label"),
|
|
panelLabel: l10n("dom.panelLabel"),
|
|
get tooltip() {
|
|
return l10n(
|
|
"dom.tooltip",
|
|
(osString == "Darwin" ? "Cmd+Opt+" : "Ctrl+Shift+") +
|
|
commandkey("devtools-commandkey-dom")
|
|
);
|
|
},
|
|
inMenu: false,
|
|
|
|
isToolSupported() {
|
|
return true;
|
|
},
|
|
|
|
build(iframeWindow, toolbox, commands) {
|
|
return new DomPanel(iframeWindow, toolbox, commands);
|
|
},
|
|
};
|
|
|
|
Tools.accessibility = {
|
|
id: "accessibility",
|
|
accesskey: l10n("accessibility.accesskey"),
|
|
ordinal: 9,
|
|
modifiers: osString == "Darwin" ? "accel,alt" : "accel,shift",
|
|
visibilityswitch: "devtools.accessibility.enabled",
|
|
icon: "chrome://devtools/skin/images/tool-accessibility.svg",
|
|
url: "chrome://devtools/content/accessibility/index.html",
|
|
label: l10n("accessibility.label"),
|
|
panelLabel: l10n("accessibility.panelLabel"),
|
|
get tooltip() {
|
|
return l10n(
|
|
"accessibility.tooltip3",
|
|
"Shift+" +
|
|
functionkey(commandkey("devtools-commandkey-accessibility-f12"))
|
|
);
|
|
},
|
|
inMenu: false,
|
|
|
|
isToolSupported(toolbox) {
|
|
return toolbox.target.hasActor("accessibility");
|
|
},
|
|
|
|
build(iframeWindow, toolbox, commands) {
|
|
return new AccessibilityPanel(iframeWindow, toolbox, commands);
|
|
},
|
|
};
|
|
|
|
Tools.application = {
|
|
id: "application",
|
|
ordinal: 10,
|
|
visibilityswitch: "devtools.application.enabled",
|
|
icon: "chrome://devtools/skin/images/tool-application.svg",
|
|
url: "chrome://devtools/content/application/index.html",
|
|
label: l10n("application.label"),
|
|
panelLabel: l10n("application.panelLabel"),
|
|
tooltip: l10n("application.tooltip"),
|
|
inMenu: false,
|
|
|
|
isToolSupported(toolbox) {
|
|
return toolbox.target.hasActor("manifest");
|
|
},
|
|
|
|
build(iframeWindow, toolbox, commands) {
|
|
return new ApplicationPanel(iframeWindow, toolbox, commands);
|
|
},
|
|
};
|
|
|
|
Tools.antitracking = {
|
|
id: "antitracking",
|
|
ordinal: 11,
|
|
visibilityswitch: "devtools.anti-tracking.enabled",
|
|
icon: "chrome://browser/skin/tracking-protection.svg",
|
|
url: "chrome://devtools/content/anti-tracking/index.html",
|
|
label: "Anti tracking",
|
|
panelLabel: "Anti tracking",
|
|
tooltip: "Anti tracking",
|
|
inMenu: false,
|
|
|
|
isToolSupported() {
|
|
return true;
|
|
},
|
|
|
|
build(iframeWindow, toolbox, commands) {
|
|
return new AntiTrackingPanel(iframeWindow, toolbox, commands);
|
|
},
|
|
};
|
|
|
|
var defaultTools = [
|
|
Tools.options,
|
|
Tools.webConsole,
|
|
Tools.inspector,
|
|
Tools.jsdebugger,
|
|
Tools.styleEditor,
|
|
Tools.performance,
|
|
Tools.netMonitor,
|
|
Tools.storage,
|
|
Tools.memory,
|
|
Tools.dom,
|
|
Tools.accessibility,
|
|
Tools.application,
|
|
];
|
|
|
|
// The Anti tracking panel is an internal tool, to be enabled manually via about:config
|
|
if (Services.prefs.getBoolPref("devtools.anti-tracking.enabled", false)) {
|
|
defaultTools.push(Tools.antitracking);
|
|
}
|
|
|
|
exports.defaultTools = defaultTools;
|
|
|
|
Tools.darkTheme = {
|
|
id: "dark",
|
|
label: l10n("options.darkTheme.label2"),
|
|
ordinal: 1,
|
|
stylesheets: ["chrome://devtools/skin/dark-theme.css"],
|
|
classList: ["theme-dark"],
|
|
};
|
|
|
|
Tools.lightTheme = {
|
|
id: "light",
|
|
label: l10n("options.lightTheme.label2"),
|
|
ordinal: 2,
|
|
stylesheets: ["chrome://devtools/skin/light-theme.css"],
|
|
classList: ["theme-light"],
|
|
};
|
|
|
|
exports.defaultThemes = [Tools.darkTheme, Tools.lightTheme];
|
|
|
|
// List buttons that can be toggled to prevent adding prefs for
|
|
// addons that have manually inserted toolbarbuttons into DOM.
|
|
// (By default, supported target is only local tab)
|
|
exports.ToolboxButtons = [
|
|
{
|
|
id: "command-button-experimental-prefs",
|
|
description: "DevTools Experimental preferences",
|
|
isToolSupported: () => !lazy.AppConstants.MOZILLA_OFFICIAL,
|
|
onClick: (event, toolbox) => DevToolsExperimentalPrefs.showTooltip(toolbox),
|
|
isChecked: () => DevToolsExperimentalPrefs.isAnyPreferenceEnabled(),
|
|
},
|
|
{
|
|
id: "command-button-responsive",
|
|
description: l10n(
|
|
"toolbox.buttons.responsive",
|
|
osString == "Darwin" ? "Cmd+Opt+M" : "Ctrl+Shift+M"
|
|
),
|
|
isToolSupported: toolbox => toolbox.commands.descriptorFront.isLocalTab,
|
|
onClick(event, toolbox) {
|
|
const { localTab } = toolbox.commands.descriptorFront;
|
|
const browserWindow = localTab.ownerDocument.defaultView;
|
|
ResponsiveUIManager.toggle(browserWindow, localTab, {
|
|
trigger: "toolbox",
|
|
});
|
|
},
|
|
isChecked(toolbox) {
|
|
const { localTab } = toolbox.commands.descriptorFront;
|
|
if (!localTab) {
|
|
return false;
|
|
}
|
|
return ResponsiveUIManager.isActiveForTab(localTab);
|
|
},
|
|
isToggle: true,
|
|
setup(toolbox, onChange) {
|
|
ResponsiveUIManager.on("on", onChange);
|
|
ResponsiveUIManager.on("off", onChange);
|
|
},
|
|
teardown(toolbox, onChange) {
|
|
ResponsiveUIManager.off("on", onChange);
|
|
ResponsiveUIManager.off("off", onChange);
|
|
},
|
|
},
|
|
{
|
|
id: "command-button-screenshot",
|
|
description: l10n("toolbox.buttons.screenshot"),
|
|
isToolSupported: toolbox => {
|
|
return (
|
|
// @backward-compat { version 87 } We need to check for the screenshot actor as well
|
|
// when connecting to older server that does not have the screenshotContentActor
|
|
toolbox.target.hasActor("screenshotContent") ||
|
|
toolbox.target.hasActor("screenshot")
|
|
);
|
|
},
|
|
async onClick(event, toolbox) {
|
|
// Special case for screenshot button to check for clipboard preference
|
|
const clipboardEnabled = Services.prefs.getBoolPref(
|
|
"devtools.screenshot.clipboard.enabled"
|
|
);
|
|
|
|
// When screenshot to clipboard is enabled disabling saving to file
|
|
const args = {
|
|
fullpage: true,
|
|
file: !clipboardEnabled,
|
|
clipboard: clipboardEnabled,
|
|
};
|
|
|
|
const messages = await captureAndSaveScreenshot(
|
|
toolbox.target,
|
|
toolbox.win,
|
|
args
|
|
);
|
|
const notificationBox = toolbox.getNotificationBox();
|
|
const priorityMap = {
|
|
error: notificationBox.PRIORITY_CRITICAL_HIGH,
|
|
warn: notificationBox.PRIORITY_WARNING_HIGH,
|
|
};
|
|
for (const { text, level } of messages) {
|
|
// captureAndSaveScreenshot returns "saved" messages, that indicate where the
|
|
// screenshot was saved. In regular toolbox, we don't want to display them as
|
|
// the download UI can be used to open them.
|
|
// But in the browser toolbox, we can't see the download UI, so we'll display the
|
|
// saved message so the user knows there the file was saved.
|
|
if (
|
|
!toolbox.isBrowserToolbox &&
|
|
level !== "warn" &&
|
|
level !== "error"
|
|
) {
|
|
continue;
|
|
}
|
|
notificationBox.appendNotification(
|
|
text,
|
|
null,
|
|
null,
|
|
priorityMap[level] || notificationBox.PRIORITY_INFO_MEDIUM
|
|
);
|
|
}
|
|
},
|
|
},
|
|
createHighlightButton({
|
|
highlighterTypes: [
|
|
HIGHLIGHTER_TYPES.RULERS,
|
|
HIGHLIGHTER_TYPES.VIEWPORT_SIZE,
|
|
],
|
|
id: "rulers",
|
|
}),
|
|
createHighlightButton({
|
|
highlighterTypes: [HIGHLIGHTER_TYPES.MEASURING],
|
|
id: "measure",
|
|
}),
|
|
{
|
|
id: "command-button-jstracer",
|
|
description: l10n(
|
|
"toolbox.buttons.jstracer",
|
|
osString == "Darwin" ? "Cmd+Shift+5" : "Ctrl+Shift+5"
|
|
),
|
|
isToolSupported: () => {
|
|
return (
|
|
lazy.AppConstants.NIGHTLY_BUILD ||
|
|
Services.prefs.getBoolPref(
|
|
"devtools.debugger.features.javascript-tracing",
|
|
false
|
|
)
|
|
);
|
|
},
|
|
async onClick(event, toolbox) {
|
|
await toolbox.commands.tracerCommand.toggle();
|
|
},
|
|
isChecked(toolbox) {
|
|
const { tracerCommand } = toolbox.commands;
|
|
const button = toolbox.doc.getElementById("command-button-jstracer");
|
|
if (button) {
|
|
button.classList.toggle(
|
|
"pending",
|
|
tracerCommand.isTracingEnabled && !tracerCommand.isTracingActive
|
|
);
|
|
}
|
|
return tracerCommand.isTracingEnabled;
|
|
},
|
|
isToggle: true,
|
|
setup(toolbox, onChange) {
|
|
toolbox.commands.tracerCommand.on("toggle", onChange);
|
|
|
|
// Automatically enable the button if this old preference was set to true.
|
|
// When enabling the tracer on all channels we will remove this preference.
|
|
if (
|
|
Services.prefs.getBoolPref(
|
|
"devtools.debugger.features.javascript-tracing",
|
|
false
|
|
)
|
|
) {
|
|
Services.prefs.setBoolPref(
|
|
"devtools.command-button-jstracer.enabled",
|
|
true
|
|
);
|
|
}
|
|
},
|
|
teardown(toolbox, onChange) {
|
|
toolbox.commands.tracerCommand.off("toggle", onChange);
|
|
},
|
|
getContextMenu(toolbox) {
|
|
const menu = new Menu();
|
|
const options = toolbox.commands.tracerCommand.getTracingOptions();
|
|
const { logMethod } = options;
|
|
menu.append(
|
|
new MenuItem({
|
|
id: "jstracer-menu-item-debugger-sidebar",
|
|
label: l10n(
|
|
"toolbox.buttons.jstracer.menu-item.trace-to-debugger-sidebar"
|
|
),
|
|
checked: logMethod == TRACER_LOG_METHODS.DEBUGGER_SIDEBAR,
|
|
type: "radio",
|
|
click: () => {
|
|
Services.prefs.setStringPref(
|
|
"devtools.debugger.javascript-tracing-log-method",
|
|
TRACER_LOG_METHODS.DEBUGGER_SIDEBAR
|
|
);
|
|
},
|
|
})
|
|
);
|
|
menu.append(
|
|
new MenuItem({
|
|
id: "jstracer-menu-item-console",
|
|
label: l10n("traceInWebConsole"),
|
|
checked: logMethod == TRACER_LOG_METHODS.CONSOLE,
|
|
type: "radio",
|
|
click: () => {
|
|
Services.prefs.setStringPref(
|
|
"devtools.debugger.javascript-tracing-log-method",
|
|
TRACER_LOG_METHODS.CONSOLE
|
|
);
|
|
},
|
|
})
|
|
);
|
|
menu.append(
|
|
new MenuItem({
|
|
id: "jstracer-menu-item-profiler",
|
|
label: l10n("traceInProfiler"),
|
|
checked: logMethod == TRACER_LOG_METHODS.PROFILER,
|
|
type: "radio",
|
|
click: () => {
|
|
Services.prefs.setStringPref(
|
|
"devtools.debugger.javascript-tracing-log-method",
|
|
TRACER_LOG_METHODS.PROFILER
|
|
);
|
|
},
|
|
})
|
|
);
|
|
menu.append(
|
|
new MenuItem({
|
|
id: "jstracer-menu-item-stdout",
|
|
label: l10n("traceInStdout"),
|
|
type: "radio",
|
|
checked: logMethod == TRACER_LOG_METHODS.STDOUT,
|
|
click: () => {
|
|
Services.prefs.setStringPref(
|
|
"devtools.debugger.javascript-tracing-log-method",
|
|
TRACER_LOG_METHODS.STDOUT
|
|
);
|
|
},
|
|
})
|
|
);
|
|
menu.append(new MenuItem({ type: "separator" }));
|
|
menu.append(
|
|
new MenuItem({
|
|
id: "jstracer-menu-item-next-interaction",
|
|
label: l10n("traceOnNextInteraction"),
|
|
type: "checkbox",
|
|
checked: options.traceOnNextInteraction,
|
|
click: () => {
|
|
Services.prefs.setBoolPref(
|
|
"devtools.debugger.javascript-tracing-on-next-interaction",
|
|
!options.traceOnNextInteraction
|
|
);
|
|
},
|
|
})
|
|
);
|
|
menu.append(
|
|
new MenuItem({
|
|
id: "jstracer-menu-item-next-load",
|
|
label: l10n("traceOnNextLoad"),
|
|
type: "checkbox",
|
|
checked: options.traceOnNextLoad,
|
|
click: () => {
|
|
Services.prefs.setBoolPref(
|
|
"devtools.debugger.javascript-tracing-on-next-load",
|
|
!options.traceOnNextLoad
|
|
);
|
|
},
|
|
})
|
|
);
|
|
menu.append(new MenuItem({ type: "separator" }));
|
|
menu.append(
|
|
new MenuItem({
|
|
id: "jstracer-menu-item-log-values",
|
|
label: l10n("traceValues"),
|
|
type: "checkbox",
|
|
checked: options.traceValues,
|
|
click: () => {
|
|
Services.prefs.setBoolPref(
|
|
"devtools.debugger.javascript-tracing-values",
|
|
!options.traceValues
|
|
);
|
|
},
|
|
})
|
|
);
|
|
menu.append(
|
|
new MenuItem({
|
|
id: "jstracer-menu-item-function-return",
|
|
label: l10n("traceFunctionReturn"),
|
|
type: "checkbox",
|
|
checked: options.traceFunctionReturn,
|
|
click: () => {
|
|
Services.prefs.setBoolPref(
|
|
"devtools.debugger.javascript-tracing-function-return",
|
|
!options.traceFunctionReturn
|
|
);
|
|
},
|
|
})
|
|
);
|
|
return menu;
|
|
},
|
|
},
|
|
];
|
|
|
|
/**
|
|
* Return a definition for a toolbox button that triggers highlighters
|
|
*
|
|
* @param {object} options
|
|
* @param {Array<string>} options.highlighterTypes
|
|
* An array of the highlighter types the button controls
|
|
* @param {string} options.id
|
|
* The button id
|
|
* @returns {object}
|
|
*/
|
|
function createHighlightButton({ highlighterTypes, id }) {
|
|
return {
|
|
id: `command-button-${id}`,
|
|
description: l10n(`toolbox.buttons.${id}`),
|
|
highlighterTypes,
|
|
isToolSupported: toolbox =>
|
|
toolbox.commands.descriptorFront.isTabDescriptor,
|
|
async onClick(event, toolbox) {
|
|
// @backward-compat { version 154 } Firefox 154 started supporting toggling
|
|
// global highlighters via Target Actor Configuration. The else branch can be later removed.
|
|
const { targetConfigurationCommand } = toolbox.commands;
|
|
if (await targetConfigurationCommand.supports("enabledHighlighters")) {
|
|
const { configuration } = targetConfigurationCommand;
|
|
let highlighters = configuration.enabledHighlighters || [];
|
|
// Check if all the highlighters were enabled
|
|
if (highlighterTypes.every(type => highlighters.includes(type))) {
|
|
// Disable the highlighters
|
|
highlighters = highlighters.filter(
|
|
type => !highlighterTypes.includes(type)
|
|
);
|
|
} else {
|
|
// Enable the highlighters
|
|
highlighters = [...highlighters, ...highlighterTypes];
|
|
}
|
|
// Instruct the backend to toggle the highlighters on/off
|
|
await targetConfigurationCommand.updateConfiguration({
|
|
enabledHighlighters: highlighters,
|
|
});
|
|
} else {
|
|
const inspectorFront = await toolbox.target.getFront("inspector");
|
|
await Promise.all(
|
|
highlighterTypes.map(async name => {
|
|
const highlighter =
|
|
await inspectorFront.getOrCreateHighlighterByType(name);
|
|
|
|
if (highlighter.isShown()) {
|
|
await highlighter.hide();
|
|
} else {
|
|
await highlighter.show();
|
|
}
|
|
})
|
|
);
|
|
}
|
|
},
|
|
isChecked(toolbox) {
|
|
const { targetConfigurationCommand } = toolbox.commands;
|
|
const { configuration } = targetConfigurationCommand;
|
|
// Note that we cannot query targetConfigurationCommand.supports as this is an async function,
|
|
// so fallback on looking if the enabledHighlighters configuration key exists
|
|
//
|
|
// @backward-compat { version 154 } Firefox 154 started supporting toggling
|
|
// global highlighters via Target Actor Configuration. The else branch can be later removed.
|
|
if ("enabledHighlighters" in configuration) {
|
|
const highlighters = configuration.enabledHighlighters || [];
|
|
const isChecked = highlighterTypes.every(type =>
|
|
highlighters.includes(type)
|
|
);
|
|
return isChecked;
|
|
}
|
|
// if the inspector doesn't exist, then the highlighter has not yet been connected
|
|
// to the front end.
|
|
const inspectorFront = toolbox.target.getCachedFront("inspector");
|
|
if (!inspectorFront) {
|
|
// initialize the inspector front asyncronously. There is a potential for buggy
|
|
// behavior here, but we need to change how the buttons get data (have them
|
|
// consume data from reducers rather than writing our own version) in order to
|
|
// fix this properly.
|
|
return false;
|
|
}
|
|
|
|
return highlighterTypes.every(name =>
|
|
inspectorFront.getKnownHighlighter(name)?.isShown()
|
|
);
|
|
},
|
|
isToggle: true,
|
|
};
|
|
}
|
|
|
|
/**
|
|
* Lookup l10n string from a string bundle.
|
|
*
|
|
* @param {string} name
|
|
* The key to lookup.
|
|
* @param {...string} args
|
|
* Optional format argument.
|
|
* @returns A localized version of the given key.
|
|
*/
|
|
function l10n(name, ...args) {
|
|
try {
|
|
return args ? L10N.getFormatStr(name, ...args) : L10N.getStr(name);
|
|
} catch (ex) {
|
|
console.log("Error reading '" + name + "'");
|
|
throw new Error("l10n error with " + name);
|
|
}
|
|
}
|
|
|
|
function commandkey(name) {
|
|
try {
|
|
return CommandKeys.formatValueSync(name);
|
|
} catch (ex) {
|
|
console.log("Error reading '" + name + "'");
|
|
throw new Error("l10n error with " + name);
|
|
}
|
|
}
|
|
|
|
function functionkey(shortkey) {
|
|
return shortkey.split("_")[1];
|
|
}
|