| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "net/sdch/sdch_owner.h" | 5 #include "net/sdch/sdch_owner.h" |
| 6 | 6 |
| 7 #include <utility> | 7 #include <utility> |
| 8 | 8 |
| 9 #include "base/location.h" | 9 #include "base/location.h" |
| 10 #include "base/macros.h" | 10 #include "base/macros.h" |
| 11 #include "base/memory/memory_pressure_listener.h" | 11 #include "base/memory/memory_pressure_listener.h" |
| 12 #include "base/prefs/testing_pref_store.h" | |
| 13 #include "base/run_loop.h" | 12 #include "base/run_loop.h" |
| 14 #include "base/single_thread_task_runner.h" | 13 #include "base/single_thread_task_runner.h" |
| 15 #include "base/strings/stringprintf.h" | 14 #include "base/strings/stringprintf.h" |
| 16 #include "base/test/histogram_tester.h" | 15 #include "base/test/histogram_tester.h" |
| 17 #include "base/test/simple_test_clock.h" | 16 #include "base/test/simple_test_clock.h" |
| 18 #include "base/thread_task_runner_handle.h" | 17 #include "base/thread_task_runner_handle.h" |
| 19 #include "base/values.h" | 18 #include "base/values.h" |
| 20 #include "net/base/sdch_manager.h" | 19 #include "net/base/sdch_manager.h" |
| 21 #include "net/log/net_log.h" | 20 #include "net/log/net_log.h" |
| 22 #include "net/url_request/url_request.h" | 21 #include "net/url_request/url_request.h" |
| 23 #include "net/url_request/url_request_context.h" | 22 #include "net/url_request/url_request_context.h" |
| 24 #include "net/url_request/url_request_error_job.h" | 23 #include "net/url_request/url_request_error_job.h" |
| 25 #include "net/url_request/url_request_job.h" | 24 #include "net/url_request/url_request_job.h" |
| 26 #include "net/url_request/url_request_job_factory.h" | 25 #include "net/url_request/url_request_job_factory.h" |
| 27 #include "net/url_request/url_request_test_util.h" | 26 #include "net/url_request/url_request_test_util.h" |
| 28 #include "testing/gtest/include/gtest/gtest.h" | 27 #include "testing/gtest/include/gtest/gtest.h" |
| 29 | 28 |
| 29 namespace net { |
| 30 |
| 30 namespace { | 31 namespace { |
| 31 | 32 |
| 32 bool GetDictionaryForURL(TestingPrefStore* store, | 33 bool GetDictionaryForURL(SdchOwner::PrefStorage* store, |
| 33 const GURL& url, | 34 const GURL& url, |
| 34 std::string* hash, | 35 std::string* hash, |
| 35 base::DictionaryValue** dict) { | 36 base::DictionaryValue** dict) { |
| 36 base::Value* sdch_val = nullptr; | |
| 37 base::DictionaryValue* sdch_dict = nullptr; | 37 base::DictionaryValue* sdch_dict = nullptr; |
| 38 if (!store->GetMutableValue("SDCH", &sdch_val)) | 38 if (!store->GetMutableValue(&sdch_dict)) |
| 39 return false; | |
| 40 if (!sdch_val->GetAsDictionary(&sdch_dict)) | |
| 41 return false; | 39 return false; |
| 42 | 40 |
| 43 base::DictionaryValue* dicts_dict = nullptr; | 41 base::DictionaryValue* dicts_dict = nullptr; |
| 44 if (!sdch_dict->GetDictionary("dictionaries", &dicts_dict)) | 42 if (!sdch_dict->GetDictionary("dictionaries", &dicts_dict)) |
| 45 return false; | 43 return false; |
| 46 | 44 |
| 47 base::DictionaryValue::Iterator it(*dicts_dict); | 45 base::DictionaryValue::Iterator it(*dicts_dict); |
| 48 while (!it.IsAtEnd()) { | 46 while (!it.IsAtEnd()) { |
| 49 const base::DictionaryValue* d = nullptr; | 47 const base::DictionaryValue* d = nullptr; |
| 50 if (!it.value().GetAsDictionary(&d)) | 48 if (!it.value().GetAsDictionary(&d)) |
| 51 continue; | 49 continue; |
| 52 std::string dict_url; | 50 std::string dict_url; |
| 53 if (d->GetString("url", &dict_url) && dict_url == url.spec()) { | 51 if (d->GetString("url", &dict_url) && dict_url == url.spec()) { |
| 54 if (hash) | 52 if (hash) |
| 55 *hash = it.key(); | 53 *hash = it.key(); |
| 56 if (dict) | 54 if (dict) |
| 57 dicts_dict->GetDictionary(it.key(), dict); | 55 dicts_dict->GetDictionary(it.key(), dict); |
| 58 return true; | 56 return true; |
| 59 } | 57 } |
| 60 it.Advance(); | 58 it.Advance(); |
| 61 } | 59 } |
| 62 | 60 |
| 63 return false; | 61 return false; |
| 64 } | 62 } |
| 65 | 63 |
| 64 // This class supports copying so we can emulate persistent storage. |
| 65 class TestPrefStorage : public SdchOwner::PrefStorage { |
| 66 public: |
| 67 explicit TestPrefStorage(bool initialized) |
| 68 : initialized_(initialized), initialization_observer_(nullptr) {} |
| 69 explicit TestPrefStorage(const TestPrefStorage& other) |
| 70 : initialized_(other.initialized_), |
| 71 initialization_observer_(nullptr) { // Don't copy observer. |
| 72 storage_.MergeDictionary(&other.storage_); |
| 73 } |
| 74 |
| 75 ~TestPrefStorage() override {} |
| 76 |
| 77 void SetInitialized() { |
| 78 DCHECK(!initialized_); |
| 79 initialized_ = true; |
| 80 if (initialization_observer_) |
| 81 initialization_observer_->OnPrefStorageInitializationComplete(true); |
| 82 } |
| 83 |
| 84 ReadError GetReadError() const override { return PERSISTENCE_FAILURE_NONE; } |
| 85 |
| 86 bool GetValue(const base::DictionaryValue** result) const override { |
| 87 *result = &storage_; |
| 88 return true; |
| 89 } |
| 90 bool GetMutableValue(base::DictionaryValue** result) override { |
| 91 *result = &storage_; |
| 92 return true; |
| 93 } |
| 94 void SetValue(scoped_ptr<base::DictionaryValue> value) override { |
| 95 storage_.Clear(); |
| 96 storage_.MergeDictionary(value.get()); |
| 97 } |
| 98 |
| 99 void ReportValueChanged() override {} |
| 100 |
| 101 // This storage class requires no special initialization. |
| 102 bool IsInitializationComplete() override { return initialized_; } |
| 103 void StartObservingInit(SdchOwner* observer) override { |
| 104 DCHECK(!initialization_observer_); |
| 105 initialization_observer_ = observer; |
| 106 } |
| 107 void StopObservingInit() override { initialization_observer_ = nullptr; } |
| 108 |
| 109 private: |
| 110 bool initialized_; |
| 111 SdchOwner* initialization_observer_; |
| 112 |
| 113 base::DictionaryValue storage_; |
| 114 }; |
| 115 |
| 66 } // namespace | 116 } // namespace |
| 67 | 117 |
| 68 namespace net { | |
| 69 | |
| 70 static const char generic_url[] = "http://www.example.com"; | 118 static const char generic_url[] = "http://www.example.com"; |
| 71 static const char generic_domain[] = "www.example.com"; | 119 static const char generic_domain[] = "www.example.com"; |
| 72 | 120 |
| 73 static std::string NewSdchDictionary(size_t dictionary_size) { | 121 static std::string NewSdchDictionary(size_t dictionary_size) { |
| 74 std::string dictionary; | 122 std::string dictionary; |
| 75 dictionary.append("Domain: "); | 123 dictionary.append("Domain: "); |
| 76 dictionary.append(generic_domain); | 124 dictionary.append(generic_domain); |
| 77 dictionary.append("\n"); | 125 dictionary.append("\n"); |
| 78 dictionary.append("\n"); | 126 dictionary.append("\n"); |
| 79 | 127 |
| (...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 256 // * Either of the above, having previously added dictionaries to create | 304 // * Either of the above, having previously added dictionaries to create |
| 257 // a particular initial state. | 305 // a particular initial state. |
| 258 class SdchOwnerTest : public testing::Test { | 306 class SdchOwnerTest : public testing::Test { |
| 259 public: | 307 public: |
| 260 static const size_t kMaxSizeForTesting = 1000 * 50; | 308 static const size_t kMaxSizeForTesting = 1000 * 50; |
| 261 static const size_t kMinFetchSpaceForTesting = 500; | 309 static const size_t kMinFetchSpaceForTesting = 500; |
| 262 | 310 |
| 263 SdchOwnerTest() | 311 SdchOwnerTest() |
| 264 : last_jobs_created_(error_jobs_created), | 312 : last_jobs_created_(error_jobs_created), |
| 265 dictionary_creation_index_(0), | 313 dictionary_creation_index_(0), |
| 266 pref_store_(new TestingPrefStore), | |
| 267 sdch_owner_(new SdchOwner(&sdch_manager_, &url_request_context_)) { | 314 sdch_owner_(new SdchOwner(&sdch_manager_, &url_request_context_)) { |
| 268 // Any jobs created on this context will immediately error, | 315 // Any jobs created on this context will immediately error, |
| 269 // which leaves the test in control of signals to SdchOwner. | 316 // which leaves the test in control of signals to SdchOwner. |
| 270 url_request_context_.set_job_factory(&job_factory_); | 317 url_request_context_.set_job_factory(&job_factory_); |
| 271 | 318 |
| 272 // Reduce sizes to reduce time for string operations. | 319 // Reduce sizes to reduce time for string operations. |
| 273 sdch_owner_->SetMaxTotalDictionarySize(kMaxSizeForTesting); | 320 sdch_owner_->SetMaxTotalDictionarySize(kMaxSizeForTesting); |
| 274 sdch_owner_->SetMinSpaceForDictionaryFetch(kMinFetchSpaceForTesting); | 321 sdch_owner_->SetMinSpaceForDictionaryFetch(kMinFetchSpaceForTesting); |
| 275 } | 322 } |
| 276 | 323 |
| 277 SdchManager& sdch_manager() { return sdch_manager_; } | 324 SdchManager& sdch_manager() { return sdch_manager_; } |
| 278 SdchOwner& sdch_owner() { return *(sdch_owner_.get()); } | 325 SdchOwner& sdch_owner() { return *(sdch_owner_.get()); } |
| 279 BoundNetLog& bound_net_log() { return net_log_; } | 326 BoundNetLog& bound_net_log() { return net_log_; } |
| 280 TestingPrefStore& pref_store() { return *(pref_store_.get()); } | |
| 281 | 327 |
| 282 int JobsRecentlyCreated() { | 328 int JobsRecentlyCreated() { |
| 283 int result = error_jobs_created - last_jobs_created_; | 329 int result = error_jobs_created - last_jobs_created_; |
| 284 last_jobs_created_ = error_jobs_created; | 330 last_jobs_created_ = error_jobs_created; |
| 285 return result; | 331 return result; |
| 286 } | 332 } |
| 287 | 333 |
| 288 bool DictionaryPresentInManager(const std::string& server_hash) { | 334 bool DictionaryPresentInManager(const std::string& server_hash) { |
| 289 // Presumes all tests use generic url. | 335 // Presumes all tests use generic url. |
| 290 SdchProblemCode tmp; | 336 SdchProblemCode tmp; |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 352 int last_jobs_created_; | 398 int last_jobs_created_; |
| 353 BoundNetLog net_log_; | 399 BoundNetLog net_log_; |
| 354 int dictionary_creation_index_; | 400 int dictionary_creation_index_; |
| 355 | 401 |
| 356 // The dependencies of these objects (sdch_owner_ -> {sdch_manager_, | 402 // The dependencies of these objects (sdch_owner_ -> {sdch_manager_, |
| 357 // url_request_context_}, url_request_context_->job_factory_) require | 403 // url_request_context_}, url_request_context_->job_factory_) require |
| 358 // this order for correct destruction semantics. | 404 // this order for correct destruction semantics. |
| 359 MockURLRequestJobFactory job_factory_; | 405 MockURLRequestJobFactory job_factory_; |
| 360 URLRequestContext url_request_context_; | 406 URLRequestContext url_request_context_; |
| 361 SdchManager sdch_manager_; | 407 SdchManager sdch_manager_; |
| 362 scoped_refptr<TestingPrefStore> pref_store_; | |
| 363 scoped_ptr<SdchOwner> sdch_owner_; | 408 scoped_ptr<SdchOwner> sdch_owner_; |
| 364 | 409 |
| 365 DISALLOW_COPY_AND_ASSIGN(SdchOwnerTest); | 410 DISALLOW_COPY_AND_ASSIGN(SdchOwnerTest); |
| 366 }; | 411 }; |
| 367 | 412 |
| 368 // Does OnGetDictionary result in a fetch when there's enough space, and not | 413 // Does OnGetDictionary result in a fetch when there's enough space, and not |
| 369 // when there's not? | 414 // when there's not? |
| 370 TEST_F(SdchOwnerTest, OnGetDictionary_Fetching) { | 415 TEST_F(SdchOwnerTest, OnGetDictionary_Fetching) { |
| 371 GURL request_url(std::string(generic_url) + "/r1"); | 416 GURL request_url(std::string(generic_url) + "/r1"); |
| 372 | 417 |
| (...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 679 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d1)); | 724 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d1)); |
| 680 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d2)); | 725 EXPECT_FALSE(DictionaryPresentInManager(server_hash_d2)); |
| 681 | 726 |
| 682 // Addition should now succeed. | 727 // Addition should now succeed. |
| 683 EXPECT_TRUE( | 728 EXPECT_TRUE( |
| 684 CreateAndAddDictionary(kMaxSizeForTesting, base::Time::Now(), nullptr)); | 729 CreateAndAddDictionary(kMaxSizeForTesting, base::Time::Now(), nullptr)); |
| 685 } | 730 } |
| 686 | 731 |
| 687 // Confirm that use of a pinned dictionary after its removal works properly. | 732 // Confirm that use of a pinned dictionary after its removal works properly. |
| 688 TEST_F(SdchOwnerTest, PinRemoveUse) { | 733 TEST_F(SdchOwnerTest, PinRemoveUse) { |
| 689 pref_store().SetInitializationCompleted(); | 734 // Pass ownership of the storage to the SdchOwner, but keep a pointer. |
| 690 sdch_owner().EnablePersistentStorage(&pref_store()); | 735 TestPrefStorage* pref_store = new TestPrefStorage(true); |
| 736 sdch_owner().EnablePersistentStorage( |
| 737 scoped_ptr<SdchOwner::PrefStorage>(pref_store)); |
| 691 | 738 |
| 692 std::string server_hash_d1; | 739 std::string server_hash_d1; |
| 693 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 2, base::Time::Now(), | 740 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 2, base::Time::Now(), |
| 694 &server_hash_d1)); | 741 &server_hash_d1)); |
| 695 | 742 |
| 696 scoped_ptr<SdchManager::DictionarySet> return_set( | 743 scoped_ptr<SdchManager::DictionarySet> return_set( |
| 697 sdch_manager().GetDictionarySet( | 744 sdch_manager().GetDictionarySet( |
| 698 GURL(std::string(generic_url) + "/x.html"))); | 745 GURL(std::string(generic_url) + "/x.html"))); |
| 699 ASSERT_TRUE(return_set.get()); | 746 ASSERT_TRUE(return_set.get()); |
| 700 EXPECT_TRUE(return_set->GetDictionaryText(server_hash_d1)); | 747 EXPECT_TRUE(return_set->GetDictionaryText(server_hash_d1)); |
| 701 | 748 |
| 702 const base::Value* result = nullptr; | 749 const base::Value* result = nullptr; |
| 703 const base::DictionaryValue* dict_result = nullptr; | 750 const base::DictionaryValue* dict_result = nullptr; |
| 704 ASSERT_TRUE(pref_store().GetValue("SDCH", &result)); | 751 ASSERT_TRUE(pref_store->GetValue(&dict_result)); |
| 705 ASSERT_TRUE(result->GetAsDictionary(&dict_result)); | |
| 706 EXPECT_TRUE(dict_result->Get("dictionaries", &result)); | 752 EXPECT_TRUE(dict_result->Get("dictionaries", &result)); |
| 707 EXPECT_TRUE(dict_result->Get("dictionaries." + server_hash_d1, &result)); | 753 EXPECT_TRUE(dict_result->Get("dictionaries." + server_hash_d1, &result)); |
| 708 | 754 |
| 709 sdch_manager().ClearData(); | 755 sdch_manager().ClearData(); |
| 710 | 756 |
| 711 ASSERT_TRUE(pref_store().GetValue("SDCH", &result)); | 757 ASSERT_TRUE(pref_store->GetValue(&dict_result)); |
| 712 ASSERT_TRUE(result->GetAsDictionary(&dict_result)); | |
| 713 EXPECT_TRUE(dict_result->Get("dictionaries", &result)); | 758 EXPECT_TRUE(dict_result->Get("dictionaries", &result)); |
| 714 EXPECT_FALSE(dict_result->Get("dictionaries." + server_hash_d1, &result)); | 759 EXPECT_FALSE(dict_result->Get("dictionaries." + server_hash_d1, &result)); |
| 715 | 760 |
| 716 scoped_ptr<SdchManager::DictionarySet> return_set2( | 761 scoped_ptr<SdchManager::DictionarySet> return_set2( |
| 717 sdch_manager().GetDictionarySet( | 762 sdch_manager().GetDictionarySet( |
| 718 GURL(std::string(generic_url) + "/x.html"))); | 763 GURL(std::string(generic_url) + "/x.html"))); |
| 719 EXPECT_FALSE(return_set2.get()); | 764 EXPECT_FALSE(return_set2.get()); |
| 720 | 765 |
| 721 sdch_manager().OnDictionaryUsed(server_hash_d1); | 766 sdch_manager().OnDictionaryUsed(server_hash_d1); |
| 722 | 767 |
| 723 ASSERT_TRUE(pref_store().GetValue("SDCH", &result)); | 768 ASSERT_TRUE(pref_store->GetValue(&dict_result)); |
| 724 ASSERT_TRUE(result->GetAsDictionary(&dict_result)); | |
| 725 EXPECT_TRUE(dict_result->Get("dictionaries", &result)); | 769 EXPECT_TRUE(dict_result->Get("dictionaries", &result)); |
| 726 EXPECT_FALSE(dict_result->Get("dictionaries." + server_hash_d1, &result)); | 770 EXPECT_FALSE(dict_result->Get("dictionaries." + server_hash_d1, &result)); |
| 727 } | 771 } |
| 728 | 772 |
| 729 TEST_F(SdchOwnerTest, UsageIntervalMetrics) { | 773 TEST_F(SdchOwnerTest, UsageIntervalMetrics) { |
| 730 const GURL url("http://www.example.com/dict0"); | 774 const GURL url("http://www.example.com/dict0"); |
| 731 | 775 |
| 732 std::string server_hash; | 776 std::string server_hash; |
| 733 base::Time last_used_time(base::Time::Now() - base::TimeDelta::FromHours(23)); | 777 base::Time last_used_time(base::Time::Now() - base::TimeDelta::FromHours(23)); |
| 734 base::Time created_time(base::Time::Now() - base::TimeDelta::FromHours(47)); | 778 base::Time created_time(base::Time::Now() - base::TimeDelta::FromHours(47)); |
| 735 | 779 |
| 736 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 3, last_used_time, | 780 EXPECT_TRUE(CreateAndAddDictionary(kMaxSizeForTesting / 3, last_used_time, |
| 737 created_time, &server_hash)); | 781 created_time, &server_hash)); |
| 738 | 782 |
| 739 base::HistogramTester tester; | 783 base::HistogramTester tester; |
| 740 | 784 |
| 741 sdch_owner().OnDictionaryUsed(server_hash); | 785 sdch_owner().OnDictionaryUsed(server_hash); |
| 742 tester.ExpectTotalCount("Sdch3.FirstUseInterval", 1); | 786 tester.ExpectTotalCount("Sdch3.FirstUseInterval", 1); |
| 743 tester.ExpectTotalCount("Sdch3.UsageInterval2", 0); | 787 tester.ExpectTotalCount("Sdch3.UsageInterval2", 0); |
| 744 | 788 |
| 745 sdch_owner().OnDictionaryUsed(server_hash); | 789 sdch_owner().OnDictionaryUsed(server_hash); |
| 746 tester.ExpectTotalCount("Sdch3.FirstUseInterval", 1); // count didn't change | 790 tester.ExpectTotalCount("Sdch3.FirstUseInterval", 1); // count didn't change |
| 747 tester.ExpectTotalCount("Sdch3.UsageInterval2", 1); | 791 tester.ExpectTotalCount("Sdch3.UsageInterval2", 1); |
| 748 } | 792 } |
| 749 | 793 |
| 750 class SdchOwnerPersistenceTest : public ::testing::Test { | 794 class SdchOwnerPersistenceTest : public ::testing::Test { |
| 751 public: | 795 public: |
| 752 SdchOwnerPersistenceTest() : pref_store_(new TestingPrefStore()) { | 796 SdchOwnerPersistenceTest() {} |
| 753 pref_store_->SetInitializationCompleted(); | |
| 754 } | |
| 755 virtual ~SdchOwnerPersistenceTest() {} | 797 virtual ~SdchOwnerPersistenceTest() {} |
| 756 | 798 |
| 757 void ClearOwner() { | 799 void ClearOwner() { |
| 758 owner_.reset(NULL); | 800 owner_.reset(NULL); |
| 759 } | 801 } |
| 760 | 802 |
| 761 void ResetOwner(bool delay) { | 803 // If the storage points is non-null it will be saved as the persistent |
| 804 // storage for the SdchOwner. |
| 805 void ResetOwner(scoped_ptr<SdchOwner::PrefStorage> storage) { |
| 762 // This has to be done first, since SdchOwner may be observing SdchManager, | 806 // This has to be done first, since SdchOwner may be observing SdchManager, |
| 763 // and SdchManager can't be destroyed with a live observer. | 807 // and SdchManager can't be destroyed with a live observer. |
| 764 owner_.reset(NULL); | 808 owner_.reset(NULL); |
| 765 manager_.reset(new SdchManager()); | 809 manager_.reset(new SdchManager()); |
| 766 fetcher_ = new MockSdchDictionaryFetcher(); | 810 fetcher_ = new MockSdchDictionaryFetcher(); |
| 767 owner_.reset(new SdchOwner(manager_.get(), | 811 owner_.reset(new SdchOwner(manager_.get(), |
| 768 &url_request_context_)); | 812 &url_request_context_)); |
| 769 owner_->SetMaxTotalDictionarySize(SdchOwnerTest::kMaxSizeForTesting); | 813 owner_->SetMaxTotalDictionarySize(SdchOwnerTest::kMaxSizeForTesting); |
| 770 owner_->SetMinSpaceForDictionaryFetch( | 814 owner_->SetMinSpaceForDictionaryFetch( |
| 771 SdchOwnerTest::kMinFetchSpaceForTesting); | 815 SdchOwnerTest::kMinFetchSpaceForTesting); |
| 772 owner_->SetFetcherForTesting(make_scoped_ptr(fetcher_)); | 816 owner_->SetFetcherForTesting(make_scoped_ptr(fetcher_)); |
| 773 if (!delay) | 817 if (storage) |
| 774 owner_->EnablePersistentStorage(pref_store_.get()); | 818 owner_->EnablePersistentStorage(std::move(storage)); |
| 775 } | 819 } |
| 776 | 820 |
| 777 void InsertDictionaryForURL(const GURL& url, const std::string& nonce) { | 821 void InsertDictionaryForURL(const GURL& url, const std::string& nonce) { |
| 778 owner_->OnDictionaryFetched(base::Time::Now(), base::Time::Now(), 1, | 822 owner_->OnDictionaryFetched(base::Time::Now(), base::Time::Now(), 1, |
| 779 CreateDictionary(url, nonce), url, net_log_, | 823 CreateDictionary(url, nonce), url, net_log_, |
| 780 false); | 824 false); |
| 781 } | 825 } |
| 782 | 826 |
| 783 bool CompleteLoadFromURL(const GURL& url, const std::string& nonce, | 827 bool CompleteLoadFromURL(const GURL& url, const std::string& nonce, |
| 784 bool was_from_cache) { | 828 bool was_from_cache) { |
| 785 return fetcher_->CompletePendingRequest(url, CreateDictionary(url, nonce), | 829 return fetcher_->CompletePendingRequest(url, CreateDictionary(url, nonce), |
| 786 net_log_, was_from_cache); | 830 net_log_, was_from_cache); |
| 787 } | 831 } |
| 788 | 832 |
| 789 std::string CreateDictionary(const GURL& url, const std::string& nonce) { | 833 std::string CreateDictionary(const GURL& url, const std::string& nonce) { |
| 790 std::string dict; | 834 std::string dict; |
| 791 dict.append("Domain: "); | 835 dict.append("Domain: "); |
| 792 dict.append(url.host()); | 836 dict.append(url.host()); |
| 793 dict.append("\n\n"); | 837 dict.append("\n\n"); |
| 794 dict.append(url.spec()); | 838 dict.append(url.spec()); |
| 795 dict.append(nonce); | 839 dict.append(nonce); |
| 796 return dict; | 840 return dict; |
| 797 } | 841 } |
| 798 | 842 |
| 799 protected: | 843 protected: |
| 800 BoundNetLog net_log_; | 844 BoundNetLog net_log_; |
| 801 scoped_refptr<TestingPrefStore> pref_store_; | |
| 802 scoped_ptr<SdchManager> manager_; | 845 scoped_ptr<SdchManager> manager_; |
| 803 MockSdchDictionaryFetcher* fetcher_; | 846 MockSdchDictionaryFetcher* fetcher_; |
| 804 scoped_ptr<SdchOwner> owner_; | 847 scoped_ptr<SdchOwner> owner_; |
| 805 TestURLRequestContext url_request_context_; | 848 TestURLRequestContext url_request_context_; |
| 806 }; | 849 }; |
| 807 | 850 |
| 808 // Test an empty persistence store. | 851 // Test an empty persistence store. |
| 809 TEST_F(SdchOwnerPersistenceTest, Empty) { | 852 TEST_F(SdchOwnerPersistenceTest, Empty) { |
| 810 ResetOwner(false); | 853 ResetOwner(make_scoped_ptr(new TestPrefStorage(true))); |
| 811 EXPECT_EQ(0, owner_->GetDictionaryCountForTesting()); | 854 EXPECT_EQ(0, owner_->GetDictionaryCountForTesting()); |
| 812 } | 855 } |
| 813 | 856 |
| 814 // Test a persistence store with an empty dictionary. | |
| 815 TEST_F(SdchOwnerPersistenceTest, Persistent_EmptyDict) { | |
| 816 pref_store_->SetValue("SDCH", make_scoped_ptr(new base::DictionaryValue()), | |
| 817 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); | |
| 818 ResetOwner(false); | |
| 819 EXPECT_EQ(0, owner_->GetDictionaryCountForTesting()); | |
| 820 } | |
| 821 | |
| 822 // Test a persistence store with a bad version number. | 857 // Test a persistence store with a bad version number. |
| 823 TEST_F(SdchOwnerPersistenceTest, Persistent_BadVersion) { | 858 TEST_F(SdchOwnerPersistenceTest, Persistent_BadVersion) { |
| 824 scoped_ptr<base::DictionaryValue> sdch_dict(new base::DictionaryValue()); | 859 scoped_ptr<base::DictionaryValue> sdch_dict(new base::DictionaryValue()); |
| 825 sdch_dict->SetInteger("version", 2); | 860 sdch_dict->SetInteger("version", 2); |
| 826 pref_store_->SetValue("SDCH", std::move(sdch_dict), | |
| 827 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); | |
| 828 | 861 |
| 829 ResetOwner(false); | 862 scoped_ptr<TestPrefStorage> storage(new TestPrefStorage(true)); |
| 863 storage->SetValue(std::move(sdch_dict)); |
| 864 |
| 865 TestPrefStorage* old_storage = storage.get(); // Save storage pointer. |
| 866 ResetOwner(std::move(storage)); // Takes ownership of storage pointer. |
| 867 |
| 868 storage.reset(new TestPrefStorage(*old_storage)); |
| 869 ResetOwner(std::move(storage)); |
| 830 EXPECT_EQ(0, owner_->GetDictionaryCountForTesting()); | 870 EXPECT_EQ(0, owner_->GetDictionaryCountForTesting()); |
| 831 } | 871 } |
| 832 | 872 |
| 833 // Test a persistence store with an empty dictionaries map. | 873 // Test a persistence store with an empty dictionaries map. |
| 834 TEST_F(SdchOwnerPersistenceTest, Persistent_EmptyDictList) { | 874 TEST_F(SdchOwnerPersistenceTest, Persistent_EmptyDictList) { |
| 835 scoped_ptr<base::DictionaryValue> sdch_dict(new base::DictionaryValue()); | 875 scoped_ptr<base::DictionaryValue> sdch_dict(new base::DictionaryValue()); |
| 836 scoped_ptr<base::DictionaryValue> dicts(new base::DictionaryValue()); | 876 scoped_ptr<base::DictionaryValue> dicts(new base::DictionaryValue()); |
| 837 sdch_dict->SetInteger("version", 1); | 877 sdch_dict->SetInteger("version", 1); |
| 838 sdch_dict->Set("dictionaries", std::move(dicts)); | 878 sdch_dict->Set("dictionaries", std::move(dicts)); |
| 839 pref_store_->SetValue("SDCH", std::move(sdch_dict), | |
| 840 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); | |
| 841 | 879 |
| 842 ResetOwner(false); | 880 scoped_ptr<TestPrefStorage> storage(new TestPrefStorage(true)); |
| 881 storage->SetValue(std::move(sdch_dict)); |
| 882 ResetOwner(std::move(storage)); |
| 843 EXPECT_EQ(0, owner_->GetDictionaryCountForTesting()); | 883 EXPECT_EQ(0, owner_->GetDictionaryCountForTesting()); |
| 844 } | 884 } |
| 845 | 885 |
| 846 TEST_F(SdchOwnerPersistenceTest, OneDict) { | 886 TEST_F(SdchOwnerPersistenceTest, OneDict) { |
| 847 const GURL url("http://www.example.com/dict"); | 887 const GURL url("http://www.example.com/dict"); |
| 848 ResetOwner(false); | 888 |
| 889 scoped_ptr<TestPrefStorage> storage(new TestPrefStorage(true)); |
| 890 TestPrefStorage* old_storage = storage.get(); // Save storage pointer. |
| 891 ResetOwner(std::move(storage)); // Takes ownership of storage pointer. |
| 849 EXPECT_EQ(0, owner_->GetDictionaryCountForTesting()); | 892 EXPECT_EQ(0, owner_->GetDictionaryCountForTesting()); |
| 850 InsertDictionaryForURL(url, "0"); | 893 InsertDictionaryForURL(url, "0"); |
| 851 EXPECT_EQ(1, owner_->GetDictionaryCountForTesting()); | 894 EXPECT_EQ(1, owner_->GetDictionaryCountForTesting()); |
| 852 | 895 |
| 853 ResetOwner(false); | 896 storage.reset(new TestPrefStorage(*old_storage)); |
| 897 ResetOwner(std::move(storage)); |
| 854 EXPECT_EQ(0, owner_->GetDictionaryCountForTesting()); | 898 EXPECT_EQ(0, owner_->GetDictionaryCountForTesting()); |
| 855 EXPECT_TRUE(CompleteLoadFromURL(url, "0", true)); | 899 EXPECT_TRUE(CompleteLoadFromURL(url, "0", true)); |
| 856 EXPECT_EQ(1, owner_->GetDictionaryCountForTesting()); | 900 EXPECT_EQ(1, owner_->GetDictionaryCountForTesting()); |
| 857 } | 901 } |
| 858 | 902 |
| 859 TEST_F(SdchOwnerPersistenceTest, TwoDicts) { | 903 TEST_F(SdchOwnerPersistenceTest, TwoDicts) { |
| 860 const GURL url0("http://www.example.com/dict0"); | 904 const GURL url0("http://www.example.com/dict0"); |
| 861 const GURL url1("http://www.example.com/dict1"); | 905 const GURL url1("http://www.example.com/dict1"); |
| 862 ResetOwner(false); | 906 |
| 907 scoped_ptr<TestPrefStorage> storage(new TestPrefStorage(true)); |
| 908 TestPrefStorage* old_storage = storage.get(); // Save storage pointer. |
| 909 ResetOwner(std::move(storage)); // Takes ownership of storage pointer. |
| 863 InsertDictionaryForURL(url0, "0"); | 910 InsertDictionaryForURL(url0, "0"); |
| 864 InsertDictionaryForURL(url1, "1"); | 911 InsertDictionaryForURL(url1, "1"); |
| 865 | 912 |
| 866 ResetOwner(false); | 913 storage.reset(new TestPrefStorage(*old_storage)); |
| 914 ResetOwner(std::move(storage)); |
| 867 EXPECT_TRUE(CompleteLoadFromURL(url0, "0", true)); | 915 EXPECT_TRUE(CompleteLoadFromURL(url0, "0", true)); |
| 868 EXPECT_TRUE(CompleteLoadFromURL(url1, "1", true)); | 916 EXPECT_TRUE(CompleteLoadFromURL(url1, "1", true)); |
| 869 EXPECT_EQ(2, owner_->GetDictionaryCountForTesting()); | 917 EXPECT_EQ(2, owner_->GetDictionaryCountForTesting()); |
| 870 EXPECT_TRUE(owner_->HasDictionaryFromURLForTesting(url0)); | 918 EXPECT_TRUE(owner_->HasDictionaryFromURLForTesting(url0)); |
| 871 EXPECT_TRUE(owner_->HasDictionaryFromURLForTesting(url1)); | 919 EXPECT_TRUE(owner_->HasDictionaryFromURLForTesting(url1)); |
| 872 } | 920 } |
| 873 | 921 |
| 874 TEST_F(SdchOwnerPersistenceTest, OneGoodDictOneBadDict) { | 922 TEST_F(SdchOwnerPersistenceTest, OneGoodDictOneBadDict) { |
| 875 const GURL url0("http://www.example.com/dict0"); | 923 const GURL url0("http://www.example.com/dict0"); |
| 876 const GURL url1("http://www.example.com/dict1"); | 924 const GURL url1("http://www.example.com/dict1"); |
| 877 ResetOwner(false); | 925 |
| 926 scoped_ptr<TestPrefStorage> storage(new TestPrefStorage(true)); |
| 927 TestPrefStorage* old_storage = storage.get(); // Save storage pointer. |
| 928 ResetOwner(std::move(storage)); // Takes ownership of storage. |
| 878 InsertDictionaryForURL(url0, "0"); | 929 InsertDictionaryForURL(url0, "0"); |
| 879 InsertDictionaryForURL(url1, "1"); | 930 InsertDictionaryForURL(url1, "1"); |
| 880 | 931 |
| 881 // Mutate the pref store a bit now. Clear the owner first, to ensure that the | 932 // Make a new storage based on the current contents of the old one. |
| 882 // SdchOwner doesn't observe these changes and object. The manual dictionary | 933 storage.reset(new TestPrefStorage(*old_storage)); |
| 883 // manipulation is a bit icky. | |
| 884 ClearOwner(); | |
| 885 base::DictionaryValue* dict = nullptr; | 934 base::DictionaryValue* dict = nullptr; |
| 886 ASSERT_TRUE(GetDictionaryForURL(pref_store_.get(), url1, nullptr, &dict)); | 935 ASSERT_TRUE(GetDictionaryForURL(storage.get(), url1, nullptr, &dict)); |
| 887 dict->Remove("use_count", nullptr); | 936 dict->Remove("use_count", nullptr); |
| 888 | 937 |
| 889 ResetOwner(false); | 938 ResetOwner(std::move(storage)); |
| 890 EXPECT_TRUE(CompleteLoadFromURL(url0, "0", true)); | 939 EXPECT_TRUE(CompleteLoadFromURL(url0, "0", true)); |
| 891 EXPECT_FALSE(CompleteLoadFromURL(url1, "1", true)); | 940 EXPECT_FALSE(CompleteLoadFromURL(url1, "1", true)); |
| 892 EXPECT_EQ(1, owner_->GetDictionaryCountForTesting()); | 941 EXPECT_EQ(1, owner_->GetDictionaryCountForTesting()); |
| 893 EXPECT_TRUE(owner_->HasDictionaryFromURLForTesting(url0)); | 942 EXPECT_TRUE(owner_->HasDictionaryFromURLForTesting(url0)); |
| 894 EXPECT_FALSE(owner_->HasDictionaryFromURLForTesting(url1)); | 943 EXPECT_FALSE(owner_->HasDictionaryFromURLForTesting(url1)); |
| 895 } | 944 } |
| 896 | 945 |
| 897 TEST_F(SdchOwnerPersistenceTest, UsingDictionaryUpdatesUseCount) { | 946 TEST_F(SdchOwnerPersistenceTest, UsingDictionaryUpdatesUseCount) { |
| 898 const GURL url("http://www.example.com/dict"); | 947 const GURL url("http://www.example.com/dict"); |
| 899 ResetOwner(false); | 948 |
| 949 scoped_ptr<TestPrefStorage> storage(new TestPrefStorage(true)); |
| 950 TestPrefStorage* old_storage = storage.get(); // Save storage pointer. |
| 951 ResetOwner(std::move(storage)); // Takes ownership of storage pointer. |
| 900 InsertDictionaryForURL(url, "0"); | 952 InsertDictionaryForURL(url, "0"); |
| 901 | 953 |
| 902 std::string hash; | 954 std::string hash; |
| 903 int old_count; | 955 int old_count; |
| 956 storage.reset(new TestPrefStorage(*old_storage)); |
| 904 { | 957 { |
| 905 ClearOwner(); | 958 ClearOwner(); |
| 906 base::DictionaryValue* dict = nullptr; | 959 base::DictionaryValue* dict = nullptr; |
| 907 ASSERT_TRUE(GetDictionaryForURL(pref_store_.get(), url, &hash, &dict)); | 960 ASSERT_TRUE(GetDictionaryForURL(storage.get(), url, &hash, &dict)); |
| 908 ASSERT_TRUE(dict->GetInteger("use_count", &old_count)); | 961 ASSERT_TRUE(dict->GetInteger("use_count", &old_count)); |
| 909 } | 962 } |
| 910 | 963 |
| 911 ResetOwner(false); | 964 old_storage = storage.get(); // Save storage pointer. |
| 965 ResetOwner(std::move(storage)); // Takes ownership of storage pointer. |
| 912 ASSERT_TRUE(CompleteLoadFromURL(url, "0", true)); | 966 ASSERT_TRUE(CompleteLoadFromURL(url, "0", true)); |
| 913 owner_->OnDictionaryUsed(hash); | 967 owner_->OnDictionaryUsed(hash); |
| 914 | 968 |
| 915 int new_count; | 969 int new_count; |
| 916 { | 970 { |
| 917 ClearOwner(); | |
| 918 base::DictionaryValue* dict = nullptr; | 971 base::DictionaryValue* dict = nullptr; |
| 919 ASSERT_TRUE(GetDictionaryForURL(pref_store_.get(), url, nullptr, &dict)); | 972 ASSERT_TRUE(GetDictionaryForURL(old_storage, url, nullptr, &dict)); |
| 920 ASSERT_TRUE(dict->GetInteger("use_count", &new_count)); | 973 ASSERT_TRUE(dict->GetInteger("use_count", &new_count)); |
| 921 } | 974 } |
| 922 | 975 |
| 923 EXPECT_EQ(old_count + 1, new_count); | 976 EXPECT_EQ(old_count + 1, new_count); |
| 924 } | 977 } |
| 925 | 978 |
| 926 TEST_F(SdchOwnerPersistenceTest, LoadingDictionaryMerges) { | 979 TEST_F(SdchOwnerPersistenceTest, LoadingDictionaryMerges) { |
| 927 const GURL url0("http://www.example.com/dict0"); | 980 const GURL url0("http://www.example.com/dict0"); |
| 928 const GURL url1("http://www.example.com/dict1"); | 981 const GURL url1("http://www.example.com/dict1"); |
| 929 | 982 |
| 930 ResetOwner(false); | 983 scoped_ptr<TestPrefStorage> storage(new TestPrefStorage(true)); |
| 984 TestPrefStorage* old_storage = storage.get(); // Save storage pointer. |
| 985 ResetOwner(std::move(storage)); // Takes ownership of storage pointer. |
| 931 InsertDictionaryForURL(url1, "1"); | 986 InsertDictionaryForURL(url1, "1"); |
| 932 | 987 |
| 933 ResetOwner(true); | 988 storage.reset(new TestPrefStorage(*old_storage)); |
| 989 ResetOwner(scoped_ptr<SdchOwner::PrefStorage>()); |
| 934 InsertDictionaryForURL(url0, "0"); | 990 InsertDictionaryForURL(url0, "0"); |
| 935 EXPECT_EQ(1, owner_->GetDictionaryCountForTesting()); | 991 EXPECT_EQ(1, owner_->GetDictionaryCountForTesting()); |
| 936 owner_->EnablePersistentStorage(pref_store_.get()); | 992 owner_->EnablePersistentStorage(std::move(storage)); |
| 937 ASSERT_TRUE(CompleteLoadFromURL(url1, "1", true)); | 993 ASSERT_TRUE(CompleteLoadFromURL(url1, "1", true)); |
| 938 EXPECT_EQ(2, owner_->GetDictionaryCountForTesting()); | 994 EXPECT_EQ(2, owner_->GetDictionaryCountForTesting()); |
| 939 } | 995 } |
| 940 | 996 |
| 941 TEST_F(SdchOwnerPersistenceTest, PersistenceMetrics) { | 997 TEST_F(SdchOwnerPersistenceTest, PersistenceMetrics) { |
| 942 const GURL url0("http://www.example.com/dict0"); | 998 const GURL url0("http://www.example.com/dict0"); |
| 943 const GURL url1("http://www.example.com/dict1"); | 999 const GURL url1("http://www.example.com/dict1"); |
| 944 ResetOwner(false); | 1000 |
| 1001 scoped_ptr<TestPrefStorage> storage(new TestPrefStorage(true)); |
| 1002 TestPrefStorage* old_storage = storage.get(); // Save storage pointer. |
| 1003 ResetOwner(std::move(storage)); // Takes ownership of storage pointer. |
| 945 | 1004 |
| 946 InsertDictionaryForURL(url0, "0"); | 1005 InsertDictionaryForURL(url0, "0"); |
| 947 InsertDictionaryForURL(url1, "1"); | 1006 InsertDictionaryForURL(url1, "1"); |
| 948 | 1007 |
| 949 ResetOwner(false); | 1008 storage.reset(new TestPrefStorage(*old_storage)); |
| 1009 ResetOwner(std::move(storage)); |
| 950 | 1010 |
| 951 base::HistogramTester tester; | 1011 base::HistogramTester tester; |
| 952 | 1012 |
| 953 EXPECT_TRUE(CompleteLoadFromURL(url0, "0", true)); | 1013 EXPECT_TRUE(CompleteLoadFromURL(url0, "0", true)); |
| 954 EXPECT_TRUE(CompleteLoadFromURL(url1, "1", false)); | 1014 EXPECT_TRUE(CompleteLoadFromURL(url1, "1", false)); |
| 955 | 1015 |
| 956 tester.ExpectTotalCount("Sdch3.NetworkBytesSpent", 1); | 1016 tester.ExpectTotalCount("Sdch3.NetworkBytesSpent", 1); |
| 957 tester.ExpectUniqueSample("Sdch3.NetworkBytesSpent", | 1017 tester.ExpectUniqueSample("Sdch3.NetworkBytesSpent", |
| 958 CreateDictionary(url1, "1").size(), 1); | 1018 CreateDictionary(url1, "1").size(), 1); |
| 959 } | 1019 } |
| 960 | 1020 |
| 961 } // namespace net | 1021 } // namespace net |
| OLD | NEW |