OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 /** |
| 6 * @fileoverview Tools is a main class that wires all components of the |
| 7 * DevTools frontend together. It is also responsible for overriding existing |
| 8 * WebInspector functionality while it is getting upstreamed into WebCore. |
| 9 */ |
| 10 goog.provide('devtools.Tools'); |
| 11 |
| 12 goog.require('devtools.DebuggerAgent'); |
| 13 |
| 14 |
| 15 /** |
| 16 * Dispatches raw message from the host. |
| 17 * @param {string} remoteName |
| 18 * @prama {string} methodName |
| 19 * @param {string} param1, param2, param3 Arguments to dispatch. |
| 20 */ |
| 21 devtools$$dispatch = function(remoteName, methodName, param1, param2, param3) { |
| 22 remoteName = 'Remote' + remoteName.substring(0, remoteName.length - 8); |
| 23 var agent = window[remoteName]; |
| 24 if (!agent) { |
| 25 debugPrint('No remote agent "' + remoteName + '" found.'); |
| 26 return; |
| 27 } |
| 28 var method = agent[methodName]; |
| 29 if (!method) { |
| 30 debugPrint('No method "' + remoteName + '.' + methodName + '" found.'); |
| 31 return; |
| 32 } |
| 33 method.call(this, param1, param2, param3); |
| 34 }; |
| 35 |
| 36 |
| 37 devtools.ToolsAgent = function() { |
| 38 RemoteToolsAgent.DidExecuteUtilityFunction = |
| 39 devtools.Callback.processCallback; |
| 40 RemoteToolsAgent.FrameNavigate = |
| 41 goog.bind(this.frameNavigate_, this); |
| 42 RemoteToolsAgent.DispatchOnClient = |
| 43 goog.bind(this.dispatchOnClient_, this); |
| 44 this.debuggerAgent_ = new devtools.DebuggerAgent(); |
| 45 }; |
| 46 |
| 47 |
| 48 /** |
| 49 * Resets tools agent to its initial state. |
| 50 */ |
| 51 devtools.ToolsAgent.prototype.reset = function() { |
| 52 DevToolsHost.reset(); |
| 53 this.debuggerAgent_.reset(); |
| 54 }; |
| 55 |
| 56 |
| 57 /** |
| 58 * @param {string} script Script exression to be evaluated in the context of the |
| 59 * inspected page. |
| 60 * @param {function(Object|string, boolean):undefined} opt_callback Function to |
| 61 * call with the result. |
| 62 */ |
| 63 devtools.ToolsAgent.prototype.evaluateJavaScript = function(script, |
| 64 opt_callback) { |
| 65 InspectorController.evaluate(script, opt_callback || function() {}); |
| 66 }; |
| 67 |
| 68 |
| 69 /** |
| 70 * @return {devtools.DebuggerAgent} Debugger agent instance. |
| 71 */ |
| 72 devtools.ToolsAgent.prototype.getDebuggerAgent = function() { |
| 73 return this.debuggerAgent_; |
| 74 }; |
| 75 |
| 76 |
| 77 /** |
| 78 * @param {string} url Url frame navigated to. |
| 79 * @see tools_agent.h |
| 80 * @private |
| 81 */ |
| 82 devtools.ToolsAgent.prototype.frameNavigate_ = function(url) { |
| 83 this.reset(); |
| 84 // Do not reset Profiles panel. |
| 85 var profiles = null; |
| 86 if ('profiles' in WebInspector.panels) { |
| 87 profiles = WebInspector.panels['profiles']; |
| 88 delete WebInspector.panels['profiles']; |
| 89 } |
| 90 WebInspector.reset(); |
| 91 if (profiles != null) { |
| 92 WebInspector.panels['profiles'] = profiles; |
| 93 } |
| 94 }; |
| 95 |
| 96 |
| 97 /** |
| 98 * @param {string} message Serialized call to be dispatched on WebInspector. |
| 99 * @private |
| 100 */ |
| 101 devtools.ToolsAgent.prototype.dispatchOnClient_ = function(message) { |
| 102 WebInspector.dispatch.apply(WebInspector, JSON.parse(message)); |
| 103 }; |
| 104 |
| 105 |
| 106 /** |
| 107 * Evaluates js expression. |
| 108 * @param {string} expr |
| 109 */ |
| 110 devtools.ToolsAgent.prototype.evaluate = function(expr) { |
| 111 RemoteToolsAgent.evaluate(expr); |
| 112 }; |
| 113 |
| 114 |
| 115 /** |
| 116 * Enables / disables resources panel in the ui. |
| 117 * @param {boolean} enabled New panel status. |
| 118 */ |
| 119 WebInspector.setResourcesPanelEnabled = function(enabled) { |
| 120 InspectorController.resourceTrackingEnabled_ = enabled; |
| 121 WebInspector.panels.resources.reset(); |
| 122 }; |
| 123 |
| 124 |
| 125 /** |
| 126 * Prints string to the inspector console or shows alert if the console doesn't |
| 127 * exist. |
| 128 * @param {string} text |
| 129 */ |
| 130 function debugPrint(text) { |
| 131 var console = WebInspector.console; |
| 132 if (console) { |
| 133 console.addMessage(new WebInspector.ConsoleMessage( |
| 134 WebInspector.ConsoleMessage.MessageSource.JS, |
| 135 WebInspector.ConsoleMessage.MessageType.Log, |
| 136 WebInspector.ConsoleMessage.MessageLevel.Log, |
| 137 1, 'chrome://devtools/<internal>', undefined, -1, text)); |
| 138 } else { |
| 139 alert(text); |
| 140 } |
| 141 } |
| 142 |
| 143 |
| 144 /** |
| 145 * Global instance of the tools agent. |
| 146 * @type {devtools.ToolsAgent} |
| 147 */ |
| 148 devtools.tools = null; |
| 149 |
| 150 |
| 151 var context = {}; // Used by WebCore's inspector routines. |
| 152 |
| 153 /////////////////////////////////////////////////////////////////////////////// |
| 154 // Here and below are overrides to existing WebInspector methods only. |
| 155 // TODO(pfeldman): Patch WebCore and upstream changes. |
| 156 var oldLoaded = WebInspector.loaded; |
| 157 WebInspector.loaded = function() { |
| 158 devtools.tools = new devtools.ToolsAgent(); |
| 159 devtools.tools.reset(); |
| 160 |
| 161 Preferences.ignoreWhitespace = false; |
| 162 Preferences.samplingCPUProfiler = true; |
| 163 oldLoaded.call(this); |
| 164 |
| 165 // Hide dock button on Mac OS. |
| 166 // TODO(pfeldman): remove once Mac OS docking is implemented. |
| 167 if (InspectorController.platform().indexOf('mac') == 0) { |
| 168 document.getElementById('dock-status-bar-item').addStyleClass('hidden'); |
| 169 } |
| 170 |
| 171 // Mute refresh action. |
| 172 document.addEventListener("keydown", function(event) { |
| 173 if (event.keyIdentifier == 'F5') { |
| 174 event.preventDefault(); |
| 175 } else if (event.keyIdentifier == 'U+0052' /* 'R' */ && |
| 176 (event.ctrlKey || event.metaKey)) { |
| 177 event.preventDefault(); |
| 178 } |
| 179 }, true); |
| 180 |
| 181 DevToolsHost.loaded(); |
| 182 }; |
| 183 |
| 184 |
| 185 /** |
| 186 * This override is necessary for adding script source asynchronously. |
| 187 * @override |
| 188 */ |
| 189 WebInspector.ScriptView.prototype.setupSourceFrameIfNeeded = function() { |
| 190 if (!this._frameNeedsSetup) { |
| 191 return; |
| 192 } |
| 193 |
| 194 this.attach(); |
| 195 |
| 196 if (this.script.source) { |
| 197 this.didResolveScriptSource_(); |
| 198 } else { |
| 199 var self = this; |
| 200 devtools.tools.getDebuggerAgent().resolveScriptSource( |
| 201 this.script.sourceID, |
| 202 function(source) { |
| 203 self.script.source = source || |
| 204 WebInspector.UIString('<source is not available>'); |
| 205 self.didResolveScriptSource_(); |
| 206 }); |
| 207 } |
| 208 }; |
| 209 |
| 210 |
| 211 /** |
| 212 * Performs source frame setup when script source is aready resolved. |
| 213 */ |
| 214 WebInspector.ScriptView.prototype.didResolveScriptSource_ = function() { |
| 215 if (!InspectorController.addSourceToFrame( |
| 216 "text/javascript", this.script.source, this.sourceFrame.element)) { |
| 217 return; |
| 218 } |
| 219 |
| 220 delete this._frameNeedsSetup; |
| 221 |
| 222 this.sourceFrame.addEventListener( |
| 223 "syntax highlighting complete", this._syntaxHighlightingComplete, this); |
| 224 this.sourceFrame.syntaxHighlightJavascript(); |
| 225 }; |
| 226 |
| 227 |
| 228 /** |
| 229 * @param {string} type Type of the the property value('object' or 'function'). |
| 230 * @param {string} className Class name of the property value. |
| 231 * @constructor |
| 232 */ |
| 233 WebInspector.UnresolvedPropertyValue = function(type, className) { |
| 234 this.type = type; |
| 235 this.className = className; |
| 236 }; |
| 237 |
| 238 |
| 239 /** |
| 240 * This function overrides standard searchableViews getters to perform search |
| 241 * only in the current view (other views are loaded asynchronously, no way to |
| 242 * search them yet). |
| 243 */ |
| 244 WebInspector.searchableViews_ = function() { |
| 245 var views = []; |
| 246 const visibleView = this.visibleView; |
| 247 if (visibleView && visibleView.performSearch) { |
| 248 views.push(visibleView); |
| 249 } |
| 250 return views; |
| 251 }; |
| 252 |
| 253 |
| 254 /** |
| 255 * @override |
| 256 */ |
| 257 WebInspector.ResourcesPanel.prototype.__defineGetter__( |
| 258 'searchableViews', |
| 259 WebInspector.searchableViews_); |
| 260 |
| 261 |
| 262 /** |
| 263 * @override |
| 264 */ |
| 265 WebInspector.ScriptsPanel.prototype.__defineGetter__( |
| 266 'searchableViews', |
| 267 WebInspector.searchableViews_); |
| 268 |
| 269 |
| 270 (function() { |
| 271 var oldShow = WebInspector.ScriptsPanel.prototype.show; |
| 272 WebInspector.ScriptsPanel.prototype.show = function() { |
| 273 devtools.tools.getDebuggerAgent().initUI(); |
| 274 this.enableToggleButton.visible = false; |
| 275 oldShow.call(this); |
| 276 }; |
| 277 })(); |
| 278 |
| 279 |
| 280 (function InterceptProfilesPanelEvents() { |
| 281 var oldShow = WebInspector.ProfilesPanel.prototype.show; |
| 282 WebInspector.ProfilesPanel.prototype.show = function() { |
| 283 devtools.tools.getDebuggerAgent().initializeProfiling(); |
| 284 this.enableToggleButton.visible = false; |
| 285 oldShow.call(this); |
| 286 // Show is called on every show event of a panel, so |
| 287 // we only need to intercept it once. |
| 288 WebInspector.ProfilesPanel.prototype.show = oldShow; |
| 289 }; |
| 290 })(); |
| 291 |
| 292 |
| 293 /* |
| 294 * @override |
| 295 * TODO(mnaganov): Restore l10n when it will be agreed that it is needed. |
| 296 */ |
| 297 WebInspector.UIString = function(string) { |
| 298 return String.vsprintf(string, Array.prototype.slice.call(arguments, 1)); |
| 299 }; |
| 300 |
| 301 |
| 302 // There is no clear way of setting frame title yet. So sniffing main resource |
| 303 // load. |
| 304 (function OverrideUpdateResource() { |
| 305 var originalUpdateResource = WebInspector.updateResource; |
| 306 WebInspector.updateResource = function(identifier, payload) { |
| 307 originalUpdateResource.call(this, identifier, payload); |
| 308 var resource = this.resources[identifier]; |
| 309 if (resource && resource.mainResource && resource.finished) { |
| 310 document.title = |
| 311 WebInspector.UIString('Developer Tools - %s', resource.url); |
| 312 } |
| 313 }; |
| 314 })(); |
| 315 |
| 316 |
| 317 // Highlight extension content scripts in the scripts list. |
| 318 (function () { |
| 319 var original = WebInspector.ScriptsPanel.prototype._addScriptToFilesMenu; |
| 320 WebInspector.ScriptsPanel.prototype._addScriptToFilesMenu = function(script) { |
| 321 var result = original.apply(this, arguments); |
| 322 var debuggerAgent = devtools.tools.getDebuggerAgent(); |
| 323 var type = debuggerAgent.getScriptContextType(script.sourceID); |
| 324 var option = script.filesSelectOption; |
| 325 if (type == 'injected' && option) { |
| 326 option.addStyleClass('injected'); |
| 327 } |
| 328 return result; |
| 329 }; |
| 330 })(); |
| 331 |
| 332 |
| 333 /** Pending WebKit upstream by apavlov). Fixes iframe vs drag problem. */ |
| 334 (function() { |
| 335 var originalDragStart = WebInspector.elementDragStart; |
| 336 WebInspector.elementDragStart = function(element) { |
| 337 var glassPane = document.createElement("div"); |
| 338 glassPane.style.cssText = |
| 339 'position:absolute;width:100%;height:100%;opacity:0;z-index:1'; |
| 340 glassPane.id = 'glass-pane-for-drag'; |
| 341 element.parentElement.appendChild(glassPane); |
| 342 |
| 343 originalDragStart.apply(this, arguments); |
| 344 }; |
| 345 |
| 346 var originalDragEnd = WebInspector.elementDragEnd; |
| 347 WebInspector.elementDragEnd = function() { |
| 348 originalDragEnd.apply(this, arguments); |
| 349 |
| 350 var glassPane = document.getElementById('glass-pane-for-drag'); |
| 351 glassPane.parentElement.removeChild(glassPane); |
| 352 }; |
| 353 })(); |
| 354 |
| 355 |
| 356 (function() { |
| 357 var originalCreatePanels = WebInspector._createPanels; |
| 358 WebInspector._createPanels = function() { |
| 359 originalCreatePanels.apply(this, arguments); |
| 360 this.panels.heap = new WebInspector.HeapProfilerPanel(); |
| 361 }; |
| 362 })(); |
| 363 |
| 364 |
| 365 (function () { |
| 366 var orig = InjectedScriptAccess.getProperties; |
| 367 InjectedScriptAccess.getProperties = function( |
| 368 objectProxy, ignoreHasOwnProperty, callback) { |
| 369 if (objectProxy.isScope) { |
| 370 devtools.tools.getDebuggerAgent().resolveScope(objectProxy.objectId, |
| 371 callback); |
| 372 } else if (objectProxy.isV8Ref) { |
| 373 devtools.tools.getDebuggerAgent().resolveChildren(objectProxy.objectId, |
| 374 callback, true); |
| 375 } else { |
| 376 orig.apply(this, arguments); |
| 377 } |
| 378 }; |
| 379 })() |
| 380 |
| 381 |
| 382 WebInspector.resourceTrackingWasEnabled = function() |
| 383 { |
| 384 InspectorController.resourceTrackingEnabled_ = true; |
| 385 this.panels.resources.resourceTrackingWasEnabled(); |
| 386 }; |
| 387 |
| 388 WebInspector.resourceTrackingWasDisabled = function() |
| 389 { |
| 390 InspectorController.resourceTrackingEnabled_ = false; |
| 391 this.panels.resources.resourceTrackingWasDisabled(); |
| 392 }; |
OLD | NEW |