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 fe768c31a5d3f3daca480350b04e8e705561d88e..ffdbb1d1bb31335f33916b6f71d4897142d4d21b 100644 |
--- a/chrome/browser/worker_host/worker_service.cc |
+++ b/chrome/browser/worker_host/worker_service.cc |
@@ -49,6 +49,7 @@ bool WorkerService::CreateWorker(const GURL &url, |
bool is_shared, |
bool off_the_record, |
const string16& name, |
+ unsigned long long document_id, |
int renderer_id, |
int render_view_route_id, |
IPC::Message::Sender* sender, |
@@ -61,10 +62,10 @@ bool WorkerService::CreateWorker(const GURL &url, |
is_shared, |
off_the_record, |
name, |
- renderer_id, |
- render_view_route_id, |
next_worker_route_id()); |
instance.AddSender(sender, sender_route_id); |
+ instance.worker_document_set()->Add( |
+ sender, document_id, renderer_id, render_view_route_id); |
WorkerProcessHost* worker = NULL; |
if (CommandLine::ForCurrentProcess()->HasSwitch( |
@@ -89,6 +90,7 @@ bool WorkerService::CreateWorker(const GURL &url, |
// 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)); |
return true; |
@@ -108,8 +110,8 @@ bool WorkerService::CreateWorker(const GURL &url, |
// Assign the accumulated document set and sender list for this pending |
// worker to the new instance. |
- DCHECK(!pending->IsDocumentSetEmpty()); |
- instance.CopyDocumentSet(*pending); |
+ DCHECK(!pending->worker_document_set()->IsEmpty()); |
+ instance.ShareDocumentSet(*pending); |
RemovePendingInstance(url, name, off_the_record); |
} |
@@ -129,6 +131,8 @@ bool WorkerService::LookupSharedWorker(const GURL &url, |
const string16& name, |
bool off_the_record, |
unsigned long long document_id, |
+ int renderer_id, |
+ int render_view_route_id, |
IPC::Message::Sender* sender, |
int sender_route_id, |
bool* url_mismatch) { |
@@ -160,7 +164,8 @@ bool WorkerService::LookupSharedWorker(const GURL &url, |
instance->AddSender(sender, sender_route_id); |
// Add the passed sender/document_id to the worker instance. |
- instance->AddToDocumentSet(sender, document_id); |
+ instance->worker_document_set()->Add( |
+ sender, document_id, renderer_id, render_view_route_id); |
return found_instance; |
} |
@@ -176,8 +181,8 @@ void WorkerService::DocumentDetached(IPC::Message::Sender* sender, |
for (WorkerProcessHost::Instances::iterator iter = queued_workers_.begin(); |
iter != queued_workers_.end();) { |
if (iter->shared()) { |
- iter->RemoveFromDocumentSet(sender, document_id); |
- if (iter->IsDocumentSetEmpty()) { |
+ iter->worker_document_set()->Remove(sender, document_id); |
+ if (iter->worker_document_set()->IsEmpty()) { |
iter = queued_workers_.erase(iter); |
continue; |
} |
@@ -189,8 +194,8 @@ void WorkerService::DocumentDetached(IPC::Message::Sender* sender, |
for (WorkerProcessHost::Instances::iterator iter = |
pending_shared_workers_.begin(); |
iter != pending_shared_workers_.end(); ) { |
- iter->RemoveFromDocumentSet(sender, document_id); |
- if (iter->IsDocumentSetEmpty()) { |
+ iter->worker_document_set()->Remove(sender, document_id); |
+ if (iter->worker_document_set()->IsEmpty()) { |
iter = pending_shared_workers_.erase(iter); |
} else { |
++iter; |
@@ -294,8 +299,35 @@ WorkerProcessHost* WorkerService::GetLeastLoadedWorker() { |
bool WorkerService::CanCreateWorkerProcess( |
const WorkerProcessHost::WorkerInstance& instance) { |
+ // Worker can be fired off if *any* parent has room. |
+ const WorkerDocumentSet::DocumentInfoSet& parents = |
+ instance.worker_document_set()->documents(); |
+ |
+ for (WorkerDocumentSet::DocumentInfoSet::const_iterator parent_iter = |
+ parents.begin(); |
+ parent_iter != parents.end(); ++parent_iter) { |
+ bool hit_total_worker_limit = false; |
+ if (TabCanCreateWorkerProcess(parent_iter->renderer_id(), |
+ parent_iter->render_view_route_id(), |
+ &hit_total_worker_limit)) { |
+ return true; |
+ } |
+ // Return false if already at the global worker limit (no need to continue |
+ // checking parent tabs). |
+ if (hit_total_worker_limit) |
+ return false; |
+ } |
+ // If we've reached here, none of the parent tabs is allowed to create an |
+ // instance. |
+ return false; |
+} |
+ |
+bool WorkerService::TabCanCreateWorkerProcess(int renderer_id, |
+ int render_view_route_id, |
+ bool* hit_total_worker_limit) { |
int total_workers = 0; |
int workers_per_tab = 0; |
+ *hit_total_worker_limit = false; |
for (ChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); |
!iter.Done(); ++iter) { |
WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); |
@@ -303,11 +335,11 @@ bool WorkerService::CanCreateWorkerProcess( |
worker->instances().begin(); |
cur_instance != worker->instances().end(); ++cur_instance) { |
total_workers++; |
- if (total_workers >= kMaxWorkersWhenSeparate) |
+ if (total_workers >= kMaxWorkersWhenSeparate) { |
+ *hit_total_worker_limit = true; |
return false; |
- if (cur_instance->renderer_id() == instance.renderer_id() && |
- cur_instance->render_view_route_id() == |
- instance.render_view_route_id()) { |
+ } |
+ if (cur_instance->RendererIsParent(renderer_id, render_view_route_id)) { |
workers_per_tab++; |
if (workers_per_tab >= kMaxWorkersPerTabWhenSeparate) |
return false; |
@@ -355,8 +387,8 @@ void WorkerService::SenderShutdown(IPC::Message::Sender* sender) { |
for (WorkerProcessHost::Instances::iterator iter = |
pending_shared_workers_.begin(); |
iter != pending_shared_workers_.end(); ) { |
- iter->RemoveAllAssociatedDocuments(sender); |
- if (iter->IsDocumentSetEmpty()) { |
+ iter->worker_document_set()->RemoveAll(sender); |
+ if (iter->worker_document_set()->IsEmpty()) { |
iter = pending_shared_workers_.erase(iter); |
} else { |
++iter; |
@@ -461,7 +493,7 @@ WorkerService::CreatePendingInstance(const GURL& url, |
// No existing pending worker - create a new one. |
WorkerProcessHost::WorkerInstance pending( |
- url, true, off_the_record, name, 0, MSG_ROUTING_NONE, MSG_ROUTING_NONE); |
+ url, true, off_the_record, name, MSG_ROUTING_NONE); |
pending_shared_workers_.push_back(pending); |
return &pending_shared_workers_.back(); |
} |