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