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 "chrome/browser/prefs/pref_hash_store_impl.h" | 5 #include "chrome/browser/prefs/pref_hash_store_impl.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/prefs/pref_service.h" | 9 #include "base/prefs/pref_service.h" |
10 #include "base/prefs/scoped_user_pref_update.h" | 10 #include "base/prefs/scoped_user_pref_update.h" |
11 #include "base/prefs/testing_pref_service.h" | 11 #include "base/prefs/testing_pref_service.h" |
12 #include "base/values.h" | 12 #include "base/values.h" |
13 #include "chrome/browser/prefs/pref_hash_store.h" | 13 #include "chrome/browser/prefs/pref_hash_store.h" |
14 #include "chrome/common/pref_names.h" | 14 #include "chrome/common/pref_names.h" |
15 #include "testing/gtest/include/gtest/gtest.h" | 15 #include "testing/gtest/include/gtest/gtest.h" |
16 | 16 |
17 TEST(PrefHashStoreImplTest, TestCase) { | 17 TEST(PrefHashStoreImplTest, AtomicHashStoreAndCheck) { |
18 base::StringValue string_1("string1"); | 18 base::StringValue string_1("string1"); |
19 base::StringValue string_2("string2"); | 19 base::StringValue string_2("string2"); |
20 | 20 |
21 TestingPrefServiceSimple local_state; | 21 TestingPrefServiceSimple local_state; |
22 PrefHashStoreImpl::RegisterPrefs(local_state.registry()); | 22 PrefHashStoreImpl::RegisterPrefs(local_state.registry()); |
23 | 23 |
24 // 32 NULL bytes is the seed that was used to generate the legacy hash. | 24 // 32 NULL bytes is the seed that was used to generate the legacy hash. |
25 PrefHashStoreImpl pref_hash_store( | 25 PrefHashStoreImpl pref_hash_store( |
26 "store_id", std::string(32,0), "device_id", &local_state); | 26 "store_id", std::string(32, 0), "device_id", &local_state); |
27 | 27 |
28 // Only NULL should be trusted in the absence of a hash. | 28 // Only NULL should be trusted in the absence of a hash. |
29 EXPECT_EQ(PrefHashStore::UNTRUSTED_UNKNOWN_VALUE, | 29 EXPECT_EQ(PrefHashStore::UNTRUSTED_UNKNOWN_VALUE, |
30 pref_hash_store.CheckValue("path1", &string_1)); | 30 pref_hash_store.CheckValue("path1", &string_1)); |
31 EXPECT_EQ(PrefHashStore::TRUSTED_UNKNOWN_VALUE, | 31 EXPECT_EQ(PrefHashStore::TRUSTED_UNKNOWN_VALUE, |
32 pref_hash_store.CheckValue("path1", NULL)); | 32 pref_hash_store.CheckValue("path1", NULL)); |
33 | 33 |
34 pref_hash_store.StoreHash("path1", &string_1); | 34 pref_hash_store.StoreHash("path1", &string_1); |
35 EXPECT_EQ(PrefHashStore::UNCHANGED, | 35 EXPECT_EQ(PrefHashStore::UNCHANGED, |
36 pref_hash_store.CheckValue("path1", &string_1)); | 36 pref_hash_store.CheckValue("path1", &string_1)); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
88 // thus shouldn't trust non-NULL unknown values. | 88 // thus shouldn't trust non-NULL unknown values. |
89 PrefHashStoreImpl pref_hash_store3( | 89 PrefHashStoreImpl pref_hash_store3( |
90 "store_id", std::string(32, 0), "device_id", &local_state); | 90 "store_id", std::string(32, 0), "device_id", &local_state); |
91 EXPECT_EQ(PrefHashStore::UNTRUSTED_UNKNOWN_VALUE, | 91 EXPECT_EQ(PrefHashStore::UNTRUSTED_UNKNOWN_VALUE, |
92 pref_hash_store3.CheckValue("new_path", &string_1)); | 92 pref_hash_store3.CheckValue("new_path", &string_1)); |
93 EXPECT_EQ(PrefHashStore::UNTRUSTED_UNKNOWN_VALUE, | 93 EXPECT_EQ(PrefHashStore::UNTRUSTED_UNKNOWN_VALUE, |
94 pref_hash_store3.CheckValue("new_path", &string_2)); | 94 pref_hash_store3.CheckValue("new_path", &string_2)); |
95 EXPECT_EQ(PrefHashStore::TRUSTED_UNKNOWN_VALUE, | 95 EXPECT_EQ(PrefHashStore::TRUSTED_UNKNOWN_VALUE, |
96 pref_hash_store3.CheckValue("new_path", NULL)); | 96 pref_hash_store3.CheckValue("new_path", NULL)); |
97 } | 97 } |
| 98 |
| 99 TEST(PrefHashStoreImplTest, SplitHashStoreAndCheck) { |
| 100 base::DictionaryValue dict; |
| 101 dict.Set("a", new base::StringValue("to be replaced")); |
| 102 dict.Set("b", new base::StringValue("same")); |
| 103 dict.Set("o", new base::StringValue("old")); |
| 104 |
| 105 base::DictionaryValue modified_dict; |
| 106 modified_dict.Set("a", new base::StringValue("replaced")); |
| 107 modified_dict.Set("b", new base::StringValue("same")); |
| 108 modified_dict.Set("c", new base::StringValue("new")); |
| 109 |
| 110 base::DictionaryValue empty_dict; |
| 111 |
| 112 TestingPrefServiceSimple local_state; |
| 113 PrefHashStoreImpl::RegisterPrefs(local_state.registry()); |
| 114 |
| 115 PrefHashStoreImpl pref_hash_store( |
| 116 "store_id", std::string(32, 0), "device_id", &local_state); |
| 117 |
| 118 std::vector<std::string> invalid_keys; |
| 119 |
| 120 // No hashes stored yet and hashes dictionary is empty (and thus not trusted). |
| 121 EXPECT_EQ(PrefHashStore::UNTRUSTED_UNKNOWN_VALUE, |
| 122 pref_hash_store.CheckSplitValue("path1", &dict, &invalid_keys)); |
| 123 EXPECT_TRUE(invalid_keys.empty()); |
| 124 |
| 125 pref_hash_store.StoreSplitHash("path1", &dict); |
| 126 |
| 127 // Verify match post storage. |
| 128 EXPECT_EQ(PrefHashStore::UNCHANGED, |
| 129 pref_hash_store.CheckSplitValue("path1", &dict, &invalid_keys)); |
| 130 EXPECT_TRUE(invalid_keys.empty()); |
| 131 |
| 132 // Verify new path is still unknown. |
| 133 EXPECT_EQ(PrefHashStore::UNTRUSTED_UNKNOWN_VALUE, |
| 134 pref_hash_store.CheckSplitValue("path2", &dict, &invalid_keys)); |
| 135 EXPECT_TRUE(invalid_keys.empty()); |
| 136 |
| 137 // Verify NULL or empty dicts are declared as having been cleared. |
| 138 EXPECT_EQ(PrefHashStore::CLEARED, |
| 139 pref_hash_store.CheckSplitValue("path1", NULL, &invalid_keys)); |
| 140 EXPECT_TRUE(invalid_keys.empty()); |
| 141 EXPECT_EQ(PrefHashStore::CLEARED, |
| 142 pref_hash_store.CheckSplitValue("path1", &empty_dict, |
| 143 &invalid_keys)); |
| 144 EXPECT_TRUE(invalid_keys.empty()); |
| 145 |
| 146 // Verify changes are properly detected. |
| 147 EXPECT_EQ(PrefHashStore::CHANGED, |
| 148 pref_hash_store.CheckSplitValue("path1", &modified_dict, |
| 149 &invalid_keys)); |
| 150 std::vector<std::string> expected_invalid_keys1; |
| 151 expected_invalid_keys1.push_back("a"); |
| 152 expected_invalid_keys1.push_back("c"); |
| 153 EXPECT_EQ(expected_invalid_keys1, invalid_keys); |
| 154 invalid_keys.clear(); |
| 155 |
| 156 // Verify |dict| still matches post check. |
| 157 EXPECT_EQ(PrefHashStore::UNCHANGED, |
| 158 pref_hash_store.CheckSplitValue("path1", &dict, &invalid_keys)); |
| 159 EXPECT_TRUE(invalid_keys.empty()); |
| 160 |
| 161 // Store hash for |modified_dict|. |
| 162 pref_hash_store.StoreSplitHash("path1", &modified_dict); |
| 163 |
| 164 // Verify |modified_dict| is now the one that verifies correctly. |
| 165 EXPECT_EQ(PrefHashStore::UNCHANGED, |
| 166 pref_hash_store.CheckSplitValue("path1", &modified_dict, |
| 167 &invalid_keys)); |
| 168 EXPECT_TRUE(invalid_keys.empty()); |
| 169 |
| 170 // Verify old dict no longer matches. |
| 171 EXPECT_EQ(PrefHashStore::CHANGED, |
| 172 pref_hash_store.CheckSplitValue("path1", &dict, &invalid_keys)); |
| 173 std::vector<std::string> expected_invalid_keys2; |
| 174 expected_invalid_keys2.push_back("a"); |
| 175 expected_invalid_keys2.push_back("o"); |
| 176 EXPECT_EQ(expected_invalid_keys2, invalid_keys); |
| 177 invalid_keys.clear(); |
| 178 |
| 179 // |pref_hash_store2| should trust its initial hashes dictionary and thus |
| 180 // trust new unknown values. |
| 181 PrefHashStoreImpl pref_hash_store2( |
| 182 "store_id", std::string(32, 0), "device_id", &local_state); |
| 183 EXPECT_EQ(PrefHashStore::TRUSTED_UNKNOWN_VALUE, |
| 184 pref_hash_store2.CheckSplitValue("new_path", &dict, &invalid_keys)); |
| 185 EXPECT_TRUE(invalid_keys.empty()); |
| 186 |
| 187 { |
| 188 // Manually corrupt the hash of hashes for "store_id". |
| 189 DictionaryPrefUpdate update(&local_state, prefs::kProfilePreferenceHashes); |
| 190 base::DictionaryValue* hash_of_hashes_dict = NULL; |
| 191 ASSERT_TRUE(update->GetDictionaryWithoutPathExpansion( |
| 192 internals::kHashOfHashesPref, &hash_of_hashes_dict)); |
| 193 hash_of_hashes_dict->SetString("store_id", std::string(64, 'A')); |
| 194 // This shouldn't have increased the number of existing hash of hashes. |
| 195 ASSERT_EQ(1U, hash_of_hashes_dict->size()); |
| 196 } |
| 197 |
| 198 // |pref_hash_store3| should no longer trust its initial hashes dictionary and |
| 199 // thus shouldn't trust unknown values. |
| 200 PrefHashStoreImpl pref_hash_store3( |
| 201 "store_id", std::string(32, 0), "device_id", &local_state); |
| 202 EXPECT_EQ(PrefHashStore::UNTRUSTED_UNKNOWN_VALUE, |
| 203 pref_hash_store3.CheckSplitValue("new_path", &dict, &invalid_keys)); |
| 204 EXPECT_TRUE(invalid_keys.empty()); |
| 205 } |
| 206 |
| 207 TEST(PrefHashStoreImplTest, EmptyAndNULLSplitDict) { |
| 208 base::DictionaryValue empty_dict; |
| 209 |
| 210 TestingPrefServiceSimple local_state; |
| 211 PrefHashStoreImpl::RegisterPrefs(local_state.registry()); |
| 212 |
| 213 PrefHashStoreImpl pref_hash_store( |
| 214 "store_id", std::string(32, 0), "device_id", &local_state); |
| 215 |
| 216 // Store hashes for a random dict to be overwritten below. |
| 217 base::DictionaryValue initial_dict; |
| 218 initial_dict.Set("a", new base::StringValue("foo")); |
| 219 pref_hash_store.StoreSplitHash("path1", &initial_dict); |
| 220 |
| 221 std::vector<std::string> invalid_keys; |
| 222 |
| 223 // Verify stored empty dictionary matches NULL and empty dictionary back. |
| 224 pref_hash_store.StoreSplitHash("path1", &empty_dict); |
| 225 EXPECT_EQ(PrefHashStore::UNCHANGED, |
| 226 pref_hash_store.CheckSplitValue("path1", NULL, &invalid_keys)); |
| 227 EXPECT_TRUE(invalid_keys.empty()); |
| 228 EXPECT_EQ(PrefHashStore::UNCHANGED, |
| 229 pref_hash_store.CheckSplitValue("path1", &empty_dict, |
| 230 &invalid_keys)); |
| 231 EXPECT_TRUE(invalid_keys.empty()); |
| 232 |
| 233 // Same when storing NULL directly. |
| 234 pref_hash_store.StoreSplitHash("path1", NULL); |
| 235 EXPECT_EQ(PrefHashStore::UNCHANGED, |
| 236 pref_hash_store.CheckSplitValue("path1", NULL, &invalid_keys)); |
| 237 EXPECT_TRUE(invalid_keys.empty()); |
| 238 EXPECT_EQ(PrefHashStore::UNCHANGED, |
| 239 pref_hash_store.CheckSplitValue("path1", &empty_dict, |
| 240 &invalid_keys)); |
| 241 EXPECT_TRUE(invalid_keys.empty()); |
| 242 |
| 243 // |pref_hash_store2| should trust its initial hashes dictionary (and thus |
| 244 // trust new unknown values) even though the last action done on local_state |
| 245 // was to clear the hashes for path1 by setting its value to NULL (this is a |
| 246 // regression test ensuring that the internal action of clearing some hashes |
| 247 // does update the stored hash of hashes). |
| 248 PrefHashStoreImpl pref_hash_store2( |
| 249 "store_id", std::string(32, 0), "device_id", &local_state); |
| 250 |
| 251 base::DictionaryValue tested_dict; |
| 252 tested_dict.Set("a", new base::StringValue("foo")); |
| 253 tested_dict.Set("b", new base::StringValue("bar")); |
| 254 EXPECT_EQ(PrefHashStore::TRUSTED_UNKNOWN_VALUE, |
| 255 pref_hash_store2.CheckSplitValue("new_path", &tested_dict, |
| 256 &invalid_keys)); |
| 257 EXPECT_TRUE(invalid_keys.empty()); |
| 258 } |
| 259 |
| 260 // Test that the PrefHashStore returns TRUSTED_UNKNOWN_VALUE when checking for |
| 261 // a split preference even if there is an existing atomic preference's hash |
| 262 // stored. There is no point providing a migration path for preferences |
| 263 // switching strategies after their initial release as split preferences are |
| 264 // turned into split preferences specifically because the atomic hash isn't |
| 265 // considered useful. |
| 266 TEST(PrefHashStoreImplTest, TrustedUnknownSplitValueFromExistingAtomic) { |
| 267 base::StringValue string("string1"); |
| 268 |
| 269 base::DictionaryValue dict; |
| 270 dict.Set("a", new base::StringValue("foo")); |
| 271 dict.Set("d", new base::StringValue("bad")); |
| 272 dict.Set("b", new base::StringValue("bar")); |
| 273 dict.Set("c", new base::StringValue("baz")); |
| 274 |
| 275 TestingPrefServiceSimple local_state; |
| 276 PrefHashStoreImpl::RegisterPrefs(local_state.registry()); |
| 277 |
| 278 PrefHashStoreImpl pref_hash_store( |
| 279 "store_id", std::string(32, 0), "device_id", &local_state); |
| 280 |
| 281 pref_hash_store.StoreHash("path1", &string); |
| 282 EXPECT_EQ(PrefHashStore::UNCHANGED, |
| 283 pref_hash_store.CheckValue("path1", &string)); |
| 284 |
| 285 // Load a new |pref_hash_store2| in which the hashes dictionary is trusted. |
| 286 PrefHashStoreImpl pref_hash_store2( |
| 287 "store_id", std::string(32, 0), "device_id", &local_state); |
| 288 std::vector<std::string> invalid_keys; |
| 289 EXPECT_EQ(PrefHashStore::TRUSTED_UNKNOWN_VALUE, |
| 290 pref_hash_store2.CheckSplitValue("path1", &dict, &invalid_keys)); |
| 291 EXPECT_TRUE(invalid_keys.empty()); |
| 292 } |
OLD | NEW |