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/shared_worker_devtools_manager.h" |
6 | 6 |
7 #include <list> | |
8 #include <map> | |
9 | |
10 #include "base/bind.h" | |
11 #include "base/lazy_instance.h" | |
12 #include "content/browser/devtools/devtools_manager_impl.h" | 7 #include "content/browser/devtools/devtools_manager_impl.h" |
13 #include "content/browser/devtools/devtools_protocol.h" | 8 #include "content/browser/devtools/devtools_protocol.h" |
14 #include "content/browser/devtools/devtools_protocol_constants.h" | 9 #include "content/browser/devtools/devtools_protocol_constants.h" |
15 #include "content/browser/devtools/ipc_devtools_agent_host.h" | 10 #include "content/browser/devtools/ipc_devtools_agent_host.h" |
16 #include "content/browser/devtools/worker_devtools_message_filter.h" | 11 #include "content/browser/shared_worker/shared_worker_instance.h" |
17 #include "content/browser/worker_host/worker_service_impl.h" | |
18 #include "content/common/devtools_messages.h" | 12 #include "content/common/devtools_messages.h" |
19 #include "content/public/browser/browser_thread.h" | 13 #include "content/public/browser/browser_thread.h" |
20 #include "content/public/browser/child_process_data.h" | 14 #include "content/public/browser/render_process_host.h" |
21 #include "content/public/common/process_type.h" | 15 #include "content/public/browser/worker_service.h" |
16 #include "ipc/ipc_listener.h" | |
22 | 17 |
23 namespace content { | 18 namespace content { |
24 | 19 |
25 // Called on the UI thread. | |
26 // static | |
27 scoped_refptr<DevToolsAgentHost> DevToolsAgentHost::GetForWorker( | |
28 int worker_process_id, | |
29 int worker_route_id) { | |
30 return WorkerDevToolsManager::GetDevToolsAgentHostForWorker( | |
31 worker_process_id, | |
32 worker_route_id); | |
33 } | |
34 | |
35 namespace { | 20 namespace { |
36 | 21 |
37 typedef std::map<WorkerDevToolsManager::WorkerId, | 22 bool SendMessageToWorker(const SharedWorkerDevToolsManager::WorkerId& worker_id, |
38 WorkerDevToolsManager::WorkerDevToolsAgentHost*> AgentHosts; | 23 IPC::Message* message) { |
39 base::LazyInstance<AgentHosts>::Leaky g_agent_map = LAZY_INSTANCE_INITIALIZER; | 24 RenderProcessHost* host = RenderProcessHost::FromID(worker_id.first); |
40 base::LazyInstance<AgentHosts>::Leaky g_orphan_map = LAZY_INSTANCE_INITIALIZER; | 25 if (!host) { |
26 delete message; | |
27 return false; | |
28 } | |
29 message->set_routing_id(worker_id.second); | |
30 host->Send(message); | |
31 return true; | |
32 } | |
41 | 33 |
42 } // namespace | 34 } // namespace |
43 | 35 |
44 struct WorkerDevToolsManager::TerminatedInspectedWorker { | 36 class SharedWorkerDevToolsManager::SharedWorkerDevToolsAgentHost |
45 TerminatedInspectedWorker(WorkerId id, | 37 : public IPCDevToolsAgentHost, |
46 const GURL& url, | 38 public IPC::Listener { |
47 const base::string16& name) | |
48 : old_worker_id(id), | |
49 worker_url(url), | |
50 worker_name(name) {} | |
51 WorkerId old_worker_id; | |
52 GURL worker_url; | |
53 base::string16 worker_name; | |
54 }; | |
55 | |
56 | |
57 class WorkerDevToolsManager::WorkerDevToolsAgentHost | |
58 : public IPCDevToolsAgentHost { | |
59 public: | 39 public: |
60 explicit WorkerDevToolsAgentHost(WorkerId worker_id) | 40 SharedWorkerDevToolsAgentHost(WorkerId worker_id) |
61 : has_worker_id_(false) { | 41 : worker_id_(worker_id), worker_attached_(true) { |
62 SetWorkerId(worker_id, false); | 42 AddRef(); |
63 } | 43 if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first)) |
64 | 44 host->AddRoute(worker_id_.second, this); |
65 void SetWorkerId(WorkerId worker_id, bool reattach) { | |
66 worker_id_ = worker_id; | |
67 if (!has_worker_id_) | |
68 AddRef(); // Balanced in ResetWorkerId. | |
69 has_worker_id_ = true; | |
70 g_agent_map.Get()[worker_id_] = this; | |
71 | |
72 BrowserThread::PostTask( | |
73 BrowserThread::IO, | |
74 FROM_HERE, | |
75 base::Bind( | |
76 &ConnectToWorker, | |
77 worker_id.first, | |
78 worker_id.second)); | |
79 | |
80 if (reattach) | |
81 Reattach(state_); | |
82 } | |
83 | |
84 void ResetWorkerId() { | |
85 g_agent_map.Get().erase(worker_id_); | |
86 has_worker_id_ = false; | |
87 Release(); // Balanced in SetWorkerId. | |
88 } | |
89 | |
90 void SaveAgentRuntimeState(const std::string& state) { | |
91 state_ = state; | |
92 } | |
93 | |
94 void ConnectionFailed() { | |
95 NotifyCloseListener(); | |
96 // Object can be deleted here. | |
97 } | |
98 | |
99 private: | |
100 virtual ~WorkerDevToolsAgentHost(); | |
101 | |
102 static void ConnectToWorker( | |
103 int worker_process_id, | |
104 int worker_route_id) { | |
105 WorkerDevToolsManager::GetInstance()->ConnectDevToolsAgentHostToWorker( | |
106 worker_process_id, worker_route_id); | |
107 } | |
108 | |
109 static void ForwardToWorkerDevToolsAgent( | |
110 int worker_process_id, | |
111 int worker_route_id, | |
112 IPC::Message* message) { | |
113 WorkerDevToolsManager::GetInstance()->ForwardToWorkerDevToolsAgent( | |
114 worker_process_id, worker_route_id, *message); | |
115 } | 45 } |
116 | 46 |
117 // IPCDevToolsAgentHost implementation. | 47 // IPCDevToolsAgentHost implementation. |
118 virtual void SendMessageToAgent(IPC::Message* message) OVERRIDE { | 48 virtual void SendMessageToAgent(IPC::Message* message) OVERRIDE { |
119 if (!has_worker_id_) { | 49 if (worker_attached_) |
120 delete message; | 50 SendMessageToWorker(worker_id_, message); |
121 return; | 51 } |
122 } | |
123 BrowserThread::PostTask( | |
124 BrowserThread::IO, FROM_HERE, | |
125 base::Bind( | |
126 &WorkerDevToolsAgentHost::ForwardToWorkerDevToolsAgent, | |
127 worker_id_.first, | |
128 worker_id_.second, | |
129 base::Owned(message))); | |
130 } | |
131 | |
132 virtual void OnClientAttached() OVERRIDE {} | 52 virtual void OnClientAttached() OVERRIDE {} |
133 virtual void OnClientDetached() OVERRIDE {} | 53 virtual void OnClientDetached() OVERRIDE {} |
134 | 54 |
135 bool has_worker_id_; | 55 // IPC::Listener implementation. |
56 virtual bool OnMessageReceived(const IPC::Message& msg) OVERRIDE { | |
57 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
58 bool handled = true; | |
59 IPC_BEGIN_MESSAGE_MAP(SharedWorkerDevToolsAgentHost, msg) | |
60 IPC_MESSAGE_HANDLER(DevToolsClientMsg_DispatchOnInspectorFrontend, | |
61 OnDispatchOnInspectorFrontend) | |
62 IPC_MESSAGE_HANDLER(DevToolsHostMsg_SaveAgentRuntimeState, | |
63 OnSaveAgentRuntimeState) | |
64 IPC_MESSAGE_UNHANDLED(handled = false) | |
65 IPC_END_MESSAGE_MAP() | |
66 return handled; | |
67 } | |
68 | |
69 void ReattachToWorker(WorkerId worker_id) { | |
70 CHECK(!worker_attached_); | |
71 worker_attached_ = true; | |
72 worker_id_ = worker_id; | |
73 AddRef(); | |
74 if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first)) | |
75 host->AddRoute(worker_id_.second, this); | |
76 Reattach(state_); | |
77 } | |
78 | |
79 void DetachFromWorker() { | |
80 CHECK(worker_attached_); | |
81 worker_attached_ = false; | |
82 if (RenderProcessHost* host = RenderProcessHost::FromID(worker_id_.first)) | |
83 host->RemoveRoute(worker_id_.second); | |
84 Release(); | |
85 } | |
86 | |
87 WorkerId worker_id() const { return worker_id_; } | |
88 | |
89 private: | |
90 virtual ~SharedWorkerDevToolsAgentHost() { | |
91 CHECK(!worker_attached_); | |
92 SharedWorkerDevToolsManager::GetInstance()->RemoveInspectedWorkerData(this); | |
93 } | |
94 | |
95 void OnDispatchOnInspectorFrontend(const std::string& message) { | |
96 DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend(this, | |
97 message); | |
98 } | |
99 | |
100 void OnSaveAgentRuntimeState(const std::string& state) { state_ = state; } | |
101 | |
136 WorkerId worker_id_; | 102 WorkerId worker_id_; |
103 bool worker_attached_; | |
137 std::string state_; | 104 std::string state_; |
138 | 105 DISALLOW_COPY_AND_ASSIGN(SharedWorkerDevToolsAgentHost); |
139 DISALLOW_COPY_AND_ASSIGN(WorkerDevToolsAgentHost); | |
140 }; | 106 }; |
141 | 107 |
142 | 108 class SharedWorkerDevToolsManager::WorkerInfo { |
143 class WorkerDevToolsManager::DetachedClientHosts { | |
144 public: | 109 public: |
145 static void WorkerReloaded(WorkerId old_id, WorkerId new_id) { | 110 WorkerInfo(const SharedWorkerInstance& instance) |
146 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 111 : instance_(instance), agent_host_(NULL) {} |
147 AgentHosts::iterator it = g_orphan_map.Get().find(old_id); | 112 |
148 if (it != g_orphan_map.Get().end()) { | 113 const SharedWorkerInstance& instance() const { return instance_; } |
149 it->second->SetWorkerId(new_id, true); | 114 |
150 g_orphan_map.Get().erase(old_id); | 115 SharedWorkerDevToolsAgentHost* agent_host() { return agent_host_; } |
151 return; | 116 void set_agent_host(SharedWorkerDevToolsAgentHost* agent_host) { |
152 } | 117 agent_host_ = agent_host; |
153 RemovePendingWorkerData(old_id); | |
154 } | |
155 | |
156 static void WorkerDestroyed(WorkerId id) { | |
157 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
158 AgentHosts::iterator it = g_agent_map.Get().find(id); | |
159 if (it == g_agent_map.Get().end()) { | |
160 RemovePendingWorkerData(id); | |
161 return; | |
162 } | |
163 | |
164 WorkerDevToolsAgentHost* agent = it->second; | |
165 DevToolsManagerImpl* devtools_manager = DevToolsManagerImpl::GetInstance(); | |
166 if (!agent->IsAttached()) { | |
167 // Agent has no client hosts -> delete it. | |
168 RemovePendingWorkerData(id); | |
169 return; | |
170 } | |
171 | |
172 // Client host is debugging this worker agent host. | |
173 std::string notification = DevToolsProtocol::CreateNotification( | |
174 devtools::Worker::disconnectedFromWorker::kName, NULL)->Serialize(); | |
175 devtools_manager->DispatchOnInspectorFrontend(agent, notification); | |
176 g_orphan_map.Get()[id] = agent; | |
177 agent->ResetWorkerId(); | |
178 } | |
179 | |
180 static void RemovePendingWorkerData(WorkerId id) { | |
181 BrowserThread::PostTask( | |
182 BrowserThread::IO, FROM_HERE, | |
183 base::Bind(&RemoveInspectedWorkerDataOnIOThread, id)); | |
184 } | 118 } |
185 | 119 |
186 private: | 120 private: |
187 DetachedClientHosts() {} | 121 const SharedWorkerInstance instance_; |
yurys
2014/03/31 13:48:23
Is it OK to store it by value?
horo
2014/04/01 08:34:09
Yes it is OK.
SharedWorkerInstance has WorkerStora
| |
188 ~DetachedClientHosts() {} | 122 SharedWorkerDevToolsAgentHost* agent_host_; |
189 | |
190 static void RemoveInspectedWorkerDataOnIOThread(WorkerId id) { | |
191 WorkerDevToolsManager::GetInstance()->RemoveInspectedWorkerData(id); | |
192 } | |
193 }; | 123 }; |
194 | 124 |
195 struct WorkerDevToolsManager::InspectedWorker { | |
196 InspectedWorker(WorkerProcessHost* host, int route_id, const GURL& url, | |
197 const base::string16& name) | |
198 : host(host), | |
199 route_id(route_id), | |
200 worker_url(url), | |
201 worker_name(name) {} | |
202 WorkerProcessHost* const host; | |
203 int const route_id; | |
204 GURL worker_url; | |
205 base::string16 worker_name; | |
206 }; | |
207 | |
208 // static | 125 // static |
209 WorkerDevToolsManager* WorkerDevToolsManager::GetInstance() { | 126 SharedWorkerDevToolsManager* SharedWorkerDevToolsManager::GetInstance() { |
210 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 127 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
211 return Singleton<WorkerDevToolsManager>::get(); | 128 return Singleton<SharedWorkerDevToolsManager>::get(); |
212 } | 129 } |
213 | 130 |
214 // static | 131 DevToolsAgentHost* SharedWorkerDevToolsManager::GetDevToolsAgentHostForWorker( |
215 DevToolsAgentHost* WorkerDevToolsManager::GetDevToolsAgentHostForWorker( | |
216 int worker_process_id, | 132 int worker_process_id, |
217 int worker_route_id) { | 133 int worker_route_id) { |
218 WorkerId id(worker_process_id, worker_route_id); | 134 WorkerId id(worker_process_id, worker_route_id); |
219 AgentHosts::iterator it = g_agent_map.Get().find(id); | 135 |
220 if (it == g_agent_map.Get().end()) | 136 WorkerInfoMap::iterator inspected_it = inspected_workers_.find(id); |
221 return new WorkerDevToolsAgentHost(id); | 137 if (inspected_it != inspected_workers_.end()) |
222 return it->second; | 138 return inspected_it->second->agent_host(); |
223 } | 139 |
224 | 140 WorkerInfoMap::iterator terminated_it = terminated_workers_.find(id); |
225 WorkerDevToolsManager::WorkerDevToolsManager() { | 141 if (terminated_it != terminated_workers_.end()) |
226 } | 142 return terminated_it->second->agent_host(); |
227 | 143 |
228 WorkerDevToolsManager::~WorkerDevToolsManager() { | 144 WorkerInfoMap::iterator paused_it = paused_workers_.find(id); |
229 } | 145 if (paused_it != paused_workers_.end()) |
230 | 146 return paused_it->second->agent_host(); |
231 bool WorkerDevToolsManager::WorkerCreated( | 147 |
232 WorkerProcessHost* worker, | 148 WorkerInfoMap::iterator uninspected_it = uninspected_workers_.find(id); |
233 const WorkerProcessHost::WorkerInstance& instance) { | 149 if (uninspected_it != uninspected_workers_.end()) { |
234 for (TerminatedInspectedWorkers::iterator it = terminated_workers_.begin(); | 150 scoped_ptr<WorkerInfo> info = |
235 it != terminated_workers_.end(); ++it) { | 151 uninspected_workers_.take_and_erase(uninspected_it); |
236 if (instance.Matches(it->worker_url, it->worker_name, | 152 SharedWorkerDevToolsAgentHost* agent_host = |
237 instance.partition(), | 153 new SharedWorkerDevToolsAgentHost(id); |
238 instance.resource_context())) { | 154 info->set_agent_host(agent_host); |
239 WorkerId new_worker_id(worker->GetData().id, instance.worker_route_id()); | 155 inspected_workers_.set(id, info.Pass()); |
240 paused_workers_[new_worker_id] = it->old_worker_id; | 156 return agent_host; |
241 terminated_workers_.erase(it); | 157 } |
242 return true; | 158 return NULL; |
243 } | 159 } |
244 } | 160 |
245 return false; | 161 SharedWorkerDevToolsManager::SharedWorkerDevToolsManager() {} |
246 } | 162 |
247 | 163 SharedWorkerDevToolsManager::~SharedWorkerDevToolsManager() {} |
248 void WorkerDevToolsManager::WorkerDestroyed( | 164 |
249 WorkerProcessHost* worker, | 165 bool SharedWorkerDevToolsManager::WorkerCreated( |
250 int worker_route_id) { | 166 int worker_process_id, |
251 InspectedWorkersList::iterator it = FindInspectedWorker( | 167 int worker_route_id, |
252 worker->GetData().id, | 168 const SharedWorkerInstance& instance) { |
253 worker_route_id); | 169 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
254 if (it == inspected_workers_.end()) | 170 const WorkerId id(worker_process_id, worker_route_id); |
255 return; | 171 WorkerInfoMap::iterator terminated_it = FindTerminatedWorker(instance); |
256 | 172 if (terminated_it == terminated_workers_.end()) { |
257 WorkerId worker_id(worker->GetData().id, worker_route_id); | 173 scoped_ptr<WorkerInfo> info(new WorkerInfo(instance)); |
258 terminated_workers_.push_back(TerminatedInspectedWorker( | 174 uninspected_workers_.set(id, info.Pass()); |
259 worker_id, | 175 return false; |
260 it->worker_url, | 176 } |
261 it->worker_name)); | 177 scoped_ptr<WorkerInfo> info = |
262 inspected_workers_.erase(it); | 178 terminated_workers_.take_and_erase(terminated_it); |
263 BrowserThread::PostTask( | 179 paused_workers_.set(id, info.Pass()); |
264 BrowserThread::UI, FROM_HERE, | 180 return true; |
265 base::Bind(&DetachedClientHosts::WorkerDestroyed, worker_id)); | 181 } |
266 } | 182 |
267 | 183 void SharedWorkerDevToolsManager::WorkerDestroyed(int worker_process_id, |
268 void WorkerDevToolsManager::WorkerContextStarted(WorkerProcessHost* process, | 184 int worker_route_id) { |
269 int worker_route_id) { | 185 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
270 WorkerId new_worker_id(process->GetData().id, worker_route_id); | 186 const WorkerId id(worker_process_id, worker_route_id); |
271 PausedWorkers::iterator it = paused_workers_.find(new_worker_id); | 187 if (uninspected_workers_.erase(id)) |
272 if (it == paused_workers_.end()) | 188 return; |
273 return; | 189 WorkerInfoMap::iterator paused_it = paused_workers_.find(id); |
274 | 190 if (paused_it != paused_workers_.end()) { |
275 BrowserThread::PostTask( | 191 scoped_ptr<WorkerInfo> info = paused_workers_.take_and_erase(paused_it); |
276 BrowserThread::UI, FROM_HERE, | 192 const WorkerId old_id = info->agent_host()->worker_id(); |
277 base::Bind( | 193 terminated_workers_.set(old_id, info.Pass()); |
278 &DetachedClientHosts::WorkerReloaded, | 194 return; |
279 it->second, | 195 } |
280 new_worker_id)); | 196 |
281 paused_workers_.erase(it); | 197 WorkerInfoMap::iterator inspected_it = inspected_workers_.find(id); |
282 } | 198 if (inspected_it == inspected_workers_.end()) |
283 | 199 return; |
284 void WorkerDevToolsManager::RemoveInspectedWorkerData( | 200 scoped_ptr<WorkerInfo> info = inspected_workers_.take_and_erase(inspected_it); |
285 const WorkerId& id) { | 201 |
286 for (TerminatedInspectedWorkers::iterator it = terminated_workers_.begin(); | 202 SharedWorkerDevToolsAgentHost* agent_host = info->agent_host(); |
287 it != terminated_workers_.end(); ++it) { | 203 if (!agent_host->IsAttached()) { |
288 if (it->old_worker_id == id) { | 204 agent_host->DetachFromWorker(); |
289 terminated_workers_.erase(it); | 205 return; |
206 } | |
207 | |
208 terminated_workers_.set(id, info.Pass()); | |
209 // Client host is debugging this worker agent host. | |
210 std::string notification = | |
211 DevToolsProtocol::CreateNotification( | |
212 devtools::Worker::disconnectedFromWorker::kName, NULL)->Serialize(); | |
213 DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend(agent_host, | |
214 notification); | |
215 agent_host->DetachFromWorker(); | |
216 } | |
217 | |
218 void SharedWorkerDevToolsManager::WorkerContextStarted(int worker_process_id, | |
219 int worker_route_id) { | |
220 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
221 const WorkerId id(worker_process_id, worker_route_id); | |
222 WorkerInfoMap::iterator paused_it = paused_workers_.find(id); | |
223 if (paused_it == paused_workers_.end()) | |
224 return; | |
225 scoped_ptr<WorkerInfo> info = paused_workers_.take_and_erase(paused_it); | |
226 info->agent_host()->ReattachToWorker(id); | |
227 inspected_workers_.set(id, info.Pass()); | |
228 } | |
229 | |
230 void SharedWorkerDevToolsManager::RemoveInspectedWorkerData( | |
231 SharedWorkerDevToolsAgentHost* agent_host) { | |
232 if (terminated_workers_.erase(agent_host->worker_id())) | |
233 return; | |
234 | |
235 for (WorkerInfoMap::iterator paused_it = paused_workers_.begin(); | |
yurys
2014/03/31 13:48:23
How can the worker be in paused_workers_ map when
horo
2014/04/01 08:34:09
This could be occur when the DevToolsAgent is deta
yurys
2014/04/01 09:01:45
Got it, thanks for explaining.
| |
236 paused_it != paused_workers_.end(); | |
237 ++paused_it) { | |
238 if (paused_it->second->agent_host() == agent_host) { | |
239 SendMessageToWorker( | |
240 paused_it->first, | |
241 new DevToolsAgentMsg_ResumeWorkerContext(paused_it->first.second)); | |
242 paused_workers_.erase(paused_it); | |
290 return; | 243 return; |
291 } | 244 } |
292 } | 245 } |
293 | 246 } |
294 for (PausedWorkers::iterator it = paused_workers_.begin(); | 247 |
295 it != paused_workers_.end(); ++it) { | 248 SharedWorkerDevToolsManager::WorkerInfoMap::iterator |
296 if (it->second == id) { | 249 SharedWorkerDevToolsManager::FindTerminatedWorker( |
297 SendResumeToWorker(it->first); | 250 const SharedWorkerInstance& instance) { |
298 paused_workers_.erase(it); | 251 WorkerInfoMap::iterator terminated_it = terminated_workers_.begin(); |
299 return; | 252 for (; terminated_it != terminated_workers_.end(); ++terminated_it) { |
300 } | 253 if (terminated_it->second->instance().Matches(instance)) |
301 } | |
302 } | |
303 | |
304 WorkerDevToolsManager::InspectedWorkersList::iterator | |
305 WorkerDevToolsManager::FindInspectedWorker( | |
306 int host_id, int route_id) { | |
307 InspectedWorkersList::iterator it = inspected_workers_.begin(); | |
308 while (it != inspected_workers_.end()) { | |
309 if (it->host->GetData().id == host_id && it->route_id == route_id) | |
310 break; | 254 break; |
311 ++it; | 255 } |
312 } | 256 return terminated_it; |
313 return it; | |
314 } | |
315 | |
316 static WorkerProcessHost* FindWorkerProcess(int worker_process_id) { | |
317 for (WorkerProcessHostIterator iter; !iter.Done(); ++iter) { | |
318 if (iter.GetData().id == worker_process_id) | |
319 return *iter; | |
320 } | |
321 return NULL; | |
322 } | |
323 | |
324 void WorkerDevToolsManager::ConnectDevToolsAgentHostToWorker( | |
325 int worker_process_id, | |
326 int worker_route_id) { | |
327 if (WorkerProcessHost* process = FindWorkerProcess(worker_process_id)) { | |
328 const WorkerProcessHost::Instances& instances = process->instances(); | |
329 for (WorkerProcessHost::Instances::const_iterator i = instances.begin(); | |
330 i != instances.end(); ++i) { | |
331 if (i->worker_route_id() == worker_route_id) { | |
332 DCHECK(FindInspectedWorker(worker_process_id, worker_route_id) == | |
333 inspected_workers_.end()); | |
334 inspected_workers_.push_back( | |
335 InspectedWorker(process, worker_route_id, i->url(), i->name())); | |
336 return; | |
337 } | |
338 } | |
339 } | |
340 NotifyConnectionFailedOnIOThread(worker_process_id, worker_route_id); | |
341 } | |
342 | |
343 void WorkerDevToolsManager::ForwardToDevToolsClient( | |
344 int worker_process_id, | |
345 int worker_route_id, | |
346 const std::string& message) { | |
347 if (FindInspectedWorker(worker_process_id, worker_route_id) == | |
348 inspected_workers_.end()) { | |
349 NOTREACHED(); | |
350 return; | |
351 } | |
352 BrowserThread::PostTask( | |
353 BrowserThread::UI, FROM_HERE, | |
354 base::Bind( | |
355 &ForwardToDevToolsClientOnUIThread, | |
356 worker_process_id, | |
357 worker_route_id, | |
358 message)); | |
359 } | |
360 | |
361 void WorkerDevToolsManager::SaveAgentRuntimeState(int worker_process_id, | |
362 int worker_route_id, | |
363 const std::string& state) { | |
364 BrowserThread::PostTask( | |
365 BrowserThread::UI, FROM_HERE, | |
366 base::Bind( | |
367 &SaveAgentRuntimeStateOnUIThread, | |
368 worker_process_id, | |
369 worker_route_id, | |
370 state)); | |
371 } | |
372 | |
373 void WorkerDevToolsManager::ForwardToWorkerDevToolsAgent( | |
374 int worker_process_id, | |
375 int worker_route_id, | |
376 const IPC::Message& message) { | |
377 InspectedWorkersList::iterator it = FindInspectedWorker( | |
378 worker_process_id, | |
379 worker_route_id); | |
380 if (it == inspected_workers_.end()) | |
381 return; | |
382 IPC::Message* msg = new IPC::Message(message); | |
383 msg->set_routing_id(worker_route_id); | |
384 it->host->Send(msg); | |
385 } | |
386 | |
387 // static | |
388 void WorkerDevToolsManager::ForwardToDevToolsClientOnUIThread( | |
389 int worker_process_id, | |
390 int worker_route_id, | |
391 const std::string& message) { | |
392 AgentHosts::iterator it = g_agent_map.Get().find(WorkerId(worker_process_id, | |
393 worker_route_id)); | |
394 if (it == g_agent_map.Get().end()) | |
395 return; | |
396 DevToolsManagerImpl::GetInstance()->DispatchOnInspectorFrontend(it->second, | |
397 message); | |
398 } | |
399 | |
400 // static | |
401 void WorkerDevToolsManager::SaveAgentRuntimeStateOnUIThread( | |
402 int worker_process_id, | |
403 int worker_route_id, | |
404 const std::string& state) { | |
405 AgentHosts::iterator it = g_agent_map.Get().find(WorkerId(worker_process_id, | |
406 worker_route_id)); | |
407 if (it == g_agent_map.Get().end()) | |
408 return; | |
409 it->second->SaveAgentRuntimeState(state); | |
410 } | |
411 | |
412 // static | |
413 void WorkerDevToolsManager::NotifyConnectionFailedOnIOThread( | |
414 int worker_process_id, | |
415 int worker_route_id) { | |
416 BrowserThread::PostTask( | |
417 BrowserThread::UI, FROM_HERE, | |
418 base::Bind( | |
419 &WorkerDevToolsManager::NotifyConnectionFailedOnUIThread, | |
420 worker_process_id, | |
421 worker_route_id)); | |
422 } | |
423 | |
424 // static | |
425 void WorkerDevToolsManager::NotifyConnectionFailedOnUIThread( | |
426 int worker_process_id, | |
427 int worker_route_id) { | |
428 AgentHosts::iterator it = g_agent_map.Get().find(WorkerId(worker_process_id, | |
429 worker_route_id)); | |
430 if (it != g_agent_map.Get().end()) | |
431 it->second->ConnectionFailed(); | |
432 } | |
433 | |
434 // static | |
435 void WorkerDevToolsManager::SendResumeToWorker(const WorkerId& id) { | |
436 if (WorkerProcessHost* process = FindWorkerProcess(id.first)) | |
437 process->Send(new DevToolsAgentMsg_ResumeWorkerContext(id.second)); | |
438 } | |
439 | |
440 WorkerDevToolsManager::WorkerDevToolsAgentHost::~WorkerDevToolsAgentHost() { | |
441 DetachedClientHosts::RemovePendingWorkerData(worker_id_); | |
442 g_agent_map.Get().erase(worker_id_); | |
443 g_orphan_map.Get().erase(worker_id_); | |
444 } | 257 } |
445 | 258 |
446 } // namespace content | 259 } // namespace content |
OLD | NEW |