OLD | NEW |
---|---|
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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 "chrome/browser/worker_host/worker_process_host.h" | 5 #include "chrome/browser/worker_host/worker_process_host.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
143 ChildProcessSecurityPolicy::GetInstance()->GrantRequestURL( | 143 ChildProcessSecurityPolicy::GetInstance()->GrantRequestURL( |
144 id(), instance.url); | 144 id(), instance.url); |
145 | 145 |
146 instances_.push_back(instance); | 146 instances_.push_back(instance); |
147 Send(new WorkerProcessMsg_CreateWorker(instance.url, | 147 Send(new WorkerProcessMsg_CreateWorker(instance.url, |
148 instance.is_shared, | 148 instance.is_shared, |
149 instance.name, | 149 instance.name, |
150 instance.worker_route_id)); | 150 instance.worker_route_id)); |
151 | 151 |
152 UpdateTitle(); | 152 UpdateTitle(); |
153 instances_.back().sender->Send( | 153 DCHECK(instance.senders.size() == 1); |
154 new ViewMsg_WorkerCreated(instance.sender_route_id)); | 154 WorkerInstance::SenderInfo info = *(instances_.back().senders.begin()); |
155 info.first->Send(new ViewMsg_WorkerCreated(info.second)); | |
155 } | 156 } |
156 | 157 |
157 bool WorkerProcessHost::FilterMessage(const IPC::Message& message, | 158 bool WorkerProcessHost::FilterMessage(const IPC::Message& message, |
158 int sender_pid) { | 159 IPC::Message::Sender* sender) { |
159 for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) { | 160 for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) { |
160 if (i->sender_id == sender_pid && | 161 if (!i->closed && i->HasSender(sender, message.routing_id())) { |
161 i->sender_route_id == message.routing_id()) { | |
162 RelayMessage( | 162 RelayMessage( |
163 message, this, i->worker_route_id, next_route_id_callback_.get()); | 163 message, this, i->worker_route_id, next_route_id_callback_.get()); |
164 return true; | 164 return true; |
165 } | 165 } |
166 } | 166 } |
167 | 167 |
168 return false; | 168 return false; |
169 } | 169 } |
170 | 170 |
171 URLRequestContext* WorkerProcessHost::GetRequestContext( | 171 URLRequestContext* WorkerProcessHost::GetRequestContext( |
172 uint32 request_id, | 172 uint32 request_id, |
173 const ViewHostMsg_Resource_Request& request_data) { | 173 const ViewHostMsg_Resource_Request& request_data) { |
174 return NULL; | 174 return NULL; |
175 } | 175 } |
176 | 176 |
177 // Sent to notify the browser process when a worker context invokes close(), so | |
178 // no new connections are sent to shared workers. | |
179 void WorkerProcessHost::OnWorkerContextClosed(int worker_route_id) { | |
180 for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) { | |
181 if (i->worker_route_id == worker_route_id) { | |
182 // Set the closed flag - this will stop any further connections from | |
183 // being sent to the shared worker (ignored for dedicated workers). | |
jam
2009/11/12 20:11:23
nit: the comment says it's ignored for dedicated w
| |
184 i->closed = true; | |
185 break; | |
186 } | |
187 } | |
188 } | |
189 | |
177 void WorkerProcessHost::OnMessageReceived(const IPC::Message& message) { | 190 void WorkerProcessHost::OnMessageReceived(const IPC::Message& message) { |
178 bool msg_is_ok = true; | 191 bool msg_is_ok = true; |
179 bool handled = MessagePortDispatcher::GetInstance()->OnMessageReceived( | 192 bool handled = MessagePortDispatcher::GetInstance()->OnMessageReceived( |
180 message, this, next_route_id_callback_.get(), &msg_is_ok); | 193 message, this, next_route_id_callback_.get(), &msg_is_ok); |
181 | 194 |
182 if (!handled) { | 195 if (!handled) { |
183 handled = true; | 196 handled = true; |
184 IPC_BEGIN_MESSAGE_MAP_EX(WorkerProcessHost, message, msg_is_ok) | 197 IPC_BEGIN_MESSAGE_MAP_EX(WorkerProcessHost, message, msg_is_ok) |
185 IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWorker, OnCreateWorker) | 198 IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWorker, OnCreateWorker) |
186 IPC_MESSAGE_HANDLER(ViewHostMsg_CancelCreateDedicatedWorker, | 199 IPC_MESSAGE_HANDLER(ViewHostMsg_CancelCreateDedicatedWorker, |
187 OnCancelCreateDedicatedWorker) | 200 OnCancelCreateDedicatedWorker) |
201 IPC_MESSAGE_HANDLER(WorkerHostMsg_WorkerContextClosed, | |
202 OnWorkerContextClosed); | |
188 IPC_MESSAGE_HANDLER(ViewHostMsg_ForwardToWorker, | 203 IPC_MESSAGE_HANDLER(ViewHostMsg_ForwardToWorker, |
189 OnForwardToWorker) | 204 OnForwardToWorker) |
jam
2009/11/12 20:11:23
can you add the new messages that you receive in R
| |
190 IPC_MESSAGE_UNHANDLED(handled = false) | 205 IPC_MESSAGE_UNHANDLED(handled = false) |
191 IPC_END_MESSAGE_MAP_EX() | 206 IPC_END_MESSAGE_MAP_EX() |
192 } | 207 } |
193 | 208 |
194 if (!msg_is_ok) { | 209 if (!msg_is_ok) { |
195 NOTREACHED(); | 210 NOTREACHED(); |
196 base::KillProcess(handle(), ResultCodes::KILLED_BAD_MESSAGE, false); | 211 base::KillProcess(handle(), ResultCodes::KILLED_BAD_MESSAGE, false); |
197 } | 212 } |
198 | 213 |
199 if (handled) | 214 if (handled) |
200 return; | 215 return; |
201 | 216 |
202 for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) { | 217 for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) { |
203 if (i->worker_route_id == message.routing_id()) { | 218 if (i->worker_route_id == message.routing_id()) { |
204 CallbackWithReturnValue<int>::Type* next_route_id = | 219 if (!i->is_shared) { |
205 GetNextRouteIdCallback(i->sender); | 220 // Don't relay messages from shared workers (all communication is via |
206 RelayMessage(message, i->sender, i->sender_route_id, next_route_id); | 221 // the message port). |
222 DCHECK(i->senders.size() == 1); | |
223 WorkerInstance::SenderInfo info = *(i->senders.begin()); | |
224 CallbackWithReturnValue<int>::Type* next_route_id = | |
225 GetNextRouteIdCallback(info.first); | |
226 RelayMessage(message, info.first, info.second, next_route_id); | |
227 } | |
207 | 228 |
208 if (message.type() == WorkerHostMsg_WorkerContextDestroyed::ID) { | 229 if (message.type() == WorkerHostMsg_WorkerContextDestroyed::ID) { |
209 instances_.erase(i); | 230 instances_.erase(i); |
210 UpdateTitle(); | 231 UpdateTitle(); |
211 } | 232 } |
212 break; | 233 break; |
213 } | 234 } |
214 } | 235 } |
215 } | 236 } |
216 | 237 |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
286 } else { | 307 } else { |
287 IPC::Message* new_message = new IPC::Message(message); | 308 IPC::Message* new_message = new IPC::Message(message); |
288 new_message->set_routing_id(route_id); | 309 new_message->set_routing_id(route_id); |
289 sender->Send(new_message); | 310 sender->Send(new_message); |
290 return; | 311 return; |
291 } | 312 } |
292 } | 313 } |
293 | 314 |
294 void WorkerProcessHost::SenderShutdown(IPC::Message::Sender* sender) { | 315 void WorkerProcessHost::SenderShutdown(IPC::Message::Sender* sender) { |
295 for (Instances::iterator i = instances_.begin(); i != instances_.end();) { | 316 for (Instances::iterator i = instances_.begin(); i != instances_.end();) { |
296 if (i->sender == sender) { | 317 bool shutdown = false; |
318 i->RemoveSenders(sender); | |
319 if (i->is_shared) { | |
320 i->RemoveAllAssociatedDocuments(sender); | |
321 if (i->document_set.empty()) | |
322 shutdown = true; | |
323 } else if (i->senders.empty()) { | |
324 shutdown = true; | |
325 } | |
326 if (shutdown) { | |
297 Send(new WorkerMsg_TerminateWorkerContext(i->worker_route_id)); | 327 Send(new WorkerMsg_TerminateWorkerContext(i->worker_route_id)); |
298 i = instances_.erase(i); | 328 i = instances_.erase(i); |
299 } else { | 329 } else { |
300 ++i; | 330 ++i; |
301 } | 331 } |
302 } | 332 } |
303 } | 333 } |
304 | 334 |
305 void WorkerProcessHost::UpdateTitle() { | 335 void WorkerProcessHost::UpdateTitle() { |
306 std::set<std::string> titles; | 336 std::set<std::string> titles; |
(...skipping 22 matching lines...) Expand all Loading... | |
329 | 359 |
330 void WorkerProcessHost::OnCreateWorker(const GURL& url, | 360 void WorkerProcessHost::OnCreateWorker(const GURL& url, |
331 bool is_shared, | 361 bool is_shared, |
332 const string16& name, | 362 const string16& name, |
333 int render_view_route_id, | 363 int render_view_route_id, |
334 int* route_id) { | 364 int* route_id) { |
335 DCHECK(instances_.size() == 1); // Only called when one process per worker. | 365 DCHECK(instances_.size() == 1); // Only called when one process per worker. |
336 *route_id = WorkerService::GetInstance()->next_worker_route_id(); | 366 *route_id = WorkerService::GetInstance()->next_worker_route_id(); |
337 WorkerService::GetInstance()->CreateWorker( | 367 WorkerService::GetInstance()->CreateWorker( |
338 url, is_shared, name, instances_.front().renderer_id, | 368 url, is_shared, name, instances_.front().renderer_id, |
339 instances_.front().render_view_route_id, this, id(), *route_id); | 369 instances_.front().render_view_route_id, this, *route_id); |
340 } | 370 } |
341 | 371 |
342 void WorkerProcessHost::OnCancelCreateDedicatedWorker(int route_id) { | 372 void WorkerProcessHost::OnCancelCreateDedicatedWorker(int route_id) { |
343 WorkerService::GetInstance()->CancelCreateDedicatedWorker(id(), route_id); | 373 WorkerService::GetInstance()->CancelCreateDedicatedWorker(this, route_id); |
344 } | 374 } |
345 | 375 |
346 void WorkerProcessHost::OnForwardToWorker(const IPC::Message& message) { | 376 void WorkerProcessHost::OnForwardToWorker(const IPC::Message& message) { |
347 WorkerService::GetInstance()->ForwardMessage(message, id()); | 377 WorkerService::GetInstance()->ForwardMessage(message, this); |
348 } | 378 } |
379 | |
380 void WorkerProcessHost::DocumentDetached(IPC::Message::Sender* parent, | |
381 unsigned long long document_id) | |
382 { | |
383 // Walk all instances and remove the document from their document set | |
jam
2009/11/12 20:11:23
very nitty nit: period at end of comment
| |
384 for (Instances::iterator i = instances_.begin(); i != instances_.end();) { | |
385 if (!i->is_shared) { | |
386 ++i; | |
387 } else { | |
388 i->RemoveFromDocumentSet(parent, document_id); | |
389 if (i->document_set.empty()) { | |
390 // This worker has no more associated documents - shut it down. | |
391 Send(new WorkerMsg_TerminateWorkerContext(i->worker_route_id)); | |
392 i = instances_.erase(i); | |
393 } else { | |
394 ++i; | |
395 } | |
396 } | |
397 } | |
398 } | |
399 | |
400 // Compares an instance based on the algorithm in the WebWorkers spec - an | |
401 // instance matches if the origins of the URLs match, and: | |
402 // a) the names are non-empty and equal | |
403 // -or- | |
404 // b) the names are both empty, and the urls are equal | |
405 bool WorkerProcessHost::WorkerInstance::Matches( | |
406 const GURL& match_url, const string16& match_name) const { | |
407 // Only match open shared workers. | |
408 if (!is_shared || closed) | |
409 return false; | |
410 | |
411 if (url.GetOrigin() != match_url.GetOrigin()) | |
412 return false; | |
413 | |
414 if (name.empty() && match_name.empty()) | |
415 return url == match_url; | |
416 | |
417 return name == match_name; | |
418 } | |
419 | |
420 void WorkerProcessHost::WorkerInstance::AddToDocumentSet( | |
421 IPC::Message::Sender* parent, unsigned long long document_id) { | |
422 DocumentInfo info(parent, document_id); | |
423 document_set.insert(info); | |
424 } | |
425 | |
426 bool WorkerProcessHost::WorkerInstance::IsInDocumentSet( | |
427 IPC::Message::Sender* parent, unsigned long long document_id) const { | |
428 DocumentInfo info(parent, document_id); | |
429 return document_set.find(info) != document_set.end(); | |
430 } | |
431 | |
432 void WorkerProcessHost::WorkerInstance::RemoveFromDocumentSet( | |
433 IPC::Message::Sender* parent, unsigned long long document_id) { | |
434 DocumentInfo info(parent, document_id); | |
435 document_set.erase(info); | |
436 } | |
437 | |
438 void WorkerProcessHost::WorkerInstance::RemoveAllAssociatedDocuments( | |
439 IPC::Message::Sender* parent) { | |
440 for (DocumentSet::iterator i = document_set.begin(); | |
441 i != document_set.end(); | |
442 ++i) { | |
443 if (i->first == parent) | |
444 document_set.erase(i); | |
jam
2009/11/12 20:11:23
this isn't safe, need to increment i only if you d
| |
445 } | |
446 } | |
447 | |
448 void WorkerProcessHost::WorkerInstance::AddSender(IPC::Message::Sender* sender, | |
449 int sender_route_id) { | |
450 SenderInfo info(sender, sender_route_id); | |
451 senders.insert(info); | |
452 // Only shared workers can have more than one associated sender. | |
453 DCHECK(is_shared || senders.size() == 1); | |
454 } | |
455 | |
456 void WorkerProcessHost::WorkerInstance::RemoveSender( | |
457 IPC::Message::Sender* sender, int sender_route_id) { | |
458 SenderInfo info(sender, sender_route_id); | |
459 senders.erase(info); | |
460 } | |
461 | |
462 void WorkerProcessHost::WorkerInstance::RemoveSenders( | |
463 IPC::Message::Sender* sender) { | |
464 for (SenderList::iterator i = senders.begin(); i != senders.end(); ++i) { | |
465 if (i->first == sender) | |
466 senders.erase(i); | |
467 } | |
468 } | |
469 | |
470 bool WorkerProcessHost::WorkerInstance::HasSender( | |
471 IPC::Message::Sender* sender, int sender_route_id) const { | |
472 SenderInfo info(sender, sender_route_id); | |
473 return senders.find(info) != senders.end(); | |
474 } | |
475 | |
476 | |
OLD | NEW |