Home | History | Annotate | Download | only in shared_worker
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "content/browser/shared_worker/shared_worker_service_impl.h"
      6 
      7 #include <algorithm>
      8 #include <iterator>
      9 #include <set>
     10 #include <vector>
     11 
     12 #include "base/callback.h"
     13 #include "base/memory/ref_counted.h"
     14 #include "content/browser/devtools/embedded_worker_devtools_manager.h"
     15 #include "content/browser/renderer_host/render_process_host_impl.h"
     16 #include "content/browser/shared_worker/shared_worker_host.h"
     17 #include "content/browser/shared_worker/shared_worker_instance.h"
     18 #include "content/browser/shared_worker/shared_worker_message_filter.h"
     19 #include "content/browser/shared_worker/worker_document_set.h"
     20 #include "content/common/view_messages.h"
     21 #include "content/common/worker_messages.h"
     22 #include "content/public/browser/browser_thread.h"
     23 #include "content/public/browser/worker_service_observer.h"
     24 
     25 namespace content {
     26 
     27 WorkerService* WorkerService::GetInstance() {
     28   return SharedWorkerServiceImpl::GetInstance();
     29 }
     30 
     31 namespace {
     32 
     33 class ScopedWorkerDependencyChecker {
     34  public:
     35   explicit ScopedWorkerDependencyChecker(SharedWorkerServiceImpl* service)
     36       : service_(service) {}
     37   ScopedWorkerDependencyChecker(SharedWorkerServiceImpl* service,
     38                                 base::Closure done_closure)
     39       : service_(service), done_closure_(done_closure) {}
     40   ~ScopedWorkerDependencyChecker() {
     41     service_->CheckWorkerDependency();
     42     if (!done_closure_.is_null())
     43       done_closure_.Run();
     44   }
     45 
     46  private:
     47   SharedWorkerServiceImpl* service_;
     48   base::Closure done_closure_;
     49   DISALLOW_COPY_AND_ASSIGN(ScopedWorkerDependencyChecker);
     50 };
     51 
     52 void UpdateWorkerDependencyOnUI(const std::vector<int>& added_ids,
     53                                 const std::vector<int>& removed_ids) {
     54   for (size_t i = 0; i < added_ids.size(); ++i) {
     55     RenderProcessHostImpl* render_process_host_impl =
     56         static_cast<RenderProcessHostImpl*>(
     57             RenderProcessHost::FromID(added_ids[i]));
     58     if (!render_process_host_impl)
     59       continue;
     60     render_process_host_impl->IncrementWorkerRefCount();
     61   }
     62   for (size_t i = 0; i < removed_ids.size(); ++i) {
     63     RenderProcessHostImpl* render_process_host_impl =
     64         static_cast<RenderProcessHostImpl*>(
     65             RenderProcessHost::FromID(removed_ids[i]));
     66     if (!render_process_host_impl)
     67       continue;
     68     render_process_host_impl->DecrementWorkerRefCount();
     69   }
     70 }
     71 
     72 void UpdateWorkerDependency(const std::vector<int>& added_ids,
     73                             const std::vector<int>& removed_ids) {
     74   BrowserThread::PostTask(
     75       BrowserThread::UI,
     76       FROM_HERE,
     77       base::Bind(&UpdateWorkerDependencyOnUI, added_ids, removed_ids));
     78 }
     79 
     80 void DecrementWorkerRefCount(int process_id) {
     81   if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
     82     BrowserThread::PostTask(BrowserThread::UI,
     83                             FROM_HERE,
     84                             base::Bind(&DecrementWorkerRefCount, process_id));
     85     return;
     86   }
     87   RenderProcessHostImpl* render_process_host_impl =
     88       static_cast<RenderProcessHostImpl*>(
     89           RenderProcessHost::FromID(process_id));
     90   if (render_process_host_impl)
     91     render_process_host_impl->DecrementWorkerRefCount();
     92 }
     93 
     94 bool TryIncrementWorkerRefCount(int worker_process_id) {
     95   RenderProcessHostImpl* render_process = static_cast<RenderProcessHostImpl*>(
     96       RenderProcessHost::FromID(worker_process_id));
     97   if (!render_process || render_process->FastShutdownStarted()) {
     98     return false;
     99   }
    100   render_process->IncrementWorkerRefCount();
    101   return true;
    102 }
    103 
    104 }  // namespace
    105 
    106 class SharedWorkerServiceImpl::SharedWorkerPendingInstance {
    107  public:
    108   struct SharedWorkerPendingRequest {
    109     SharedWorkerPendingRequest(SharedWorkerMessageFilter* filter,
    110                                int route_id,
    111                                unsigned long long document_id,
    112                                int render_process_id,
    113                                int render_frame_route_id)
    114         : filter(filter),
    115           route_id(route_id),
    116           document_id(document_id),
    117           render_process_id(render_process_id),
    118           render_frame_route_id(render_frame_route_id) {}
    119     SharedWorkerMessageFilter* const filter;
    120     const int route_id;
    121     const unsigned long long document_id;
    122     const int render_process_id;
    123     const int render_frame_route_id;
    124   };
    125 
    126   typedef ScopedVector<SharedWorkerPendingRequest> SharedWorkerPendingRequests;
    127 
    128   explicit SharedWorkerPendingInstance(
    129       scoped_ptr<SharedWorkerInstance> instance)
    130       : instance_(instance.Pass()) {}
    131   ~SharedWorkerPendingInstance() {}
    132   SharedWorkerInstance* instance() { return instance_.get(); }
    133   SharedWorkerInstance* release_instance() { return instance_.release(); }
    134   SharedWorkerPendingRequests* requests() { return &requests_; }
    135   SharedWorkerMessageFilter* FindFilter(int process_id) {
    136     for (size_t i = 0; i < requests_.size(); ++i) {
    137       if (requests_[i]->render_process_id == process_id)
    138         return requests_[i]->filter;
    139     }
    140     return NULL;
    141   }
    142   void AddRequest(scoped_ptr<SharedWorkerPendingRequest> request_info) {
    143     requests_.push_back(request_info.release());
    144   }
    145   void RemoveRequest(int process_id) {
    146     for (SharedWorkerPendingRequests::iterator request_itr = requests_.begin();
    147          request_itr != requests_.end();) {
    148       if ((*request_itr)->render_process_id == process_id)
    149         request_itr = requests_.erase(request_itr);
    150       else
    151         ++request_itr;
    152     }
    153   }
    154   void RegisterToSharedWorkerHost(SharedWorkerHost* host) {
    155     for (size_t i = 0; i < requests_.size(); ++i) {
    156       SharedWorkerPendingRequest* request = requests_[i];
    157       host->AddFilter(request->filter, request->route_id);
    158       host->worker_document_set()->Add(request->filter,
    159                                        request->document_id,
    160                                        request->render_process_id,
    161                                        request->render_frame_route_id);
    162     }
    163   }
    164   void SendWorkerCreatedMessages() {
    165     for (size_t i = 0; i < requests_.size(); ++i) {
    166       SharedWorkerPendingRequest* request = requests_[i];
    167       request->filter->Send(new ViewMsg_WorkerCreated(request->route_id));
    168     }
    169   }
    170 
    171  private:
    172   scoped_ptr<SharedWorkerInstance> instance_;
    173   SharedWorkerPendingRequests requests_;
    174   DISALLOW_COPY_AND_ASSIGN(SharedWorkerPendingInstance);
    175 };
    176 
    177 class SharedWorkerServiceImpl::SharedWorkerReserver
    178     : public base::RefCountedThreadSafe<SharedWorkerReserver> {
    179  public:
    180   SharedWorkerReserver(int pending_instance_id,
    181                        int worker_process_id,
    182                        int worker_route_id,
    183                        bool is_new_worker,
    184                        const SharedWorkerInstance& instance)
    185       : worker_process_id_(worker_process_id),
    186         worker_route_id_(worker_route_id),
    187         is_new_worker_(is_new_worker),
    188         instance_(instance) {}
    189 
    190   void TryReserve(const base::Callback<void(bool)>& success_cb,
    191                   const base::Closure& failure_cb,
    192                   bool (*try_increment_worker_ref_count)(int)) {
    193     DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
    194     if (!try_increment_worker_ref_count(worker_process_id_)) {
    195       BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, failure_cb);
    196       return;
    197     }
    198     bool pause_on_start = false;
    199     if (is_new_worker_) {
    200       pause_on_start =
    201           EmbeddedWorkerDevToolsManager::GetInstance()->SharedWorkerCreated(
    202               worker_process_id_, worker_route_id_, instance_);
    203     }
    204     BrowserThread::PostTask(
    205         BrowserThread::IO, FROM_HERE, base::Bind(success_cb, pause_on_start));
    206   }
    207 
    208  private:
    209   friend class base::RefCountedThreadSafe<SharedWorkerReserver>;
    210   ~SharedWorkerReserver() {}
    211 
    212   const int worker_process_id_;
    213   const int worker_route_id_;
    214   const bool is_new_worker_;
    215   const SharedWorkerInstance instance_;
    216 };
    217 
    218 // static
    219 bool (*SharedWorkerServiceImpl::s_try_increment_worker_ref_count_)(int) =
    220     TryIncrementWorkerRefCount;
    221 
    222 SharedWorkerServiceImpl* SharedWorkerServiceImpl::GetInstance() {
    223   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    224   return Singleton<SharedWorkerServiceImpl>::get();
    225 }
    226 
    227 SharedWorkerServiceImpl::SharedWorkerServiceImpl()
    228     : update_worker_dependency_(UpdateWorkerDependency),
    229       next_pending_instance_id_(0) {
    230 }
    231 
    232 SharedWorkerServiceImpl::~SharedWorkerServiceImpl() {}
    233 
    234 void SharedWorkerServiceImpl::ResetForTesting() {
    235   last_worker_depended_renderers_.clear();
    236   worker_hosts_.clear();
    237   observers_.Clear();
    238   update_worker_dependency_ = UpdateWorkerDependency;
    239   s_try_increment_worker_ref_count_ = TryIncrementWorkerRefCount;
    240 }
    241 
    242 bool SharedWorkerServiceImpl::TerminateWorker(int process_id, int route_id) {
    243   SharedWorkerHost* host =
    244       worker_hosts_.get(std::make_pair(process_id, route_id));
    245   if (!host || !host->instance())
    246     return false;
    247   host->TerminateWorker();
    248   return true;
    249 }
    250 
    251 std::vector<WorkerService::WorkerInfo> SharedWorkerServiceImpl::GetWorkers() {
    252   std::vector<WorkerService::WorkerInfo> results;
    253   for (WorkerHostMap::const_iterator iter = worker_hosts_.begin();
    254        iter != worker_hosts_.end();
    255        ++iter) {
    256     SharedWorkerHost* host = iter->second;
    257     const SharedWorkerInstance* instance = host->instance();
    258     if (instance) {
    259       WorkerService::WorkerInfo info;
    260       info.url = instance->url();
    261       info.name = instance->name();
    262       info.route_id = host->worker_route_id();
    263       info.process_id = host->process_id();
    264       info.handle = host->container_render_filter()->PeerHandle();
    265       results.push_back(info);
    266     }
    267   }
    268   return results;
    269 }
    270 
    271 void SharedWorkerServiceImpl::AddObserver(WorkerServiceObserver* observer) {
    272   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    273   observers_.AddObserver(observer);
    274 }
    275 
    276 void SharedWorkerServiceImpl::RemoveObserver(WorkerServiceObserver* observer) {
    277   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    278   observers_.RemoveObserver(observer);
    279 }
    280 
    281 void SharedWorkerServiceImpl::CreateWorker(
    282     const ViewHostMsg_CreateWorker_Params& params,
    283     int route_id,
    284     SharedWorkerMessageFilter* filter,
    285     ResourceContext* resource_context,
    286     const WorkerStoragePartitionId& partition_id,
    287     bool* url_mismatch) {
    288   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    289   *url_mismatch = false;
    290   scoped_ptr<SharedWorkerInstance> instance(
    291       new SharedWorkerInstance(params.url,
    292                                params.name,
    293                                params.content_security_policy,
    294                                params.security_policy_type,
    295                                resource_context,
    296                                partition_id));
    297   scoped_ptr<SharedWorkerPendingInstance::SharedWorkerPendingRequest> request(
    298       new SharedWorkerPendingInstance::SharedWorkerPendingRequest(
    299           filter,
    300           route_id,
    301           params.document_id,
    302           filter->render_process_id(),
    303           params.render_frame_route_id));
    304   if (SharedWorkerPendingInstance* pending = FindPendingInstance(*instance)) {
    305     if (params.url != pending->instance()->url()) {
    306       *url_mismatch = true;
    307       return;
    308     }
    309     pending->AddRequest(request.Pass());
    310     return;
    311   }
    312   scoped_ptr<SharedWorkerPendingInstance> pending_instance(
    313       new SharedWorkerPendingInstance(instance.Pass()));
    314   pending_instance->AddRequest(request.Pass());
    315   ReserveRenderProcessToCreateWorker(pending_instance.Pass(), url_mismatch);
    316 }
    317 
    318 void SharedWorkerServiceImpl::ForwardToWorker(
    319     const IPC::Message& message,
    320     SharedWorkerMessageFilter* filter) {
    321   for (WorkerHostMap::const_iterator iter = worker_hosts_.begin();
    322        iter != worker_hosts_.end();
    323        ++iter) {
    324     if (iter->second->FilterMessage(message, filter))
    325       return;
    326   }
    327 }
    328 
    329 void SharedWorkerServiceImpl::DocumentDetached(
    330     unsigned long long document_id,
    331     SharedWorkerMessageFilter* filter) {
    332   ScopedWorkerDependencyChecker checker(this);
    333   for (WorkerHostMap::const_iterator iter = worker_hosts_.begin();
    334        iter != worker_hosts_.end();
    335        ++iter) {
    336     iter->second->DocumentDetached(filter, document_id);
    337   }
    338 }
    339 
    340 void SharedWorkerServiceImpl::WorkerContextClosed(
    341     int worker_route_id,
    342     SharedWorkerMessageFilter* filter) {
    343   ScopedWorkerDependencyChecker checker(this);
    344   if (SharedWorkerHost* host = FindSharedWorkerHost(filter, worker_route_id))
    345     host->WorkerContextClosed();
    346 }
    347 
    348 void SharedWorkerServiceImpl::WorkerContextDestroyed(
    349     int worker_route_id,
    350     SharedWorkerMessageFilter* filter) {
    351   ScopedWorkerDependencyChecker checker(this);
    352   scoped_ptr<SharedWorkerHost> host =
    353       worker_hosts_.take_and_erase(std::make_pair(filter->render_process_id(),
    354                                                   worker_route_id));
    355   if (!host)
    356     return;
    357   host->WorkerContextDestroyed();
    358 }
    359 
    360 void SharedWorkerServiceImpl::WorkerReadyForInspection(
    361     int worker_route_id,
    362     SharedWorkerMessageFilter* filter) {
    363   if (SharedWorkerHost* host = FindSharedWorkerHost(filter, worker_route_id))
    364     host->WorkerReadyForInspection();
    365 }
    366 
    367 void SharedWorkerServiceImpl::WorkerScriptLoaded(
    368     int worker_route_id,
    369     SharedWorkerMessageFilter* filter) {
    370   if (SharedWorkerHost* host = FindSharedWorkerHost(filter, worker_route_id))
    371     host->WorkerScriptLoaded();
    372 }
    373 
    374 void SharedWorkerServiceImpl::WorkerScriptLoadFailed(
    375     int worker_route_id,
    376     SharedWorkerMessageFilter* filter) {
    377   ScopedWorkerDependencyChecker checker(this);
    378   scoped_ptr<SharedWorkerHost> host =
    379       worker_hosts_.take_and_erase(std::make_pair(filter->render_process_id(),
    380                                                   worker_route_id));
    381   if (!host)
    382     return;
    383   host->WorkerScriptLoadFailed();
    384 }
    385 
    386 void SharedWorkerServiceImpl::WorkerConnected(
    387     int message_port_id,
    388     int worker_route_id,
    389     SharedWorkerMessageFilter* filter) {
    390   if (SharedWorkerHost* host = FindSharedWorkerHost(filter, worker_route_id))
    391     host->WorkerConnected(message_port_id);
    392 }
    393 
    394 void SharedWorkerServiceImpl::AllowDatabase(
    395     int worker_route_id,
    396     const GURL& url,
    397     const base::string16& name,
    398     const base::string16& display_name,
    399     unsigned long estimated_size,
    400     bool* result,
    401     SharedWorkerMessageFilter* filter) {
    402   if (SharedWorkerHost* host = FindSharedWorkerHost(filter, worker_route_id))
    403     host->AllowDatabase(url, name, display_name, estimated_size, result);
    404 }
    405 
    406 void SharedWorkerServiceImpl::AllowFileSystem(
    407     int worker_route_id,
    408     const GURL& url,
    409     IPC::Message* reply_msg,
    410     SharedWorkerMessageFilter* filter) {
    411   if (SharedWorkerHost* host = FindSharedWorkerHost(filter, worker_route_id)) {
    412     host->AllowFileSystem(url, make_scoped_ptr(reply_msg));
    413   } else {
    414     filter->Send(reply_msg);
    415     return;
    416   }
    417 }
    418 
    419 void SharedWorkerServiceImpl::AllowIndexedDB(
    420     int worker_route_id,
    421     const GURL& url,
    422     const base::string16& name,
    423     bool* result,
    424     SharedWorkerMessageFilter* filter) {
    425   if (SharedWorkerHost* host = FindSharedWorkerHost(filter, worker_route_id))
    426     host->AllowIndexedDB(url, name, result);
    427 }
    428 
    429 void SharedWorkerServiceImpl::OnSharedWorkerMessageFilterClosing(
    430     SharedWorkerMessageFilter* filter) {
    431   ScopedWorkerDependencyChecker checker(this);
    432   std::vector<ProcessRouteIdPair> remove_list;
    433   for (WorkerHostMap::iterator iter = worker_hosts_.begin();
    434        iter != worker_hosts_.end();
    435        ++iter) {
    436     iter->second->FilterShutdown(filter);
    437     if (iter->first.first == filter->render_process_id())
    438       remove_list.push_back(iter->first);
    439   }
    440   for (size_t i = 0; i < remove_list.size(); ++i) {
    441     scoped_ptr<SharedWorkerHost> host =
    442         worker_hosts_.take_and_erase(remove_list[i]);
    443   }
    444 
    445   std::vector<int> remove_pending_instance_list;
    446   for (PendingInstaneMap::iterator iter = pending_instances_.begin();
    447        iter != pending_instances_.end();
    448        ++iter) {
    449     iter->second->RemoveRequest(filter->render_process_id());
    450     if (!iter->second->requests()->size())
    451       remove_pending_instance_list.push_back(iter->first);
    452   }
    453   for (size_t i = 0; i < remove_pending_instance_list.size(); ++i)
    454     pending_instances_.take_and_erase(remove_pending_instance_list[i]);
    455 }
    456 
    457 void SharedWorkerServiceImpl::NotifyWorkerDestroyed(int worker_process_id,
    458                                                     int worker_route_id) {
    459   FOR_EACH_OBSERVER(WorkerServiceObserver,
    460                     observers_,
    461                     WorkerDestroyed(worker_process_id, worker_route_id));
    462 }
    463 
    464 void SharedWorkerServiceImpl::ReserveRenderProcessToCreateWorker(
    465     scoped_ptr<SharedWorkerPendingInstance> pending_instance,
    466     bool* url_mismatch) {
    467   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    468   DCHECK(!FindPendingInstance(*pending_instance->instance()));
    469   if (url_mismatch)
    470     *url_mismatch = false;
    471   if (!pending_instance->requests()->size())
    472     return;
    473   int worker_process_id = -1;
    474   int worker_route_id = MSG_ROUTING_NONE;
    475   bool is_new_worker = true;
    476   SharedWorkerHost* host = FindSharedWorkerHost(*pending_instance->instance());
    477   if (host) {
    478     if (pending_instance->instance()->url() != host->instance()->url()) {
    479       if (url_mismatch)
    480         *url_mismatch = true;
    481       return;
    482     }
    483     worker_process_id = host->process_id();
    484     worker_route_id = host->worker_route_id();
    485     is_new_worker = false;
    486   } else {
    487     SharedWorkerMessageFilter* first_filter =
    488         (*pending_instance->requests()->begin())->filter;
    489     worker_process_id = first_filter->render_process_id();
    490     worker_route_id = first_filter->GetNextRoutingID();
    491   }
    492   const int pending_instance_id = next_pending_instance_id_++;
    493   scoped_refptr<SharedWorkerReserver> reserver(
    494       new SharedWorkerReserver(pending_instance_id,
    495                                worker_process_id,
    496                                worker_route_id,
    497                                is_new_worker,
    498                                *pending_instance->instance()));
    499   BrowserThread::PostTask(
    500       BrowserThread::UI,
    501       FROM_HERE,
    502       base::Bind(
    503           &SharedWorkerReserver::TryReserve,
    504           reserver,
    505           base::Bind(&SharedWorkerServiceImpl::RenderProcessReservedCallback,
    506                      base::Unretained(this),
    507                      pending_instance_id,
    508                      worker_process_id,
    509                      worker_route_id,
    510                      is_new_worker),
    511           base::Bind(
    512               &SharedWorkerServiceImpl::RenderProcessReserveFailedCallback,
    513               base::Unretained(this),
    514               pending_instance_id,
    515               worker_process_id,
    516               worker_route_id,
    517               is_new_worker),
    518           s_try_increment_worker_ref_count_));
    519   pending_instances_.set(pending_instance_id, pending_instance.Pass());
    520 }
    521 
    522 void SharedWorkerServiceImpl::RenderProcessReservedCallback(
    523     int pending_instance_id,
    524     int worker_process_id,
    525     int worker_route_id,
    526     bool is_new_worker,
    527     bool pause_on_start) {
    528   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    529   // To offset the TryIncrementWorkerRefCount called for the reservation,
    530   // calls DecrementWorkerRefCount after CheckWorkerDependency in
    531   // ScopeWorkerDependencyChecker's destructor.
    532   ScopedWorkerDependencyChecker checker(
    533       this, base::Bind(&DecrementWorkerRefCount, worker_process_id));
    534   scoped_ptr<SharedWorkerPendingInstance> pending_instance =
    535       pending_instances_.take_and_erase(pending_instance_id);
    536   if (!pending_instance)
    537     return;
    538   if (!is_new_worker) {
    539     SharedWorkerHost* existing_host =
    540         worker_hosts_.get(std::make_pair(worker_process_id, worker_route_id));
    541     if (!existing_host) {
    542       // Retry reserving a renderer process if the existed Shared Worker was
    543       // destroyed on IO thread while reserving the renderer process on UI
    544       // thread.
    545       ReserveRenderProcessToCreateWorker(pending_instance.Pass(), NULL);
    546       return;
    547     }
    548     pending_instance->RegisterToSharedWorkerHost(existing_host);
    549     pending_instance->SendWorkerCreatedMessages();
    550     return;
    551   }
    552   SharedWorkerMessageFilter* filter =
    553       pending_instance->FindFilter(worker_process_id);
    554   if (!filter) {
    555     pending_instance->RemoveRequest(worker_process_id);
    556     // Retry reserving a renderer process if the requested renderer process was
    557     // destroyed on IO thread while reserving the renderer process on UI thread.
    558     ReserveRenderProcessToCreateWorker(pending_instance.Pass(), NULL);
    559     return;
    560   }
    561   scoped_ptr<SharedWorkerHost> host(new SharedWorkerHost(
    562       pending_instance->release_instance(), filter, worker_route_id));
    563   pending_instance->RegisterToSharedWorkerHost(host.get());
    564   const GURL url = host->instance()->url();
    565   const base::string16 name = host->instance()->name();
    566   host->Start(pause_on_start);
    567   worker_hosts_.set(std::make_pair(worker_process_id, worker_route_id),
    568                     host.Pass());
    569   FOR_EACH_OBSERVER(
    570       WorkerServiceObserver,
    571       observers_,
    572       WorkerCreated(url, name, worker_process_id, worker_route_id));
    573 }
    574 
    575 void SharedWorkerServiceImpl::RenderProcessReserveFailedCallback(
    576     int pending_instance_id,
    577     int worker_process_id,
    578     int worker_route_id,
    579     bool is_new_worker) {
    580   worker_hosts_.take_and_erase(
    581       std::make_pair(worker_process_id, worker_route_id));
    582   scoped_ptr<SharedWorkerPendingInstance> pending_instance =
    583       pending_instances_.take_and_erase(pending_instance_id);
    584   if (!pending_instance)
    585     return;
    586   pending_instance->RemoveRequest(worker_process_id);
    587   // Retry reserving a renderer process.
    588   ReserveRenderProcessToCreateWorker(pending_instance.Pass(), NULL);
    589 }
    590 
    591 SharedWorkerHost* SharedWorkerServiceImpl::FindSharedWorkerHost(
    592     SharedWorkerMessageFilter* filter,
    593     int worker_route_id) {
    594   return worker_hosts_.get(std::make_pair(filter->render_process_id(),
    595                                           worker_route_id));
    596 }
    597 
    598 SharedWorkerHost* SharedWorkerServiceImpl::FindSharedWorkerHost(
    599     const SharedWorkerInstance& instance) {
    600   for (WorkerHostMap::const_iterator iter = worker_hosts_.begin();
    601        iter != worker_hosts_.end();
    602        ++iter) {
    603     SharedWorkerHost* host = iter->second;
    604     if (host->instance() && !host->closed() &&
    605         host->instance()->Matches(instance)) {
    606       return iter->second;
    607     }
    608   }
    609   return NULL;
    610 }
    611 
    612 SharedWorkerServiceImpl::SharedWorkerPendingInstance*
    613 SharedWorkerServiceImpl::FindPendingInstance(
    614     const SharedWorkerInstance& instance) {
    615   for (PendingInstaneMap::iterator iter = pending_instances_.begin();
    616        iter != pending_instances_.end();
    617        ++iter) {
    618     if (iter->second->instance()->Matches(instance))
    619       return iter->second;
    620   }
    621   return NULL;
    622 }
    623 
    624 const std::set<int>
    625 SharedWorkerServiceImpl::GetRenderersWithWorkerDependency() {
    626   std::set<int> dependent_renderers;
    627   for (WorkerHostMap::iterator host_iter = worker_hosts_.begin();
    628        host_iter != worker_hosts_.end();
    629        ++host_iter) {
    630     const int process_id = host_iter->first.first;
    631     if (dependent_renderers.count(process_id))
    632       continue;
    633     if (host_iter->second->instance() &&
    634         host_iter->second->worker_document_set()->ContainsExternalRenderer(
    635             process_id)) {
    636       dependent_renderers.insert(process_id);
    637     }
    638   }
    639   return dependent_renderers;
    640 }
    641 
    642 void SharedWorkerServiceImpl::CheckWorkerDependency() {
    643   const std::set<int> current_worker_depended_renderers =
    644       GetRenderersWithWorkerDependency();
    645   std::vector<int> added_items = base::STLSetDifference<std::vector<int> >(
    646       current_worker_depended_renderers, last_worker_depended_renderers_);
    647   std::vector<int> removed_items = base::STLSetDifference<std::vector<int> >(
    648       last_worker_depended_renderers_, current_worker_depended_renderers);
    649   if (!added_items.empty() || !removed_items.empty()) {
    650     last_worker_depended_renderers_ = current_worker_depended_renderers;
    651     update_worker_dependency_(added_items, removed_items);
    652   }
    653 }
    654 
    655 void SharedWorkerServiceImpl::ChangeUpdateWorkerDependencyFuncForTesting(
    656     UpdateWorkerDependencyFunc new_func) {
    657   update_worker_dependency_ = new_func;
    658 }
    659 
    660 void SharedWorkerServiceImpl::ChangeTryIncrementWorkerRefCountFuncForTesting(
    661     bool (*new_func)(int)) {
    662   s_try_increment_worker_ref_count_ = new_func;
    663 }
    664 
    665 }  // namespace content
    666