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("BreakpointsSidebarPane.js"); 28 importScript("CallStackSidebarPane.js"); 29 importScript("FilePathScoreFunction.js"); 30 importScript("FilteredItemSelectionDialog.js"); 31 importScript("UISourceCodeFrame.js"); 32 importScript("JavaScriptSourceFrame.js"); 33 importScript("NavigatorOverlayController.js"); 34 importScript("NavigatorView.js"); 35 importScript("RevisionHistoryView.js"); 36 importScript("ScopeChainSidebarPane.js"); 37 importScript("ScriptsNavigator.js"); 38 importScript("ScriptsSearchScope.js"); 39 importScript("StyleSheetOutlineDialog.js"); 40 importScript("TabbedEditorContainer.js"); 41 importScript("WatchExpressionsSidebarPane.js"); 42 importScript("WorkersSidebarPane.js"); 43 44 /** 45 * @constructor 46 * @implements {WebInspector.TabbedEditorContainerDelegate} 47 * @implements {WebInspector.ContextMenu.Provider} 48 * @extends {WebInspector.Panel} 49 * @param {WebInspector.Workspace=} workspaceForTest 50 */ 51 WebInspector.ScriptsPanel = function(workspaceForTest) 52 { 53 WebInspector.Panel.call(this, "scripts"); 54 this.registerRequiredCSS("scriptsPanel.css"); 55 this.registerRequiredCSS("textPrompt.css"); // Watch Expressions autocomplete. 56 57 WebInspector.settings.navigatorWasOnceHidden = WebInspector.settings.createSetting("navigatorWasOnceHidden", false); 58 WebInspector.settings.debuggerSidebarHidden = WebInspector.settings.createSetting("debuggerSidebarHidden", false); 59 60 this._workspace = workspaceForTest || WebInspector.workspace; 61 62 function viewGetter() 63 { 64 return this.visibleView; 65 } 66 WebInspector.GoToLineDialog.install(this, viewGetter.bind(this)); 67 68 var helpSection = WebInspector.shortcutsScreen.section(WebInspector.UIString("Sources Panel")); 69 this.debugToolbar = this._createDebugToolbar(); 70 71 const initialDebugSidebarWidth = 225; 72 const minimumDebugSidebarWidthPercent = 0.5; 73 this.createSidebarView(this.element, WebInspector.SidebarView.SidebarPosition.End, initialDebugSidebarWidth); 74 this.splitView.element.id = "scripts-split-view"; 75 this.splitView.setSidebarElementConstraints(Preferences.minScriptsSidebarWidth); 76 this.splitView.setMainElementConstraints(minimumDebugSidebarWidthPercent); 77 78 // Create scripts navigator 79 const initialNavigatorWidth = 225; 80 const minimumViewsContainerWidthPercent = 0.5; 81 this.editorView = new WebInspector.SidebarView(WebInspector.SidebarView.SidebarPosition.Start, "scriptsPanelNavigatorSidebarWidth", initialNavigatorWidth); 82 this.editorView.element.tabIndex = 0; 83 84 this.editorView.setSidebarElementConstraints(Preferences.minScriptsSidebarWidth); 85 this.editorView.setMainElementConstraints(minimumViewsContainerWidthPercent); 86 this.editorView.show(this.splitView.mainElement); 87 88 this._navigator = new WebInspector.ScriptsNavigator(); 89 this._navigator.view.show(this.editorView.sidebarElement); 90 91 var tabbedEditorPlaceholderText = WebInspector.isMac() ? WebInspector.UIString("Hit Cmd+O to open a file") : WebInspector.UIString("Hit Ctrl+O to open a file"); 92 93 this._editorContentsElement = this.editorView.mainElement.createChild("div", "fill"); 94 this._editorFooterElement = this.editorView.mainElement.createChild("div", "inspector-footer status-bar hidden"); 95 this._editorContainer = new WebInspector.TabbedEditorContainer(this, "previouslyViewedFiles", tabbedEditorPlaceholderText); 96 this._editorContainer.show(this._editorContentsElement); 97 98 this._navigatorController = new WebInspector.NavigatorOverlayController(this.editorView, this._navigator.view, this._editorContainer.view); 99 100 this._navigator.addEventListener(WebInspector.ScriptsNavigator.Events.ScriptSelected, this._scriptSelected, this); 101 this._navigator.addEventListener(WebInspector.ScriptsNavigator.Events.ItemSearchStarted, this._itemSearchStarted, this); 102 this._navigator.addEventListener(WebInspector.ScriptsNavigator.Events.ItemCreationRequested, this._itemCreationRequested, this); 103 this._navigator.addEventListener(WebInspector.ScriptsNavigator.Events.ItemRenamingRequested, this._itemRenamingRequested, this); 104 105 this._editorContainer.addEventListener(WebInspector.TabbedEditorContainer.Events.EditorSelected, this._editorSelected, this); 106 this._editorContainer.addEventListener(WebInspector.TabbedEditorContainer.Events.EditorClosed, this._editorClosed, this); 107 108 this._debugSidebarResizeWidgetElement = this.splitView.mainElement.createChild("div", "resizer-widget"); 109 this._debugSidebarResizeWidgetElement.id = "scripts-debug-sidebar-resizer-widget"; 110 this.splitView.installResizer(this._debugSidebarResizeWidgetElement); 111 112 this.sidebarPanes = {}; 113 this.sidebarPanes.watchExpressions = new WebInspector.WatchExpressionsSidebarPane(); 114 this.sidebarPanes.callstack = new WebInspector.CallStackSidebarPane(); 115 this.sidebarPanes.scopechain = new WebInspector.ScopeChainSidebarPane(); 116 this.sidebarPanes.jsBreakpoints = new WebInspector.JavaScriptBreakpointsSidebarPane(WebInspector.breakpointManager, this._showSourceLocation.bind(this)); 117 this.sidebarPanes.domBreakpoints = WebInspector.domBreakpointsSidebarPane.createProxy(this); 118 this.sidebarPanes.xhrBreakpoints = new WebInspector.XHRBreakpointsSidebarPane(); 119 this.sidebarPanes.eventListenerBreakpoints = new WebInspector.EventListenerBreakpointsSidebarPane(); 120 121 if (Capabilities.canInspectWorkers && !WebInspector.WorkerManager.isWorkerFrontend()) { 122 WorkerAgent.enable(); 123 this.sidebarPanes.workerList = new WebInspector.WorkersSidebarPane(WebInspector.workerManager); 124 } 125 126 this.sidebarPanes.callstack.registerShortcuts(this.registerShortcuts.bind(this)); 127 this.registerShortcuts(WebInspector.ScriptsPanelDescriptor.ShortcutKeys.GoToMember, this._showOutlineDialog.bind(this)); 128 this.registerShortcuts(WebInspector.ScriptsPanelDescriptor.ShortcutKeys.ToggleBreakpoint, this._toggleBreakpoint.bind(this)); 129 130 this._pauseOnExceptionButton = new WebInspector.StatusBarButton("", "scripts-pause-on-exceptions-status-bar-item", 3); 131 this._pauseOnExceptionButton.addEventListener("click", this._togglePauseOnExceptions, this); 132 133 this._toggleFormatSourceButton = new WebInspector.StatusBarButton(WebInspector.UIString("Pretty print"), "scripts-toggle-pretty-print-status-bar-item"); 134 this._toggleFormatSourceButton.toggled = false; 135 this._toggleFormatSourceButton.addEventListener("click", this._toggleFormatSource, this); 136 137 this._scriptViewStatusBarItemsContainer = document.createElement("div"); 138 this._scriptViewStatusBarItemsContainer.className = "inline-block"; 139 140 this._scriptViewStatusBarTextContainer = document.createElement("div"); 141 this._scriptViewStatusBarTextContainer.className = "inline-block"; 142 143 this._installDebuggerSidebarController(); 144 145 WebInspector.dockController.addEventListener(WebInspector.DockController.Events.DockSideChanged, this._dockSideChanged.bind(this)); 146 WebInspector.settings.splitVerticallyWhenDockedToRight.addChangeListener(this._dockSideChanged.bind(this)); 147 this._dockSideChanged(); 148 149 /** @type {!Map.<!WebInspector.UISourceCode, !WebInspector.SourceFrame>} */ 150 this._sourceFramesByUISourceCode = new Map(); 151 this._updateDebuggerButtons(); 152 this._pauseOnExceptionStateChanged(); 153 if (WebInspector.debuggerModel.isPaused()) 154 this._debuggerPaused(); 155 156 WebInspector.settings.pauseOnExceptionStateString.addChangeListener(this._pauseOnExceptionStateChanged, this); 157 WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerWasEnabled, this._debuggerWasEnabled, this); 158 WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerWasDisabled, this._debuggerWasDisabled, this); 159 WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this); 160 WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerResumed, this._debuggerResumed, this); 161 WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.CallFrameSelected, this._callFrameSelected, this); 162 WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.ConsoleCommandEvaluatedInSelectedCallFrame, this._consoleCommandEvaluatedInSelectedCallFrame, this); 163 WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.ExecutionLineChanged, this._executionLineChanged, this); 164 WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointsActiveStateChanged, this._breakpointsActiveStateChanged, this); 165 166 WebInspector.startBatchUpdate(); 167 this._workspace.uiSourceCodes().forEach(this._addUISourceCode.bind(this)); 168 WebInspector.endBatchUpdate(); 169 170 this._workspace.addEventListener(WebInspector.Workspace.Events.UISourceCodeAdded, this._uiSourceCodeAdded, this); 171 this._workspace.addEventListener(WebInspector.Workspace.Events.UISourceCodeRemoved, this._uiSourceCodeRemoved, this); 172 this._workspace.addEventListener(WebInspector.Workspace.Events.ProjectWillReset, this._projectWillReset.bind(this), this); 173 WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.GlobalObjectCleared, this._debuggerReset, this); 174 175 WebInspector.advancedSearchController.registerSearchScope(new WebInspector.ScriptsSearchScope(this._workspace)); 176 } 177 178 WebInspector.ScriptsPanel.prototype = { 179 get statusBarItems() 180 { 181 return [this._pauseOnExceptionButton.element, this._toggleFormatSourceButton.element, this._scriptViewStatusBarItemsContainer]; 182 }, 183 184 /** 185 * @return {?Element} 186 */ 187 statusBarText: function() 188 { 189 return this._scriptViewStatusBarTextContainer; 190 }, 191 192 defaultFocusedElement: function() 193 { 194 return this._editorContainer.view.defaultFocusedElement() || this._navigator.view.defaultFocusedElement(); 195 }, 196 197 get paused() 198 { 199 return this._paused; 200 }, 201 202 wasShown: function() 203 { 204 WebInspector.Panel.prototype.wasShown.call(this); 205 this._navigatorController.wasShown(); 206 }, 207 208 willHide: function() 209 { 210 WebInspector.Panel.prototype.willHide.call(this); 211 WebInspector.closeViewInDrawer(); 212 }, 213 214 /** 215 * @param {WebInspector.Event} event 216 */ 217 _uiSourceCodeAdded: function(event) 218 { 219 var uiSourceCode = /** @type {WebInspector.UISourceCode} */ (event.data); 220 this._addUISourceCode(uiSourceCode); 221 }, 222 223 /** 224 * @param {WebInspector.UISourceCode} uiSourceCode 225 */ 226 _addUISourceCode: function(uiSourceCode) 227 { 228 if (this._toggleFormatSourceButton.toggled) 229 uiSourceCode.setFormatted(true); 230 if (uiSourceCode.project().isServiceProject()) 231 return; 232 this._navigator.addUISourceCode(uiSourceCode); 233 this._editorContainer.addUISourceCode(uiSourceCode); 234 // Replace debugger script-based uiSourceCode with a network-based one. 235 var currentUISourceCode = this._currentUISourceCode; 236 if (currentUISourceCode && currentUISourceCode.project().isServiceProject() && currentUISourceCode !== uiSourceCode && currentUISourceCode.url === uiSourceCode.url) { 237 this._showFile(uiSourceCode); 238 this._editorContainer.removeUISourceCode(currentUISourceCode); 239 } 240 }, 241 242 _uiSourceCodeRemoved: function(event) 243 { 244 var uiSourceCode = /** @type {WebInspector.UISourceCode} */ (event.data); 245 this._removeUISourceCodes([uiSourceCode]); 246 }, 247 248 /** 249 * @param {Array.<WebInspector.UISourceCode>} uiSourceCodes 250 */ 251 _removeUISourceCodes: function(uiSourceCodes) 252 { 253 for (var i = 0; i < uiSourceCodes.length; ++i) { 254 this._navigator.removeUISourceCode(uiSourceCodes[i]); 255 this._removeSourceFrame(uiSourceCodes[i]); 256 } 257 this._editorContainer.removeUISourceCodes(uiSourceCodes); 258 }, 259 260 _consoleCommandEvaluatedInSelectedCallFrame: function(event) 261 { 262 this.sidebarPanes.scopechain.update(WebInspector.debuggerModel.selectedCallFrame()); 263 }, 264 265 _debuggerPaused: function() 266 { 267 var details = WebInspector.debuggerModel.debuggerPausedDetails(); 268 269 this._paused = true; 270 this._waitingToPause = false; 271 this._stepping = false; 272 273 this._updateDebuggerButtons(); 274 275 WebInspector.inspectorView.setCurrentPanel(this); 276 this.sidebarPanes.callstack.update(details.callFrames); 277 278 if (details.reason === WebInspector.DebuggerModel.BreakReason.DOM) { 279 WebInspector.domBreakpointsSidebarPane.highlightBreakpoint(details.auxData); 280 function didCreateBreakpointHitStatusMessage(element) 281 { 282 this.sidebarPanes.callstack.setStatus(element); 283 } 284 WebInspector.domBreakpointsSidebarPane.createBreakpointHitStatusMessage(details.auxData, didCreateBreakpointHitStatusMessage.bind(this)); 285 } else if (details.reason === WebInspector.DebuggerModel.BreakReason.EventListener) { 286 var eventName = details.auxData.eventName; 287 this.sidebarPanes.eventListenerBreakpoints.highlightBreakpoint(details.auxData.eventName); 288 var eventNameForUI = WebInspector.EventListenerBreakpointsSidebarPane.eventNameForUI(eventName, details.auxData); 289 this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a \"%s\" Event Listener.", eventNameForUI)); 290 } else if (details.reason === WebInspector.DebuggerModel.BreakReason.XHR) { 291 this.sidebarPanes.xhrBreakpoints.highlightBreakpoint(details.auxData["breakpointURL"]); 292 this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a XMLHttpRequest.")); 293 } else if (details.reason === WebInspector.DebuggerModel.BreakReason.Exception) 294 this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on exception: '%s'.", details.auxData.description)); 295 else if (details.reason === WebInspector.DebuggerModel.BreakReason.Assert) 296 this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on assertion.")); 297 else if (details.reason === WebInspector.DebuggerModel.BreakReason.CSPViolation) 298 this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a script blocked due to Content Security Policy directive: \"%s\".", details.auxData["directiveText"])); 299 else if (details.reason === WebInspector.DebuggerModel.BreakReason.DebugCommand) 300 this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a debugged function")); 301 else { 302 function didGetUILocation(uiLocation) 303 { 304 var breakpoint = WebInspector.breakpointManager.findBreakpoint(uiLocation.uiSourceCode, uiLocation.lineNumber); 305 if (!breakpoint) 306 return; 307 this.sidebarPanes.jsBreakpoints.highlightBreakpoint(breakpoint); 308 this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a JavaScript breakpoint.")); 309 } 310 if (details.callFrames.length) 311 details.callFrames[0].createLiveLocation(didGetUILocation.bind(this)); 312 else 313 console.warn("ScriptsPanel paused, but callFrames.length is zero."); // TODO remove this once we understand this case better 314 } 315 316 this._enableDebuggerSidebar(true); 317 this._toggleDebuggerSidebarButton.setEnabled(false); 318 window.focus(); 319 InspectorFrontendHost.bringToFront(); 320 }, 321 322 _debuggerResumed: function() 323 { 324 this._paused = false; 325 this._waitingToPause = false; 326 this._stepping = false; 327 328 this._clearInterface(); 329 this._toggleDebuggerSidebarButton.setEnabled(true); 330 }, 331 332 _debuggerWasEnabled: function() 333 { 334 this._updateDebuggerButtons(); 335 }, 336 337 _debuggerWasDisabled: function() 338 { 339 this._debuggerReset(); 340 }, 341 342 _debuggerReset: function() 343 { 344 this._debuggerResumed(); 345 this.sidebarPanes.watchExpressions.reset(); 346 }, 347 348 _projectWillReset: function(event) 349 { 350 var project = event.data; 351 var uiSourceCodes = project.uiSourceCodes(); 352 this._removeUISourceCodes(uiSourceCodes); 353 if (project.type() === WebInspector.projectTypes.Network) 354 this._editorContainer.reset(); 355 }, 356 357 get visibleView() 358 { 359 return this._editorContainer.visibleView; 360 }, 361 362 _updateScriptViewStatusBarItems: function() 363 { 364 this._scriptViewStatusBarItemsContainer.removeChildren(); 365 this._scriptViewStatusBarTextContainer.removeChildren(); 366 367 var sourceFrame = this.visibleView; 368 if (sourceFrame) { 369 var statusBarItems = sourceFrame.statusBarItems() || []; 370 for (var i = 0; i < statusBarItems.length; ++i) 371 this._scriptViewStatusBarItemsContainer.appendChild(statusBarItems[i]); 372 var statusBarText = sourceFrame.statusBarText(); 373 if (statusBarText) 374 this._scriptViewStatusBarTextContainer.appendChild(statusBarText); 375 } 376 }, 377 378 /** 379 * @param {Element} anchor 380 */ 381 canShowAnchorLocation: function(anchor) 382 { 383 if (WebInspector.debuggerModel.debuggerEnabled() && anchor.uiSourceCode) 384 return true; 385 var uiSourceCode = WebInspector.workspace.uiSourceCodeForURL(anchor.href); 386 if (uiSourceCode) { 387 anchor.uiSourceCode = uiSourceCode; 388 return true; 389 } 390 return false; 391 }, 392 393 /** 394 * @param {Element} anchor 395 */ 396 showAnchorLocation: function(anchor) 397 { 398 this._showSourceLocation(anchor.uiSourceCode, anchor.lineNumber, anchor.columnNumber); 399 }, 400 401 /** 402 * @param {WebInspector.UISourceCode} uiSourceCode 403 * @param {number=} lineNumber 404 * @param {number=} columnNumber 405 */ 406 showUISourceCode: function(uiSourceCode, lineNumber, columnNumber) 407 { 408 this._showSourceLocation(uiSourceCode, lineNumber, columnNumber); 409 }, 410 411 /** 412 * @param {WebInspector.UISourceCode} uiSourceCode 413 * @param {number=} lineNumber 414 * @param {number=} columnNumber 415 */ 416 _showSourceLocation: function(uiSourceCode, lineNumber, columnNumber) 417 { 418 var sourceFrame = this._showFile(uiSourceCode); 419 if (typeof lineNumber === "number") 420 sourceFrame.highlightPosition(lineNumber, columnNumber); 421 sourceFrame.focus(); 422 423 WebInspector.notifications.dispatchEventToListeners(WebInspector.UserMetrics.UserAction, { 424 action: WebInspector.UserMetrics.UserActionNames.OpenSourceLink, 425 url: uiSourceCode.originURL(), 426 lineNumber: lineNumber 427 }); 428 }, 429 430 /** 431 * @param {WebInspector.UISourceCode} uiSourceCode 432 * @return {WebInspector.SourceFrame} 433 */ 434 _showFile: function(uiSourceCode) 435 { 436 var sourceFrame = this._getOrCreateSourceFrame(uiSourceCode); 437 if (this._currentUISourceCode === uiSourceCode) 438 return sourceFrame; 439 this._currentUISourceCode = uiSourceCode; 440 if (!uiSourceCode.project().isServiceProject()) 441 this._navigator.revealUISourceCode(uiSourceCode, true); 442 this._editorContainer.showFile(uiSourceCode); 443 this._updateScriptViewStatusBarItems(); 444 445 if (this._currentUISourceCode.project().type() === WebInspector.projectTypes.Snippets) 446 this._runSnippetButton.element.removeStyleClass("hidden"); 447 else 448 this._runSnippetButton.element.addStyleClass("hidden"); 449 450 return sourceFrame; 451 }, 452 453 /** 454 * @param {WebInspector.UISourceCode} uiSourceCode 455 * @return {WebInspector.SourceFrame} 456 */ 457 _createSourceFrame: function(uiSourceCode) 458 { 459 var sourceFrame; 460 switch (uiSourceCode.contentType()) { 461 case WebInspector.resourceTypes.Script: 462 sourceFrame = new WebInspector.JavaScriptSourceFrame(this, uiSourceCode); 463 break; 464 case WebInspector.resourceTypes.Document: 465 sourceFrame = new WebInspector.JavaScriptSourceFrame(this, uiSourceCode); 466 break; 467 case WebInspector.resourceTypes.Stylesheet: 468 default: 469 sourceFrame = new WebInspector.UISourceCodeFrame(uiSourceCode); 470 break; 471 } 472 this._sourceFramesByUISourceCode.put(uiSourceCode, sourceFrame); 473 return sourceFrame; 474 }, 475 476 /** 477 * @param {WebInspector.UISourceCode} uiSourceCode 478 * @return {WebInspector.SourceFrame} 479 */ 480 _getOrCreateSourceFrame: function(uiSourceCode) 481 { 482 return this._sourceFramesByUISourceCode.get(uiSourceCode) || this._createSourceFrame(uiSourceCode); 483 }, 484 485 /** 486 * @param {WebInspector.UISourceCode} uiSourceCode 487 * @return {WebInspector.SourceFrame} 488 */ 489 viewForFile: function(uiSourceCode) 490 { 491 return this._getOrCreateSourceFrame(uiSourceCode); 492 }, 493 494 /** 495 * @param {WebInspector.UISourceCode} uiSourceCode 496 */ 497 _removeSourceFrame: function(uiSourceCode) 498 { 499 var sourceFrame = this._sourceFramesByUISourceCode.get(uiSourceCode); 500 if (!sourceFrame) 501 return; 502 this._sourceFramesByUISourceCode.remove(uiSourceCode); 503 sourceFrame.dispose(); 504 }, 505 506 _clearCurrentExecutionLine: function() 507 { 508 if (this._executionSourceFrame) 509 this._executionSourceFrame.clearExecutionLine(); 510 delete this._executionSourceFrame; 511 }, 512 513 _executionLineChanged: function(event) 514 { 515 var uiLocation = event.data; 516 517 this._clearCurrentExecutionLine(); 518 if (!uiLocation) 519 return; 520 var sourceFrame = this._getOrCreateSourceFrame(uiLocation.uiSourceCode); 521 sourceFrame.setExecutionLine(uiLocation.lineNumber); 522 this._executionSourceFrame = sourceFrame; 523 }, 524 525 _revealExecutionLine: function(uiLocation) 526 { 527 var uiSourceCode = uiLocation.uiSourceCode; 528 // Some scripts (anonymous and snippets evaluations) are not added to files select by default. 529 if (this._currentUISourceCode && this._currentUISourceCode.scriptFile() && this._currentUISourceCode.scriptFile().isDivergingFromVM()) 530 return; 531 if (this._toggleFormatSourceButton.toggled && !uiSourceCode.formatted()) 532 uiSourceCode.setFormatted(true); 533 var sourceFrame = this._showFile(uiSourceCode); 534 sourceFrame.revealLine(uiLocation.lineNumber); 535 sourceFrame.focus(); 536 }, 537 538 _callFrameSelected: function(event) 539 { 540 var callFrame = event.data; 541 542 if (!callFrame) 543 return; 544 545 this.sidebarPanes.scopechain.update(callFrame); 546 this.sidebarPanes.watchExpressions.refreshExpressions(); 547 this.sidebarPanes.callstack.setSelectedCallFrame(callFrame); 548 callFrame.createLiveLocation(this._revealExecutionLine.bind(this)); 549 }, 550 551 _editorClosed: function(event) 552 { 553 this._navigatorController.hideNavigatorOverlay(); 554 var uiSourceCode = /** @type {WebInspector.UISourceCode} */ (event.data); 555 556 if (this._currentUISourceCode === uiSourceCode) 557 delete this._currentUISourceCode; 558 559 // ScriptsNavigator does not need to update on EditorClosed. 560 this._updateScriptViewStatusBarItems(); 561 WebInspector.searchController.resetSearch(); 562 }, 563 564 _editorSelected: function(event) 565 { 566 var uiSourceCode = /** @type {WebInspector.UISourceCode} */ (event.data); 567 var sourceFrame = this._showFile(uiSourceCode); 568 this._navigatorController.hideNavigatorOverlay(); 569 if (!this._navigatorController.isNavigatorPinned()) 570 sourceFrame.focus(); 571 WebInspector.searchController.resetSearch(); 572 }, 573 574 _scriptSelected: function(event) 575 { 576 var uiSourceCode = /** @type {WebInspector.UISourceCode} */ (event.data.uiSourceCode); 577 var sourceFrame = this._showFile(uiSourceCode); 578 this._navigatorController.hideNavigatorOverlay(); 579 if (sourceFrame && (!this._navigatorController.isNavigatorPinned() || event.data.focusSource)) 580 sourceFrame.focus(); 581 }, 582 583 _itemSearchStarted: function(event) 584 { 585 var searchText = /** @type {string} */ (event.data); 586 WebInspector.OpenResourceDialog.show(this, this.editorView.mainElement, searchText); 587 }, 588 589 _pauseOnExceptionStateChanged: function() 590 { 591 var pauseOnExceptionsState = WebInspector.settings.pauseOnExceptionStateString.get(); 592 switch (pauseOnExceptionsState) { 593 case WebInspector.DebuggerModel.PauseOnExceptionsState.DontPauseOnExceptions: 594 this._pauseOnExceptionButton.title = WebInspector.UIString("Don't pause on exceptions.\nClick to Pause on all exceptions."); 595 break; 596 case WebInspector.DebuggerModel.PauseOnExceptionsState.PauseOnAllExceptions: 597 this._pauseOnExceptionButton.title = WebInspector.UIString("Pause on all exceptions.\nClick to Pause on uncaught exceptions."); 598 break; 599 case WebInspector.DebuggerModel.PauseOnExceptionsState.PauseOnUncaughtExceptions: 600 this._pauseOnExceptionButton.title = WebInspector.UIString("Pause on uncaught exceptions.\nClick to Not pause on exceptions."); 601 break; 602 } 603 this._pauseOnExceptionButton.state = pauseOnExceptionsState; 604 }, 605 606 _updateDebuggerButtons: function() 607 { 608 if (WebInspector.debuggerModel.debuggerEnabled()) { 609 this._pauseOnExceptionButton.visible = true; 610 } else { 611 this._pauseOnExceptionButton.visible = false; 612 } 613 614 if (this._paused) { 615 this._updateButtonTitle(this._pauseButton, WebInspector.UIString("Resume script execution (%s).")) 616 this._pauseButton.state = true; 617 618 this._pauseButton.setEnabled(true); 619 this._stepOverButton.setEnabled(true); 620 this._stepIntoButton.setEnabled(true); 621 this._stepOutButton.setEnabled(true); 622 623 this.debuggerStatusElement.textContent = WebInspector.UIString("Paused"); 624 } else { 625 this._updateButtonTitle(this._pauseButton, WebInspector.UIString("Pause script execution (%s).")) 626 this._pauseButton.state = false; 627 628 this._pauseButton.setEnabled(!this._waitingToPause); 629 this._stepOverButton.setEnabled(false); 630 this._stepIntoButton.setEnabled(false); 631 this._stepOutButton.setEnabled(false); 632 633 if (this._waitingToPause) 634 this.debuggerStatusElement.textContent = WebInspector.UIString("Pausing"); 635 else if (this._stepping) 636 this.debuggerStatusElement.textContent = WebInspector.UIString("Stepping"); 637 else 638 this.debuggerStatusElement.textContent = ""; 639 } 640 }, 641 642 _clearInterface: function() 643 { 644 this.sidebarPanes.callstack.update(null); 645 this.sidebarPanes.scopechain.update(null); 646 this.sidebarPanes.jsBreakpoints.clearBreakpointHighlight(); 647 WebInspector.domBreakpointsSidebarPane.clearBreakpointHighlight(); 648 this.sidebarPanes.eventListenerBreakpoints.clearBreakpointHighlight(); 649 this.sidebarPanes.xhrBreakpoints.clearBreakpointHighlight(); 650 651 this._clearCurrentExecutionLine(); 652 this._updateDebuggerButtons(); 653 }, 654 655 _togglePauseOnExceptions: function() 656 { 657 var nextStateMap = {}; 658 var stateEnum = WebInspector.DebuggerModel.PauseOnExceptionsState; 659 nextStateMap[stateEnum.DontPauseOnExceptions] = stateEnum.PauseOnAllExceptions; 660 nextStateMap[stateEnum.PauseOnAllExceptions] = stateEnum.PauseOnUncaughtExceptions; 661 nextStateMap[stateEnum.PauseOnUncaughtExceptions] = stateEnum.DontPauseOnExceptions; 662 WebInspector.settings.pauseOnExceptionStateString.set(nextStateMap[this._pauseOnExceptionButton.state]); 663 }, 664 665 /** 666 * @param {Event=} event 667 * @return {boolean} 668 */ 669 _runSnippet: function(event) 670 { 671 if (this._currentUISourceCode.project().type() !== WebInspector.projectTypes.Snippets) 672 return false; 673 WebInspector.scriptSnippetModel.evaluateScriptSnippet(this._currentUISourceCode); 674 return true; 675 }, 676 677 /** 678 * @param {Event=} event 679 * @return {boolean} 680 */ 681 _togglePause: function(event) 682 { 683 if (this._paused) { 684 this._paused = false; 685 this._waitingToPause = false; 686 DebuggerAgent.resume(); 687 } else { 688 this._stepping = false; 689 this._waitingToPause = true; 690 DebuggerAgent.pause(); 691 } 692 693 this._clearInterface(); 694 return true; 695 }, 696 697 /** 698 * @param {Event=} event 699 * @return {boolean} 700 */ 701 _stepOverClicked: function(event) 702 { 703 if (!this._paused) 704 return true; 705 706 this._paused = false; 707 this._stepping = true; 708 709 this._clearInterface(); 710 711 DebuggerAgent.stepOver(); 712 return true; 713 }, 714 715 /** 716 * @param {Event=} event 717 * @return {boolean} 718 */ 719 _stepIntoClicked: function(event) 720 { 721 if (!this._paused) 722 return true; 723 724 this._paused = false; 725 this._stepping = true; 726 727 this._clearInterface(); 728 729 DebuggerAgent.stepInto(); 730 return true; 731 }, 732 733 /** 734 * @param {Event=} event 735 * @return {boolean} 736 */ 737 _stepOutClicked: function(event) 738 { 739 if (!this._paused) 740 return true; 741 742 this._paused = false; 743 this._stepping = true; 744 745 this._clearInterface(); 746 747 DebuggerAgent.stepOut(); 748 return true; 749 }, 750 751 _toggleBreakpointsClicked: function(event) 752 { 753 WebInspector.debuggerModel.setBreakpointsActive(!WebInspector.debuggerModel.breakpointsActive()); 754 }, 755 756 _breakpointsActiveStateChanged: function(event) 757 { 758 var active = event.data; 759 this._toggleBreakpointsButton.toggled = !active; 760 if (active) { 761 this._toggleBreakpointsButton.title = WebInspector.UIString("Deactivate breakpoints."); 762 WebInspector.inspectorView.element.removeStyleClass("breakpoints-deactivated"); 763 this.sidebarPanes.jsBreakpoints.listElement.removeStyleClass("breakpoints-list-deactivated"); 764 } else { 765 this._toggleBreakpointsButton.title = WebInspector.UIString("Activate breakpoints."); 766 WebInspector.inspectorView.element.addStyleClass("breakpoints-deactivated"); 767 this.sidebarPanes.jsBreakpoints.listElement.addStyleClass("breakpoints-list-deactivated"); 768 } 769 }, 770 771 _createDebugToolbar: function() 772 { 773 var debugToolbar = document.createElement("div"); 774 debugToolbar.className = "status-bar"; 775 debugToolbar.id = "scripts-debug-toolbar"; 776 777 var title, handler; 778 var platformSpecificModifier = WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta; 779 780 // Run snippet. 781 title = WebInspector.UIString("Run snippet (%s)."); 782 handler = this._runSnippet.bind(this); 783 this._runSnippetButton = this._createButtonAndRegisterShortcuts("scripts-run-snippet", title, handler, WebInspector.ScriptsPanelDescriptor.ShortcutKeys.RunSnippet); 784 debugToolbar.appendChild(this._runSnippetButton.element); 785 this._runSnippetButton.element.addStyleClass("hidden"); 786 787 // Continue. 788 handler = this._togglePause.bind(this); 789 this._pauseButton = this._createButtonAndRegisterShortcuts("scripts-pause", "", handler, WebInspector.ScriptsPanelDescriptor.ShortcutKeys.PauseContinue); 790 debugToolbar.appendChild(this._pauseButton.element); 791 792 // Step over. 793 title = WebInspector.UIString("Step over next function call (%s)."); 794 handler = this._stepOverClicked.bind(this); 795 this._stepOverButton = this._createButtonAndRegisterShortcuts("scripts-step-over", title, handler, WebInspector.ScriptsPanelDescriptor.ShortcutKeys.StepOver); 796 debugToolbar.appendChild(this._stepOverButton.element); 797 798 // Step into. 799 title = WebInspector.UIString("Step into next function call (%s)."); 800 handler = this._stepIntoClicked.bind(this); 801 this._stepIntoButton = this._createButtonAndRegisterShortcuts("scripts-step-into", title, handler, WebInspector.ScriptsPanelDescriptor.ShortcutKeys.StepInto); 802 debugToolbar.appendChild(this._stepIntoButton.element); 803 804 // Step out. 805 title = WebInspector.UIString("Step out of current function (%s)."); 806 handler = this._stepOutClicked.bind(this); 807 this._stepOutButton = this._createButtonAndRegisterShortcuts("scripts-step-out", title, handler, WebInspector.ScriptsPanelDescriptor.ShortcutKeys.StepOut); 808 debugToolbar.appendChild(this._stepOutButton.element); 809 810 this._toggleBreakpointsButton = new WebInspector.StatusBarButton(WebInspector.UIString("Deactivate breakpoints."), "scripts-toggle-breakpoints"); 811 this._toggleBreakpointsButton.toggled = false; 812 this._toggleBreakpointsButton.addEventListener("click", this._toggleBreakpointsClicked, this); 813 debugToolbar.appendChild(this._toggleBreakpointsButton.element); 814 815 this.debuggerStatusElement = document.createElement("div"); 816 this.debuggerStatusElement.id = "scripts-debugger-status"; 817 debugToolbar.appendChild(this.debuggerStatusElement); 818 819 return debugToolbar; 820 }, 821 822 /** 823 * @param {WebInspector.StatusBarButton} button 824 * @param {string} buttonTitle 825 */ 826 _updateButtonTitle: function(button, buttonTitle) 827 { 828 var hasShortcuts = button.shortcuts && button.shortcuts.length; 829 if (hasShortcuts) 830 button.title = String.vsprintf(buttonTitle, [button.shortcuts[0].name]); 831 else 832 button.title = buttonTitle; 833 }, 834 835 /** 836 * @param {string} buttonId 837 * @param {string} buttonTitle 838 * @param {function(Event=):boolean} handler 839 * @param {!Array.<!WebInspector.KeyboardShortcut.Descriptor>} shortcuts 840 * @return {WebInspector.StatusBarButton} 841 */ 842 _createButtonAndRegisterShortcuts: function(buttonId, buttonTitle, handler, shortcuts) 843 { 844 var button = new WebInspector.StatusBarButton(buttonTitle, buttonId); 845 button.element.addEventListener("click", handler, false); 846 button.shortcuts = shortcuts; 847 this._updateButtonTitle(button, buttonTitle); 848 this.registerShortcuts(shortcuts, handler); 849 return button; 850 }, 851 852 searchCanceled: function() 853 { 854 if (this._searchView) 855 this._searchView.searchCanceled(); 856 857 delete this._searchView; 858 delete this._searchQuery; 859 }, 860 861 /** 862 * @param {string} query 863 * @param {boolean} shouldJump 864 */ 865 performSearch: function(query, shouldJump) 866 { 867 WebInspector.searchController.updateSearchMatchesCount(0, this); 868 869 if (!this.visibleView) 870 return; 871 872 this._searchView = this.visibleView; 873 this._searchQuery = query; 874 875 function finishedCallback(view, searchMatches) 876 { 877 if (!searchMatches) 878 return; 879 880 WebInspector.searchController.updateSearchMatchesCount(searchMatches, this); 881 } 882 883 function currentMatchChanged(currentMatchIndex) 884 { 885 WebInspector.searchController.updateCurrentMatchIndex(currentMatchIndex, this); 886 } 887 888 this._searchView.performSearch(query, shouldJump, finishedCallback.bind(this), currentMatchChanged.bind(this)); 889 }, 890 891 /** 892 * @return {number} 893 */ 894 minimalSearchQuerySize: function() 895 { 896 return 0; 897 }, 898 899 jumpToNextSearchResult: function() 900 { 901 if (!this._searchView) 902 return; 903 904 if (this._searchView !== this.visibleView) { 905 this.performSearch(this._searchQuery, true); 906 return; 907 } 908 909 this._searchView.jumpToNextSearchResult(); 910 return true; 911 }, 912 913 jumpToPreviousSearchResult: function() 914 { 915 if (!this._searchView) 916 return; 917 918 if (this._searchView !== this.visibleView) { 919 this.performSearch(this._searchQuery, true); 920 if (this._searchView) 921 this._searchView.jumpToLastSearchResult(); 922 return; 923 } 924 925 this._searchView.jumpToPreviousSearchResult(); 926 }, 927 928 /** 929 * @return {boolean} 930 */ 931 canSearchAndReplace: function() 932 { 933 var view = /** @type {WebInspector.SourceFrame} */ (this.visibleView); 934 return !!view && view.canEditSource(); 935 }, 936 937 /** 938 * @param {string} text 939 */ 940 replaceSelectionWith: function(text) 941 { 942 var view = /** @type {WebInspector.SourceFrame} */ (this.visibleView); 943 view.replaceSearchMatchWith(text); 944 }, 945 946 /** 947 * @param {string} query 948 * @param {string} text 949 */ 950 replaceAllWith: function(query, text) 951 { 952 var view = /** @type {WebInspector.SourceFrame} */ (this.visibleView); 953 view.replaceAllWith(query, text); 954 }, 955 956 _toggleFormatSource: function() 957 { 958 this._toggleFormatSourceButton.toggled = !this._toggleFormatSourceButton.toggled; 959 var uiSourceCodes = this._workspace.uiSourceCodes(); 960 for (var i = 0; i < uiSourceCodes.length; ++i) 961 uiSourceCodes[i].setFormatted(this._toggleFormatSourceButton.toggled); 962 963 var currentFile = this._editorContainer.currentFile(); 964 965 WebInspector.notifications.dispatchEventToListeners(WebInspector.UserMetrics.UserAction, { 966 action: WebInspector.UserMetrics.UserActionNames.TogglePrettyPrint, 967 enabled: this._toggleFormatSourceButton.toggled, 968 url: currentFile ? currentFile.originURL() : null 969 }); 970 }, 971 972 addToWatch: function(expression) 973 { 974 this.sidebarPanes.watchExpressions.addExpression(expression); 975 }, 976 977 /** 978 * @return {boolean} 979 */ 980 _toggleBreakpoint: function() 981 { 982 var sourceFrame = this.visibleView; 983 if (!sourceFrame) 984 return false; 985 986 if (sourceFrame instanceof WebInspector.JavaScriptSourceFrame) { 987 var javaScriptSourceFrame = /** @type {WebInspector.JavaScriptSourceFrame} */ (sourceFrame); 988 javaScriptSourceFrame.toggleBreakpointOnCurrentLine(); 989 return true; 990 } 991 return false; 992 }, 993 994 /** 995 * @param {Event=} event 996 * @return {boolean} 997 */ 998 _showOutlineDialog: function(event) 999 { 1000 var uiSourceCode = this._editorContainer.currentFile(); 1001 if (!uiSourceCode) 1002 return false; 1003 1004 switch (uiSourceCode.contentType()) { 1005 case WebInspector.resourceTypes.Document: 1006 case WebInspector.resourceTypes.Script: 1007 WebInspector.JavaScriptOutlineDialog.show(this.visibleView, uiSourceCode); 1008 return true; 1009 case WebInspector.resourceTypes.Stylesheet: 1010 WebInspector.StyleSheetOutlineDialog.show(this.visibleView, uiSourceCode); 1011 return true; 1012 } 1013 return false; 1014 }, 1015 1016 _installDebuggerSidebarController: function() 1017 { 1018 this._toggleDebuggerSidebarButton = new WebInspector.StatusBarButton("", "right-sidebar-show-hide-button scripts-debugger-show-hide-button", 3); 1019 this._toggleDebuggerSidebarButton.addEventListener("click", clickHandler, this); 1020 this.editorView.element.appendChild(this._toggleDebuggerSidebarButton.element); 1021 this._enableDebuggerSidebar(!WebInspector.settings.debuggerSidebarHidden.get()); 1022 1023 function clickHandler() 1024 { 1025 this._enableDebuggerSidebar(this._toggleDebuggerSidebarButton.state === "left"); 1026 } 1027 }, 1028 1029 /** 1030 * @param {boolean} show 1031 */ 1032 _enableDebuggerSidebar: function(show) 1033 { 1034 this._toggleDebuggerSidebarButton.state = show ? "right" : "left"; 1035 this._toggleDebuggerSidebarButton.title = show ? WebInspector.UIString("Hide debugger") : WebInspector.UIString("Show debugger"); 1036 if (show) 1037 this.splitView.showSidebarElement(); 1038 else 1039 this.splitView.hideSidebarElement(); 1040 this._debugSidebarResizeWidgetElement.enableStyleClass("hidden", !show); 1041 WebInspector.settings.debuggerSidebarHidden.set(!show); 1042 }, 1043 1044 /** 1045 * @param {WebInspector.Event} event 1046 */ 1047 _itemCreationRequested: function(event) 1048 { 1049 var project = event.data.project; 1050 var path = event.data.path; 1051 var filePath; 1052 var shouldHideNavigator; 1053 var uiSourceCode; 1054 project.createFile(path, null, fileCreated.bind(this)); 1055 1056 /** 1057 * @param {?string} path 1058 */ 1059 function fileCreated(path) 1060 { 1061 if (!path) 1062 return; 1063 filePath = path; 1064 uiSourceCode = project.uiSourceCode(filePath); 1065 this._showSourceLocation(uiSourceCode); 1066 1067 shouldHideNavigator = !this._navigatorController.isNavigatorPinned(); 1068 if (this._navigatorController.isNavigatorHidden()) 1069 this._navigatorController.showNavigatorOverlay(); 1070 this._navigator.rename(uiSourceCode, callback.bind(this)); 1071 } 1072 1073 /** 1074 * @param {boolean} committed 1075 */ 1076 function callback(committed) 1077 { 1078 if (shouldHideNavigator) 1079 this._navigatorController.hideNavigatorOverlay(); 1080 1081 if (!committed) { 1082 project.deleteFile(uiSourceCode); 1083 return; 1084 } 1085 1086 this._showSourceLocation(uiSourceCode); 1087 } 1088 }, 1089 1090 /** 1091 * @param {WebInspector.Event} event 1092 */ 1093 _itemRenamingRequested: function(event) 1094 { 1095 var uiSourceCode = /** @type {WebInspector.UISourceCode} */ (event.data); 1096 1097 var shouldHideNavigator = !this._navigatorController.isNavigatorPinned(); 1098 if (this._navigatorController.isNavigatorHidden()) 1099 this._navigatorController.showNavigatorOverlay(); 1100 this._navigator.rename(uiSourceCode, callback.bind(this)); 1101 1102 /** 1103 * @param {boolean} committed 1104 */ 1105 function callback(committed) 1106 { 1107 if (shouldHideNavigator && committed) { 1108 this._navigatorController.hideNavigatorOverlay(); 1109 this._showSourceLocation(uiSourceCode); 1110 } 1111 } 1112 }, 1113 1114 /** 1115 * @param {WebInspector.UISourceCode} uiSourceCode 1116 */ 1117 _showLocalHistory: function(uiSourceCode) 1118 { 1119 WebInspector.RevisionHistoryView.showHistory(uiSourceCode); 1120 }, 1121 1122 /** 1123 * @param {WebInspector.ContextMenu} contextMenu 1124 * @param {Object} target 1125 */ 1126 appendApplicableItems: function(event, contextMenu, target) 1127 { 1128 this._appendUISourceCodeItems(contextMenu, target); 1129 this._appendFunctionItems(contextMenu, target); 1130 }, 1131 1132 /** 1133 * @param {WebInspector.UISourceCode} uiSourceCode 1134 */ 1135 _mapFileSystemToNetwork: function(uiSourceCode) 1136 { 1137 WebInspector.SelectUISourceCodeForProjectTypeDialog.show(uiSourceCode.name(), WebInspector.projectTypes.Network, mapFileSystemToNetwork.bind(this), this.editorView.mainElement) 1138 1139 /** 1140 * @param {WebInspector.UISourceCode} networkUISourceCode 1141 */ 1142 function mapFileSystemToNetwork(networkUISourceCode) 1143 { 1144 this._workspace.addMapping(networkUISourceCode, uiSourceCode, WebInspector.fileSystemWorkspaceProvider); 1145 } 1146 }, 1147 1148 /** 1149 * @param {WebInspector.UISourceCode} uiSourceCode 1150 */ 1151 _removeNetworkMapping: function(uiSourceCode) 1152 { 1153 if (confirm(WebInspector.UIString("Are you sure you want to remove network mapping?"))) 1154 this._workspace.removeMapping(uiSourceCode); 1155 }, 1156 1157 /** 1158 * @param {WebInspector.UISourceCode} networkUISourceCode 1159 */ 1160 _mapNetworkToFileSystem: function(networkUISourceCode) 1161 { 1162 WebInspector.SelectUISourceCodeForProjectTypeDialog.show(networkUISourceCode.name(), WebInspector.projectTypes.FileSystem, mapNetworkToFileSystem.bind(this), this.editorView.mainElement) 1163 1164 /** 1165 * @param {WebInspector.UISourceCode} uiSourceCode 1166 */ 1167 function mapNetworkToFileSystem(uiSourceCode) 1168 { 1169 this._workspace.addMapping(networkUISourceCode, uiSourceCode, WebInspector.fileSystemWorkspaceProvider); 1170 } 1171 }, 1172 1173 /** 1174 * @param {WebInspector.ContextMenu} contextMenu 1175 * @param {WebInspector.UISourceCode} uiSourceCode 1176 */ 1177 _appendUISourceCodeMappingItems: function(contextMenu, uiSourceCode) 1178 { 1179 if (uiSourceCode.project().type() === WebInspector.projectTypes.FileSystem) { 1180 var hasMappings = !!uiSourceCode.url; 1181 if (!hasMappings) 1182 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Map to network resource\u2026" : "Map to Network Resource\u2026"), this._mapFileSystemToNetwork.bind(this, uiSourceCode)); 1183 else 1184 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove network mapping" : "Remove Network Mapping"), this._removeNetworkMapping.bind(this, uiSourceCode)); 1185 } 1186 1187 if (uiSourceCode.project().type() === WebInspector.projectTypes.Network) { 1188 /** 1189 * @param {WebInspector.Project} project 1190 */ 1191 function filterProject(project) 1192 { 1193 return project.type() === WebInspector.projectTypes.FileSystem; 1194 } 1195 1196 if (!this._workspace.projects().filter(filterProject).length) 1197 return; 1198 if (this._workspace.uiSourceCodeForURL(uiSourceCode.url) === uiSourceCode) 1199 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Map to file system resource\u2026" : "Map to File System Resource\u2026"), this._mapNetworkToFileSystem.bind(this, uiSourceCode)); 1200 } 1201 }, 1202 1203 /** 1204 * @param {WebInspector.ContextMenu} contextMenu 1205 * @param {Object} target 1206 */ 1207 _appendUISourceCodeItems: function(contextMenu, target) 1208 { 1209 if (!(target instanceof WebInspector.UISourceCode)) 1210 return; 1211 1212 var uiSourceCode = /** @type {WebInspector.UISourceCode} */ (target); 1213 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Local modifications\u2026" : "Local Modifications\u2026"), this._showLocalHistory.bind(this, uiSourceCode)); 1214 1215 if (WebInspector.isolatedFileSystemManager.supportsFileSystems()) 1216 this._appendUISourceCodeMappingItems(contextMenu, uiSourceCode); 1217 1218 var resource = WebInspector.resourceForURL(uiSourceCode.url); 1219 if (resource && resource.request) 1220 contextMenu.appendApplicableItems(resource.request); 1221 }, 1222 1223 /** 1224 * @param {WebInspector.ContextMenu} contextMenu 1225 * @param {Object} target 1226 */ 1227 _appendFunctionItems: function(contextMenu, target) 1228 { 1229 if (!(target instanceof WebInspector.RemoteObject)) 1230 return; 1231 var remoteObject = /** @type {WebInspector.RemoteObject} */ (target); 1232 if (remoteObject.type !== "function") 1233 return; 1234 1235 function didGetDetails(error, response) 1236 { 1237 if (error) { 1238 console.error(error); 1239 return; 1240 } 1241 1242 WebInspector.inspectorView.setCurrentPanel(this); 1243 var uiLocation = WebInspector.debuggerModel.rawLocationToUILocation(response.location); 1244 this._showSourceLocation(uiLocation.uiSourceCode, uiLocation.lineNumber, uiLocation.columnNumber); 1245 } 1246 1247 function revealFunction() 1248 { 1249 DebuggerAgent.getFunctionDetails(remoteObject.objectId, didGetDetails.bind(this)); 1250 } 1251 1252 contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Show function definition" : "Show Function Definition"), revealFunction.bind(this)); 1253 }, 1254 1255 showGoToSourceDialog: function() 1256 { 1257 var uiSourceCodes = this._editorContainer.historyUISourceCodes(); 1258 /** @type {!Map.<WebInspector.UISourceCode, number>} */ 1259 var defaultScores = new Map(); 1260 for (var i = 1; i < uiSourceCodes.length; ++i) // Skip current element 1261 defaultScores.put(uiSourceCodes[i], uiSourceCodes.length - i); 1262 WebInspector.OpenResourceDialog.show(this, this.editorView.mainElement, undefined, defaultScores); 1263 }, 1264 1265 _dockSideChanged: function() 1266 { 1267 var dockSide = WebInspector.dockController.dockSide(); 1268 var vertically = dockSide === WebInspector.DockController.State.DockedToRight && WebInspector.settings.splitVerticallyWhenDockedToRight.get(); 1269 this._splitVertically(vertically); 1270 }, 1271 1272 /** 1273 * @param {boolean} vertically 1274 */ 1275 _splitVertically: function(vertically) 1276 { 1277 if (this.sidebarPaneView && vertically === !this.splitView.isVertical()) 1278 return; 1279 1280 if (this.sidebarPaneView) 1281 this.sidebarPaneView.detach(); 1282 1283 this.splitView.setVertical(!vertically); 1284 1285 if (!vertically) { 1286 this.sidebarPaneView = new WebInspector.SidebarPaneStack(); 1287 for (var pane in this.sidebarPanes) 1288 this.sidebarPaneView.addPane(this.sidebarPanes[pane]); 1289 1290 this.sidebarElement.appendChild(this.debugToolbar); 1291 } else { 1292 this._enableDebuggerSidebar(true); 1293 1294 this.sidebarPaneView = new WebInspector.SplitView(true, this.name + "PanelSplitSidebarRatio", 0.5); 1295 1296 var group1 = new WebInspector.SidebarPaneStack(); 1297 group1.show(this.sidebarPaneView.firstElement()); 1298 group1.element.id = "scripts-sidebar-stack-pane"; 1299 group1.addPane(this.sidebarPanes.callstack); 1300 group1.addPane(this.sidebarPanes.jsBreakpoints); 1301 group1.addPane(this.sidebarPanes.domBreakpoints); 1302 group1.addPane(this.sidebarPanes.xhrBreakpoints); 1303 group1.addPane(this.sidebarPanes.eventListenerBreakpoints); 1304 if (this.sidebarPanes.workerList) 1305 group1.addPane(this.sidebarPanes.workerList); 1306 1307 var group2 = new WebInspector.SidebarTabbedPane(); 1308 group2.show(this.sidebarPaneView.secondElement()); 1309 group2.addPane(this.sidebarPanes.scopechain); 1310 group2.addPane(this.sidebarPanes.watchExpressions); 1311 1312 this.sidebarPaneView.firstElement().appendChild(this.debugToolbar); 1313 } 1314 1315 this.sidebarPaneView.element.id = "scripts-debug-sidebar-contents"; 1316 this.sidebarPaneView.show(this.splitView.sidebarElement); 1317 1318 this.sidebarPanes.scopechain.expand(); 1319 this.sidebarPanes.jsBreakpoints.expand(); 1320 this.sidebarPanes.callstack.expand(); 1321 1322 if (WebInspector.settings.watchExpressions.get().length > 0) 1323 this.sidebarPanes.watchExpressions.expand(); 1324 }, 1325 1326 /** 1327 * @return {boolean} 1328 */ 1329 canSetFooterElement: function() 1330 { 1331 return true; 1332 }, 1333 1334 /** 1335 * @param {Element?} element 1336 */ 1337 setFooterElement: function(element) 1338 { 1339 if (element) { 1340 this._editorFooterElement.removeStyleClass("hidden"); 1341 this._editorFooterElement.appendChild(element); 1342 this._editorContentsElement.style.bottom = this._editorFooterElement.offsetHeight + "px"; 1343 } else { 1344 this._editorFooterElement.addStyleClass("hidden"); 1345 this._editorFooterElement.removeChildren(); 1346 this._editorContentsElement.style.bottom = 0; 1347 } 1348 this.doResize(); 1349 }, 1350 1351 __proto__: WebInspector.Panel.prototype 1352 } 1353