| 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_service.h" | 5 #include "chrome/browser/worker_host/worker_service.h" |
| 6 | 6 |
| 7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
| 8 #include "base/singleton.h" | 8 #include "base/singleton.h" |
| 9 #include "base/sys_info.h" | 9 #include "base/sys_info.h" |
| 10 #include "base/thread.h" | 10 #include "base/thread.h" |
| (...skipping 29 matching lines...) Expand all Loading... |
| 40 | 40 |
| 41 void WorkerService::Initialize(ResourceDispatcherHost* rdh) { | 41 void WorkerService::Initialize(ResourceDispatcherHost* rdh) { |
| 42 resource_dispatcher_host_ = rdh; | 42 resource_dispatcher_host_ = rdh; |
| 43 } | 43 } |
| 44 | 44 |
| 45 WorkerService::~WorkerService() { | 45 WorkerService::~WorkerService() { |
| 46 } | 46 } |
| 47 | 47 |
| 48 bool WorkerService::CreateWorker(const GURL &url, | 48 bool WorkerService::CreateWorker(const GURL &url, |
| 49 bool is_shared, | 49 bool is_shared, |
| 50 bool off_the_record, |
| 50 const string16& name, | 51 const string16& name, |
| 51 int renderer_id, | 52 int renderer_id, |
| 52 int render_view_route_id, | 53 int render_view_route_id, |
| 53 IPC::Message::Sender* sender, | 54 IPC::Message::Sender* sender, |
| 54 int sender_route_id) { | 55 int sender_route_id) { |
| 55 // Generate a unique route id for the browser-worker communication that's | 56 // Generate a unique route id for the browser-worker communication that's |
| 56 // unique among all worker processes. That way when the worker process sends | 57 // unique among all worker processes. That way when the worker process sends |
| 57 // a wrapped IPC message through us, we know which WorkerProcessHost to give | 58 // a wrapped IPC message through us, we know which WorkerProcessHost to give |
| 58 // it to. | 59 // it to. |
| 59 WorkerProcessHost::WorkerInstance instance(url, | 60 WorkerProcessHost::WorkerInstance instance(url, |
| 60 is_shared, | 61 is_shared, |
| 62 off_the_record, |
| 61 name, | 63 name, |
| 62 renderer_id, | 64 renderer_id, |
| 63 render_view_route_id, | 65 render_view_route_id, |
| 64 next_worker_route_id()); | 66 next_worker_route_id()); |
| 65 instance.AddSender(sender, sender_route_id); | 67 instance.AddSender(sender, sender_route_id); |
| 66 | 68 |
| 67 WorkerProcessHost* worker = NULL; | 69 WorkerProcessHost* worker = NULL; |
| 68 if (CommandLine::ForCurrentProcess()->HasSwitch( | 70 if (CommandLine::ForCurrentProcess()->HasSwitch( |
| 69 switches::kWebWorkerProcessPerCore)) { | 71 switches::kWebWorkerProcessPerCore)) { |
| 70 worker = GetProcessToFillUpCores(); | 72 worker = GetProcessToFillUpCores(); |
| 71 } else if (CommandLine::ForCurrentProcess()->HasSwitch( | 73 } else if (CommandLine::ForCurrentProcess()->HasSwitch( |
| 72 switches::kWebWorkerShareProcesses)) { | 74 switches::kWebWorkerShareProcesses)) { |
| 73 worker = GetProcessForDomain(url); | 75 worker = GetProcessForDomain(url); |
| 74 } else { // One process per worker. | 76 } else { // One process per worker. |
| 75 if (!CanCreateWorkerProcess(instance)) { | 77 if (!CanCreateWorkerProcess(instance)) { |
| 76 queued_workers_.push_back(instance); | 78 queued_workers_.push_back(instance); |
| 77 return true; | 79 return true; |
| 78 } | 80 } |
| 79 } | 81 } |
| 80 | 82 |
| 81 // Check to see if this shared worker is already running (two pages may have | 83 // Check to see if this shared worker is already running (two pages may have |
| 82 // tried to start up the worker simultaneously). | 84 // tried to start up the worker simultaneously). |
| 83 if (is_shared) { | 85 if (is_shared) { |
| 84 // See if a worker with this name already exists. | 86 // See if a worker with this name already exists. |
| 85 WorkerProcessHost::WorkerInstance* existing_instance = | 87 WorkerProcessHost::WorkerInstance* existing_instance = |
| 86 FindSharedWorkerInstance(url, name); | 88 FindSharedWorkerInstance(url, name, off_the_record); |
| 87 // If this worker is already running, no need to create a new copy. Just | 89 // If this worker is already running, no need to create a new copy. Just |
| 88 // inform the caller that the worker has been created. | 90 // inform the caller that the worker has been created. |
| 89 if (existing_instance) { | 91 if (existing_instance) { |
| 90 existing_instance->AddSender(sender, sender_route_id); | 92 existing_instance->AddSender(sender, sender_route_id); |
| 91 sender->Send(new ViewMsg_WorkerCreated(sender_route_id)); | 93 sender->Send(new ViewMsg_WorkerCreated(sender_route_id)); |
| 92 return true; | 94 return true; |
| 93 } | 95 } |
| 94 | 96 |
| 95 // Look to see if there's a pending instance. | 97 // Look to see if there's a pending instance. |
| 96 WorkerProcessHost::WorkerInstance* pending = FindPendingInstance(url, name); | 98 WorkerProcessHost::WorkerInstance* pending = FindPendingInstance( |
| 99 url, name, off_the_record); |
| 97 // If there's no instance *and* no pending instance, then it means the | 100 // If there's no instance *and* no pending instance, then it means the |
| 98 // worker started up and exited already. Log a warning because this should | 101 // worker started up and exited already. Log a warning because this should |
| 99 // be a very rare occurrence and is probably a bug, but it *can* happen so | 102 // be a very rare occurrence and is probably a bug, but it *can* happen so |
| 100 // handle it gracefully. | 103 // handle it gracefully. |
| 101 if (!pending) { | 104 if (!pending) { |
| 102 DLOG(WARNING) << "Pending worker already exited"; | 105 DLOG(WARNING) << "Pending worker already exited"; |
| 103 return false; | 106 return false; |
| 104 } | 107 } |
| 105 | 108 |
| 106 // Assign the accumulated document set and sender list for this pending | 109 // Assign the accumulated document set and sender list for this pending |
| 107 // worker to the new instance. | 110 // worker to the new instance. |
| 108 DCHECK(!pending->IsDocumentSetEmpty()); | 111 DCHECK(!pending->IsDocumentSetEmpty()); |
| 109 instance.CopyDocumentSet(*pending); | 112 instance.CopyDocumentSet(*pending); |
| 110 RemovePendingInstance(url, name); | 113 RemovePendingInstance(url, name, off_the_record); |
| 111 } | 114 } |
| 112 | 115 |
| 113 if (!worker) { | 116 if (!worker) { |
| 114 worker = new WorkerProcessHost(resource_dispatcher_host_); | 117 worker = new WorkerProcessHost(resource_dispatcher_host_); |
| 115 if (!worker->Init()) { | 118 if (!worker->Init()) { |
| 116 delete worker; | 119 delete worker; |
| 117 return false; | 120 return false; |
| 118 } | 121 } |
| 119 } | 122 } |
| 120 | 123 |
| 121 worker->CreateWorker(instance); | 124 worker->CreateWorker(instance); |
| 122 return true; | 125 return true; |
| 123 } | 126 } |
| 124 | 127 |
| 125 bool WorkerService::LookupSharedWorker(const GURL &url, | 128 bool WorkerService::LookupSharedWorker(const GURL &url, |
| 126 const string16& name, | 129 const string16& name, |
| 130 bool off_the_record, |
| 127 unsigned long long document_id, | 131 unsigned long long document_id, |
| 128 IPC::Message::Sender* sender, | 132 IPC::Message::Sender* sender, |
| 129 int sender_route_id, | 133 int sender_route_id, |
| 130 bool* url_mismatch) { | 134 bool* url_mismatch) { |
| 131 bool found_instance = true; | 135 bool found_instance = true; |
| 132 WorkerProcessHost::WorkerInstance* instance = | 136 WorkerProcessHost::WorkerInstance* instance = |
| 133 FindSharedWorkerInstance(url, name); | 137 FindSharedWorkerInstance(url, name, off_the_record); |
| 134 | 138 |
| 135 if (!instance) { | 139 if (!instance) { |
| 136 // If no worker instance currently exists, we need to create a pending | 140 // If no worker instance currently exists, we need to create a pending |
| 137 // instance - this is to make sure that any subsequent lookups passing a | 141 // instance - this is to make sure that any subsequent lookups passing a |
| 138 // mismatched URL get the appropriate url_mismatch error at lookup time. | 142 // mismatched URL get the appropriate url_mismatch error at lookup time. |
| 139 // Having named shared workers was a Really Bad Idea due to details like | 143 // Having named shared workers was a Really Bad Idea due to details like |
| 140 // this. | 144 // this. |
| 141 instance = CreatePendingInstance(url, name); | 145 instance = CreatePendingInstance(url, name, off_the_record); |
| 142 found_instance = false; | 146 found_instance = false; |
| 143 } | 147 } |
| 144 | 148 |
| 145 // Make sure the passed-in instance matches the URL - if not, return an | 149 // Make sure the passed-in instance matches the URL - if not, return an |
| 146 // error. | 150 // error. |
| 147 if (url != instance->url()) { | 151 if (url != instance->url()) { |
| 148 *url_mismatch = true; | 152 *url_mismatch = true; |
| 149 return false; | 153 return false; |
| 150 } else { | 154 } else { |
| 151 *url_mismatch = false; | 155 *url_mismatch = false; |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 | 395 |
| 392 WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); | 396 WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); |
| 393 WorkerProcessHost::Instances::const_iterator instance = | 397 WorkerProcessHost::Instances::const_iterator instance = |
| 394 worker->instances().begin(); | 398 worker->instances().begin(); |
| 395 return instance == worker->instances().end() ? NULL : &*instance; | 399 return instance == worker->instances().end() ? NULL : &*instance; |
| 396 } | 400 } |
| 397 return NULL; | 401 return NULL; |
| 398 } | 402 } |
| 399 | 403 |
| 400 WorkerProcessHost::WorkerInstance* | 404 WorkerProcessHost::WorkerInstance* |
| 401 WorkerService::FindSharedWorkerInstance(const GURL& url, const string16& name) { | 405 WorkerService::FindSharedWorkerInstance(const GURL& url, const string16& name, |
| 406 bool off_the_record) { |
| 402 for (ChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); | 407 for (ChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); |
| 403 !iter.Done(); ++iter) { | 408 !iter.Done(); ++iter) { |
| 404 WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); | 409 WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); |
| 405 for (WorkerProcessHost::Instances::iterator instance_iter = | 410 for (WorkerProcessHost::Instances::iterator instance_iter = |
| 406 worker->mutable_instances().begin(); | 411 worker->mutable_instances().begin(); |
| 407 instance_iter != worker->mutable_instances().end(); | 412 instance_iter != worker->mutable_instances().end(); |
| 408 ++instance_iter) { | 413 ++instance_iter) { |
| 409 if (instance_iter->Matches(url, name)) | 414 if (instance_iter->Matches(url, name, off_the_record)) |
| 410 return &(*instance_iter); | 415 return &(*instance_iter); |
| 411 } | 416 } |
| 412 } | 417 } |
| 413 return NULL; | 418 return NULL; |
| 414 } | 419 } |
| 415 | 420 |
| 416 WorkerProcessHost::WorkerInstance* | 421 WorkerProcessHost::WorkerInstance* |
| 417 WorkerService::FindPendingInstance(const GURL& url, const string16& name) { | 422 WorkerService::FindPendingInstance(const GURL& url, const string16& name, |
| 423 bool off_the_record) { |
| 418 // Walk the pending instances looking for a matching pending worker. | 424 // Walk the pending instances looking for a matching pending worker. |
| 419 for (WorkerProcessHost::Instances::iterator iter = | 425 for (WorkerProcessHost::Instances::iterator iter = |
| 420 pending_shared_workers_.begin(); | 426 pending_shared_workers_.begin(); |
| 421 iter != pending_shared_workers_.end(); | 427 iter != pending_shared_workers_.end(); |
| 422 ++iter) { | 428 ++iter) { |
| 423 if (iter->Matches(url, name)) { | 429 if (iter->Matches(url, name, off_the_record)) { |
| 424 return &(*iter); | 430 return &(*iter); |
| 425 } | 431 } |
| 426 } | 432 } |
| 427 return NULL; | 433 return NULL; |
| 428 } | 434 } |
| 429 | 435 |
| 430 | 436 |
| 431 void WorkerService::RemovePendingInstance(const GURL& url, | 437 void WorkerService::RemovePendingInstance(const GURL& url, |
| 432 const string16& name) { | 438 const string16& name, |
| 439 bool off_the_record) { |
| 433 // Walk the pending instances looking for a matching pending worker. | 440 // Walk the pending instances looking for a matching pending worker. |
| 434 for (WorkerProcessHost::Instances::iterator iter = | 441 for (WorkerProcessHost::Instances::iterator iter = |
| 435 pending_shared_workers_.begin(); | 442 pending_shared_workers_.begin(); |
| 436 iter != pending_shared_workers_.end(); | 443 iter != pending_shared_workers_.end(); |
| 437 ++iter) { | 444 ++iter) { |
| 438 if (iter->Matches(url, name)) { | 445 if (iter->Matches(url, name, off_the_record)) { |
| 439 pending_shared_workers_.erase(iter); | 446 pending_shared_workers_.erase(iter); |
| 440 break; | 447 break; |
| 441 } | 448 } |
| 442 } | 449 } |
| 443 } | 450 } |
| 444 | 451 |
| 445 WorkerProcessHost::WorkerInstance* | 452 WorkerProcessHost::WorkerInstance* |
| 446 WorkerService::CreatePendingInstance(const GURL& url, | 453 WorkerService::CreatePendingInstance(const GURL& url, |
| 447 const string16& name) { | 454 const string16& name, |
| 455 bool off_the_record) { |
| 448 // Look for an existing pending worker. | 456 // Look for an existing pending worker. |
| 449 WorkerProcessHost::WorkerInstance* instance = | 457 WorkerProcessHost::WorkerInstance* instance = |
| 450 FindPendingInstance(url, name); | 458 FindPendingInstance(url, name, off_the_record); |
| 451 if (instance) | 459 if (instance) |
| 452 return instance; | 460 return instance; |
| 453 | 461 |
| 454 // No existing pending worker - create a new one. | 462 // No existing pending worker - create a new one. |
| 455 WorkerProcessHost::WorkerInstance pending( | 463 WorkerProcessHost::WorkerInstance pending( |
| 456 url, true, name, 0, MSG_ROUTING_NONE, MSG_ROUTING_NONE); | 464 url, true, off_the_record, name, 0, MSG_ROUTING_NONE, MSG_ROUTING_NONE); |
| 457 pending_shared_workers_.push_back(pending); | 465 pending_shared_workers_.push_back(pending); |
| 458 return &pending_shared_workers_.back(); | 466 return &pending_shared_workers_.back(); |
| 459 } | 467 } |
| OLD | NEW |