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