fc821444ca686916fba79ba5ffa605af1139f206
[WebKit-https.git] / Source / WebInspectorUI / UserInterface / Views / DebuggerSidebarPanel.js
1 /*
2  * Copyright (C) 2013, 2015 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. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 WI.DebuggerSidebarPanel = class DebuggerSidebarPanel extends WI.NavigationSidebarPanel
27 {
28     constructor()
29     {
30         super("debugger", WI.UIString("Debugger"), true);
31
32         WI.Frame.addEventListener(WI.Frame.Event.MainResourceDidChange, this._mainResourceDidChange, this);
33         WI.Frame.addEventListener(WI.Frame.Event.ResourceWasAdded, this._resourceAdded, this);
34         WI.Target.addEventListener(WI.Target.Event.ResourceAdded, this._resourceAdded, this);
35
36         WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.BreakpointAdded, this._breakpointAdded, this);
37         WI.domDebuggerManager.addEventListener(WI.DOMDebuggerManager.Event.DOMBreakpointAdded, this._breakpointAdded, this);
38         WI.domDebuggerManager.addEventListener(WI.DOMDebuggerManager.Event.EventBreakpointAdded, this._breakpointAdded, this);
39         WI.domDebuggerManager.addEventListener(WI.DOMDebuggerManager.Event.URLBreakpointAdded, this._breakpointAdded, this);
40
41         WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.BreakpointRemoved, this._breakpointRemoved, this);
42         WI.domDebuggerManager.addEventListener(WI.DOMDebuggerManager.Event.DOMBreakpointRemoved, this._breakpointRemoved, this);
43         WI.domDebuggerManager.addEventListener(WI.DOMDebuggerManager.Event.EventBreakpointRemoved, this._breakpointRemoved, this);
44         WI.domDebuggerManager.addEventListener(WI.DOMDebuggerManager.Event.URLBreakpointRemoved, this._breakpointRemoved, this);
45
46         WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.BreakpointsEnabledDidChange, this._breakpointsEnabledDidChange, this);
47         WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.ScriptAdded, this._scriptAdded, this);
48         WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.ScriptRemoved, this._scriptRemoved, this);
49         WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.ScriptsCleared, this._scriptsCleared, this);
50         WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.Paused, this._debuggerDidPause, this);
51         WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.Resumed, this._debuggerDidResume, this);
52         WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.CallFramesDidChange, this._debuggerCallFramesDidChange, this);
53         WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.ActiveCallFrameDidChange, this._debuggerActiveCallFrameDidChange, this);
54         WI.debuggerManager.addEventListener(WI.DebuggerManager.Event.WaitingToPause, this._debuggerWaitingToPause, this);
55
56         WI.DOMBreakpoint.addEventListener(WI.DOMBreakpoint.Event.DOMNodeChanged, this._handleDOMBreakpointDOMNodeChanged, this);
57
58         WI.timelineManager.addEventListener(WI.TimelineManager.Event.CapturingWillStart, this._timelineCapturingWillStart, this);
59         WI.timelineManager.addEventListener(WI.TimelineManager.Event.CapturingStopped, this._timelineCapturingStopped, this);
60
61         WI.auditManager.addEventListener(WI.AuditManager.Event.TestScheduled, this._handleAuditManagerTestScheduled, this);
62         WI.auditManager.addEventListener(WI.AuditManager.Event.TestCompleted, this._handleAuditManagerTestCompleted, this);
63
64         WI.targetManager.addEventListener(WI.TargetManager.Event.TargetAdded, this._targetAdded, this);
65         WI.targetManager.addEventListener(WI.TargetManager.Event.TargetRemoved, this._targetRemoved, this);
66
67         this._timelineRecordingWarningElement = document.createElement("div");
68         this._timelineRecordingWarningElement.classList.add("warning-banner");
69         this._timelineRecordingWarningElement.append(WI.UIString("Debugger disabled during Timeline recording"), document.createElement("br"));
70         let timelineStopRecordingLink = this._timelineRecordingWarningElement.appendChild(document.createElement("a"));
71         timelineStopRecordingLink.textContent = WI.UIString("Stop recording");
72         timelineStopRecordingLink.addEventListener("click", () => { WI.timelineManager.stopCapturing(); });
73
74         this._auditTestWarningElement = document.createElement("div");
75         this._auditTestWarningElement.classList.add("warning-banner");
76         this._auditTestWarningElement.append(WI.UIString("Debugger disabled during Audit"), document.createElement("br"));
77         let auditStopRecordingLink = this._auditTestWarningElement.appendChild(document.createElement("a"));
78         auditStopRecordingLink.textContent = WI.UIString("Stop Audit");
79         auditStopRecordingLink.addEventListener("click", () => { WI.auditManager.stop(); });
80
81         this._breakpointsDisabledWarningElement = document.createElement("div");
82         this._breakpointsDisabledWarningElement.classList.add("warning-banner");
83         this._breakpointsDisabledWarningElement.append(WI.UIString("Breakpoints disabled"), document.createElement("br"));
84         let enableBreakpointsLink = this._breakpointsDisabledWarningElement.appendChild(document.createElement("a"));
85         enableBreakpointsLink.textContent = WI.UIString("Enable breakpoints");
86         enableBreakpointsLink.addEventListener("click", () => { WI.debuggerToggleBreakpoints(); });
87
88         this._navigationBar = new WI.NavigationBar;
89         this.addSubview(this._navigationBar);
90
91         var breakpointsImage = {src: "Images/Breakpoints.svg", width: 15, height: 15};
92         var pauseImage = {src: "Images/Pause.svg", width: 15, height: 15};
93         var resumeImage = {src: "Images/Resume.svg", width: 15, height: 15};
94         var stepOverImage = {src: "Images/StepOver.svg", width: 15, height: 15};
95         var stepIntoImage = {src: "Images/StepInto.svg", width: 15, height: 15};
96         var stepOutImage = {src: "Images/StepOut.svg", width: 15, height: 15};
97
98         var toolTip = WI.UIString("Enable all breakpoints (%s)").format(WI.toggleBreakpointsKeyboardShortcut.displayName);
99         var altToolTip = WI.UIString("Disable all breakpoints (%s)").format(WI.toggleBreakpointsKeyboardShortcut.displayName);
100
101         this._debuggerBreakpointsButtonItem = new WI.ActivateButtonNavigationItem("debugger-breakpoints", toolTip, altToolTip, breakpointsImage.src, breakpointsImage.width, breakpointsImage.height);
102         this._debuggerBreakpointsButtonItem.activated = WI.debuggerManager.breakpointsEnabled;
103         this._debuggerBreakpointsButtonItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI.debuggerToggleBreakpoints, this);
104         this._navigationBar.addNavigationItem(this._debuggerBreakpointsButtonItem);
105
106         toolTip = WI.UIString("Pause script execution (%s or %s)").format(WI.pauseOrResumeKeyboardShortcut.displayName, WI.pauseOrResumeAlternateKeyboardShortcut.displayName);
107         altToolTip = WI.UIString("Continue script execution (%s or %s)").format(WI.pauseOrResumeKeyboardShortcut.displayName, WI.pauseOrResumeAlternateKeyboardShortcut.displayName);
108
109         this._debuggerPauseResumeButtonItem = new WI.ToggleButtonNavigationItem("debugger-pause-resume", toolTip, altToolTip, pauseImage.src, resumeImage.src, pauseImage.width, pauseImage.height);
110         this._debuggerPauseResumeButtonItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI.debuggerPauseResumeToggle, this);
111         this._navigationBar.addNavigationItem(this._debuggerPauseResumeButtonItem);
112
113         this._debuggerStepOverButtonItem = new WI.ButtonNavigationItem("debugger-step-over", WI.UIString("Step over (%s or %s)").format(WI.stepOverKeyboardShortcut.displayName, WI.stepOverAlternateKeyboardShortcut.displayName), stepOverImage.src, stepOverImage.width, stepOverImage.height);
114         this._debuggerStepOverButtonItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI.debuggerStepOver, this);
115         this._debuggerStepOverButtonItem.enabled = false;
116         this._navigationBar.addNavigationItem(this._debuggerStepOverButtonItem);
117
118         this._debuggerStepIntoButtonItem = new WI.ButtonNavigationItem("debugger-step-into", WI.UIString("Step into (%s or %s)").format(WI.stepIntoKeyboardShortcut.displayName, WI.stepIntoAlternateKeyboardShortcut.displayName), stepIntoImage.src, stepIntoImage.width, stepIntoImage.height);
119         this._debuggerStepIntoButtonItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI.debuggerStepInto, this);
120         this._debuggerStepIntoButtonItem.enabled = false;
121         this._navigationBar.addNavigationItem(this._debuggerStepIntoButtonItem);
122
123         this._debuggerStepOutButtonItem = new WI.ButtonNavigationItem("debugger-step-out", WI.UIString("Step out (%s or %s)").format(WI.stepOutKeyboardShortcut.displayName, WI.stepOutAlternateKeyboardShortcut.displayName), stepOutImage.src, stepOutImage.width, stepOutImage.height);
124         this._debuggerStepOutButtonItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, WI.debuggerStepOut, this);
125         this._debuggerStepOutButtonItem.enabled = false;
126         this._navigationBar.addNavigationItem(this._debuggerStepOutButtonItem);
127
128         // Add this offset-sections class name so the sticky headers don't overlap the navigation bar.
129         this.element.classList.add(WI.DebuggerSidebarPanel.OffsetSectionsStyleClassName);
130
131         function showResourcesWithIssuesOnlyFilterFunction(treeElement)
132         {
133             // Issues are only shown in the scripts tree outline.
134             if (treeElement.treeOutline !== this._scriptsContentTreeOutline)
135                 return true;
136
137             // Keep issues.
138             if (treeElement instanceof WI.IssueTreeElement)
139                 return true;
140
141             // Keep resources with issues.
142             if (treeElement.hasChildren) {
143                 for (let child of treeElement.children) {
144                     if (child instanceof WI.IssueTreeElement)
145                         return true;
146                 }
147             }
148             return false;
149         }
150
151         this.filterBar.addFilterBarButton("debugger-show-resources-with-issues-only", showResourcesWithIssuesOnlyFilterFunction.bind(this), false, WI.UIString("Only show resources with issues"), WI.UIString("Show all resources"), "Images/Errors.svg", 15, 15);
152
153         this._breakpointsContentTreeOutline = this.contentTreeOutline;
154
155         let breakpointsRow = new WI.DetailsSectionRow;
156         breakpointsRow.element.appendChild(this._breakpointsContentTreeOutline.element);
157
158         let breakpointNavigationBarWrapper = document.createElement("div");
159
160         let breakpointNavigationBar = new WI.NavigationBar;
161         breakpointNavigationBarWrapper.appendChild(breakpointNavigationBar.element);
162
163         this._createBreakpointButton = new WI.ButtonNavigationItem("create-breakpoint", WI.UIString("Create Breakpoint"), "Images/Plus13.svg", 13, 13);
164         this._createBreakpointButton.element.addEventListener("mousedown", this._handleCreateBreakpointMouseDown.bind(this));
165         breakpointNavigationBar.addNavigationItem(this._createBreakpointButton);
166
167         let breakpointsGroup = new WI.DetailsSectionGroup([breakpointsRow]);
168         let breakpointsSection = new WI.DetailsSection("breakpoints", WI.UIString("Breakpoints"), [breakpointsGroup], breakpointNavigationBarWrapper);
169         this.contentView.element.appendChild(breakpointsSection.element);
170
171         this._breakpointsContentTreeOutline.addEventListener(WI.TreeOutline.Event.ElementAdded, this._handleBreakpointElementAddedOrRemoved, this);
172         this._breakpointsContentTreeOutline.addEventListener(WI.TreeOutline.Event.ElementRemoved, this._handleBreakpointElementAddedOrRemoved, this);
173         this._breakpointsContentTreeOutline.addEventListener(WI.TreeOutline.Event.SelectionDidChange, this._treeSelectionDidChange, this);
174         this._breakpointsContentTreeOutline.ondelete = this._breakpointTreeOutlineDeleteTreeElement.bind(this);
175         this._breakpointsContentTreeOutline.populateContextMenu = function(contextMenu, event, treeElement) {
176             this._breakpointTreeOutlineContextMenuTreeElement(contextMenu, event, treeElement);
177
178             WI.TreeOutline.prototype.populateContextMenu(contextMenu, event, treeElement);
179         }.bind(this);
180
181         this._scriptsContentTreeOutline = this.createContentTreeOutline();
182         this._scriptsContentTreeOutline.addEventListener(WI.TreeOutline.Event.SelectionDidChange, this._treeSelectionDidChange, this);
183         this._scriptsContentTreeOutline.includeSourceMapResourceChildren = true;
184
185         let scriptsRow = new WI.DetailsSectionRow;
186         scriptsRow.element.appendChild(this._scriptsContentTreeOutline.element);
187
188         let scriptsGroup = new WI.DetailsSectionGroup([scriptsRow]);
189         this._scriptsSection = new WI.DetailsSection("scripts", WI.UIString("Sources"), [scriptsGroup]);
190         this.contentView.element.appendChild(this._scriptsSection.element);
191
192         this._callStackTreeOutline = this.createContentTreeOutline({suppressFiltering: true});
193         this._callStackTreeOutline.addEventListener(WI.TreeOutline.Event.SelectionDidChange, this._treeSelectionDidChange, this);
194
195         this._callStackRow = new WI.DetailsSectionRow;
196         this._callStackRow.element.appendChild(this._callStackTreeOutline.element);
197
198         this._callStackGroup = new WI.DetailsSectionGroup([this._callStackRow]);
199         this._callStackSection = new WI.DetailsSection("call-stack", WI.UIString("Call Stack"), [this._callStackGroup]);
200
201         this._mainTargetTreeElement = null;
202         this._activeCallFrameTreeElement = null;
203
204         this._pauseReasonTreeOutline = null;
205
206         this._pauseReasonLinkContainerElement = document.createElement("span");
207         this._pauseReasonTextRow = new WI.DetailsSectionTextRow;
208         this._pauseReasonGroup = new WI.DetailsSectionGroup([this._pauseReasonTextRow]);
209         this._pauseReasonSection = new WI.DetailsSection("paused-reason", WI.UIString("Pause Reason"), [this._pauseReasonGroup], this._pauseReasonLinkContainerElement);
210
211         WI.Breakpoint.addEventListener(WI.Breakpoint.Event.DisplayLocationDidChange, this._handleDebuggerObjectDisplayLocationDidChange, this);
212         WI.IssueMessage.addEventListener(WI.IssueMessage.Event.DisplayLocationDidChange, this._handleDebuggerObjectDisplayLocationDidChange, this);
213         WI.consoleManager.addEventListener(WI.ConsoleManager.Event.IssueAdded, this._handleIssueAdded, this);
214         WI.consoleManager.addEventListener(WI.ConsoleManager.Event.Cleared, this._handleIssuesCleared, this);
215
216         WI.debuggerManager.addBreakpoint(WI.debuggerManager.allExceptionsBreakpoint);
217         WI.debuggerManager.addBreakpoint(WI.debuggerManager.uncaughtExceptionsBreakpoint);
218
219         // COMPATIBILITY (iOS 10): DebuggerAgent.setPauseOnAssertions did not exist yet.
220         if (InspectorBackend.domains.Debugger.setPauseOnAssertions && WI.settings.showAssertionFailuresBreakpoint.value)
221             WI.debuggerManager.addBreakpoint(WI.debuggerManager.assertionFailuresBreakpoint);
222
223         for (let target of WI.targets)
224             this._addTarget(target);
225         this._updateCallStackTreeOutline();
226
227         if (WI.networkManager.mainFrame)
228             this._addResourcesRecursivelyForFrame(WI.networkManager.mainFrame);
229
230         for (let script of WI.debuggerManager.knownNonResourceScripts)
231             this._addScript(script);
232
233         if (WI.domDebuggerManager.supported) {
234             if (WI.settings.showAllRequestsBreakpoint.value)
235                 WI.domDebuggerManager.addURLBreakpoint(WI.domDebuggerManager.allRequestsBreakpoint);
236
237             for (let eventBreakpoint of WI.domDebuggerManager.eventBreakpoints)
238                 this._addBreakpoint(eventBreakpoint);
239
240             for (let domBreakpoint of WI.domDebuggerManager.domBreakpoints)
241                 this._addBreakpoint(domBreakpoint);
242
243             for (let eventListenerBreakpoint of WI.domManager.eventListenerBreakpoints)
244                 this._addBreakpoint(eventListenerBreakpoint);
245
246             for (let urlBreakpoints of WI.domDebuggerManager.urlBreakpoints)
247                 this._addBreakpoint(urlBreakpoints);
248         }
249
250         if (WI.debuggerManager.paused)
251             this._debuggerDidPause(null);
252
253         if (WI.debuggerManager.breakpointsDisabledTemporarily) {
254             if (WI.timelineManager.isCapturing())
255                 this._timelineCapturingWillStart();
256
257             if (WI.auditManager.runningState === WI.AuditManager.RunningState.Active || WI.auditManager.runningState === WI.AuditManager.RunningState.Stopping)
258                 this._handleAuditManagerTestScheduled();
259         }
260
261         this._updateBreakpointsDisabledBanner();
262     }
263
264     // Public
265
266     get minimumWidth()
267     {
268         return this._navigationBar.minimumWidth;
269     }
270
271     closed()
272     {
273         super.closed();
274
275         WI.Frame.removeEventListener(null, null, this);
276         WI.Target.removeEventListener(null, null, this);
277         WI.debuggerManager.removeEventListener(null, null, this);
278         WI.domDebuggerManager.removeEventListener(null, null, this);
279         WI.DOMBreakpoint.removeEventListener(null, null, this);
280         WI.timelineManager.removeEventListener(null, null, this);
281         WI.targetManager.removeEventListener(null, null, this);
282         WI.Breakpoint.removeEventListener(null, null, this);
283         WI.IssueMessage.removeEventListener(null, null, this);
284     }
285
286     showDefaultContentView()
287     {
288         if (WI.networkManager.mainFrame) {
289             let mainTreeElement = this._scriptsContentTreeOutline.findTreeElement(WI.networkManager.mainFrame.mainResource);
290             if (mainTreeElement && this.showDefaultContentViewForTreeElement(mainTreeElement))
291                 return;
292         }
293
294         let currentTreeElement = this._scriptsContentTreeOutline.children[0];
295         while (currentTreeElement && !currentTreeElement.root) {
296             if (currentTreeElement instanceof WI.ResourceTreeElement || currentTreeElement instanceof WI.ScriptTreeElement) {
297                 if (this.showDefaultContentViewForTreeElement(currentTreeElement))
298                     return;
299             }
300
301             currentTreeElement = currentTreeElement.traverseNextTreeElement(false, null, true);
302         }
303     }
304
305     treeElementForRepresentedObject(representedObject)
306     {
307         // The main resource is used as the representedObject instead of Frame in our tree.
308         if (representedObject instanceof WI.Frame)
309             representedObject = representedObject.mainResource;
310
311         let treeElement = this._breakpointsContentTreeOutline.findTreeElement(representedObject);
312         if (!treeElement)
313             treeElement = this._scriptsContentTreeOutline.findTreeElement(representedObject);
314
315         if (treeElement)
316             return treeElement;
317
318         // Only special case Script objects.
319         if (!(representedObject instanceof WI.Script)) {
320             console.error("Didn't find a TreeElement for representedObject", representedObject);
321             return null;
322         }
323
324         // If the Script has a URL we should have found it earlier.
325         if (representedObject.url) {
326             console.error("Didn't find a ScriptTreeElement for a Script with a URL.");
327             return null;
328         }
329
330         // Since the Script does not have a URL we consider it an 'anonymous' script. These scripts happen from calls to
331         // window.eval() or browser features like Auto Fill and Reader. They are not normally added to the sidebar, but since
332         // we have a ScriptContentView asking for the tree element we will make a ScriptTreeElement on demand and add it.
333
334         return this._addScript(representedObject);
335     }
336
337     // Protected
338
339     saveStateToCookie(cookie)
340     {
341         console.assert(cookie);
342
343         var selectedTreeElement = this._breakpointsContentTreeOutline.selectedTreeElement;
344         if (!selectedTreeElement) {
345             super.saveStateToCookie(cookie);
346             return;
347         }
348
349         var representedObject = selectedTreeElement.representedObject;
350
351         if (representedObject === WI.debuggerManager.allExceptionsBreakpoint) {
352             cookie[WI.DebuggerSidebarPanel.SelectedAllExceptionsCookieKey] = true;
353             return;
354         }
355
356         if (representedObject === WI.debuggerManager.uncaughtExceptionsBreakpoint) {
357             cookie[WI.DebuggerSidebarPanel.SelectedUncaughtExceptionsCookieKey] = true;
358             return;
359         }
360
361         if (representedObject === WI.debuggerManager.assertionFailuresBreakpoint) {
362             cookie[WI.DebuggerSidebarPanel.SelectedAssertionFailuresCookieKey] = true;
363             return;
364         }
365
366         if (representedObject === WI.domDebuggerManager.allRequestsBreakpoint) {
367             cookie[WI.DebuggerSidebarPanel.SelectedAllRequestsCookieKey] = true;
368             return;
369         }
370
371         super.saveStateToCookie(cookie);
372     }
373
374     restoreStateFromCookie(cookie, relaxedMatchDelay)
375     {
376         console.assert(cookie);
377
378         function revealAndSelect(treeOutline, breakpoint) {
379             let treeElement = treeOutline.findTreeElement(breakpoint);
380             if (!treeElement)
381                 return;
382
383             treeElement.revealAndSelect();
384         }
385
386         // Eagerly resolve the special breakpoints; otherwise, use the default behavior.
387         if (cookie[WI.DebuggerSidebarPanel.SelectedAllExceptionsCookieKey])
388             revealAndSelect(this._breakpointsContentTreeOutline, WI.debuggerManager.allExceptionsBreakpoint);
389         else if (cookie[WI.DebuggerSidebarPanel.SelectedUncaughtExceptionsCookieKey])
390             revealAndSelect(this._breakpointsContentTreeOutline, WI.debuggerManager.uncaughtExceptionsBreakpoint);
391         else if (cookie[WI.DebuggerSidebarPanel.SelectedAssertionFailuresCookieKey])
392             revealAndSelect(this._breakpointsContentTreeOutline, WI.debuggerManager.assertionFailuresBreakpoint);
393         else if (cookie[WI.DebuggerSidebarPanel.SelectedAllRequestsCookieKey])
394             revealAndSelect(this._breakpointsContentTreeOutline, WI.domDebuggerManager.allRequestsBreakpoint);
395         else
396             super.restoreStateFromCookie(cookie, relaxedMatchDelay);
397     }
398
399     // Popover delegate
400
401     willDismissPopover(popover)
402     {
403         let breakpoint = popover.breakpoint;
404         if (!breakpoint)
405             return;
406
407         if (breakpoint instanceof WI.EventBreakpoint)
408             WI.domDebuggerManager.addEventBreakpoint(breakpoint);
409         else if (breakpoint instanceof WI.URLBreakpoint)
410             WI.domDebuggerManager.addURLBreakpoint(breakpoint);
411     }
412
413     // Private
414
415     _debuggerWaitingToPause(event)
416     {
417         this._debuggerPauseResumeButtonItem.enabled = false;
418     }
419
420     _debuggerDidPause(event)
421     {
422         this.contentView.element.insertBefore(this._callStackSection.element, this.contentView.element.firstChild);
423
424         if (this._updatePauseReason())
425             this.contentView.element.insertBefore(this._pauseReasonSection.element, this.contentView.element.firstChild);
426
427         this._debuggerPauseResumeButtonItem.enabled = true;
428         this._debuggerPauseResumeButtonItem.toggled = true;
429         this._debuggerStepOverButtonItem.enabled = true;
430         this._debuggerStepIntoButtonItem.enabled = true;
431         this._debuggerStepOutButtonItem.enabled = true;
432
433         this.element.classList.add(WI.DebuggerSidebarPanel.DebuggerPausedStyleClassName);
434     }
435
436     _debuggerDidResume(event)
437     {
438         this._callStackSection.element.remove();
439
440         this._pauseReasonSection.element.remove();
441
442         this._debuggerPauseResumeButtonItem.enabled = true;
443         this._debuggerPauseResumeButtonItem.toggled = false;
444         this._debuggerStepOverButtonItem.enabled = false;
445         this._debuggerStepIntoButtonItem.enabled = false;
446         this._debuggerStepOutButtonItem.enabled = false;
447
448         this.element.classList.remove(WI.DebuggerSidebarPanel.DebuggerPausedStyleClassName);
449     }
450
451     _breakpointsEnabledDidChange(event)
452     {
453         this._debuggerBreakpointsButtonItem.activated = WI.debuggerManager.breakpointsEnabled;
454
455         this._updateBreakpointsDisabledBanner();
456     }
457
458     _addBreakpoint(breakpoint)
459     {
460         let constructor = WI.BreakpointTreeElement;
461         let options = {};
462         let parentTreeElement = this._breakpointsContentTreeOutline;
463
464         let getDOMNodeTreeElement = (domNode) => {
465             console.assert(domNode, "Missing DOMNode for identifier", breakpoint.domNodeIdentifier);
466             if (!domNode)
467                 return null;
468
469             let domNodeTreeElement = this._breakpointsContentTreeOutline.findTreeElement(domNode);
470             if (!domNodeTreeElement) {
471                 domNodeTreeElement = new WI.DOMNodeTreeElement(domNode);
472                 this._addTreeElement(domNodeTreeElement, parentTreeElement);
473             }
474             return domNodeTreeElement;
475         };
476
477         if (breakpoint === WI.debuggerManager.allExceptionsBreakpoint) {
478             options.className = WI.DebuggerSidebarPanel.ExceptionIconStyleClassName;
479             options.title = WI.UIString("All Exceptions");
480         } else if (breakpoint === WI.debuggerManager.uncaughtExceptionsBreakpoint) {
481             options.className = WI.DebuggerSidebarPanel.ExceptionIconStyleClassName;
482             options.title = WI.UIString("Uncaught Exceptions");
483         } else if (breakpoint === WI.debuggerManager.assertionFailuresBreakpoint) {
484             options.className = WI.DebuggerSidebarPanel.AssertionIconStyleClassName;
485             options.title = WI.UIString("Assertion Failures");
486         } else if (breakpoint instanceof WI.DOMBreakpoint) {
487             if (!breakpoint.domNodeIdentifier)
488                 return null;
489
490             constructor = WI.DOMBreakpointTreeElement;
491
492             let domNode = WI.domManager.nodeForId(breakpoint.domNodeIdentifier);
493             parentTreeElement = getDOMNodeTreeElement(domNode);
494         } else if (breakpoint instanceof WI.EventBreakpoint) {
495             constructor = WI.EventBreakpointTreeElement;
496
497             if (breakpoint.eventListener) {
498                 let eventTargetTreeElement = null;
499                 if (breakpoint.eventListener.onWindow) {
500                     if (!DebuggerSidebarPanel.__windowEventTargetRepresentedObject)
501                         DebuggerSidebarPanel.__windowEventTargetRepresentedObject = {__window: true};
502
503                     eventTargetTreeElement = this._breakpointsContentTreeOutline.findTreeElement(DebuggerSidebarPanel.__windowEventTargetRepresentedObject);
504                     if (!eventTargetTreeElement) {
505                         const subtitle = null;
506                         eventTargetTreeElement = new WI.GeneralTreeElement(["event-target-window"], WI.unlocalizedString("window"), subtitle, DebuggerSidebarPanel.__windowEventTargetRepresentedObject);
507                         this._addTreeElement(eventTargetTreeElement, parentTreeElement);
508                     }
509                 } else if (breakpoint.eventListener.node)
510                     eventTargetTreeElement = getDOMNodeTreeElement(breakpoint.eventListener.node);
511                 if (eventTargetTreeElement)
512                     parentTreeElement = eventTargetTreeElement;
513             }
514         } else if (breakpoint instanceof WI.URLBreakpoint) {
515             constructor = WI.URLBreakpointTreeElement;
516
517             if (breakpoint === WI.domDebuggerManager.allRequestsBreakpoint) {
518                 options.className = WI.DebuggerSidebarPanel.AssertionIconStyleClassName;
519                 options.title = WI.UIString("All Requests");
520             }
521         } else {
522             let sourceCode = breakpoint.sourceCodeLocation && breakpoint.sourceCodeLocation.displaySourceCode;
523             if (!sourceCode)
524                 return null;
525
526             if (this._breakpointsContentTreeOutline.findTreeElement(breakpoint))
527                 return null;
528
529             parentTreeElement = this._addTreeElementForSourceCodeToTreeOutline(sourceCode, this._breakpointsContentTreeOutline);
530
531             // Mark disabled breakpoints as resolved if there is source code loaded with that URL.
532             // This gives the illusion the breakpoint was resolved, but since we don't send disabled
533             // breakpoints to the backend we don't know for sure. If the user enables the breakpoint
534             // it will be resolved properly.
535             if (breakpoint.disabled)
536                 breakpoint.resolved = true;
537         }
538
539         let breakpointTreeElement = new constructor(breakpoint, options);
540         this._addTreeElement(breakpointTreeElement, parentTreeElement);
541         if (parentTreeElement.children.length === 1)
542             parentTreeElement.expand();
543         return breakpointTreeElement;
544     }
545
546     _removeBreakpoint(breakpoint)
547     {
548         if (this._pauseReasonTreeOutline) {
549             let pauseReasonBreakpointTreeElement = this._pauseReasonTreeOutline.getCachedTreeElement(breakpoint);
550             if (pauseReasonBreakpointTreeElement)
551                 pauseReasonBreakpointTreeElement.status = null;
552         }
553
554         let breakpointTreeElement = this._breakpointsContentTreeOutline.getCachedTreeElement(breakpoint);
555         if (!breakpointTreeElement)
556             return;
557
558         this._removeDebuggerTreeElement(breakpointTreeElement);
559     }
560
561     _addBreakpointsForSourceCode(sourceCode)
562     {
563         var breakpoints = WI.debuggerManager.breakpointsForSourceCode(sourceCode);
564         for (var i = 0; i < breakpoints.length; ++i)
565             this._addBreakpoint(breakpoints[i], sourceCode);
566     }
567
568     _addIssuesForSourceCode(sourceCode)
569     {
570         var issues = WI.consoleManager.issuesForSourceCode(sourceCode);
571         for (var issue of issues)
572             this._addIssue(issue);
573     }
574
575     _addTreeElementForSourceCodeToTreeOutline(sourceCode, treeOutline)
576     {
577         let treeElement = treeOutline.getCachedTreeElement(sourceCode);
578         if (!treeElement) {
579             if (sourceCode instanceof WI.SourceMapResource)
580                 treeElement = new WI.SourceMapResourceTreeElement(sourceCode);
581             else if (sourceCode instanceof WI.Resource)
582                 treeElement = new WI.ResourceTreeElement(sourceCode);
583             else if (sourceCode instanceof WI.Script)
584                 treeElement = new WI.ScriptTreeElement(sourceCode);
585         }
586
587         if (!treeElement) {
588             console.error("Unknown sourceCode instance", sourceCode);
589             return null;
590         }
591
592         if (!treeElement.parent) {
593             treeElement.hasChildren = false;
594             treeElement.expand();
595
596             this._addTreeElement(treeElement, treeOutline);
597         }
598
599         return treeElement;
600     }
601
602     _addResourcesRecursivelyForFrame(frame)
603     {
604         this._addResource(frame.mainResource);
605
606         for (let resource of frame.resourceCollection)
607             this._addResource(resource);
608
609         for (let childFrame of frame.childFrameCollection)
610             this._addResourcesRecursivelyForFrame(childFrame);
611     }
612
613     _resourceAdded(event)
614     {
615         this._addResource(event.data.resource);
616     }
617
618     _addResource(resource)
619     {
620         if (![WI.Resource.Type.Document, WI.Resource.Type.Script].includes(resource.type))
621             return;
622
623         let treeElement = this._addTreeElementForSourceCodeToTreeOutline(resource, this._scriptsContentTreeOutline);
624         this._addBreakpointsForSourceCode(resource);
625         this._addIssuesForSourceCode(resource);
626
627         if (this.parentSidebar && !this.contentBrowser.currentContentView)
628             this.showDefaultContentViewForTreeElement(treeElement);
629     }
630
631     _mainResourceDidChange(event)
632     {
633         if (event.target.isMainFrame()) {
634             // Aggressively prune resources now so the old resources are removed before
635             // the new main resource is added below. This avoids a visual flash when the
636             // prune normally happens on a later event loop cycle.
637             this.pruneStaleResourceTreeElements();
638             this.contentBrowser.contentViewContainer.closeAllContentViews();
639
640             for (let domBreakpoint of WI.domDebuggerManager.domBreakpoints)
641                 this._removeBreakpoint(domBreakpoint);
642         }
643
644         if (!event.data.oldMainResource) {
645             var resource = event.target.mainResource;
646             this._addTreeElementForSourceCodeToTreeOutline(resource, this._scriptsContentTreeOutline);
647             this._addBreakpointsForSourceCode(resource);
648             this._addIssuesForSourceCode(resource);
649         }
650     }
651
652     _timelineCapturingWillStart(event)
653     {
654         this._updateTemporarilyDisabledBreakpointsButtons();
655
656         this.contentView.element.insertBefore(this._timelineRecordingWarningElement, this.contentView.element.firstChild);
657         this._updateBreakpointsDisabledBanner();
658     }
659
660     _timelineCapturingStopped(event)
661     {
662         this._updateTemporarilyDisabledBreakpointsButtons();
663
664         this._timelineRecordingWarningElement.remove();
665         this._updateBreakpointsDisabledBanner();
666     }
667
668     _handleAuditManagerTestScheduled(event)
669     {
670         this._updateTemporarilyDisabledBreakpointsButtons();
671
672         this.contentView.element.insertBefore(this._auditTestWarningElement, this.contentView.element.firstChild);
673         this._updateBreakpointsDisabledBanner();
674     }
675
676     _handleAuditManagerTestCompleted(event)
677     {
678         this._updateTemporarilyDisabledBreakpointsButtons();
679
680         this._auditTestWarningElement.remove();
681         this._updateBreakpointsDisabledBanner();
682     }
683
684     _updateTemporarilyDisabledBreakpointsButtons()
685     {
686         let breakpointsDisabledTemporarily = WI.debuggerManager.breakpointsDisabledTemporarily;
687         this._debuggerBreakpointsButtonItem.enabled = !breakpointsDisabledTemporarily;
688         this._debuggerPauseResumeButtonItem.enabled = !breakpointsDisabledTemporarily;
689     }
690
691     _updateBreakpointsDisabledBanner()
692     {
693         let breakpointsEnabled = WI.debuggerManager.breakpointsEnabled;
694         let timelineWarningShowing = !!this._timelineRecordingWarningElement.parentElement;
695         let auditWarningShowing = !!this._auditTestWarningElement.parentElement;
696
697         if (!breakpointsEnabled && !timelineWarningShowing && !auditWarningShowing)
698             this.contentView.element.insertBefore(this._breakpointsDisabledWarningElement, this.contentView.element.firstChild);
699         else
700             this._breakpointsDisabledWarningElement.remove();
701     }
702
703     _scriptAdded(event)
704     {
705         this._addScript(event.data.script);
706     }
707
708     _addScript(script)
709     {
710         // COMPATIBILITY(iOS 9): Backends could send the frontend built-in code, filter out JSC internals.
711         if (!script.url && !script.sourceURL)
712             return null;
713
714         // In general, do not show dynamically added script elements.
715         if (script.dynamicallyAddedScriptElement && !script.sourceURL)
716             return null;
717
718         // Don't add breakpoints if the script is represented by a Resource. They were
719         // already added by _resourceAdded.
720         if (script.resource)
721             return null;
722
723         let treeElement = this._addTreeElementForSourceCodeToTreeOutline(script, this._scriptsContentTreeOutline);
724         this._addBreakpointsForSourceCode(script);
725         this._addIssuesForSourceCode(script);
726
727         if (this.parentSidebar && !this.contentBrowser.currentContentView)
728             this.showDefaultContentViewForTreeElement(treeElement);
729
730         return treeElement;
731     }
732
733     _scriptRemoved(event)
734     {
735         function removeScript(script, treeOutline)
736         {
737             let scriptTreeElement = treeOutline.getCachedTreeElement(script);
738             if (scriptTreeElement)
739                 scriptTreeElement.parent.removeChild(scriptTreeElement);
740         }
741
742         let script = event.data.script;
743         removeScript(script, this._breakpointsContentTreeOutline);
744         removeScript(script, this._scriptsContentTreeOutline);
745     }
746
747     _scriptsCleared(event)
748     {
749         for (var i = this._breakpointsContentTreeOutline.children.length - 1; i >= 0; --i) {
750             var treeElement = this._breakpointsContentTreeOutline.children[i];
751             if (!(treeElement instanceof WI.ScriptTreeElement))
752                 continue;
753
754             this._breakpointsContentTreeOutline.removeChildAtIndex(i, true, true);
755         }
756
757         this._scriptsContentTreeOutline.removeChildren();
758
759         this._addResourcesRecursivelyForFrame(WI.networkManager.mainFrame);
760     }
761
762     _breakpointAdded(event)
763     {
764         var breakpoint = event.data.breakpoint;
765         this._addBreakpoint(breakpoint);
766     }
767
768     _breakpointRemoved(event)
769     {
770         var breakpoint = event.data.breakpoint;
771         this._removeBreakpoint(breakpoint);
772     }
773
774     _findThreadTreeElementForTarget(target)
775     {
776         for (let child of this._callStackTreeOutline.children) {
777             if (child.target === target)
778                 return child;
779         }
780
781         return null;
782     }
783
784     _targetAdded(event)
785     {
786         this._addTarget(event.data.target);
787     }
788
789     _addTarget(target)
790     {
791         let treeElement = new WI.ThreadTreeElement(target);
792         this._callStackTreeOutline.appendChild(treeElement);
793
794         // FIXME: When WI.mainTarget changes?
795         if (target === WI.mainTarget)
796             this._mainTargetTreeElement = treeElement;
797
798         this._updateCallStackTreeOutline();
799     }
800
801     _targetRemoved(event)
802     {
803         let target = event.data.target;
804         let treeElement = this._findThreadTreeElementForTarget(target);
805         this._callStackTreeOutline.removeChild(treeElement);
806
807         this._updateCallStackTreeOutline();
808     }
809
810     _updateCallStackTreeOutline()
811     {
812         let singleThreadShowing = WI.targets.length <= 1;
813         this._callStackTreeOutline.element.classList.toggle("single-thread", singleThreadShowing);
814         if (this._mainTargetTreeElement)
815             this._mainTargetTreeElement.selectable = !singleThreadShowing;
816     }
817
818     _handleDebuggerObjectDisplayLocationDidChange(event)
819     {
820         var debuggerObject = event.target;
821
822         if (event.data.oldDisplaySourceCode === debuggerObject.sourceCodeLocation.displaySourceCode)
823             return;
824
825         // A known debugger object (breakpoint, issueMessage, etc.) moved between resources. Remove
826         // the old tree element and create a new tree element with the updated file.
827
828         let wasSelected = false;
829         let oldDebuggerTreeElement = this._breakpointsContentTreeOutline.getCachedTreeElement(debuggerObject);
830         if (oldDebuggerTreeElement)
831             wasSelected = oldDebuggerTreeElement.selected;
832
833         let newDebuggerTreeElement = null;
834         if (debuggerObject instanceof WI.Breakpoint)
835             newDebuggerTreeElement = this._addBreakpoint(debuggerObject);
836         else if (debuggerObject instanceof WI.IssueMessage)
837             newDebuggerTreeElement = this._addIssue(debuggerObject);
838         if (!newDebuggerTreeElement)
839             return;
840
841         if (oldDebuggerTreeElement)
842             this._removeDebuggerTreeElement(oldDebuggerTreeElement);
843
844         if (wasSelected)
845             newDebuggerTreeElement.revealAndSelect(true, false, true);
846     }
847
848     _removeDebuggerTreeElement(debuggerTreeElement)
849     {
850         // If this is a BreakpointTreeElement being deleted because of a cause
851         // outside of the TreeOutline then deselect if it is selected to avoid
852         // TreeOutline selection changes causing unexpected ContentView changes.
853         if (!debuggerTreeElement.__deletedViaDeleteKeyboardShortcut)
854             debuggerTreeElement.deselect();
855
856         let parentTreeElement = debuggerTreeElement.parent;
857         parentTreeElement.removeChild(debuggerTreeElement);
858
859         if (parentTreeElement.children.length || parentTreeElement === this._breakpointsContentTreeOutline)
860             return;
861
862         parentTreeElement.treeOutline.removeChild(parentTreeElement);
863     }
864
865     _debuggerCallFramesDidChange(event)
866     {
867         let target = event.data.target;
868         let treeElement = this._findThreadTreeElementForTarget(target);
869         treeElement.refresh();
870     }
871
872     _debuggerActiveCallFrameDidChange()
873     {
874         if (this._activeCallFrameTreeElement) {
875             this._activeCallFrameTreeElement.isActiveCallFrame = false;
876             this._activeCallFrameTreeElement = null;
877         }
878
879         if (!WI.debuggerManager.activeCallFrame)
880             return;
881
882         this._activeCallFrameTreeElement = this._callStackTreeOutline.findTreeElement(WI.debuggerManager.activeCallFrame);
883         if (this._activeCallFrameTreeElement)
884             this._activeCallFrameTreeElement.isActiveCallFrame = true;
885     }
886
887     _breakpointsBeneathTreeElement(treeElement)
888     {
889         console.assert(treeElement instanceof WI.ResourceTreeElement || treeElement instanceof WI.ScriptTreeElement);
890         if (!(treeElement instanceof WI.ResourceTreeElement) && !(treeElement instanceof WI.ScriptTreeElement))
891             return [];
892
893         var breakpoints = [];
894         var breakpointTreeElements = treeElement.children;
895         for (var i = 0; i < breakpointTreeElements.length; ++i) {
896             console.assert(breakpointTreeElements[i] instanceof WI.BreakpointTreeElement);
897             console.assert(breakpointTreeElements[i].breakpoint);
898             var breakpoint = breakpointTreeElements[i].breakpoint;
899             if (breakpoint)
900                 breakpoints.push(breakpoint);
901         }
902
903         return breakpoints;
904     }
905
906     _removeAllBreakpoints(breakpoints)
907     {
908         for (var i = 0; i < breakpoints.length; ++i) {
909             var breakpoint = breakpoints[i];
910             if (WI.debuggerManager.isBreakpointRemovable(breakpoint))
911                 WI.debuggerManager.removeBreakpoint(breakpoint);
912         }
913     }
914
915     _toggleAllBreakpoints(breakpoints, disabled)
916     {
917         for (var i = 0; i < breakpoints.length; ++i)
918             breakpoints[i].disabled = disabled;
919     }
920
921     _breakpointTreeOutlineDeleteTreeElement(treeElement)
922     {
923         console.assert(treeElement.selected);
924
925         if (treeElement.representedObject === DebuggerSidebarPanel.__windowEventTargetRepresentedObject) {
926             let eventBreakpointsOnWindow = WI.domManager.eventListenerBreakpoints.filter((eventBreakpoint) => eventBreakpoint.eventListener.onWindow);
927             for (let eventBreakpoint of eventBreakpointsOnWindow)
928                 WI.domManager.removeBreakpointForEventListener(eventBreakpoint.eventListener);
929             return true;
930         }
931
932         console.assert(treeElement instanceof WI.ResourceTreeElement || treeElement instanceof WI.ScriptTreeElement);
933         if (!(treeElement instanceof WI.ResourceTreeElement) && !(treeElement instanceof WI.ScriptTreeElement))
934             return false;
935
936         var wasTopResourceTreeElement = treeElement.previousSibling === this._assertionsBreakpointTreeElement || treeElement.previousSibling === this._allUncaughtExceptionsBreakpointTreeElement;
937         var nextSibling = treeElement.nextSibling;
938
939         var breakpoints = this._breakpointsBeneathTreeElement(treeElement);
940         this._removeAllBreakpoints(breakpoints);
941
942         if (wasTopResourceTreeElement && nextSibling)
943             nextSibling.select(true, true);
944
945         return true;
946     }
947
948     _breakpointTreeOutlineContextMenuTreeElement(contextMenu, event, treeElement)
949     {
950         // This check is necessary since the context menu is created by the TreeOutline, meaning
951         // that any child could be the target of the context menu event.
952         if (!(treeElement instanceof WI.ResourceTreeElement) && !(treeElement instanceof WI.ScriptTreeElement))
953             return;
954
955         let breakpoints = this._breakpointsBeneathTreeElement(treeElement);
956         let shouldDisable = breakpoints.some((breakpoint) => !breakpoint.disabled);
957
958         let removeAllResourceBreakpoints = () => {
959             this._removeAllBreakpoints(breakpoints);
960         };
961
962         let toggleAllResourceBreakpoints = () => {
963             this._toggleAllBreakpoints(breakpoints, shouldDisable);
964         };
965
966         if (shouldDisable)
967             contextMenu.appendItem(WI.UIString("Disable Breakpoints"), toggleAllResourceBreakpoints);
968         else
969             contextMenu.appendItem(WI.UIString("Enable Breakpoints"), toggleAllResourceBreakpoints);
970         contextMenu.appendItem(WI.UIString("Delete Breakpoints"), removeAllResourceBreakpoints);
971     }
972
973     _treeSelectionDidChange(event)
974     {
975         if (!this.selected)
976             return;
977
978         let treeElement = event.target.selectedTreeElement;
979         if (!treeElement)
980             return;
981
982         if (treeElement instanceof WI.DOMNodeTreeElement
983             || treeElement instanceof WI.DOMBreakpointTreeElement
984             || treeElement instanceof WI.EventBreakpointTreeElement
985             || treeElement instanceof WI.URLBreakpointTreeElement)
986             return;
987
988         if (treeElement.representedObject === DebuggerSidebarPanel.__windowEventTargetRepresentedObject)
989             return;
990
991         const options = {
992             ignoreNetworkTab: true,
993             ignoreSearchTab: true,
994         };
995
996         if (treeElement instanceof WI.ResourceTreeElement || treeElement instanceof WI.ScriptTreeElement) {
997             WI.showSourceCode(treeElement.representedObject, options);
998             return;
999         }
1000
1001         if (treeElement instanceof WI.CallFrameTreeElement) {
1002             let callFrame = treeElement.callFrame;
1003             if (callFrame.id)
1004                 WI.debuggerManager.activeCallFrame = callFrame;
1005
1006             if (callFrame.sourceCodeLocation)
1007                 WI.showSourceCodeLocation(callFrame.sourceCodeLocation, options);
1008
1009             return;
1010         }
1011
1012         if (treeElement instanceof WI.IssueTreeElement) {
1013             WI.showSourceCodeLocation(treeElement.issueMessage.sourceCodeLocation, options);
1014             return;
1015         }
1016
1017         if (!(treeElement instanceof WI.BreakpointTreeElement))
1018             return;
1019
1020         let breakpoint = treeElement.breakpoint;
1021         if (treeElement.treeOutline === this._pauseReasonTreeOutline) {
1022             WI.showSourceCodeLocation(breakpoint.sourceCodeLocation, options);
1023             return;
1024         }
1025
1026         if (!treeElement.parent.representedObject)
1027             return;
1028
1029         console.assert(treeElement.parent.representedObject instanceof WI.SourceCode);
1030         if (!(treeElement.parent.representedObject instanceof WI.SourceCode))
1031             return;
1032
1033         WI.showSourceCodeLocation(breakpoint.sourceCodeLocation, options);
1034     }
1035
1036     _addTreeElement(treeElement, parentTreeElement)
1037     {
1038         if (!parentTreeElement)
1039             parentTreeElement = this._breakpointsContentTreeOutline;
1040
1041         let comparator = (a, b) => {
1042             const rankFunctions = [
1043                 (treeElement) => treeElement.representedObject === WI.debuggerManager.allExceptionsBreakpoint,
1044                 (treeElement) => treeElement.representedObject === WI.debuggerManager.uncaughtExceptionsBreakpoint,
1045                 (treeElement) => treeElement.representedObject === WI.debuggerManager.assertionFailuresBreakpoint,
1046                 (treeElement) => treeElement.representedObject === WI.domDebuggerManager.allRequestsBreakpoint,
1047                 (treeElement) => treeElement instanceof WI.BreakpointTreeElement || treeElement instanceof WI.ResourceTreeElement || treeElement instanceof WI.ScriptTreeElement,
1048                 (treeElement) => treeElement instanceof WI.EventBreakpointTreeElement,
1049                 (treeElement) => treeElement instanceof WI.DOMNodeTreeElement,
1050                 (treeElement) => treeElement instanceof WI.DOMBreakpointTreeElement,
1051                 (treeElement) => treeElement instanceof WI.URLBreakpointTreeElement,
1052             ];
1053
1054             let aRank = rankFunctions.findIndex((rankFunction) => rankFunction(a));
1055             let bRank = rankFunctions.findIndex((rankFunction) => rankFunction(b));
1056             if (aRank >= 0 && bRank >= 0) {
1057                 if (aRank < bRank)
1058                     return -1;
1059                 if (bRank < aRank)
1060                     return 1;
1061             }
1062
1063             if (a instanceof WI.BreakpointTreeElement && b instanceof WI.BreakpointTreeElement)
1064                 return this._compareBreakpointTreeElements(a, b);
1065
1066             return a.mainTitle.extendedLocaleCompare(b.mainTitle) || a.subtitle.extendedLocaleCompare(b.subtitle);
1067         };
1068
1069         parentTreeElement.insertChild(treeElement, insertionIndexForObjectInListSortedByFunction(treeElement, parentTreeElement.children, comparator));
1070     }
1071
1072     _compareBreakpointTreeElements(a, b)
1073     {
1074         if (!a.representedObject || !b.representedObject)
1075             return 0;
1076
1077         let aLocation = a.representedObject.sourceCodeLocation;
1078         let bLocation = b.representedObject.sourceCodeLocation;
1079         if (!aLocation || !bLocation)
1080             return 0;
1081
1082         var comparisonResult = aLocation.displayLineNumber - bLocation.displayLineNumber;
1083         if (comparisonResult !== 0)
1084             return comparisonResult;
1085
1086         return aLocation.displayColumnNumber - bLocation.displayColumnNumber;
1087     }
1088
1089     _updatePauseReason()
1090     {
1091         this._pauseReasonTreeOutline = null;
1092
1093         this._updatePauseReasonGotoArrow();
1094         return this._updatePauseReasonSection();
1095     }
1096
1097     _updatePauseReasonSection()
1098     {
1099         let target = WI.debuggerManager.activeCallFrame.target;
1100         let targetData = WI.debuggerManager.dataForTarget(target);
1101         let {pauseReason, pauseData} = targetData;
1102
1103         switch (pauseReason) {
1104         case WI.DebuggerManager.PauseReason.AnimationFrame:
1105             console.assert(pauseData, "Expected data with an animation frame, but found none.");
1106             if (!pauseData)
1107                 return false;
1108
1109             var eventBreakpoint = WI.domDebuggerManager.eventBreakpointForTypeAndEventName(WI.EventBreakpoint.Type.AnimationFrame, pauseData.eventName);
1110             console.assert(eventBreakpoint, "Expected AnimationFrame breakpoint for event name.", pauseData.eventName);
1111             if (!eventBreakpoint)
1112                 return false;
1113
1114             this._pauseReasonTreeOutline = this.createContentTreeOutline({suppressFiltering: true});
1115
1116             var eventBreakpointTreeElement = new WI.EventBreakpointTreeElement(eventBreakpoint, {
1117                 className: WI.DebuggerSidebarPanel.PausedBreakpointIconStyleClassName,
1118                 title: WI.UIString("%s Fired").format(pauseData.eventName),
1119             });
1120             this._pauseReasonTreeOutline.appendChild(eventBreakpointTreeElement);
1121
1122             var eventBreakpointRow = new WI.DetailsSectionRow;
1123             eventBreakpointRow.element.appendChild(this._pauseReasonTreeOutline.element);
1124
1125             this._pauseReasonGroup.rows = [eventBreakpointRow];
1126             return true;
1127
1128         case WI.DebuggerManager.PauseReason.Assertion:
1129             // FIXME: We should include the assertion condition string.
1130             console.assert(pauseData, "Expected data with an assertion, but found none.");
1131             if (pauseData && pauseData.message) {
1132                 this._pauseReasonTextRow.text = WI.UIString("Assertion with message: %s").format(pauseData.message);
1133                 return true;
1134             }
1135
1136             this._pauseReasonTextRow.text = WI.UIString("Assertion Failed");
1137             this._pauseReasonGroup.rows = [this._pauseReasonTextRow];
1138             return true;
1139
1140         case WI.DebuggerManager.PauseReason.Breakpoint:
1141             console.assert(pauseData, "Expected breakpoint identifier, but found none.");
1142             if (pauseData && pauseData.breakpointId) {
1143                 this._pauseReasonTreeOutline = this.createContentTreeOutline({suppressFiltering: true});
1144                 this._pauseReasonTreeOutline.addEventListener(WI.TreeOutline.Event.SelectionDidChange, this._treeSelectionDidChange, this);
1145
1146                 let breakpoint = WI.debuggerManager.breakpointForIdentifier(pauseData.breakpointId);
1147                 let breakpointTreeElement = new WI.BreakpointTreeElement(breakpoint, {
1148                     className: WI.DebuggerSidebarPanel.PausedBreakpointIconStyleClassName,
1149                     title: WI.UIString("Triggered Breakpoint"),
1150                 });
1151                 let breakpointDetailsSection = new WI.DetailsSectionRow;
1152                 this._pauseReasonTreeOutline.appendChild(breakpointTreeElement);
1153                 breakpointDetailsSection.element.appendChild(this._pauseReasonTreeOutline.element);
1154
1155                 this._pauseReasonGroup.rows = [breakpointDetailsSection];
1156                 return true;
1157             }
1158             break;
1159
1160         case WI.DebuggerManager.PauseReason.CSPViolation:
1161             console.assert(pauseData, "Expected data with a CSP Violation, but found none.");
1162             if (pauseData) {
1163                 // COMPATIBILITY (iOS 8): 'directive' was 'directiveText'.
1164                 this._pauseReasonTextRow.text = WI.UIString("Content Security Policy violation of directive: %s").format(pauseData.directive || pauseData.directiveText);
1165                 this._pauseReasonGroup.rows = [this._pauseReasonTextRow];
1166                 return true;
1167             }
1168             break;
1169
1170         case WI.DebuggerManager.PauseReason.DebuggerStatement:
1171             this._pauseReasonTextRow.text = WI.UIString("Debugger Statement");
1172             this._pauseReasonGroup.rows = [this._pauseReasonTextRow];
1173             return true;
1174
1175         case WI.DebuggerManager.PauseReason.DOM:
1176             console.assert(WI.domDebuggerManager.supported);
1177             console.assert(pauseData, "Expected DOM breakpoint data, but found none.");
1178             if (pauseData && pauseData.nodeId) {
1179                 let domNode = WI.domManager.nodeForId(pauseData.nodeId);
1180                 let domBreakpoints = WI.domDebuggerManager.domBreakpointsForNode(domNode);
1181                 let domBreakpoint;
1182                 for (let breakpoint of domBreakpoints) {
1183                     if (breakpoint.type === pauseData.type) {
1184                         domBreakpoint = breakpoint;
1185                         break;
1186                     }
1187                 }
1188
1189                 if (!domBreakpoint)
1190                     return;
1191
1192                 this._pauseReasonTreeOutline = this.createContentTreeOutline({suppressFiltering: true});
1193
1194                 let type = WI.DOMBreakpointTreeElement.displayNameForType(domBreakpoint.type);
1195                 let domBreakpointTreeElement = new WI.DOMBreakpointTreeElement(domBreakpoint, {
1196                     className: WI.DebuggerSidebarPanel.PausedBreakpointIconStyleClassName,
1197                     title: type,
1198                 });
1199                 let domBreakpointRow = new WI.DetailsSectionRow;
1200                 this._pauseReasonTreeOutline.appendChild(domBreakpointTreeElement);
1201                 domBreakpointRow.element.appendChild(this._pauseReasonTreeOutline.element);
1202
1203                 let ownerElementRow = new WI.DetailsSectionSimpleRow(WI.UIString("Element"), WI.linkifyNodeReference(domNode));
1204                 this._pauseReasonGroup.rows = [domBreakpointRow, ownerElementRow];
1205
1206                 if (domBreakpoint.type !== WI.DOMBreakpoint.Type.SubtreeModified)
1207                     return true;
1208
1209                 console.assert(pauseData.targetNode);
1210
1211                 let remoteObject = WI.RemoteObject.fromPayload(pauseData.targetNode, target);
1212                 remoteObject.pushNodeToFrontend((nodeId) => {
1213                     if (!nodeId)
1214                         return;
1215
1216                     let node = WI.domManager.nodeForId(nodeId);
1217                     console.assert(node, "Missing node for id.", nodeId);
1218                     if (!node)
1219                         return;
1220
1221                     let fragment = document.createDocumentFragment();
1222                     let description = pauseData.insertion ? WI.UIString("Child added to ") : WI.UIString("Removed descendant ");
1223                     fragment.append(description, WI.linkifyNodeReference(node));
1224
1225                     let targetDescriptionRow = new WI.DetailsSectionSimpleRow(WI.UIString("Details"), fragment);
1226                     targetDescriptionRow.element.classList.add("target-description");
1227
1228                     this._pauseReasonGroup.rows = this._pauseReasonGroup.rows.concat(targetDescriptionRow);
1229                 });
1230
1231                 return true;
1232             }
1233             break;
1234
1235         case WI.DebuggerManager.PauseReason.EventListener:
1236             console.assert(pauseData, "Expected data with an event listener, but found none.");
1237             if (!pauseData)
1238                 return false;
1239
1240             var eventBreakpoint = null;
1241             if (pauseData.eventListenerId)
1242                 eventBreakpoint = WI.domManager.breakpointForEventListenerId(pauseData.eventListenerId);
1243             if (!eventBreakpoint)
1244                 eventBreakpoint = WI.domDebuggerManager.eventBreakpointForTypeAndEventName(WI.EventBreakpoint.Type.Listener, pauseData.eventName);
1245
1246             console.assert(eventBreakpoint, "Expected Event Listener breakpoint for event name.", pauseData.eventName);
1247             if (!eventBreakpoint)
1248                 return false;
1249
1250             this._pauseReasonTreeOutline = this.createContentTreeOutline({suppressFiltering: true});
1251
1252             var eventBreakpointTreeElement = new WI.EventBreakpointTreeElement(eventBreakpoint, {
1253                 className: WI.DebuggerSidebarPanel.PausedBreakpointIconStyleClassName,
1254                 title: WI.UIString("\u201C%s\u201D Event Fired").format(pauseData.eventName),
1255             });
1256             this._pauseReasonTreeOutline.appendChild(eventBreakpointTreeElement);
1257
1258             var eventBreakpointRow = new WI.DetailsSectionRow;
1259             eventBreakpointRow.element.appendChild(this._pauseReasonTreeOutline.element);
1260
1261             var rows = [eventBreakpointRow];
1262
1263             var eventListener = eventBreakpoint.eventListener;
1264             if (eventListener) {
1265                 console.assert(eventListener.eventListenerId === pauseData.eventListenerId);
1266
1267                 let value = null;
1268                 if (eventListener.onWindow)
1269                     value = WI.unlocalizedString("window");
1270                 else if (eventListener.node)
1271                     value = WI.linkifyNodeReference(eventListener.node);
1272                 if (value)
1273                     rows.push(new WI.DetailsSectionSimpleRow(WI.UIString("Target"), value));
1274             }
1275
1276             this._pauseReasonGroup.rows = rows;
1277             return true;
1278
1279         case WI.DebuggerManager.PauseReason.Exception:
1280             console.assert(pauseData, "Expected data with an exception, but found none.");
1281             if (pauseData) {
1282                 // FIXME: We should improve the appearance of thrown objects. This works well for exception strings.
1283                 var data = WI.RemoteObject.fromPayload(pauseData, target);
1284                 this._pauseReasonTextRow.text = WI.UIString("Exception with thrown value: %s").format(data.description);
1285                 this._pauseReasonGroup.rows = [this._pauseReasonTextRow];
1286                 return true;
1287             }
1288             break;
1289
1290         case WI.DebuggerManager.PauseReason.PauseOnNextStatement:
1291             this._pauseReasonTextRow.text = WI.UIString("Immediate Pause Requested");
1292             this._pauseReasonGroup.rows = [this._pauseReasonTextRow];
1293             return true;
1294
1295         case WI.DebuggerManager.PauseReason.Timer:
1296             console.assert(pauseData, "Expected data with a timer, but found none.");
1297             if (!pauseData)
1298                 return false;
1299
1300             var eventBreakpoint = WI.domDebuggerManager.eventBreakpointForTypeAndEventName(WI.EventBreakpoint.Type.Timer, pauseData.eventName);
1301             console.assert(eventBreakpoint, "Expected Timer breakpoint for event name.", pauseData.eventName);
1302             if (!eventBreakpoint)
1303                 return false;
1304
1305             this._pauseReasonTreeOutline = this.createContentTreeOutline({suppressFiltering: true});
1306
1307             var eventBreakpointTreeElement = new WI.EventBreakpointTreeElement(eventBreakpoint, {
1308                 className: WI.DebuggerSidebarPanel.PausedBreakpointIconStyleClassName,
1309                 title: WI.UIString("%s Fired").format(pauseData.eventName),
1310             });
1311             this._pauseReasonTreeOutline.appendChild(eventBreakpointTreeElement);
1312
1313             var eventBreakpointRow = new WI.DetailsSectionRow;
1314             eventBreakpointRow.element.appendChild(this._pauseReasonTreeOutline.element);
1315
1316             this._pauseReasonGroup.rows = [eventBreakpointRow];
1317             return true;
1318
1319         case WI.DebuggerManager.PauseReason.Fetch:
1320         case WI.DebuggerManager.PauseReason.XHR:
1321             console.assert(WI.domDebuggerManager.supported);
1322             console.assert(pauseData, "Expected URL breakpoint data, but found none.");
1323             if (pauseData) {
1324                 if (pauseData.breakpointURL) {
1325                     let urlBreakpoint = WI.domDebuggerManager.urlBreakpointForURL(pauseData.breakpointURL);
1326                     console.assert(urlBreakpoint, "Expected URL breakpoint for URL.", pauseData.breakpointURL);
1327
1328                     this._pauseReasonTreeOutline = this.createContentTreeOutline({suppressFiltering: true});
1329
1330                     let urlBreakpointTreeElement = new WI.URLBreakpointTreeElement(urlBreakpoint, {
1331                         className: WI.DebuggerSidebarPanel.PausedBreakpointIconStyleClassName,
1332                         title: WI.DOMDebuggerManager.supportsURLBreakpoints() ? WI.UIString("Triggered URL Breakpoint") : WI.UIString("Triggered XHR Breakpoint"),
1333                     });
1334                     let urlBreakpointRow = new WI.DetailsSectionRow;
1335                     this._pauseReasonTreeOutline.appendChild(urlBreakpointTreeElement);
1336                     urlBreakpointRow.element.appendChild(this._pauseReasonTreeOutline.element);
1337
1338                     this._pauseReasonTextRow.text = pauseData.url;
1339                     this._pauseReasonGroup.rows = [urlBreakpointRow, this._pauseReasonTextRow];
1340                 } else {
1341                     console.assert(pauseData.breakpointURL === "", "Should be the All Requests breakpoint which has an empty URL");
1342                     this._pauseReasonTextRow.text = WI.UIString("Requesting: %s").format(pauseData.url);
1343                     this._pauseReasonGroup.rows = [this._pauseReasonTextRow];
1344                 }
1345                 this._pauseReasonTextRow.element.title = pauseData.url;
1346                 return true;
1347             }
1348             break;
1349
1350         case WI.DebuggerManager.PauseReason.Other:
1351             console.error("Paused for unknown reason. We should always have a reason.");
1352             break;
1353         }
1354
1355         return false;
1356     }
1357
1358     _updatePauseReasonGotoArrow()
1359     {
1360         this._pauseReasonLinkContainerElement.removeChildren();
1361
1362         var activeCallFrame = WI.debuggerManager.activeCallFrame;
1363         if (!activeCallFrame)
1364             return;
1365
1366         var sourceCodeLocation = activeCallFrame.sourceCodeLocation;
1367         if (!sourceCodeLocation)
1368             return;
1369
1370         const options = {
1371             useGoToArrowButton: true,
1372             ignoreNetworkTab: true,
1373             ignoreSearchTab: true,
1374         };
1375         let linkElement = WI.createSourceCodeLocationLink(sourceCodeLocation, options);
1376         this._pauseReasonLinkContainerElement.appendChild(linkElement);
1377     }
1378
1379     _addIssue(issueMessage)
1380     {
1381         let issueTreeElement = this._scriptsContentTreeOutline.findTreeElement(issueMessage);
1382         if (issueTreeElement)
1383             return issueTreeElement;
1384
1385         let parentTreeElement = this._addTreeElementForSourceCodeToTreeOutline(issueMessage.sourceCodeLocation.sourceCode, this._scriptsContentTreeOutline);
1386         if (!parentTreeElement)
1387             return null;
1388
1389         issueTreeElement = new WI.IssueTreeElement(issueMessage);
1390
1391         parentTreeElement.insertChild(issueTreeElement, insertionIndexForObjectInListSortedByFunction(issueTreeElement, parentTreeElement.children, this._compareBreakpointTreeElements));
1392         if (parentTreeElement.children.length === 1)
1393             parentTreeElement.expand();
1394
1395         return issueTreeElement;
1396     }
1397
1398     _handleDOMBreakpointDOMNodeChanged(event)
1399     {
1400         let breakpoint = event.target;
1401         if (breakpoint.domNodeIdentifier)
1402             this._addBreakpoint(breakpoint);
1403         else
1404             this._removeBreakpoint(breakpoint);
1405     }
1406
1407     _handleIssueAdded(event)
1408     {
1409         var issue = event.data.issue;
1410
1411         // We only want to show issues originating from JavaScript source code.
1412         if (!issue.sourceCodeLocation || !issue.sourceCodeLocation.sourceCode || (issue.source !== "javascript" && issue.source !== "console-api"))
1413             return;
1414
1415         this._addIssue(issue);
1416     }
1417
1418     _handleIssuesCleared(event)
1419     {
1420         let currentTreeElement = this._scriptsContentTreeOutline.children[0];
1421         let issueTreeElements = [];
1422
1423         while (currentTreeElement && !currentTreeElement.root) {
1424             if (currentTreeElement instanceof WI.IssueTreeElement)
1425                 issueTreeElements.push(currentTreeElement);
1426             currentTreeElement = currentTreeElement.traverseNextTreeElement(false, null, true);
1427         }
1428
1429         issueTreeElements.forEach((treeElement) => treeElement.parent.removeChild(treeElement));
1430     }
1431
1432     _handleBreakpointElementAddedOrRemoved(event)
1433     {
1434         let treeElement = event.data.element;
1435
1436         let setting = null;
1437         if (treeElement.breakpoint === WI.debuggerManager.assertionFailuresBreakpoint)
1438             setting = WI.settings.showAssertionFailuresBreakpoint;
1439         else if (treeElement.representedObject === WI.domDebuggerManager.allRequestsBreakpoint)
1440             setting = WI.settings.showAllRequestsBreakpoint;
1441
1442         if (setting)
1443             setting.value = !!treeElement.parent;
1444     }
1445
1446     _handleCreateBreakpointMouseDown(event)
1447     {
1448         if (this._ignoreCreateBreakpointMouseDown)
1449             return;
1450
1451         this._ignoreCreateBreakpointMouseDown = true;
1452
1453         let contextMenu = WI.ContextMenu.createFromEvent(event);
1454         contextMenu.addBeforeShowCallback(() => {
1455             this._ignoreCreateBreakpointMouseDown = false;
1456         });
1457
1458         // COMPATIBILITY (iOS 10): DebuggerAgent.setPauseOnAssertions did not exist yet.
1459         if (InspectorBackend.domains.Debugger.setPauseOnAssertions) {
1460             let assertionFailuresBreakpointShown = WI.settings.showAssertionFailuresBreakpoint.value;
1461
1462             contextMenu.appendCheckboxItem(WI.UIString("Assertion Failures"), () => {
1463                 if (assertionFailuresBreakpointShown)
1464                     WI.debuggerManager.removeBreakpoint(WI.debuggerManager.assertionFailuresBreakpoint);
1465                 else {
1466                     WI.debuggerManager.assertionFailuresBreakpoint.disabled = false;
1467                     WI.debuggerManager.addBreakpoint(WI.debuggerManager.assertionFailuresBreakpoint);
1468                 }
1469             }, assertionFailuresBreakpointShown);
1470         }
1471
1472         if (WI.domDebuggerManager.supported) {
1473             contextMenu.appendSeparator();
1474
1475             contextMenu.appendItem(WI.UIString("Event Breakpoint\u2026"), () => {
1476                 let popover = new WI.EventBreakpointPopover(this);
1477                 popover.show(this._createBreakpointButton.element, [WI.RectEdge.MAX_Y, WI.RectEdge.MIN_Y, WI.RectEdge.MAX_X]);
1478             });
1479
1480             contextMenu.appendSeparator();
1481
1482             let allRequestsBreakpointShown = WI.settings.showAllRequestsBreakpoint.value;
1483
1484             contextMenu.appendCheckboxItem(WI.UIString("All Requests"), () => {
1485                 if (allRequestsBreakpointShown)
1486                     WI.domDebuggerManager.removeURLBreakpoint(WI.domDebuggerManager.allRequestsBreakpoint);
1487                 else {
1488                     WI.domDebuggerManager.allRequestsBreakpoint.disabled = false;
1489                     WI.domDebuggerManager.addURLBreakpoint(WI.domDebuggerManager.allRequestsBreakpoint);
1490                 }
1491             }, allRequestsBreakpointShown);
1492
1493             contextMenu.appendItem(WI.DOMDebuggerManager.supportsURLBreakpoints() ? WI.UIString("URL Breakpoint\u2026") : WI.UIString("XHR Breakpoint\u2026"), () => {
1494                 let popover = new WI.URLBreakpointPopover(this);
1495                 popover.show(this._createBreakpointButton.element, [WI.RectEdge.MAX_Y, WI.RectEdge.MIN_Y, WI.RectEdge.MAX_X]);
1496             });
1497         }
1498
1499         contextMenu.show();
1500     }
1501 };
1502
1503 WI.DebuggerSidebarPanel.DebuggerPausedStyleClassName = "paused";
1504 WI.DebuggerSidebarPanel.ExceptionIconStyleClassName = "breakpoint-exception-icon";
1505 WI.DebuggerSidebarPanel.AssertionIconStyleClassName = "breakpoint-assertion-icon";
1506 WI.DebuggerSidebarPanel.PausedBreakpointIconStyleClassName = "breakpoint-paused-icon";
1507
1508 WI.DebuggerSidebarPanel.SelectedAllExceptionsCookieKey = "debugger-sidebar-panel-all-exceptions-breakpoint";
1509 WI.DebuggerSidebarPanel.SelectedUncaughtExceptionsCookieKey = "debugger-sidebar-panel-uncaught-exceptions-breakpoint";
1510 WI.DebuggerSidebarPanel.SelectedAssertionFailuresCookieKey = "debugger-sidebar-panel-assertion-failures-breakpoint";
1511 WI.DebuggerSidebarPanel.SelectedAllRequestsCookieKey = "debugger-sidebar-panel-all-requests-breakpoint";