Commit 237f8276 authored by Dmitry Gozman's avatar Dmitry Gozman Committed by Commit Bot

[DevTools] Support multiple sessions in Target domain

BUG=590878

Change-Id: Idcebf0336623322813b4cdfac66183d37c28f2bd
Reviewed-on: https://chromium-review.googlesource.com/573411
Commit-Queue: Dmitry Gozman <dgozman@chromium.org>
Reviewed-by: default avatarAndrey Kosyakov <caseq@chromium.org>
Cr-Commit-Position: refs/heads/master@{#488395}
parent 17173492
......@@ -186,6 +186,10 @@ void DevToolsAgentHostImpl::ForceAttachClient(DevToolsAgentHostClient* client) {
InnerAttachClient(client);
}
void DevToolsAgentHostImpl::AttachMultiClient(DevToolsAgentHostClient* client) {
InnerAttachClient(client);
}
bool DevToolsAgentHostImpl::DetachClient(DevToolsAgentHostClient* client) {
if (!SessionByClient(client))
return false;
......
......@@ -44,6 +44,7 @@ class CONTENT_EXPORT DevToolsAgentHostImpl : public DevToolsAgentHost {
void DisconnectWebContents() override;
void ConnectWebContents(WebContents* wc) override;
void AttachMultiClient(DevToolsAgentHostClient* client);
bool Inspect();
protected:
......
......@@ -1657,6 +1657,8 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, TargetDiscovery) {
EXPECT_TRUE(params->GetBoolean("targetInfo.attached", &is_attached));
EXPECT_TRUE(is_attached);
params = WaitForNotification("Target.attachedToTarget", true);
std::string session_id;
EXPECT_TRUE(params->GetString("sessionId", &session_id));
EXPECT_TRUE(params->GetString("targetInfo.targetId", &temp));
EXPECT_EQ(attached_id, temp);
EXPECT_TRUE(notifications_.empty());
......@@ -1667,9 +1669,11 @@ IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, TargetDiscovery) {
EXPECT_TRUE(notifications_.empty());
command_params.reset(new base::DictionaryValue());
command_params->SetString("targetId", attached_id);
command_params->SetString("sessionId", session_id);
SendCommand("Target.detachFromTarget", std::move(command_params), true);
params = WaitForNotification("Target.detachedFromTarget", true);
EXPECT_TRUE(params->GetString("sessionId", &temp));
EXPECT_EQ(session_id, temp);
EXPECT_TRUE(params->GetString("targetId", &temp));
EXPECT_EQ(attached_id, temp);
EXPECT_TRUE(notifications_.empty());
......@@ -1737,6 +1741,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessDevToolsProtocolTest, TargetNoDiscovery) {
command_params->SetBoolean("value", true);
SendCommand("Target.setAttachToFrames", std::move(command_params), false);
params = WaitForNotification("Target.attachedToTarget", true);
std::string session_id;
EXPECT_TRUE(params->GetString("sessionId", &session_id));
EXPECT_TRUE(params->GetString("targetInfo.targetId", &target_id));
EXPECT_TRUE(params->GetString("targetInfo.type", &temp));
EXPECT_EQ("iframe", temp);
......@@ -1748,10 +1754,13 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessDevToolsProtocolTest, TargetNoDiscovery) {
params = WaitForNotification("Target.detachedFromTarget", true);
EXPECT_TRUE(params->GetString("targetId", &temp));
EXPECT_EQ(target_id, temp);
EXPECT_TRUE(params->GetString("sessionId", &temp));
EXPECT_EQ(session_id, temp);
// Navigate back to cross-site iframe.
NavigateFrameToURL(root->child_at(0), cross_site_url);
params = WaitForNotification("Target.attachedToTarget", true);
EXPECT_TRUE(params->GetString("sessionId", &session_id));
EXPECT_TRUE(params->GetString("targetInfo.targetId", &target_id));
EXPECT_TRUE(params->GetString("targetInfo.type", &temp));
EXPECT_EQ("iframe", temp);
......@@ -1764,6 +1773,8 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessDevToolsProtocolTest, TargetNoDiscovery) {
params = WaitForNotification("Target.detachedFromTarget", true);
EXPECT_TRUE(params->GetString("targetId", &temp));
EXPECT_EQ(target_id, temp);
EXPECT_TRUE(params->GetString("sessionId", &temp));
EXPECT_EQ(session_id, temp);
}
IN_PROC_BROWSER_TEST_F(DevToolsProtocolTest, SetAndGetCookies) {
......
......@@ -176,8 +176,8 @@ void TargetAutoAttacher::ReattachTargetsOfType(const Hosts& new_hosts,
for (auto& it : new_hosts) {
DevToolsAgentHost* host = it.get();
if (old_hosts.find(host) == old_hosts.end()) {
if (attach_callback_.Run(host, waiting_for_debugger))
auto_attached_hosts_.insert(host);
attach_callback_.Run(host, waiting_for_debugger);
auto_attached_hosts_.insert(host);
}
}
}
......
......@@ -18,7 +18,7 @@ namespace protocol {
class TargetAutoAttacher : public ServiceWorkerDevToolsManager::Observer {
public:
// Second parameter is |waiting_for_debugger|, returns whether it succeeded.
using AttachCallback = base::Callback<bool(DevToolsAgentHost*, bool)>;
using AttachCallback = base::Callback<void(DevToolsAgentHost*, bool)>;
using DetachCallback = base::Callback<void(DevToolsAgentHost*)>;
TargetAutoAttacher(AttachCallback attach_callback,
......
......@@ -11,7 +11,6 @@
#include "content/browser/devtools/protocol/devtools_domain_handler.h"
#include "content/browser/devtools/protocol/target.h"
#include "content/browser/devtools/protocol/target_auto_attacher.h"
#include "content/public/browser/devtools_agent_host_client.h"
#include "content/public/browser/devtools_agent_host_observer.h"
namespace content {
......@@ -23,7 +22,6 @@ namespace protocol {
class TargetHandler : public DevToolsDomainHandler,
public Target::Backend,
public DevToolsAgentHostClient,
public DevToolsAgentHostObserver {
public:
TargetHandler();
......@@ -46,10 +44,12 @@ class TargetHandler : public DevToolsDomainHandler,
Response SetRemoteLocations(
std::unique_ptr<protocol::Array<Target::RemoteLocation>>) override;
Response AttachToTarget(const std::string& target_id,
bool* out_success) override;
Response DetachFromTarget(const std::string& target_id) override;
Response SendMessageToTarget(const std::string& target_id,
const std::string& message) override;
std::string* out_session_id) override;
Response DetachFromTarget(Maybe<std::string> session_id,
Maybe<std::string> target_id) override;
Response SendMessageToTarget(const std::string& message,
Maybe<std::string> session_id,
Maybe<std::string> target_id) override;
Response GetTargetInfo(
const std::string& target_id,
std::unique_ptr<Target::TargetInfo>* target_info) override;
......@@ -69,14 +69,14 @@ class TargetHandler : public DevToolsDomainHandler,
override;
private:
using RawHostsMap = std::map<std::string, DevToolsAgentHost*>;
class Session;
void TargetCreatedInternal(DevToolsAgentHost* host);
void TargetInfoChangedInternal(DevToolsAgentHost* host);
void TargetDestroyedInternal(DevToolsAgentHost* host);
bool AttachToTargetInternal(DevToolsAgentHost* host,
bool waiting_for_debugger);
void DetachFromTargetInternal(DevToolsAgentHost* host);
void AutoAttach(DevToolsAgentHost* host, bool waiting_for_debugger);
void AutoDetach(DevToolsAgentHost* host);
Response FindSession(Maybe<std::string> session_id,
Maybe<std::string> target_id,
Session** session,
bool fall_through);
// DevToolsAgentHostObserver implementation.
bool ShouldForceDevToolsAgentHostCreation() override;
......@@ -85,17 +85,13 @@ class TargetHandler : public DevToolsDomainHandler,
void DevToolsAgentHostAttached(DevToolsAgentHost* agent_host) override;
void DevToolsAgentHostDetached(DevToolsAgentHost* agent_host) override;
// DevToolsAgentHostClient implementation.
void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
const std::string& message) override;
void AgentHostClosed(DevToolsAgentHost* agent_host,
bool replaced_with_another_client) override;
std::unique_ptr<Target::Frontend> frontend_;
TargetAutoAttacher auto_attacher_;
bool discover_;
std::map<std::string, scoped_refptr<DevToolsAgentHost>> attached_hosts_;
RawHostsMap reported_hosts_;
std::map<std::string, std::unique_ptr<Session>> attached_sessions_;
std::map<DevToolsAgentHost*, Session*> auto_attached_sessions_;
std::set<DevToolsAgentHost*> reported_hosts_;
int last_session_id_ = 0;
DISALLOW_COPY_AND_ASSIGN(TargetHandler);
};
......
......@@ -184,9 +184,9 @@ TestRunner.Page = class {
}
async createSession() {
await DevToolsAPI._sendCommandOrDie('Target.attachToTarget', {targetId: this._targetId});
var session = new TestRunner.Session(this);
DevToolsAPI._sessions.set(this._targetId, session);
var sessionId = (await DevToolsAPI._sendCommandOrDie('Target.attachToTarget', {targetId: this._targetId})).sessionId;
var session = new TestRunner.Session(this, sessionId);
DevToolsAPI._sessions.set(sessionId, session);
return session;
}
......@@ -195,18 +195,12 @@ TestRunner.Page = class {
}
async _navigate(url) {
if (DevToolsAPI._sessions.get(this._targetId))
this._testRunner.die(`Cannot navigate to ${url} with active session`, new Error());
var session = await this.createSession();
await session._navigate(url);
await session.disconnect();
}
async loadHTML(html) {
if (DevToolsAPI._sessions.get(this._targetId))
this._testRunner.die('Cannot loadHTML with active session', new Error());
html = html.replace(/'/g, "\\'").replace(/\n/g, '\\n');
var session = await this.createSession();
await session.protocol.Runtime.evaluate({expression: `document.write('${html}');document.close();`});
......@@ -215,9 +209,10 @@ TestRunner.Page = class {
};
TestRunner.Session = class {
constructor(page) {
constructor(page, sessionId) {
this._testRunner = page._testRunner;
this._page = page;
this._sessionId = sessionId;
this._requestId = 0;
this._dispatchTable = new Map();
this._eventHandlers = new Map();
......@@ -225,12 +220,12 @@ TestRunner.Session = class {
}
async disconnect() {
await DevToolsAPI._sendCommandOrDie('Target.detachFromTarget', {targetId: this._page._targetId});
await DevToolsAPI._sendCommandOrDie('Target.detachFromTarget', {sessionId: this._sessionId});
DevToolsAPI._sessions.delete(this._page._targetId);
}
sendRawCommand(requestId, message) {
DevToolsAPI._sendCommandOrDie('Target.sendMessageToTarget', {targetId: this._page._targetId, message: message});
DevToolsAPI._sendCommandOrDie('Target.sendMessageToTarget', {sessionId: this._sessionId, message: message});
return new Promise(f => this._dispatchTable.set(requestId, f));
}
......@@ -394,9 +389,9 @@ DevToolsAPI.dispatchMessage = function(messageOrObject) {
} else {
var eventName = messageObject.method;
if (eventName === 'Target.receivedMessageFromTarget') {
var targetId = messageObject.params.targetId;
var sessionId = messageObject.params.sessionId;
var message = messageObject.params.message;
var session = DevToolsAPI._sessions.get(targetId);
var session = DevToolsAPI._sessions.get(sessionId);
if (session)
session._dispatchMessage(JSON.parse(message));
}
......
......@@ -4,18 +4,18 @@ Debugger-related command should be issued: {
"id": "<id>",
"method": "Target.sendMessageToTarget",
"params": {
"targetId": "<id>",
"message": {
"id": "<id>",
"method": "Target.sendMessageToTarget",
"params": {
"targetId": "<id>",
"message": {
"id": "<id>",
"method": "Debugger.enable"
}
},
"sessionId": "<id>"
}
}
},
"sessionId": "<id>"
}
}
Suspending targets.
......@@ -24,18 +24,18 @@ Debugger-related command should be issued: {
"id": "<id>",
"method": "Target.sendMessageToTarget",
"params": {
"targetId": "<id>",
"message": {
"id": "<id>",
"method": "Target.sendMessageToTarget",
"params": {
"targetId": "<id>",
"message": {
"id": "<id>",
"method": "Debugger.enable"
}
},
"sessionId": "<id>"
}
}
},
"sessionId": "<id>"
}
}
......@@ -38,18 +38,16 @@
namespace blink {
using protocol::Maybe;
using protocol::Response;
namespace WorkerAgentState {
static const char kAutoAttach[] = "autoAttach";
static const char kWaitForDebuggerOnStart[] = "waitForDebuggerOnStart";
static const char kAttachedWorkerIds[] = "attachedWorkerIds";
static const char kAttachedSessionIds[] = "attachedSessionIds";
};
namespace {
// TODO(dgozman): support multiple sessions in protocol.
static const int kSessionId = 1;
} // namespace
int InspectorWorkerAgent::s_last_connection_ = 0;
InspectorWorkerAgent::InspectorWorkerAgent(InspectedFrames* inspected_frames)
: inspected_frames_(inspected_frames) {}
......@@ -60,10 +58,10 @@ void InspectorWorkerAgent::Restore() {
if (!AutoAttachEnabled())
return;
instrumenting_agents_->addInspectorWorkerAgent(this);
protocol::DictionaryValue* attached = AttachedWorkerIds();
protocol::DictionaryValue* attached = AttachedSessionIds();
for (size_t i = 0; i < attached->size(); ++i)
GetFrontend()->detachedFromTarget(attached->at(i).first);
state_->remove(WorkerAgentState::kAttachedWorkerIds);
state_->remove(WorkerAgentState::kAttachedSessionIds);
ConnectToAllProxies();
}
......@@ -74,7 +72,7 @@ Response InspectorWorkerAgent::disable() {
}
state_->setBoolean(WorkerAgentState::kAutoAttach, false);
state_->setBoolean(WorkerAgentState::kWaitForDebuggerOnStart, false);
state_->remove(WorkerAgentState::kAttachedWorkerIds);
state_->remove(WorkerAgentState::kAttachedSessionIds);
return Response::OK();
}
......@@ -104,13 +102,33 @@ bool InspectorWorkerAgent::AutoAttachEnabled() {
return state_->booleanProperty(WorkerAgentState::kAutoAttach, false);
}
Response InspectorWorkerAgent::sendMessageToTarget(const String& target_id,
const String& message) {
WorkerInspectorProxy* proxy = connected_proxies_.at(target_id);
if (!proxy)
return Response::Error("Not attached to a target with given id");
proxy->SendMessageToInspector(kSessionId, message);
return Response::OK();
Response InspectorWorkerAgent::sendMessageToTarget(const String& message,
Maybe<String> session_id,
Maybe<String> target_id) {
if (session_id.isJust()) {
auto it = session_id_to_connection_.find(session_id.fromJust());
if (it == session_id_to_connection_.end())
return Response::Error("No session with given id");
WorkerInspectorProxy* proxy = connected_proxies_.at(it->value);
proxy->SendMessageToInspector(it->value, message);
return Response::OK();
}
if (target_id.isJust()) {
int connection = 0;
for (auto& it : connected_proxies_) {
if (it.value->InspectorId() == target_id.fromJust()) {
if (connection)
return Response::Error("Multiple sessions attached, specify id");
connection = it.key;
}
}
if (!connection)
return Response::Error("No target with given id");
WorkerInspectorProxy* proxy = connected_proxies_.at(connection);
proxy->SendMessageToInspector(connection, message);
return Response::OK();
}
return Response::Error("Session id must be specified");
}
void InspectorWorkerAgent::SetTracingSessionId(
......@@ -138,12 +156,20 @@ void InspectorWorkerAgent::DidStartWorker(WorkerInspectorProxy* proxy,
void InspectorWorkerAgent::WorkerTerminated(WorkerInspectorProxy* proxy) {
DCHECK(GetFrontend() && AutoAttachEnabled());
if (connected_proxies_.find(proxy->InspectorId()) == connected_proxies_.end())
return;
AttachedWorkerIds()->remove(proxy->InspectorId());
GetFrontend()->detachedFromTarget(proxy->InspectorId());
proxy->DisconnectFromInspector(kSessionId, this);
connected_proxies_.erase(proxy->InspectorId());
Vector<String> session_ids;
for (auto& it : session_id_to_connection_) {
if (connected_proxies_.at(it.value) == proxy)
session_ids.push_back(it.key);
}
for (const String& session_id : session_ids) {
AttachedSessionIds()->remove(session_id);
GetFrontend()->detachedFromTarget(session_id, proxy->InspectorId());
int connection = session_id_to_connection_.at(session_id);
proxy->DisconnectFromInspector(connection, this);
connected_proxies_.erase(connection);
connection_to_session_id_.erase(connection);
session_id_to_connection_.erase(session_id);
}
}
void InspectorWorkerAgent::ConnectToAllProxies() {
......@@ -152,19 +178,23 @@ void InspectorWorkerAgent::ConnectToAllProxies() {
DCHECK(proxy->GetExecutionContext()->IsDocument());
Document* document = ToDocument(proxy->GetExecutionContext());
if (document->GetFrame() &&
inspected_frames_->Contains(document->GetFrame()))
inspected_frames_->Contains(document->GetFrame())) {
ConnectToProxy(proxy, false);
}
}
}
void InspectorWorkerAgent::DisconnectFromAllProxies(bool report_to_frontend) {
for (auto& id_proxy : connected_proxies_) {
for (auto& it : session_id_to_connection_) {
WorkerInspectorProxy* proxy = connected_proxies_.at(it.value);
if (report_to_frontend) {
AttachedWorkerIds()->remove(id_proxy.key);
GetFrontend()->detachedFromTarget(id_proxy.key);
AttachedSessionIds()->remove(it.key);
GetFrontend()->detachedFromTarget(it.key, proxy->InspectorId());
}
id_proxy.value->DisconnectFromInspector(kSessionId, this);
proxy->DisconnectFromInspector(it.value, this);
}
connection_to_session_id_.clear();
session_id_to_connection_.clear();
connected_proxies_.clear();
}
......@@ -175,33 +205,36 @@ void InspectorWorkerAgent::DidCommitLoadForLocalFrame(LocalFrame* frame) {
// During navigation workers from old page may die after a while.
// Usually, it's fine to report them terminated later, but some tests
// expect strict set of workers, and we reuse renderer between tests.
for (auto& id_proxy : connected_proxies_) {
AttachedWorkerIds()->remove(id_proxy.key);
GetFrontend()->detachedFromTarget(id_proxy.key);
id_proxy.value->DisconnectFromInspector(kSessionId, this);
}
connected_proxies_.clear();
DisconnectFromAllProxies(true);
}
protocol::DictionaryValue* InspectorWorkerAgent::AttachedWorkerIds() {
protocol::DictionaryValue* InspectorWorkerAgent::AttachedSessionIds() {
protocol::DictionaryValue* ids =
state_->getObject(WorkerAgentState::kAttachedWorkerIds);
state_->getObject(WorkerAgentState::kAttachedSessionIds);
if (!ids) {
std::unique_ptr<protocol::DictionaryValue> new_ids =
protocol::DictionaryValue::create();
ids = new_ids.get();
state_->setObject(WorkerAgentState::kAttachedWorkerIds, std::move(new_ids));
state_->setObject(WorkerAgentState::kAttachedSessionIds,
std::move(new_ids));
}
return ids;
}
void InspectorWorkerAgent::ConnectToProxy(WorkerInspectorProxy* proxy,
bool waiting_for_debugger) {
connected_proxies_.Set(proxy->InspectorId(), proxy);
proxy->ConnectToInspector(kSessionId, this);
int connection = ++s_last_connection_;
connected_proxies_.Set(connection, proxy);
String session_id = proxy->InspectorId() + "-" + String::Number(connection);
session_id_to_connection_.Set(session_id, connection);
connection_to_session_id_.Set(connection, session_id);
proxy->ConnectToInspector(connection, this);
DCHECK(GetFrontend());
AttachedWorkerIds()->setBoolean(proxy->InspectorId(), true);
GetFrontend()->attachedToTarget(protocol::Target::TargetInfo::create()
AttachedSessionIds()->setBoolean(session_id, true);
GetFrontend()->attachedToTarget(session_id,
protocol::Target::TargetInfo::create()
.setTargetId(proxy->InspectorId())
.setType("worker")
.setTitle(proxy->Url())
......@@ -213,10 +246,13 @@ void InspectorWorkerAgent::ConnectToProxy(WorkerInspectorProxy* proxy,
void InspectorWorkerAgent::DispatchMessageFromWorker(
WorkerInspectorProxy* proxy,
int session_id,
int connection,
const String& message) {
DCHECK(session_id == kSessionId);
GetFrontend()->receivedMessageFromTarget(proxy->InspectorId(), message);
auto it = connection_to_session_id_.find(connection);
if (it == connection_to_session_id_.end())
return;
GetFrontend()->receivedMessageFromTarget(it->value, message,
proxy->InspectorId());
}
DEFINE_TRACE(InspectorWorkerAgent) {
......
......@@ -65,8 +65,10 @@ class CORE_EXPORT InspectorWorkerAgent final
protocol::Response setAutoAttach(bool auto_attach,
bool wait_for_debugger_on_start) override;
protocol::Response setAttachToFrames(bool attach) override;
protocol::Response sendMessageToTarget(const String& target_id,
const String& message) override;
protocol::Response sendMessageToTarget(
const String& message,
protocol::Maybe<String> session_id,
protocol::Maybe<String> target_id) override;
void SetTracingSessionId(const String&);
......@@ -75,16 +77,19 @@ class CORE_EXPORT InspectorWorkerAgent final
void ConnectToAllProxies();
void DisconnectFromAllProxies(bool report_to_frontend);
void ConnectToProxy(WorkerInspectorProxy*, bool waiting_for_debugger);
protocol::DictionaryValue* AttachedWorkerIds();
protocol::DictionaryValue* AttachedSessionIds();
// WorkerInspectorProxy::PageInspector implementation.
void DispatchMessageFromWorker(WorkerInspectorProxy*,
int session_id,
int connection,
const String& message) override;
Member<InspectedFrames> inspected_frames_;
HeapHashMap<String, Member<WorkerInspectorProxy>> connected_proxies_;
HeapHashMap<int, Member<WorkerInspectorProxy>> connected_proxies_;
HashMap<int, String> connection_to_session_id_;
HashMap<String, int> session_id_to_connection_;
String tracing_session_id_;
static int s_last_connection_;
};
} // namespace blink
......
......@@ -3601,6 +3601,11 @@
"id": "TargetID",
"type": "string"
},
{
"id": "SessionID",
"type": "string",
"description": "Unique identifier of attached debugging session."
},
{
"id": "BrowserContextID",
"type": "string"
......@@ -3656,10 +3661,11 @@
},
{
"name": "sendMessageToTarget",
"description": "Sends protocol message to the target with given id.",
"description": "Sends protocol message over session with given id.",
"parameters": [
{ "name": "targetId", "$ref": "TargetID" },
{ "name": "message", "type": "string" }
{ "name": "message", "type": "string" },
{ "name": "sessionId", "$ref": "SessionID", "optional": true, "description": "Identifier of the session." },
{ "name": "targetId", "$ref": "TargetID", "optional": true, "deprecated": true, "description": "Deprecated." }
]
},
{
......@@ -3696,14 +3702,15 @@
{ "name": "targetId", "$ref": "TargetID" }
],
"returns": [
{ "name": "success", "type": "boolean", "description": "Whether attach succeeded." }
{ "name": "sessionId", "$ref": "SessionID", "description": "Id assigned to the session." }
]
},
{
"name": "detachFromTarget",
"description": "Detaches from the target with given id.",
"description": "Detaches session with given id.",
"parameters": [
{ "name": "targetId", "$ref": "TargetID" }
{ "name": "sessionId", "$ref": "SessionID", "optional": true, "description": "Session to detach." },
{ "name": "targetId", "$ref": "TargetID", "optional": true, "deprecated": true, "description": "Deprecated." }
]
},
{
......@@ -3770,23 +3777,26 @@
"name": "attachedToTarget",
"description": "Issued when attached to target because of auto-attach or <code>attachToTarget</code> command.",
"parameters": [
{ "name": "sessionId", "$ref": "SessionID", "description": "Identifier assigned to the session used to send/receive messages." },
{ "name": "targetInfo", "$ref": "TargetInfo" },
{ "name": "waitingForDebugger", "type": "boolean" }
]
},
{
"name": "detachedFromTarget",
"description": "Issued when detached from target for any reason (including <code>detachFromTarget</code> command).",
"description": "Issued when detached from target for any reason (including <code>detachFromTarget</code> command). Can be issued multiple times per target if multiple sessions have been attached to it.",
"parameters": [
{ "name": "targetId", "$ref": "TargetID" }
{ "name": "sessionId", "$ref": "SessionID", "description": "Detached session identifier." },
{ "name": "targetId", "$ref": "TargetID", "optional": true, "deprecated": true, "description": "Deprecated." }
]
},
{
"name": "receivedMessageFromTarget",
"description": "Notifies about new protocol message from attached target.",
"description": "Notifies about a new protocol message received from the session (as reported in <code>attachedToTarget</code> event).",
"parameters": [
{ "name": "targetId", "$ref": "TargetID" },
{ "name": "message", "type": "string" }
{ "name": "sessionId", "$ref": "SessionID", "description": "Identifier of a session which sends a message." },
{ "name": "message", "type": "string" },
{ "name": "targetId", "$ref": "TargetID", "optional": true, "deprecated": true, "description": "Deprecated." }
]
}
]
......
......@@ -457,10 +457,8 @@ SDK.ChildTargetManager = class {
InspectorFrontendHostAPI.Events.DevicesDiscoveryConfigChanged, this._devicesDiscoveryConfigChanged, this);
}
// TODO(dgozman): this is O(n^2) when removing main target.
var childTargets = this._targetManager._targets.filter(child => child.parentTarget() === this._parentTarget);
for (var child of childTargets)
this.detachedFromTarget(child.id());
for (var sessionId of this._childConnections.keys())
this.detachedFromTarget(sessionId, undefined);
}
/**
......@@ -534,10 +532,11 @@ SDK.ChildTargetManager = class {
/**
* @override
* @param {string} sessionId
* @param {!Protocol.Target.TargetInfo} targetInfo
* @param {boolean} waitingForDebugger
*/
attachedToTarget(targetInfo, waitingForDebugger) {
attachedToTarget(sessionId, targetInfo, waitingForDebugger) {
var targetName = '';
if (targetInfo.type === 'node') {
targetName = Common.UIString('Node.js: %s', targetInfo.url);
......@@ -548,7 +547,7 @@ SDK.ChildTargetManager = class {
}
var target = this._targetManager.createTarget(
targetInfo.targetId, targetName, this._capabilitiesForType(targetInfo.type),
this._createChildConnection.bind(this, this._targetAgent, targetInfo.targetId), this._parentTarget);
this._createChildConnection.bind(this, this._targetAgent, sessionId), this._parentTarget);
// Only pause the new worker if debugging SW - we are going through the pause on start checkbox.
if (!this._parentTarget.parentTarget() && Runtime.queryParam('isSharedWorker') && waitingForDebugger) {
......@@ -564,33 +563,35 @@ SDK.ChildTargetManager = class {
/**
* @override
* @param {string} childTargetId
* @param {string} sessionId
* @param {string=} childTargetId
*/
detachedFromTarget(childTargetId) {
this._childConnections.get(childTargetId)._onDisconnect.call(null, 'target terminated');
this._childConnections.delete(childTargetId);
detachedFromTarget(sessionId, childTargetId) {
this._childConnections.get(sessionId)._onDisconnect.call(null, 'target terminated');
this._childConnections.delete(sessionId);
}
/**
* @override
* @param {string} childTargetId
* @param {string} sessionId
* @param {string} message
* @param {string=} childTargetId
*/
receivedMessageFromTarget(childTargetId, message) {
var connection = this._childConnections.get(childTargetId);
receivedMessageFromTarget(sessionId, message, childTargetId) {
var connection = this._childConnections.get(sessionId);
if (connection)
connection._onMessage.call(null, message);
}
/**
* @param {!Protocol.TargetAgent} agent
* @param {string} childTargetId
* @param {string} sessionId
* @param {!Protocol.InspectorBackend.Connection.Params} params
* @return {!Protocol.InspectorBackend.Connection}
*/
_createChildConnection(agent, childTargetId, params) {
var connection = new SDK.ChildConnection(agent, childTargetId, params);
this._childConnections.set(childTargetId, connection);
_createChildConnection(agent, sessionId, params) {
var connection = new SDK.ChildConnection(agent, sessionId, params);
this._childConnections.set(sessionId, connection);
return connection;
}
};
......@@ -601,12 +602,12 @@ SDK.ChildTargetManager = class {
SDK.ChildConnection = class {
/**
* @param {!Protocol.TargetAgent} agent
* @param {string} targetId
* @param {string} sessionId
* @param {!Protocol.InspectorBackend.Connection.Params} params
*/
constructor(agent, targetId, params) {
constructor(agent, sessionId, params) {
this._agent = agent;
this._targetId = targetId;
this._sessionId = sessionId;
this._onMessage = params.onMessage;
this._onDisconnect = params.onDisconnect;
}
......@@ -616,7 +617,7 @@ SDK.ChildConnection = class {
* @param {string} message
*/
sendMessage(message) {
this._agent.sendMessageToTarget(this._targetId, message);
this._agent.sendMessageToTarget(message, this._sessionId);
}
/**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment