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 agent->SelfDestruct(); |
yurys
2012/12/21 13:48:02
RemovePendingWorkerData is missing
| |
143 return; | 185 return; |
144 } | 186 } |
145 g_orphan_map.Get()[id] = cookie; | 187 |
188 // Client host is debugging this worker agent host. | |
189 devtools_manager->DispatchOnInspectorFrontend( | |
190 agent, | |
191 WebDevToolsAgent::workerDisconnectedFromWorkerEvent().utf8()); | |
192 g_orphan_map.Get()[id] = agent; | |
193 agent->ResetWorkerId(); | |
146 } | 194 } |
147 | 195 |
148 private: | 196 private: |
149 DetachedClientHosts() {} | 197 DetachedClientHosts() { } |
150 ~DetachedClientHosts() {} | 198 ~DetachedClientHosts() { } |
151 | |
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 | 199 |
167 static void RemovePendingWorkerData(WorkerId id) { | 200 static void RemovePendingWorkerData(WorkerId id) { |
168 BrowserThread::PostTask( | 201 BrowserThread::PostTask( |
169 BrowserThread::IO, FROM_HERE, | 202 BrowserThread::IO, FROM_HERE, |
170 base::Bind(&RemoveInspectedWorkerDataOnIOThread, id)); | 203 base::Bind(&RemoveInspectedWorkerDataOnIOThread, id)); |
171 } | 204 } |
172 | 205 |
173 static void RemoveInspectedWorkerDataOnIOThread(WorkerId id) { | 206 static void RemoveInspectedWorkerDataOnIOThread(WorkerId id) { |
174 WorkerDevToolsManager::GetInstance()->RemoveInspectedWorkerData(id); | 207 WorkerDevToolsManager::GetInstance()->RemoveInspectedWorkerData(id); |
175 } | 208 } |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
298 } | 331 } |
299 | 332 |
300 static WorkerProcessHost* FindWorkerProcess(int worker_process_id) { | 333 static WorkerProcessHost* FindWorkerProcess(int worker_process_id) { |
301 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { | 334 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { |
302 if (iter.GetData().id == worker_process_id) | 335 if (iter.GetData().id == worker_process_id) |
303 return *iter; | 336 return *iter; |
304 } | 337 } |
305 return NULL; | 338 return NULL; |
306 } | 339 } |
307 | 340 |
308 void WorkerDevToolsManager::RegisterDevToolsAgentHostForWorker( | 341 void WorkerDevToolsManager::ConnectDevToolsAgentHostToWorker( |
309 int worker_process_id, | 342 int worker_process_id, |
310 int worker_route_id) { | 343 int worker_route_id) { |
311 if (WorkerProcessHost* process = FindWorkerProcess(worker_process_id)) { | 344 if (WorkerProcessHost* process = FindWorkerProcess(worker_process_id)) { |
312 const WorkerProcessHost::Instances& instances = process->instances(); | 345 const WorkerProcessHost::Instances& instances = process->instances(); |
313 for (WorkerProcessHost::Instances::const_iterator i = instances.begin(); | 346 for (WorkerProcessHost::Instances::const_iterator i = instances.begin(); |
314 i != instances.end(); ++i) { | 347 i != instances.end(); ++i) { |
315 if (i->worker_route_id() == worker_route_id) { | 348 if (i->worker_route_id() == worker_route_id) { |
316 DCHECK(FindInspectedWorker(worker_process_id, worker_route_id) == | 349 DCHECK(FindInspectedWorker(worker_process_id, worker_route_id) == |
317 inspected_workers_.end()); | 350 inspected_workers_.end()); |
318 inspected_workers_.push_back( | 351 inspected_workers_.push_back( |
319 InspectedWorker(process, worker_route_id, i->url(), i->name())); | 352 InspectedWorker(process, worker_route_id, i->url(), i->name())); |
320 return; | 353 return; |
321 } | 354 } |
322 } | 355 } |
323 } | 356 } |
324 NotifyWorkerDestroyedOnIOThread(worker_process_id, worker_route_id); | 357 NotifyConnectionFailedOnIOThread(worker_process_id, worker_route_id); |
325 } | 358 } |
326 | 359 |
327 void WorkerDevToolsManager::ForwardToDevToolsClient( | 360 void WorkerDevToolsManager::ForwardToDevToolsClient( |
328 int worker_process_id, | 361 int worker_process_id, |
329 int worker_route_id, | 362 int worker_route_id, |
330 const std::string& message) { | 363 const std::string& message) { |
331 if (FindInspectedWorker(worker_process_id, worker_route_id) == | 364 if (FindInspectedWorker(worker_process_id, worker_route_id) == |
332 inspected_workers_.end()) { | 365 inspected_workers_.end()) { |
333 NOTREACHED(); | 366 NOTREACHED(); |
334 return; | 367 return; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
383 | 416 |
384 // static | 417 // static |
385 void WorkerDevToolsManager::SaveAgentRuntimeStateOnUIThread( | 418 void WorkerDevToolsManager::SaveAgentRuntimeStateOnUIThread( |
386 int worker_process_id, | 419 int worker_process_id, |
387 int worker_route_id, | 420 int worker_route_id, |
388 const std::string& state) { | 421 const std::string& state) { |
389 AgentHosts::iterator it = g_agent_map.Get().find(WorkerId(worker_process_id, | 422 AgentHosts::iterator it = g_agent_map.Get().find(WorkerId(worker_process_id, |
390 worker_route_id)); | 423 worker_route_id)); |
391 if (it == g_agent_map.Get().end()) | 424 if (it == g_agent_map.Get().end()) |
392 return; | 425 return; |
393 DevToolsManagerImpl::GetInstance()->SaveAgentRuntimeState(it->second, state); | 426 it->second->SaveAgentRuntimeState(state); |
394 } | 427 } |
395 | 428 |
396 // static | 429 // static |
397 void WorkerDevToolsManager::NotifyWorkerDestroyedOnIOThread( | 430 void WorkerDevToolsManager::NotifyConnectionFailedOnIOThread( |
398 int worker_process_id, | 431 int worker_process_id, |
399 int worker_route_id) { | 432 int worker_route_id) { |
400 BrowserThread::PostTask( | 433 BrowserThread::PostTask( |
401 BrowserThread::UI, FROM_HERE, | 434 BrowserThread::UI, FROM_HERE, |
402 base::Bind( | 435 base::Bind( |
403 &WorkerDevToolsManager::NotifyWorkerDestroyedOnUIThread, | 436 &WorkerDevToolsManager::NotifyConnectionFailedOnUIThread, |
404 worker_process_id, | 437 worker_process_id, |
405 worker_route_id)); | 438 worker_route_id)); |
406 } | 439 } |
407 | 440 |
408 // static | 441 // static |
409 void WorkerDevToolsManager::NotifyWorkerDestroyedOnUIThread( | 442 void WorkerDevToolsManager::NotifyConnectionFailedOnUIThread( |
410 int worker_process_id, | 443 int worker_process_id, |
411 int worker_route_id) { | 444 int worker_route_id) { |
412 AgentHosts::iterator it = g_agent_map.Get().find(WorkerId(worker_process_id, | 445 AgentHosts::iterator it = g_agent_map.Get().find(WorkerId(worker_process_id, |
413 worker_route_id)); | 446 worker_route_id)); |
414 if (it != g_agent_map.Get().end()) | 447 if (it != g_agent_map.Get().end()) |
415 it->second->WorkerDestroyed(); | 448 it->second->ConnectionFailed(); |
416 } | 449 } |
417 | 450 |
418 // static | 451 // static |
419 void WorkerDevToolsManager::SendResumeToWorker(const WorkerId& id) { | 452 void WorkerDevToolsManager::SendResumeToWorker(const WorkerId& id) { |
420 if (WorkerProcessHost* process = FindWorkerProcess(id.first)) | 453 if (WorkerProcessHost* process = FindWorkerProcess(id.first)) |
421 process->Send(new DevToolsAgentMsg_ResumeWorkerContext(id.second)); | 454 process->Send(new DevToolsAgentMsg_ResumeWorkerContext(id.second)); |
422 } | 455 } |
423 | 456 |
424 } // namespace content | 457 } // namespace content |
OLD | NEW |