| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 2008 Apple 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 | |
| 6 * are met: | |
| 7 * 1. Redistributions of source code must retain the above copyright | |
| 8 * notice, this list of conditions and the following disclaimer. | |
| 9 * 2. Redistributions in binary form must reproduce the above copyright | |
| 10 * notice, this list of conditions and the following disclaimer in the | |
| 11 * documentation and/or other materials provided with the distribution. | |
| 12 * | |
| 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY | |
| 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
| 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
| 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR | |
| 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |
| 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
| 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
| 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY | |
| 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 24 */ | |
| 25 | |
| 26 /** | |
| 27 * @constructor | |
| 28 * @extends {WebInspector.SidebarPane} | |
| 29 * @param {!WebInspector.BreakpointManager} breakpointManager | |
| 30 * @param {function(!WebInspector.UISourceCode, number=, number=, boolean=)} sho
wSourceLineDelegate | |
| 31 */ | |
| 32 WebInspector.JavaScriptBreakpointsSidebarPane = function(breakpointManager, show
SourceLineDelegate) | |
| 33 { | |
| 34 WebInspector.SidebarPane.call(this, WebInspector.UIString("Breakpoints")); | |
| 35 this.registerRequiredCSS("components/breakpointsList.css"); | |
| 36 | |
| 37 this._breakpointManager = breakpointManager; | |
| 38 this._showSourceLineDelegate = showSourceLineDelegate; | |
| 39 | |
| 40 this.listElement = createElementWithClass("ol", "breakpoint-list"); | |
| 41 | |
| 42 this.emptyElement = this.bodyElement.createChild("div", "info"); | |
| 43 this.emptyElement.textContent = WebInspector.UIString("No Breakpoints"); | |
| 44 | |
| 45 this._items = new Map(); | |
| 46 | |
| 47 var breakpointLocations = this._breakpointManager.allBreakpointLocations(); | |
| 48 for (var i = 0; i < breakpointLocations.length; ++i) | |
| 49 this._addBreakpoint(breakpointLocations[i].breakpoint, breakpointLocatio
ns[i].uiLocation); | |
| 50 | |
| 51 this._breakpointManager.addEventListener(WebInspector.BreakpointManager.Even
ts.BreakpointAdded, this._breakpointAdded, this); | |
| 52 this._breakpointManager.addEventListener(WebInspector.BreakpointManager.Even
ts.BreakpointRemoved, this._breakpointRemoved, this); | |
| 53 | |
| 54 this.emptyElement.addEventListener("contextmenu", this._emptyElementContextM
enu.bind(this), true); | |
| 55 } | |
| 56 | |
| 57 WebInspector.JavaScriptBreakpointsSidebarPane.prototype = { | |
| 58 _emptyElementContextMenu: function(event) | |
| 59 { | |
| 60 var contextMenu = new WebInspector.ContextMenu(event); | |
| 61 this._appendBreakpointActiveItem(contextMenu); | |
| 62 contextMenu.show(); | |
| 63 }, | |
| 64 | |
| 65 /** | |
| 66 * @param {!WebInspector.ContextMenu} contextMenu | |
| 67 */ | |
| 68 _appendBreakpointActiveItem: function(contextMenu) | |
| 69 { | |
| 70 var breakpointActive = this._breakpointManager.breakpointsActive(); | |
| 71 var breakpointActiveTitle = breakpointActive ? | |
| 72 WebInspector.UIString.capitalize("Deactivate ^breakpoints") : | |
| 73 WebInspector.UIString.capitalize("Activate ^breakpoints"); | |
| 74 contextMenu.appendItem(breakpointActiveTitle, this._breakpointManager.se
tBreakpointsActive.bind(this._breakpointManager, !breakpointActive)); | |
| 75 }, | |
| 76 | |
| 77 /** | |
| 78 * @param {!WebInspector.Event} event | |
| 79 */ | |
| 80 _breakpointAdded: function(event) | |
| 81 { | |
| 82 this._breakpointRemoved(event); | |
| 83 | |
| 84 var breakpoint = /** @type {!WebInspector.BreakpointManager.Breakpoint}
*/ (event.data.breakpoint); | |
| 85 var uiLocation = /** @type {!WebInspector.UILocation} */ (event.data.uiL
ocation); | |
| 86 this._addBreakpoint(breakpoint, uiLocation); | |
| 87 }, | |
| 88 | |
| 89 /** | |
| 90 * @param {!WebInspector.BreakpointManager.Breakpoint} breakpoint | |
| 91 * @param {!WebInspector.UILocation} uiLocation | |
| 92 */ | |
| 93 _addBreakpoint: function(breakpoint, uiLocation) | |
| 94 { | |
| 95 var element = createElementWithClass("li", "cursor-pointer"); | |
| 96 element.addEventListener("contextmenu", this._breakpointContextMenu.bind
(this, breakpoint), true); | |
| 97 element.addEventListener("click", this._breakpointClicked.bind(this, uiL
ocation), false); | |
| 98 | |
| 99 var checkbox = element.createChild("input", "checkbox-elem"); | |
| 100 checkbox.type = "checkbox"; | |
| 101 checkbox.checked = breakpoint.enabled(); | |
| 102 checkbox.addEventListener("click", this._breakpointCheckboxClicked.bind(
this, breakpoint), false); | |
| 103 | |
| 104 element.createTextChild(uiLocation.linkText()); | |
| 105 | |
| 106 var snippetElement = element.createChild("div", "source-text monospace")
; | |
| 107 | |
| 108 /** | |
| 109 * @param {?string} content | |
| 110 */ | |
| 111 function didRequestContent(content) | |
| 112 { | |
| 113 var lineNumber = uiLocation.lineNumber | |
| 114 var columnNumber = uiLocation.columnNumber; | |
| 115 var contentString = new String(content); | |
| 116 if (lineNumber < contentString.lineCount()) { | |
| 117 var lineText = contentString.lineAt(lineNumber); | |
| 118 var maxSnippetLength = 200; | |
| 119 var snippetStartIndex = columnNumber > 100 ? columnNumber : 0; | |
| 120 snippetElement.textContent = lineText.substr(snippetStartIndex).
trimEnd(maxSnippetLength); | |
| 121 } | |
| 122 } | |
| 123 | |
| 124 uiLocation.uiSourceCode.requestContent(didRequestContent); | |
| 125 | |
| 126 element._data = uiLocation; | |
| 127 var currentElement = this.listElement.firstChild; | |
| 128 while (currentElement) { | |
| 129 if (currentElement._data && this._compareBreakpoints(currentElement.
_data, element._data) > 0) | |
| 130 break; | |
| 131 currentElement = currentElement.nextSibling; | |
| 132 } | |
| 133 this._addListElement(element, currentElement); | |
| 134 | |
| 135 var breakpointItem = { element: element, checkbox: checkbox }; | |
| 136 this._items.set(breakpoint, breakpointItem); | |
| 137 | |
| 138 this.expand(); | |
| 139 }, | |
| 140 | |
| 141 /** | |
| 142 * @param {!WebInspector.Event} event | |
| 143 */ | |
| 144 _breakpointRemoved: function(event) | |
| 145 { | |
| 146 var breakpoint = /** @type {!WebInspector.BreakpointManager.Breakpoint}
*/ (event.data.breakpoint); | |
| 147 var breakpointItem = this._items.get(breakpoint); | |
| 148 if (!breakpointItem) | |
| 149 return; | |
| 150 this._items.remove(breakpoint); | |
| 151 this._removeListElement(breakpointItem.element); | |
| 152 }, | |
| 153 | |
| 154 /** | |
| 155 * @param {!WebInspector.BreakpointManager.Breakpoint} breakpoint | |
| 156 */ | |
| 157 highlightBreakpoint: function(breakpoint) | |
| 158 { | |
| 159 var breakpointItem = this._items.get(breakpoint); | |
| 160 if (!breakpointItem) | |
| 161 return; | |
| 162 breakpointItem.element.classList.add("breakpoint-hit"); | |
| 163 this._highlightedBreakpointItem = breakpointItem; | |
| 164 }, | |
| 165 | |
| 166 clearBreakpointHighlight: function() | |
| 167 { | |
| 168 if (this._highlightedBreakpointItem) { | |
| 169 this._highlightedBreakpointItem.element.classList.remove("breakpoint
-hit"); | |
| 170 delete this._highlightedBreakpointItem; | |
| 171 } | |
| 172 }, | |
| 173 | |
| 174 _breakpointClicked: function(uiLocation, event) | |
| 175 { | |
| 176 this._showSourceLineDelegate(uiLocation.uiSourceCode, uiLocation.lineNum
ber); | |
| 177 }, | |
| 178 | |
| 179 /** | |
| 180 * @param {!WebInspector.BreakpointManager.Breakpoint} breakpoint | |
| 181 * @param {!Event} event | |
| 182 */ | |
| 183 _breakpointCheckboxClicked: function(breakpoint, event) | |
| 184 { | |
| 185 // Breakpoint element has it's own click handler. | |
| 186 event.consume(); | |
| 187 breakpoint.setEnabled(event.target.checked); | |
| 188 }, | |
| 189 | |
| 190 /** | |
| 191 * @param {!WebInspector.BreakpointManager.Breakpoint} breakpoint | |
| 192 * @param {!Event} event | |
| 193 */ | |
| 194 _breakpointContextMenu: function(breakpoint, event) | |
| 195 { | |
| 196 var breakpoints = this._items.valuesArray(); | |
| 197 var contextMenu = new WebInspector.ContextMenu(event); | |
| 198 contextMenu.appendItem(WebInspector.UIString.capitalize("Remove ^breakpo
int"), breakpoint.remove.bind(breakpoint)); | |
| 199 if (breakpoints.length > 1) { | |
| 200 var removeAllTitle = WebInspector.UIString.capitalize("Remove ^all ^
breakpoints"); | |
| 201 contextMenu.appendItem(removeAllTitle, this._breakpointManager.remov
eAllBreakpoints.bind(this._breakpointManager)); | |
| 202 } | |
| 203 | |
| 204 contextMenu.appendSeparator(); | |
| 205 this._appendBreakpointActiveItem(contextMenu); | |
| 206 | |
| 207 function enabledBreakpointCount(breakpoints) | |
| 208 { | |
| 209 var count = 0; | |
| 210 for (var i = 0; i < breakpoints.length; ++i) { | |
| 211 if (breakpoints[i].checkbox.checked) | |
| 212 count++; | |
| 213 } | |
| 214 return count; | |
| 215 } | |
| 216 if (breakpoints.length > 1) { | |
| 217 var enableBreakpointCount = enabledBreakpointCount(breakpoints); | |
| 218 var enableTitle = WebInspector.UIString.capitalize("Enable ^all ^bre
akpoints"); | |
| 219 var disableTitle = WebInspector.UIString.capitalize("Disable ^all ^b
reakpoints"); | |
| 220 | |
| 221 contextMenu.appendSeparator(); | |
| 222 | |
| 223 contextMenu.appendItem(enableTitle, this._breakpointManager.toggleAl
lBreakpoints.bind(this._breakpointManager, true), !(enableBreakpointCount != bre
akpoints.length)); | |
| 224 contextMenu.appendItem(disableTitle, this._breakpointManager.toggleA
llBreakpoints.bind(this._breakpointManager, false), !(enableBreakpointCount > 1)
); | |
| 225 } | |
| 226 | |
| 227 contextMenu.show(); | |
| 228 }, | |
| 229 | |
| 230 _addListElement: function(element, beforeElement) | |
| 231 { | |
| 232 if (beforeElement) | |
| 233 this.listElement.insertBefore(element, beforeElement); | |
| 234 else { | |
| 235 if (!this.listElement.firstChild) { | |
| 236 this.bodyElement.removeChild(this.emptyElement); | |
| 237 this.bodyElement.appendChild(this.listElement); | |
| 238 } | |
| 239 this.listElement.appendChild(element); | |
| 240 } | |
| 241 }, | |
| 242 | |
| 243 _removeListElement: function(element) | |
| 244 { | |
| 245 this.listElement.removeChild(element); | |
| 246 if (!this.listElement.firstChild) { | |
| 247 this.bodyElement.removeChild(this.listElement); | |
| 248 this.bodyElement.appendChild(this.emptyElement); | |
| 249 } | |
| 250 }, | |
| 251 | |
| 252 _compare: function(x, y) | |
| 253 { | |
| 254 if (x !== y) | |
| 255 return x < y ? -1 : 1; | |
| 256 return 0; | |
| 257 }, | |
| 258 | |
| 259 _compareBreakpoints: function(b1, b2) | |
| 260 { | |
| 261 return this._compare(b1.uiSourceCode.originURL(), b2.uiSourceCode.origin
URL()) || this._compare(b1.lineNumber, b2.lineNumber); | |
| 262 }, | |
| 263 | |
| 264 reset: function() | |
| 265 { | |
| 266 this.listElement.removeChildren(); | |
| 267 if (this.listElement.parentElement) { | |
| 268 this.bodyElement.removeChild(this.listElement); | |
| 269 this.bodyElement.appendChild(this.emptyElement); | |
| 270 } | |
| 271 this._items.clear(); | |
| 272 }, | |
| 273 | |
| 274 __proto__: WebInspector.SidebarPane.prototype | |
| 275 } | |
| 276 | |
| 277 /** | |
| 278 * @constructor | |
| 279 * @extends {WebInspector.NativeBreakpointsSidebarPane} | |
| 280 * @implements {WebInspector.TargetManager.Observer} | |
| 281 */ | |
| 282 WebInspector.XHRBreakpointsSidebarPane = function() | |
| 283 { | |
| 284 WebInspector.NativeBreakpointsSidebarPane.call(this, WebInspector.UIString("
XHR Breakpoints")); | |
| 285 | |
| 286 /** @type {!Map.<string, !Element>} */ | |
| 287 this._breakpointElements = new Map(); | |
| 288 | |
| 289 var addButton = this.titleElement.createChild("button", "pane-title-button a
dd"); | |
| 290 addButton.title = WebInspector.UIString("Add XHR breakpoint"); | |
| 291 addButton.addEventListener("click", this._addButtonClicked.bind(this), false
); | |
| 292 | |
| 293 this.emptyElement.addEventListener("contextmenu", this._emptyElementContextM
enu.bind(this), true); | |
| 294 | |
| 295 WebInspector.targetManager.observeTargets(this); | |
| 296 } | |
| 297 | |
| 298 WebInspector.XHRBreakpointsSidebarPane.prototype = { | |
| 299 /** | |
| 300 * @override | |
| 301 * @param {!WebInspector.Target} target | |
| 302 */ | |
| 303 targetAdded: function(target) | |
| 304 { | |
| 305 this._restoreBreakpoints(target); | |
| 306 }, | |
| 307 | |
| 308 /** | |
| 309 * @override | |
| 310 * @param {!WebInspector.Target} target | |
| 311 */ | |
| 312 targetRemoved: function(target) { }, | |
| 313 | |
| 314 _emptyElementContextMenu: function(event) | |
| 315 { | |
| 316 var contextMenu = new WebInspector.ContextMenu(event); | |
| 317 contextMenu.appendItem(WebInspector.UIString.capitalize("Add ^breakpoint
"), this._addButtonClicked.bind(this)); | |
| 318 contextMenu.show(); | |
| 319 }, | |
| 320 | |
| 321 _addButtonClicked: function(event) | |
| 322 { | |
| 323 if (event) | |
| 324 event.consume(); | |
| 325 | |
| 326 this.expand(); | |
| 327 | |
| 328 var inputElementContainer = createElementWithClass("p", "breakpoint-cond
ition"); | |
| 329 inputElementContainer.textContent = WebInspector.UIString("Break when UR
L contains:"); | |
| 330 | |
| 331 var inputElement = inputElementContainer.createChild("span", "editing"); | |
| 332 inputElement.id = "breakpoint-condition-input"; | |
| 333 this.addListElement(inputElementContainer, /** @type {?Element} */ (this
.listElement.firstChild)); | |
| 334 | |
| 335 /** | |
| 336 * @param {boolean} accept | |
| 337 * @param {!Element} e | |
| 338 * @param {string} text | |
| 339 * @this {WebInspector.XHRBreakpointsSidebarPane} | |
| 340 */ | |
| 341 function finishEditing(accept, e, text) | |
| 342 { | |
| 343 this.removeListElement(inputElementContainer); | |
| 344 if (accept) { | |
| 345 this._setBreakpoint(text, true); | |
| 346 this._saveBreakpoints(); | |
| 347 } | |
| 348 } | |
| 349 | |
| 350 var config = new WebInspector.InplaceEditor.Config(finishEditing.bind(th
is, true), finishEditing.bind(this, false)); | |
| 351 WebInspector.InplaceEditor.startEditing(inputElement, config); | |
| 352 }, | |
| 353 | |
| 354 /** | |
| 355 * @param {string} url | |
| 356 * @param {boolean} enabled | |
| 357 * @param {!WebInspector.Target=} target | |
| 358 */ | |
| 359 _setBreakpoint: function(url, enabled, target) | |
| 360 { | |
| 361 if (enabled) | |
| 362 this._updateBreakpointOnTarget(url, true, target); | |
| 363 | |
| 364 if (this._breakpointElements.has(url)) | |
| 365 return; | |
| 366 | |
| 367 var element = createElement("li"); | |
| 368 element._url = url; | |
| 369 element.addEventListener("contextmenu", this._contextMenu.bind(this, url
), true); | |
| 370 | |
| 371 var label = createCheckboxLabel(undefined, enabled); | |
| 372 label.classList.add("checkbox-elem"); | |
| 373 element.appendChild(label); | |
| 374 label.checkboxElement.addEventListener("click", this._checkboxClicked.bi
nd(this, url), false); | |
| 375 element._checkboxElement = label.checkboxElement; | |
| 376 | |
| 377 var labelElement = label.createChild("span", "cursor-auto"); | |
| 378 if (!url) | |
| 379 labelElement.textContent = WebInspector.UIString("Any XHR"); | |
| 380 else | |
| 381 labelElement.textContent = WebInspector.UIString("URL contains \"%s\
"", url); | |
| 382 labelElement.addEventListener("dblclick", this._labelClicked.bind(this,
url), false); | |
| 383 | |
| 384 var currentElement = /** @type {?Element} */ (this.listElement.firstChil
d); | |
| 385 while (currentElement) { | |
| 386 if (currentElement._url && currentElement._url < element._url) | |
| 387 break; | |
| 388 currentElement = /** @type {?Element} */ (currentElement.nextSibling
); | |
| 389 } | |
| 390 this.addListElement(element, currentElement); | |
| 391 this._breakpointElements.set(url, element); | |
| 392 }, | |
| 393 | |
| 394 /** | |
| 395 * @param {string} url | |
| 396 * @param {!WebInspector.Target=} target | |
| 397 */ | |
| 398 _removeBreakpoint: function(url, target) | |
| 399 { | |
| 400 var element = this._breakpointElements.get(url); | |
| 401 if (!element) | |
| 402 return; | |
| 403 | |
| 404 this.removeListElement(element); | |
| 405 this._breakpointElements.delete(url); | |
| 406 if (element._checkboxElement.checked) | |
| 407 this._updateBreakpointOnTarget(url, false, target); | |
| 408 }, | |
| 409 | |
| 410 /** | |
| 411 * @param {string} url | |
| 412 * @param {boolean} enable | |
| 413 * @param {!WebInspector.Target=} target | |
| 414 */ | |
| 415 _updateBreakpointOnTarget: function(url, enable, target) | |
| 416 { | |
| 417 var targets = target ? [target] : WebInspector.targetManager.targets(); | |
| 418 for (var i = 0; i < targets.length; ++i) { | |
| 419 if (enable) | |
| 420 targets[i].domdebuggerAgent().setXHRBreakpoint(url); | |
| 421 else | |
| 422 targets[i].domdebuggerAgent().removeXHRBreakpoint(url); | |
| 423 } | |
| 424 }, | |
| 425 | |
| 426 _contextMenu: function(url, event) | |
| 427 { | |
| 428 var contextMenu = new WebInspector.ContextMenu(event); | |
| 429 | |
| 430 /** | |
| 431 * @this {WebInspector.XHRBreakpointsSidebarPane} | |
| 432 */ | |
| 433 function removeBreakpoint() | |
| 434 { | |
| 435 this._removeBreakpoint(url); | |
| 436 this._saveBreakpoints(); | |
| 437 } | |
| 438 | |
| 439 /** | |
| 440 * @this {WebInspector.XHRBreakpointsSidebarPane} | |
| 441 */ | |
| 442 function removeAllBreakpoints() | |
| 443 { | |
| 444 for (var url of this._breakpointElements.keys()) | |
| 445 this._removeBreakpoint(url); | |
| 446 this._saveBreakpoints(); | |
| 447 } | |
| 448 var removeAllTitle = WebInspector.UIString.capitalize("Remove ^all ^brea
kpoints"); | |
| 449 | |
| 450 contextMenu.appendItem(WebInspector.UIString.capitalize("Add ^breakpoint
"), this._addButtonClicked.bind(this)); | |
| 451 contextMenu.appendItem(WebInspector.UIString.capitalize("Remove ^breakpo
int"), removeBreakpoint.bind(this)); | |
| 452 contextMenu.appendItem(removeAllTitle, removeAllBreakpoints.bind(this)); | |
| 453 contextMenu.show(); | |
| 454 }, | |
| 455 | |
| 456 _checkboxClicked: function(url, event) | |
| 457 { | |
| 458 this._updateBreakpointOnTarget(url, event.target.checked); | |
| 459 this._saveBreakpoints(); | |
| 460 }, | |
| 461 | |
| 462 _labelClicked: function(url) | |
| 463 { | |
| 464 var element = this._breakpointElements.get(url); | |
| 465 var inputElement = createElementWithClass("span", "breakpoint-condition
editing"); | |
| 466 inputElement.textContent = url; | |
| 467 this.listElement.insertBefore(inputElement, element); | |
| 468 element.classList.add("hidden"); | |
| 469 | |
| 470 /** | |
| 471 * @param {boolean} accept | |
| 472 * @param {!Element} e | |
| 473 * @param {string} text | |
| 474 * @this {WebInspector.XHRBreakpointsSidebarPane} | |
| 475 */ | |
| 476 function finishEditing(accept, e, text) | |
| 477 { | |
| 478 this.removeListElement(inputElement); | |
| 479 if (accept) { | |
| 480 this._removeBreakpoint(url); | |
| 481 this._setBreakpoint(text, element._checkboxElement.checked); | |
| 482 this._saveBreakpoints(); | |
| 483 } else | |
| 484 element.classList.remove("hidden"); | |
| 485 } | |
| 486 | |
| 487 WebInspector.InplaceEditor.startEditing(inputElement, new WebInspector.I
nplaceEditor.Config(finishEditing.bind(this, true), finishEditing.bind(this, fal
se))); | |
| 488 }, | |
| 489 | |
| 490 highlightBreakpoint: function(url) | |
| 491 { | |
| 492 var element = this._breakpointElements.get(url); | |
| 493 if (!element) | |
| 494 return; | |
| 495 this.expand(); | |
| 496 element.classList.add("breakpoint-hit"); | |
| 497 this._highlightedElement = element; | |
| 498 }, | |
| 499 | |
| 500 clearBreakpointHighlight: function() | |
| 501 { | |
| 502 if (this._highlightedElement) { | |
| 503 this._highlightedElement.classList.remove("breakpoint-hit"); | |
| 504 delete this._highlightedElement; | |
| 505 } | |
| 506 }, | |
| 507 | |
| 508 _saveBreakpoints: function() | |
| 509 { | |
| 510 var breakpoints = []; | |
| 511 for (var url of this._breakpointElements.keys()) | |
| 512 breakpoints.push({ url: url, enabled: this._breakpointElements.get(u
rl)._checkboxElement.checked }); | |
| 513 WebInspector.settings.xhrBreakpoints.set(breakpoints); | |
| 514 }, | |
| 515 | |
| 516 /** | |
| 517 * @param {!WebInspector.Target} target | |
| 518 */ | |
| 519 _restoreBreakpoints: function(target) | |
| 520 { | |
| 521 var breakpoints = WebInspector.settings.xhrBreakpoints.get(); | |
| 522 for (var i = 0; i < breakpoints.length; ++i) { | |
| 523 var breakpoint = breakpoints[i]; | |
| 524 if (breakpoint && typeof breakpoint.url === "string") | |
| 525 this._setBreakpoint(breakpoint.url, breakpoint.enabled, target); | |
| 526 } | |
| 527 }, | |
| 528 | |
| 529 __proto__: WebInspector.NativeBreakpointsSidebarPane.prototype | |
| 530 } | |
| 531 | |
| 532 /** | |
| 533 * @constructor | |
| 534 * @extends {WebInspector.SidebarPane} | |
| 535 * @implements {WebInspector.TargetManager.Observer} | |
| 536 */ | |
| 537 WebInspector.EventListenerBreakpointsSidebarPane = function() | |
| 538 { | |
| 539 WebInspector.SidebarPane.call(this, WebInspector.UIString("Event Listener Br
eakpoints")); | |
| 540 this.registerRequiredCSS("components/breakpointsList.css"); | |
| 541 | |
| 542 this._categoriesTreeOutline = new TreeOutline(); | |
| 543 this._categoriesTreeOutline.element.tabIndex = 0; | |
| 544 this._categoriesTreeOutline.element.classList.add("event-listener-breakpoint
s"); | |
| 545 this.bodyElement.appendChild(this._categoriesTreeOutline.element); | |
| 546 | |
| 547 this._categoryItems = []; | |
| 548 // FIXME: uncomment following once inspector stops being drop targer in majo
r ports. | |
| 549 // Otherwise, inspector page reacts on drop event and tries to load the even
t data. | |
| 550 // this._createCategory(WebInspector.UIString("Drag"), ["drag", "drop", "dra
gstart", "dragend", "dragenter", "dragleave", "dragover"]); | |
| 551 this._createCategory(WebInspector.UIString("Animation"), ["requestAnimationF
rame", "cancelAnimationFrame", "animationFrameFired"], true); | |
| 552 this._createCategory(WebInspector.UIString("Control"), ["resize", "scroll",
"zoom", "focus", "blur", "select", "change", "submit", "reset"]); | |
| 553 this._createCategory(WebInspector.UIString("Clipboard"), ["copy", "cut", "pa
ste", "beforecopy", "beforecut", "beforepaste"]); | |
| 554 this._createCategory(WebInspector.UIString("DOM Mutation"), ["DOMActivate",
"DOMFocusIn", "DOMFocusOut", "DOMAttrModified", "DOMCharacterDataModified", "DOM
NodeInserted", "DOMNodeInsertedIntoDocument", "DOMNodeRemoved", "DOMNodeRemovedF
romDocument", "DOMSubtreeModified", "DOMContentLoaded"]); | |
| 555 this._createCategory(WebInspector.UIString("Device"), ["deviceorientation",
"devicemotion"]); | |
| 556 this._createCategory(WebInspector.UIString("Drag / drop"), ["dragenter", "dr
agover", "dragleave", "drop"]); | |
| 557 this._createCategory(WebInspector.UIString("Keyboard"), ["keydown", "keyup",
"keypress", "input"]); | |
| 558 this._createCategory(WebInspector.UIString("Load"), ["load", "beforeunload",
"unload", "abort", "error", "hashchange", "popstate"]); | |
| 559 this._createCategory(WebInspector.UIString("Media"), ["play", "pause", "play
ing", "canplay", "canplaythrough", "seeking", "seeked", "timeupdate", "ended", "
ratechange", "durationchange", "volumechange", "loadstart", "progress", "suspend
", "abort", "error", "emptied", "stalled", "loadedmetadata", "loadeddata", "wait
ing"], false, ["audio", "video"]); | |
| 560 this._createCategory(WebInspector.UIString("Mouse"), ["click", "dblclick", "
mousedown", "mouseup", "mouseover", "mousemove", "mouseout", "mouseenter", "mous
eleave", "mousewheel", "wheel", "contextmenu"]); | |
| 561 this._createCategory(WebInspector.UIString("Promise"), ["newPromise", "promi
seResolved", "promiseRejected"], true); | |
| 562 this._createCategory(WebInspector.UIString("Script"), ["scriptFirstStatement
"], true); | |
| 563 this._createCategory(WebInspector.UIString("Timer"), ["setTimer", "clearTime
r", "timerFired"], true); | |
| 564 this._createCategory(WebInspector.UIString("Touch"), ["touchstart", "touchmo
ve", "touchend", "touchcancel"]); | |
| 565 this._createCategory(WebInspector.UIString("XHR"), ["readystatechange", "loa
d", "loadstart", "loadend", "abort", "error", "progress", "timeout"], false, ["X
MLHttpRequest", "XMLHttpRequestUpload"]); | |
| 566 this._createCategory(WebInspector.UIString("WebGL"), ["webglErrorFired", "we
bglWarningFired"], true); | |
| 567 this._createCategory(WebInspector.UIString("Window"), ["close"], true); | |
| 568 | |
| 569 WebInspector.targetManager.observeTargets(this); | |
| 570 } | |
| 571 | |
| 572 WebInspector.EventListenerBreakpointsSidebarPane.categoryListener = "listener:"; | |
| 573 WebInspector.EventListenerBreakpointsSidebarPane.categoryInstrumentation = "inst
rumentation:"; | |
| 574 WebInspector.EventListenerBreakpointsSidebarPane.eventTargetAny = "*"; | |
| 575 | |
| 576 /** | |
| 577 * @param {string} eventName | |
| 578 * @param {!Object=} auxData | |
| 579 * @return {string} | |
| 580 */ | |
| 581 WebInspector.EventListenerBreakpointsSidebarPane.eventNameForUI = function(event
Name, auxData) | |
| 582 { | |
| 583 if (!WebInspector.EventListenerBreakpointsSidebarPane._eventNamesForUI) { | |
| 584 WebInspector.EventListenerBreakpointsSidebarPane._eventNamesForUI = { | |
| 585 "instrumentation:setTimer": WebInspector.UIString("Set Timer"), | |
| 586 "instrumentation:clearTimer": WebInspector.UIString("Clear Timer"), | |
| 587 "instrumentation:timerFired": WebInspector.UIString("Timer Fired"), | |
| 588 "instrumentation:newPromise": WebInspector.UIString("Promise Created
"), | |
| 589 "instrumentation:promiseResolved": WebInspector.UIString("Promise Re
solved"), | |
| 590 "instrumentation:promiseRejected": WebInspector.UIString("Promise Re
jected"), | |
| 591 "instrumentation:scriptFirstStatement": WebInspector.UIString("Scrip
t First Statement"), | |
| 592 "instrumentation:requestAnimationFrame": WebInspector.UIString("Requ
est Animation Frame"), | |
| 593 "instrumentation:cancelAnimationFrame": WebInspector.UIString("Cance
l Animation Frame"), | |
| 594 "instrumentation:animationFrameFired": WebInspector.UIString("Animat
ion Frame Fired"), | |
| 595 "instrumentation:webglErrorFired": WebInspector.UIString("WebGL Erro
r Fired"), | |
| 596 "instrumentation:webglWarningFired": WebInspector.UIString("WebGL Wa
rning Fired") | |
| 597 }; | |
| 598 } | |
| 599 if (auxData) { | |
| 600 if (eventName === "instrumentation:webglErrorFired" && auxData["webglErr
orName"]) { | |
| 601 var errorName = auxData["webglErrorName"]; | |
| 602 // If there is a hex code of the error, display only this. | |
| 603 errorName = errorName.replace(/^.*(0x[0-9a-f]+).*$/i, "$1"); | |
| 604 return WebInspector.UIString("WebGL Error Fired (%s)", errorName); | |
| 605 } | |
| 606 } | |
| 607 return WebInspector.EventListenerBreakpointsSidebarPane._eventNamesForUI[eve
ntName] || eventName.substring(eventName.indexOf(":") + 1); | |
| 608 } | |
| 609 | |
| 610 WebInspector.EventListenerBreakpointsSidebarPane.prototype = { | |
| 611 /** | |
| 612 * @override | |
| 613 * @param {!WebInspector.Target} target | |
| 614 */ | |
| 615 targetAdded: function(target) | |
| 616 { | |
| 617 this._restoreBreakpoints(target); | |
| 618 }, | |
| 619 | |
| 620 /** | |
| 621 * @override | |
| 622 * @param {!WebInspector.Target} target | |
| 623 */ | |
| 624 targetRemoved: function(target) { }, | |
| 625 | |
| 626 /** | |
| 627 * @param {string} name | |
| 628 * @param {!Array.<string>} eventNames | |
| 629 * @param {boolean=} isInstrumentationEvent | |
| 630 * @param {!Array.<string>=} targetNames | |
| 631 */ | |
| 632 _createCategory: function(name, eventNames, isInstrumentationEvent, targetNa
mes) | |
| 633 { | |
| 634 var labelNode = createCheckboxLabel(name); | |
| 635 | |
| 636 var categoryItem = {}; | |
| 637 categoryItem.element = new TreeElement(labelNode); | |
| 638 this._categoriesTreeOutline.appendChild(categoryItem.element); | |
| 639 categoryItem.element.listItemElement.classList.add("event-category"); | |
| 640 categoryItem.element.selectable = true; | |
| 641 | |
| 642 categoryItem.checkbox = labelNode.checkboxElement; | |
| 643 categoryItem.checkbox.addEventListener("click", this._categoryCheckboxCl
icked.bind(this, categoryItem), true); | |
| 644 | |
| 645 categoryItem.targetNames = this._stringArrayToLowerCase(targetNames || [
WebInspector.EventListenerBreakpointsSidebarPane.eventTargetAny]); | |
| 646 categoryItem.children = {}; | |
| 647 var category = (isInstrumentationEvent ? WebInspector.EventListenerBreak
pointsSidebarPane.categoryInstrumentation : WebInspector.EventListenerBreakpoin
tsSidebarPane.categoryListener); | |
| 648 for (var i = 0; i < eventNames.length; ++i) { | |
| 649 var eventName = category + eventNames[i]; | |
| 650 | |
| 651 var breakpointItem = {}; | |
| 652 var title = WebInspector.EventListenerBreakpointsSidebarPane.eventNa
meForUI(eventName); | |
| 653 | |
| 654 labelNode = createCheckboxLabel(title); | |
| 655 labelNode.classList.add("source-code"); | |
| 656 | |
| 657 breakpointItem.element = new TreeElement(labelNode); | |
| 658 categoryItem.element.appendChild(breakpointItem.element); | |
| 659 | |
| 660 breakpointItem.element.listItemElement.createChild("div", "breakpoin
t-hit-marker"); | |
| 661 breakpointItem.element.selectable = false; | |
| 662 | |
| 663 breakpointItem.checkbox = labelNode.checkboxElement; | |
| 664 breakpointItem.checkbox.addEventListener("click", this._breakpointCh
eckboxClicked.bind(this, eventName, categoryItem.targetNames), true); | |
| 665 breakpointItem.parent = categoryItem; | |
| 666 | |
| 667 categoryItem.children[eventName] = breakpointItem; | |
| 668 } | |
| 669 this._categoryItems.push(categoryItem); | |
| 670 }, | |
| 671 | |
| 672 /** | |
| 673 * @param {!Array.<string>} array | |
| 674 * @return {!Array.<string>} | |
| 675 */ | |
| 676 _stringArrayToLowerCase: function(array) | |
| 677 { | |
| 678 return array.map(function(value) { | |
| 679 return value.toLowerCase(); | |
| 680 }); | |
| 681 }, | |
| 682 | |
| 683 _categoryCheckboxClicked: function(categoryItem) | |
| 684 { | |
| 685 var checked = categoryItem.checkbox.checked; | |
| 686 for (var eventName in categoryItem.children) { | |
| 687 var breakpointItem = categoryItem.children[eventName]; | |
| 688 if (breakpointItem.checkbox.checked === checked) | |
| 689 continue; | |
| 690 if (checked) | |
| 691 this._setBreakpoint(eventName, categoryItem.targetNames); | |
| 692 else | |
| 693 this._removeBreakpoint(eventName, categoryItem.targetNames); | |
| 694 } | |
| 695 this._saveBreakpoints(); | |
| 696 }, | |
| 697 | |
| 698 /** | |
| 699 * @param {string} eventName | |
| 700 * @param {!Array.<string>} targetNames | |
| 701 * @param {!Event} event | |
| 702 */ | |
| 703 _breakpointCheckboxClicked: function(eventName, targetNames, event) | |
| 704 { | |
| 705 if (event.target.checked) | |
| 706 this._setBreakpoint(eventName, targetNames); | |
| 707 else | |
| 708 this._removeBreakpoint(eventName, targetNames); | |
| 709 this._saveBreakpoints(); | |
| 710 }, | |
| 711 | |
| 712 /** | |
| 713 * @param {string} eventName | |
| 714 * @param {?Array.<string>=} eventTargetNames | |
| 715 * @param {!WebInspector.Target=} target | |
| 716 */ | |
| 717 _setBreakpoint: function(eventName, eventTargetNames, target) | |
| 718 { | |
| 719 eventTargetNames = eventTargetNames || [WebInspector.EventListenerBreakp
ointsSidebarPane.eventTargetAny]; | |
| 720 for (var i = 0; i < eventTargetNames.length; ++i) { | |
| 721 var eventTargetName = eventTargetNames[i]; | |
| 722 var breakpointItem = this._findBreakpointItem(eventName, eventTarget
Name); | |
| 723 if (!breakpointItem) | |
| 724 continue; | |
| 725 breakpointItem.checkbox.checked = true; | |
| 726 breakpointItem.parent.dirtyCheckbox = true; | |
| 727 this._updateBreakpointOnTarget(eventName, eventTargetName, true, tar
get); | |
| 728 } | |
| 729 this._updateCategoryCheckboxes(); | |
| 730 }, | |
| 731 | |
| 732 /** | |
| 733 * @param {string} eventName | |
| 734 * @param {?Array.<string>=} eventTargetNames | |
| 735 * @param {!WebInspector.Target=} target | |
| 736 */ | |
| 737 _removeBreakpoint: function(eventName, eventTargetNames, target) | |
| 738 { | |
| 739 eventTargetNames = eventTargetNames || [WebInspector.EventListenerBreakp
ointsSidebarPane.eventTargetAny]; | |
| 740 for (var i = 0; i < eventTargetNames.length; ++i) { | |
| 741 var eventTargetName = eventTargetNames[i]; | |
| 742 var breakpointItem = this._findBreakpointItem(eventName, eventTarget
Name); | |
| 743 if (!breakpointItem) | |
| 744 continue; | |
| 745 breakpointItem.checkbox.checked = false; | |
| 746 breakpointItem.parent.dirtyCheckbox = true; | |
| 747 this._updateBreakpointOnTarget(eventName, eventTargetName, false, ta
rget); | |
| 748 } | |
| 749 this._updateCategoryCheckboxes(); | |
| 750 }, | |
| 751 | |
| 752 /** | |
| 753 * @param {string} eventName | |
| 754 * @param {string} eventTargetName | |
| 755 * @param {boolean} enable | |
| 756 * @param {!WebInspector.Target=} target | |
| 757 */ | |
| 758 _updateBreakpointOnTarget: function(eventName, eventTargetName, enable, targ
et) | |
| 759 { | |
| 760 var targets = target ? [target] : WebInspector.targetManager.targets(); | |
| 761 for (var i = 0; i < targets.length; ++i) { | |
| 762 if (eventName.startsWith(WebInspector.EventListenerBreakpointsSideba
rPane.categoryListener)) { | |
| 763 var protocolEventName = eventName.substring(WebInspector.EventLi
stenerBreakpointsSidebarPane.categoryListener.length); | |
| 764 if (enable) | |
| 765 targets[i].domdebuggerAgent().setEventListenerBreakpoint(pro
tocolEventName, eventTargetName); | |
| 766 else | |
| 767 targets[i].domdebuggerAgent().removeEventListenerBreakpoint(
protocolEventName, eventTargetName); | |
| 768 } else if (eventName.startsWith(WebInspector.EventListenerBreakpoint
sSidebarPane.categoryInstrumentation)) { | |
| 769 var protocolEventName = eventName.substring(WebInspector.EventLi
stenerBreakpointsSidebarPane.categoryInstrumentation.length); | |
| 770 if (enable) | |
| 771 targets[i].domdebuggerAgent().setInstrumentationBreakpoint(p
rotocolEventName); | |
| 772 else | |
| 773 targets[i].domdebuggerAgent().removeInstrumentationBreakpoin
t(protocolEventName); | |
| 774 } | |
| 775 } | |
| 776 }, | |
| 777 | |
| 778 _updateCategoryCheckboxes: function() | |
| 779 { | |
| 780 for (var i = 0; i < this._categoryItems.length; ++i) { | |
| 781 var categoryItem = this._categoryItems[i]; | |
| 782 if (!categoryItem.dirtyCheckbox) | |
| 783 continue; | |
| 784 categoryItem.dirtyCheckbox = false; | |
| 785 var hasEnabled = false; | |
| 786 var hasDisabled = false; | |
| 787 for (var eventName in categoryItem.children) { | |
| 788 var breakpointItem = categoryItem.children[eventName]; | |
| 789 if (breakpointItem.checkbox.checked) | |
| 790 hasEnabled = true; | |
| 791 else | |
| 792 hasDisabled = true; | |
| 793 } | |
| 794 categoryItem.checkbox.checked = hasEnabled; | |
| 795 categoryItem.checkbox.indeterminate = hasEnabled && hasDisabled; | |
| 796 } | |
| 797 }, | |
| 798 | |
| 799 /** | |
| 800 * @param {string} eventName | |
| 801 * @param {string=} targetName | |
| 802 * @return {?Object} | |
| 803 */ | |
| 804 _findBreakpointItem: function(eventName, targetName) | |
| 805 { | |
| 806 targetName = (targetName || WebInspector.EventListenerBreakpointsSidebar
Pane.eventTargetAny).toLowerCase(); | |
| 807 for (var i = 0; i < this._categoryItems.length; ++i) { | |
| 808 var categoryItem = this._categoryItems[i]; | |
| 809 if (categoryItem.targetNames.indexOf(targetName) === -1) | |
| 810 continue; | |
| 811 var breakpointItem = categoryItem.children[eventName]; | |
| 812 if (breakpointItem) | |
| 813 return breakpointItem; | |
| 814 } | |
| 815 return null; | |
| 816 }, | |
| 817 | |
| 818 /** | |
| 819 * @param {string} eventName | |
| 820 * @param {string=} targetName | |
| 821 */ | |
| 822 highlightBreakpoint: function(eventName, targetName) | |
| 823 { | |
| 824 var breakpointItem = this._findBreakpointItem(eventName, targetName); | |
| 825 if (!breakpointItem || !breakpointItem.checkbox.checked) | |
| 826 breakpointItem = this._findBreakpointItem(eventName, WebInspector.Ev
entListenerBreakpointsSidebarPane.eventTargetAny); | |
| 827 if (!breakpointItem) | |
| 828 return; | |
| 829 this.expand(); | |
| 830 breakpointItem.parent.element.expand(); | |
| 831 breakpointItem.element.listItemElement.classList.add("breakpoint-hit"); | |
| 832 this._highlightedElement = breakpointItem.element.listItemElement; | |
| 833 }, | |
| 834 | |
| 835 clearBreakpointHighlight: function() | |
| 836 { | |
| 837 if (this._highlightedElement) { | |
| 838 this._highlightedElement.classList.remove("breakpoint-hit"); | |
| 839 delete this._highlightedElement; | |
| 840 } | |
| 841 }, | |
| 842 | |
| 843 _saveBreakpoints: function() | |
| 844 { | |
| 845 var breakpoints = []; | |
| 846 for (var i = 0; i < this._categoryItems.length; ++i) { | |
| 847 var categoryItem = this._categoryItems[i]; | |
| 848 for (var eventName in categoryItem.children) { | |
| 849 var breakpointItem = categoryItem.children[eventName]; | |
| 850 if (breakpointItem.checkbox.checked) | |
| 851 breakpoints.push({ eventName: eventName, targetNames: catego
ryItem.targetNames }); | |
| 852 } | |
| 853 } | |
| 854 WebInspector.settings.eventListenerBreakpoints.set(breakpoints); | |
| 855 }, | |
| 856 | |
| 857 /** | |
| 858 * @param {!WebInspector.Target} target | |
| 859 */ | |
| 860 _restoreBreakpoints: function(target) | |
| 861 { | |
| 862 var breakpoints = WebInspector.settings.eventListenerBreakpoints.get(); | |
| 863 for (var i = 0; i < breakpoints.length; ++i) { | |
| 864 var breakpoint = breakpoints[i]; | |
| 865 if (breakpoint && typeof breakpoint.eventName === "string") | |
| 866 this._setBreakpoint(breakpoint.eventName, breakpoint.targetNames
, target); | |
| 867 } | |
| 868 }, | |
| 869 | |
| 870 __proto__: WebInspector.SidebarPane.prototype | |
| 871 } | |
| OLD | NEW |