Web Inspector: document Debugger.paused, introduce types for ids in Debugger domain.
[WebKit.git] / Source / WebCore / inspector / front-end / ScriptsPanel.js
1 /*
2  * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3  * Copyright (C) 2011 Google Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 WebInspector.ScriptsPanel = function(presentationModel)
28 {
29     WebInspector.Panel.call(this, "scripts");
30
31     WebInspector.settings.pauseOnExceptionStateString = WebInspector.settings.createSetting("pauseOnExceptionStateString", WebInspector.ScriptsPanel.PauseOnExceptionsState.DontPauseOnExceptions);
32
33     this._presentationModel = presentationModel;
34
35     this.registerShortcuts();
36
37     this.topStatusBar = document.createElement("div");
38     this.topStatusBar.className = "status-bar";
39     this.topStatusBar.id = "scripts-status-bar";
40     this.element.appendChild(this.topStatusBar);
41
42     this.backButton = document.createElement("button");
43     this.backButton.className = "status-bar-item";
44     this.backButton.id = "scripts-back";
45     this.backButton.title = WebInspector.UIString("Show the previous script resource.");
46     this.backButton.disabled = true;
47     this.backButton.appendChild(document.createElement("img"));
48     this.backButton.addEventListener("click", this._goBack.bind(this), false);
49     this.topStatusBar.appendChild(this.backButton);
50
51     this.forwardButton = document.createElement("button");
52     this.forwardButton.className = "status-bar-item";
53     this.forwardButton.id = "scripts-forward";
54     this.forwardButton.title = WebInspector.UIString("Show the next script resource.");
55     this.forwardButton.disabled = true;
56     this.forwardButton.appendChild(document.createElement("img"));
57     this.forwardButton.addEventListener("click", this._goForward.bind(this), false);
58     this.topStatusBar.appendChild(this.forwardButton);
59
60     this._filesSelectElement = document.createElement("select");
61     this._filesSelectElement.className = "status-bar-item";
62     this._filesSelectElement.id = "scripts-files";
63     this._filesSelectElement.addEventListener("change", this._filesSelectChanged.bind(this), false);
64     this._filesSelectElement.addEventListener("keyup", this._filesSelectChanged.bind(this), false);
65     this.topStatusBar.appendChild(this._filesSelectElement);
66
67     this.functionsSelectElement = document.createElement("select");
68     this.functionsSelectElement.className = "status-bar-item";
69     this.functionsSelectElement.id = "scripts-functions";
70
71     // FIXME: append the functions select element to the top status bar when it is implemented.
72     // this.topStatusBar.appendChild(this.functionsSelectElement);
73
74     this._createSidebarButtons();
75
76     this.toggleBreakpointsButton = new WebInspector.StatusBarButton(WebInspector.UIString("Deactivate all breakpoints."), "toggle-breakpoints");
77     this.toggleBreakpointsButton.toggled = true;
78     this.toggleBreakpointsButton.addEventListener("click", this.toggleBreakpointsClicked.bind(this), false);
79     this.sidebarButtonsElement.appendChild(this.toggleBreakpointsButton.element);
80
81     this.debuggerStatusElement = document.createElement("div");
82     this.debuggerStatusElement.id = "scripts-debugger-status";
83     this.sidebarButtonsElement.appendChild(this.debuggerStatusElement);
84
85     this.viewsContainerElement = document.createElement("div");
86     this.viewsContainerElement.id = "script-resource-views";
87
88     this.sidebarElement = document.createElement("div");
89     this.sidebarElement.id = "scripts-sidebar";
90
91     this.sidebarResizeElement = document.createElement("div");
92     this.sidebarResizeElement.className = "sidebar-resizer-vertical";
93     this.sidebarResizeElement.addEventListener("mousedown", this._startSidebarResizeDrag.bind(this), false);
94
95     this.sidebarResizeWidgetElement = document.createElement("div");
96     this.sidebarResizeWidgetElement.id = "scripts-sidebar-resizer-widget";
97     this.sidebarResizeWidgetElement.addEventListener("mousedown", this._startSidebarResizeDrag.bind(this), false);
98     this.topStatusBar.appendChild(this.sidebarResizeWidgetElement);
99
100     this.sidebarPanes = {};
101     this.sidebarPanes.watchExpressions = new WebInspector.WatchExpressionsSidebarPane();
102     this.sidebarPanes.callstack = new WebInspector.CallStackSidebarPane(this._presentationModel);
103     this.sidebarPanes.scopechain = new WebInspector.ScopeChainSidebarPane();
104     this.sidebarPanes.jsBreakpoints = new WebInspector.JavaScriptBreakpointsSidebarPane(this._presentationModel, this._showSourceLine.bind(this));
105     if (Preferences.nativeInstrumentationEnabled) {
106         this.sidebarPanes.domBreakpoints = WebInspector.domBreakpointsSidebarPane;
107         this.sidebarPanes.xhrBreakpoints = new WebInspector.XHRBreakpointsSidebarPane();
108         this.sidebarPanes.eventListenerBreakpoints = new WebInspector.EventListenerBreakpointsSidebarPane();
109     }
110
111     if (Preferences.canInspectWorkers && WebInspector.workerManager)
112         this.sidebarElement.addEventListener("contextmenu", this._contextMenu.bind(this), false);
113     if (Preferences.canInspectWorkers && WebInspector.workerManager && WebInspector.settings.workerInspectionEnabled.get()) {
114         WorkerAgent.setWorkerInspectionEnabled(true);
115         this.sidebarPanes.workerList = new WebInspector.WorkerListSidebarPane(WebInspector.workerManager);
116     } else
117         this.sidebarPanes.workers = new WebInspector.WorkersSidebarPane();
118
119     for (var pane in this.sidebarPanes)
120         this.sidebarElement.appendChild(this.sidebarPanes[pane].element);
121
122     this.sidebarPanes.callstack.expanded = true;
123
124     this.sidebarPanes.scopechain.expanded = true;
125     this.sidebarPanes.jsBreakpoints.expanded = true;
126
127     var helpSection = WebInspector.shortcutsScreen.section(WebInspector.UIString("Scripts Panel"));
128     this.sidebarPanes.callstack.registerShortcuts(helpSection, this.registerShortcut.bind(this));
129
130     var panelEnablerHeading = WebInspector.UIString("You need to enable debugging before you can use the Scripts panel.");
131     var panelEnablerDisclaimer = WebInspector.UIString("Enabling debugging will make scripts run slower.");
132     var panelEnablerButton = WebInspector.UIString("Enable Debugging");
133
134     this.panelEnablerView = new WebInspector.PanelEnablerView("scripts", panelEnablerHeading, panelEnablerDisclaimer, panelEnablerButton);
135     this.panelEnablerView.addEventListener("enable clicked", this._enableDebugging, this);
136
137     this.element.appendChild(this.panelEnablerView.element);
138     this.element.appendChild(this.viewsContainerElement);
139     this.element.appendChild(this.sidebarElement);
140     this.element.appendChild(this.sidebarResizeElement);
141
142     this.enableToggleButton = new WebInspector.StatusBarButton("", "enable-toggle-status-bar-item");
143     this.enableToggleButton.addEventListener("click", this._toggleDebugging.bind(this), false);
144     if (Preferences.debuggerAlwaysEnabled)
145         this.enableToggleButton.element.addStyleClass("hidden");
146
147     this._pauseOnExceptionButton = new WebInspector.StatusBarButton("", "scripts-pause-on-exceptions-status-bar-item", 3);
148     this._pauseOnExceptionButton.addEventListener("click", this._togglePauseOnExceptions.bind(this), false);
149
150     this._toggleFormatSourceButton = new WebInspector.StatusBarButton(WebInspector.UIString("Pretty print"), "scripts-toggle-pretty-print-status-bar-item");
151     this._toggleFormatSourceButton.toggled = false;
152     this._toggleFormatSourceButton.addEventListener("click", this._toggleFormatSource.bind(this), false);
153
154     this._scriptViewStatusBarItemsContainer = document.createElement("div");
155     this._scriptViewStatusBarItemsContainer.style.display = "inline-block";
156
157     this._debuggerEnabled = Preferences.debuggerAlwaysEnabled;
158
159     this.reset();
160
161     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerWasEnabled, this._debuggerWasEnabled, this);
162     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerWasDisabled, this._debuggerWasDisabled, this);
163
164     this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.UISourceCodeAdded, this._uiSourceCodeAdded, this)
165     this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.UISourceCodeReplaced, this._uiSourceCodeReplaced, this);
166     this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.ConsoleMessageAdded, this._consoleMessageAdded, this);
167     this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.ConsoleMessagesCleared, this._consoleMessagesCleared, this);
168     this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.BreakpointAdded, this._breakpointAdded, this);
169     this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.BreakpointRemoved, this._breakpointRemoved, this);
170     this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.DebuggerPaused, this._debuggerPaused, this);
171     this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.DebuggerResumed, this._debuggerResumed, this);
172     this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.CallFrameSelected, this._callFrameSelected, this);
173
174     var enableDebugger = Preferences.debuggerAlwaysEnabled || WebInspector.settings.debuggerEnabled.get();
175     if (enableDebugger)
176         WebInspector.debuggerModel.enableDebugger();
177
178     WebInspector.settings.showScriptFolders.addChangeListener(this._showScriptFoldersSettingChanged.bind(this));
179 }
180
181 // Keep these in sync with WebCore::ScriptDebugServer
182 WebInspector.ScriptsPanel.PauseOnExceptionsState = {
183     DontPauseOnExceptions : "none",
184     PauseOnAllExceptions : "all",
185     PauseOnUncaughtExceptions: "uncaught"
186 };
187
188 WebInspector.ScriptsPanel.BreakReason = {
189     DOM: "DOM",
190     EventListener: "EventListener",
191     XHR: "XHR",
192     Exception: "exception"
193 }
194
195 WebInspector.ScriptsPanel.prototype = {
196     get toolbarItemLabel()
197     {
198         return WebInspector.UIString("Scripts");
199     },
200
201     get statusBarItems()
202     {
203         return [this.enableToggleButton.element, this._pauseOnExceptionButton.element, this._toggleFormatSourceButton.element, this._scriptViewStatusBarItemsContainer];
204     },
205
206     get defaultFocusedElement()
207     {
208         return this._filesSelectElement;
209     },
210
211     get paused()
212     {
213         return this._paused;
214     },
215
216     show: function()
217     {
218         WebInspector.Panel.prototype.show.call(this);
219         this.sidebarResizeElement.style.right = (this.sidebarElement.offsetWidth - 3) + "px";
220         if (Preferences.nativeInstrumentationEnabled)
221             this.sidebarElement.insertBefore(this.sidebarPanes.domBreakpoints.element, this.sidebarPanes.xhrBreakpoints.element);
222         this.sidebarPanes.watchExpressions.show();
223     },
224
225     get breakpointsActivated()
226     {
227         return this.toggleBreakpointsButton.toggled;
228     },
229
230     _uiSourceCodeAdded: function(event)
231     {
232         var uiSourceCode = event.data;
233
234         if (!uiSourceCode.url) {
235             // Anonymous sources are shown only when stepping.
236             return;
237         }
238
239         this._addOptionToFilesSelect(uiSourceCode);
240
241         var lastViewedURL = WebInspector.settings.lastViewedScriptFile.get();
242         if (!this._filesSelectElement.initialSelectionProcessed) {
243             this._filesSelectElement.initialSelectionProcessed = true;
244             // Option we just added is the only option in files select.
245             // We have to show corresponding source frame immediately.
246             this._showSourceFrameAndAddToHistory(uiSourceCode);
247             // Restore original value of lastViewedScriptFile because
248             // source frame was shown as a result of initial load.
249             WebInspector.settings.lastViewedScriptFile.set(lastViewedURL);
250         } else if (uiSourceCode.url === lastViewedURL)
251             this._showSourceFrameAndAddToHistory(uiSourceCode);
252     },
253
254     _showScriptFoldersSettingChanged: function()
255     {
256         var selectedOption = this._filesSelectElement[this._filesSelectElement.selectedIndex];
257         var uiSourceCode = selectedOption ? selectedOption._uiSourceCode : null;
258
259         var options = Array.prototype.slice.call(this._filesSelectElement);
260         this._resetFilesSelect();
261         for (var i = 0; i < options.length; ++i) {
262             if (options[i]._uiSourceCode)
263                 this._addOptionToFilesSelect(options[i]._uiSourceCode);
264         }
265
266         if (uiSourceCode) {
267             var index = uiSourceCode._option.index;
268             if (typeof index === "number")
269                 this._filesSelectElement.selectedIndex = index;
270         }
271     },
272
273     _addOptionToFilesSelect: function(uiSourceCode)
274     {
275         var showScriptFolders = WebInspector.settings.showScriptFolders.get();
276
277         var select = this._filesSelectElement;
278         if (!select.domainOptions)
279             select.domainOptions = {};
280         if (!select.folderOptions)
281             select.folderOptions = {};
282
283         var option = document.createElement("option");
284         option._uiSourceCode = uiSourceCode;
285         var parsedURL = uiSourceCode.url.asParsedURL();
286
287         var names = this._folderAndDisplayNameForScriptURL(uiSourceCode.url);
288         const indent = (!showScriptFolders || WebInspector.isMac()) ? "" : "\u00a0\u00a0\u00a0\u00a0";
289         option.text = indent + (names.displayName ? names.displayName : WebInspector.UIString("(program)"));
290         option.displayName = names.displayName;
291
292         var folderNameForSorting;
293         if (uiSourceCode.isContentScript)
294             folderNameForSorting = "2:" + names.folderName;
295         else
296             folderNameForSorting = "0:" + (names.domain ? names.domain + "\t\t" : "") + names.folderName;
297
298         option.nameForSorting = folderNameForSorting + "\t/\t" + names.displayName; // Use '\t' to make files stick to their folder.
299         option.title = uiSourceCode.url;
300         if (uiSourceCode.isContentScript)
301             option.addStyleClass("extension-script");
302
303         function insertOrdered(option)
304         {
305             function optionCompare(a, b)
306             {
307                 if (showScriptFolders)
308                     return a.nameForSorting.localeCompare(b.nameForSorting);
309                 else
310                     return a.displayName.localeCompare(b.displayName);
311             }
312             var insertionIndex = insertionIndexForObjectInListSortedByFunction(option, select.childNodes, optionCompare);
313             select.insertBefore(option, insertionIndex < 0 ? null : select.childNodes.item(insertionIndex));
314         }
315
316         insertOrdered(option);
317
318         if (uiSourceCode.isContentScript && !select.contentScriptSection) {
319             var contentScriptSection = document.createElement("option");
320             contentScriptSection.text = "\u2014 " + WebInspector.UIString("Content scripts") + " \u2014";
321             contentScriptSection.disabled = true;
322             contentScriptSection.nameForSorting = "1/ContentScriptSeparator";
323             select.contentScriptSection = contentScriptSection;
324             insertOrdered(contentScriptSection);
325         }
326
327         if (showScriptFolders && !uiSourceCode.isContentScript && names.domain && !select.domainOptions[names.domain]) {
328             var domainOption = document.createElement("option");
329             domainOption.text = "\u2014 " + names.domain + " \u2014";
330             domainOption.nameForSorting = "0:" + names.domain;
331             domainOption.disabled = true;
332             select.domainOptions[names.domain] = domainOption;
333             insertOrdered(domainOption);
334         }
335
336         if (showScriptFolders && names.folderName && !select.folderOptions[names.folderName]) {
337             var folderOption = document.createElement("option");
338             folderOption.text = names.folderName;
339             folderOption.nameForSorting = folderNameForSorting;
340             folderOption.disabled = true;
341             select.folderOptions[names.folderName] = folderOption;
342             insertOrdered(folderOption);
343         }
344
345         option._uiSourceCode = uiSourceCode;
346         uiSourceCode._option = option;
347     },
348
349     _folderAndDisplayNameForScriptURL: function(url)
350     {
351         var parsedURL = url.asParsedURL();
352         if (parsedURL)
353             url = parsedURL.path;
354
355         var folderName = "";
356         var displayName = url;
357
358         var pathLength = displayName.indexOf("?");
359         if (pathLength === -1)
360             pathLength = displayName.length;
361
362         var fromIndex = displayName.lastIndexOf("/", pathLength - 2);
363         if (fromIndex !== -1) {
364             folderName = displayName.substring(0, fromIndex);
365             displayName = displayName.substring(fromIndex + 1);
366         }
367
368         if (displayName.length > 80)
369             displayName = "\u2026" + displayName.substring(displayName.length - 80);
370
371         if (folderName.length > 80)
372             folderName = "\u2026" + folderName.substring(folderName.length - 80);
373
374         return { domain: (parsedURL ? parsedURL.host : ""), folderName: folderName, displayName: displayName };
375     },
376
377     setScriptSourceIsBeingEdited: function(uiSourceCode, inEditMode)
378     {
379         var option = uiSourceCode._option;
380         if (!option)
381             return;
382         if (inEditMode)
383             option.text = option.text.replace(/[^*]$/, "$&*");
384         else
385             option.text = option.text.replace(/[*]$/, "");
386     },
387
388     _consoleMessagesCleared: function()
389     {
390         for (var i = 0; i < this._filesSelectElement.length; ++i) {
391             var option = this._filesSelectElement[i];
392             if (option._uiSourceCode && option._uiSourceCode._sourceFrame)
393                 option._uiSourceCode._sourceFrame.clearMessages();
394         }
395     },
396
397     _consoleMessageAdded: function(event)
398     {
399         var message = event.data;
400
401         var sourceFrame = message.uiSourceCode._sourceFrame;
402         if (sourceFrame && sourceFrame.loaded)
403             sourceFrame.addMessageToSource(message.lineNumber, message.originalMessage);
404     },
405
406     _breakpointAdded: function(event)
407     {
408         var breakpoint = event.data;
409
410         var sourceFrame = breakpoint.uiSourceCode._sourceFrame;
411         if (sourceFrame && sourceFrame.loaded)
412             sourceFrame.addBreakpoint(breakpoint.lineNumber, breakpoint.resolved, breakpoint.condition, breakpoint.enabled);
413
414         this.sidebarPanes.jsBreakpoints.addBreakpoint(breakpoint);
415     },
416
417     _breakpointRemoved: function(event)
418     {
419         var breakpoint = event.data;
420
421         var sourceFrame = breakpoint.uiSourceCode._sourceFrame;
422         if (sourceFrame && sourceFrame.loaded)
423             sourceFrame.removeBreakpoint(breakpoint.lineNumber);
424
425         this.sidebarPanes.jsBreakpoints.removeBreakpoint(breakpoint.uiSourceCode, breakpoint.lineNumber);
426     },
427
428     evaluateInSelectedCallFrame: function(code, objectGroup, includeCommandLineAPI, returnByValue, callback)
429     {
430         function didEvaluate()
431         {
432             if (objectGroup === "console")
433                 this.sidebarPanes.scopechain.update(this._presentationModel.selectedCallFrame);
434             callback.apply(null, arguments);
435         }
436         var selectedCallFrame = this._presentationModel.selectedCallFrame;
437         selectedCallFrame.evaluate(code, objectGroup, includeCommandLineAPI, returnByValue, didEvaluate.bind(this));
438     },
439
440     getSelectedCallFrameVariables: function(callback)
441     {
442         var result = { this: true };
443
444         var selectedCallFrame = this._presentationModel.selectedCallFrame;
445         if (!selectedCallFrame)
446             callback(result);
447
448         var pendingRequests = 0;
449
450         function propertiesCollected(properties)
451         {
452             for (var i = 0; properties && i < properties.length; ++i)
453                 result[properties[i].name] = true;
454             if (--pendingRequests == 0)
455                 callback(result);
456         }
457
458         for (var i = 0; i < selectedCallFrame.scopeChain.length; ++i) {
459             var scope = selectedCallFrame.scopeChain[i];
460             var object = WebInspector.RemoteObject.fromPayload(scope.object);
461             pendingRequests++;
462             object.getAllProperties(propertiesCollected);
463         }
464     },
465
466     _debuggerPaused: function(event)
467     {
468         var callFrames = event.data.callFrames;
469         var details = event.data.details;
470
471         this._paused = true;
472         this._waitingToPause = false;
473         this._stepping = false;
474
475         this._updateDebuggerButtons();
476
477         WebInspector.setCurrentPanel(this);
478
479         this.sidebarPanes.callstack.update(callFrames, details);
480         this.sidebarPanes.callstack.selectedCallFrame = this._presentationModel.selectedCallFrame;
481
482         if (details.reason === WebInspector.ScriptsPanel.BreakReason.DOM) {
483             this.sidebarPanes.domBreakpoints.highlightBreakpoint(details.auxData);
484             function didCreateBreakpointHitStatusMessage(element)
485             {
486                 this.sidebarPanes.callstack.setStatus(element);
487             }
488             this.sidebarPanes.domBreakpoints.createBreakpointHitStatusMessage(details.auxData, didCreateBreakpointHitStatusMessage.bind(this));
489         } else if (details.reason === WebInspector.ScriptsPanel.BreakReason.EventListener) {
490             var eventName = details.auxData.eventName;
491             this.sidebarPanes.eventListenerBreakpoints.highlightBreakpoint(details.auxData.eventName);
492             var eventNameForUI = WebInspector.EventListenerBreakpointsSidebarPane.eventNameForUI(eventName);
493             this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a \"%s\" Event Listener.", eventNameForUI));
494         } else if (details.reason === WebInspector.ScriptsPanel.BreakReason.XHR) {
495             this.sidebarPanes.xhrBreakpoints.highlightBreakpoint(details.auxData.breakpointURL);
496             this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a XMLHttpRequest."));
497         } else if (details.reason === WebInspector.ScriptsPanel.BreakReason.Exception) {
498             this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on exception: '%s'.", details.auxData.description));
499         } else {
500             function didGetSourceLocation(uiSourceCode, lineNumber)
501             {
502                 if (!uiSourceCode || !this._presentationModel.findBreakpoint(uiSourceCode, lineNumber))
503                     return;
504                 this.sidebarPanes.jsBreakpoints.highlightBreakpoint(uiSourceCode, lineNumber);
505                 this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a JavaScript breakpoint."));
506             }
507             callFrames[0].sourceLine(didGetSourceLocation.bind(this));
508         }
509
510         window.focus();
511         InspectorFrontendHost.bringToFront();
512     },
513
514     _debuggerResumed: function()
515     {
516         this._paused = false;
517         this._waitingToPause = false;
518         this._stepping = false;
519
520         this._clearInterface();
521     },
522
523     _debuggerWasEnabled: function()
524     {
525         this._setPauseOnExceptions(WebInspector.settings.pauseOnExceptionStateString.get());
526
527         if (this._debuggerEnabled)
528             return;
529
530         this._debuggerEnabled = true;
531         this.reset(true);
532     },
533
534     _debuggerWasDisabled: function()
535     {
536         if (!this._debuggerEnabled)
537             return;
538
539         this._debuggerEnabled = false;
540         this.reset(true);
541     },
542
543     reset: function(preserveItems)
544     {
545         this.visibleView = null;
546
547         delete this.currentQuery;
548         this.searchCanceled();
549
550         this._debuggerResumed();
551
552         this._backForwardList = [];
553         this._currentBackForwardIndex = -1;
554         this._updateBackAndForwardButtons();
555
556         this._resetFilesSelect();
557         delete this._filesSelectElement.initialSelectionProcessed;
558
559         this.functionsSelectElement.removeChildren();
560         this.viewsContainerElement.removeChildren();
561
562         this.sidebarPanes.jsBreakpoints.reset();
563         this.sidebarPanes.watchExpressions.reset();
564         if (!preserveItems && this.sidebarPanes.workers)
565             this.sidebarPanes.workers.reset();
566     },
567
568     _resetFilesSelect: function()
569     {
570         this._filesSelectElement.removeChildren();
571         this._filesSelectElement.domainOptions = {};
572         this._filesSelectElement.folderOptions = {};
573         delete this._filesSelectElement.contentScriptSection;
574     },
575
576     get visibleView()
577     {
578         return this._visibleView;
579     },
580
581     set visibleView(x)
582     {
583         if (this._visibleView === x)
584             return;
585
586         if (this._visibleView)
587             this._visibleView.hide();
588
589         this._visibleView = x;
590
591         if (x) {
592             x.show(this.viewsContainerElement);
593             this._scriptViewStatusBarItemsContainer.removeChildren();
594             var statusBarItems = x.statusBarItems || [];
595             for (var i = 0; i < statusBarItems.length; ++i)
596                 this._scriptViewStatusBarItemsContainer.appendChild(statusBarItems[i]);
597         }
598     },
599
600     canShowAnchorLocation: function(anchor)
601     {
602         return this._debuggerEnabled && WebInspector.debuggerModel.scriptsForURL(anchor.href).length;
603     },
604
605     showAnchorLocation: function(anchor)
606     {
607         this._showSourceLine(anchor.uiSourceCode, anchor.lineNumber);
608     },
609
610     _showSourceLine: function(uiSourceCode, lineNumber)
611     {
612         var sourceFrame = this._showSourceFrameAndAddToHistory(uiSourceCode);
613         sourceFrame.highlightLine(lineNumber);
614     },
615
616     _showSourceFrameAndAddToHistory: function(uiSourceCode)
617     {
618         if (!uiSourceCode._option)
619             return;
620
621         var sourceFrame = this._showSourceFrame(uiSourceCode);
622
623         var oldIndex = this._currentBackForwardIndex;
624         if (oldIndex >= 0)
625             this._backForwardList.splice(oldIndex + 1, this._backForwardList.length - oldIndex);
626
627         // Check for a previous entry of the same object in _backForwardList.
628         // If one is found, remove it.
629         var previousEntryIndex = this._backForwardList.indexOf(uiSourceCode);
630         if (previousEntryIndex !== -1)
631             this._backForwardList.splice(previousEntryIndex, 1);
632
633         this._backForwardList.push(uiSourceCode);
634         this._currentBackForwardIndex = this._backForwardList.length - 1;
635
636         this._updateBackAndForwardButtons();
637
638         return sourceFrame;
639     },
640
641     _showSourceFrame: function(uiSourceCode)
642     {
643         this._filesSelectElement.selectedIndex = uiSourceCode._option.index;
644
645         var sourceFrame = uiSourceCode._sourceFrame || this._createSourceFrame(uiSourceCode);
646         this.visibleView = sourceFrame;
647
648         if (uiSourceCode.url)
649             WebInspector.settings.lastViewedScriptFile.set(uiSourceCode.url);
650
651         return sourceFrame;
652     },
653
654     _createSourceFrame: function(uiSourceCode)
655     {
656         var sourceFrame = new WebInspector.JavaScriptSourceFrame(this._presentationModel, uiSourceCode);
657         this.addChildView(sourceFrame);
658         sourceFrame._uiSourceCode = uiSourceCode;
659         sourceFrame.addEventListener(WebInspector.SourceFrame.Events.Loaded, this._sourceFrameLoaded, this);
660         uiSourceCode._sourceFrame = sourceFrame;
661         return sourceFrame;
662     },
663
664     _removeSourceFrame: function(uiSourceCode)
665     {
666         var sourceFrame = uiSourceCode._sourceFrame;
667         if (!sourceFrame)
668             return;
669         delete uiSourceCode._sourceFrame;
670         this.removeChildView(sourceFrame);
671         sourceFrame.removeEventListener(WebInspector.SourceFrame.Events.Loaded, this._sourceFrameLoaded, this);
672     },
673
674     _uiSourceCodeReplaced: function(event)
675     {
676         var oldUISourceCode = event.data.oldUISourceCode;
677         var uiSourceCode = event.data.uiSourceCode;
678
679         // Re-bind file select option from old source file to new one.
680         var option = oldUISourceCode._option;
681         if (!option)
682             return;
683         delete oldUISourceCode._option;
684         option._uiSourceCode = uiSourceCode;
685         uiSourceCode._option = option;
686
687         // Remove old source frame and create new one if needed.
688         this._removeSourceFrame(oldUISourceCode);
689         if (option === this._filesSelectElement[this._filesSelectElement.selectedIndex])
690             this._showSourceFrame(uiSourceCode);
691     },
692
693     _sourceFrameLoaded: function(event)
694     {
695         var sourceFrame = event.target;
696         var uiSourceCode = sourceFrame._uiSourceCode;
697
698         var messages = this._presentationModel.messagesForUISourceCode(uiSourceCode);
699         for (var i = 0; i < messages.length; ++i) {
700             var message = messages[i];
701             sourceFrame.addMessageToSource(message.lineNumber, message.originalMessage);
702         }
703
704         var breakpoints = this._presentationModel.breakpointsForUISourceCode(uiSourceCode);
705         for (var i = 0; i < breakpoints.length; ++i) {
706             var breakpoint = breakpoints[i];
707             sourceFrame.addBreakpoint(breakpoint.lineNumber, breakpoint.resolved, breakpoint.condition, breakpoint.enabled);
708         }
709     },
710
711     _clearCurrentExecutionLine: function()
712     {
713         if (this._executionSourceFrame)
714             this._executionSourceFrame.clearExecutionLine();
715         delete this._executionSourceFrame;
716     },
717
718     _callFrameSelected: function(event)
719     {
720         var callFrame = event.data;
721
722         this._clearCurrentExecutionLine();
723
724         if (!callFrame)
725             return;
726
727         this.sidebarPanes.scopechain.update(callFrame);
728         this.sidebarPanes.watchExpressions.refreshExpressions();
729         this.sidebarPanes.callstack.selectedCallFrame = this._presentationModel.selectedCallFrame;
730
731         function didGetSourceLocation(uiSourceCode, lineNumber)
732         {
733             if (!uiSourceCode)
734                 return;
735
736             if (!uiSourceCode._option) {
737                 // Anonymous scripts are not added to files select by default.
738                 this._addOptionToFilesSelect(uiSourceCode);
739             }
740             var sourceFrame = this._showSourceFrameAndAddToHistory(uiSourceCode);
741             sourceFrame.setExecutionLine(lineNumber);
742             this._executionSourceFrame = sourceFrame;
743         }
744         callFrame.sourceLine(didGetSourceLocation.bind(this));
745     },
746
747     _filesSelectChanged: function()
748     {
749         if (this._filesSelectElement.selectedIndex === -1)
750             return;
751
752         var uiSourceCode = this._filesSelectElement[this._filesSelectElement.selectedIndex]._uiSourceCode;
753         this._showSourceFrameAndAddToHistory(uiSourceCode);
754     },
755
756     _startSidebarResizeDrag: function(event)
757     {
758         WebInspector.elementDragStart(this.sidebarElement, this._sidebarResizeDrag.bind(this), this._endSidebarResizeDrag.bind(this), event, "ew-resize");
759
760         if (event.target === this.sidebarResizeWidgetElement)
761             this._dragOffset = (event.target.offsetWidth - (event.pageX - event.target.totalOffsetLeft()));
762         else
763             this._dragOffset = 0;
764     },
765
766     _endSidebarResizeDrag: function(event)
767     {
768         WebInspector.elementDragEnd(event);
769         delete this._dragOffset;
770         this.saveSidebarWidth();
771     },
772
773     _sidebarResizeDrag: function(event)
774     {
775         var x = event.pageX + this._dragOffset;
776         var newWidth = Number.constrain(window.innerWidth - x, Preferences.minScriptsSidebarWidth, window.innerWidth * 0.66);
777         this.setSidebarWidth(newWidth);
778         event.preventDefault();
779     },
780
781     setSidebarWidth: function(newWidth)
782     {
783         this.sidebarElement.style.width = newWidth + "px";
784         this.sidebarButtonsElement.style.width = newWidth + "px";
785         this.viewsContainerElement.style.right = newWidth + "px";
786         this.sidebarResizeWidgetElement.style.right = newWidth + "px";
787         this.sidebarResizeElement.style.right = (newWidth - 3) + "px";
788
789         this.doResize();
790     },
791
792     _setPauseOnExceptions: function(pauseOnExceptionsState)
793     {
794         pauseOnExceptionsState = pauseOnExceptionsState || WebInspector.ScriptsPanel.PauseOnExceptionsState.DontPauseOnExceptions;
795         function callback(error)
796         {
797             if (error)
798                 return;
799             if (pauseOnExceptionsState == WebInspector.ScriptsPanel.PauseOnExceptionsState.DontPauseOnExceptions)
800                 this._pauseOnExceptionButton.title = WebInspector.UIString("Don't pause on exceptions.\nClick to Pause on all exceptions.");
801             else if (pauseOnExceptionsState == WebInspector.ScriptsPanel.PauseOnExceptionsState.PauseOnAllExceptions)
802                 this._pauseOnExceptionButton.title = WebInspector.UIString("Pause on all exceptions.\nClick to Pause on uncaught exceptions.");
803             else if (pauseOnExceptionsState == WebInspector.ScriptsPanel.PauseOnExceptionsState.PauseOnUncaughtExceptions)
804                 this._pauseOnExceptionButton.title = WebInspector.UIString("Pause on uncaught exceptions.\nClick to Not pause on exceptions.");
805
806             this._pauseOnExceptionButton.state = pauseOnExceptionsState;
807             WebInspector.settings.pauseOnExceptionStateString.set(pauseOnExceptionsState);
808         }
809         DebuggerAgent.setPauseOnExceptions(pauseOnExceptionsState, callback.bind(this));
810     },
811
812     _updateDebuggerButtons: function()
813     {
814         if (this._debuggerEnabled) {
815             this.enableToggleButton.title = WebInspector.UIString("Debugging enabled. Click to disable.");
816             this.enableToggleButton.toggled = true;
817             this._pauseOnExceptionButton.visible = true;
818             this.panelEnablerView.visible = false;
819         } else {
820             this.enableToggleButton.title = WebInspector.UIString("Debugging disabled. Click to enable.");
821             this.enableToggleButton.toggled = false;
822             this._pauseOnExceptionButton.visible = false;
823             this.panelEnablerView.visible = true;
824         }
825
826         if (this._paused) {
827             this.pauseButton.addStyleClass("paused");
828
829             this.pauseButton.disabled = false;
830             this.stepOverButton.disabled = false;
831             this.stepIntoButton.disabled = false;
832             this.stepOutButton.disabled = false;
833
834             this.debuggerStatusElement.textContent = WebInspector.UIString("Paused");
835         } else {
836             this.pauseButton.removeStyleClass("paused");
837
838             this.pauseButton.disabled = this._waitingToPause;
839             this.stepOverButton.disabled = true;
840             this.stepIntoButton.disabled = true;
841             this.stepOutButton.disabled = true;
842
843             if (this._waitingToPause)
844                 this.debuggerStatusElement.textContent = WebInspector.UIString("Pausing");
845             else if (this._stepping)
846                 this.debuggerStatusElement.textContent = WebInspector.UIString("Stepping");
847             else
848                 this.debuggerStatusElement.textContent = "";
849         }
850     },
851
852     _updateBackAndForwardButtons: function()
853     {
854         this.backButton.disabled = this._currentBackForwardIndex <= 0;
855         this.forwardButton.disabled = this._currentBackForwardIndex >= (this._backForwardList.length - 1);
856     },
857
858     _clearInterface: function()
859     {
860         this.sidebarPanes.callstack.update(null);
861         this.sidebarPanes.scopechain.update(null);
862         this.sidebarPanes.jsBreakpoints.clearBreakpointHighlight();
863         if (Preferences.nativeInstrumentationEnabled) {
864             this.sidebarPanes.domBreakpoints.clearBreakpointHighlight();
865             this.sidebarPanes.eventListenerBreakpoints.clearBreakpointHighlight();
866             this.sidebarPanes.xhrBreakpoints.clearBreakpointHighlight();
867         }
868
869         this._clearCurrentExecutionLine();
870         this._updateDebuggerButtons();
871     },
872
873     _goBack: function()
874     {
875         if (this._currentBackForwardIndex <= 0) {
876             console.error("Can't go back from index " + this._currentBackForwardIndex);
877             return;
878         }
879
880         this._showSourceFrame(this._backForwardList[--this._currentBackForwardIndex]);
881         this._updateBackAndForwardButtons();
882     },
883
884     _goForward: function()
885     {
886         if (this._currentBackForwardIndex >= this._backForwardList.length - 1) {
887             console.error("Can't go forward from index " + this._currentBackForwardIndex);
888             return;
889         }
890
891         this._showSourceFrame(this._backForwardList[++this._currentBackForwardIndex]);
892         this._updateBackAndForwardButtons();
893     },
894
895     _enableDebugging: function()
896     {
897         if (this._debuggerEnabled)
898             return;
899         this._toggleDebugging(this.panelEnablerView.alwaysEnabled);
900     },
901
902     _toggleDebugging: function(optionalAlways)
903     {
904         this._paused = false;
905         this._waitingToPause = false;
906         this._stepping = false;
907
908         if (this._debuggerEnabled) {
909             WebInspector.settings.debuggerEnabled.set(false);
910             WebInspector.debuggerModel.disableDebugger();
911         } else {
912             WebInspector.settings.debuggerEnabled.set(!!optionalAlways);
913             WebInspector.debuggerModel.enableDebugger();
914         }
915     },
916
917     _togglePauseOnExceptions: function()
918     {
919         var nextStateMap = {};
920         var stateEnum = WebInspector.ScriptsPanel.PauseOnExceptionsState;
921         nextStateMap[stateEnum.DontPauseOnExceptions] = stateEnum.PauseOnAllExceptions;
922         nextStateMap[stateEnum.PauseOnAllExceptions] = stateEnum.PauseOnUncaughtExceptions;
923         nextStateMap[stateEnum.PauseOnUncaughtExceptions] = stateEnum.DontPauseOnExceptions;
924         this._setPauseOnExceptions(nextStateMap[this._pauseOnExceptionButton.state]);
925     },
926
927     _togglePause: function()
928     {
929         if (this._paused) {
930             this._paused = false;
931             this._waitingToPause = false;
932             DebuggerAgent.resume();
933         } else {
934             this._stepping = false;
935             this._waitingToPause = true;
936             DebuggerAgent.pause();
937         }
938
939         this._clearInterface();
940     },
941
942     _stepOverClicked: function()
943     {
944         if (!this._paused)
945             return;
946
947         this._paused = false;
948         this._stepping = true;
949
950         this._clearInterface();
951
952         DebuggerAgent.stepOver();
953     },
954
955     _stepIntoClicked: function()
956     {
957         if (!this._paused)
958             return;
959
960         this._paused = false;
961         this._stepping = true;
962
963         this._clearInterface();
964
965         DebuggerAgent.stepInto();
966     },
967
968     _stepOutClicked: function()
969     {
970         if (!this._paused)
971             return;
972
973         this._paused = false;
974         this._stepping = true;
975
976         this._clearInterface();
977
978         DebuggerAgent.stepOut();
979     },
980
981     toggleBreakpointsClicked: function()
982     {
983         this.toggleBreakpointsButton.toggled = !this.toggleBreakpointsButton.toggled;
984         if (this.toggleBreakpointsButton.toggled) {
985             DebuggerAgent.setBreakpointsActive(true);
986             this.toggleBreakpointsButton.title = WebInspector.UIString("Deactivate all breakpoints.");
987             document.getElementById("main-panels").removeStyleClass("breakpoints-deactivated");
988         } else {
989             DebuggerAgent.setBreakpointsActive(false);
990             this.toggleBreakpointsButton.title = WebInspector.UIString("Activate all breakpoints.");
991             document.getElementById("main-panels").addStyleClass("breakpoints-deactivated");
992         }
993     },
994
995     elementsToRestoreScrollPositionsFor: function()
996     {
997         return [ this.sidebarElement ];
998     },
999
1000     _createSidebarButtons: function()
1001     {
1002         this.sidebarButtonsElement = document.createElement("div");
1003         this.sidebarButtonsElement.id = "scripts-sidebar-buttons";
1004         this.topStatusBar.appendChild(this.sidebarButtonsElement);
1005
1006         var title, handler, shortcuts;
1007         var platformSpecificModifier = WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta;
1008
1009         // Continue.
1010         title = WebInspector.UIString("Pause script execution (%s).");
1011         handler = this._togglePause.bind(this);
1012         shortcuts = [];
1013         shortcuts.push(WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.F8));
1014         shortcuts.push(WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.Slash, platformSpecificModifier));
1015         this.pauseButton = this._createSidebarButtonAndRegisterShortcuts("scripts-pause", title, handler, shortcuts, WebInspector.UIString("Pause/Continue"));
1016
1017         // Step over.
1018         title = WebInspector.UIString("Step over next function call (%s).");
1019         handler = this._stepOverClicked.bind(this);
1020         shortcuts = [];
1021         shortcuts.push(WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.F10));
1022         shortcuts.push(WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.SingleQuote, platformSpecificModifier));
1023         this.stepOverButton = this._createSidebarButtonAndRegisterShortcuts("scripts-step-over", title, handler, shortcuts, WebInspector.UIString("Step over"));
1024
1025         // Step into.
1026         title = WebInspector.UIString("Step into next function call (%s).");
1027         handler = this._stepIntoClicked.bind(this);
1028         shortcuts = [];
1029         shortcuts.push(WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.F11));
1030         shortcuts.push(WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.Semicolon, platformSpecificModifier));
1031         this.stepIntoButton = this._createSidebarButtonAndRegisterShortcuts("scripts-step-into", title, handler, shortcuts, WebInspector.UIString("Step into"));
1032
1033         // Step out.
1034         title = WebInspector.UIString("Step out of current function (%s).");
1035         handler = this._stepOutClicked.bind(this);
1036         shortcuts = [];
1037         shortcuts.push(WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.F11, WebInspector.KeyboardShortcut.Modifiers.Shift));
1038         shortcuts.push(WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.Semicolon, WebInspector.KeyboardShortcut.Modifiers.Shift, platformSpecificModifier));
1039         this.stepOutButton = this._createSidebarButtonAndRegisterShortcuts("scripts-step-out", title, handler, shortcuts, WebInspector.UIString("Step out"));
1040     },
1041
1042     _createSidebarButtonAndRegisterShortcuts: function(buttonId, buttonTitle, handler, shortcuts, shortcutDescription)
1043     {
1044         var button = document.createElement("button");
1045         button.className = "status-bar-item";
1046         button.id = buttonId;
1047         button.title = String.vsprintf(buttonTitle, [shortcuts[0].name]);
1048         button.disabled = true;
1049         button.appendChild(document.createElement("img"));
1050         button.addEventListener("click", handler, false);
1051         this.sidebarButtonsElement.appendChild(button);
1052
1053         var shortcutNames = [];
1054         for (var i = 0; i < shortcuts.length; ++i) {
1055             this.registerShortcut(shortcuts[i].key, handler);
1056             shortcutNames.push(shortcuts[i].name);
1057         }
1058         var section = WebInspector.shortcutsScreen.section(WebInspector.UIString("Scripts Panel"));
1059         section.addAlternateKeys(shortcutNames, shortcutDescription);
1060
1061         return button;
1062     },
1063
1064     searchCanceled: function()
1065     {
1066         if (this._searchView)
1067             this._searchView.searchCanceled();
1068
1069         delete this._searchView;
1070         delete this._searchQuery;
1071     },
1072
1073     performSearch: function(query)
1074     {
1075         WebInspector.searchController.updateSearchMatchesCount(0, this);
1076
1077         if (!this.visibleView)
1078             return;
1079
1080         // Call searchCanceled since it will reset everything we need before doing a new search.
1081         this.searchCanceled();
1082
1083         this._searchView = this.visibleView;
1084         this._searchQuery = query;
1085
1086         function finishedCallback(view, searchMatches)
1087         {
1088             if (!searchMatches)
1089                 return;
1090
1091             WebInspector.searchController.updateSearchMatchesCount(searchMatches, this);
1092             view.jumpToFirstSearchResult();
1093             WebInspector.searchController.updateCurrentMatchIndex(view.currentSearchResultIndex + 1, this);
1094         }
1095
1096         this._searchView.performSearch(query, finishedCallback.bind(this));
1097     },
1098
1099     jumpToNextSearchResult: function()
1100     {
1101         if (!this._searchView)
1102             return;
1103
1104         if (this._searchView !== this.visibleView) {
1105             this.performSearch(this._searchQuery);
1106             return;
1107         }
1108
1109         if (this._searchView.showingLastSearchResult())
1110             this._searchView.jumpToFirstSearchResult();
1111         else
1112             this._searchView.jumpToNextSearchResult();
1113         WebInspector.searchController.updateCurrentMatchIndex(this._searchView.currentSearchResultIndex + 1, this);
1114     },
1115
1116     jumpToPreviousSearchResult: function()
1117     {
1118         if (!this._searchView)
1119             return;
1120
1121         if (this._searchView !== this.visibleView) {
1122             this.performSearch(this._searchQuery);
1123             if (this._searchView)
1124                 this._searchView.jumpToLastSearchResult();
1125             return;
1126         }
1127
1128         if (this._searchView.showingFirstSearchResult())
1129             this._searchView.jumpToLastSearchResult();
1130         else
1131             this._searchView.jumpToPreviousSearchResult();
1132         WebInspector.searchController.updateCurrentMatchIndex(this._searchView.currentSearchResultIndex + 1, this);
1133     },
1134
1135     _toggleFormatSource: function()
1136     {
1137         this._toggleFormatSourceButton.toggled = !this._toggleFormatSourceButton.toggled;
1138         this._presentationModel.setFormatSource(this._toggleFormatSourceButton.toggled);
1139     },
1140
1141     _contextMenu: function(event)
1142     {
1143         var contextMenu = new WebInspector.ContextMenu();
1144
1145         function enableWorkerInspection()
1146         {
1147             var newValue = !WebInspector.settings.workerInspectionEnabled.get();
1148             WebInspector.settings.workerInspectionEnabled.set(newValue);
1149             WorkerAgent.setWorkerInspectionEnabled(newValue);
1150             if (newValue) {
1151                 var element = this.sidebarPanes.workers.element;
1152                 delete this.sidebarPanes.workers;
1153                 this.sidebarPanes.workerList = new WebInspector.WorkerListSidebarPane(WebInspector.workerManager);
1154                 element.parentNode.replaceChild(this.sidebarPanes.workerList.element, element);
1155             } else {
1156                 var element = this.sidebarPanes.workerList.element;
1157                 delete this.sidebarPanes.workerList;
1158                 this.sidebarPanes.workers = new WebInspector.WorkersSidebarPane();
1159                 element.parentNode.replaceChild(this.sidebarPanes.workers.element, element);
1160             }
1161         }
1162         contextMenu.appendCheckboxItem(WebInspector.UIString("Enable worker inspection"), enableWorkerInspection.bind(this), WebInspector.settings.workerInspectionEnabled.get());
1163
1164         contextMenu.show(event);
1165     }
1166 }
1167
1168 WebInspector.ScriptsPanel.prototype.__proto__ = WebInspector.Panel.prototype;