Chromium Code Reviews| 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..bae13526fce900e63bcc0266547e0a0e23263310 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; |
| + scoped_refptr<ServiceWorkerRegistration>()); |
|
nhiroki
2014/05/21 04:01:01
nit: indent
|
| } |
| 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( |
|
nhiroki
2014/05/21 04:01:01
nit: There is an extra whitespace before "new".
|
| + 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,238 @@ 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_); |
| + disk_cache()->DoomEntry( |
| + id, base::Bind(&ServiceWorkerStorage::OnResourcePurged, |
| + weak_factory_.GetWeakPtr(), id)); |
| +} |
| + |
| +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 |