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

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

Issue 2969753002: [DevTools] Split auto-attach part of TargetHandler into a separate class (Closed)
Patch Set: rebased, addressed comment 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 "content/browser/devtools/devtools_manager.h" 7 #include "content/browser/devtools/devtools_manager.h"
8 #include "content/browser/devtools/devtools_session.h" 8 #include "content/browser/devtools/devtools_session.h"
9 #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/frame_host/frame_tree.h"
12 #include "content/browser/frame_host/frame_tree_node.h"
13 #include "content/browser/frame_host/render_frame_host_impl.h"
14 9
15 namespace content { 10 namespace content {
16 namespace protocol { 11 namespace protocol {
17 12
18 namespace { 13 namespace {
19 14
20 using ScopeAgentsMap =
21 std::map<GURL, std::unique_ptr<ServiceWorkerDevToolsAgentHost::List>>;
22
23 void GetMatchingHostsByScopeMap(
24 const ServiceWorkerDevToolsAgentHost::List& agent_hosts,
25 const std::set<GURL>& urls,
26 ScopeAgentsMap* scope_agents_map) {
27 std::set<base::StringPiece> host_name_set;
28 for (const GURL& url : urls)
29 host_name_set.insert(url.host_piece());
30 for (const auto& host : agent_hosts) {
31 if (host_name_set.find(host->scope().host_piece()) == host_name_set.end())
32 continue;
33 const auto& it = scope_agents_map->find(host->scope());
34 if (it == scope_agents_map->end()) {
35 std::unique_ptr<ServiceWorkerDevToolsAgentHost::List> new_list(
36 new ServiceWorkerDevToolsAgentHost::List());
37 new_list->push_back(host);
38 (*scope_agents_map)[host->scope()] = std::move(new_list);
39 } else {
40 it->second->push_back(host);
41 }
42 }
43 }
44
45 void AddEligibleHosts(const ServiceWorkerDevToolsAgentHost::List& list,
46 ServiceWorkerDevToolsAgentHost::Map* result) {
47 base::Time last_installed_time;
48 base::Time last_doomed_time;
49 for (const auto& host : list) {
50 if (host->version_installed_time() > last_installed_time)
51 last_installed_time = host->version_installed_time();
52 if (host->version_doomed_time() > last_doomed_time)
53 last_doomed_time = host->version_doomed_time();
54 }
55 for (const auto& host : list) {
56 // We don't attech old redundant Service Workers when there is newer
57 // installed Service Worker.
58 if (host->version_doomed_time().is_null() ||
59 (last_installed_time < last_doomed_time &&
60 last_doomed_time == host->version_doomed_time())) {
61 (*result)[host->GetId()] = host;
62 }
63 }
64 }
65
66 ServiceWorkerDevToolsAgentHost::Map GetMatchingServiceWorkers(
67 BrowserContext* browser_context,
68 const std::set<GURL>& urls) {
69 ServiceWorkerDevToolsAgentHost::Map result;
70 if (!browser_context)
71 return result;
72
73 ServiceWorkerDevToolsAgentHost::List agent_hosts;
74 ServiceWorkerDevToolsManager::GetInstance()
75 ->AddAllAgentHostsForBrowserContext(browser_context, &agent_hosts);
76
77 ScopeAgentsMap scope_agents_map;
78 GetMatchingHostsByScopeMap(agent_hosts, urls, &scope_agents_map);
79
80 for (const auto& it : scope_agents_map)
81 AddEligibleHosts(*it.second.get(), &result);
82
83 return result;
84 }
85
86 std::unique_ptr<Target::TargetInfo> CreateInfo(DevToolsAgentHost* host) { 15 std::unique_ptr<Target::TargetInfo> CreateInfo(DevToolsAgentHost* host) {
87 return Target::TargetInfo::Create() 16 return Target::TargetInfo::Create()
88 .SetTargetId(host->GetId()) 17 .SetTargetId(host->GetId())
89 .SetTitle(host->GetTitle()) 18 .SetTitle(host->GetTitle())
90 .SetUrl(host->GetURL().spec()) 19 .SetUrl(host->GetURL().spec())
91 .SetType(host->GetType()) 20 .SetType(host->GetType())
92 .SetAttached(host->IsAttached()) 21 .SetAttached(host->IsAttached())
93 .Build(); 22 .Build();
94 } 23 }
95 24
96 } // namespace 25 } // namespace
97 26
98 TargetHandler::TargetHandler() 27 TargetHandler::TargetHandler()
99 : DevToolsDomainHandler(Target::Metainfo::domainName), 28 : DevToolsDomainHandler(Target::Metainfo::domainName),
100 discover_(false), 29 auto_attacher_(base::Bind(&TargetHandler::AttachToTargetInternal,
101 auto_attach_(false), 30 base::Unretained(this)),
102 wait_for_debugger_on_start_(false), 31 base::Bind(&TargetHandler::DetachFromTargetInternal,
103 attach_to_frames_(false), 32 base::Unretained(this))),
104 render_frame_host_(nullptr) { 33 discover_(false) {}
105 }
106 34
107 TargetHandler::~TargetHandler() { 35 TargetHandler::~TargetHandler() {
108 } 36 }
109 37
110 // static 38 // static
111 std::vector<TargetHandler*> TargetHandler::ForAgentHost( 39 std::vector<TargetHandler*> TargetHandler::ForAgentHost(
112 DevToolsAgentHostImpl* host) { 40 DevToolsAgentHostImpl* host) {
113 return DevToolsSession::HandlersForAgentHost<TargetHandler>( 41 return DevToolsSession::HandlersForAgentHost<TargetHandler>(
114 host, Target::Metainfo::domainName); 42 host, Target::Metainfo::domainName);
115 } 43 }
116 44
117 void TargetHandler::Wire(UberDispatcher* dispatcher) { 45 void TargetHandler::Wire(UberDispatcher* dispatcher) {
118 frontend_.reset(new Target::Frontend(dispatcher->channel())); 46 frontend_.reset(new Target::Frontend(dispatcher->channel()));
119 Target::Dispatcher::wire(dispatcher, this); 47 Target::Dispatcher::wire(dispatcher, this);
120 } 48 }
121 49
122 void TargetHandler::SetRenderFrameHost(RenderFrameHostImpl* render_frame_host) { 50 void TargetHandler::SetRenderFrameHost(RenderFrameHostImpl* render_frame_host) {
123 render_frame_host_ = render_frame_host; 51 auto_attacher_.SetRenderFrameHost(render_frame_host);
124 UpdateFrames();
125 } 52 }
126 53
127 Response TargetHandler::Disable() { 54 Response TargetHandler::Disable() {
128 SetAutoAttach(false, false); 55 SetAutoAttach(false, false);
129 SetDiscoverTargets(false); 56 SetDiscoverTargets(false);
130 for (const auto& id_host : attached_hosts_) 57 for (const auto& id_host : attached_hosts_)
131 id_host.second->DetachClient(this); 58 id_host.second->DetachClient(this);
132 attached_hosts_.clear(); 59 attached_hosts_.clear();
133 return Response::OK(); 60 return Response::OK();
134 } 61 }
135 62
136 void TargetHandler::UpdateServiceWorkers() { 63 void TargetHandler::DidCommitNavigation() {
137 UpdateServiceWorkers(false); 64 auto_attacher_.UpdateServiceWorkers();
138 } 65 }
139 66
140 void TargetHandler::UpdateFrames() { 67 void TargetHandler::RenderFrameHostChanged() {
141 if (!auto_attach_ || !attach_to_frames_) 68 auto_attacher_.UpdateFrames();
142 return;
143
144 HostsMap new_hosts;
145 if (render_frame_host_) {
146 FrameTreeNode* root = render_frame_host_->frame_tree_node();
147 std::queue<FrameTreeNode*> queue;
148 queue.push(root);
149 while (!queue.empty()) {
150 FrameTreeNode* node = queue.front();
151 queue.pop();
152 bool cross_process = node->current_frame_host()->IsCrossProcessSubframe();
153 if (node != root && cross_process) {
154 scoped_refptr<DevToolsAgentHost> new_host =
155 RenderFrameDevToolsAgentHost::GetOrCreateFor(node);
156 new_hosts[new_host->GetId()] = new_host;
157 } else {
158 for (size_t i = 0; i < node->child_count(); ++i)
159 queue.push(node->child_at(i));
160 }
161 }
162 }
163
164 // TODO(dgozman): support wait_for_debugger_on_start_.
165 ReattachTargetsOfType(new_hosts, DevToolsAgentHost::kTypeFrame, false);
166 }
167
168 void TargetHandler::UpdateServiceWorkers(bool waiting_for_debugger) {
169 if (!auto_attach_)
170 return;
171
172 frame_urls_.clear();
173 BrowserContext* browser_context = nullptr;
174 if (render_frame_host_) {
175 // TODO(dgozman): do not traverse inside cross-process subframes.
176 for (FrameTreeNode* node :
177 render_frame_host_->frame_tree_node()->frame_tree()->Nodes()) {
178 frame_urls_.insert(node->current_url());
179 }
180 browser_context = render_frame_host_->GetProcess()->GetBrowserContext();
181 }
182
183 auto matching = GetMatchingServiceWorkers(browser_context, frame_urls_);
184 HostsMap new_hosts;
185 for (const auto& pair : matching) {
186 if (pair.second->IsReadyForInspection())
187 new_hosts[pair.first] = pair.second;
188 }
189 ReattachTargetsOfType(
190 new_hosts, DevToolsAgentHost::kTypeServiceWorker, waiting_for_debugger);
191 }
192
193 void TargetHandler::ReattachTargetsOfType(
194 const HostsMap& new_hosts,
195 const std::string& type,
196 bool waiting_for_debugger) {
197 HostsMap old_hosts = attached_hosts_;
198 for (const auto& pair : old_hosts) {
199 if (pair.second->GetType() == type &&
200 new_hosts.find(pair.first) == new_hosts.end()) {
201 DetachFromTargetInternal(pair.second.get());
202 }
203 }
204 for (const auto& pair : new_hosts) {
205 if (old_hosts.find(pair.first) == old_hosts.end())
206 AttachToTargetInternal(pair.second.get(), waiting_for_debugger);
207 }
208 } 69 }
209 70
210 void TargetHandler::TargetCreatedInternal(DevToolsAgentHost* host) { 71 void TargetHandler::TargetCreatedInternal(DevToolsAgentHost* host) {
211 if (reported_hosts_.find(host->GetId()) != reported_hosts_.end()) 72 if (reported_hosts_.find(host->GetId()) != reported_hosts_.end())
212 return; 73 return;
213 frontend_->TargetCreated(CreateInfo(host)); 74 frontend_->TargetCreated(CreateInfo(host));
214 reported_hosts_[host->GetId()] = host; 75 reported_hosts_[host->GetId()] = host;
215 } 76 }
216 77
217 void TargetHandler::TargetInfoChangedInternal(DevToolsAgentHost* host) { 78 void TargetHandler::TargetInfoChangedInternal(DevToolsAgentHost* host) {
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 DevToolsAgentHost::RemoveObserver(this); 122 DevToolsAgentHost::RemoveObserver(this);
262 RawHostsMap copy = reported_hosts_; 123 RawHostsMap copy = reported_hosts_;
263 for (const auto& id_host : copy) 124 for (const auto& id_host : copy)
264 TargetDestroyedInternal(id_host.second); 125 TargetDestroyedInternal(id_host.second);
265 } 126 }
266 return Response::OK(); 127 return Response::OK();
267 } 128 }
268 129
269 Response TargetHandler::SetAutoAttach( 130 Response TargetHandler::SetAutoAttach(
270 bool auto_attach, bool wait_for_debugger_on_start) { 131 bool auto_attach, bool wait_for_debugger_on_start) {
271 wait_for_debugger_on_start_ = wait_for_debugger_on_start; 132 auto_attacher_.SetAutoAttach(auto_attach, wait_for_debugger_on_start);
272 if (auto_attach_ == auto_attach)
273 return Response::FallThrough();
274 auto_attach_ = auto_attach;
275 if (auto_attach_) {
276 ServiceWorkerDevToolsManager::GetInstance()->AddObserver(this);
277 UpdateServiceWorkers();
278 UpdateFrames();
279 } else {
280 ServiceWorkerDevToolsManager::GetInstance()->RemoveObserver(this);
281 HostsMap empty;
282 ReattachTargetsOfType(empty, DevToolsAgentHost::kTypeFrame, false);
283 ReattachTargetsOfType(empty, DevToolsAgentHost::kTypeServiceWorker, false);
284 }
285 return Response::FallThrough(); 133 return Response::FallThrough();
286 } 134 }
287 135
288 Response TargetHandler::SetAttachToFrames(bool value) { 136 Response TargetHandler::SetAttachToFrames(bool value) {
289 if (attach_to_frames_ == value) 137 auto_attacher_.SetAttachToFrames(value);
290 return Response::OK();
291 attach_to_frames_ = value;
292 if (attach_to_frames_) {
293 UpdateFrames();
294 } else {
295 HostsMap empty;
296 ReattachTargetsOfType(empty, DevToolsAgentHost::kTypeFrame, false);
297 }
298 return Response::OK(); 138 return Response::OK();
299 } 139 }
300 140
301 Response TargetHandler::SetRemoteLocations( 141 Response TargetHandler::SetRemoteLocations(
302 std::unique_ptr<protocol::Array<Target::RemoteLocation>>) { 142 std::unique_ptr<protocol::Array<Target::RemoteLocation>>) {
303 return Response::Error("Not supported"); 143 return Response::Error("Not supported");
304 } 144 }
305 145
306 Response TargetHandler::AttachToTarget(const std::string& target_id, 146 Response TargetHandler::AttachToTarget(const std::string& target_id,
307 bool* out_success) { 147 bool* out_success) {
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
409 return; // Already disconnected. 249 return; // Already disconnected.
410 250
411 frontend_->ReceivedMessageFromTarget(host->GetId(), message); 251 frontend_->ReceivedMessageFromTarget(host->GetId(), message);
412 } 252 }
413 253
414 void TargetHandler::AgentHostClosed( 254 void TargetHandler::AgentHostClosed(
415 DevToolsAgentHost* host, 255 DevToolsAgentHost* host,
416 bool replaced_with_another_client) { 256 bool replaced_with_another_client) {
417 frontend_->DetachedFromTarget(host->GetId()); 257 frontend_->DetachedFromTarget(host->GetId());
418 attached_hosts_.erase(host->GetId()); 258 attached_hosts_.erase(host->GetId());
259 auto_attacher_.AgentHostClosed(host);
419 } 260 }
420 261
421 // -------------- DevToolsAgentHostObserver ----------------- 262 // -------------- DevToolsAgentHostObserver -----------------
422 263
423 bool TargetHandler::ShouldForceDevToolsAgentHostCreation() { 264 bool TargetHandler::ShouldForceDevToolsAgentHostCreation() {
424 return true; 265 return true;
425 } 266 }
426 267
427 void TargetHandler::DevToolsAgentHostCreated(DevToolsAgentHost* agent_host) { 268 void TargetHandler::DevToolsAgentHostCreated(DevToolsAgentHost* agent_host) {
428 // If we start discovering late, all existing agent hosts will be reported, 269 // If we start discovering late, all existing agent hosts will be reported,
429 // but we could have already attached to some. 270 // but we could have already attached to some.
430 TargetCreatedInternal(agent_host); 271 TargetCreatedInternal(agent_host);
431 } 272 }
432 273
433 void TargetHandler::DevToolsAgentHostDestroyed(DevToolsAgentHost* agent_host) { 274 void TargetHandler::DevToolsAgentHostDestroyed(DevToolsAgentHost* agent_host) {
434 DCHECK(attached_hosts_.find(agent_host->GetId()) == attached_hosts_.end()); 275 DCHECK(attached_hosts_.find(agent_host->GetId()) == attached_hosts_.end());
435 TargetDestroyedInternal(agent_host); 276 TargetDestroyedInternal(agent_host);
436 } 277 }
437 278
438 void TargetHandler::DevToolsAgentHostAttached(DevToolsAgentHost* host) { 279 void TargetHandler::DevToolsAgentHostAttached(DevToolsAgentHost* host) {
439 TargetInfoChangedInternal(host); 280 TargetInfoChangedInternal(host);
440 } 281 }
441 282
442 void TargetHandler::DevToolsAgentHostDetached(DevToolsAgentHost* host) { 283 void TargetHandler::DevToolsAgentHostDetached(DevToolsAgentHost* host) {
443 TargetInfoChangedInternal(host); 284 TargetInfoChangedInternal(host);
444 } 285 }
445 286
446 // -------- ServiceWorkerDevToolsManager::Observer ----------
447
448 void TargetHandler::WorkerCreated(
449 ServiceWorkerDevToolsAgentHost* host) {
450 BrowserContext* browser_context = nullptr;
451 if (render_frame_host_)
452 browser_context = render_frame_host_->GetProcess()->GetBrowserContext();
453 auto hosts = GetMatchingServiceWorkers(browser_context, frame_urls_);
454 if (hosts.find(host->GetId()) != hosts.end() && !host->IsAttached() &&
455 !host->IsPausedForDebugOnStart() && wait_for_debugger_on_start_) {
456 host->PauseForDebugOnStart();
457 }
458 }
459
460 void TargetHandler::WorkerReadyForInspection(
461 ServiceWorkerDevToolsAgentHost* host) {
462 DCHECK(host->IsReadyForInspection());
463 if (ServiceWorkerDevToolsManager::GetInstance()
464 ->debug_service_worker_on_start()) {
465 // When debug_service_worker_on_start is true, a new DevTools window will
466 // be opened in ServiceWorkerDevToolsManager::WorkerReadyForInspection.
467 return;
468 }
469 UpdateServiceWorkers(host->IsPausedForDebugOnStart());
470 }
471
472 void TargetHandler::WorkerVersionInstalled(
473 ServiceWorkerDevToolsAgentHost* host) {
474 UpdateServiceWorkers();
475 }
476
477 void TargetHandler::WorkerVersionDoomed(
478 ServiceWorkerDevToolsAgentHost* host) {
479 UpdateServiceWorkers();
480 }
481
482 void TargetHandler::WorkerDestroyed(
483 ServiceWorkerDevToolsAgentHost* host) {
484 UpdateServiceWorkers();
485 }
486
487 } // namespace protocol 287 } // namespace protocol
488 } // namespace content 288 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/devtools/protocol/target_handler.h ('k') | content/browser/devtools/render_frame_devtools_agent_host.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698