1 /* 2 * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. 3 * Copyright (C) 2007 Matt Lilek (pewtermoose (at) gmail.com). 4 * Copyright (C) 2009 Joseph Pecoraro 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 16 * its contributors may be used to endorse or promote products derived 17 * from this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 var WebInspector = { 32 _panelDescriptors: function() 33 { 34 this.panels = {}; 35 WebInspector.inspectorView = new WebInspector.InspectorView(); 36 WebInspector.inspectorView.show(document.body); 37 38 var elements = new WebInspector.ElementsPanelDescriptor(); 39 var network = new WebInspector.NetworkPanelDescriptor(); 40 var sources = new WebInspector.SourcesPanelDescriptor(); 41 var timeline = new WebInspector.TimelinePanelDescriptor(); 42 var profiles = new WebInspector.ProfilesPanelDescriptor(); 43 var resources = new WebInspector.PanelDescriptor("resources", WebInspector.UIString("Resources"), "ResourcesPanel", "ResourcesPanel.js"); 44 var audits = new WebInspector.PanelDescriptor("audits", WebInspector.UIString("Audits"), "AuditsPanel", "AuditsPanel.js"); 45 var console = new WebInspector.PanelDescriptor("console", WebInspector.UIString("Console"), "ConsolePanel"); 46 47 if (WebInspector.WorkerManager.isWorkerFrontend()) 48 return [sources, timeline, profiles, console]; 49 50 var panelDescriptors = [elements, network, sources, timeline, profiles, resources, audits, console]; 51 if (WebInspector.experimentsSettings.layersPanel.isEnabled()) { 52 var layers = new WebInspector.LayersPanelDescriptor(); 53 panelDescriptors.push(layers); 54 } 55 return panelDescriptors; 56 }, 57 58 _createGlobalStatusBarItems: function() 59 { 60 if (this.inspectElementModeController) 61 this.inspectorView.appendToLeftToolbar(this.inspectElementModeController.toggleSearchButton.element); 62 63 if (Capabilities.canScreencast) { 64 this._toggleScreencastButton = new WebInspector.StatusBarButton(WebInspector.UIString("Toggle screencast."), "screencast-status-bar-item"); 65 this._toggleScreencastButton.addEventListener("click", this._toggleScreencastButtonClicked.bind(this), false); 66 this.inspectorView.appendToLeftToolbar(this._toggleScreencastButton.element); 67 } 68 69 this.inspectorView.appendToRightToolbar(this.settingsController.statusBarItem); 70 if (WebInspector.queryParamsObject["can_dock"]) 71 this.inspectorView.appendToRightToolbar(this.dockController.element); 72 73 var closeButtonToolbarItem = document.createElementWithClass("div", "toolbar-close-button-item"); 74 var closeButtonElement = closeButtonToolbarItem.createChild("div", "close-button"); 75 closeButtonElement.addEventListener("click", WebInspector.close.bind(WebInspector), true); 76 this.inspectorView.appendToRightToolbar(closeButtonToolbarItem); 77 }, 78 79 /** 80 * @return {boolean} 81 */ 82 isInspectingDevice: function() 83 { 84 return !!WebInspector.queryParamsObject["remoteFrontend"]; 85 }, 86 87 _toggleScreencastButtonClicked: function() 88 { 89 this._toggleScreencastButton.toggled = !this._toggleScreencastButton.toggled; 90 WebInspector.settings.screencastEnabled.set(this._toggleScreencastButton.toggled); 91 92 if (this._toggleScreencastButton.toggled) { 93 if (!this._screencastView) { 94 // Rebuild the UI upon first invocation. 95 this._screencastView = new WebInspector.ScreencastView(); 96 this._screencastSplitView = new WebInspector.SplitView(true, WebInspector.settings.screencastSidebarWidth.name); 97 this._screencastSplitView.markAsRoot(); 98 this._screencastSplitView.show(document.body); 99 100 this._screencastView.show(this._screencastSplitView.firstElement()); 101 102 this.inspectorView.element.remove(); 103 this.inspectorView.show(this._screencastSplitView.secondElement()); 104 } 105 this._screencastSplitView.showBoth(); 106 } else { 107 this._screencastSplitView.showOnlySecond(); 108 } 109 }, 110 111 112 showConsole: function() 113 { 114 if (this.consoleView.isShowing() && !WebInspector.inspectorView.drawer().isHiding()) 115 return; 116 this.inspectorView.showViewInDrawer("console"); 117 }, 118 119 _resetErrorAndWarningCounts: function() 120 { 121 WebInspector.inspectorView.setErrorAndWarningCounts(0, 0); 122 }, 123 124 _updateErrorAndWarningCounts: function() 125 { 126 var errors = WebInspector.console.errors; 127 var warnings = WebInspector.console.warnings; 128 WebInspector.inspectorView.setErrorAndWarningCounts(errors, warnings); 129 }, 130 131 get inspectedPageDomain() 132 { 133 var parsedURL = WebInspector.inspectedPageURL && WebInspector.inspectedPageURL.asParsedURL(); 134 return parsedURL ? parsedURL.host : ""; 135 }, 136 137 _initializeCapability: function(name, callback, error, result) 138 { 139 Capabilities[name] = result; 140 if (callback) 141 callback(); 142 }, 143 144 _zoomIn: function() 145 { 146 this._zoomLevel = Math.min(this._zoomLevel + 1, WebInspector.Zoom.Table.length - WebInspector.Zoom.DefaultOffset - 1); 147 this._requestZoom(); 148 }, 149 150 _zoomOut: function() 151 { 152 this._zoomLevel = Math.max(this._zoomLevel - 1, -WebInspector.Zoom.DefaultOffset); 153 this._requestZoom(); 154 }, 155 156 _resetZoom: function() 157 { 158 this._zoomLevel = 0; 159 this._requestZoom(); 160 }, 161 162 /** 163 * @return {number} 164 * @this {WebInspector} 165 */ 166 zoomFactor: function() 167 { 168 // For backwards compatibility, zoomLevel takes integers (with 0 being default zoom). 169 var index = this._zoomLevel + WebInspector.Zoom.DefaultOffset; 170 index = Math.min(WebInspector.Zoom.Table.length - 1, index); 171 index = Math.max(0, index); 172 return WebInspector.Zoom.Table[index]; 173 }, 174 175 _requestZoom: function() 176 { 177 WebInspector.settings.zoomLevel.set(this._zoomLevel); 178 InspectorFrontendHost.setZoomFactor(this.zoomFactor()); 179 }, 180 181 _debuggerPaused: function() 182 { 183 this.debuggerModel.removeEventListener(WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this); 184 WebInspector.showPanel("sources"); 185 } 186 } 187 188 WebInspector.Events = { 189 InspectorLoaded: "InspectorLoaded" 190 } 191 192 {(function parseQueryParameters() 193 { 194 WebInspector.queryParamsObject = {}; 195 var queryParams = window.location.search; 196 if (!queryParams) 197 return; 198 var params = queryParams.substring(1).split("&"); 199 for (var i = 0; i < params.length; ++i) { 200 var pair = params[i].split("="); 201 WebInspector.queryParamsObject[pair[0]] = pair[1]; 202 } 203 })();} 204 205 WebInspector.suggestReload = function() 206 { 207 if (window.confirm(WebInspector.UIString("It is recommended to restart inspector after making these changes. Would you like to restart it?"))) 208 this.reload(); 209 } 210 211 WebInspector.reload = function() 212 { 213 InspectorAgent.reset(); 214 215 var queryParams = window.location.search; 216 var url = window.location.href; 217 url = url.substring(0, url.length - queryParams.length); 218 var queryParamsObject = {}; 219 for (var name in WebInspector.queryParamsObject) 220 queryParamsObject[name] = WebInspector.queryParamsObject[name]; 221 if (this.dockController) 222 queryParamsObject["dockSide"] = this.dockController.dockSide(); 223 var names = Object.keys(queryParamsObject); 224 for (var i = 0; i < names.length; ++i) 225 url += (i ? "&" : "?") + names[i] + "=" + queryParamsObject[names[i]]; 226 document.location = url; 227 } 228 229 WebInspector.loaded = function() 230 { 231 if (!InspectorFrontendHost.sendMessageToEmbedder) { 232 var helpScreen = new WebInspector.HelpScreen(WebInspector.UIString("Incompatible Chrome version")); 233 var p = helpScreen.contentElement.createChild("p", "help-section"); 234 p.textContent = WebInspector.UIString("Please upgrade to a newer Chrome version (you might need a Dev or Canary build)."); 235 helpScreen.showModal(); 236 return; 237 } 238 239 InspectorBackend.loadFromJSONIfNeeded("../protocol.json"); 240 WebInspector.dockController = new WebInspector.DockController(); 241 242 if (WebInspector.WorkerManager.isDedicatedWorkerFrontend()) { 243 // Do not create socket for the worker front-end. 244 WebInspector.doLoadedDone(); 245 return; 246 } 247 248 var ws; 249 if ("ws" in WebInspector.queryParamsObject) 250 ws = "ws://" + WebInspector.queryParamsObject.ws; 251 else if ("page" in WebInspector.queryParamsObject) { 252 var page = WebInspector.queryParamsObject.page; 253 var host = "host" in WebInspector.queryParamsObject ? WebInspector.queryParamsObject.host : window.location.host; 254 ws = "ws://" + host + "/devtools/page/" + page; 255 } 256 257 if (ws) { 258 WebInspector.socket = new WebSocket(ws); 259 WebInspector.socket.onmessage = function(message) { InspectorBackend.dispatch(message.data); } 260 WebInspector.socket.onerror = function(error) { console.error(error); } 261 WebInspector.socket.onopen = function() { 262 InspectorFrontendHost.sendMessageToBackend = WebInspector.socket.send.bind(WebInspector.socket); 263 WebInspector.doLoadedDone(); 264 } 265 WebInspector.socket.onclose = function() { 266 if (!WebInspector.socket._detachReason) 267 (new WebInspector.RemoteDebuggingTerminatedScreen("websocket_closed")).showModal(); 268 } 269 return; 270 } 271 272 WebInspector.doLoadedDone(); 273 274 // In case of loading as a web page with no bindings / harness, kick off initialization manually. 275 if (InspectorFrontendHost.isStub) { 276 InspectorFrontendAPI.dispatchQueryParameters(WebInspector.queryParamsObject); 277 WebInspector._doLoadedDoneWithCapabilities(); 278 } 279 } 280 281 WebInspector.doLoadedDone = function() 282 { 283 // Install styles and themes 284 WebInspector.installPortStyles(); 285 if (WebInspector.socket) 286 document.body.classList.add("remote"); 287 if (WebInspector.queryParamsObject["overlayContents"]) 288 document.body.classList.add("overlay-contents"); 289 290 if (WebInspector.queryParamsObject.toolbarColor && WebInspector.queryParamsObject.textColor) 291 WebInspector.setToolbarColors(WebInspector.queryParamsObject.toolbarColor, WebInspector.queryParamsObject.textColor); 292 293 WebInspector.WorkerManager.loaded(); 294 295 PageAgent.canScreencast(WebInspector._initializeCapability.bind(WebInspector, "canScreencast", null)); 296 WorkerAgent.canInspectWorkers(WebInspector._initializeCapability.bind(WebInspector, "canInspectWorkers", WebInspector._doLoadedDoneWithCapabilities.bind(WebInspector))); 297 } 298 299 WebInspector._doLoadedDoneWithCapabilities = function() 300 { 301 new WebInspector.VersionController().updateVersion(); 302 303 WebInspector.shortcutsScreen = new WebInspector.ShortcutsScreen(); 304 this._registerShortcuts(); 305 306 // set order of some sections explicitly 307 WebInspector.shortcutsScreen.section(WebInspector.UIString("Console")); 308 WebInspector.shortcutsScreen.section(WebInspector.UIString("Elements Panel")); 309 310 this.console = new WebInspector.ConsoleModel(); 311 this.console.addEventListener(WebInspector.ConsoleModel.Events.ConsoleCleared, this._resetErrorAndWarningCounts, this); 312 this.console.addEventListener(WebInspector.ConsoleModel.Events.MessageAdded, this._updateErrorAndWarningCounts, this); 313 this.console.addEventListener(WebInspector.ConsoleModel.Events.RepeatCountUpdated, this._updateErrorAndWarningCounts, this); 314 this.networkManager = new WebInspector.NetworkManager(); 315 this.resourceTreeModel = new WebInspector.ResourceTreeModel(this.networkManager); 316 this.debuggerModel = new WebInspector.DebuggerModel(); 317 this.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this); 318 this.networkLog = new WebInspector.NetworkLog(); 319 this.domAgent = new WebInspector.DOMAgent(); 320 this.domAgent.addEventListener(WebInspector.DOMAgent.Events.InspectNodeRequested, this._inspectNodeRequested, this); 321 this.runtimeModel = new WebInspector.RuntimeModel(this.resourceTreeModel); 322 323 var panelDescriptors = this._panelDescriptors(); 324 this.advancedSearchController = new WebInspector.AdvancedSearchController(); 325 for (var i = 0; i < panelDescriptors.length; ++i) 326 panelDescriptors[i].registerShortcuts(); 327 328 WebInspector.CSSMetadata.requestCSSShorthandData(); 329 330 this.consoleView = new WebInspector.ConsoleView(WebInspector.WorkerManager.isWorkerFrontend()); 331 332 InspectorBackend.registerInspectorDispatcher(this); 333 334 this.isolatedFileSystemManager = new WebInspector.IsolatedFileSystemManager(); 335 this.isolatedFileSystemDispatcher = new WebInspector.IsolatedFileSystemDispatcher(this.isolatedFileSystemManager); 336 this.workspace = new WebInspector.Workspace(this.isolatedFileSystemManager.mapping()); 337 338 this.cssModel = new WebInspector.CSSStyleModel(this.workspace); 339 this.timelineManager = new WebInspector.TimelineManager(); 340 this.tracingAgent = new WebInspector.TracingAgent(); 341 342 if (!WebInspector.WorkerManager.isWorkerFrontend()) 343 this.inspectElementModeController = new WebInspector.InspectElementModeController(); 344 345 this.settingsController = new WebInspector.SettingsController(); 346 347 this.domBreakpointsSidebarPane = new WebInspector.DOMBreakpointsSidebarPane(); 348 349 this._zoomLevel = WebInspector.settings.zoomLevel.get(); 350 if (this._zoomLevel) 351 this._requestZoom(); 352 353 var autoselectPanel = WebInspector.UIString("a panel chosen automatically"); 354 var openAnchorLocationSetting = WebInspector.settings.createSetting("openLinkHandler", autoselectPanel); 355 this.openAnchorLocationRegistry = new WebInspector.HandlerRegistry(openAnchorLocationSetting); 356 this.openAnchorLocationRegistry.registerHandler(autoselectPanel, function() { return false; }); 357 358 new WebInspector.WorkspaceController(this.workspace); 359 360 this.fileSystemWorkspaceProvider = new WebInspector.FileSystemWorkspaceProvider(this.isolatedFileSystemManager, this.workspace); 361 362 this.networkWorkspaceProvider = new WebInspector.SimpleWorkspaceProvider(this.workspace, WebInspector.projectTypes.Network); 363 new WebInspector.NetworkUISourceCodeProvider(this.networkWorkspaceProvider, this.workspace); 364 365 this.breakpointManager = new WebInspector.BreakpointManager(WebInspector.settings.breakpoints, this.debuggerModel, this.workspace); 366 367 this.scriptSnippetModel = new WebInspector.ScriptSnippetModel(this.workspace); 368 369 this.overridesSupport = new WebInspector.OverridesSupport(); 370 this.overridesSupport.applyInitialOverrides(); 371 372 new WebInspector.DebuggerScriptMapping(this.workspace, this.networkWorkspaceProvider); 373 this.liveEditSupport = new WebInspector.LiveEditSupport(this.workspace); 374 new WebInspector.CSSStyleSheetMapping(this.cssModel, this.workspace, this.networkWorkspaceProvider); 375 new WebInspector.PresentationConsoleMessageHelper(this.workspace); 376 377 this._createGlobalStatusBarItems(); 378 379 WebInspector.startBatchUpdate(); 380 for (var i = 0; i < panelDescriptors.length; ++i) 381 WebInspector.inspectorView.addPanel(panelDescriptors[i]); 382 WebInspector.endBatchUpdate(); 383 384 this.addMainEventListeners(document); 385 386 window.addEventListener("resize", this.windowResize.bind(this), true); 387 388 var errorWarningCount = document.getElementById("error-warning-count"); 389 errorWarningCount.addEventListener("click", this.showConsole.bind(this), false); 390 this._updateErrorAndWarningCounts(); 391 392 this.extensionServer.initExtensions(); 393 394 this.console.enableAgent(); 395 396 InspectorAgent.enable(WebInspector.inspectorView.showInitialPanel.bind(WebInspector.inspectorView)); 397 this.databaseModel = new WebInspector.DatabaseModel(); 398 this.domStorageModel = new WebInspector.DOMStorageModel(); 399 400 this.cpuProfilerModel = new WebInspector.CPUProfilerModel(); 401 HeapProfilerAgent.enable(); 402 403 WebInspector.settings.showPaintRects = WebInspector.settings.createBackendSetting("showPaintRects", false, PageAgent.setShowPaintRects.bind(PageAgent)); 404 WebInspector.settings.showDebugBorders = WebInspector.settings.createBackendSetting("showDebugBorders", false, PageAgent.setShowDebugBorders.bind(PageAgent)); 405 WebInspector.settings.continuousPainting = WebInspector.settings.createBackendSetting("continuousPainting", false, PageAgent.setContinuousPaintingEnabled.bind(PageAgent)); 406 WebInspector.settings.showFPSCounter = WebInspector.settings.createBackendSetting("showFPSCounter", false, PageAgent.setShowFPSCounter.bind(PageAgent)); 407 WebInspector.settings.showScrollBottleneckRects = WebInspector.settings.createBackendSetting("showScrollBottleneckRects", false, PageAgent.setShowScrollBottleneckRects.bind(PageAgent)); 408 409 if (WebInspector.settings.showPaintRects.get() || WebInspector.settings.showDebugBorders.get() || WebInspector.settings.continuousPainting.get() || 410 WebInspector.settings.showFPSCounter.get() || WebInspector.settings.showScrollBottleneckRects.get()) { 411 WebInspector.settings.showRenderingViewInDrawer.set(true); 412 } 413 414 WebInspector.settings.showMetricsRulers.addChangeListener(showRulersChanged); 415 function showRulersChanged() 416 { 417 PageAgent.setShowViewportSizeOnResize(true, WebInspector.settings.showMetricsRulers.get()); 418 } 419 showRulersChanged(); 420 421 WebInspector.WorkerManager.loadCompleted(); 422 InspectorFrontendAPI.loadCompleted(); 423 424 if (Capabilities.canScreencast && WebInspector.settings.screencastEnabled.get()) 425 this._toggleScreencastButtonClicked(); 426 427 WebInspector.notifications.dispatchEventToListeners(WebInspector.Events.InspectorLoaded); 428 } 429 430 var windowLoaded = function() 431 { 432 WebInspector.loaded(); 433 window.removeEventListener("DOMContentLoaded", windowLoaded, false); 434 delete windowLoaded; 435 }; 436 437 window.addEventListener("DOMContentLoaded", windowLoaded, false); 438 439 // We'd like to enforce asynchronous interaction between the inspector controller and the frontend. 440 // It is needed to prevent re-entering the backend code. 441 // Also, native dispatches do not guarantee setTimeouts to be serialized, so we 442 // enforce serialization using 'messagesToDispatch' queue. It is also important that JSC debugger 443 // tests require that each command was dispatch within individual timeout callback, so we don't batch them. 444 445 var messagesToDispatch = []; 446 447 WebInspector.dispatchQueueIsEmpty = function() { 448 return messagesToDispatch.length == 0; 449 } 450 451 WebInspector.dispatch = function(message) { 452 messagesToDispatch.push(message); 453 setTimeout(function() { 454 InspectorBackend.dispatch(messagesToDispatch.shift()); 455 }, 0); 456 } 457 458 WebInspector.windowResize = function(event) 459 { 460 if (WebInspector.inspectorView) 461 WebInspector.inspectorView.onResize(); 462 if (WebInspector.settingsController) 463 WebInspector.settingsController.resize(); 464 if (WebInspector._screencastSplitView) 465 WebInspector._screencastSplitView.doResize(); 466 } 467 468 WebInspector.close = function(event) 469 { 470 InspectorFrontendHost.closeWindow(); 471 } 472 473 WebInspector.documentClick = function(event) 474 { 475 var anchor = event.target.enclosingNodeOrSelfWithNodeName("a"); 476 if (!anchor || (anchor.target === "_blank")) 477 return; 478 479 // Prevent the link from navigating, since we don't do any navigation by following links normally. 480 event.consume(true); 481 482 function followLink() 483 { 484 if (WebInspector.isBeingEdited(event.target)) 485 return; 486 if (WebInspector.openAnchorLocationRegistry.dispatch({ url: anchor.href, lineNumber: anchor.lineNumber})) 487 return; 488 if (WebInspector.showAnchorLocation(anchor)) 489 return; 490 491 const profileMatch = WebInspector.ProfilesPanelDescriptor.ProfileURLRegExp.exec(anchor.href); 492 if (profileMatch) { 493 WebInspector.showPanel("profiles").showProfile(profileMatch[1], profileMatch[2]); 494 return; 495 } 496 497 var parsedURL = anchor.href.asParsedURL(); 498 if (parsedURL && parsedURL.scheme === "webkit-link-action") { 499 if (parsedURL.host === "show-panel") { 500 var panel = parsedURL.path.substring(1); 501 if (WebInspector.panel(panel)) 502 WebInspector.showPanel(panel); 503 } 504 return; 505 } 506 507 InspectorFrontendHost.openInNewTab(anchor.href); 508 } 509 510 if (WebInspector.followLinkTimeout) 511 clearTimeout(WebInspector.followLinkTimeout); 512 513 if (anchor.preventFollowOnDoubleClick) { 514 // Start a timeout if this is the first click, if the timeout is canceled 515 // before it fires, then a double clicked happened or another link was clicked. 516 if (event.detail === 1) 517 WebInspector.followLinkTimeout = setTimeout(followLink, 333); 518 return; 519 } 520 521 followLink(); 522 } 523 524 WebInspector.openResource = function(resourceURL, inResourcesPanel) 525 { 526 var resource = WebInspector.resourceForURL(resourceURL); 527 if (inResourcesPanel && resource) 528 WebInspector.showPanel("resources").showResource(resource); 529 else 530 InspectorFrontendHost.openInNewTab(resourceURL); 531 } 532 533 WebInspector._registerShortcuts = function() 534 { 535 var shortcut = WebInspector.KeyboardShortcut; 536 var section = WebInspector.shortcutsScreen.section(WebInspector.UIString("All Panels")); 537 var keys = [ 538 shortcut.makeDescriptor("[", shortcut.Modifiers.CtrlOrMeta), 539 shortcut.makeDescriptor("]", shortcut.Modifiers.CtrlOrMeta) 540 ]; 541 section.addRelatedKeys(keys, WebInspector.UIString("Go to the panel to the left/right")); 542 543 keys = [ 544 shortcut.makeDescriptor("[", shortcut.Modifiers.CtrlOrMeta | shortcut.Modifiers.Alt), 545 shortcut.makeDescriptor("]", shortcut.Modifiers.CtrlOrMeta | shortcut.Modifiers.Alt) 546 ]; 547 section.addRelatedKeys(keys, WebInspector.UIString("Go back/forward in panel history")); 548 549 var toggleConsoleLabel = WebInspector.UIString("Show console"); 550 section.addKey(shortcut.makeDescriptor(shortcut.Keys.Tilde, shortcut.Modifiers.Ctrl), toggleConsoleLabel); 551 var doNotOpenDrawerOnEsc = WebInspector.experimentsSettings.doNotOpenDrawerOnEsc.isEnabled(); 552 var toggleDrawerLabel = doNotOpenDrawerOnEsc ? WebInspector.UIString("Hide drawer") : WebInspector.UIString("Toggle drawer"); 553 section.addKey(shortcut.makeDescriptor(shortcut.Keys.Esc), toggleDrawerLabel); 554 section.addKey(shortcut.makeDescriptor("f", shortcut.Modifiers.CtrlOrMeta), WebInspector.UIString("Search")); 555 556 var advancedSearchShortcut = WebInspector.AdvancedSearchController.createShortcut(); 557 section.addKey(advancedSearchShortcut, WebInspector.UIString("Search across all sources")); 558 559 var inspectElementModeShortcut = WebInspector.InspectElementModeController.createShortcut(); 560 section.addKey(inspectElementModeShortcut, WebInspector.UIString("Select node to inspect")); 561 562 var openResourceShortcut = WebInspector.KeyboardShortcut.makeDescriptor("o", WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta); 563 section.addKey(openResourceShortcut, WebInspector.UIString("Go to source")); 564 565 if (WebInspector.isMac()) { 566 keys = [ 567 shortcut.makeDescriptor("g", shortcut.Modifiers.Meta), 568 shortcut.makeDescriptor("g", shortcut.Modifiers.Meta | shortcut.Modifiers.Shift) 569 ]; 570 section.addRelatedKeys(keys, WebInspector.UIString("Find next/previous")); 571 } 572 573 var goToShortcut = WebInspector.GoToLineDialog.createShortcut(); 574 section.addKey(goToShortcut, WebInspector.UIString("Go to line")); 575 576 keys = [ 577 shortcut.Keys.F1, 578 shortcut.makeDescriptor("?") 579 ]; 580 section.addAlternateKeys(keys, WebInspector.UIString("Show general settings")); 581 } 582 583 WebInspector.documentKeyDown = function(event) 584 { 585 if (WebInspector.currentFocusElement() && WebInspector.currentFocusElement().handleKeyEvent) { 586 WebInspector.currentFocusElement().handleKeyEvent(event); 587 if (event.handled) { 588 event.consume(true); 589 return; 590 } 591 } 592 593 if (WebInspector.inspectorView.currentPanel()) { 594 WebInspector.inspectorView.currentPanel().handleShortcut(event); 595 if (event.handled) { 596 event.consume(true); 597 return; 598 } 599 } 600 601 if (WebInspector.advancedSearchController.handleShortcut(event)) 602 return; 603 if (WebInspector.inspectElementModeController && WebInspector.inspectElementModeController.handleShortcut(event)) 604 return; 605 606 switch (event.keyIdentifier) { 607 case "U+004F": // O key 608 case "U+0050": // P key 609 if (!event.shiftKey && !event.altKey && WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event)) { 610 WebInspector.showPanel("sources").showGoToSourceDialog(); 611 event.consume(true); 612 } 613 break; 614 case "U+0052": // R key 615 if (WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event)) { 616 WebInspector.debuggerModel.skipAllPauses(true, true); 617 WebInspector.resourceTreeModel.reloadPage(event.shiftKey); 618 event.consume(true); 619 } 620 if (window.DEBUG && event.altKey) { 621 WebInspector.reload(); 622 return; 623 } 624 break; 625 case "F5": 626 if (!WebInspector.isMac()) { 627 WebInspector.resourceTreeModel.reloadPage(event.ctrlKey || event.shiftKey); 628 event.consume(true); 629 } 630 break; 631 } 632 633 var isValidZoomShortcut = WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event) && 634 !event.altKey && 635 !InspectorFrontendHost.isStub; 636 switch (event.keyCode) { 637 case 107: // + 638 case 187: // + 639 if (isValidZoomShortcut) { 640 WebInspector._zoomIn(); 641 event.consume(true); 642 } 643 break; 644 case 109: // - 645 case 189: // - 646 if (isValidZoomShortcut) { 647 WebInspector._zoomOut(); 648 event.consume(true); 649 } 650 break; 651 case 48: // 0 652 case 96: // Numpad 0 653 // Zoom reset shortcut does not allow "Shift" when handled by the browser. 654 if (isValidZoomShortcut && !event.shiftKey) { 655 WebInspector._resetZoom(); 656 event.consume(true); 657 } 658 break; 659 } 660 661 } 662 663 WebInspector.postDocumentKeyDown = function(event) 664 { 665 const helpKey = WebInspector.isMac() ? "U+003F" : "U+00BF"; // "?" for both platforms 666 667 if (event.keyIdentifier === "F1" || 668 (event.keyIdentifier === helpKey && event.shiftKey && (!WebInspector.isBeingEdited(event.target) || event.metaKey))) { 669 this.settingsController.showSettingsScreen(WebInspector.SettingsScreen.Tabs.General); 670 event.consume(true); 671 return; 672 } 673 674 const Esc = "U+001B"; 675 676 if (event.handled) 677 return; 678 679 var doNotOpenDrawerOnEsc = WebInspector.experimentsSettings.doNotOpenDrawerOnEsc.isEnabled(); 680 if (event.keyIdentifier === Esc) { 681 if (this.inspectorView.drawer().visible()) 682 this.inspectorView.drawer().hide(); 683 else if (!doNotOpenDrawerOnEsc) 684 this.inspectorView.drawer().show(); 685 } 686 687 if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Tilde.code && event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey) 688 this.showConsole(); 689 } 690 691 WebInspector.documentCanCopy = function(event) 692 { 693 if (WebInspector.inspectorView.currentPanel() && WebInspector.inspectorView.currentPanel().handleCopyEvent) 694 event.preventDefault(); 695 } 696 697 WebInspector.documentCopy = function(event) 698 { 699 if (WebInspector.inspectorView.currentPanel() && WebInspector.inspectorView.currentPanel().handleCopyEvent) 700 WebInspector.inspectorView.currentPanel().handleCopyEvent(event); 701 } 702 703 WebInspector.contextMenuEventFired = function(event) 704 { 705 if (event.handled || event.target.classList.contains("popup-glasspane")) 706 event.preventDefault(); 707 } 708 709 WebInspector.showPanel = function(panel) 710 { 711 return WebInspector.inspectorView.showPanel(panel); 712 } 713 714 WebInspector.panel = function(panel) 715 { 716 return WebInspector.inspectorView.panel(panel); 717 } 718 719 WebInspector.bringToFront = function() 720 { 721 InspectorFrontendHost.bringToFront(); 722 } 723 724 /** 725 * @param {string=} messageLevel 726 * @param {boolean=} showConsole 727 */ 728 WebInspector.log = function(message, messageLevel, showConsole) 729 { 730 // remember 'this' for setInterval() callback 731 var self = this; 732 733 // return indication if we can actually log a message 734 function isLogAvailable() 735 { 736 return WebInspector.ConsoleMessage && WebInspector.RemoteObject && self.console; 737 } 738 739 // flush the queue of pending messages 740 function flushQueue() 741 { 742 var queued = WebInspector.log.queued; 743 if (!queued) 744 return; 745 746 for (var i = 0; i < queued.length; ++i) 747 logMessage(queued[i]); 748 749 delete WebInspector.log.queued; 750 } 751 752 // flush the queue if it console is available 753 // - this function is run on an interval 754 function flushQueueIfAvailable() 755 { 756 if (!isLogAvailable()) 757 return; 758 759 clearInterval(WebInspector.log.interval); 760 delete WebInspector.log.interval; 761 762 flushQueue(); 763 } 764 765 // actually log the message 766 function logMessage(message) 767 { 768 // post the message 769 var msg = WebInspector.ConsoleMessage.create( 770 WebInspector.ConsoleMessage.MessageSource.Other, 771 messageLevel || WebInspector.ConsoleMessage.MessageLevel.Debug, 772 message); 773 774 self.console.addMessage(msg); 775 if (showConsole) 776 WebInspector.showConsole(); 777 } 778 779 // if we can't log the message, queue it 780 if (!isLogAvailable()) { 781 if (!WebInspector.log.queued) 782 WebInspector.log.queued = []; 783 784 WebInspector.log.queued.push(message); 785 786 if (!WebInspector.log.interval) 787 WebInspector.log.interval = setInterval(flushQueueIfAvailable, 1000); 788 789 return; 790 } 791 792 // flush the pending queue if any 793 flushQueue(); 794 795 // log the message 796 logMessage(message); 797 } 798 799 WebInspector.showErrorMessage = function(error) 800 { 801 WebInspector.log(error, WebInspector.ConsoleMessage.MessageLevel.Error, true); 802 } 803 804 // Inspector.inspect protocol event 805 WebInspector.inspect = function(payload, hints) 806 { 807 var object = WebInspector.RemoteObject.fromPayload(payload); 808 if (object.subtype === "node") { 809 function callback(nodeId) 810 { 811 WebInspector._updateFocusedNode(nodeId); 812 object.release(); 813 } 814 object.pushNodeToFrontend(callback); 815 WebInspector.showPanel("elements"); 816 return; 817 } 818 819 if (object.type === "function") { 820 /** 821 * @param {?Protocol.Error} error 822 * @param {!DebuggerAgent.FunctionDetails} response 823 */ 824 function didGetDetails(error, response) 825 { 826 object.release(); 827 828 if (error) { 829 console.error(error); 830 return; 831 } 832 833 var uiLocation = WebInspector.debuggerModel.rawLocationToUILocation(response.location); 834 if (!uiLocation) 835 return; 836 837 WebInspector.panel("sources").showUILocation(uiLocation, true); 838 } 839 DebuggerAgent.getFunctionDetails(object.objectId, didGetDetails.bind(this)); 840 return; 841 } 842 843 if (hints.databaseId) 844 WebInspector.showPanel("resources").selectDatabase(WebInspector.databaseModel.databaseForId(hints.databaseId)); 845 else if (hints.domStorageId) 846 WebInspector.showPanel("resources").selectDOMStorage(WebInspector.domStorageModel.storageForId(hints.domStorageId)); 847 else if (hints.copyToClipboard) 848 InspectorFrontendHost.copyText(object.value); 849 object.release(); 850 } 851 852 // Inspector.detached protocol event 853 WebInspector.detached = function(reason) 854 { 855 WebInspector.socket._detachReason = reason; 856 (new WebInspector.RemoteDebuggingTerminatedScreen(reason)).showModal(); 857 } 858 859 WebInspector.targetCrashed = function() 860 { 861 (new WebInspector.HelpScreenUntilReload( 862 WebInspector.UIString("Inspected target crashed"), 863 WebInspector.UIString("Inspected target has crashed. Once it reloads we will attach to it automatically."))).showModal(); 864 } 865 866 WebInspector._inspectNodeRequested = function(event) 867 { 868 WebInspector._updateFocusedNode(event.data); 869 } 870 871 WebInspector._updateFocusedNode = function(nodeId) 872 { 873 if (WebInspector.inspectElementModeController && WebInspector.inspectElementModeController.enabled()) { 874 InspectorFrontendHost.bringToFront(); 875 WebInspector.inspectElementModeController.disable(); 876 } 877 WebInspector.showPanel("elements").revealAndSelectNode(nodeId); 878 } 879 880 WebInspector.showAnchorLocation = function(anchor) 881 { 882 var preferredPanel = this.panels[anchor.preferredPanel]; 883 if (preferredPanel && WebInspector._showAnchorLocationInPanel(anchor, preferredPanel)) 884 return true; 885 if (WebInspector._showAnchorLocationInPanel(anchor, this.panel("sources"))) 886 return true; 887 if (WebInspector._showAnchorLocationInPanel(anchor, this.panel("resources"))) 888 return true; 889 if (WebInspector._showAnchorLocationInPanel(anchor, this.panel("network"))) 890 return true; 891 return false; 892 } 893 894 WebInspector._showAnchorLocationInPanel = function(anchor, panel) 895 { 896 if (!panel) 897 return false; 898 899 var result = panel.showAnchorLocation(anchor); 900 if (result) { 901 // FIXME: support webkit-html-external-link links here. 902 if (anchor.classList.contains("webkit-html-external-link")) { 903 anchor.classList.remove("webkit-html-external-link"); 904 anchor.classList.add("webkit-html-resource-link"); 905 } 906 } 907 return result; 908 } 909 910 WebInspector.evaluateInConsole = function(expression, showResultOnly) 911 { 912 this.showConsole(); 913 this.consoleView.evaluateUsingTextPrompt(expression, showResultOnly); 914 } 915 916 WebInspector.addMainEventListeners = function(doc) 917 { 918 doc.addEventListener("keydown", this.documentKeyDown.bind(this), true); 919 doc.addEventListener("keydown", this.postDocumentKeyDown.bind(this), false); 920 doc.addEventListener("beforecopy", this.documentCanCopy.bind(this), true); 921 doc.addEventListener("copy", this.documentCopy.bind(this), false); 922 doc.addEventListener("contextmenu", this.contextMenuEventFired.bind(this), true); 923 doc.addEventListener("click", this.documentClick.bind(this), true); 924 } 925 926 WebInspector.Zoom = { 927 Table: [0.25, 0.33, 0.5, 0.66, 0.75, 0.9, 1, 1.1, 1.25, 1.5, 1.75, 2, 2.5, 3, 4, 5], 928 DefaultOffset: 6 929 } 930 931 932 // Ex-DevTools.js content 933 934 /** 935 * @param {!ExtensionDescriptor} extensionInfo 936 * @return {string} 937 */ 938 function buildPlatformExtensionAPI(extensionInfo) 939 { 940 return "var extensionInfo = " + JSON.stringify(extensionInfo) + ";" + 941 "var tabId = " + WebInspector._inspectedTabId + ";" + 942 platformExtensionAPI.toString(); 943 } 944 945 WebInspector.setInspectedTabId = function(tabId) 946 { 947 WebInspector._inspectedTabId = tabId; 948 } 949 950 /** 951 * @return {string} 952 */ 953 WebInspector.getSelectionBackgroundColor = function() 954 { 955 return InspectorFrontendHost.getSelectionBackgroundColor(); 956 } 957 958 /** 959 * @return {string} 960 */ 961 WebInspector.getSelectionForegroundColor = function() 962 { 963 return InspectorFrontendHost.getSelectionForegroundColor(); 964 } 965 966 window.DEBUG = true; 967