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