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 b0c59e037b0dc89c26df81b5d30e45f53644db80..077ae33dd4a77c45b022efcccdacf7af11d9b961 100644 |
--- a/content/browser/service_worker/service_worker_storage.cc |
+++ b/content/browser/service_worker/service_worker_storage.cc |
@@ -14,8 +14,8 @@ |
#include "base/trace_event/trace_event.h" |
#include "content/browser/service_worker/service_worker_context_core.h" |
#include "content/browser/service_worker/service_worker_disk_cache.h" |
+#include "content/browser/service_worker/service_worker_disk_cache_migrator.h" |
#include "content/browser/service_worker/service_worker_info.h" |
-#include "content/browser/service_worker/service_worker_metrics.h" |
#include "content/browser/service_worker/service_worker_registration.h" |
#include "content/browser/service_worker/service_worker_utils.h" |
#include "content/browser/service_worker/service_worker_version.h" |
@@ -60,7 +60,8 @@ void CompleteFindSoon( |
const base::FilePath::CharType kDatabaseName[] = |
FILE_PATH_LITERAL("Database"); |
const base::FilePath::CharType kDiskCacheName[] = |
- FILE_PATH_LITERAL("Cache"); |
+ FILE_PATH_LITERAL("ScriptCache"); |
+const base::FilePath::CharType kOldDiskCacheName[] = FILE_PATH_LITERAL("Cache"); |
const int kMaxMemDiskCacheSize = 10 * 1024 * 1024; |
const int kMaxDiskCacheSize = 250 * 1024 * 1024; |
@@ -207,7 +208,9 @@ void ResponseComparer::OnReadDataComplete(int result) { |
ServiceWorkerStorage::InitialData::InitialData() |
: next_registration_id(kInvalidServiceWorkerRegistrationId), |
next_version_id(kInvalidServiceWorkerVersionId), |
- next_resource_id(kInvalidServiceWorkerResourceId) { |
+ next_resource_id(kInvalidServiceWorkerResourceId), |
+ disk_cache_migration_needed(false), |
+ old_disk_cache_deletion_needed(false) { |
} |
ServiceWorkerStorage::InitialData::~InitialData() { |
@@ -928,6 +931,8 @@ ServiceWorkerStorage::ServiceWorkerStorage( |
disk_cache_thread_(disk_cache_thread), |
quota_manager_proxy_(quota_manager_proxy), |
special_storage_policy_(special_storage_policy), |
+ disk_cache_migration_needed_(false), |
+ old_disk_cache_deletion_needed_(false), |
is_purge_pending_(false), |
has_checked_for_stale_resources_(false), |
weak_factory_(this) { |
@@ -948,6 +953,13 @@ base::FilePath ServiceWorkerStorage::GetDiskCachePath() { |
.Append(kDiskCacheName); |
} |
+base::FilePath ServiceWorkerStorage::GetOldDiskCachePath() { |
+ if (path_.empty()) |
+ return base::FilePath(); |
+ return path_.Append(ServiceWorkerContextCore::kServiceWorkerDirectory) |
+ .Append(kOldDiskCacheName); |
+} |
+ |
bool ServiceWorkerStorage::LazyInitialize(const base::Closure& callback) { |
if (!context_) |
return false; |
@@ -987,6 +999,8 @@ void ServiceWorkerStorage::DidReadInitialData( |
next_version_id_ = data->next_version_id; |
next_resource_id_ = data->next_resource_id; |
registered_origins_.swap(data->origins); |
+ disk_cache_migration_needed_ = data->disk_cache_migration_needed; |
+ old_disk_cache_deletion_needed_ = data->old_disk_cache_deletion_needed; |
state_ = INITIALIZED; |
} else { |
DVLOG(2) << "Failed to initialize: " |
@@ -1407,10 +1421,11 @@ ServiceWorkerStorage::FindInstallingRegistrationForId( |
} |
ServiceWorkerDiskCache* ServiceWorkerStorage::disk_cache() { |
+ DCHECK_EQ(INITIALIZED, state_); |
if (disk_cache_) |
return disk_cache_.get(); |
- disk_cache_ = ServiceWorkerDiskCache::CreateWithBlockFileBackend(); |
+ disk_cache_ = ServiceWorkerDiskCache::CreateWithSimpleBackend(); |
base::FilePath path = GetDiskCachePath(); |
if (path.empty()) { |
@@ -1420,17 +1435,90 @@ ServiceWorkerDiskCache* ServiceWorkerStorage::disk_cache() { |
return disk_cache_.get(); |
} |
+ if (disk_cache_migration_needed_) { |
+ // Defer the start of initialization until a migration is complete. |
+ disk_cache_->set_is_waiting_to_initialize(true); |
+ DCHECK(!disk_cache_migrator_); |
+ disk_cache_migrator_.reset(new ServiceWorkerDiskCacheMigrator( |
+ GetOldDiskCachePath(), GetDiskCachePath(), kMaxDiskCacheSize, |
+ disk_cache_thread_)); |
+ disk_cache_migrator_->Start( |
+ base::Bind(&ServiceWorkerStorage::DidMigrateDiskCache, |
+ weak_factory_.GetWeakPtr())); |
+ return disk_cache_.get(); |
+ } |
+ |
+ if (old_disk_cache_deletion_needed_) { |
+ // Lazily delete the old diskcache. |
+ BrowserThread::PostAfterStartupTask( |
+ FROM_HERE, database_task_manager_->GetTaskRunner(), |
+ base::Bind(&DeleteOldDiskCacheInDB, database_.get(), |
+ GetOldDiskCachePath())); |
+ } |
+ |
+ ServiceWorkerMetrics::RecordDiskCacheMigrationResult( |
+ ServiceWorkerMetrics::MIGRATION_NOT_NECESSARY); |
+ |
+ InitializeDiskCache(); |
+ return disk_cache_.get(); |
+} |
+ |
+void ServiceWorkerStorage::DidMigrateDiskCache(ServiceWorkerStatusCode status) { |
+ disk_cache_migrator_.reset(); |
+ if (status != SERVICE_WORKER_OK) { |
+ OnDiskCacheMigrationFailed(); |
+ return; |
+ } |
+ |
+ PostTaskAndReplyWithResult( |
+ database_task_manager_->GetTaskRunner(), FROM_HERE, |
+ base::Bind(&ServiceWorkerDatabase::SetDiskCacheMigrationNotNeeded, |
+ base::Unretained(database_.get())), |
+ base::Bind(&ServiceWorkerStorage::DidSetDiskCacheMigrationNotNeeded, |
+ weak_factory_.GetWeakPtr())); |
+} |
+ |
+void ServiceWorkerStorage::DidSetDiskCacheMigrationNotNeeded( |
+ ServiceWorkerDatabase::Status status) { |
+ if (status != ServiceWorkerDatabase::STATUS_OK) { |
+ OnDiskCacheMigrationFailed(); |
+ return; |
+ } |
+ |
+ // Lazily delete the old diskcache and update the database. |
+ BrowserThread::PostAfterStartupTask( |
+ FROM_HERE, database_task_manager_->GetTaskRunner(), |
+ base::Bind(&DeleteOldDiskCacheInDB, database_.get(), |
+ GetOldDiskCachePath())); |
+ |
+ ServiceWorkerMetrics::RecordDiskCacheMigrationResult( |
+ ServiceWorkerMetrics::MIGRATION_OK); |
+ InitializeDiskCache(); |
+} |
+ |
+void ServiceWorkerStorage::OnDiskCacheMigrationFailed() { |
+ ServiceWorkerMetrics::RecordDiskCacheMigrationResult( |
+ ServiceWorkerMetrics::MIGRATION_ERROR_FAILED); |
+ |
+ // Give up migration and recreate the whole storage. |
+ ScheduleDeleteAndStartOver(); |
+ |
+ // Lazily delete the old diskcache. Don't have to update the database |
+ // because it will be deleted by DeleteAndStartOver. |
+ BrowserThread::PostAfterStartupTask( |
+ FROM_HERE, disk_cache_thread_.get(), |
+ base::Bind(base::IgnoreResult(&base::DeleteFile), GetOldDiskCachePath(), |
+ true)); |
+} |
+ |
+void ServiceWorkerStorage::InitializeDiskCache() { |
+ disk_cache_->set_is_waiting_to_initialize(false); |
int rv = disk_cache_->InitWithDiskBackend( |
- path, |
- kMaxDiskCacheSize, |
- false, |
- disk_cache_thread_, |
+ GetDiskCachePath(), kMaxDiskCacheSize, false, disk_cache_thread_, |
base::Bind(&ServiceWorkerStorage::OnDiskCacheInitialized, |
weak_factory_.GetWeakPtr())); |
if (rv != net::ERR_IO_PENDING) |
OnDiskCacheInitialized(rv); |
- |
- return disk_cache_.get(); |
} |
void ServiceWorkerStorage::OnDiskCacheInitialized(int rv) { |
@@ -1588,11 +1676,36 @@ void ServiceWorkerStorage::ReadInitialDataFromDB( |
return; |
} |
+ status = |
+ database->IsDiskCacheMigrationNeeded(&data->disk_cache_migration_needed); |
+ if (status != ServiceWorkerDatabase::STATUS_OK) { |
+ original_task_runner->PostTask( |
+ FROM_HERE, base::Bind(callback, base::Owned(data.release()), status)); |
+ return; |
+ } |
+ |
+ status = database->IsOldDiskCacheDeletionNeeded( |
+ &data->old_disk_cache_deletion_needed); |
+ 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::DeleteOldDiskCacheInDB( |
+ ServiceWorkerDatabase* database, |
+ const base::FilePath& disk_cache_path) { |
+ // Ignore a failure. A retry will happen on the next initialization. |
+ if (!base::DeleteFile(disk_cache_path, true)) |
+ return; |
+ database->SetOldDiskCacheDeletionNotNeeded(); |
+} |
+ |
void ServiceWorkerStorage::DeleteRegistrationFromDB( |
ServiceWorkerDatabase* database, |
scoped_refptr<base::SequencedTaskRunner> original_task_runner, |