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/service_worker/service_worker_job_coordinator.h" 6 7 #include "base/memory/scoped_ptr.h" 8 #include "base/stl_util.h" 9 #include "content/browser/service_worker/service_worker_register_job_base.h" 10 11 namespace content { 12 13 ServiceWorkerJobCoordinator::JobQueue::JobQueue() {} 14 15 ServiceWorkerJobCoordinator::JobQueue::~JobQueue() { 16 DCHECK(jobs_.empty()) << "Destroying JobQueue with " << jobs_.size() 17 << " unfinished jobs"; 18 STLDeleteElements(&jobs_); 19 } 20 21 ServiceWorkerRegisterJobBase* ServiceWorkerJobCoordinator::JobQueue::Push( 22 scoped_ptr<ServiceWorkerRegisterJobBase> job) { 23 if (jobs_.empty()) { 24 job->Start(); 25 jobs_.push_back(job.release()); 26 } else if (!job->Equals(jobs_.back())) { 27 jobs_.push_back(job.release()); 28 } 29 // Note we are releasing 'job' here. 30 31 DCHECK(!jobs_.empty()); 32 return jobs_.back(); 33 } 34 35 void ServiceWorkerJobCoordinator::JobQueue::Pop( 36 ServiceWorkerRegisterJobBase* job) { 37 DCHECK(job == jobs_.front()); 38 jobs_.pop_front(); 39 delete job; 40 if (!jobs_.empty()) 41 jobs_.front()->Start(); 42 } 43 44 void ServiceWorkerJobCoordinator::JobQueue::AbortAll() { 45 for (size_t i = 0; i < jobs_.size(); ++i) 46 jobs_[i]->Abort(); 47 STLDeleteElements(&jobs_); 48 } 49 50 void ServiceWorkerJobCoordinator::JobQueue::ClearForShutdown() { 51 STLDeleteElements(&jobs_); 52 } 53 54 ServiceWorkerJobCoordinator::ServiceWorkerJobCoordinator( 55 base::WeakPtr<ServiceWorkerContextCore> context) 56 : context_(context) { 57 } 58 59 ServiceWorkerJobCoordinator::~ServiceWorkerJobCoordinator() { 60 if (!context_) { 61 for (RegistrationJobMap::iterator it = job_queues_.begin(); 62 it != job_queues_.end(); ++it) { 63 it->second.ClearForShutdown(); 64 } 65 job_queues_.clear(); 66 } 67 DCHECK(job_queues_.empty()) << "Destroying ServiceWorkerJobCoordinator with " 68 << job_queues_.size() << " job queues"; 69 } 70 71 void ServiceWorkerJobCoordinator::Register( 72 const GURL& pattern, 73 const GURL& script_url, 74 ServiceWorkerProviderHost* provider_host, 75 const ServiceWorkerRegisterJob::RegistrationCallback& callback) { 76 scoped_ptr<ServiceWorkerRegisterJobBase> job( 77 new ServiceWorkerRegisterJob(context_, pattern, script_url)); 78 ServiceWorkerRegisterJob* queued_job = 79 static_cast<ServiceWorkerRegisterJob*>( 80 job_queues_[pattern].Push(job.Pass())); 81 queued_job->AddCallback(callback, provider_host); 82 } 83 84 void ServiceWorkerJobCoordinator::Unregister( 85 const GURL& pattern, 86 const ServiceWorkerUnregisterJob::UnregistrationCallback& callback) { 87 scoped_ptr<ServiceWorkerRegisterJobBase> job( 88 new ServiceWorkerUnregisterJob(context_, pattern)); 89 ServiceWorkerUnregisterJob* queued_job = 90 static_cast<ServiceWorkerUnregisterJob*>( 91 job_queues_[pattern].Push(job.Pass())); 92 queued_job->AddCallback(callback); 93 } 94 95 void ServiceWorkerJobCoordinator::Update( 96 ServiceWorkerRegistration* registration) { 97 DCHECK(registration); 98 DCHECK(registration->GetNewestVersion()); 99 job_queues_[registration->pattern()].Push( 100 make_scoped_ptr<ServiceWorkerRegisterJobBase>( 101 new ServiceWorkerRegisterJob(context_, registration))); 102 } 103 104 void ServiceWorkerJobCoordinator::AbortAll() { 105 for (RegistrationJobMap::iterator it = job_queues_.begin(); 106 it != job_queues_.end(); ++it) { 107 it->second.AbortAll(); 108 } 109 job_queues_.clear(); 110 } 111 112 void ServiceWorkerJobCoordinator::FinishJob(const GURL& pattern, 113 ServiceWorkerRegisterJobBase* job) { 114 RegistrationJobMap::iterator pending_jobs = job_queues_.find(pattern); 115 DCHECK(pending_jobs != job_queues_.end()) << "Deleting non-existent job."; 116 pending_jobs->second.Pop(job); 117 if (pending_jobs->second.empty()) 118 job_queues_.erase(pending_jobs); 119 } 120 121 } // namespace content 122