Web Inspector: move sources panel out of experimental.
[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  * @implements {WebInspector.TabbedEditorContainerDelegate}
30  * @implements {WebInspector.ContextMenu.Provider}
31  * @extends {WebInspector.Panel}
32  * @param {WebInspector.CompositeUISourceCodeProvider=} uiSourceCodeProviderForTest
33  */
34 WebInspector.ScriptsPanel = function(uiSourceCodeProviderForTest)
35 {
36     WebInspector.Panel.call(this, "scripts");
37     this.registerRequiredCSS("scriptsPanel.css");
38
39     WebInspector.settings.pauseOnExceptionStateString = WebInspector.settings.createSetting("pauseOnExceptionStateString", WebInspector.ScriptsPanel.PauseOnExceptionsState.DontPauseOnExceptions);
40     WebInspector.settings.navigatorWasOnceHidden = WebInspector.settings.createSetting("navigatorWasOnceHidden", false);
41     WebInspector.settings.debuggerSidebarHidden = WebInspector.settings.createSetting("debuggerSidebarHidden", false);
42
43     var scriptMapping = new WebInspector.DebuggerScriptMapping();
44     var providers = scriptMapping.uiSourceCodeProviders();
45     providers = providers.concat(new WebInspector.StylesUISourceCodeProvider());
46     this._uiSourceCodeProvider = uiSourceCodeProviderForTest || new WebInspector.CompositeUISourceCodeProvider(providers);
47
48     new WebInspector.PresentationConsoleMessageHelper(this._uiSourceCodeProvider);
49     new WebInspector.DebuggerResourceBinding(this._uiSourceCodeProvider);
50
51     function viewGetter()
52     {
53         return this.visibleView;
54     }
55     WebInspector.GoToLineDialog.install(this, viewGetter.bind(this));
56
57     var helpSection = WebInspector.shortcutsScreen.section(WebInspector.UIString("Sources Panel"));
58     this.debugToolbar = this._createDebugToolbar(helpSection);
59
60     const initialDebugSidebarWidth = 225;
61     const maximalDebugSidebarWidthPercent = 50;
62     this.createSplitView(this.element, WebInspector.SplitView.SidebarPosition.Right, initialDebugSidebarWidth);
63     this.splitView.element.id = "scripts-split-view";
64     this.splitView.minimalSidebarWidth = Preferences.minScriptsSidebarWidth;
65     this.splitView.minimalMainWidthPercent = 100 - maximalDebugSidebarWidthPercent;
66
67     this.sidebarElement.appendChild(this.debugToolbar);
68
69     this.debugSidebarResizeWidgetElement = document.createElement("div");
70     this.debugSidebarResizeWidgetElement.id = "scripts-debug-sidebar-resizer-widget";
71     this.splitView.installResizer(this.debugSidebarResizeWidgetElement);
72
73     // Create scripts navigator
74     const initialNavigatorWidth = 225;
75     const minimalViewsContainerWidthPercent = 50;
76     this.editorView = new WebInspector.SplitView(WebInspector.SplitView.SidebarPosition.Left, "scriptsPanelNavigatorSidebarWidth", initialNavigatorWidth);
77     this.editorView.element.tabIndex = 0;
78
79     this.editorView.minimalSidebarWidth = Preferences.minScriptsSidebarWidth;
80     this.editorView.minimalMainWidthPercent = minimalViewsContainerWidthPercent;
81     this.editorView.show(this.splitView.mainElement);
82
83     this._navigator = new WebInspector.ScriptsNavigator();
84     this._navigator.view.show(this.editorView.sidebarElement);
85
86     this._editorContainer = new WebInspector.TabbedEditorContainer(this, "previouslyViewedFiles");
87     this._editorContainer.show(this.editorView.mainElement);
88     WebInspector.OpenScriptDialog.install(this, this._uiSourceCodeProvider, this.editorView.mainElement);
89
90     this._navigatorController = new WebInspector.NavigatorOverlayController(this, this.editorView, this._navigator.view, this._editorContainer.view);
91
92     this._navigator.addEventListener(WebInspector.ScriptsNavigator.Events.ScriptSelected, this._scriptSelected, this);
93     this._navigator.addEventListener(WebInspector.ScriptsNavigator.Events.SnippetCreationRequested, this._snippetCreationRequested, this);
94     this._navigator.addEventListener(WebInspector.ScriptsNavigator.Events.FileRenamed, this._fileRenamed, this);
95
96     this._editorContainer.addEventListener(WebInspector.TabbedEditorContainer.Events.EditorSelected, this._editorSelected, this);
97     this._editorContainer.addEventListener(WebInspector.TabbedEditorContainer.Events.EditorClosed, this._editorClosed, this);
98
99     this.splitView.mainElement.appendChild(this.debugSidebarResizeWidgetElement);
100
101     this.sidebarPanes = {};
102     this.sidebarPanes.watchExpressions = new WebInspector.WatchExpressionsSidebarPane();
103     this.sidebarPanes.callstack = new WebInspector.CallStackSidebarPane();
104     this.sidebarPanes.scopechain = new WebInspector.ScopeChainSidebarPane();
105     this.sidebarPanes.jsBreakpoints = new WebInspector.JavaScriptBreakpointsSidebarPane(WebInspector.breakpointManager, this._showSourceLine.bind(this));
106     if (Capabilities.nativeInstrumentationEnabled) {
107         this.sidebarPanes.domBreakpoints = WebInspector.domBreakpointsSidebarPane;
108         this.sidebarPanes.xhrBreakpoints = new WebInspector.XHRBreakpointsSidebarPane();
109         this.sidebarPanes.eventListenerBreakpoints = new WebInspector.EventListenerBreakpointsSidebarPane();
110     }
111
112     if (Preferences.exposeWorkersInspection && !WebInspector.WorkerManager.isWorkerFrontend()) {
113         WorkerAgent.setWorkerInspectionEnabled(true);
114         this.sidebarPanes.workerList = new WebInspector.WorkerListSidebarPane(WebInspector.workerManager);
115     } else
116         this.sidebarPanes.workers = new WebInspector.WorkersSidebarPane();
117
118     this._debugSidebarContentsElement = document.createElement("div");
119     this._debugSidebarContentsElement.id = "scripts-debug-sidebar-contents";
120     this.sidebarElement.appendChild(this._debugSidebarContentsElement);
121
122     for (var pane in this.sidebarPanes)
123         this._debugSidebarContentsElement.appendChild(this.sidebarPanes[pane].element);
124
125     this.sidebarPanes.callstack.expanded = true;
126
127     this.sidebarPanes.scopechain.expanded = true;
128     this.sidebarPanes.jsBreakpoints.expanded = true;
129
130     this.sidebarPanes.callstack.registerShortcuts(helpSection, this.registerShortcut.bind(this));
131     var evaluateInConsoleShortcut = WebInspector.KeyboardShortcut.makeDescriptor("e", WebInspector.KeyboardShortcut.Modifiers.Shift | WebInspector.KeyboardShortcut.Modifiers.Ctrl);
132     helpSection.addKey(evaluateInConsoleShortcut.name, WebInspector.UIString("Evaluate selection in console"));
133     this.registerShortcut(evaluateInConsoleShortcut.key, this._evaluateSelectionInConsole.bind(this));
134
135     var openResourceShortcut = WebInspector.OpenResourceDialog.createShortcut();
136     helpSection.addKey(openResourceShortcut.name, WebInspector.UIString("Open file"));
137
138     var outlineShortcut = WebInspector.KeyboardShortcut.makeDescriptor("o", WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta | WebInspector.KeyboardShortcut.Modifiers.Shift);
139     helpSection.addKey(outlineShortcut.name, WebInspector.UIString("Go to member"));
140     this.registerShortcut(outlineShortcut.key, this._showOutlineDialog.bind(this));
141
142     var panelEnablerHeading = WebInspector.UIString("You need to enable debugging before you can use the Scripts panel.");
143     var panelEnablerDisclaimer = WebInspector.UIString("Enabling debugging will make scripts run slower.");
144     var panelEnablerButton = WebInspector.UIString("Enable Debugging");
145
146     this.panelEnablerView = new WebInspector.PanelEnablerView("scripts", panelEnablerHeading, panelEnablerDisclaimer, panelEnablerButton);
147     this.panelEnablerView.addEventListener("enable clicked", this.enableDebugging, this);
148
149     this.enableToggleButton = new WebInspector.StatusBarButton("", "enable-toggle-status-bar-item");
150     this.enableToggleButton.addEventListener("click", this.toggleDebugging, this);
151     if (!Capabilities.debuggerCausesRecompilation)
152         this.enableToggleButton.element.addStyleClass("hidden");
153
154     this._pauseOnExceptionButton = new WebInspector.StatusBarButton("", "scripts-pause-on-exceptions-status-bar-item", 3);
155     this._pauseOnExceptionButton.addEventListener("click", this._togglePauseOnExceptions, this);
156
157     this._toggleFormatSourceButton = new WebInspector.StatusBarButton(WebInspector.UIString("Pretty print"), "scripts-toggle-pretty-print-status-bar-item");
158     this._toggleFormatSourceButton.toggled = false;
159     this._toggleFormatSourceButton.addEventListener("click", this._toggleFormatSource, this);
160
161     this._scriptViewStatusBarItemsContainer = document.createElement("div");
162     this._scriptViewStatusBarItemsContainer.style.display = "inline-block";
163
164     this._debuggerEnabled = !Capabilities.debuggerCausesRecompilation;
165     this._installDebuggerSidebarController();
166
167     this._sourceFramesByUISourceCode = new Map();
168     this._reset(false);
169
170     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerWasEnabled, this._debuggerWasEnabled, this);
171     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerWasDisabled, this._debuggerWasDisabled, this);
172     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
173     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerResumed, this._debuggerResumed, this);
174     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.CallFrameSelected, this._callFrameSelected, this);
175     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.ConsoleCommandEvaluatedInSelectedCallFrame, this._consoleCommandEvaluatedInSelectedCallFrame, this);
176     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.ExecutionLineChanged, this._executionLineChanged, this);
177     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.GlobalObjectCleared, this._reset.bind(this, false));
178     WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointsActiveStateChanged, this._breakpointsActiveStateChanged, this);
179
180     this._uiSourceCodeProvider.addEventListener(WebInspector.UISourceCodeProvider.Events.UISourceCodeAdded, this._handleUISourceCodeAdded, this);
181     this._uiSourceCodeProvider.addEventListener(WebInspector.UISourceCodeProvider.Events.UISourceCodeReplaced, this._uiSourceCodeReplaced, this);
182     this._uiSourceCodeProvider.addEventListener(WebInspector.UISourceCodeProvider.Events.UISourceCodeRemoved, this._uiSourceCodeRemoved, this);
183
184     var enableDebugger = !Capabilities.debuggerCausesRecompilation || WebInspector.settings.debuggerEnabled.get();
185     if (enableDebugger)
186         WebInspector.debuggerModel.enableDebugger();
187
188     WebInspector.advancedSearchController.registerSearchScope(new WebInspector.ScriptsSearchScope(this._uiSourceCodeProvider));
189     WebInspector.ContextMenu.registerProvider(this);
190 }
191
192 // Keep these in sync with WebCore::ScriptDebugServer
193 WebInspector.ScriptsPanel.PauseOnExceptionsState = {
194     DontPauseOnExceptions : "none",
195     PauseOnAllExceptions : "all",
196     PauseOnUncaughtExceptions: "uncaught"
197 };
198
199 WebInspector.ScriptsPanel.prototype = {
200     get toolbarItemLabel()
201     {
202         return WebInspector.UIString("Sources");
203     },
204
205     get statusBarItems()
206     {
207         return [this.enableToggleButton.element, this._pauseOnExceptionButton.element, this._toggleFormatSourceButton.element, this._scriptViewStatusBarItemsContainer];
208     },
209
210     defaultFocusedElement: function()
211     {
212         return this._navigator.view.defaultFocusedElement();
213     },
214
215     get paused()
216     {
217         return this._paused;
218     },
219
220     wasShown: function()
221     {
222         WebInspector.Panel.prototype.wasShown.call(this);
223         if (Capabilities.nativeInstrumentationEnabled)
224             this._debugSidebarContentsElement.insertBefore(this.sidebarPanes.domBreakpoints.element, this.sidebarPanes.xhrBreakpoints.element);
225         this.sidebarPanes.watchExpressions.show();
226
227         this._navigatorController.wasShown();
228     },
229
230     willHide: function()
231     {
232         WebInspector.Panel.prototype.willHide.call(this);
233         WebInspector.closeViewInDrawer();
234     },
235
236     /**
237      * @param {WebInspector.Event} event
238      */
239     _handleUISourceCodeAdded: function(event)
240     {
241         var uiSourceCode = /** @type {WebInspector.UISourceCode} */ event.data;
242         if (this._toggleFormatSourceButton.toggled)
243             uiSourceCode.setFormatted(true);
244         this._uiSourceCodeAdded(uiSourceCode);
245     },
246
247     _loadUISourceCodes: function()
248     {
249         var uiSourceCodes = this._uiSourceCodeProvider.uiSourceCodes();
250         for (var i = 0; i < uiSourceCodes.length; ++i)
251             this._uiSourceCodeAdded(uiSourceCodes[i]);
252     },
253
254     /**
255      * @param {WebInspector.UISourceCode} uiSourceCode
256      */
257     _uiSourceCodeAdded: function(uiSourceCode)
258     {
259         if (!uiSourceCode.url || uiSourceCode.isSnippetEvaluation) {
260             // Anonymous sources and snippets evaluations are shown only when stepping.
261             return;
262         }
263
264         this._addUISourceCode(uiSourceCode);
265     },
266
267     /**
268      * @param {WebInspector.UISourceCode} uiSourceCode
269      */
270     _addUISourceCode: function(uiSourceCode)
271     {
272         this._navigator.addUISourceCode(uiSourceCode);
273         this._editorContainer.uiSourceCodeAdded(uiSourceCode);
274     },
275
276     _uiSourceCodeRemoved: function(event)
277     {
278         var uiSourceCode = /** @type {WebInspector.UISourceCode} */ event.data;
279         this._removeSourceFrame(uiSourceCode);
280     },
281
282     _consoleCommandEvaluatedInSelectedCallFrame: function(event)
283     {
284         this.sidebarPanes.scopechain.update(WebInspector.debuggerModel.selectedCallFrame());
285     },
286
287     _debuggerPaused: function(event)
288     {
289         var details = /** @type {WebInspector.DebuggerPausedDetails} */ event.data;
290
291         this._paused = true;
292         this._waitingToPause = false;
293         this._stepping = false;
294
295         this._updateDebuggerButtons();
296
297         WebInspector.inspectorView.setCurrentPanel(this);
298         this.sidebarPanes.callstack.update(details.callFrames);
299
300         if (details.reason === WebInspector.DebuggerModel.BreakReason.DOM) {
301             this.sidebarPanes.domBreakpoints.highlightBreakpoint(details.auxData);
302             function didCreateBreakpointHitStatusMessage(element)
303             {
304                 this.sidebarPanes.callstack.setStatus(element);
305             }
306             this.sidebarPanes.domBreakpoints.createBreakpointHitStatusMessage(details.auxData, didCreateBreakpointHitStatusMessage.bind(this));
307         } else if (details.reason === WebInspector.DebuggerModel.BreakReason.EventListener) {
308             var eventName = details.auxData.eventName;
309             this.sidebarPanes.eventListenerBreakpoints.highlightBreakpoint(details.auxData.eventName);
310             var eventNameForUI = WebInspector.EventListenerBreakpointsSidebarPane.eventNameForUI(eventName);
311             this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a \"%s\" Event Listener.", eventNameForUI));
312         } else if (details.reason === WebInspector.DebuggerModel.BreakReason.XHR) {
313             this.sidebarPanes.xhrBreakpoints.highlightBreakpoint(details.auxData["breakpointURL"]);
314             this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a XMLHttpRequest."));
315         } else if (details.reason === WebInspector.DebuggerModel.BreakReason.Exception) {
316             this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on exception: '%s'.", details.auxData.description));
317         } else {
318             function didGetUILocation(uiLocation)
319             {
320                 var breakpoint = WebInspector.breakpointManager.findBreakpoint(uiLocation.uiSourceCode, uiLocation.lineNumber);
321                 if (!breakpoint)
322                     return;
323                 this.sidebarPanes.jsBreakpoints.highlightBreakpoint(breakpoint);
324                 this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a JavaScript breakpoint."));
325             }
326             details.callFrames[0].createLiveLocation(didGetUILocation.bind(this));
327         }
328
329         this._showDebuggerSidebar();
330         this._toggleDebuggerSidebarButton.disabled = true;
331         window.focus();
332         InspectorFrontendHost.bringToFront();
333     },
334
335     _debuggerResumed: function()
336     {
337         this._paused = false;
338         this._waitingToPause = false;
339         this._stepping = false;
340
341         this._clearInterface();
342         this._toggleDebuggerSidebarButton.disabled = false;
343     },
344
345     _debuggerWasEnabled: function()
346     {
347         this._setPauseOnExceptions(WebInspector.settings.pauseOnExceptionStateString.get());
348
349         if (this._debuggerEnabled)
350             return;
351
352         this._debuggerEnabled = true;
353         this._reset(true);
354     },
355
356     _debuggerWasDisabled: function()
357     {
358         if (!this._debuggerEnabled)
359             return;
360
361         this._debuggerEnabled = false;
362         this._reset(true);
363     },
364
365     _reset: function(preserveItems)
366     {
367         delete this.currentQuery;
368         this.searchCanceled();
369
370         this._debuggerResumed();
371
372         delete this._currentUISourceCode;
373         this._navigator.reset();
374         this._editorContainer.reset();
375         this._updateScriptViewStatusBarItems();
376
377         this.sidebarPanes.jsBreakpoints.reset();
378         this.sidebarPanes.watchExpressions.reset();
379         if (!preserveItems && this.sidebarPanes.workers)
380             this.sidebarPanes.workers.reset();
381         this._loadUISourceCodes();
382     },
383
384     get visibleView()
385     {
386         return this._editorContainer.visibleView;
387     },
388
389     _updateScriptViewStatusBarItems: function()
390     {
391         this._scriptViewStatusBarItemsContainer.removeChildren();
392
393         var sourceFrame = this.visibleView;
394         if (sourceFrame) {
395             var statusBarItems = sourceFrame.statusBarItems || [];
396             for (var i = 0; i < statusBarItems.length; ++i)
397                 this._scriptViewStatusBarItemsContainer.appendChild(statusBarItems[i]);
398         }
399     },
400
401     canShowAnchorLocation: function(anchor)
402     {
403         if (this._debuggerEnabled && anchor.uiSourceCode)
404             return true;
405         var uiSourceCodes = this._uiSourceCodeProvider.uiSourceCodes();
406         for (var i = 0; i < uiSourceCodes.length; ++i) {
407             if (uiSourceCodes[i].url === anchor.href) {
408                 anchor.uiSourceCode = uiSourceCodes[i];
409                 return true;
410             }
411         }
412         return false;
413     },
414
415     showAnchorLocation: function(anchor)
416     {
417         this._showSourceLine(anchor.uiSourceCode, anchor.lineNumber);
418     },
419
420     showFunctionDefinition: function(functionLocation)
421     {
422         WebInspector.showPanelForAnchorNavigation(this);
423         var uiLocation = WebInspector.debuggerModel.rawLocationToUILocation(functionLocation);
424         this._showSourceLine(uiLocation.uiSourceCode, uiLocation.lineNumber);
425     },
426
427     showUISourceCode: function(uiSourceCode)
428     {
429         this._showSourceLine(uiSourceCode);
430     },
431
432     /**
433      * @param {WebInspector.UISourceCode} uiSourceCode
434      * @param {number=} lineNumber
435      */
436     _showSourceLine: function(uiSourceCode, lineNumber)
437     {
438         var sourceFrame = this._showFile(uiSourceCode);
439         if (typeof lineNumber === "number")
440             sourceFrame.highlightLine(lineNumber);
441         sourceFrame.focus();
442     },
443
444     /**
445      * @param {WebInspector.UISourceCode} uiSourceCode
446      * @return {WebInspector.SourceFrame}
447      */
448     _showFile: function(uiSourceCode)
449     {
450         var sourceFrame = this._getOrCreateSourceFrame(uiSourceCode);
451         if (this._currentUISourceCode === uiSourceCode)
452             return sourceFrame;
453         this._currentUISourceCode = uiSourceCode;
454
455         if (this._navigator.isScriptSourceAdded(uiSourceCode))
456             this._navigator.revealUISourceCode(uiSourceCode);
457         this._editorContainer.showFile(uiSourceCode);
458         this._updateScriptViewStatusBarItems();
459
460         return sourceFrame;
461     },
462
463     /**
464      * @param {WebInspector.UISourceCode} uiSourceCode
465      * @return {WebInspector.SourceFrame}
466      */
467     _createSourceFrame: function(uiSourceCode)
468     {
469         var sourceFrame;
470         if (uiSourceCode instanceof WebInspector.JavaScriptSource)
471             sourceFrame = new WebInspector.JavaScriptSourceFrame(this, uiSourceCode);
472         else if (uiSourceCode instanceof WebInspector.StyleSource)
473             sourceFrame = new WebInspector.StyleSourceFrame(uiSourceCode);
474         else {
475             console.assert(false, "Unknown UISourceCode type");
476             sourceFrame = new WebInspector.SourceFrame(uiSourceCode);
477         }
478          
479         this._sourceFramesByUISourceCode.put(uiSourceCode, sourceFrame);
480         return sourceFrame;
481     },
482
483     /**
484      * @param {WebInspector.UISourceCode} uiSourceCode
485      * @return {WebInspector.SourceFrame}
486      */
487     _getOrCreateSourceFrame: function(uiSourceCode)
488     {
489         return this._sourceFramesByUISourceCode.get(uiSourceCode) || this._createSourceFrame(uiSourceCode);
490     },
491
492     /**
493      * @param {WebInspector.UISourceCode} uiSourceCode
494      * @return {WebInspector.SourceFrame}
495      */
496     viewForFile: function(uiSourceCode)
497     {
498         return this._getOrCreateSourceFrame(uiSourceCode);
499     },
500
501     /**
502      * @param {WebInspector.UISourceCode} uiSourceCode
503      */
504     _removeSourceFrame: function(uiSourceCode)
505     {
506         var sourceFrame = this._sourceFramesByUISourceCode.get(uiSourceCode);
507         if (!sourceFrame)
508             return;
509         this._sourceFramesByUISourceCode.remove(uiSourceCode);
510         sourceFrame.detach();
511     },
512
513     /**
514      * @param {WebInspector.Event} event
515      */
516     _uiSourceCodeReplaced: function(event)
517     {
518         var oldUISourceCode = /** @type {WebInspector.UISourceCode} */ event.data.oldUISourceCode;
519         var uiSourceCode = /** @type {WebInspector.UISourceCode} */ event.data.uiSourceCode;
520
521         this._navigator.replaceUISourceCode(oldUISourceCode, uiSourceCode);
522         this._editorContainer.replaceFile(oldUISourceCode, uiSourceCode);
523         this._removeSourceFrame(oldUISourceCode);
524     },
525
526     _clearCurrentExecutionLine: function()
527     {
528         if (this._executionSourceFrame)
529             this._executionSourceFrame.clearExecutionLine();
530         delete this._executionSourceFrame;
531     },
532
533     _executionLineChanged: function(event)
534     {
535         var uiLocation = event.data;
536
537         this._clearCurrentExecutionLine();
538         if (!uiLocation)
539             return;
540         var sourceFrame = this._getOrCreateSourceFrame(uiLocation.uiSourceCode);
541         sourceFrame.setExecutionLine(uiLocation.lineNumber);
542         this._executionSourceFrame = sourceFrame;
543     },
544
545     _revealExecutionLine: function(uiLocation)
546     {
547         // Some scripts (anonymous and snippets evaluations) are not added to files select by default.
548         this._editorContainer.uiSourceCodeAdded(uiLocation.uiSourceCode);
549         var sourceFrame = this._showFile(uiLocation.uiSourceCode);
550         sourceFrame.revealLine(uiLocation.lineNumber);
551     },
552
553     _callFrameSelected: function(event)
554     {
555         var callFrame = event.data;
556
557         if (!callFrame)
558             return;
559
560         this.sidebarPanes.scopechain.update(callFrame);
561         this.sidebarPanes.watchExpressions.refreshExpressions();
562         this.sidebarPanes.callstack.setSelectedCallFrame(callFrame);
563         callFrame.createLiveLocation(this._revealExecutionLine.bind(this));
564     },
565
566     _editorClosed: function(event)
567     {
568         this._navigatorController.hideNavigatorOverlay();
569         var uiSourceCode = /** @type {WebInspector.UISourceCode} */ event.data;
570
571         if (this._currentUISourceCode === uiSourceCode)
572             delete this._currentUISourceCode;
573
574         // ScriptsNavigator does not need to update on EditorClosed.
575         this._updateScriptViewStatusBarItems();
576     },
577
578     _editorSelected: function(event)
579     {
580         var uiSourceCode = /** @type {WebInspector.UISourceCode} */ event.data;
581         WebInspector.RevisionHistoryView.uiSourceCodeSelected(uiSourceCode);
582         this._showFile(uiSourceCode);
583         this._navigatorController.hideNavigatorOverlay();
584     },
585
586     _scriptSelected: function(event)
587     {
588         var uiSourceCode = /** @type {WebInspector.UISourceCode} */ event.data.uiSourceCode;
589         var sourceFrame = this._showFile(uiSourceCode);
590         this._navigatorController.hideNavigatorOverlay();
591         if (sourceFrame && event.data.focusSource)
592             sourceFrame.focus();
593     },
594
595     _setPauseOnExceptions: function(pauseOnExceptionsState)
596     {
597         pauseOnExceptionsState = pauseOnExceptionsState || WebInspector.ScriptsPanel.PauseOnExceptionsState.DontPauseOnExceptions;
598         function callback(error)
599         {
600             if (error)
601                 return;
602             if (pauseOnExceptionsState == WebInspector.ScriptsPanel.PauseOnExceptionsState.DontPauseOnExceptions)
603                 this._pauseOnExceptionButton.title = WebInspector.UIString("Don't pause on exceptions.\nClick to Pause on all exceptions.");
604             else if (pauseOnExceptionsState == WebInspector.ScriptsPanel.PauseOnExceptionsState.PauseOnAllExceptions)
605                 this._pauseOnExceptionButton.title = WebInspector.UIString("Pause on all exceptions.\nClick to Pause on uncaught exceptions.");
606             else if (pauseOnExceptionsState == WebInspector.ScriptsPanel.PauseOnExceptionsState.PauseOnUncaughtExceptions)
607                 this._pauseOnExceptionButton.title = WebInspector.UIString("Pause on uncaught exceptions.\nClick to Not pause on exceptions.");
608
609             this._pauseOnExceptionButton.state = pauseOnExceptionsState;
610             WebInspector.settings.pauseOnExceptionStateString.set(pauseOnExceptionsState);
611         }
612         DebuggerAgent.setPauseOnExceptions(pauseOnExceptionsState, callback.bind(this));
613     },
614
615     _updateDebuggerButtons: function()
616     {
617         if (this._debuggerEnabled) {
618             this.enableToggleButton.title = WebInspector.UIString("Debugging enabled. Click to disable.");
619             this.enableToggleButton.toggled = true;
620             this._pauseOnExceptionButton.visible = true;
621             this.panelEnablerView.detach();
622         } else {
623             this.enableToggleButton.title = WebInspector.UIString("Debugging disabled. Click to enable.");
624             this.enableToggleButton.toggled = false;
625             this._pauseOnExceptionButton.visible = false;
626             this.panelEnablerView.show(this.element);
627         }
628
629         if (this._paused) {
630             this.pauseButton.addStyleClass("paused");
631
632             this.pauseButton.disabled = false;
633             this.stepOverButton.disabled = false;
634             this.stepIntoButton.disabled = false;
635             this.stepOutButton.disabled = false;
636
637             this.debuggerStatusElement.textContent = WebInspector.UIString("Paused");
638         } else {
639             this.pauseButton.removeStyleClass("paused");
640
641             this.pauseButton.disabled = this._waitingToPause;
642             this.stepOverButton.disabled = true;
643             this.stepIntoButton.disabled = true;
644             this.stepOutButton.disabled = true;
645
646             if (this._waitingToPause)
647                 this.debuggerStatusElement.textContent = WebInspector.UIString("Pausing");
648             else if (this._stepping)
649                 this.debuggerStatusElement.textContent = WebInspector.UIString("Stepping");
650             else
651                 this.debuggerStatusElement.textContent = "";
652         }
653     },
654
655     _clearInterface: function()
656     {
657         this.sidebarPanes.callstack.update(null);
658         this.sidebarPanes.scopechain.update(null);
659         this.sidebarPanes.jsBreakpoints.clearBreakpointHighlight();
660         if (Capabilities.nativeInstrumentationEnabled) {
661             this.sidebarPanes.domBreakpoints.clearBreakpointHighlight();
662             this.sidebarPanes.eventListenerBreakpoints.clearBreakpointHighlight();
663             this.sidebarPanes.xhrBreakpoints.clearBreakpointHighlight();
664         }
665
666         this._clearCurrentExecutionLine();
667         this._updateDebuggerButtons();
668     },
669
670     get debuggingEnabled()
671     {
672         return this._debuggerEnabled;
673     },
674
675     enableDebugging: function()
676     {
677         if (this._debuggerEnabled)
678             return;
679         this.toggleDebugging(this.panelEnablerView.alwaysEnabled);
680     },
681
682     disableDebugging: function()
683     {
684         if (!this._debuggerEnabled)
685             return;
686         this.toggleDebugging(this.panelEnablerView.alwaysEnabled);
687     },
688
689     toggleDebugging: function(optionalAlways)
690     {
691         this._paused = false;
692         this._waitingToPause = false;
693         this._stepping = false;
694
695         if (this._debuggerEnabled) {
696             WebInspector.settings.debuggerEnabled.set(false);
697             WebInspector.debuggerModel.disableDebugger();
698         } else {
699             WebInspector.settings.debuggerEnabled.set(!!optionalAlways);
700             WebInspector.debuggerModel.enableDebugger();
701         }
702     },
703
704     _togglePauseOnExceptions: function()
705     {
706         var nextStateMap = {};
707         var stateEnum = WebInspector.ScriptsPanel.PauseOnExceptionsState;
708         nextStateMap[stateEnum.DontPauseOnExceptions] = stateEnum.PauseOnAllExceptions;
709         nextStateMap[stateEnum.PauseOnAllExceptions] = stateEnum.PauseOnUncaughtExceptions;
710         nextStateMap[stateEnum.PauseOnUncaughtExceptions] = stateEnum.DontPauseOnExceptions;
711         this._setPauseOnExceptions(nextStateMap[this._pauseOnExceptionButton.state]);
712     },
713
714     _togglePause: function()
715     {
716         if (this._paused) {
717             this._paused = false;
718             this._waitingToPause = false;
719             DebuggerAgent.resume();
720         } else {
721             this._stepping = false;
722             this._waitingToPause = true;
723             DebuggerAgent.pause();
724         }
725
726         this._clearInterface();
727     },
728
729     _stepOverClicked: function()
730     {
731         if (!this._paused)
732             return;
733
734         this._paused = false;
735         this._stepping = true;
736
737         this._clearInterface();
738
739         DebuggerAgent.stepOver();
740     },
741
742     _stepIntoClicked: function()
743     {
744         if (!this._paused)
745             return;
746
747         this._paused = false;
748         this._stepping = true;
749
750         this._clearInterface();
751
752         DebuggerAgent.stepInto();
753     },
754
755     _stepOutClicked: function()
756     {
757         if (!this._paused)
758             return;
759
760         this._paused = false;
761         this._stepping = true;
762
763         this._clearInterface();
764
765         DebuggerAgent.stepOut();
766     },
767
768     _toggleBreakpointsClicked: function(event)
769     {
770         WebInspector.debuggerModel.setBreakpointsActive(!WebInspector.debuggerModel.breakpointsActive());
771     },
772
773     _breakpointsActiveStateChanged: function(event)
774     {
775         var active = event.data;
776         this._toggleBreakpointsButton.toggled = active;
777         if (active) {
778             this._toggleBreakpointsButton.title = WebInspector.UIString("Deactivate all breakpoints.");
779             WebInspector.inspectorView.element.removeStyleClass("breakpoints-deactivated");
780         } else {
781             this._toggleBreakpointsButton.title = WebInspector.UIString("Activate all breakpoints.");
782             WebInspector.inspectorView.element.addStyleClass("breakpoints-deactivated");
783         }
784     },
785
786     _evaluateSelectionInConsole: function()
787     {
788         var selection = window.getSelection();
789         if (selection.type === "Range" && !selection.isCollapsed)
790             WebInspector.evaluateInConsole(selection.toString());
791     },
792
793     _createDebugToolbar: function(section)
794     {
795         var debugToolbar = document.createElement("div");
796         debugToolbar.className = "status-bar";
797         debugToolbar.id = "scripts-debug-toolbar";
798
799         var title, handler, shortcuts;
800         var platformSpecificModifier = WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta;
801
802         // Continue.
803         title = WebInspector.UIString("Pause script execution (%s).");
804         handler = this._togglePause.bind(this);
805         shortcuts = [];
806         shortcuts.push(WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.F8));
807         shortcuts.push(WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.Slash, platformSpecificModifier));
808         this.pauseButton = this._createButtonAndRegisterShortcuts(section, "scripts-pause", title, handler, shortcuts, WebInspector.UIString("Pause/Continue"));
809         debugToolbar.appendChild(this.pauseButton);
810
811         // Step over.
812         title = WebInspector.UIString("Step over next function call (%s).");
813         handler = this._stepOverClicked.bind(this);
814         shortcuts = [];
815         shortcuts.push(WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.F10));
816         shortcuts.push(WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.SingleQuote, platformSpecificModifier));
817         this.stepOverButton = this._createButtonAndRegisterShortcuts(section, "scripts-step-over", title, handler, shortcuts, WebInspector.UIString("Step over"));
818         debugToolbar.appendChild(this.stepOverButton);
819
820         // Step into.
821         title = WebInspector.UIString("Step into next function call (%s).");
822         handler = this._stepIntoClicked.bind(this);
823         shortcuts = [];
824         shortcuts.push(WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.F11));
825         shortcuts.push(WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.Semicolon, platformSpecificModifier));
826         this.stepIntoButton = this._createButtonAndRegisterShortcuts(section, "scripts-step-into", title, handler, shortcuts, WebInspector.UIString("Step into"));
827         debugToolbar.appendChild(this.stepIntoButton);
828
829         // Step out.
830         title = WebInspector.UIString("Step out of current function (%s).");
831         handler = this._stepOutClicked.bind(this);
832         shortcuts = [];
833         shortcuts.push(WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.F11, WebInspector.KeyboardShortcut.Modifiers.Shift));
834         shortcuts.push(WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.Semicolon, WebInspector.KeyboardShortcut.Modifiers.Shift | platformSpecificModifier));
835         this.stepOutButton = this._createButtonAndRegisterShortcuts(section, "scripts-step-out", title, handler, shortcuts, WebInspector.UIString("Step out"));
836         debugToolbar.appendChild(this.stepOutButton);
837
838         this._toggleBreakpointsButton = new WebInspector.StatusBarButton(WebInspector.UIString("Deactivate all breakpoints."), "toggle-breakpoints");
839         this._toggleBreakpointsButton.toggled = true;
840         this._toggleBreakpointsButton.addEventListener("click", this._toggleBreakpointsClicked, this);
841         debugToolbar.appendChild(this._toggleBreakpointsButton.element);
842
843         this.debuggerStatusElement = document.createElement("div");
844         this.debuggerStatusElement.id = "scripts-debugger-status";
845         debugToolbar.appendChild(this.debuggerStatusElement);
846
847         return debugToolbar;
848     },
849
850     _createButtonAndRegisterShortcuts: function(section, buttonId, buttonTitle, handler, shortcuts, shortcutDescription)
851     {
852         var button = document.createElement("button");
853         button.className = "status-bar-item";
854         button.id = buttonId;
855         button.title = String.vsprintf(buttonTitle, [shortcuts[0].name]);
856         button.disabled = true;
857         button.appendChild(document.createElement("img"));
858         button.addEventListener("click", handler, false);
859
860         var shortcutNames = [];
861         for (var i = 0; i < shortcuts.length; ++i) {
862             this.registerShortcut(shortcuts[i].key, handler);
863             shortcutNames.push(shortcuts[i].name);
864         }
865         section.addAlternateKeys(shortcutNames, shortcutDescription);
866
867         return button;
868     },
869
870     searchCanceled: function()
871     {
872         if (this._searchView)
873             this._searchView.searchCanceled();
874
875         delete this._searchView;
876         delete this._searchQuery;
877     },
878
879     performSearch: function(query)
880     {
881         WebInspector.searchController.updateSearchMatchesCount(0, this);
882
883         if (!this.visibleView)
884             return;
885
886         // Call searchCanceled since it will reset everything we need before doing a new search.
887         this.searchCanceled();
888
889         this._searchView = this.visibleView;
890         this._searchQuery = query;
891
892         function finishedCallback(view, searchMatches)
893         {
894             if (!searchMatches)
895                 return;
896
897             WebInspector.searchController.updateSearchMatchesCount(searchMatches, this);
898             view.jumpToFirstSearchResult();
899             WebInspector.searchController.updateCurrentMatchIndex(view.currentSearchResultIndex, this);
900         }
901
902         this._searchView.performSearch(query, finishedCallback.bind(this));
903     },
904
905     jumpToNextSearchResult: function()
906     {
907         if (!this._searchView)
908             return;
909
910         if (this._searchView !== this.visibleView) {
911             this.performSearch(this._searchQuery);
912             return;
913         }
914
915         if (this._searchView.showingLastSearchResult())
916             this._searchView.jumpToFirstSearchResult();
917         else
918             this._searchView.jumpToNextSearchResult();
919         WebInspector.searchController.updateCurrentMatchIndex(this._searchView.currentSearchResultIndex, this);
920     },
921
922     jumpToPreviousSearchResult: function()
923     {
924         if (!this._searchView)
925             return;
926
927         if (this._searchView !== this.visibleView) {
928             this.performSearch(this._searchQuery);
929             if (this._searchView)
930                 this._searchView.jumpToLastSearchResult();
931             return;
932         }
933
934         if (this._searchView.showingFirstSearchResult())
935             this._searchView.jumpToLastSearchResult();
936         else
937             this._searchView.jumpToPreviousSearchResult();
938         WebInspector.searchController.updateCurrentMatchIndex(this._searchView.currentSearchResultIndex, this);
939     },
940
941     _toggleFormatSource: function()
942     {
943         this._toggleFormatSourceButton.toggled = !this._toggleFormatSourceButton.toggled;
944         var uiSourceCodes = this._uiSourceCodeProvider.uiSourceCodes();
945         for (var i = 0; i < uiSourceCodes.length; ++i)
946             uiSourceCodes[i].setFormatted(this._toggleFormatSourceButton.toggled);
947     },
948
949     addToWatch: function(expression)
950     {
951         this.sidebarPanes.watchExpressions.addExpression(expression);
952     },
953
954     _showOutlineDialog: function()
955     {
956          var uiSourceCode = this._editorContainer.currentFile();
957          if (!uiSourceCode)
958              return;
959
960          if (uiSourceCode instanceof WebInspector.JavaScriptSource)
961              WebInspector.JavaScriptOutlineDialog.show(this.visibleView, uiSourceCode);
962          else if (uiSourceCode instanceof WebInspector.StyleSource)
963              WebInspector.StyleSheetOutlineDialog.show(this.visibleView, /** @type {WebInspector.StyleSource} */ uiSourceCode);
964     },
965
966     _installDebuggerSidebarController: function()
967     {
968         this._toggleDebuggerSidebarButton = new WebInspector.StatusBarButton(WebInspector.UIString("Hide debugger"), "scripts-debugger-show-hide-button", 3);
969         this._toggleDebuggerSidebarButton.state = "shown";
970         this._toggleDebuggerSidebarButton.addEventListener("click", clickHandler, this);
971
972         function clickHandler()
973         {
974             if (this._toggleDebuggerSidebarButton.state === "shown")
975                 this._hideDebuggerSidebar();
976             else
977                 this._showDebuggerSidebar();
978         }
979         this.editorView.element.appendChild(this._toggleDebuggerSidebarButton.element);
980
981         if (WebInspector.settings.debuggerSidebarHidden.get())
982             this._hideDebuggerSidebar();
983
984     },
985
986     _showDebuggerSidebar: function()
987     {
988         if (this._toggleDebuggerSidebarButton.state === "shown")
989             return;
990         this._toggleDebuggerSidebarButton.state = "shown";
991         this._toggleDebuggerSidebarButton.title = WebInspector.UIString("Hide debugger");
992         this.splitView.showSidebarElement();
993         WebInspector.settings.debuggerSidebarHidden.set(false);
994     },
995
996     _hideDebuggerSidebar: function()
997     {
998         if (this._toggleDebuggerSidebarButton.state === "hidden")
999             return;
1000         this._toggleDebuggerSidebarButton.state = "hidden";
1001         this._toggleDebuggerSidebarButton.title = WebInspector.UIString("Show debugger");
1002         this.splitView.hideSidebarElement();
1003         WebInspector.settings.debuggerSidebarHidden.set(true);
1004     },
1005
1006     _fileRenamed: function(event)
1007     {
1008         var uiSourceCode = /** @type {WebInspector.UISourceCode} */ event.data.uiSourceCode;
1009         var name = /** @type {string} */ event.data.name;
1010         if (!uiSourceCode.isSnippet)
1011             return;
1012         var snippetJavaScriptSource = /** @type {WebInspector.SnippetJavaScriptSource} */ uiSourceCode;
1013         WebInspector.scriptSnippetModel.renameScriptSnippet(snippetJavaScriptSource, name);
1014     },
1015         
1016     _snippetCreationRequested: function()
1017     {
1018         var snippetJavaScriptSource = WebInspector.scriptSnippetModel.createScriptSnippet();
1019         this._showSourceLine(snippetJavaScriptSource);
1020         
1021         var shouldHideNavigator = !this._navigatorController.isNavigatorPinned();
1022         if (this._navigatorController.isNavigatorHidden())
1023             this._navigatorController.showNavigatorOverlay();
1024         this._navigator.rename(snippetJavaScriptSource, callback.bind(this));
1025     
1026         /**
1027          * @param {boolean} committed
1028          */
1029         function callback(committed)
1030         {
1031             if (shouldHideNavigator)
1032                 this._navigatorController.hideNavigatorOverlay();
1033
1034             if (!committed) {
1035                 WebInspector.scriptSnippetModel.deleteScriptSnippet(snippetJavaScriptSource);
1036                 return;
1037             }
1038
1039             this._showSourceLine(snippetJavaScriptSource);
1040         }
1041     },
1042
1043     /**
1044      * @param {WebInspector.UISourceCodeProvider} uiSourceCodeProvider
1045      */
1046     registerUISourceCodeProvider: function(uiSourceCodeProvider)
1047     {
1048         this._uiSourceCodeProvider._registerUISourceCodeProvider(uiSourceCodeProvider);
1049     },
1050
1051     /**
1052      * @param {WebInspector.UISourceCode} uiSourceCode
1053      */
1054     _showLocalHistory: function(uiSourceCode)
1055     {
1056         WebInspector.RevisionHistoryView.showHistory(uiSourceCode);
1057     },
1058
1059     /** 
1060      * @param {WebInspector.ContextMenu} contextMenu
1061      * @param {Object} target
1062      */
1063     appendApplicableItems: function(contextMenu, target)
1064     {
1065         if (target instanceof WebInspector.UISourceCode) {
1066             contextMenu.appendSeparator();
1067             contextMenu.appendItem(WebInspector.UIString("Revision history..."), this._showLocalHistory.bind(this, /** @type {WebInspector.UISourceCode} */ target));
1068             contextMenu.appendSeparator();
1069         }
1070     }
1071 }
1072
1073 WebInspector.ScriptsPanel.prototype.__proto__ = WebInspector.Panel.prototype;
1074
1075 /**
1076  * @constructor
1077  * @extends {WebInspector.Object}
1078  * @implements {WebInspector.UISourceCodeProvider}
1079  * @param {Array.<WebInspector.UISourceCodeProvider>} uiSourceCodeProviders
1080  */
1081 WebInspector.CompositeUISourceCodeProvider = function(uiSourceCodeProviders)
1082 {
1083     WebInspector.Object.call(this);
1084     this._uiSourceCodeProviders = [];
1085     for (var i = 0; i < uiSourceCodeProviders.length; ++i)
1086         this._registerUISourceCodeProvider(uiSourceCodeProviders[i]);
1087 }
1088
1089 WebInspector.CompositeUISourceCodeProvider.prototype = {
1090     /**
1091      * @param {WebInspector.UISourceCodeProvider} uiSourceCodeProvider
1092      */
1093     _registerUISourceCodeProvider: function(uiSourceCodeProvider)
1094     {
1095         this._uiSourceCodeProviders.push(uiSourceCodeProvider);
1096         uiSourceCodeProvider.addEventListener(WebInspector.UISourceCodeProvider.Events.UISourceCodeAdded, this._handleUISourceCodeAdded, this);
1097         uiSourceCodeProvider.addEventListener(WebInspector.UISourceCodeProvider.Events.UISourceCodeReplaced, this._handleUISourceCodeReplaced, this);
1098         uiSourceCodeProvider.addEventListener(WebInspector.UISourceCodeProvider.Events.UISourceCodeRemoved, this._handleUISourceCodeRemoved, this);
1099     },
1100
1101     _handleUISourceCodeAdded: function(event)
1102     {
1103         this.dispatchEventToListeners(WebInspector.UISourceCodeProvider.Events.UISourceCodeAdded, event.data);
1104     },
1105
1106     /**
1107      * @param {WebInspector.Event} event
1108      */
1109     _handleUISourceCodeReplaced: function(event)
1110     {
1111         this.dispatchEventToListeners(WebInspector.UISourceCodeProvider.Events.UISourceCodeReplaced, event.data);
1112     },
1113
1114     /**
1115      * @param {WebInspector.Event} event
1116      */
1117     _handleUISourceCodeRemoved: function(event)
1118     {
1119         this.dispatchEventToListeners(WebInspector.UISourceCodeProvider.Events.UISourceCodeRemoved, event.data);
1120     },
1121
1122     /**
1123      * @return {Array.<WebInspector.UISourceCode>}
1124      */
1125     uiSourceCodes: function()
1126     {
1127         var result = [];
1128         for (var i = 0; i < this._uiSourceCodeProviders.length; ++i) {
1129             var uiSourceCodes = this._uiSourceCodeProviders[i].uiSourceCodes();
1130             for (var j = 0; j < uiSourceCodes.length; ++j)
1131                 result.push(uiSourceCodes[j]);
1132         }
1133         return result;
1134     }
1135 }
1136
1137 WebInspector.CompositeUISourceCodeProvider.prototype.__proto__ = WebInspector.Object.prototype;