blob: aa8d18fe4dd7c512672ccc291c6c2395f650085e [file] [log] [blame]
Blink Reformat4c46d092018-04-07 15:32:371/*
2 * Copyright (C) 2011 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
6 * met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
13 * distribution.
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30
Tim van der Lippe046db882020-02-13 13:55:1131import * as Common from '../common/common.js';
32import * as SDK from '../sdk/sdk.js';
Jack Franklin536a31d2020-09-25 13:15:2433import * as Sources from '../sources/sources.js';
Tim van der Lippe046db882020-02-13 13:55:1134import * as UI from '../ui/ui.js';
35
Blink Reformat4c46d092018-04-07 15:32:3736/**
Tim van der Lippe046db882020-02-13 13:55:1137 * @implements {UI.ContextFlavorListener.ContextFlavorListener}
38 * @implements {UI.ListControl.ListDelegate<!SDK.DOMDebuggerModel.DOMBreakpoint>}
Blink Reformat4c46d092018-04-07 15:32:3739 */
Tim van der Lippe046db882020-02-13 13:55:1140export class DOMBreakpointsSidebarPane extends UI.Widget.VBox {
Blink Reformat4c46d092018-04-07 15:32:3741 constructor() {
42 super(true);
Jack Franklin71519f82020-11-03 12:08:5943 this.registerRequiredCSS('browser_debugger/domBreakpointsSidebarPane.css', {enableLegacyPatching: true});
Blink Reformat4c46d092018-04-07 15:32:3744
Jack Franklin536a31d2020-09-25 13:15:2445 /** @type {!WeakMap<!Element, !HTMLInputElement>} */
46 this.elementToCheckboxes = new WeakMap();
47
Blink Reformat4c46d092018-04-07 15:32:3748 this._emptyElement = this.contentElement.createChild('div', 'gray-info-message');
Tim van der Lippe046db882020-02-13 13:55:1149 this._emptyElement.textContent = Common.UIString.UIString('No breakpoints');
50 /** @type {!UI.ListModel.ListModel.<!SDK.DOMDebuggerModel.DOMBreakpoint>} */
51 this._breakpoints = new UI.ListModel.ListModel();
52 /** @type {!UI.ListControl.ListControl.<!SDK.DOMDebuggerModel.DOMBreakpoint>} */
53 this._list = new UI.ListControl.ListControl(this._breakpoints, this, UI.ListControl.ListMode.NonViewport);
Jack Lynch8a344762019-12-12 03:17:3854 this.contentElement.appendChild(this._list.element);
55 this._list.element.classList.add('breakpoint-list', 'hidden');
56 UI.ARIAUtils.markAsList(this._list.element);
57 UI.ARIAUtils.setAccessibleName(this._list.element, ls`DOM Breakpoints list`);
58 this._emptyElement.tabIndex = -1;
Blink Reformat4c46d092018-04-07 15:32:3759
Paul Lewisdaac1062020-03-05 14:37:1060 SDK.SDKModel.TargetManager.instance().addModelListener(
Tim van der Lippe046db882020-02-13 13:55:1161 SDK.DOMDebuggerModel.DOMDebuggerModel, SDK.DOMDebuggerModel.Events.DOMBreakpointAdded, this._breakpointAdded,
62 this);
Paul Lewisdaac1062020-03-05 14:37:1063 SDK.SDKModel.TargetManager.instance().addModelListener(
Tim van der Lippe046db882020-02-13 13:55:1164 SDK.DOMDebuggerModel.DOMDebuggerModel, SDK.DOMDebuggerModel.Events.DOMBreakpointToggled,
65 this._breakpointToggled, this);
Paul Lewisdaac1062020-03-05 14:37:1066 SDK.SDKModel.TargetManager.instance().addModelListener(
Tim van der Lippe046db882020-02-13 13:55:1167 SDK.DOMDebuggerModel.DOMDebuggerModel, SDK.DOMDebuggerModel.Events.DOMBreakpointsRemoved,
68 this._breakpointsRemoved, this);
Blink Reformat4c46d092018-04-07 15:32:3769
Paul Lewisdaac1062020-03-05 14:37:1070 for (const domDebuggerModel of SDK.SDKModel.TargetManager.instance().models(
71 SDK.DOMDebuggerModel.DOMDebuggerModel)) {
Blink Reformat4c46d092018-04-07 15:32:3772 domDebuggerModel.retrieveDOMBreakpoints();
Tim van der Lippe1d6e57a2019-09-30 11:55:3473 for (const breakpoint of domDebuggerModel.domBreakpoints()) {
Blink Reformat4c46d092018-04-07 15:32:3774 this._addBreakpoint(breakpoint);
Tim van der Lippe1d6e57a2019-09-30 11:55:3475 }
Blink Reformat4c46d092018-04-07 15:32:3776 }
77
Jack Lynch8a344762019-12-12 03:17:3878 this._highlightedBreakpoint = null;
Blink Reformat4c46d092018-04-07 15:32:3779 this._update();
80 }
81
82 /**
Jack Lynch8a344762019-12-12 03:17:3883 * @override
84 * @param {!SDK.DOMDebuggerModel.DOMBreakpoint} item
85 * @return {!Element}
86 */
87 createElementForItem(item) {
Tim van der Lippef49e2322020-05-01 15:03:0988 const element = document.createElement('div');
89 element.classList.add('breakpoint-entry');
Jack Lynch8a344762019-12-12 03:17:3890 element.addEventListener('contextmenu', this._contextMenu.bind(this, item), true);
91 UI.ARIAUtils.markAsListitem(element);
Christy Chend05ba962020-06-05 23:12:2592 element.tabIndex = -1;
Jack Lynch8a344762019-12-12 03:17:3893
Michael Liaoe7d3fb52020-10-01 21:44:0494 const checkboxLabel = UI.UIUtils.CheckboxLabel.create(/* title */ undefined, item.enabled);
Jack Lynch8a344762019-12-12 03:17:3895 const checkboxElement = checkboxLabel.checkboxElement;
96 checkboxElement.addEventListener('click', this._checkboxClicked.bind(this, item), false);
Christy Chend05ba962020-06-05 23:12:2597 checkboxElement.tabIndex = this._list.selectedItem() === item ? 0 : -1;
Jack Franklin536a31d2020-09-25 13:15:2498 this.elementToCheckboxes.set(element, checkboxElement);
Jack Lynch8a344762019-12-12 03:17:3899 element.appendChild(checkboxLabel);
100
Tim van der Lippef49e2322020-05-01 15:03:09101 const labelElement = document.createElement('div');
102 labelElement.classList.add('dom-breakpoint');
Jack Lynch8a344762019-12-12 03:17:38103 element.appendChild(labelElement);
Jack Franklin536a31d2020-09-25 13:15:24104 const description = document.createElement('div');
Paul Lewis2a4f9fe2020-01-09 15:19:41105 const breakpointTypeLabel = BreakpointTypeLabels.get(item.type);
Jack Franklin536a31d2020-09-25 13:15:24106 description.textContent = breakpointTypeLabel || null;
Michael Liaoe7d3fb52020-10-01 21:44:04107 UI.ARIAUtils.setAccessibleName(checkboxElement, ls`${breakpointTypeLabel}`);
Tim van der Lippe6ab9f462020-05-01 14:22:38108 const linkifiedNode = document.createElement('monospace');
Jack Lynch8a344762019-12-12 03:17:38109 linkifiedNode.style.display = 'block';
110 labelElement.appendChild(linkifiedNode);
Jack Franklin536a31d2020-09-25 13:15:24111 Common.Linkifier.Linkifier.linkify(item.node, {preventKeyboardFocus: true, tooltip: undefined}).then(linkified => {
Jack Lynch8a344762019-12-12 03:17:38112 linkifiedNode.appendChild(linkified);
113 UI.ARIAUtils.setAccessibleName(checkboxElement, ls`${breakpointTypeLabel}: ${linkified.deepTextContent()}`);
114 });
115
116 labelElement.appendChild(description);
117
118 const checkedStateText = item.enabled ? ls`checked` : ls`unchecked`;
119 if (item === this._highlightedBreakpoint) {
120 element.classList.add('breakpoint-hit');
121 UI.ARIAUtils.setDescription(element, ls`${checkedStateText} breakpoint hit`);
Christy Chend05ba962020-06-05 23:12:25122 UI.ARIAUtils.setDescription(checkboxElement, ls`breakpoint hit`);
Jack Lynch8a344762019-12-12 03:17:38123 } else {
124 UI.ARIAUtils.setDescription(element, checkedStateText);
125 }
126
127
128 this._emptyElement.classList.add('hidden');
129 this._list.element.classList.remove('hidden');
130
131 return element;
132 }
133
134 /**
135 * @override
136 * @param {!SDK.DOMDebuggerModel.DOMBreakpoint} item
137 * @return {number}
138 */
139 heightForItem(item) {
140 return 0;
141 }
142
143 /**
144 * @override
145 * @param {!SDK.DOMDebuggerModel.DOMBreakpoint} item
146 * @return {boolean}
147 */
148 isItemSelectable(item) {
149 return true;
150 }
151
152 /**
153 * @override
154 * @param {?Element} fromElement
155 * @param {?Element} toElement
156 * @return {boolean}
157 */
158 updateSelectedItemARIA(fromElement, toElement) {
159 return true;
160 }
161
162 /**
163 * @override
164 * @param {?SDK.DOMDebuggerModel.DOMBreakpoint} from
165 * @param {?SDK.DOMDebuggerModel.DOMBreakpoint} to
166 * @param {?Element} fromElement
167 * @param {?Element} toElement
168 */
169 selectedItemChanged(from, to, fromElement, toElement) {
170 if (fromElement) {
Jack Franklin536a31d2020-09-25 13:15:24171 const fromCheckbox = this.elementToCheckboxes.get(fromElement);
172 if (fromCheckbox) {
173 fromCheckbox.tabIndex = -1;
174 }
Jack Lynch8a344762019-12-12 03:17:38175 }
176
177 if (toElement) {
Jack Franklin536a31d2020-09-25 13:15:24178 const toCheckbox = this.elementToCheckboxes.get(toElement);
179 if (!toCheckbox) {
180 return;
181 }
182
183 this.setDefaultFocusedElement(toCheckbox);
184 toCheckbox.tabIndex = 0;
Jack Lynch8a344762019-12-12 03:17:38185 if (this.hasFocus()) {
Jack Franklin536a31d2020-09-25 13:15:24186 toCheckbox.focus();
Jack Lynch8a344762019-12-12 03:17:38187 }
188 }
189 }
190
191 /**
Tim van der Lippec02a97c2020-02-14 14:39:27192 * @param {!Common.EventTarget.EventTargetEvent} event
Blink Reformat4c46d092018-04-07 15:32:37193 */
194 _breakpointAdded(event) {
195 this._addBreakpoint(/** @type {!SDK.DOMDebuggerModel.DOMBreakpoint} */ (event.data));
196 }
197
198 /**
Tim van der Lippec02a97c2020-02-14 14:39:27199 * @param {!Common.EventTarget.EventTargetEvent} event
Blink Reformat4c46d092018-04-07 15:32:37200 */
201 _breakpointToggled(event) {
Jack Lynch8a344762019-12-12 03:17:38202 const hadFocus = this.hasFocus();
Blink Reformat4c46d092018-04-07 15:32:37203 const breakpoint = /** @type {!SDK.DOMDebuggerModel.DOMBreakpoint} */ (event.data);
Jack Lynch8a344762019-12-12 03:17:38204 this._list.refreshItem(breakpoint);
205 if (hadFocus) {
206 this.focus();
Tim van der Lippe1d6e57a2019-09-30 11:55:34207 }
Blink Reformat4c46d092018-04-07 15:32:37208 }
209
210 /**
Tim van der Lippec02a97c2020-02-14 14:39:27211 * @param {!Common.EventTarget.EventTargetEvent} event
Blink Reformat4c46d092018-04-07 15:32:37212 */
213 _breakpointsRemoved(event) {
Jack Lynch8a344762019-12-12 03:17:38214 const hadFocus = this.hasFocus();
Blink Reformat4c46d092018-04-07 15:32:37215 const breakpoints = /** @type {!Array<!SDK.DOMDebuggerModel.DOMBreakpoint>} */ (event.data);
Jack Lynch8a344762019-12-12 03:17:38216 let lastIndex = -1;
Blink Reformat4c46d092018-04-07 15:32:37217 for (const breakpoint of breakpoints) {
Jack Lynch8a344762019-12-12 03:17:38218 const index = this._breakpoints.indexOf(breakpoint);
219 if (index >= 0) {
220 this._breakpoints.remove(index);
221 lastIndex = index;
Blink Reformat4c46d092018-04-07 15:32:37222 }
223 }
Jack Lynch8a344762019-12-12 03:17:38224 if (this._breakpoints.length === 0) {
Blink Reformat4c46d092018-04-07 15:32:37225 this._emptyElement.classList.remove('hidden');
Jack Lynch8a344762019-12-12 03:17:38226 this.setDefaultFocusedElement(this._emptyElement);
227 this._list.element.classList.add('hidden');
228 } else if (lastIndex >= 0) {
229 const breakpointToSelect = this._breakpoints.at(lastIndex);
230 if (breakpointToSelect) {
231 this._list.selectItem(breakpointToSelect);
232 }
233 }
234 if (hadFocus) {
235 this.focus();
Blink Reformat4c46d092018-04-07 15:32:37236 }
237 }
238
239 /**
240 * @param {!SDK.DOMDebuggerModel.DOMBreakpoint} breakpoint
241 */
242 _addBreakpoint(breakpoint) {
Jack Lynch8a344762019-12-12 03:17:38243 this._breakpoints.insertWithComparator(breakpoint, (breakpointA, breakpointB) => {
244 if (breakpointA.type > breakpointB.type) {
245 return -1;
Tim van der Lippe1d6e57a2019-09-30 11:55:34246 }
Jack Lynch8a344762019-12-12 03:17:38247 if (breakpointA.type < breakpointB.type) {
248 return 1;
249 }
250 return 0;
251 });
252 if (!this.hasFocus()) {
253 this._list.selectItem(this._breakpoints.at(0));
Blink Reformat4c46d092018-04-07 15:32:37254 }
Blink Reformat4c46d092018-04-07 15:32:37255 }
256
257 /**
258 * @param {!SDK.DOMDebuggerModel.DOMBreakpoint} breakpoint
259 * @param {!Event} event
260 */
261 _contextMenu(breakpoint, event) {
Tim van der Lippe046db882020-02-13 13:55:11262 const contextMenu = new UI.ContextMenu.ContextMenu(event);
Jack Lynch8a344762019-12-12 03:17:38263 contextMenu.defaultSection().appendItem(
Jack Franklin536a31d2020-09-25 13:15:24264 ls`Reveal DOM node in Elements panel`, () => Common.Revealer.reveal(breakpoint.node));
Tim van der Lippe046db882020-02-13 13:55:11265 contextMenu.defaultSection().appendItem(Common.UIString.UIString('Remove breakpoint'), () => {
Blink Reformat4c46d092018-04-07 15:32:37266 breakpoint.domDebuggerModel.removeDOMBreakpoint(breakpoint.node, breakpoint.type);
267 });
Tim van der Lippe046db882020-02-13 13:55:11268 contextMenu.defaultSection().appendItem(Common.UIString.UIString('Remove all DOM breakpoints'), () => {
Blink Reformat4c46d092018-04-07 15:32:37269 breakpoint.domDebuggerModel.removeAllDOMBreakpoints();
270 });
271 contextMenu.show();
272 }
273
274 /**
275 * @param {!SDK.DOMDebuggerModel.DOMBreakpoint} breakpoint
Jack Lynch8a344762019-12-12 03:17:38276 * @param {!Event} event
Blink Reformat4c46d092018-04-07 15:32:37277 */
Jack Lynch8a344762019-12-12 03:17:38278 _checkboxClicked(breakpoint, event) {
Jack Franklin536a31d2020-09-25 13:15:24279 breakpoint.domDebuggerModel.toggleDOMBreakpoint(
280 breakpoint, event.target ? /** @type {!HTMLInputElement} */ (event.target).checked : false);
Blink Reformat4c46d092018-04-07 15:32:37281 }
282
283 /**
284 * @override
285 * @param {?Object} object
286 */
287 flavorChanged(object) {
288 this._update();
289 }
290
291 _update() {
Tim van der Lipped1a00aa2020-08-19 16:03:56292 const details = UI.Context.Context.instance().flavor(SDK.DebuggerModel.DebuggerPausedDetails);
Jack Lynch8a344762019-12-12 03:17:38293 if (this._highlightedBreakpoint) {
294 const oldHighlightedBreakpoint = this._highlightedBreakpoint;
Jack Franklin536a31d2020-09-25 13:15:24295 this._highlightedBreakpoint = null;
Jack Lynch8a344762019-12-12 03:17:38296 this._list.refreshItem(oldHighlightedBreakpoint);
297 }
Blink Reformat4c46d092018-04-07 15:32:37298 if (!details || !details.auxData || details.reason !== SDK.DebuggerModel.BreakReason.DOM) {
Blink Reformat4c46d092018-04-07 15:32:37299 return;
300 }
Jack Lynch8a344762019-12-12 03:17:38301
Tim van der Lippe046db882020-02-13 13:55:11302 const domDebuggerModel = details.debuggerModel.target().model(SDK.DOMDebuggerModel.DOMDebuggerModel);
Tim van der Lippe1d6e57a2019-09-30 11:55:34303 if (!domDebuggerModel) {
Blink Reformat4c46d092018-04-07 15:32:37304 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34305 }
Sigurd Schneider5a5b7352020-10-05 11:13:05306 const data = domDebuggerModel.resolveDOMBreakpointData(/** @type {*} */ (details.auxData));
Tim van der Lippe1d6e57a2019-09-30 11:55:34307 if (!data) {
Blink Reformat4c46d092018-04-07 15:32:37308 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34309 }
Blink Reformat4c46d092018-04-07 15:32:37310
Jack Lynch8a344762019-12-12 03:17:38311 for (const breakpoint of this._breakpoints) {
312 if (breakpoint.node === data.node && breakpoint.type === data.type) {
313 this._highlightedBreakpoint = breakpoint;
Tim van der Lippe1d6e57a2019-09-30 11:55:34314 }
Blink Reformat4c46d092018-04-07 15:32:37315 }
Jack Lynch8a344762019-12-12 03:17:38316 if (this._highlightedBreakpoint) {
317 this._list.refreshItem(this._highlightedBreakpoint);
Tim van der Lippe1d6e57a2019-09-30 11:55:34318 }
Paul Lewis75c7d0d2020-03-19 12:17:26319 UI.ViewManager.ViewManager.instance().showView('sources.domBreakpoints');
Blink Reformat4c46d092018-04-07 15:32:37320 }
Paul Lewis7f7a9202019-11-26 16:10:56321}
Blink Reformat4c46d092018-04-07 15:32:37322
Paul Lewis7f7a9202019-11-26 16:10:56323export const BreakpointTypeLabels = new Map([
Tim van der Lippe046db882020-02-13 13:55:11324 [Protocol.DOMDebugger.DOMBreakpointType.SubtreeModified, Common.UIString.UIString('Subtree modified')],
325 [Protocol.DOMDebugger.DOMBreakpointType.AttributeModified, Common.UIString.UIString('Attribute modified')],
326 [Protocol.DOMDebugger.DOMBreakpointType.NodeRemoved, Common.UIString.UIString('Node removed')],
Blink Reformat4c46d092018-04-07 15:32:37327]);
328
329/**
330 * @implements {UI.ContextMenu.Provider}
331 */
Paul Lewis7f7a9202019-11-26 16:10:56332export class ContextMenuProvider {
Blink Reformat4c46d092018-04-07 15:32:37333 /**
334 * @override
335 * @param {!Event} event
Tim van der Lippe046db882020-02-13 13:55:11336 * @param {!UI.ContextMenu.ContextMenu} contextMenu
Blink Reformat4c46d092018-04-07 15:32:37337 * @param {!Object} object
338 */
339 appendApplicableItems(event, contextMenu, object) {
Tim van der Lippe046db882020-02-13 13:55:11340 const node = /** @type {!SDK.DOMModel.DOMNode} */ (object);
Tim van der Lippe1d6e57a2019-09-30 11:55:34341 if (node.pseudoType()) {
Blink Reformat4c46d092018-04-07 15:32:37342 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34343 }
Tim van der Lippe046db882020-02-13 13:55:11344 const domDebuggerModel = node.domModel().target().model(SDK.DOMDebuggerModel.DOMDebuggerModel);
Tim van der Lippe1d6e57a2019-09-30 11:55:34345 if (!domDebuggerModel) {
Blink Reformat4c46d092018-04-07 15:32:37346 return;
Tim van der Lippe1d6e57a2019-09-30 11:55:34347 }
Blink Reformat4c46d092018-04-07 15:32:37348
349 /**
Tim van der Lippe046db882020-02-13 13:55:11350 * @param {!Protocol.DOMDebugger.DOMBreakpointType} type
Blink Reformat4c46d092018-04-07 15:32:37351 */
352 function toggleBreakpoint(type) {
Sigurd Schneider5a5b7352020-10-05 11:13:05353 if (!domDebuggerModel) {
354 return;
355 }
Tim van der Lippe1d6e57a2019-09-30 11:55:34356 if (domDebuggerModel.hasDOMBreakpoint(node, type)) {
Blink Reformat4c46d092018-04-07 15:32:37357 domDebuggerModel.removeDOMBreakpoint(node, type);
Tim van der Lippe1d6e57a2019-09-30 11:55:34358 } else {
Blink Reformat4c46d092018-04-07 15:32:37359 domDebuggerModel.setDOMBreakpoint(node, type);
Tim van der Lippe1d6e57a2019-09-30 11:55:34360 }
Blink Reformat4c46d092018-04-07 15:32:37361 }
362
Tim van der Lippe046db882020-02-13 13:55:11363 const breakpointsMenu = contextMenu.debugSection().appendSubMenuItem(Common.UIString.UIString('Break on'));
Jack Franklin536a31d2020-09-25 13:15:24364 for (const type of Object.values(Protocol.DOMDebugger.DOMBreakpointType)) {
Blink Reformat4c46d092018-04-07 15:32:37365 const label = Sources.DebuggerPausedMessage.BreakpointTypeNouns.get(type);
Jack Franklin536a31d2020-09-25 13:15:24366 if (label) {
367 breakpointsMenu.defaultSection().appendCheckboxItem(
368 label, toggleBreakpoint.bind(null, type), domDebuggerModel.hasDOMBreakpoint(node, type));
369 }
Blink Reformat4c46d092018-04-07 15:32:37370 }
371 }
Paul Lewis7f7a9202019-11-26 16:10:56372}