OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "chrome/browser/prefs/tracked/tracked_preferences_migration.h" |
| 6 |
| 7 #include "base/bind.h" |
| 8 #include "base/callback.h" |
| 9 #include "base/macros.h" |
| 10 #include "base/memory/ref_counted.h" |
| 11 #include "base/memory/scoped_ptr.h" |
| 12 #include "base/memory/weak_ptr.h" |
| 13 #include "base/prefs/json_pref_store.h" |
| 14 #include "base/values.h" |
| 15 |
| 16 namespace { |
| 17 |
| 18 class TrackedPreferencesMigrator |
| 19 : public base::RefCounted<TrackedPreferencesMigrator> { |
| 20 public: |
| 21 // Constructs a TrackedPreferencesMigrator which sets itself up as the |
| 22 // OnFileReadInterceptor for both |unprotected_pref_store| and |
| 23 // |protected_pref_store|. It guarantees that the most recent pref value |
| 24 // for |unprotected_pref_names| and |protected_pref_names| are in the |
| 25 // appropriate JsonPrefStores before those stores even sees those values. |
| 26 TrackedPreferencesMigrator( |
| 27 const std::set<std::string>& unprotected_pref_names, |
| 28 const std::set<std::string>& protected_pref_names, |
| 29 JsonPrefStore* unprotected_pref_store, |
| 30 JsonPrefStore* protected_pref_store); |
| 31 |
| 32 private: |
| 33 friend class base::RefCounted<TrackedPreferencesMigrator>; |
| 34 |
| 35 enum PrefStoreID { |
| 36 UNPROTECTED_PREFERENCE_STORE, |
| 37 PROTECTED_PREFERENCE_STORE |
| 38 }; |
| 39 |
| 40 ~TrackedPreferencesMigrator(); |
| 41 |
| 42 // Stores the data coming in for the store identified by |id| into this class |
| 43 // and then calls MigrateIfReady(); |
| 44 void OnFileRead( |
| 45 PrefStoreID id, |
| 46 scoped_ptr<base::DictionaryValue> prefs, |
| 47 const JsonPrefStore::FinalizePrefsReadCallback& finalize_prefs_read); |
| 48 |
| 49 // Proceeds with migration if both |unprotected_prefs_| and |protected_prefs_| |
| 50 // have been set. |
| 51 void MigrateIfReady(); |
| 52 |
| 53 const std::set<std::string> unprotected_pref_names_; |
| 54 const std::set<std::string> protected_pref_names_; |
| 55 |
| 56 scoped_ptr<base::DictionaryValue> unprotected_prefs_; |
| 57 scoped_ptr<base::DictionaryValue> protected_prefs_; |
| 58 |
| 59 JsonPrefStore::FinalizePrefsReadCallback finalize_unprotected_prefs_read_; |
| 60 JsonPrefStore::FinalizePrefsReadCallback finalize_protected_prefs_read_; |
| 61 |
| 62 DISALLOW_COPY_AND_ASSIGN(TrackedPreferencesMigrator); |
| 63 }; |
| 64 |
| 65 // Silently removes all |keys_to_clean| from |pref_store| if the weak pointer is |
| 66 // still valid. |
| 67 void CleanupPrefStore(const base::WeakPtr<JsonPrefStore>& pref_store, |
| 68 const std::set<std::string>& keys_to_clean) { |
| 69 if (pref_store) { |
| 70 for (std::set<std::string>::const_iterator it = keys_to_clean.begin(); |
| 71 it != keys_to_clean.end(); ++it) { |
| 72 // Silently clean the values as they have already been copied to their |
| 73 // new authoritative store and we don't want to alert PrefStore observers |
| 74 // about the irrelevant removal of this value which no one should be |
| 75 // reading anymore. |
| 76 pref_store->RemoveValueSilently(*it); |
| 77 } |
| 78 } |
| 79 } |
| 80 |
| 81 // If |wait_for_commit_to_destination_store|: schedules a cleanup of the |
| 82 // |keys_to_clean| from the |source_pref_store| once the |
| 83 // |destination_pref_store| they were migrated to was successfully written to |
| 84 // disk. Otherwise, executes the cleanup right away. |
| 85 void ScheduleSourcePrefStoreCleanup( |
| 86 const base::WeakPtr<JsonPrefStore>& source_pref_store, |
| 87 const std::set<std::string>& keys_to_clean, |
| 88 bool wait_for_commit_to_destination_store, |
| 89 JsonPrefStore* destination_pref_store) { |
| 90 DCHECK(source_pref_store); |
| 91 DCHECK(destination_pref_store); |
| 92 DCHECK(!keys_to_clean.empty()); |
| 93 if (wait_for_commit_to_destination_store) { |
| 94 destination_pref_store->RegisterOnNextSuccessfulWriteCallback( |
| 95 base::Bind(&CleanupPrefStore, source_pref_store, keys_to_clean)); |
| 96 } else { |
| 97 CleanupPrefStore(source_pref_store, keys_to_clean); |
| 98 } |
| 99 } |
| 100 |
| 101 // Copies the value of each pref in |pref_names| which is set in |old_store|, |
| 102 // but not in |new_store| into |new_store|. Sets |old_store_needs_cleanup| to |
| 103 // true if any old duplicates remain in |old_store| and sets |new_store_altered| |
| 104 // to true if any value was copied to |new_store|. |
| 105 void MigratePrefsFromOldToNewStore( |
| 106 const std::set<std::string>& pref_names, |
| 107 const base::DictionaryValue* old_store, |
| 108 base::DictionaryValue* new_store, |
| 109 bool* old_store_needs_cleanup, |
| 110 bool* new_store_altered) { |
| 111 for (std::set<std::string>::const_iterator it = pref_names.begin(); |
| 112 it != pref_names.end(); ++it) { |
| 113 const std::string& pref_name = *it; |
| 114 |
| 115 const base::Value* value_in_old_store = NULL; |
| 116 if (!old_store->Get(pref_name, &value_in_old_store)) |
| 117 continue; |
| 118 |
| 119 // Whether this value ends up being copied below or was left behind by a |
| 120 // previous incomplete migration, it should be cleaned up. |
| 121 *old_store_needs_cleanup = true; |
| 122 |
| 123 if (new_store->Get(pref_name, NULL)) |
| 124 continue; |
| 125 |
| 126 // Copy the value from |old_store| to |new_store| rather than moving it to |
| 127 // avoid data loss should |old_store| be flushed to disk without |new_store| |
| 128 // having equivalently been successfully flushed to disk (e.g., on crash or |
| 129 // in cases where |new_store| is read-only following a read error on |
| 130 // startup). |
| 131 new_store->Set(pref_name, value_in_old_store->DeepCopy()); |
| 132 *new_store_altered = true; |
| 133 } |
| 134 } |
| 135 |
| 136 TrackedPreferencesMigrator::TrackedPreferencesMigrator( |
| 137 const std::set<std::string>& unprotected_pref_names, |
| 138 const std::set<std::string>& protected_pref_names, |
| 139 JsonPrefStore* unprotected_pref_store, |
| 140 JsonPrefStore* protected_pref_store) |
| 141 : unprotected_pref_names_(unprotected_pref_names), |
| 142 protected_pref_names_(protected_pref_names) { |
| 143 // The callbacks bound below will own this TrackedPreferencesMigrator by |
| 144 // reference. |
| 145 unprotected_pref_store->InterceptNextFileRead( |
| 146 base::Bind(&TrackedPreferencesMigrator::OnFileRead, |
| 147 this, |
| 148 UNPROTECTED_PREFERENCE_STORE)); |
| 149 protected_pref_store->InterceptNextFileRead( |
| 150 base::Bind(&TrackedPreferencesMigrator::OnFileRead, |
| 151 this, |
| 152 PROTECTED_PREFERENCE_STORE)); |
| 153 } |
| 154 |
| 155 TrackedPreferencesMigrator::~TrackedPreferencesMigrator() {} |
| 156 |
| 157 void TrackedPreferencesMigrator::OnFileRead( |
| 158 PrefStoreID id, |
| 159 scoped_ptr<base::DictionaryValue> prefs, |
| 160 const JsonPrefStore::FinalizePrefsReadCallback& finalize_prefs_read) { |
| 161 switch (id) { |
| 162 case UNPROTECTED_PREFERENCE_STORE: |
| 163 unprotected_prefs_ = prefs.Pass(); |
| 164 finalize_unprotected_prefs_read_ = finalize_prefs_read; |
| 165 break; |
| 166 case PROTECTED_PREFERENCE_STORE: |
| 167 protected_prefs_ = prefs.Pass(); |
| 168 finalize_protected_prefs_read_ = finalize_prefs_read; |
| 169 break; |
| 170 } |
| 171 |
| 172 MigrateIfReady(); |
| 173 } |
| 174 |
| 175 void TrackedPreferencesMigrator::MigrateIfReady() { |
| 176 // Wait for both stores to have been read before proceeding. |
| 177 if (!protected_prefs_ || !unprotected_prefs_) |
| 178 return; |
| 179 |
| 180 bool protected_prefs_need_cleanup = false; |
| 181 bool unprotected_prefs_altered = false; |
| 182 MigratePrefsFromOldToNewStore(unprotected_pref_names_, |
| 183 protected_prefs_.get(), |
| 184 unprotected_prefs_.get(), |
| 185 &protected_prefs_need_cleanup, |
| 186 &unprotected_prefs_altered); |
| 187 bool unprotected_prefs_need_cleanup = false; |
| 188 bool protected_prefs_altered = false; |
| 189 MigratePrefsFromOldToNewStore(protected_pref_names_, |
| 190 unprotected_prefs_.get(), |
| 191 protected_prefs_.get(), |
| 192 &unprotected_prefs_need_cleanup, |
| 193 &protected_prefs_altered); |
| 194 |
| 195 // Hand the processed prefs back to their respective JsonPrefStore and keep |
| 196 // weak pointers to those stores to make a best effort attempt at cleaning up |
| 197 // duplicate values once those values' destination store was successfully |
| 198 // written to disk. |
| 199 base::WeakPtr<JsonPrefStore> unprotected_pref_store = |
| 200 finalize_unprotected_prefs_read_.Run(unprotected_prefs_.Pass(), |
| 201 unprotected_prefs_altered); |
| 202 base::WeakPtr<JsonPrefStore> protected_pref_store = |
| 203 finalize_protected_prefs_read_.Run(protected_prefs_.Pass(), |
| 204 protected_prefs_altered); |
| 205 DCHECK(unprotected_pref_store); |
| 206 DCHECK(protected_pref_store); |
| 207 |
| 208 if (unprotected_prefs_need_cleanup) { |
| 209 // Cleanup the |protected_pref_names_| from the |unprotected_pref_store| |
| 210 // once they were successfully written to the |protected_pref_store|. |
| 211 ScheduleSourcePrefStoreCleanup(unprotected_pref_store, |
| 212 protected_pref_names_, |
| 213 protected_prefs_altered, |
| 214 protected_pref_store.get()); |
| 215 } |
| 216 |
| 217 if (protected_prefs_need_cleanup) { |
| 218 // Cleanup the |unprotected_pref_names_| from the |protected_pref_store| |
| 219 // once they were successfully written to the |unprotected_pref_store|. |
| 220 ScheduleSourcePrefStoreCleanup(protected_pref_store, |
| 221 unprotected_pref_names_, |
| 222 unprotected_prefs_altered, |
| 223 unprotected_pref_store.get()); |
| 224 } |
| 225 } |
| 226 |
| 227 } // namespace |
| 228 |
| 229 void SetupTrackedPreferencesMigration( |
| 230 const std::set<std::string>& unprotected_pref_names, |
| 231 const std::set<std::string>& protected_pref_names, |
| 232 JsonPrefStore* unprotected_pref_store, |
| 233 JsonPrefStore* protected_pref_store) { |
| 234 scoped_refptr<TrackedPreferencesMigrator> prefs_migrator( |
| 235 new TrackedPreferencesMigrator(unprotected_pref_names, |
| 236 protected_pref_names, |
| 237 unprotected_pref_store, |
| 238 protected_pref_store)); |
| 239 } |
OLD | NEW |