1 // Copyright 2017 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/safe_browsing/test_safe_browsing_database_helper.h"
6 
7 #include <utility>
8 
9 #include "base/bind.h"
10 #include "base/files/file_path.h"
11 #include "base/files/file_util.h"
12 #include "base/location.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/strings/stringprintf.h"
15 #include "chrome/browser/safe_browsing/safe_browsing_service.h"
16 #include "chrome/browser/safe_browsing/test_safe_browsing_service.h"
17 #include "components/safe_browsing/core/db/v4_database.h"
18 #include "components/safe_browsing/core/db/v4_protocol_manager_util.h"
19 #include "components/safe_browsing/core/db/v4_test_util.h"
20 #include "components/security_interstitials/core/unsafe_resource.h"
21 
22 namespace {
23 
24 // UI manager that never actually shows any interstitials, but emulates as if
25 // the user chose to proceed through them.
26 class FakeSafeBrowsingUIManager
27     : public safe_browsing::TestSafeBrowsingUIManager {
28  public:
FakeSafeBrowsingUIManager()29   FakeSafeBrowsingUIManager() {}
30 
31  protected:
~FakeSafeBrowsingUIManager()32   ~FakeSafeBrowsingUIManager() override {}
33 
DisplayBlockingPage(const UnsafeResource & resource)34   void DisplayBlockingPage(const UnsafeResource& resource) override {
35     resource.callback_thread->PostTask(
36         FROM_HERE, base::BindOnce(resource.callback, true /* proceed */,
37                                   true /* showed_interstitial */));
38   }
39 
40  private:
41   DISALLOW_COPY_AND_ASSIGN(FakeSafeBrowsingUIManager);
42 };
43 
44 }  // namespace
45 
46 // This class automatically inserts lists into the store map when initializing
47 // the test database.
48 class InsertingDatabaseFactory : public safe_browsing::TestV4DatabaseFactory {
49  public:
InsertingDatabaseFactory(safe_browsing::TestV4StoreFactory * store_factory,const std::vector<safe_browsing::ListIdentifier> & lists_to_insert)50   explicit InsertingDatabaseFactory(
51       safe_browsing::TestV4StoreFactory* store_factory,
52       const std::vector<safe_browsing::ListIdentifier>& lists_to_insert)
53       : lists_to_insert_(lists_to_insert), store_factory_(store_factory) {}
54 
Create(const scoped_refptr<base::SequencedTaskRunner> & db_task_runner,std::unique_ptr<safe_browsing::StoreMap> store_map)55   std::unique_ptr<safe_browsing::V4Database> Create(
56       const scoped_refptr<base::SequencedTaskRunner>& db_task_runner,
57       std::unique_ptr<safe_browsing::StoreMap> store_map) override {
58     const base::FilePath base_store_path(FILE_PATH_LITERAL("UrlDb.store"));
59     for (const auto& id : lists_to_insert_) {
60       if (!base::Contains(*store_map, id)) {
61         const base::FilePath store_path =
62             base_store_path.InsertBeforeExtensionASCII(base::StringPrintf(
63                 " (%d)", base::GetUniquePathNumber(base_store_path)));
64         (*store_map)[id] =
65             store_factory_->CreateV4Store(db_task_runner, store_path);
66       }
67     }
68 
69     for (const auto& it : *store_map)
70       lists_.push_back(it.first);
71     return safe_browsing::TestV4DatabaseFactory::Create(db_task_runner,
72                                                         std::move(store_map));
73   }
74 
lists()75   const std::vector<safe_browsing::ListIdentifier> lists() { return lists_; }
76 
77  private:
78   std::vector<safe_browsing::ListIdentifier> lists_to_insert_;
79   std::vector<safe_browsing::ListIdentifier> lists_;
80   safe_browsing::TestV4StoreFactory* store_factory_;
81 };
82 
TestSafeBrowsingDatabaseHelper()83 TestSafeBrowsingDatabaseHelper::TestSafeBrowsingDatabaseHelper()
84     : TestSafeBrowsingDatabaseHelper(
85           std::make_unique<
86               safe_browsing::TestV4GetHashProtocolManagerFactory>(),
87           std::vector<safe_browsing::ListIdentifier>()) {}
88 
TestSafeBrowsingDatabaseHelper(std::unique_ptr<safe_browsing::TestV4GetHashProtocolManagerFactory> v4_get_hash_factory,std::vector<safe_browsing::ListIdentifier> lists_to_insert)89 TestSafeBrowsingDatabaseHelper::TestSafeBrowsingDatabaseHelper(
90     std::unique_ptr<safe_browsing::TestV4GetHashProtocolManagerFactory>
91         v4_get_hash_factory,
92     std::vector<safe_browsing::ListIdentifier> lists_to_insert)
93     : v4_get_hash_factory_(v4_get_hash_factory.get()) {
94   sb_factory_ =
95       std::make_unique<safe_browsing::TestSafeBrowsingServiceFactory>();
96   sb_factory_->SetTestUIManager(new FakeSafeBrowsingUIManager());
97   sb_factory_->UseV4LocalDatabaseManager();
98   safe_browsing::SafeBrowsingService::RegisterFactory(sb_factory_.get());
99 
100   auto store_factory = std::make_unique<safe_browsing::TestV4StoreFactory>();
101   auto v4_db_factory = std::make_unique<InsertingDatabaseFactory>(
102       store_factory.get(), lists_to_insert);
103 
104   v4_db_factory_ = v4_db_factory.get();
105 
106   safe_browsing::V4Database::RegisterStoreFactoryForTest(
107       std::move(store_factory));
108   safe_browsing::V4Database::RegisterDatabaseFactoryForTest(
109       std::move(v4_db_factory));
110 
111   if (v4_get_hash_factory) {
112     safe_browsing::V4GetHashProtocolManager::RegisterFactory(
113         std::move(v4_get_hash_factory));
114   }
115 }
116 
~TestSafeBrowsingDatabaseHelper()117 TestSafeBrowsingDatabaseHelper::~TestSafeBrowsingDatabaseHelper() {
118   safe_browsing::V4GetHashProtocolManager::RegisterFactory(nullptr);
119   safe_browsing::V4Database::RegisterDatabaseFactoryForTest(nullptr);
120   safe_browsing::V4Database::RegisterStoreFactoryForTest(nullptr);
121   safe_browsing::SafeBrowsingService::RegisterFactory(nullptr);
122 }
123 
AddFullHashToDbAndFullHashCache(const GURL & bad_url,const safe_browsing::ListIdentifier & list_id,const safe_browsing::ThreatMetadata & threat_metadata)124 void TestSafeBrowsingDatabaseHelper::AddFullHashToDbAndFullHashCache(
125     const GURL& bad_url,
126     const safe_browsing::ListIdentifier& list_id,
127     const safe_browsing::ThreatMetadata& threat_metadata) {
128   // Should only be called if we are mocking the v4 hash factory.
129   DCHECK(v4_get_hash_factory_);
130 
131   LocallyMarkPrefixAsBad(bad_url, list_id);
132 
133   safe_browsing::FullHashInfo full_hash_info =
134       GetFullHashInfoWithMetadata(bad_url, list_id, threat_metadata);
135   v4_get_hash_factory_->AddToFullHashCache(full_hash_info);
136 }
137 
LocallyMarkPrefixAsBad(const GURL & url,const safe_browsing::ListIdentifier & list_id)138 void TestSafeBrowsingDatabaseHelper::LocallyMarkPrefixAsBad(
139     const GURL& url,
140     const safe_browsing::ListIdentifier& list_id) {
141   safe_browsing::FullHash full_hash =
142       safe_browsing::V4ProtocolManagerUtil::GetFullHash(url);
143   v4_db_factory_->MarkPrefixAsBad(list_id, full_hash);
144 }
145 
HasListSynced(const safe_browsing::ListIdentifier & list_id)146 bool TestSafeBrowsingDatabaseHelper::HasListSynced(
147     const safe_browsing::ListIdentifier& list_id) {
148   return base::Contains(v4_db_factory_->lists(), list_id);
149 }
150