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("StyleSheetOutlineDialog.js");
41 importScript("TabbedEditorContainer.js");
42 importScript("WatchExpressionsSidebarPane.js");
43 importScript("WorkersSidebarPane.js");
44 importScript("ThreadsToolbar.js");
45 importScript("ScriptFormatterEditorAction.js");
46 importScript("InplaceFormatterEditorAction.js");
47 importScript("ScriptFormatter.js");
48 importScript("SourcesView.js");
52 * @implements {WebInspector.ContextMenu.Provider}
53 * @extends {WebInspector.Panel}
54 * @param {!WebInspector.Workspace=} workspaceForTest
56 WebInspector.SourcesPanel = function(workspaceForTest)
58 WebInspector.Panel.call(this, "sources");
59 this.registerRequiredCSS("sourcesPanel.css");
60 this.registerRequiredCSS("suggestBox.css");
61 new WebInspector.UpgradeFileSystemDropTarget(this.element);
63 WebInspector.settings.showEditorInDrawer = WebInspector.settings.createSetting("showEditorInDrawer", true);
65 this._workspace = workspaceForTest || WebInspector.workspace;
67 var helpSection = WebInspector.shortcutsScreen.section(WebInspector.UIString("Sources Panel"));
68 this.debugToolbar = this._createDebugToolbar();
69 this._debugToolbarDrawer = this._createDebugToolbarDrawer();
70 this.threadsToolbar = new WebInspector.ThreadsToolbar();
72 const initialDebugSidebarWidth = 225;
73 this._splitView = new WebInspector.SplitView(true, true, "sourcesPanelSplitViewState", initialDebugSidebarWidth);
74 this._splitView.enableShowModeSaving();
75 this._splitView.show(this.element);
77 // Create scripts navigator
78 const initialNavigatorWidth = 225;
79 this.editorView = new WebInspector.SplitView(true, false, "sourcesPanelNavigatorSplitViewState", initialNavigatorWidth);
80 this.editorView.enableShowModeSaving();
81 this.editorView.element.id = "scripts-editor-split-view";
82 this.editorView.element.tabIndex = 0;
83 this.editorView.show(this._splitView.mainElement());
85 this._navigator = new WebInspector.SourcesNavigator(this._workspace);
86 this._navigator.view.setMinimumSize(Preferences.minSidebarWidth, 25);
87 this._navigator.view.show(this.editorView.sidebarElement());
88 this._navigator.addEventListener(WebInspector.SourcesNavigator.Events.SourceSelected, this._sourceSelected, this);
89 this._navigator.addEventListener(WebInspector.SourcesNavigator.Events.SourceRenamed, this._sourceRenamed, this);
91 this._sourcesView = new WebInspector.SourcesView(this._workspace, this);
92 this._sourcesView.addEventListener(WebInspector.SourcesView.Events.EditorSelected, this._editorSelected.bind(this));
93 this._sourcesView.addEventListener(WebInspector.SourcesView.Events.EditorClosed, this._editorClosed.bind(this));
94 this._sourcesView.registerShortcuts(this.registerShortcuts.bind(this));
96 if (WebInspector.experimentsSettings.showEditorInDrawer.isEnabled()) {
97 this._drawerEditorView = new WebInspector.SourcesPanel.DrawerEditorView();
98 this._sourcesView.show(this._drawerEditorView.element);
100 this._sourcesView.show(this.editorView.mainElement());
103 this._debugSidebarResizeWidgetElement = document.createElementWithClass("div", "resizer-widget");
104 this._debugSidebarResizeWidgetElement.id = "scripts-debug-sidebar-resizer-widget";
105 this._splitView.addEventListener(WebInspector.SplitView.Events.ShowModeChanged, this._updateDebugSidebarResizeWidget, this);
106 this._updateDebugSidebarResizeWidget();
107 this._splitView.installResizer(this._debugSidebarResizeWidgetElement);
109 this.sidebarPanes = {};
110 this.sidebarPanes.watchExpressions = new WebInspector.WatchExpressionsSidebarPane();
111 this.sidebarPanes.callstack = new WebInspector.CallStackSidebarPane();
112 this.sidebarPanes.callstack.addEventListener(WebInspector.CallStackSidebarPane.Events.CallFrameSelected, this._callFrameSelectedInSidebar.bind(this));
113 this.sidebarPanes.callstack.addEventListener(WebInspector.CallStackSidebarPane.Events.CallFrameRestarted, this._callFrameRestartedInSidebar.bind(this));
114 this.sidebarPanes.callstack.registerShortcuts(this.registerShortcuts.bind(this));
116 this.sidebarPanes.scopechain = new WebInspector.ScopeChainSidebarPane();
117 this.sidebarPanes.jsBreakpoints = new WebInspector.JavaScriptBreakpointsSidebarPane(WebInspector.debuggerModel, WebInspector.breakpointManager, this.showUISourceCode.bind(this));
118 this.sidebarPanes.domBreakpoints = WebInspector.domBreakpointsSidebarPane.createProxy(this);
119 this.sidebarPanes.xhrBreakpoints = new WebInspector.XHRBreakpointsSidebarPane();
120 this.sidebarPanes.eventListenerBreakpoints = new WebInspector.EventListenerBreakpointsSidebarPane();
122 if (Capabilities.isMainFrontend)
123 this.sidebarPanes.workerList = new WebInspector.WorkersSidebarPane();
125 this._extensionSidebarPanes = [];
127 this._installDebuggerSidebarController();
129 WebInspector.dockController.addEventListener(WebInspector.DockController.Events.DockSideChanged, this._dockSideChanged.bind(this));
130 WebInspector.settings.splitVerticallyWhenDockedToRight.addChangeListener(this._dockSideChanged.bind(this));
131 this._dockSideChanged();
133 this._updateDebuggerButtons();
134 this._pauseOnExceptionEnabledChanged();
135 if (WebInspector.debuggerModel.isPaused())
136 this._showDebuggerPausedDetails(WebInspector.debuggerModel.debuggerPausedDetails());
138 WebInspector.settings.pauseOnExceptionEnabled.addChangeListener(this._pauseOnExceptionEnabledChanged, this);
139 WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerWasEnabled, this._debuggerWasEnabled, this);
140 WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerWasDisabled, this._debuggerWasDisabled, this);
141 WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
142 WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerResumed, this._debuggerResumed, this);
143 WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.CallFrameSelected, this._callFrameSelected, this);
144 WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.ConsoleCommandEvaluatedInSelectedCallFrame, this._consoleCommandEvaluatedInSelectedCallFrame, this);
145 WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointsActiveStateChanged, this._breakpointsActiveStateChanged, this);
146 WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.GlobalObjectCleared, this._debuggerReset, this);
149 WebInspector.SourcesPanel.minToolbarWidth = 215;
151 WebInspector.SourcesPanel.prototype = {
155 defaultFocusedElement: function()
157 return this._sourcesView.defaultFocusedElement() || this._navigator.view.defaultFocusedElement();
166 * @return {!WebInspector.SourcesPanel.DrawerEditor}
168 _drawerEditor: function()
170 var drawerEditorInstance = WebInspector.moduleManager.instance(WebInspector.DrawerEditor);
171 console.assert(drawerEditorInstance instanceof WebInspector.SourcesPanel.DrawerEditor, "WebInspector.DrawerEditor module instance does not use WebInspector.SourcesPanel.DrawerEditor as an implementation. ");
172 return /** @type {!WebInspector.SourcesPanel.DrawerEditor} */ (drawerEditorInstance);
177 if (WebInspector.experimentsSettings.showEditorInDrawer.isEnabled()) {
178 this._drawerEditor()._panelWasShown();
179 this._sourcesView.show(this.editorView.mainElement());
181 WebInspector.Panel.prototype.wasShown.call(this);
186 WebInspector.Panel.prototype.willHide.call(this);
187 if (WebInspector.experimentsSettings.showEditorInDrawer.isEnabled()) {
188 this._drawerEditor()._panelWillHide();
189 this._sourcesView.show(this._drawerEditorView.element);
194 * @return {!WebInspector.SearchableView}
196 searchableView: function()
198 return this._sourcesView.searchableView();
201 _consoleCommandEvaluatedInSelectedCallFrame: function(event)
203 this.sidebarPanes.scopechain.update(WebInspector.debuggerModel.selectedCallFrame());
207 * @param {!WebInspector.Event} event
209 _debuggerPaused: function(event)
211 var details = /** @type {!WebInspector.DebuggerPausedDetails} */ (event.data);
212 WebInspector.inspectorView.setCurrentPanel(this);
213 this._showDebuggerPausedDetails(details);
217 * @param {?WebInspector.DebuggerPausedDetails} details
219 _showDebuggerPausedDetails: function(details)
222 this._waitingToPause = false;
224 this._updateDebuggerButtons();
226 this.sidebarPanes.callstack.update(details);
229 * @param {!Element} element
230 * @this {WebInspector.SourcesPanel}
232 function didCreateBreakpointHitStatusMessage(element)
234 this.sidebarPanes.callstack.setStatus(element);
238 * @param {!WebInspector.UILocation} uiLocation
239 * @this {WebInspector.SourcesPanel}
241 function didGetUILocation(uiLocation)
243 var breakpoint = WebInspector.breakpointManager.findBreakpointOnLine(uiLocation.uiSourceCode, uiLocation.lineNumber);
246 this.sidebarPanes.jsBreakpoints.highlightBreakpoint(breakpoint);
247 this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a JavaScript breakpoint."));
250 if (details.reason === WebInspector.DebuggerModel.BreakReason.DOM) {
251 WebInspector.domBreakpointsSidebarPane.highlightBreakpoint(details.auxData);
252 WebInspector.domBreakpointsSidebarPane.createBreakpointHitStatusMessage(details, didCreateBreakpointHitStatusMessage.bind(this));
253 } else if (details.reason === WebInspector.DebuggerModel.BreakReason.EventListener) {
254 var eventName = details.auxData.eventName;
255 this.sidebarPanes.eventListenerBreakpoints.highlightBreakpoint(details.auxData.eventName);
256 var eventNameForUI = WebInspector.EventListenerBreakpointsSidebarPane.eventNameForUI(eventName, details.auxData);
257 this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a \"%s\" Event Listener.", eventNameForUI));
258 } else if (details.reason === WebInspector.DebuggerModel.BreakReason.XHR) {
259 this.sidebarPanes.xhrBreakpoints.highlightBreakpoint(details.auxData["breakpointURL"]);
260 this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a XMLHttpRequest."));
261 } else if (details.reason === WebInspector.DebuggerModel.BreakReason.Exception)
262 this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on exception: '%s'.", details.auxData.description));
263 else if (details.reason === WebInspector.DebuggerModel.BreakReason.Assert)
264 this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on assertion."));
265 else if (details.reason === WebInspector.DebuggerModel.BreakReason.CSPViolation)
266 this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a script blocked due to Content Security Policy directive: \"%s\".", details.auxData["directiveText"]));
267 else if (details.reason === WebInspector.DebuggerModel.BreakReason.DebugCommand)
268 this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a debugged function"));
270 if (details.callFrames.length)
271 details.callFrames[0].createLiveLocation(didGetUILocation.bind(this));
273 console.warn("ScriptsPanel paused, but callFrames.length is zero."); // TODO remove this once we understand this case better
276 this._splitView.showBoth(true);
277 this._toggleDebuggerSidebarButton.setEnabled(false);
279 InspectorFrontendHost.bringToFront();
282 _debuggerResumed: function()
284 this._paused = false;
285 this._waitingToPause = false;
287 this._clearInterface();
288 this._toggleDebuggerSidebarButton.setEnabled(true);
291 _debuggerWasEnabled: function()
293 this._updateDebuggerButtons();
296 _debuggerWasDisabled: function()
298 this._debuggerReset();
301 _debuggerReset: function()
303 this._debuggerResumed();
304 this.sidebarPanes.watchExpressions.reset();
305 delete this._skipExecutionLineRevealing;
309 * @return {!WebInspector.View}
313 return this._sourcesView.visibleView();
317 * @param {!WebInspector.UISourceCode} uiSourceCode
318 * @param {number=} lineNumber
319 * @param {number=} columnNumber
320 * @param {boolean=} forceShowInPanel
322 showUISourceCode: function(uiSourceCode, lineNumber, columnNumber, forceShowInPanel)
324 this._showEditor(forceShowInPanel);
325 this._sourcesView.showSourceLocation(uiSourceCode, lineNumber, columnNumber);
328 _showEditor: function(forceShowInPanel)
330 if (this._sourcesView.isShowing())
333 if (this._shouldShowEditorInDrawer() && !forceShowInPanel)
334 this._drawerEditor()._show();
336 WebInspector.inspectorView.showPanel("sources");
340 * @param {!WebInspector.UILocation} uiLocation
341 * @param {boolean=} forceShowInPanel
343 showUILocation: function(uiLocation, forceShowInPanel)
345 this.showUISourceCode(uiLocation.uiSourceCode, uiLocation.lineNumber, uiLocation.columnNumber, forceShowInPanel);
351 _shouldShowEditorInDrawer: function()
353 return WebInspector.experimentsSettings.showEditorInDrawer.isEnabled() && WebInspector.settings.showEditorInDrawer.get() && WebInspector.inspectorView.isDrawerEditorShown();
357 * @param {!WebInspector.UISourceCode} uiSourceCode
359 _revealInNavigator: function(uiSourceCode)
361 this._navigator.revealUISourceCode(uiSourceCode);
364 _executionLineChanged: function(uiLocation)
366 this._sourcesView.clearCurrentExecutionLine();
367 this._sourcesView.setExecutionLine(uiLocation);
368 if (this._skipExecutionLineRevealing)
370 this._skipExecutionLineRevealing = true;
371 this._sourcesView.showSourceLocation(uiLocation.uiSourceCode, uiLocation.lineNumber, 0, undefined, true);
374 _callFrameSelected: function(event)
376 var callFrame = event.data;
381 this.sidebarPanes.scopechain.update(callFrame);
382 this.sidebarPanes.watchExpressions.refreshExpressions();
383 this.sidebarPanes.callstack.setSelectedCallFrame(callFrame);
384 callFrame.createLiveLocation(this._executionLineChanged.bind(this));
388 * @param {!WebInspector.Event} event
390 _sourceSelected: function(event)
392 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data.uiSourceCode);
393 this._sourcesView.showSourceLocation(uiSourceCode, undefined, undefined, !event.data.focusSource)
397 * @param {!WebInspector.Event} event
399 _sourceRenamed: function(event)
401 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data);
402 this._sourcesView.sourceRenamed(uiSourceCode);
405 _pauseOnExceptionEnabledChanged: function()
407 var enabled = WebInspector.settings.pauseOnExceptionEnabled.get();
408 this._pauseOnExceptionButton.toggled = enabled;
409 this._pauseOnExceptionButton.title = WebInspector.UIString(enabled ? "Don't pause on exceptions." : "Pause on exceptions.");
410 this._debugToolbarDrawer.classList.toggle("expanded", enabled);
413 _updateDebuggerButtons: function()
416 this._updateButtonTitle(this._pauseButton, WebInspector.UIString("Resume script execution (%s)."))
417 this._pauseButton.state = true;
418 this._pauseButton.setLongClickOptionsEnabled((function() { return [ this._longResumeButton ] }).bind(this));
420 this._pauseButton.setEnabled(true);
421 this._stepOverButton.setEnabled(true);
422 this._stepIntoButton.setEnabled(true);
423 this._stepOutButton.setEnabled(true);
425 this._updateButtonTitle(this._pauseButton, WebInspector.UIString("Pause script execution (%s)."))
426 this._pauseButton.state = false;
427 this._pauseButton.setLongClickOptionsEnabled(null);
429 this._pauseButton.setEnabled(!this._waitingToPause);
430 this._stepOverButton.setEnabled(false);
431 this._stepIntoButton.setEnabled(false);
432 this._stepOutButton.setEnabled(false);
436 _clearInterface: function()
438 this.sidebarPanes.callstack.update(null);
439 this.sidebarPanes.scopechain.update(null);
440 this.sidebarPanes.jsBreakpoints.clearBreakpointHighlight();
441 WebInspector.domBreakpointsSidebarPane.clearBreakpointHighlight();
442 this.sidebarPanes.eventListenerBreakpoints.clearBreakpointHighlight();
443 this.sidebarPanes.xhrBreakpoints.clearBreakpointHighlight();
445 this._sourcesView.clearCurrentExecutionLine();
446 this._updateDebuggerButtons();
449 _togglePauseOnExceptions: function()
451 WebInspector.settings.pauseOnExceptionEnabled.set(!this._pauseOnExceptionButton.toggled);
457 _runSnippet: function()
459 var uiSourceCode = this._sourcesView.currentUISourceCode();
460 if (uiSourceCode.project().type() !== WebInspector.projectTypes.Snippets)
463 var currentExecutionContext = WebInspector.context.flavor(WebInspector.ExecutionContext);
464 if (!currentExecutionContext)
467 WebInspector.scriptSnippetModel.evaluateScriptSnippet(currentExecutionContext, uiSourceCode);
472 * @param {!WebInspector.Event} event
474 _editorSelected: function(event)
476 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data);
477 this._editorChanged(uiSourceCode);
481 * @param {!WebInspector.Event} event
483 _editorClosed: function(event)
485 var wasSelected = /** @type {boolean} */ (event.data.wasSelected);
487 this._editorChanged(null);
491 * @param {?WebInspector.UISourceCode} uiSourceCode
493 _editorChanged: function(uiSourceCode)
495 var isSnippet = uiSourceCode && uiSourceCode.project().type() === WebInspector.projectTypes.Snippets;
496 this._runSnippetButton.element.classList.toggle("hidden", !isSnippet);
502 togglePause: function()
505 delete this._skipExecutionLineRevealing;
506 this._paused = false;
507 this._waitingToPause = false;
508 WebInspector.debuggerModel.resume();
510 this._waitingToPause = true;
511 // Make sure pauses didn't stick skipped.
512 WebInspector.debuggerModel.skipAllPauses(false);
513 DebuggerAgent.pause();
516 this._clearInterface();
523 _longResume: function()
528 this._paused = false;
529 this._waitingToPause = false;
530 WebInspector.debuggerModel.skipAllPausesUntilReloadOrTimeout(500);
531 WebInspector.debuggerModel.resume();
533 this._clearInterface();
540 _stepOverClicked: function()
545 delete this._skipExecutionLineRevealing;
546 this._paused = false;
548 this._clearInterface();
550 WebInspector.debuggerModel.stepOver();
557 _stepIntoClicked: function()
562 delete this._skipExecutionLineRevealing;
563 this._paused = false;
565 this._clearInterface();
567 WebInspector.debuggerModel.stepInto();
574 _stepOutClicked: function()
579 delete this._skipExecutionLineRevealing;
580 this._paused = false;
582 this._clearInterface();
584 WebInspector.debuggerModel.stepOut();
589 * @param {!WebInspector.Event} event
591 _callFrameSelectedInSidebar: function(event)
593 var callFrame = /** @type {!WebInspector.DebuggerModel.CallFrame} */ (event.data);
594 delete this._skipExecutionLineRevealing;
595 WebInspector.debuggerModel.setSelectedCallFrame(callFrame);
598 _callFrameRestartedInSidebar: function()
600 delete this._skipExecutionLineRevealing;
604 * @param {!WebInspector.DebuggerModel.Location} rawLocation
606 continueToLocation: function(rawLocation)
611 delete this._skipExecutionLineRevealing;
612 this._paused = false;
613 this._clearInterface();
614 rawLocation.continueToLocation();
617 _toggleBreakpointsClicked: function(event)
619 WebInspector.debuggerModel.setBreakpointsActive(!WebInspector.debuggerModel.breakpointsActive());
622 _breakpointsActiveStateChanged: function(event)
624 var active = event.data;
625 this._toggleBreakpointsButton.toggled = !active;
626 this.sidebarPanes.jsBreakpoints.listElement.classList.toggle("breakpoints-list-deactivated", !active);
627 this._sourcesView.toggleBreakpointsActiveState(active);
629 this._toggleBreakpointsButton.title = WebInspector.UIString("Deactivate breakpoints.");
631 this._toggleBreakpointsButton.title = WebInspector.UIString("Activate breakpoints.");
634 _createDebugToolbar: function()
636 var debugToolbar = document.createElement("div");
637 debugToolbar.className = "scripts-debug-toolbar";
640 var platformSpecificModifier = WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta;
643 title = WebInspector.UIString("Run snippet (%s).");
644 handler = this._runSnippet.bind(this);
645 this._runSnippetButton = this._createButtonAndRegisterShortcuts("scripts-run-snippet", title, handler, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.RunSnippet);
646 debugToolbar.appendChild(this._runSnippetButton.element);
647 this._runSnippetButton.element.classList.add("hidden");
650 handler = this.togglePause.bind(this);
651 this._pauseButton = this._createButtonAndRegisterShortcuts("scripts-pause", "", handler, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.PauseContinue);
652 debugToolbar.appendChild(this._pauseButton.element);
655 title = WebInspector.UIString("Resume with all pauses blocked for 500 ms");
656 this._longResumeButton = new WebInspector.StatusBarButton(title, "scripts-long-resume");
657 this._longResumeButton.addEventListener("click", this._longResume.bind(this), this);
660 title = WebInspector.UIString("Step over next function call (%s).");
661 handler = this._stepOverClicked.bind(this);
662 this._stepOverButton = this._createButtonAndRegisterShortcuts("scripts-step-over", title, handler, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.StepOver);
663 debugToolbar.appendChild(this._stepOverButton.element);
666 title = WebInspector.UIString("Step into next function call (%s).");
667 handler = this._stepIntoClicked.bind(this);
668 this._stepIntoButton = this._createButtonAndRegisterShortcuts("scripts-step-into", title, handler, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.StepInto);
669 debugToolbar.appendChild(this._stepIntoButton.element);
672 title = WebInspector.UIString("Step out of current function (%s).");
673 handler = this._stepOutClicked.bind(this);
674 this._stepOutButton = this._createButtonAndRegisterShortcuts("scripts-step-out", title, handler, WebInspector.ShortcutsScreen.SourcesPanelShortcuts.StepOut);
675 debugToolbar.appendChild(this._stepOutButton.element);
677 // Toggle Breakpoints
678 this._toggleBreakpointsButton = new WebInspector.StatusBarButton(WebInspector.UIString("Deactivate breakpoints."), "scripts-toggle-breakpoints");
679 this._toggleBreakpointsButton.toggled = false;
680 this._toggleBreakpointsButton.addEventListener("click", this._toggleBreakpointsClicked, this);
681 debugToolbar.appendChild(this._toggleBreakpointsButton.element);
683 // Pause on Exception
684 this._pauseOnExceptionButton = new WebInspector.StatusBarButton("", "scripts-pause-on-exceptions-status-bar-item");
685 this._pauseOnExceptionButton.addEventListener("click", this._togglePauseOnExceptions, this);
686 debugToolbar.appendChild(this._pauseOnExceptionButton.element);
691 _createDebugToolbarDrawer: function()
693 var debugToolbarDrawer = document.createElement("div");
694 debugToolbarDrawer.className = "scripts-debug-toolbar-drawer";
696 var label = WebInspector.UIString("Pause On Caught Exceptions");
697 var setting = WebInspector.settings.pauseOnCaughtException;
698 debugToolbarDrawer.appendChild(WebInspector.SettingsUI.createSettingCheckbox(label, setting, true));
700 return debugToolbarDrawer;
704 * @param {!WebInspector.StatusBarButton} button
705 * @param {string} buttonTitle
707 _updateButtonTitle: function(button, buttonTitle)
709 var hasShortcuts = button.shortcuts && button.shortcuts.length;
711 button.title = String.vsprintf(buttonTitle, [button.shortcuts[0].name]);
713 button.title = buttonTitle;
717 * @param {string} buttonId
718 * @param {string} buttonTitle
719 * @param {function(?Event=):boolean} handler
720 * @param {!Array.<!WebInspector.KeyboardShortcut.Descriptor>} shortcuts
721 * @return {!WebInspector.StatusBarButton}
723 _createButtonAndRegisterShortcuts: function(buttonId, buttonTitle, handler, shortcuts)
725 var button = new WebInspector.StatusBarButton(buttonTitle, buttonId);
726 button.element.addEventListener("click", handler, false);
727 button.shortcuts = shortcuts;
728 this._updateButtonTitle(button, buttonTitle);
729 this.registerShortcuts(shortcuts, handler);
733 addToWatch: function(expression)
735 this.sidebarPanes.watchExpressions.addExpression(expression);
738 _installDebuggerSidebarController: function()
740 this._toggleNavigatorSidebarButton = this.editorView.createShowHideSidebarButton("navigator", "scripts-navigator-show-hide-button");
741 this.editorView.mainElement().appendChild(this._toggleNavigatorSidebarButton.element);
743 this._toggleDebuggerSidebarButton = this._splitView.createShowHideSidebarButton("debugger", "scripts-debugger-show-hide-button");
745 this._splitView.mainElement().appendChild(this._toggleDebuggerSidebarButton.element);
746 this._splitView.mainElement().appendChild(this._debugSidebarResizeWidgetElement);
749 _updateDebugSidebarResizeWidget: function()
751 this._debugSidebarResizeWidgetElement.classList.toggle("hidden", this._splitView.showMode() !== WebInspector.SplitView.ShowMode.Both);
755 * @param {!WebInspector.UISourceCode} uiSourceCode
757 _showLocalHistory: function(uiSourceCode)
759 WebInspector.RevisionHistoryView.showHistory(uiSourceCode);
763 * @param {!WebInspector.ContextMenu} contextMenu
764 * @param {!Object} target
766 appendApplicableItems: function(event, contextMenu, target)
768 this._appendUISourceCodeItems(event, contextMenu, target);
769 this._appendRemoteObjectItems(contextMenu, target);
772 _suggestReload: function()
774 if (window.confirm(WebInspector.UIString("It is recommended to restart inspector after making these changes. Would you like to restart it?")))
775 WebInspector.reload();
779 * @param {!WebInspector.UISourceCode} uiSourceCode
781 _mapFileSystemToNetwork: function(uiSourceCode)
783 WebInspector.SelectUISourceCodeForProjectTypesDialog.show(uiSourceCode.name(), [WebInspector.projectTypes.Network, WebInspector.projectTypes.ContentScripts], mapFileSystemToNetwork.bind(this), this.editorView.mainElement())
786 * @param {!WebInspector.UISourceCode} networkUISourceCode
787 * @this {WebInspector.SourcesPanel}
789 function mapFileSystemToNetwork(networkUISourceCode)
791 this._workspace.addMapping(networkUISourceCode, uiSourceCode, WebInspector.fileSystemWorkspaceBinding);
792 this._suggestReload();
797 * @param {!WebInspector.UISourceCode} uiSourceCode
799 _removeNetworkMapping: function(uiSourceCode)
801 if (confirm(WebInspector.UIString("Are you sure you want to remove network mapping?"))) {
802 this._workspace.removeMapping(uiSourceCode);
803 this._suggestReload();
808 * @param {!WebInspector.UISourceCode} networkUISourceCode
810 _mapNetworkToFileSystem: function(networkUISourceCode)
812 WebInspector.SelectUISourceCodeForProjectTypesDialog.show(networkUISourceCode.name(), [WebInspector.projectTypes.FileSystem], mapNetworkToFileSystem.bind(this), this.editorView.mainElement())
815 * @param {!WebInspector.UISourceCode} uiSourceCode
816 * @this {WebInspector.SourcesPanel}
818 function mapNetworkToFileSystem(uiSourceCode)
820 this._workspace.addMapping(networkUISourceCode, uiSourceCode, WebInspector.fileSystemWorkspaceBinding);
821 this._suggestReload();
826 * @param {!WebInspector.ContextMenu} contextMenu
827 * @param {!WebInspector.UISourceCode} uiSourceCode
829 _appendUISourceCodeMappingItems: function(contextMenu, uiSourceCode)
831 if (uiSourceCode.project().type() === WebInspector.projectTypes.FileSystem) {
832 var hasMappings = !!uiSourceCode.url;
834 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Map to network resource\u2026" : "Map to Network Resource\u2026"), this._mapFileSystemToNetwork.bind(this, uiSourceCode));
836 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove network mapping" : "Remove Network Mapping"), this._removeNetworkMapping.bind(this, uiSourceCode));
840 * @param {!WebInspector.Project} project
842 function filterProject(project)
844 return project.type() === WebInspector.projectTypes.FileSystem;
847 if (uiSourceCode.project().type() === WebInspector.projectTypes.Network || uiSourceCode.project().type() === WebInspector.projectTypes.ContentScripts) {
848 if (!this._workspace.projects().filter(filterProject).length)
850 if (this._workspace.uiSourceCodeForURL(uiSourceCode.url) === uiSourceCode)
851 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Map to file system resource\u2026" : "Map to File System Resource\u2026"), this._mapNetworkToFileSystem.bind(this, uiSourceCode));
856 * @param {!Event} event
857 * @param {!WebInspector.ContextMenu} contextMenu
858 * @param {!Object} target
860 _appendUISourceCodeItems: function(event, contextMenu, target)
862 if (!(target instanceof WebInspector.UISourceCode))
865 var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (target);
866 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Local modifications\u2026" : "Local Modifications\u2026"), this._showLocalHistory.bind(this, uiSourceCode));
867 this._appendUISourceCodeMappingItems(contextMenu, uiSourceCode);
869 if (!event.target.isSelfOrDescendant(this.editorView.sidebarElement())) {
870 contextMenu.appendSeparator();
871 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Reveal in navigator" : "Reveal in Navigator"), this._handleContextMenuReveal.bind(this, uiSourceCode));
876 * @param {!WebInspector.UISourceCode} uiSourceCode
878 _handleContextMenuReveal: function(uiSourceCode)
880 this.editorView.showBoth();
881 this._revealInNavigator(uiSourceCode);
885 * @param {!WebInspector.ContextMenu} contextMenu
886 * @param {!Object} target
888 _appendRemoteObjectItems: function(contextMenu, target)
890 if (!(target instanceof WebInspector.RemoteObject))
892 var remoteObject = /** @type {!WebInspector.RemoteObject} */ (target);
893 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Store as global variable" : "Store as Global Variable"), this._saveToTempVariable.bind(this, remoteObject));
894 if (remoteObject.type === "function")
895 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Show function definition" : "Show Function Definition"), this._showFunctionDefinition.bind(this, remoteObject));
899 * @param {!WebInspector.RemoteObject} remoteObject
901 _saveToTempVariable: function(remoteObject)
903 var currentExecutionContext = WebInspector.context.flavor(WebInspector.ExecutionContext);
904 if (!currentExecutionContext)
907 currentExecutionContext.evaluate("window", "", false, true, false, false, didGetGlobalObject.bind(null, currentExecutionContext.target()));
909 * @param {!WebInspector.Target} target
910 * @param {?WebInspector.RemoteObject} global
911 * @param {boolean=} wasThrown
913 function didGetGlobalObject(target, global, wasThrown)
916 * @suppressReceiverCheck
919 function remoteFunction(value)
923 while ((prefix + index) in this)
925 var name = prefix + index;
930 if (wasThrown || !global)
931 failedToSave(target, global);
933 global.callFunction(remoteFunction, [WebInspector.RemoteObject.toCallArgument(remoteObject)], didSave.bind(null, global));
937 * @param {!WebInspector.RemoteObject} global
938 * @param {?WebInspector.RemoteObject} result
939 * @param {boolean=} wasThrown
941 function didSave(global, result, wasThrown)
943 var currentExecutionContext = WebInspector.context.flavor(WebInspector.ExecutionContext);
945 if (!currentExecutionContext || wasThrown || !result || result.type !== "string")
946 failedToSave(global.target(), result);
948 WebInspector.ConsoleModel.evaluateCommandInConsole(currentExecutionContext, result.value);
952 * @param {!WebInspector.Target} target
953 * @param {?WebInspector.RemoteObject} result
955 function failedToSave(target, result)
957 var message = WebInspector.UIString("Failed to save to temp variable.");
959 message += " " + result.description;
962 target.consoleModel.showErrorMessage(message)
967 * @param {!WebInspector.RemoteObject} remoteObject
969 _showFunctionDefinition: function(remoteObject)
972 * @param {?Protocol.Error} error
973 * @param {!DebuggerAgent.FunctionDetails} response
974 * @this {WebInspector.SourcesPanel}
976 function didGetFunctionDetails(error, response)
979 console.error(error);
983 var uiLocation = WebInspector.debuggerModel.rawLocationToUILocation(response.location);
987 this.showUILocation(uiLocation, true);
989 DebuggerAgent.getFunctionDetails(remoteObject.objectId, didGetFunctionDetails.bind(this));
992 showGoToSourceDialog: function()
994 this._sourcesView.showOpenResourceDialog();
997 _dockSideChanged: function()
999 var vertically = WebInspector.dockController.isVertical() && WebInspector.settings.splitVerticallyWhenDockedToRight.get();
1000 this._splitVertically(vertically);
1004 * @param {boolean} vertically
1006 _splitVertically: function(vertically)
1008 if (this.sidebarPaneView && vertically === !this._splitView.isVertical())
1011 if (this.sidebarPaneView)
1012 this.sidebarPaneView.detach();
1014 this._splitView.setVertical(!vertically);
1017 this._splitView.uninstallResizer(this._sourcesView.statusBarContainerElement());
1019 this._splitView.installResizer(this._sourcesView.statusBarContainerElement());
1021 // Create vertical box with stack.
1022 var vbox = new WebInspector.VBox();
1023 vbox.element.appendChild(this._debugToolbarDrawer);
1024 vbox.element.appendChild(this.debugToolbar);
1025 vbox.element.appendChild(this.threadsToolbar.element);
1026 vbox.setMinimumAndPreferredSizes(25, 25, WebInspector.SourcesPanel.minToolbarWidth, 100);
1027 var sidebarPaneStack = new WebInspector.SidebarPaneStack();
1028 sidebarPaneStack.element.classList.add("flex-auto");
1029 sidebarPaneStack.show(vbox.element);
1032 // Populate the only stack.
1033 for (var pane in this.sidebarPanes)
1034 sidebarPaneStack.addPane(this.sidebarPanes[pane]);
1035 this._extensionSidebarPanesContainer = sidebarPaneStack;
1037 this.sidebarPaneView = vbox;
1039 var splitView = new WebInspector.SplitView(true, true, "sourcesPanelDebuggerSidebarSplitViewState", 0.5);
1040 vbox.show(splitView.mainElement());
1042 // Populate the left stack.
1043 sidebarPaneStack.addPane(this.sidebarPanes.callstack);
1044 sidebarPaneStack.addPane(this.sidebarPanes.jsBreakpoints);
1045 sidebarPaneStack.addPane(this.sidebarPanes.domBreakpoints);
1046 sidebarPaneStack.addPane(this.sidebarPanes.xhrBreakpoints);
1047 sidebarPaneStack.addPane(this.sidebarPanes.eventListenerBreakpoints);
1048 if (this.sidebarPanes.workerList)
1049 sidebarPaneStack.addPane(this.sidebarPanes.workerList);
1051 var tabbedPane = new WebInspector.SidebarTabbedPane();
1052 tabbedPane.show(splitView.sidebarElement());
1053 tabbedPane.addPane(this.sidebarPanes.scopechain);
1054 tabbedPane.addPane(this.sidebarPanes.watchExpressions);
1055 this._extensionSidebarPanesContainer = tabbedPane;
1057 this.sidebarPaneView = splitView;
1059 for (var i = 0; i < this._extensionSidebarPanes.length; ++i)
1060 this._extensionSidebarPanesContainer.addPane(this._extensionSidebarPanes[i]);
1062 this.sidebarPaneView.show(this._splitView.sidebarElement());
1064 this.sidebarPanes.scopechain.expand();
1065 this.sidebarPanes.jsBreakpoints.expand();
1066 this.sidebarPanes.callstack.expand();
1068 if (WebInspector.settings.watchExpressions.get().length > 0)
1069 this.sidebarPanes.watchExpressions.expand();
1073 * @param {string} id
1074 * @param {!WebInspector.SidebarPane} pane
1076 addExtensionSidebarPane: function(id, pane)
1078 this._extensionSidebarPanes.push(pane);
1079 this._extensionSidebarPanesContainer.addPane(pane);
1080 this.setHideOnDetach();
1084 * @return {!WebInspector.SourcesView}
1086 sourcesView: function()
1088 return this._sourcesView;
1091 __proto__: WebInspector.Panel.prototype
1096 * @param {!Element} element
1098 WebInspector.UpgradeFileSystemDropTarget = function(element)
1100 element.addEventListener("dragenter", this._onDragEnter.bind(this), true);
1101 element.addEventListener("dragover", this._onDragOver.bind(this), true);
1102 this._element = element;
1105 WebInspector.UpgradeFileSystemDropTarget.dragAndDropFilesType = "Files";
1107 WebInspector.UpgradeFileSystemDropTarget.prototype = {
1108 _onDragEnter: function (event)
1110 if (event.dataTransfer.types.indexOf(WebInspector.UpgradeFileSystemDropTarget.dragAndDropFilesType) === -1)
1112 event.consume(true);
1115 _onDragOver: function (event)
1117 if (event.dataTransfer.types.indexOf(WebInspector.UpgradeFileSystemDropTarget.dragAndDropFilesType) === -1)
1119 event.dataTransfer.dropEffect = "copy";
1120 event.consume(true);
1121 if (this._dragMaskElement)
1123 this._dragMaskElement = this._element.createChild("div", "fill drag-mask");
1124 this._dragMaskElement.createChild("div", "fill drag-mask-inner").textContent = WebInspector.UIString("Drop workspace folder here");
1125 this._dragMaskElement.addEventListener("drop", this._onDrop.bind(this), true);
1126 this._dragMaskElement.addEventListener("dragleave", this._onDragLeave.bind(this), true);
1129 _onDrop: function (event)
1131 event.consume(true);
1133 var items = /** @type {!Array.<!DataTransferItem>} */ (event.dataTransfer.items);
1136 var entry = items[0].webkitGetAsEntry();
1137 if (!entry.isDirectory)
1139 InspectorFrontendHost.upgradeDraggedFileSystemPermissions(entry.filesystem);
1142 _onDragLeave: function (event)
1144 event.consume(true);
1148 _removeMask: function ()
1150 this._dragMaskElement.remove();
1151 delete this._dragMaskElement;
1157 * @implements {WebInspector.DrawerEditor}
1159 WebInspector.SourcesPanel.DrawerEditor = function()
1161 this._panel = WebInspector.inspectorView.panel("sources");
1164 WebInspector.SourcesPanel.DrawerEditor.prototype = {
1166 * @return {!WebInspector.View}
1170 return this._panel._drawerEditorView;
1173 installedIntoDrawer: function()
1175 if (this._panel.isShowing())
1176 this._panelWasShown();
1178 this._panelWillHide();
1181 _panelWasShown: function()
1183 WebInspector.inspectorView.setDrawerEditorAvailable(false);
1184 WebInspector.inspectorView.hideDrawerEditor();
1187 _panelWillHide: function()
1189 WebInspector.inspectorView.setDrawerEditorAvailable(true);
1190 if (WebInspector.inspectorView.isDrawerEditorShown())
1191 WebInspector.inspectorView.showDrawerEditor();
1196 WebInspector.inspectorView.showDrawerEditor();
1202 * @extends {WebInspector.VBox}
1204 WebInspector.SourcesPanel.DrawerEditorView = function()
1206 WebInspector.VBox.call(this);
1207 this.element.id = "drawer-editor-view";
1210 WebInspector.SourcesPanel.DrawerEditorView.prototype = {
1211 __proto__: WebInspector.VBox.prototype
1217 * @implements {WebInspector.ContextMenu.Provider}
1219 WebInspector.SourcesPanel.ContextMenuProvider = function()
1223 WebInspector.SourcesPanel.ContextMenuProvider.prototype = {
1225 * @param {!WebInspector.ContextMenu} contextMenu
1226 * @param {!Object} target
1228 appendApplicableItems: function(event, contextMenu, target)
1230 WebInspector.inspectorView.panel("sources").appendApplicableItems(event, contextMenu, target);
1236 * @implements {WebInspector.Revealer}
1238 WebInspector.SourcesPanel.UILocationRevealer = function()
1242 WebInspector.SourcesPanel.UILocationRevealer.prototype = {
1244 * @param {!Object} uiLocation
1246 reveal: function(uiLocation)
1248 if (uiLocation instanceof WebInspector.UILocation)
1249 /** @type {!WebInspector.SourcesPanel} */ (WebInspector.inspectorView.panel("sources")).showUILocation(uiLocation);
1255 * @implements {WebInspector.Revealer}
1257 WebInspector.SourcesPanel.UISourceCodeRevealer = function()
1261 WebInspector.SourcesPanel.UISourceCodeRevealer.prototype = {
1263 * @param {!Object} uiSourceCode
1265 reveal: function(uiSourceCode)
1267 if (uiSourceCode instanceof WebInspector.UISourceCode)
1268 /** @type {!WebInspector.SourcesPanel} */ (WebInspector.inspectorView.panel("sources")).showUISourceCode(uiSourceCode);
1274 * @implements {WebInspector.ActionDelegate}
1276 WebInspector.SourcesPanel.ShowGoToSourceDialogActionDelegate = function() {}
1278 WebInspector.SourcesPanel.ShowGoToSourceDialogActionDelegate.prototype = {
1282 handleAction: function()
1284 /** @type {!WebInspector.SourcesPanel} */ (WebInspector.inspectorView.showPanel("sources")).showGoToSourceDialog();
1291 * @extends {WebInspector.UISettingDelegate}
1293 WebInspector.SourcesPanel.SkipStackFramePatternSettingDelegate = function()
1295 WebInspector.UISettingDelegate.call(this);
1298 WebInspector.SourcesPanel.SkipStackFramePatternSettingDelegate.prototype = {
1301 * @return {!Element}
1303 settingElement: function()
1305 return WebInspector.SettingsUI.createSettingInputField(WebInspector.UIString("Pattern"), WebInspector.settings.skipStackFramesPattern, false, 1000, "100px", WebInspector.SettingsUI.regexValidator);
1308 __proto__: WebInspector.UISettingDelegate.prototype
1313 * @extends {WebInspector.UISettingDelegate}
1315 WebInspector.SourcesPanel.DisableJavaScriptSettingDelegate = function()
1317 WebInspector.UISettingDelegate.call(this);
1320 WebInspector.SourcesPanel.DisableJavaScriptSettingDelegate.prototype = {
1323 * @return {!Element}
1325 settingElement: function()
1327 var disableJSElement = WebInspector.SettingsUI.createSettingCheckbox(WebInspector.UIString("Disable JavaScript"), WebInspector.settings.javaScriptDisabled);
1328 this._disableJSCheckbox = disableJSElement.getElementsByTagName("input")[0];
1329 WebInspector.settings.javaScriptDisabled.addChangeListener(this._settingChanged, this);
1330 var disableJSInfoParent = this._disableJSCheckbox.parentElement.createChild("span", "monospace");
1331 this._disableJSInfo = disableJSInfoParent.createChild("span", "object-info-state-note hidden");
1332 this._disableJSInfo.title = WebInspector.UIString("JavaScript is blocked on the inspected page (may be disabled in browser settings).");
1334 WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, this._updateScriptDisabledCheckbox, this);
1335 this._updateScriptDisabledCheckbox();
1336 return disableJSElement;
1340 * @param {!WebInspector.Event} event
1342 _settingChanged: function(event)
1344 PageAgent.setScriptExecutionDisabled(event.data, this._updateScriptDisabledCheckbox.bind(this));
1347 _updateScriptDisabledCheckbox: function()
1349 PageAgent.getScriptExecutionStatus(executionStatusCallback.bind(this));
1352 * @param {?Protocol.Error} error
1353 * @param {string} status
1354 * @this {WebInspector.SourcesPanel.DisableJavaScriptSettingDelegate}
1356 function executionStatusCallback(error, status)
1358 if (error || !status)
1361 var forbidden = (status === "forbidden");
1362 var disabled = forbidden || (status === "disabled");
1364 this._disableJSInfo.classList.toggle("hidden", !forbidden);
1365 this._disableJSCheckbox.checked = disabled;
1366 this._disableJSCheckbox.disabled = forbidden;
1370 __proto__: WebInspector.UISettingDelegate.prototype