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
3 // found in the LICENSE file.
5 #include "chrome/browser/prefs/pref_hash_store_impl.h"
7 #include "base/logging.h"
8 #include "base/metrics/histogram.h"
9 #include "base/prefs/pref_registry_simple.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/prefs/scoped_user_pref_update.h"
12 #include "base/values.h"
13 #include "chrome/common/pref_names.h"
15 PrefHashStoreImpl::PrefHashStoreImpl(const std::string
& hash_store_id
,
16 const std::string
& seed
,
17 const std::string
& device_id
,
18 PrefService
* local_state
)
19 : hash_store_id_(hash_store_id
),
20 pref_hash_calculator_(seed
, device_id
),
21 local_state_(local_state
),
22 initial_hashes_dictionary_trusted_(IsHashDictionaryTrusted()) {
23 UMA_HISTOGRAM_BOOLEAN("Settings.HashesDictionaryTrusted",
24 initial_hashes_dictionary_trusted_
);
28 void PrefHashStoreImpl::RegisterPrefs(PrefRegistrySimple
* registry
) {
29 // Register the top level dictionary to map profile names to dictionaries of
30 // tracked preferences.
31 registry
->RegisterDictionaryPref(prefs::kProfilePreferenceHashes
);
34 PrefHashStore::ValueState
PrefHashStoreImpl::CheckValue(
35 const std::string
& path
, const base::Value
* initial_value
) const {
36 const base::DictionaryValue
* pref_hash_dicts
=
37 local_state_
->GetDictionary(prefs::kProfilePreferenceHashes
);
38 const base::DictionaryValue
* hashed_prefs
= NULL
;
39 pref_hash_dicts
->GetDictionaryWithoutPathExpansion(hash_store_id_
,
42 std::string last_hash
;
43 if (!hashed_prefs
|| !hashed_prefs
->GetString(path
, &last_hash
)) {
44 // In the absence of a hash for this pref, always trust a NULL value, but
45 // only trust an existing value if the initial hashes dictionary is trusted.
46 return (!initial_value
|| initial_hashes_dictionary_trusted_
) ?
47 TRUSTED_UNKNOWN_VALUE
: UNTRUSTED_UNKNOWN_VALUE
;
50 PrefHashCalculator::ValidationResult validation_result
=
51 pref_hash_calculator_
.Validate(path
, initial_value
, last_hash
);
52 switch (validation_result
) {
53 case PrefHashCalculator::VALID
:
55 case PrefHashCalculator::VALID_LEGACY
:
57 case PrefHashCalculator::INVALID
:
58 return initial_value
? CHANGED
: CLEARED
;
60 NOTREACHED() << "Unexpected PrefHashCalculator::ValidationResult: "
62 return UNTRUSTED_UNKNOWN_VALUE
;
65 void PrefHashStoreImpl::StoreHash(
66 const std::string
& path
, const base::Value
* new_value
) {
67 DictionaryPrefUpdate
update(local_state_
, prefs::kProfilePreferenceHashes
);
69 // Get the dictionary corresponding to the profile name, which may have a
71 base::DictionaryValue
* hashes_dict
= NULL
;
72 if (!update
->GetDictionaryWithoutPathExpansion(hash_store_id_
,
74 hashes_dict
= new base::DictionaryValue
;
75 update
->SetWithoutPathExpansion(hash_store_id_
, hashes_dict
);
78 hashes_dict
->SetString(
79 path
, pref_hash_calculator_
.Calculate(path
, new_value
));
81 // Get the dictionary where the hash of hashes are stored.
82 base::DictionaryValue
* hash_of_hashes_dict
= NULL
;
83 if (!update
->GetDictionaryWithoutPathExpansion(internals::kHashOfHashesPref
,
84 &hash_of_hashes_dict
)) {
85 hash_of_hashes_dict
= new base::DictionaryValue
;
86 update
->SetWithoutPathExpansion(internals::kHashOfHashesPref
,
89 // Use the |hash_store_id_| as the hashed path to avoid having the hash
90 // depend on kProfilePreferenceHashes.
91 std::string
hash_of_hashes(pref_hash_calculator_
.Calculate(hash_store_id_
,
93 hash_of_hashes_dict
->SetStringWithoutPathExpansion(hash_store_id_
,
97 bool PrefHashStoreImpl::IsHashDictionaryTrusted() const {
98 const base::DictionaryValue
* pref_hash_dicts
=
99 local_state_
->GetDictionary(prefs::kProfilePreferenceHashes
);
100 const base::DictionaryValue
* hashes_dict
= NULL
;
101 const base::DictionaryValue
* hash_of_hashes_dict
= NULL
;
102 std::string hash_of_hashes
;
103 // The absence of the hashes dictionary isn't trusted. Nor is the absence of
104 // the hash of hashes for this |hash_store_id_|.
105 if (!pref_hash_dicts
->GetDictionaryWithoutPathExpansion(
106 hash_store_id_
, &hashes_dict
) ||
107 !pref_hash_dicts
->GetDictionaryWithoutPathExpansion(
108 internals::kHashOfHashesPref
, &hash_of_hashes_dict
) ||
109 !hash_of_hashes_dict
->GetStringWithoutPathExpansion(
110 hash_store_id_
, &hash_of_hashes
)) {
114 return pref_hash_calculator_
.Validate(
115 hash_store_id_
, hashes_dict
, hash_of_hashes
) == PrefHashCalculator::VALID
;