| Index: chrome/browser/prefs/tracked/tracked_preferences_migration.cc
|
| diff --git a/chrome/browser/prefs/tracked/tracked_preferences_migration.cc b/chrome/browser/prefs/tracked/tracked_preferences_migration.cc
|
| index 079903d669dfb35df9d0c22c5cf6f07be11a2daa..1bdf8b5950894ec1e4f80120f348d458cb2de394 100644
|
| --- a/chrome/browser/prefs/tracked/tracked_preferences_migration.cc
|
| +++ b/chrome/browser/prefs/tracked/tracked_preferences_migration.cc
|
| @@ -11,6 +11,10 @@
|
| #include "base/memory/scoped_ptr.h"
|
| #include "base/values.h"
|
| #include "chrome/browser/prefs/interceptable_pref_filter.h"
|
| +#include "chrome/browser/prefs/pref_hash_store.h"
|
| +#include "chrome/browser/prefs/pref_hash_store_transaction.h"
|
| +#include "chrome/browser/prefs/tracked/dictionary_hash_store_contents.h"
|
| +#include "chrome/browser/prefs/tracked/hash_store_contents.h"
|
|
|
| namespace {
|
|
|
| @@ -28,6 +32,9 @@ class TrackedPreferencesMigrator
|
| register_on_successful_unprotected_store_write_callback,
|
| const base::Callback<void(const base::Closure&)>&
|
| register_on_successful_protected_store_write_callback,
|
| + scoped_ptr<PrefHashStore> unprotected_pref_hash_store,
|
| + scoped_ptr<PrefHashStore> protected_pref_hash_store,
|
| + scoped_ptr<HashStoreContents> legacy_pref_hash_store,
|
| InterceptablePrefFilter* unprotected_pref_filter,
|
| InterceptablePrefFilter* protected_pref_filter);
|
|
|
| @@ -68,6 +75,10 @@ class TrackedPreferencesMigrator
|
| InterceptablePrefFilter::FinalizeFilterOnLoadCallback
|
| finalize_protected_filter_on_load_;
|
|
|
| + scoped_ptr<PrefHashStore> unprotected_pref_hash_store_;
|
| + scoped_ptr<PrefHashStore> protected_pref_hash_store_;
|
| + scoped_ptr<HashStoreContents> legacy_pref_hash_store_;
|
| +
|
| base::DictionaryValue* unprotected_prefs_;
|
| base::DictionaryValue* protected_prefs_;
|
|
|
| @@ -109,35 +120,77 @@ void ScheduleSourcePrefStoreCleanup(
|
| // true if any old duplicates remain in |old_store| and sets |new_store_altered|
|
| // to true if any value was copied to |new_store|.
|
| void MigratePrefsFromOldToNewStore(const std::set<std::string>& pref_names,
|
| - const base::DictionaryValue* old_store,
|
| + base::DictionaryValue* old_store,
|
| base::DictionaryValue* new_store,
|
| + PrefHashStore* new_hash_store,
|
| bool* old_store_needs_cleanup,
|
| - bool* new_store_altered) {
|
| + bool* new_store_altered,
|
| + HashStoreContents* legacy_hash_store) {
|
| + DictionaryHashStoreContents old_hash_store(old_store);
|
| + const base::DictionaryValue* old_hash_store_contents =
|
| + old_hash_store.GetContents();
|
| + const base::DictionaryValue* legacy_hash_store_contents =
|
| + legacy_hash_store->GetContents();
|
| + scoped_ptr<PrefHashStoreTransaction> new_hash_store_transaction(
|
| + new_hash_store->BeginTransaction(new_store));
|
| +
|
| for (std::set<std::string>::const_iterator it = pref_names.begin();
|
| - it != pref_names.end(); ++it) {
|
| - const std::string& pref_name = *it;
|
| -
|
| - const base::Value* value_in_old_store = NULL;
|
| - if (!old_store->Get(pref_name, &value_in_old_store))
|
| - continue;
|
| -
|
| - // Whether this value ends up being copied below or was left behind by a
|
| - // previous incomplete migration, it should be cleaned up.
|
| - *old_store_needs_cleanup = true;
|
| -
|
| - if (new_store->Get(pref_name, NULL))
|
| - continue;
|
| -
|
| - // Copy the value from |old_store| to |new_store| rather than moving it to
|
| - // avoid data loss should |old_store| be flushed to disk without |new_store|
|
| - // having equivalently been successfully flushed to disk (e.g., on crash or
|
| - // in cases where |new_store| is read-only following a read error on
|
| - // startup).
|
| - new_store->Set(pref_name, value_in_old_store->DeepCopy());
|
| - *new_store_altered = true;
|
| + it != pref_names.end();
|
| + ++it) {
|
| + const std::string& pref_name = *it;
|
| + const base::Value* value_in_old_store = NULL;
|
| +
|
| + // If the destination does not have a hash for this pref we will
|
| + // unconditionally attempt to move it.
|
| + bool destination_hash_missing =
|
| + !new_hash_store_transaction->HasHash(pref_name);
|
| + // If we migrate the value we will also attempt to migrate the hash.
|
| + bool migrated_value = false;
|
| + if (old_store->Get(pref_name, &value_in_old_store)) {
|
| + // Whether this value ends up being copied below or was left behind by a
|
| + // previous incomplete migration, it should be cleaned up.
|
| + *old_store_needs_cleanup = true;
|
| +
|
| + if (!new_store->Get(pref_name, NULL)) {
|
| + // Copy the value from |old_store| to |new_store| rather than moving it
|
| + // to avoid data loss should |old_store| be flushed to disk without
|
| + // |new_store| having equivalently been successfully flushed to disk
|
| + // (e.g., on crash or in cases where |new_store| is read-only following
|
| + // a read error on startup).
|
| + scoped_ptr<base::Value> value_copy(value_in_old_store->DeepCopy());
|
| + new_store->Set(pref_name, value_copy.release());
|
| + migrated_value = true;
|
| + *new_store_altered = true;
|
| + }
|
| + }
|
| +
|
| + if (destination_hash_missing || migrated_value) {
|
| + const base::Value* old_hash = NULL;
|
| + if (old_hash_store_contents)
|
| + old_hash_store_contents->Get(pref_name, &old_hash);
|
| + if (!old_hash && legacy_hash_store_contents)
|
| + legacy_hash_store_contents->Get(pref_name, &old_hash);
|
| + if (old_hash || !destination_hash_missing) {
|
| + new_hash_store_transaction->ImportHash(pref_name, old_hash);
|
| + *new_store_altered = true;
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +void CleanupMigratedHashes(const std::set<std::string>& migrated_pref_names,
|
| + PrefHashStore* origin_pref_hash_store,
|
| + base::DictionaryValue* origin_pref_store) {
|
| + scoped_ptr<PrefHashStoreTransaction> transaction(
|
| + origin_pref_hash_store->BeginTransaction(origin_pref_store));
|
| + for (std::set<std::string>::const_iterator it = migrated_pref_names.begin();
|
| + it != migrated_pref_names.end();
|
| + ++it) {
|
| + transaction->ClearHash(*it);
|
| }
|
| }
|
|
|
| +
|
| TrackedPreferencesMigrator::TrackedPreferencesMigrator(
|
| const std::set<std::string>& unprotected_pref_names,
|
| const std::set<std::string>& protected_pref_names,
|
| @@ -148,6 +201,9 @@ TrackedPreferencesMigrator::TrackedPreferencesMigrator(
|
| register_on_successful_unprotected_store_write_callback,
|
| const base::Callback<void(const base::Closure&)>&
|
| register_on_successful_protected_store_write_callback,
|
| + scoped_ptr<PrefHashStore> unprotected_pref_hash_store,
|
| + scoped_ptr<PrefHashStore> protected_pref_hash_store,
|
| + scoped_ptr<HashStoreContents> legacy_pref_hash_store,
|
| InterceptablePrefFilter* unprotected_pref_filter,
|
| InterceptablePrefFilter* protected_pref_filter)
|
| : unprotected_pref_names_(unprotected_pref_names),
|
| @@ -158,6 +214,9 @@ TrackedPreferencesMigrator::TrackedPreferencesMigrator(
|
| register_on_successful_unprotected_store_write_callback),
|
| register_on_successful_protected_store_write_callback_(
|
| register_on_successful_protected_store_write_callback),
|
| + unprotected_pref_hash_store_(unprotected_pref_hash_store.Pass()),
|
| + protected_pref_hash_store_(protected_pref_hash_store.Pass()),
|
| + legacy_pref_hash_store_(legacy_pref_hash_store.Pass()),
|
| unprotected_prefs_(NULL),
|
| protected_prefs_(NULL) {
|
| // The callbacks bound below will own this TrackedPreferencesMigrator by
|
| @@ -203,15 +262,31 @@ void TrackedPreferencesMigrator::MigrateIfReady() {
|
| MigratePrefsFromOldToNewStore(unprotected_pref_names_,
|
| protected_prefs_,
|
| unprotected_prefs_,
|
| + unprotected_pref_hash_store_.get(),
|
| &protected_prefs_need_cleanup,
|
| - &unprotected_prefs_altered);
|
| + &unprotected_prefs_altered,
|
| + legacy_pref_hash_store_.get());
|
| bool unprotected_prefs_need_cleanup = false;
|
| bool protected_prefs_altered = false;
|
| MigratePrefsFromOldToNewStore(protected_pref_names_,
|
| unprotected_prefs_,
|
| protected_prefs_,
|
| + protected_pref_hash_store_.get(),
|
| &unprotected_prefs_need_cleanup,
|
| - &protected_prefs_altered);
|
| + &protected_prefs_altered,
|
| + legacy_pref_hash_store_.get());
|
| +
|
| +
|
| +
|
| + if (!unprotected_prefs_altered && !protected_prefs_altered) {
|
| + CleanupMigratedHashes(unprotected_pref_names_,
|
| + protected_pref_hash_store_.get(),
|
| + protected_prefs_);
|
| + CleanupMigratedHashes(protected_pref_names_,
|
| + unprotected_pref_hash_store_.get(),
|
| + unprotected_prefs_);
|
| + legacy_pref_hash_store_->Reset();
|
| + }
|
|
|
| // Allow preference loading to proceed.
|
| unprotected_prefs_ = NULL;
|
| @@ -242,6 +317,7 @@ void TrackedPreferencesMigrator::MigrateIfReady() {
|
| }
|
| }
|
|
|
| +
|
| } // namespace
|
|
|
| void SetupTrackedPreferencesMigration(
|
| @@ -254,6 +330,9 @@ void SetupTrackedPreferencesMigration(
|
| register_on_successful_unprotected_store_write_callback,
|
| const base::Callback<void(const base::Closure&)>&
|
| register_on_successful_protected_store_write_callback,
|
| + scoped_ptr<PrefHashStore> unprotected_pref_hash_store,
|
| + scoped_ptr<PrefHashStore> protected_pref_hash_store,
|
| + scoped_ptr<HashStoreContents> legacy_pref_hash_store,
|
| InterceptablePrefFilter* unprotected_pref_filter,
|
| InterceptablePrefFilter* protected_pref_filter) {
|
| scoped_refptr<TrackedPreferencesMigrator> prefs_migrator(
|
| @@ -264,6 +343,9 @@ void SetupTrackedPreferencesMigration(
|
| protected_store_cleaner,
|
| register_on_successful_unprotected_store_write_callback,
|
| register_on_successful_protected_store_write_callback,
|
| + unprotected_pref_hash_store.Pass(),
|
| + protected_pref_hash_store.Pass(),
|
| + legacy_pref_hash_store.Pass(),
|
| unprotected_pref_filter,
|
| protected_pref_filter));
|
| }
|
|
|