| 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 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 WorkerService::GetInstance(), &WorkerService::next_worker_route_id)); | 58 WorkerService::GetInstance(), &WorkerService::next_worker_route_id)); |
| 59 } | 59 } |
| 60 | 60 |
| 61 WorkerProcessHost::~WorkerProcessHost() { | 61 WorkerProcessHost::~WorkerProcessHost() { |
| 62 // Let interested observers know we are being deleted. | 62 // Let interested observers know we are being deleted. |
| 63 NotificationService::current()->Notify( | 63 NotificationService::current()->Notify( |
| 64 NotificationType::WORKER_PROCESS_HOST_SHUTDOWN, | 64 NotificationType::WORKER_PROCESS_HOST_SHUTDOWN, |
| 65 Source<WorkerProcessHost>(this), | 65 Source<WorkerProcessHost>(this), |
| 66 NotificationService::NoDetails()); | 66 NotificationService::NoDetails()); |
| 67 | 67 |
| 68 // If we crashed, tell the RenderViewHost. | 68 // If we crashed, tell the RenderViewHosts. |
| 69 for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) { | 69 for (Instances::iterator i = instances_.begin(); i != instances_.end(); ++i) { |
| 70 ChromeThread::PostTask( | 70 const WorkerDocumentSet::DocumentInfoSet& parents = |
| 71 ChromeThread::UI, FROM_HERE, | 71 i->worker_document_set()->documents(); |
| 72 new WorkerCrashTask(i->renderer_id(), i->render_view_route_id())); | 72 for (WorkerDocumentSet::DocumentInfoSet::const_iterator parent_iter = |
| 73 parents.begin(); parent_iter != parents.end(); ++parent_iter) { |
| 74 ChromeThread::PostTask( |
| 75 ChromeThread::UI, FROM_HERE, |
| 76 new WorkerCrashTask(parent_iter->renderer_id(), |
| 77 parent_iter->render_view_route_id())); |
| 78 } |
| 73 } | 79 } |
| 74 | 80 |
| 75 ChildProcessSecurityPolicy::GetInstance()->Remove(id()); | 81 ChildProcessSecurityPolicy::GetInstance()->Remove(id()); |
| 76 } | 82 } |
| 77 | 83 |
| 78 bool WorkerProcessHost::Init() { | 84 bool WorkerProcessHost::Init() { |
| 79 if (!CreateChannel()) | 85 if (!CreateChannel()) |
| 80 return false; | 86 return false; |
| 81 | 87 |
| 82 FilePath exe_path = GetChildPath(); | 88 FilePath exe_path = GetChildPath(); |
| (...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 323 sender->Send(new_message); | 329 sender->Send(new_message); |
| 324 return; | 330 return; |
| 325 } | 331 } |
| 326 } | 332 } |
| 327 | 333 |
| 328 void WorkerProcessHost::SenderShutdown(IPC::Message::Sender* sender) { | 334 void WorkerProcessHost::SenderShutdown(IPC::Message::Sender* sender) { |
| 329 for (Instances::iterator i = instances_.begin(); i != instances_.end();) { | 335 for (Instances::iterator i = instances_.begin(); i != instances_.end();) { |
| 330 bool shutdown = false; | 336 bool shutdown = false; |
| 331 i->RemoveSenders(sender); | 337 i->RemoveSenders(sender); |
| 332 if (i->shared()) { | 338 if (i->shared()) { |
| 333 i->RemoveAllAssociatedDocuments(sender); | 339 i->worker_document_set()->RemoveAll(sender); |
| 334 if (i->IsDocumentSetEmpty()) { | 340 if (i->worker_document_set()->IsEmpty()) { |
| 335 shutdown = true; | 341 shutdown = true; |
| 336 } | 342 } |
| 337 } else if (i->NumSenders() == 0) { | 343 } else if (i->NumSenders() == 0) { |
| 338 shutdown = true; | 344 shutdown = true; |
| 339 } | 345 } |
| 340 if (shutdown) { | 346 if (shutdown) { |
| 341 Send(new WorkerMsg_TerminateWorkerContext(i->worker_route_id())); | 347 Send(new WorkerMsg_TerminateWorkerContext(i->worker_route_id())); |
| 342 i = instances_.erase(i); | 348 i = instances_.erase(i); |
| 343 } else { | 349 } else { |
| 344 ++i; | 350 ++i; |
| (...skipping 22 matching lines...) Expand all Loading... |
| 367 display_title += ", "; | 373 display_title += ", "; |
| 368 display_title += *i; | 374 display_title += *i; |
| 369 } | 375 } |
| 370 | 376 |
| 371 set_name(ASCIIToWide(display_title)); | 377 set_name(ASCIIToWide(display_title)); |
| 372 } | 378 } |
| 373 | 379 |
| 374 void WorkerProcessHost::OnLookupSharedWorker(const GURL& url, | 380 void WorkerProcessHost::OnLookupSharedWorker(const GURL& url, |
| 375 const string16& name, | 381 const string16& name, |
| 376 unsigned long long document_id, | 382 unsigned long long document_id, |
| 383 int render_view_route_id, |
| 377 int* route_id, | 384 int* route_id, |
| 378 bool* url_mismatch) { | 385 bool* url_mismatch) { |
| 379 int new_route_id = WorkerService::GetInstance()->next_worker_route_id(); | 386 int new_route_id = WorkerService::GetInstance()->next_worker_route_id(); |
| 380 // TODO(atwilson): Add code to merge document sets for nested shared workers. | 387 // TODO(atwilson): Add code to pass in the current worker's document set for |
| 388 // these nested workers. Code below will not work for SharedWorkers as it |
| 389 // only looks at a single parent. |
| 390 DCHECK(instances_.front().worker_document_set()->documents().size() == 1); |
| 391 WorkerDocumentSet::DocumentInfoSet::const_iterator first_parent = |
| 392 instances_.front().worker_document_set()->documents().begin(); |
| 381 bool worker_found = WorkerService::GetInstance()->LookupSharedWorker( | 393 bool worker_found = WorkerService::GetInstance()->LookupSharedWorker( |
| 382 url, name, instances_.front().off_the_record(), document_id, this, | 394 url, name, instances_.front().off_the_record(), document_id, |
| 395 first_parent->renderer_id(), first_parent->render_view_route_id(), this, |
| 383 new_route_id, url_mismatch); | 396 new_route_id, url_mismatch); |
| 384 *route_id = worker_found ? new_route_id : MSG_ROUTING_NONE; | 397 *route_id = worker_found ? new_route_id : MSG_ROUTING_NONE; |
| 385 } | 398 } |
| 386 | 399 |
| 387 void WorkerProcessHost::OnCreateWorker(const GURL& url, | 400 void WorkerProcessHost::OnCreateWorker( |
| 388 bool shared, | 401 const ViewHostMsg_CreateWorker_Params& params, int* route_id) { |
| 389 const string16& name, | |
| 390 int render_view_route_id, | |
| 391 int* route_id) { | |
| 392 DCHECK(instances_.size() == 1); // Only called when one process per worker. | 402 DCHECK(instances_.size() == 1); // Only called when one process per worker. |
| 403 // TODO(atwilson): Add code to pass in the current worker's document set for |
| 404 // these nested workers. Code below will not work for SharedWorkers as it |
| 405 // only looks at a single parent. |
| 406 DCHECK(instances_.front().worker_document_set()->documents().size() == 1); |
| 407 WorkerDocumentSet::DocumentInfoSet::const_iterator first_parent = |
| 408 instances_.front().worker_document_set()->documents().begin(); |
| 393 *route_id = WorkerService::GetInstance()->next_worker_route_id(); | 409 *route_id = WorkerService::GetInstance()->next_worker_route_id(); |
| 394 WorkerService::GetInstance()->CreateWorker( | 410 WorkerService::GetInstance()->CreateWorker( |
| 395 url, shared, instances_.front().off_the_record(), name, | 411 params.url, params.is_shared, instances_.front().off_the_record(), |
| 396 instances_.front().renderer_id(), | 412 params.name, params.document_id, first_parent->renderer_id(), |
| 397 instances_.front().render_view_route_id(), this, *route_id); | 413 first_parent->render_view_route_id(), this, *route_id); |
| 398 // TODO(atwilson): Add code to merge document sets for nested shared workers. | |
| 399 } | 414 } |
| 400 | 415 |
| 401 void WorkerProcessHost::OnCancelCreateDedicatedWorker(int route_id) { | 416 void WorkerProcessHost::OnCancelCreateDedicatedWorker(int route_id) { |
| 402 WorkerService::GetInstance()->CancelCreateDedicatedWorker(this, route_id); | 417 WorkerService::GetInstance()->CancelCreateDedicatedWorker(this, route_id); |
| 403 } | 418 } |
| 404 | 419 |
| 405 void WorkerProcessHost::OnForwardToWorker(const IPC::Message& message) { | 420 void WorkerProcessHost::OnForwardToWorker(const IPC::Message& message) { |
| 406 WorkerService::GetInstance()->ForwardMessage(message, this); | 421 WorkerService::GetInstance()->ForwardMessage(message, this); |
| 407 } | 422 } |
| 408 | 423 |
| 409 void WorkerProcessHost::DocumentDetached(IPC::Message::Sender* parent, | 424 void WorkerProcessHost::DocumentDetached(IPC::Message::Sender* parent, |
| 410 unsigned long long document_id) | 425 unsigned long long document_id) |
| 411 { | 426 { |
| 412 // Walk all instances and remove the document from their document set. | 427 // Walk all instances and remove the document from their document set. |
| 413 for (Instances::iterator i = instances_.begin(); i != instances_.end();) { | 428 for (Instances::iterator i = instances_.begin(); i != instances_.end();) { |
| 414 if (!i->shared()) { | 429 if (!i->shared()) { |
| 415 ++i; | 430 ++i; |
| 416 } else { | 431 } else { |
| 417 i->RemoveFromDocumentSet(parent, document_id); | 432 i->worker_document_set()->Remove(parent, document_id); |
| 418 if (i->IsDocumentSetEmpty()) { | 433 if (i->worker_document_set()->IsEmpty()) { |
| 419 // This worker has no more associated documents - shut it down. | 434 // This worker has no more associated documents - shut it down. |
| 420 Send(new WorkerMsg_TerminateWorkerContext(i->worker_route_id())); | 435 Send(new WorkerMsg_TerminateWorkerContext(i->worker_route_id())); |
| 421 i = instances_.erase(i); | 436 i = instances_.erase(i); |
| 422 } else { | 437 } else { |
| 423 ++i; | 438 ++i; |
| 424 } | 439 } |
| 425 } | 440 } |
| 426 } | 441 } |
| 427 } | 442 } |
| 428 | 443 |
| 429 WorkerProcessHost::WorkerInstance::WorkerInstance(const GURL& url, | 444 WorkerProcessHost::WorkerInstance::WorkerInstance(const GURL& url, |
| 430 bool shared, | 445 bool shared, |
| 431 bool off_the_record, | 446 bool off_the_record, |
| 432 const string16& name, | 447 const string16& name, |
| 433 int renderer_id, | |
| 434 int render_view_route_id, | |
| 435 int worker_route_id) | 448 int worker_route_id) |
| 436 : url_(url), | 449 : url_(url), |
| 437 shared_(shared), | 450 shared_(shared), |
| 438 off_the_record_(off_the_record), | 451 off_the_record_(off_the_record), |
| 439 closed_(false), | 452 closed_(false), |
| 440 name_(name), | 453 name_(name), |
| 441 renderer_id_(renderer_id), | 454 worker_route_id_(worker_route_id), |
| 442 render_view_route_id_(render_view_route_id), | 455 worker_document_set_(new WorkerDocumentSet()) { |
| 443 worker_route_id_(worker_route_id) { | |
| 444 } | 456 } |
| 445 | 457 |
| 446 // Compares an instance based on the algorithm in the WebWorkers spec - an | 458 // Compares an instance based on the algorithm in the WebWorkers spec - an |
| 447 // instance matches if the origins of the URLs match, and: | 459 // instance matches if the origins of the URLs match, and: |
| 448 // a) the names are non-empty and equal | 460 // a) the names are non-empty and equal |
| 449 // -or- | 461 // -or- |
| 450 // b) the names are both empty, and the urls are equal | 462 // b) the names are both empty, and the urls are equal |
| 451 bool WorkerProcessHost::WorkerInstance::Matches( | 463 bool WorkerProcessHost::WorkerInstance::Matches( |
| 452 const GURL& match_url, const string16& match_name, | 464 const GURL& match_url, const string16& match_name, |
| 453 bool off_the_record) const { | 465 bool off_the_record) const { |
| 454 // Only match open shared workers. | 466 // Only match open shared workers. |
| 455 if (!shared_ || closed_) | 467 if (!shared_ || closed_) |
| 456 return false; | 468 return false; |
| 457 | 469 |
| 458 // Incognito workers don't match non-incognito workers. | 470 // Incognito workers don't match non-incognito workers. |
| 459 if (off_the_record_ != off_the_record) | 471 if (off_the_record_ != off_the_record) |
| 460 return false; | 472 return false; |
| 461 | 473 |
| 462 if (url_.GetOrigin() != match_url.GetOrigin()) | 474 if (url_.GetOrigin() != match_url.GetOrigin()) |
| 463 return false; | 475 return false; |
| 464 | 476 |
| 465 if (name_.empty() && match_name.empty()) | 477 if (name_.empty() && match_name.empty()) |
| 466 return url_ == match_url; | 478 return url_ == match_url; |
| 467 | 479 |
| 468 return name_ == match_name; | 480 return name_ == match_name; |
| 469 } | 481 } |
| 470 | 482 |
| 471 void WorkerProcessHost::WorkerInstance::AddToDocumentSet( | |
| 472 IPC::Message::Sender* parent, unsigned long long document_id) { | |
| 473 if (!IsInDocumentSet(parent, document_id)) { | |
| 474 DocumentInfo info(parent, document_id); | |
| 475 document_set_.push_back(info); | |
| 476 } | |
| 477 } | |
| 478 | |
| 479 bool WorkerProcessHost::WorkerInstance::IsInDocumentSet( | |
| 480 IPC::Message::Sender* parent, unsigned long long document_id) const { | |
| 481 for (DocumentSet::const_iterator i = document_set_.begin(); | |
| 482 i != document_set_.end(); ++i) { | |
| 483 if (i->first == parent && i->second == document_id) | |
| 484 return true; | |
| 485 } | |
| 486 return false; | |
| 487 } | |
| 488 | |
| 489 void WorkerProcessHost::WorkerInstance::RemoveFromDocumentSet( | |
| 490 IPC::Message::Sender* parent, unsigned long long document_id) { | |
| 491 for (DocumentSet::iterator i = document_set_.begin(); | |
| 492 i != document_set_.end(); i++) { | |
| 493 if (i->first == parent && i->second == document_id) { | |
| 494 document_set_.erase(i); | |
| 495 break; | |
| 496 } | |
| 497 } | |
| 498 // Should not be duplicate copies in the document set. | |
| 499 DCHECK(!IsInDocumentSet(parent, document_id)); | |
| 500 } | |
| 501 | |
| 502 void WorkerProcessHost::WorkerInstance::RemoveAllAssociatedDocuments( | |
| 503 IPC::Message::Sender* parent) { | |
| 504 for (DocumentSet::iterator i = document_set_.begin(); | |
| 505 i != document_set_.end();) { | |
| 506 if (i->first == parent) | |
| 507 i = document_set_.erase(i); | |
| 508 else | |
| 509 ++i; | |
| 510 } | |
| 511 } | |
| 512 | |
| 513 void WorkerProcessHost::WorkerInstance::AddSender(IPC::Message::Sender* sender, | 483 void WorkerProcessHost::WorkerInstance::AddSender(IPC::Message::Sender* sender, |
| 514 int sender_route_id) { | 484 int sender_route_id) { |
| 515 if (!HasSender(sender, sender_route_id)) { | 485 if (!HasSender(sender, sender_route_id)) { |
| 516 SenderInfo info(sender, sender_route_id); | 486 SenderInfo info(sender, sender_route_id); |
| 517 senders_.push_back(info); | 487 senders_.push_back(info); |
| 518 } | 488 } |
| 519 // Only shared workers can have more than one associated sender. | 489 // Only shared workers can have more than one associated sender. |
| 520 DCHECK(shared_ || senders_.size() == 1); | 490 DCHECK(shared_ || senders_.size() == 1); |
| 521 } | 491 } |
| 522 | 492 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 545 bool WorkerProcessHost::WorkerInstance::HasSender( | 515 bool WorkerProcessHost::WorkerInstance::HasSender( |
| 546 IPC::Message::Sender* sender, int sender_route_id) const { | 516 IPC::Message::Sender* sender, int sender_route_id) const { |
| 547 for (SenderList::const_iterator i = senders_.begin(); i != senders_.end(); | 517 for (SenderList::const_iterator i = senders_.begin(); i != senders_.end(); |
| 548 ++i) { | 518 ++i) { |
| 549 if (i->first == sender && i->second == sender_route_id) | 519 if (i->first == sender && i->second == sender_route_id) |
| 550 return true; | 520 return true; |
| 551 } | 521 } |
| 552 return false; | 522 return false; |
| 553 } | 523 } |
| 554 | 524 |
| 525 bool WorkerProcessHost::WorkerInstance::RendererIsParent( |
| 526 int renderer_id, int render_view_route_id) const { |
| 527 const WorkerDocumentSet::DocumentInfoSet& parents = |
| 528 worker_document_set()->documents(); |
| 529 for (WorkerDocumentSet::DocumentInfoSet::const_iterator parent_iter = |
| 530 parents.begin(); |
| 531 parent_iter != parents.end(); ++parent_iter) { |
| 532 if (parent_iter->renderer_id() == renderer_id && |
| 533 parent_iter->render_view_route_id() == render_view_route_id) { |
| 534 return true; |
| 535 } |
| 536 } |
| 537 return false; |
| 538 } |
| 539 |
| 555 WorkerProcessHost::WorkerInstance::SenderInfo | 540 WorkerProcessHost::WorkerInstance::SenderInfo |
| 556 WorkerProcessHost::WorkerInstance::GetSender() const { | 541 WorkerProcessHost::WorkerInstance::GetSender() const { |
| 557 DCHECK(NumSenders() == 1); | 542 DCHECK(NumSenders() == 1); |
| 558 return *senders_.begin(); | 543 return *senders_.begin(); |
| 559 } | 544 } |
| OLD | NEW |