Revert 268405 "Make sure that ScratchBuffer::Allocate() always r..."
[chromium-blink-merge.git] / content / browser / shared_worker / shared_worker_service_impl.cc
blob4a689fa812fe422e522ffe3193c8d6f5394b7e7f
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.
5 #include "content/browser/shared_worker/shared_worker_service_impl.h"
7 #include <algorithm>
8 #include <iterator>
9 #include <set>
10 #include <vector>
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"
25 namespace content {
26 namespace {
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();
41 private:
42 SharedWorkerServiceImpl* service_;
43 base::Closure done_closure_;
44 DISALLOW_COPY_AND_ASSIGN(ScopedWorkerDependencyChecker);
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();
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();
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));
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;
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();
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;
95 render_process->IncrementWorkerRefCount();
96 return true;
99 } // namespace
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;
121 typedef ScopedVector<SharedWorkerPendingRequest> SharedWorkerPendingRequests;
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;
135 return NULL;
137 void AddRequest(scoped_ptr<SharedWorkerPendingRequest> request_info) {
138 requests_.push_back(request_info.release());
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;
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);
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));
166 private:
167 scoped_ptr<SharedWorkerInstance> instance_;
168 SharedWorkerPendingRequests requests_;
169 DISALLOW_COPY_AND_ASSIGN(SharedWorkerPendingInstance);
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) {}
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;
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_);
199 BrowserThread::PostTask(
200 BrowserThread::IO, FROM_HERE, base::Bind(success_cb, pause_on_start));
203 private:
204 friend class base::RefCountedThreadSafe<SharedWorkerReserver>;
205 ~SharedWorkerReserver() {}
207 const int worker_process_id_;
208 const int worker_route_id_;
209 const bool is_new_worker_;
210 const SharedWorkerInstance instance_;
213 // static
214 bool (*SharedWorkerServiceImpl::s_try_increment_worker_ref_count_)(int) =
215 TryIncrementWorkerRefCount;
217 SharedWorkerServiceImpl* SharedWorkerServiceImpl::GetInstance() {
218 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
219 return Singleton<SharedWorkerServiceImpl>::get();
222 SharedWorkerServiceImpl::SharedWorkerServiceImpl()
223 : update_worker_dependency_(UpdateWorkerDependency),
224 next_pending_instance_id_(0) {
227 SharedWorkerServiceImpl::~SharedWorkerServiceImpl() {}
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;
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;
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);
263 return results;
266 void SharedWorkerServiceImpl::AddObserver(WorkerServiceObserver* observer) {
267 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
268 observers_.AddObserver(observer);
271 void SharedWorkerServiceImpl::RemoveObserver(WorkerServiceObserver* observer) {
272 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
273 observers_.RemoveObserver(observer);
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;
304 pending->AddRequest(request.Pass());
305 return;
307 scoped_ptr<SharedWorkerPendingInstance> pending_instance(
308 new SharedWorkerPendingInstance(instance.Pass()));
309 pending_instance->AddRequest(request.Pass());
310 ReserveRenderProcessToCreateWorker(pending_instance.Pass(), url_mismatch);
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;
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);
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();
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();
355 void SharedWorkerServiceImpl::WorkerScriptLoaded(
356 int worker_route_id,
357 SharedWorkerMessageFilter* filter) {
358 if (SharedWorkerHost* host = FindSharedWorkerHost(filter, worker_route_id))
359 host->WorkerScriptLoaded();
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();
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);
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);
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);
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);
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);
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]);
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);
437 for (size_t i = 0; i < remove_pending_instance_list.size(); ++i)
438 pending_instances_.take_and_erase(remove_pending_instance_list[i]);
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));
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;
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();
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());
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;
532 pending_instance->RegisterToSharedWorkerHost(existing_host);
533 pending_instance->SendWorkerCreatedMessages();
534 return;
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;
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));
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);
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));
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;
593 return NULL;
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;
605 return NULL;
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);
623 return dependent_renderers;
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);
647 void SharedWorkerServiceImpl::ChangeUpdateWorkerDependencyFuncForTesting(
648 UpdateWorkerDependencyFunc new_func) {
649 update_worker_dependency_ = new_func;
652 void SharedWorkerServiceImpl::ChangeTryIncrementWorkerRefCountFuncForTesting(
653 bool (*new_func)(int)) {
654 s_try_increment_worker_ref_count_ = new_func;
657 } // namespace content