Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / devtools / front_end / sources / SourcesPanel.js
1 /*
2  * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3  * Copyright (C) 2011 Google Inc. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
17  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
18  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  */
26
27 /**
28  * @constructor
29  * @extends {WebInspector.Panel}
30  * @implements {WebInspector.ContextMenu.Provider}
31  * @implements {WebInspector.TargetManager.Observer}
32  * @param {!WebInspector.Workspace=} workspaceForTest
33  */
34 WebInspector.SourcesPanel = function(workspaceForTest)
35 {
36     WebInspector.Panel.call(this, "sources");
37     this.registerRequiredCSS("sourcesPanel.css");
38     new WebInspector.UpgradeFileSystemDropTarget(this.element);
39
40     this._workspace = workspaceForTest || WebInspector.workspace;
41
42     this.debugToolbar = this._createDebugToolbar();
43     this._debugToolbarDrawer = this._createDebugToolbarDrawer();
44
45     const initialDebugSidebarWidth = 225;
46     this._splitView = new WebInspector.SplitView(true, true, "sourcesPanelSplitViewState", initialDebugSidebarWidth);
47     this._splitView.enableShowModeSaving();
48     this._splitView.show(this.element);
49
50     // Create scripts navigator
51     const initialNavigatorWidth = 225;
52     this.editorView = new WebInspector.SplitView(true, false, "sourcesPanelNavigatorSplitViewState", initialNavigatorWidth);
53     this.editorView.enableShowModeSaving();
54     this.editorView.element.id = "scripts-editor-split-view";
55     this.editorView.element.tabIndex = 0;
56     this.editorView.show(this._splitView.mainElement());
57
58     this._navigator = new WebInspector.SourcesNavigator(this._workspace);
59     this._navigator.view.setMinimumSize(100, 25);
60     this._navigator.view.show(this.editorView.sidebarElement());
61     this._navigator.addEventListener(WebInspector.SourcesNavigator.Events.SourceSelected, this._sourceSelected, this);
62     this._navigator.addEventListener(WebInspector.SourcesNavigator.Events.SourceRenamed, this._sourceRenamed, this);
63
64     this._sourcesView = new WebInspector.SourcesView(this._workspace, this);
65     this._sourcesView.addEventListener(WebInspector.SourcesView.Events.EditorSelected, this._editorSelected.bind(this));
66     this._sourcesView.addEventListener(WebInspector.SourcesView.Events.EditorClosed, this._editorClosed.bind(this));
67     this._sourcesView.registerShortcuts(this.registerShortcuts.bind(this));
68     this._sourcesView.show(this.editorView.mainElement());
69
70     this._debugSidebarResizeWidgetElement = document.createElementWithClass("div", "resizer-widget");
71     this._debugSidebarResizeWidgetElement.id = "scripts-debug-sidebar-resizer-widget";
72     this._splitView.addEventListener(WebInspector.SplitView.Events.ShowModeChanged, this._updateDebugSidebarResizeWidget, this);
73     this._updateDebugSidebarResizeWidget();
74     this._splitView.installResizer(this._debugSidebarResizeWidgetElement);
75
76     this.sidebarPanes = {};
77     this.sidebarPanes.threads = new WebInspector.ThreadsSidebarPane();
78     this.sidebarPanes.watchExpressions = new WebInspector.WatchExpressionsSidebarPane();
79     this.sidebarPanes.callstack = new WebInspector.CallStackSidebarPane();
80     this.sidebarPanes.callstack.addEventListener(WebInspector.CallStackSidebarPane.Events.CallFrameSelected, this._callFrameSelectedInSidebar.bind(this));
81     this.sidebarPanes.callstack.registerShortcuts(this.registerShortcuts.bind(this));
82
83     this.sidebarPanes.scopechain = new WebInspector.ScopeChainSidebarPane();
84     this.sidebarPanes.jsBreakpoints = new WebInspector.JavaScriptBreakpointsSidebarPane(WebInspector.breakpointManager, this.showUISourceCode.bind(this));
85     this.sidebarPanes.domBreakpoints = WebInspector.domBreakpointsSidebarPane.createProxy(this);
86     this.sidebarPanes.xhrBreakpoints = new WebInspector.XHRBreakpointsSidebarPane();
87     this.sidebarPanes.eventListenerBreakpoints = new WebInspector.EventListenerBreakpointsSidebarPane();
88
89     this._extensionSidebarPanes = [];
90     this._installDebuggerSidebarController();
91
92     WebInspector.dockController.addEventListener(WebInspector.DockController.Events.DockSideChanged, this._dockSideChanged.bind(this));
93     WebInspector.settings.splitVerticallyWhenDockedToRight.addChangeListener(this._dockSideChanged.bind(this));
94     this._dockSideChanged();
95
96     this._updateDebuggerButtons();
97     this._pauseOnExceptionEnabledChanged();
98     WebInspector.settings.pauseOnExceptionEnabled.addChangeListener(this._pauseOnExceptionEnabledChanged, this);
99     this._setTarget(WebInspector.context.flavor(WebInspector.Target));
100     WebInspector.breakpointManager.addEventListener(WebInspector.BreakpointManager.Events.BreakpointsActiveStateChanged, this._breakpointsActiveStateChanged, this);
101     WebInspector.context.addFlavorChangeListener(WebInspector.Target, this._onCurrentTargetChanged, this);
102     WebInspector.targetManager.addModelListener(WebInspector.DebuggerModel, WebInspector.DebuggerModel.Events.DebuggerWasEnabled, this._debuggerWasEnabled, this);
103     WebInspector.targetManager.addModelListener(WebInspector.DebuggerModel, WebInspector.DebuggerModel.Events.DebuggerWasDisabled, this._debuggerReset, this);
104     WebInspector.targetManager.addModelListener(WebInspector.DebuggerModel, WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
105     WebInspector.targetManager.addModelListener(WebInspector.DebuggerModel, WebInspector.DebuggerModel.Events.DebuggerResumed, this._debuggerResumed, this);
106     WebInspector.targetManager.addModelListener(WebInspector.DebuggerModel, WebInspector.DebuggerModel.Events.CallFrameSelected, this._callFrameSelected, this);
107     WebInspector.targetManager.addModelListener(WebInspector.DebuggerModel, WebInspector.DebuggerModel.Events.ConsoleCommandEvaluatedInSelectedCallFrame, this._consoleCommandEvaluatedInSelectedCallFrame, this);
108     WebInspector.targetManager.addModelListener(WebInspector.DebuggerModel, WebInspector.DebuggerModel.Events.GlobalObjectCleared, this._debuggerReset, this);
109     WebInspector.targetManager.observeTargets(this);
110 }
111
112 WebInspector.SourcesPanel.minToolbarWidth = 215;
113
114 WebInspector.SourcesPanel.prototype = {
115     /**
116      * @param {?WebInspector.Target} target
117      */
118     _setTarget: function(target)
119     {
120         if (!target)
121             return;
122
123         if (target.debuggerModel.isPaused()) {
124             this._showDebuggerPausedDetails(/** @type {!WebInspector.DebuggerPausedDetails} */ (target.debuggerModel.debuggerPausedDetails()));
125             var callFrame = target.debuggerModel.selectedCallFrame();
126             if (callFrame)
127                 this._selectCallFrame(callFrame);
128         } else {
129             this._paused = false;
130             this._clearInterface();
131             this._toggleDebuggerSidebarButton.setEnabled(true);
132         }
133     },
134
135     /**
136      * @param {!WebInspector.Event} event
137      */
138     _onCurrentTargetChanged: function(event)
139     {
140         var target = /** @type {?WebInspector.Target} */ (event.data);
141         this._setTarget(target);
142     },
143
144     /**
145      * @return {!Element}
146      */
147     defaultFocusedElement: function()
148     {
149         return this._sourcesView.defaultFocusedElement();
150     },
151
152     /**
153      * @return {boolean}
154      */
155     paused: function()
156     {
157         return this._paused;
158     },
159
160     wasShown: function()
161     {
162         WebInspector.context.setFlavor(WebInspector.SourcesPanel, this);
163         WebInspector.Panel.prototype.wasShown.call(this);
164     },
165
166     willHide: function()
167     {
168         WebInspector.Panel.prototype.willHide.call(this);
169         WebInspector.context.setFlavor(WebInspector.SourcesPanel, null);
170     },
171
172     /**
173      * @return {!WebInspector.SearchableView}
174      */
175     searchableView: function()
176     {
177         return this._sourcesView.searchableView();
178     },
179
180     _consoleCommandEvaluatedInSelectedCallFrame: function(event)
181     {
182         var target = /** @type {!WebInspector.Target} */  (event.target.target());
183         if (WebInspector.context.flavor(WebInspector.Target) !== target)
184             return;
185         this.sidebarPanes.scopechain.update(target.debuggerModel.selectedCallFrame());
186     },
187
188     /**
189      * @param {!WebInspector.Event} event
190      */
191     _debuggerPaused: function(event)
192     {
193         var details = /** @type {!WebInspector.DebuggerPausedDetails} */ (event.data);
194         if (!this._paused)
195             WebInspector.inspectorView.setCurrentPanel(this);
196
197         if (WebInspector.context.flavor(WebInspector.Target) === details.target())
198             this._showDebuggerPausedDetails(details);
199         else if (!this._paused)
200             WebInspector.context.setFlavor(WebInspector.Target, details.target());
201     },
202
203     /**
204      * @param {!WebInspector.DebuggerPausedDetails} details
205      */
206     _showDebuggerPausedDetails: function(details)
207     {
208         this._paused = true;
209         this._updateDebuggerButtons();
210
211         this.sidebarPanes.callstack.update(details);
212
213         /**
214          * @param {!Element} element
215          * @this {WebInspector.SourcesPanel}
216          */
217         function didCreateBreakpointHitStatusMessage(element)
218         {
219             this.sidebarPanes.callstack.setStatus(element);
220         }
221
222         /**
223          * @param {!WebInspector.UILocation} uiLocation
224          * @this {WebInspector.SourcesPanel}
225          */
226         function didGetUILocation(uiLocation)
227         {
228             var breakpoint = WebInspector.breakpointManager.findBreakpointOnLine(uiLocation.uiSourceCode, uiLocation.lineNumber);
229             if (!breakpoint)
230                 return;
231             this.sidebarPanes.jsBreakpoints.highlightBreakpoint(breakpoint);
232             this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a JavaScript breakpoint."));
233         }
234
235         if (details.reason === WebInspector.DebuggerModel.BreakReason.DOM) {
236             WebInspector.domBreakpointsSidebarPane.highlightBreakpoint(details.auxData);
237             WebInspector.domBreakpointsSidebarPane.createBreakpointHitStatusMessage(details, didCreateBreakpointHitStatusMessage.bind(this));
238         } else if (details.reason === WebInspector.DebuggerModel.BreakReason.EventListener) {
239             var eventName = details.auxData["eventName"];
240             var targetName = details.auxData["targetName"];
241             this.sidebarPanes.eventListenerBreakpoints.highlightBreakpoint(eventName, targetName);
242             var eventNameForUI = WebInspector.EventListenerBreakpointsSidebarPane.eventNameForUI(eventName, details.auxData);
243             this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a \"%s\" Event Listener.", eventNameForUI));
244         } else if (details.reason === WebInspector.DebuggerModel.BreakReason.XHR) {
245             this.sidebarPanes.xhrBreakpoints.highlightBreakpoint(details.auxData["breakpointURL"]);
246             this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a XMLHttpRequest."));
247         } else if (details.reason === WebInspector.DebuggerModel.BreakReason.Exception)
248             this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on exception: '%s'.", details.auxData["description"]));
249         else if (details.reason === WebInspector.DebuggerModel.BreakReason.Assert)
250             this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on assertion."));
251         else if (details.reason === WebInspector.DebuggerModel.BreakReason.CSPViolation)
252             this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a script blocked due to Content Security Policy directive: \"%s\".", details.auxData["directiveText"]));
253         else if (details.reason === WebInspector.DebuggerModel.BreakReason.DebugCommand)
254             this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a debugged function"));
255         else {
256             if (details.callFrames.length)
257                 WebInspector.debuggerWorkspaceBinding.createCallFrameLiveLocation(details.callFrames[0], didGetUILocation.bind(this));
258             else
259                 console.warn("ScriptsPanel paused, but callFrames.length is zero."); // TODO remove this once we understand this case better
260         }
261
262         this._splitView.showBoth(true);
263         this._toggleDebuggerSidebarButton.setEnabled(false);
264         window.focus();
265         InspectorFrontendHost.bringToFront();
266     },
267
268     /**
269      * @param {!WebInspector.Event} event
270      */
271     _debuggerResumed: function(event)
272     {
273         var target = /** @type {!WebInspector.Target} */  (event.target.target());
274         if (WebInspector.context.flavor(WebInspector.Target) !== target)
275             return;
276         this._paused = false;
277         this._clearInterface();
278         this._toggleDebuggerSidebarButton.setEnabled(true);
279     },
280
281     /**
282      * @param {!WebInspector.Event} event
283      */
284     _debuggerWasEnabled: function(event)
285     {
286         var target = /** @type {!WebInspector.Target} */  (event.target.target());
287         if (WebInspector.context.flavor(WebInspector.Target) !== target)
288             return;
289
290         this._updateDebuggerButtons();
291     },
292
293     /**
294      * @param {!WebInspector.Event} event
295      */
296     _debuggerReset: function(event)
297     {
298         this._debuggerResumed(event);
299     },
300
301     /**
302      * @return {!WebInspector.View}
303      */
304     get visibleView()
305     {
306         return this._sourcesView.visibleView();
307     },
308
309     /**
310      * @param {!WebInspector.UISourceCode} uiSourceCode
311      * @param {number=} lineNumber
312      * @param {number=} columnNumber
313      * @param {boolean=} forceShowInPanel
314      */
315     showUISourceCode: function(uiSourceCode, lineNumber, columnNumber, forceShowInPanel)
316     {
317         this._showEditor(forceShowInPanel);
318         this._sourcesView.showSourceLocation(uiSourceCode, lineNumber, columnNumber);
319     },
320
321     _showEditor: function(forceShowInPanel)
322     {
323         WebInspector.inspectorView.showPanel("sources");
324     },
325
326     /**
327      * @param {!WebInspector.UILocation} uiLocation
328      * @param {boolean=} forceShowInPanel
329      */
330     showUILocation: function(uiLocation, forceShowInPanel)
331     {
332         this.showUISourceCode(uiLocation.uiSourceCode, uiLocation.lineNumber, uiLocation.columnNumber, forceShowInPanel);
333     },
334
335     /**
336      * @param {!WebInspector.UISourceCode} uiSourceCode
337      */
338     _revealInNavigator: function(uiSourceCode)
339     {
340         this._navigator.revealUISourceCode(uiSourceCode);
341     },
342
343     /**
344      * @param {boolean} ignoreExecutionLineEvents
345      */
346     setIgnoreExecutionLineEvents: function(ignoreExecutionLineEvents)
347     {
348         this._ignoreExecutionLineEvents = ignoreExecutionLineEvents;
349     },
350
351     _executionLineChanged: function(uiLocation)
352     {
353         this._sourcesView.clearCurrentExecutionLine();
354         this._sourcesView.setExecutionLine(uiLocation);
355         if (this._ignoreExecutionLineEvents)
356             return;
357         this._sourcesView.showSourceLocation(uiLocation.uiSourceCode, uiLocation.lineNumber, 0, undefined, true);
358     },
359
360     /**
361      * @param {!WebInspector.Event} event
362      */
363     _callFrameSelected: function(event)
364     {
365         var callFrame = /** @type {?WebInspector.DebuggerModel.CallFrame} */ (event.data);
366
367         if (!callFrame || callFrame.target() !== WebInspector.context.flavor(WebInspector.Target))
368             return;
369
370         this._selectCallFrame(callFrame);
371     },
372
373     /**
374      * @param {!WebInspector.DebuggerModel.CallFrame}  callFrame
375      */
376     _selectCallFrame: function(callFrame)
377     {
378         this.sidebarPanes.scopechain.update(callFrame);
379         this.sidebarPanes.watchExpressions.refreshExpressions();
380         this.sidebarPanes.callstack.setSelectedCallFrame(callFrame);
381         WebInspector.debuggerWorkspaceBinding.createCallFrameLiveLocation(callFrame, this._executionLineChanged.bind(this));
382     },
383
384     /**
385      * @param {!WebInspector.Event} event
386      */
387     _sourceSelected: function(event)
388     {
389         var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data.uiSourceCode);
390         this._sourcesView.showSourceLocation(uiSourceCode, undefined, undefined, !event.data.focusSource)
391     },
392
393     /**
394      * @param {!WebInspector.Event} event
395      */
396     _sourceRenamed: function(event)
397     {
398         var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data);
399         this._sourcesView.sourceRenamed(uiSourceCode);
400     },
401
402     _pauseOnExceptionEnabledChanged: function()
403     {
404         var enabled = WebInspector.settings.pauseOnExceptionEnabled.get();
405         this._pauseOnExceptionButton.toggled = enabled;
406         this._pauseOnExceptionButton.title = WebInspector.UIString(enabled ? "Don't pause on exceptions." : "Pause on exceptions.");
407         this._debugToolbarDrawer.classList.toggle("expanded", enabled);
408     },
409
410     _updateDebuggerButtons: function()
411     {
412         var currentTarget = WebInspector.context.flavor(WebInspector.Target);
413         if (!currentTarget)
414             return;
415
416         if (this._paused) {
417             this._updateButtonTitle(this._pauseButton, WebInspector.UIString("Resume script execution (%s)."))
418             this._pauseButton.state = true;
419             this._pauseButton.setLongClickOptionsEnabled((function() { return [ this._longResumeButton ] }).bind(this));
420
421             this._pauseButton.setEnabled(true);
422             this._stepOverButton.setEnabled(true);
423             this._stepIntoButton.setEnabled(true);
424             this._stepOutButton.setEnabled(true);
425         } else {
426             this._updateButtonTitle(this._pauseButton, WebInspector.UIString("Pause script execution (%s)."))
427             this._pauseButton.state = false;
428             this._pauseButton.setLongClickOptionsEnabled(null);
429
430             this._pauseButton.setEnabled(!currentTarget.debuggerModel.isPausing());
431             this._stepOverButton.setEnabled(false);
432             this._stepIntoButton.setEnabled(false);
433             this._stepOutButton.setEnabled(false);
434         }
435     },
436
437     _clearInterface: function()
438     {
439         this.sidebarPanes.callstack.update(null);
440         this.sidebarPanes.scopechain.update(null);
441         this.sidebarPanes.jsBreakpoints.clearBreakpointHighlight();
442         WebInspector.domBreakpointsSidebarPane.clearBreakpointHighlight();
443         this.sidebarPanes.eventListenerBreakpoints.clearBreakpointHighlight();
444         this.sidebarPanes.xhrBreakpoints.clearBreakpointHighlight();
445
446         this._sourcesView.clearCurrentExecutionLine();
447         this._updateDebuggerButtons();
448     },
449
450     _togglePauseOnExceptions: function()
451     {
452         WebInspector.settings.pauseOnExceptionEnabled.set(!this._pauseOnExceptionButton.toggled);
453     },
454
455     /**
456      * @return {boolean}
457      */
458     _runSnippet: function()
459     {
460         var uiSourceCode = this._sourcesView.currentUISourceCode();
461         if (uiSourceCode.project().type() !== WebInspector.projectTypes.Snippets)
462             return false;
463
464         var currentExecutionContext = WebInspector.context.flavor(WebInspector.ExecutionContext);
465         if (!currentExecutionContext)
466             return false;
467
468         WebInspector.scriptSnippetModel.evaluateScriptSnippet(currentExecutionContext, uiSourceCode);
469         return true;
470     },
471
472     /**
473      * @param {!WebInspector.Event} event
474      */
475     _editorSelected: function(event)
476     {
477         var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data);
478         this._editorChanged(uiSourceCode);
479    },
480
481     /**
482      * @param {!WebInspector.Event} event
483      */
484     _editorClosed: function(event)
485     {
486         var wasSelected = /** @type {boolean} */ (event.data.wasSelected);
487         if (wasSelected)
488             this._editorChanged(null);
489     },
490
491     /**
492      * @param {?WebInspector.UISourceCode} uiSourceCode
493      */
494     _editorChanged: function(uiSourceCode)
495     {
496         var isSnippet = uiSourceCode && uiSourceCode.project().type() === WebInspector.projectTypes.Snippets;
497         this._runSnippetButton.element.classList.toggle("hidden", !isSnippet);
498     },
499
500     /**
501      * @return {boolean}
502      */
503     togglePause: function()
504     {
505         var target = WebInspector.context.flavor(WebInspector.Target);
506         if (!target)
507             return true;
508
509         if (this._paused) {
510             this._paused = false;
511             target.debuggerModel.resume();
512         } else {
513             // Make sure pauses didn't stick skipped.
514             target.debuggerModel.pause();
515         }
516
517         this._clearInterface();
518         return true;
519     },
520
521     /**
522      * @return {?WebInspector.DebuggerModel}
523      */
524     _prepareToResume: function()
525     {
526         if (!this._paused)
527             return null;
528
529         this._paused = false;
530
531         this._clearInterface();
532         var target = WebInspector.context.flavor(WebInspector.Target);
533         return target ? target.debuggerModel : null;
534     },
535
536     /**
537      * @return {boolean}
538      */
539     _longResume: function()
540     {
541         var debuggerModel = this._prepareToResume();
542         if (!debuggerModel)
543             return true;
544
545         debuggerModel.skipAllPausesUntilReloadOrTimeout(500);
546         debuggerModel.resume();
547         return true;
548     },
549
550     /**
551      * @return {boolean}
552      */
553     _stepOverClicked: function()
554     {
555         var debuggerModel = this._prepareToResume();
556         if (!debuggerModel)
557             return true;
558
559         debuggerModel.stepOver();
560         return true;
561     },
562
563     /**
564      * @return {boolean}
565      */
566     _stepIntoClicked: function()
567     {
568         var debuggerModel = this._prepareToResume();
569         if (!debuggerModel)
570             return true;
571
572         debuggerModel.stepInto();
573         return true;
574     },
575
576     /**
577      * @return {boolean}
578      */
579     _stepOutClicked: function()
580     {
581         var debuggerModel = this._prepareToResume();
582         if (!debuggerModel)
583             return true;
584
585         debuggerModel.stepOut();
586         return true;
587     },
588
589     /**
590      * @param {!WebInspector.Event} event
591      */
592     _callFrameSelectedInSidebar: function(event)
593     {
594         var callFrame = /** @type {!WebInspector.DebuggerModel.CallFrame} */ (event.data);
595         callFrame.target().debuggerModel.setSelectedCallFrame(callFrame);
596     },
597
598     /**
599      * @param {!WebInspector.DebuggerModel.Location} rawLocation
600      */
601     continueToLocation: function(rawLocation)
602     {
603         if (!this._prepareToResume())
604             return;
605
606         rawLocation.continueToLocation();
607     },
608
609     _toggleBreakpointsClicked: function(event)
610     {
611         WebInspector.breakpointManager.setBreakpointsActive(!WebInspector.breakpointManager.breakpointsActive());
612     },
613
614     _breakpointsActiveStateChanged: function(event)
615     {
616         var active = event.data;
617         this._toggleBreakpointsButton.toggled = !active;
618         this.sidebarPanes.jsBreakpoints.listElement.classList.toggle("breakpoints-list-deactivated", !active);
619         this._sourcesView.toggleBreakpointsActiveState(active);
620         if (active)
621             this._toggleBreakpointsButton.title = WebInspector.UIString("Deactivate breakpoints.");
622         else
623             this._toggleBreakpointsButton.title = WebInspector.UIString("Activate breakpoints.");
624     },
625
626     _createDebugToolbar: function()
627     {
628         var debugToolbar = document.createElementWithClass("div", "scripts-debug-toolbar");
629
630         var title, handler;
631         var platformSpecificModifier = WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta;
632
633         // Run snippet.
634         title = WebInspector.UIString("Run snippet (%s).");
635         handler = this._runSnippet.bind(this);
636         this._runSnippetButton = this._createButtonAndRegisterShortcuts("scripts-run-snippet", title, handler, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.RunSnippet);
637         debugToolbar.appendChild(this._runSnippetButton.element);
638         this._runSnippetButton.element.classList.add("hidden");
639
640         // Continue.
641         this._pauseButton = this._createButtonAndRegisterShortcutsForAction("scripts-pause", "", "debugger.toggle-pause");
642         debugToolbar.appendChild(this._pauseButton.element);
643
644         // Long resume.
645         title = WebInspector.UIString("Resume with all pauses blocked for 500 ms");
646         this._longResumeButton = new WebInspector.StatusBarButton(title, "scripts-long-resume");
647         this._longResumeButton.addEventListener("click", this._longResume.bind(this), this);
648
649         // Step over.
650         title = WebInspector.UIString("Step over next function call (%s).");
651         handler = this._stepOverClicked.bind(this);
652         this._stepOverButton = this._createButtonAndRegisterShortcuts("scripts-step-over", title, handler, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.StepOver);
653         debugToolbar.appendChild(this._stepOverButton.element);
654
655         // Step into.
656         title = WebInspector.UIString("Step into next function call (%s).");
657         handler = this._stepIntoClicked.bind(this);
658         this._stepIntoButton = this._createButtonAndRegisterShortcuts("scripts-step-into", title, handler, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.StepInto);
659         debugToolbar.appendChild(this._stepIntoButton.element);
660
661         // Step out.
662         title = WebInspector.UIString("Step out of current function (%s).");
663         handler = this._stepOutClicked.bind(this);
664         this._stepOutButton = this._createButtonAndRegisterShortcuts("scripts-step-out", title, handler, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.StepOut);
665         debugToolbar.appendChild(this._stepOutButton.element);
666
667         // Toggle Breakpoints
668         this._toggleBreakpointsButton = new WebInspector.StatusBarButton(WebInspector.UIString("Deactivate breakpoints."), "scripts-toggle-breakpoints");
669         this._toggleBreakpointsButton.toggled = false;
670         this._toggleBreakpointsButton.addEventListener("click", this._toggleBreakpointsClicked, this);
671         debugToolbar.appendChild(this._toggleBreakpointsButton.element);
672
673         // Pause on Exception
674         this._pauseOnExceptionButton = new WebInspector.StatusBarButton("", "scripts-pause-on-exceptions-status-bar-item");
675         this._pauseOnExceptionButton.addEventListener("click", this._togglePauseOnExceptions, this);
676         debugToolbar.appendChild(this._pauseOnExceptionButton.element);
677
678         return debugToolbar;
679     },
680
681     _createDebugToolbarDrawer: function()
682     {
683         var debugToolbarDrawer = document.createElementWithClass("div", "scripts-debug-toolbar-drawer");
684
685         var label = WebInspector.UIString("Pause On Caught Exceptions");
686         var setting = WebInspector.settings.pauseOnCaughtException;
687         debugToolbarDrawer.appendChild(WebInspector.SettingsUI.createSettingCheckbox(label, setting, true));
688
689         return debugToolbarDrawer;
690     },
691
692     /**
693      * @param {!WebInspector.StatusBarButton} button
694      * @param {string} buttonTitle
695      */
696     _updateButtonTitle: function(button, buttonTitle)
697     {
698         var hasShortcuts = button.shortcuts && button.shortcuts.length;
699         if (hasShortcuts)
700             button.title = String.vsprintf(buttonTitle, [button.shortcuts[0].name]);
701         else
702             button.title = buttonTitle;
703     },
704
705     /**
706      * @param {string} buttonId
707      * @param {string} buttonTitle
708      * @param {function(!Event=):boolean} handler
709      * @param {!Array.<!WebInspector.KeyboardShortcut.Descriptor>} shortcuts
710      * @return {!WebInspector.StatusBarButton}
711      */
712     _createButtonAndRegisterShortcuts: function(buttonId, buttonTitle, handler, shortcuts)
713     {
714         var button = new WebInspector.StatusBarButton(buttonTitle, buttonId);
715         button.element.addEventListener("click", handler, false);
716         button.shortcuts = shortcuts;
717         this._updateButtonTitle(button, buttonTitle);
718         this.registerShortcuts(shortcuts, handler);
719         return button;
720     },
721
722     /**
723      * @param {string} buttonId
724      * @param {string} buttonTitle
725      * @param {string} actionId
726      * @return {!WebInspector.StatusBarButton}
727      */
728     _createButtonAndRegisterShortcutsForAction: function(buttonId, buttonTitle, actionId)
729     {
730         /**
731          * @return {boolean}
732          */
733         function handler()
734         {
735             return WebInspector.actionRegistry.execute(actionId);
736         }
737         var shortcuts = WebInspector.shortcutRegistry.shortcutDescriptorsForAction(actionId);
738         return this._createButtonAndRegisterShortcuts(buttonId, buttonTitle, handler, shortcuts);
739     },
740
741     addToWatch: function(expression)
742     {
743         this.sidebarPanes.watchExpressions.addExpression(expression);
744     },
745
746     _installDebuggerSidebarController: function()
747     {
748         this._toggleNavigatorSidebarButton = this.editorView.createShowHideSidebarButton("navigator", "scripts-navigator-show-hide-button");
749         this.editorView.mainElement().appendChild(this._toggleNavigatorSidebarButton.element);
750
751         this._toggleDebuggerSidebarButton = this._splitView.createShowHideSidebarButton("debugger", "scripts-debugger-show-hide-button");
752
753         this._splitView.mainElement().appendChild(this._toggleDebuggerSidebarButton.element);
754         this._splitView.mainElement().appendChild(this._debugSidebarResizeWidgetElement);
755     },
756
757     _updateDebugSidebarResizeWidget: function()
758     {
759         this._debugSidebarResizeWidgetElement.classList.toggle("hidden", this._splitView.showMode() !== WebInspector.SplitView.ShowMode.Both);
760     },
761
762     /**
763      * @param {!WebInspector.UISourceCode} uiSourceCode
764      */
765     _showLocalHistory: function(uiSourceCode)
766     {
767         WebInspector.RevisionHistoryView.showHistory(uiSourceCode);
768     },
769
770     /**
771      * @param {!Event} event
772      * @param {!WebInspector.ContextMenu} contextMenu
773      * @param {!Object} target
774      */
775     appendApplicableItems: function(event, contextMenu, target)
776     {
777         this._appendUISourceCodeItems(event, contextMenu, target);
778         this._appendRemoteObjectItems(contextMenu, target);
779     },
780
781     _suggestReload: function()
782     {
783         if (window.confirm(WebInspector.UIString("It is recommended to restart inspector after making these changes. Would you like to restart it?")))
784             WebInspector.reload();
785     },
786
787     /**
788      * @param {!WebInspector.UISourceCode} uiSourceCode
789      */
790     _mapFileSystemToNetwork: function(uiSourceCode)
791     {
792         WebInspector.SelectUISourceCodeForProjectTypesDialog.show(uiSourceCode.name(), [WebInspector.projectTypes.Network, WebInspector.projectTypes.ContentScripts], mapFileSystemToNetwork.bind(this), this.editorView.mainElement())
793
794         /**
795          * @param {!WebInspector.UISourceCode} networkUISourceCode
796          * @this {WebInspector.SourcesPanel}
797          */
798         function mapFileSystemToNetwork(networkUISourceCode)
799         {
800             this._workspace.addMapping(networkUISourceCode, uiSourceCode, WebInspector.fileSystemWorkspaceBinding);
801             this._suggestReload();
802         }
803     },
804
805     /**
806      * @param {!WebInspector.UISourceCode} uiSourceCode
807      */
808     _removeNetworkMapping: function(uiSourceCode)
809     {
810         if (confirm(WebInspector.UIString("Are you sure you want to remove network mapping?"))) {
811             this._workspace.removeMapping(uiSourceCode);
812             this._suggestReload();
813         }
814     },
815
816     /**
817      * @param {!WebInspector.UISourceCode} networkUISourceCode
818      */
819     _mapNetworkToFileSystem: function(networkUISourceCode)
820     {
821         WebInspector.SelectUISourceCodeForProjectTypesDialog.show(networkUISourceCode.name(), [WebInspector.projectTypes.FileSystem], mapNetworkToFileSystem.bind(this), this.editorView.mainElement())
822
823         /**
824          * @param {!WebInspector.UISourceCode} uiSourceCode
825          * @this {WebInspector.SourcesPanel}
826          */
827         function mapNetworkToFileSystem(uiSourceCode)
828         {
829             this._workspace.addMapping(networkUISourceCode, uiSourceCode, WebInspector.fileSystemWorkspaceBinding);
830             this._suggestReload();
831         }
832     },
833
834     /**
835      * @param {!WebInspector.ContextMenu} contextMenu
836      * @param {!WebInspector.UISourceCode} uiSourceCode
837      */
838     _appendUISourceCodeMappingItems: function(contextMenu, uiSourceCode)
839     {
840         if (uiSourceCode.project().type() === WebInspector.projectTypes.FileSystem) {
841             var hasMappings = !!uiSourceCode.url;
842             if (!hasMappings)
843                 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Map to network resource\u2026" : "Map to Network Resource\u2026"), this._mapFileSystemToNetwork.bind(this, uiSourceCode));
844             else
845                 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove network mapping" : "Remove Network Mapping"), this._removeNetworkMapping.bind(this, uiSourceCode));
846         }
847
848         /**
849          * @param {!WebInspector.Project} project
850          */
851         function filterProject(project)
852         {
853             return project.type() === WebInspector.projectTypes.FileSystem;
854         }
855
856         if (uiSourceCode.project().type() === WebInspector.projectTypes.Network || uiSourceCode.project().type() === WebInspector.projectTypes.ContentScripts) {
857             if (!this._workspace.projects().filter(filterProject).length)
858                 return;
859             if (this._workspace.uiSourceCodeForURL(uiSourceCode.url) === uiSourceCode)
860                 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Map to file system resource\u2026" : "Map to File System Resource\u2026"), this._mapNetworkToFileSystem.bind(this, uiSourceCode));
861         }
862     },
863
864     /**
865      * @param {!Event} event
866      * @param {!WebInspector.ContextMenu} contextMenu
867      * @param {!Object} target
868      */
869     _appendUISourceCodeItems: function(event, contextMenu, target)
870     {
871         if (!(target instanceof WebInspector.UISourceCode))
872             return;
873
874         var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (target);
875         var project = uiSourceCode.project();
876         if (project.type() !== WebInspector.projectTypes.FileSystem)
877             contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Local modifications\u2026" : "Local Modifications\u2026"), this._showLocalHistory.bind(this, uiSourceCode));
878         this._appendUISourceCodeMappingItems(contextMenu, uiSourceCode);
879
880         if (uiSourceCode.contentType() === WebInspector.resourceTypes.Script && project.type() !== WebInspector.projectTypes.Snippets)
881             this.sidebarPanes.callstack.appendBlackboxURLContextMenuItems(contextMenu, uiSourceCode.url);
882
883         if (!event.target.isSelfOrDescendant(this.editorView.sidebarElement())) {
884             contextMenu.appendSeparator();
885             contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Reveal in navigator" : "Reveal in Navigator"), this._handleContextMenuReveal.bind(this, uiSourceCode));
886         }
887     },
888
889     /**
890      * @param {!WebInspector.UISourceCode} uiSourceCode
891      */
892     _handleContextMenuReveal: function(uiSourceCode)
893     {
894         this.editorView.showBoth();
895         this._revealInNavigator(uiSourceCode);
896     },
897
898     /**
899      * @param {!WebInspector.ContextMenu} contextMenu
900      * @param {!Object} target
901      */
902     _appendRemoteObjectItems: function(contextMenu, target)
903     {
904         if (!(target instanceof WebInspector.RemoteObject))
905             return;
906         var remoteObject = /** @type {!WebInspector.RemoteObject} */ (target);
907         contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Store as global variable" : "Store as Global Variable"), this._saveToTempVariable.bind(this, remoteObject));
908         if (remoteObject.type === "function")
909             contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Show function definition" : "Show Function Definition"), this._showFunctionDefinition.bind(this, remoteObject));
910     },
911
912     /**
913      * @param {!WebInspector.RemoteObject} remoteObject
914      */
915     _saveToTempVariable: function(remoteObject)
916     {
917         var currentExecutionContext = WebInspector.context.flavor(WebInspector.ExecutionContext);
918         if (!currentExecutionContext)
919             return;
920
921         currentExecutionContext.evaluate("window", "", false, true, false, false, didGetGlobalObject.bind(null, currentExecutionContext.target()));
922         /**
923          * @param {!WebInspector.Target} target
924          * @param {?WebInspector.RemoteObject} global
925          * @param {boolean=} wasThrown
926          */
927         function didGetGlobalObject(target, global, wasThrown)
928         {
929             /**
930              * @suppressReceiverCheck
931              * @this {Window}
932              */
933             function remoteFunction(value)
934             {
935                 var prefix = "temp";
936                 var index = 1;
937                 while ((prefix + index) in this)
938                     ++index;
939                 var name = prefix + index;
940                 this[name] = value;
941                 return name;
942             }
943
944             if (wasThrown || !global)
945                 failedToSave(target, global);
946             else
947                 global.callFunction(remoteFunction, [WebInspector.RemoteObject.toCallArgument(remoteObject)], didSave.bind(null, global));
948         }
949
950         /**
951          * @param {!WebInspector.RemoteObject} global
952          * @param {?WebInspector.RemoteObject} result
953          * @param {boolean=} wasThrown
954          */
955         function didSave(global, result, wasThrown)
956         {
957             var currentExecutionContext = WebInspector.context.flavor(WebInspector.ExecutionContext);
958             global.release();
959             if (!currentExecutionContext || wasThrown || !result || result.type !== "string")
960                 failedToSave(global.target(), result);
961             else
962                 WebInspector.ConsoleModel.evaluateCommandInConsole(currentExecutionContext, result.value);
963         }
964
965         /**
966          * @param {!WebInspector.Target} target
967          * @param {?WebInspector.RemoteObject} result
968          */
969         function failedToSave(target, result)
970         {
971             var message = WebInspector.UIString("Failed to save to temp variable.");
972             if (result) {
973                 message += " " + result.description;
974                 result.release();
975             }
976             WebInspector.console.error(message);
977         }
978     },
979
980     /**
981      * @param {!WebInspector.RemoteObject} remoteObject
982      */
983     _showFunctionDefinition: function(remoteObject)
984     {
985         var debuggerModel = remoteObject.target().debuggerModel;
986
987         /**
988          * @param {?WebInspector.DebuggerModel.FunctionDetails} response
989          * @this {WebInspector.SourcesPanel}
990          */
991         function didGetFunctionDetails(response)
992         {
993             if (!response || !response.location)
994                 return;
995
996             var location = response.location;
997             if (!location)
998                 return;
999
1000             var uiLocation = WebInspector.debuggerWorkspaceBinding.rawLocationToUILocation(location);
1001             if (uiLocation)
1002                 this.showUILocation(uiLocation, true);
1003         }
1004         debuggerModel.functionDetails(remoteObject, didGetFunctionDetails.bind(this));
1005     },
1006
1007     showGoToSourceDialog: function()
1008     {
1009         this._sourcesView.showOpenResourceDialog();
1010     },
1011
1012     _dockSideChanged: function()
1013     {
1014         var vertically = WebInspector.dockController.isVertical() && WebInspector.settings.splitVerticallyWhenDockedToRight.get();
1015         this._splitVertically(vertically);
1016     },
1017
1018     /**
1019      * @param {boolean} vertically
1020      */
1021     _splitVertically: function(vertically)
1022     {
1023         if (this.sidebarPaneView && vertically === !this._splitView.isVertical())
1024             return;
1025
1026         if (this.sidebarPaneView)
1027             this.sidebarPaneView.detach();
1028
1029         this._splitView.setVertical(!vertically);
1030
1031         if (!vertically)
1032             this._splitView.uninstallResizer(this._sourcesView.statusBarContainerElement());
1033         else
1034             this._splitView.installResizer(this._sourcesView.statusBarContainerElement());
1035
1036         // Create vertical box with stack.
1037         var vbox = new WebInspector.VBox();
1038         vbox.element.appendChild(this._debugToolbarDrawer);
1039         vbox.element.appendChild(this.debugToolbar);
1040         vbox.setMinimumAndPreferredSizes(25, 25, WebInspector.SourcesPanel.minToolbarWidth, 100);
1041         var sidebarPaneStack = new WebInspector.SidebarPaneStack();
1042         sidebarPaneStack.element.classList.add("flex-auto");
1043         sidebarPaneStack.show(vbox.element);
1044
1045         if (!vertically) {
1046             // Populate the only stack.
1047             for (var pane in this.sidebarPanes)
1048                 sidebarPaneStack.addPane(this.sidebarPanes[pane]);
1049             this._extensionSidebarPanesContainer = sidebarPaneStack;
1050             this.sidebarPaneView = vbox;
1051         } else {
1052             var splitView = new WebInspector.SplitView(true, true, "sourcesPanelDebuggerSidebarSplitViewState", 0.5);
1053             vbox.show(splitView.mainElement());
1054
1055             // Populate the left stack.
1056             sidebarPaneStack.addPane(this.sidebarPanes.threads);
1057             sidebarPaneStack.addPane(this.sidebarPanes.callstack);
1058             sidebarPaneStack.addPane(this.sidebarPanes.jsBreakpoints);
1059             sidebarPaneStack.addPane(this.sidebarPanes.domBreakpoints);
1060             sidebarPaneStack.addPane(this.sidebarPanes.xhrBreakpoints);
1061             sidebarPaneStack.addPane(this.sidebarPanes.eventListenerBreakpoints);
1062             if (this.sidebarPanes.workerList)
1063                 sidebarPaneStack.addPane(this.sidebarPanes.workerList);
1064
1065             var tabbedPane = new WebInspector.SidebarTabbedPane();
1066             tabbedPane.show(splitView.sidebarElement());
1067             tabbedPane.addPane(this.sidebarPanes.scopechain);
1068             tabbedPane.addPane(this.sidebarPanes.watchExpressions);
1069             this._extensionSidebarPanesContainer = tabbedPane;
1070
1071             this.sidebarPaneView = splitView;
1072         }
1073         for (var i = 0; i < this._extensionSidebarPanes.length; ++i)
1074             this._extensionSidebarPanesContainer.addPane(this._extensionSidebarPanes[i]);
1075
1076         this.sidebarPaneView.show(this._splitView.sidebarElement());
1077         this.sidebarPanes.threads.expand();
1078         this.sidebarPanes.scopechain.expand();
1079         this.sidebarPanes.jsBreakpoints.expand();
1080         this.sidebarPanes.callstack.expand();
1081         this._sidebarPaneStack = sidebarPaneStack;
1082         this._updateTargetsSidebarVisibility();
1083         if (WebInspector.settings.watchExpressions.get().length > 0)
1084             this.sidebarPanes.watchExpressions.expand();
1085     },
1086
1087     /**
1088      * @param {string} id
1089      * @param {!WebInspector.SidebarPane} pane
1090      */
1091     addExtensionSidebarPane: function(id, pane)
1092     {
1093         this._extensionSidebarPanes.push(pane);
1094         this._extensionSidebarPanesContainer.addPane(pane);
1095         this.setHideOnDetach();
1096     },
1097
1098     /**
1099      * @return {!WebInspector.SourcesView}
1100      */
1101     sourcesView: function()
1102     {
1103         return this._sourcesView;
1104     },
1105
1106     /**
1107      * @param {!WebInspector.Target} target
1108      */
1109     targetAdded: function(target)
1110     {
1111         this._updateTargetsSidebarVisibility();
1112     },
1113
1114     /**
1115      * @param {!WebInspector.Target} target
1116      */
1117     targetRemoved: function(target)
1118     {
1119         this._updateTargetsSidebarVisibility();
1120     },
1121
1122     _updateTargetsSidebarVisibility: function()
1123     {
1124         if (!this._sidebarPaneStack)
1125             return;
1126         this._sidebarPaneStack.togglePaneHidden(this.sidebarPanes.threads, WebInspector.targetManager.targets().length < 2);
1127     },
1128
1129     __proto__: WebInspector.Panel.prototype
1130 }
1131
1132 /**
1133  * @constructor
1134  * @param {!Element} element
1135  */
1136 WebInspector.UpgradeFileSystemDropTarget = function(element)
1137 {
1138     element.addEventListener("dragenter", this._onDragEnter.bind(this), true);
1139     element.addEventListener("dragover", this._onDragOver.bind(this), true);
1140     this._element = element;
1141 }
1142
1143 WebInspector.UpgradeFileSystemDropTarget.dragAndDropFilesType = "Files";
1144
1145 WebInspector.UpgradeFileSystemDropTarget.prototype = {
1146     _onDragEnter: function (event)
1147     {
1148         if (event.dataTransfer.types.indexOf(WebInspector.UpgradeFileSystemDropTarget.dragAndDropFilesType) === -1)
1149             return;
1150         event.consume(true);
1151     },
1152
1153     _onDragOver: function (event)
1154     {
1155         if (event.dataTransfer.types.indexOf(WebInspector.UpgradeFileSystemDropTarget.dragAndDropFilesType) === -1)
1156             return;
1157         event.dataTransfer.dropEffect = "copy";
1158         event.consume(true);
1159         if (this._dragMaskElement)
1160             return;
1161         this._dragMaskElement = this._element.createChild("div", "fill drag-mask");
1162         this._dragMaskElement.createChild("div", "fill drag-mask-inner").textContent = WebInspector.UIString("Drop workspace folder here");
1163         this._dragMaskElement.addEventListener("drop", this._onDrop.bind(this), true);
1164         this._dragMaskElement.addEventListener("dragleave", this._onDragLeave.bind(this), true);
1165     },
1166
1167     _onDrop: function (event)
1168     {
1169         event.consume(true);
1170         this._removeMask();
1171         var items = /** @type {!Array.<!DataTransferItem>} */ (event.dataTransfer.items);
1172         if (!items.length)
1173             return;
1174         var entry = items[0].webkitGetAsEntry();
1175         if (!entry.isDirectory)
1176             return;
1177         InspectorFrontendHost.upgradeDraggedFileSystemPermissions(entry.filesystem);
1178     },
1179
1180     _onDragLeave: function (event)
1181     {
1182         event.consume(true);
1183         this._removeMask();
1184     },
1185
1186     _removeMask: function ()
1187     {
1188         this._dragMaskElement.remove();
1189         delete this._dragMaskElement;
1190     }
1191 }
1192
1193 /**
1194  * @constructor
1195  * @implements {WebInspector.ContextMenu.Provider}
1196  */
1197 WebInspector.SourcesPanel.ContextMenuProvider = function()
1198 {
1199 }
1200
1201 WebInspector.SourcesPanel.ContextMenuProvider.prototype = {
1202     /**
1203      * @param {!Event} event
1204      * @param {!WebInspector.ContextMenu} contextMenu
1205      * @param {!Object} target
1206      */
1207     appendApplicableItems: function(event, contextMenu, target)
1208     {
1209         WebInspector.inspectorView.panel("sources").appendApplicableItems(event, contextMenu, target);
1210     }
1211 }
1212
1213 /**
1214  * @constructor
1215  * @implements {WebInspector.Revealer}
1216  */
1217 WebInspector.SourcesPanel.UILocationRevealer = function()
1218 {
1219 }
1220
1221 WebInspector.SourcesPanel.UILocationRevealer.prototype = {
1222     /**
1223      * @param {!Object} uiLocation
1224      */
1225     reveal: function(uiLocation)
1226     {
1227         if (uiLocation instanceof WebInspector.UILocation)
1228             /** @type {!WebInspector.SourcesPanel} */ (WebInspector.inspectorView.panel("sources")).showUILocation(uiLocation);
1229     }
1230 }
1231
1232 /**
1233  * @constructor
1234  * @implements {WebInspector.Revealer}
1235  */
1236 WebInspector.SourcesPanel.UISourceCodeRevealer = function()
1237 {
1238 }
1239
1240 WebInspector.SourcesPanel.UISourceCodeRevealer.prototype = {
1241     /**
1242      * @param {!Object} uiSourceCode
1243      */
1244     reveal: function(uiSourceCode)
1245     {
1246         if (uiSourceCode instanceof WebInspector.UISourceCode)
1247             /** @type {!WebInspector.SourcesPanel} */ (WebInspector.inspectorView.panel("sources")).showUISourceCode(uiSourceCode);
1248     }
1249 }
1250
1251 /**
1252  * @constructor
1253  * @implements {WebInspector.ActionDelegate}
1254  */
1255 WebInspector.SourcesPanel.ShowGoToSourceDialogActionDelegate = function() {}
1256
1257 WebInspector.SourcesPanel.ShowGoToSourceDialogActionDelegate.prototype = {
1258     /**
1259      * @return {boolean}
1260      */
1261     handleAction: function()
1262     {
1263         var panel = /** @type {?WebInspector.SourcesPanel} */ (WebInspector.inspectorView.showPanel("sources"));
1264         if (!panel)
1265             return false;
1266         panel.showGoToSourceDialog();
1267         return true;
1268     }
1269 }
1270
1271 /**
1272  * @constructor
1273  * @extends {WebInspector.UISettingDelegate}
1274  */
1275 WebInspector.SourcesPanel.DisableJavaScriptSettingDelegate = function()
1276 {
1277     WebInspector.UISettingDelegate.call(this);
1278 }
1279
1280 WebInspector.SourcesPanel.DisableJavaScriptSettingDelegate.prototype = {
1281     /**
1282      * @override
1283      * @return {!Element}
1284      */
1285     settingElement: function()
1286     {
1287         var disableJSElement = WebInspector.SettingsUI.createSettingCheckbox(WebInspector.UIString("Disable JavaScript"), WebInspector.settings.javaScriptDisabled);
1288         this._disableJSCheckbox = disableJSElement.getElementsByTagName("input")[0];
1289         WebInspector.settings.javaScriptDisabled.addChangeListener(this._settingChanged, this);
1290         var disableJSInfoParent = this._disableJSCheckbox.parentElement.createChild("span", "monospace");
1291         this._disableJSInfo = disableJSInfoParent.createChild("span", "object-info-state-note hidden");
1292         this._disableJSInfo.title = WebInspector.UIString("JavaScript is blocked on the inspected page (may be disabled in browser settings).");
1293
1294         WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, this._updateScriptDisabledCheckbox, this);
1295         this._updateScriptDisabledCheckbox();
1296         return disableJSElement;
1297     },
1298
1299     /**
1300      * @param {!WebInspector.Event} event
1301      */
1302     _settingChanged: function(event)
1303     {
1304         PageAgent.setScriptExecutionDisabled(event.data, this._updateScriptDisabledCheckbox.bind(this));
1305     },
1306
1307     _updateScriptDisabledCheckbox: function()
1308     {
1309         PageAgent.getScriptExecutionStatus(executionStatusCallback.bind(this));
1310
1311         /**
1312          * @param {?Protocol.Error} error
1313          * @param {string} status
1314          * @this {WebInspector.SourcesPanel.DisableJavaScriptSettingDelegate}
1315          */
1316         function executionStatusCallback(error, status)
1317         {
1318             if (error || !status)
1319                 return;
1320
1321             var forbidden = (status === "forbidden");
1322             var disabled = forbidden || (status === "disabled");
1323
1324             this._disableJSInfo.classList.toggle("hidden", !forbidden);
1325             this._disableJSCheckbox.checked = disabled;
1326             this._disableJSCheckbox.disabled = forbidden;
1327         }
1328     },
1329
1330     __proto__: WebInspector.UISettingDelegate.prototype
1331 }
1332
1333 /**
1334  * @constructor
1335  * @implements {WebInspector.ActionDelegate}
1336  */
1337 WebInspector.SourcesPanel.TogglePauseActionDelegate = function()
1338 {
1339 }
1340
1341 WebInspector.SourcesPanel.TogglePauseActionDelegate.prototype = {
1342     /**
1343      * @return {boolean}
1344      */
1345     handleAction: function()
1346     {
1347         var panel = /** @type {?WebInspector.SourcesPanel} */ (WebInspector.inspectorView.showPanel("sources"));
1348         if (!panel)
1349             return false;
1350         panel.togglePause();
1351         return true;
1352     }
1353 }