| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2014 The Chromium Authors. All rights reserved. | 2 * Copyright 2014 The Chromium Authors. All rights reserved. |
| 3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
| 4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
| 5 */ | 5 */ |
| 6 | |
| 7 /** | 6 /** |
| 8 * @constructor | 7 * @unrestricted |
| 9 * @extends {WebInspector.Object} | |
| 10 */ | 8 */ |
| 11 WebInspector.TargetManager = function() | 9 WebInspector.TargetManager = class extends WebInspector.Object { |
| 12 { | 10 constructor() { |
| 13 WebInspector.Object.call(this); | 11 super(); |
| 14 /** @type {!Array.<!WebInspector.Target>} */ | 12 /** @type {!Array.<!WebInspector.Target>} */ |
| 15 this._targets = []; | 13 this._targets = []; |
| 16 /** @type {!Array.<!WebInspector.TargetManager.Observer>} */ | 14 /** @type {!Array.<!WebInspector.TargetManager.Observer>} */ |
| 17 this._observers = []; | 15 this._observers = []; |
| 18 this._observerCapabiliesMaskSymbol = Symbol("observerCapabilitiesMask"); | 16 this._observerCapabiliesMaskSymbol = Symbol('observerCapabilitiesMask'); |
| 19 /** @type {!Map<symbol, !Array<{modelClass: !Function, thisObject: (!Object|
undefined), listener: function(!WebInspector.Event)}>>} */ | 17 /** @type {!Map<symbol, !Array<{modelClass: !Function, thisObject: (!Object|
undefined), listener: function(!WebInspector.Event)}>>} */ |
| 20 this._modelListeners = new Map(); | 18 this._modelListeners = new Map(); |
| 21 this._isSuspended = false; | 19 this._isSuspended = false; |
| 20 } |
| 21 |
| 22 suspendAllTargets() { |
| 23 if (this._isSuspended) |
| 24 return; |
| 25 this._isSuspended = true; |
| 26 this.dispatchEventToListeners(WebInspector.TargetManager.Events.SuspendState
Changed); |
| 27 |
| 28 for (var i = 0; i < this._targets.length; ++i) { |
| 29 for (var model of this._targets[i].models()) |
| 30 model.suspendModel(); |
| 31 } |
| 32 } |
| 33 |
| 34 /** |
| 35 * @return {!Promise} |
| 36 */ |
| 37 resumeAllTargets() { |
| 38 if (!this._isSuspended) |
| 39 throw new Error('Not suspended'); |
| 40 this._isSuspended = false; |
| 41 this.dispatchEventToListeners(WebInspector.TargetManager.Events.SuspendState
Changed); |
| 42 |
| 43 var promises = []; |
| 44 for (var i = 0; i < this._targets.length; ++i) { |
| 45 for (var model of this._targets[i].models()) |
| 46 promises.push(model.resumeModel()); |
| 47 } |
| 48 return Promise.all(promises); |
| 49 } |
| 50 |
| 51 suspendAndResumeAllTargets() { |
| 52 this.suspendAllTargets(); |
| 53 this.resumeAllTargets(); |
| 54 } |
| 55 |
| 56 /** |
| 57 * @return {boolean} |
| 58 */ |
| 59 allTargetsSuspended() { |
| 60 return this._isSuspended; |
| 61 } |
| 62 |
| 63 /** |
| 64 * @return {string} |
| 65 */ |
| 66 inspectedURL() { |
| 67 return this._targets[0] ? this._targets[0].inspectedURL() : ''; |
| 68 } |
| 69 |
| 70 /** |
| 71 * @param {!WebInspector.TargetManager.Events} eventName |
| 72 * @param {!WebInspector.Event} event |
| 73 */ |
| 74 _redispatchEvent(eventName, event) { |
| 75 this.dispatchEventToListeners(eventName, event.data); |
| 76 } |
| 77 |
| 78 /** |
| 79 * @param {boolean=} bypassCache |
| 80 * @param {string=} injectedScript |
| 81 */ |
| 82 reloadPage(bypassCache, injectedScript) { |
| 83 if (!this._targets.length) |
| 84 return; |
| 85 |
| 86 var resourceTreeModel = WebInspector.ResourceTreeModel.fromTarget(this._targ
ets[0]); |
| 87 if (!resourceTreeModel) |
| 88 return; |
| 89 |
| 90 resourceTreeModel.reloadPage(bypassCache, injectedScript); |
| 91 } |
| 92 |
| 93 /** |
| 94 * @param {!Function} modelClass |
| 95 * @param {symbol} eventType |
| 96 * @param {function(!WebInspector.Event)} listener |
| 97 * @param {!Object=} thisObject |
| 98 */ |
| 99 addModelListener(modelClass, eventType, listener, thisObject) { |
| 100 for (var i = 0; i < this._targets.length; ++i) { |
| 101 var model = this._targets[i].model(modelClass); |
| 102 if (model) |
| 103 model.addEventListener(eventType, listener, thisObject); |
| 104 } |
| 105 if (!this._modelListeners.has(eventType)) |
| 106 this._modelListeners.set(eventType, []); |
| 107 this._modelListeners.get(eventType).push({modelClass: modelClass, thisObject
: thisObject, listener: listener}); |
| 108 } |
| 109 |
| 110 /** |
| 111 * @param {!Function} modelClass |
| 112 * @param {symbol} eventType |
| 113 * @param {function(!WebInspector.Event)} listener |
| 114 * @param {!Object=} thisObject |
| 115 */ |
| 116 removeModelListener(modelClass, eventType, listener, thisObject) { |
| 117 if (!this._modelListeners.has(eventType)) |
| 118 return; |
| 119 |
| 120 for (var i = 0; i < this._targets.length; ++i) { |
| 121 var model = this._targets[i].model(modelClass); |
| 122 if (model) |
| 123 model.removeEventListener(eventType, listener, thisObject); |
| 124 } |
| 125 |
| 126 var listeners = this._modelListeners.get(eventType); |
| 127 for (var i = 0; i < listeners.length; ++i) { |
| 128 if (listeners[i].modelClass === modelClass && listeners[i].listener === li
stener && |
| 129 listeners[i].thisObject === thisObject) |
| 130 listeners.splice(i--, 1); |
| 131 } |
| 132 if (!listeners.length) |
| 133 this._modelListeners.delete(eventType); |
| 134 } |
| 135 |
| 136 /** |
| 137 * @param {!WebInspector.TargetManager.Observer} targetObserver |
| 138 * @param {number=} capabilitiesMask |
| 139 */ |
| 140 observeTargets(targetObserver, capabilitiesMask) { |
| 141 if (this._observerCapabiliesMaskSymbol in targetObserver) |
| 142 throw new Error('Observer can only be registered once'); |
| 143 targetObserver[this._observerCapabiliesMaskSymbol] = capabilitiesMask || 0; |
| 144 this.targets(capabilitiesMask).forEach(targetObserver.targetAdded.bind(targe
tObserver)); |
| 145 this._observers.push(targetObserver); |
| 146 } |
| 147 |
| 148 /** |
| 149 * @param {!WebInspector.TargetManager.Observer} targetObserver |
| 150 */ |
| 151 unobserveTargets(targetObserver) { |
| 152 delete targetObserver[this._observerCapabiliesMaskSymbol]; |
| 153 this._observers.remove(targetObserver); |
| 154 } |
| 155 |
| 156 /** |
| 157 * @param {string} name |
| 158 * @param {number} capabilitiesMask |
| 159 * @param {!InspectorBackendClass.Connection.Factory} connectionFactory |
| 160 * @param {?WebInspector.Target} parentTarget |
| 161 * @return {!WebInspector.Target} |
| 162 */ |
| 163 createTarget(name, capabilitiesMask, connectionFactory, parentTarget) { |
| 164 var target = new WebInspector.Target(this, name, capabilitiesMask, connectio
nFactory, parentTarget); |
| 165 |
| 166 var logAgent = target.hasLogCapability() ? target.logAgent() : null; |
| 167 |
| 168 /** @type {!WebInspector.ConsoleModel} */ |
| 169 target.consoleModel = new WebInspector.ConsoleModel(target, logAgent); |
| 170 |
| 171 var networkManager = null; |
| 172 var resourceTreeModel = null; |
| 173 if (target.hasNetworkCapability()) |
| 174 networkManager = new WebInspector.NetworkManager(target); |
| 175 if (networkManager && target.hasDOMCapability()) { |
| 176 resourceTreeModel = new WebInspector.ResourceTreeModel( |
| 177 target, networkManager, WebInspector.SecurityOriginManager.fromTarget(
target)); |
| 178 new WebInspector.NetworkLog(target, resourceTreeModel, networkManager); |
| 179 } |
| 180 |
| 181 /** @type {!WebInspector.RuntimeModel} */ |
| 182 target.runtimeModel = new WebInspector.RuntimeModel(target); |
| 183 |
| 184 if (target.hasJSCapability()) |
| 185 new WebInspector.DebuggerModel(target); |
| 186 |
| 187 if (resourceTreeModel) { |
| 188 var domModel = new WebInspector.DOMModel(target); |
| 189 // TODO(eostroukhov) CSSModel should not depend on RTM |
| 190 new WebInspector.CSSModel(target, domModel); |
| 191 } |
| 192 |
| 193 /** @type {?WebInspector.SubTargetsManager} */ |
| 194 target.subTargetsManager = target.hasTargetCapability() ? new WebInspector.S
ubTargetsManager(target) : null; |
| 195 /** @type {!WebInspector.CPUProfilerModel} */ |
| 196 target.cpuProfilerModel = new WebInspector.CPUProfilerModel(target); |
| 197 /** @type {!WebInspector.HeapProfilerModel} */ |
| 198 target.heapProfilerModel = new WebInspector.HeapProfilerModel(target); |
| 199 |
| 200 target.tracingManager = new WebInspector.TracingManager(target); |
| 201 |
| 202 if (target.subTargetsManager && target.hasBrowserCapability()) |
| 203 target.serviceWorkerManager = new WebInspector.ServiceWorkerManager(target
, target.subTargetsManager); |
| 204 |
| 205 this.addTarget(target); |
| 206 return target; |
| 207 } |
| 208 |
| 209 /** |
| 210 * @param {!WebInspector.Target} target |
| 211 * @return {!Array<!WebInspector.TargetManager.Observer>} |
| 212 */ |
| 213 _observersForTarget(target) { |
| 214 return this._observers.filter( |
| 215 (observer) => target.hasAllCapabilities(observer[this._observerCapabilie
sMaskSymbol] || 0)); |
| 216 } |
| 217 |
| 218 /** |
| 219 * @param {!WebInspector.Target} target |
| 220 */ |
| 221 addTarget(target) { |
| 222 this._targets.push(target); |
| 223 var resourceTreeModel = WebInspector.ResourceTreeModel.fromTarget(target); |
| 224 if (this._targets.length === 1 && resourceTreeModel) { |
| 225 resourceTreeModel[WebInspector.TargetManager._listenersSymbol] = [ |
| 226 setupRedispatch.call( |
| 227 this, WebInspector.ResourceTreeModel.Events.MainFrameNavigated, |
| 228 WebInspector.TargetManager.Events.MainFrameNavigated), |
| 229 setupRedispatch.call(this, WebInspector.ResourceTreeModel.Events.Load, W
ebInspector.TargetManager.Events.Load), |
| 230 setupRedispatch.call( |
| 231 this, WebInspector.ResourceTreeModel.Events.PageReloadRequested, |
| 232 WebInspector.TargetManager.Events.PageReloadRequested), |
| 233 setupRedispatch.call( |
| 234 this, WebInspector.ResourceTreeModel.Events.WillReloadPage, |
| 235 WebInspector.TargetManager.Events.WillReloadPage) |
| 236 ]; |
| 237 } |
| 238 var copy = this._observersForTarget(target); |
| 239 for (var i = 0; i < copy.length; ++i) |
| 240 copy[i].targetAdded(target); |
| 241 |
| 242 for (var pair of this._modelListeners) { |
| 243 var listeners = pair[1]; |
| 244 for (var i = 0; i < listeners.length; ++i) { |
| 245 var model = target.model(listeners[i].modelClass); |
| 246 if (model) |
| 247 model.addEventListener(/** @type {symbol} */ (pair[0]), listeners[i].l
istener, listeners[i].thisObject); |
| 248 } |
| 249 } |
| 250 |
| 251 /** |
| 252 * @param {!WebInspector.ResourceTreeModel.Events} sourceEvent |
| 253 * @param {!WebInspector.TargetManager.Events} targetEvent |
| 254 * @return {!WebInspector.EventTarget.EventDescriptor} |
| 255 * @this {WebInspector.TargetManager} |
| 256 */ |
| 257 function setupRedispatch(sourceEvent, targetEvent) { |
| 258 return resourceTreeModel.addEventListener(sourceEvent, this._redispatchEve
nt.bind(this, targetEvent)); |
| 259 } |
| 260 } |
| 261 |
| 262 /** |
| 263 * @param {!WebInspector.Target} target |
| 264 */ |
| 265 removeTarget(target) { |
| 266 if (!this._targets.includes(target)) |
| 267 return; |
| 268 this._targets.remove(target); |
| 269 var resourceTreeModel = WebInspector.ResourceTreeModel.fromTarget(target); |
| 270 var treeModelListeners = resourceTreeModel && resourceTreeModel[WebInspector
.TargetManager._listenersSymbol]; |
| 271 if (treeModelListeners) |
| 272 WebInspector.EventTarget.removeEventListeners(treeModelListeners); |
| 273 |
| 274 var copy = this._observersForTarget(target); |
| 275 for (var i = 0; i < copy.length; ++i) |
| 276 copy[i].targetRemoved(target); |
| 277 |
| 278 for (var pair of this._modelListeners) { |
| 279 var listeners = pair[1]; |
| 280 for (var i = 0; i < listeners.length; ++i) { |
| 281 var model = target.model(listeners[i].modelClass); |
| 282 if (model) |
| 283 model.removeEventListener(/** @type {symbol} */ (pair[0]), listeners[i
].listener, listeners[i].thisObject); |
| 284 } |
| 285 } |
| 286 } |
| 287 |
| 288 /** |
| 289 * @param {number=} capabilitiesMask |
| 290 * @return {!Array.<!WebInspector.Target>} |
| 291 */ |
| 292 targets(capabilitiesMask) { |
| 293 if (!capabilitiesMask) |
| 294 return this._targets.slice(); |
| 295 else |
| 296 return this._targets.filter((target) => target.hasAllCapabilities(capabili
tiesMask || 0)); |
| 297 } |
| 298 |
| 299 /** |
| 300 * |
| 301 * @param {number} id |
| 302 * @return {?WebInspector.Target} |
| 303 */ |
| 304 targetById(id) { |
| 305 for (var i = 0; i < this._targets.length; ++i) { |
| 306 if (this._targets[i].id() === id) |
| 307 return this._targets[i]; |
| 308 } |
| 309 return null; |
| 310 } |
| 311 |
| 312 /** |
| 313 * @return {?WebInspector.Target} |
| 314 */ |
| 315 mainTarget() { |
| 316 return this._targets[0] || null; |
| 317 } |
| 318 |
| 319 /** |
| 320 * @param {!WebInspector.Target} target |
| 321 */ |
| 322 suspendReload(target) { |
| 323 var resourceTreeModel = WebInspector.ResourceTreeModel.fromTarget(target); |
| 324 if (resourceTreeModel) |
| 325 resourceTreeModel.suspendReload(); |
| 326 } |
| 327 |
| 328 /** |
| 329 * @param {!WebInspector.Target} target |
| 330 */ |
| 331 resumeReload(target) { |
| 332 var resourceTreeModel = WebInspector.ResourceTreeModel.fromTarget(target); |
| 333 if (resourceTreeModel) |
| 334 setImmediate(resourceTreeModel.resumeReload.bind(resourceTreeModel)); |
| 335 } |
| 336 |
| 337 /** |
| 338 * @param {function()} webSocketConnectionLostCallback |
| 339 */ |
| 340 connectToMainTarget(webSocketConnectionLostCallback) { |
| 341 this._webSocketConnectionLostCallback = webSocketConnectionLostCallback; |
| 342 this._connectAndCreateMainTarget(); |
| 343 } |
| 344 |
| 345 _connectAndCreateMainTarget() { |
| 346 var capabilities = WebInspector.Target.Capability.Browser | WebInspector.Tar
get.Capability.DOM | |
| 347 WebInspector.Target.Capability.JS | WebInspector.Target.Capability.Log | |
| 348 WebInspector.Target.Capability.Network | WebInspector.Target.Capability.
Target; |
| 349 if (Runtime.queryParam('isSharedWorker')) { |
| 350 capabilities = WebInspector.Target.Capability.Browser | WebInspector.Targe
t.Capability.Log | |
| 351 WebInspector.Target.Capability.Network | WebInspector.Target.Capabilit
y.Target; |
| 352 } else if (Runtime.queryParam('v8only')) { |
| 353 capabilities = WebInspector.Target.Capability.JS; |
| 354 } |
| 355 |
| 356 var target = |
| 357 this.createTarget(WebInspector.UIString('Main'), capabilities, this._cre
ateMainConnection.bind(this), null); |
| 358 target.runtimeAgent().runIfWaitingForDebugger(); |
| 359 } |
| 360 |
| 361 /** |
| 362 * @param {!InspectorBackendClass.Connection.Params} params |
| 363 * @return {!InspectorBackendClass.Connection} |
| 364 */ |
| 365 _createMainConnection(params) { |
| 366 if (Runtime.queryParam('ws')) { |
| 367 var ws = 'ws://' + Runtime.queryParam('ws'); |
| 368 this._mainConnection = new WebInspector.WebSocketConnection(ws, this._webS
ocketConnectionLostCallback, params); |
| 369 } else if (InspectorFrontendHost.isHostedMode()) { |
| 370 this._mainConnection = new WebInspector.StubConnection(params); |
| 371 } else { |
| 372 this._mainConnection = new WebInspector.MainConnection(params); |
| 373 } |
| 374 return this._mainConnection; |
| 375 } |
| 376 |
| 377 /** |
| 378 * @param {function(string)} onMessage |
| 379 * @return {!Promise<!InspectorBackendClass.Connection>} |
| 380 */ |
| 381 interceptMainConnection(onMessage) { |
| 382 var params = {onMessage: onMessage, onDisconnect: this._connectAndCreateMain
Target.bind(this)}; |
| 383 return this._mainConnection.disconnect().then(this._createMainConnection.bin
d(this, params)); |
| 384 } |
| 22 }; | 385 }; |
| 23 | 386 |
| 24 /** @enum {symbol} */ | 387 /** @enum {symbol} */ |
| 25 WebInspector.TargetManager.Events = { | 388 WebInspector.TargetManager.Events = { |
| 26 InspectedURLChanged: Symbol("InspectedURLChanged"), | 389 InspectedURLChanged: Symbol('InspectedURLChanged'), |
| 27 Load: Symbol("Load"), | 390 Load: Symbol('Load'), |
| 28 MainFrameNavigated: Symbol("MainFrameNavigated"), | 391 MainFrameNavigated: Symbol('MainFrameNavigated'), |
| 29 NameChanged: Symbol("NameChanged"), | 392 NameChanged: Symbol('NameChanged'), |
| 30 PageReloadRequested: Symbol("PageReloadRequested"), | 393 PageReloadRequested: Symbol('PageReloadRequested'), |
| 31 WillReloadPage: Symbol("WillReloadPage"), | 394 WillReloadPage: Symbol('WillReloadPage'), |
| 32 TargetDisposed: Symbol("TargetDisposed"), | 395 TargetDisposed: Symbol('TargetDisposed'), |
| 33 SuspendStateChanged: Symbol("SuspendStateChanged") | 396 SuspendStateChanged: Symbol('SuspendStateChanged') |
| 34 }; | 397 }; |
| 35 | 398 |
| 36 WebInspector.TargetManager._listenersSymbol = Symbol("WebInspector.TargetManager
.Listeners"); | 399 WebInspector.TargetManager._listenersSymbol = Symbol('WebInspector.TargetManager
.Listeners'); |
| 37 | |
| 38 WebInspector.TargetManager.prototype = { | |
| 39 suspendAllTargets: function() | |
| 40 { | |
| 41 if (this._isSuspended) | |
| 42 return; | |
| 43 this._isSuspended = true; | |
| 44 this.dispatchEventToListeners(WebInspector.TargetManager.Events.SuspendS
tateChanged); | |
| 45 | |
| 46 for (var i = 0; i < this._targets.length; ++i) { | |
| 47 for (var model of this._targets[i].models()) | |
| 48 model.suspendModel(); | |
| 49 } | |
| 50 }, | |
| 51 | |
| 52 /** | |
| 53 * @return {!Promise} | |
| 54 */ | |
| 55 resumeAllTargets: function() | |
| 56 { | |
| 57 if (!this._isSuspended) | |
| 58 throw new Error("Not suspended"); | |
| 59 this._isSuspended = false; | |
| 60 this.dispatchEventToListeners(WebInspector.TargetManager.Events.SuspendS
tateChanged); | |
| 61 | |
| 62 var promises = []; | |
| 63 for (var i = 0; i < this._targets.length; ++i) { | |
| 64 for (var model of this._targets[i].models()) | |
| 65 promises.push(model.resumeModel()); | |
| 66 } | |
| 67 return Promise.all(promises); | |
| 68 }, | |
| 69 | |
| 70 suspendAndResumeAllTargets: function() | |
| 71 { | |
| 72 this.suspendAllTargets(); | |
| 73 this.resumeAllTargets(); | |
| 74 }, | |
| 75 | |
| 76 /** | |
| 77 * @return {boolean} | |
| 78 */ | |
| 79 allTargetsSuspended: function() | |
| 80 { | |
| 81 return this._isSuspended; | |
| 82 }, | |
| 83 | |
| 84 /** | |
| 85 * @return {string} | |
| 86 */ | |
| 87 inspectedURL: function() | |
| 88 { | |
| 89 return this._targets[0] ? this._targets[0].inspectedURL() : ""; | |
| 90 }, | |
| 91 | |
| 92 /** | |
| 93 * @param {!WebInspector.TargetManager.Events} eventName | |
| 94 * @param {!WebInspector.Event} event | |
| 95 */ | |
| 96 _redispatchEvent: function(eventName, event) | |
| 97 { | |
| 98 this.dispatchEventToListeners(eventName, event.data); | |
| 99 }, | |
| 100 | |
| 101 /** | |
| 102 * @param {boolean=} bypassCache | |
| 103 * @param {string=} injectedScript | |
| 104 */ | |
| 105 reloadPage: function(bypassCache, injectedScript) | |
| 106 { | |
| 107 if (!this._targets.length) | |
| 108 return; | |
| 109 | |
| 110 var resourceTreeModel = WebInspector.ResourceTreeModel.fromTarget(this._
targets[0]); | |
| 111 if (!resourceTreeModel) | |
| 112 return; | |
| 113 | |
| 114 resourceTreeModel.reloadPage(bypassCache, injectedScript); | |
| 115 }, | |
| 116 | |
| 117 /** | |
| 118 * @param {!Function} modelClass | |
| 119 * @param {symbol} eventType | |
| 120 * @param {function(!WebInspector.Event)} listener | |
| 121 * @param {!Object=} thisObject | |
| 122 */ | |
| 123 addModelListener: function(modelClass, eventType, listener, thisObject) | |
| 124 { | |
| 125 for (var i = 0; i < this._targets.length; ++i) { | |
| 126 var model = this._targets[i].model(modelClass); | |
| 127 if (model) | |
| 128 model.addEventListener(eventType, listener, thisObject); | |
| 129 } | |
| 130 if (!this._modelListeners.has(eventType)) | |
| 131 this._modelListeners.set(eventType, []); | |
| 132 this._modelListeners.get(eventType).push({ modelClass: modelClass, thisO
bject: thisObject, listener: listener }); | |
| 133 }, | |
| 134 | |
| 135 /** | |
| 136 * @param {!Function} modelClass | |
| 137 * @param {symbol} eventType | |
| 138 * @param {function(!WebInspector.Event)} listener | |
| 139 * @param {!Object=} thisObject | |
| 140 */ | |
| 141 removeModelListener: function(modelClass, eventType, listener, thisObject) | |
| 142 { | |
| 143 if (!this._modelListeners.has(eventType)) | |
| 144 return; | |
| 145 | |
| 146 for (var i = 0; i < this._targets.length; ++i) { | |
| 147 var model = this._targets[i].model(modelClass); | |
| 148 if (model) | |
| 149 model.removeEventListener(eventType, listener, thisObject); | |
| 150 } | |
| 151 | |
| 152 var listeners = this._modelListeners.get(eventType); | |
| 153 for (var i = 0; i < listeners.length; ++i) { | |
| 154 if (listeners[i].modelClass === modelClass && listeners[i].listener
=== listener && listeners[i].thisObject === thisObject) | |
| 155 listeners.splice(i--, 1); | |
| 156 } | |
| 157 if (!listeners.length) | |
| 158 this._modelListeners.delete(eventType); | |
| 159 }, | |
| 160 | |
| 161 /** | |
| 162 * @param {!WebInspector.TargetManager.Observer} targetObserver | |
| 163 * @param {number=} capabilitiesMask | |
| 164 */ | |
| 165 observeTargets: function(targetObserver, capabilitiesMask) | |
| 166 { | |
| 167 if (this._observerCapabiliesMaskSymbol in targetObserver) | |
| 168 throw new Error("Observer can only be registered once"); | |
| 169 targetObserver[this._observerCapabiliesMaskSymbol] = capabilitiesMask ||
0; | |
| 170 this.targets(capabilitiesMask).forEach(targetObserver.targetAdded.bind(t
argetObserver)); | |
| 171 this._observers.push(targetObserver); | |
| 172 }, | |
| 173 | |
| 174 /** | |
| 175 * @param {!WebInspector.TargetManager.Observer} targetObserver | |
| 176 */ | |
| 177 unobserveTargets: function(targetObserver) | |
| 178 { | |
| 179 delete targetObserver[this._observerCapabiliesMaskSymbol]; | |
| 180 this._observers.remove(targetObserver); | |
| 181 }, | |
| 182 | |
| 183 /** | |
| 184 * @param {string} name | |
| 185 * @param {number} capabilitiesMask | |
| 186 * @param {!InspectorBackendClass.Connection.Factory} connectionFactory | |
| 187 * @param {?WebInspector.Target} parentTarget | |
| 188 * @return {!WebInspector.Target} | |
| 189 */ | |
| 190 createTarget: function(name, capabilitiesMask, connectionFactory, parentTarg
et) | |
| 191 { | |
| 192 var target = new WebInspector.Target(this, name, capabilitiesMask, conne
ctionFactory, parentTarget); | |
| 193 | |
| 194 var logAgent = target.hasLogCapability() ? target.logAgent() : null; | |
| 195 | |
| 196 /** @type {!WebInspector.ConsoleModel} */ | |
| 197 target.consoleModel = new WebInspector.ConsoleModel(target, logAgent); | |
| 198 | |
| 199 var networkManager = null; | |
| 200 var resourceTreeModel = null; | |
| 201 if (target.hasNetworkCapability()) | |
| 202 networkManager = new WebInspector.NetworkManager(target); | |
| 203 if (networkManager && target.hasDOMCapability()) { | |
| 204 resourceTreeModel = new WebInspector.ResourceTreeModel(target, netwo
rkManager, WebInspector.SecurityOriginManager.fromTarget(target)); | |
| 205 new WebInspector.NetworkLog(target, resourceTreeModel, networkManage
r); | |
| 206 } | |
| 207 | |
| 208 /** @type {!WebInspector.RuntimeModel} */ | |
| 209 target.runtimeModel = new WebInspector.RuntimeModel(target); | |
| 210 | |
| 211 if (target.hasJSCapability()) | |
| 212 new WebInspector.DebuggerModel(target); | |
| 213 | |
| 214 if (resourceTreeModel) { | |
| 215 var domModel = new WebInspector.DOMModel(target); | |
| 216 // TODO(eostroukhov) CSSModel should not depend on RTM | |
| 217 new WebInspector.CSSModel(target, domModel); | |
| 218 } | |
| 219 | |
| 220 /** @type {?WebInspector.SubTargetsManager} */ | |
| 221 target.subTargetsManager = target.hasTargetCapability() ? new WebInspect
or.SubTargetsManager(target) : null; | |
| 222 /** @type {!WebInspector.CPUProfilerModel} */ | |
| 223 target.cpuProfilerModel = new WebInspector.CPUProfilerModel(target); | |
| 224 /** @type {!WebInspector.HeapProfilerModel} */ | |
| 225 target.heapProfilerModel = new WebInspector.HeapProfilerModel(target); | |
| 226 | |
| 227 target.tracingManager = new WebInspector.TracingManager(target); | |
| 228 | |
| 229 if (target.subTargetsManager && target.hasBrowserCapability()) | |
| 230 target.serviceWorkerManager = new WebInspector.ServiceWorkerManager(
target, target.subTargetsManager); | |
| 231 | |
| 232 this.addTarget(target); | |
| 233 return target; | |
| 234 }, | |
| 235 | |
| 236 /** | |
| 237 * @param {!WebInspector.Target} target | |
| 238 * @return {!Array<!WebInspector.TargetManager.Observer>} | |
| 239 */ | |
| 240 _observersForTarget: function(target) | |
| 241 { | |
| 242 return this._observers.filter((observer) => target.hasAllCapabilities(ob
server[this._observerCapabiliesMaskSymbol] || 0)); | |
| 243 }, | |
| 244 | |
| 245 /** | |
| 246 * @param {!WebInspector.Target} target | |
| 247 */ | |
| 248 addTarget: function(target) | |
| 249 { | |
| 250 this._targets.push(target); | |
| 251 var resourceTreeModel = WebInspector.ResourceTreeModel.fromTarget(target
); | |
| 252 if (this._targets.length === 1 && resourceTreeModel) { | |
| 253 resourceTreeModel[WebInspector.TargetManager._listenersSymbol] = [ | |
| 254 setupRedispatch.call(this, WebInspector.ResourceTreeModel.Events
.MainFrameNavigated, WebInspector.TargetManager.Events.MainFrameNavigated), | |
| 255 setupRedispatch.call(this, WebInspector.ResourceTreeModel.Events
.Load, WebInspector.TargetManager.Events.Load), | |
| 256 setupRedispatch.call(this, WebInspector.ResourceTreeModel.Events
.PageReloadRequested, WebInspector.TargetManager.Events.PageReloadRequested), | |
| 257 setupRedispatch.call(this, WebInspector.ResourceTreeModel.Events
.WillReloadPage, WebInspector.TargetManager.Events.WillReloadPage) | |
| 258 ]; | |
| 259 } | |
| 260 var copy = this._observersForTarget(target); | |
| 261 for (var i = 0; i < copy.length; ++i) | |
| 262 copy[i].targetAdded(target); | |
| 263 | |
| 264 for (var pair of this._modelListeners) { | |
| 265 var listeners = pair[1]; | |
| 266 for (var i = 0; i < listeners.length; ++i) { | |
| 267 var model = target.model(listeners[i].modelClass); | |
| 268 if (model) | |
| 269 model.addEventListener(/** @type {symbol} */ (pair[0]), list
eners[i].listener, listeners[i].thisObject); | |
| 270 } | |
| 271 } | |
| 272 | |
| 273 /** | |
| 274 * @param {!WebInspector.ResourceTreeModel.Events} sourceEvent | |
| 275 * @param {!WebInspector.TargetManager.Events} targetEvent | |
| 276 * @return {!WebInspector.EventTarget.EventDescriptor} | |
| 277 * @this {WebInspector.TargetManager} | |
| 278 */ | |
| 279 function setupRedispatch(sourceEvent, targetEvent) | |
| 280 { | |
| 281 return resourceTreeModel.addEventListener(sourceEvent, this._redispa
tchEvent.bind(this, targetEvent)); | |
| 282 } | |
| 283 }, | |
| 284 | |
| 285 /** | |
| 286 * @param {!WebInspector.Target} target | |
| 287 */ | |
| 288 removeTarget: function(target) | |
| 289 { | |
| 290 if (!this._targets.includes(target)) | |
| 291 return; | |
| 292 this._targets.remove(target); | |
| 293 var resourceTreeModel = WebInspector.ResourceTreeModel.fromTarget(target
); | |
| 294 var treeModelListeners = resourceTreeModel && resourceTreeModel[WebInspe
ctor.TargetManager._listenersSymbol]; | |
| 295 if (treeModelListeners) | |
| 296 WebInspector.EventTarget.removeEventListeners(treeModelListeners); | |
| 297 | |
| 298 var copy = this._observersForTarget(target); | |
| 299 for (var i = 0; i < copy.length; ++i) | |
| 300 copy[i].targetRemoved(target); | |
| 301 | |
| 302 for (var pair of this._modelListeners) { | |
| 303 var listeners = pair[1]; | |
| 304 for (var i = 0; i < listeners.length; ++i) { | |
| 305 var model = target.model(listeners[i].modelClass); | |
| 306 if (model) | |
| 307 model.removeEventListener(/** @type {symbol} */ (pair[0]), l
isteners[i].listener, listeners[i].thisObject); | |
| 308 } | |
| 309 } | |
| 310 }, | |
| 311 | |
| 312 /** | |
| 313 * @param {number=} capabilitiesMask | |
| 314 * @return {!Array.<!WebInspector.Target>} | |
| 315 */ | |
| 316 targets: function(capabilitiesMask) | |
| 317 { | |
| 318 if (!capabilitiesMask) | |
| 319 return this._targets.slice(); | |
| 320 else | |
| 321 return this._targets.filter((target) => target.hasAllCapabilities(ca
pabilitiesMask || 0)); | |
| 322 }, | |
| 323 | |
| 324 /** | |
| 325 * | |
| 326 * @param {number} id | |
| 327 * @return {?WebInspector.Target} | |
| 328 */ | |
| 329 targetById: function(id) | |
| 330 { | |
| 331 for (var i = 0; i < this._targets.length; ++i) { | |
| 332 if (this._targets[i].id() === id) | |
| 333 return this._targets[i]; | |
| 334 } | |
| 335 return null; | |
| 336 }, | |
| 337 | |
| 338 /** | |
| 339 * @return {?WebInspector.Target} | |
| 340 */ | |
| 341 mainTarget: function() | |
| 342 { | |
| 343 return this._targets[0] || null; | |
| 344 }, | |
| 345 | |
| 346 /** | |
| 347 * @param {!WebInspector.Target} target | |
| 348 */ | |
| 349 suspendReload: function(target) | |
| 350 { | |
| 351 var resourceTreeModel = WebInspector.ResourceTreeModel.fromTarget(target
); | |
| 352 if (resourceTreeModel) | |
| 353 resourceTreeModel.suspendReload(); | |
| 354 }, | |
| 355 | |
| 356 /** | |
| 357 * @param {!WebInspector.Target} target | |
| 358 */ | |
| 359 resumeReload: function(target) | |
| 360 { | |
| 361 var resourceTreeModel = WebInspector.ResourceTreeModel.fromTarget(target
); | |
| 362 if (resourceTreeModel) | |
| 363 setImmediate(resourceTreeModel.resumeReload.bind(resourceTreeModel))
; | |
| 364 }, | |
| 365 | |
| 366 /** | |
| 367 * @param {function()} webSocketConnectionLostCallback | |
| 368 */ | |
| 369 connectToMainTarget: function(webSocketConnectionLostCallback) | |
| 370 { | |
| 371 this._webSocketConnectionLostCallback = webSocketConnectionLostCallback; | |
| 372 this._connectAndCreateMainTarget(); | |
| 373 }, | |
| 374 | |
| 375 _connectAndCreateMainTarget: function() | |
| 376 { | |
| 377 var capabilities = | |
| 378 WebInspector.Target.Capability.Browser | WebInspector.Target.Capabil
ity.DOM | | |
| 379 WebInspector.Target.Capability.JS | WebInspector.Target.Capability.L
og | | |
| 380 WebInspector.Target.Capability.Network | WebInspector.Target.Capabil
ity.Target; | |
| 381 if (Runtime.queryParam("isSharedWorker")) { | |
| 382 capabilities = | |
| 383 WebInspector.Target.Capability.Browser | WebInspector.Target.Cap
ability.Log | | |
| 384 WebInspector.Target.Capability.Network | WebInspector.Target.Cap
ability.Target; | |
| 385 } else if (Runtime.queryParam("v8only")) { | |
| 386 capabilities = WebInspector.Target.Capability.JS; | |
| 387 } | |
| 388 | |
| 389 var target = this.createTarget(WebInspector.UIString("Main"), capabiliti
es, this._createMainConnection.bind(this), null); | |
| 390 target.runtimeAgent().runIfWaitingForDebugger(); | |
| 391 }, | |
| 392 | |
| 393 /** | |
| 394 * @param {!InspectorBackendClass.Connection.Params} params | |
| 395 * @return {!InspectorBackendClass.Connection} | |
| 396 */ | |
| 397 _createMainConnection: function(params) | |
| 398 { | |
| 399 if (Runtime.queryParam("ws")) { | |
| 400 var ws = "ws://" + Runtime.queryParam("ws"); | |
| 401 this._mainConnection = new WebInspector.WebSocketConnection(ws, this
._webSocketConnectionLostCallback, params); | |
| 402 } else if (InspectorFrontendHost.isHostedMode()) { | |
| 403 this._mainConnection = new WebInspector.StubConnection(params); | |
| 404 } else { | |
| 405 this._mainConnection = new WebInspector.MainConnection(params); | |
| 406 } | |
| 407 return this._mainConnection; | |
| 408 }, | |
| 409 | |
| 410 /** | |
| 411 * @param {function(string)} onMessage | |
| 412 * @return {!Promise<!InspectorBackendClass.Connection>} | |
| 413 */ | |
| 414 interceptMainConnection: function(onMessage) | |
| 415 { | |
| 416 var params = { | |
| 417 onMessage: onMessage, | |
| 418 onDisconnect: this._connectAndCreateMainTarget.bind(this) | |
| 419 }; | |
| 420 return this._mainConnection.disconnect().then(this._createMainConnection
.bind(this, params)); | |
| 421 }, | |
| 422 | |
| 423 __proto__: WebInspector.Object.prototype | |
| 424 }; | |
| 425 | 400 |
| 426 /** | 401 /** |
| 427 * @interface | 402 * @interface |
| 428 */ | 403 */ |
| 429 WebInspector.TargetManager.Observer = function() | 404 WebInspector.TargetManager.Observer = function() {}; |
| 430 { | 405 |
| 406 WebInspector.TargetManager.Observer.prototype = { |
| 407 /** |
| 408 * @param {!WebInspector.Target} target |
| 409 */ |
| 410 targetAdded: function(target) {}, |
| 411 |
| 412 /** |
| 413 * @param {!WebInspector.Target} target |
| 414 */ |
| 415 targetRemoved: function(target) {}, |
| 431 }; | 416 }; |
| 432 | 417 |
| 433 WebInspector.TargetManager.Observer.prototype = { | |
| 434 /** | |
| 435 * @param {!WebInspector.Target} target | |
| 436 */ | |
| 437 targetAdded: function(target) { }, | |
| 438 | |
| 439 /** | |
| 440 * @param {!WebInspector.Target} target | |
| 441 */ | |
| 442 targetRemoved: function(target) { }, | |
| 443 }; | |
| 444 | |
| 445 /** | 418 /** |
| 446 * @type {!WebInspector.TargetManager} | 419 * @type {!WebInspector.TargetManager} |
| 447 */ | 420 */ |
| 448 WebInspector.targetManager = new WebInspector.TargetManager(); | 421 WebInspector.targetManager = new WebInspector.TargetManager(); |
| OLD | NEW |