blob: 13e4b4b703ca28e5a47cdaddac99a1a5bb869b78 [file] [log] [blame]
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/service_worker/service_worker_job_coordinator.h"
#include "base/memory/scoped_ptr.h"
#include "base/stl_util.h"
#include "content/browser/service_worker/service_worker_register_job_base.h"
namespace content {
ServiceWorkerJobCoordinator::JobQueue::JobQueue() {}
ServiceWorkerJobCoordinator::JobQueue::~JobQueue() {
DCHECK(jobs_.empty()) << "Destroying JobQueue with " << jobs_.size()
<< " unfinished jobs";
STLDeleteElements(&jobs_);
}
ServiceWorkerRegisterJobBase* ServiceWorkerJobCoordinator::JobQueue::Push(
scoped_ptr<ServiceWorkerRegisterJobBase> job) {
if (jobs_.empty()) {
job->Start();
jobs_.push_back(job.release());
} else if (!job->Equals(jobs_.back())) {
jobs_.push_back(job.release());
}
// Note we are releasing 'job' here.
DCHECK(!jobs_.empty());
return jobs_.back();
}
void ServiceWorkerJobCoordinator::JobQueue::Pop(
ServiceWorkerRegisterJobBase* job) {
DCHECK(job == jobs_.front());
jobs_.pop_front();
delete job;
if (!jobs_.empty())
jobs_.front()->Start();
}
void ServiceWorkerJobCoordinator::JobQueue::AbortAll() {
for (size_t i = 0; i < jobs_.size(); ++i)
jobs_[i]->Abort();
STLDeleteElements(&jobs_);
}
void ServiceWorkerJobCoordinator::JobQueue::ClearForShutdown() {
STLDeleteElements(&jobs_);
}
ServiceWorkerJobCoordinator::ServiceWorkerJobCoordinator(
base::WeakPtr<ServiceWorkerContextCore> context)
: context_(context) {
}
ServiceWorkerJobCoordinator::~ServiceWorkerJobCoordinator() {
if (!context_) {
for (RegistrationJobMap::iterator it = job_queues_.begin();
it != job_queues_.end(); ++it) {
it->second.ClearForShutdown();
}
job_queues_.clear();
}
DCHECK(job_queues_.empty()) << "Destroying ServiceWorkerJobCoordinator with "
<< job_queues_.size() << " job queues";
}
void ServiceWorkerJobCoordinator::Register(
const GURL& pattern,
const GURL& script_url,
int source_process_id,
const ServiceWorkerRegisterJob::RegistrationCallback& callback) {
scoped_ptr<ServiceWorkerRegisterJobBase> job(
new ServiceWorkerRegisterJob(context_, pattern, script_url));
ServiceWorkerRegisterJob* queued_job =
static_cast<ServiceWorkerRegisterJob*>(
job_queues_[pattern].Push(job.Pass()));
queued_job->AddCallback(callback, source_process_id);
}
void ServiceWorkerJobCoordinator::Unregister(
const GURL& pattern,
const ServiceWorkerUnregisterJob::UnregistrationCallback& callback) {
scoped_ptr<ServiceWorkerRegisterJobBase> job(
new ServiceWorkerUnregisterJob(context_, pattern));
ServiceWorkerUnregisterJob* queued_job =
static_cast<ServiceWorkerUnregisterJob*>(
job_queues_[pattern].Push(job.Pass()));
queued_job->AddCallback(callback);
}
void ServiceWorkerJobCoordinator::Update(
ServiceWorkerRegistration* registration) {
job_queues_[registration->pattern()].Push(
make_scoped_ptr<ServiceWorkerRegisterJobBase>(
new ServiceWorkerRegisterJob(context_, registration)));
}
void ServiceWorkerJobCoordinator::AbortAll() {
for (RegistrationJobMap::iterator it = job_queues_.begin();
it != job_queues_.end(); ++it) {
it->second.AbortAll();
}
job_queues_.clear();
}
void ServiceWorkerJobCoordinator::FinishJob(const GURL& pattern,
ServiceWorkerRegisterJobBase* job) {
RegistrationJobMap::iterator pending_jobs = job_queues_.find(pattern);
DCHECK(pending_jobs != job_queues_.end()) << "Deleting non-existent job.";
pending_jobs->second.Pop(job);
if (pending_jobs->second.empty())
job_queues_.erase(pending_jobs);
}
} // namespace content