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