☠☠ backed out by 401003622904 ☠ ☠ | |
author | David Walsh <dwalsh@mozilla.com> |
Tue, 21 Apr 2020 21:55:42 +0000 | |
changeset 525324 | 3fc026e3b0e70ae939db76d08f108d3dc8be6077 |
parent 525323 | da168cc5c08f8ec33691f141c55e987e20906f20 |
child 525325 | 208d2317ac56072d9aa5f97ae2dbee09b1f97cf3 |
push id | 113646 |
push user | dwalsh@mozilla.com |
push date | Wed, 22 Apr 2020 01:59:13 +0000 |
treeherder | autoland@3fc026e3b0e7 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jlast, Honza |
bugs | 1630957 |
milestone | 77.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/devtools/client/debugger/babel.config.js +++ b/devtools/client/debugger/babel.config.js @@ -11,16 +11,17 @@ module.exports = { overrides: [ { test: [ "./src", "./packages/*/index.js", "./packages/*/src", /[/\\]node_modules[/\\]devtools-/, /[/\\]node_modules[/\\]react-aria-components[/\\]/, + "../../shared", ], presets: [ "@babel/preset-react", [ "@babel/preset-env", { targets: { browsers: ["last 1 Chrome version", "last 1 Firefox version"],
--- a/devtools/client/debugger/jest-test.config.js +++ b/devtools/client/debugger/jest-test.config.js @@ -36,12 +36,14 @@ module.exports = { snapshotSerializers: [ "jest-serializer-babel-ast", "enzyme-to-json/serializer", ], moduleNameMapper: { "\\.css$": "<rootDir>/src/test/__mocks__/styleMock.js", "\\.svg$": "<rootDir>/src/test/__mocks__/svgMock.js", "^Services": "<rootDir>/src/test/fixtures/Services", + "^chrome": "<rootDir>/src/test/fixtures/Chrome", + "^ChromeUtils": "<rootDir>/src/test/fixtures/ChromeUtils", // Map all require("devtools/...") to the real devtools root. "^devtools\\/(.*)": "<rootDir>/../../$1", }, };
--- a/devtools/client/debugger/src/client/firefox/types.js +++ b/devtools/client/debugger/src/client/firefox/types.js @@ -426,9 +426,10 @@ export type Panel = {| emit: (eventName: string) => void, openLink: (url: URL) => void, openInspector: () => void, openElementInInspector: (grip: Object) => void, openConsoleAndEvaluate: (input: string) => void, highlightDomElement: (grip: Object) => void, unHighlightDomElement: (grip: Object) => void, getToolboxStore: () => any, + panelWin: Object, |};
--- a/devtools/client/debugger/src/components/App.js +++ b/devtools/client/debugger/src/components/App.js @@ -53,24 +53,27 @@ import PrimaryPanes from "./PrimaryPanes import Editor from "./Editor"; import SecondaryPanes from "./SecondaryPanes"; import WelcomeBox from "./WelcomeBox"; import EditorTabs from "./Editor/Tabs"; import EditorFooter from "./Editor/Footer"; import QuickOpenModal from "./QuickOpenModal"; import WhyPaused from "./SecondaryPanes/WhyPaused"; -type OwnProps = {||}; +type OwnProps = { + toolboxDoc: Object, +}; type Props = { selectedSource: ?Source, orientation: OrientationType, startPanelCollapsed: boolean, endPanelCollapsed: boolean, activeSearch: ?ActiveSearchType, quickOpenEnabled: boolean, + toolboxDoc: Object, setActiveSearch: typeof actions.setActiveSearch, closeActiveSearch: typeof actions.closeActiveSearch, closeProjectSearch: typeof actions.closeProjectSearch, openQuickOpen: typeof actions.openQuickOpen, closeQuickOpen: typeof actions.closeQuickOpen, setOrientation: typeof actions.setOrientation, }; @@ -93,19 +96,23 @@ class App extends Component<Props, State super(props); this.state = { shortcutsModalEnabled: false, startPanelSize: 0, endPanelSize: 0, }; } - getChildContext = () => { - return { shortcuts, l10n: L10N }; - }; + getChildContext() { + return { + toolboxDoc: this.props.toolboxDoc, + shortcuts, + l10n: L10N, + }; + } componentDidMount() { horizontalLayoutBreakpoint.addListener(this.onLayoutChange); verticalLayoutBreakpoint.addListener(this.onLayoutChange); this.setOrientation(); shortcuts.on(L10N.getStr("symbolSearch.search.key2"), (_, e) => this.toggleQuickOpenModal(_, e, "@") @@ -326,16 +333,17 @@ class App extends Component<Props, State {this.renderShortcutsModal()} </A11yIntention> </div> ); } } App.childContextTypes = { + toolboxDoc: PropTypes.object, shortcuts: PropTypes.object, l10n: PropTypes.object, }; const mapStateToProps = state => ({ selectedSource: getSelectedSource(state), startPanelCollapsed: getPaneCollapse(state, "start"), endPanelCollapsed: getPaneCollapse(state, "end"),
--- a/devtools/client/debugger/src/components/SecondaryPanes/CommandBar.js +++ b/devtools/client/debugger/src/components/SecondaryPanes/CommandBar.js @@ -4,33 +4,40 @@ // @flow import PropTypes from "prop-types"; import React, { Component } from "react"; import { connect } from "../../utils/connect"; import classnames from "classnames"; -import { features } from "../../utils/prefs"; +import { features, javascriptPrefs } from "../../utils/prefs"; import { getIsWaitingOnBreak, getSkipPausing, getCurrentThread, isTopFrameSelected, getThreadContext, } from "../../selectors"; import { formatKeyShortcut } from "../../utils/text"; import actions from "../../actions"; import { debugBtn } from "../shared/Button/CommandBarButton"; import AccessibleImage from "../shared/AccessibleImage"; import "./CommandBar.css"; import { appinfo } from "devtools-services"; import type { ThreadContext } from "../../types"; +// $FlowIgnore +const MenuButton = require("devtools/client/shared/components/menu/MenuButton"); +// $FlowIgnore +const MenuItem = require("devtools/client/shared/components/menu/MenuItem"); +// $FlowIgnore +const MenuList = require("devtools/client/shared/components/menu/MenuList"); + const isMacOS = appinfo.OS === "Darwin"; // NOTE: the "resume" command will call either the resume or breakOnNext action // depending on whether or not the debugger is paused or running const COMMANDS = ["resume", "stepOver", "stepIn", "stepOut"]; type CommandActionType = "resume" | "stepOver" | "stepIn" | "stepOut"; const KEYS = { @@ -223,33 +230,67 @@ class CommandBar extends Component<Props } onClick={toggleSkipPausing} > <AccessibleImage className="disable-pausing" /> </button> ); } + renderSettingsButton() { + const { toolboxDoc } = this.context; + + return ( + <MenuButton + menuId="debugger-settings-menu-button" + toolboxDoc={toolboxDoc} + className="devtools-button command-bar-button debugger-settings-menu-button" + title={L10N.getStr("settings.label")} + > + {() => this.renderSettingsMenuItems()} + </MenuButton> + ); + } + + renderSettingsMenuItems() { + return ( + <MenuList id="debugger-settings-menu-list"> + <MenuItem + key="debugger-settings-menu-item-disable-javascript" + className="menu-item debugger-settings-menu-item-disable-javascript" + checked={!javascriptPrefs.enableJavaScript} + label={L10N.getStr("settings.disableJavaScript.label")} + tooltip={L10N.getStr("settings.disableJavaScript.tooltip")} + onClick={() => { + javascriptPrefs.enableJavaScript = !javascriptPrefs.enableJavaScript; + }} + /> + </MenuList> + ); + } + render() { return ( <div className={classnames("command-bar", { vertical: !this.props.horizontal, })} > {this.renderStepButtons()} <div className="filler" /> {this.renderSkipPausingButton()} + {this.renderSettingsButton()} </div> ); } } CommandBar.contextTypes = { shortcuts: PropTypes.object, + toolboxDoc: PropTypes.object, }; const mapStateToProps = state => ({ cx: getThreadContext(state), isWaitingOnBreak: getIsWaitingOnBreak(state, getCurrentThread(state)), skipPausing: getSkipPausing(state), topFrameSelected: isTopFrameSelected(state, getCurrentThread(state)), });
--- a/devtools/client/debugger/src/components/shared/Button/styles/CommandBarButton.css +++ b/devtools/client/debugger/src/components/shared/Button/styles/CommandBarButton.css @@ -14,26 +14,40 @@ min-width: 30px; } .command-bar-button:disabled { opacity: 0.6; cursor: default; } -.command-bar-button:not(.disabled):hover { +.command-bar-button:not(.disabled):hover, +.devtools-button.debugger-settings-menu-button:empty:not(:disabled):not([aria-expanded="true"]):hover { background: var(--theme-toolbar-background-hover); } -.theme-dark .command-bar-button:not(.disabled):hover { +.theme-dark .command-bar-button:not(.disabled):hover, +.devtools-button.debugger-settings-menu-button:empty:not(:disabled):not([aria-expanded="true"]):hover { background: var(--theme-toolbar-hover); } :root.theme-dark .command-bar-button { color: var(--theme-body-color); } .command-bar-button > * { width: 16px; height: 16px; display: inline-block; vertical-align: middle; } + +/** + * Settings icon and menu + */ +.devtools-button.debugger-settings-menu-button { + border-radius: 0; + margin: 0; +} + +.devtools-button.debugger-settings-menu-button::before { + background-image: url("chrome://devtools/skin/images/settings.svg"); +}
--- a/devtools/client/debugger/src/main.development.js +++ b/devtools/client/debugger/src/main.development.js @@ -28,10 +28,11 @@ bootstrap(React, ReactDOM).then(connecti openConsoleAndEvaluate: input => alert(`console.log: ${input}`), highlightDomElement: (grip: Object) => console.log("highlighting dom element"), unHighlightDomElement: (grip: Object) => console.log("unhighlighting dom element"), getToolboxStore: () => { throw new Error("Cannot connect to Toolbox store when running Launchpad"); }, + panelWin: window, }); });
new file mode 100644 --- /dev/null +++ b/devtools/client/debugger/src/test/fixtures/Chrome.js @@ -0,0 +1,10 @@ +/* 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"; + +module.exports = { + Cu: {}, + components: {}, +};
new file mode 100644 --- /dev/null +++ b/devtools/client/debugger/src/test/fixtures/ChromeUtils.js @@ -0,0 +1,7 @@ +/* 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"; + +module.exports = {};
--- a/devtools/client/debugger/src/test/fixtures/Services.js +++ b/devtools/client/debugger/src/test/fixtures/Services.js @@ -1,9 +1,11 @@ /* 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"; module.exports = { appinfo: "", + prefs: { getBoolPref: () => {}, addObserver: () => {} }, + obs: { addObserver: () => {} }, };
--- a/devtools/client/debugger/src/test/tests-setup.js +++ b/devtools/client/debugger/src/test/tests-setup.js @@ -3,17 +3,16 @@ * file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */ // @flow // $FlowIgnore global.Worker = require("workerjs"); import path from "path"; -// import getConfig from "../../bin/getConfig"; import { readFileSync } from "fs"; import Enzyme from "enzyme"; // $FlowIgnore import Adapter from "enzyme-adapter-react-16"; import { setupHelper } from "../utils/dbg"; import { prefs } from "../utils/prefs"; import { startSourceMapWorker, stopSourceMapWorker } from "devtools-source-map"; @@ -46,16 +45,53 @@ function getL10nBundle() { } } global.DebuggerConfig = {}; global.L10N = require("devtools-launchpad").L10N; global.L10N.setBundle(getL10nBundle()); global.jasmine.DEFAULT_TIMEOUT_INTERVAL = 20000; global.performance = { now: () => 0 }; +global.isWorker = false; + +global.define = function() {}; +global.loader = { + lazyServiceGetter: () => {}, + lazyGetter: (context, name, fn) => { + try { + global[name] = fn(); + } catch (_) {} + }, + lazyRequireGetter: (context, name, _path, destruct) => { + if ( + !_path || + _path.startsWith("resource://") || + _path.match(/server\/actors/) + ) { + return; + } + + const excluded = [ + "Debugger", + "devtools/shared/event-emitter", + "devtools/client/shared/autocomplete-popup", + "devtools/client/framework/devtools", + "devtools/client/shared/keycodes", + "devtools/client/shared/sourceeditor/editor", + "devtools/client/shared/telemetry", + "devtools/shared/screenshot/save", + "devtools/client/shared/focus", + ]; + if (!excluded.includes(_path)) { + // $FlowIgnore + const module = require(_path); + global[name] = destruct ? module[name] : module; + } + }, +}; const { URL } = require("url"); global.URL = URL; global.indexedDB = mockIndexeddDB(); Enzyme.configure({ adapter: new Adapter() });
--- a/devtools/client/debugger/src/utils/bootstrap.js +++ b/devtools/client/debugger/src/utils/bootstrap.js @@ -37,24 +37,26 @@ function renderPanel(component, store, p root.className = "launchpad-root theme-body"; root.style.setProperty("flex", "1"); const mount = document.querySelector("#mount"); if (!mount) { return; } mount.appendChild(root); + const toolboxDoc = panel.panelWin.parent.document; + ReactDOM.render( React.createElement( Provider, { store }, React.createElement( ToolboxProvider, { store: panel.getToolboxStore() }, - React.createElement(component) + React.createElement(component, { toolboxDoc }) ) ), root ); } type Workers = { sourceMaps: typeof SourceMaps,
--- a/devtools/client/debugger/src/utils/prefs.js +++ b/devtools/client/debugger/src/utils/prefs.js @@ -72,16 +72,17 @@ if (isDevelopment()) { pref("devtools.debugger.features.event-listeners-breakpoints", true); pref("devtools.debugger.features.dom-mutation-breakpoints", true); pref("devtools.debugger.features.log-points", true); pref("devtools.debugger.features.inline-preview", true); pref("devtools.debugger.features.overlay-step-buttons", true); pref("devtools.debugger.features.watchpoints", true); pref("devtools.debugger.features.frame-step", true); pref("devtools.editor.tabsize", 2); + pref("javascript.enabled", true); } export const prefs = new PrefsHelper("devtools", { fission: ["Bool", "browsertoolbox.fission"], logging: ["Bool", "debugger.logging"], editorWrapping: ["Bool", "debugger.ui.editor-wrapping"], alphabetizeOutline: ["Bool", "debugger.alphabetize-outline"], autoPrettyPrint: ["Bool", "debugger.auto-pretty-print"], @@ -116,16 +117,20 @@ export const prefs = new PrefsHelper("de projectDirectoryRoot: ["Char", "debugger.project-directory-root", ""], skipPausing: ["Bool", "debugger.skip-pausing"], mapScopes: ["Bool", "debugger.map-scopes-enabled"], logActions: ["Bool", "debugger.log-actions"], logEventBreakpoints: ["Bool", "debugger.log-event-breakpoints"], indentSize: ["Int", "editor.tabsize"], }); +export const javascriptPrefs = new PrefsHelper("javascript", { + enableJavaScript: ["Bool", "enabled"], +}); + // The pref may not be defined. Defaulting to null isn't viable (cursor never blinks). // Can't use CodeMirror.defaults here because it's loaded later. // Hardcode the fallback value to that of CodeMirror.defaults.cursorBlinkRate. prefs.cursorBlinkRate = Services.prefs.getIntPref("ui.caretBlinkTime", 530); export const features = new PrefsHelper("devtools.debugger.features", { asyncStepping: ["Bool", "async-stepping"], wasm: ["Bool", "wasm"],
--- a/devtools/client/debugger/test/mochitest/browser.ini +++ b/devtools/client/debugger/test/mochitest/browser.ini @@ -198,8 +198,9 @@ skip-if = (os == 'linux' && debug) || (o skip-if = debug [browser_dbg-toolbox-unselected-pause.js] skip-if = asan # Bug 1591064 [browser_dbg-toolbox-workers.js] skip-if = asan || !nightly_build # Bug 1591064, parent intercept mode is needed bug 1588154 [browser_dbg-wrong-fetch.js] [browser_dbg-worker-nested.js] [browser_dbg-step-in-navigate.js] +[browser_dbg-settings-disable-javascript.js]
new file mode 100644 --- /dev/null +++ b/devtools/client/debugger/test/mochitest/browser_dbg-settings-disable-javascript.js @@ -0,0 +1,36 @@ +/* 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/>. */ + +async function toggleJavaScript(dbg, shouldBeCheckedAtStart) { + const menuItemClassName = ".debugger-settings-menu-item-disable-javascript"; + + const menuButton = findElementWithSelector(dbg, ".debugger-settings-menu-button"); + menuButton.click(); + + // Wait for the menu to show before trying to click the item + const { parent } = dbg.panel.panelWin; + const { document } = parent; + + const menuItem = document.querySelector(menuItemClassName); + is( + !!menuItem.getAttribute("aria-checked"), + shouldBeCheckedAtStart, + "Item is checked before clicking" + ); + menuItem.click(); +} + +// Tests that using the Settings menu to enable and disable JavaScript +// updates the pref properly +add_task(async function() { + const dbg = await initDebugger("doc-scripts.html", "simple1.js"); + + info("Clicking the disable javascript button in the settings menu"); + await toggleJavaScript(dbg, false); + is(Services.prefs.getBoolPref("javascript.enabled"), false, "JavaScript is disabled"); + + info("Clicking the disable javascript button in the settings menu to reenable JavaScript"); + await toggleJavaScript(dbg, true); + is(Services.prefs.getBoolPref("javascript.enabled"), true, "JavaScript is enabled"); +});
--- a/devtools/client/debugger/test/mochitest/helpers.js +++ b/devtools/client/debugger/test/mochitest/helpers.js @@ -576,16 +576,17 @@ async function clearDebuggerPreferences( Services.prefs.clearUserPref("devtools.debugger.ignore-caught-exceptions"); Services.prefs.clearUserPref("devtools.debugger.pending-selected-location"); Services.prefs.clearUserPref("devtools.debugger.expressions"); Services.prefs.clearUserPref("devtools.debugger.breakpoints-visible"); Services.prefs.clearUserPref("devtools.debugger.call-stack-visible"); Services.prefs.clearUserPref("devtools.debugger.scopes-visible"); Services.prefs.clearUserPref("devtools.debugger.skip-pausing"); Services.prefs.clearUserPref("devtools.debugger.map-scopes-enabled"); + Services.prefs.clearUserPref("javascript.enabled"); await pushPref("devtools.debugger.log-actions", true); for (const pref of prefs) { await pushPref(...pref); } } /** * Intilializes the debugger.
--- a/devtools/client/locales/en-US/debugger.properties +++ b/devtools/client/locales/en-US/debugger.properties @@ -474,16 +474,27 @@ downloadFile.accesskey=d # LOCALIZATION NOTE (inlinePreview.show.label): Context menu item # for showing the inline preview blocks inlinePreview.show.label=Show inline preview # LOCALIZATION NOTE (inlinePreview.hide.label): Context menu item # for hiding the inline preview block inlinePreview.hide.label=Hide inline preview +# LOCALIZATION NOTE (settings.label): Label for Settings button +settings.label=Debugger Settings + +# LOCALIZATION NOTE (settings.disableJavaScript.label): Context menu item +# tooltip for disabling JavaScript +settings.disableJavaScript.label=Disable JavaScript + +# LOCALIZATION NOTE (settings.disableJavaScript.tooltip): Context menu item +# tooltip for disabling JavaScript +settings.disableJavaScript.tooltip=Disables JavaScript in the current tab (Requires refresh) + # LOCALIZATION NOTE (preview.noProperties): Label shown in the preview # popup when there are no properties to show. preview.noProperties=No properties # LOCALIZATION NOTE (framework.disableGrouping): This is the text that appears in the # context menu to disable framework grouping. framework.disableGrouping=Disable framework grouping framework.disableGrouping.accesskey=u