| 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..4f3203540d57123fc7180042a6f12da7ada9b093
|
| --- /dev/null
|
| +++ b/chrome/browser/extensions/app_data_migrator.cc
|
| @@ -0,0 +1,178 @@
|
| +// Copyright 2015 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 "base/memory/weak_ptr.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 base::WeakPtr;
|
| +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(WeakPtr<extensions::AppDataMigrator> migrator,
|
| + StoragePartition* old_partition,
|
| + StoragePartition* current_partition,
|
| + const extensions::Extension* extension,
|
| + const base::Closure& reply) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| +
|
| + // Since this method is static and it's being run as a closure task, check to
|
| + // make sure the calling object is still around.
|
| + if (!migrator.get()) {
|
| + return;
|
| + }
|
| +
|
| + 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(WeakPtr<extensions::AppDataMigrator> migrator,
|
| + StoragePartition* old_partition,
|
| + StoragePartition* current_partition,
|
| + const extensions::Extension* extension,
|
| + const base::Closure& reply) {
|
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
|
| +
|
| + 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, migrator, old_partition, current_partition,
|
| + 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), weak_factory_(this) {
|
| +}
|
| +
|
| +AppDataMigrator::~AppDataMigrator() {
|
| +}
|
| +
|
| +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)
|
| + registry_->RemoveEnabled(extension->id());
|
| + else
|
| + registry_->AddEnabled(old);
|
| +
|
| + MigrateLegacyPartition(weak_factory_.GetWeakPtr(), old_partition,
|
| + new_partition, extension, reply);
|
| +}
|
| +
|
| +} // namespace extensions
|
|
|