Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / content / browser / shared_worker / shared_worker_service_impl.cc
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::WorkerScriptLoaded(
361     int worker_route_id,
362     SharedWorkerMessageFilter* filter) {
363   if (SharedWorkerHost* host = FindSharedWorkerHost(filter, worker_route_id))
364     host->WorkerScriptLoaded();
365 }
366
367 void SharedWorkerServiceImpl::WorkerScriptLoadFailed(
368     int worker_route_id,
369     SharedWorkerMessageFilter* filter) {
370   ScopedWorkerDependencyChecker checker(this);
371   scoped_ptr<SharedWorkerHost> host =
372       worker_hosts_.take_and_erase(std::make_pair(filter->render_process_id(),
373                                                   worker_route_id));
374   if (!host)
375     return;
376   host->WorkerScriptLoadFailed();
377 }
378
379 void SharedWorkerServiceImpl::WorkerConnected(
380     int message_port_id,
381     int worker_route_id,
382     SharedWorkerMessageFilter* filter) {
383   if (SharedWorkerHost* host = FindSharedWorkerHost(filter, worker_route_id))
384     host->WorkerConnected(message_port_id);
385 }
386
387 void SharedWorkerServiceImpl::AllowDatabase(
388     int worker_route_id,
389     const GURL& url,
390     const base::string16& name,
391     const base::string16& display_name,
392     unsigned long estimated_size,
393     bool* result,
394     SharedWorkerMessageFilter* filter) {
395   if (SharedWorkerHost* host = FindSharedWorkerHost(filter, worker_route_id))
396     host->AllowDatabase(url, name, display_name, estimated_size, result);
397 }
398
399 void SharedWorkerServiceImpl::AllowFileSystem(
400     int worker_route_id,
401     const GURL& url,
402     IPC::Message* reply_msg,
403     SharedWorkerMessageFilter* filter) {
404   if (SharedWorkerHost* host = FindSharedWorkerHost(filter, worker_route_id)) {
405     host->AllowFileSystem(url, make_scoped_ptr(reply_msg));
406   } else {
407     filter->Send(reply_msg);
408     return;
409   }
410 }
411
412 void SharedWorkerServiceImpl::AllowIndexedDB(
413     int worker_route_id,
414     const GURL& url,
415     const base::string16& name,
416     bool* result,
417     SharedWorkerMessageFilter* filter) {
418   if (SharedWorkerHost* host = FindSharedWorkerHost(filter, worker_route_id))
419     host->AllowIndexedDB(url, name, result);
420 }
421
422 void SharedWorkerServiceImpl::OnSharedWorkerMessageFilterClosing(
423     SharedWorkerMessageFilter* filter) {
424   ScopedWorkerDependencyChecker checker(this);
425   std::vector<ProcessRouteIdPair> remove_list;
426   for (WorkerHostMap::iterator iter = worker_hosts_.begin();
427        iter != worker_hosts_.end();
428        ++iter) {
429     iter->second->FilterShutdown(filter);
430     if (iter->first.first == filter->render_process_id())
431       remove_list.push_back(iter->first);
432   }
433   for (size_t i = 0; i < remove_list.size(); ++i) {
434     scoped_ptr<SharedWorkerHost> host =
435         worker_hosts_.take_and_erase(remove_list[i]);
436   }
437
438   std::vector<int> remove_pending_instance_list;
439   for (PendingInstaneMap::iterator iter = pending_instances_.begin();
440        iter != pending_instances_.end();
441        ++iter) {
442     iter->second->RemoveRequest(filter->render_process_id());
443     if (!iter->second->requests()->size())
444       remove_pending_instance_list.push_back(iter->first);
445   }
446   for (size_t i = 0; i < remove_pending_instance_list.size(); ++i)
447     pending_instances_.take_and_erase(remove_pending_instance_list[i]);
448 }
449
450 void SharedWorkerServiceImpl::NotifyWorkerDestroyed(int worker_process_id,
451                                                     int worker_route_id) {
452   FOR_EACH_OBSERVER(WorkerServiceObserver,
453                     observers_,
454                     WorkerDestroyed(worker_process_id, worker_route_id));
455 }
456
457 void SharedWorkerServiceImpl::ReserveRenderProcessToCreateWorker(
458     scoped_ptr<SharedWorkerPendingInstance> pending_instance,
459     bool* url_mismatch) {
460   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
461   DCHECK(!FindPendingInstance(*pending_instance->instance()));
462   if (url_mismatch)
463     *url_mismatch = false;
464   if (!pending_instance->requests()->size())
465     return;
466   int worker_process_id = -1;
467   int worker_route_id = MSG_ROUTING_NONE;
468   bool is_new_worker = true;
469   SharedWorkerHost* host = FindSharedWorkerHost(*pending_instance->instance());
470   if (host) {
471     if (pending_instance->instance()->url() != host->instance()->url()) {
472       if (url_mismatch)
473         *url_mismatch = true;
474       return;
475     }
476     worker_process_id = host->process_id();
477     worker_route_id = host->worker_route_id();
478     is_new_worker = false;
479   } else {
480     SharedWorkerMessageFilter* first_filter =
481         (*pending_instance->requests()->begin())->filter;
482     worker_process_id = first_filter->render_process_id();
483     worker_route_id = first_filter->GetNextRoutingID();
484   }
485   const int pending_instance_id = next_pending_instance_id_++;
486   scoped_refptr<SharedWorkerReserver> reserver(
487       new SharedWorkerReserver(pending_instance_id,
488                                worker_process_id,
489                                worker_route_id,
490                                is_new_worker,
491                                *pending_instance->instance()));
492   BrowserThread::PostTask(
493       BrowserThread::UI,
494       FROM_HERE,
495       base::Bind(
496           &SharedWorkerReserver::TryReserve,
497           reserver,
498           base::Bind(&SharedWorkerServiceImpl::RenderProcessReservedCallback,
499                      base::Unretained(this),
500                      pending_instance_id,
501                      worker_process_id,
502                      worker_route_id,
503                      is_new_worker),
504           base::Bind(
505               &SharedWorkerServiceImpl::RenderProcessReserveFailedCallback,
506               base::Unretained(this),
507               pending_instance_id,
508               worker_process_id,
509               worker_route_id,
510               is_new_worker),
511           s_try_increment_worker_ref_count_));
512   pending_instances_.set(pending_instance_id, pending_instance.Pass());
513 }
514
515 void SharedWorkerServiceImpl::RenderProcessReservedCallback(
516     int pending_instance_id,
517     int worker_process_id,
518     int worker_route_id,
519     bool is_new_worker,
520     bool pause_on_start) {
521   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
522   // To offset the TryIncrementWorkerRefCount called for the reservation,
523   // calls DecrementWorkerRefCount after CheckWorkerDependency in
524   // ScopeWorkerDependencyChecker's destructor.
525   ScopedWorkerDependencyChecker checker(
526       this, base::Bind(&DecrementWorkerRefCount, worker_process_id));
527   scoped_ptr<SharedWorkerPendingInstance> pending_instance =
528       pending_instances_.take_and_erase(pending_instance_id);
529   if (!pending_instance)
530     return;
531   if (!is_new_worker) {
532     SharedWorkerHost* existing_host =
533         worker_hosts_.get(std::make_pair(worker_process_id, worker_route_id));
534     if (!existing_host) {
535       // Retry reserving a renderer process if the existed Shared Worker was
536       // destroyed on IO thread while reserving the renderer process on UI
537       // thread.
538       ReserveRenderProcessToCreateWorker(pending_instance.Pass(), NULL);
539       return;
540     }
541     pending_instance->RegisterToSharedWorkerHost(existing_host);
542     pending_instance->SendWorkerCreatedMessages();
543     return;
544   }
545   SharedWorkerMessageFilter* filter =
546       pending_instance->FindFilter(worker_process_id);
547   if (!filter) {
548     pending_instance->RemoveRequest(worker_process_id);
549     // Retry reserving a renderer process if the requested renderer process was
550     // destroyed on IO thread while reserving the renderer process on UI thread.
551     ReserveRenderProcessToCreateWorker(pending_instance.Pass(), NULL);
552     return;
553   }
554   scoped_ptr<SharedWorkerHost> host(new SharedWorkerHost(
555       pending_instance->release_instance(), filter, worker_route_id));
556   pending_instance->RegisterToSharedWorkerHost(host.get());
557   const GURL url = host->instance()->url();
558   const base::string16 name = host->instance()->name();
559   host->Start(pause_on_start);
560   worker_hosts_.set(std::make_pair(worker_process_id, worker_route_id),
561                     host.Pass());
562   FOR_EACH_OBSERVER(
563       WorkerServiceObserver,
564       observers_,
565       WorkerCreated(url, name, worker_process_id, worker_route_id));
566 }
567
568 void SharedWorkerServiceImpl::RenderProcessReserveFailedCallback(
569     int pending_instance_id,
570     int worker_process_id,
571     int worker_route_id,
572     bool is_new_worker) {
573   worker_hosts_.take_and_erase(
574       std::make_pair(worker_process_id, worker_route_id));
575   scoped_ptr<SharedWorkerPendingInstance> pending_instance =
576       pending_instances_.take_and_erase(pending_instance_id);
577   if (!pending_instance)
578     return;
579   pending_instance->RemoveRequest(worker_process_id);
580   // Retry reserving a renderer process.
581   ReserveRenderProcessToCreateWorker(pending_instance.Pass(), NULL);
582 }
583
584 SharedWorkerHost* SharedWorkerServiceImpl::FindSharedWorkerHost(
585     SharedWorkerMessageFilter* filter,
586     int worker_route_id) {
587   return worker_hosts_.get(std::make_pair(filter->render_process_id(),
588                                           worker_route_id));
589 }
590
591 SharedWorkerHost* SharedWorkerServiceImpl::FindSharedWorkerHost(
592     const SharedWorkerInstance& instance) {
593   for (WorkerHostMap::const_iterator iter = worker_hosts_.begin();
594        iter != worker_hosts_.end();
595        ++iter) {
596     SharedWorkerHost* host = iter->second;
597     if (host->instance() && !host->closed() &&
598         host->instance()->Matches(instance)) {
599       return iter->second;
600     }
601   }
602   return NULL;
603 }
604
605 SharedWorkerServiceImpl::SharedWorkerPendingInstance*
606 SharedWorkerServiceImpl::FindPendingInstance(
607     const SharedWorkerInstance& instance) {
608   for (PendingInstaneMap::iterator iter = pending_instances_.begin();
609        iter != pending_instances_.end();
610        ++iter) {
611     if (iter->second->instance()->Matches(instance))
612       return iter->second;
613   }
614   return NULL;
615 }
616
617 const std::set<int>
618 SharedWorkerServiceImpl::GetRenderersWithWorkerDependency() {
619   std::set<int> dependent_renderers;
620   for (WorkerHostMap::iterator host_iter = worker_hosts_.begin();
621        host_iter != worker_hosts_.end();
622        ++host_iter) {
623     const int process_id = host_iter->first.first;
624     if (dependent_renderers.count(process_id))
625       continue;
626     if (host_iter->second->instance() &&
627         host_iter->second->worker_document_set()->ContainsExternalRenderer(
628             process_id)) {
629       dependent_renderers.insert(process_id);
630     }
631   }
632   return dependent_renderers;
633 }
634
635 void SharedWorkerServiceImpl::CheckWorkerDependency() {
636   const std::set<int> current_worker_depended_renderers =
637       GetRenderersWithWorkerDependency();
638   std::vector<int> added_items = base::STLSetDifference<std::vector<int> >(
639       current_worker_depended_renderers, last_worker_depended_renderers_);
640   std::vector<int> removed_items = base::STLSetDifference<std::vector<int> >(
641       last_worker_depended_renderers_, current_worker_depended_renderers);
642   if (!added_items.empty() || !removed_items.empty()) {
643     last_worker_depended_renderers_ = current_worker_depended_renderers;
644     update_worker_dependency_(added_items, removed_items);
645   }
646 }
647
648 void SharedWorkerServiceImpl::ChangeUpdateWorkerDependencyFuncForTesting(
649     UpdateWorkerDependencyFunc new_func) {
650   update_worker_dependency_ = new_func;
651 }
652
653 void SharedWorkerServiceImpl::ChangeTryIncrementWorkerRefCountFuncForTesting(
654     bool (*new_func)(int)) {
655   s_try_increment_worker_ref_count_ = new_func;
656 }
657
658 }  // namespace content