OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "content/browser/debugger/worker_devtools_manager_io.h" | |
6 | |
7 #include <list> | |
8 | |
9 #include "base/tuple.h" | |
10 #include "chrome/browser/profiles/profile_manager.h" | |
11 #include "content/browser/browser_thread.h" | |
12 #include "content/browser/debugger/devtools_manager.h" | |
13 #include "content/browser/debugger/devtools_window.h" | |
14 #include "content/browser/debugger/worker_devtools_message_filter.h" | |
15 #include "content/browser/worker_host/worker_process_host.h" | |
16 #include "content/common/devtools_messages.h" | |
17 | |
18 namespace { | |
19 | |
20 | |
pfeldman
2011/07/11 12:07:16
Blank line
yurys
2011/07/11 15:13:11
Done.
| |
21 void NotifyWorkerDevToolsClientClosingOnIOThread(int worker_process_host_id, | |
22 int worker_route_id) { | |
23 WorkerDevToolsManagerIO::GetInstance()->WorkerDevToolsClientClosing( | |
24 worker_process_host_id, | |
25 worker_route_id); | |
26 } | |
27 | |
28 class WorkerDevToolsClients : public DevToolsClientHost::CloseListener { | |
pfeldman
2011/07/11 12:07:16
ClientsUI ?
yurys
2011/07/11 15:13:11
Done.
| |
29 public: | |
30 static WorkerDevToolsClients* GetInstance() { | |
31 static WorkerDevToolsClients* instance = new WorkerDevToolsClients(); | |
32 return instance; | |
33 } | |
34 | |
35 DevToolsClientHost* FindDevToolsClient(int worker_process_host_id, | |
36 int worker_route_id) { | |
37 WorkerIdToClientHostMap::iterator it = | |
38 worker_id_to_client_host_.find(WorkerId(worker_process_host_id, | |
39 worker_route_id)); | |
40 if (it == worker_id_to_client_host_.end()) | |
41 return NULL; | |
42 return it->second; | |
43 } | |
44 | |
45 bool FindWorkerInfo(DevToolsClientHost* client_host, | |
46 int* host_id, | |
47 int* route_id) { | |
48 for (WorkerIdToClientHostMap::const_iterator it = | |
49 worker_id_to_client_host_.begin(); | |
50 it != worker_id_to_client_host_.end(); ++it) { | |
51 if (it->second == client_host) { | |
52 WorkerId id = it->first; | |
53 *host_id = id.first; | |
54 *route_id = id.second; | |
55 return true; | |
56 } | |
57 } | |
58 return false; | |
59 } | |
60 | |
61 void RegisterDevToolsClientForWorker(int worker_process_host_id, | |
62 int worker_route_id, | |
63 DevToolsClientHost* client) { | |
64 client->set_close_listener(this); | |
65 WorkerId worker_id(worker_process_host_id, worker_route_id); | |
66 worker_id_to_client_host_[worker_id] = client; | |
67 } | |
68 | |
69 private: | |
70 WorkerDevToolsClients() {} | |
71 virtual ~WorkerDevToolsClients() {} | |
72 | |
73 virtual void ClientHostClosing(DevToolsClientHost* host) { | |
74 WorkerIdToClientHostMap::iterator it = worker_id_to_client_host_.begin(); | |
75 for (; it != worker_id_to_client_host_.end(); ++it) { | |
76 if (it->second == host) { | |
77 WorkerId id = it->first; | |
78 BrowserThread::PostTask( | |
79 BrowserThread::IO, FROM_HERE, | |
80 NewRunnableFunction(NotifyWorkerDevToolsClientClosingOnIOThread, | |
81 id.first, id.second)); | |
82 worker_id_to_client_host_.erase(it); | |
83 return; | |
84 } | |
85 } | |
86 } | |
87 | |
88 typedef std::pair<int, int> WorkerId; | |
89 typedef std::map<WorkerId, DevToolsClientHost*> WorkerIdToClientHostMap; | |
90 WorkerIdToClientHostMap worker_id_to_client_host_; | |
91 | |
92 DISALLOW_COPY_AND_ASSIGN(WorkerDevToolsClients); | |
93 }; | |
94 | |
95 } // namespace | |
96 | |
97 class WorkerDevToolsManagerIO::InspectedWorkersList { | |
98 public: | |
99 InspectedWorkersList() {} | |
100 | |
101 void AddInstance(WorkerProcessHost* host, int route_id) { | |
102 DCHECK(!Contains(host->id(), route_id)); | |
103 map_.push_back(Entry(host, route_id)); | |
104 } | |
105 | |
106 bool Contains(int host_id, int route_id) { | |
107 return FindHost(host_id, route_id) != NULL; | |
108 } | |
109 | |
110 WorkerProcessHost* FindHost(int host_id, int route_id) { | |
111 Entries::iterator it = FindEntry(host_id, route_id); | |
112 if (it == map_.end()) | |
113 return NULL; | |
114 return it->host; | |
115 } | |
116 | |
117 WorkerProcessHost* RemoveInstance(int host_id, int route_id) { | |
118 Entries::iterator it = FindEntry(host_id, route_id); | |
119 if (it == map_.end()) | |
120 return NULL; | |
121 WorkerProcessHost* host = it->host; | |
122 map_.erase(it); | |
123 return host; | |
124 } | |
125 | |
126 void WorkerDevToolsMessageFilterClosing(int worker_process_host_id) { | |
127 Entries::iterator it = map_.begin(); | |
128 while (it != map_.end()) { | |
129 if (it->host->id() == worker_process_host_id) | |
130 it = map_.erase(it); | |
131 else | |
132 ++it; | |
133 } | |
134 } | |
135 | |
136 private: | |
137 struct Entry { | |
138 Entry(WorkerProcessHost* host, int route_id) | |
139 : host(host), | |
140 route_id(route_id) {} | |
141 WorkerProcessHost* const host; | |
142 int const route_id; | |
143 }; | |
144 typedef std::list<Entry> Entries; | |
145 | |
146 Entries::iterator FindEntry(int host_id, int route_id) { | |
147 Entries::iterator it = map_.begin(); | |
148 while (it != map_.end()) { | |
149 if (it->host->id() == host_id && it->route_id == route_id) | |
150 break; | |
151 } | |
152 return it; | |
153 } | |
154 | |
155 Entries map_; | |
156 DISALLOW_COPY_AND_ASSIGN(InspectedWorkersList); | |
157 }; | |
158 | |
159 // static | |
160 WorkerDevToolsManagerIO* WorkerDevToolsManagerIO::GetInstance() { | |
161 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
162 return Singleton<WorkerDevToolsManagerIO>::get(); | |
163 } | |
164 | |
165 WorkerDevToolsManagerIO::WorkerDevToolsManagerIO() | |
166 : inspected_workers_(new InspectedWorkersList()) { | |
167 } | |
168 | |
169 WorkerDevToolsManagerIO::~WorkerDevToolsManagerIO() { | |
170 } | |
171 | |
172 bool WorkerDevToolsManagerIO::ForwardToWorkerDevToolsAgentOnUIThread( | |
173 DevToolsClientHost* from, | |
174 const IPC::Message& message) { | |
175 int worker_process_host_id; | |
176 int worker_route_id; | |
177 if (!WorkerDevToolsClients::GetInstance()->FindWorkerInfo( | |
178 from, &worker_process_host_id, &worker_route_id)) | |
179 return false; | |
180 BrowserThread::PostTask( | |
181 BrowserThread::IO, FROM_HERE, | |
182 NewRunnableFunction( | |
183 ForwardToWorkerDevToolsAgentOnIOThread, | |
184 worker_process_host_id, | |
185 worker_route_id, | |
186 IPC::Message(message))); | |
187 return true; | |
188 } | |
189 | |
190 static void OpenDevToolsForWorkerOnUIThread(int worker_process_host_id, | |
191 int worker_route_id) { | |
192 Profile* profile = ProfileManager::GetDefaultProfile(); | |
193 if (!profile) | |
194 return; | |
195 DevToolsWindow* window = DevToolsWindow::CreateDevToolsWindowForWorker( | |
196 profile); | |
197 window->Show(DEVTOOLS_TOGGLE_ACTION_NONE); | |
198 WorkerDevToolsClients::GetInstance()->RegisterDevToolsClientForWorker( | |
199 worker_process_host_id, worker_route_id, window); | |
200 } | |
201 | |
202 static WorkerProcessHost* FindWorkerProcessHostForWorker( | |
203 int worker_process_host_id, | |
204 int worker_route_id) { | |
205 BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); | |
206 for (; !iter.Done(); ++iter) { | |
207 if (iter->id() != worker_process_host_id) | |
208 continue; | |
209 WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); | |
210 const WorkerProcessHost::Instances& instances = worker->instances(); | |
211 for (WorkerProcessHost::Instances::const_iterator i = instances.begin(); | |
212 i != instances.end(); ++i) { | |
213 if (i->shared() && i->worker_route_id() == worker_route_id) | |
214 return worker; | |
215 } | |
216 return NULL; | |
217 } | |
218 return NULL; | |
219 } | |
220 | |
221 void WorkerDevToolsManagerIO::OpenDevToolsForWorker(int worker_process_host_id, | |
222 int worker_route_id) { | |
223 WorkerProcessHost* host = FindWorkerProcessHostForWorker( | |
224 worker_process_host_id, | |
225 worker_route_id); | |
226 if (!host) | |
227 return; | |
228 | |
229 // DevTools client is already attached. | |
230 if (inspected_workers_->Contains(worker_process_host_id, worker_route_id)) | |
231 return; | |
232 | |
233 host->Send(new WorkerDevToolsAgentMsg_Attach(worker_route_id)); | |
234 | |
235 inspected_workers_->AddInstance(host, worker_route_id); | |
236 BrowserThread::PostTask( | |
237 BrowserThread::UI, FROM_HERE, | |
238 NewRunnableFunction( | |
239 OpenDevToolsForWorkerOnUIThread, | |
240 worker_process_host_id, | |
241 worker_route_id)); | |
242 } | |
243 | |
244 void WorkerDevToolsManagerIO::WorkerDevToolsClientClosing( | |
245 int worker_process_host_id, | |
246 int worker_route_id) { | |
247 WorkerProcessHost* host = inspected_workers_->RemoveInstance( | |
248 worker_process_host_id, worker_route_id); | |
249 if (host) | |
250 host->Send(new WorkerDevToolsAgentMsg_Detach(worker_route_id)); | |
251 } | |
252 | |
253 static void ForwardToDevToolsClientOnUIThread( | |
254 int worker_process_host_id, | |
255 int worker_route_id, | |
256 const IPC::Message& message) { | |
257 DevToolsClientHost* client = WorkerDevToolsClients::GetInstance()-> | |
258 FindDevToolsClient(worker_process_host_id, worker_route_id); | |
259 if (client) | |
260 client->SendMessageToClient(message); | |
261 } | |
262 | |
263 void WorkerDevToolsManagerIO::ForwardToDevToolsClient( | |
264 int worker_process_host_id, | |
265 int worker_route_id, | |
266 const IPC::Message& message) { | |
267 if (!inspected_workers_->Contains(worker_process_host_id, worker_route_id)) { | |
268 NOTREACHED(); | |
269 return; | |
270 } | |
271 BrowserThread::PostTask( | |
272 BrowserThread::UI, FROM_HERE, | |
273 NewRunnableFunction( | |
274 ForwardToDevToolsClientOnUIThread, | |
275 worker_process_host_id, | |
276 worker_route_id, | |
277 IPC::Message(message))); | |
278 } | |
279 | |
280 void WorkerDevToolsManagerIO::WorkerProcessDestroying( | |
281 int worker_process_host_id) { | |
282 inspected_workers_->WorkerDevToolsMessageFilterClosing( | |
283 worker_process_host_id); | |
284 } | |
285 | |
286 void WorkerDevToolsManagerIO::ForwardToWorkerDevToolsAgentOnIOThread( | |
287 int worker_process_host_id, | |
288 int worker_route_id, | |
289 const IPC::Message& message) { | |
290 WorkerDevToolsManagerIO::GetInstance()->ForwardToWorkerDevToolsAgent( | |
291 worker_process_host_id, worker_route_id, message); | |
292 } | |
293 | |
294 void WorkerDevToolsManagerIO::ForwardToWorkerDevToolsAgent( | |
295 int worker_process_host_id, | |
296 int worker_route_id, | |
297 const IPC::Message& message) { | |
298 WorkerProcessHost* host = inspected_workers_->FindHost( | |
299 worker_process_host_id, | |
300 worker_route_id); | |
301 if (!host) | |
302 return; | |
303 IPC::Message* msg = new IPC::Message(message); | |
304 msg->set_routing_id(worker_route_id); | |
305 host->Send(msg); | |
306 } | |
OLD | NEW |