| 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.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/sys_info.h" |   11 #include "base/sys_info.h" | 
|   11 #include "base/threading/thread.h" |   12 #include "base/threading/thread.h" | 
|   12 #include "chrome/common/chrome_switches.h" |   13 #include "chrome/common/chrome_switches.h" | 
|   13 #include "content/browser/worker_host/worker_message_filter.h" |   14 #include "content/browser/worker_host/worker_message_filter.h" | 
|   14 #include "content/browser/worker_host/worker_process_host.h" |   15 #include "content/browser/worker_host/worker_process_host.h" | 
|   15 #include "content/common/view_messages.h" |   16 #include "content/common/view_messages.h" | 
|   16 #include "content/common/worker_messages.h" |   17 #include "content/common/worker_messages.h" | 
|   17 #include "net/base/registry_controlled_domain.h" |   18 #include "net/base/registry_controlled_domain.h" | 
|   18  |   19  | 
|   19 const int WorkerService::kMaxWorkerProcessesWhenSharing = 10; |   20 const int WorkerService::kMaxWorkerProcessesWhenSharing = 10; | 
|   20 const int WorkerService::kMaxWorkersWhenSeparate = 64; |   21 const int WorkerService::kMaxWorkersWhenSeparate = 64; | 
|   21 const int WorkerService::kMaxWorkersPerTabWhenSeparate = 16; |   22 const int WorkerService::kMaxWorkersPerTabWhenSeparate = 16; | 
|   22  |   23  | 
|   23 WorkerService* WorkerService::GetInstance() { |   24 WorkerService* WorkerService::GetInstance() { | 
 |   25   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 
|   24   return Singleton<WorkerService>::get(); |   26   return Singleton<WorkerService>::get(); | 
|   25 } |   27 } | 
|   26  |   28  | 
|   27 WorkerService::WorkerService() : next_worker_route_id_(0) { |   29 WorkerService::WorkerService() : next_worker_route_id_(0) { | 
|   28 } |   30 } | 
|   29  |   31  | 
|   30 WorkerService::~WorkerService() { |   32 WorkerService::~WorkerService() { | 
 |   33   // Since we're a Singleton, we are deleted on the UI thread instead. | 
 |   34   DetachFromThread(); | 
|   31 } |   35 } | 
|   32  |   36  | 
|   33 void WorkerService::OnWorkerMessageFilterClosing(WorkerMessageFilter* filter) { |   37 void WorkerService::OnWorkerMessageFilterClosing(WorkerMessageFilter* filter) { | 
 |   38   DCHECK(CalledOnValidThread()); | 
|   34   for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); |   39   for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); | 
|   35      !iter.Done(); ++iter) { |   40      !iter.Done(); ++iter) { | 
|   36     WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); |   41     WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); | 
|   37     worker->FilterShutdown(filter); |   42     worker->FilterShutdown(filter); | 
|   38   } |   43   } | 
|   39  |   44  | 
|   40   // See if that process had any queued workers. |   45   // See if that process had any queued workers. | 
|   41   for (WorkerProcessHost::Instances::iterator i = queued_workers_.begin(); |   46   for (WorkerProcessHost::Instances::iterator i = queued_workers_.begin(); | 
|   42        i != queued_workers_.end();) { |   47        i != queued_workers_.end();) { | 
|   43     i->RemoveFilters(filter); |   48     i->RemoveFilters(filter); | 
| (...skipping 20 matching lines...) Expand all  Loading... | 
|   64   // the queued workers, or a renderer has shut down, in which case it doesn't |   69   // the queued workers, or a renderer has shut down, in which case it doesn't | 
|   65   // affect anything.  We call this function in both scenarios because then we |   70   // affect anything.  We call this function in both scenarios because then we | 
|   66   // don't have to keep track which filters are from worker processes. |   71   // don't have to keep track which filters are from worker processes. | 
|   67   TryStartingQueuedWorker(); |   72   TryStartingQueuedWorker(); | 
|   68 } |   73 } | 
|   69  |   74  | 
|   70 void WorkerService::CreateWorker( |   75 void WorkerService::CreateWorker( | 
|   71     const ViewHostMsg_CreateWorker_Params& params, |   76     const ViewHostMsg_CreateWorker_Params& params, | 
|   72     int route_id, |   77     int route_id, | 
|   73     WorkerMessageFilter* filter, |   78     WorkerMessageFilter* filter, | 
|   74     net::URLRequestContextGetter* request_context) { |   79     net::URLRequestContext* request_context, | 
|   75  |   80     const content::ResourceContext& resource_context) { | 
 |   81   DCHECK(CalledOnValidThread()); | 
 |   82   // TODO(willchan): Eliminate the need for this downcast. | 
|   76   ChromeURLRequestContext* context = static_cast<ChromeURLRequestContext*>( |   83   ChromeURLRequestContext* context = static_cast<ChromeURLRequestContext*>( | 
|   77       request_context->GetURLRequestContext()); |   84       request_context); | 
|   78  |   85  | 
|   79   // Generate a unique route id for the browser-worker communication that's |   86   // Generate a unique route id for the browser-worker communication that's | 
|   80   // unique among all worker processes.  That way when the worker process sends |   87   // unique among all worker processes.  That way when the worker process sends | 
|   81   // a wrapped IPC message through us, we know which WorkerProcessHost to give |   88   // a wrapped IPC message through us, we know which WorkerProcessHost to give | 
|   82   // it to. |   89   // it to. | 
|   83   WorkerProcessHost::WorkerInstance instance( |   90   WorkerProcessHost::WorkerInstance instance( | 
|   84       params.url, |   91       params.url, | 
|   85       params.is_shared, |   92       params.is_shared, | 
|   86       context->is_incognito(), |   93       context->is_incognito(), | 
|   87       params.name, |   94       params.name, | 
|   88       next_worker_route_id(), |   95       next_worker_route_id(), | 
|   89       params.is_shared ? 0 : filter->render_process_id(), |   96       params.is_shared ? 0 : filter->render_process_id(), | 
|   90       params.is_shared ? 0 : params.parent_appcache_host_id, |   97       params.is_shared ? 0 : params.parent_appcache_host_id, | 
|   91       params.is_shared ? params.script_resource_appcache_id : 0, |   98       params.is_shared ? params.script_resource_appcache_id : 0, | 
|   92       request_context); |   99       request_context, | 
 |  100       resource_context); | 
|   93   instance.AddFilter(filter, route_id); |  101   instance.AddFilter(filter, route_id); | 
|   94   instance.worker_document_set()->Add( |  102   instance.worker_document_set()->Add( | 
|   95       filter, params.document_id, filter->render_process_id(), |  103       filter, params.document_id, filter->render_process_id(), | 
|   96       params.render_view_route_id); |  104       params.render_view_route_id); | 
|   97  |  105  | 
|   98   CreateWorkerFromInstance(instance); |  106   CreateWorkerFromInstance(instance); | 
|   99 } |  107 } | 
|  100  |  108  | 
|  101 void WorkerService::LookupSharedWorker( |  109 void WorkerService::LookupSharedWorker( | 
|  102     const ViewHostMsg_CreateWorker_Params& params, |  110     const ViewHostMsg_CreateWorker_Params& params, | 
|  103     int route_id, |  111     int route_id, | 
|  104     WorkerMessageFilter* filter, |  112     WorkerMessageFilter* filter, | 
|  105     bool incognito, |  113     bool incognito, | 
|  106     bool* exists, |  114     bool* exists, | 
|  107     bool* url_mismatch) { |  115     bool* url_mismatch) { | 
|  108  |  116   DCHECK(CalledOnValidThread()); | 
|  109   *exists = true; |  117   *exists = true; | 
|  110   WorkerProcessHost::WorkerInstance* instance = FindSharedWorkerInstance( |  118   WorkerProcessHost::WorkerInstance* instance = FindSharedWorkerInstance( | 
|  111       params.url, params.name, incognito); |  119       params.url, params.name, incognito); | 
|  112  |  120  | 
|  113   if (!instance) { |  121   if (!instance) { | 
|  114     // If no worker instance currently exists, we need to create a pending |  122     // If no worker instance currently exists, we need to create a pending | 
|  115     // instance - this is to make sure that any subsequent lookups passing a |  123     // instance - this is to make sure that any subsequent lookups passing a | 
|  116     // mismatched URL get the appropriate url_mismatch error at lookup time. |  124     // mismatched URL get the appropriate url_mismatch error at lookup time. | 
|  117     // Having named shared workers was a Really Bad Idea due to details like |  125     // Having named shared workers was a Really Bad Idea due to details like | 
|  118     // this. |  126     // this. | 
| (...skipping 18 matching lines...) Expand all  Loading... | 
|  137     // worker's document set for nested workers. |  145     // worker's document set for nested workers. | 
|  138     instance->worker_document_set()->Add( |  146     instance->worker_document_set()->Add( | 
|  139         filter, params.document_id, filter->render_process_id(), |  147         filter, params.document_id, filter->render_process_id(), | 
|  140         params.render_view_route_id); |  148         params.render_view_route_id); | 
|  141   } |  149   } | 
|  142 } |  150 } | 
|  143  |  151  | 
|  144 void WorkerService::CancelCreateDedicatedWorker( |  152 void WorkerService::CancelCreateDedicatedWorker( | 
|  145     int route_id, |  153     int route_id, | 
|  146     WorkerMessageFilter* filter) { |  154     WorkerMessageFilter* filter) { | 
 |  155   DCHECK(CalledOnValidThread()); | 
|  147   for (WorkerProcessHost::Instances::iterator i = queued_workers_.begin(); |  156   for (WorkerProcessHost::Instances::iterator i = queued_workers_.begin(); | 
|  148        i != queued_workers_.end(); ++i) { |  157        i != queued_workers_.end(); ++i) { | 
|  149     if (i->HasFilter(filter, route_id)) { |  158     if (i->HasFilter(filter, route_id)) { | 
|  150       DCHECK(!i->shared()); |  159       DCHECK(!i->shared()); | 
|  151       queued_workers_.erase(i); |  160       queued_workers_.erase(i); | 
|  152       return; |  161       return; | 
|  153     } |  162     } | 
|  154   } |  163   } | 
|  155  |  164  | 
|  156   // There could be a race condition where the WebWorkerProxy told us to cancel |  165   // There could be a race condition where the WebWorkerProxy told us to cancel | 
| (...skipping 13 matching lines...) Expand all  Loading... | 
|  170         return; |  179         return; | 
|  171       } |  180       } | 
|  172     } |  181     } | 
|  173   } |  182   } | 
|  174  |  183  | 
|  175   DCHECK(false) << "Couldn't find worker to cancel"; |  184   DCHECK(false) << "Couldn't find worker to cancel"; | 
|  176 } |  185 } | 
|  177  |  186  | 
|  178 void WorkerService::ForwardToWorker(const IPC::Message& message, |  187 void WorkerService::ForwardToWorker(const IPC::Message& message, | 
|  179                                     WorkerMessageFilter* filter) { |  188                                     WorkerMessageFilter* filter) { | 
 |  189   DCHECK(CalledOnValidThread()); | 
|  180   for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); |  190   for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); | 
|  181        !iter.Done(); ++iter) { |  191        !iter.Done(); ++iter) { | 
|  182     WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); |  192     WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); | 
|  183     if (worker->FilterMessage(message, filter)) |  193     if (worker->FilterMessage(message, filter)) | 
|  184       return; |  194       return; | 
|  185   } |  195   } | 
|  186  |  196  | 
|  187   // TODO(jabdelmalek): tell filter that callee is gone |  197   // TODO(jabdelmalek): tell filter that callee is gone | 
|  188 } |  198 } | 
|  189  |  199  | 
|  190 void WorkerService::DocumentDetached(unsigned long long document_id, |  200 void WorkerService::DocumentDetached(unsigned long long document_id, | 
|  191                                      WorkerMessageFilter* filter) { |  201                                      WorkerMessageFilter* filter) { | 
 |  202   DCHECK(CalledOnValidThread()); | 
|  192   // Any associated shared workers can be shut down. |  203   // Any associated shared workers can be shut down. | 
|  193   for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); |  204   for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); | 
|  194        !iter.Done(); ++iter) { |  205        !iter.Done(); ++iter) { | 
|  195     WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); |  206     WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); | 
|  196     worker->DocumentDetached(filter, document_id); |  207     worker->DocumentDetached(filter, document_id); | 
|  197   } |  208   } | 
|  198  |  209  | 
|  199   // Remove any queued shared workers for this document. |  210   // Remove any queued shared workers for this document. | 
|  200   for (WorkerProcessHost::Instances::iterator iter = queued_workers_.begin(); |  211   for (WorkerProcessHost::Instances::iterator iter = queued_workers_.begin(); | 
|  201        iter != queued_workers_.end();) { |  212        iter != queued_workers_.end();) { | 
| (...skipping 15 matching lines...) Expand all  Loading... | 
|  217     if (iter->worker_document_set()->IsEmpty()) { |  228     if (iter->worker_document_set()->IsEmpty()) { | 
|  218       iter = pending_shared_workers_.erase(iter); |  229       iter = pending_shared_workers_.erase(iter); | 
|  219     } else { |  230     } else { | 
|  220       ++iter; |  231       ++iter; | 
|  221     } |  232     } | 
|  222   } |  233   } | 
|  223 } |  234 } | 
|  224  |  235  | 
|  225 bool WorkerService::CreateWorkerFromInstance( |  236 bool WorkerService::CreateWorkerFromInstance( | 
|  226     WorkerProcessHost::WorkerInstance instance) { |  237     WorkerProcessHost::WorkerInstance instance) { | 
 |  238   DCHECK(CalledOnValidThread()); | 
|  227   // TODO(michaeln): We need to ensure that a process is working |  239   // TODO(michaeln): We need to ensure that a process is working | 
|  228   // on behalf of a single profile. The process sharing logic below |  240   // on behalf of a single profile. The process sharing logic below | 
|  229   // does not ensure that. Consider making WorkerService a per profile |  241   // does not ensure that. Consider making WorkerService a per profile | 
|  230   // object to help with this. |  242   // object to help with this. | 
|  231   WorkerProcessHost* worker = NULL; |  243   WorkerProcessHost* worker = NULL; | 
|  232   if (CommandLine::ForCurrentProcess()->HasSwitch( |  244   if (CommandLine::ForCurrentProcess()->HasSwitch( | 
|  233           switches::kWebWorkerProcessPerCore)) { |  245           switches::kWebWorkerProcessPerCore)) { | 
|  234     worker = GetProcessToFillUpCores(); |  246     worker = GetProcessToFillUpCores(); | 
|  235   } else if (CommandLine::ForCurrentProcess()->HasSwitch( |  247   } else if (CommandLine::ForCurrentProcess()->HasSwitch( | 
|  236                  switches::kWebWorkerShareProcesses)) { |  248                  switches::kWebWorkerShareProcesses)) { | 
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  302         iter = queued_workers_.erase(iter); |  314         iter = queued_workers_.erase(iter); | 
|  303       } else { |  315       } else { | 
|  304         ++iter; |  316         ++iter; | 
|  305       } |  317       } | 
|  306     } |  318     } | 
|  307   } |  319   } | 
|  308  |  320  | 
|  309   if (!worker) { |  321   if (!worker) { | 
|  310     WorkerMessageFilter* first_filter = instance.filters().begin()->first; |  322     WorkerMessageFilter* first_filter = instance.filters().begin()->first; | 
|  311     worker = new WorkerProcessHost( |  323     worker = new WorkerProcessHost( | 
|  312         first_filter->resource_dispatcher_host(), |  324         instance.request_context(), | 
|  313         instance.request_context()); |  325         instance.resource_context()); | 
|  314     // TODO(atwilson): This won't work if the message is from a worker process. |  326     // TODO(atwilson): This won't work if the message is from a worker process. | 
|  315     // We don't support that yet though (this message is only sent from |  327     // We don't support that yet though (this message is only sent from | 
|  316     // renderers) but when we do, we'll need to add code to pass in the current |  328     // renderers) but when we do, we'll need to add code to pass in the current | 
|  317     // worker's document set for nested workers. |  329     // worker's document set for nested workers. | 
|  318     if (!worker->Init(first_filter->render_process_id())) { |  330     if (!worker->Init(first_filter->render_process_id())) { | 
|  319       delete worker; |  331       delete worker; | 
|  320       return false; |  332       return false; | 
|  321     } |  333     } | 
|  322   } |  334   } | 
|  323  |  335  | 
|  324   // TODO(michaeln): As written, test can fail per my earlier comment in |  336   // TODO(michaeln): As written, test can fail per my earlier comment in | 
|  325   // this method, but that's a bug. |  337   // this method, but that's a bug. | 
|  326   // DCHECK(worker->request_context() == instance.request_context()); |  338   // DCHECK(worker->request_context() == instance.request_context()); | 
|  327  |  339  | 
|  328   worker->CreateWorker(instance); |  340   worker->CreateWorker(instance); | 
|  329   return true; |  341   return true; | 
|  330 } |  342 } | 
|  331  |  343  | 
|  332 WorkerProcessHost* WorkerService::GetProcessForDomain(const GURL& url) { |  344 WorkerProcessHost* WorkerService::GetProcessForDomain(const GURL& url) { | 
 |  345   DCHECK(CalledOnValidThread()); | 
|  333   int num_processes = 0; |  346   int num_processes = 0; | 
|  334   std::string domain = |  347   std::string domain = | 
|  335       net::RegistryControlledDomainService::GetDomainAndRegistry(url); |  348       net::RegistryControlledDomainService::GetDomainAndRegistry(url); | 
|  336   for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); |  349   for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); | 
|  337        !iter.Done(); ++iter) { |  350        !iter.Done(); ++iter) { | 
|  338     num_processes++; |  351     num_processes++; | 
|  339     WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); |  352     WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); | 
|  340     for (WorkerProcessHost::Instances::const_iterator instance = |  353     for (WorkerProcessHost::Instances::const_iterator instance = | 
|  341              worker->instances().begin(); |  354              worker->instances().begin(); | 
|  342          instance != worker->instances().end(); ++instance) { |  355          instance != worker->instances().end(); ++instance) { | 
|  343       if (net::RegistryControlledDomainService::GetDomainAndRegistry( |  356       if (net::RegistryControlledDomainService::GetDomainAndRegistry( | 
|  344               instance->url()) == domain) { |  357               instance->url()) == domain) { | 
|  345         return worker; |  358         return worker; | 
|  346       } |  359       } | 
|  347     } |  360     } | 
|  348   } |  361   } | 
|  349  |  362  | 
|  350   if (num_processes >= kMaxWorkerProcessesWhenSharing) |  363   if (num_processes >= kMaxWorkerProcessesWhenSharing) | 
|  351     return GetLeastLoadedWorker(); |  364     return GetLeastLoadedWorker(); | 
|  352  |  365  | 
|  353   return NULL; |  366   return NULL; | 
|  354 } |  367 } | 
|  355  |  368  | 
|  356 WorkerProcessHost* WorkerService::GetProcessToFillUpCores() { |  369 WorkerProcessHost* WorkerService::GetProcessToFillUpCores() { | 
 |  370   DCHECK(CalledOnValidThread()); | 
|  357   int num_processes = 0; |  371   int num_processes = 0; | 
|  358   BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); |  372   BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); | 
|  359   for (; !iter.Done(); ++iter) |  373   for (; !iter.Done(); ++iter) | 
|  360     num_processes++; |  374     num_processes++; | 
|  361  |  375  | 
|  362   if (num_processes >= base::SysInfo::NumberOfProcessors()) |  376   if (num_processes >= base::SysInfo::NumberOfProcessors()) | 
|  363     return GetLeastLoadedWorker(); |  377     return GetLeastLoadedWorker(); | 
|  364  |  378  | 
|  365   return NULL; |  379   return NULL; | 
|  366 } |  380 } | 
|  367  |  381  | 
|  368 WorkerProcessHost* WorkerService::GetLeastLoadedWorker() { |  382 WorkerProcessHost* WorkerService::GetLeastLoadedWorker() { | 
 |  383   DCHECK(CalledOnValidThread()); | 
|  369   WorkerProcessHost* smallest = NULL; |  384   WorkerProcessHost* smallest = NULL; | 
|  370   for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); |  385   for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); | 
|  371        !iter.Done(); ++iter) { |  386        !iter.Done(); ++iter) { | 
|  372     WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); |  387     WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); | 
|  373     if (!smallest || worker->instances().size() < smallest->instances().size()) |  388     if (!smallest || worker->instances().size() < smallest->instances().size()) | 
|  374       smallest = worker; |  389       smallest = worker; | 
|  375   } |  390   } | 
|  376  |  391  | 
|  377   return smallest; |  392   return smallest; | 
|  378 } |  393 } | 
|  379  |  394  | 
|  380 bool WorkerService::CanCreateWorkerProcess( |  395 bool WorkerService::CanCreateWorkerProcess( | 
|  381     const WorkerProcessHost::WorkerInstance& instance) { |  396     const WorkerProcessHost::WorkerInstance& instance) { | 
 |  397   DCHECK(CalledOnValidThread()); | 
|  382   // Worker can be fired off if *any* parent has room. |  398   // Worker can be fired off if *any* parent has room. | 
|  383   const WorkerDocumentSet::DocumentInfoSet& parents = |  399   const WorkerDocumentSet::DocumentInfoSet& parents = | 
|  384         instance.worker_document_set()->documents(); |  400         instance.worker_document_set()->documents(); | 
|  385  |  401  | 
|  386   for (WorkerDocumentSet::DocumentInfoSet::const_iterator parent_iter = |  402   for (WorkerDocumentSet::DocumentInfoSet::const_iterator parent_iter = | 
|  387            parents.begin(); |  403            parents.begin(); | 
|  388        parent_iter != parents.end(); ++parent_iter) { |  404        parent_iter != parents.end(); ++parent_iter) { | 
|  389     bool hit_total_worker_limit = false; |  405     bool hit_total_worker_limit = false; | 
|  390     if (TabCanCreateWorkerProcess(parent_iter->render_process_id(), |  406     if (TabCanCreateWorkerProcess(parent_iter->render_process_id(), | 
|  391                                   parent_iter->render_view_id(), |  407                                   parent_iter->render_view_id(), | 
|  392                                   &hit_total_worker_limit)) { |  408                                   &hit_total_worker_limit)) { | 
|  393       return true; |  409       return true; | 
|  394     } |  410     } | 
|  395     // Return false if already at the global worker limit (no need to continue |  411     // Return false if already at the global worker limit (no need to continue | 
|  396     // checking parent tabs). |  412     // checking parent tabs). | 
|  397     if (hit_total_worker_limit) |  413     if (hit_total_worker_limit) | 
|  398       return false; |  414       return false; | 
|  399   } |  415   } | 
|  400   // If we've reached here, none of the parent tabs is allowed to create an |  416   // If we've reached here, none of the parent tabs is allowed to create an | 
|  401   // instance. |  417   // instance. | 
|  402   return false; |  418   return false; | 
|  403 } |  419 } | 
|  404  |  420  | 
|  405 bool WorkerService::TabCanCreateWorkerProcess(int render_process_id, |  421 bool WorkerService::TabCanCreateWorkerProcess(int render_process_id, | 
|  406                                               int render_view_id, |  422                                               int render_view_id, | 
|  407                                               bool* hit_total_worker_limit) { |  423                                               bool* hit_total_worker_limit) { | 
 |  424   DCHECK(CalledOnValidThread()); | 
|  408   int total_workers = 0; |  425   int total_workers = 0; | 
|  409   int workers_per_tab = 0; |  426   int workers_per_tab = 0; | 
|  410   *hit_total_worker_limit = false; |  427   *hit_total_worker_limit = false; | 
|  411   for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); |  428   for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); | 
|  412        !iter.Done(); ++iter) { |  429        !iter.Done(); ++iter) { | 
|  413     WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); |  430     WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); | 
|  414     for (WorkerProcessHost::Instances::const_iterator cur_instance = |  431     for (WorkerProcessHost::Instances::const_iterator cur_instance = | 
|  415              worker->instances().begin(); |  432              worker->instances().begin(); | 
|  416          cur_instance != worker->instances().end(); ++cur_instance) { |  433          cur_instance != worker->instances().end(); ++cur_instance) { | 
|  417       total_workers++; |  434       total_workers++; | 
|  418       if (total_workers >= kMaxWorkersWhenSeparate) { |  435       if (total_workers >= kMaxWorkersWhenSeparate) { | 
|  419         *hit_total_worker_limit = true; |  436         *hit_total_worker_limit = true; | 
|  420         return false; |  437         return false; | 
|  421       } |  438       } | 
|  422       if (cur_instance->RendererIsParent(render_process_id, render_view_id)) { |  439       if (cur_instance->RendererIsParent(render_process_id, render_view_id)) { | 
|  423         workers_per_tab++; |  440         workers_per_tab++; | 
|  424         if (workers_per_tab >= kMaxWorkersPerTabWhenSeparate) |  441         if (workers_per_tab >= kMaxWorkersPerTabWhenSeparate) | 
|  425           return false; |  442           return false; | 
|  426       } |  443       } | 
|  427     } |  444     } | 
|  428   } |  445   } | 
|  429  |  446  | 
|  430   return true; |  447   return true; | 
|  431 } |  448 } | 
|  432  |  449  | 
|  433 void WorkerService::TryStartingQueuedWorker() { |  450 void WorkerService::TryStartingQueuedWorker() { | 
 |  451   DCHECK(CalledOnValidThread()); | 
|  434   if (queued_workers_.empty()) |  452   if (queued_workers_.empty()) | 
|  435     return; |  453     return; | 
|  436  |  454  | 
|  437   for (WorkerProcessHost::Instances::iterator i = queued_workers_.begin(); |  455   for (WorkerProcessHost::Instances::iterator i = queued_workers_.begin(); | 
|  438        i != queued_workers_.end();) { |  456        i != queued_workers_.end();) { | 
|  439     if (CanCreateWorkerProcess(*i)) { |  457     if (CanCreateWorkerProcess(*i)) { | 
|  440       WorkerProcessHost::WorkerInstance instance = *i; |  458       WorkerProcessHost::WorkerInstance instance = *i; | 
|  441       queued_workers_.erase(i); |  459       queued_workers_.erase(i); | 
|  442       CreateWorkerFromInstance(instance); |  460       CreateWorkerFromInstance(instance); | 
|  443  |  461  | 
|  444       // CreateWorkerFromInstance can modify the queued_workers_ list when it |  462       // CreateWorkerFromInstance can modify the queued_workers_ list when it | 
|  445       // coalesces queued instances after starting a shared worker, so we |  463       // coalesces queued instances after starting a shared worker, so we | 
|  446       // have to rescan the list from the beginning (our iterator is now |  464       // have to rescan the list from the beginning (our iterator is now | 
|  447       // invalid). This is not a big deal as having any queued workers will be |  465       // invalid). This is not a big deal as having any queued workers will be | 
|  448       // rare in practice so the list will be small. |  466       // rare in practice so the list will be small. | 
|  449       i = queued_workers_.begin(); |  467       i = queued_workers_.begin(); | 
|  450     } else { |  468     } else { | 
|  451       ++i; |  469       ++i; | 
|  452     } |  470     } | 
|  453   } |  471   } | 
|  454 } |  472 } | 
|  455  |  473  | 
|  456 bool WorkerService::GetRendererForWorker(int worker_process_id, |  474 bool WorkerService::GetRendererForWorker(int worker_process_id, | 
|  457                                          int* render_process_id, |  475                                          int* render_process_id, | 
|  458                                          int* render_view_id) const { |  476                                          int* render_view_id) const { | 
 |  477   DCHECK(CalledOnValidThread()); | 
|  459   for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); |  478   for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); | 
|  460        !iter.Done(); ++iter) { |  479        !iter.Done(); ++iter) { | 
|  461     if (iter->id() != worker_process_id) |  480     if (iter->id() != worker_process_id) | 
|  462         continue; |  481         continue; | 
|  463  |  482  | 
|  464     // This code assumes one worker per process, see function comment in header! |  483     // This code assumes one worker per process, see function comment in header! | 
|  465     WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); |  484     WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); | 
|  466     WorkerProcessHost::Instances::const_iterator first_instance = |  485     WorkerProcessHost::Instances::const_iterator first_instance = | 
|  467         worker->instances().begin(); |  486         worker->instances().begin(); | 
|  468     if (first_instance == worker->instances().end()) |  487     if (first_instance == worker->instances().end()) | 
|  469       return false; |  488       return false; | 
|  470  |  489  | 
|  471     WorkerDocumentSet::DocumentInfoSet::const_iterator info = |  490     WorkerDocumentSet::DocumentInfoSet::const_iterator info = | 
|  472         first_instance->worker_document_set()->documents().begin(); |  491         first_instance->worker_document_set()->documents().begin(); | 
|  473     *render_process_id = info->render_process_id(); |  492     *render_process_id = info->render_process_id(); | 
|  474     *render_view_id = info->render_view_id(); |  493     *render_view_id = info->render_view_id(); | 
|  475     return true; |  494     return true; | 
|  476   } |  495   } | 
|  477   return false; |  496   return false; | 
|  478 } |  497 } | 
|  479  |  498  | 
|  480 const WorkerProcessHost::WorkerInstance* WorkerService::FindWorkerInstance( |  499 const WorkerProcessHost::WorkerInstance* WorkerService::FindWorkerInstance( | 
|  481       int worker_process_id) { |  500       int worker_process_id) { | 
 |  501   DCHECK(CalledOnValidThread()); | 
|  482   for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); |  502   for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); | 
|  483        !iter.Done(); ++iter) { |  503        !iter.Done(); ++iter) { | 
|  484     if (iter->id() != worker_process_id) |  504     if (iter->id() != worker_process_id) | 
|  485         continue; |  505         continue; | 
|  486  |  506  | 
|  487     WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); |  507     WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); | 
|  488     WorkerProcessHost::Instances::const_iterator instance = |  508     WorkerProcessHost::Instances::const_iterator instance = | 
|  489         worker->instances().begin(); |  509         worker->instances().begin(); | 
|  490     return instance == worker->instances().end() ? NULL : &*instance; |  510     return instance == worker->instances().end() ? NULL : &*instance; | 
|  491   } |  511   } | 
|  492   return NULL; |  512   return NULL; | 
|  493 } |  513 } | 
|  494  |  514  | 
|  495 WorkerProcessHost::WorkerInstance* |  515 WorkerProcessHost::WorkerInstance* | 
|  496 WorkerService::FindSharedWorkerInstance(const GURL& url, const string16& name, |  516 WorkerService::FindSharedWorkerInstance(const GURL& url, const string16& name, | 
|  497                                         bool incognito) { |  517                                         bool incognito) { | 
 |  518   DCHECK(CalledOnValidThread()); | 
|  498   for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); |  519   for (BrowserChildProcessHost::Iterator iter(ChildProcessInfo::WORKER_PROCESS); | 
|  499        !iter.Done(); ++iter) { |  520        !iter.Done(); ++iter) { | 
|  500     WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); |  521     WorkerProcessHost* worker = static_cast<WorkerProcessHost*>(*iter); | 
|  501     for (WorkerProcessHost::Instances::iterator instance_iter = |  522     for (WorkerProcessHost::Instances::iterator instance_iter = | 
|  502              worker->mutable_instances().begin(); |  523              worker->mutable_instances().begin(); | 
|  503          instance_iter != worker->mutable_instances().end(); |  524          instance_iter != worker->mutable_instances().end(); | 
|  504          ++instance_iter) { |  525          ++instance_iter) { | 
|  505       if (instance_iter->Matches(url, name, incognito)) |  526       if (instance_iter->Matches(url, name, incognito)) | 
|  506         return &(*instance_iter); |  527         return &(*instance_iter); | 
|  507     } |  528     } | 
|  508   } |  529   } | 
|  509   return NULL; |  530   return NULL; | 
|  510 } |  531 } | 
|  511  |  532  | 
|  512 WorkerProcessHost::WorkerInstance* |  533 WorkerProcessHost::WorkerInstance* | 
|  513 WorkerService::FindPendingInstance(const GURL& url, const string16& name, |  534 WorkerService::FindPendingInstance(const GURL& url, const string16& name, | 
|  514                                    bool incognito) { |  535                                    bool incognito) { | 
 |  536   DCHECK(CalledOnValidThread()); | 
|  515   // Walk the pending instances looking for a matching pending worker. |  537   // Walk the pending instances looking for a matching pending worker. | 
|  516   for (WorkerProcessHost::Instances::iterator iter = |  538   for (WorkerProcessHost::Instances::iterator iter = | 
|  517            pending_shared_workers_.begin(); |  539            pending_shared_workers_.begin(); | 
|  518        iter != pending_shared_workers_.end(); |  540        iter != pending_shared_workers_.end(); | 
|  519        ++iter) { |  541        ++iter) { | 
|  520     if (iter->Matches(url, name, incognito)) { |  542     if (iter->Matches(url, name, incognito)) { | 
|  521       return &(*iter); |  543       return &(*iter); | 
|  522     } |  544     } | 
|  523   } |  545   } | 
|  524   return NULL; |  546   return NULL; | 
|  525 } |  547 } | 
|  526  |  548  | 
|  527  |  549  | 
|  528 void WorkerService::RemovePendingInstances(const GURL& url, |  550 void WorkerService::RemovePendingInstances(const GURL& url, | 
|  529                                            const string16& name, |  551                                            const string16& name, | 
|  530                                            bool incognito) { |  552                                            bool incognito) { | 
 |  553   DCHECK(CalledOnValidThread()); | 
|  531   // Walk the pending instances looking for a matching pending worker. |  554   // Walk the pending instances looking for a matching pending worker. | 
|  532   for (WorkerProcessHost::Instances::iterator iter = |  555   for (WorkerProcessHost::Instances::iterator iter = | 
|  533            pending_shared_workers_.begin(); |  556            pending_shared_workers_.begin(); | 
|  534        iter != pending_shared_workers_.end(); ) { |  557        iter != pending_shared_workers_.end(); ) { | 
|  535     if (iter->Matches(url, name, incognito)) { |  558     if (iter->Matches(url, name, incognito)) { | 
|  536       iter = pending_shared_workers_.erase(iter); |  559       iter = pending_shared_workers_.erase(iter); | 
|  537     } else { |  560     } else { | 
|  538       ++iter; |  561       ++iter; | 
|  539     } |  562     } | 
|  540   } |  563   } | 
|  541 } |  564 } | 
|  542  |  565  | 
|  543 WorkerProcessHost::WorkerInstance* |  566 WorkerProcessHost::WorkerInstance* | 
|  544 WorkerService::CreatePendingInstance(const GURL& url, |  567 WorkerService::CreatePendingInstance(const GURL& url, | 
|  545                                      const string16& name, |  568                                      const string16& name, | 
|  546                                      bool incognito) { |  569                                      bool incognito) { | 
 |  570   DCHECK(CalledOnValidThread()); | 
|  547   // Look for an existing pending shared worker. |  571   // Look for an existing pending shared worker. | 
|  548   WorkerProcessHost::WorkerInstance* instance = |  572   WorkerProcessHost::WorkerInstance* instance = | 
|  549       FindPendingInstance(url, name, incognito); |  573       FindPendingInstance(url, name, incognito); | 
|  550   if (instance) |  574   if (instance) | 
|  551     return instance; |  575     return instance; | 
|  552  |  576  | 
|  553   // No existing pending worker - create a new one. |  577   // No existing pending worker - create a new one. | 
|  554   WorkerProcessHost::WorkerInstance pending( |  578   WorkerProcessHost::WorkerInstance pending(url, true, incognito, name); | 
|  555       url, true, incognito, name, MSG_ROUTING_NONE, 0, 0, 0, NULL); |  | 
|  556   pending_shared_workers_.push_back(pending); |  579   pending_shared_workers_.push_back(pending); | 
|  557   return &pending_shared_workers_.back(); |  580   return &pending_shared_workers_.back(); | 
|  558 } |  581 } | 
| OLD | NEW |