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

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: 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/prefs/json_pref_store.h"
13 #include "base/values.h"
14
15 namespace {
16
17 class TrackedPreferencesMigrator
18 : public base::RefCounted<TrackedPreferencesMigrator> {
19 public:
20 enum PrefStoreID {
Bernhard Bauer 2014/04/29 16:38:53 This could be private, right?
gab 2014/04/29 20:12:14 Done.
21 UNPROTECTED_PREFERENCE_STORE,
22 PROTECTED_PREFERENCE_STORE
23 };
24
25 // Constructs a TrackedPreferencesMigrator which sets itself up as the
26 // OnFileReadInterceptor for both |unprotected_pref_store| and
27 // |protected_pref_store|. It guarantees that the most recent pref value
28 // for |unprotected_pref_names| and |protected_pref_names| are in the
29 // appropriate JsonPrefStores before those stores even sees those values.
30 TrackedPreferencesMigrator(
31 const std::set<std::string>& unprotected_pref_names,
32 const std::set<std::string>& protected_pref_names,
33 JsonPrefStore* unprotected_pref_store,
34 JsonPrefStore* protected_pref_store);
35
36 ~TrackedPreferencesMigrator();
Bernhard Bauer 2014/04/29 16:38:53 Destructors should be private for refcounted class
gab 2014/04/29 20:12:14 That's what I wanted to do, but it doesn't work be
Bernhard Bauer 2014/04/29 21:20:28 You'll need to friend the base class, i.e. base::R
gab 2014/04/29 22:36:05 Ah I see, done, thanks!
37
38 private:
39 // Stores the data coming in for the store identified by |id| into this class
40 // and then calls MigrateIfReady();
41 void OnFileRead(
42 PrefStoreID id,
43 scoped_ptr<base::DictionaryValue> prefs,
44 bool read_only,
45 const JsonPrefStore::FinalizePrefsReadCallback& finalize_prefs_read);
46
47 // Proceeds with migration if both |unprotected_prefs_| and |protected_prefs_|
48 // have been set.
49 void MigrateIfReady();
50
51 // Copies the value of each pref in |pref_names| which is set in |old_store|,
52 // but not in |new_store| into |new_store|. Sets |old_store_needs_cleanup| to
53 // true if any old duplicates remain in |old_store| and sets
54 // |new_store_altered| to true if any value was copied to |new_store|.
55 static void MigratePrefsFromOldToNewStore(
Bernhard Bauer 2014/04/29 15:13:04 I think this could live outside of the class if it
gab 2014/04/29 15:46:44 I debated both and went this way because it was sl
Bernhard Bauer 2014/04/29 16:38:53 Hm, but class declarations don't need to be groupe
gab 2014/04/29 20:12:14 Ok, done. I put the free-method between TrackedPre
56 const std::set<std::string>& pref_names,
57 const base::DictionaryValue* old_store,
58 base::DictionaryValue* new_store,
59 bool* old_store_needs_cleanup,
60 bool* new_store_altered);
61
62 const std::set<std::string> unprotected_pref_names_;
63 const std::set<std::string> protected_pref_names_;
64
65 scoped_ptr<base::DictionaryValue> unprotected_prefs_;
66 scoped_ptr<base::DictionaryValue> protected_prefs_;
67
68 JsonPrefStore::FinalizePrefsReadCallback finalize_unprotected_prefs_read_;
69 JsonPrefStore::FinalizePrefsReadCallback finalize_protected_prefs_read_;
70
71 // Set to true if either store is reported to be read-only (in which case the
72 // migration will be copy only -- no deletions).
73 bool read_only_;
74
75 DISALLOW_COPY_AND_ASSIGN(TrackedPreferencesMigrator);
76 };
77
78 TrackedPreferencesMigrator::TrackedPreferencesMigrator(
79 const std::set<std::string>& unprotected_pref_names,
80 const std::set<std::string>& protected_pref_names,
81 JsonPrefStore* unprotected_pref_store,
Bernhard Bauer 2014/04/29 15:13:04 Nit: Unindent by two spaces.
gab 2014/04/29 15:46:44 Done.
82 JsonPrefStore* protected_pref_store)
83 : unprotected_pref_names_(unprotected_pref_names),
Bernhard Bauer 2014/04/29 15:13:04 Unindent this line and the following ones too, by
gab 2014/04/29 15:46:44 I thought we wanted an extra 4 spaces here, but gi
84 protected_pref_names_(protected_pref_names),
85 read_only_(false) {
86 // The callbacks binded below will own this TrackedPreferencesMigrator by
Bernhard Bauer 2014/04/29 15:13:04 Nit: "bound"
gab 2014/04/29 15:46:44 Done.
87 // reference.
88 unprotected_pref_store->InterceptNextFileRead(
89 base::Bind(&TrackedPreferencesMigrator::OnFileRead, this,
90 UNPROTECTED_PREFERENCE_STORE));
91 protected_pref_store->InterceptNextFileRead(
92 base::Bind(&TrackedPreferencesMigrator::OnFileRead, this,
93 PROTECTED_PREFERENCE_STORE));
94 }
95
96 TrackedPreferencesMigrator::~TrackedPreferencesMigrator() {}
97
98 void TrackedPreferencesMigrator::OnFileRead(
99 PrefStoreID id,
100 scoped_ptr<base::DictionaryValue> prefs,
101 bool read_only,
102 const JsonPrefStore::FinalizePrefsReadCallback& finalize_prefs_read) {
103 if (read_only)
104 read_only_ = true;
105
106 switch (id) {
107 case UNPROTECTED_PREFERENCE_STORE:
108 unprotected_prefs_ = prefs.Pass();
109 finalize_unprotected_prefs_read_ = finalize_prefs_read;
110 break;
111 case PROTECTED_PREFERENCE_STORE:
112 protected_prefs_ = prefs.Pass();
113 finalize_protected_prefs_read_ = finalize_prefs_read;
114 break;
115 }
116
117 MigrateIfReady();
118 }
119
120 void TrackedPreferencesMigrator::MigrateIfReady() {
121 // Wait for both stores to have been read before proceeding.
122 if (!protected_prefs_ || !unprotected_prefs_)
123 return;
124
125 bool protected_prefs_need_cleanup = false;
126 bool unprotected_prefs_altered = false;
127 MigratePrefsFromOldToNewStore(unprotected_pref_names_,
128 protected_prefs_.get(),
129 unprotected_prefs_.get(),
130 &protected_prefs_need_cleanup,
131 &unprotected_prefs_altered);
132 bool unprotected_prefs_need_cleanup = false;
133 bool protected_prefs_altered = false;
134 MigratePrefsFromOldToNewStore(protected_pref_names_,
135 unprotected_prefs_.get(),
136 protected_prefs_.get(),
137 &unprotected_prefs_need_cleanup,
138 &protected_prefs_altered);
139
140 if (!read_only_) {
141 // TODO(gab): Register callbacks to cleanup values from their old store when
142 // we get confirmation that the copies were successfully flushed out to
143 // their new respective stores.
144 }
145
146 // Finally, hand the prefs back to their respective JsonPrefStore.
147 finalize_unprotected_prefs_read_.Run(unprotected_prefs_.Pass(),
148 unprotected_prefs_altered);
149 finalize_protected_prefs_read_.Run(protected_prefs_.Pass(),
150 protected_prefs_altered);
151 }
152
153 // static
154 void TrackedPreferencesMigrator::MigratePrefsFromOldToNewStore(
155 const std::set<std::string>& pref_names,
156 const base::DictionaryValue* old_store,
157 base::DictionaryValue* new_store,
158 bool* old_store_needs_cleanup,
159 bool* new_store_altered) {
160 const base::Value* tmp = NULL;
Bernhard Bauer 2014/04/29 15:13:04 Could you come up with a better name for this vari
gab 2014/04/29 15:46:44 Done.
161 for (std::set<std::string>::const_iterator it = pref_names.begin();
162 it != pref_names.end(); ++it) {
163 const std::string& pref_name = *it;
164 if (old_store->Get(pref_name, &tmp)) {
Bernhard Bauer 2014/04/29 15:13:04 You could probably invert the conditions here and
gab 2014/04/29 15:46:44 This nesting is required to set |old_store_needs_c
Bernhard Bauer 2014/04/29 16:38:53 Hm, wouldn't the following work? if (!old_store
gab 2014/04/29 20:12:14 Not sure which one I prefer; I've heard of people
Bernhard Bauer 2014/04/29 21:20:28 Huh. I would have assumed that the compiler would
165 *old_store_needs_cleanup = true;
166 if (!new_store->Get(pref_name, &tmp)) {
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 // on crash.
171 new_store->Set(pref_name, tmp->DeepCopy());
172 *new_store_altered = true;
173 }
174 }
175 }
176 }
177
178 } // namespace
179
180 void SetupTrackedPrefererencesMigration(
181 const std::set<std::string>& unprotected_pref_names,
182 const std::set<std::string>& protected_pref_names,
183 JsonPrefStore* unprotected_pref_store,
184 JsonPrefStore* protected_pref_store) {
185 scoped_refptr<TrackedPreferencesMigrator> prefs_migrator(
186 new TrackedPreferencesMigrator(unprotected_pref_names,
187 protected_pref_names,
188 unprotected_pref_store,
189 protected_pref_store));
190 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698