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

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: comment nit 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/interceptable_pref_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 InterceptablePrefFilter* unprotected_pref_filter,
32 InterceptablePrefFilter* protected_pref_filter);
33
34 private:
35 friend class base::RefCounted<TrackedPreferencesMigrator>;
36
37 enum PrefFilterID {
38 UNPROTECTED_PREF_FILTER,
39 PROTECTED_PREF_FILTER
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 InterceptablePrefFilter::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 InterceptablePrefFilter::FinalizeFilterOnLoadCallback
67 finalize_unprotected_filter_on_load_;
68 InterceptablePrefFilter::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 (via
88 // |register_on_successful_destination_store_write_callback|) a cleanup of the
89 // |keys_to_clean| from the source pref store (through |source_store_cleaner|)
90 // once the destination pref store they were migrated to was successfully
91 // written to disk. Otherwise, executes the cleanup right away.
92 void ScheduleSourcePrefStoreCleanup(
93 const base::Callback<void(const base::Closure&)>&
94 register_on_successful_destination_store_write_callback,
95 const base::Callback<void(const std::string& key)>& source_store_cleaner,
96 const std::set<std::string>& keys_to_clean,
97 bool wait_for_commit_to_destination_store) {
98 DCHECK(!keys_to_clean.empty());
99 if (wait_for_commit_to_destination_store) {
100 register_on_successful_destination_store_write_callback.Run(
101 base::Bind(&CleanupPrefStore, source_store_cleaner, keys_to_clean));
102 } else {
103 CleanupPrefStore(source_store_cleaner, keys_to_clean);
104 }
105 }
106
107 // 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
109 // 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|.
111 void MigratePrefsFromOldToNewStore(const std::set<std::string>& pref_names,
112 const base::DictionaryValue* old_store,
113 base::DictionaryValue* new_store,
114 bool* old_store_needs_cleanup,
115 bool* new_store_altered) {
116 for (std::set<std::string>::const_iterator it = pref_names.begin();
117 it != pref_names.end(); ++it) {
118 const std::string& pref_name = *it;
119
120 const base::Value* value_in_old_store = NULL;
121 if (!old_store->Get(pref_name, &value_in_old_store))
122 continue;
123
124 // Whether this value ends up being copied below or was left behind by a
125 // previous incomplete migration, it should be cleaned up.
126 *old_store_needs_cleanup = true;
127
128 if (new_store->Get(pref_name, NULL))
129 continue;
130
131 // Copy the value from |old_store| to |new_store| rather than moving it to
132 // avoid data loss should |old_store| be flushed to disk without |new_store|
133 // having equivalently been successfully flushed to disk (e.g., on crash or
134 // in cases where |new_store| is read-only following a read error on
135 // startup).
136 new_store->Set(pref_name, value_in_old_store->DeepCopy());
137 *new_store_altered = true;
138 }
139 }
140
141 TrackedPreferencesMigrator::TrackedPreferencesMigrator(
142 const std::set<std::string>& unprotected_pref_names,
143 const std::set<std::string>& protected_pref_names,
144 const base::Callback<void(const std::string& key)>&
145 unprotected_store_cleaner,
146 const base::Callback<void(const std::string& key)>& protected_store_cleaner,
147 const base::Callback<void(const base::Closure&)>&
148 register_on_successful_unprotected_store_write_callback,
149 const base::Callback<void(const base::Closure&)>&
150 register_on_successful_protected_store_write_callback,
151 InterceptablePrefFilter* unprotected_pref_filter,
152 InterceptablePrefFilter* protected_pref_filter)
153 : unprotected_pref_names_(unprotected_pref_names),
154 protected_pref_names_(protected_pref_names),
155 unprotected_store_cleaner_(unprotected_store_cleaner),
156 protected_store_cleaner_(protected_store_cleaner),
157 register_on_successful_unprotected_store_write_callback_(
158 register_on_successful_unprotected_store_write_callback),
159 register_on_successful_protected_store_write_callback_(
160 register_on_successful_protected_store_write_callback) {
161 // The callbacks bound below will own this TrackedPreferencesMigrator by
162 // reference.
163 unprotected_pref_filter->InterceptNextFilterOnLoad(
164 base::Bind(&TrackedPreferencesMigrator::InterceptFilterOnLoad,
165 this,
166 UNPROTECTED_PREF_FILTER));
167 protected_pref_filter->InterceptNextFilterOnLoad(
168 base::Bind(&TrackedPreferencesMigrator::InterceptFilterOnLoad,
169 this,
170 PROTECTED_PREF_FILTER));
171 }
172
173 TrackedPreferencesMigrator::~TrackedPreferencesMigrator() {}
174
175 void TrackedPreferencesMigrator::InterceptFilterOnLoad(
176 PrefFilterID id,
177 const InterceptablePrefFilter::FinalizeFilterOnLoadCallback&
178 finalize_filter_on_load,
179 scoped_ptr<base::DictionaryValue> prefs) {
180 switch (id) {
181 case UNPROTECTED_PREF_FILTER:
182 finalize_unprotected_filter_on_load_ = finalize_filter_on_load;
183 unprotected_prefs_ = prefs.Pass();
184 break;
185 case PROTECTED_PREF_FILTER:
186 finalize_protected_filter_on_load_ = finalize_filter_on_load;
187 protected_prefs_ = prefs.Pass();
188 break;
189 }
190
191 MigrateIfReady();
192 }
193
194 void TrackedPreferencesMigrator::MigrateIfReady() {
195 // Wait for both stores to have been read before proceeding.
196 if (!protected_prefs_ || !unprotected_prefs_)
197 return;
198
199 bool protected_prefs_need_cleanup = false;
200 bool unprotected_prefs_altered = false;
201 MigratePrefsFromOldToNewStore(unprotected_pref_names_,
202 protected_prefs_.get(),
203 unprotected_prefs_.get(),
204 &protected_prefs_need_cleanup,
205 &unprotected_prefs_altered);
206 bool unprotected_prefs_need_cleanup = false;
207 bool protected_prefs_altered = false;
208 MigratePrefsFromOldToNewStore(protected_pref_names_,
209 unprotected_prefs_.get(),
210 protected_prefs_.get(),
211 &unprotected_prefs_need_cleanup,
212 &protected_prefs_altered);
213
214 // Hand the processed prefs back to their respective filters.
215 finalize_unprotected_filter_on_load_.Run(unprotected_prefs_.Pass(),
216 unprotected_prefs_altered);
217 finalize_protected_filter_on_load_.Run(protected_prefs_.Pass(),
218 protected_prefs_altered);
219
220 if (unprotected_prefs_need_cleanup) {
221 // Schedule a cleanup of the |protected_pref_names_| from the unprotected
222 // prefs once the protected prefs were successfully written to disk (or
223 // do it immediately if |!protected_prefs_altered|).
224 ScheduleSourcePrefStoreCleanup(
225 register_on_successful_protected_store_write_callback_,
226 unprotected_store_cleaner_,
227 protected_pref_names_,
228 protected_prefs_altered);
229 }
230
231 if (protected_prefs_need_cleanup) {
232 // Schedule a cleanup of the |unprotected_pref_names_| from the protected
233 // prefs once the unprotected prefs were successfully written to disk (or
234 // do it immediately if |!unprotected_prefs_altered|).
235 ScheduleSourcePrefStoreCleanup(
236 register_on_successful_unprotected_store_write_callback_,
237 protected_store_cleaner_,
238 unprotected_pref_names_,
239 unprotected_prefs_altered);
240 }
241 }
242
243 } // namespace
244
245 void SetupTrackedPreferencesMigration(
246 const std::set<std::string>& unprotected_pref_names,
247 const std::set<std::string>& protected_pref_names,
248 const base::Callback<void(const std::string& key)>&
249 unprotected_store_cleaner,
250 const base::Callback<void(const std::string& key)>& protected_store_cleaner,
251 const base::Callback<void(const base::Closure&)>&
252 register_on_successful_unprotected_store_write_callback,
253 const base::Callback<void(const base::Closure&)>&
254 register_on_successful_protected_store_write_callback,
255 InterceptablePrefFilter* unprotected_pref_filter,
256 InterceptablePrefFilter* protected_pref_filter) {
257 scoped_refptr<TrackedPreferencesMigrator> prefs_migrator(
258 new TrackedPreferencesMigrator(
259 unprotected_pref_names,
260 protected_pref_names,
261 unprotected_store_cleaner,
262 protected_store_cleaner,
263 register_on_successful_unprotected_store_write_callback,
264 register_on_successful_protected_store_write_callback,
265 unprotected_pref_filter,
266 protected_pref_filter));
267 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698