| Index: content/browser/service_worker/service_worker_storage.cc
|
| diff --git a/content/browser/service_worker/service_worker_storage.cc b/content/browser/service_worker/service_worker_storage.cc
|
| index a9a5b774ac0597ced39ad398f1b67815c82a5a26..9a79263d718d49b94d630fe81914daa1fcee4091 100644
|
| --- a/content/browser/service_worker/service_worker_storage.cc
|
| +++ b/content/browser/service_worker/service_worker_storage.cc
|
| @@ -25,17 +25,6 @@ namespace content {
|
|
|
| namespace {
|
|
|
| -typedef base::Callback<void(
|
| - ServiceWorkerStorage::InitialData* data,
|
| - ServiceWorkerDatabase::Status status)> InitializeCallback;
|
| -typedef base::Callback<void(
|
| - const ServiceWorkerDatabase::RegistrationData& data,
|
| - const std::vector<ServiceWorkerDatabase::ResourceRecord>& resources,
|
| - ServiceWorkerDatabase::Status status)> ReadRegistrationCallback;
|
| -typedef base::Callback<void(
|
| - bool origin_is_deletable,
|
| - ServiceWorkerDatabase::Status status)> DeleteRegistrationCallback;
|
| -
|
| void RunSoon(const tracked_objects::Location& from_here,
|
| const base::Closure& closure) {
|
| base::MessageLoop::current()->PostTask(from_here, closure);
|
| @@ -60,8 +49,11 @@ const base::FilePath::CharType kServiceWorkerDirectory[] =
|
| FILE_PATH_LITERAL("Service Worker");
|
| const base::FilePath::CharType kDatabaseName[] =
|
| FILE_PATH_LITERAL("Database");
|
| +const base::FilePath::CharType kDiskCacheName[] =
|
| + FILE_PATH_LITERAL("Cache");
|
|
|
| const int kMaxMemDiskCacheSize = 10 * 1024 * 1024;
|
| +const int kMaxDiskCacheSize = 250 * 1024 * 1024;
|
|
|
| void EmptyCompletionCallback(int) {}
|
|
|
| @@ -77,59 +69,6 @@ ServiceWorkerStatusCode DatabaseStatusToStatusCode(
|
| }
|
| }
|
|
|
| -void ReadInitialDataFromDB(
|
| - ServiceWorkerDatabase* database,
|
| - scoped_refptr<base::SequencedTaskRunner> original_task_runner,
|
| - const InitializeCallback& callback) {
|
| - DCHECK(database);
|
| - scoped_ptr<ServiceWorkerStorage::InitialData> data(
|
| - new ServiceWorkerStorage::InitialData());
|
| -
|
| - ServiceWorkerDatabase::Status status =
|
| - database->GetNextAvailableIds(&data->next_registration_id,
|
| - &data->next_version_id,
|
| - &data->next_resource_id);
|
| - if (status != ServiceWorkerDatabase::STATUS_OK) {
|
| - original_task_runner->PostTask(
|
| - FROM_HERE, base::Bind(callback, base::Owned(data.release()), status));
|
| - return;
|
| - }
|
| -
|
| - status = database->GetOriginsWithRegistrations(&data->origins);
|
| - original_task_runner->PostTask(
|
| - FROM_HERE, base::Bind(callback, base::Owned(data.release()), status));
|
| -}
|
| -
|
| -void DeleteRegistrationFromDB(
|
| - ServiceWorkerDatabase* database,
|
| - scoped_refptr<base::SequencedTaskRunner> original_task_runner,
|
| - int64 registration_id,
|
| - const GURL& origin,
|
| - const DeleteRegistrationCallback& callback) {
|
| - DCHECK(database);
|
| - ServiceWorkerDatabase::Status status =
|
| - database->DeleteRegistration(registration_id, origin);
|
| - if (status != ServiceWorkerDatabase::STATUS_OK) {
|
| - original_task_runner->PostTask(
|
| - FROM_HERE, base::Bind(callback, false, status));
|
| - return;
|
| - }
|
| -
|
| - // TODO(nhiroki): Add convenient method to ServiceWorkerDatabase to check the
|
| - // unique origin list.
|
| - std::vector<ServiceWorkerDatabase::RegistrationData> registrations;
|
| - status = database->GetRegistrationsForOrigin(origin, ®istrations);
|
| - if (status != ServiceWorkerDatabase::STATUS_OK) {
|
| - original_task_runner->PostTask(
|
| - FROM_HERE, base::Bind(callback, false, status));
|
| - return;
|
| - }
|
| -
|
| - bool deletable = registrations.empty();
|
| - original_task_runner->PostTask(
|
| - FROM_HERE, base::Bind(callback, deletable, status));
|
| -}
|
| -
|
| } // namespace
|
|
|
| ServiceWorkerStorage::InitialData::InitialData()
|
| @@ -155,14 +94,11 @@ ServiceWorkerStorage::ServiceWorkerStorage(
|
| database_task_runner_(database_task_runner),
|
| disk_cache_thread_(disk_cache_thread),
|
| quota_manager_proxy_(quota_manager_proxy),
|
| + is_purge_pending_(false),
|
| weak_factory_(this) {
|
| - if (!path.empty()) {
|
| + if (!path.empty())
|
| path_ = path.Append(kServiceWorkerDirectory);
|
| - database_.reset(new ServiceWorkerDatabase(path_.Append(kDatabaseName)));
|
| - } else {
|
| - // Create an in-memory database.
|
| - database_.reset(new ServiceWorkerDatabase(base::FilePath()));
|
| - }
|
| + database_.reset(new ServiceWorkerDatabase(GetDatabasePath()));
|
| }
|
|
|
| ServiceWorkerStorage::~ServiceWorkerStorage() {
|
| @@ -170,112 +106,107 @@ ServiceWorkerStorage::~ServiceWorkerStorage() {
|
| database_task_runner_->DeleteSoon(FROM_HERE, database_.release());
|
| }
|
|
|
| -void ServiceWorkerStorage::FindRegistrationForPattern(
|
| - const GURL& scope,
|
| +void ServiceWorkerStorage::FindRegistrationForDocument(
|
| + const GURL& document_url,
|
| const FindRegistrationCallback& callback) {
|
| - scoped_refptr<ServiceWorkerRegistration> null_registration;
|
| if (!LazyInitialize(base::Bind(
|
| - &ServiceWorkerStorage::FindRegistrationForPattern,
|
| - weak_factory_.GetWeakPtr(), scope, callback))) {
|
| + &ServiceWorkerStorage::FindRegistrationForDocument,
|
| + weak_factory_.GetWeakPtr(), document_url, callback))) {
|
| if (state_ != INITIALIZING || !context_) {
|
| - CompleteFindSoon(FROM_HERE, null_registration,
|
| - SERVICE_WORKER_ERROR_FAILED, callback);
|
| + CompleteFindNow(scoped_refptr<ServiceWorkerRegistration>(),
|
| + SERVICE_WORKER_ERROR_FAILED, callback);
|
| }
|
| return;
|
| }
|
| DCHECK_EQ(INITIALIZED, state_);
|
|
|
| // See if there are any stored registrations for the origin.
|
| - if (!ContainsKey(registered_origins_, scope.GetOrigin())) {
|
| + if (!ContainsKey(registered_origins_, document_url.GetOrigin())) {
|
| // Look for something currently being installed.
|
| scoped_refptr<ServiceWorkerRegistration> installing_registration =
|
| - FindInstallingRegistrationForPattern(scope);
|
| - if (installing_registration) {
|
| - CompleteFindSoon(
|
| - FROM_HERE, installing_registration, SERVICE_WORKER_OK, callback);
|
| - return;
|
| - }
|
| - CompleteFindSoon(
|
| - FROM_HERE, null_registration, SERVICE_WORKER_ERROR_NOT_FOUND, callback);
|
| + FindInstallingRegistrationForDocument(document_url);
|
| + CompleteFindNow(
|
| + installing_registration,
|
| + installing_registration ?
|
| + SERVICE_WORKER_OK : SERVICE_WORKER_ERROR_NOT_FOUND,
|
| + callback);
|
| return;
|
| }
|
|
|
| - RegistrationList* registrations = new RegistrationList();
|
| - PostTaskAndReplyWithResult(
|
| - database_task_runner_,
|
| + database_task_runner_->PostTask(
|
| FROM_HERE,
|
| - base::Bind(&ServiceWorkerDatabase::GetRegistrationsForOrigin,
|
| - base::Unretained(database_.get()),
|
| - scope.GetOrigin(), base::Unretained(registrations)),
|
| - base::Bind(&ServiceWorkerStorage::DidGetRegistrationsForPattern,
|
| - weak_factory_.GetWeakPtr(), scope, callback,
|
| - base::Owned(registrations)));
|
| + base::Bind(
|
| + &FindForDocumentInDB,
|
| + database_.get(),
|
| + base::MessageLoopProxy::current(),
|
| + document_url,
|
| + base::Bind(&ServiceWorkerStorage::DidFindRegistrationForDocument,
|
| + weak_factory_.GetWeakPtr(), document_url, callback)));
|
| }
|
|
|
| -void ServiceWorkerStorage::FindRegistrationForDocument(
|
| - const GURL& document_url,
|
| +void ServiceWorkerStorage::FindRegistrationForPattern(
|
| + const GURL& scope,
|
| const FindRegistrationCallback& callback) {
|
| - scoped_refptr<ServiceWorkerRegistration> null_registration;
|
| if (!LazyInitialize(base::Bind(
|
| - &ServiceWorkerStorage::FindRegistrationForDocument,
|
| - weak_factory_.GetWeakPtr(), document_url, callback))) {
|
| - if (state_ != INITIALIZING || !context_)
|
| - CompleteFindNow(null_registration, SERVICE_WORKER_ERROR_FAILED, callback);
|
| + &ServiceWorkerStorage::FindRegistrationForPattern,
|
| + weak_factory_.GetWeakPtr(), scope, callback))) {
|
| + if (state_ != INITIALIZING || !context_) {
|
| + CompleteFindSoon(FROM_HERE, scoped_refptr<ServiceWorkerRegistration>(),
|
| + SERVICE_WORKER_ERROR_FAILED, callback);
|
| + }
|
| return;
|
| }
|
| DCHECK_EQ(INITIALIZED, state_);
|
|
|
| // See if there are any stored registrations for the origin.
|
| - if (!ContainsKey(registered_origins_, document_url.GetOrigin())) {
|
| + if (!ContainsKey(registered_origins_, scope.GetOrigin())) {
|
| // Look for something currently being installed.
|
| scoped_refptr<ServiceWorkerRegistration> installing_registration =
|
| - FindInstallingRegistrationForDocument(document_url);
|
| - if (installing_registration) {
|
| - CompleteFindNow(installing_registration, SERVICE_WORKER_OK, callback);
|
| - return;
|
| - }
|
| - CompleteFindNow(
|
| - null_registration, SERVICE_WORKER_ERROR_NOT_FOUND, callback);
|
| + FindInstallingRegistrationForPattern(scope);
|
| + CompleteFindSoon(
|
| + FROM_HERE, installing_registration,
|
| + installing_registration ?
|
| + SERVICE_WORKER_OK : SERVICE_WORKER_ERROR_NOT_FOUND,
|
| + callback);
|
| return;
|
| }
|
|
|
| - RegistrationList* registrations = new RegistrationList();
|
| - PostTaskAndReplyWithResult(
|
| - database_task_runner_,
|
| + database_task_runner_->PostTask(
|
| FROM_HERE,
|
| - base::Bind(&ServiceWorkerDatabase::GetRegistrationsForOrigin,
|
| - base::Unretained(database_.get()),
|
| - document_url.GetOrigin(), base::Unretained(registrations)),
|
| - base::Bind(&ServiceWorkerStorage::DidGetRegistrationsForDocument,
|
| - weak_factory_.GetWeakPtr(), document_url, callback,
|
| - base::Owned(registrations)));
|
| + base::Bind(
|
| + &FindForPatternInDB,
|
| + database_.get(),
|
| + base::MessageLoopProxy::current(),
|
| + scope,
|
| + base::Bind(&ServiceWorkerStorage::DidFindRegistrationForPattern,
|
| + weak_factory_.GetWeakPtr(), scope, callback)));
|
| }
|
|
|
| void ServiceWorkerStorage::FindRegistrationForId(
|
| int64 registration_id,
|
| const GURL& origin,
|
| const FindRegistrationCallback& callback) {
|
| - scoped_refptr<ServiceWorkerRegistration> null_registration;
|
| if (!LazyInitialize(base::Bind(
|
| &ServiceWorkerStorage::FindRegistrationForId,
|
| weak_factory_.GetWeakPtr(), registration_id, origin, callback))) {
|
| - if (state_ != INITIALIZING || !context_)
|
| - CompleteFindNow(null_registration, SERVICE_WORKER_ERROR_FAILED, callback);
|
| + if (state_ != INITIALIZING || !context_) {
|
| + CompleteFindNow(scoped_refptr<ServiceWorkerRegistration>(),
|
| + SERVICE_WORKER_ERROR_FAILED, callback);
|
| + }
|
| return;
|
| }
|
| DCHECK_EQ(INITIALIZED, state_);
|
|
|
| // See if there are any stored registrations for the origin.
|
| if (!ContainsKey(registered_origins_, origin)) {
|
| - // Look for somthing currently being installed.
|
| + // Look for something currently being installed.
|
| scoped_refptr<ServiceWorkerRegistration> installing_registration =
|
| FindInstallingRegistrationForId(registration_id);
|
| - if (installing_registration) {
|
| - CompleteFindNow(installing_registration, SERVICE_WORKER_OK, callback);
|
| - return;
|
| - }
|
| CompleteFindNow(
|
| - null_registration, SERVICE_WORKER_ERROR_NOT_FOUND, callback);
|
| + installing_registration,
|
| + installing_registration ?
|
| + SERVICE_WORKER_OK : SERVICE_WORKER_ERROR_NOT_FOUND,
|
| + callback);
|
| return;
|
| }
|
|
|
| @@ -286,20 +217,14 @@ void ServiceWorkerStorage::FindRegistrationForId(
|
| return;
|
| }
|
|
|
| - ServiceWorkerDatabase::RegistrationData* data =
|
| - new ServiceWorkerDatabase::RegistrationData;
|
| - ResourceList* resources = new ResourceList;
|
| - PostTaskAndReplyWithResult(
|
| - database_task_runner_,
|
| + database_task_runner_->PostTask(
|
| FROM_HERE,
|
| - base::Bind(&ServiceWorkerDatabase::ReadRegistration,
|
| - base::Unretained(database_.get()),
|
| + base::Bind(&FindForIdInDB,
|
| + database_.get(),
|
| + base::MessageLoopProxy::current(),
|
| registration_id, origin,
|
| - base::Unretained(data),
|
| - base::Unretained(resources)),
|
| - base::Bind(&ServiceWorkerStorage::DidReadRegistrationForId,
|
| - weak_factory_.GetWeakPtr(),
|
| - callback, base::Owned(data), base::Owned(resources)));
|
| + base::Bind(&ServiceWorkerStorage::DidFindRegistrationForId,
|
| + weak_factory_.GetWeakPtr(), callback)));
|
| }
|
|
|
| void ServiceWorkerStorage::GetAllRegistrations(
|
| @@ -351,15 +276,17 @@ void ServiceWorkerStorage::StoreRegistration(
|
| data.is_active = false; // initially stored in the waiting state
|
|
|
| ResourceList resources;
|
| - PostTaskAndReplyWithResult(
|
| - database_task_runner_,
|
| + version->script_cache_map()->GetResources(&resources);
|
| +
|
| + database_task_runner_->PostTask(
|
| FROM_HERE,
|
| - base::Bind(&ServiceWorkerDatabase::WriteRegistration,
|
| - base::Unretained(database_.get()), data, resources),
|
| - base::Bind(&ServiceWorkerStorage::DidStoreRegistration,
|
| - weak_factory_.GetWeakPtr(),
|
| - registration->script_url().GetOrigin(),
|
| - callback));
|
| + base::Bind(&WriteRegistrationInDB,
|
| + database_.get(),
|
| + base::MessageLoopProxy::current(),
|
| + data, resources,
|
| + base::Bind(&ServiceWorkerStorage::DidStoreRegistration,
|
| + weak_factory_.GetWeakPtr(),
|
| + callback)));
|
| }
|
|
|
| void ServiceWorkerStorage::UpdateToActiveState(
|
| @@ -453,6 +380,18 @@ void ServiceWorkerStorage::NotifyDoneInstallingRegistration(
|
| installing_registrations_.erase(registration->id());
|
| }
|
|
|
| +base::FilePath ServiceWorkerStorage::GetDatabasePath() {
|
| + if (path_.empty())
|
| + return base::FilePath();
|
| + return path_.Append(kDatabaseName);
|
| +}
|
| +
|
| +base::FilePath ServiceWorkerStorage::GetDiskCachePath() {
|
| + if (path_.empty())
|
| + return base::FilePath();
|
| + return path_.Append(kDiskCacheName);
|
| +}
|
| +
|
| bool ServiceWorkerStorage::LazyInitialize(const base::Closure& callback) {
|
| if (!context_)
|
| return false;
|
| @@ -507,118 +446,70 @@ void ServiceWorkerStorage::DidReadInitialData(
|
| pending_tasks_.clear();
|
| }
|
|
|
| -void ServiceWorkerStorage::DidGetRegistrationsForPattern(
|
| - const GURL& scope,
|
| +void ServiceWorkerStorage::DidFindRegistrationForDocument(
|
| + const GURL& document_url,
|
| const FindRegistrationCallback& callback,
|
| - RegistrationList* registrations,
|
| + const ServiceWorkerDatabase::RegistrationData& data,
|
| + const ResourceList& resources,
|
| ServiceWorkerDatabase::Status status) {
|
| - DCHECK(registrations);
|
| - if (status != ServiceWorkerDatabase::STATUS_OK) {
|
| - // TODO(nhiroki): Handle database error (http://crbug.com/371675).
|
| - callback.Run(SERVICE_WORKER_ERROR_FAILED,
|
| - scoped_refptr<ServiceWorkerRegistration>());
|
| + if (status == ServiceWorkerDatabase::STATUS_OK) {
|
| + callback.Run(SERVICE_WORKER_OK, GetOrCreateRegistration(data, resources));
|
| return;
|
| }
|
|
|
| - // Find one with a matching scope.
|
| - for (RegistrationList::const_iterator it = registrations->begin();
|
| - it != registrations->end(); ++it) {
|
| - if (scope == it->scope) {
|
| - scoped_refptr<ServiceWorkerRegistration> registration =
|
| - context_->GetLiveRegistration(it->registration_id);
|
| - if (!registration)
|
| - registration = CreateRegistration(*it);
|
| - callback.Run(SERVICE_WORKER_OK, registration);
|
| - return;
|
| - }
|
| - }
|
| -
|
| - // Look for something currently being installed.
|
| - scoped_refptr<ServiceWorkerRegistration> installing_registration =
|
| - FindInstallingRegistrationForPattern(scope);
|
| - if (installing_registration) {
|
| - callback.Run(SERVICE_WORKER_OK, installing_registration);
|
| + if (status == ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND) {
|
| + // Look for something currently being installed.
|
| + scoped_refptr<ServiceWorkerRegistration> installing_registration =
|
| + FindInstallingRegistrationForDocument(document_url);
|
| + callback.Run(installing_registration ?
|
| + SERVICE_WORKER_OK : SERVICE_WORKER_ERROR_NOT_FOUND,
|
| + installing_registration);
|
| return;
|
| }
|
|
|
| - callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND,
|
| + // TODO(nhiroki): Handle database error (http://crbug.com/371675).
|
| + callback.Run(DatabaseStatusToStatusCode(status),
|
| scoped_refptr<ServiceWorkerRegistration>());
|
| }
|
|
|
| -void ServiceWorkerStorage::DidGetRegistrationsForDocument(
|
| - const GURL& document_url,
|
| +void ServiceWorkerStorage::DidFindRegistrationForPattern(
|
| + const GURL& scope,
|
| const FindRegistrationCallback& callback,
|
| - RegistrationList* registrations,
|
| + const ServiceWorkerDatabase::RegistrationData& data,
|
| + const ResourceList& resources,
|
| ServiceWorkerDatabase::Status status) {
|
| - DCHECK(registrations);
|
| - if (status != ServiceWorkerDatabase::STATUS_OK) {
|
| - // TODO(nhiroki): Handle database error (http://crbug.com/371675).
|
| - callback.Run(SERVICE_WORKER_ERROR_FAILED,
|
| - scoped_refptr<ServiceWorkerRegistration>());
|
| + if (status == ServiceWorkerDatabase::STATUS_OK) {
|
| + callback.Run(SERVICE_WORKER_OK, GetOrCreateRegistration(data, resources));
|
| return;
|
| }
|
|
|
| - // Find one with a pattern match.
|
| - for (RegistrationList::const_iterator it = registrations->begin();
|
| - it != registrations->end(); ++it) {
|
| - // TODO(michaeln): if there are multiple matches the one with
|
| - // the longest scope should win.
|
| - if (ServiceWorkerUtils::ScopeMatches(it->scope, document_url)) {
|
| - scoped_refptr<ServiceWorkerRegistration> registration =
|
| - context_->GetLiveRegistration(it->registration_id);
|
| - if (registration) {
|
| - callback.Run(SERVICE_WORKER_OK, registration);
|
| - return;
|
| - }
|
| - callback.Run(SERVICE_WORKER_OK, CreateRegistration(*it));
|
| - return;
|
| - }
|
| - }
|
| -
|
| - // Look for something currently being installed.
|
| - // TODO(michaeln): Should be mixed in with the stored registrations
|
| - // for this test.
|
| - scoped_refptr<ServiceWorkerRegistration> installing_registration =
|
| - FindInstallingRegistrationForDocument(document_url);
|
| - if (installing_registration) {
|
| - callback.Run(SERVICE_WORKER_OK, installing_registration);
|
| + if (status == ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND) {
|
| + scoped_refptr<ServiceWorkerRegistration> installing_registration =
|
| + FindInstallingRegistrationForPattern(scope);
|
| + callback.Run(installing_registration ?
|
| + SERVICE_WORKER_OK : SERVICE_WORKER_ERROR_NOT_FOUND,
|
| + installing_registration);
|
| return;
|
| }
|
|
|
| - callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND,
|
| + // TODO(nhiroki): Handle database error (http://crbug.com/371675).
|
| + callback.Run(DatabaseStatusToStatusCode(status),
|
| scoped_refptr<ServiceWorkerRegistration>());
|
| }
|
|
|
| -void ServiceWorkerStorage::DidReadRegistrationForId(
|
| +void ServiceWorkerStorage::DidFindRegistrationForId(
|
| const FindRegistrationCallback& callback,
|
| - ServiceWorkerDatabase::RegistrationData* registration,
|
| - ResourceList* resources,
|
| + const ServiceWorkerDatabase::RegistrationData& data,
|
| + const ResourceList& resources,
|
| ServiceWorkerDatabase::Status status) {
|
| - DCHECK(registration);
|
| - DCHECK(resources);
|
| -
|
| if (status == ServiceWorkerDatabase::STATUS_OK) {
|
| - callback.Run(SERVICE_WORKER_OK, CreateRegistration(*registration));
|
| + callback.Run(SERVICE_WORKER_OK,
|
| + GetOrCreateRegistration(data, resources));
|
| return;
|
| }
|
| -
|
| - if (status == ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND) {
|
| - // Look for somthing currently being installed.
|
| - scoped_refptr<ServiceWorkerRegistration> installing_registration =
|
| - FindInstallingRegistrationForId(registration->registration_id);
|
| - if (installing_registration) {
|
| - callback.Run(SERVICE_WORKER_OK, installing_registration);
|
| - return;
|
| - }
|
| - callback.Run(SERVICE_WORKER_ERROR_NOT_FOUND,
|
| - scoped_refptr<ServiceWorkerRegistration>());
|
| - return;
|
| - }
|
| -
|
| // TODO(nhiroki): Handle database error (http://crbug.com/371675).
|
| callback.Run(DatabaseStatusToStatusCode(status),
|
| scoped_refptr<ServiceWorkerRegistration>());
|
| - return;
|
| }
|
|
|
| void ServiceWorkerStorage::DidGetAllRegistrations(
|
| @@ -668,8 +559,9 @@ void ServiceWorkerStorage::DidGetAllRegistrations(
|
| }
|
|
|
| void ServiceWorkerStorage::DidStoreRegistration(
|
| - const GURL& origin,
|
| const StatusCallback& callback,
|
| + const GURL& origin,
|
| + const std::vector<int64>& newly_purgeable_resources,
|
| ServiceWorkerDatabase::Status status) {
|
| if (status != ServiceWorkerDatabase::STATUS_OK) {
|
| // TODO(nhiroki): Handle database error (http://crbug.com/371675).
|
| @@ -678,6 +570,7 @@ void ServiceWorkerStorage::DidStoreRegistration(
|
| }
|
| registered_origins_.insert(origin);
|
| callback.Run(SERVICE_WORKER_OK);
|
| + StartPurgingResources(newly_purgeable_resources);
|
| }
|
|
|
| void ServiceWorkerStorage::DidUpdateToActiveState(
|
| @@ -691,6 +584,7 @@ void ServiceWorkerStorage::DidDeleteRegistration(
|
| const GURL& origin,
|
| const StatusCallback& callback,
|
| bool origin_is_deletable,
|
| + const std::vector<int64>& newly_purgeable_resources,
|
| ServiceWorkerDatabase::Status status) {
|
| if (status != ServiceWorkerDatabase::STATUS_OK) {
|
| // TODO(nhiroki): Handle database error (http://crbug.com/371675).
|
| @@ -700,21 +594,27 @@ void ServiceWorkerStorage::DidDeleteRegistration(
|
| if (origin_is_deletable)
|
| registered_origins_.erase(origin);
|
| callback.Run(SERVICE_WORKER_OK);
|
| + StartPurgingResources(newly_purgeable_resources);
|
| }
|
|
|
| scoped_refptr<ServiceWorkerRegistration>
|
| -ServiceWorkerStorage::CreateRegistration(
|
| - const ServiceWorkerDatabase::RegistrationData& data) {
|
| - scoped_refptr<ServiceWorkerRegistration> registration(
|
| - new ServiceWorkerRegistration(
|
| - data.scope, data.script, data.registration_id, context_));
|
| +ServiceWorkerStorage::GetOrCreateRegistration(
|
| + const ServiceWorkerDatabase::RegistrationData& data,
|
| + const ResourceList& resources) {
|
| + scoped_refptr<ServiceWorkerRegistration> registration =
|
| + context_->GetLiveRegistration(data.registration_id);
|
| + if (registration)
|
| + return registration;
|
|
|
| + registration = new ServiceWorkerRegistration(
|
| + data.scope, data.script, data.registration_id, context_);
|
| scoped_refptr<ServiceWorkerVersion> version =
|
| context_->GetLiveVersion(data.version_id);
|
| if (!version) {
|
| version = new ServiceWorkerVersion(registration, data.version_id, context_);
|
| version->SetStatus(data.is_active ?
|
| ServiceWorkerVersion::ACTIVE : ServiceWorkerVersion::INSTALLED);
|
| + version->script_cache_map()->SetResources(resources);
|
| }
|
|
|
| if (version->status() == ServiceWorkerVersion::ACTIVE)
|
| @@ -725,7 +625,6 @@ ServiceWorkerStorage::CreateRegistration(
|
| NOTREACHED();
|
| // TODO(michaeln): Hmmm, what if DeleteReg was invoked after
|
| // the Find result we're returning here? NOTREACHED condition?
|
| -
|
| return registration;
|
| }
|
|
|
| @@ -733,8 +632,7 @@ ServiceWorkerRegistration*
|
| ServiceWorkerStorage::FindInstallingRegistrationForDocument(
|
| const GURL& document_url) {
|
| // TODO(michaeln): if there are multiple matches the one with
|
| - // the longest scope should win, and these should on equal footing
|
| - // with the stored registrations in FindRegistrationForDocument().
|
| + // the longest scope should win.
|
| for (RegistrationRefsById::const_iterator it =
|
| installing_registrations_.begin();
|
| it != installing_registrations_.end(); ++it) {
|
| @@ -772,13 +670,240 @@ ServiceWorkerDiskCache* ServiceWorkerStorage::disk_cache() {
|
| if (disk_cache_)
|
| return disk_cache_.get();
|
|
|
| - // TODO(michaeln): Store data on disk and do error checking.
|
| disk_cache_.reset(new ServiceWorkerDiskCache);
|
| - int rv = disk_cache_->InitWithMemBackend(
|
| - kMaxMemDiskCacheSize,
|
| - base::Bind(&EmptyCompletionCallback));
|
| - DCHECK_EQ(net::OK, rv);
|
| +
|
| + base::FilePath path = GetDiskCachePath();
|
| + if (path.empty()) {
|
| + int rv = disk_cache_->InitWithMemBackend(
|
| + kMaxMemDiskCacheSize,
|
| + base::Bind(&EmptyCompletionCallback));
|
| + DCHECK_EQ(net::OK, rv);
|
| + return disk_cache_.get();
|
| + }
|
| +
|
| + int rv = disk_cache_->InitWithDiskBackend(
|
| + path, kMaxDiskCacheSize, false,
|
| + disk_cache_thread_.get(),
|
| + base::Bind(&ServiceWorkerStorage::OnDiskCacheInitialized,
|
| + weak_factory_.GetWeakPtr()));
|
| + if (rv != net::ERR_IO_PENDING)
|
| + OnDiskCacheInitialized(rv);
|
| +
|
| return disk_cache_.get();
|
| }
|
|
|
| +void ServiceWorkerStorage::OnDiskCacheInitialized(int rv) {
|
| + if (rv != net::OK) {
|
| + LOG(ERROR) << "Failed to open the serviceworker diskcache.";
|
| + // TODO(michaeln): DeleteAndStartOver()
|
| + disk_cache_->Disable();
|
| + state_ = DISABLED;
|
| + }
|
| +}
|
| +
|
| +void ServiceWorkerStorage::StartPurgingResources(
|
| + const std::vector<int64>& ids) {
|
| + for (size_t i = 0; i < ids.size(); ++i)
|
| + purgeable_reource_ids_.push_back(ids[i]);
|
| +
|
| + if (purgeable_reource_ids_.empty() || is_purge_pending_)
|
| + return;
|
| +
|
| + // Do one at a time until we're done, use RunSoon to avoid recursion when
|
| + // DoomEntry returns immediately.
|
| + is_purge_pending_ = true;
|
| + int64 id = purgeable_reource_ids_.front();
|
| + purgeable_reource_ids_.pop_front();
|
| + RunSoon(FROM_HERE,
|
| + base::Bind(&ServiceWorkerStorage::PurgeResource,
|
| + weak_factory_.GetWeakPtr(), id));
|
| +}
|
| +
|
| +void ServiceWorkerStorage::PurgeResource(int64 id) {
|
| + DCHECK(is_purge_pending_);
|
| + int rv = disk_cache()->DoomEntry(
|
| + id, base::Bind(&ServiceWorkerStorage::OnResourcePurged,
|
| + weak_factory_.GetWeakPtr(), id));
|
| + if (rv != net::ERR_IO_PENDING)
|
| + OnResourcePurged(id, rv);
|
| +}
|
| +
|
| +void ServiceWorkerStorage::OnResourcePurged(int64 id, int rv) {
|
| + DCHECK(is_purge_pending_);
|
| + is_purge_pending_ = false;
|
| +
|
| + database_task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(base::IgnoreResult(
|
| + &ServiceWorkerDatabase::ClearPurgeableResourceIds),
|
| + base::Unretained(database_.get()),
|
| + std::set<int64>(&id, &id + 1)));
|
| +
|
| + // Continue purging the remaining resources.
|
| + StartPurgingResources(std::vector<int64>());
|
| +}
|
| +
|
| +void ServiceWorkerStorage::ReadInitialDataFromDB(
|
| + ServiceWorkerDatabase* database,
|
| + scoped_refptr<base::SequencedTaskRunner> original_task_runner,
|
| + const InitializeCallback& callback) {
|
| + DCHECK(database);
|
| + scoped_ptr<ServiceWorkerStorage::InitialData> data(
|
| + new ServiceWorkerStorage::InitialData());
|
| +
|
| + ServiceWorkerDatabase::Status status =
|
| + database->GetNextAvailableIds(&data->next_registration_id,
|
| + &data->next_version_id,
|
| + &data->next_resource_id);
|
| + if (status != ServiceWorkerDatabase::STATUS_OK) {
|
| + original_task_runner->PostTask(
|
| + FROM_HERE, base::Bind(callback, base::Owned(data.release()), status));
|
| + return;
|
| + }
|
| +
|
| + status = database->GetOriginsWithRegistrations(&data->origins);
|
| + original_task_runner->PostTask(
|
| + FROM_HERE, base::Bind(callback, base::Owned(data.release()), status));
|
| +}
|
| +
|
| +void ServiceWorkerStorage::DeleteRegistrationFromDB(
|
| + ServiceWorkerDatabase* database,
|
| + scoped_refptr<base::SequencedTaskRunner> original_task_runner,
|
| + int64 registration_id,
|
| + const GURL& origin,
|
| + const DeleteRegistrationCallback& callback) {
|
| + DCHECK(database);
|
| +
|
| + std::vector<int64> newly_purgeable_resources;
|
| + ServiceWorkerDatabase::Status status =
|
| + database->DeleteRegistration(registration_id, origin,
|
| + &newly_purgeable_resources);
|
| + if (status != ServiceWorkerDatabase::STATUS_OK) {
|
| + original_task_runner->PostTask(
|
| + FROM_HERE, base::Bind(callback, false, std::vector<int64>(), status));
|
| + return;
|
| + }
|
| +
|
| + // TODO(nhiroki): Add convenient method to ServiceWorkerDatabase to check the
|
| + // unique origin list.
|
| + std::vector<ServiceWorkerDatabase::RegistrationData> registrations;
|
| + status = database->GetRegistrationsForOrigin(origin, ®istrations);
|
| + if (status != ServiceWorkerDatabase::STATUS_OK) {
|
| + original_task_runner->PostTask(
|
| + FROM_HERE, base::Bind(callback, false, std::vector<int64>(), status));
|
| + return;
|
| + }
|
| +
|
| + bool deletable = registrations.empty();
|
| + original_task_runner->PostTask(
|
| + FROM_HERE, base::Bind(callback, deletable,
|
| + newly_purgeable_resources, status));
|
| +}
|
| +
|
| +void ServiceWorkerStorage::WriteRegistrationInDB(
|
| + ServiceWorkerDatabase* database,
|
| + scoped_refptr<base::SequencedTaskRunner> original_task_runner,
|
| + const ServiceWorkerDatabase::RegistrationData& data,
|
| + const ResourceList& resources,
|
| + const WriteRegistrationCallback& callback) {
|
| + DCHECK(database);
|
| + std::vector<int64> newly_purgeable_resources;
|
| + ServiceWorkerDatabase::Status status =
|
| + database->WriteRegistration(data, resources, &newly_purgeable_resources);
|
| + original_task_runner->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(callback, data.script.GetOrigin(),
|
| + newly_purgeable_resources, status));
|
| +}
|
| +
|
| +void ServiceWorkerStorage::FindForDocumentInDB(
|
| + ServiceWorkerDatabase* database,
|
| + scoped_refptr<base::SequencedTaskRunner> original_task_runner,
|
| + const GURL& document_url,
|
| + const FindInDBCallback& callback) {
|
| + GURL origin = document_url.GetOrigin();
|
| + RegistrationList registrations;
|
| + ServiceWorkerDatabase::Status status =
|
| + database->GetRegistrationsForOrigin(origin, ®istrations);
|
| + if (status != ServiceWorkerDatabase::STATUS_OK) {
|
| + original_task_runner->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(callback,
|
| + ServiceWorkerDatabase::RegistrationData(),
|
| + ResourceList(),
|
| + status));
|
| + return;
|
| + }
|
| +
|
| + // Find one with a pattern match.
|
| + // TODO(michaeln): if there are multiple matches the one with
|
| + // the longest scope should win.
|
| + ServiceWorkerDatabase::RegistrationData data;
|
| + ResourceList resources;
|
| + status = ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND;
|
| + for (RegistrationList::const_iterator it = registrations.begin();
|
| + it != registrations.end(); ++it) {
|
| + if (!ServiceWorkerUtils::ScopeMatches(it->scope, document_url))
|
| + continue;
|
| + status = database->ReadRegistration(it->registration_id, origin,
|
| + &data, &resources);
|
| + break; // We're done looping.
|
| + }
|
| +
|
| + original_task_runner->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(callback, data, resources, status));
|
| +}
|
| +
|
| +void ServiceWorkerStorage::FindForPatternInDB(
|
| + ServiceWorkerDatabase* database,
|
| + scoped_refptr<base::SequencedTaskRunner> original_task_runner,
|
| + const GURL& scope,
|
| + const FindInDBCallback& callback) {
|
| + GURL origin = scope.GetOrigin();
|
| + std::vector<ServiceWorkerDatabase::RegistrationData> registrations;
|
| + ServiceWorkerDatabase::Status status =
|
| + database->GetRegistrationsForOrigin(origin, ®istrations);
|
| + if (status != ServiceWorkerDatabase::STATUS_OK) {
|
| + original_task_runner->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(callback,
|
| + ServiceWorkerDatabase::RegistrationData(),
|
| + ResourceList(),
|
| + status));
|
| + return;
|
| + }
|
| +
|
| + // Find one with an exact matching scope.
|
| + ServiceWorkerDatabase::RegistrationData data;
|
| + ResourceList resources;
|
| + status = ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND;
|
| + for (RegistrationList::const_iterator it = registrations.begin();
|
| + it != registrations.end(); ++it) {
|
| + if (scope != it->scope)
|
| + continue;
|
| + status = database->ReadRegistration(it->registration_id, origin,
|
| + &data, &resources);
|
| + break; // We're done looping.
|
| + }
|
| +
|
| + original_task_runner->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(callback, data, resources, status));
|
| +}
|
| +
|
| +void ServiceWorkerStorage::FindForIdInDB(
|
| + ServiceWorkerDatabase* database,
|
| + scoped_refptr<base::SequencedTaskRunner> original_task_runner,
|
| + int64 registration_id,
|
| + const GURL& origin,
|
| + const FindInDBCallback& callback) {
|
| + ServiceWorkerDatabase::RegistrationData data;
|
| + ResourceList resources;
|
| + ServiceWorkerDatabase::Status status =
|
| + database->ReadRegistration(registration_id, origin, &data, &resources);
|
| + original_task_runner->PostTask(
|
| + FROM_HERE, base::Bind(callback, data, resources, status));
|
| +}
|
| +
|
| } // namespace content
|
|
|