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)); |
} |