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/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 } | |
OLD | NEW |