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

Side by Side Diff: content/browser/devtools/embedded_worker_devtools_manager.cc

Issue 349033009: DevTools: Added service workers to chrome://inspect/#devices (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed lifetime again Created 6 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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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/embedded_worker_devtools_manager.h" 5 #include "content/browser/devtools/embedded_worker_devtools_manager.h"
6 6
7 #include "content/browser/devtools/devtools_manager_impl.h" 7 #include "content/browser/devtools/devtools_manager_impl.h"
8 #include "content/browser/devtools/devtools_protocol.h" 8 #include "content/browser/devtools/devtools_protocol.h"
9 #include "content/browser/devtools/devtools_protocol_constants.h" 9 #include "content/browser/devtools/devtools_protocol_constants.h"
10 #include "content/browser/devtools/ipc_devtools_agent_host.h" 10 #include "content/browser/devtools/ipc_devtools_agent_host.h"
11 #include "content/browser/service_worker/service_worker_context_core.h"
12 #include "content/browser/service_worker/service_worker_version.h"
11 #include "content/browser/shared_worker/shared_worker_instance.h" 13 #include "content/browser/shared_worker/shared_worker_instance.h"
12 #include "content/common/devtools_messages.h" 14 #include "content/common/devtools_messages.h"
13 #include "content/public/browser/browser_thread.h" 15 #include "content/public/browser/browser_thread.h"
14 #include "content/public/browser/render_process_host.h" 16 #include "content/public/browser/render_process_host.h"
15 #include "content/public/browser/worker_service.h" 17 #include "content/public/browser/worker_service.h"
16 #include "ipc/ipc_listener.h" 18 #include "ipc/ipc_listener.h"
17 19
18 namespace content { 20 namespace content {
19 21
20 namespace { 22 namespace {
21 23
22 bool SendMessageToWorker( 24 bool SendMessageToWorker(
23 const EmbeddedWorkerDevToolsManager::WorkerId& worker_id, 25 const EmbeddedWorkerDevToolsManager::WorkerId& worker_id,
24 IPC::Message* message) { 26 IPC::Message* message) {
25 RenderProcessHost* host = RenderProcessHost::FromID(worker_id.first); 27 RenderProcessHost* host = RenderProcessHost::FromID(worker_id.first);
26 if (!host) { 28 if (!host) {
27 delete message; 29 delete message;
28 return false; 30 return false;
29 } 31 }
30 message->set_routing_id(worker_id.second); 32 message->set_routing_id(worker_id.second);
31 host->Send(message); 33 host->Send(message);
32 return true; 34 return true;
33 } 35 }
34 36
35 } // namespace 37 } // namespace
36 38
37 EmbeddedWorkerDevToolsManager::ServiceWorkerIdentifier::ServiceWorkerIdentifier( 39 EmbeddedWorkerDevToolsManager::ServiceWorkerIdentifier::ServiceWorkerIdentifier(
38 const ServiceWorkerContextCore* const service_worker_context, 40 const ServiceWorkerContextCore* service_worker_context,
41 base::WeakPtr<ServiceWorkerContextCore> service_worker_context_weak,
39 int64 service_worker_version_id) 42 int64 service_worker_version_id)
40 : service_worker_context_(service_worker_context), 43 : service_worker_context_(service_worker_context),
44 service_worker_context_weak_(service_worker_context_weak),
41 service_worker_version_id_(service_worker_version_id) { 45 service_worker_version_id_(service_worker_version_id) {
42 } 46 }
43 47
44 EmbeddedWorkerDevToolsManager::ServiceWorkerIdentifier::ServiceWorkerIdentifier( 48 EmbeddedWorkerDevToolsManager::ServiceWorkerIdentifier::ServiceWorkerIdentifier(
45 const ServiceWorkerIdentifier& other) 49 const ServiceWorkerIdentifier& other)
46 : service_worker_context_(other.service_worker_context_), 50 : service_worker_context_(other.service_worker_context_),
51 service_worker_context_weak_(other.service_worker_context_weak_),
47 service_worker_version_id_(other.service_worker_version_id_) { 52 service_worker_version_id_(other.service_worker_version_id_) {
48 } 53 }
49 54
55 EmbeddedWorkerDevToolsManager::
56 ServiceWorkerIdentifier::~ServiceWorkerIdentifier() {
57 }
58
50 bool EmbeddedWorkerDevToolsManager::ServiceWorkerIdentifier::Matches( 59 bool EmbeddedWorkerDevToolsManager::ServiceWorkerIdentifier::Matches(
51 const ServiceWorkerIdentifier& other) const { 60 const ServiceWorkerIdentifier& other) const {
52 return service_worker_context_ == other.service_worker_context_ && 61 return service_worker_context_ == other.service_worker_context_ &&
53 service_worker_version_id_ == other.service_worker_version_id_; 62 service_worker_version_id_ == other.service_worker_version_id_;
54 } 63 }
55 64
56 EmbeddedWorkerDevToolsManager::WorkerInfo::WorkerInfo( 65 EmbeddedWorkerDevToolsManager::WorkerInfo::WorkerInfo(
57 const SharedWorkerInstance& instance) 66 const SharedWorkerInstance& instance)
58 : shared_worker_instance_(new SharedWorkerInstance(instance)), 67 : shared_worker_instance_(new SharedWorkerInstance(instance)),
59 state_(WORKER_UNINSPECTED), 68 state_(WORKER_UNINSPECTED),
(...skipping 21 matching lines...) Expand all
81 return service_worker_id_->Matches(other); 90 return service_worker_id_->Matches(other);
82 } 91 }
83 92
84 EmbeddedWorkerDevToolsManager::WorkerInfo::~WorkerInfo() { 93 EmbeddedWorkerDevToolsManager::WorkerInfo::~WorkerInfo() {
85 } 94 }
86 95
87 class EmbeddedWorkerDevToolsManager::EmbeddedWorkerDevToolsAgentHost 96 class EmbeddedWorkerDevToolsManager::EmbeddedWorkerDevToolsAgentHost
88 : public IPCDevToolsAgentHost, 97 : public IPCDevToolsAgentHost,
89 public IPC::Listener { 98 public IPC::Listener {
90 public: 99 public:
91 explicit EmbeddedWorkerDevToolsAgentHost(WorkerId worker_id) 100 EmbeddedWorkerDevToolsAgentHost(WorkerId worker_id, const GURL& url)
92 : worker_id_(worker_id), worker_attached_(false) { 101 : worker_id_(worker_id), worker_attached_(false), url_(url) {
93 AttachToWorker(); 102 WorkerCreated();
94 } 103 }
95 104
96 // DevToolsAgentHost override. 105 // DevToolsAgentHost override.
97 virtual bool IsWorker() const OVERRIDE { return true; } 106 virtual bool IsWorker() const OVERRIDE { return true; }
107 virtual GURL GetURL() OVERRIDE { return url_; }
98 108
99 // IPCDevToolsAgentHost implementation. 109 // IPCDevToolsAgentHost implementation.
100 virtual void SendMessageToAgent(IPC::Message* message) OVERRIDE { 110 virtual void SendMessageToAgent(IPC::Message* message) OVERRIDE {
101 if (worker_attached_) 111 if (worker_attached_)
102 SendMessageToWorker(worker_id_, message); 112 SendMessageToWorker(worker_id_, message);
103 else 113 else
104 delete message; 114 delete message;
105 } 115 }
106 virtual void Attach() OVERRIDE { 116 virtual void Attach() OVERRIDE {
107 AttachToWorker(); 117 AttachToWorker();
(...skipping 24 matching lines...) Expand all
132 AttachToWorker(); 142 AttachToWorker();
133 Reattach(state_); 143 Reattach(state_);
134 } 144 }
135 145
136 void DetachFromWorker() { 146 void DetachFromWorker() {
137 if (!worker_attached_) 147 if (!worker_attached_)
138 return; 148 return;
139 worker_attached_ = false; 149 worker_attached_ = false;
140 if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first)) 150 if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first))
141 host->RemoveRoute(worker_id_.second); 151 host->RemoveRoute(worker_id_.second);
152 }
153
154 void WorkerDestroyed() {
142 Release(); 155 Release();
143 } 156 }
144 157
158 void WorkerCreated() {
159 AddRef();
160 }
161
145 WorkerId worker_id() const { return worker_id_; } 162 WorkerId worker_id() const { return worker_id_; }
146 163
147 private: 164 private:
148 virtual ~EmbeddedWorkerDevToolsAgentHost() { 165 virtual ~EmbeddedWorkerDevToolsAgentHost() {
149 CHECK(!worker_attached_); 166 CHECK(!worker_attached_);
150 EmbeddedWorkerDevToolsManager::GetInstance()->RemoveInspectedWorkerData( 167 EmbeddedWorkerDevToolsManager::GetInstance()->RemoveInspectedWorkerData(
151 this); 168 this);
152 } 169 }
153 170
154 void OnDispatchOnInspectorFrontend(const std::string& message) { 171 void OnDispatchOnInspectorFrontend(const std::string& message) {
155 DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend(this, 172 DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend(this,
156 message); 173 message);
157 } 174 }
158 175
159 void OnSaveAgentRuntimeState(const std::string& state) { state_ = state; } 176 void OnSaveAgentRuntimeState(const std::string& state) { state_ = state; }
160 177
161 void AttachToWorker() { 178 void AttachToWorker() {
162 if (worker_attached_) 179 if (worker_attached_)
163 return; 180 return;
164 worker_attached_ = true; 181 worker_attached_ = true;
165 AddRef();
166 if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first)) 182 if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first))
167 host->AddRoute(worker_id_.second, this); 183 host->AddRoute(worker_id_.second, this);
168 } 184 }
169 185
170 WorkerId worker_id_; 186 WorkerId worker_id_;
171 bool worker_attached_; 187 bool worker_attached_;
188 GURL url_;
172 std::string state_; 189 std::string state_;
173 DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerDevToolsAgentHost); 190 DISALLOW_COPY_AND_ASSIGN(EmbeddedWorkerDevToolsAgentHost);
174 }; 191 };
175 192
176 // static 193 // static
177 EmbeddedWorkerDevToolsManager* EmbeddedWorkerDevToolsManager::GetInstance() { 194 EmbeddedWorkerDevToolsManager* EmbeddedWorkerDevToolsManager::GetInstance() {
178 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 195 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
179 return Singleton<EmbeddedWorkerDevToolsManager>::get(); 196 return Singleton<EmbeddedWorkerDevToolsManager>::get();
180 } 197 }
181 198
182 DevToolsAgentHost* EmbeddedWorkerDevToolsManager::GetDevToolsAgentHostForWorker( 199 DevToolsAgentHost*
200 EmbeddedWorkerDevToolsManager::GetDevToolsAgentHostForWorker(
183 int worker_process_id, 201 int worker_process_id,
184 int worker_route_id) { 202 int worker_route_id) {
203 return GetOrCreateAgentHost(worker_process_id, worker_route_id, GURL());
204 }
205
206 DevToolsAgentHost* EmbeddedWorkerDevToolsManager::GetOrCreateAgentHost(
207 int worker_process_id,
208 int worker_route_id,
209 const GURL& url) {
185 WorkerId id(worker_process_id, worker_route_id); 210 WorkerId id(worker_process_id, worker_route_id);
186 211
187 WorkerInfoMap::iterator it = workers_.find(id); 212 WorkerInfoMap::iterator it = workers_.find(id);
188 if (it == workers_.end()) 213 if (it == workers_.end())
189 return NULL; 214 return NULL;
190 215
191 WorkerInfo* info = it->second; 216 WorkerInfo* info = it->second;
192 if (info->state() != WORKER_UNINSPECTED && 217 if (info->state() != WORKER_UNINSPECTED &&
193 info->state() != WORKER_PAUSED_FOR_DEBUG_ON_START) { 218 info->state() != WORKER_PAUSED_FOR_DEBUG_ON_START) {
194 return info->agent_host(); 219 return info->agent_host();
195 } 220 }
196 221
197 EmbeddedWorkerDevToolsAgentHost* agent_host = 222 EmbeddedWorkerDevToolsAgentHost* agent_host =
198 new EmbeddedWorkerDevToolsAgentHost(id); 223 new EmbeddedWorkerDevToolsAgentHost(id, url);
199 info->set_agent_host(agent_host); 224 info->set_agent_host(agent_host);
200 info->set_state(WORKER_INSPECTED); 225 info->set_state(WORKER_INSPECTED);
201 return agent_host; 226 return agent_host;
202 } 227 }
203 228
204 DevToolsAgentHost* 229 DevToolsAgentHost*
205 EmbeddedWorkerDevToolsManager::GetDevToolsAgentHostForServiceWorker( 230 EmbeddedWorkerDevToolsManager::GetDevToolsAgentHostForServiceWorker(
206 const ServiceWorkerIdentifier& service_worker_id) { 231 const ServiceWorkerIdentifier& service_worker_id) {
207 WorkerInfoMap::iterator it = FindExistingServiceWorkerInfo(service_worker_id); 232 WorkerInfoMap::iterator it = FindExistingServiceWorkerInfo(service_worker_id);
208 if (it == workers_.end()) 233 if (it == workers_.end())
209 return NULL; 234 return NULL;
210 return GetDevToolsAgentHostForWorker(it->first.first, it->first.second); 235 return GetDevToolsAgentHostForWorker(it->first.first, it->first.second);
211 } 236 }
212 237
238 void EmbeddedWorkerDevToolsManager::GetOrCreateAllHosts(
239 const DevToolsAgentHost::ListCallback& callback) {
240 std::map<WorkerId, ServiceWorkerIdentifier> ids;
241 for (WorkerInfoMap::iterator it = workers_.begin();
242 it != workers_.end(); ++it) {
243 if (const ServiceWorkerIdentifier* worker_id =
244 it->second->service_worker_id()) {
245 ids.insert(std::make_pair(it->first, *worker_id));
246 }
247 }
248 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
249 base::Bind(&EmbeddedWorkerDevToolsManager::GetServiceWorkerUrlsOnIO,
250 ids, callback));
251 }
252
253 // static
254 void EmbeddedWorkerDevToolsManager::GetServiceWorkerUrlsOnIO(
255 const std::map<WorkerId, ServiceWorkerIdentifier>& ids,
256 const DevToolsAgentHost::ListCallback& callback) {
257 std::map<WorkerId, GURL> url_map;
258 for (std::map<WorkerId, ServiceWorkerIdentifier>::const_iterator it =
259 ids.begin(); it != ids.end(); ++it) {
260 if (ServiceWorkerContextCore* context =
261 it->second.service_worker_context_weak_.get()) {
262 if (ServiceWorkerVersion* version =
263 context->GetLiveVersion(it->second.service_worker_version_id_)) {
264 url_map[it->first] = version->script_url();
265 }
266 }
267 }
268 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
269 base::Bind(&EmbeddedWorkerDevToolsManager::CreateAgentHosts,
270 url_map, callback));
271 }
272
273 // static
274 void EmbeddedWorkerDevToolsManager::CreateAgentHosts(
275 const std::map<WorkerId, GURL> url_map,
276 const DevToolsAgentHost::ListCallback& callback) {
277 DevToolsAgentHost::List agent_hosts;
278 EmbeddedWorkerDevToolsManager* instance = GetInstance();
279 for (WorkerInfoMap::iterator it = instance->workers_.begin();
280 it != instance->workers_.end(); ++it) {
281 if (it->second->service_worker_id()) {
282 std::map<WorkerId, GURL>::const_iterator url_it = url_map.find(it->first);
283 if (url_it != url_map.end()) {
284 agent_hosts.push_back(instance->GetOrCreateAgentHost(
285 it->first.first, it->first.second, url_it->second));
286 }
287 } else {
288 agent_hosts.push_back(instance->GetOrCreateAgentHost(
289 it->first.first, it->first.second, GURL()));
290 }
291 }
292 callback.Run(agent_hosts);
293 }
294
213 EmbeddedWorkerDevToolsManager::EmbeddedWorkerDevToolsManager() 295 EmbeddedWorkerDevToolsManager::EmbeddedWorkerDevToolsManager()
214 : debug_service_worker_on_start_(false) { 296 : debug_service_worker_on_start_(false) {
215 } 297 }
216 298
217 EmbeddedWorkerDevToolsManager::~EmbeddedWorkerDevToolsManager() { 299 EmbeddedWorkerDevToolsManager::~EmbeddedWorkerDevToolsManager() {
218 } 300 }
219 301
220 bool EmbeddedWorkerDevToolsManager::SharedWorkerCreated( 302 bool EmbeddedWorkerDevToolsManager::SharedWorkerCreated(
221 int worker_process_id, 303 int worker_process_id,
222 int worker_route_id, 304 int worker_route_id,
(...skipping 28 matching lines...) Expand all
251 return true; 333 return true;
252 } 334 }
253 335
254 void EmbeddedWorkerDevToolsManager::WorkerDestroyed(int worker_process_id, 336 void EmbeddedWorkerDevToolsManager::WorkerDestroyed(int worker_process_id,
255 int worker_route_id) { 337 int worker_route_id) {
256 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 338 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
257 const WorkerId id(worker_process_id, worker_route_id); 339 const WorkerId id(worker_process_id, worker_route_id);
258 WorkerInfoMap::iterator it = workers_.find(id); 340 WorkerInfoMap::iterator it = workers_.find(id);
259 DCHECK(it != workers_.end()); 341 DCHECK(it != workers_.end());
260 WorkerInfo* info = it->second; 342 WorkerInfo* info = it->second;
343 EmbeddedWorkerDevToolsAgentHost* agent_host = info->agent_host();
261 switch (info->state()) { 344 switch (info->state()) {
262 case WORKER_UNINSPECTED: 345 case WORKER_UNINSPECTED:
263 case WORKER_PAUSED_FOR_DEBUG_ON_START: 346 case WORKER_PAUSED_FOR_DEBUG_ON_START:
264 workers_.erase(it); 347 workers_.erase(it);
265 break; 348 break;
266 case WORKER_INSPECTED: { 349 case WORKER_INSPECTED: {
267 EmbeddedWorkerDevToolsAgentHost* agent_host = info->agent_host();
268 info->set_state(WORKER_TERMINATED); 350 info->set_state(WORKER_TERMINATED);
269 if (!agent_host->IsAttached()) { 351 if (agent_host->IsAttached()) {
352 // Client host is debugging this worker agent host.
353 std::string notification =
354 DevToolsProtocol::CreateNotification(
355 devtools::Worker::disconnectedFromWorker::kName, NULL)
356 ->Serialize();
357 DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend(
358 agent_host, notification);
270 agent_host->DetachFromWorker(); 359 agent_host->DetachFromWorker();
271 return;
272 } 360 }
273 // Client host is debugging this worker agent host.
274 std::string notification =
275 DevToolsProtocol::CreateNotification(
276 devtools::Worker::disconnectedFromWorker::kName, NULL)
277 ->Serialize();
278 DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend(
279 agent_host, notification);
280 agent_host->DetachFromWorker();
281 break; 361 break;
282 } 362 }
283 case WORKER_TERMINATED: 363 case WORKER_TERMINATED:
284 NOTREACHED(); 364 NOTREACHED();
285 break; 365 break;
286 case WORKER_PAUSED_FOR_REATTACH: { 366 case WORKER_PAUSED_FOR_REATTACH: {
287 scoped_ptr<WorkerInfo> worker_info = workers_.take_and_erase(it); 367 scoped_ptr<WorkerInfo> worker_info = workers_.take_and_erase(it);
288 worker_info->set_state(WORKER_TERMINATED); 368 worker_info->set_state(WORKER_TERMINATED);
289 const WorkerId old_id = worker_info->agent_host()->worker_id(); 369 const WorkerId old_id = worker_info->agent_host()->worker_id();
290 workers_.set(old_id, worker_info.Pass()); 370 workers_.set(old_id, worker_info.Pass());
291 break; 371 break;
292 } 372 }
293 } 373 }
374 if (agent_host)
375 agent_host->WorkerDestroyed();
294 } 376 }
295 377
296 void EmbeddedWorkerDevToolsManager::WorkerContextStarted(int worker_process_id, 378 void EmbeddedWorkerDevToolsManager::WorkerContextStarted(int worker_process_id,
297 int worker_route_id) { 379 int worker_route_id) {
298 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 380 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
299 const WorkerId id(worker_process_id, worker_route_id); 381 const WorkerId id(worker_process_id, worker_route_id);
300 WorkerInfoMap::iterator it = workers_.find(id); 382 WorkerInfoMap::iterator it = workers_.find(id);
301 DCHECK(it != workers_.end()); 383 DCHECK(it != workers_.end());
302 WorkerInfo* info = it->second; 384 WorkerInfo* info = it->second;
303 if (info->state() == WORKER_PAUSED_FOR_DEBUG_ON_START) { 385 if (info->state() == WORKER_PAUSED_FOR_DEBUG_ON_START) {
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
362 } 444 }
363 return it; 445 return it;
364 } 446 }
365 447
366 void EmbeddedWorkerDevToolsManager::MoveToPausedState( 448 void EmbeddedWorkerDevToolsManager::MoveToPausedState(
367 const WorkerId& id, 449 const WorkerId& id,
368 const WorkerInfoMap::iterator& it) { 450 const WorkerInfoMap::iterator& it) {
369 DCHECK_EQ(WORKER_TERMINATED, it->second->state()); 451 DCHECK_EQ(WORKER_TERMINATED, it->second->state());
370 scoped_ptr<WorkerInfo> info = workers_.take_and_erase(it); 452 scoped_ptr<WorkerInfo> info = workers_.take_and_erase(it);
371 info->set_state(WORKER_PAUSED_FOR_REATTACH); 453 info->set_state(WORKER_PAUSED_FOR_REATTACH);
454 if (EmbeddedWorkerDevToolsAgentHost* agent_host = info->agent_host())
455 agent_host->WorkerCreated();
372 workers_.set(id, info.Pass()); 456 workers_.set(id, info.Pass());
373 } 457 }
374 458
375 void EmbeddedWorkerDevToolsManager::ResetForTesting() { 459 void EmbeddedWorkerDevToolsManager::ResetForTesting() {
376 workers_.clear(); 460 workers_.clear();
377 } 461 }
378 462
379 } // namespace content 463 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698