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