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. 4 5 #include "chrome/browser/prefs/pref_hash_filter.h" 6 7 #include <map> 8 #include <set> 9 #include <string> 10 #include <utility> 11 #include <vector> 12 13 #include "base/basictypes.h" 14 #include "base/bind.h" 15 #include "base/callback_forward.h" 16 #include "base/compiler_specific.h" 17 #include "base/logging.h" 18 #include "base/memory/ref_counted.h" 19 #include "base/memory/scoped_ptr.h" 20 #include "base/prefs/testing_pref_store.h" 21 #include "base/values.h" 22 #include "chrome/browser/prefs/mock_validation_delegate.h" 23 #include "chrome/browser/prefs/pref_hash_store.h" 24 #include "chrome/browser/prefs/pref_hash_store_transaction.h" 25 #include "chrome/browser/prefs/tracked/hash_store_contents.h" 26 #include "chrome/common/pref_names.h" 27 #include "testing/gtest/include/gtest/gtest.h" 28 29 namespace { 30 31 const char kAtomicPref[] = "atomic_pref"; 32 const char kAtomicPref2[] = "atomic_pref2"; 33 const char kAtomicPref3[] = "pref3"; 34 const char kAtomicPref4[] = "pref4"; 35 const char kReportOnlyPref[] = "report_only"; 36 const char kReportOnlySplitPref[] = "report_only_split_pref"; 37 const char kSplitPref[] = "split_pref"; 38 39 const PrefHashFilter::TrackedPreferenceMetadata kTestTrackedPrefs[] = { 40 { 41 0, kAtomicPref, PrefHashFilter::ENFORCE_ON_LOAD, 42 PrefHashFilter::TRACKING_STRATEGY_ATOMIC 43 }, 44 { 45 1, kReportOnlyPref, PrefHashFilter::NO_ENFORCEMENT, 46 PrefHashFilter::TRACKING_STRATEGY_ATOMIC 47 }, 48 { 49 2, kSplitPref, PrefHashFilter::ENFORCE_ON_LOAD, 50 PrefHashFilter::TRACKING_STRATEGY_SPLIT 51 }, 52 { 53 3, kReportOnlySplitPref, PrefHashFilter::NO_ENFORCEMENT, 54 PrefHashFilter::TRACKING_STRATEGY_SPLIT 55 }, 56 { 57 4, kAtomicPref2, PrefHashFilter::ENFORCE_ON_LOAD, 58 PrefHashFilter::TRACKING_STRATEGY_ATOMIC 59 }, 60 { 61 5, kAtomicPref3, PrefHashFilter::ENFORCE_ON_LOAD, 62 PrefHashFilter::TRACKING_STRATEGY_ATOMIC 63 }, 64 { 65 6, kAtomicPref4, PrefHashFilter::ENFORCE_ON_LOAD, 66 PrefHashFilter::TRACKING_STRATEGY_ATOMIC 67 }, 68 }; 69 70 } // namespace 71 72 // A PrefHashStore that allows simulation of CheckValue results and captures 73 // checked and stored values. 74 class MockPrefHashStore : public PrefHashStore { 75 public: 76 typedef std::pair<const void*, PrefHashFilter::PrefTrackingStrategy> 77 ValuePtrStrategyPair; 78 79 MockPrefHashStore() 80 : transactions_performed_(0), transaction_active_(false) {} 81 82 virtual ~MockPrefHashStore() { 83 EXPECT_FALSE(transaction_active_); 84 } 85 86 // Set the result that will be returned when |path| is passed to 87 // |CheckValue/CheckSplitValue|. 88 void SetCheckResult(const std::string& path, 89 PrefHashStoreTransaction::ValueState result); 90 91 // Set the invalid_keys that will be returned when |path| is passed to 92 // |CheckSplitValue|. SetCheckResult should already have been called for 93 // |path| with |result == CHANGED| for this to make any sense. 94 void SetInvalidKeysResult( 95 const std::string& path, 96 const std::vector<std::string>& invalid_keys_result); 97 98 // Returns the number of transactions that were performed. 99 size_t transactions_performed() { return transactions_performed_; } 100 101 // Returns the number of paths checked. 102 size_t checked_paths_count() const { 103 return checked_values_.size(); 104 } 105 106 // Returns the number of paths stored. 107 size_t stored_paths_count() const { 108 return stored_values_.size(); 109 } 110 111 // Returns the pointer value and strategy that was passed to 112 // |CheckHash/CheckSplitHash| for |path|. The returned pointer could since 113 // have been freed and is thus not safe to dereference. 114 ValuePtrStrategyPair checked_value(const std::string& path) const { 115 std::map<std::string, ValuePtrStrategyPair>::const_iterator value = 116 checked_values_.find(path); 117 if (value != checked_values_.end()) 118 return value->second; 119 return std::make_pair( 120 reinterpret_cast<void*>(0xBAD), 121 static_cast<PrefHashFilter::PrefTrackingStrategy>(-1)); 122 } 123 124 // Returns the pointer value that was passed to |StoreHash/StoreSplitHash| for 125 // |path|. The returned pointer could since have been freed and is thus not 126 // safe to dereference. 127 ValuePtrStrategyPair stored_value(const std::string& path) const { 128 std::map<std::string, ValuePtrStrategyPair>::const_iterator value = 129 stored_values_.find(path); 130 if (value != stored_values_.end()) 131 return value->second; 132 return std::make_pair( 133 reinterpret_cast<void*>(0xBAD), 134 static_cast<PrefHashFilter::PrefTrackingStrategy>(-1)); 135 } 136 137 // PrefHashStore implementation. 138 virtual scoped_ptr<PrefHashStoreTransaction> BeginTransaction( 139 scoped_ptr<HashStoreContents> storage) OVERRIDE; 140 141 private: 142 // A MockPrefHashStoreTransaction is handed to the caller on 143 // MockPrefHashStore::BeginTransaction(). It then stores state in its 144 // underlying MockPrefHashStore about calls it receives from that same caller 145 // which can later be verified in tests. 146 class MockPrefHashStoreTransaction : public PrefHashStoreTransaction { 147 public: 148 explicit MockPrefHashStoreTransaction(MockPrefHashStore* outer) 149 : outer_(outer) {} 150 151 virtual ~MockPrefHashStoreTransaction() { 152 outer_->transaction_active_ = false; 153 ++outer_->transactions_performed_; 154 } 155 156 // PrefHashStoreTransaction implementation. 157 virtual PrefHashStoreTransaction::ValueState CheckValue( 158 const std::string& path, const base::Value* value) const OVERRIDE; 159 virtual void StoreHash(const std::string& path, 160 const base::Value* new_value) OVERRIDE; 161 virtual PrefHashStoreTransaction::ValueState CheckSplitValue( 162 const std::string& path, 163 const base::DictionaryValue* initial_split_value, 164 std::vector<std::string>* invalid_keys) const OVERRIDE; 165 virtual void StoreSplitHash( 166 const std::string& path, 167 const base::DictionaryValue* split_value) OVERRIDE; 168 virtual bool HasHash(const std::string& path) const OVERRIDE; 169 virtual void ImportHash(const std::string& path, 170 const base::Value* hash) OVERRIDE; 171 virtual void ClearHash(const std::string& path) OVERRIDE; 172 virtual bool IsSuperMACValid() const OVERRIDE; 173 virtual bool StampSuperMac() OVERRIDE; 174 175 private: 176 MockPrefHashStore* outer_; 177 178 DISALLOW_COPY_AND_ASSIGN(MockPrefHashStoreTransaction); 179 }; 180 181 // Records a call to this mock's CheckValue/CheckSplitValue methods. 182 PrefHashStoreTransaction::ValueState RecordCheckValue( 183 const std::string& path, 184 const base::Value* value, 185 PrefHashFilter::PrefTrackingStrategy strategy); 186 187 // Records a call to this mock's StoreHash/StoreSplitHash methods. 188 void RecordStoreHash(const std::string& path, 189 const base::Value* new_value, 190 PrefHashFilter::PrefTrackingStrategy strategy); 191 192 std::map<std::string, PrefHashStoreTransaction::ValueState> check_results_; 193 std::map<std::string, std::vector<std::string> > invalid_keys_results_; 194 std::map<std::string, ValuePtrStrategyPair> checked_values_; 195 std::map<std::string, ValuePtrStrategyPair> stored_values_; 196 197 // Number of transactions that are expected to be performed in the scope of 198 // this test (defaults to 1). 199 size_t transactions_expected_; 200 201 // Number of transactions that were performed via this MockPrefHashStore. 202 // Verified to match |transactions_expected_| when this MockPrefHashStore is 203 // deleted. 204 size_t transactions_performed_; 205 206 // Whether a transaction is currently active (only one transaction should be 207 // active at a time). 208 bool transaction_active_; 209 210 DISALLOW_COPY_AND_ASSIGN(MockPrefHashStore); 211 }; 212 213 void MockPrefHashStore::SetCheckResult( 214 const std::string& path, PrefHashStoreTransaction::ValueState result) { 215 check_results_.insert(std::make_pair(path, result)); 216 } 217 218 void MockPrefHashStore::SetInvalidKeysResult( 219 const std::string& path, 220 const std::vector<std::string>& invalid_keys_result) { 221 // Ensure |check_results_| has a CHANGED entry for |path|. 222 std::map<std::string, 223 PrefHashStoreTransaction::ValueState>::const_iterator result = 224 check_results_.find(path); 225 ASSERT_TRUE(result != check_results_.end()); 226 ASSERT_EQ(PrefHashStoreTransaction::CHANGED, result->second); 227 228 invalid_keys_results_.insert(std::make_pair(path, invalid_keys_result)); 229 } 230 231 scoped_ptr<PrefHashStoreTransaction> MockPrefHashStore::BeginTransaction( 232 scoped_ptr<HashStoreContents> storage) { 233 EXPECT_FALSE(transaction_active_); 234 return scoped_ptr<PrefHashStoreTransaction>( 235 new MockPrefHashStoreTransaction(this)); 236 } 237 238 PrefHashStoreTransaction::ValueState MockPrefHashStore::RecordCheckValue( 239 const std::string& path, 240 const base::Value* value, 241 PrefHashFilter::PrefTrackingStrategy strategy) { 242 // Record that |path| was checked and validate that it wasn't previously 243 // checked. 244 EXPECT_TRUE(checked_values_.insert( 245 std::make_pair(path, std::make_pair(value, strategy))).second); 246 std::map<std::string, 247 PrefHashStoreTransaction::ValueState>::const_iterator result = 248 check_results_.find(path); 249 if (result != check_results_.end()) 250 return result->second; 251 return PrefHashStoreTransaction::UNCHANGED; 252 } 253 254 void MockPrefHashStore::RecordStoreHash( 255 const std::string& path, 256 const base::Value* new_value, 257 PrefHashFilter::PrefTrackingStrategy strategy) { 258 EXPECT_TRUE(stored_values_.insert( 259 std::make_pair(path, std::make_pair(new_value, strategy))).second); 260 } 261 262 PrefHashStoreTransaction::ValueState 263 MockPrefHashStore::MockPrefHashStoreTransaction::CheckValue( 264 const std::string& path, const base::Value* value) const { 265 return outer_->RecordCheckValue(path, value, 266 PrefHashFilter::TRACKING_STRATEGY_ATOMIC); 267 } 268 269 void MockPrefHashStore::MockPrefHashStoreTransaction::StoreHash( 270 const std::string& path, 271 const base::Value* new_value) { 272 outer_->RecordStoreHash(path, new_value, 273 PrefHashFilter::TRACKING_STRATEGY_ATOMIC); 274 } 275 276 PrefHashStoreTransaction::ValueState 277 MockPrefHashStore::MockPrefHashStoreTransaction::CheckSplitValue( 278 const std::string& path, 279 const base::DictionaryValue* initial_split_value, 280 std::vector<std::string>* invalid_keys) const { 281 EXPECT_TRUE(invalid_keys && invalid_keys->empty()); 282 283 std::map<std::string, std::vector<std::string> >::const_iterator 284 invalid_keys_result = outer_->invalid_keys_results_.find(path); 285 if (invalid_keys_result != outer_->invalid_keys_results_.end()) { 286 invalid_keys->insert(invalid_keys->begin(), 287 invalid_keys_result->second.begin(), 288 invalid_keys_result->second.end()); 289 } 290 291 return outer_->RecordCheckValue(path, initial_split_value, 292 PrefHashFilter::TRACKING_STRATEGY_SPLIT); 293 } 294 295 void MockPrefHashStore::MockPrefHashStoreTransaction::StoreSplitHash( 296 const std::string& path, 297 const base::DictionaryValue* new_value) { 298 outer_->RecordStoreHash(path, new_value, 299 PrefHashFilter::TRACKING_STRATEGY_SPLIT); 300 } 301 302 bool MockPrefHashStore::MockPrefHashStoreTransaction::HasHash( 303 const std::string& path) const { 304 ADD_FAILURE() << "Unexpected call."; 305 return false; 306 } 307 308 void MockPrefHashStore::MockPrefHashStoreTransaction::ImportHash( 309 const std::string& path, 310 const base::Value* hash) { 311 ADD_FAILURE() << "Unexpected call."; 312 } 313 314 void MockPrefHashStore::MockPrefHashStoreTransaction::ClearHash( 315 const std::string& path) { 316 ADD_FAILURE() << "Unexpected call."; 317 } 318 319 bool MockPrefHashStore::MockPrefHashStoreTransaction::IsSuperMACValid() const { 320 // TODO(erikwright): Test that the result of this method is reported to 321 // Settings.HashesDictionaryTrusted. 322 return false; 323 } 324 325 bool MockPrefHashStore::MockPrefHashStoreTransaction::StampSuperMac() { 326 // TODO(erikwright): Test that, when there are no other changes to the store, 327 // the result of this method determines the value of |prefs_altered| in the 328 // |post_filter_on_load_callback| invocation. 329 return false; 330 } 331 332 std::vector<PrefHashFilter::TrackedPreferenceMetadata> GetConfiguration( 333 PrefHashFilter::EnforcementLevel max_enforcement_level) { 334 std::vector<PrefHashFilter::TrackedPreferenceMetadata> configuration( 335 kTestTrackedPrefs, kTestTrackedPrefs + arraysize(kTestTrackedPrefs)); 336 for (std::vector<PrefHashFilter::TrackedPreferenceMetadata>::iterator it = 337 configuration.begin(); 338 it != configuration.end(); 339 ++it) { 340 if (it->enforcement_level > max_enforcement_level) 341 it->enforcement_level = max_enforcement_level; 342 } 343 return configuration; 344 } 345 346 class PrefHashFilterTest 347 : public testing::TestWithParam<PrefHashFilter::EnforcementLevel> { 348 public: 349 PrefHashFilterTest() : mock_pref_hash_store_(NULL), 350 pref_store_contents_(new base::DictionaryValue), 351 last_filter_on_load_modified_prefs_(false), 352 reset_recorded_(false) {} 353 354 virtual void SetUp() OVERRIDE { 355 // Construct a PrefHashFilter and MockPrefHashStore for the test. 356 InitializePrefHashFilter(GetConfiguration(GetParam())); 357 } 358 359 protected: 360 // Initializes |pref_hash_filter_| with a PrefHashFilter that uses a 361 // MockPrefHashStore. The raw pointer to the MockPrefHashStore (owned by the 362 // PrefHashFilter) is stored in |mock_pref_hash_store_|. 363 void InitializePrefHashFilter(const std::vector< 364 PrefHashFilter::TrackedPreferenceMetadata>& configuration) { 365 scoped_ptr<MockPrefHashStore> temp_mock_pref_hash_store( 366 new MockPrefHashStore); 367 mock_pref_hash_store_ = temp_mock_pref_hash_store.get(); 368 pref_hash_filter_.reset(new PrefHashFilter( 369 temp_mock_pref_hash_store.PassAs<PrefHashStore>(), 370 configuration, 371 base::Bind(&PrefHashFilterTest::RecordReset, base::Unretained(this)), 372 &mock_validation_delegate_, 373 arraysize(kTestTrackedPrefs), 374 true)); 375 } 376 377 // Verifies whether a reset was reported by the PrefHashFiler. Also verifies 378 // that kPreferenceResetTime was set (or not) accordingly. 379 void VerifyRecordedReset(bool reset_expected) { 380 EXPECT_EQ(reset_expected, reset_recorded_); 381 EXPECT_EQ(reset_expected, 382 pref_store_contents_->Get(prefs::kPreferenceResetTime, NULL)); 383 } 384 385 // Calls FilterOnLoad() on |pref_hash_Filter_|. |pref_store_contents_| is 386 // handed off, but should be given back to us synchronously through 387 // GetPrefsBack() as there is no FilterOnLoadInterceptor installed on 388 // |pref_hash_filter_|. 389 void DoFilterOnLoad(bool expect_prefs_modifications) { 390 pref_hash_filter_->FilterOnLoad( 391 base::Bind(&PrefHashFilterTest::GetPrefsBack, base::Unretained(this), 392 expect_prefs_modifications), 393 pref_store_contents_.Pass()); 394 } 395 396 MockPrefHashStore* mock_pref_hash_store_; 397 scoped_ptr<base::DictionaryValue> pref_store_contents_; 398 bool last_filter_on_load_modified_prefs_; 399 MockValidationDelegate mock_validation_delegate_; 400 scoped_ptr<PrefHashFilter> pref_hash_filter_; 401 402 private: 403 // Stores |prefs| back in |pref_store_contents| and ensure 404 // |expected_schedule_write| matches the reported |schedule_write|. 405 void GetPrefsBack(bool expected_schedule_write, 406 scoped_ptr<base::DictionaryValue> prefs, 407 bool schedule_write) { 408 pref_store_contents_ = prefs.Pass(); 409 EXPECT_TRUE(pref_store_contents_); 410 EXPECT_EQ(expected_schedule_write, schedule_write); 411 } 412 413 void RecordReset() { 414 // As-is |reset_recorded_| is only designed to remember a single reset, make 415 // sure none was previously recorded. 416 EXPECT_FALSE(reset_recorded_); 417 reset_recorded_ = true; 418 } 419 420 bool reset_recorded_; 421 422 DISALLOW_COPY_AND_ASSIGN(PrefHashFilterTest); 423 }; 424 425 TEST_P(PrefHashFilterTest, EmptyAndUnchanged) { 426 DoFilterOnLoad(false); 427 // All paths checked. 428 ASSERT_EQ(arraysize(kTestTrackedPrefs), 429 mock_pref_hash_store_->checked_paths_count()); 430 // No paths stored, since they all return |UNCHANGED|. 431 ASSERT_EQ(0u, mock_pref_hash_store_->stored_paths_count()); 432 // Since there was nothing in |pref_store_contents_| the checked value should 433 // have been NULL for all tracked preferences. 434 for (size_t i = 0; i < arraysize(kTestTrackedPrefs); ++i) { 435 ASSERT_EQ(NULL, mock_pref_hash_store_->checked_value( 436 kTestTrackedPrefs[i].name).first); 437 } 438 ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed()); 439 VerifyRecordedReset(false); 440 441 // Delegate saw all paths, and all unchanged. 442 ASSERT_EQ(arraysize(kTestTrackedPrefs), 443 mock_validation_delegate_.recorded_validations_count()); 444 ASSERT_EQ(arraysize(kTestTrackedPrefs), 445 mock_validation_delegate_.CountValidationsOfState( 446 PrefHashStoreTransaction::UNCHANGED)); 447 } 448 449 TEST_P(PrefHashFilterTest, FilterTrackedPrefUpdate) { 450 base::DictionaryValue root_dict; 451 // Ownership of |string_value| is transfered to |root_dict|. 452 base::Value* string_value = base::Value::CreateStringValue("string value"); 453 root_dict.Set(kAtomicPref, string_value); 454 455 // No path should be stored on FilterUpdate. 456 pref_hash_filter_->FilterUpdate(kAtomicPref); 457 ASSERT_EQ(0u, mock_pref_hash_store_->stored_paths_count()); 458 459 // One path should be stored on FilterSerializeData. 460 pref_hash_filter_->FilterSerializeData(&root_dict); 461 ASSERT_EQ(1u, mock_pref_hash_store_->stored_paths_count()); 462 MockPrefHashStore::ValuePtrStrategyPair stored_value = 463 mock_pref_hash_store_->stored_value(kAtomicPref); 464 ASSERT_EQ(string_value, stored_value.first); 465 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC, stored_value.second); 466 467 ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed()); 468 VerifyRecordedReset(false); 469 } 470 471 TEST_P(PrefHashFilterTest, FilterSplitPrefUpdate) { 472 base::DictionaryValue root_dict; 473 // Ownership of |dict_value| is transfered to |root_dict|. 474 base::DictionaryValue* dict_value = new base::DictionaryValue; 475 dict_value->SetString("a", "foo"); 476 dict_value->SetInteger("b", 1234); 477 root_dict.Set(kSplitPref, dict_value); 478 479 // No path should be stored on FilterUpdate. 480 pref_hash_filter_->FilterUpdate(kSplitPref); 481 ASSERT_EQ(0u, mock_pref_hash_store_->stored_paths_count()); 482 483 // One path should be stored on FilterSerializeData. 484 pref_hash_filter_->FilterSerializeData(&root_dict); 485 ASSERT_EQ(1u, mock_pref_hash_store_->stored_paths_count()); 486 MockPrefHashStore::ValuePtrStrategyPair stored_value = 487 mock_pref_hash_store_->stored_value(kSplitPref); 488 ASSERT_EQ(dict_value, stored_value.first); 489 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT, stored_value.second); 490 491 ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed()); 492 VerifyRecordedReset(false); 493 } 494 495 TEST_P(PrefHashFilterTest, FilterUntrackedPrefUpdate) { 496 base::DictionaryValue root_dict; 497 root_dict.Set("untracked", base::Value::CreateStringValue("some value")); 498 pref_hash_filter_->FilterUpdate("untracked"); 499 500 // No paths should be stored on FilterUpdate. 501 ASSERT_EQ(0u, mock_pref_hash_store_->stored_paths_count()); 502 503 // Nor on FilterSerializeData. 504 pref_hash_filter_->FilterSerializeData(&root_dict); 505 ASSERT_EQ(0u, mock_pref_hash_store_->stored_paths_count()); 506 507 // No transaction should even be started on FilterSerializeData() if there are 508 // no updates to perform. 509 ASSERT_EQ(0u, mock_pref_hash_store_->transactions_performed()); 510 } 511 512 TEST_P(PrefHashFilterTest, MultiplePrefsFilterSerializeData) { 513 base::DictionaryValue root_dict; 514 // Ownership of the following values is transfered to |root_dict|. 515 base::Value* int_value1 = base::Value::CreateIntegerValue(1); 516 base::Value* int_value2 = base::Value::CreateIntegerValue(2); 517 base::Value* int_value3 = base::Value::CreateIntegerValue(3); 518 base::Value* int_value4 = base::Value::CreateIntegerValue(4); 519 base::DictionaryValue* dict_value = new base::DictionaryValue; 520 dict_value->Set("a", base::Value::CreateBooleanValue(true)); 521 root_dict.Set(kAtomicPref, int_value1); 522 root_dict.Set(kAtomicPref2, int_value2); 523 root_dict.Set(kAtomicPref3, int_value3); 524 root_dict.Set("untracked", int_value4); 525 root_dict.Set(kSplitPref, dict_value); 526 527 // Only update kAtomicPref, kAtomicPref3, and kSplitPref. 528 pref_hash_filter_->FilterUpdate(kAtomicPref); 529 pref_hash_filter_->FilterUpdate(kAtomicPref3); 530 pref_hash_filter_->FilterUpdate(kSplitPref); 531 ASSERT_EQ(0u, mock_pref_hash_store_->stored_paths_count()); 532 533 // Update kAtomicPref3 again, nothing should be stored still. 534 base::Value* int_value5 = base::Value::CreateIntegerValue(5); 535 root_dict.Set(kAtomicPref3, int_value5); 536 ASSERT_EQ(0u, mock_pref_hash_store_->stored_paths_count()); 537 538 // On FilterSerializeData, only kAtomicPref, kAtomicPref3, and kSplitPref 539 // should get a new hash. 540 pref_hash_filter_->FilterSerializeData(&root_dict); 541 ASSERT_EQ(3u, mock_pref_hash_store_->stored_paths_count()); 542 MockPrefHashStore::ValuePtrStrategyPair stored_value_atomic1 = 543 mock_pref_hash_store_->stored_value(kAtomicPref); 544 ASSERT_EQ(int_value1, stored_value_atomic1.first); 545 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC, 546 stored_value_atomic1.second); 547 ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed()); 548 549 MockPrefHashStore::ValuePtrStrategyPair stored_value_atomic3 = 550 mock_pref_hash_store_->stored_value(kAtomicPref3); 551 ASSERT_EQ(int_value5, stored_value_atomic3.first); 552 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC, 553 stored_value_atomic3.second); 554 555 MockPrefHashStore::ValuePtrStrategyPair stored_value_split = 556 mock_pref_hash_store_->stored_value(kSplitPref); 557 ASSERT_EQ(dict_value, stored_value_split.first); 558 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT, stored_value_split.second); 559 } 560 561 TEST_P(PrefHashFilterTest, EmptyAndUnknown) { 562 ASSERT_FALSE(pref_store_contents_->Get(kAtomicPref, NULL)); 563 ASSERT_FALSE(pref_store_contents_->Get(kSplitPref, NULL)); 564 // NULL values are always trusted by the PrefHashStore. 565 mock_pref_hash_store_->SetCheckResult( 566 kAtomicPref, PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE); 567 mock_pref_hash_store_->SetCheckResult( 568 kSplitPref, PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE); 569 DoFilterOnLoad(false); 570 ASSERT_EQ(arraysize(kTestTrackedPrefs), 571 mock_pref_hash_store_->checked_paths_count()); 572 ASSERT_EQ(2u, mock_pref_hash_store_->stored_paths_count()); 573 ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed()); 574 575 MockPrefHashStore::ValuePtrStrategyPair stored_atomic_value = 576 mock_pref_hash_store_->stored_value(kAtomicPref); 577 ASSERT_EQ(NULL, stored_atomic_value.first); 578 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC, 579 stored_atomic_value.second); 580 581 MockPrefHashStore::ValuePtrStrategyPair stored_split_value = 582 mock_pref_hash_store_->stored_value(kSplitPref); 583 ASSERT_EQ(NULL, stored_split_value.first); 584 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT, 585 stored_split_value.second); 586 587 // Delegate saw all prefs, two of which had the expected value_state. 588 ASSERT_EQ(arraysize(kTestTrackedPrefs), 589 mock_validation_delegate_.recorded_validations_count()); 590 ASSERT_EQ(2u, 591 mock_validation_delegate_.CountValidationsOfState( 592 PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE)); 593 ASSERT_EQ(arraysize(kTestTrackedPrefs) - 2u, 594 mock_validation_delegate_.CountValidationsOfState( 595 PrefHashStoreTransaction::UNCHANGED)); 596 597 const MockValidationDelegate::ValidationEvent* validated_split_pref = 598 mock_validation_delegate_.GetEventForPath(kSplitPref); 599 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT, 600 validated_split_pref->strategy); 601 EXPECT_EQ(TrackedPreferenceHelper::DONT_RESET, 602 validated_split_pref->reset_action); 603 const MockValidationDelegate::ValidationEvent* validated_atomic_pref = 604 mock_validation_delegate_.GetEventForPath(kAtomicPref); 605 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC, 606 validated_atomic_pref->strategy); 607 EXPECT_EQ(TrackedPreferenceHelper::DONT_RESET, 608 validated_atomic_pref->reset_action); 609 } 610 611 TEST_P(PrefHashFilterTest, InitialValueUnknown) { 612 // Ownership of these values is transfered to |pref_store_contents_|. 613 base::StringValue* string_value = new base::StringValue("string value"); 614 pref_store_contents_->Set(kAtomicPref, string_value); 615 616 base::DictionaryValue* dict_value = new base::DictionaryValue; 617 dict_value->SetString("a", "foo"); 618 dict_value->SetInteger("b", 1234); 619 pref_store_contents_->Set(kSplitPref, dict_value); 620 621 ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, NULL)); 622 ASSERT_TRUE(pref_store_contents_->Get(kSplitPref, NULL)); 623 624 mock_pref_hash_store_->SetCheckResult( 625 kAtomicPref, PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE); 626 mock_pref_hash_store_->SetCheckResult( 627 kSplitPref, PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE); 628 // If we are enforcing, expect this to report changes. 629 DoFilterOnLoad(GetParam() >= PrefHashFilter::ENFORCE_ON_LOAD); 630 ASSERT_EQ(arraysize(kTestTrackedPrefs), 631 mock_pref_hash_store_->checked_paths_count()); 632 ASSERT_EQ(2u, mock_pref_hash_store_->stored_paths_count()); 633 ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed()); 634 635 // Delegate saw all prefs, two of which had the expected value_state. 636 ASSERT_EQ(arraysize(kTestTrackedPrefs), 637 mock_validation_delegate_.recorded_validations_count()); 638 ASSERT_EQ(2u, 639 mock_validation_delegate_.CountValidationsOfState( 640 PrefHashStoreTransaction::UNTRUSTED_UNKNOWN_VALUE)); 641 ASSERT_EQ(arraysize(kTestTrackedPrefs) - 2u, 642 mock_validation_delegate_.CountValidationsOfState( 643 PrefHashStoreTransaction::UNCHANGED)); 644 645 MockPrefHashStore::ValuePtrStrategyPair stored_atomic_value = 646 mock_pref_hash_store_->stored_value(kAtomicPref); 647 MockPrefHashStore::ValuePtrStrategyPair stored_split_value = 648 mock_pref_hash_store_->stored_value(kSplitPref); 649 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC, 650 stored_atomic_value.second); 651 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT, 652 stored_split_value.second); 653 if (GetParam() == PrefHashFilter::ENFORCE_ON_LOAD) { 654 // Ensure the prefs were cleared and the hashes for NULL were restored if 655 // the current enforcement level denies seeding. 656 ASSERT_FALSE(pref_store_contents_->Get(kAtomicPref, NULL)); 657 ASSERT_EQ(NULL, stored_atomic_value.first); 658 659 ASSERT_FALSE(pref_store_contents_->Get(kSplitPref, NULL)); 660 ASSERT_EQ(NULL, stored_split_value.first); 661 662 VerifyRecordedReset(true); 663 } else { 664 // Otherwise the values should have remained intact and the hashes should 665 // have been updated to match them. 666 const base::Value* atomic_value_in_store; 667 ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, &atomic_value_in_store)); 668 ASSERT_EQ(string_value, atomic_value_in_store); 669 ASSERT_EQ(string_value, stored_atomic_value.first); 670 671 const base::Value* split_value_in_store; 672 ASSERT_TRUE(pref_store_contents_->Get(kSplitPref, &split_value_in_store)); 673 ASSERT_EQ(dict_value, split_value_in_store); 674 ASSERT_EQ(dict_value, stored_split_value.first); 675 676 VerifyRecordedReset(false); 677 } 678 } 679 680 TEST_P(PrefHashFilterTest, InitialValueTrustedUnknown) { 681 // Ownership of this value is transfered to |pref_store_contents_|. 682 base::Value* string_value = base::Value::CreateStringValue("test"); 683 pref_store_contents_->Set(kAtomicPref, string_value); 684 685 base::DictionaryValue* dict_value = new base::DictionaryValue; 686 dict_value->SetString("a", "foo"); 687 dict_value->SetInteger("b", 1234); 688 pref_store_contents_->Set(kSplitPref, dict_value); 689 690 ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, NULL)); 691 ASSERT_TRUE(pref_store_contents_->Get(kSplitPref, NULL)); 692 693 mock_pref_hash_store_->SetCheckResult( 694 kAtomicPref, PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE); 695 mock_pref_hash_store_->SetCheckResult( 696 kSplitPref, PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE); 697 DoFilterOnLoad(false); 698 ASSERT_EQ(arraysize(kTestTrackedPrefs), 699 mock_pref_hash_store_->checked_paths_count()); 700 ASSERT_EQ(2u, mock_pref_hash_store_->stored_paths_count()); 701 ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed()); 702 703 // Delegate saw all prefs, two of which had the expected value_state. 704 ASSERT_EQ(arraysize(kTestTrackedPrefs), 705 mock_validation_delegate_.recorded_validations_count()); 706 ASSERT_EQ(2u, 707 mock_validation_delegate_.CountValidationsOfState( 708 PrefHashStoreTransaction::TRUSTED_UNKNOWN_VALUE)); 709 ASSERT_EQ(arraysize(kTestTrackedPrefs) - 2u, 710 mock_validation_delegate_.CountValidationsOfState( 711 PrefHashStoreTransaction::UNCHANGED)); 712 713 // Seeding is always allowed for trusted unknown values. 714 const base::Value* atomic_value_in_store; 715 ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, &atomic_value_in_store)); 716 ASSERT_EQ(string_value, atomic_value_in_store); 717 MockPrefHashStore::ValuePtrStrategyPair stored_atomic_value = 718 mock_pref_hash_store_->stored_value(kAtomicPref); 719 ASSERT_EQ(string_value, stored_atomic_value.first); 720 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC, 721 stored_atomic_value.second); 722 723 const base::Value* split_value_in_store; 724 ASSERT_TRUE(pref_store_contents_->Get(kSplitPref, &split_value_in_store)); 725 ASSERT_EQ(dict_value, split_value_in_store); 726 MockPrefHashStore::ValuePtrStrategyPair stored_split_value = 727 mock_pref_hash_store_->stored_value(kSplitPref); 728 ASSERT_EQ(dict_value, stored_split_value.first); 729 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT, 730 stored_split_value.second); 731 } 732 733 TEST_P(PrefHashFilterTest, InitialValueChanged) { 734 // Ownership of this value is transfered to |pref_store_contents_|. 735 base::Value* int_value = base::Value::CreateIntegerValue(1234); 736 pref_store_contents_->Set(kAtomicPref, int_value); 737 738 base::DictionaryValue* dict_value = new base::DictionaryValue; 739 dict_value->SetString("a", "foo"); 740 dict_value->SetInteger("b", 1234); 741 dict_value->SetInteger("c", 56); 742 dict_value->SetBoolean("d", false); 743 pref_store_contents_->Set(kSplitPref, dict_value); 744 745 ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, NULL)); 746 ASSERT_TRUE(pref_store_contents_->Get(kSplitPref, NULL)); 747 748 mock_pref_hash_store_->SetCheckResult(kAtomicPref, 749 PrefHashStoreTransaction::CHANGED); 750 mock_pref_hash_store_->SetCheckResult(kSplitPref, 751 PrefHashStoreTransaction::CHANGED); 752 753 std::vector<std::string> mock_invalid_keys; 754 mock_invalid_keys.push_back("a"); 755 mock_invalid_keys.push_back("c"); 756 mock_pref_hash_store_->SetInvalidKeysResult(kSplitPref, mock_invalid_keys); 757 758 DoFilterOnLoad(GetParam() >= PrefHashFilter::ENFORCE_ON_LOAD); 759 ASSERT_EQ(arraysize(kTestTrackedPrefs), 760 mock_pref_hash_store_->checked_paths_count()); 761 ASSERT_EQ(2u, mock_pref_hash_store_->stored_paths_count()); 762 ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed()); 763 764 MockPrefHashStore::ValuePtrStrategyPair stored_atomic_value = 765 mock_pref_hash_store_->stored_value(kAtomicPref); 766 MockPrefHashStore::ValuePtrStrategyPair stored_split_value = 767 mock_pref_hash_store_->stored_value(kSplitPref); 768 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC, 769 stored_atomic_value.second); 770 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT, 771 stored_split_value.second); 772 if (GetParam() == PrefHashFilter::ENFORCE_ON_LOAD) { 773 // Ensure the atomic pref was cleared and the hash for NULL was restored if 774 // the current enforcement level prevents changes. 775 ASSERT_FALSE(pref_store_contents_->Get(kAtomicPref, NULL)); 776 ASSERT_EQ(NULL, stored_atomic_value.first); 777 778 // The split pref on the other hand should only have been stripped of its 779 // invalid keys. 780 const base::Value* split_value_in_store; 781 ASSERT_TRUE(pref_store_contents_->Get(kSplitPref, &split_value_in_store)); 782 ASSERT_EQ(2U, dict_value->size()); 783 ASSERT_FALSE(dict_value->HasKey("a")); 784 ASSERT_TRUE(dict_value->HasKey("b")); 785 ASSERT_FALSE(dict_value->HasKey("c")); 786 ASSERT_TRUE(dict_value->HasKey("d")); 787 ASSERT_EQ(dict_value, stored_split_value.first); 788 789 VerifyRecordedReset(true); 790 } else { 791 // Otherwise the value should have remained intact and the hash should have 792 // been updated to match it. 793 const base::Value* atomic_value_in_store; 794 ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, &atomic_value_in_store)); 795 ASSERT_EQ(int_value, atomic_value_in_store); 796 ASSERT_EQ(int_value, stored_atomic_value.first); 797 798 const base::Value* split_value_in_store; 799 ASSERT_TRUE(pref_store_contents_->Get(kSplitPref, &split_value_in_store)); 800 ASSERT_EQ(dict_value, split_value_in_store); 801 ASSERT_EQ(4U, dict_value->size()); 802 ASSERT_TRUE(dict_value->HasKey("a")); 803 ASSERT_TRUE(dict_value->HasKey("b")); 804 ASSERT_TRUE(dict_value->HasKey("c")); 805 ASSERT_TRUE(dict_value->HasKey("d")); 806 ASSERT_EQ(dict_value, stored_split_value.first); 807 808 VerifyRecordedReset(false); 809 } 810 } 811 812 TEST_P(PrefHashFilterTest, EmptyCleared) { 813 ASSERT_FALSE(pref_store_contents_->Get(kAtomicPref, NULL)); 814 ASSERT_FALSE(pref_store_contents_->Get(kSplitPref, NULL)); 815 mock_pref_hash_store_->SetCheckResult(kAtomicPref, 816 PrefHashStoreTransaction::CLEARED); 817 mock_pref_hash_store_->SetCheckResult(kSplitPref, 818 PrefHashStoreTransaction::CLEARED); 819 DoFilterOnLoad(false); 820 ASSERT_EQ(arraysize(kTestTrackedPrefs), 821 mock_pref_hash_store_->checked_paths_count()); 822 ASSERT_EQ(2u, mock_pref_hash_store_->stored_paths_count()); 823 ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed()); 824 825 // Delegate saw all prefs, two of which had the expected value_state. 826 ASSERT_EQ(arraysize(kTestTrackedPrefs), 827 mock_validation_delegate_.recorded_validations_count()); 828 ASSERT_EQ(2u, 829 mock_validation_delegate_.CountValidationsOfState( 830 PrefHashStoreTransaction::CLEARED)); 831 ASSERT_EQ(arraysize(kTestTrackedPrefs) - 2u, 832 mock_validation_delegate_.CountValidationsOfState( 833 PrefHashStoreTransaction::UNCHANGED)); 834 835 // Regardless of the enforcement level, the only thing that should be done is 836 // to restore the hash for NULL. The value itself should still be NULL. 837 ASSERT_FALSE(pref_store_contents_->Get(kAtomicPref, NULL)); 838 MockPrefHashStore::ValuePtrStrategyPair stored_atomic_value = 839 mock_pref_hash_store_->stored_value(kAtomicPref); 840 ASSERT_EQ(NULL, stored_atomic_value.first); 841 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC, 842 stored_atomic_value.second); 843 844 ASSERT_FALSE(pref_store_contents_->Get(kSplitPref, NULL)); 845 MockPrefHashStore::ValuePtrStrategyPair stored_split_value = 846 mock_pref_hash_store_->stored_value(kSplitPref); 847 ASSERT_EQ(NULL, stored_split_value.first); 848 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT, 849 stored_split_value.second); 850 } 851 852 TEST_P(PrefHashFilterTest, InitialValueMigrated) { 853 // Only test atomic prefs, split prefs were introduce after the migration. 854 855 // Ownership of this value is transfered to |pref_store_contents_|. 856 base::ListValue* list_value = new base::ListValue; 857 list_value->Append(base::Value::CreateStringValue("test")); 858 pref_store_contents_->Set(kAtomicPref, list_value); 859 860 ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, NULL)); 861 862 mock_pref_hash_store_->SetCheckResult(kAtomicPref, 863 PrefHashStoreTransaction::WEAK_LEGACY); 864 865 DoFilterOnLoad(GetParam() >= PrefHashFilter::ENFORCE_ON_LOAD); 866 ASSERT_EQ(arraysize(kTestTrackedPrefs), 867 mock_pref_hash_store_->checked_paths_count()); 868 ASSERT_EQ(1u, mock_pref_hash_store_->stored_paths_count()); 869 ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed()); 870 871 // Delegate saw all prefs, one of which had the expected value_state. 872 ASSERT_EQ(arraysize(kTestTrackedPrefs), 873 mock_validation_delegate_.recorded_validations_count()); 874 ASSERT_EQ(1u, 875 mock_validation_delegate_.CountValidationsOfState( 876 PrefHashStoreTransaction::WEAK_LEGACY)); 877 ASSERT_EQ(arraysize(kTestTrackedPrefs) - 1u, 878 mock_validation_delegate_.CountValidationsOfState( 879 PrefHashStoreTransaction::UNCHANGED)); 880 881 MockPrefHashStore::ValuePtrStrategyPair stored_atomic_value = 882 mock_pref_hash_store_->stored_value(kAtomicPref); 883 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC, 884 stored_atomic_value.second); 885 if (GetParam() == PrefHashFilter::ENFORCE_ON_LOAD) { 886 // Ensure the pref was cleared and the hash for NULL was restored if the 887 // current enforcement level prevents migration. 888 ASSERT_FALSE(pref_store_contents_->Get(kAtomicPref, NULL)); 889 ASSERT_EQ(NULL, stored_atomic_value.first); 890 891 VerifyRecordedReset(true); 892 } else { 893 // Otherwise the value should have remained intact and the hash should have 894 // been updated to match it. 895 const base::Value* atomic_value_in_store; 896 ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, &atomic_value_in_store)); 897 ASSERT_EQ(list_value, atomic_value_in_store); 898 ASSERT_EQ(list_value, stored_atomic_value.first); 899 900 VerifyRecordedReset(false); 901 } 902 } 903 904 TEST_P(PrefHashFilterTest, InitialValueUnchangedLegacyId) { 905 // Ownership of these values is transfered to |pref_store_contents_|. 906 base::StringValue* string_value = new base::StringValue("string value"); 907 pref_store_contents_->Set(kAtomicPref, string_value); 908 909 base::DictionaryValue* dict_value = new base::DictionaryValue; 910 dict_value->SetString("a", "foo"); 911 dict_value->SetInteger("b", 1234); 912 pref_store_contents_->Set(kSplitPref, dict_value); 913 914 ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, NULL)); 915 ASSERT_TRUE(pref_store_contents_->Get(kSplitPref, NULL)); 916 917 mock_pref_hash_store_->SetCheckResult( 918 kAtomicPref, PrefHashStoreTransaction::SECURE_LEGACY); 919 mock_pref_hash_store_->SetCheckResult( 920 kSplitPref, PrefHashStoreTransaction::SECURE_LEGACY); 921 DoFilterOnLoad(false); 922 ASSERT_EQ(arraysize(kTestTrackedPrefs), 923 mock_pref_hash_store_->checked_paths_count()); 924 ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed()); 925 926 // Delegate saw all prefs, two of which had the expected value_state. 927 ASSERT_EQ(arraysize(kTestTrackedPrefs), 928 mock_validation_delegate_.recorded_validations_count()); 929 ASSERT_EQ(2u, 930 mock_validation_delegate_.CountValidationsOfState( 931 PrefHashStoreTransaction::SECURE_LEGACY)); 932 ASSERT_EQ(arraysize(kTestTrackedPrefs) - 2u, 933 mock_validation_delegate_.CountValidationsOfState( 934 PrefHashStoreTransaction::UNCHANGED)); 935 936 // Ensure that both the atomic and split hashes were restored. 937 ASSERT_EQ(2u, mock_pref_hash_store_->stored_paths_count()); 938 939 // In all cases, the values should have remained intact and the hashes should 940 // have been updated to match them. 941 942 MockPrefHashStore::ValuePtrStrategyPair stored_atomic_value = 943 mock_pref_hash_store_->stored_value(kAtomicPref); 944 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_ATOMIC, 945 stored_atomic_value.second); 946 const base::Value* atomic_value_in_store; 947 ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, &atomic_value_in_store)); 948 ASSERT_EQ(string_value, atomic_value_in_store); 949 ASSERT_EQ(string_value, stored_atomic_value.first); 950 951 MockPrefHashStore::ValuePtrStrategyPair stored_split_value = 952 mock_pref_hash_store_->stored_value(kSplitPref); 953 ASSERT_EQ(PrefHashFilter::TRACKING_STRATEGY_SPLIT, 954 stored_split_value.second); 955 const base::Value* split_value_in_store; 956 ASSERT_TRUE(pref_store_contents_->Get(kSplitPref, &split_value_in_store)); 957 ASSERT_EQ(dict_value, split_value_in_store); 958 ASSERT_EQ(dict_value, stored_split_value.first); 959 960 VerifyRecordedReset(false); 961 } 962 963 TEST_P(PrefHashFilterTest, DontResetReportOnly) { 964 // Ownership of these values is transfered to |pref_store_contents_|. 965 base::Value* int_value1 = base::Value::CreateIntegerValue(1); 966 base::Value* int_value2 = base::Value::CreateIntegerValue(2); 967 base::Value* report_only_val = base::Value::CreateIntegerValue(3); 968 base::DictionaryValue* report_only_split_val = new base::DictionaryValue; 969 report_only_split_val->SetInteger("a", 1234); 970 pref_store_contents_->Set(kAtomicPref, int_value1); 971 pref_store_contents_->Set(kAtomicPref2, int_value2); 972 pref_store_contents_->Set(kReportOnlyPref, report_only_val); 973 pref_store_contents_->Set(kReportOnlySplitPref, report_only_split_val); 974 975 ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, NULL)); 976 ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref2, NULL)); 977 ASSERT_TRUE(pref_store_contents_->Get(kReportOnlyPref, NULL)); 978 ASSERT_TRUE(pref_store_contents_->Get(kReportOnlySplitPref, NULL)); 979 980 mock_pref_hash_store_->SetCheckResult(kAtomicPref, 981 PrefHashStoreTransaction::CHANGED); 982 mock_pref_hash_store_->SetCheckResult(kAtomicPref2, 983 PrefHashStoreTransaction::CHANGED); 984 mock_pref_hash_store_->SetCheckResult(kReportOnlyPref, 985 PrefHashStoreTransaction::CHANGED); 986 mock_pref_hash_store_->SetCheckResult(kReportOnlySplitPref, 987 PrefHashStoreTransaction::CHANGED); 988 989 DoFilterOnLoad(GetParam() >= PrefHashFilter::ENFORCE_ON_LOAD); 990 // All prefs should be checked and a new hash should be stored for each tested 991 // pref. 992 ASSERT_EQ(arraysize(kTestTrackedPrefs), 993 mock_pref_hash_store_->checked_paths_count()); 994 ASSERT_EQ(4u, mock_pref_hash_store_->stored_paths_count()); 995 ASSERT_EQ(1u, mock_pref_hash_store_->transactions_performed()); 996 997 // Delegate saw all prefs, four of which had the expected value_state. 998 ASSERT_EQ(arraysize(kTestTrackedPrefs), 999 mock_validation_delegate_.recorded_validations_count()); 1000 ASSERT_EQ(4u, 1001 mock_validation_delegate_.CountValidationsOfState( 1002 PrefHashStoreTransaction::CHANGED)); 1003 ASSERT_EQ(arraysize(kTestTrackedPrefs) - 4u, 1004 mock_validation_delegate_.CountValidationsOfState( 1005 PrefHashStoreTransaction::UNCHANGED)); 1006 1007 // No matter what the enforcement level is, the report only pref should never 1008 // be reset. 1009 ASSERT_TRUE(pref_store_contents_->Get(kReportOnlyPref, NULL)); 1010 ASSERT_TRUE(pref_store_contents_->Get(kReportOnlySplitPref, NULL)); 1011 ASSERT_EQ(report_only_val, 1012 mock_pref_hash_store_->stored_value(kReportOnlyPref).first); 1013 ASSERT_EQ(report_only_split_val, 1014 mock_pref_hash_store_->stored_value(kReportOnlySplitPref).first); 1015 1016 // All other prefs should have been reset if the enforcement level allows it. 1017 if (GetParam() == PrefHashFilter::ENFORCE_ON_LOAD) { 1018 ASSERT_FALSE(pref_store_contents_->Get(kAtomicPref, NULL)); 1019 ASSERT_FALSE(pref_store_contents_->Get(kAtomicPref2, NULL)); 1020 ASSERT_EQ(NULL, mock_pref_hash_store_->stored_value(kAtomicPref).first); 1021 ASSERT_EQ(NULL, mock_pref_hash_store_->stored_value(kAtomicPref2).first); 1022 1023 VerifyRecordedReset(true); 1024 } else { 1025 const base::Value* value_in_store; 1026 const base::Value* value_in_store2; 1027 ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref, &value_in_store)); 1028 ASSERT_TRUE(pref_store_contents_->Get(kAtomicPref2, &value_in_store2)); 1029 ASSERT_EQ(int_value1, value_in_store); 1030 ASSERT_EQ(int_value1, 1031 mock_pref_hash_store_->stored_value(kAtomicPref).first); 1032 ASSERT_EQ(int_value2, value_in_store2); 1033 ASSERT_EQ(int_value2, 1034 mock_pref_hash_store_->stored_value(kAtomicPref2).first); 1035 1036 VerifyRecordedReset(false); 1037 } 1038 } 1039 1040 INSTANTIATE_TEST_CASE_P( 1041 PrefHashFilterTestInstance, PrefHashFilterTest, 1042 testing::Values(PrefHashFilter::NO_ENFORCEMENT, 1043 PrefHashFilter::ENFORCE_ON_LOAD)); 1044