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