OLD | NEW |
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 "components/user_prefs/tracked/pref_hash_store_impl.h" | 5 #include "services/preferences/tracked/pref_hash_store_impl.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/macros.h" | 11 #include "base/macros.h" |
12 #include "base/metrics/histogram_macros.h" | 12 #include "base/metrics/histogram_macros.h" |
13 #include "components/user_prefs/tracked/device_id.h" | 13 #include "services/preferences/tracked/device_id.h" |
14 #include "components/user_prefs/tracked/hash_store_contents.h" | 14 #include "services/preferences/tracked/hash_store_contents.h" |
15 | 15 |
16 namespace { | 16 namespace { |
17 | 17 |
| 18 using ValueState = |
| 19 prefs::mojom::TrackedPreferenceValidationDelegate::ValueState; |
| 20 |
18 // Returns a deterministic ID for this machine. | 21 // Returns a deterministic ID for this machine. |
19 std::string GenerateDeviceId() { | 22 std::string GenerateDeviceId() { |
20 static std::string cached_device_id; | 23 static std::string cached_device_id; |
21 if (!cached_device_id.empty()) | 24 if (!cached_device_id.empty()) |
22 return cached_device_id; | 25 return cached_device_id; |
23 | 26 |
24 std::string device_id; | 27 std::string device_id; |
25 MachineIdStatus status = GetDeterministicMachineSpecificId(&device_id); | 28 MachineIdStatus status = GetDeterministicMachineSpecificId(&device_id); |
26 if (status != MachineIdStatus::NOT_IMPLEMENTED) { | 29 if (status != MachineIdStatus::NOT_IMPLEMENTED) { |
27 // TODO(proberge): Remove this histogram once we validate that machine id | 30 // TODO(proberge): Remove this histogram once we validate that machine id |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 | 78 |
76 DISALLOW_COPY_AND_ASSIGN(PrefHashStoreTransactionImpl); | 79 DISALLOW_COPY_AND_ASSIGN(PrefHashStoreTransactionImpl); |
77 }; | 80 }; |
78 | 81 |
79 PrefHashStoreImpl::PrefHashStoreImpl(const std::string& seed, | 82 PrefHashStoreImpl::PrefHashStoreImpl(const std::string& seed, |
80 const std::string& legacy_device_id, | 83 const std::string& legacy_device_id, |
81 bool use_super_mac) | 84 bool use_super_mac) |
82 : pref_hash_calculator_(seed, GenerateDeviceId(), legacy_device_id), | 85 : pref_hash_calculator_(seed, GenerateDeviceId(), legacy_device_id), |
83 use_super_mac_(use_super_mac) {} | 86 use_super_mac_(use_super_mac) {} |
84 | 87 |
85 PrefHashStoreImpl::~PrefHashStoreImpl() { | 88 PrefHashStoreImpl::~PrefHashStoreImpl() {} |
86 } | |
87 | 89 |
88 std::unique_ptr<PrefHashStoreTransaction> PrefHashStoreImpl::BeginTransaction( | 90 std::unique_ptr<PrefHashStoreTransaction> PrefHashStoreImpl::BeginTransaction( |
89 HashStoreContents* storage) { | 91 HashStoreContents* storage) { |
90 return std::unique_ptr<PrefHashStoreTransaction>( | 92 return std::unique_ptr<PrefHashStoreTransaction>( |
91 new PrefHashStoreTransactionImpl(this, std::move(storage))); | 93 new PrefHashStoreTransactionImpl(this, std::move(storage))); |
92 } | 94 } |
93 | 95 |
94 std::string PrefHashStoreImpl::ComputeMac(const std::string& path, | 96 std::string PrefHashStoreImpl::ComputeMac(const std::string& path, |
95 const base::Value* value) { | 97 const base::Value* value) { |
96 return pref_hash_calculator_.Calculate(path, value); | 98 return pref_hash_calculator_.Calculate(path, value); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
147 const base::DictionaryValue* hashes_dict = contents_->GetContents(); | 149 const base::DictionaryValue* hashes_dict = contents_->GetContents(); |
148 contents_->SetSuperMac(outer_->ComputeMac("", hashes_dict)); | 150 contents_->SetSuperMac(outer_->ComputeMac("", hashes_dict)); |
149 } | 151 } |
150 } | 152 } |
151 | 153 |
152 base::StringPiece | 154 base::StringPiece |
153 PrefHashStoreImpl::PrefHashStoreTransactionImpl::GetStoreUMASuffix() const { | 155 PrefHashStoreImpl::PrefHashStoreTransactionImpl::GetStoreUMASuffix() const { |
154 return contents_->GetUMASuffix(); | 156 return contents_->GetUMASuffix(); |
155 } | 157 } |
156 | 158 |
157 PrefHashStoreTransaction::ValueState | 159 ValueState PrefHashStoreImpl::PrefHashStoreTransactionImpl::CheckValue( |
158 PrefHashStoreImpl::PrefHashStoreTransactionImpl::CheckValue( | |
159 const std::string& path, | 160 const std::string& path, |
160 const base::Value* initial_value) const { | 161 const base::Value* initial_value) const { |
161 std::string last_hash; | 162 std::string last_hash; |
162 contents_->GetMac(path, &last_hash); | 163 contents_->GetMac(path, &last_hash); |
163 | 164 |
164 if (last_hash.empty()) { | 165 if (last_hash.empty()) { |
165 // In the absence of a hash for this pref, always trust a NULL value, but | 166 // In the absence of a hash for this pref, always trust a NULL value, but |
166 // only trust an existing value if the initial hashes dictionary is trusted. | 167 // only trust an existing value if the initial hashes dictionary is trusted. |
167 if (!initial_value) | 168 if (!initial_value) |
168 return TRUSTED_NULL_VALUE; | 169 return ValueState::TRUSTED_NULL_VALUE; |
169 else if (super_mac_valid_) | 170 else if (super_mac_valid_) |
170 return TRUSTED_UNKNOWN_VALUE; | 171 return ValueState::TRUSTED_UNKNOWN_VALUE; |
171 else | 172 else |
172 return UNTRUSTED_UNKNOWN_VALUE; | 173 return ValueState::UNTRUSTED_UNKNOWN_VALUE; |
173 } | 174 } |
174 | 175 |
175 PrefHashCalculator::ValidationResult validation_result = | 176 PrefHashCalculator::ValidationResult validation_result = |
176 outer_->pref_hash_calculator_.Validate(path, initial_value, last_hash); | 177 outer_->pref_hash_calculator_.Validate(path, initial_value, last_hash); |
177 switch (validation_result) { | 178 switch (validation_result) { |
178 case PrefHashCalculator::VALID: | 179 case PrefHashCalculator::VALID: |
179 return UNCHANGED; | 180 return ValueState::UNCHANGED; |
180 case PrefHashCalculator::VALID_SECURE_LEGACY: | 181 case PrefHashCalculator::VALID_SECURE_LEGACY: |
181 return SECURE_LEGACY; | 182 return ValueState::SECURE_LEGACY; |
182 case PrefHashCalculator::INVALID: | 183 case PrefHashCalculator::INVALID: |
183 return initial_value ? CHANGED : CLEARED; | 184 return initial_value ? ValueState::CHANGED : ValueState::CLEARED; |
184 } | 185 } |
185 NOTREACHED() << "Unexpected PrefHashCalculator::ValidationResult: " | 186 NOTREACHED() << "Unexpected PrefHashCalculator::ValidationResult: " |
186 << validation_result; | 187 << validation_result; |
187 return UNTRUSTED_UNKNOWN_VALUE; | 188 return ValueState::UNTRUSTED_UNKNOWN_VALUE; |
188 } | 189 } |
189 | 190 |
190 void PrefHashStoreImpl::PrefHashStoreTransactionImpl::StoreHash( | 191 void PrefHashStoreImpl::PrefHashStoreTransactionImpl::StoreHash( |
191 const std::string& path, | 192 const std::string& path, |
192 const base::Value* new_value) { | 193 const base::Value* new_value) { |
193 const std::string mac = outer_->ComputeMac(path, new_value); | 194 const std::string mac = outer_->ComputeMac(path, new_value); |
194 contents_->SetMac(path, mac); | 195 contents_->SetMac(path, mac); |
195 super_mac_dirty_ = true; | 196 super_mac_dirty_ = true; |
196 } | 197 } |
197 | 198 |
198 PrefHashStoreTransaction::ValueState | 199 ValueState PrefHashStoreImpl::PrefHashStoreTransactionImpl::CheckSplitValue( |
199 PrefHashStoreImpl::PrefHashStoreTransactionImpl::CheckSplitValue( | |
200 const std::string& path, | 200 const std::string& path, |
201 const base::DictionaryValue* initial_split_value, | 201 const base::DictionaryValue* initial_split_value, |
202 std::vector<std::string>* invalid_keys) const { | 202 std::vector<std::string>* invalid_keys) const { |
203 DCHECK(invalid_keys && invalid_keys->empty()); | 203 DCHECK(invalid_keys && invalid_keys->empty()); |
204 | 204 |
205 std::map<std::string, std::string> split_macs; | 205 std::map<std::string, std::string> split_macs; |
206 const bool has_hashes = contents_->GetSplitMacs(path, &split_macs); | 206 const bool has_hashes = contents_->GetSplitMacs(path, &split_macs); |
207 | 207 |
208 // Treat NULL and empty the same; otherwise we would need to store a hash for | 208 // Treat NULL and empty the same; otherwise we would need to store a hash for |
209 // the entire dictionary (or some other special beacon) to differentiate these | 209 // the entire dictionary (or some other special beacon) to differentiate these |
210 // two cases which are really the same for dictionaries. | 210 // two cases which are really the same for dictionaries. |
211 if (!initial_split_value || initial_split_value->empty()) | 211 if (!initial_split_value || initial_split_value->empty()) |
212 return has_hashes ? CLEARED : UNCHANGED; | 212 return has_hashes ? ValueState::CLEARED : ValueState::UNCHANGED; |
213 | 213 |
214 if (!has_hashes) | 214 if (!has_hashes) |
215 return super_mac_valid_ ? TRUSTED_UNKNOWN_VALUE : UNTRUSTED_UNKNOWN_VALUE; | 215 return super_mac_valid_ ? ValueState::TRUSTED_UNKNOWN_VALUE |
| 216 : ValueState::UNTRUSTED_UNKNOWN_VALUE; |
216 | 217 |
217 bool has_secure_legacy_id_hashes = false; | 218 bool has_secure_legacy_id_hashes = false; |
218 std::string keyed_path(path); | 219 std::string keyed_path(path); |
219 keyed_path.push_back('.'); | 220 keyed_path.push_back('.'); |
220 const size_t common_part_length = keyed_path.length(); | 221 const size_t common_part_length = keyed_path.length(); |
221 for (base::DictionaryValue::Iterator it(*initial_split_value); !it.IsAtEnd(); | 222 for (base::DictionaryValue::Iterator it(*initial_split_value); !it.IsAtEnd(); |
222 it.Advance()) { | 223 it.Advance()) { |
223 std::map<std::string, std::string>::iterator entry = | 224 std::map<std::string, std::string>::iterator entry = |
224 split_macs.find(it.key()); | 225 split_macs.find(it.key()); |
225 if (entry == split_macs.end()) { | 226 if (entry == split_macs.end()) { |
226 invalid_keys->push_back(it.key()); | 227 invalid_keys->push_back(it.key()); |
227 } else { | 228 } else { |
228 // Keep the common part from the old |keyed_path| and replace the key to | 229 // Keep the common part from the old |keyed_path| and replace the key to |
229 // get the new |keyed_path|. | 230 // get the new |keyed_path|. |
230 keyed_path.replace(common_part_length, std::string::npos, it.key()); | 231 keyed_path.replace(common_part_length, std::string::npos, it.key()); |
231 switch (outer_->pref_hash_calculator_.Validate(keyed_path, &it.value(), | 232 switch (outer_->pref_hash_calculator_.Validate(keyed_path, &it.value(), |
232 entry->second)) { | 233 entry->second)) { |
233 case PrefHashCalculator::VALID: | 234 case PrefHashCalculator::VALID: |
234 break; | 235 break; |
235 case SECURE_LEGACY: | 236 case PrefHashCalculator::VALID_SECURE_LEGACY: |
236 // Secure legacy device IDs based hashes are still accepted, but we | 237 // Secure legacy device IDs based hashes are still accepted, but we |
237 // should make sure to notify the caller for them to update the legacy | 238 // should make sure to notify the caller for them to update the legacy |
238 // hashes. | 239 // hashes. |
239 has_secure_legacy_id_hashes = true; | 240 has_secure_legacy_id_hashes = true; |
240 break; | 241 break; |
241 case PrefHashCalculator::INVALID: | 242 case PrefHashCalculator::INVALID: |
242 invalid_keys->push_back(it.key()); | 243 invalid_keys->push_back(it.key()); |
243 break; | 244 break; |
244 } | 245 } |
245 // Remove processed MACs, remaining MACs at the end will also be | 246 // Remove processed MACs, remaining MACs at the end will also be |
246 // considered invalid. | 247 // considered invalid. |
247 split_macs.erase(entry); | 248 split_macs.erase(entry); |
248 } | 249 } |
249 } | 250 } |
250 | 251 |
251 // Anything left in the map is missing from the data. | 252 // Anything left in the map is missing from the data. |
252 for (std::map<std::string, std::string>::const_iterator it = | 253 for (std::map<std::string, std::string>::const_iterator it = |
253 split_macs.begin(); | 254 split_macs.begin(); |
254 it != split_macs.end(); ++it) { | 255 it != split_macs.end(); ++it) { |
255 invalid_keys->push_back(it->first); | 256 invalid_keys->push_back(it->first); |
256 } | 257 } |
257 | 258 |
258 return invalid_keys->empty() | 259 return invalid_keys->empty() |
259 ? (has_secure_legacy_id_hashes ? SECURE_LEGACY : UNCHANGED) | 260 ? (has_secure_legacy_id_hashes ? ValueState::SECURE_LEGACY |
260 : CHANGED; | 261 : ValueState::UNCHANGED) |
| 262 : ValueState::CHANGED; |
261 } | 263 } |
262 | 264 |
263 void PrefHashStoreImpl::PrefHashStoreTransactionImpl::StoreSplitHash( | 265 void PrefHashStoreImpl::PrefHashStoreTransactionImpl::StoreSplitHash( |
264 const std::string& path, | 266 const std::string& path, |
265 const base::DictionaryValue* split_value) { | 267 const base::DictionaryValue* split_value) { |
266 contents_->RemoveEntry(path); | 268 contents_->RemoveEntry(path); |
267 | 269 |
268 if (split_value) { | 270 if (split_value) { |
269 std::unique_ptr<base::DictionaryValue> split_macs = | 271 std::unique_ptr<base::DictionaryValue> split_macs = |
270 outer_->ComputeSplitMacs(path, split_value); | 272 outer_->ComputeSplitMacs(path, split_value); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
310 bool PrefHashStoreImpl::PrefHashStoreTransactionImpl::IsSuperMACValid() const { | 312 bool PrefHashStoreImpl::PrefHashStoreTransactionImpl::IsSuperMACValid() const { |
311 return super_mac_valid_; | 313 return super_mac_valid_; |
312 } | 314 } |
313 | 315 |
314 bool PrefHashStoreImpl::PrefHashStoreTransactionImpl::StampSuperMac() { | 316 bool PrefHashStoreImpl::PrefHashStoreTransactionImpl::StampSuperMac() { |
315 if (!outer_->use_super_mac_ || super_mac_valid_) | 317 if (!outer_->use_super_mac_ || super_mac_valid_) |
316 return false; | 318 return false; |
317 super_mac_dirty_ = true; | 319 super_mac_dirty_ = true; |
318 return true; | 320 return true; |
319 } | 321 } |
OLD | NEW |