2 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
3 * Copyright (C) 2011 Google Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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.
27 importScript("BreakpointsSidebarPane.js");
28 importScript("CallStackSidebarPane.js");
29 importScript("SimpleHistoryManager.js");
30 importScript("EditingLocationHistoryManager.js");
31 importScript("FilePathScoreFunction.js");
32 importScript("FilteredItemSelectionDialog.js");
33 importScript("UISourceCodeFrame.js");
34 importScript("JavaScriptSourceFrame.js");
35 importScript("CSSSourceFrame.js");
36 importScript("NavigatorView.js");
37 importScript("RevisionHistoryView.js");
38 importScript("ScopeChainSidebarPane.js");
39 importScript("SourcesNavigator.js");
40 importScript("SourcesSearchScope.js");
41 importScript("StyleSheetOutlineDialog.js");
42 importScript("TabbedEditorContainer.js");
43 importScript("WatchExpressionsSidebarPane.js");
44 importScript("WorkersSidebarPane.js");
45 importScript("ThreadsToolbar.js");
46 importScript("ScriptFormatterEditorAction.js");
47 importScript("InplaceFormatterEditorAction.js");
48 importScript("ScriptFormatter.js");
49 importScript("SourcesView.js");
53 * @implements {WebInspector.ContextMenu.Provider}
54 * @extends {WebInspector.Panel}
55 * @param {!WebInspector.Workspace=} workspaceForTest
57 WebInspector.SourcesPanel = function(workspaceForTest)
59 WebInspector.Panel.call(this, "sources");
60 this.registerRequiredCSS("sourcesPanel.css");
61 this.registerRequiredCSS("textPrompt.css"); // Watch Expressions autocomplete.
62 new WebInspector.UpgradeFileSystemDropTarget(this.element);
64 WebInspector.settings.showEditorInDrawer = WebInspector.settings.createSetting("showEditorInDrawer", true);
66 this._workspace = workspaceForTest || WebInspector.workspace;
68 var helpSection = WebInspector.shortcutsScreen.section(WebInspector.UIString("Sources Panel"));
69 this.debugToolbar = this._createDebugToolbar();
70 this._debugToolbarDrawer = this._createDebugToolbarDrawer();
71 this.threadsToolbar = new WebInspector.ThreadsToolbar();
73 const initialDebugSidebarWidth = 225;
74 this._splitView = new WebInspector.SplitView(true, true, "sourcesPanelSplitViewState", initialDebugSidebarWidth);
75 this._splitView.enableShowModeSaving();
76 this._splitView.show(this.element);
78 // Create scripts navigator
79 const initialNavigatorWidth = 225;
80 this.editorView = new WebInspector.SplitView(true, false, "sourcesPanelNavigatorSplitViewState", initialNavigatorWidth);
81 this.editorView.enableShowModeSaving();
82 this.editorView.element.id = "scripts-editor-split-view";
83 this.editorView.element.tabIndex = 0;
84 this.editorView.show(this._splitView.mainElement());
86 this._navigator = new WebInspector.SourcesNavigator(this._workspace);
87 this._navigator.view.setMinimumSize(Preferences.minSidebarWidth, 25);
88 this._navigator.view.show(this.editorView.sidebarElement());
89 this._navigator.addEventListener(WebInspector.SourcesNavigator.Events.SourceSelected, this._sourceSelected, this);
90 this._navigator.addEventListener(WebInspector.SourcesNavigator.Events.SourceRenamed, this._sourceRenamed, this);
92 this._sourcesView = new WebInspector.SourcesView(this._workspace, this);
93 this._sourcesView.addEventListener(WebInspector.SourcesView.Events.EditorSelected, this._editorSelected.bind(this));
94 this._sourcesView.addEventListener(WebInspector.SourcesView.Events.EditorClosed, this._editorClosed.bind(this));
95 this._sourcesView.registerShortcuts(this.registerShortcuts.bind(this));
97 this._drawerEditorView = new WebInspector.SourcesPanel.DrawerEditorView();
98 this._sourcesView.show(this._drawerEditorView.element);
100 this._debugSidebarResizeWidgetElement = document.createElementWithClass("div", "resizer-widget");
101 this._debugSidebarResizeWidgetElement.id = "scripts-debug-sidebar-resizer-widget";
102 this._splitView.addEventListener(WebInspector.SplitView.Events.ShowModeChanged, this._updateDebugSidebarResizeWidget, this);
103 this._updateDebugSidebarResizeWidget();
104 this._splitView.installResizer(this._debugSidebarResizeWidgetElement);
106 this.sidebarPanes = {};
107 this.sidebarPanes.watchExpressions = new WebInspector.WatchExpressionsSidebarPane();
108 this.sidebarPanes.callstack = new WebInspector.CallStackSidebarPane();
109 this.sidebarPanes.callstack.addEventListener(WebInspector.CallStackSidebarPane.Events.CallFrameSelected, this._callFrameSelectedInSidebar.bind(this));
110 this.sidebarPanes.callstack.addEventListener(WebInspector.CallStackSidebarPane.Events.CallFrameRestarted, this._callFrameRestartedInSidebar.bind(this));
111 this.sidebarPanes.callstack.registerShortcuts(this.registerShortcuts.bind(this));
113 this.sidebarPanes.scopechain = new WebInspector.ScopeChainSidebarPane();
114 this.sidebarPanes.jsBreakpoints = new WebInspector.JavaScriptBreakpointsSidebarPane(WebInspector.debuggerModel, WebInspector.breakpointManager, this.showUISourceCode.bind(this));
115 this.sidebarPanes.domBreakpoints = WebInspector.domBreakpointsSidebarPane.createProxy(this);
116 this.sidebarPanes.xhrBreakpoints = new WebInspector.XHRBreakpointsSidebarPane();
117 this.sidebarPanes.eventListenerBreakpoints = new WebInspector.EventListenerBreakpointsSidebarPane();
119 if (Capabilities.isMainFrontend)
120 this.sidebarPanes.workerList = new WebInspector.WorkersSidebarPane();
122 this._extensionSidebarPanes = [];
124 this._installDebuggerSidebarController();
126 WebInspector.dockController.addEventListener(WebInspector.DockController.Events.DockSideChanged, this._dockSideChanged.bind(this));
127 WebInspector.settings.splitVerticallyWhenDockedToRight.addChangeListener(this._dockSideChanged.bind(this));
128 this._dockSideChanged();
130 this._updateDebuggerButtons();
131 this._pauseOnExceptionEnabledChanged();
132 if (WebInspector.debuggerModel.isPaused())
133 this._showDebuggerPausedDetails();
135 WebInspector.settings.pauseOnExceptionEnabled.addChangeListener(this._pauseOnExceptionEnabledChanged, this);
136 WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerWasEnabled, this._debuggerWasEnabled, this);
137 WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerWasDisabled, this._debuggerWasDisabled, this);
138 WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
139 WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerResumed, this._debuggerResumed, this);
140 WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.CallFrameSelected, this._callFrameSelected, this);
141 WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.ConsoleCommandEvaluatedInSelectedCallFrame, this._consoleCommandEvaluatedInSelectedCallFrame, this);
142 WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointsActiveStateChanged, this._breakpointsActiveStateChanged, this);
143 WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.GlobalObjectCleared, this._debuggerReset, this);
146 WebInspector.SourcesPanel.minToolbarWidth = 215;
148 WebInspector.SourcesPanel.prototype = {
152 defaultFocusedElement: function()
154 return this._sourcesView.defaultFocusedElement() || this._navigator.view.defaultFocusedElement();
163 * @return {!WebInspector.SourcesPanel.DrawerEditor}
165 _drawerEditor: function()
167 var drawerEditorInstance = WebInspector.moduleManager.instance(WebInspector.DrawerEditor);
168 console.assert(drawerEditorInstance instanceof WebInspector.SourcesPanel.DrawerEditor, "WebInspector.DrawerEditor module instance does not use WebInspector.SourcesPanel.DrawerEditor as an implementation. ");
169 return /** @type {!WebInspector.SourcesPanel.DrawerEditor} */ (drawerEditorInstance);
174 this._drawerEditor()._panelWasShown();
175 this._sourcesView.show(this.editorView.mainElement());
176 WebInspector.Panel.prototype.wasShown.call(this);
181 WebInspector.Panel.prototype.willHide.call(this);
182 this._drawerEditor()._panelWillHide();
183 this._sourcesView.show(this._drawerEditorView.element);
187 * @return {!WebInspector.SearchableView}
189 searchableView: function()
191 return this._sourcesView.searchableView();
194 _consoleCommandEvaluatedInSelectedCallFrame: function(event)
196 this.sidebarPanes.scopechain.update(WebInspector.debuggerModel.selectedCallFrame());
199 _debuggerPaused: function()
201 WebInspector.inspectorView.setCurrentPanel(this);
202 this._showDebuggerPausedDetails();
205 _showDebuggerPausedDetails: function()
207 var details = WebInspector.debuggerModel.debuggerPausedDetails();
210 this._waitingToPause = false;
212 this._updateDebuggerButtons();
214 this.sidebarPanes.callstack.update(details.callFrames, details.asyncStackTrace);
217 * @param {!Element} element
218 * @this {WebInspector.SourcesPanel}
220 function didCreateBreakpointHitStatusMessage(element)
222 this.sidebarPanes.callstack.setStatus(element);
226 * @param {!WebInspector.UILocation} uiLocation
227 * @this {WebInspector.SourcesPanel}
229 function didGetUILocation(uiLocation)
231 var breakpoint = WebInspector.breakpointManager.findBreakpointOnLine(uiLocation.uiSourceCode, uiLocation.lineNumber);
234 this.sidebarPanes.jsBreakpoints.highlightBreakpoint(breakpoint);
235 this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a JavaScript breakpoint."));
238 if (details.reason === WebInspector.DebuggerModel.BreakReason.DOM) {
239 WebInspector.domBreakpointsSidebarPane.highlightBreakpoint(details.auxData);
240 WebInspector.domBreakpointsSidebarPane.createBreakpointHitStatusMessage(details.auxData, didCreateBreakpointHitStatusMessage.bind(this));
241 } else if (details.reason === WebInspector.DebuggerModel.BreakReason.EventListener) {
242 var eventName = details.auxData.eventName;
243 this.sidebarPanes.eventListenerBreakpoints.highlightBreakpoint(details.auxData.eventName);
244 var eventNameForUI = WebInspector.EventListenerBreakpointsSidebarPane.eventNameForUI(eventName, details.auxData);
245 this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a \"%s\" Event Listener.", eventNameForUI));
246 } else if (details.reason === WebInspector.DebuggerModel.BreakReason.XHR) {
247 this.sidebarPanes.xhrBreakpoints.highlightBreakpoint(details.auxData["breakpointURL"]);
248 this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a XMLHttpRequest."));
249 } else if (details.reason === WebInspector.DebuggerModel.BreakReason.Exception)
250 this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on exception: '%s'.", details.auxData.description));
251 else if (details.reason === WebInspector.DebuggerModel.BreakReason.Assert)
252 this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on assertion."));
253 else if (details.reason === WebInspector.DebuggerModel.BreakReason.CSPViolation)
254 this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a script blocked due to Content Security Policy directive: \"%s\".", details.auxData["directiveText"]));
255 else if (details.reason === WebInspector.DebuggerModel.BreakReason.DebugCommand)
256 this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a debugged function"));
258 if (details.callFrames.length)
259 details.callFrames[0].createLiveLocation(didGetUILocation.bind(this));
261 console.warn("ScriptsPanel paused, but callFrames.length is zero."); // TODO remove this once we understand this case better
264 this._splitView.showBoth(true);
265 this._toggleDebuggerSidebarButton.setEnabled(false);
267 InspectorFrontendHost.bringToFront();
270 _debuggerResumed: function()
272 this._paused = false;
273 this._waitingToPause = false;
275 this._clearInterface();
276 this._toggleDebuggerSidebarButton.setEnabled(true);
279 _debuggerWasEnabled: function()
281 this._updateDebuggerButtons();
284 _debuggerWasDisabled: function()
286 this._debuggerReset();
289 _debuggerReset: function()
291 this._debuggerResumed();
292 this.sidebarPanes.watchExpressions.reset();
293 delete this._skipExecutionLineRevealing;
297 * @return {!WebInspector.View}
301 return this._sourcesView.visibleView();
305 * @param {!WebInspector.UISourceCode} uiSourceCode
306 * @param {number=} lineNumber
307 * @param {number=} columnNumber
308 * @param {boolean=} forceShowInPanel
310 showUISourceCode: function(uiSourceCode, lineNumber, columnNumber, forceShowInPanel)
312 this._showEditor(forceShowInPanel);
313 this._sourcesView.showSourceLocation(uiSourceCode, lineNumber, columnNumber);
316 _showEditor: function(forceShowInPanel)
318 if (this._sourcesView.isShowing())
321 if (this._shouldShowEditorInDrawer() && !forceShowInPanel)
322 this._drawerEditor()._show();
324 WebInspector.inspectorView.showPanel("sources");
328 * @param {!WebInspector.UILocation} uiLocation
329 * @param {boolean=} forceShowInPanel
331 showUILocation: function(uiLocation, forceShowInPanel)
333 this.showUISourceCode(uiLocation.uiSourceCode, uiLocation.lineNumber, uiLocation.columnNumber, forceShowInPanel);
339 _shouldShowEditorInDrawer: function()
341 return WebInspector.experimentsSettings.showEditorInDrawer.isEnabled() && WebInspector.settings.showEditorInDrawer.get() && WebInspector.inspectorView.isDrawerEditorShown();
345 * @param {!WebInspector.UISourceCode} uiSourceCode
347 _revealInNavigator: function(uiSourceCode)
349 this._navigator.revealUISourceCode(uiSourceCode);
352 _executionLineChanged: function(uiLocation)
354 this._sourcesView.clearCurrentExecutionLine();
355 this._sourcesView.setExecutionLine(uiLocation);
356 if (this._skipExecutionLineRevealing)
358 this._skipExecutionLineRevealing = true;
359 this._sourcesView.showSourceLocation(uiLocation.uiSourceCode, uiLocation.lineNumber, 0, undefined, true);
362 _callFrameSelected: function(event)
364 var callFrame = event.data;
369 this.sidebarPanes.scopechain.update(callFrame);
370 this.sidebarPanes.watchExpressions.refreshExpressions();
371 this.sidebarPanes.callstack.setSelectedCallFrame(callFrame);
372 callFrame.createLiveLocation(this._executionLineChanged.bind(this));
376 * @param {!WebInspector.Event} event
378 _sourceSelected: function(event)
380 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data.uiSourceCode);
381 this._sourcesView.showSourceLocation(uiSourceCode, undefined, undefined, !event.data.focusSource)
385 * @param {!WebInspector.Event} event
387 _sourceRenamed: function(event)
389 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data);
390 this._sourcesView.sourceRenamed(uiSourceCode);
393 _pauseOnExceptionEnabledChanged: function()
395 var enabled = WebInspector.settings.pauseOnExceptionEnabled.get();
396 this._pauseOnExceptionButton.toggled = enabled;
397 this._pauseOnExceptionButton.title = WebInspector.UIString(enabled ? "Don't pause on exceptions." : "Pause on exceptions.");
398 this._debugToolbarDrawer.classList.toggle("expanded", enabled);
401 _updateDebuggerButtons: function()
404 this._updateButtonTitle(this._pauseButton, WebInspector.UIString("Resume script execution (%s)."))
405 this._pauseButton.state = true;
406 this._pauseButton.setLongClickOptionsEnabled((function() { return [ this._longResumeButton ] }).bind(this));
408 this._pauseButton.setEnabled(true);
409 this._stepOverButton.setEnabled(true);
410 this._stepIntoButton.setEnabled(true);
411 this._stepOutButton.setEnabled(true);
413 this._updateButtonTitle(this._pauseButton, WebInspector.UIString("Pause script execution (%s)."))
414 this._pauseButton.state = false;
415 this._pauseButton.setLongClickOptionsEnabled(null);
417 this._pauseButton.setEnabled(!this._waitingToPause);
418 this._stepOverButton.setEnabled(false);
419 this._stepIntoButton.setEnabled(false);
420 this._stepOutButton.setEnabled(false);
424 _clearInterface: function()
426 this.sidebarPanes.callstack.update(null, null);
427 this.sidebarPanes.scopechain.update(null);
428 this.sidebarPanes.jsBreakpoints.clearBreakpointHighlight();
429 WebInspector.domBreakpointsSidebarPane.clearBreakpointHighlight();
430 this.sidebarPanes.eventListenerBreakpoints.clearBreakpointHighlight();
431 this.sidebarPanes.xhrBreakpoints.clearBreakpointHighlight();
433 this._sourcesView.clearCurrentExecutionLine();
434 this._updateDebuggerButtons();
437 _togglePauseOnExceptions: function()
439 WebInspector.settings.pauseOnExceptionEnabled.set(!this._pauseOnExceptionButton.toggled);
445 _runSnippet: function()
447 var uiSourceCode = this._sourcesView.currentUISourceCode();
448 if (uiSourceCode.project().type() !== WebInspector.projectTypes.Snippets)
450 WebInspector.scriptSnippetModel.evaluateScriptSnippet(uiSourceCode);
455 * @param {!WebInspector.Event} event
457 _editorSelected: function(event)
459 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data);
460 this._editorChanged(uiSourceCode);
464 * @param {!WebInspector.Event} event
466 _editorClosed: function(event)
468 var wasSelected = /** @type {boolean} */ (event.data.wasSelected);
470 this._editorChanged(null);
474 * @param {?WebInspector.UISourceCode} uiSourceCode
476 _editorChanged: function(uiSourceCode)
478 var isSnippet = uiSourceCode && uiSourceCode.project().type() === WebInspector.projectTypes.Snippets;
479 this._runSnippetButton.element.classList.toggle("hidden", !isSnippet);
485 _togglePause: function()
488 delete this._skipExecutionLineRevealing;
489 this._paused = false;
490 this._waitingToPause = false;
491 WebInspector.debuggerModel.resume();
493 this._waitingToPause = true;
494 // Make sure pauses didn't stick skipped.
495 WebInspector.debuggerModel.skipAllPauses(false);
496 DebuggerAgent.pause();
499 this._clearInterface();
506 _longResume: function()
511 this._paused = false;
512 this._waitingToPause = false;
513 WebInspector.debuggerModel.skipAllPausesUntilReloadOrTimeout(500);
514 WebInspector.debuggerModel.resume();
516 this._clearInterface();
523 _stepOverClicked: function()
528 delete this._skipExecutionLineRevealing;
529 this._paused = false;
531 this._clearInterface();
533 WebInspector.debuggerModel.stepOver();
540 _stepIntoClicked: function()
545 delete this._skipExecutionLineRevealing;
546 this._paused = false;
548 this._clearInterface();
550 WebInspector.debuggerModel.stepInto();
557 _stepOutClicked: function()
562 delete this._skipExecutionLineRevealing;
563 this._paused = false;
565 this._clearInterface();
567 WebInspector.debuggerModel.stepOut();
572 * @param {!WebInspector.Event} event
574 _callFrameSelectedInSidebar: function(event)
576 var callFrame = /** @type {!WebInspector.DebuggerModel.CallFrame} */ (event.data);
577 delete this._skipExecutionLineRevealing;
578 WebInspector.debuggerModel.setSelectedCallFrame(callFrame);
581 _callFrameRestartedInSidebar: function()
583 delete this._skipExecutionLineRevealing;
586 continueToLocation: function(rawLocation)
591 delete this._skipExecutionLineRevealing;
592 this._paused = false;
593 this._clearInterface();
594 WebInspector.debuggerModel.continueToLocation(rawLocation);
597 _toggleBreakpointsClicked: function(event)
599 WebInspector.debuggerModel.setBreakpointsActive(!WebInspector.debuggerModel.breakpointsActive());
602 _breakpointsActiveStateChanged: function(event)
604 var active = event.data;
605 this._toggleBreakpointsButton.toggled = !active;
606 this.sidebarPanes.jsBreakpoints.listElement.classList.toggle("breakpoints-list-deactivated", !active);
607 this._sourcesView.toggleBreakpointsActiveState(active);
609 this._toggleBreakpointsButton.title = WebInspector.UIString("Deactivate breakpoints.");
611 this._toggleBreakpointsButton.title = WebInspector.UIString("Activate breakpoints.");
614 _createDebugToolbar: function()
616 var debugToolbar = document.createElement("div");
617 debugToolbar.className = "scripts-debug-toolbar";
620 var platformSpecificModifier = WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta;
623 title = WebInspector.UIString("Run snippet (%s).");
624 handler = this._runSnippet.bind(this);
625 this._runSnippetButton = this._createButtonAndRegisterShortcuts("scripts-run-snippet", title, handler, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.RunSnippet);
626 debugToolbar.appendChild(this._runSnippetButton.element);
627 this._runSnippetButton.element.classList.add("hidden");
630 handler = this._togglePause.bind(this);
631 this._pauseButton = this._createButtonAndRegisterShortcuts("scripts-pause", "", handler, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.PauseContinue);
632 debugToolbar.appendChild(this._pauseButton.element);
635 title = WebInspector.UIString("Resume with all pauses blocked for 500 ms");
636 this._longResumeButton = new WebInspector.StatusBarButton(title, "scripts-long-resume");
637 this._longResumeButton.addEventListener("click", this._longResume.bind(this), this);
640 title = WebInspector.UIString("Step over next function call (%s).");
641 handler = this._stepOverClicked.bind(this);
642 this._stepOverButton = this._createButtonAndRegisterShortcuts("scripts-step-over", title, handler, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.StepOver);
643 debugToolbar.appendChild(this._stepOverButton.element);
646 title = WebInspector.UIString("Step into next function call (%s).");
647 handler = this._stepIntoClicked.bind(this);
648 this._stepIntoButton = this._createButtonAndRegisterShortcuts("scripts-step-into", title, handler, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.StepInto);
649 debugToolbar.appendChild(this._stepIntoButton.element);
652 title = WebInspector.UIString("Step out of current function (%s).");
653 handler = this._stepOutClicked.bind(this);
654 this._stepOutButton = this._createButtonAndRegisterShortcuts("scripts-step-out", title, handler, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.StepOut);
655 debugToolbar.appendChild(this._stepOutButton.element);
657 // Toggle Breakpoints
658 this._toggleBreakpointsButton = new WebInspector.StatusBarButton(WebInspector.UIString("Deactivate breakpoints."), "scripts-toggle-breakpoints");
659 this._toggleBreakpointsButton.toggled = false;
660 this._toggleBreakpointsButton.addEventListener("click", this._toggleBreakpointsClicked, this);
661 debugToolbar.appendChild(this._toggleBreakpointsButton.element);
663 // Pause on Exception
664 this._pauseOnExceptionButton = new WebInspector.StatusBarButton("", "scripts-pause-on-exceptions-status-bar-item");
665 this._pauseOnExceptionButton.addEventListener("click", this._togglePauseOnExceptions, this);
666 debugToolbar.appendChild(this._pauseOnExceptionButton.element);
671 _createDebugToolbarDrawer: function()
673 var debugToolbarDrawer = document.createElement("div");
674 debugToolbarDrawer.className = "scripts-debug-toolbar-drawer";
676 var label = WebInspector.UIString("Pause On Caught Exceptions");
677 var setting = WebInspector.settings.pauseOnCaughtException;
678 debugToolbarDrawer.appendChild(WebInspector.SettingsUI.createSettingCheckbox(label, setting, true));
680 return debugToolbarDrawer;
684 * @param {!WebInspector.StatusBarButton} button
685 * @param {string} buttonTitle
687 _updateButtonTitle: function(button, buttonTitle)
689 var hasShortcuts = button.shortcuts && button.shortcuts.length;
691 button.title = String.vsprintf(buttonTitle, [button.shortcuts[0].name]);
693 button.title = buttonTitle;
697 * @param {string} buttonId
698 * @param {string} buttonTitle
699 * @param {function(?Event=):boolean} handler
700 * @param {!Array.<!WebInspector.KeyboardShortcut.Descriptor>} shortcuts
701 * @return {!WebInspector.StatusBarButton}
703 _createButtonAndRegisterShortcuts: function(buttonId, buttonTitle, handler, shortcuts)
705 var button = new WebInspector.StatusBarButton(buttonTitle, buttonId);
706 button.element.addEventListener("click", handler, false);
707 button.shortcuts = shortcuts;
708 this._updateButtonTitle(button, buttonTitle);
709 this.registerShortcuts(shortcuts, handler);
713 addToWatch: function(expression)
715 this.sidebarPanes.watchExpressions.addExpression(expression);
718 _installDebuggerSidebarController: function()
720 this._toggleNavigatorSidebarButton = this.editorView.createShowHideSidebarButton("navigator", "scripts-navigator-show-hide-button");
721 this.editorView.mainElement().appendChild(this._toggleNavigatorSidebarButton.element);
723 this._toggleDebuggerSidebarButton = this._splitView.createShowHideSidebarButton("debugger", "scripts-debugger-show-hide-button");
725 this._splitView.mainElement().appendChild(this._toggleDebuggerSidebarButton.element);
726 this._splitView.mainElement().appendChild(this._debugSidebarResizeWidgetElement);
729 _updateDebugSidebarResizeWidget: function()
731 this._debugSidebarResizeWidgetElement.classList.toggle("hidden", this._splitView.showMode() !== WebInspector.SplitView.ShowMode.Both);
735 * @param {!WebInspector.UISourceCode} uiSourceCode
737 _showLocalHistory: function(uiSourceCode)
739 WebInspector.RevisionHistoryView.showHistory(uiSourceCode);
743 * @param {!WebInspector.ContextMenu} contextMenu
744 * @param {!Object} target
746 appendApplicableItems: function(event, contextMenu, target)
748 this._appendUISourceCodeItems(event, contextMenu, target);
749 this._appendRemoteObjectItems(contextMenu, target);
752 _suggestReload: function()
754 if (window.confirm(WebInspector.UIString("It is recommended to restart inspector after making these changes. Would you like to restart it?")))
755 WebInspector.reload();
759 * @param {!WebInspector.UISourceCode} uiSourceCode
761 _mapFileSystemToNetwork: function(uiSourceCode)
763 WebInspector.SelectUISourceCodeForProjectTypeDialog.show(uiSourceCode.name(), WebInspector.projectTypes.Network, mapFileSystemToNetwork.bind(this), this.editorView.mainElement())
766 * @param {!WebInspector.UISourceCode} networkUISourceCode
767 * @this {WebInspector.SourcesPanel}
769 function mapFileSystemToNetwork(networkUISourceCode)
771 this._workspace.addMapping(networkUISourceCode, uiSourceCode, WebInspector.fileSystemWorkspaceProvider);
772 this._suggestReload();
777 * @param {!WebInspector.UISourceCode} uiSourceCode
779 _removeNetworkMapping: function(uiSourceCode)
781 if (confirm(WebInspector.UIString("Are you sure you want to remove network mapping?"))) {
782 this._workspace.removeMapping(uiSourceCode);
783 this._suggestReload();
788 * @param {!WebInspector.UISourceCode} networkUISourceCode
790 _mapNetworkToFileSystem: function(networkUISourceCode)
792 WebInspector.SelectUISourceCodeForProjectTypeDialog.show(networkUISourceCode.name(), WebInspector.projectTypes.FileSystem, mapNetworkToFileSystem.bind(this), this.editorView.mainElement())
795 * @param {!WebInspector.UISourceCode} uiSourceCode
796 * @this {WebInspector.SourcesPanel}
798 function mapNetworkToFileSystem(uiSourceCode)
800 this._workspace.addMapping(networkUISourceCode, uiSourceCode, WebInspector.fileSystemWorkspaceProvider);
805 * @param {!WebInspector.ContextMenu} contextMenu
806 * @param {!WebInspector.UISourceCode} uiSourceCode
808 _appendUISourceCodeMappingItems: function(contextMenu, uiSourceCode)
810 if (uiSourceCode.project().type() === WebInspector.projectTypes.FileSystem) {
811 var hasMappings = !!uiSourceCode.url;
813 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Map to network resource\u2026" : "Map to Network Resource\u2026"), this._mapFileSystemToNetwork.bind(this, uiSourceCode));
815 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove network mapping" : "Remove Network Mapping"), this._removeNetworkMapping.bind(this, uiSourceCode));
819 * @param {!WebInspector.Project} project
821 function filterProject(project)
823 return project.type() === WebInspector.projectTypes.FileSystem;
826 if (uiSourceCode.project().type() === WebInspector.projectTypes.Network) {
827 if (!this._workspace.projects().filter(filterProject).length)
829 if (this._workspace.uiSourceCodeForURL(uiSourceCode.url) === uiSourceCode)
830 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Map to file system resource\u2026" : "Map to File System Resource\u2026"), this._mapNetworkToFileSystem.bind(this, uiSourceCode));
835 * @param {!Event} event
836 * @param {!WebInspector.ContextMenu} contextMenu
837 * @param {!Object} target
839 _appendUISourceCodeItems: function(event, contextMenu, target)
841 if (!(target instanceof WebInspector.UISourceCode))
844 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (target);
845 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Local modifications\u2026" : "Local Modifications\u2026"), this._showLocalHistory.bind(this, uiSourceCode));
846 this._appendUISourceCodeMappingItems(contextMenu, uiSourceCode);
848 if (!event.target.isSelfOrDescendant(this.editorView.sidebarElement())) {
849 contextMenu.appendSeparator();
850 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Reveal in navigator" : "Reveal in Navigator"), this._handleContextMenuReveal.bind(this, uiSourceCode));
855 * @param {!WebInspector.UISourceCode} uiSourceCode
857 _handleContextMenuReveal: function(uiSourceCode)
859 this.editorView.showBoth();
860 this._revealInNavigator(uiSourceCode);
864 * @param {!WebInspector.ContextMenu} contextMenu
865 * @param {!Object} target
867 _appendRemoteObjectItems: function(contextMenu, target)
869 if (!(target instanceof WebInspector.RemoteObject))
871 var remoteObject = /** @type {!WebInspector.RemoteObject} */ (target);
872 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Store as global variable" : "Store as Global Variable"), this._saveToTempVariable.bind(this, remoteObject));
873 if (remoteObject.type === "function")
874 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Show function definition" : "Show Function Definition"), this._showFunctionDefinition.bind(this, remoteObject));
878 * @param {!WebInspector.RemoteObject} remoteObject
880 _saveToTempVariable: function(remoteObject)
882 WebInspector.runtimeModel.evaluate("window", "", false, true, false, false, didGetGlobalObject);
885 * @param {?WebInspector.RemoteObject} global
886 * @param {boolean=} wasThrown
888 function didGetGlobalObject(global, wasThrown)
891 * @suppressReceiverCheck
894 function remoteFunction(value)
898 while ((prefix + index) in this)
900 var name = prefix + index;
905 if (wasThrown || !global)
906 failedToSave(global);
908 global.callFunction(remoteFunction, [WebInspector.RemoteObject.toCallArgument(remoteObject)], didSave.bind(null, global));
912 * @param {!WebInspector.RemoteObject} global
913 * @param {?WebInspector.RemoteObject} result
914 * @param {boolean=} wasThrown
916 function didSave(global, result, wasThrown)
919 if (wasThrown || !result || result.type !== "string")
920 failedToSave(result);
922 WebInspector.console.evaluate(result.value);
926 * @param {?WebInspector.RemoteObject} result
928 function failedToSave(result)
930 var message = WebInspector.UIString("Failed to save to temp variable.");
932 message += " " + result.description;
935 WebInspector.console.showErrorMessage(message)
940 * @param {!WebInspector.RemoteObject} remoteObject
942 _showFunctionDefinition: function(remoteObject)
945 * @param {?Protocol.Error} error
946 * @param {!DebuggerAgent.FunctionDetails} response
947 * @this {WebInspector.SourcesPanel}
949 function didGetFunctionDetails(error, response)
952 console.error(error);
956 var uiLocation = WebInspector.debuggerModel.rawLocationToUILocation(response.location);
960 this.showUILocation(uiLocation, true);
962 DebuggerAgent.getFunctionDetails(remoteObject.objectId, didGetFunctionDetails.bind(this));
965 showGoToSourceDialog: function()
967 this._sourcesView.showOpenResourceDialog();
970 _dockSideChanged: function()
972 var vertically = WebInspector.dockController.isVertical() && WebInspector.settings.splitVerticallyWhenDockedToRight.get();
973 this._splitVertically(vertically);
977 * @param {boolean} vertically
979 _splitVertically: function(vertically)
981 if (this.sidebarPaneView && vertically === !this._splitView.isVertical())
984 if (this.sidebarPaneView)
985 this.sidebarPaneView.detach();
987 this._splitView.setVertical(!vertically);
990 this._splitView.uninstallResizer(this._sourcesView.statusBarContainerElement());
992 this._splitView.installResizer(this._sourcesView.statusBarContainerElement());
994 // Create vertical box with stack.
995 var vbox = new WebInspector.VBox();
996 vbox.element.appendChild(this._debugToolbarDrawer);
997 vbox.element.appendChild(this.debugToolbar);
998 vbox.element.appendChild(this.threadsToolbar.element);
999 vbox.setMinimumSize(WebInspector.SourcesPanel.minToolbarWidth, 25);
1000 var sidebarPaneStack = new WebInspector.SidebarPaneStack();
1001 sidebarPaneStack.element.classList.add("flex-auto");
1002 sidebarPaneStack.show(vbox.element);
1005 // Populate the only stack.
1006 for (var pane in this.sidebarPanes)
1007 sidebarPaneStack.addPane(this.sidebarPanes[pane]);
1008 this._extensionSidebarPanesContainer = sidebarPaneStack;
1010 this.sidebarPaneView = vbox;
1012 var splitView = new WebInspector.SplitView(true, true, "sourcesPanelDebuggerSidebarSplitViewState", 0.5);
1013 vbox.show(splitView.mainElement());
1015 // Populate the left stack.
1016 sidebarPaneStack.addPane(this.sidebarPanes.callstack);
1017 sidebarPaneStack.addPane(this.sidebarPanes.jsBreakpoints);
1018 sidebarPaneStack.addPane(this.sidebarPanes.domBreakpoints);
1019 sidebarPaneStack.addPane(this.sidebarPanes.xhrBreakpoints);
1020 sidebarPaneStack.addPane(this.sidebarPanes.eventListenerBreakpoints);
1021 if (this.sidebarPanes.workerList)
1022 sidebarPaneStack.addPane(this.sidebarPanes.workerList);
1024 var tabbedPane = new WebInspector.SidebarTabbedPane();
1025 tabbedPane.show(splitView.sidebarElement());
1026 tabbedPane.addPane(this.sidebarPanes.scopechain);
1027 tabbedPane.addPane(this.sidebarPanes.watchExpressions);
1028 this._extensionSidebarPanesContainer = tabbedPane;
1030 this.sidebarPaneView = splitView;
1032 for (var i = 0; i < this._extensionSidebarPanes.length; ++i)
1033 this._extensionSidebarPanesContainer.addPane(this._extensionSidebarPanes[i]);
1035 this.sidebarPaneView.show(this._splitView.sidebarElement());
1037 this.sidebarPanes.scopechain.expand();
1038 this.sidebarPanes.jsBreakpoints.expand();
1039 this.sidebarPanes.callstack.expand();
1041 if (WebInspector.settings.watchExpressions.get().length > 0)
1042 this.sidebarPanes.watchExpressions.expand();
1046 * @param {string} id
1047 * @param {!WebInspector.SidebarPane} pane
1049 addExtensionSidebarPane: function(id, pane)
1051 this._extensionSidebarPanes.push(pane);
1052 this._extensionSidebarPanesContainer.addPane(pane);
1053 this.setHideOnDetach();
1057 * @return {!WebInspector.SourcesView}
1059 sourcesView: function()
1061 return this._sourcesView;
1064 __proto__: WebInspector.Panel.prototype
1069 * @param {!Element} element
1071 WebInspector.UpgradeFileSystemDropTarget = function(element)
1073 element.addEventListener("dragenter", this._onDragEnter.bind(this), true);
1074 element.addEventListener("dragover", this._onDragOver.bind(this), true);
1075 this._element = element;
1078 WebInspector.UpgradeFileSystemDropTarget.dragAndDropFilesType = "Files";
1080 WebInspector.UpgradeFileSystemDropTarget.prototype = {
1081 _onDragEnter: function (event)
1083 if (event.dataTransfer.types.indexOf(WebInspector.UpgradeFileSystemDropTarget.dragAndDropFilesType) === -1)
1085 event.consume(true);
1088 _onDragOver: function (event)
1090 if (event.dataTransfer.types.indexOf(WebInspector.UpgradeFileSystemDropTarget.dragAndDropFilesType) === -1)
1092 event.dataTransfer.dropEffect = "copy";
1093 event.consume(true);
1094 if (this._dragMaskElement)
1096 this._dragMaskElement = this._element.createChild("div", "fill drag-mask");
1097 this._dragMaskElement.createChild("div", "fill drag-mask-inner").textContent = WebInspector.UIString("Drop workspace folder here");
1098 this._dragMaskElement.addEventListener("drop", this._onDrop.bind(this), true);
1099 this._dragMaskElement.addEventListener("dragleave", this._onDragLeave.bind(this), true);
1102 _onDrop: function (event)
1104 event.consume(true);
1106 var items = /** @type {!Array.<!DataTransferItem>} */ (event.dataTransfer.items);
1109 var entry = items[0].webkitGetAsEntry();
1110 if (!entry.isDirectory)
1112 InspectorFrontendHost.upgradeDraggedFileSystemPermissions(entry.filesystem);
1115 _onDragLeave: function (event)
1117 event.consume(true);
1121 _removeMask: function ()
1123 this._dragMaskElement.remove();
1124 delete this._dragMaskElement;
1130 * @implements {WebInspector.DrawerEditor}
1132 WebInspector.SourcesPanel.DrawerEditor = function()
1134 this._panel = WebInspector.inspectorView.panel("sources");
1137 WebInspector.SourcesPanel.DrawerEditor.prototype = {
1139 * @return {!WebInspector.View}
1143 return this._panel._drawerEditorView;
1146 installedIntoDrawer: function()
1148 if (this._panel.isShowing())
1149 this._panelWasShown();
1151 this._panelWillHide();
1154 _panelWasShown: function()
1156 WebInspector.inspectorView.setDrawerEditorAvailable(false);
1157 WebInspector.inspectorView.hideDrawerEditor();
1160 _panelWillHide: function()
1162 WebInspector.inspectorView.setDrawerEditorAvailable(true);
1163 if (WebInspector.inspectorView.isDrawerEditorShown())
1164 WebInspector.inspectorView.showDrawerEditor();
1169 WebInspector.inspectorView.showDrawerEditor();
1175 * @extends {WebInspector.VBox}
1177 WebInspector.SourcesPanel.DrawerEditorView = function()
1179 WebInspector.VBox.call(this);
1180 this.element.id = "drawer-editor-view";
1183 WebInspector.SourcesPanel.DrawerEditorView.prototype = {
1184 __proto__: WebInspector.VBox.prototype
1190 * @implements {WebInspector.ContextMenu.Provider}
1192 WebInspector.SourcesPanel.ContextMenuProvider = function()
1196 WebInspector.SourcesPanel.ContextMenuProvider.prototype = {
1198 * @param {!WebInspector.ContextMenu} contextMenu
1199 * @param {!Object} target
1201 appendApplicableItems: function(event, contextMenu, target)
1203 WebInspector.inspectorView.panel("sources").appendApplicableItems(event, contextMenu, target);
1209 * @implements {WebInspector.Revealer}
1211 WebInspector.SourcesPanel.UILocationRevealer = function()
1215 WebInspector.SourcesPanel.UILocationRevealer.prototype = {
1217 * @param {!Object} uiLocation
1219 reveal: function(uiLocation)
1221 if (uiLocation instanceof WebInspector.UILocation)
1222 /** @type {!WebInspector.SourcesPanel} */ (WebInspector.inspectorView.panel("sources")).showUILocation(uiLocation);
1228 * @implements {WebInspector.ActionDelegate}
1230 WebInspector.SourcesPanel.ShowGoToSourceDialogActionDelegate = function() {}
1232 WebInspector.SourcesPanel.ShowGoToSourceDialogActionDelegate.prototype = {
1236 handleAction: function()
1238 /** @type {!WebInspector.SourcesPanel} */ (WebInspector.inspectorView.showPanel("sources")).showGoToSourceDialog();