| Index: chrome/browser/worker_host/worker_service.cc
|
| diff --git a/chrome/browser/worker_host/worker_service.cc b/chrome/browser/worker_host/worker_service.cc
|
| index ffdbb1d1bb31335f33916b6f71d4897142d4d21b..fda28d49cda70dd1621f06193d331bf53906b0a1 100644
|
| --- a/chrome/browser/worker_host/worker_service.cc
|
| +++ b/chrome/browser/worker_host/worker_service.cc
|
| @@ -67,13 +67,19 @@ bool WorkerService::CreateWorker(const GURL &url,
|
| instance.worker_document_set()->Add(
|
| sender, document_id, renderer_id, render_view_route_id);
|
|
|
| + return CreateWorkerFromInstance(instance);
|
| +}
|
| +
|
| +bool WorkerService::CreateWorkerFromInstance(
|
| + WorkerProcessHost::WorkerInstance instance) {
|
| +
|
| WorkerProcessHost* worker = NULL;
|
| if (CommandLine::ForCurrentProcess()->HasSwitch(
|
| switches::kWebWorkerProcessPerCore)) {
|
| worker = GetProcessToFillUpCores();
|
| } else if (CommandLine::ForCurrentProcess()->HasSwitch(
|
| switches::kWebWorkerShareProcesses)) {
|
| - worker = GetProcessForDomain(url);
|
| + worker = GetProcessForDomain(instance.url());
|
| } else { // One process per worker.
|
| if (!CanCreateWorkerProcess(instance)) {
|
| queued_workers_.push_back(instance);
|
| @@ -83,22 +89,25 @@ bool WorkerService::CreateWorker(const GURL &url,
|
|
|
| // Check to see if this shared worker is already running (two pages may have
|
| // tried to start up the worker simultaneously).
|
| - if (is_shared) {
|
| + if (instance.shared()) {
|
| // See if a worker with this name already exists.
|
| WorkerProcessHost::WorkerInstance* existing_instance =
|
| - FindSharedWorkerInstance(url, name, off_the_record);
|
| + FindSharedWorkerInstance(
|
| + instance.url(), instance.name(), instance.off_the_record());
|
| // If this worker is already running, no need to create a new copy. Just
|
| // inform the caller that the worker has been created.
|
| if (existing_instance) {
|
| // TODO(atwilson): Change this to scan the sender list (crbug.com/29243).
|
| - existing_instance->AddSender(sender, sender_route_id);
|
| - sender->Send(new ViewMsg_WorkerCreated(sender_route_id));
|
| + WorkerProcessHost::WorkerInstance::SenderInfo sender_info =
|
| + instance.GetSender();
|
| + existing_instance->AddSender(sender_info.first, sender_info.second);
|
| + sender_info.first->Send(new ViewMsg_WorkerCreated(sender_info.second));
|
| return true;
|
| }
|
|
|
| // Look to see if there's a pending instance.
|
| WorkerProcessHost::WorkerInstance* pending = FindPendingInstance(
|
| - url, name, off_the_record);
|
| + instance.url(), instance.name(), instance.off_the_record());
|
| // If there's no instance *and* no pending instance, then it means the
|
| // worker started up and exited already. Log a warning because this should
|
| // be a very rare occurrence and is probably a bug, but it *can* happen so
|
| @@ -112,7 +121,24 @@ bool WorkerService::CreateWorker(const GURL &url,
|
| // worker to the new instance.
|
| DCHECK(!pending->worker_document_set()->IsEmpty());
|
| instance.ShareDocumentSet(*pending);
|
| - RemovePendingInstance(url, name, off_the_record);
|
| + RemovePendingInstances(
|
| + instance.url(), instance.name(), instance.off_the_record());
|
| +
|
| + // Remove any queued instances of this worker and copy over the sender to
|
| + // this instance.
|
| + for (WorkerProcessHost::Instances::iterator iter = queued_workers_.begin();
|
| + iter != queued_workers_.end();) {
|
| + if (iter->Matches(instance.url(), instance.name(),
|
| + instance.off_the_record())) {
|
| + DCHECK(iter->NumSenders() == 1);
|
| + WorkerProcessHost::WorkerInstance::SenderInfo sender_info =
|
| + iter->GetSender();
|
| + instance.AddSender(sender_info.first, sender_info.second);
|
| + iter = queued_workers_.erase(iter);
|
| + } else {
|
| + ++iter;
|
| + }
|
| + }
|
| }
|
|
|
| if (!worker) {
|
| @@ -403,15 +429,16 @@ void WorkerService::WorkerProcessDestroyed(WorkerProcessHost* process) {
|
| for (WorkerProcessHost::Instances::iterator i = queued_workers_.begin();
|
| i != queued_workers_.end();) {
|
| if (CanCreateWorkerProcess(*i)) {
|
| - WorkerProcessHost* worker =
|
| - new WorkerProcessHost(resource_dispatcher_host_);
|
| - if (!worker->Init()) {
|
| - delete worker;
|
| - return;
|
| - }
|
| -
|
| - worker->CreateWorker(*i);
|
| - i = queued_workers_.erase(i);
|
| + WorkerProcessHost::WorkerInstance instance = *i;
|
| + queued_workers_.erase(i);
|
| + CreateWorkerFromInstance(instance);
|
| +
|
| + // CreateWorkerFromInstance can modify the queued_workers_ list when it
|
| + // coalesces queued instances after starting a shared worker, so we
|
| + // have to rescan the list from the beginning (our iterator is now
|
| + // invalid). This is not a big deal as having any queued workers will be
|
| + // rare in practice so the list will be small.
|
| + i = queued_workers_.begin();
|
| } else {
|
| ++i;
|
| }
|
| @@ -466,17 +493,20 @@ WorkerService::FindPendingInstance(const GURL& url, const string16& name,
|
| }
|
|
|
|
|
| -void WorkerService::RemovePendingInstance(const GURL& url,
|
| - const string16& name,
|
| - bool off_the_record) {
|
| +void WorkerService::RemovePendingInstances(const GURL& url,
|
| + const string16& name,
|
| + bool off_the_record) {
|
| // Walk the pending instances looking for a matching pending worker.
|
| for (WorkerProcessHost::Instances::iterator iter =
|
| pending_shared_workers_.begin();
|
| - iter != pending_shared_workers_.end();
|
| - ++iter) {
|
| + iter != pending_shared_workers_.end(); ) {
|
| + // Pending workers should have no senders - only actively running worker
|
| + // instances have senders.
|
| + DCHECK(iter->NumSenders() == 0);
|
| if (iter->Matches(url, name, off_the_record)) {
|
| - pending_shared_workers_.erase(iter);
|
| - break;
|
| + iter = pending_shared_workers_.erase(iter);
|
| + } else {
|
| + ++iter;
|
| }
|
| }
|
| }
|
|
|