Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(6018)

Unified Diff: chrome/browser/extensions/app_data_migrator.cc

Issue 671873004: Migrates legacy packaged app data when it's upgraded to a platform app (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Addresses review comments Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/extensions/app_data_migrator.cc
diff --git a/chrome/browser/extensions/app_data_migrator.cc b/chrome/browser/extensions/app_data_migrator.cc
new file mode 100644
index 0000000000000000000000000000000000000000..6e19a329e1dfd8c1e1825a2adf3483a95b70b289
--- /dev/null
+++ b/chrome/browser/extensions/app_data_migrator.cc
@@ -0,0 +1,168 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/extensions/app_data_migrator.h"
+
+#include "base/files/file_util.h"
+#include "chrome/browser/profiles/profile.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/indexed_db_context.h"
+#include "content/public/browser/storage_partition.h"
+#include "extensions/browser/extension_registry.h"
+#include "extensions/common/extension.h"
+#include "storage/browser/fileapi/file_system_context.h"
+#include "storage/browser/fileapi/sandbox_file_system_backend_delegate.h"
+#include "storage/common/fileapi/file_system_types.h"
+
+using content::BrowserContext;
+using content::BrowserThread;
+using content::IndexedDBContext;
+using content::StoragePartition;
+using storage::FileSystemContext;
+using storage::SandboxFileSystemBackendDelegate;
+
+namespace {
+
+void MigrateOnFileSystemThread(FileSystemContext* old_fs_context,
+ FileSystemContext* fs_context,
+ const extensions::Extension* extension) {
+ DCHECK(
+ old_fs_context->default_file_task_runner()->RunsTasksOnCurrentThread());
+
+ SandboxFileSystemBackendDelegate* old_sandbox_delegate =
+ old_fs_context->sandbox_delegate();
+ SandboxFileSystemBackendDelegate* sandbox_delegate =
+ fs_context->sandbox_delegate();
+
+ GURL extension_url =
+ extensions::Extension::GetBaseURLFromExtensionId(extension->id());
+
+ scoped_ptr<storage::SandboxFileSystemBackendDelegate::OriginEnumerator>
+ enumerator(old_sandbox_delegate->CreateOriginEnumerator());
+
+ // Find out if there is a file system that needs migration.
+ GURL origin;
+ do {
+ origin = enumerator->Next();
+ } while (origin != extension_url && !origin.is_empty());
+
+ if (!origin.is_empty()) {
+ // Copy the temporary file system.
+ if (enumerator->HasFileSystemType(storage::kFileSystemTypeTemporary)) {
+ old_sandbox_delegate->CopyFileSystem(
+ extension_url, storage::kFileSystemTypeTemporary, sandbox_delegate);
+ }
+ // Copy the persistent file system.
+ if (enumerator->HasFileSystemType(storage::kFileSystemTypePersistent)) {
+ old_sandbox_delegate->CopyFileSystem(
+ extension_url, storage::kFileSystemTypePersistent, sandbox_delegate);
+ }
+ }
+}
+
+void MigrateOnIndexedDBThread(IndexedDBContext* old_indexed_db_context,
+ IndexedDBContext* indexed_db_context,
+ const extensions::Extension* extension) {
+ DCHECK(old_indexed_db_context->TaskRunner()->RunsTasksOnCurrentThread());
+
+ GURL extension_url =
+ extensions::Extension::GetBaseURLFromExtensionId(extension->id());
+
+ old_indexed_db_context->CopyOriginData(extension_url, indexed_db_context);
+}
+
+void MigrateFileSystem(StoragePartition* old_partition,
+ StoragePartition* current_partition,
+ const extensions::Extension* extension,
+ const base::Closure& reply) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ // Retrieve the fs contexts in preparation for migration.
+ FileSystemContext* old_fs_context = old_partition->GetFileSystemContext();
+ FileSystemContext* fs_context = current_partition->GetFileSystemContext();
+
+ // Perform the file system migration on the old file system's
+ // sequenced task runner. This is to ensure it queues after any
+ // in-flight file system operations. After it completes, it should
+ // invoke the original callback passed into DoMigrationAndReply.
+ old_fs_context->default_file_task_runner()->PostTaskAndReply(
+ FROM_HERE,
+ base::Bind(&MigrateOnFileSystemThread, make_scoped_refptr(old_fs_context),
+ make_scoped_refptr(fs_context), make_scoped_refptr(extension)),
+ reply);
+}
+
+void MigrateLegacyPartition(StoragePartition* old_partition,
+ StoragePartition* current_partition,
+ const extensions::Extension* extension,
+ const base::Closure& reply) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ // Retrieve both IndexedDB contexts in preparation for migration.
cmumford 2015/01/06 15:30:26 Nit: I'm not sure this context (and the one above)
+ IndexedDBContext* indexed_db_context =
+ current_partition->GetIndexedDBContext();
+ IndexedDBContext* old_indexed_db_context =
+ old_partition->GetIndexedDBContext();
+
+ // Create a closure for the file system migration. This is the next step in
+ // the migration flow after the IndexedDB migration.
+ base::Closure migrate_fs =
+ base::Bind(&MigrateFileSystem, old_partition, current_partition,
tzik 2015/01/16 05:56:36 This closure may run after the profile has gone.
+ make_scoped_refptr(extension), reply);
+
+ // Perform the IndexedDB migration on the old context's sequenced task
+ // runner. After completion, it should call MigrateFileSystem.
+ old_indexed_db_context->TaskRunner()->PostTaskAndReply(
+ FROM_HERE, base::Bind(&MigrateOnIndexedDBThread,
+ make_scoped_refptr(old_indexed_db_context),
+ make_scoped_refptr(indexed_db_context),
+ make_scoped_refptr(extension)),
+ migrate_fs);
+}
+
+} // namespace
+
+namespace extensions {
+
+AppDataMigrator::AppDataMigrator(Profile* profile, ExtensionRegistry* registry)
+ : profile_(profile), registry_(registry) {
+}
+
+bool AppDataMigrator::NeedsMigration(const Extension* old,
+ const Extension* extension) {
+ return old && old->is_legacy_packaged_app() && extension->is_platform_app();
+}
+
+void AppDataMigrator::DoMigrationAndReply(const Extension* old,
+ const Extension* extension,
+ const base::Closure& reply) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(NeedsMigration(old, extension));
+
+ // This should retrieve the general storage partition.
+ content::StoragePartition* old_partition =
+ BrowserContext::GetStoragePartitionForSite(
+ profile_, Extension::GetBaseURLFromExtensionId(extension->id()));
+
+ // Enable the new extension so we can access its storage partition.
+ bool old_was_disabled = registry_->AddEnabled(extension);
+
+ // This should create a new isolated partition for the new version of the
+ // extension.
+ StoragePartition* new_partition = BrowserContext::GetStoragePartitionForSite(
+ profile_, Extension::GetBaseURLFromExtensionId(extension->id()));
+
+ // Now, restore the enabled/disabled state of the new and old extensions.
+ if (!old_was_disabled) {
cmumford 2015/01/06 15:30:26 No need for braces when scoping a single line of c
+ registry_->AddEnabled(old);
+ } else {
+ registry_->RemoveEnabled(extension->id());
+ }
+
+ // Begin the actual migration flow.
cmumford 2015/01/06 15:30:26 Nit: does this comment add much?
+ MigrateLegacyPartition(old_partition, new_partition, extension, reply);
+}
+
+} // namespace extensions

Powered by Google App Engine
This is Rietveld 408576698