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 |