Chromium Code Reviews| 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 |