Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(325)

Side by Side Diff: components/user_prefs/tracked/tracked_preferences_migration.cc

Issue 2782803002: Move tracked prefs into services/preferences/tracked. (Closed)
Patch Set: rebase Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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 "components/user_prefs/tracked/tracked_preferences_migration.h"
6
7 #include <utility>
8
9 #include "base/bind.h"
10 #include "base/callback.h"
11 #include "base/macros.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/metrics/histogram.h"
14 #include "base/values.h"
15 #include "components/user_prefs/tracked/dictionary_hash_store_contents.h"
16 #include "components/user_prefs/tracked/hash_store_contents.h"
17 #include "components/user_prefs/tracked/interceptable_pref_filter.h"
18 #include "components/user_prefs/tracked/pref_hash_store.h"
19 #include "components/user_prefs/tracked/pref_hash_store_transaction.h"
20
21 namespace {
22
23 class TrackedPreferencesMigrator
24 : public base::RefCounted<TrackedPreferencesMigrator> {
25 public:
26 TrackedPreferencesMigrator(
27 const std::set<std::string>& unprotected_pref_names,
28 const std::set<std::string>& protected_pref_names,
29 const base::Callback<void(const std::string& key)>&
30 unprotected_store_cleaner,
31 const base::Callback<void(const std::string& key)>&
32 protected_store_cleaner,
33 const base::Callback<void(const base::Closure&)>&
34 register_on_successful_unprotected_store_write_callback,
35 const base::Callback<void(const base::Closure&)>&
36 register_on_successful_protected_store_write_callback,
37 std::unique_ptr<PrefHashStore> unprotected_pref_hash_store,
38 std::unique_ptr<PrefHashStore> protected_pref_hash_store,
39 InterceptablePrefFilter* unprotected_pref_filter,
40 InterceptablePrefFilter* protected_pref_filter);
41
42 private:
43 friend class base::RefCounted<TrackedPreferencesMigrator>;
44
45 enum PrefFilterID {
46 UNPROTECTED_PREF_FILTER,
47 PROTECTED_PREF_FILTER
48 };
49
50 ~TrackedPreferencesMigrator();
51
52 // Stores the data coming in from the filter identified by |id| into this
53 // class and then calls MigrateIfReady();
54 void InterceptFilterOnLoad(
55 PrefFilterID id,
56 const InterceptablePrefFilter::FinalizeFilterOnLoadCallback&
57 finalize_filter_on_load,
58 std::unique_ptr<base::DictionaryValue> prefs);
59
60 // Proceeds with migration if both |unprotected_prefs_| and |protected_prefs_|
61 // have been set.
62 void MigrateIfReady();
63
64 const std::set<std::string> unprotected_pref_names_;
65 const std::set<std::string> protected_pref_names_;
66
67 const base::Callback<void(const std::string& key)> unprotected_store_cleaner_;
68 const base::Callback<void(const std::string& key)> protected_store_cleaner_;
69 const base::Callback<void(const base::Closure&)>
70 register_on_successful_unprotected_store_write_callback_;
71 const base::Callback<void(const base::Closure&)>
72 register_on_successful_protected_store_write_callback_;
73
74 InterceptablePrefFilter::FinalizeFilterOnLoadCallback
75 finalize_unprotected_filter_on_load_;
76 InterceptablePrefFilter::FinalizeFilterOnLoadCallback
77 finalize_protected_filter_on_load_;
78
79 std::unique_ptr<PrefHashStore> unprotected_pref_hash_store_;
80 std::unique_ptr<PrefHashStore> protected_pref_hash_store_;
81
82 std::unique_ptr<base::DictionaryValue> unprotected_prefs_;
83 std::unique_ptr<base::DictionaryValue> protected_prefs_;
84
85 DISALLOW_COPY_AND_ASSIGN(TrackedPreferencesMigrator);
86 };
87
88 // Invokes |store_cleaner| for every |keys_to_clean|.
89 void CleanupPrefStore(
90 const base::Callback<void(const std::string& key)>& store_cleaner,
91 const std::set<std::string>& keys_to_clean) {
92 for (std::set<std::string>::const_iterator it = keys_to_clean.begin();
93 it != keys_to_clean.end(); ++it) {
94 store_cleaner.Run(*it);
95 }
96 }
97
98 // If |wait_for_commit_to_destination_store|: schedules (via
99 // |register_on_successful_destination_store_write_callback|) a cleanup of the
100 // |keys_to_clean| from the source pref store (through |source_store_cleaner|)
101 // once the destination pref store they were migrated to was successfully
102 // written to disk. Otherwise, executes the cleanup right away.
103 void ScheduleSourcePrefStoreCleanup(
104 const base::Callback<void(const base::Closure&)>&
105 register_on_successful_destination_store_write_callback,
106 const base::Callback<void(const std::string& key)>& source_store_cleaner,
107 const std::set<std::string>& keys_to_clean,
108 bool wait_for_commit_to_destination_store) {
109 DCHECK(!keys_to_clean.empty());
110 if (wait_for_commit_to_destination_store) {
111 register_on_successful_destination_store_write_callback.Run(
112 base::Bind(&CleanupPrefStore, source_store_cleaner, keys_to_clean));
113 } else {
114 CleanupPrefStore(source_store_cleaner, keys_to_clean);
115 }
116 }
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 DictionaryHashStoreContents dictionary_contents(origin_pref_store);
124 std::unique_ptr<PrefHashStoreTransaction> transaction(
125 origin_pref_hash_store->BeginTransaction(&dictionary_contents));
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
133 // Copies the value of each pref in |pref_names| which is set in |old_store|,
134 // but not in |new_store| into |new_store|. Sets |old_store_needs_cleanup| to
135 // true if any old duplicates remain in |old_store| and sets |new_store_altered|
136 // to true if any value was copied to |new_store|.
137 void MigratePrefsFromOldToNewStore(const std::set<std::string>& pref_names,
138 base::DictionaryValue* old_store,
139 base::DictionaryValue* new_store,
140 PrefHashStore* new_hash_store,
141 bool* old_store_needs_cleanup,
142 bool* new_store_altered) {
143 const base::DictionaryValue* old_hash_store_contents =
144 DictionaryHashStoreContents(old_store).GetContents();
145 DictionaryHashStoreContents dictionary_contents(new_store);
146 std::unique_ptr<PrefHashStoreTransaction> new_hash_store_transaction(
147 new_hash_store->BeginTransaction(&dictionary_contents));
148
149 for (std::set<std::string>::const_iterator it = pref_names.begin();
150 it != pref_names.end();
151 ++it) {
152 const std::string& pref_name = *it;
153 const base::Value* value_in_old_store = NULL;
154
155 // If the destination does not have a hash for this pref we will
156 // unconditionally attempt to move it.
157 bool destination_hash_missing =
158 !new_hash_store_transaction->HasHash(pref_name);
159 // If we migrate the value we will also attempt to migrate the hash.
160 bool migrated_value = false;
161 if (old_store->Get(pref_name, &value_in_old_store)) {
162 // Whether this value ends up being copied below or was left behind by a
163 // previous incomplete migration, it should be cleaned up.
164 *old_store_needs_cleanup = true;
165
166 if (!new_store->Get(pref_name, NULL)) {
167 // Copy the value from |old_store| to |new_store| rather than moving it
168 // to avoid data loss should |old_store| be flushed to disk without
169 // |new_store| having equivalently been successfully flushed to disk
170 // (e.g., on crash or in cases where |new_store| is read-only following
171 // a read error on startup).
172 new_store->Set(pref_name, value_in_old_store->DeepCopy());
173 migrated_value = true;
174 *new_store_altered = true;
175 }
176 }
177
178 if (destination_hash_missing || migrated_value) {
179 const base::Value* old_hash = NULL;
180 if (old_hash_store_contents)
181 old_hash_store_contents->Get(pref_name, &old_hash);
182 if (old_hash) {
183 new_hash_store_transaction->ImportHash(pref_name, old_hash);
184 *new_store_altered = true;
185 } else if (!destination_hash_missing) {
186 // Do not allow values to be migrated without MACs if the destination
187 // already has a MAC (http://crbug.com/414554). Remove the migrated
188 // value in order to provide the same no-op behaviour as if the pref was
189 // added to the wrong file when there was already a value for
190 // |pref_name| in |new_store|.
191 new_store->Remove(pref_name, NULL);
192 *new_store_altered = true;
193 }
194 }
195 }
196 }
197
198 TrackedPreferencesMigrator::TrackedPreferencesMigrator(
199 const std::set<std::string>& unprotected_pref_names,
200 const std::set<std::string>& protected_pref_names,
201 const base::Callback<void(const std::string& key)>&
202 unprotected_store_cleaner,
203 const base::Callback<void(const std::string& key)>& protected_store_cleaner,
204 const base::Callback<void(const base::Closure&)>&
205 register_on_successful_unprotected_store_write_callback,
206 const base::Callback<void(const base::Closure&)>&
207 register_on_successful_protected_store_write_callback,
208 std::unique_ptr<PrefHashStore> unprotected_pref_hash_store,
209 std::unique_ptr<PrefHashStore> protected_pref_hash_store,
210 InterceptablePrefFilter* unprotected_pref_filter,
211 InterceptablePrefFilter* protected_pref_filter)
212 : unprotected_pref_names_(unprotected_pref_names),
213 protected_pref_names_(protected_pref_names),
214 unprotected_store_cleaner_(unprotected_store_cleaner),
215 protected_store_cleaner_(protected_store_cleaner),
216 register_on_successful_unprotected_store_write_callback_(
217 register_on_successful_unprotected_store_write_callback),
218 register_on_successful_protected_store_write_callback_(
219 register_on_successful_protected_store_write_callback),
220 unprotected_pref_hash_store_(std::move(unprotected_pref_hash_store)),
221 protected_pref_hash_store_(std::move(protected_pref_hash_store)) {
222 // The callbacks bound below will own this TrackedPreferencesMigrator by
223 // reference.
224 unprotected_pref_filter->InterceptNextFilterOnLoad(
225 base::Bind(&TrackedPreferencesMigrator::InterceptFilterOnLoad,
226 this,
227 UNPROTECTED_PREF_FILTER));
228 protected_pref_filter->InterceptNextFilterOnLoad(
229 base::Bind(&TrackedPreferencesMigrator::InterceptFilterOnLoad,
230 this,
231 PROTECTED_PREF_FILTER));
232 }
233
234 TrackedPreferencesMigrator::~TrackedPreferencesMigrator() {}
235
236 void TrackedPreferencesMigrator::InterceptFilterOnLoad(
237 PrefFilterID id,
238 const InterceptablePrefFilter::FinalizeFilterOnLoadCallback&
239 finalize_filter_on_load,
240 std::unique_ptr<base::DictionaryValue> prefs) {
241 switch (id) {
242 case UNPROTECTED_PREF_FILTER:
243 finalize_unprotected_filter_on_load_ = finalize_filter_on_load;
244 unprotected_prefs_ = std::move(prefs);
245 break;
246 case PROTECTED_PREF_FILTER:
247 finalize_protected_filter_on_load_ = finalize_filter_on_load;
248 protected_prefs_ = std::move(prefs);
249 break;
250 }
251
252 MigrateIfReady();
253 }
254
255 void TrackedPreferencesMigrator::MigrateIfReady() {
256 // Wait for both stores to have been read before proceeding.
257 if (!protected_prefs_ || !unprotected_prefs_)
258 return;
259
260 bool protected_prefs_need_cleanup = false;
261 bool unprotected_prefs_altered = false;
262 MigratePrefsFromOldToNewStore(
263 unprotected_pref_names_, protected_prefs_.get(), unprotected_prefs_.get(),
264 unprotected_pref_hash_store_.get(), &protected_prefs_need_cleanup,
265 &unprotected_prefs_altered);
266 bool unprotected_prefs_need_cleanup = false;
267 bool protected_prefs_altered = false;
268 MigratePrefsFromOldToNewStore(
269 protected_pref_names_, unprotected_prefs_.get(), protected_prefs_.get(),
270 protected_pref_hash_store_.get(), &unprotected_prefs_need_cleanup,
271 &protected_prefs_altered);
272
273 if (!unprotected_prefs_altered && !protected_prefs_altered) {
274 // Clean up any MACs that might have been previously migrated from the
275 // various stores. It's safe to leave them behind for a little while as they
276 // will be ignored unless the corresponding value is _also_ present. The
277 // cleanup must be deferred until the MACs have been written to their target
278 // stores, and doing so in a subsequent launch is easier than within the
279 // same process.
280 CleanupMigratedHashes(unprotected_pref_names_,
281 protected_pref_hash_store_.get(),
282 protected_prefs_.get());
283 CleanupMigratedHashes(protected_pref_names_,
284 unprotected_pref_hash_store_.get(),
285 unprotected_prefs_.get());
286 }
287
288 // Hand the processed prefs back to their respective filters.
289 finalize_unprotected_filter_on_load_.Run(std::move(unprotected_prefs_),
290 unprotected_prefs_altered);
291 finalize_protected_filter_on_load_.Run(std::move(protected_prefs_),
292 protected_prefs_altered);
293
294 if (unprotected_prefs_need_cleanup) {
295 // Schedule a cleanup of the |protected_pref_names_| from the unprotected
296 // prefs once the protected prefs were successfully written to disk (or
297 // do it immediately if |!protected_prefs_altered|).
298 ScheduleSourcePrefStoreCleanup(
299 register_on_successful_protected_store_write_callback_,
300 unprotected_store_cleaner_,
301 protected_pref_names_,
302 protected_prefs_altered);
303 }
304
305 if (protected_prefs_need_cleanup) {
306 // Schedule a cleanup of the |unprotected_pref_names_| from the protected
307 // prefs once the unprotected prefs were successfully written to disk (or
308 // do it immediately if |!unprotected_prefs_altered|).
309 ScheduleSourcePrefStoreCleanup(
310 register_on_successful_unprotected_store_write_callback_,
311 protected_store_cleaner_,
312 unprotected_pref_names_,
313 unprotected_prefs_altered);
314 }
315 }
316
317 } // namespace
318
319 void SetupTrackedPreferencesMigration(
320 const std::set<std::string>& unprotected_pref_names,
321 const std::set<std::string>& protected_pref_names,
322 const base::Callback<void(const std::string& key)>&
323 unprotected_store_cleaner,
324 const base::Callback<void(const std::string& key)>& protected_store_cleaner,
325 const base::Callback<void(const base::Closure&)>&
326 register_on_successful_unprotected_store_write_callback,
327 const base::Callback<void(const base::Closure&)>&
328 register_on_successful_protected_store_write_callback,
329 std::unique_ptr<PrefHashStore> unprotected_pref_hash_store,
330 std::unique_ptr<PrefHashStore> protected_pref_hash_store,
331 InterceptablePrefFilter* unprotected_pref_filter,
332 InterceptablePrefFilter* protected_pref_filter) {
333 scoped_refptr<TrackedPreferencesMigrator> prefs_migrator(
334 new TrackedPreferencesMigrator(
335 unprotected_pref_names, protected_pref_names,
336 unprotected_store_cleaner, protected_store_cleaner,
337 register_on_successful_unprotected_store_write_callback,
338 register_on_successful_protected_store_write_callback,
339 std::move(unprotected_pref_hash_store),
340 std::move(protected_pref_hash_store), unprotected_pref_filter,
341 protected_pref_filter));
342 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698