OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/prefs/tracked/tracked_preferences_migration.h" | 5 #include "chrome/browser/prefs/tracked/tracked_preferences_migration.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback.h" | 8 #include "base/callback.h" |
9 #include "base/macros.h" | 9 #include "base/macros.h" |
10 #include "base/memory/ref_counted.h" | 10 #include "base/memory/ref_counted.h" |
11 #include "base/memory/scoped_ptr.h" | 11 #include "base/metrics/histogram.h" |
12 #include "base/values.h" | 12 #include "base/values.h" |
13 #include "chrome/browser/prefs/interceptable_pref_filter.h" | 13 #include "chrome/browser/prefs/interceptable_pref_filter.h" |
| 14 #include "chrome/browser/prefs/pref_hash_store.h" |
| 15 #include "chrome/browser/prefs/pref_hash_store_transaction.h" |
| 16 #include "chrome/browser/prefs/tracked/dictionary_hash_store_contents.h" |
| 17 #include "chrome/browser/prefs/tracked/hash_store_contents.h" |
14 | 18 |
15 namespace { | 19 namespace { |
16 | 20 |
17 class TrackedPreferencesMigrator | 21 class TrackedPreferencesMigrator |
18 : public base::RefCounted<TrackedPreferencesMigrator> { | 22 : public base::RefCounted<TrackedPreferencesMigrator> { |
19 public: | 23 public: |
20 TrackedPreferencesMigrator( | 24 TrackedPreferencesMigrator( |
21 const std::set<std::string>& unprotected_pref_names, | 25 const std::set<std::string>& unprotected_pref_names, |
22 const std::set<std::string>& protected_pref_names, | 26 const std::set<std::string>& protected_pref_names, |
23 const base::Callback<void(const std::string& key)>& | 27 const base::Callback<void(const std::string& key)>& |
24 unprotected_store_cleaner, | 28 unprotected_store_cleaner, |
25 const base::Callback<void(const std::string& key)>& | 29 const base::Callback<void(const std::string& key)>& |
26 protected_store_cleaner, | 30 protected_store_cleaner, |
27 const base::Callback<void(const base::Closure&)>& | 31 const base::Callback<void(const base::Closure&)>& |
28 register_on_successful_unprotected_store_write_callback, | 32 register_on_successful_unprotected_store_write_callback, |
29 const base::Callback<void(const base::Closure&)>& | 33 const base::Callback<void(const base::Closure&)>& |
30 register_on_successful_protected_store_write_callback, | 34 register_on_successful_protected_store_write_callback, |
| 35 scoped_ptr<PrefHashStore> unprotected_pref_hash_store, |
| 36 scoped_ptr<PrefHashStore> protected_pref_hash_store, |
| 37 scoped_ptr<HashStoreContents> legacy_pref_hash_store, |
31 InterceptablePrefFilter* unprotected_pref_filter, | 38 InterceptablePrefFilter* unprotected_pref_filter, |
32 InterceptablePrefFilter* protected_pref_filter); | 39 InterceptablePrefFilter* protected_pref_filter); |
33 | 40 |
34 private: | 41 private: |
35 friend class base::RefCounted<TrackedPreferencesMigrator>; | 42 friend class base::RefCounted<TrackedPreferencesMigrator>; |
36 | 43 |
37 enum PrefFilterID { | 44 enum PrefFilterID { |
38 UNPROTECTED_PREF_FILTER, | 45 UNPROTECTED_PREF_FILTER, |
39 PROTECTED_PREF_FILTER | 46 PROTECTED_PREF_FILTER |
40 }; | 47 }; |
(...skipping 20 matching lines...) Expand all Loading... |
61 const base::Callback<void(const base::Closure&)> | 68 const base::Callback<void(const base::Closure&)> |
62 register_on_successful_unprotected_store_write_callback_; | 69 register_on_successful_unprotected_store_write_callback_; |
63 const base::Callback<void(const base::Closure&)> | 70 const base::Callback<void(const base::Closure&)> |
64 register_on_successful_protected_store_write_callback_; | 71 register_on_successful_protected_store_write_callback_; |
65 | 72 |
66 InterceptablePrefFilter::FinalizeFilterOnLoadCallback | 73 InterceptablePrefFilter::FinalizeFilterOnLoadCallback |
67 finalize_unprotected_filter_on_load_; | 74 finalize_unprotected_filter_on_load_; |
68 InterceptablePrefFilter::FinalizeFilterOnLoadCallback | 75 InterceptablePrefFilter::FinalizeFilterOnLoadCallback |
69 finalize_protected_filter_on_load_; | 76 finalize_protected_filter_on_load_; |
70 | 77 |
| 78 scoped_ptr<PrefHashStore> unprotected_pref_hash_store_; |
| 79 scoped_ptr<PrefHashStore> protected_pref_hash_store_; |
| 80 scoped_ptr<HashStoreContents> legacy_pref_hash_store_; |
| 81 |
71 scoped_ptr<base::DictionaryValue> unprotected_prefs_; | 82 scoped_ptr<base::DictionaryValue> unprotected_prefs_; |
72 scoped_ptr<base::DictionaryValue> protected_prefs_; | 83 scoped_ptr<base::DictionaryValue> protected_prefs_; |
73 | 84 |
74 DISALLOW_COPY_AND_ASSIGN(TrackedPreferencesMigrator); | 85 DISALLOW_COPY_AND_ASSIGN(TrackedPreferencesMigrator); |
75 }; | 86 }; |
76 | 87 |
77 // Invokes |store_cleaner| for every |keys_to_clean|. | 88 // Invokes |store_cleaner| for every |keys_to_clean|. |
78 void CleanupPrefStore( | 89 void CleanupPrefStore( |
79 const base::Callback<void(const std::string& key)>& store_cleaner, | 90 const base::Callback<void(const std::string& key)>& store_cleaner, |
80 const std::set<std::string>& keys_to_clean) { | 91 const std::set<std::string>& keys_to_clean) { |
(...skipping 16 matching lines...) Expand all Loading... |
97 bool wait_for_commit_to_destination_store) { | 108 bool wait_for_commit_to_destination_store) { |
98 DCHECK(!keys_to_clean.empty()); | 109 DCHECK(!keys_to_clean.empty()); |
99 if (wait_for_commit_to_destination_store) { | 110 if (wait_for_commit_to_destination_store) { |
100 register_on_successful_destination_store_write_callback.Run( | 111 register_on_successful_destination_store_write_callback.Run( |
101 base::Bind(&CleanupPrefStore, source_store_cleaner, keys_to_clean)); | 112 base::Bind(&CleanupPrefStore, source_store_cleaner, keys_to_clean)); |
102 } else { | 113 } else { |
103 CleanupPrefStore(source_store_cleaner, keys_to_clean); | 114 CleanupPrefStore(source_store_cleaner, keys_to_clean); |
104 } | 115 } |
105 } | 116 } |
106 | 117 |
| 118 // Removes hashes for |migrated_pref_names| from |origin_pref_store| using |
| 119 // the configuration/implementation in |origin_pref_hash_store|. |
| 120 void CleanupMigratedHashes(const std::set<std::string>& migrated_pref_names, |
| 121 PrefHashStore* origin_pref_hash_store, |
| 122 base::DictionaryValue* origin_pref_store) { |
| 123 scoped_ptr<PrefHashStoreTransaction> transaction( |
| 124 origin_pref_hash_store->BeginTransaction(scoped_ptr<HashStoreContents>( |
| 125 new DictionaryHashStoreContents(origin_pref_store)))); |
| 126 for (std::set<std::string>::const_iterator it = migrated_pref_names.begin(); |
| 127 it != migrated_pref_names.end(); |
| 128 ++it) { |
| 129 transaction->ClearHash(*it); |
| 130 } |
| 131 } |
| 132 |
107 // Copies the value of each pref in |pref_names| which is set in |old_store|, | 133 // Copies the value of each pref in |pref_names| which is set in |old_store|, |
108 // but not in |new_store| into |new_store|. Sets |old_store_needs_cleanup| to | 134 // but not in |new_store| into |new_store|. Sets |old_store_needs_cleanup| to |
109 // true if any old duplicates remain in |old_store| and sets |new_store_altered| | 135 // true if any old duplicates remain in |old_store| and sets |new_store_altered| |
110 // to true if any value was copied to |new_store|. | 136 // to true if any value was copied to |new_store|. |
111 void MigratePrefsFromOldToNewStore(const std::set<std::string>& pref_names, | 137 void MigratePrefsFromOldToNewStore(const std::set<std::string>& pref_names, |
112 const base::DictionaryValue* old_store, | 138 base::DictionaryValue* old_store, |
113 base::DictionaryValue* new_store, | 139 base::DictionaryValue* new_store, |
| 140 PrefHashStore* new_hash_store, |
| 141 HashStoreContents* legacy_hash_store, |
114 bool* old_store_needs_cleanup, | 142 bool* old_store_needs_cleanup, |
115 bool* new_store_altered) { | 143 bool* new_store_altered, |
| 144 bool* used_legacy_pref_hashes) { |
| 145 const base::DictionaryValue* old_hash_store_contents = |
| 146 DictionaryHashStoreContents(old_store).GetContents(); |
| 147 const base::DictionaryValue* legacy_hash_store_contents = |
| 148 legacy_hash_store->GetContents(); |
| 149 scoped_ptr<PrefHashStoreTransaction> new_hash_store_transaction( |
| 150 new_hash_store->BeginTransaction(scoped_ptr<HashStoreContents>( |
| 151 new DictionaryHashStoreContents(new_store)))); |
| 152 |
116 for (std::set<std::string>::const_iterator it = pref_names.begin(); | 153 for (std::set<std::string>::const_iterator it = pref_names.begin(); |
117 it != pref_names.end(); ++it) { | 154 it != pref_names.end(); |
118 const std::string& pref_name = *it; | 155 ++it) { |
| 156 const std::string& pref_name = *it; |
| 157 const base::Value* value_in_old_store = NULL; |
119 | 158 |
120 const base::Value* value_in_old_store = NULL; | 159 // If the destination does not have a hash for this pref we will |
121 if (!old_store->Get(pref_name, &value_in_old_store)) | 160 // unconditionally attempt to move it. |
122 continue; | 161 bool destination_hash_missing = |
| 162 !new_hash_store_transaction->HasHash(pref_name); |
| 163 // If we migrate the value we will also attempt to migrate the hash. |
| 164 bool migrated_value = false; |
| 165 if (old_store->Get(pref_name, &value_in_old_store)) { |
| 166 // Whether this value ends up being copied below or was left behind by a |
| 167 // previous incomplete migration, it should be cleaned up. |
| 168 *old_store_needs_cleanup = true; |
123 | 169 |
124 // Whether this value ends up being copied below or was left behind by a | 170 if (!new_store->Get(pref_name, NULL)) { |
125 // previous incomplete migration, it should be cleaned up. | 171 // Copy the value from |old_store| to |new_store| rather than moving it |
126 *old_store_needs_cleanup = true; | 172 // to avoid data loss should |old_store| be flushed to disk without |
| 173 // |new_store| having equivalently been successfully flushed to disk |
| 174 // (e.g., on crash or in cases where |new_store| is read-only following |
| 175 // a read error on startup). |
| 176 new_store->Set(pref_name, value_in_old_store->DeepCopy()); |
| 177 migrated_value = true; |
| 178 *new_store_altered = true; |
| 179 } |
| 180 } |
127 | 181 |
128 if (new_store->Get(pref_name, NULL)) | 182 if (destination_hash_missing || migrated_value) { |
129 continue; | 183 const base::Value* old_hash = NULL; |
130 | 184 if (old_hash_store_contents) |
131 // Copy the value from |old_store| to |new_store| rather than moving it to | 185 old_hash_store_contents->Get(pref_name, &old_hash); |
132 // avoid data loss should |old_store| be flushed to disk without |new_store| | 186 if (!old_hash && legacy_hash_store_contents) { |
133 // having equivalently been successfully flushed to disk (e.g., on crash or | 187 legacy_hash_store_contents->Get(pref_name, &old_hash); |
134 // in cases where |new_store| is read-only following a read error on | 188 if (old_hash) |
135 // startup). | 189 *used_legacy_pref_hashes = true; |
136 new_store->Set(pref_name, value_in_old_store->DeepCopy()); | 190 } |
137 *new_store_altered = true; | 191 if (old_hash) { |
| 192 new_hash_store_transaction->ImportHash(pref_name, old_hash); |
| 193 *new_store_altered = true; |
| 194 } else if (!destination_hash_missing) { |
| 195 new_hash_store_transaction->ClearHash(pref_name); |
| 196 *new_store_altered = true; |
| 197 } |
| 198 } |
138 } | 199 } |
139 } | 200 } |
140 | 201 |
141 TrackedPreferencesMigrator::TrackedPreferencesMigrator( | 202 TrackedPreferencesMigrator::TrackedPreferencesMigrator( |
142 const std::set<std::string>& unprotected_pref_names, | 203 const std::set<std::string>& unprotected_pref_names, |
143 const std::set<std::string>& protected_pref_names, | 204 const std::set<std::string>& protected_pref_names, |
144 const base::Callback<void(const std::string& key)>& | 205 const base::Callback<void(const std::string& key)>& |
145 unprotected_store_cleaner, | 206 unprotected_store_cleaner, |
146 const base::Callback<void(const std::string& key)>& protected_store_cleaner, | 207 const base::Callback<void(const std::string& key)>& protected_store_cleaner, |
147 const base::Callback<void(const base::Closure&)>& | 208 const base::Callback<void(const base::Closure&)>& |
148 register_on_successful_unprotected_store_write_callback, | 209 register_on_successful_unprotected_store_write_callback, |
149 const base::Callback<void(const base::Closure&)>& | 210 const base::Callback<void(const base::Closure&)>& |
150 register_on_successful_protected_store_write_callback, | 211 register_on_successful_protected_store_write_callback, |
| 212 scoped_ptr<PrefHashStore> unprotected_pref_hash_store, |
| 213 scoped_ptr<PrefHashStore> protected_pref_hash_store, |
| 214 scoped_ptr<HashStoreContents> legacy_pref_hash_store, |
151 InterceptablePrefFilter* unprotected_pref_filter, | 215 InterceptablePrefFilter* unprotected_pref_filter, |
152 InterceptablePrefFilter* protected_pref_filter) | 216 InterceptablePrefFilter* protected_pref_filter) |
153 : unprotected_pref_names_(unprotected_pref_names), | 217 : unprotected_pref_names_(unprotected_pref_names), |
154 protected_pref_names_(protected_pref_names), | 218 protected_pref_names_(protected_pref_names), |
155 unprotected_store_cleaner_(unprotected_store_cleaner), | 219 unprotected_store_cleaner_(unprotected_store_cleaner), |
156 protected_store_cleaner_(protected_store_cleaner), | 220 protected_store_cleaner_(protected_store_cleaner), |
157 register_on_successful_unprotected_store_write_callback_( | 221 register_on_successful_unprotected_store_write_callback_( |
158 register_on_successful_unprotected_store_write_callback), | 222 register_on_successful_unprotected_store_write_callback), |
159 register_on_successful_protected_store_write_callback_( | 223 register_on_successful_protected_store_write_callback_( |
160 register_on_successful_protected_store_write_callback) { | 224 register_on_successful_protected_store_write_callback), |
| 225 unprotected_pref_hash_store_(unprotected_pref_hash_store.Pass()), |
| 226 protected_pref_hash_store_(protected_pref_hash_store.Pass()), |
| 227 legacy_pref_hash_store_(legacy_pref_hash_store.Pass()) { |
161 // The callbacks bound below will own this TrackedPreferencesMigrator by | 228 // The callbacks bound below will own this TrackedPreferencesMigrator by |
162 // reference. | 229 // reference. |
163 unprotected_pref_filter->InterceptNextFilterOnLoad( | 230 unprotected_pref_filter->InterceptNextFilterOnLoad( |
164 base::Bind(&TrackedPreferencesMigrator::InterceptFilterOnLoad, | 231 base::Bind(&TrackedPreferencesMigrator::InterceptFilterOnLoad, |
165 this, | 232 this, |
166 UNPROTECTED_PREF_FILTER)); | 233 UNPROTECTED_PREF_FILTER)); |
167 protected_pref_filter->InterceptNextFilterOnLoad( | 234 protected_pref_filter->InterceptNextFilterOnLoad( |
168 base::Bind(&TrackedPreferencesMigrator::InterceptFilterOnLoad, | 235 base::Bind(&TrackedPreferencesMigrator::InterceptFilterOnLoad, |
169 this, | 236 this, |
170 PROTECTED_PREF_FILTER)); | 237 PROTECTED_PREF_FILTER)); |
(...skipping 18 matching lines...) Expand all Loading... |
189 } | 256 } |
190 | 257 |
191 MigrateIfReady(); | 258 MigrateIfReady(); |
192 } | 259 } |
193 | 260 |
194 void TrackedPreferencesMigrator::MigrateIfReady() { | 261 void TrackedPreferencesMigrator::MigrateIfReady() { |
195 // Wait for both stores to have been read before proceeding. | 262 // Wait for both stores to have been read before proceeding. |
196 if (!protected_prefs_ || !unprotected_prefs_) | 263 if (!protected_prefs_ || !unprotected_prefs_) |
197 return; | 264 return; |
198 | 265 |
| 266 bool used_legacy_pref_hashes = false; |
199 bool protected_prefs_need_cleanup = false; | 267 bool protected_prefs_need_cleanup = false; |
200 bool unprotected_prefs_altered = false; | 268 bool unprotected_prefs_altered = false; |
201 MigratePrefsFromOldToNewStore(unprotected_pref_names_, | 269 MigratePrefsFromOldToNewStore(unprotected_pref_names_, |
202 protected_prefs_.get(), | 270 protected_prefs_.get(), |
203 unprotected_prefs_.get(), | 271 unprotected_prefs_.get(), |
| 272 unprotected_pref_hash_store_.get(), |
| 273 legacy_pref_hash_store_.get(), |
204 &protected_prefs_need_cleanup, | 274 &protected_prefs_need_cleanup, |
205 &unprotected_prefs_altered); | 275 &unprotected_prefs_altered, |
| 276 &used_legacy_pref_hashes); |
206 bool unprotected_prefs_need_cleanup = false; | 277 bool unprotected_prefs_need_cleanup = false; |
207 bool protected_prefs_altered = false; | 278 bool protected_prefs_altered = false; |
208 MigratePrefsFromOldToNewStore(protected_pref_names_, | 279 MigratePrefsFromOldToNewStore(protected_pref_names_, |
209 unprotected_prefs_.get(), | 280 unprotected_prefs_.get(), |
210 protected_prefs_.get(), | 281 protected_prefs_.get(), |
| 282 protected_pref_hash_store_.get(), |
| 283 legacy_pref_hash_store_.get(), |
211 &unprotected_prefs_need_cleanup, | 284 &unprotected_prefs_need_cleanup, |
212 &protected_prefs_altered); | 285 &protected_prefs_altered, |
| 286 &used_legacy_pref_hashes); |
| 287 UMA_HISTOGRAM_BOOLEAN("Settings.MigratedHashesFromLocalState", |
| 288 used_legacy_pref_hashes); |
| 289 |
| 290 if (!unprotected_prefs_altered && !protected_prefs_altered) { |
| 291 // Clean up any MACs that might have been previously migrated from the |
| 292 // various stores. It's safe to leave them behind for a little while as they |
| 293 // will be ignored unless the corresponding value is _also_ present. The |
| 294 // cleanup must be deferred until the MACs have been written to their target |
| 295 // stores, and doing so in a subsequent launch is easier than within the |
| 296 // same process. |
| 297 CleanupMigratedHashes(unprotected_pref_names_, |
| 298 protected_pref_hash_store_.get(), |
| 299 protected_prefs_.get()); |
| 300 CleanupMigratedHashes(protected_pref_names_, |
| 301 unprotected_pref_hash_store_.get(), |
| 302 unprotected_prefs_.get()); |
| 303 legacy_pref_hash_store_->Reset(); |
| 304 } |
213 | 305 |
214 // Hand the processed prefs back to their respective filters. | 306 // Hand the processed prefs back to their respective filters. |
215 finalize_unprotected_filter_on_load_.Run(unprotected_prefs_.Pass(), | 307 finalize_unprotected_filter_on_load_.Run(unprotected_prefs_.Pass(), |
216 unprotected_prefs_altered); | 308 unprotected_prefs_altered); |
217 finalize_protected_filter_on_load_.Run(protected_prefs_.Pass(), | 309 finalize_protected_filter_on_load_.Run(protected_prefs_.Pass(), |
218 protected_prefs_altered); | 310 protected_prefs_altered); |
219 | 311 |
220 if (unprotected_prefs_need_cleanup) { | 312 if (unprotected_prefs_need_cleanup) { |
221 // Schedule a cleanup of the |protected_pref_names_| from the unprotected | 313 // Schedule a cleanup of the |protected_pref_names_| from the unprotected |
222 // prefs once the protected prefs were successfully written to disk (or | 314 // prefs once the protected prefs were successfully written to disk (or |
(...skipping 22 matching lines...) Expand all Loading... |
245 void SetupTrackedPreferencesMigration( | 337 void SetupTrackedPreferencesMigration( |
246 const std::set<std::string>& unprotected_pref_names, | 338 const std::set<std::string>& unprotected_pref_names, |
247 const std::set<std::string>& protected_pref_names, | 339 const std::set<std::string>& protected_pref_names, |
248 const base::Callback<void(const std::string& key)>& | 340 const base::Callback<void(const std::string& key)>& |
249 unprotected_store_cleaner, | 341 unprotected_store_cleaner, |
250 const base::Callback<void(const std::string& key)>& protected_store_cleaner, | 342 const base::Callback<void(const std::string& key)>& protected_store_cleaner, |
251 const base::Callback<void(const base::Closure&)>& | 343 const base::Callback<void(const base::Closure&)>& |
252 register_on_successful_unprotected_store_write_callback, | 344 register_on_successful_unprotected_store_write_callback, |
253 const base::Callback<void(const base::Closure&)>& | 345 const base::Callback<void(const base::Closure&)>& |
254 register_on_successful_protected_store_write_callback, | 346 register_on_successful_protected_store_write_callback, |
| 347 scoped_ptr<PrefHashStore> unprotected_pref_hash_store, |
| 348 scoped_ptr<PrefHashStore> protected_pref_hash_store, |
| 349 scoped_ptr<HashStoreContents> legacy_pref_hash_store, |
255 InterceptablePrefFilter* unprotected_pref_filter, | 350 InterceptablePrefFilter* unprotected_pref_filter, |
256 InterceptablePrefFilter* protected_pref_filter) { | 351 InterceptablePrefFilter* protected_pref_filter) { |
257 scoped_refptr<TrackedPreferencesMigrator> prefs_migrator( | 352 scoped_refptr<TrackedPreferencesMigrator> prefs_migrator( |
258 new TrackedPreferencesMigrator( | 353 new TrackedPreferencesMigrator( |
259 unprotected_pref_names, | 354 unprotected_pref_names, |
260 protected_pref_names, | 355 protected_pref_names, |
261 unprotected_store_cleaner, | 356 unprotected_store_cleaner, |
262 protected_store_cleaner, | 357 protected_store_cleaner, |
263 register_on_successful_unprotected_store_write_callback, | 358 register_on_successful_unprotected_store_write_callback, |
264 register_on_successful_protected_store_write_callback, | 359 register_on_successful_protected_store_write_callback, |
| 360 unprotected_pref_hash_store.Pass(), |
| 361 protected_pref_hash_store.Pass(), |
| 362 legacy_pref_hash_store.Pass(), |
265 unprotected_pref_filter, | 363 unprotected_pref_filter, |
266 protected_pref_filter)); | 364 protected_pref_filter)); |
267 } | 365 } |
OLD | NEW |