Chromium Code Reviews| Index: third_party/WebKit/Source/devtools/front_end/sdk/SubTargetsManager.js |
| diff --git a/third_party/WebKit/Source/devtools/front_end/sdk/SubTargetsManager.js b/third_party/WebKit/Source/devtools/front_end/sdk/SubTargetsManager.js |
| index b0750a35c3a56ec8735a6f22f0e9e52b95a033cc..aa2043b92d138bc114a740b7d54443052529ff37 100644 |
| --- a/third_party/WebKit/Source/devtools/front_end/sdk/SubTargetsManager.js |
| +++ b/third_party/WebKit/Source/devtools/front_end/sdk/SubTargetsManager.js |
| @@ -18,6 +18,8 @@ WebInspector.SubTargetsManager = function(target) |
| this._attachedTargets = new Map(); |
| /** @type {!Map<string, !WebInspector.SubTargetConnection>} */ |
| this._connections = new Map(); |
| + /** @type {!Map<string, !WebInspector.PendingConnection>} */ |
| + this._pendingConnections = new Map(); |
| this._agent.setAutoAttach(true /* autoAttach */, true /* waitForDebuggerOnStart */); |
| this._agent.setAttachToFrames(Runtime.experiments.isEnabled("autoAttachToCrossProcessSubframes")); |
| @@ -71,6 +73,8 @@ WebInspector.SubTargetsManager.prototype = { |
| this._agent.detachFromTarget(connection._targetId); |
| connection._onDisconnect.call(null, "disposed"); |
| } |
| + for (var pending of this._pendingConnections.values()) |
| + WebInspector.targetConnectionManager.removeConnection(pending); |
| this._connections.clear(); |
| this._attachedTargets.clear(); |
| }, |
| @@ -158,7 +162,10 @@ WebInspector.SubTargetsManager.prototype = { |
| var parsedURL = targetInfo.url.asParsedURL(); |
| targetName = parsedURL ? parsedURL.lastPathComponentWithFragment() : "#" + (++this._lastAnonymousTargetId); |
| } |
| - var target = WebInspector.targetManager.createTarget(targetName, this._capabilitiesForType(targetInfo.type), this._createConnection.bind(this, targetInfo.id), this.target()); |
| + var target = WebInspector.targetManager.createTarget(targetName, this._capabilitiesForType(targetInfo.type), this._createConnection.bind(this, targetInfo.id), this.target(), true); |
| + var targetConnection = this._targetCreated(targetInfo); |
| + targetConnection && targetConnection._attached(target); |
|
dgozman
2016/10/26 22:14:06
Why do we need this?
eostroukhov
2016/10/27 23:42:24
For targets, that can be disconnected from, mappin
|
| + WebInspector.targetManager.addTarget(target); |
| target[WebInspector.SubTargetsManager._InfoSymbol] = targetInfo; |
| this._attachedTargets.set(targetInfo.id, target); |
| @@ -195,6 +202,8 @@ WebInspector.SubTargetsManager.prototype = { |
| if (connection) |
| connection._onDisconnect.call(null, "target terminated"); |
| this._connections.delete(targetId); |
| + var targetConnection = this._pendingConnections.get(targetId); |
| + targetConnection && targetConnection._detached(); |
|
dgozman
2016/10/26 22:14:06
style: let's follow the surrounding code and do pr
eostroukhov
2016/10/27 23:42:24
Done.
|
| }, |
| /** |
| @@ -210,12 +219,19 @@ WebInspector.SubTargetsManager.prototype = { |
| /** |
| * @param {!WebInspector.TargetInfo} targetInfo |
| + * @return {?WebInspector.PendingConnection} |
| */ |
| _targetCreated: function(targetInfo) |
| { |
| if (targetInfo.type !== "node") |
| - return; |
| - this._agent.attachToTarget(targetInfo.id); |
| + return null; |
| + var connection = this._pendingConnections.get(targetInfo.id); |
|
dgozman
2016/10/26 22:14:06
How come we could have one?
eostroukhov
2016/10/27 23:42:24
Speculatively, the code supports a case when attac
|
| + if (connection) |
| + return connection; |
| + connection = new WebInspector.PendingConnection(targetInfo, this.target().targetAgent()); |
|
dgozman
2016/10/26 22:14:06
this._agent
eostroukhov
2016/10/27 23:42:24
Done.
|
| + WebInspector.targetConnectionManager.addConnection(connection); |
| + this._pendingConnections.set(targetInfo.id, connection); |
| + return connection; |
| }, |
| /** |
| @@ -223,7 +239,11 @@ WebInspector.SubTargetsManager.prototype = { |
| */ |
| _targetDestroyed: function(targetId) |
| { |
| - // All the work is done in _detachedFromTarget. |
| + var connection = this._pendingConnections.get(targetId); |
| + if (!connection) |
| + return; |
| + WebInspector.targetConnectionManager.removeConnection(connection); |
| + this._pendingConnections.delete(targetId); |
| }, |
| __proto__: WebInspector.SDKModel.prototype |
| @@ -332,7 +352,7 @@ WebInspector.TargetInfo = function(payload) |
| this.id = payload.targetId; |
| this.url = payload.url; |
| this.type = payload.type; |
| - if (this.type !== "page" && this.type !== "iframe") { |
| + if (this.type !== "page" && this.type !== "iframe" && this.type !== "node") { |
| this.title = WebInspector.UIString("Worker: %s", this.url); |
| this.canActivate = false; |
| } else { |
| @@ -340,3 +360,99 @@ WebInspector.TargetInfo = function(payload) |
| this.canActivate = true; |
| } |
| }; |
| + |
| +/** |
| + * @constructor |
| + * @implements {WebInspector.TargetConnectionManager.Connection} |
| + * @param {!WebInspector.TargetInfo} info |
| + * @param {!Protocol.TargetAgent} targetAgent |
| + */ |
| +WebInspector.PendingConnection = function(info, targetAgent) |
| +{ |
| + this._info = info; |
| + this._targetAgent = targetAgent; |
| + /** @type {?Promise} */ |
| + this._connectPromise = null; |
| + /** @type {?WebInspector.Target} */ |
| + this._target = null; |
| +}; |
| + |
| +WebInspector.PendingConnection.prototype = { |
| + /** |
| + * @override |
| + * @return {string} |
| + */ |
| + id: function() |
| + { |
| + return this._info.id; |
| + }, |
| + |
| + /** |
| + * @override |
| + * @return {string} |
| + */ |
| + name: function() |
| + { |
| + return this._info.title; |
| + }, |
| + |
| + /** |
| + * @override |
| + * @return {!Promise} |
| + */ |
| + connect: function() |
| + { |
| + if (this._target) |
| + return Promise.resolve(this._target); |
| + if (this._connectPromise) |
| + return this._connectPromise; |
| + var resolveFn, rejectFn; |
| + var promise = new Promise((resolve, reject) => { |
|
dgozman
2016/10/26 22:14:06
The following pattern is used heavily in inspector
eostroukhov
2016/10/27 23:42:24
Done (TIL - parentheses are optional for arrow fun
|
| + resolveFn = resolve; |
| + rejectFn = reject; |
| + }).then((target) => { |
| + this._target = target |
| + this._connectPromise = null; |
| + }); |
| + promise[WebInspector.PendingConnection._resolveSymbol] = resolveFn; |
| + this._connectPromise = promise; |
| + this._targetAgent.attachToTarget(this.id()); |
| + return promise; |
| + }, |
| + |
| + /** |
| + * @override |
| + * @return {!Promise} |
| + */ |
| + disconnect: function() |
| + { |
| + var agent = this._targetAgent; |
| + var detachFn = agent.detachFromTarget.bind(agent, this.id()); |
| + if (this._connectPromise) |
| + return this._connectPromise.then(detachFn); |
| + if (this._target) |
| + detachFn(); |
| + return Promise.resolve(); |
| + }, |
| + |
| + /** |
| + * @return {?WebInspector.Target} |
| + */ |
| + target: function() |
| + { |
| + return this._target; |
| + }, |
| + |
| + _attached: function(target) { |
| + target[WebInspector.TargetConnectionManager.Connection.symbol] = this; |
| + this._connectPromise && this._connectPromise[WebInspector.PendingConnection._resolveSymbol](target); |
| + }, |
| + |
| + _detached: function() |
| + { |
| + this._target = null; |
| + }, |
| +}; |
| + |
| +WebInspector.PendingConnection._LastAnonymousTargetId = 0; |
| +WebInspector.PendingConnection._resolveSymbol = Symbol("resolve"); |