Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(426)

Side by Side Diff: content/browser/devtools/protocol/target_handler.cc

Issue 2951913002: [DevTools] Support multiple sessions in Target domain (Closed)
Patch Set: simplify Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2016 The Chromium Authors. All rights reserved. 1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/devtools/protocol/target_handler.h" 5 #include "content/browser/devtools/protocol/target_handler.h"
6 6
7 #include "base/strings/stringprintf.h"
7 #include "content/browser/devtools/devtools_manager.h" 8 #include "content/browser/devtools/devtools_manager.h"
8 #include "content/browser/devtools/devtools_session.h" 9 #include "content/browser/devtools/devtools_session.h"
9 #include "content/browser/devtools/render_frame_devtools_agent_host.h" 10 #include "content/browser/devtools/render_frame_devtools_agent_host.h"
10 #include "content/browser/devtools/service_worker_devtools_agent_host.h" 11 #include "content/browser/devtools/service_worker_devtools_agent_host.h"
11 #include "content/browser/frame_host/frame_tree.h" 12 #include "content/browser/frame_host/frame_tree.h"
12 #include "content/browser/frame_host/frame_tree_node.h" 13 #include "content/browser/frame_host/frame_tree_node.h"
13 #include "content/browser/frame_host/render_frame_host_impl.h" 14 #include "content/browser/frame_host/render_frame_host_impl.h"
15 #include "content/public/browser/devtools_agent_host_client.h"
14 16
15 namespace content { 17 namespace content {
16 namespace protocol { 18 namespace protocol {
17 19
18 namespace { 20 namespace {
19 21
20 using ScopeAgentsMap = 22 using ScopeAgentsMap =
21 std::map<GURL, std::unique_ptr<ServiceWorkerDevToolsAgentHost::List>>; 23 std::map<GURL, std::unique_ptr<ServiceWorkerDevToolsAgentHost::List>>;
22 24
23 void GetMatchingHostsByScopeMap( 25 void GetMatchingHostsByScopeMap(
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 return Target::TargetInfo::Create() 89 return Target::TargetInfo::Create()
88 .SetTargetId(host->GetId()) 90 .SetTargetId(host->GetId())
89 .SetTitle(host->GetTitle()) 91 .SetTitle(host->GetTitle())
90 .SetUrl(host->GetURL().spec()) 92 .SetUrl(host->GetURL().spec())
91 .SetType(host->GetType()) 93 .SetType(host->GetType())
92 .Build(); 94 .Build();
93 } 95 }
94 96
95 } // namespace 97 } // namespace
96 98
99 class TargetHandler::Session : public DevToolsAgentHostClient {
100 public:
101 Session(TargetHandler* handler,
102 DevToolsAgentHost* agent_host,
caseq 2017/06/27 18:29:29 pass as scoped_refptr<> to indicate we keep it.
103 const std::string& id,
104 bool is_auto_attach)
105 : handler_(handler),
106 agent_host_(agent_host),
107 id_(id),
108 is_auto_attach_(is_auto_attach) {}
109
110 ~Session() override {
111 if (agent_host_)
112 agent_host_->DetachClient(this);
113 }
114
115 bool is_auto_attach() const { return is_auto_attach_; }
116 DevToolsAgentHost* agent_host() const { return agent_host_.get(); }
117
118 void Attach() {
119 static_cast<DevToolsAgentHostImpl*>(agent_host_.get())
120 ->AttachMultiClient(this);
121 }
122
123 // DevToolsAgentHostClient implementation.
124 void DispatchProtocolMessage(DevToolsAgentHost* agent_host,
125 const std::string& message) override {
126 handler_->frontend_->ReceivedMessageFromTarget(id_, message);
127 }
128
129 void AgentHostClosed(DevToolsAgentHost* agent_host,
130 bool replaced_with_another_client) override {
131 handler_->frontend_->DetachedFromTarget(id_);
caseq 2017/06/27 18:29:29 Most of the logic in this methods looks like it co
132 if (is_auto_attach_)
133 handler_->auto_attached_hosts_.erase(agent_host->GetId());
134 agent_host_ = nullptr;
135 handler_->attached_sessions_.erase(id_); // |this| is deleted here.
136 }
137
138 private:
139 TargetHandler* handler_;
140 scoped_refptr<DevToolsAgentHost> agent_host_;
141 std::string id_;
142 bool is_auto_attach_;
143
144 DISALLOW_COPY_AND_ASSIGN(Session);
145 };
146
97 TargetHandler::TargetHandler() 147 TargetHandler::TargetHandler()
98 : DevToolsDomainHandler(Target::Metainfo::domainName), 148 : DevToolsDomainHandler(Target::Metainfo::domainName),
99 discover_(false), 149 discover_(false),
100 auto_attach_(false), 150 auto_attach_(false),
101 wait_for_debugger_on_start_(false), 151 wait_for_debugger_on_start_(false),
102 attach_to_frames_(false), 152 attach_to_frames_(false),
103 render_frame_host_(nullptr) { 153 render_frame_host_(nullptr) {
104 } 154 }
105 155
106 TargetHandler::~TargetHandler() { 156 TargetHandler::~TargetHandler() {
(...skipping 12 matching lines...) Expand all
119 } 169 }
120 170
121 void TargetHandler::SetRenderFrameHost(RenderFrameHostImpl* render_frame_host) { 171 void TargetHandler::SetRenderFrameHost(RenderFrameHostImpl* render_frame_host) {
122 render_frame_host_ = render_frame_host; 172 render_frame_host_ = render_frame_host;
123 UpdateFrames(); 173 UpdateFrames();
124 } 174 }
125 175
126 Response TargetHandler::Disable() { 176 Response TargetHandler::Disable() {
127 SetAutoAttach(false, false); 177 SetAutoAttach(false, false);
128 SetDiscoverTargets(false); 178 SetDiscoverTargets(false);
129 for (const auto& id_host : attached_hosts_) 179 attached_sessions_.clear();
130 id_host.second->DetachClient(this);
131 attached_hosts_.clear();
132 return Response::OK(); 180 return Response::OK();
133 } 181 }
134 182
135 void TargetHandler::UpdateServiceWorkers() { 183 void TargetHandler::UpdateServiceWorkers() {
136 UpdateServiceWorkers(false); 184 UpdateServiceWorkers(false);
137 } 185 }
138 186
139 void TargetHandler::UpdateFrames() { 187 void TargetHandler::UpdateFrames() {
140 if (!auto_attach_ || !attach_to_frames_) 188 if (!auto_attach_ || !attach_to_frames_)
141 return; 189 return;
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 auto matching = GetMatchingServiceWorkers(browser_context, frame_urls_); 230 auto matching = GetMatchingServiceWorkers(browser_context, frame_urls_);
183 HostsMap new_hosts; 231 HostsMap new_hosts;
184 for (const auto& pair : matching) { 232 for (const auto& pair : matching) {
185 if (pair.second->IsReadyForInspection()) 233 if (pair.second->IsReadyForInspection())
186 new_hosts[pair.first] = pair.second; 234 new_hosts[pair.first] = pair.second;
187 } 235 }
188 ReattachTargetsOfType( 236 ReattachTargetsOfType(
189 new_hosts, DevToolsAgentHost::kTypeServiceWorker, waiting_for_debugger); 237 new_hosts, DevToolsAgentHost::kTypeServiceWorker, waiting_for_debugger);
190 } 238 }
191 239
192 void TargetHandler::ReattachTargetsOfType( 240 void TargetHandler::ReattachTargetsOfType(const HostsMap& new_hosts,
193 const HostsMap& new_hosts, 241 const std::string& type,
194 const std::string& type, 242 bool waiting_for_debugger) {
195 bool waiting_for_debugger) { 243 std::vector<std::string> ids_to_detach;
196 HostsMap old_hosts = attached_hosts_; 244 for (const auto& pair : attached_sessions_) {
197 for (const auto& pair : old_hosts) { 245 Session* session = pair.second.get();
198 if (pair.second->GetType() == type && 246 if (session->is_auto_attach() && session->agent_host()->GetType() == type &&
199 new_hosts.find(pair.first) == new_hosts.end()) { 247 new_hosts.find(session->agent_host()->GetId()) == new_hosts.end()) {
200 DetachFromTargetInternal(pair.second.get()); 248 ids_to_detach.push_back(pair.first);
249 auto_attached_hosts_.erase(session->agent_host()->GetId());
201 } 250 }
202 } 251 }
252 for (const std::string& session_id : ids_to_detach)
253 DetachFromSessionInternal(session_id);
203 for (const auto& pair : new_hosts) { 254 for (const auto& pair : new_hosts) {
204 if (old_hosts.find(pair.first) == old_hosts.end()) 255 if (auto_attached_hosts_.find(pair.first) == auto_attached_hosts_.end()) {
205 AttachToTargetInternal(pair.second.get(), waiting_for_debugger); 256 DevToolsAgentHost* host = pair.second.get();
257 AttachToTargetInternal(host, waiting_for_debugger, true);
258 auto_attached_hosts_[host->GetId()] = host;
259 }
206 } 260 }
207 } 261 }
208 262
209 void TargetHandler::TargetCreatedInternal(DevToolsAgentHost* host) { 263 void TargetHandler::TargetCreatedInternal(DevToolsAgentHost* host) {
210 if (reported_hosts_.find(host->GetId()) != reported_hosts_.end()) 264 if (reported_hosts_.find(host->GetId()) != reported_hosts_.end())
211 return; 265 return;
212 frontend_->TargetCreated(CreateInfo(host)); 266 frontend_->TargetCreated(CreateInfo(host));
213 reported_hosts_[host->GetId()] = host; 267 reported_hosts_[host->GetId()] = host;
214 } 268 }
215 269
216 void TargetHandler::TargetDestroyedInternal( 270 void TargetHandler::TargetDestroyedInternal(
217 DevToolsAgentHost* host) { 271 DevToolsAgentHost* host) {
218 auto it = reported_hosts_.find(host->GetId()); 272 auto it = reported_hosts_.find(host->GetId());
219 if (it == reported_hosts_.end()) 273 if (it == reported_hosts_.end())
220 return; 274 return;
221 if (discover_) 275 if (discover_)
222 frontend_->TargetDestroyed(host->GetId()); 276 frontend_->TargetDestroyed(host->GetId());
223 reported_hosts_.erase(it); 277 reported_hosts_.erase(it);
224 } 278 }
225 279
226 bool TargetHandler::AttachToTargetInternal( 280 std::string TargetHandler::AttachToTargetInternal(DevToolsAgentHost* host,
227 DevToolsAgentHost* host, bool waiting_for_debugger) { 281 bool waiting_for_debugger,
228 attached_hosts_[host->GetId()] = host; 282 bool is_auto_attach) {
229 if (!host->AttachClient(this)) { 283 std::string session_id =
230 attached_hosts_.erase(host->GetId()); 284 base::StringPrintf("%s:%d", host->GetId().c_str(), ++last_session_id_);
285 Session* session = new Session(this, host, session_id, is_auto_attach);
286 attached_sessions_[session_id].reset(session);
287 session->Attach();
288 frontend_->AttachedToTarget(session_id, CreateInfo(host),
289 waiting_for_debugger);
290 return session_id;
291 }
292
293 bool TargetHandler::DetachFromSessionInternal(const std::string& session_id) {
294 auto it = attached_sessions_.find(session_id);
295 if (it == attached_sessions_.end())
231 return false; 296 return false;
232 } 297 frontend_->DetachedFromTarget(session_id);
233 frontend_->AttachedToTarget(CreateInfo(host), waiting_for_debugger); 298 attached_sessions_.erase(it);
234 return true; 299 return true;
235 } 300 }
236 301
237 void TargetHandler::DetachFromTargetInternal(DevToolsAgentHost* host) { 302 bool TargetHandler::IsAttachedToAgentHost(DevToolsAgentHost* agent_host) {
238 auto it = attached_hosts_.find(host->GetId()); 303 for (auto& it : attached_sessions_) {
239 if (it == attached_hosts_.end()) 304 if (it.second->agent_host() == agent_host)
240 return; 305 return true;
241 host->DetachClient(this); 306 }
242 frontend_->DetachedFromTarget(host->GetId()); 307 return false;
243 attached_hosts_.erase(it);
244 } 308 }
245 309
246 // ----------------- Protocol ---------------------- 310 // ----------------- Protocol ----------------------
247 311
248 Response TargetHandler::SetDiscoverTargets(bool discover) { 312 Response TargetHandler::SetDiscoverTargets(bool discover) {
249 if (discover_ == discover) 313 if (discover_ == discover)
250 return Response::OK(); 314 return Response::OK();
251 discover_ = discover; 315 discover_ = discover;
252 if (discover_) { 316 if (discover_) {
253 DevToolsAgentHost::AddObserver(this); 317 DevToolsAgentHost::AddObserver(this);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 } 355 }
292 return Response::OK(); 356 return Response::OK();
293 } 357 }
294 358
295 Response TargetHandler::SetRemoteLocations( 359 Response TargetHandler::SetRemoteLocations(
296 std::unique_ptr<protocol::Array<Target::RemoteLocation>>) { 360 std::unique_ptr<protocol::Array<Target::RemoteLocation>>) {
297 return Response::Error("Not supported"); 361 return Response::Error("Not supported");
298 } 362 }
299 363
300 Response TargetHandler::AttachToTarget(const std::string& target_id, 364 Response TargetHandler::AttachToTarget(const std::string& target_id,
301 bool* out_success) { 365 Maybe<std::string>* out_session_id) {
302 // TODO(dgozman): only allow reported hosts. 366 // TODO(dgozman): only allow reported hosts.
303 scoped_refptr<DevToolsAgentHost> agent_host = 367 scoped_refptr<DevToolsAgentHost> agent_host =
304 DevToolsAgentHost::GetForId(target_id); 368 DevToolsAgentHost::GetForId(target_id);
305 if (!agent_host) 369 if (!agent_host)
306 return Response::InvalidParams("No target with given id found"); 370 return Response::InvalidParams("No target with given id found");
307 *out_success = AttachToTargetInternal(agent_host.get(), false); 371 *out_session_id = AttachToTargetInternal(agent_host.get(), false, false);
308 return Response::OK(); 372 return Response::OK();
309 } 373 }
310 374
311 Response TargetHandler::DetachFromTarget(const std::string& target_id) { 375 Response TargetHandler::DetachFromTarget(const std::string& session_id) {
312 auto it = attached_hosts_.find(target_id); 376 if (!DetachFromSessionInternal(session_id))
313 if (it == attached_hosts_.end()) 377 return Response::Error("No session with given id");
314 return Response::Error("Not attached to the target");
315 DevToolsAgentHost* agent_host = it->second.get();
316 DetachFromTargetInternal(agent_host);
317 return Response::OK(); 378 return Response::OK();
318 } 379 }
319 380
320 Response TargetHandler::SendMessageToTarget( 381 Response TargetHandler::SendMessageToTarget(const std::string& session_id,
321 const std::string& target_id, 382 const std::string& message) {
322 const std::string& message) { 383 auto it = attached_sessions_.find(session_id);
323 auto it = attached_hosts_.find(target_id); 384 if (it == attached_sessions_.end())
324 if (it == attached_hosts_.end())
325 return Response::FallThrough(); 385 return Response::FallThrough();
326 it->second->DispatchProtocolMessage(this, message); 386 it->second->agent_host()->DispatchProtocolMessage(it->second.get(), message);
327 return Response::OK(); 387 return Response::OK();
328 } 388 }
329 389
330 Response TargetHandler::GetTargetInfo( 390 Response TargetHandler::GetTargetInfo(
331 const std::string& target_id, 391 const std::string& target_id,
332 std::unique_ptr<Target::TargetInfo>* target_info) { 392 std::unique_ptr<Target::TargetInfo>* target_info) {
333 // TODO(dgozman): only allow reported hosts. 393 // TODO(dgozman): only allow reported hosts.
334 scoped_refptr<DevToolsAgentHost> agent_host( 394 scoped_refptr<DevToolsAgentHost> agent_host(
335 DevToolsAgentHost::GetForId(target_id)); 395 DevToolsAgentHost::GetForId(target_id));
336 if (!agent_host) 396 if (!agent_host)
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 } 446 }
387 447
388 Response TargetHandler::GetTargets( 448 Response TargetHandler::GetTargets(
389 std::unique_ptr<protocol::Array<Target::TargetInfo>>* target_infos) { 449 std::unique_ptr<protocol::Array<Target::TargetInfo>>* target_infos) {
390 *target_infos = protocol::Array<Target::TargetInfo>::create(); 450 *target_infos = protocol::Array<Target::TargetInfo>::create();
391 for (const auto& host : DevToolsAgentHost::GetOrCreateAll()) 451 for (const auto& host : DevToolsAgentHost::GetOrCreateAll())
392 (*target_infos)->addItem(CreateInfo(host.get())); 452 (*target_infos)->addItem(CreateInfo(host.get()));
393 return Response::OK(); 453 return Response::OK();
394 } 454 }
395 455
396 // ---------------- DevToolsAgentHostClient ----------------
397
398 void TargetHandler::DispatchProtocolMessage(
399 DevToolsAgentHost* host,
400 const std::string& message) {
401 auto it = attached_hosts_.find(host->GetId());
402 if (it == attached_hosts_.end())
403 return; // Already disconnected.
404
405 frontend_->ReceivedMessageFromTarget(host->GetId(), message);
406 }
407
408 void TargetHandler::AgentHostClosed(
409 DevToolsAgentHost* host,
410 bool replaced_with_another_client) {
411 frontend_->DetachedFromTarget(host->GetId());
412 attached_hosts_.erase(host->GetId());
413 }
414
415 // -------------- DevToolsAgentHostObserver ----------------- 456 // -------------- DevToolsAgentHostObserver -----------------
416 457
417 bool TargetHandler::ShouldForceDevToolsAgentHostCreation() { 458 bool TargetHandler::ShouldForceDevToolsAgentHostCreation() {
418 return true; 459 return true;
419 } 460 }
420 461
421 void TargetHandler::DevToolsAgentHostCreated(DevToolsAgentHost* agent_host) { 462 void TargetHandler::DevToolsAgentHostCreated(DevToolsAgentHost* agent_host) {
422 if (agent_host->GetType() == "node" && agent_host->IsAttached()) 463 if (agent_host->GetType() == "node" && agent_host->IsAttached())
423 return; 464 return;
424 // If we start discovering late, all existing agent hosts will be reported, 465 // If we start discovering late, all existing agent hosts will be reported,
425 // but we could have already attached to some. 466 // but we could have already attached to some.
426 TargetCreatedInternal(agent_host); 467 TargetCreatedInternal(agent_host);
427 } 468 }
428 469
429 void TargetHandler::DevToolsAgentHostDestroyed(DevToolsAgentHost* agent_host) { 470 void TargetHandler::DevToolsAgentHostDestroyed(DevToolsAgentHost* agent_host) {
430 DCHECK(attached_hosts_.find(agent_host->GetId()) == attached_hosts_.end()); 471 DCHECK(auto_attached_hosts_.find(agent_host->GetId()) ==
472 auto_attached_hosts_.end());
431 TargetDestroyedInternal(agent_host); 473 TargetDestroyedInternal(agent_host);
432 } 474 }
433 475
434 void TargetHandler::DevToolsAgentHostAttached(DevToolsAgentHost* host) { 476 void TargetHandler::DevToolsAgentHostAttached(DevToolsAgentHost* host) {
435 if (host->GetType() == "node" && 477 if (host->GetType() == "node" &&
436 reported_hosts_.find(host->GetId()) != reported_hosts_.end() && 478 reported_hosts_.find(host->GetId()) != reported_hosts_.end() &&
437 attached_hosts_.find(host->GetId()) == attached_hosts_.end()) { 479 !IsAttachedToAgentHost(host)) {
438 TargetDestroyedInternal(host); 480 TargetDestroyedInternal(host);
439 } 481 }
440 } 482 }
441 483
442 void TargetHandler::DevToolsAgentHostDetached(DevToolsAgentHost* host) { 484 void TargetHandler::DevToolsAgentHostDetached(DevToolsAgentHost* host) {
443 if (host->GetType() == "node" && 485 if (host->GetType() == "node" &&
444 reported_hosts_.find(host->GetId()) == reported_hosts_.end() && 486 reported_hosts_.find(host->GetId()) == reported_hosts_.end() &&
445 attached_hosts_.find(host->GetId()) == attached_hosts_.end()) { 487 !IsAttachedToAgentHost(host)) {
446 TargetCreatedInternal(host); 488 TargetCreatedInternal(host);
447 } 489 }
448 } 490 }
449 491
450 // -------- ServiceWorkerDevToolsManager::Observer ---------- 492 // -------- ServiceWorkerDevToolsManager::Observer ----------
451 493
452 void TargetHandler::WorkerCreated( 494 void TargetHandler::WorkerCreated(
453 ServiceWorkerDevToolsAgentHost* host) { 495 ServiceWorkerDevToolsAgentHost* host) {
454 BrowserContext* browser_context = nullptr; 496 BrowserContext* browser_context = nullptr;
455 if (render_frame_host_) 497 if (render_frame_host_)
(...skipping 27 matching lines...) Expand all
483 UpdateServiceWorkers(); 525 UpdateServiceWorkers();
484 } 526 }
485 527
486 void TargetHandler::WorkerDestroyed( 528 void TargetHandler::WorkerDestroyed(
487 ServiceWorkerDevToolsAgentHost* host) { 529 ServiceWorkerDevToolsAgentHost* host) {
488 UpdateServiceWorkers(); 530 UpdateServiceWorkers();
489 } 531 }
490 532
491 } // namespace protocol 533 } // namespace protocol
492 } // namespace content 534 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698