OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/worker_devtools_manager.h" | 5 #include "content/browser/devtools/worker_devtools_manager.h" |
6 | 6 |
7 #include <list> | 7 #include <list> |
8 #include <map> | 8 #include <map> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
11 #include "base/lazy_instance.h" | 11 #include "base/lazy_instance.h" |
12 #include "content/browser/devtools/devtools_agent_host.h" | 12 #include "content/browser/devtools/devtools_agent_host.h" |
13 #include "content/browser/devtools/devtools_manager_impl.h" | 13 #include "content/browser/devtools/devtools_manager_impl.h" |
14 #include "content/browser/devtools/worker_devtools_message_filter.h" | 14 #include "content/browser/devtools/worker_devtools_message_filter.h" |
15 #include "content/browser/worker_host/worker_service_impl.h" | 15 #include "content/browser/worker_host/worker_service_impl.h" |
16 #include "content/common/devtools_messages.h" | 16 #include "content/common/devtools_messages.h" |
17 #include "content/public/browser/browser_thread.h" | 17 #include "content/public/browser/browser_thread.h" |
18 #include "content/public/browser/child_process_data.h" | 18 #include "content/public/browser/child_process_data.h" |
19 #include "content/public/browser/devtools_agent_host_registry.h" | 19 #include "content/public/browser/devtools_agent_host_registry.h" |
20 #include "content/public/common/process_type.h" | 20 #include "content/public/common/process_type.h" |
21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDevToolsAgent.h" | 21 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDevToolsAgent.h" |
22 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebCString.h
" | 22 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebCString.h
" |
23 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" | 23 #include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h" |
24 | 24 |
| 25 using WebKit::WebDevToolsAgent; |
| 26 |
25 namespace content { | 27 namespace content { |
26 | 28 |
27 // Called on the UI thread. | 29 // Called on the UI thread. |
28 // static | 30 // static |
29 DevToolsAgentHost* DevToolsAgentHostRegistry::GetDevToolsAgentHostForWorker( | 31 DevToolsAgentHost* DevToolsAgentHostRegistry::GetDevToolsAgentHostForWorker( |
30 int worker_process_id, | 32 int worker_process_id, |
31 int worker_route_id) { | 33 int worker_route_id) { |
32 return WorkerDevToolsManager::GetDevToolsAgentHostForWorker( | 34 return WorkerDevToolsManager::GetDevToolsAgentHostForWorker( |
33 worker_process_id, | 35 worker_process_id, |
34 worker_route_id); | 36 worker_route_id); |
35 } | 37 } |
36 | 38 |
37 namespace { | 39 namespace { |
38 | 40 |
| 41 static WorkerDevToolsManager::WorkerId g_null_id = std::make_pair(-1, -1); |
| 42 |
39 typedef std::map<WorkerDevToolsManager::WorkerId, | 43 typedef std::map<WorkerDevToolsManager::WorkerId, |
40 WorkerDevToolsManager::WorkerDevToolsAgentHost*> AgentHosts; | 44 WorkerDevToolsManager::WorkerDevToolsAgentHost*> AgentHosts; |
41 typedef std::map<WorkerDevToolsManager::WorkerId, | |
42 int> OrphanHosts; | |
43 base::LazyInstance<AgentHosts>::Leaky g_agent_map = LAZY_INSTANCE_INITIALIZER; | 45 base::LazyInstance<AgentHosts>::Leaky g_agent_map = LAZY_INSTANCE_INITIALIZER; |
44 base::LazyInstance<OrphanHosts>::Leaky g_orphan_map = LAZY_INSTANCE_INITIALIZER; | 46 base::LazyInstance<AgentHosts>::Leaky g_orphan_map = LAZY_INSTANCE_INITIALIZER; |
45 | 47 |
46 } // namespace | 48 } // namespace |
47 | 49 |
48 struct WorkerDevToolsManager::TerminatedInspectedWorker { | 50 struct WorkerDevToolsManager::TerminatedInspectedWorker { |
49 TerminatedInspectedWorker(WorkerId id, const GURL& url, const string16& name) | 51 TerminatedInspectedWorker(WorkerId id, const GURL& url, const string16& name) |
50 : old_worker_id(id), | 52 : old_worker_id(id), |
51 worker_url(url), | 53 worker_url(url), |
52 worker_name(name) {} | 54 worker_name(name) {} |
53 WorkerId old_worker_id; | 55 WorkerId old_worker_id; |
54 GURL worker_url; | 56 GURL worker_url; |
55 string16 worker_name; | 57 string16 worker_name; |
56 }; | 58 }; |
57 | 59 |
58 | 60 |
59 class WorkerDevToolsManager::WorkerDevToolsAgentHost | 61 class WorkerDevToolsManager::WorkerDevToolsAgentHost |
60 : public DevToolsAgentHost { | 62 : public DevToolsAgentHost { |
61 public: | 63 public: |
62 explicit WorkerDevToolsAgentHost(WorkerId worker_id) | 64 explicit WorkerDevToolsAgentHost(WorkerId worker_id) { |
63 : worker_id_(worker_id) { | 65 SetWorkerId(worker_id, false); |
| 66 } |
| 67 |
| 68 void SetWorkerId(WorkerId worker_id, bool reattach) { |
| 69 worker_id_ = worker_id; |
64 g_agent_map.Get()[worker_id_] = this; | 70 g_agent_map.Get()[worker_id_] = this; |
| 71 |
65 BrowserThread::PostTask( | 72 BrowserThread::PostTask( |
66 BrowserThread::IO, | 73 BrowserThread::IO, |
67 FROM_HERE, | 74 FROM_HERE, |
68 base::Bind( | 75 base::Bind( |
69 &RegisterAgent, | 76 &ConnectToWorker, |
70 worker_id.first, | 77 worker_id.first, |
71 worker_id.second)); | 78 worker_id.second)); |
| 79 |
| 80 if (reattach) |
| 81 Reattach(state_); |
72 } | 82 } |
73 | 83 |
74 void WorkerDestroyed() { | 84 void ResetWorkerId() { |
75 NotifyCloseListener(); | 85 g_agent_map.Get().erase(worker_id_); |
| 86 worker_id_ = g_null_id; |
| 87 } |
| 88 |
| 89 virtual void Detach() { |
| 90 DevToolsAgentHost::Detach(); |
| 91 SelfDestruct(); |
| 92 } |
| 93 |
| 94 void SaveAgentRuntimeState(const std::string& state) { |
| 95 state_ = state; |
| 96 } |
| 97 |
| 98 void ConnectionFailed() { |
| 99 // Depending on whether we are connected or not, we should disconnect and |
| 100 // self-destruct. |
| 101 if (NotifyCloseListener()) |
| 102 return; // Detach will delete this instance. |
| 103 SelfDestruct(); |
| 104 } |
| 105 |
| 106 void SelfDestruct() { |
76 delete this; | 107 delete this; |
77 } | 108 } |
78 | 109 |
79 private: | 110 private: |
80 virtual ~WorkerDevToolsAgentHost() { | 111 virtual ~WorkerDevToolsAgentHost() { |
81 g_agent_map.Get().erase(worker_id_); | 112 g_agent_map.Get().erase(worker_id_); |
82 } | 113 } |
83 | 114 |
84 static void RegisterAgent( | 115 static void ConnectToWorker( |
85 int worker_process_id, | 116 int worker_process_id, |
86 int worker_route_id) { | 117 int worker_route_id) { |
87 WorkerDevToolsManager::GetInstance()->RegisterDevToolsAgentHostForWorker( | 118 WorkerDevToolsManager::GetInstance()->ConnectDevToolsAgentHostToWorker( |
88 worker_process_id, worker_route_id); | 119 worker_process_id, worker_route_id); |
89 } | 120 } |
90 | 121 |
91 static void ForwardToWorkerDevToolsAgent( | 122 static void ForwardToWorkerDevToolsAgent( |
92 int worker_process_id, | 123 int worker_process_id, |
93 int worker_route_id, | 124 int worker_route_id, |
94 IPC::Message* message) { | 125 IPC::Message* message) { |
95 WorkerDevToolsManager::GetInstance()->ForwardToWorkerDevToolsAgent( | 126 WorkerDevToolsManager::GetInstance()->ForwardToWorkerDevToolsAgent( |
96 worker_process_id, worker_route_id, *message); | 127 worker_process_id, worker_route_id, *message); |
97 } | 128 } |
98 | 129 |
99 // DevToolsAgentHost implementation. | 130 // DevToolsAgentHost implementation. |
100 virtual void SendMessageToAgent(IPC::Message* message) OVERRIDE { | 131 virtual void SendMessageToAgent(IPC::Message* message) OVERRIDE { |
| 132 if (worker_id_ == g_null_id) { |
| 133 delete message; |
| 134 return; |
| 135 } |
101 BrowserThread::PostTask( | 136 BrowserThread::PostTask( |
102 BrowserThread::IO, FROM_HERE, | 137 BrowserThread::IO, FROM_HERE, |
103 base::Bind( | 138 base::Bind( |
104 &WorkerDevToolsAgentHost::ForwardToWorkerDevToolsAgent, | 139 &WorkerDevToolsAgentHost::ForwardToWorkerDevToolsAgent, |
105 worker_id_.first, | 140 worker_id_.first, |
106 worker_id_.second, | 141 worker_id_.second, |
107 base::Owned(message))); | 142 base::Owned(message))); |
108 } | 143 } |
| 144 |
109 virtual void NotifyClientAttaching() OVERRIDE {} | 145 virtual void NotifyClientAttaching() OVERRIDE {} |
110 virtual void NotifyClientDetaching() OVERRIDE {} | 146 virtual void NotifyClientDetaching() OVERRIDE {} |
111 virtual int GetRenderProcessId() OVERRIDE { return -1; } | 147 virtual int GetRenderProcessId() OVERRIDE { return -1; } |
112 | 148 |
113 WorkerId worker_id_; | 149 WorkerId worker_id_; |
| 150 std::string state_; |
114 | 151 |
115 DISALLOW_COPY_AND_ASSIGN(WorkerDevToolsAgentHost); | 152 DISALLOW_COPY_AND_ASSIGN(WorkerDevToolsAgentHost); |
116 }; | 153 }; |
117 | 154 |
118 | 155 |
119 class WorkerDevToolsManager::DetachedClientHosts { | 156 class WorkerDevToolsManager::DetachedClientHosts { |
120 public: | 157 public: |
121 static void WorkerReloaded(WorkerId old_id, WorkerId new_id) { | 158 static void WorkerReloaded(WorkerId old_id, WorkerId new_id) { |
122 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 159 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
123 if (ReattachClient(old_id, new_id)) | 160 AgentHosts::iterator it = g_orphan_map.Get().find(old_id); |
| 161 if (it != g_orphan_map.Get().end()) { |
| 162 g_orphan_map.Get().erase(old_id); |
| 163 it->second->SetWorkerId(new_id, true); |
124 return; | 164 return; |
| 165 } |
125 RemovePendingWorkerData(old_id); | 166 RemovePendingWorkerData(old_id); |
126 } | 167 } |
127 | 168 |
128 static void WorkerDestroyed(WorkerId id) { | 169 static void WorkerDestroyed(WorkerId id) { |
129 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 170 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
130 AgentHosts::iterator it = g_agent_map.Get().find(id); | 171 AgentHosts::iterator it = g_agent_map.Get().find(id); |
131 if (it == g_agent_map.Get().end()) { | 172 if (it == g_agent_map.Get().end()) { |
132 RemovePendingWorkerData(id); | 173 RemovePendingWorkerData(id); |
133 return; | 174 return; |
134 } | 175 } |
| 176 |
135 WorkerDevToolsAgentHost* agent = it->second; | 177 WorkerDevToolsAgentHost* agent = it->second; |
136 DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend( | 178 DevToolsManagerImpl* devtools_manager = DevToolsManagerImpl::GetInstance(); |
137 agent, | 179 DevToolsClientHost* client_host = |
138 WebKit::WebDevToolsAgent::workerDisconnectedFromWorkerEvent().utf8()); | 180 devtools_manager->GetDevToolsClientHostFor(agent); |
139 int cookie = DevToolsManagerImpl::GetInstance()->DetachClientHost(agent); | 181 |
140 agent->WorkerDestroyed(); | 182 if (!client_host) { |
141 if (cookie == -1) { | 183 // Agent has no client hosts -> delete it. |
142 RemovePendingWorkerData(id); | 184 RemovePendingWorkerData(id); |
| 185 agent->SelfDestruct(); |
143 return; | 186 return; |
144 } | 187 } |
145 g_orphan_map.Get()[id] = cookie; | 188 |
| 189 // Client host is debugging this worker agent host. |
| 190 devtools_manager->DispatchOnInspectorFrontend( |
| 191 agent, |
| 192 WebDevToolsAgent::workerDisconnectedFromWorkerEvent().utf8()); |
| 193 g_orphan_map.Get()[id] = agent; |
| 194 agent->ResetWorkerId(); |
146 } | 195 } |
147 | 196 |
148 private: | 197 private: |
149 DetachedClientHosts() {} | 198 DetachedClientHosts() {} |
150 ~DetachedClientHosts() {} | 199 ~DetachedClientHosts() {} |
151 | 200 |
152 static bool ReattachClient(WorkerId old_id, WorkerId new_id) { | |
153 OrphanHosts::iterator it = g_orphan_map.Get().find(old_id); | |
154 if (it == g_orphan_map.Get().end()) | |
155 return false; | |
156 DevToolsAgentHost* agent = | |
157 WorkerDevToolsManager::GetDevToolsAgentHostForWorker( | |
158 new_id.first, | |
159 new_id.second); | |
160 DevToolsManagerImpl::GetInstance()->AttachClientHost( | |
161 it->second, | |
162 agent); | |
163 g_orphan_map.Get().erase(it); | |
164 return true; | |
165 } | |
166 | |
167 static void RemovePendingWorkerData(WorkerId id) { | 201 static void RemovePendingWorkerData(WorkerId id) { |
168 BrowserThread::PostTask( | 202 BrowserThread::PostTask( |
169 BrowserThread::IO, FROM_HERE, | 203 BrowserThread::IO, FROM_HERE, |
170 base::Bind(&RemoveInspectedWorkerDataOnIOThread, id)); | 204 base::Bind(&RemoveInspectedWorkerDataOnIOThread, id)); |
171 } | 205 } |
172 | 206 |
173 static void RemoveInspectedWorkerDataOnIOThread(WorkerId id) { | 207 static void RemoveInspectedWorkerDataOnIOThread(WorkerId id) { |
174 WorkerDevToolsManager::GetInstance()->RemoveInspectedWorkerData(id); | 208 WorkerDevToolsManager::GetInstance()->RemoveInspectedWorkerData(id); |
175 } | 209 } |
176 }; | 210 }; |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
298 } | 332 } |
299 | 333 |
300 static WorkerProcessHost* FindWorkerProcess(int worker_process_id) { | 334 static WorkerProcessHost* FindWorkerProcess(int worker_process_id) { |
301 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { | 335 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { |
302 if (iter.GetData().id == worker_process_id) | 336 if (iter.GetData().id == worker_process_id) |
303 return *iter; | 337 return *iter; |
304 } | 338 } |
305 return NULL; | 339 return NULL; |
306 } | 340 } |
307 | 341 |
308 void WorkerDevToolsManager::RegisterDevToolsAgentHostForWorker( | 342 void WorkerDevToolsManager::ConnectDevToolsAgentHostToWorker( |
309 int worker_process_id, | 343 int worker_process_id, |
310 int worker_route_id) { | 344 int worker_route_id) { |
311 if (WorkerProcessHost* process = FindWorkerProcess(worker_process_id)) { | 345 if (WorkerProcessHost* process = FindWorkerProcess(worker_process_id)) { |
312 const WorkerProcessHost::Instances& instances = process->instances(); | 346 const WorkerProcessHost::Instances& instances = process->instances(); |
313 for (WorkerProcessHost::Instances::const_iterator i = instances.begin(); | 347 for (WorkerProcessHost::Instances::const_iterator i = instances.begin(); |
314 i != instances.end(); ++i) { | 348 i != instances.end(); ++i) { |
315 if (i->worker_route_id() == worker_route_id) { | 349 if (i->worker_route_id() == worker_route_id) { |
316 DCHECK(FindInspectedWorker(worker_process_id, worker_route_id) == | 350 DCHECK(FindInspectedWorker(worker_process_id, worker_route_id) == |
317 inspected_workers_.end()); | 351 inspected_workers_.end()); |
318 inspected_workers_.push_back( | 352 inspected_workers_.push_back( |
319 InspectedWorker(process, worker_route_id, i->url(), i->name())); | 353 InspectedWorker(process, worker_route_id, i->url(), i->name())); |
320 return; | 354 return; |
321 } | 355 } |
322 } | 356 } |
323 } | 357 } |
324 NotifyWorkerDestroyedOnIOThread(worker_process_id, worker_route_id); | 358 NotifyConnectionFailedOnIOThread(worker_process_id, worker_route_id); |
325 } | 359 } |
326 | 360 |
327 void WorkerDevToolsManager::ForwardToDevToolsClient( | 361 void WorkerDevToolsManager::ForwardToDevToolsClient( |
328 int worker_process_id, | 362 int worker_process_id, |
329 int worker_route_id, | 363 int worker_route_id, |
330 const std::string& message) { | 364 const std::string& message) { |
331 if (FindInspectedWorker(worker_process_id, worker_route_id) == | 365 if (FindInspectedWorker(worker_process_id, worker_route_id) == |
332 inspected_workers_.end()) { | 366 inspected_workers_.end()) { |
333 NOTREACHED(); | 367 NOTREACHED(); |
334 return; | 368 return; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
383 | 417 |
384 // static | 418 // static |
385 void WorkerDevToolsManager::SaveAgentRuntimeStateOnUIThread( | 419 void WorkerDevToolsManager::SaveAgentRuntimeStateOnUIThread( |
386 int worker_process_id, | 420 int worker_process_id, |
387 int worker_route_id, | 421 int worker_route_id, |
388 const std::string& state) { | 422 const std::string& state) { |
389 AgentHosts::iterator it = g_agent_map.Get().find(WorkerId(worker_process_id, | 423 AgentHosts::iterator it = g_agent_map.Get().find(WorkerId(worker_process_id, |
390 worker_route_id)); | 424 worker_route_id)); |
391 if (it == g_agent_map.Get().end()) | 425 if (it == g_agent_map.Get().end()) |
392 return; | 426 return; |
393 DevToolsManagerImpl::GetInstance()->SaveAgentRuntimeState(it->second, state); | 427 it->second->SaveAgentRuntimeState(state); |
394 } | 428 } |
395 | 429 |
396 // static | 430 // static |
397 void WorkerDevToolsManager::NotifyWorkerDestroyedOnIOThread( | 431 void WorkerDevToolsManager::NotifyConnectionFailedOnIOThread( |
398 int worker_process_id, | 432 int worker_process_id, |
399 int worker_route_id) { | 433 int worker_route_id) { |
400 BrowserThread::PostTask( | 434 BrowserThread::PostTask( |
401 BrowserThread::UI, FROM_HERE, | 435 BrowserThread::UI, FROM_HERE, |
402 base::Bind( | 436 base::Bind( |
403 &WorkerDevToolsManager::NotifyWorkerDestroyedOnUIThread, | 437 &WorkerDevToolsManager::NotifyConnectionFailedOnUIThread, |
404 worker_process_id, | 438 worker_process_id, |
405 worker_route_id)); | 439 worker_route_id)); |
406 } | 440 } |
407 | 441 |
408 // static | 442 // static |
409 void WorkerDevToolsManager::NotifyWorkerDestroyedOnUIThread( | 443 void WorkerDevToolsManager::NotifyConnectionFailedOnUIThread( |
410 int worker_process_id, | 444 int worker_process_id, |
411 int worker_route_id) { | 445 int worker_route_id) { |
412 AgentHosts::iterator it = g_agent_map.Get().find(WorkerId(worker_process_id, | 446 AgentHosts::iterator it = g_agent_map.Get().find(WorkerId(worker_process_id, |
413 worker_route_id)); | 447 worker_route_id)); |
414 if (it != g_agent_map.Get().end()) | 448 if (it != g_agent_map.Get().end()) |
415 it->second->WorkerDestroyed(); | 449 it->second->ConnectionFailed(); |
416 } | 450 } |
417 | 451 |
418 // static | 452 // static |
419 void WorkerDevToolsManager::SendResumeToWorker(const WorkerId& id) { | 453 void WorkerDevToolsManager::SendResumeToWorker(const WorkerId& id) { |
420 if (WorkerProcessHost* process = FindWorkerProcess(id.first)) | 454 if (WorkerProcessHost* process = FindWorkerProcess(id.first)) |
421 process->Send(new DevToolsAgentMsg_ResumeWorkerContext(id.second)); | 455 process->Send(new DevToolsAgentMsg_ResumeWorkerContext(id.second)); |
422 } | 456 } |
423 | 457 |
424 } // namespace content | 458 } // namespace content |
OLD | NEW |