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

Side by Side Diff: chrome/browser/prefs/tracked/tracked_preferences_migration.cc

Issue 257003007: Introduce a new framework for back-and-forth tracked/protected preferences migration. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fix some tests -- more to come Created 6 years, 7 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 | Annotate | Revision Log
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 "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/values.h"
13 #include "chrome/browser/prefs/pref_hash_filter.h"
14
15 namespace {
16
17 class TrackedPreferencesMigrator
18 : public base::RefCounted<TrackedPreferencesMigrator> {
19 public:
20 TrackedPreferencesMigrator(
21 const std::set<std::string>& unprotected_pref_names,
22 const std::set<std::string>& protected_pref_names,
23 const base::Callback<void(const std::string& key)>&
24 unprotected_store_cleaner,
25 const base::Callback<void(const std::string& key)>&
26 protected_store_cleaner,
27 const base::Callback<void(const base::Closure&)>&
28 register_on_successful_unprotected_store_write_callback,
29 const base::Callback<void(const base::Closure&)>&
30 register_on_successful_protected_store_write_callback,
31 PrefHashFilter* unprotected_pref_hash_filter,
32 PrefHashFilter* protected_pref_hash_filter);
33
34 private:
35 friend class base::RefCounted<TrackedPreferencesMigrator>;
36
37 enum PrefFilterID {
38 UNPROTECTED_PREF_hash_FILTER,
39 PROTECTED_PREF_hash_FILTER
gab 2014/05/05 13:53:46 Fix case.
gab 2014/05/05 17:30:36 Done.
40 };
41
42 ~TrackedPreferencesMigrator();
43
44 // Stores the data coming in from the filter identified by |id| into this
45 // class and then calls MigrateIfReady();
46 void InterceptFilterOnLoad(
47 PrefFilterID id,
48 const PrefHashFilter::FinalizeFilterOnLoadCallback&
49 finalize_filter_on_load,
50 scoped_ptr<base::DictionaryValue> prefs);
51
52 // Proceeds with migration if both |unprotected_prefs_| and |protected_prefs_|
53 // have been set.
54 void MigrateIfReady();
55
56 const std::set<std::string> unprotected_pref_names_;
57 const std::set<std::string> protected_pref_names_;
58
59 const base::Callback<void(const std::string& key)> unprotected_store_cleaner_;
60 const base::Callback<void(const std::string& key)> protected_store_cleaner_;
61 const base::Callback<void(const base::Closure&)>
62 register_on_successful_unprotected_store_write_callback_;
63 const base::Callback<void(const base::Closure&)>
64 register_on_successful_protected_store_write_callback_;
65
66 PrefHashFilter::FinalizeFilterOnLoadCallback
67 finalize_unprotected_filter_on_load_;
68 PrefHashFilter::FinalizeFilterOnLoadCallback
69 finalize_protected_filter_on_load_;
70
71 scoped_ptr<base::DictionaryValue> unprotected_prefs_;
72 scoped_ptr<base::DictionaryValue> protected_prefs_;
73
74 DISALLOW_COPY_AND_ASSIGN(TrackedPreferencesMigrator);
75 };
76
77 // Invokes |store_cleaner| for every |keys_to_clean|.
78 void CleanupPrefStore(
79 const base::Callback<void(const std::string& key)>& store_cleaner,
80 const std::set<std::string>& keys_to_clean) {
81 for (std::set<std::string>::const_iterator it = keys_to_clean.begin();
82 it != keys_to_clean.end(); ++it) {
83 store_cleaner.Run(*it);
84 }
85 }
86
87 // If |wait_for_commit_to_destination_store|: schedules a cleanup of the
88 // |keys_to_clean| from the |source_pref_store| once the
89 // |destination_pref_store| they were migrated to was successfully written to
gab 2014/05/05 13:53:46 Update this comment to match new arguments.
gab 2014/05/05 17:30:36 Done.
90 // disk. Otherwise, executes the cleanup right away.
91 void ScheduleSourcePrefStoreCleanup(
92 const base::Callback<void(const base::Closure&)>&
93 register_on_successful_destination_store_write_callback,
94 const base::Callback<void(const std::string& key)>& source_store_cleaner,
95 const std::set<std::string>& keys_to_clean,
96 bool wait_for_commit_to_destination_store) {
97 DCHECK(!keys_to_clean.empty());
98 if (wait_for_commit_to_destination_store) {
99 register_on_successful_destination_store_write_callback.Run(
100 base::Bind(&CleanupPrefStore, source_store_cleaner, keys_to_clean));
101 } else {
102 CleanupPrefStore(source_store_cleaner, keys_to_clean);
103 }
104 }
105
106 // Copies the value of each pref in |pref_names| which is set in |old_store|,
107 // but not in |new_store| into |new_store|. Sets |old_store_needs_cleanup| to
108 // true if any old duplicates remain in |old_store| and sets |new_store_altered|
109 // to true if any value was copied to |new_store|.
110 void MigratePrefsFromOldToNewStore(const std::set<std::string>& pref_names,
111 const base::DictionaryValue* old_store,
112 base::DictionaryValue* new_store,
113 bool* old_store_needs_cleanup,
114 bool* new_store_altered) {
115 for (std::set<std::string>::const_iterator it = pref_names.begin();
116 it != pref_names.end(); ++it) {
117 const std::string& pref_name = *it;
118
119 const base::Value* value_in_old_store = NULL;
120 if (!old_store->Get(pref_name, &value_in_old_store))
121 continue;
122
123 // Whether this value ends up being copied below or was left behind by a
124 // previous incomplete migration, it should be cleaned up.
125 *old_store_needs_cleanup = true;
126
127 if (new_store->Get(pref_name, NULL))
128 continue;
129
130 // Copy the value from |old_store| to |new_store| rather than moving it to
131 // avoid data loss should |old_store| be flushed to disk without |new_store|
132 // having equivalently been successfully flushed to disk (e.g., on crash or
133 // in cases where |new_store| is read-only following a read error on
134 // startup).
135 new_store->Set(pref_name, value_in_old_store->DeepCopy());
136 *new_store_altered = true;
137 }
138 }
139
140 TrackedPreferencesMigrator::TrackedPreferencesMigrator(
141 const std::set<std::string>& unprotected_pref_names,
142 const std::set<std::string>& protected_pref_names,
143 const base::Callback<void(const std::string& key)>&
144 unprotected_store_cleaner,
145 const base::Callback<void(const std::string& key)>& protected_store_cleaner,
146 const base::Callback<void(const base::Closure&)>&
147 register_on_successful_unprotected_store_write_callback,
148 const base::Callback<void(const base::Closure&)>&
149 register_on_successful_protected_store_write_callback,
150 PrefHashFilter* unprotected_pref_hash_filter,
151 PrefHashFilter* protected_pref_hash_filter)
152 : unprotected_pref_names_(unprotected_pref_names),
153 protected_pref_names_(protected_pref_names),
154 unprotected_store_cleaner_(unprotected_store_cleaner),
155 protected_store_cleaner_(protected_store_cleaner),
156 register_on_successful_unprotected_store_write_callback_(
157 register_on_successful_unprotected_store_write_callback),
158 register_on_successful_protected_store_write_callback_(
159 register_on_successful_protected_store_write_callback) {
160 // The callbacks bound below will own this TrackedPreferencesMigrator by
161 // reference.
162 unprotected_pref_hash_filter->InterceptNextFilterOnLoad(
163 base::Bind(&TrackedPreferencesMigrator::InterceptFilterOnLoad,
164 this,
165 UNPROTECTED_PREF_hash_FILTER));
166 protected_pref_hash_filter->InterceptNextFilterOnLoad(
167 base::Bind(&TrackedPreferencesMigrator::InterceptFilterOnLoad,
168 this,
169 PROTECTED_PREF_hash_FILTER));
170 }
171
172 TrackedPreferencesMigrator::~TrackedPreferencesMigrator() {}
173
174 void TrackedPreferencesMigrator::InterceptFilterOnLoad(
175 PrefFilterID id,
176 const PrefHashFilter::FinalizeFilterOnLoadCallback& finalize_filter_on_load,
177 scoped_ptr<base::DictionaryValue> prefs) {
178 switch (id) {
179 case UNPROTECTED_PREF_hash_FILTER:
180 finalize_unprotected_filter_on_load_ = finalize_filter_on_load;
181 unprotected_prefs_ = prefs.Pass();
182 break;
183 case PROTECTED_PREF_hash_FILTER:
184 finalize_protected_filter_on_load_ = finalize_filter_on_load;
185 protected_prefs_ = prefs.Pass();
186 break;
187 }
188
189 MigrateIfReady();
190 }
191
192 void TrackedPreferencesMigrator::MigrateIfReady() {
193 // Wait for both stores to have been read before proceeding.
194 if (!protected_prefs_ || !unprotected_prefs_)
195 return;
196
197 bool protected_prefs_need_cleanup = false;
198 bool unprotected_prefs_altered = false;
199 MigratePrefsFromOldToNewStore(unprotected_pref_names_,
200 protected_prefs_.get(),
201 unprotected_prefs_.get(),
202 &protected_prefs_need_cleanup,
203 &unprotected_prefs_altered);
204 bool unprotected_prefs_need_cleanup = false;
205 bool protected_prefs_altered = false;
206 MigratePrefsFromOldToNewStore(protected_pref_names_,
207 unprotected_prefs_.get(),
208 protected_prefs_.get(),
209 &unprotected_prefs_need_cleanup,
210 &protected_prefs_altered);
211
212 // Hand the processed prefs back to their respective filters.
213 finalize_unprotected_filter_on_load_.Run(unprotected_prefs_.Pass(),
214 unprotected_prefs_altered);
215 finalize_protected_filter_on_load_.Run(protected_prefs_.Pass(),
216 protected_prefs_altered);
217
218 if (unprotected_prefs_need_cleanup) {
219 // Schedule a cleanup of the |protected_pref_names_| from the unprotected
220 // prefs once the protected prefs were successfully written to disk (or
221 // do it immediately if |!protected_prefs_altered|).
222 ScheduleSourcePrefStoreCleanup(
223 register_on_successful_protected_store_write_callback_,
224 unprotected_store_cleaner_,
225 protected_pref_names_,
226 protected_prefs_altered);
227 }
228
229 if (protected_prefs_need_cleanup) {
230 // Schedule a cleanup of the |unprotected_pref_names_| from the protected
231 // prefs once the unprotected prefs were successfully written to disk (or
232 // do it immediately if |!unprotected_prefs_altered|).
233 ScheduleSourcePrefStoreCleanup(
234 register_on_successful_unprotected_store_write_callback_,
235 protected_store_cleaner_,
236 unprotected_pref_names_,
237 unprotected_prefs_altered);
238 }
239 }
240
241 } // namespace
242
243 void SetupTrackedPreferencesMigration(
244 const std::set<std::string>& unprotected_pref_names,
245 const std::set<std::string>& protected_pref_names,
246 const base::Callback<void(const std::string& key)>&
247 unprotected_store_cleaner,
248 const base::Callback<void(const std::string& key)>& protected_store_cleaner,
249 const base::Callback<void(const base::Closure&)>&
250 register_on_successful_unprotected_store_write_callback,
251 const base::Callback<void(const base::Closure&)>&
252 register_on_successful_protected_store_write_callback,
253 PrefHashFilter* unprotected_pref_hash_filter,
254 PrefHashFilter* protected_pref_hash_filter) {
255 scoped_refptr<TrackedPreferencesMigrator> prefs_migrator(
256 new TrackedPreferencesMigrator(
257 unprotected_pref_names,
258 protected_pref_names,
259 unprotected_store_cleaner,
260 protected_store_cleaner,
261 register_on_successful_unprotected_store_write_callback,
262 register_on_successful_protected_store_write_callback,
263 unprotected_pref_hash_filter,
264 protected_pref_hash_filter));
265 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698