| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 "content/browser/worker_host/worker_service.h" | 5 #include "content/browser/worker_host/worker_service_impl.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 10 #include "base/logging.h" | 10 #include "base/logging.h" |
| 11 #include "base/sys_info.h" | 11 #include "base/sys_info.h" |
| 12 #include "base/threading/thread.h" | 12 #include "base/threading/thread.h" |
| 13 #include "content/browser/resource_context.h" | 13 #include "content/browser/resource_context.h" |
| 14 #include "content/browser/worker_host/worker_message_filter.h" | 14 #include "content/browser/worker_host/worker_message_filter.h" |
| 15 #include "content/browser/worker_host/worker_process_host.h" | 15 #include "content/browser/worker_host/worker_process_host.h" |
| 16 #include "content/browser/worker_host/worker_service_observer.h" | |
| 17 #include "content/common/view_messages.h" | 16 #include "content/common/view_messages.h" |
| 18 #include "content/common/worker_messages.h" | 17 #include "content/common/worker_messages.h" |
| 18 #include "content/public/browser/worker_service_observer.h" |
| 19 #include "content/public/common/content_switches.h" | 19 #include "content/public/common/content_switches.h" |
| 20 #include "content/public/common/process_type.h" | 20 #include "content/public/common/process_type.h" |
| 21 #include "net/base/registry_controlled_domain.h" | 21 #include "net/base/registry_controlled_domain.h" |
| 22 | 22 |
| 23 using content::BrowserThread; | 23 namespace content { |
| 24 | 24 |
| 25 const int WorkerService::kMaxWorkerProcessesWhenSharing = 10; | 25 const int WorkerServiceImpl::kMaxWorkerProcessesWhenSharing = 10; |
| 26 const int WorkerService::kMaxWorkersWhenSeparate = 64; | 26 const int WorkerServiceImpl::kMaxWorkersWhenSeparate = 64; |
| 27 const int WorkerService::kMaxWorkersPerTabWhenSeparate = 16; | 27 const int WorkerServiceImpl::kMaxWorkersPerTabWhenSeparate = 16; |
| 28 | 28 |
| 29 WorkerService* WorkerService::GetInstance() { | 29 WorkerService* WorkerService::GetInstance() { |
| 30 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 30 return WorkerServiceImpl::GetInstance(); |
| 31 return Singleton<WorkerService>::get(); | |
| 32 } | 31 } |
| 33 | 32 |
| 34 WorkerService::WorkerService() : next_worker_route_id_(0) { | 33 WorkerServiceImpl* WorkerServiceImpl::GetInstance() { |
| 34 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 35 return Singleton<WorkerServiceImpl>::get(); |
| 35 } | 36 } |
| 36 | 37 |
| 37 WorkerService::~WorkerService() { | 38 WorkerServiceImpl::WorkerServiceImpl() : next_worker_route_id_(0) { |
| 39 } |
| 40 |
| 41 WorkerServiceImpl::~WorkerServiceImpl() { |
| 38 // The observers in observers_ can't be used here because they might be | 42 // The observers in observers_ can't be used here because they might be |
| 39 // gone already. | 43 // gone already. |
| 40 } | 44 } |
| 41 | 45 |
| 42 void WorkerService::OnWorkerMessageFilterClosing(WorkerMessageFilter* filter) { | 46 void WorkerServiceImpl::OnWorkerMessageFilterClosing( |
| 47 WorkerMessageFilter* filter) { |
| 43 for (BrowserChildProcessHost::Iterator iter(content::PROCESS_TYPE_WORKER); | 48 for (BrowserChildProcessHost::Iterator iter(content::PROCESS_TYPE_WORKER); |
| 44 !iter.Done(); ++iter) { | 49 !iter.Done(); ++iter) { |
| 45 WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); | 50 WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); |
| 46 worker->FilterShutdown(filter); | 51 worker->FilterShutdown(filter); |
| 47 } | 52 } |
| 48 | 53 |
| 49 // See if that process had any queued workers. | 54 // See if that process had any queued workers. |
| 50 for (WorkerProcessHost::Instances::iterator i = queued_workers_.begin(); | 55 for (WorkerProcessHost::Instances::iterator i = queued_workers_.begin(); |
| 51 i != queued_workers_.end();) { | 56 i != queued_workers_.end();) { |
| 52 i->RemoveFilters(filter); | 57 i->RemoveFilters(filter); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 69 } | 74 } |
| 70 } | 75 } |
| 71 | 76 |
| 72 // Either a worker proceess has shut down, in which case we can start one of | 77 // Either a worker proceess has shut down, in which case we can start one of |
| 73 // the queued workers, or a renderer has shut down, in which case it doesn't | 78 // the queued workers, or a renderer has shut down, in which case it doesn't |
| 74 // affect anything. We call this function in both scenarios because then we | 79 // affect anything. We call this function in both scenarios because then we |
| 75 // don't have to keep track which filters are from worker processes. | 80 // don't have to keep track which filters are from worker processes. |
| 76 TryStartingQueuedWorker(); | 81 TryStartingQueuedWorker(); |
| 77 } | 82 } |
| 78 | 83 |
| 79 void WorkerService::CreateWorker( | 84 void WorkerServiceImpl::CreateWorker( |
| 80 const ViewHostMsg_CreateWorker_Params& params, | 85 const ViewHostMsg_CreateWorker_Params& params, |
| 81 int route_id, | 86 int route_id, |
| 82 WorkerMessageFilter* filter, | 87 WorkerMessageFilter* filter, |
| 83 const content::ResourceContext& resource_context) { | 88 const content::ResourceContext& resource_context) { |
| 84 // Generate a unique route id for the browser-worker communication that's | 89 // Generate a unique route id for the browser-worker communication that's |
| 85 // unique among all worker processes. That way when the worker process sends | 90 // unique among all worker processes. That way when the worker process sends |
| 86 // a wrapped IPC message through us, we know which WorkerProcessHost to give | 91 // a wrapped IPC message through us, we know which WorkerProcessHost to give |
| 87 // it to. | 92 // it to. |
| 88 WorkerProcessHost::WorkerInstance instance( | 93 WorkerProcessHost::WorkerInstance instance( |
| 89 params.url, | 94 params.url, |
| 90 params.name, | 95 params.name, |
| 91 next_worker_route_id(), | 96 next_worker_route_id(), |
| 92 0, | 97 0, |
| 93 params.script_resource_appcache_id, | 98 params.script_resource_appcache_id, |
| 94 &resource_context); | 99 &resource_context); |
| 95 instance.AddFilter(filter, route_id); | 100 instance.AddFilter(filter, route_id); |
| 96 instance.worker_document_set()->Add( | 101 instance.worker_document_set()->Add( |
| 97 filter, params.document_id, filter->render_process_id(), | 102 filter, params.document_id, filter->render_process_id(), |
| 98 params.render_view_route_id); | 103 params.render_view_route_id); |
| 99 | 104 |
| 100 CreateWorkerFromInstance(instance); | 105 CreateWorkerFromInstance(instance); |
| 101 } | 106 } |
| 102 | 107 |
| 103 void WorkerService::LookupSharedWorker( | 108 void WorkerServiceImpl::LookupSharedWorker( |
| 104 const ViewHostMsg_CreateWorker_Params& params, | 109 const ViewHostMsg_CreateWorker_Params& params, |
| 105 int route_id, | 110 int route_id, |
| 106 WorkerMessageFilter* filter, | 111 WorkerMessageFilter* filter, |
| 107 const content::ResourceContext* resource_context, | 112 const content::ResourceContext* resource_context, |
| 108 bool* exists, | 113 bool* exists, |
| 109 bool* url_mismatch) { | 114 bool* url_mismatch) { |
| 110 *exists = true; | 115 *exists = true; |
| 111 WorkerProcessHost::WorkerInstance* instance = FindSharedWorkerInstance( | 116 WorkerProcessHost::WorkerInstance* instance = FindSharedWorkerInstance( |
| 112 params.url, params.name, resource_context); | 117 params.url, params.name, resource_context); |
| 113 | 118 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 135 // TODO(atwilson): This won't work if the message is from a worker process. | 140 // TODO(atwilson): This won't work if the message is from a worker process. |
| 136 // We don't support that yet though (this message is only sent from | 141 // We don't support that yet though (this message is only sent from |
| 137 // renderers) but when we do, we'll need to add code to pass in the current | 142 // renderers) but when we do, we'll need to add code to pass in the current |
| 138 // worker's document set for nested workers. | 143 // worker's document set for nested workers. |
| 139 instance->worker_document_set()->Add( | 144 instance->worker_document_set()->Add( |
| 140 filter, params.document_id, filter->render_process_id(), | 145 filter, params.document_id, filter->render_process_id(), |
| 141 params.render_view_route_id); | 146 params.render_view_route_id); |
| 142 } | 147 } |
| 143 } | 148 } |
| 144 | 149 |
| 145 void WorkerService::CancelCreateDedicatedWorker( | 150 void WorkerServiceImpl::CancelCreateDedicatedWorker( |
| 146 int route_id, | 151 int route_id, |
| 147 WorkerMessageFilter* filter) { | 152 WorkerMessageFilter* filter) { |
| 148 | 153 |
| 149 NOTREACHED(); | 154 NOTREACHED(); |
| 150 } | 155 } |
| 151 | 156 |
| 152 void WorkerService::ForwardToWorker(const IPC::Message& message, | 157 void WorkerServiceImpl::ForwardToWorker(const IPC::Message& message, |
| 153 WorkerMessageFilter* filter) { | 158 WorkerMessageFilter* filter) { |
| 154 for (BrowserChildProcessHost::Iterator iter(content::PROCESS_TYPE_WORKER); | 159 for (BrowserChildProcessHost::Iterator iter(content::PROCESS_TYPE_WORKER); |
| 155 !iter.Done(); ++iter) { | 160 !iter.Done(); ++iter) { |
| 156 WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); | 161 WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); |
| 157 if (worker->FilterMessage(message, filter)) | 162 if (worker->FilterMessage(message, filter)) |
| 158 return; | 163 return; |
| 159 } | 164 } |
| 160 | 165 |
| 161 // TODO(jabdelmalek): tell filter that callee is gone | 166 // TODO(jabdelmalek): tell filter that callee is gone |
| 162 } | 167 } |
| 163 | 168 |
| 164 void WorkerService::DocumentDetached(unsigned long long document_id, | 169 void WorkerServiceImpl::DocumentDetached(unsigned long long document_id, |
| 165 WorkerMessageFilter* filter) { | 170 WorkerMessageFilter* filter) { |
| 166 // Any associated shared workers can be shut down. | 171 // Any associated shared workers can be shut down. |
| 167 for (BrowserChildProcessHost::Iterator iter(content::PROCESS_TYPE_WORKER); | 172 for (BrowserChildProcessHost::Iterator iter(content::PROCESS_TYPE_WORKER); |
| 168 !iter.Done(); ++iter) { | 173 !iter.Done(); ++iter) { |
| 169 WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); | 174 WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); |
| 170 worker->DocumentDetached(filter, document_id); | 175 worker->DocumentDetached(filter, document_id); |
| 171 } | 176 } |
| 172 | 177 |
| 173 // Remove any queued shared workers for this document. | 178 // Remove any queued shared workers for this document. |
| 174 for (WorkerProcessHost::Instances::iterator iter = queued_workers_.begin(); | 179 for (WorkerProcessHost::Instances::iterator iter = queued_workers_.begin(); |
| 175 iter != queued_workers_.end();) { | 180 iter != queued_workers_.end();) { |
| (...skipping 12 matching lines...) Expand all Loading... |
| 188 iter != pending_shared_workers_.end(); ) { | 193 iter != pending_shared_workers_.end(); ) { |
| 189 iter->worker_document_set()->Remove(filter, document_id); | 194 iter->worker_document_set()->Remove(filter, document_id); |
| 190 if (iter->worker_document_set()->IsEmpty()) { | 195 if (iter->worker_document_set()->IsEmpty()) { |
| 191 iter = pending_shared_workers_.erase(iter); | 196 iter = pending_shared_workers_.erase(iter); |
| 192 } else { | 197 } else { |
| 193 ++iter; | 198 ++iter; |
| 194 } | 199 } |
| 195 } | 200 } |
| 196 } | 201 } |
| 197 | 202 |
| 198 bool WorkerService::CreateWorkerFromInstance( | 203 bool WorkerServiceImpl::CreateWorkerFromInstance( |
| 199 WorkerProcessHost::WorkerInstance instance) { | 204 WorkerProcessHost::WorkerInstance instance) { |
| 200 // TODO(michaeln): We need to ensure that a process is working | 205 // TODO(michaeln): We need to ensure that a process is working |
| 201 // on behalf of a single browser context. The process sharing logic below | 206 // on behalf of a single browser context. The process sharing logic below |
| 202 // does not ensure that. Consider making WorkerService a per browser context | 207 // does not ensure that. Consider making WorkerService a per browser context |
| 203 // object to help with this. | 208 // object to help with this. |
| 204 WorkerProcessHost* worker = NULL; | 209 WorkerProcessHost* worker = NULL; |
| 205 if (CommandLine::ForCurrentProcess()->HasSwitch( | 210 if (CommandLine::ForCurrentProcess()->HasSwitch( |
| 206 switches::kWebWorkerProcessPerCore)) { | 211 switches::kWebWorkerProcessPerCore)) { |
| 207 worker = GetProcessToFillUpCores(); | 212 worker = GetProcessToFillUpCores(); |
| 208 } else if (CommandLine::ForCurrentProcess()->HasSwitch( | 213 } else if (CommandLine::ForCurrentProcess()->HasSwitch( |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 295 // TODO(michaeln): As written, test can fail per my earlier comment in | 300 // TODO(michaeln): As written, test can fail per my earlier comment in |
| 296 // this method, but that's a bug. | 301 // this method, but that's a bug. |
| 297 // DCHECK(worker->request_context() == instance.request_context()); | 302 // DCHECK(worker->request_context() == instance.request_context()); |
| 298 | 303 |
| 299 worker->CreateWorker(instance); | 304 worker->CreateWorker(instance); |
| 300 FOR_EACH_OBSERVER(WorkerServiceObserver, observers_, | 305 FOR_EACH_OBSERVER(WorkerServiceObserver, observers_, |
| 301 WorkerCreated(worker, instance)); | 306 WorkerCreated(worker, instance)); |
| 302 return true; | 307 return true; |
| 303 } | 308 } |
| 304 | 309 |
| 305 WorkerProcessHost* WorkerService::GetProcessForDomain(const GURL& url) { | 310 WorkerProcessHost* WorkerServiceImpl::GetProcessForDomain(const GURL& url) { |
| 306 int num_processes = 0; | 311 int num_processes = 0; |
| 307 std::string domain = | 312 std::string domain = |
| 308 net::RegistryControlledDomainService::GetDomainAndRegistry(url); | 313 net::RegistryControlledDomainService::GetDomainAndRegistry(url); |
| 309 for (BrowserChildProcessHost::Iterator iter(content::PROCESS_TYPE_WORKER); | 314 for (BrowserChildProcessHost::Iterator iter(content::PROCESS_TYPE_WORKER); |
| 310 !iter.Done(); ++iter) { | 315 !iter.Done(); ++iter) { |
| 311 num_processes++; | 316 num_processes++; |
| 312 WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); | 317 WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); |
| 313 for (WorkerProcessHost::Instances::const_iterator instance = | 318 for (WorkerProcessHost::Instances::const_iterator instance = |
| 314 worker->instances().begin(); | 319 worker->instances().begin(); |
| 315 instance != worker->instances().end(); ++instance) { | 320 instance != worker->instances().end(); ++instance) { |
| 316 if (net::RegistryControlledDomainService::GetDomainAndRegistry( | 321 if (net::RegistryControlledDomainService::GetDomainAndRegistry( |
| 317 instance->url()) == domain) { | 322 instance->url()) == domain) { |
| 318 return worker; | 323 return worker; |
| 319 } | 324 } |
| 320 } | 325 } |
| 321 } | 326 } |
| 322 | 327 |
| 323 if (num_processes >= kMaxWorkerProcessesWhenSharing) | 328 if (num_processes >= kMaxWorkerProcessesWhenSharing) |
| 324 return GetLeastLoadedWorker(); | 329 return GetLeastLoadedWorker(); |
| 325 | 330 |
| 326 return NULL; | 331 return NULL; |
| 327 } | 332 } |
| 328 | 333 |
| 329 WorkerProcessHost* WorkerService::GetProcessToFillUpCores() { | 334 WorkerProcessHost* WorkerServiceImpl::GetProcessToFillUpCores() { |
| 330 int num_processes = 0; | 335 int num_processes = 0; |
| 331 BrowserChildProcessHost::Iterator iter(content::PROCESS_TYPE_WORKER); | 336 BrowserChildProcessHost::Iterator iter(content::PROCESS_TYPE_WORKER); |
| 332 for (; !iter.Done(); ++iter) | 337 for (; !iter.Done(); ++iter) |
| 333 num_processes++; | 338 num_processes++; |
| 334 | 339 |
| 335 if (num_processes >= base::SysInfo::NumberOfProcessors()) | 340 if (num_processes >= base::SysInfo::NumberOfProcessors()) |
| 336 return GetLeastLoadedWorker(); | 341 return GetLeastLoadedWorker(); |
| 337 | 342 |
| 338 return NULL; | 343 return NULL; |
| 339 } | 344 } |
| 340 | 345 |
| 341 WorkerProcessHost* WorkerService::GetLeastLoadedWorker() { | 346 WorkerProcessHost* WorkerServiceImpl::GetLeastLoadedWorker() { |
| 342 WorkerProcessHost* smallest = NULL; | 347 WorkerProcessHost* smallest = NULL; |
| 343 for (BrowserChildProcessHost::Iterator iter(content::PROCESS_TYPE_WORKER); | 348 for (BrowserChildProcessHost::Iterator iter(content::PROCESS_TYPE_WORKER); |
| 344 !iter.Done(); ++iter) { | 349 !iter.Done(); ++iter) { |
| 345 WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); | 350 WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); |
| 346 if (!smallest || worker->instances().size() < smallest->instances().size()) | 351 if (!smallest || worker->instances().size() < smallest->instances().size()) |
| 347 smallest = worker; | 352 smallest = worker; |
| 348 } | 353 } |
| 349 | 354 |
| 350 return smallest; | 355 return smallest; |
| 351 } | 356 } |
| 352 | 357 |
| 353 bool WorkerService::CanCreateWorkerProcess( | 358 bool WorkerServiceImpl::CanCreateWorkerProcess( |
| 354 const WorkerProcessHost::WorkerInstance& instance) { | 359 const WorkerProcessHost::WorkerInstance& instance) { |
| 355 // Worker can be fired off if *any* parent has room. | 360 // Worker can be fired off if *any* parent has room. |
| 356 const WorkerDocumentSet::DocumentInfoSet& parents = | 361 const WorkerDocumentSet::DocumentInfoSet& parents = |
| 357 instance.worker_document_set()->documents(); | 362 instance.worker_document_set()->documents(); |
| 358 | 363 |
| 359 for (WorkerDocumentSet::DocumentInfoSet::const_iterator parent_iter = | 364 for (WorkerDocumentSet::DocumentInfoSet::const_iterator parent_iter = |
| 360 parents.begin(); | 365 parents.begin(); |
| 361 parent_iter != parents.end(); ++parent_iter) { | 366 parent_iter != parents.end(); ++parent_iter) { |
| 362 bool hit_total_worker_limit = false; | 367 bool hit_total_worker_limit = false; |
| 363 if (TabCanCreateWorkerProcess(parent_iter->render_process_id(), | 368 if (TabCanCreateWorkerProcess(parent_iter->render_process_id(), |
| 364 parent_iter->render_view_id(), | 369 parent_iter->render_view_id(), |
| 365 &hit_total_worker_limit)) { | 370 &hit_total_worker_limit)) { |
| 366 return true; | 371 return true; |
| 367 } | 372 } |
| 368 // Return false if already at the global worker limit (no need to continue | 373 // Return false if already at the global worker limit (no need to continue |
| 369 // checking parent tabs). | 374 // checking parent tabs). |
| 370 if (hit_total_worker_limit) | 375 if (hit_total_worker_limit) |
| 371 return false; | 376 return false; |
| 372 } | 377 } |
| 373 // If we've reached here, none of the parent tabs is allowed to create an | 378 // If we've reached here, none of the parent tabs is allowed to create an |
| 374 // instance. | 379 // instance. |
| 375 return false; | 380 return false; |
| 376 } | 381 } |
| 377 | 382 |
| 378 bool WorkerService::TabCanCreateWorkerProcess(int render_process_id, | 383 bool WorkerServiceImpl::TabCanCreateWorkerProcess( |
| 379 int render_view_id, | 384 int render_process_id, |
| 380 bool* hit_total_worker_limit) { | 385 int render_view_id, |
| 386 bool* hit_total_worker_limit) { |
| 381 int total_workers = 0; | 387 int total_workers = 0; |
| 382 int workers_per_tab = 0; | 388 int workers_per_tab = 0; |
| 383 *hit_total_worker_limit = false; | 389 *hit_total_worker_limit = false; |
| 384 for (BrowserChildProcessHost::Iterator iter(content::PROCESS_TYPE_WORKER); | 390 for (BrowserChildProcessHost::Iterator iter(content::PROCESS_TYPE_WORKER); |
| 385 !iter.Done(); ++iter) { | 391 !iter.Done(); ++iter) { |
| 386 WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); | 392 WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); |
| 387 for (WorkerProcessHost::Instances::const_iterator cur_instance = | 393 for (WorkerProcessHost::Instances::const_iterator cur_instance = |
| 388 worker->instances().begin(); | 394 worker->instances().begin(); |
| 389 cur_instance != worker->instances().end(); ++cur_instance) { | 395 cur_instance != worker->instances().end(); ++cur_instance) { |
| 390 total_workers++; | 396 total_workers++; |
| 391 if (total_workers >= kMaxWorkersWhenSeparate) { | 397 if (total_workers >= kMaxWorkersWhenSeparate) { |
| 392 *hit_total_worker_limit = true; | 398 *hit_total_worker_limit = true; |
| 393 return false; | 399 return false; |
| 394 } | 400 } |
| 395 if (cur_instance->RendererIsParent(render_process_id, render_view_id)) { | 401 if (cur_instance->RendererIsParent(render_process_id, render_view_id)) { |
| 396 workers_per_tab++; | 402 workers_per_tab++; |
| 397 if (workers_per_tab >= kMaxWorkersPerTabWhenSeparate) | 403 if (workers_per_tab >= kMaxWorkersPerTabWhenSeparate) |
| 398 return false; | 404 return false; |
| 399 } | 405 } |
| 400 } | 406 } |
| 401 } | 407 } |
| 402 | 408 |
| 403 return true; | 409 return true; |
| 404 } | 410 } |
| 405 | 411 |
| 406 void WorkerService::TryStartingQueuedWorker() { | 412 void WorkerServiceImpl::TryStartingQueuedWorker() { |
| 407 if (queued_workers_.empty()) | 413 if (queued_workers_.empty()) |
| 408 return; | 414 return; |
| 409 | 415 |
| 410 for (WorkerProcessHost::Instances::iterator i = queued_workers_.begin(); | 416 for (WorkerProcessHost::Instances::iterator i = queued_workers_.begin(); |
| 411 i != queued_workers_.end();) { | 417 i != queued_workers_.end();) { |
| 412 if (CanCreateWorkerProcess(*i)) { | 418 if (CanCreateWorkerProcess(*i)) { |
| 413 WorkerProcessHost::WorkerInstance instance = *i; | 419 WorkerProcessHost::WorkerInstance instance = *i; |
| 414 queued_workers_.erase(i); | 420 queued_workers_.erase(i); |
| 415 CreateWorkerFromInstance(instance); | 421 CreateWorkerFromInstance(instance); |
| 416 | 422 |
| 417 // CreateWorkerFromInstance can modify the queued_workers_ list when it | 423 // CreateWorkerFromInstance can modify the queued_workers_ list when it |
| 418 // coalesces queued instances after starting a shared worker, so we | 424 // coalesces queued instances after starting a shared worker, so we |
| 419 // have to rescan the list from the beginning (our iterator is now | 425 // have to rescan the list from the beginning (our iterator is now |
| 420 // invalid). This is not a big deal as having any queued workers will be | 426 // invalid). This is not a big deal as having any queued workers will be |
| 421 // rare in practice so the list will be small. | 427 // rare in practice so the list will be small. |
| 422 i = queued_workers_.begin(); | 428 i = queued_workers_.begin(); |
| 423 } else { | 429 } else { |
| 424 ++i; | 430 ++i; |
| 425 } | 431 } |
| 426 } | 432 } |
| 427 } | 433 } |
| 428 | 434 |
| 429 bool WorkerService::GetRendererForWorker(int worker_process_id, | 435 bool WorkerServiceImpl::GetRendererForWorker(int worker_process_id, |
| 430 int* render_process_id, | 436 int* render_process_id, |
| 431 int* render_view_id) const { | 437 int* render_view_id) const { |
| 432 for (BrowserChildProcessHost::Iterator iter(content::PROCESS_TYPE_WORKER); | 438 for (BrowserChildProcessHost::Iterator iter(content::PROCESS_TYPE_WORKER); |
| 433 !iter.Done(); ++iter) { | 439 !iter.Done(); ++iter) { |
| 434 if (iter->id() != worker_process_id) | 440 if (iter->id() != worker_process_id) |
| 435 continue; | 441 continue; |
| 436 | 442 |
| 437 // This code assumes one worker per process, see function comment in header! | 443 // This code assumes one worker per process, see function comment in header! |
| 438 WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); | 444 WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); |
| 439 WorkerProcessHost::Instances::const_iterator first_instance = | 445 WorkerProcessHost::Instances::const_iterator first_instance = |
| 440 worker->instances().begin(); | 446 worker->instances().begin(); |
| 441 if (first_instance == worker->instances().end()) | 447 if (first_instance == worker->instances().end()) |
| 442 return false; | 448 return false; |
| 443 | 449 |
| 444 WorkerDocumentSet::DocumentInfoSet::const_iterator info = | 450 WorkerDocumentSet::DocumentInfoSet::const_iterator info = |
| 445 first_instance->worker_document_set()->documents().begin(); | 451 first_instance->worker_document_set()->documents().begin(); |
| 446 *render_process_id = info->render_process_id(); | 452 *render_process_id = info->render_process_id(); |
| 447 *render_view_id = info->render_view_id(); | 453 *render_view_id = info->render_view_id(); |
| 448 return true; | 454 return true; |
| 449 } | 455 } |
| 450 return false; | 456 return false; |
| 451 } | 457 } |
| 452 | 458 |
| 453 const WorkerProcessHost::WorkerInstance* WorkerService::FindWorkerInstance( | 459 const WorkerProcessHost::WorkerInstance* WorkerServiceImpl::FindWorkerInstance( |
| 454 int worker_process_id) { | 460 int worker_process_id) { |
| 455 for (BrowserChildProcessHost::Iterator iter(content::PROCESS_TYPE_WORKER); | 461 for (BrowserChildProcessHost::Iterator iter(content::PROCESS_TYPE_WORKER); |
| 456 !iter.Done(); ++iter) { | 462 !iter.Done(); ++iter) { |
| 457 if (iter->id() != worker_process_id) | 463 if (iter->id() != worker_process_id) |
| 458 continue; | 464 continue; |
| 459 | 465 |
| 460 WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); | 466 WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); |
| 461 WorkerProcessHost::Instances::const_iterator instance = | 467 WorkerProcessHost::Instances::const_iterator instance = |
| 462 worker->instances().begin(); | 468 worker->instances().begin(); |
| 463 return instance == worker->instances().end() ? NULL : &*instance; | 469 return instance == worker->instances().end() ? NULL : &*instance; |
| 464 } | 470 } |
| 465 return NULL; | 471 return NULL; |
| 466 } | 472 } |
| 467 | 473 |
| 468 void WorkerService::AddObserver(WorkerServiceObserver* observer) { | 474 void WorkerServiceImpl::AddObserver(WorkerServiceObserver* observer) { |
| 469 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 475 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 470 observers_.AddObserver(observer); | 476 observers_.AddObserver(observer); |
| 471 } | 477 } |
| 472 | 478 |
| 473 void WorkerService::RemoveObserver(WorkerServiceObserver* observer) { | 479 void WorkerServiceImpl::RemoveObserver(WorkerServiceObserver* observer) { |
| 474 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 480 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 475 observers_.RemoveObserver(observer); | 481 observers_.RemoveObserver(observer); |
| 476 } | 482 } |
| 477 | 483 |
| 478 void WorkerService::NotifyWorkerDestroyed( | 484 void WorkerServiceImpl::NotifyWorkerDestroyed( |
| 479 WorkerProcessHost* process, | 485 WorkerProcessHost* process, |
| 480 int worker_route_id) { | 486 int worker_route_id) { |
| 481 FOR_EACH_OBSERVER(WorkerServiceObserver, observers_, | 487 FOR_EACH_OBSERVER(WorkerServiceObserver, observers_, |
| 482 WorkerDestroyed(process, worker_route_id)); | 488 WorkerDestroyed(process, worker_route_id)); |
| 483 } | 489 } |
| 484 | 490 |
| 485 void WorkerService::NotifyWorkerContextStarted(WorkerProcessHost* process, | 491 void WorkerServiceImpl::NotifyWorkerContextStarted(WorkerProcessHost* process, |
| 486 int worker_route_id) { | 492 int worker_route_id) { |
| 487 FOR_EACH_OBSERVER(WorkerServiceObserver, observers_, | 493 FOR_EACH_OBSERVER(WorkerServiceObserver, observers_, |
| 488 WorkerContextStarted(process, worker_route_id)); | 494 WorkerContextStarted(process, worker_route_id)); |
| 489 } | 495 } |
| 490 | 496 |
| 491 WorkerProcessHost::WorkerInstance* | 497 WorkerProcessHost::WorkerInstance* WorkerServiceImpl::FindSharedWorkerInstance( |
| 492 WorkerService::FindSharedWorkerInstance( | |
| 493 const GURL& url, | 498 const GURL& url, |
| 494 const string16& name, | 499 const string16& name, |
| 495 const content::ResourceContext* resource_context) { | 500 const content::ResourceContext* resource_context) { |
| 496 for (BrowserChildProcessHost::Iterator iter(content::PROCESS_TYPE_WORKER); | 501 for (BrowserChildProcessHost::Iterator iter(content::PROCESS_TYPE_WORKER); |
| 497 !iter.Done(); ++iter) { | 502 !iter.Done(); ++iter) { |
| 498 WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); | 503 WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); |
| 499 for (WorkerProcessHost::Instances::iterator instance_iter = | 504 for (WorkerProcessHost::Instances::iterator instance_iter = |
| 500 worker->mutable_instances().begin(); | 505 worker->mutable_instances().begin(); |
| 501 instance_iter != worker->mutable_instances().end(); | 506 instance_iter != worker->mutable_instances().end(); |
| 502 ++instance_iter) { | 507 ++instance_iter) { |
| 503 if (instance_iter->Matches(url, name, resource_context)) | 508 if (instance_iter->Matches(url, name, resource_context)) |
| 504 return &(*instance_iter); | 509 return &(*instance_iter); |
| 505 } | 510 } |
| 506 } | 511 } |
| 507 return NULL; | 512 return NULL; |
| 508 } | 513 } |
| 509 | 514 |
| 510 WorkerProcessHost::WorkerInstance* | 515 WorkerProcessHost::WorkerInstance* WorkerServiceImpl::FindPendingInstance( |
| 511 WorkerService::FindPendingInstance( | |
| 512 const GURL& url, | 516 const GURL& url, |
| 513 const string16& name, | 517 const string16& name, |
| 514 const content::ResourceContext* resource_context) { | 518 const content::ResourceContext* resource_context) { |
| 515 // Walk the pending instances looking for a matching pending worker. | 519 // Walk the pending instances looking for a matching pending worker. |
| 516 for (WorkerProcessHost::Instances::iterator iter = | 520 for (WorkerProcessHost::Instances::iterator iter = |
| 517 pending_shared_workers_.begin(); | 521 pending_shared_workers_.begin(); |
| 518 iter != pending_shared_workers_.end(); | 522 iter != pending_shared_workers_.end(); |
| 519 ++iter) { | 523 ++iter) { |
| 520 if (iter->Matches(url, name, resource_context)) { | 524 if (iter->Matches(url, name, resource_context)) { |
| 521 return &(*iter); | 525 return &(*iter); |
| 522 } | 526 } |
| 523 } | 527 } |
| 524 return NULL; | 528 return NULL; |
| 525 } | 529 } |
| 526 | 530 |
| 527 | 531 |
| 528 void WorkerService::RemovePendingInstances( | 532 void WorkerServiceImpl::RemovePendingInstances( |
| 529 const GURL& url, | 533 const GURL& url, |
| 530 const string16& name, | 534 const string16& name, |
| 531 const content::ResourceContext* resource_context) { | 535 const content::ResourceContext* resource_context) { |
| 532 // Walk the pending instances looking for a matching pending worker. | 536 // Walk the pending instances looking for a matching pending worker. |
| 533 for (WorkerProcessHost::Instances::iterator iter = | 537 for (WorkerProcessHost::Instances::iterator iter = |
| 534 pending_shared_workers_.begin(); | 538 pending_shared_workers_.begin(); |
| 535 iter != pending_shared_workers_.end(); ) { | 539 iter != pending_shared_workers_.end(); ) { |
| 536 if (iter->Matches(url, name, resource_context)) { | 540 if (iter->Matches(url, name, resource_context)) { |
| 537 iter = pending_shared_workers_.erase(iter); | 541 iter = pending_shared_workers_.erase(iter); |
| 538 } else { | 542 } else { |
| 539 ++iter; | 543 ++iter; |
| 540 } | 544 } |
| 541 } | 545 } |
| 542 } | 546 } |
| 543 | 547 |
| 544 WorkerProcessHost::WorkerInstance* | 548 WorkerProcessHost::WorkerInstance* WorkerServiceImpl::CreatePendingInstance( |
| 545 WorkerService::CreatePendingInstance( | |
| 546 const GURL& url, | 549 const GURL& url, |
| 547 const string16& name, | 550 const string16& name, |
| 548 const content::ResourceContext* resource_context) { | 551 const content::ResourceContext* resource_context) { |
| 549 // Look for an existing pending shared worker. | 552 // Look for an existing pending shared worker. |
| 550 WorkerProcessHost::WorkerInstance* instance = | 553 WorkerProcessHost::WorkerInstance* instance = |
| 551 FindPendingInstance(url, name, resource_context); | 554 FindPendingInstance(url, name, resource_context); |
| 552 if (instance) | 555 if (instance) |
| 553 return instance; | 556 return instance; |
| 554 | 557 |
| 555 // No existing pending worker - create a new one. | 558 // No existing pending worker - create a new one. |
| 556 WorkerProcessHost::WorkerInstance pending(url, true, name, resource_context); | 559 WorkerProcessHost::WorkerInstance pending(url, true, name, resource_context); |
| 557 pending_shared_workers_.push_back(pending); | 560 pending_shared_workers_.push_back(pending); |
| 558 return &pending_shared_workers_.back(); | 561 return &pending_shared_workers_.back(); |
| 559 } | 562 } |
| 563 |
| 564 } // namespace content |
| OLD | NEW |