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

Side by Side Diff: chrome/browser/prefs/pref_hash_store_impl.cc

Issue 324493002: Move preference MACs to the protected preference stores. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Pull some stuff from Persistent to WriteablePrefStore. Created 6 years, 6 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
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/prefs/pref_hash_store_impl.h" 5 #include "chrome/browser/prefs/pref_hash_store_impl.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "base/metrics/histogram.h" 8 #include "base/metrics/histogram.h"
9 #include "base/values.h" 9 #include "base/values.h"
10 #include "chrome/browser/prefs/pref_hash_store_transaction.h" 10 #include "chrome/browser/prefs/pref_hash_store_transaction.h"
11 #include "chrome/browser/prefs/tracked/hash_store_contents.h" 11 #include "chrome/browser/prefs/tracked/hash_store_contents.h"
12 12
13 namespace {
14
15 // Returns true if the dictionary of hashes stored in |contents| is trusted
16 // (which implies unknown values can be trusted as newly tracked values).
17 bool IsHashDictionaryTrusted(const PrefHashCalculator& calculator,
18 const HashStoreContents& contents) {
19 const base::DictionaryValue* store_contents = contents.GetContents();
20 std::string super_mac = contents.GetSuperMac();
21 // The store must be initialized and have a valid super MAC to be trusted.
22 return store_contents && !super_mac.empty() &&
23 calculator.Validate(contents.hash_store_id(),
24 store_contents,
25 super_mac) == PrefHashCalculator::VALID;
26 }
27
28 } // namespace
29
30 class PrefHashStoreImpl::PrefHashStoreTransactionImpl 13 class PrefHashStoreImpl::PrefHashStoreTransactionImpl
31 : public PrefHashStoreTransaction { 14 : public PrefHashStoreTransaction {
32 public: 15 public:
33 // Constructs a PrefHashStoreTransactionImpl which can use the private 16 // Constructs a PrefHashStoreTransactionImpl which can use the private
34 // members of its |outer| PrefHashStoreImpl. 17 // members of its |outer| PrefHashStoreImpl.
35 explicit PrefHashStoreTransactionImpl(PrefHashStoreImpl* outer); 18 explicit PrefHashStoreTransactionImpl(PrefHashStoreImpl* outer);
36 virtual ~PrefHashStoreTransactionImpl(); 19 virtual ~PrefHashStoreTransactionImpl();
37 20
38 // PrefHashStoreTransaction implementation. 21 // PrefHashStoreTransaction implementation.
39 virtual ValueState CheckValue(const std::string& path, 22 virtual ValueState CheckValue(const std::string& path,
40 const base::Value* value) const OVERRIDE; 23 const base::Value* value) const OVERRIDE;
41 virtual void StoreHash(const std::string& path, 24 virtual void StoreHash(const std::string& path,
42 const base::Value* value) OVERRIDE; 25 const base::Value* value) OVERRIDE;
26 virtual const base::Value* GetHash(const std::string& path) const OVERRIDE;
27 virtual void ImportHash(const std::string& path,
28 const base::Value* hash) OVERRIDE;
29 virtual void ClearHash(const std::string& path) OVERRIDE;
30 virtual bool StampSuperMac() OVERRIDE;
31
43 virtual ValueState CheckSplitValue( 32 virtual ValueState CheckSplitValue(
44 const std::string& path, 33 const std::string& path,
45 const base::DictionaryValue* initial_split_value, 34 const base::DictionaryValue* initial_split_value,
46 std::vector<std::string>* invalid_keys) const OVERRIDE; 35 std::vector<std::string>* invalid_keys) const OVERRIDE;
47 virtual void StoreSplitHash( 36 virtual void StoreSplitHash(
48 const std::string& path, 37 const std::string& path,
49 const base::DictionaryValue* split_value) OVERRIDE; 38 const base::DictionaryValue* split_value) OVERRIDE;
50 39
51 private: 40 private:
52 bool GetSplitMacs(const std::string& path, 41 bool GetSplitMacs(const std::string& path,
53 std::map<std::string, std::string>* split_macs) const; 42 std::map<std::string, std::string>* split_macs) const;
54 PrefHashStoreImpl* outer_; 43 PrefHashStoreImpl* outer_;
55 bool has_changed_; 44 bool has_changed_;
45 bool super_mac_dirty_;
56 46
57 DISALLOW_COPY_AND_ASSIGN(PrefHashStoreTransactionImpl); 47 DISALLOW_COPY_AND_ASSIGN(PrefHashStoreTransactionImpl);
58 }; 48 };
59 49
60 PrefHashStoreImpl::PrefHashStoreImpl(const std::string& seed, 50 PrefHashStoreImpl::PrefHashStoreImpl(const std::string& seed,
61 const std::string& device_id, 51 const std::string& device_id)
62 scoped_ptr<HashStoreContents> contents)
63 : pref_hash_calculator_(seed, device_id), 52 : pref_hash_calculator_(seed, device_id),
64 contents_(contents.Pass()), 53 initial_hashes_dictionary_trusted_(false),
65 initial_hashes_dictionary_trusted_(
66 IsHashDictionaryTrusted(pref_hash_calculator_, *contents_)),
67 has_pending_write_(false) { 54 has_pending_write_(false) {
68 DCHECK(contents_);
69 UMA_HISTOGRAM_BOOLEAN("Settings.HashesDictionaryTrusted", 55 UMA_HISTOGRAM_BOOLEAN("Settings.HashesDictionaryTrusted",
70 initial_hashes_dictionary_trusted_); 56 initial_hashes_dictionary_trusted_);
gab 2014/06/06 21:54:59 This histogram should also move.
erikwright (departed) 2014/06/10 20:27:47 Done.
71 } 57 }
72 58
73 PrefHashStoreImpl::~PrefHashStoreImpl() {} 59 PrefHashStoreImpl::~PrefHashStoreImpl() {}
74 60
61 void PrefHashStoreImpl::SetHashStoreContents(
gab 2014/06/06 21:54:59 Call this method Init()? And explicitly state that
62 scoped_ptr<HashStoreContents> contents) {
63 contents_ = contents.Pass();
64
65 const base::DictionaryValue* store_contents = contents_->GetContents();
66 std::string super_mac = contents_->GetSuperMac();
67
68 // The store must be initialized and have a valid super MAC to be trusted.
69 initial_hashes_dictionary_trusted_ =
70 store_contents && !super_mac.empty() &&
71 pref_hash_calculator_.Validate(contents_->hash_store_id(),
72 store_contents,
73 super_mac) == PrefHashCalculator::VALID;
74 }
75
76 bool PrefHashStoreImpl::IsInitialized() const {
77 return contents_->IsInitialized();
78 }
79
75 void PrefHashStoreImpl::Reset() { 80 void PrefHashStoreImpl::Reset() {
76 contents_->Reset(); 81 contents_->Reset();
77 } 82 }
78 83
79 scoped_ptr<PrefHashStoreTransaction> PrefHashStoreImpl::BeginTransaction() { 84 scoped_ptr<PrefHashStoreTransaction> PrefHashStoreImpl::BeginTransaction() {
80 return scoped_ptr<PrefHashStoreTransaction>( 85 return scoped_ptr<PrefHashStoreTransaction>(
81 new PrefHashStoreTransactionImpl(this)); 86 new PrefHashStoreTransactionImpl(this));
82 } 87 }
83 88
84 PrefHashStoreImpl::StoreVersion PrefHashStoreImpl::GetCurrentVersion() const {
85 if (!contents_->IsInitialized())
86 return VERSION_UNINITIALIZED;
87
88 int current_version;
89 if (!contents_->GetVersion(&current_version)) {
90 return VERSION_PRE_MIGRATION;
91 }
92
93 DCHECK_GT(current_version, VERSION_PRE_MIGRATION);
94 return static_cast<StoreVersion>(current_version);
95 }
96
97 void PrefHashStoreImpl::CommitPendingWrite() { 89 void PrefHashStoreImpl::CommitPendingWrite() {
98 if (has_pending_write_) { 90 if (has_pending_write_) {
99 contents_->CommitPendingWrite(); 91 contents_->CommitPendingWrite();
100 has_pending_write_ = false; 92 has_pending_write_ = false;
101 } 93 }
102 } 94 }
103 95
104 PrefHashStoreImpl::PrefHashStoreTransactionImpl::PrefHashStoreTransactionImpl( 96 PrefHashStoreImpl::PrefHashStoreTransactionImpl::PrefHashStoreTransactionImpl(
105 PrefHashStoreImpl* outer) : outer_(outer), has_changed_(false) { 97 PrefHashStoreImpl* outer)
98 : outer_(outer), has_changed_(false), super_mac_dirty_(false) {
106 } 99 }
107 100
108 PrefHashStoreImpl::PrefHashStoreTransactionImpl:: 101 PrefHashStoreImpl::PrefHashStoreTransactionImpl::
109 ~PrefHashStoreTransactionImpl() { 102 ~PrefHashStoreTransactionImpl() {
110 // Update the super MAC if and only if the hashes dictionary has been
111 // modified in this transaction.
112 if (has_changed_) { 103 if (has_changed_) {
113 // Get the dictionary of hashes (or NULL if it doesn't exist). 104 // Update the super MAC if and only if the hashes dictionary has been
114 const base::DictionaryValue* hashes_dict = outer_->contents_->GetContents(); 105 // modified in this transaction. Imports do not necessarily affect the super
115 outer_->contents_->SetSuperMac(outer_->pref_hash_calculator_.Calculate( 106 // MAC (will not transition it from invalid to valid).
116 outer_->contents_->hash_store_id(), hashes_dict)); 107 if (super_mac_dirty_) {
108 // Get the dictionary of hashes (or NULL if it doesn't exist).
109 const base::DictionaryValue* hashes_dict =
110 outer_->contents_->GetContents();
111 outer_->contents_->SetSuperMac(outer_->pref_hash_calculator_.Calculate(
112 outer_->contents_->hash_store_id(), hashes_dict));
113 }
117 114
118 outer_->has_pending_write_ = true; 115 outer_->has_pending_write_ = true;
119 } 116 }
120
121 // Mark this hash store has having been updated to the latest version (in
122 // practice only initialization transactions will actually do this, but
123 // since they always occur before minor update transaction it's okay
124 // to unconditionally do this here). Only do this if this store's version
125 // isn't already at VERSION_LATEST (to avoid scheduling a write when
126 // unecessary). Note, this is outside of |if (has_changed)| to also seed
127 // version number of otherwise unchanged profiles.
128 int current_version;
129 if (!outer_->contents_->GetVersion(&current_version) ||
130 current_version != VERSION_LATEST) {
131 outer_->contents_->SetVersion(VERSION_LATEST);
132 outer_->has_pending_write_ = true;
133 }
134 } 117 }
135 118
119 const base::Value* PrefHashStoreImpl::PrefHashStoreTransactionImpl::GetHash(
120 const std::string& path) const {
121 const base::DictionaryValue* hashed_prefs = outer_->contents_->GetContents();
122
123 const base::Value* last_hash = NULL;
124 if (hashed_prefs)
125 hashed_prefs->Get(path, &last_hash);
126 return last_hash;
127 }
128
136 PrefHashStoreTransaction::ValueState 129 PrefHashStoreTransaction::ValueState
137 PrefHashStoreImpl::PrefHashStoreTransactionImpl::CheckValue( 130 PrefHashStoreImpl::PrefHashStoreTransactionImpl::CheckValue(
138 const std::string& path, const base::Value* initial_value) const { 131 const std::string& path, const base::Value* initial_value) const {
139 const base::DictionaryValue* hashed_prefs = outer_->contents_->GetContents(); 132 const base::DictionaryValue* hashed_prefs = outer_->contents_->GetContents();
140 133
141 std::string last_hash; 134 std::string last_hash;
142 if (hashed_prefs) 135 if (hashed_prefs)
143 hashed_prefs->GetString(path, &last_hash); 136 hashed_prefs->GetString(path, &last_hash);
144 137
145 if (last_hash.empty()) { 138 if (last_hash.empty()) {
(...skipping 19 matching lines...) Expand all
165 << validation_result; 158 << validation_result;
166 return UNTRUSTED_UNKNOWN_VALUE; 159 return UNTRUSTED_UNKNOWN_VALUE;
167 } 160 }
168 161
169 void PrefHashStoreImpl::PrefHashStoreTransactionImpl::StoreHash( 162 void PrefHashStoreImpl::PrefHashStoreTransactionImpl::StoreHash(
170 const std::string& path, const base::Value* new_value) { 163 const std::string& path, const base::Value* new_value) {
171 const std::string mac = 164 const std::string mac =
172 outer_->pref_hash_calculator_.Calculate(path, new_value); 165 outer_->pref_hash_calculator_.Calculate(path, new_value);
173 (*outer_->contents_->GetMutableContents())->SetString(path, mac); 166 (*outer_->contents_->GetMutableContents())->SetString(path, mac);
174 has_changed_ = true; 167 has_changed_ = true;
168 super_mac_dirty_ = true;
169 }
170
171 void PrefHashStoreImpl::PrefHashStoreTransactionImpl::ImportHash(
172 const std::string& path,
173 const base::Value* hash) {
gab 2014/06/06 21:54:59 I think |hash| should be passed as a std::string.
erikwright (departed) 2014/06/09 18:34:50 That requires separate pairs of methods for atomic
gab 2014/06/09 20:24:33 Duh, of course, passing it via a Value object is f
erikwright (departed) 2014/06/10 20:27:47 I thought about that, but it's consistent with Sto
174 if (!hash)
175 (*outer_->contents_->GetMutableContents())->RemovePath(path, NULL);
176 else
177 (*outer_->contents_->GetMutableContents())->Set(path, hash->DeepCopy());
178 has_changed_ = true;
179 super_mac_dirty_ =
180 super_mac_dirty_ || outer_->initial_hashes_dictionary_trusted_;
gab 2014/06/06 21:54:59 It's incorrect to re-write the super MAC here if t
erikwright (departed) 2014/06/09 18:34:50 We talked about this offline. It's correct to keep
181 }
182
183 void PrefHashStoreImpl::PrefHashStoreTransactionImpl::ClearHash(
184 const std::string& path) {
185 (*outer_->contents_->GetMutableContents())->RemovePath(path, NULL);
186 has_changed_ = true;
187 super_mac_dirty_ =
188 super_mac_dirty_ || outer_->initial_hashes_dictionary_trusted_;
189 }
190
191 bool PrefHashStoreImpl::PrefHashStoreTransactionImpl::StampSuperMac() {
192 if (outer_->initial_hashes_dictionary_trusted_)
193 return false;
194 has_changed_ = true;
195 super_mac_dirty_ = true;
196 return true;
175 } 197 }
176 198
177 PrefHashStoreTransaction::ValueState 199 PrefHashStoreTransaction::ValueState
178 PrefHashStoreImpl::PrefHashStoreTransactionImpl::CheckSplitValue( 200 PrefHashStoreImpl::PrefHashStoreTransactionImpl::CheckSplitValue(
179 const std::string& path, 201 const std::string& path,
180 const base::DictionaryValue* initial_split_value, 202 const base::DictionaryValue* initial_split_value,
181 std::vector<std::string>* invalid_keys) const { 203 std::vector<std::string>* invalid_keys) const {
182 DCHECK(invalid_keys && invalid_keys->empty()); 204 DCHECK(invalid_keys && invalid_keys->empty());
183 205
184 std::map<std::string, std::string> split_macs; 206 std::map<std::string, std::string> split_macs;
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 it.Advance()) { 287 it.Advance()) {
266 // Keep the common part from the old |keyed_path| and replace the key to 288 // Keep the common part from the old |keyed_path| and replace the key to
267 // get the new |keyed_path|. 289 // get the new |keyed_path|.
268 keyed_path.replace(common_part_length, std::string::npos, it.key()); 290 keyed_path.replace(common_part_length, std::string::npos, it.key());
269 (*mutable_dictionary)->SetString( 291 (*mutable_dictionary)->SetString(
270 keyed_path, 292 keyed_path,
271 outer_->pref_hash_calculator_.Calculate(keyed_path, &it.value())); 293 outer_->pref_hash_calculator_.Calculate(keyed_path, &it.value()));
272 } 294 }
273 } 295 }
274 has_changed_ = true; 296 has_changed_ = true;
297 super_mac_dirty_ = true;
275 } 298 }
276 299
277 bool PrefHashStoreImpl::PrefHashStoreTransactionImpl::GetSplitMacs( 300 bool PrefHashStoreImpl::PrefHashStoreTransactionImpl::GetSplitMacs(
278 const std::string& key, 301 const std::string& key,
279 std::map<std::string, std::string>* split_macs) const { 302 std::map<std::string, std::string>* split_macs) const {
280 DCHECK(split_macs); 303 DCHECK(split_macs);
281 DCHECK(split_macs->empty()); 304 DCHECK(split_macs->empty());
282 305
283 const base::DictionaryValue* hashed_prefs = outer_->contents_->GetContents(); 306 const base::DictionaryValue* hashed_prefs = outer_->contents_->GetContents();
284 const base::DictionaryValue* split_mac_dictionary = NULL; 307 const base::DictionaryValue* split_mac_dictionary = NULL;
285 if (!hashed_prefs || !hashed_prefs->GetDictionary(key, &split_mac_dictionary)) 308 if (!hashed_prefs || !hashed_prefs->GetDictionary(key, &split_mac_dictionary))
286 return false; 309 return false;
287 for (base::DictionaryValue::Iterator it(*split_mac_dictionary); !it.IsAtEnd(); 310 for (base::DictionaryValue::Iterator it(*split_mac_dictionary); !it.IsAtEnd();
288 it.Advance()) { 311 it.Advance()) {
289 std::string mac_string; 312 std::string mac_string;
290 if (!it.value().GetAsString(&mac_string)) { 313 if (!it.value().GetAsString(&mac_string)) {
291 NOTREACHED(); 314 NOTREACHED();
292 continue; 315 continue;
293 } 316 }
294 split_macs->insert(make_pair(it.key(), mac_string)); 317 split_macs->insert(make_pair(it.key(), mac_string));
295 } 318 }
296 return true; 319 return true;
297 } 320 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698