Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "components/safe_browsing_db/v4_local_database_manager.h" | |
| 6 #include "base/base64.h" | |
| 5 #include "base/files/scoped_temp_dir.h" | 7 #include "base/files/scoped_temp_dir.h" |
| 6 #include "base/memory/ptr_util.h" | 8 #include "base/memory/ptr_util.h" |
| 7 #include "base/memory/ref_counted.h" | 9 #include "base/memory/ref_counted.h" |
| 8 #include "base/run_loop.h" | 10 #include "base/run_loop.h" |
| 9 #include "base/test/test_simple_task_runner.h" | 11 #include "base/test/test_simple_task_runner.h" |
| 10 #include "base/threading/thread_task_runner_handle.h" | 12 #include "base/threading/thread_task_runner_handle.h" |
| 11 #include "components/safe_browsing_db/v4_database.h" | 13 #include "components/safe_browsing_db/v4_database.h" |
| 12 #include "components/safe_browsing_db/v4_local_database_manager.h" | |
| 13 #include "components/safe_browsing_db/v4_test_util.h" | 14 #include "components/safe_browsing_db/v4_test_util.h" |
| 14 #include "content/public/test/test_browser_thread_bundle.h" | 15 #include "content/public/test/test_browser_thread_bundle.h" |
| 15 #include "crypto/sha2.h" | 16 #include "crypto/sha2.h" |
| 16 #include "net/url_request/test_url_fetcher_factory.h" | 17 #include "net/url_request/test_url_fetcher_factory.h" |
| 17 #include "testing/platform_test.h" | 18 #include "testing/platform_test.h" |
| 18 | 19 |
| 19 namespace safe_browsing { | 20 namespace safe_browsing { |
| 20 | 21 |
| 21 namespace { | 22 namespace { |
| 22 | 23 |
| 23 typedef base::Callback<void()> NullCallback; | 24 typedef std::vector<FullHashInfo> FullHashInfos; |
| 24 | 25 |
| 25 // Utility function for populating hashes. | 26 // Utility function for populating hashes. |
| 26 FullHash HashForUrl(const GURL& url) { | 27 FullHash HashForUrl(const GURL& url) { |
| 27 std::vector<FullHash> full_hashes; | 28 std::vector<FullHash> full_hashes; |
| 28 V4ProtocolManagerUtil::UrlToFullHashes(url, &full_hashes); | 29 V4ProtocolManagerUtil::UrlToFullHashes(url, &full_hashes); |
| 29 // ASSERT_GE(full_hashes.size(), 1u); | 30 // ASSERT_GE(full_hashes.size(), 1u); |
| 30 return full_hashes[0]; | 31 return full_hashes[0]; |
| 31 } | 32 } |
| 32 | 33 |
| 33 // Always returns misses from GetFullHashes(). | 34 // Always returns misses from GetFullHashes(). |
| 34 class FakeGetHashProtocolManager : public V4GetHashProtocolManager { | 35 class FakeGetHashProtocolManager : public V4GetHashProtocolManager { |
| 35 public: | 36 public: |
| 36 FakeGetHashProtocolManager( | 37 FakeGetHashProtocolManager( |
| 37 net::URLRequestContextGetter* request_context_getter, | 38 net::URLRequestContextGetter* request_context_getter, |
| 38 const StoresToCheck& stores_to_check, | 39 const StoresToCheck& stores_to_check, |
| 39 const V4ProtocolConfig& config) | 40 const V4ProtocolConfig& config, |
| 41 FullHashInfos full_hash_infos) | |
|
Nathan Parker
2017/02/07 22:59:58
nit: const FullHashInfos&, here and below. Perfor
vakh (use Gerrit instead)
2017/02/07 23:11:21
Done.
| |
| 40 : V4GetHashProtocolManager(request_context_getter, | 42 : V4GetHashProtocolManager(request_context_getter, |
| 41 stores_to_check, | 43 stores_to_check, |
| 42 config) {} | 44 config), |
| 45 full_hash_infos_(full_hash_infos) {} | |
| 43 | 46 |
| 44 void GetFullHashes(const FullHashToStoreAndHashPrefixesMap&, | 47 void GetFullHashes(const FullHashToStoreAndHashPrefixesMap&, |
| 45 FullHashCallback callback) override { | 48 FullHashCallback callback) override { |
| 46 std::vector<FullHashInfo> full_hash_infos; | |
| 47 | |
| 48 // Async, since the real manager might use a fetcher. | 49 // Async, since the real manager might use a fetcher. |
| 49 base::ThreadTaskRunnerHandle::Get()->PostTask( | 50 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 50 FROM_HERE, base::Bind(callback, full_hash_infos)); | 51 FROM_HERE, base::Bind(callback, full_hash_infos_)); |
| 51 } | 52 } |
| 53 | |
| 54 private: | |
| 55 FullHashInfos full_hash_infos_; | |
| 52 }; | 56 }; |
| 53 | 57 |
| 54 class FakeGetHashProtocolManagerFactory | 58 class FakeGetHashProtocolManagerFactory |
| 55 : public V4GetHashProtocolManagerFactory { | 59 : public V4GetHashProtocolManagerFactory { |
| 56 public: | 60 public: |
| 61 FakeGetHashProtocolManagerFactory(FullHashInfos full_hash_infos) | |
| 62 : full_hash_infos_(full_hash_infos) {} | |
| 63 | |
| 57 std::unique_ptr<V4GetHashProtocolManager> CreateProtocolManager( | 64 std::unique_ptr<V4GetHashProtocolManager> CreateProtocolManager( |
| 58 net::URLRequestContextGetter* request_context_getter, | 65 net::URLRequestContextGetter* request_context_getter, |
| 59 const StoresToCheck& stores_to_check, | 66 const StoresToCheck& stores_to_check, |
| 60 const V4ProtocolConfig& config) override { | 67 const V4ProtocolConfig& config) override { |
| 61 return base::MakeUnique<FakeGetHashProtocolManager>( | 68 return base::MakeUnique<FakeGetHashProtocolManager>( |
| 62 request_context_getter, stores_to_check, config); | 69 request_context_getter, stores_to_check, config, full_hash_infos_); |
| 63 } | 70 } |
| 71 | |
| 72 private: | |
| 73 FullHashInfos full_hash_infos_; | |
| 64 }; | 74 }; |
| 65 | 75 |
| 66 // Use FakeGetHashProtocolManagerFactory in scope, then reset. | 76 // Use FakeGetHashProtocolManagerFactory in scope, then reset. |
| 67 class ScopedFakeGetHashProtocolManagerFactory { | 77 class ScopedFakeGetHashProtocolManagerFactory { |
| 68 public: | 78 public: |
| 69 ScopedFakeGetHashProtocolManagerFactory() { | 79 ScopedFakeGetHashProtocolManagerFactory(FullHashInfos full_hash_infos) { |
| 70 V4GetHashProtocolManager::RegisterFactory( | 80 V4GetHashProtocolManager::RegisterFactory( |
| 71 base::MakeUnique<FakeGetHashProtocolManagerFactory>()); | 81 base::MakeUnique<FakeGetHashProtocolManagerFactory>(full_hash_infos)); |
| 72 } | 82 } |
| 73 ~ScopedFakeGetHashProtocolManagerFactory() { | 83 ~ScopedFakeGetHashProtocolManagerFactory() { |
| 74 V4GetHashProtocolManager::RegisterFactory(nullptr); | 84 V4GetHashProtocolManager::RegisterFactory(nullptr); |
| 75 } | 85 } |
| 76 }; | 86 }; |
| 77 | 87 |
| 78 } // namespace | 88 } // namespace |
| 79 | 89 |
| 80 class FakeV4Database : public V4Database { | 90 class FakeV4Database : public V4Database { |
| 81 public: | 91 public: |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 162 if (manager_to_cancel_) { | 172 if (manager_to_cancel_) { |
| 163 manager_to_cancel_->CancelCheck(this); | 173 manager_to_cancel_->CancelCheck(this); |
| 164 } | 174 } |
| 165 } | 175 } |
| 166 | 176 |
| 167 void OnCheckResourceUrlResult(const GURL& url, | 177 void OnCheckResourceUrlResult(const GURL& url, |
| 168 SBThreatType threat_type, | 178 SBThreatType threat_type, |
| 169 const std::string& threat_hash) override { | 179 const std::string& threat_hash) override { |
| 170 DCHECK_EQ(expected_url, url); | 180 DCHECK_EQ(expected_url, url); |
| 171 DCHECK_EQ(expected_sb_threat_type, threat_type); | 181 DCHECK_EQ(expected_sb_threat_type, threat_type); |
| 172 // |threat_hash| is empty because GetFullHashes calls back with empty | 182 DCHECK(threat_type != SB_THREAT_TYPE_SAFE || threat_hash.empty()); |
|
Nathan Parker
2017/02/07 22:59:58
nit: I had to think about what this was asserting.
vakh (use Gerrit instead)
2017/02/07 23:11:21
I read it as: "Either it is not safe, or the hash
Scott Hess - ex-Googler
2017/02/07 23:37:51
Well, that's also how I read it - but I still have
vakh (use Gerrit instead)
2017/02/07 23:51:22
Acknowledged.
Re-wrote to be more accurate and le
| |
| 173 // |full_hash_infos|. | |
| 174 DCHECK(threat_hash.empty()); | |
| 175 on_check_resource_url_result_called_ = true; | 183 on_check_resource_url_result_called_ = true; |
| 176 } | 184 } |
| 177 | 185 |
| 178 SBThreatType expected_sb_threat_type; | 186 SBThreatType expected_sb_threat_type; |
| 179 GURL expected_url; | 187 GURL expected_url; |
| 180 bool on_check_browse_url_result_called_; | 188 bool on_check_browse_url_result_called_; |
| 181 bool on_check_resource_url_result_called_; | 189 bool on_check_resource_url_result_called_; |
| 182 V4LocalDatabaseManager* manager_to_cancel_; | 190 V4LocalDatabaseManager* manager_to_cancel_; |
| 183 }; | 191 }; |
| 184 | 192 |
| (...skipping 255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 440 // The database is unavailable so the check should get queued. | 448 // The database is unavailable so the check should get queued. |
| 441 EXPECT_EQ(1ul, GetQueuedChecks().size()); | 449 EXPECT_EQ(1ul, GetQueuedChecks().size()); |
| 442 | 450 |
| 443 StopLocalDatabaseManager(); | 451 StopLocalDatabaseManager(); |
| 444 EXPECT_TRUE(GetQueuedChecks().empty()); | 452 EXPECT_TRUE(GetQueuedChecks().empty()); |
| 445 } | 453 } |
| 446 | 454 |
| 447 // Verify that a window where checks cannot be cancelled is closed. | 455 // Verify that a window where checks cannot be cancelled is closed. |
| 448 TEST_F(V4LocalDatabaseManagerTest, CancelPending) { | 456 TEST_F(V4LocalDatabaseManagerTest, CancelPending) { |
| 449 // Setup to receive full-hash misses. | 457 // Setup to receive full-hash misses. |
| 450 ScopedFakeGetHashProtocolManagerFactory pin; | 458 ScopedFakeGetHashProtocolManagerFactory pin(FullHashInfos({})); |
| 451 | 459 |
| 452 // Reset the database manager so it picks up the replacement protocol manager. | 460 // Reset the database manager so it picks up the replacement protocol manager. |
| 453 ResetLocalDatabaseManager(); | 461 ResetLocalDatabaseManager(); |
| 454 WaitForTasksOnTaskRunner(); | 462 WaitForTasksOnTaskRunner(); |
| 455 | 463 |
| 456 // An URL and matching prefix. | 464 // An URL and matching prefix. |
| 457 const GURL url("http://example.com/a/"); | 465 const GURL url("http://example.com/a/"); |
| 458 const HashPrefix hash_prefix("eW\x1A\xF\xA9"); | 466 const HashPrefix hash_prefix("eW\x1A\xF\xA9"); |
| 459 | 467 |
| 460 // Put a match in the db that will cause a protocol-manager request. | 468 // Put a match in the db that will cause a protocol-manager request. |
| (...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 667 // Whitelisted. | 675 // Whitelisted. |
| 668 EXPECT_TRUE( | 676 EXPECT_TRUE( |
| 669 v4_local_database_manager_->MatchModuleWhitelistString("chrome.dll")); | 677 v4_local_database_manager_->MatchModuleWhitelistString("chrome.dll")); |
| 670 | 678 |
| 671 EXPECT_FALSE(FakeV4LocalDatabaseManager::PerformFullHashCheckCalled( | 679 EXPECT_FALSE(FakeV4LocalDatabaseManager::PerformFullHashCheckCalled( |
| 672 v4_local_database_manager_)); | 680 v4_local_database_manager_)); |
| 673 } | 681 } |
| 674 | 682 |
| 675 // This verifies the fix for race in http://crbug.com/660293 | 683 // This verifies the fix for race in http://crbug.com/660293 |
| 676 TEST_F(V4LocalDatabaseManagerTest, TestCheckBrowseUrlWithSameClientAndCancel) { | 684 TEST_F(V4LocalDatabaseManagerTest, TestCheckBrowseUrlWithSameClientAndCancel) { |
| 677 ScopedFakeGetHashProtocolManagerFactory pin; | 685 ScopedFakeGetHashProtocolManagerFactory pin(FullHashInfos({})); |
| 678 // Reset the database manager so it picks up the replacement protocol manager. | 686 // Reset the database manager so it picks up the replacement protocol manager. |
| 679 ResetLocalDatabaseManager(); | 687 ResetLocalDatabaseManager(); |
| 680 WaitForTasksOnTaskRunner(); | 688 WaitForTasksOnTaskRunner(); |
| 681 | 689 |
| 682 StoreAndHashPrefixes store_and_hash_prefixes; | 690 StoreAndHashPrefixes store_and_hash_prefixes; |
| 683 store_and_hash_prefixes.emplace_back(GetUrlMalwareId(), | 691 store_and_hash_prefixes.emplace_back(GetUrlMalwareId(), |
| 684 HashPrefix("sن\340\t\006_")); | 692 HashPrefix("sن\340\t\006_")); |
| 685 ReplaceV4Database(store_and_hash_prefixes); | 693 ReplaceV4Database(store_and_hash_prefixes); |
| 686 | 694 |
| 687 GURL first_url("http://example.com/a"); | 695 GURL first_url("http://example.com/a"); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 702 WaitForTasksOnTaskRunner(); | 710 WaitForTasksOnTaskRunner(); |
| 703 // |on_check_browse_url_result_called_| is true only if OnCheckBrowseUrlResult | 711 // |on_check_browse_url_result_called_| is true only if OnCheckBrowseUrlResult |
| 704 // gets called with the |url| equal to |expected_url|, which is |second_url| | 712 // gets called with the |url| equal to |expected_url|, which is |second_url| |
| 705 // in | 713 // in |
| 706 // this test. | 714 // this test. |
| 707 EXPECT_TRUE(client.on_check_browse_url_result_called_); | 715 EXPECT_TRUE(client.on_check_browse_url_result_called_); |
| 708 } | 716 } |
| 709 | 717 |
| 710 TEST_F(V4LocalDatabaseManagerTest, TestCheckResourceUrl) { | 718 TEST_F(V4LocalDatabaseManagerTest, TestCheckResourceUrl) { |
| 711 // Setup to receive full-hash misses. | 719 // Setup to receive full-hash misses. |
| 712 ScopedFakeGetHashProtocolManagerFactory pin; | 720 ScopedFakeGetHashProtocolManagerFactory pin(FullHashInfos({})); |
| 713 | 721 |
| 714 // Reset the database manager so it picks up the replacement protocol manager. | 722 // Reset the database manager so it picks up the replacement protocol manager. |
| 715 ResetLocalDatabaseManager(); | 723 ResetLocalDatabaseManager(); |
| 716 WaitForTasksOnTaskRunner(); | 724 WaitForTasksOnTaskRunner(); |
| 717 | 725 |
| 718 // An URL and matching prefix. | 726 // An URL and matching prefix. |
| 719 const GURL url("http://example.com/a/"); | 727 const GURL url("http://example.com/a/"); |
| 720 const HashPrefix hash_prefix("eW\x1A\xF\xA9"); | 728 const HashPrefix hash_prefix("eW\x1A\xF\xA9"); |
| 721 | 729 |
| 722 // Put a match in the db that will cause a protocol-manager request. | 730 // Put a match in the db that will cause a protocol-manager request. |
| 723 StoreAndHashPrefixes store_and_hash_prefixes; | 731 StoreAndHashPrefixes store_and_hash_prefixes; |
| 724 store_and_hash_prefixes.emplace_back(GetChromeUrlClientIncidentId(), | 732 store_and_hash_prefixes.emplace_back(GetChromeUrlClientIncidentId(), |
| 725 hash_prefix); | 733 hash_prefix); |
| 726 ReplaceV4Database(store_and_hash_prefixes, true /* stores_available */); | 734 ReplaceV4Database(store_and_hash_prefixes, true /* stores_available */); |
| 727 | 735 |
| 728 TestClient client(SB_THREAT_TYPE_SAFE, url); | 736 TestClient client(SB_THREAT_TYPE_SAFE, url); |
| 729 EXPECT_FALSE(v4_local_database_manager_->CheckResourceUrl(url, &client)); | 737 EXPECT_FALSE(v4_local_database_manager_->CheckResourceUrl(url, &client)); |
| 730 EXPECT_FALSE(client.on_check_resource_url_result_called_); | 738 EXPECT_FALSE(client.on_check_resource_url_result_called_); |
| 731 WaitForTasksOnTaskRunner(); | 739 WaitForTasksOnTaskRunner(); |
| 732 EXPECT_TRUE(client.on_check_resource_url_result_called_); | 740 EXPECT_TRUE(client.on_check_resource_url_result_called_); |
| 733 } | 741 } |
| 734 | 742 |
| 735 TEST_F(V4LocalDatabaseManagerTest, TestSubresourceFilterCallback) { | 743 TEST_F(V4LocalDatabaseManagerTest, TestSubresourceFilterCallback) { |
| 736 // Setup to receive full-hash misses. | 744 // Setup to receive full-hash misses. |
| 737 ScopedFakeGetHashProtocolManagerFactory pin; | 745 ScopedFakeGetHashProtocolManagerFactory pin(FullHashInfos({})); |
| 738 | 746 |
| 739 // Reset the database manager so it picks up the replacement protocol manager. | 747 // Reset the database manager so it picks up the replacement protocol manager. |
| 740 ResetLocalDatabaseManager(); | 748 ResetLocalDatabaseManager(); |
| 741 WaitForTasksOnTaskRunner(); | 749 WaitForTasksOnTaskRunner(); |
| 742 | 750 |
| 743 // An URL and matching prefix. | 751 // An URL and matching prefix. |
| 744 const GURL url("http://example.com/a/"); | 752 const GURL url("http://example.com/a/"); |
| 745 const HashPrefix hash_prefix("eW\x1A\xF\xA9"); | 753 const HashPrefix hash_prefix("eW\x1A\xF\xA9"); |
| 746 | 754 |
| 747 // Put a match in the db that will cause a protocol-manager request. | 755 // Put a match in the db that will cause a protocol-manager request. |
| 748 StoreAndHashPrefixes store_and_hash_prefixes; | 756 StoreAndHashPrefixes store_and_hash_prefixes; |
| 749 store_and_hash_prefixes.emplace_back(GetUrlSubresourceFilterId(), | 757 store_and_hash_prefixes.emplace_back(GetUrlSubresourceFilterId(), |
| 750 hash_prefix); | 758 hash_prefix); |
| 751 ReplaceV4Database(store_and_hash_prefixes, true /* stores_available */); | 759 ReplaceV4Database(store_and_hash_prefixes, true /* stores_available */); |
| 752 | 760 |
| 753 // Test that a request flows through to the callback. | 761 // Test that a request flows through to the callback. |
| 754 { | 762 { |
| 755 TestClient client(SB_THREAT_TYPE_SAFE, url); | 763 TestClient client(SB_THREAT_TYPE_SAFE, url); |
| 756 EXPECT_FALSE( | 764 EXPECT_FALSE( |
| 757 v4_local_database_manager_->CheckUrlForSubresourceFilter(url, &client)); | 765 v4_local_database_manager_->CheckUrlForSubresourceFilter(url, &client)); |
| 758 EXPECT_FALSE(client.on_check_browse_url_result_called_); | 766 EXPECT_FALSE(client.on_check_browse_url_result_called_); |
| 759 WaitForTasksOnTaskRunner(); | 767 WaitForTasksOnTaskRunner(); |
| 760 EXPECT_TRUE(client.on_check_browse_url_result_called_); | 768 EXPECT_TRUE(client.on_check_browse_url_result_called_); |
| 761 } | 769 } |
| 762 } | 770 } |
| 763 | 771 |
| 772 TEST_F(V4LocalDatabaseManagerTest, TestCheckResourceUrlReturnsBad) { | |
| 773 std::string base64_encoded = "ZVcaD6lke9GaaZEf07X3CpuEgMAqbpAyPw3sX/7eK9M="; | |
| 774 std::string base64_decoded; | |
| 775 base::Base64Decode(base64_encoded, &base64_decoded); | |
| 776 FullHashInfo fhi(base64_decoded, GetChromeUrlClientIncidentId(), | |
| 777 base::Time::Now() + base::TimeDelta::FromMinutes(5)); | |
|
Nathan Parker
2017/02/07 22:59:59
Is this time used? Anything with a real clock can
vakh (use Gerrit instead)
2017/02/07 23:11:21
Done.
| |
| 778 | |
| 779 // Setup to receive full-hash hit. | |
| 780 ScopedFakeGetHashProtocolManagerFactory pin(FullHashInfos({fhi})); | |
| 781 | |
| 782 // Reset the database manager so it picks up the replacement protocol manager. | |
| 783 ResetLocalDatabaseManager(); | |
| 784 WaitForTasksOnTaskRunner(); | |
| 785 | |
| 786 // An URL and matching prefix. | |
| 787 const GURL url("http://example.com/a/"); | |
| 788 const HashPrefix hash_prefix("eW\x1A\xF\xA9"); | |
| 789 | |
| 790 // Put a match in the db that will cause a protocol-manager request. | |
| 791 StoreAndHashPrefixes store_and_hash_prefixes; | |
| 792 store_and_hash_prefixes.emplace_back(GetChromeUrlClientIncidentId(), | |
| 793 hash_prefix); | |
| 794 ReplaceV4Database(store_and_hash_prefixes, true /* stores_available */); | |
| 795 | |
| 796 TestClient client(SB_THREAT_TYPE_BLACKLISTED_RESOURCE, url); | |
| 797 EXPECT_FALSE(v4_local_database_manager_->CheckResourceUrl(url, &client)); | |
| 798 EXPECT_FALSE(client.on_check_resource_url_result_called_); | |
| 799 WaitForTasksOnTaskRunner(); | |
| 800 EXPECT_TRUE(client.on_check_resource_url_result_called_); | |
| 801 } | |
| 802 | |
| 764 // TODO(nparker): Add tests for | 803 // TODO(nparker): Add tests for |
| 765 // CheckDownloadUrl() | 804 // CheckDownloadUrl() |
| 766 // CheckExtensionIDs() | 805 // CheckExtensionIDs() |
|
Nathan Parker
2017/02/07 22:59:58
I'll just leave and arrow pointing to these...
/'\
vakh (use Gerrit instead)
2017/02/07 23:11:21
Acknowledged. Will implement very soon.
| |
| 767 | 806 |
| 768 } // namespace safe_browsing | 807 } // namespace safe_browsing |
| OLD | NEW |