Upstream version 10.39.225.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::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