a6e20d60cdab00038e76c39b5f05e824694f0cf7
[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 importScript("BreakpointsSidebarPane.js");
28 importScript("CallStackSidebarPane.js");
29 importScript("FilteredItemSelectionDialog.js");
30 importScript("UISourceCodeFrame.js");
31 importScript("JavaScriptSourceFrame.js");
32 importScript("NavigatorOverlayController.js");
33 importScript("NavigatorView.js");
34 importScript("RevisionHistoryView.js");
35 importScript("ScopeChainSidebarPane.js");
36 importScript("ScriptsNavigator.js");
37 importScript("ScriptsSearchScope.js");
38 importScript("SnippetJavaScriptSourceFrame.js");
39 importScript("StyleSheetOutlineDialog.js");
40 importScript("TabbedEditorContainer.js");
41 importScript("WatchExpressionsSidebarPane.js");
42 importScript("WorkersSidebarPane.js");
43
44 /**
45  * @constructor
46  * @implements {WebInspector.TabbedEditorContainerDelegate}
47  * @implements {WebInspector.ContextMenu.Provider}
48  * @extends {WebInspector.Panel}
49  * @param {WebInspector.Workspace=} workspaceForTest
50  */
51 WebInspector.ScriptsPanel = function(workspaceForTest)
52 {
53     WebInspector.Panel.call(this, "scripts");
54     this.registerRequiredCSS("scriptsPanel.css");
55
56     WebInspector.settings.navigatorWasOnceHidden = WebInspector.settings.createSetting("navigatorWasOnceHidden", false);
57     WebInspector.settings.debuggerSidebarHidden = WebInspector.settings.createSetting("debuggerSidebarHidden", false);
58
59     this._workspace = workspaceForTest || WebInspector.workspace;
60
61     function viewGetter()
62     {
63         return this.visibleView;
64     }
65     WebInspector.GoToLineDialog.install(this, viewGetter.bind(this));
66
67     var helpSection = WebInspector.shortcutsScreen.section(WebInspector.UIString("Sources Panel"));
68     this.debugToolbar = this._createDebugToolbar();
69
70     const initialDebugSidebarWidth = 225;
71     const minimumDebugSidebarWidthPercent = 50;
72     this.createSidebarView(this.element, WebInspector.SidebarView.SidebarPosition.End, initialDebugSidebarWidth);
73     this.splitView.element.id = "scripts-split-view";
74     this.splitView.setMinimumSidebarWidth(Preferences.minScriptsSidebarWidth);
75     this.splitView.setMinimumMainWidthPercent(minimumDebugSidebarWidthPercent);
76
77     this.debugSidebarResizeWidgetElement = document.createElement("div");
78     this.debugSidebarResizeWidgetElement.id = "scripts-debug-sidebar-resizer-widget";
79     this.splitView.installResizer(this.debugSidebarResizeWidgetElement);
80
81     // Create scripts navigator
82     const initialNavigatorWidth = 225;
83     const minimumViewsContainerWidthPercent = 50;
84     this.editorView = new WebInspector.SidebarView(WebInspector.SidebarView.SidebarPosition.Start, "scriptsPanelNavigatorSidebarWidth", initialNavigatorWidth);
85     this.editorView.element.tabIndex = 0;
86
87     this.editorView.setMinimumSidebarWidth(Preferences.minScriptsSidebarWidth);
88     this.editorView.setMinimumMainWidthPercent(minimumViewsContainerWidthPercent);
89     this.editorView.show(this.splitView.mainElement);
90
91     this._navigator = new WebInspector.ScriptsNavigator();
92     this._navigator.view.show(this.editorView.sidebarElement);
93
94     this._editorContainer = new WebInspector.TabbedEditorContainer(this, "previouslyViewedFiles");
95     this._editorContainer.show(this.editorView.mainElement);
96
97     this._navigatorController = new WebInspector.NavigatorOverlayController(this.editorView, this._navigator.view, this._editorContainer.view);
98
99     this._navigator.addEventListener(WebInspector.ScriptsNavigator.Events.ScriptSelected, this._scriptSelected, this);
100     this._navigator.addEventListener(WebInspector.ScriptsNavigator.Events.SnippetCreationRequested, this._snippetCreationRequested, this);
101     this._navigator.addEventListener(WebInspector.ScriptsNavigator.Events.ItemRenamingRequested, this._itemRenamingRequested, this);
102     this._navigator.addEventListener(WebInspector.ScriptsNavigator.Events.FileRenamed, this._fileRenamed, this);
103
104     this._editorContainer.addEventListener(WebInspector.TabbedEditorContainer.Events.EditorSelected, this._editorSelected, this);
105     this._editorContainer.addEventListener(WebInspector.TabbedEditorContainer.Events.EditorClosed, this._editorClosed, this);
106
107     this.splitView.mainElement.appendChild(this.debugSidebarResizeWidgetElement);
108
109     this.sidebarPanes = {};
110     this.sidebarPanes.watchExpressions = new WebInspector.WatchExpressionsSidebarPane();
111     this.sidebarPanes.callstack = new WebInspector.CallStackSidebarPane();
112     this.sidebarPanes.scopechain = new WebInspector.ScopeChainSidebarPane();
113     this.sidebarPanes.jsBreakpoints = new WebInspector.JavaScriptBreakpointsSidebarPane(WebInspector.breakpointManager, this._showSourceLine.bind(this));
114     this.sidebarPanes.domBreakpoints = WebInspector.domBreakpointsSidebarPane.createProxy(this);
115     this.sidebarPanes.xhrBreakpoints = new WebInspector.XHRBreakpointsSidebarPane();
116     this.sidebarPanes.eventListenerBreakpoints = new WebInspector.EventListenerBreakpointsSidebarPane();
117
118     if (Capabilities.canInspectWorkers && !WebInspector.WorkerManager.isWorkerFrontend()) {
119         WorkerAgent.enable();
120         this.sidebarPanes.workerList = new WebInspector.WorkersSidebarPane(WebInspector.workerManager);
121     }
122
123     this.sidebarPanes.callstack.registerShortcuts(this.registerShortcuts.bind(this));
124     this.registerShortcuts(WebInspector.ScriptsPanelDescriptor.ShortcutKeys.EvaluateSelectionInConsole, this._evaluateSelectionInConsole.bind(this));
125     this.registerShortcuts(WebInspector.ScriptsPanelDescriptor.ShortcutKeys.GoToMember, this._showOutlineDialog.bind(this));
126     this.registerShortcuts(WebInspector.ScriptsPanelDescriptor.ShortcutKeys.ToggleBreakpoint, this._toggleBreakpoint.bind(this));
127
128     var panelEnablerHeading = WebInspector.UIString("You need to enable debugging before you can use the Scripts panel.");
129     var panelEnablerDisclaimer = WebInspector.UIString("Enabling debugging will make scripts run slower.");
130     var panelEnablerButton = WebInspector.UIString("Enable Debugging");
131
132     this.panelEnablerView = new WebInspector.PanelEnablerView("scripts", panelEnablerHeading, panelEnablerDisclaimer, panelEnablerButton);
133     this.panelEnablerView.addEventListener("enable clicked", this._enableDebugging, this);
134
135     this.enableToggleButton = new WebInspector.StatusBarButton("", "enable-toggle-status-bar-item");
136     this.enableToggleButton.addEventListener("click", this._toggleDebugging, this);
137     if (!Capabilities.debuggerCausesRecompilation)
138         this.enableToggleButton.element.addStyleClass("hidden");
139
140     this._pauseOnExceptionButton = new WebInspector.StatusBarButton("", "scripts-pause-on-exceptions-status-bar-item", 3);
141     this._pauseOnExceptionButton.addEventListener("click", this._togglePauseOnExceptions, this);
142
143     this._toggleFormatSourceButton = new WebInspector.StatusBarButton(WebInspector.UIString("Pretty print"), "scripts-toggle-pretty-print-status-bar-item");
144     this._toggleFormatSourceButton.toggled = false;
145     this._toggleFormatSourceButton.addEventListener("click", this._toggleFormatSource, this);
146
147     this._scriptViewStatusBarItemsContainer = document.createElement("div");
148     this._scriptViewStatusBarItemsContainer.style.display = "inline-block";
149
150     this._installDebuggerSidebarController();
151
152     WebInspector.dockController.addEventListener(WebInspector.DockController.Events.DockSideChanged, this._dockSideChanged.bind(this));
153     WebInspector.settings.splitVerticallyWhenDockedToRight.addChangeListener(this._dockSideChanged.bind(this));
154     this._dockSideChanged();
155
156     this._sourceFramesByUISourceCode = new Map();
157     this._updateDebuggerButtons();
158     this._pauseOnExceptionStateChanged();
159     if (WebInspector.debuggerModel.isPaused())
160         this._debuggerPaused();
161
162     WebInspector.settings.pauseOnExceptionStateString.addChangeListener(this._pauseOnExceptionStateChanged, this);
163     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerWasEnabled, this._debuggerWasEnabled, this);
164     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerWasDisabled, this._debuggerWasDisabled, this);
165     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
166     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerResumed, this._debuggerResumed, this);
167     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.CallFrameSelected, this._callFrameSelected, this);
168     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.ConsoleCommandEvaluatedInSelectedCallFrame, this._consoleCommandEvaluatedInSelectedCallFrame, this);
169     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.ExecutionLineChanged, this._executionLineChanged, this);
170     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointsActiveStateChanged, this._breakpointsActiveStateChanged, this);
171
172     WebInspector.startBatchUpdate();
173     var uiSourceCodes = this._workspace.uiSourceCodes();
174     for (var i = 0; i < uiSourceCodes.length; ++i)
175         this._addUISourceCode(uiSourceCodes[i]);
176     WebInspector.endBatchUpdate();
177
178     this._workspace.addEventListener(WebInspector.UISourceCodeProvider.Events.UISourceCodeAdded, this._uiSourceCodeAdded, this);
179     this._workspace.addEventListener(WebInspector.UISourceCodeProvider.Events.UISourceCodeRemoved, this._uiSourceCodeRemoved, this);
180     this._workspace.addEventListener(WebInspector.Workspace.Events.ProjectWillReset, this._projectWillReset.bind(this), this);
181     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.GlobalObjectCleared, this._debuggerReset, this);
182
183     WebInspector.advancedSearchController.registerSearchScope(new WebInspector.ScriptsSearchScope(this._workspace));
184 }
185
186 WebInspector.ScriptsPanel.prototype = {
187     get statusBarItems()
188     {
189         return [this.enableToggleButton.element, this._pauseOnExceptionButton.element, this._toggleFormatSourceButton.element, this._scriptViewStatusBarItemsContainer];
190     },
191
192     /**
193      * @return {?Element}
194      */
195     statusBarText: function()
196     {
197         var sourceFrame = this.visibleView;
198         return sourceFrame ? sourceFrame.statusBarText() : null;
199     },
200
201     defaultFocusedElement: function()
202     {
203         return this._editorContainer.view.defaultFocusedElement() || this._navigator.view.defaultFocusedElement();
204     },
205
206     get paused()
207     {
208         return this._paused;
209     },
210
211     wasShown: function()
212     {
213         WebInspector.Panel.prototype.wasShown.call(this);
214         this._navigatorController.wasShown();
215     },
216
217     willHide: function()
218     {
219         WebInspector.Panel.prototype.willHide.call(this);
220         WebInspector.closeViewInDrawer();
221     },
222
223     /**
224      * @param {WebInspector.Event} event
225      */
226     _uiSourceCodeAdded: function(event)
227     {
228         var uiSourceCode = /** @type {WebInspector.UISourceCode} */ (event.data);
229         this._addUISourceCode(uiSourceCode);
230     },
231
232     /**
233      * @param {WebInspector.UISourceCode} uiSourceCode
234      */
235     _addUISourceCode: function(uiSourceCode)
236     {
237         if (this._toggleFormatSourceButton.toggled)
238             uiSourceCode.setFormatted(true);
239         if (uiSourceCode.project().isServiceProject())
240             return;
241         this._navigator.addUISourceCode(uiSourceCode);
242         this._editorContainer.addUISourceCode(uiSourceCode);
243         // Replace debugger script-based uiSourceCode with a network-based one.
244         var currentUISourceCode = this._currentUISourceCode;
245         if (currentUISourceCode && currentUISourceCode.project().isServiceProject() && currentUISourceCode !== uiSourceCode && currentUISourceCode.url === uiSourceCode.url) {
246             this._showFile(uiSourceCode);
247             this._editorContainer.removeUISourceCode(currentUISourceCode);
248         }
249     },
250
251     _uiSourceCodeRemoved: function(event)
252     {
253         var uiSourceCode = /** @type {WebInspector.UISourceCode} */ (event.data);
254         this._removeUISourceCodes([uiSourceCode]);
255     },
256
257     /**
258      * @param {Array.<WebInspector.UISourceCode>} uiSourceCodes
259      */
260     _removeUISourceCodes: function(uiSourceCodes)
261     {
262         for (var i = 0; i < uiSourceCodes.length; ++i) {
263             this._navigator.removeUISourceCode(uiSourceCodes[i]);
264             this._removeSourceFrame(uiSourceCodes[i]);
265         }
266         this._editorContainer.removeUISourceCodes(uiSourceCodes);
267     },
268
269     _consoleCommandEvaluatedInSelectedCallFrame: function(event)
270     {
271         this.sidebarPanes.scopechain.update(WebInspector.debuggerModel.selectedCallFrame());
272     },
273
274     _debuggerPaused: function()
275     {
276         var details = WebInspector.debuggerModel.debuggerPausedDetails();
277
278         this._paused = true;
279         this._waitingToPause = false;
280         this._stepping = false;
281
282         this._updateDebuggerButtons();
283
284         WebInspector.inspectorView.setCurrentPanel(this);
285         this.sidebarPanes.callstack.update(details.callFrames);
286
287         if (details.reason === WebInspector.DebuggerModel.BreakReason.DOM) {
288             WebInspector.domBreakpointsSidebarPane.highlightBreakpoint(details.auxData);
289             function didCreateBreakpointHitStatusMessage(element)
290             {
291                 this.sidebarPanes.callstack.setStatus(element);
292             }
293             WebInspector.domBreakpointsSidebarPane.createBreakpointHitStatusMessage(details.auxData, didCreateBreakpointHitStatusMessage.bind(this));
294         } else if (details.reason === WebInspector.DebuggerModel.BreakReason.EventListener) {
295             var eventName = details.auxData.eventName;
296             this.sidebarPanes.eventListenerBreakpoints.highlightBreakpoint(details.auxData.eventName);
297             var eventNameForUI = WebInspector.EventListenerBreakpointsSidebarPane.eventNameForUI(eventName);
298             this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a \"%s\" Event Listener.", eventNameForUI));
299         } else if (details.reason === WebInspector.DebuggerModel.BreakReason.XHR) {
300             this.sidebarPanes.xhrBreakpoints.highlightBreakpoint(details.auxData["breakpointURL"]);
301             this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a XMLHttpRequest."));
302         } else if (details.reason === WebInspector.DebuggerModel.BreakReason.Exception)
303             this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on exception: '%s'.", details.auxData.description));
304         else if (details.reason === WebInspector.DebuggerModel.BreakReason.Assert)
305             this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on assertion."));
306         else if (details.reason === WebInspector.DebuggerModel.BreakReason.CSPViolation)
307             this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a script blocked due to Content Security Policy directive: \"%s\".", details.auxData["directiveText"]));
308         else {
309             function didGetUILocation(uiLocation)
310             {
311                 var breakpoint = WebInspector.breakpointManager.findBreakpoint(uiLocation.uiSourceCode, uiLocation.lineNumber);
312                 if (!breakpoint)
313                     return;
314                 this.sidebarPanes.jsBreakpoints.highlightBreakpoint(breakpoint);
315                 this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a JavaScript breakpoint."));
316             }
317             if (details.callFrames.length) 
318                 details.callFrames[0].createLiveLocation(didGetUILocation.bind(this));
319             else
320                 console.warn("ScriptsPanel paused, but callFrames.length is zero."); // TODO remove this once we understand this case better
321         }
322
323         this._showDebuggerSidebar();
324         this._toggleDebuggerSidebarButton.setEnabled(false);
325         window.focus();
326         InspectorFrontendHost.bringToFront();
327     },
328
329     _debuggerResumed: function()
330     {
331         this._paused = false;
332         this._waitingToPause = false;
333         this._stepping = false;
334
335         this._clearInterface();
336         this._toggleDebuggerSidebarButton.setEnabled(true);
337     },
338
339     _debuggerWasEnabled: function()
340     {
341         this._updateDebuggerButtons();
342     },
343
344     _debuggerWasDisabled: function()
345     {
346         this._debuggerReset();
347     },
348
349     _debuggerReset: function()
350     {
351         this._debuggerResumed();
352         this.sidebarPanes.watchExpressions.reset();
353     },
354
355     _projectWillReset: function(event)
356     {
357         var project = event.data;
358         var uiSourceCodes = project.uiSourceCodes();
359         this._removeUISourceCodes(uiSourceCodes);
360         if (project.type() === WebInspector.projectTypes.Network)
361             this._editorContainer.reset();
362     },
363
364     get visibleView()
365     {
366         return this._editorContainer.visibleView;
367     },
368
369     _updateScriptViewStatusBarItems: function()
370     {
371         this._scriptViewStatusBarItemsContainer.removeChildren();
372
373         var sourceFrame = this.visibleView;
374         if (sourceFrame) {
375             var statusBarItems = sourceFrame.statusBarItems() || [];
376             for (var i = 0; i < statusBarItems.length; ++i)
377                 this._scriptViewStatusBarItemsContainer.appendChild(statusBarItems[i]);
378         }
379     },
380
381     canShowAnchorLocation: function(anchor)
382     {
383         if (WebInspector.debuggerModel.debuggerEnabled() && anchor.uiSourceCode)
384             return true;
385         var uiSourceCode = WebInspector.workspace.uiSourceCodeForURL(anchor.href);
386         if (uiSourceCode) {
387             anchor.uiSourceCode = uiSourceCode;
388             return true;
389         }
390         return false;
391     },
392
393     showAnchorLocation: function(anchor)
394     {
395         this._showSourceLine(anchor.uiSourceCode, anchor.lineNumber);
396     },
397
398     /**
399      * @param {WebInspector.UISourceCode} uiSourceCode
400      * @param {number} lineNumber
401      */
402     showUISourceCode: function(uiSourceCode, lineNumber)
403     {
404         this._showSourceLine(uiSourceCode, lineNumber);
405     },
406
407     /**
408      * @param {WebInspector.UISourceCode} uiSourceCode
409      * @param {number=} lineNumber
410      */
411     _showSourceLine: function(uiSourceCode, lineNumber)
412     {
413         var sourceFrame = this._showFile(uiSourceCode);
414         if (typeof lineNumber === "number")
415             sourceFrame.highlightLine(lineNumber);
416         sourceFrame.focus();
417
418         WebInspector.notifications.dispatchEventToListeners(WebInspector.UserMetrics.UserAction, {
419             action: WebInspector.UserMetrics.UserActionNames.OpenSourceLink,
420             url: uiSourceCode.originURL(),
421             lineNumber: lineNumber
422         });
423     },
424
425     /**
426      * @param {WebInspector.UISourceCode} uiSourceCode
427      * @return {WebInspector.SourceFrame}
428      */
429     _showFile: function(uiSourceCode)
430     {
431         var sourceFrame = this._getOrCreateSourceFrame(uiSourceCode);
432         if (this._currentUISourceCode === uiSourceCode)
433             return sourceFrame;
434         this._currentUISourceCode = uiSourceCode;
435         if (!uiSourceCode.project().isServiceProject())
436             this._navigator.revealUISourceCode(uiSourceCode, true);
437         this._editorContainer.showFile(uiSourceCode);
438         this._updateScriptViewStatusBarItems();
439
440         return sourceFrame;
441     },
442
443     /**
444      * @param {WebInspector.UISourceCode} uiSourceCode
445      * @return {WebInspector.SourceFrame}
446      */
447     _createSourceFrame: function(uiSourceCode)
448     {
449         var sourceFrame;
450         switch (uiSourceCode.contentType()) {
451         case WebInspector.resourceTypes.Script:
452             if (uiSourceCode.project().type() === WebInspector.projectTypes.Snippets)
453                 sourceFrame = new WebInspector.SnippetJavaScriptSourceFrame(this, uiSourceCode);
454             else
455                 sourceFrame = new WebInspector.JavaScriptSourceFrame(this, uiSourceCode);
456             break;
457         case WebInspector.resourceTypes.Document:
458             sourceFrame = new WebInspector.JavaScriptSourceFrame(this, uiSourceCode);
459             break;
460         case WebInspector.resourceTypes.Stylesheet:
461         default:
462             sourceFrame = new WebInspector.UISourceCodeFrame(uiSourceCode);
463         break;
464         }
465         this._sourceFramesByUISourceCode.put(uiSourceCode, sourceFrame);
466         return sourceFrame;
467     },
468
469     /**
470      * @param {WebInspector.UISourceCode} uiSourceCode
471      * @return {WebInspector.SourceFrame}
472      */
473     _getOrCreateSourceFrame: function(uiSourceCode)
474     {
475         return this._sourceFramesByUISourceCode.get(uiSourceCode) || this._createSourceFrame(uiSourceCode);
476     },
477
478     /**
479      * @param {WebInspector.UISourceCode} uiSourceCode
480      * @return {WebInspector.SourceFrame}
481      */
482     viewForFile: function(uiSourceCode)
483     {
484         return this._getOrCreateSourceFrame(uiSourceCode);
485     },
486
487     /**
488      * @param {WebInspector.UISourceCode} uiSourceCode
489      */
490     _removeSourceFrame: function(uiSourceCode)
491     {
492         var sourceFrame = this._sourceFramesByUISourceCode.get(uiSourceCode);
493         if (!sourceFrame)
494             return;
495         this._sourceFramesByUISourceCode.remove(uiSourceCode);
496         sourceFrame.dispose();
497     },
498
499     _clearCurrentExecutionLine: function()
500     {
501         if (this._executionSourceFrame)
502             this._executionSourceFrame.clearExecutionLine();
503         delete this._executionSourceFrame;
504     },
505
506     _executionLineChanged: function(event)
507     {
508         var uiLocation = event.data;
509
510         this._clearCurrentExecutionLine();
511         if (!uiLocation)
512             return;
513         var sourceFrame = this._getOrCreateSourceFrame(uiLocation.uiSourceCode);
514         sourceFrame.setExecutionLine(uiLocation.lineNumber);
515         this._executionSourceFrame = sourceFrame;
516     },
517
518     _revealExecutionLine: function(uiLocation)
519     {
520         var uiSourceCode = uiLocation.uiSourceCode;
521         // Some scripts (anonymous and snippets evaluations) are not added to files select by default.
522         if (this._currentUISourceCode && this._currentUISourceCode.scriptFile() && this._currentUISourceCode.scriptFile().isDivergingFromVM())
523             return;
524         if (this._toggleFormatSourceButton.toggled && !uiSourceCode.formatted())
525             uiSourceCode.setFormatted(true);
526         var sourceFrame = this._showFile(uiSourceCode);
527         sourceFrame.revealLine(uiLocation.lineNumber);
528         sourceFrame.focus();
529     },
530
531     _callFrameSelected: function(event)
532     {
533         var callFrame = event.data;
534
535         if (!callFrame)
536             return;
537
538         this.sidebarPanes.scopechain.update(callFrame);
539         this.sidebarPanes.watchExpressions.refreshExpressions();
540         this.sidebarPanes.callstack.setSelectedCallFrame(callFrame);
541         callFrame.createLiveLocation(this._revealExecutionLine.bind(this));
542     },
543
544     _editorClosed: function(event)
545     {
546         this._navigatorController.hideNavigatorOverlay();
547         var uiSourceCode = /** @type {WebInspector.UISourceCode} */ (event.data);
548
549         if (this._currentUISourceCode === uiSourceCode)
550             delete this._currentUISourceCode;
551
552         // ScriptsNavigator does not need to update on EditorClosed.
553         this._updateScriptViewStatusBarItems();
554         WebInspector.searchController.resetSearch();
555     },
556
557     _editorSelected: function(event)
558     {
559         var uiSourceCode = /** @type {WebInspector.UISourceCode} */ (event.data);
560         var sourceFrame = this._showFile(uiSourceCode);
561         this._navigatorController.hideNavigatorOverlay();
562         sourceFrame.focus();
563         WebInspector.searchController.resetSearch();
564     },
565
566     _scriptSelected: function(event)
567     {
568         var uiSourceCode = /** @type {WebInspector.UISourceCode} */ (event.data.uiSourceCode);
569         var sourceFrame = this._showFile(uiSourceCode);
570         this._navigatorController.hideNavigatorOverlay();
571         if (sourceFrame && event.data.focusSource)
572             sourceFrame.focus();
573     },
574
575     _pauseOnExceptionStateChanged: function()
576     {
577         var pauseOnExceptionsState = WebInspector.settings.pauseOnExceptionStateString.get();
578         switch (pauseOnExceptionsState) {
579         case WebInspector.DebuggerModel.PauseOnExceptionsState.DontPauseOnExceptions:
580             this._pauseOnExceptionButton.title = WebInspector.UIString("Don't pause on exceptions.\nClick to Pause on all exceptions.");
581             break;
582         case WebInspector.DebuggerModel.PauseOnExceptionsState.PauseOnAllExceptions:
583             this._pauseOnExceptionButton.title = WebInspector.UIString("Pause on all exceptions.\nClick to Pause on uncaught exceptions.");
584             break;
585         case WebInspector.DebuggerModel.PauseOnExceptionsState.PauseOnUncaughtExceptions:
586             this._pauseOnExceptionButton.title = WebInspector.UIString("Pause on uncaught exceptions.\nClick to Not pause on exceptions.");
587             break;
588         }
589         this._pauseOnExceptionButton.state = pauseOnExceptionsState;
590     },
591
592     _updateDebuggerButtons: function()
593     {
594         if (WebInspector.debuggerModel.debuggerEnabled()) {
595             this.enableToggleButton.title = WebInspector.UIString("Debugging enabled. Click to disable.");
596             this.enableToggleButton.toggled = true;
597             this._pauseOnExceptionButton.visible = true;
598             this.panelEnablerView.detach();
599         } else {
600             this.enableToggleButton.title = WebInspector.UIString("Debugging disabled. Click to enable.");
601             this.enableToggleButton.toggled = false;
602             this._pauseOnExceptionButton.visible = false;
603             this.panelEnablerView.show(this.element);
604         }
605
606         if (this._paused) {
607             this._updateButtonTitle(this.pauseButton, WebInspector.UIString("Resume script execution (%s)."))
608             this.pauseButton.addStyleClass("paused");
609
610             this.pauseButton.disabled = false;
611             this.stepOverButton.disabled = false;
612             this.stepIntoButton.disabled = false;
613             this.stepOutButton.disabled = false;
614
615             this.debuggerStatusElement.textContent = WebInspector.UIString("Paused");
616         } else {
617             this._updateButtonTitle(this.pauseButton, WebInspector.UIString("Pause script execution (%s)."))
618             this.pauseButton.removeStyleClass("paused");
619
620             this.pauseButton.disabled = this._waitingToPause;
621             this.stepOverButton.disabled = true;
622             this.stepIntoButton.disabled = true;
623             this.stepOutButton.disabled = true;
624
625             if (this._waitingToPause)
626                 this.debuggerStatusElement.textContent = WebInspector.UIString("Pausing");
627             else if (this._stepping)
628                 this.debuggerStatusElement.textContent = WebInspector.UIString("Stepping");
629             else
630                 this.debuggerStatusElement.textContent = "";
631         }
632     },
633
634     _clearInterface: function()
635     {
636         this.sidebarPanes.callstack.update(null);
637         this.sidebarPanes.scopechain.update(null);
638         this.sidebarPanes.jsBreakpoints.clearBreakpointHighlight();
639         WebInspector.domBreakpointsSidebarPane.clearBreakpointHighlight();
640         this.sidebarPanes.eventListenerBreakpoints.clearBreakpointHighlight();
641         this.sidebarPanes.xhrBreakpoints.clearBreakpointHighlight();
642
643         this._clearCurrentExecutionLine();
644         this._updateDebuggerButtons();
645     },
646
647     _enableDebugging: function()
648     {
649         this._toggleDebugging(this.panelEnablerView.alwaysEnabled);
650     },
651
652     _toggleDebugging: function(optionalAlways)
653     {
654         this._paused = false;
655         this._waitingToPause = false;
656         this._stepping = false;
657
658         if (WebInspector.debuggerModel.debuggerEnabled()) {
659             WebInspector.settings.debuggerEnabled.set(false);
660             WebInspector.debuggerModel.disableDebugger();
661         } else {
662             WebInspector.settings.debuggerEnabled.set(!!optionalAlways);
663             WebInspector.debuggerModel.enableDebugger();
664         }
665     },
666
667     _togglePauseOnExceptions: function()
668     {
669         var nextStateMap = {};
670         var stateEnum = WebInspector.DebuggerModel.PauseOnExceptionsState;
671         nextStateMap[stateEnum.DontPauseOnExceptions] = stateEnum.PauseOnAllExceptions;
672         nextStateMap[stateEnum.PauseOnAllExceptions] = stateEnum.PauseOnUncaughtExceptions;
673         nextStateMap[stateEnum.PauseOnUncaughtExceptions] = stateEnum.DontPauseOnExceptions;
674         WebInspector.settings.pauseOnExceptionStateString.set(nextStateMap[this._pauseOnExceptionButton.state]);
675     },
676
677     /**
678      * @param {Event=} event
679      * @return {boolean}
680      */
681     _togglePause: function(event)
682     {
683         if (this._paused) {
684             this._paused = false;
685             this._waitingToPause = false;
686             DebuggerAgent.resume();
687         } else {
688             this._stepping = false;
689             this._waitingToPause = true;
690             DebuggerAgent.pause();
691         }
692
693         this._clearInterface();
694         return true;
695     },
696
697     /**
698      * @param {Event=} event
699      * @return {boolean}
700      */
701     _stepOverClicked: function(event)
702     {
703         if (!this._paused)
704             return true;
705
706         this._paused = false;
707         this._stepping = true;
708
709         this._clearInterface();
710
711         DebuggerAgent.stepOver();
712         return true;
713     },
714
715     /**
716      * @param {Event=} event
717      * @return {boolean}
718      */
719     _stepIntoClicked: function(event)
720     {
721         if (!this._paused)
722             return true;
723
724         this._paused = false;
725         this._stepping = true;
726
727         this._clearInterface();
728
729         DebuggerAgent.stepInto();
730         return true;
731     },
732
733     /**
734      * @param {Event=} event
735      * @return {boolean}
736      */
737     _stepOutClicked: function(event)
738     {
739         if (!this._paused)
740             return true;
741
742         this._paused = false;
743         this._stepping = true;
744
745         this._clearInterface();
746
747         DebuggerAgent.stepOut();
748         return true;
749     },
750
751     _toggleBreakpointsClicked: function(event)
752     {
753         WebInspector.debuggerModel.setBreakpointsActive(!WebInspector.debuggerModel.breakpointsActive());
754     },
755
756     _breakpointsActiveStateChanged: function(event)
757     {
758         var active = event.data;
759         this._toggleBreakpointsButton.toggled = active;
760         if (active) {
761             this._toggleBreakpointsButton.title = WebInspector.UIString("Deactivate breakpoints.");
762             WebInspector.inspectorView.element.removeStyleClass("breakpoints-deactivated");
763             this.sidebarPanes.jsBreakpoints.listElement.removeStyleClass("breakpoints-list-deactivated");
764         } else {
765             this._toggleBreakpointsButton.title = WebInspector.UIString("Activate breakpoints.");
766             WebInspector.inspectorView.element.addStyleClass("breakpoints-deactivated");
767             this.sidebarPanes.jsBreakpoints.listElement.addStyleClass("breakpoints-list-deactivated");
768         }
769     },
770
771     /**
772      * @param {Event=} event
773      * @return {boolean}
774      */
775     _evaluateSelectionInConsole: function(event)
776     {
777         var selection = window.getSelection();
778         if (selection.type !== "Range" || selection.isCollapsed)
779             return false;
780         WebInspector.evaluateInConsole(selection.toString());
781         return true;
782     },
783
784     _createDebugToolbar: function()
785     {
786         var debugToolbar = document.createElement("div");
787         debugToolbar.className = "status-bar";
788         debugToolbar.id = "scripts-debug-toolbar";
789
790         var title, handler;
791         var platformSpecificModifier = WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta;
792
793         // Continue.
794         handler = this._togglePause.bind(this);
795         this.pauseButton = this._createButtonAndRegisterShortcuts("scripts-pause", "", handler, WebInspector.ScriptsPanelDescriptor.ShortcutKeys.PauseContinue);
796         debugToolbar.appendChild(this.pauseButton);
797
798         // Step over.
799         title = WebInspector.UIString("Step over next function call (%s).");
800         handler = this._stepOverClicked.bind(this);
801         this.stepOverButton = this._createButtonAndRegisterShortcuts("scripts-step-over", title, handler, WebInspector.ScriptsPanelDescriptor.ShortcutKeys.StepOver);
802         debugToolbar.appendChild(this.stepOverButton);
803
804         // Step into.
805         title = WebInspector.UIString("Step into next function call (%s).");
806         handler = this._stepIntoClicked.bind(this);
807         this.stepIntoButton = this._createButtonAndRegisterShortcuts("scripts-step-into", title, handler, WebInspector.ScriptsPanelDescriptor.ShortcutKeys.StepInto);
808         debugToolbar.appendChild(this.stepIntoButton);
809
810         // Step out.
811         title = WebInspector.UIString("Step out of current function (%s).");
812         handler = this._stepOutClicked.bind(this);
813         this.stepOutButton = this._createButtonAndRegisterShortcuts("scripts-step-out", title, handler, WebInspector.ScriptsPanelDescriptor.ShortcutKeys.StepOut);
814         debugToolbar.appendChild(this.stepOutButton);
815
816         this._toggleBreakpointsButton = new WebInspector.StatusBarButton(WebInspector.UIString("Deactivate breakpoints."), "toggle-breakpoints");
817         this._toggleBreakpointsButton.toggled = true;
818         this._toggleBreakpointsButton.addEventListener("click", this._toggleBreakpointsClicked, this);
819         debugToolbar.appendChild(this._toggleBreakpointsButton.element);
820
821         this.debuggerStatusElement = document.createElement("div");
822         this.debuggerStatusElement.id = "scripts-debugger-status";
823         debugToolbar.appendChild(this.debuggerStatusElement);
824
825         return debugToolbar;
826     },
827
828     _updateButtonTitle: function(button, buttonTitle)
829     {
830         button.buttonTitle = buttonTitle;
831         var hasShortcuts = button.shortcuts && button.shortcuts.length;
832         if (hasShortcuts)
833             button.title = String.vsprintf(buttonTitle, [button.shortcuts[0].name]);
834         else
835             button.title = buttonTitle;
836     },
837
838     /**
839      * @param {string} buttonId
840      * @param {string} buttonTitle
841      * @param {function(Event=):boolean} handler
842      * @param {!Array.<!WebInspector.KeyboardShortcut.Descriptor>} shortcuts
843      */
844     _createButtonAndRegisterShortcuts: function(buttonId, buttonTitle, handler, shortcuts)
845     {
846         var button = document.createElement("button");
847         button.className = "status-bar-item";
848         button.id = buttonId;
849         button.shortcuts = shortcuts;
850         this._updateButtonTitle(button, buttonTitle);
851         button.disabled = true;
852         button.appendChild(document.createElement("img"));
853         button.addEventListener("click", handler, false);
854
855         this.registerShortcuts(shortcuts, handler);
856
857         return button;
858     },
859
860     searchCanceled: function()
861     {
862         if (this._searchView)
863             this._searchView.searchCanceled();
864
865         delete this._searchView;
866         delete this._searchQuery;
867     },
868
869     /**
870      * @param {string} query
871      */
872     performSearch: function(query)
873     {
874         WebInspector.searchController.updateSearchMatchesCount(0, this);
875
876         if (!this.visibleView)
877             return;
878
879         // Call searchCanceled since it will reset everything we need before doing a new search.
880         this.searchCanceled();
881
882         this._searchView = this.visibleView;
883         this._searchQuery = query;
884
885         function finishedCallback(view, searchMatches)
886         {
887             if (!searchMatches)
888                 return;
889
890             WebInspector.searchController.updateSearchMatchesCount(searchMatches, this);
891             view.jumpToNextSearchResult();
892             WebInspector.searchController.updateCurrentMatchIndex(view.currentSearchResultIndex, this);
893         }
894
895         this._searchView.performSearch(query, finishedCallback.bind(this));
896     },
897
898     jumpToNextSearchResult: function()
899     {
900         if (!this._searchView)
901             return;
902
903         if (this._searchView !== this.visibleView) {
904             this.performSearch(this._searchQuery);
905             return;
906         }
907
908         if (this._searchView.showingLastSearchResult())
909             this._searchView.jumpToFirstSearchResult();
910         else
911             this._searchView.jumpToNextSearchResult();
912         WebInspector.searchController.updateCurrentMatchIndex(this._searchView.currentSearchResultIndex, this);
913         return true;
914     },
915
916     jumpToPreviousSearchResult: function()
917     {
918         if (!this._searchView)
919             return;
920
921         if (this._searchView !== this.visibleView) {
922             this.performSearch(this._searchQuery);
923             if (this._searchView)
924                 this._searchView.jumpToLastSearchResult();
925             return;
926         }
927
928         if (this._searchView.showingFirstSearchResult())
929             this._searchView.jumpToLastSearchResult();
930         else
931             this._searchView.jumpToPreviousSearchResult();
932         WebInspector.searchController.updateCurrentMatchIndex(this._searchView.currentSearchResultIndex, this);
933     },
934
935     /**
936      * @return {boolean}
937      */
938     canSearchAndReplace: function()
939     {
940         var view = /** @type {WebInspector.SourceFrame} */ (this.visibleView);
941         return !!view && view.canEditSource();
942     },
943
944     /**
945      * @param {string} text
946      */
947     replaceSelectionWith: function(text)
948     {
949         var view = /** @type {WebInspector.SourceFrame} */ (this.visibleView);
950         view.replaceSearchMatchWith(text);
951     },
952
953     /**
954      * @param {string} query
955      * @param {string} text
956      */
957     replaceAllWith: function(query, text)
958     {
959         var view = /** @type {WebInspector.SourceFrame} */ (this.visibleView);
960         view.replaceAllWith(query, text);
961     },
962
963     _toggleFormatSource: function()
964     {
965         this._toggleFormatSourceButton.toggled = !this._toggleFormatSourceButton.toggled;
966         var uiSourceCodes = this._workspace.uiSourceCodes();
967         for (var i = 0; i < uiSourceCodes.length; ++i)
968             uiSourceCodes[i].setFormatted(this._toggleFormatSourceButton.toggled);
969
970         WebInspector.notifications.dispatchEventToListeners(WebInspector.UserMetrics.UserAction, {
971             action: WebInspector.UserMetrics.UserActionNames.TogglePrettyPrint,
972             enabled: this._toggleFormatSourceButton.toggled,
973             url: this._editorContainer.currentFile().originURL()
974         });
975     },
976
977     addToWatch: function(expression)
978     {
979         this.sidebarPanes.watchExpressions.addExpression(expression);
980     },
981
982     /**
983      * @return {boolean}
984      */
985     _toggleBreakpoint: function()
986     {
987         var sourceFrame = this.visibleView;
988         if (!sourceFrame)
989             return false;
990
991         if (sourceFrame instanceof WebInspector.JavaScriptSourceFrame) {
992             var javaScriptSourceFrame = /** @type {WebInspector.JavaScriptSourceFrame} */ (sourceFrame);
993             javaScriptSourceFrame.toggleBreakpointOnCurrentLine();
994             return true;
995         }
996         return false;
997     },
998
999     /**
1000      * @param {Event=} event
1001      * @return {boolean}
1002      */
1003     _showOutlineDialog: function(event)
1004     {
1005         var uiSourceCode = this._editorContainer.currentFile();
1006         if (!uiSourceCode)
1007             return false;
1008
1009         switch (uiSourceCode.contentType()) {
1010         case WebInspector.resourceTypes.Document:
1011         case WebInspector.resourceTypes.Script:
1012             WebInspector.JavaScriptOutlineDialog.show(this.visibleView, uiSourceCode);
1013             return true;
1014         case WebInspector.resourceTypes.Stylesheet:
1015             WebInspector.StyleSheetOutlineDialog.show(this.visibleView, uiSourceCode);
1016             return true;
1017         }
1018         return false;
1019     },
1020
1021     _installDebuggerSidebarController: function()
1022     {
1023         this._toggleDebuggerSidebarButton = new WebInspector.StatusBarButton(WebInspector.UIString("Hide debugger"), "scripts-debugger-show-hide-button", 3);
1024         this._toggleDebuggerSidebarButton.state = "shown";
1025         this._toggleDebuggerSidebarButton.addEventListener("click", clickHandler, this);
1026
1027         function clickHandler()
1028         {
1029             if (this._toggleDebuggerSidebarButton.state === "shown")
1030                 this._hideDebuggerSidebar();
1031             else
1032                 this._showDebuggerSidebar();
1033         }
1034         this.editorView.element.appendChild(this._toggleDebuggerSidebarButton.element);
1035
1036         if (WebInspector.settings.debuggerSidebarHidden.get())
1037             this._hideDebuggerSidebar();
1038
1039     },
1040
1041     _showDebuggerSidebar: function()
1042     {
1043         if (this._toggleDebuggerSidebarButton.state === "shown")
1044             return;
1045         this._toggleDebuggerSidebarButton.state = "shown";
1046         this._toggleDebuggerSidebarButton.title = WebInspector.UIString("Hide debugger");
1047         this.splitView.showSidebarElement();
1048         this.debugSidebarResizeWidgetElement.removeStyleClass("hidden");
1049         WebInspector.settings.debuggerSidebarHidden.set(false);
1050     },
1051
1052     _hideDebuggerSidebar: function()
1053     {
1054         if (this._toggleDebuggerSidebarButton.state === "hidden")
1055             return;
1056         this._toggleDebuggerSidebarButton.state = "hidden";
1057         this._toggleDebuggerSidebarButton.title = WebInspector.UIString("Show debugger");
1058         this.splitView.hideSidebarElement();
1059         this.debugSidebarResizeWidgetElement.addStyleClass("hidden");
1060         WebInspector.settings.debuggerSidebarHidden.set(true);
1061     },
1062
1063     _fileRenamed: function(event)
1064     {
1065         var uiSourceCode = /** @type {WebInspector.UISourceCode} */ (event.data.uiSourceCode);
1066         var name = /** @type {string} */ (event.data.name);
1067         if (uiSourceCode.project().type() !== WebInspector.projectTypes.Snippets)
1068             return;
1069         WebInspector.scriptSnippetModel.renameScriptSnippet(uiSourceCode, name);
1070         uiSourceCode.rename(name);
1071     },
1072         
1073     /**
1074      * @param {WebInspector.Event} event
1075      */
1076     _snippetCreationRequested: function(event)
1077     {
1078         var uiSourceCode = WebInspector.scriptSnippetModel.createScriptSnippet();
1079         this._showSourceLine(uiSourceCode);
1080         
1081         var shouldHideNavigator = !this._navigatorController.isNavigatorPinned();
1082         if (this._navigatorController.isNavigatorHidden())
1083             this._navigatorController.showNavigatorOverlay();
1084         this._navigator.rename(uiSourceCode, callback.bind(this));
1085     
1086         /**
1087          * @param {boolean} committed
1088          */
1089         function callback(committed)
1090         {
1091             if (shouldHideNavigator)
1092                 this._navigatorController.hideNavigatorOverlay();
1093
1094             if (!committed) {
1095                 WebInspector.scriptSnippetModel.deleteScriptSnippet(uiSourceCode);
1096                 return;
1097             }
1098
1099             this._showSourceLine(uiSourceCode);
1100         }
1101     },
1102
1103     /**
1104      * @param {WebInspector.Event} event
1105      */
1106     _itemRenamingRequested: function(event)
1107     {
1108         var uiSourceCode = /** @type {WebInspector.UISourceCode} */ (event.data);
1109         
1110         var shouldHideNavigator = !this._navigatorController.isNavigatorPinned();
1111         if (this._navigatorController.isNavigatorHidden())
1112             this._navigatorController.showNavigatorOverlay();
1113         this._navigator.rename(uiSourceCode, callback.bind(this));
1114     
1115         /**
1116          * @param {boolean} committed
1117          */
1118         function callback(committed)
1119         {
1120             if (shouldHideNavigator && committed) {
1121                 this._navigatorController.hideNavigatorOverlay();
1122                 this._showSourceLine(uiSourceCode);
1123             }
1124         }
1125     },
1126
1127     /**
1128      * @param {WebInspector.UISourceCode} uiSourceCode
1129      */
1130     _showLocalHistory: function(uiSourceCode)
1131     {
1132         WebInspector.RevisionHistoryView.showHistory(uiSourceCode);
1133     },
1134
1135     /**
1136      * @param {WebInspector.ContextMenu} contextMenu
1137      * @param {Object} target
1138      */
1139     appendApplicableItems: function(event, contextMenu, target)
1140     {
1141         this._appendUISourceCodeItems(contextMenu, target);
1142         this._appendFunctionItems(contextMenu, target);
1143     },
1144
1145     /** 
1146      * @param {WebInspector.UISourceCode} uiSourceCode
1147      */
1148     _mapFileSystemToNetwork: function(uiSourceCode)
1149     {
1150         WebInspector.SelectUISourceCodeForProjectTypeDialog.show(uiSourceCode.name(), WebInspector.projectTypes.Network, mapFileSystemToNetwork.bind(this), this.editorView.mainElement)                
1151
1152         /** 
1153          * @param {WebInspector.UISourceCode} networkUISourceCode
1154          */
1155         function mapFileSystemToNetwork(networkUISourceCode)
1156         {
1157             this._workspace.addMapping(networkUISourceCode, uiSourceCode, WebInspector.fileSystemWorkspaceProvider);
1158         }
1159     },
1160
1161     /** 
1162      * @param {WebInspector.UISourceCode} uiSourceCode
1163      */
1164     _removeNetworkMapping: function(uiSourceCode)
1165     {
1166         if (confirm(WebInspector.UIString("Are you sure you want to remove network mapping?")))
1167             this._workspace.removeMapping(uiSourceCode);
1168     },
1169
1170     /** 
1171      * @param {WebInspector.UISourceCode} networkUISourceCode
1172      */
1173     _mapNetworkToFileSystem: function(networkUISourceCode)
1174     {
1175         WebInspector.SelectUISourceCodeForProjectTypeDialog.show(networkUISourceCode.name(), WebInspector.projectTypes.FileSystem, mapNetworkToFileSystem.bind(this), this.editorView.mainElement)                
1176
1177         /** 
1178          * @param {WebInspector.UISourceCode} uiSourceCode
1179          */
1180         function mapNetworkToFileSystem(uiSourceCode)
1181         {
1182             this._workspace.addMapping(networkUISourceCode, uiSourceCode, WebInspector.fileSystemWorkspaceProvider);
1183         }
1184     },
1185
1186     /** 
1187      * @param {WebInspector.ContextMenu} contextMenu
1188      * @param {WebInspector.UISourceCode} uiSourceCode
1189      */
1190     _appendUISourceCodeMappingItems: function(contextMenu, uiSourceCode)
1191     {
1192         if (uiSourceCode.project().type() === WebInspector.projectTypes.FileSystem) {
1193             var hasMappings = !!uiSourceCode.url;
1194             if (!hasMappings)
1195                 contextMenu.appendItem(WebInspector.UIString("Map to network resource..."), this._mapFileSystemToNetwork.bind(this, uiSourceCode));
1196             else
1197                 contextMenu.appendItem(WebInspector.UIString("Remove network mapping"), this._removeNetworkMapping.bind(this, uiSourceCode));
1198         }
1199
1200         if (uiSourceCode.project().type() === WebInspector.projectTypes.Network) {
1201             /** 
1202              * @param {WebInspector.Project} project
1203              */
1204             function filterProject(project)
1205             {
1206                 return project.type() === WebInspector.projectTypes.FileSystem;
1207             }
1208
1209             if (!this._workspace.projects().filter(filterProject).length)
1210                 return;
1211             if (this._workspace.uiSourceCodeForURL(uiSourceCode.url) === uiSourceCode)
1212                 contextMenu.appendItem(WebInspector.UIString("Map to file system resource..."), this._mapNetworkToFileSystem.bind(this, uiSourceCode));
1213         }
1214     },
1215
1216     /** 
1217      * @param {WebInspector.ContextMenu} contextMenu
1218      * @param {Object} target
1219      */
1220     _appendUISourceCodeItems: function(contextMenu, target)
1221     {
1222         if (!(target instanceof WebInspector.UISourceCode))
1223             return;
1224
1225         var uiSourceCode = /** @type {WebInspector.UISourceCode} */ (target);
1226         contextMenu.appendItem(WebInspector.UIString("Local modifications..."), this._showLocalHistory.bind(this, uiSourceCode));
1227
1228         if (WebInspector.isolatedFileSystemManager.supportsFileSystems() && WebInspector.experimentsSettings.fileSystemProject.isEnabled())
1229             this._appendUISourceCodeMappingItems(contextMenu, uiSourceCode);
1230
1231         var resource = WebInspector.resourceForURL(uiSourceCode.url);
1232         if (resource && resource.request)
1233             contextMenu.appendApplicableItems(resource.request);
1234     },
1235
1236     /** 
1237      * @param {WebInspector.ContextMenu} contextMenu
1238      * @param {Object} target
1239      */
1240     _appendFunctionItems: function(contextMenu, target)
1241     {
1242         if (!(target instanceof WebInspector.RemoteObject))
1243             return;
1244         var remoteObject = /** @type {WebInspector.RemoteObject} */ (target);
1245         if (remoteObject.type !== "function")
1246             return;
1247
1248         function didGetDetails(error, response)
1249         {
1250             if (error) {
1251                 console.error(error);
1252                 return;
1253             }
1254             WebInspector.inspectorView.showPanelForAnchorNavigation(this);
1255             var uiLocation = WebInspector.debuggerModel.rawLocationToUILocation(response.location);
1256             this._showSourceLine(uiLocation.uiSourceCode, uiLocation.lineNumber);
1257         }
1258
1259         function revealFunction()
1260         {
1261             DebuggerAgent.getFunctionDetails(remoteObject.objectId, didGetDetails.bind(this));
1262         }
1263
1264         contextMenu.appendItem(WebInspector.UIString("Show function definition"), revealFunction.bind(this));
1265     },
1266
1267     showGoToSourceDialog: function()
1268     {
1269         WebInspector.OpenResourceDialog.show(this, this.editorView.mainElement);
1270     },
1271
1272     _dockSideChanged: function()
1273     {
1274         var dockSide = WebInspector.dockController.dockSide();
1275         var vertically = dockSide === WebInspector.DockController.State.DockedToRight && WebInspector.settings.splitVerticallyWhenDockedToRight.get();
1276         this._splitVertically(vertically);
1277     },
1278
1279     /**
1280      * @param {boolean} vertically
1281      */
1282     _splitVertically: function(vertically)
1283     {
1284         if (this.sidebarPaneView && vertically === !this.splitView.isVertical())
1285             return;
1286
1287         if (this.sidebarPaneView)
1288             this.sidebarPaneView.detach();
1289
1290         this.splitView.setVertical(!vertically);
1291
1292         if (!vertically) {
1293             this.sidebarPaneView = new WebInspector.SidebarPaneStack();
1294             for (var pane in this.sidebarPanes)
1295                 this.sidebarPaneView.addPane(this.sidebarPanes[pane]);
1296
1297             this.sidebarElement.appendChild(this.debugToolbar);
1298         } else {
1299             this._showDebuggerSidebar();
1300
1301             this.sidebarPaneView = new WebInspector.SplitView(true, this.name + "PanelSplitSidebarRatio", 0.5);
1302
1303             var group1 = new WebInspector.SidebarPaneStack();
1304             group1.show(this.sidebarPaneView.firstElement());
1305             group1.element.id = "scripts-sidebar-stack-pane";
1306             group1.addPane(this.sidebarPanes.watchExpressions);
1307             group1.addPane(this.sidebarPanes.callstack);
1308             group1.addPane(this.sidebarPanes.scopechain);
1309
1310             var group2 = new WebInspector.SidebarTabbedPane();
1311             group2.show(this.sidebarPaneView.secondElement());
1312             group2.addPane(this.sidebarPanes.jsBreakpoints);
1313             group2.addPane(this.sidebarPanes.domBreakpoints);
1314             group2.addPane(this.sidebarPanes.xhrBreakpoints);
1315             group2.addPane(this.sidebarPanes.eventListenerBreakpoints);
1316             group2.addPane(this.sidebarPanes.workerList);
1317
1318             this.sidebarPaneView.firstElement().appendChild(this.debugToolbar);
1319         }
1320
1321         this.sidebarPaneView.element.id = "scripts-debug-sidebar-contents";
1322         this.sidebarPaneView.show(this.splitView.sidebarElement);
1323
1324         this.sidebarPanes.scopechain.expand();
1325         this.sidebarPanes.jsBreakpoints.expand();
1326         this.sidebarPanes.callstack.expand();
1327
1328         if (WebInspector.settings.watchExpressions.get().length > 0)
1329             this.sidebarPanes.watchExpressions.expand();
1330     },
1331
1332     __proto__: WebInspector.Panel.prototype
1333 }