From 5cb8b24f196c4ac146b01f4efc3aec2b54ab940c Mon Sep 17 00:00:00 2001 From: Jason Laster Date: Tue, 17 Sep 2019 21:17:58 +0000 Subject: [PATCH] Bug 1110276 - Log on Events (UI). r=davidwalsh Differential Revision: https://phabricator.services.mozilla.com/D46077 --HG-- extra : moz-landing-system : lando --- .../debugger/src/actions/event-listeners.js | 9 +++++++ .../debugger/src/actions/types/index.js | 4 +++ .../client/debugger/src/client/firefox.js | 2 +- .../debugger/src/client/firefox/commands.js | 7 +++++ .../src/components/SecondaryPanes/index.js | 27 ++++++++++++++++++- .../debugger/src/reducers/event-listeners.js | 14 ++++++++++ devtools/client/debugger/src/utils/dbg.js | 2 +- devtools/client/debugger/src/utils/prefs.js | 6 ++--- .../debugger/test/mochitest/browser.ini | 1 + .../browser_dbg-event-breakpoints.js | 14 +++++++--- .../test/mochitest/browser_dbg-log-events.js | 23 ++++++++++++++++ .../mochitest/examples/event-breakpoints.js | 13 ++++----- .../client/debugger/test/mochitest/helpers.js | 14 +++++++++- devtools/client/framework/toolbox.js | 2 +- .../client/locales/en-US/debugger.properties | 7 +++++ devtools/client/preferences/debugger.js | 2 +- devtools/server/actors/thread.js | 6 +++++ devtools/shared/specs/thread.js | 6 +++++ 18 files changed, 138 insertions(+), 21 deletions(-) create mode 100644 devtools/client/debugger/test/mochitest/browser_dbg-log-events.js diff --git a/devtools/client/debugger/src/actions/event-listeners.js b/devtools/client/debugger/src/actions/event-listeners.js index 187596fea68c..e2112ff763da 100644 --- a/devtools/client/debugger/src/actions/event-listeners.js +++ b/devtools/client/debugger/src/actions/event-listeners.js @@ -9,6 +9,7 @@ import { uniq, remove } from "lodash"; import { getActiveEventListeners, getEventListenerExpanded, + shouldLogEventBreakpoints, } from "../selectors"; import type { ThunkArgs } from "./types"; @@ -48,6 +49,14 @@ export function removeEventListenerBreakpoints(eventsToRemove: string[]) { }; } +export function toggleEventLogging() { + return async ({ dispatch, getState, client }: ThunkArgs) => { + const logEventBreakpoints = !shouldLogEventBreakpoints(getState()); + await client.toggleEventLogging(logEventBreakpoints); + dispatch({ type: "TOGGLE_EVENT_LISTENERS", logEventBreakpoints }); + }; +} + export function addEventListenerExpanded(category: string) { return async ({ dispatch, getState }: ThunkArgs) => { const expanded = await getEventListenerExpanded(getState()); diff --git a/devtools/client/debugger/src/actions/types/index.js b/devtools/client/debugger/src/actions/types/index.js index 1d53647c4fc5..17d86b23a1ec 100644 --- a/devtools/client/debugger/src/actions/types/index.js +++ b/devtools/client/debugger/src/actions/types/index.js @@ -181,6 +181,10 @@ export type EventListenerAction = | {| +type: "UPDATE_EVENT_LISTENER_EXPANDED", +expanded: EventListenerExpandedList, + |} + | {| + +type: "TOGGLE_EVENT_LISTENERS", + +logEventBreakpoints: boolean, |}; /** diff --git a/devtools/client/debugger/src/client/firefox.js b/devtools/client/debugger/src/client/firefox.js index 7176b9850609..dce2905cec0e 100644 --- a/devtools/client/debugger/src/client/firefox.js +++ b/devtools/client/debugger/src/client/firefox.js @@ -45,7 +45,7 @@ export async function onConnect(connection: any, actions: Object) { pauseWorkersUntilAttach: true, wasmBinarySource: supportsWasm, skipBreakpoints: prefs.skipPausing, - logEventBreakpoints: features.logEventBreakpoints, + logEventBreakpoints: prefs.logEventBreakpoints, }); // Retrieve possible event listener breakpoints diff --git a/devtools/client/debugger/src/client/firefox/commands.js b/devtools/client/debugger/src/client/firefox/commands.js index a3c12ccaea48..cb9d6c388b9b 100644 --- a/devtools/client/debugger/src/client/firefox/commands.js +++ b/devtools/client/debugger/src/client/firefox/commands.js @@ -419,6 +419,12 @@ async function getSources( return sources.map(source => prepareSourcePayload(client, source)); } +async function toggleEventLogging(logEventBreakpoints: boolean) { + return forEachThread(thread => + thread.toggleEventLogging(logEventBreakpoints) + ); +} + async function fetchSources(): Promise> { return getSources(currentThreadFront); } @@ -544,6 +550,7 @@ const clientCommands = { getProperties, getFrameScopes, pauseOnExceptions, + toggleEventLogging, fetchSources, registerSourceActor, fetchThreads, diff --git a/devtools/client/debugger/src/components/SecondaryPanes/index.js b/devtools/client/debugger/src/components/SecondaryPanes/index.js index 65d9de282149..8b50b75909b0 100644 --- a/devtools/client/debugger/src/components/SecondaryPanes/index.js +++ b/devtools/client/debugger/src/components/SecondaryPanes/index.js @@ -27,6 +27,7 @@ import { getThreadContext, getSourceFromId, getSkipPausing, + shouldLogEventBreakpoints, } from "../../selectors"; import AccessibleImage from "../shared/AccessibleImage"; @@ -99,6 +100,7 @@ type Props = { shouldPauseOnCaughtExceptions: boolean, workers: ThreadList, skipPausing: boolean, + logEventBreakpoints: boolean, source: ?Source, toggleShortcutsModal: () => void, toggleAllBreakpoints: typeof actions.toggleAllBreakpoints, @@ -106,6 +108,7 @@ type Props = { evaluateExpressions: typeof actions.evaluateExpressions, pauseOnExceptions: typeof actions.pauseOnExceptions, breakOnNext: typeof actions.breakOnNext, + toggleEventLogging: typeof actions.toggleEventLogging, }; const mdnLink = @@ -277,6 +280,26 @@ class SecondaryPanes extends Component { ]; } + getEventButtons() { + const { logEventBreakpoints } = this.props; + return [ +
+ +
, + ]; + } + getWatchItem(): AccordionPaneItem { return { header: L10N.getStr("watchExpressions.header"), @@ -366,7 +389,7 @@ class SecondaryPanes extends Component { return { header: L10N.getStr("eventListenersHeader1"), className: "event-listeners-pane", - buttons: [], + buttons: this.getEventButtons(), component: , opened: prefs.eventListenersVisible, onToggle: opened => { @@ -540,6 +563,7 @@ const mapStateToProps = state => { shouldPauseOnCaughtExceptions: getShouldPauseOnCaughtExceptions(state), workers: getThreads(state), skipPausing: getSkipPausing(state), + logEventBreakpoints: shouldLogEventBreakpoints(state), source: selectedFrame && getSourceFromId(state, selectedFrame.location.sourceId), }; @@ -553,5 +577,6 @@ export default connect( pauseOnExceptions: actions.pauseOnExceptions, toggleMapScopes: actions.toggleMapScopes, breakOnNext: actions.breakOnNext, + toggleEventLogging: actions.toggleEventLogging, } )(SecondaryPanes); diff --git a/devtools/client/debugger/src/reducers/event-listeners.js b/devtools/client/debugger/src/reducers/event-listeners.js index f23968c93eed..9aaeeef3dcdc 100644 --- a/devtools/client/debugger/src/reducers/event-listeners.js +++ b/devtools/client/debugger/src/reducers/event-listeners.js @@ -4,6 +4,8 @@ // @flow +import { prefs } from "../utils/prefs"; + import type { State } from "./types"; import type { EventListenerAction, @@ -16,6 +18,7 @@ export type EventListenersState = {| +active: EventListenerActiveList, +categories: EventListenerCategoryList, +expanded: EventListenerExpandedList, + +logEventBreakpoints: boolean, |}; export function initialEventListenerState(): EventListenersState { @@ -23,6 +26,7 @@ export function initialEventListenerState(): EventListenersState { active: [], categories: [], expanded: [], + logEventBreakpoints: prefs.logEventBreakpoints, }; } @@ -40,6 +44,12 @@ function update( case "UPDATE_EVENT_LISTENER_EXPANDED": return { ...state, expanded: action.expanded }; + case "TOGGLE_EVENT_LISTENERS": { + const { logEventBreakpoints } = action; + prefs.logEventBreakpoints = logEventBreakpoints; + return { ...state, logEventBreakpoints }; + } + default: return state; } @@ -61,4 +71,8 @@ export function getEventListenerExpanded( return state.eventListenerBreakpoints.expanded; } +export function shouldLogEventBreakpoints(state: State) { + return state.eventListenerBreakpoints.logEventBreakpoints; +} + export default update; diff --git a/devtools/client/debugger/src/utils/dbg.js b/devtools/client/debugger/src/utils/dbg.js index e81b433fafc0..d84981812697 100644 --- a/devtools/client/debugger/src/utils/dbg.js +++ b/devtools/client/debugger/src/utils/dbg.js @@ -88,7 +88,7 @@ export function setupHelper(obj: Object) { evaluate: expression => evaluate(dbg, expression), sendPacketToThread: packet => sendPacketToThread(dbg, packet), sendPacket: packet => sendPacket(dbg, packet), - dumpThread: () => sendPacketToThread(dbg, { type: "dumpThread" }), + dumpThread: () => dbg.connection.tabConnection.threadFront.dumpThread(), getDocument: url => getDocumentForUrl(dbg, url), }, formatters: { diff --git a/devtools/client/debugger/src/utils/prefs.js b/devtools/client/debugger/src/utils/prefs.js index 7254a547870f..2d2fee2846ce 100644 --- a/devtools/client/debugger/src/utils/prefs.js +++ b/devtools/client/debugger/src/utils/prefs.js @@ -48,6 +48,8 @@ if (isDevelopment()) { pref("devtools.debugger.map-scopes-enabled", false); pref("devtools.debugger.prefs-schema-version", prefsSchemaVersion); pref("devtools.debugger.skip-pausing", false); + pref("devtools.debugger.log-actions", true); + pref("devtools.debugger.log-event-breakpoints", false); pref("devtools.debugger.features.workers", true); pref("devtools.debugger.features.async-stepping", false); pref("devtools.debugger.features.wasm", true); @@ -69,9 +71,7 @@ if (isDevelopment()) { 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.log-actions", true); pref("devtools.debugger.features.overlay-step-buttons", true); - pref("devtools.debugger.features.log-event-breakpoints", false); pref("devtools.debugger.features.watchpoints", false); } @@ -114,6 +114,7 @@ export const prefs = new PrefsHelper("devtools", { skipPausing: ["Bool", "debugger.skip-pausing"], mapScopes: ["Bool", "debugger.map-scopes-enabled"], logActions: ["Bool", "debugger.log-actions"], + logEventBreakpoints: ["Bool", "debugger.log-event-breakpoints"], }); export const features = new PrefsHelper("devtools.debugger.features", { @@ -140,7 +141,6 @@ export const features = new PrefsHelper("devtools.debugger.features", { logPoints: ["Bool", "log-points"], showOverlayStepButtons: ["Bool", "overlay-step-buttons"], inlinePreview: ["Bool", "inline-preview"], - logEventBreakpoints: ["Bool", "log-event-breakpoints"], watchpoints: ["Bool", "watchpoints"], }); diff --git a/devtools/client/debugger/test/mochitest/browser.ini b/devtools/client/debugger/test/mochitest/browser.ini index fe3c35d98666..5eae8acd40c1 100644 --- a/devtools/client/debugger/test/mochitest/browser.ini +++ b/devtools/client/debugger/test/mochitest/browser.ini @@ -79,6 +79,7 @@ skip-if = ccov && os == 'win' # Bug 1443132 [browser_dbg-keyboard-shortcuts.js] skip-if = os == "linux" # bug 1351952 [browser_dbg-layout-changes.js] +[browser_dbg-log-events.js] [browser_dbg-log-points.js] [browser_dbg-outline.js] skip-if = verify diff --git a/devtools/client/debugger/test/mochitest/browser_dbg-event-breakpoints.js b/devtools/client/debugger/test/mochitest/browser_dbg-event-breakpoints.js index fdb0fc97880f..9ca65a6f795b 100644 --- a/devtools/client/debugger/test/mochitest/browser_dbg-event-breakpoints.js +++ b/devtools/client/debugger/test/mochitest/browser_dbg-event-breakpoints.js @@ -14,9 +14,15 @@ function assertPauseLocation(dbg, line) { } add_task(async function() { - await pushPref("devtools.debugger.features.event-listeners-breakpoints", true); + await pushPref( + "devtools.debugger.features.event-listeners-breakpoints", + true + ); - const dbg = await initDebugger("doc-event-breakpoints.html", "event-breakpoints"); + const dbg = await initDebugger( + "doc-event-breakpoints.html", + "event-breakpoints" + ); await selectSource(dbg, "event-breakpoints"); await waitForSelectedSource(dbg, "event-breakpoints"); @@ -43,6 +49,6 @@ add_task(async function() { await resume(dbg); await waitForPaused(dbg); - assertPauseLocation(dbg, 29); + assertPauseLocation(dbg, 28); await resume(dbg); -}); \ No newline at end of file +}); diff --git a/devtools/client/debugger/test/mochitest/browser_dbg-log-events.js b/devtools/client/debugger/test/mochitest/browser_dbg-log-events.js new file mode 100644 index 000000000000..f3c1cfbca838 --- /dev/null +++ b/devtools/client/debugger/test/mochitest/browser_dbg-log-events.js @@ -0,0 +1,23 @@ +/* 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 . */ + +/* + * Tests that we can log event listeners calls + */ + +add_task(async function() { + Services.prefs.setBoolPref("devtools.toolbox.splitconsoleEnabled", true); + const dbg = await initDebugger( + "doc-event-breakpoints.html", + "event-breakpoints.js" + ); + + await clickElement(dbg, "logEventsCheckbox"); + await dbg.actions.addEventListenerBreakpoints(["event.mouse.click"]); + clickElementInTab("#click-target"); + + await hasConsoleMessage(dbg, "click"); + await waitForRequestsToSettle(dbg); + ok(true); +}); diff --git a/devtools/client/debugger/test/mochitest/examples/event-breakpoints.js b/devtools/client/debugger/test/mochitest/examples/event-breakpoints.js index 97e7864c577b..8bbdd090a2d4 100644 --- a/devtools/client/debugger/test/mochitest/examples/event-breakpoints.js +++ b/devtools/client/debugger/test/mochitest/examples/event-breakpoints.js @@ -16,7 +16,7 @@ document.getElementById("xhr-button").onmousedown = xhrHandler; function xhrHandler() { var xhr = new XMLHttpRequest(); xhr.open("GET", "doc-event-breakpoints.html", true); - xhr.onload = function(){ + xhr.onload = function() { console.log("xhr load"); }; xhr.send(); @@ -24,11 +24,8 @@ function xhrHandler() { document.getElementById("timer-button").onmousedown = timerHandler; function timerHandler() { - setTimeout( - () => { - console.log("timer callback"); - }, - 50 - ); + setTimeout(() => { + console.log("timer callback"); + }, 50); console.log("timer set"); -} \ No newline at end of file +} diff --git a/devtools/client/debugger/test/mochitest/helpers.js b/devtools/client/debugger/test/mochitest/helpers.js index c919c0bbf6f0..634ded32bc00 100644 --- a/devtools/client/debugger/test/mochitest/helpers.js +++ b/devtools/client/debugger/test/mochitest/helpers.js @@ -1036,6 +1036,17 @@ function invokeInTab(fnc, ...args) { }); } + +function clickElementInTab(selector) { + info(`click element ${selector} in tab`); + + return ContentTask.spawn(gBrowser.selectedBrowser, { selector }, function*({ + selector + }) { + content.wrappedJSObject.document.querySelector(selector).click(); + }); +} + const isLinux = Services.appinfo.OS === "Linux"; const isMac = Services.appinfo.OS === "Darwin"; const cmdOrCtrl = isLinux ? { ctrlKey: true } : { metaKey: true }; @@ -1293,7 +1304,8 @@ const selectors = { inlinePreviewOpenInspector: ".inline-preview-value button.open-inspector", addGetWatchpoint: "#node-menu-add-get-watchpoint", addSetWatchpoint: "#node-menu-add-set-watchpoint", - removeWatchpoint: "#node-menu-remove-watchpoint" + removeWatchpoint: "#node-menu-remove-watchpoint", + logEventsCheckbox: ".events-header input", }; function getSelector(elementName, ...args) { diff --git a/devtools/client/framework/toolbox.js b/devtools/client/framework/toolbox.js index 0c98ed951efa..a84461df1f31 100644 --- a/devtools/client/framework/toolbox.js +++ b/devtools/client/framework/toolbox.js @@ -598,7 +598,7 @@ Toolbox.prototype = { "devtools.debugger.skip-pausing" ), logEventBreakpoints: Services.prefs.getBoolPref( - "devtools.debugger.features.log-event-breakpoints" + "devtools.debugger.log-event-breakpoints" ), }); diff --git a/devtools/client/locales/en-US/debugger.properties b/devtools/client/locales/en-US/debugger.properties index bf443d8a2792..6e7d794b7af7 100644 --- a/devtools/client/locales/en-US/debugger.properties +++ b/devtools/client/locales/en-US/debugger.properties @@ -583,6 +583,13 @@ scopes.notPaused=Not paused # tooltip for checkbox and label scopes.mapping.label=Map original variable names +# LOCALIZATION NOTE (eventlisteners.log.label): Event listeners tooltip for +# checkbox and label +eventlisteners.log.label=Log events to the console + +# LOCALIZATION NOTE (eventlisteners.log): Checkbox label for logging events +eventlisteners.log=Log + # LOCALIZATION NOTE (scopes.helpTooltip.label): Scopes right sidebar pane # icon tooltip for link to MDN scopes.helpTooltip.label=Learn more about map scopes diff --git a/devtools/client/preferences/debugger.js b/devtools/client/preferences/debugger.js index 7601bb2be143..601c92723fcd 100644 --- a/devtools/client/preferences/debugger.js +++ b/devtools/client/preferences/debugger.js @@ -60,6 +60,7 @@ pref("devtools.debugger.skip-pausing", false); pref("devtools.debugger.logging", false); pref("devtools.debugger.map-scopes-enabled", false); pref("devtools.debugger.log-actions", false); +pref("devtools.debugger.log-event-breakpoints", false); pref("devtools.debugger.features.wasm", true); pref("devtools.debugger.features.shortcuts", true); @@ -85,5 +86,4 @@ pref("devtools.debugger.features.log-points", true); pref("devtools.debugger.features.overlay-step-buttons", false); pref("devtools.debugger.features.overlay-step-buttons", true); pref("devtools.debugger.features.inline-preview", true); -pref("devtools.debugger.features.log-event-breakpoints", false); pref("devtools.debugger.features.watchpoints", false); diff --git a/devtools/server/actors/thread.js b/devtools/server/actors/thread.js index c8a0d2bdc8ff..ed2002e228ad 100644 --- a/devtools/server/actors/thread.js +++ b/devtools/server/actors/thread.js @@ -406,6 +406,11 @@ const ThreadActor = ActorClassWithSpec(threadSpec, { } }, + toggleEventLogging(logEventBreakpoints) { + this._options.logEventBreakpoints = logEventBreakpoints; + return this._options.logEventBreakpoints; + }, + _setBreakpointsOnAttach(breakpoints) { for (const { location, options } of Object.values(breakpoints)) { this.setBreakpoint(location, options); @@ -2082,6 +2087,7 @@ const ThreadActor = ActorClassWithSpec(threadSpec, { return { pauseOnExceptions: this._options.pauseOnExceptions, ignoreCaughtExceptions: this._options.ignoreCaughtExceptions, + logEventBreakpoints: this._options.logEventBreakpoints, skipBreakpoints: this.skipBreakpoints, breakpoints: this.breakpointActorMap.listKeys(), }; diff --git a/devtools/shared/specs/thread.js b/devtools/shared/specs/thread.js index b3bcdcbd64d8..b868a4d44ee7 100644 --- a/devtools/shared/specs/thread.js +++ b/devtools/shared/specs/thread.js @@ -159,6 +159,12 @@ const threadSpec = generateActorSpec({ request: {}, }, + toggleEventLogging: { + request: { + logEventBreakpoints: Arg(0, "string"), + }, + }, + // For testing. debuggerRequests: { response: {