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