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
3 // found in the LICENSE file.
4 
5 #include "components/safe_browsing/core/db/v4_local_database_manager.h"
6 
7 #include <utility>
8 
9 #include "base/bind.h"
10 #include "base/command_line.h"
11 #include "base/files/file_path.h"
12 #include "base/files/file_util.h"
13 #include "base/files/scoped_temp_dir.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/run_loop.h"
16 #include "base/sequenced_task_runner.h"
17 #include "base/strings/string_tokenizer.h"
18 #include "base/test/metrics/histogram_tester.h"
19 #include "base/test/scoped_feature_list.h"
20 #include "base/test/test_simple_task_runner.h"
21 #include "base/threading/thread_task_runner_handle.h"
22 #include "components/safe_browsing/core/common/test_task_environment.h"
23 #include "components/safe_browsing/core/db/v4_database.h"
24 #include "components/safe_browsing/core/db/v4_protocol_manager_util.h"
25 #include "components/safe_browsing/core/db/v4_test_util.h"
26 #include "components/safe_browsing/core/features.h"
27 #include "crypto/sha2.h"
28 #include "services/network/public/cpp/shared_url_loader_factory.h"
29 #include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
30 #include "services/network/test/test_url_loader_factory.h"
31 #include "testing/platform_test.h"
32 
33 namespace safe_browsing {
34 
35 namespace {
36 
37 typedef std::vector<FullHashInfo> FullHashInfos;
38 
39 // Utility function for populating hashes.
HashForUrl(const GURL & url)40 FullHash HashForUrl(const GURL& url) {
41   std::vector<FullHash> full_hashes;
42   V4ProtocolManagerUtil::UrlToFullHashes(url, &full_hashes);
43   // ASSERT_GE(full_hashes.size(), 1u);
44   return full_hashes[0];
45 }
46 
47 // Use this if you want GetFullHashes() to always return prescribed results.
48 class FakeGetHashProtocolManager : public V4GetHashProtocolManager {
49  public:
FakeGetHashProtocolManager(scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,const StoresToCheck & stores_to_check,const V4ProtocolConfig & config,const FullHashInfos & full_hash_infos)50   FakeGetHashProtocolManager(
51       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
52       const StoresToCheck& stores_to_check,
53       const V4ProtocolConfig& config,
54       const FullHashInfos& full_hash_infos)
55       : V4GetHashProtocolManager(url_loader_factory, stores_to_check, config),
56         full_hash_infos_(full_hash_infos) {}
57 
GetFullHashes(const FullHashToStoreAndHashPrefixesMap,const std::vector<std::string> &,FullHashCallback callback)58   void GetFullHashes(const FullHashToStoreAndHashPrefixesMap,
59                      const std::vector<std::string>&,
60                      FullHashCallback callback) override {
61     // Async, since the real manager might use a fetcher.
62     base::ThreadTaskRunnerHandle::Get()->PostTask(
63         FROM_HERE, base::BindOnce(std::move(callback), full_hash_infos_));
64   }
65 
66  private:
67   FullHashInfos full_hash_infos_;
68 };
69 
70 class FakeGetHashProtocolManagerFactory
71     : public V4GetHashProtocolManagerFactory {
72  public:
FakeGetHashProtocolManagerFactory(const FullHashInfos & full_hash_infos)73   FakeGetHashProtocolManagerFactory(const FullHashInfos& full_hash_infos)
74       : full_hash_infos_(full_hash_infos) {}
75 
CreateProtocolManager(scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,const StoresToCheck & stores_to_check,const V4ProtocolConfig & config)76   std::unique_ptr<V4GetHashProtocolManager> CreateProtocolManager(
77       scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory,
78       const StoresToCheck& stores_to_check,
79       const V4ProtocolConfig& config) override {
80     return std::make_unique<FakeGetHashProtocolManager>(
81         url_loader_factory, stores_to_check, config, full_hash_infos_);
82   }
83 
84  private:
85   FullHashInfos full_hash_infos_;
86 };
87 
88 // Use FakeGetHashProtocolManagerFactory in scope, then reset.
89 // You should make sure the DatabaseManager is created _after_ this.
90 class ScopedFakeGetHashProtocolManagerFactory {
91  public:
ScopedFakeGetHashProtocolManagerFactory(const FullHashInfos & full_hash_infos)92   ScopedFakeGetHashProtocolManagerFactory(
93       const FullHashInfos& full_hash_infos) {
94     V4GetHashProtocolManager::RegisterFactory(
95         std::make_unique<FakeGetHashProtocolManagerFactory>(full_hash_infos));
96   }
~ScopedFakeGetHashProtocolManagerFactory()97   ~ScopedFakeGetHashProtocolManagerFactory() {
98     V4GetHashProtocolManager::RegisterFactory(nullptr);
99   }
100 };
101 
102 }  // namespace
103 
104 class FakeV4Database : public V4Database {
105  public:
Create(const scoped_refptr<base::SequencedTaskRunner> & db_task_runner,std::unique_ptr<StoreMap> store_map,const StoreAndHashPrefixes & store_and_hash_prefixes,NewDatabaseReadyCallback new_db_callback,bool stores_available)106   static void Create(
107       const scoped_refptr<base::SequencedTaskRunner>& db_task_runner,
108       std::unique_ptr<StoreMap> store_map,
109       const StoreAndHashPrefixes& store_and_hash_prefixes,
110       NewDatabaseReadyCallback new_db_callback,
111       bool stores_available) {
112     // Mimics V4Database::Create
113     const scoped_refptr<base::SingleThreadTaskRunner>& callback_task_runner =
114         base::ThreadTaskRunnerHandle::Get();
115     db_task_runner->PostTask(
116         FROM_HERE,
117         base::BindOnce(&FakeV4Database::CreateOnTaskRunner, db_task_runner,
118                        std::move(store_map), store_and_hash_prefixes,
119                        callback_task_runner, std::move(new_db_callback),
120                        stores_available));
121   }
122 
123   // V4Database implementation
GetStoresMatchingFullHash(const FullHash & full_hash,const StoresToCheck & stores_to_check,StoreAndHashPrefixes * store_and_hash_prefixes)124   void GetStoresMatchingFullHash(
125       const FullHash& full_hash,
126       const StoresToCheck& stores_to_check,
127       StoreAndHashPrefixes* store_and_hash_prefixes) override {
128     store_and_hash_prefixes->clear();
129     for (const StoreAndHashPrefix& stored_sahp : store_and_hash_prefixes_) {
130       if (stores_to_check.count(stored_sahp.list_id) == 0)
131         continue;
132       const PrefixSize& prefix_size = stored_sahp.hash_prefix.size();
133       if (!full_hash.compare(0, prefix_size, stored_sahp.hash_prefix)) {
134         store_and_hash_prefixes->push_back(stored_sahp);
135       }
136     }
137   }
138 
AreAllStoresAvailable(const StoresToCheck & stores_to_check) const139   bool AreAllStoresAvailable(
140       const StoresToCheck& stores_to_check) const override {
141     return stores_available_;
142   }
143 
AreAnyStoresAvailable(const StoresToCheck & stores_to_check) const144   bool AreAnyStoresAvailable(
145       const StoresToCheck& stores_to_check) const override {
146     return stores_available_;
147   }
148 
149  private:
CreateOnTaskRunner(const scoped_refptr<base::SequencedTaskRunner> & db_task_runner,std::unique_ptr<StoreMap> store_map,const StoreAndHashPrefixes & store_and_hash_prefixes,const scoped_refptr<base::SingleThreadTaskRunner> & callback_task_runner,NewDatabaseReadyCallback new_db_callback,bool stores_available)150   static void CreateOnTaskRunner(
151       const scoped_refptr<base::SequencedTaskRunner>& db_task_runner,
152       std::unique_ptr<StoreMap> store_map,
153       const StoreAndHashPrefixes& store_and_hash_prefixes,
154       const scoped_refptr<base::SingleThreadTaskRunner>& callback_task_runner,
155       NewDatabaseReadyCallback new_db_callback,
156       bool stores_available) {
157     // Mimics the semantics of V4Database::CreateOnTaskRunner
158     std::unique_ptr<FakeV4Database> fake_v4_database(
159         new FakeV4Database(db_task_runner, std::move(store_map),
160                            store_and_hash_prefixes, stores_available));
161     callback_task_runner->PostTask(FROM_HERE,
162                                    base::BindOnce(std::move(new_db_callback),
163                                                   std::move(fake_v4_database)));
164   }
165 
FakeV4Database(const scoped_refptr<base::SequencedTaskRunner> & db_task_runner,std::unique_ptr<StoreMap> store_map,const StoreAndHashPrefixes & store_and_hash_prefixes,bool stores_available)166   FakeV4Database(const scoped_refptr<base::SequencedTaskRunner>& db_task_runner,
167                  std::unique_ptr<StoreMap> store_map,
168                  const StoreAndHashPrefixes& store_and_hash_prefixes,
169                  bool stores_available)
170       : V4Database(db_task_runner, std::move(store_map)),
171         store_and_hash_prefixes_(store_and_hash_prefixes),
172         stores_available_(stores_available) {}
173 
174   const StoreAndHashPrefixes store_and_hash_prefixes_;
175   const bool stores_available_;
176 };
177 
178 // TODO(nparker): This might be simpler with a mock and EXPECT calls.
179 // That would also catch unexpected calls.
180 class TestClient : public SafeBrowsingDatabaseManager::Client {
181  public:
TestClient(SBThreatType sb_threat_type,const GURL & url,V4LocalDatabaseManager * manager_to_cancel=nullptr)182   TestClient(SBThreatType sb_threat_type,
183              const GURL& url,
184              V4LocalDatabaseManager* manager_to_cancel = nullptr)
185       : expected_sb_threat_type_(sb_threat_type),
186         expected_urls_(1, url),
187         manager_to_cancel_(manager_to_cancel) {}
188 
TestClient(SBThreatType sb_threat_type,const std::vector<GURL> & url_chain)189   TestClient(SBThreatType sb_threat_type, const std::vector<GURL>& url_chain)
190       : expected_sb_threat_type_(sb_threat_type), expected_urls_(url_chain) {}
191 
OnCheckBrowseUrlResult(const GURL & url,SBThreatType threat_type,const ThreatMetadata & metadata)192   void OnCheckBrowseUrlResult(const GURL& url,
193                               SBThreatType threat_type,
194                               const ThreatMetadata& metadata) override {
195     ASSERT_EQ(expected_urls_[0], url);
196     ASSERT_EQ(expected_sb_threat_type_, threat_type);
197     on_check_browse_url_result_called_ = true;
198     if (manager_to_cancel_) {
199       manager_to_cancel_->CancelCheck(this);
200     }
201   }
202 
OnCheckResourceUrlResult(const GURL & url,SBThreatType threat_type,const std::string & threat_hash)203   void OnCheckResourceUrlResult(const GURL& url,
204                                 SBThreatType threat_type,
205                                 const std::string& threat_hash) override {
206     ASSERT_EQ(expected_urls_[0], url);
207     ASSERT_EQ(expected_sb_threat_type_, threat_type);
208     ASSERT_EQ(threat_type == SB_THREAT_TYPE_SAFE, threat_hash.empty());
209     on_check_resource_url_result_called_ = true;
210   }
211 
OnCheckDownloadUrlResult(const std::vector<GURL> & url_chain,SBThreatType threat_type)212   void OnCheckDownloadUrlResult(const std::vector<GURL>& url_chain,
213                                 SBThreatType threat_type) override {
214     ASSERT_EQ(expected_urls_, url_chain);
215     ASSERT_EQ(expected_sb_threat_type_, threat_type);
216     on_check_download_urls_result_called_ = true;
217   }
218 
mutable_expected_urls()219   std::vector<GURL>* mutable_expected_urls() { return &expected_urls_; }
220 
on_check_browse_url_result_called()221   bool on_check_browse_url_result_called() {
222     return on_check_browse_url_result_called_;
223   }
on_check_download_urls_result_called()224   bool on_check_download_urls_result_called() {
225     return on_check_download_urls_result_called_;
226   }
on_check_resource_url_result_called()227   bool on_check_resource_url_result_called() {
228     return on_check_resource_url_result_called_;
229   }
230 
231  private:
232   const SBThreatType expected_sb_threat_type_;
233   std::vector<GURL> expected_urls_;
234   bool on_check_browse_url_result_called_ = false;
235   bool on_check_download_urls_result_called_ = false;
236   bool on_check_resource_url_result_called_ = false;
237   V4LocalDatabaseManager* manager_to_cancel_;
238 };
239 
240 class TestAllowlistClient : public SafeBrowsingDatabaseManager::Client {
241  public:
242   // |match_expected| specifies whether a full hash match is expected.
243   // |expected_sb_threat_type| identifies which callback method to expect to get
244   // called.
TestAllowlistClient(bool match_expected,SBThreatType expected_sb_threat_type)245   explicit TestAllowlistClient(bool match_expected,
246                                SBThreatType expected_sb_threat_type)
247       : expected_sb_threat_type_(expected_sb_threat_type),
248         match_expected_(match_expected) {}
249 
OnCheckWhitelistUrlResult(bool is_allowlisted)250   void OnCheckWhitelistUrlResult(bool is_allowlisted) override {
251     EXPECT_EQ(match_expected_, is_allowlisted);
252     EXPECT_EQ(SB_THREAT_TYPE_CSD_WHITELIST, expected_sb_threat_type_);
253     callback_called_ = true;
254   }
255 
OnCheckUrlForHighConfidenceAllowlist(bool is_allowlisted)256   void OnCheckUrlForHighConfidenceAllowlist(bool is_allowlisted) override {
257     EXPECT_EQ(match_expected_, is_allowlisted);
258     EXPECT_EQ(SB_THREAT_TYPE_HIGH_CONFIDENCE_ALLOWLIST,
259               expected_sb_threat_type_);
260     callback_called_ = true;
261   }
262 
callback_called()263   bool callback_called() { return callback_called_; }
264 
265  private:
266   const SBThreatType expected_sb_threat_type_;
267   const bool match_expected_;
268   bool callback_called_ = false;
269 };
270 
271 class TestExtensionClient : public SafeBrowsingDatabaseManager::Client {
272  public:
TestExtensionClient(const std::set<FullHash> & expected_bad_crxs)273   TestExtensionClient(const std::set<FullHash>& expected_bad_crxs)
274       : expected_bad_crxs_(expected_bad_crxs),
275         on_check_extensions_result_called_(false) {}
276 
OnCheckExtensionsResult(const std::set<FullHash> & bad_crxs)277   void OnCheckExtensionsResult(const std::set<FullHash>& bad_crxs) override {
278     EXPECT_EQ(expected_bad_crxs_, bad_crxs);
279     on_check_extensions_result_called_ = true;
280   }
281 
on_check_extensions_result_called()282   bool on_check_extensions_result_called() {
283     return on_check_extensions_result_called_;
284   }
285 
286  private:
287   const std::set<FullHash> expected_bad_crxs_;
288   bool on_check_extensions_result_called_;
289 };
290 
291 class FakeV4LocalDatabaseManager : public V4LocalDatabaseManager {
292  public:
FakeV4LocalDatabaseManager(const base::FilePath & base_path,ExtendedReportingLevelCallback extended_reporting_level_callback,scoped_refptr<base::SequencedTaskRunner> task_runner)293   FakeV4LocalDatabaseManager(
294       const base::FilePath& base_path,
295       ExtendedReportingLevelCallback extended_reporting_level_callback,
296       scoped_refptr<base::SequencedTaskRunner> task_runner)
297       : V4LocalDatabaseManager(base_path,
298                                extended_reporting_level_callback,
299                                task_runner),
300         perform_full_hash_check_called_(false) {}
301 
302   // V4LocalDatabaseManager impl:
PerformFullHashCheck(std::unique_ptr<PendingCheck> check)303   void PerformFullHashCheck(std::unique_ptr<PendingCheck> check) override {
304     perform_full_hash_check_called_ = true;
305   }
306 
PerformFullHashCheckCalled(scoped_refptr<safe_browsing::V4LocalDatabaseManager> & v4_ldbm)307   static bool PerformFullHashCheckCalled(
308       scoped_refptr<safe_browsing::V4LocalDatabaseManager>& v4_ldbm) {
309     FakeV4LocalDatabaseManager* fake =
310         static_cast<FakeV4LocalDatabaseManager*>(v4_ldbm.get());
311     return fake->perform_full_hash_check_called_;
312   }
313 
314  private:
~FakeV4LocalDatabaseManager()315   ~FakeV4LocalDatabaseManager() override {}
316 
317   bool perform_full_hash_check_called_;
318 };
319 
320 class V4LocalDatabaseManagerTest : public PlatformTest {
321  public:
V4LocalDatabaseManagerTest()322   V4LocalDatabaseManagerTest() : task_runner_(new base::TestSimpleTaskRunner) {}
323 
SetUp()324   void SetUp() override {
325     PlatformTest::SetUp();
326 
327     task_environment_ = CreateTestTaskEnvironment();
328 
329     test_shared_loader_factory_ =
330         base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>(
331             &test_url_loader_factory_);
332 
333     ASSERT_TRUE(base_dir_.CreateUniqueTempDir());
334     DVLOG(1) << "base_dir_: " << base_dir_.GetPath().value();
335 
336     extended_reporting_level_ = SBER_LEVEL_OFF;
337     erl_callback_ = base::BindRepeating(
338         &V4LocalDatabaseManagerTest::GetExtendedReportingLevel,
339         base::Unretained(this));
340 
341     v4_local_database_manager_ =
342         base::WrapRefCounted(new V4LocalDatabaseManager(
343             base_dir_.GetPath(), erl_callback_, task_runner_));
344 
345     StartLocalDatabaseManager();
346   }
347 
TearDown()348   void TearDown() override {
349     StopLocalDatabaseManager();
350 
351     PlatformTest::TearDown();
352   }
353 
ForceDisableLocalDatabaseManager()354   void ForceDisableLocalDatabaseManager() {
355     v4_local_database_manager_->enabled_ = false;
356   }
357 
ForceEnableLocalDatabaseManager()358   void ForceEnableLocalDatabaseManager() {
359     v4_local_database_manager_->enabled_ = true;
360   }
361 
GetQueuedChecks()362   const V4LocalDatabaseManager::QueuedChecks& GetQueuedChecks() {
363     return v4_local_database_manager_->queued_checks_;
364   }
365 
GetExtendedReportingLevel()366   ExtendedReportingLevel GetExtendedReportingLevel() {
367     return extended_reporting_level_;
368   }
369 
PopulateArtificialDatabase()370   void PopulateArtificialDatabase() {
371     v4_local_database_manager_->PopulateArtificialDatabase();
372   }
373 
ReplaceV4Database(const StoreAndHashPrefixes & store_and_hash_prefixes,bool stores_available=false)374   void ReplaceV4Database(const StoreAndHashPrefixes& store_and_hash_prefixes,
375                          bool stores_available = false) {
376     // Disable the V4LocalDatabaseManager first so that if the callback to
377     // verify checksum has been scheduled, then it doesn't do anything when it
378     // is called back.
379     ForceDisableLocalDatabaseManager();
380     // Wait to make sure that the callback gets executed if it has already been
381     // scheduled.
382     WaitForTasksOnTaskRunner();
383     // Re-enable the V4LocalDatabaseManager otherwise the checks won't work and
384     // the fake database won't be set either.
385     ForceEnableLocalDatabaseManager();
386 
387     NewDatabaseReadyCallback db_ready_callback =
388         base::BindOnce(&V4LocalDatabaseManager::DatabaseReadyForChecks,
389                        base::Unretained(v4_local_database_manager_.get()));
390     FakeV4Database::Create(task_runner_, std::make_unique<StoreMap>(),
391                            store_and_hash_prefixes,
392                            std::move(db_ready_callback), stores_available);
393     WaitForTasksOnTaskRunner();
394   }
395 
ResetLocalDatabaseManager()396   void ResetLocalDatabaseManager() {
397     StopLocalDatabaseManager();
398     v4_local_database_manager_ =
399         base::WrapRefCounted(new V4LocalDatabaseManager(
400             base_dir_.GetPath(), erl_callback_, task_runner_));
401     StartLocalDatabaseManager();
402   }
403 
ResetV4Database()404   void ResetV4Database() {
405     V4Database::Destroy(std::move(v4_local_database_manager_->v4_database_));
406   }
407 
StartLocalDatabaseManager()408   void StartLocalDatabaseManager() {
409     v4_local_database_manager_->StartOnIOThread(test_shared_loader_factory_,
410                                                 GetTestV4ProtocolConfig());
411   }
412 
StopLocalDatabaseManager()413   void StopLocalDatabaseManager() {
414     if (v4_local_database_manager_) {
415       v4_local_database_manager_->StopOnIOThread(true);
416     }
417 
418     // Force destruction of the database.
419     WaitForTasksOnTaskRunner();
420   }
421 
WaitForTasksOnTaskRunner()422   void WaitForTasksOnTaskRunner() {
423     // Wait for tasks on the task runner so we're sure that the
424     // V4LocalDatabaseManager has read the data from disk.
425     task_runner_->RunPendingTasks();
426     base::RunLoop().RunUntilIdle();
427   }
428 
429   // For those tests that need the fake manager
SetupFakeManager()430   void SetupFakeManager() {
431     // StopLocalDatabaseManager before resetting it because that's what
432     // ~V4LocalDatabaseManager expects.
433     StopLocalDatabaseManager();
434     v4_local_database_manager_ =
435         base::WrapRefCounted(new FakeV4LocalDatabaseManager(
436             base_dir_.GetPath(), erl_callback_, task_runner_));
437     StartLocalDatabaseManager();
438     WaitForTasksOnTaskRunner();
439   }
440 
441   const SBThreatTypeSet usual_threat_types_ = CreateSBThreatTypeSet(
442       {SB_THREAT_TYPE_URL_PHISHING, SB_THREAT_TYPE_URL_MALWARE,
443        SB_THREAT_TYPE_URL_UNWANTED});
444 
445   network::TestURLLoaderFactory test_url_loader_factory_;
446   scoped_refptr<network::SharedURLLoaderFactory> test_shared_loader_factory_;
447   base::ScopedTempDir base_dir_;
448   ExtendedReportingLevel extended_reporting_level_;
449   ExtendedReportingLevelCallback erl_callback_;
450   scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
451   std::unique_ptr<base::test::TaskEnvironment> task_environment_;
452   scoped_refptr<V4LocalDatabaseManager> v4_local_database_manager_;
453 };
454 
TEST_F(V4LocalDatabaseManagerTest,TestGetThreatSource)455 TEST_F(V4LocalDatabaseManagerTest, TestGetThreatSource) {
456   WaitForTasksOnTaskRunner();
457   EXPECT_EQ(ThreatSource::LOCAL_PVER4,
458             v4_local_database_manager_->GetThreatSource());
459 }
460 
TEST_F(V4LocalDatabaseManagerTest,TestIsSupported)461 TEST_F(V4LocalDatabaseManagerTest, TestIsSupported) {
462   WaitForTasksOnTaskRunner();
463   EXPECT_TRUE(v4_local_database_manager_->IsSupported());
464 }
465 
TEST_F(V4LocalDatabaseManagerTest,TestCanCheckUrl)466 TEST_F(V4LocalDatabaseManagerTest, TestCanCheckUrl) {
467   WaitForTasksOnTaskRunner();
468   EXPECT_TRUE(
469       v4_local_database_manager_->CanCheckUrl(GURL("http://example.com/a/")));
470   EXPECT_TRUE(
471       v4_local_database_manager_->CanCheckUrl(GURL("https://example.com/a/")));
472   EXPECT_TRUE(
473       v4_local_database_manager_->CanCheckUrl(GURL("ftp://example.com/a/")));
474   EXPECT_FALSE(
475       v4_local_database_manager_->CanCheckUrl(GURL("adp://example.com/a/")));
476 }
477 
TEST_F(V4LocalDatabaseManagerTest,TestCheckBrowseUrlWithEmptyStoresReturnsNoMatch)478 TEST_F(V4LocalDatabaseManagerTest,
479        TestCheckBrowseUrlWithEmptyStoresReturnsNoMatch) {
480   WaitForTasksOnTaskRunner();
481   // Both the stores are empty right now so CheckBrowseUrl should return true.
482   EXPECT_TRUE(v4_local_database_manager_->CheckBrowseUrl(
483       GURL("http://example.com/a/"), usual_threat_types_, nullptr));
484 }
485 
TEST_F(V4LocalDatabaseManagerTest,TestCheckBrowseUrlWithFakeDbReturnsMatch)486 TEST_F(V4LocalDatabaseManagerTest, TestCheckBrowseUrlWithFakeDbReturnsMatch) {
487   WaitForTasksOnTaskRunner();
488 
489   std::string url_bad_no_scheme("example.com/bad/");
490   FullHash bad_full_hash(crypto::SHA256HashString(url_bad_no_scheme));
491   const HashPrefix bad_hash_prefix(bad_full_hash.substr(0, 5));
492   StoreAndHashPrefixes store_and_hash_prefixes;
493   store_and_hash_prefixes.emplace_back(GetUrlMalwareId(), bad_hash_prefix);
494   ReplaceV4Database(store_and_hash_prefixes);
495 
496   const GURL url_bad("https://" + url_bad_no_scheme);
497   EXPECT_FALSE(v4_local_database_manager_->CheckBrowseUrl(
498       url_bad, usual_threat_types_, nullptr));
499 
500   // Wait for PerformFullHashCheck to complete.
501   WaitForTasksOnTaskRunner();
502 }
503 
TEST_F(V4LocalDatabaseManagerTest,TestCheckCsdWhitelistWithPrefixMatch)504 TEST_F(V4LocalDatabaseManagerTest, TestCheckCsdWhitelistWithPrefixMatch) {
505   // Setup to receive full-hash misses. We won't make URL requests.
506   ScopedFakeGetHashProtocolManagerFactory pin(FullHashInfos({}));
507   ResetLocalDatabaseManager();
508   WaitForTasksOnTaskRunner();
509 
510   std::string url_safe_no_scheme("example.com/safe/");
511   FullHash safe_full_hash(crypto::SHA256HashString(url_safe_no_scheme));
512   const HashPrefix safe_hash_prefix(safe_full_hash.substr(0, 5));
513   StoreAndHashPrefixes store_and_hash_prefixes;
514   store_and_hash_prefixes.emplace_back(GetUrlCsdWhitelistId(),
515                                        safe_hash_prefix);
516   ReplaceV4Database(store_and_hash_prefixes, /* stores_available= */ true);
517 
518   TestAllowlistClient client(
519       /* match_expected= */ false,
520       /* expected_sb_threat_type= */ SB_THREAT_TYPE_CSD_WHITELIST);
521   const GURL url_check("https://" + url_safe_no_scheme);
522   EXPECT_EQ(AsyncMatch::ASYNC, v4_local_database_manager_->CheckCsdWhitelistUrl(
523                                    url_check, &client));
524 
525   EXPECT_FALSE(client.callback_called());
526 
527   // Wait for PerformFullHashCheck to complete.
528   WaitForTasksOnTaskRunner();
529   EXPECT_TRUE(client.callback_called());
530 }
531 
532 // This is like CsdWhitelistWithPrefixMatch, but we also verify the
533 // full-hash-match results in an appropriate callback value.
TEST_F(V4LocalDatabaseManagerTest,TestCheckCsdWhitelistWithPrefixTheFullMatch)534 TEST_F(V4LocalDatabaseManagerTest,
535        TestCheckCsdWhitelistWithPrefixTheFullMatch) {
536   std::string url_safe_no_scheme("example.com/safe/");
537   FullHash safe_full_hash(crypto::SHA256HashString(url_safe_no_scheme));
538 
539   // Setup to receive full-hash hit. We won't make URL requests.
540   FullHashInfos infos(
541       {{safe_full_hash, GetUrlCsdWhitelistId(), base::Time::Now()}});
542   ScopedFakeGetHashProtocolManagerFactory pin(infos);
543   ResetLocalDatabaseManager();
544   WaitForTasksOnTaskRunner();
545 
546   const HashPrefix safe_hash_prefix(safe_full_hash.substr(0, 5));
547   StoreAndHashPrefixes store_and_hash_prefixes;
548   store_and_hash_prefixes.emplace_back(GetUrlCsdWhitelistId(),
549                                        safe_hash_prefix);
550   ReplaceV4Database(store_and_hash_prefixes, /* stores_available= */ true);
551 
552   TestAllowlistClient client(
553       /* match_expected= */ true,
554       /* expected_sb_threat_type= */ SB_THREAT_TYPE_CSD_WHITELIST);
555   const GURL url_check("https://" + url_safe_no_scheme);
556   EXPECT_EQ(AsyncMatch::ASYNC, v4_local_database_manager_->CheckCsdWhitelistUrl(
557                                    url_check, &client));
558 
559   EXPECT_FALSE(client.callback_called());
560 
561   // Wait for PerformFullHashCheck to complete.
562   WaitForTasksOnTaskRunner();
563   EXPECT_TRUE(client.callback_called());
564 }
565 
TEST_F(V4LocalDatabaseManagerTest,TestCheckCsdWhitelistWithFullMatch)566 TEST_F(V4LocalDatabaseManagerTest, TestCheckCsdWhitelistWithFullMatch) {
567   // Setup to receive full-hash misses. We won't make URL requests.
568   ScopedFakeGetHashProtocolManagerFactory pin(FullHashInfos({}));
569   ResetLocalDatabaseManager();
570   WaitForTasksOnTaskRunner();
571 
572   std::string url_safe_no_scheme("example.com/safe/");
573   FullHash safe_full_hash(crypto::SHA256HashString(url_safe_no_scheme));
574   StoreAndHashPrefixes store_and_hash_prefixes;
575   store_and_hash_prefixes.emplace_back(GetUrlCsdWhitelistId(), safe_full_hash);
576   ReplaceV4Database(store_and_hash_prefixes, /* stores_available= */ true);
577 
578   TestAllowlistClient client(
579       /* match_expected= */ false,
580       /* expected_sb_threat_type= */ SB_THREAT_TYPE_CSD_WHITELIST);
581   const GURL url_check("https://" + url_safe_no_scheme);
582   EXPECT_EQ(AsyncMatch::MATCH, v4_local_database_manager_->CheckCsdWhitelistUrl(
583                                    url_check, &client));
584 
585   WaitForTasksOnTaskRunner();
586   EXPECT_FALSE(client.callback_called());
587 }
588 
TEST_F(V4LocalDatabaseManagerTest,TestCheckCsdWhitelistWithNoMatch)589 TEST_F(V4LocalDatabaseManagerTest, TestCheckCsdWhitelistWithNoMatch) {
590   // Setup to receive full-hash misses. We won't make URL requests.
591   ScopedFakeGetHashProtocolManagerFactory pin(FullHashInfos({}));
592   ResetLocalDatabaseManager();
593   WaitForTasksOnTaskRunner();
594 
595   // Add a full hash that won't match the URL we check.
596   std::string url_safe_no_scheme("example.com/safe/");
597   FullHash safe_full_hash(crypto::SHA256HashString(url_safe_no_scheme));
598   StoreAndHashPrefixes store_and_hash_prefixes;
599   store_and_hash_prefixes.emplace_back(GetUrlMalwareId(), safe_full_hash);
600   ReplaceV4Database(store_and_hash_prefixes, /* stores_available= */ true);
601 
602   TestAllowlistClient client(
603       /* match_expected= */ true,
604       /* expected_sb_threat_type= */ SB_THREAT_TYPE_CSD_WHITELIST);
605   const GURL url_check("https://other.com/");
606   EXPECT_EQ(
607       AsyncMatch::NO_MATCH,
608       v4_local_database_manager_->CheckCsdWhitelistUrl(url_check, &client));
609 
610   WaitForTasksOnTaskRunner();
611   EXPECT_FALSE(client.callback_called());
612 }
613 
614 // When allowlist is unavailable, all URLS should be allowed.
TEST_F(V4LocalDatabaseManagerTest,TestCheckCsdWhitelistUnavailable)615 TEST_F(V4LocalDatabaseManagerTest, TestCheckCsdWhitelistUnavailable) {
616   // Setup to receive full-hash misses. We won't make URL requests.
617   ScopedFakeGetHashProtocolManagerFactory pin(FullHashInfos({}));
618   ResetLocalDatabaseManager();
619   WaitForTasksOnTaskRunner();
620 
621   StoreAndHashPrefixes store_and_hash_prefixes;
622   ReplaceV4Database(store_and_hash_prefixes, /* stores_available= */ false);
623 
624   TestAllowlistClient client(
625       /* match_expected= */ false,
626       /* expected_sb_threat_type= */ SB_THREAT_TYPE_CSD_WHITELIST);
627   const GURL url_check("https://other.com/");
628   EXPECT_EQ(AsyncMatch::MATCH, v4_local_database_manager_->CheckCsdWhitelistUrl(
629                                    url_check, &client));
630 
631   WaitForTasksOnTaskRunner();
632   EXPECT_FALSE(client.callback_called());
633 }
634 
TEST_F(V4LocalDatabaseManagerTest,TestCheckBrowseUrlReturnsNoMatchWhenDisabled)635 TEST_F(V4LocalDatabaseManagerTest,
636        TestCheckBrowseUrlReturnsNoMatchWhenDisabled) {
637   WaitForTasksOnTaskRunner();
638 
639   // The same URL returns |false| in the previous test because
640   // v4_local_database_manager_ is enabled.
641   ForceDisableLocalDatabaseManager();
642 
643   EXPECT_TRUE(v4_local_database_manager_->CheckBrowseUrl(
644       GURL("http://example.com/a/"), usual_threat_types_, nullptr));
645 }
646 
647 // Hash prefix matches on the high confidence allowlist, but full hash match
648 // fails.
TEST_F(V4LocalDatabaseManagerTest,TestCheckUrlForHCAllowlistWithPrefixMatchButNoFullHashMatch)649 TEST_F(V4LocalDatabaseManagerTest,
650        TestCheckUrlForHCAllowlistWithPrefixMatchButNoFullHashMatch) {
651   base::test::ScopedFeatureList feature_list;
652   feature_list.InitWithFeatures({safe_browsing::kRealTimeUrlLookupEnabled}, {});
653 
654   std::string url_safe_no_scheme("example.com/safe/");
655   FullHash safe_full_hash(crypto::SHA256HashString(url_safe_no_scheme));
656 
657   // Setup to receive full-hash misses. We won't make URL requests.
658   ScopedFakeGetHashProtocolManagerFactory pin(FullHashInfos({}));
659   ResetLocalDatabaseManager();
660   WaitForTasksOnTaskRunner();
661 
662   // Setup to match hash prefix in the local database.
663   const HashPrefix safe_hash_prefix(safe_full_hash.substr(0, 5));
664   StoreAndHashPrefixes store_and_hash_prefixes;
665   store_and_hash_prefixes.emplace_back(GetUrlHighConfidenceAllowlistId(),
666                                        safe_hash_prefix);
667   ReplaceV4Database(store_and_hash_prefixes, /* stores_available= */ true);
668 
669   // Setup the allowlist client to verify the callback.
670   TestAllowlistClient client(
671       /* match_expected= */ false,
672       /* expected_sb_threat_type= */ SB_THREAT_TYPE_HIGH_CONFIDENCE_ALLOWLIST);
673 
674   // Lookup the high confidence allowlist.
675   const GURL url_check("https://" + url_safe_no_scheme);
676   EXPECT_EQ(AsyncMatch::ASYNC,
677             v4_local_database_manager_->CheckUrlForHighConfidenceAllowlist(
678                 url_check, &client));
679 
680   EXPECT_FALSE(client.callback_called());
681 
682   // Wait for PerformFullHashCheck to complete.
683   WaitForTasksOnTaskRunner();
684   EXPECT_TRUE(client.callback_called());
685 }
686 
687 // Hash prefix matches on the high confidence allowlist, and subsequently the
688 // full hash also matches.
TEST_F(V4LocalDatabaseManagerTest,TestCheckUrlForHCAllowlistWithPrefixMatchAndFullHashMatch)689 TEST_F(V4LocalDatabaseManagerTest,
690        TestCheckUrlForHCAllowlistWithPrefixMatchAndFullHashMatch) {
691   base::test::ScopedFeatureList feature_list;
692   feature_list.InitWithFeatures({safe_browsing::kRealTimeUrlLookupEnabled}, {});
693 
694   std::string url_safe_no_scheme("example.com/safe/");
695   FullHash safe_full_hash(crypto::SHA256HashString(url_safe_no_scheme));
696 
697   // Setup to receive full-hash hit. We won't make URL requests.
698   FullHashInfos infos(
699       {{safe_full_hash, GetUrlHighConfidenceAllowlistId(), base::Time::Now()}});
700   ScopedFakeGetHashProtocolManagerFactory pin(infos);
701   ResetLocalDatabaseManager();
702   WaitForTasksOnTaskRunner();
703 
704   // Setup to match hash prefix in the local database.
705   const HashPrefix safe_hash_prefix(safe_full_hash.substr(0, 5));
706   StoreAndHashPrefixes store_and_hash_prefixes;
707   store_and_hash_prefixes.emplace_back(GetUrlHighConfidenceAllowlistId(),
708                                        safe_hash_prefix);
709   ReplaceV4Database(store_and_hash_prefixes, /* stores_available= */ true);
710 
711   // Setup the allowlist client to verify the callback.
712   TestAllowlistClient client(
713       /* match_expected= */ true,
714       /* expected_sb_threat_type= */ SB_THREAT_TYPE_HIGH_CONFIDENCE_ALLOWLIST);
715 
716   // Lookup the high confidence allowlist.
717   const GURL url_check("https://" + url_safe_no_scheme);
718   EXPECT_EQ(AsyncMatch::ASYNC,
719             v4_local_database_manager_->CheckUrlForHighConfidenceAllowlist(
720                 url_check, &client));
721 
722   EXPECT_FALSE(client.callback_called());
723 
724   // Wait for PerformFullHashCheck to complete.
725   WaitForTasksOnTaskRunner();
726   EXPECT_TRUE(client.callback_called());
727 }
728 
729 // Full hash match on the high confidence allowlist. Returns |MATCH|
730 // synchronously and callback isn't called.
TEST_F(V4LocalDatabaseManagerTest,TestCheckUrlForHCAllowlistWithLocalFullHashMatch)731 TEST_F(V4LocalDatabaseManagerTest,
732        TestCheckUrlForHCAllowlistWithLocalFullHashMatch) {
733   base::test::ScopedFeatureList feature_list;
734   feature_list.InitWithFeatures({safe_browsing::kRealTimeUrlLookupEnabled}, {});
735 
736   std::string url_safe_no_scheme("example.com/safe/");
737   FullHash safe_full_hash(crypto::SHA256HashString(url_safe_no_scheme));
738 
739   // Setup to receive full-hash misses. We won't make URL requests.
740   ScopedFakeGetHashProtocolManagerFactory pin(FullHashInfos({}));
741   ResetLocalDatabaseManager();
742   WaitForTasksOnTaskRunner();
743 
744   // Setup to match full hash in the local database.
745   StoreAndHashPrefixes store_and_hash_prefixes;
746   store_and_hash_prefixes.emplace_back(GetUrlHighConfidenceAllowlistId(),
747                                        safe_full_hash);
748   ReplaceV4Database(store_and_hash_prefixes, /* stores_available= */ true);
749 
750   // Setup the allowlist client to verify the callback isn't called.
751   TestAllowlistClient client(
752       /* match_expected= */ false,
753       /* expected_sb_threat_type= */ SB_THREAT_TYPE_HIGH_CONFIDENCE_ALLOWLIST);
754   const GURL url_check("https://" + url_safe_no_scheme);
755   EXPECT_EQ(AsyncMatch::MATCH,
756             v4_local_database_manager_->CheckUrlForHighConfidenceAllowlist(
757                 url_check, &client));
758 
759   WaitForTasksOnTaskRunner();
760   EXPECT_FALSE(client.callback_called());
761 }
762 
763 // Hash prefix has no match on the high confidence allowlist. Returns |NO_MATCH|
764 // synchronously and callback isn't called.
TEST_F(V4LocalDatabaseManagerTest,TestCheckUrlForHCAllowlistWithNoMatch)765 TEST_F(V4LocalDatabaseManagerTest, TestCheckUrlForHCAllowlistWithNoMatch) {
766   base::test::ScopedFeatureList feature_list;
767   feature_list.InitWithFeatures({safe_browsing::kRealTimeUrlLookupEnabled}, {});
768 
769   std::string url_safe_no_scheme("example.com/safe/");
770   FullHash safe_full_hash(crypto::SHA256HashString(url_safe_no_scheme));
771 
772   // Setup to receive full-hash misses. We won't make URL requests.
773   ScopedFakeGetHashProtocolManagerFactory pin(FullHashInfos({}));
774   ResetLocalDatabaseManager();
775   WaitForTasksOnTaskRunner();
776 
777   // Add a full hash that won't match the URL we check.
778   StoreAndHashPrefixes store_and_hash_prefixes;
779   store_and_hash_prefixes.emplace_back(GetUrlMalwareId(), safe_full_hash);
780   ReplaceV4Database(store_and_hash_prefixes, /* stores_available= */ true);
781 
782   // Setup the allowlist client to verify the callback isn't called.
783   TestAllowlistClient client(
784       /* match_expected= */ false,
785       /* expected_sb_threat_type= */ SB_THREAT_TYPE_HIGH_CONFIDENCE_ALLOWLIST);
786   const GURL url_check("https://example.com/other/");
787   EXPECT_EQ(AsyncMatch::NO_MATCH,
788             v4_local_database_manager_->CheckUrlForHighConfidenceAllowlist(
789                 url_check, &client));
790 
791   WaitForTasksOnTaskRunner();
792   EXPECT_FALSE(client.callback_called());
793 }
794 
795 // When allowlist is unavailable, all URLS should be considered MATCH.
TEST_F(V4LocalDatabaseManagerTest,TestCheckUrlForHCAllowlistUnavailable)796 TEST_F(V4LocalDatabaseManagerTest, TestCheckUrlForHCAllowlistUnavailable) {
797   base::test::ScopedFeatureList feature_list;
798   feature_list.InitWithFeatures({safe_browsing::kRealTimeUrlLookupEnabled}, {});
799 
800   // Setup to receive full-hash misses. We won't make URL requests.
801   ScopedFakeGetHashProtocolManagerFactory pin(FullHashInfos({}));
802   ResetLocalDatabaseManager();
803   WaitForTasksOnTaskRunner();
804 
805   // Setup local database as unavailable.
806   StoreAndHashPrefixes store_and_hash_prefixes;
807   ReplaceV4Database(store_and_hash_prefixes, /* stores_available= */ false);
808 
809   // Setup the allowlist client to verify the callback isn't called.
810   TestAllowlistClient client(
811       /* match_expected= */ false,
812       /* expected_sb_threat_type= */ SB_THREAT_TYPE_HIGH_CONFIDENCE_ALLOWLIST);
813 
814   const GURL url_check("https://example.com/safe");
815   EXPECT_EQ(AsyncMatch::MATCH,
816             v4_local_database_manager_->CheckUrlForHighConfidenceAllowlist(
817                 url_check, &client));
818 
819   WaitForTasksOnTaskRunner();
820   EXPECT_FALSE(client.callback_called());
821 }
822 
TEST_F(V4LocalDatabaseManagerTest,TestGetSeverestThreatTypeAndMetadata)823 TEST_F(V4LocalDatabaseManagerTest, TestGetSeverestThreatTypeAndMetadata) {
824   base::HistogramTester histograms;
825   WaitForTasksOnTaskRunner();
826 
827   FullHash fh_malware("Malware");
828   FullHashInfo fhi_malware(fh_malware, GetUrlMalwareId(), base::Time::Now());
829   fhi_malware.metadata.population_id = "malware_popid";
830 
831   FullHash fh_api("api");
832   FullHashInfo fhi_api(fh_api, GetChromeUrlApiId(), base::Time::Now());
833   fhi_api.metadata.population_id = "api_popid";
834 
835   FullHash fh_example("example");
836   std::vector<FullHashInfo> fhis({fhi_malware, fhi_api});
837   std::vector<FullHash> full_hashes({fh_malware, fh_example, fh_api});
838 
839   std::vector<SBThreatType> full_hash_threat_types(full_hashes.size(),
840                                                    SB_THREAT_TYPE_SAFE);
841   SBThreatType result_threat_type;
842   ThreatMetadata metadata;
843   FullHash matching_full_hash;
844 
845   const std::vector<SBThreatType> expected_full_hash_threat_types(
846       {SB_THREAT_TYPE_URL_MALWARE, SB_THREAT_TYPE_SAFE,
847        SB_THREAT_TYPE_API_ABUSE});
848 
849   v4_local_database_manager_->GetSeverestThreatTypeAndMetadata(
850       fhis, full_hashes, &full_hash_threat_types, &result_threat_type,
851       &metadata, &matching_full_hash);
852   EXPECT_EQ(expected_full_hash_threat_types, full_hash_threat_types);
853 
854   EXPECT_EQ(SB_THREAT_TYPE_URL_MALWARE, result_threat_type);
855   EXPECT_EQ("malware_popid", metadata.population_id);
856   EXPECT_EQ(fh_malware, matching_full_hash);
857 
858   // Reversing the list has no effect.
859   std::reverse(std::begin(fhis), std::end(fhis));
860   full_hash_threat_types.assign(full_hashes.size(), SB_THREAT_TYPE_SAFE);
861 
862   v4_local_database_manager_->GetSeverestThreatTypeAndMetadata(
863       fhis, full_hashes, &full_hash_threat_types, &result_threat_type,
864       &metadata, &matching_full_hash);
865   EXPECT_EQ(expected_full_hash_threat_types, full_hash_threat_types);
866   EXPECT_EQ(SB_THREAT_TYPE_URL_MALWARE, result_threat_type);
867   EXPECT_EQ("malware_popid", metadata.population_id);
868   EXPECT_EQ(fh_malware, matching_full_hash);
869 
870   histograms.ExpectUniqueSample(
871       "SafeBrowsing.V4LocalDatabaseManager.ThreatInfoSize",
872       /* sample */ 2, /* expected_count */ 2);
873 }
874 
TEST_F(V4LocalDatabaseManagerTest,TestChecksAreQueued)875 TEST_F(V4LocalDatabaseManagerTest, TestChecksAreQueued) {
876   const GURL url("https://www.example.com/");
877   TestClient client(SB_THREAT_TYPE_SAFE, url);
878   EXPECT_TRUE(GetQueuedChecks().empty());
879   v4_local_database_manager_->CheckBrowseUrl(url, usual_threat_types_, &client);
880   // The database is unavailable so the check should get queued.
881   EXPECT_EQ(1ul, GetQueuedChecks().size());
882 
883   // The following function waits for the DB to load.
884   WaitForTasksOnTaskRunner();
885   EXPECT_TRUE(GetQueuedChecks().empty());
886 
887   ResetV4Database();
888   v4_local_database_manager_->CheckBrowseUrl(url, usual_threat_types_, &client);
889   // The database is unavailable so the check should get queued.
890   EXPECT_EQ(1ul, GetQueuedChecks().size());
891 
892   StopLocalDatabaseManager();
893   EXPECT_TRUE(GetQueuedChecks().empty());
894 }
895 
896 // Verify that a window where checks cannot be cancelled is closed.
TEST_F(V4LocalDatabaseManagerTest,CancelPending)897 TEST_F(V4LocalDatabaseManagerTest, CancelPending) {
898   // Setup to receive full-hash misses.
899   ScopedFakeGetHashProtocolManagerFactory pin(FullHashInfos({}));
900 
901   // Reset the database manager so it picks up the replacement protocol manager.
902   ResetLocalDatabaseManager();
903   WaitForTasksOnTaskRunner();
904 
905   // Put a match in the db that will cause a protocol-manager request.
906   std::string url_bad_no_scheme("example.com/bad/");
907   FullHash bad_full_hash(crypto::SHA256HashString(url_bad_no_scheme));
908   const HashPrefix bad_hash_prefix(bad_full_hash.substr(0, 5));
909   StoreAndHashPrefixes store_and_hash_prefixes;
910   store_and_hash_prefixes.emplace_back(GetUrlMalwareId(), bad_hash_prefix);
911   ReplaceV4Database(store_and_hash_prefixes);
912 
913   const GURL url_bad("https://" + url_bad_no_scheme);
914   // Test that a request flows through to the callback.
915   {
916     TestClient client(SB_THREAT_TYPE_SAFE, url_bad);
917     EXPECT_FALSE(v4_local_database_manager_->CheckBrowseUrl(
918         url_bad, usual_threat_types_, &client));
919     EXPECT_FALSE(client.on_check_browse_url_result_called());
920     WaitForTasksOnTaskRunner();
921     EXPECT_TRUE(client.on_check_browse_url_result_called());
922   }
923 
924   // Test that cancel prevents the callback from being called.
925   {
926     TestClient client(SB_THREAT_TYPE_SAFE, url_bad);
927     EXPECT_FALSE(v4_local_database_manager_->CheckBrowseUrl(
928         url_bad, usual_threat_types_, &client));
929     v4_local_database_manager_->CancelCheck(&client);
930     EXPECT_FALSE(client.on_check_browse_url_result_called());
931     WaitForTasksOnTaskRunner();
932     EXPECT_FALSE(client.on_check_browse_url_result_called());
933   }
934 }
935 
936 // When the database load flushes the queued requests, make sure that
937 // CancelCheck() is not fatal in the client callback.
TEST_F(V4LocalDatabaseManagerTest,CancelQueued)938 TEST_F(V4LocalDatabaseManagerTest, CancelQueued) {
939   const GURL url("http://example.com/a/");
940 
941   TestClient client1(SB_THREAT_TYPE_SAFE, url,
942                      v4_local_database_manager_.get());
943   TestClient client2(SB_THREAT_TYPE_SAFE, url);
944   EXPECT_FALSE(v4_local_database_manager_->CheckBrowseUrl(
945       url, usual_threat_types_, &client1));
946   EXPECT_FALSE(v4_local_database_manager_->CheckBrowseUrl(
947       url, usual_threat_types_, &client2));
948   EXPECT_EQ(2ul, GetQueuedChecks().size());
949   EXPECT_FALSE(client1.on_check_browse_url_result_called());
950   EXPECT_FALSE(client2.on_check_browse_url_result_called());
951   WaitForTasksOnTaskRunner();
952   EXPECT_TRUE(client1.on_check_browse_url_result_called());
953   EXPECT_TRUE(client2.on_check_browse_url_result_called());
954 }
955 
956 // This test is somewhat similar to TestCheckBrowseUrlWithFakeDbReturnsMatch but
957 // it uses a fake V4LocalDatabaseManager to assert that PerformFullHashCheck is
958 // called async.
TEST_F(V4LocalDatabaseManagerTest,PerformFullHashCheckCalledAsync)959 TEST_F(V4LocalDatabaseManagerTest, PerformFullHashCheckCalledAsync) {
960   SetupFakeManager();
961 
962   std::string url_bad_no_scheme("example.com/bad/");
963   FullHash bad_full_hash(crypto::SHA256HashString(url_bad_no_scheme));
964   const HashPrefix bad_hash_prefix(bad_full_hash.substr(0, 5));
965   StoreAndHashPrefixes store_and_hash_prefixes;
966   store_and_hash_prefixes.emplace_back(GetUrlMalwareId(), bad_hash_prefix);
967   ReplaceV4Database(store_and_hash_prefixes);
968 
969   const GURL url_bad("https://" + url_bad_no_scheme);
970   // The fake database returns a matched hash prefix.
971   EXPECT_FALSE(v4_local_database_manager_->CheckBrowseUrl(
972       url_bad, usual_threat_types_, nullptr));
973 
974   EXPECT_FALSE(FakeV4LocalDatabaseManager::PerformFullHashCheckCalled(
975       v4_local_database_manager_));
976 
977   // Wait for PerformFullHashCheck to complete.
978   WaitForTasksOnTaskRunner();
979 
980   EXPECT_TRUE(FakeV4LocalDatabaseManager::PerformFullHashCheckCalled(
981       v4_local_database_manager_));
982 }
983 
TEST_F(V4LocalDatabaseManagerTest,UsingWeakPtrDropsCallback)984 TEST_F(V4LocalDatabaseManagerTest, UsingWeakPtrDropsCallback) {
985   SetupFakeManager();
986 
987   std::string url_bad_no_scheme("example.com/bad/");
988   FullHash bad_full_hash(crypto::SHA256HashString(url_bad_no_scheme));
989   const HashPrefix bad_hash_prefix(bad_full_hash.substr(0, 5));
990   StoreAndHashPrefixes store_and_hash_prefixes;
991   store_and_hash_prefixes.emplace_back(GetUrlMalwareId(), bad_hash_prefix);
992   ReplaceV4Database(store_and_hash_prefixes);
993 
994   const GURL url_bad("https://" + url_bad_no_scheme);
995   EXPECT_FALSE(v4_local_database_manager_->CheckBrowseUrl(
996       url_bad, usual_threat_types_, nullptr));
997   v4_local_database_manager_->StopOnIOThread(true);
998 
999   // Release the V4LocalDatabaseManager object right away before the callback
1000   // gets called. When the callback gets called, without using a weak-ptr
1001   // factory, this leads to a use after free. However, using the weak-ptr means
1002   // that the callback is simply dropped.
1003   v4_local_database_manager_ = nullptr;
1004 
1005   // Wait for the tasks scheduled by StopOnIOThread to complete.
1006   WaitForTasksOnTaskRunner();
1007 }
1008 
TEST_F(V4LocalDatabaseManagerTest,TestMatchDownloadWhitelistString)1009 TEST_F(V4LocalDatabaseManagerTest, TestMatchDownloadWhitelistString) {
1010   SetupFakeManager();
1011   const std::string good_cert = "Good Cert";
1012   const std::string other_cert = "Other Cert";
1013   FullHash good_hash(crypto::SHA256HashString(good_cert));
1014 
1015   StoreAndHashPrefixes store_and_hash_prefixes;
1016   store_and_hash_prefixes.emplace_back(GetCertCsdDownloadWhitelistId(),
1017                                        good_hash);
1018 
1019   ReplaceV4Database(store_and_hash_prefixes, false /* not available */);
1020   // Verify it defaults to false when DB is not available.
1021   EXPECT_FALSE(
1022       v4_local_database_manager_->MatchDownloadWhitelistString(good_cert));
1023 
1024   ReplaceV4Database(store_and_hash_prefixes, true /* available */);
1025   // Not whitelisted.
1026   EXPECT_FALSE(
1027       v4_local_database_manager_->MatchDownloadWhitelistString(other_cert));
1028   // Whitelisted.
1029   EXPECT_TRUE(
1030       v4_local_database_manager_->MatchDownloadWhitelistString(good_cert));
1031 
1032   EXPECT_FALSE(FakeV4LocalDatabaseManager::PerformFullHashCheckCalled(
1033       v4_local_database_manager_));
1034 }
1035 
TEST_F(V4LocalDatabaseManagerTest,TestMatchDownloadWhitelistUrl)1036 TEST_F(V4LocalDatabaseManagerTest, TestMatchDownloadWhitelistUrl) {
1037   SetupFakeManager();
1038   GURL good_url("http://safe.com");
1039   GURL other_url("http://iffy.com");
1040 
1041   StoreAndHashPrefixes store_and_hash_prefixes;
1042   store_and_hash_prefixes.emplace_back(GetUrlCsdDownloadWhitelistId(),
1043                                        HashForUrl(good_url));
1044 
1045   ReplaceV4Database(store_and_hash_prefixes, false /* not available */);
1046   // Verify it defaults to false when DB is not available.
1047   EXPECT_FALSE(v4_local_database_manager_->MatchDownloadWhitelistUrl(good_url));
1048 
1049   ReplaceV4Database(store_and_hash_prefixes, true /* available */);
1050   // Not whitelisted.
1051   EXPECT_FALSE(
1052       v4_local_database_manager_->MatchDownloadWhitelistUrl(other_url));
1053   // Whitelisted.
1054   EXPECT_TRUE(v4_local_database_manager_->MatchDownloadWhitelistUrl(good_url));
1055 
1056   EXPECT_FALSE(FakeV4LocalDatabaseManager::PerformFullHashCheckCalled(
1057       v4_local_database_manager_));
1058 }
1059 
TEST_F(V4LocalDatabaseManagerTest,TestMatchMalwareIP)1060 TEST_F(V4LocalDatabaseManagerTest, TestMatchMalwareIP) {
1061   SetupFakeManager();
1062 
1063   // >>> hashlib.sha1(socket.inet_pton(socket.AF_INET6,
1064   // '::ffff:192.168.1.2')).digest() + chr(128)
1065   // '\xb3\xe0z\xafAv#h\x9a\xcf<\xf3ee\x94\xda\xf6y\xb1\xad\x80'
1066   StoreAndHashPrefixes store_and_hash_prefixes;
1067   store_and_hash_prefixes.emplace_back(GetIpMalwareId(),
1068                                        FullHash("\xB3\xE0z\xAF"
1069                                                 "Av#h\x9A\xCF<\xF3"
1070                                                 "ee\x94\xDA\xF6y\xB1\xAD\x80"));
1071   ReplaceV4Database(store_and_hash_prefixes);
1072 
1073   EXPECT_FALSE(v4_local_database_manager_->MatchMalwareIP(""));
1074   // Not blacklisted.
1075   EXPECT_FALSE(v4_local_database_manager_->MatchMalwareIP("192.168.1.1"));
1076   // Blacklisted.
1077   EXPECT_TRUE(v4_local_database_manager_->MatchMalwareIP("192.168.1.2"));
1078 
1079   EXPECT_FALSE(FakeV4LocalDatabaseManager::PerformFullHashCheckCalled(
1080       v4_local_database_manager_));
1081 }
1082 
1083 // This verifies the fix for race in http://crbug.com/660293
TEST_F(V4LocalDatabaseManagerTest,TestCheckBrowseUrlWithSameClientAndCancel)1084 TEST_F(V4LocalDatabaseManagerTest, TestCheckBrowseUrlWithSameClientAndCancel) {
1085   ScopedFakeGetHashProtocolManagerFactory pin(FullHashInfos({}));
1086   // Reset the database manager so it picks up the replacement protocol manager.
1087   ResetLocalDatabaseManager();
1088   WaitForTasksOnTaskRunner();
1089 
1090   StoreAndHashPrefixes store_and_hash_prefixes;
1091   store_and_hash_prefixes.emplace_back(GetUrlMalwareId(),
1092                                        HashPrefix("sن\340\t\006_"));
1093   ReplaceV4Database(store_and_hash_prefixes);
1094 
1095   GURL first_url("http://example.com/a");
1096   GURL second_url("http://example.com/");
1097   TestClient client(SB_THREAT_TYPE_SAFE, first_url);
1098   // The fake database returns a matched hash prefix.
1099   EXPECT_FALSE(v4_local_database_manager_->CheckBrowseUrl(
1100       first_url, usual_threat_types_, &client));
1101 
1102   // That check gets queued. Now, let's cancel the check. After this, we should
1103   // not receive a call for |OnCheckBrowseUrlResult| with |first_url|.
1104   v4_local_database_manager_->CancelCheck(&client);
1105 
1106   // Now, re-use that client but for |second_url|.
1107   client.mutable_expected_urls()->assign(1, second_url);
1108   EXPECT_FALSE(v4_local_database_manager_->CheckBrowseUrl(
1109       second_url, usual_threat_types_, &client));
1110 
1111   // Wait for PerformFullHashCheck to complete.
1112   WaitForTasksOnTaskRunner();
1113   // |on_check_browse_url_result_called_| is true only if OnCheckBrowseUrlResult
1114   // gets called with the |url| equal to |expected_url|, which is |second_url|
1115   // in
1116   // this test.
1117   EXPECT_TRUE(client.on_check_browse_url_result_called());
1118 }
1119 
TEST_F(V4LocalDatabaseManagerTest,TestCheckResourceUrl)1120 TEST_F(V4LocalDatabaseManagerTest, TestCheckResourceUrl) {
1121   // Setup to receive full-hash misses.
1122   ScopedFakeGetHashProtocolManagerFactory pin(FullHashInfos({}));
1123 
1124   // Reset the database manager so it picks up the replacement protocol manager.
1125   ResetLocalDatabaseManager();
1126   WaitForTasksOnTaskRunner();
1127 
1128   std::string url_bad_no_scheme("example.com/bad/");
1129   FullHash bad_full_hash(crypto::SHA256HashString(url_bad_no_scheme));
1130   const HashPrefix bad_hash_prefix(bad_full_hash.substr(0, 5));
1131   StoreAndHashPrefixes store_and_hash_prefixes;
1132   store_and_hash_prefixes.emplace_back(GetChromeUrlClientIncidentId(),
1133                                        bad_hash_prefix);
1134   ReplaceV4Database(store_and_hash_prefixes, /* stores_available= */ true);
1135 
1136   const GURL url_bad("https://" + url_bad_no_scheme);
1137   TestClient client(SB_THREAT_TYPE_SAFE, url_bad);
1138   EXPECT_FALSE(v4_local_database_manager_->CheckResourceUrl(url_bad, &client));
1139   EXPECT_FALSE(client.on_check_resource_url_result_called());
1140   WaitForTasksOnTaskRunner();
1141   EXPECT_TRUE(client.on_check_resource_url_result_called());
1142 }
1143 
TEST_F(V4LocalDatabaseManagerTest,TestSubresourceFilterCallback)1144 TEST_F(V4LocalDatabaseManagerTest, TestSubresourceFilterCallback) {
1145   // Setup to receive full-hash misses.
1146   ScopedFakeGetHashProtocolManagerFactory pin(FullHashInfos({}));
1147 
1148   // Reset the database manager so it picks up the replacement protocol manager.
1149   ResetLocalDatabaseManager();
1150   WaitForTasksOnTaskRunner();
1151 
1152   std::string url_bad_no_scheme("example.com/bad/");
1153   FullHash bad_full_hash(crypto::SHA256HashString(url_bad_no_scheme));
1154   const HashPrefix bad_hash_prefix(bad_full_hash.substr(0, 5));
1155 
1156   // Put a match in the db that will cause a protocol-manager request.
1157   StoreAndHashPrefixes store_and_hash_prefixes;
1158   store_and_hash_prefixes.emplace_back(GetUrlSubresourceFilterId(),
1159                                        bad_hash_prefix);
1160   ReplaceV4Database(store_and_hash_prefixes, /* stores_available= */ true);
1161 
1162   const GURL url_bad("https://" + url_bad_no_scheme);
1163   // Test that a request flows through to the callback.
1164   {
1165     TestClient client(SB_THREAT_TYPE_SAFE, url_bad);
1166     EXPECT_FALSE(v4_local_database_manager_->CheckUrlForSubresourceFilter(
1167         url_bad, &client));
1168     EXPECT_FALSE(client.on_check_browse_url_result_called());
1169     WaitForTasksOnTaskRunner();
1170     EXPECT_TRUE(client.on_check_browse_url_result_called());
1171   }
1172 }
1173 
TEST_F(V4LocalDatabaseManagerTest,TestCheckResourceUrlReturnsBad)1174 TEST_F(V4LocalDatabaseManagerTest, TestCheckResourceUrlReturnsBad) {
1175   // Setup to receive full-hash hit.
1176   std::string url_bad_no_scheme("example.com/bad/");
1177   FullHash bad_full_hash(crypto::SHA256HashString(url_bad_no_scheme));
1178   FullHashInfo fhi(bad_full_hash, GetChromeUrlClientIncidentId(), base::Time());
1179   ScopedFakeGetHashProtocolManagerFactory pin(FullHashInfos({fhi}));
1180 
1181   // Reset the database manager so it picks up the replacement protocol manager.
1182   ResetLocalDatabaseManager();
1183   WaitForTasksOnTaskRunner();
1184 
1185   // Put a match in the db that will cause a protocol-manager request.
1186   const HashPrefix bad_hash_prefix(bad_full_hash.substr(0, 5));
1187   StoreAndHashPrefixes store_and_hash_prefixes;
1188   store_and_hash_prefixes.emplace_back(GetChromeUrlClientIncidentId(),
1189                                        bad_hash_prefix);
1190   ReplaceV4Database(store_and_hash_prefixes, /* stores_available= */ true);
1191 
1192   const GURL url_bad("https://" + url_bad_no_scheme);
1193   TestClient client(SB_THREAT_TYPE_BLACKLISTED_RESOURCE, url_bad);
1194   EXPECT_FALSE(v4_local_database_manager_->CheckResourceUrl(url_bad, &client));
1195   EXPECT_FALSE(client.on_check_resource_url_result_called());
1196   WaitForTasksOnTaskRunner();
1197   EXPECT_TRUE(client.on_check_resource_url_result_called());
1198 }
1199 
TEST_F(V4LocalDatabaseManagerTest,TestCheckExtensionIDsNothingBlacklisted)1200 TEST_F(V4LocalDatabaseManagerTest, TestCheckExtensionIDsNothingBlacklisted) {
1201   // Setup to receive full-hash misses.
1202   ScopedFakeGetHashProtocolManagerFactory pin(FullHashInfos({}));
1203 
1204   // Reset the database manager so it picks up the replacement protocol manager.
1205   ResetLocalDatabaseManager();
1206   WaitForTasksOnTaskRunner();
1207 
1208   // bad_extension_id is in the local DB but the full hash won't match.
1209   const FullHash bad_extension_id("aaaabbbbccccdddd"),
1210       good_extension_id("ddddccccbbbbaaaa");
1211 
1212   // Put a match in the db that will cause a protocol-manager request.
1213   StoreAndHashPrefixes store_and_hash_prefixes;
1214   store_and_hash_prefixes.emplace_back(GetChromeExtMalwareId(),
1215                                        bad_extension_id);
1216   ReplaceV4Database(store_and_hash_prefixes, /* stores_available= */ true);
1217 
1218   const std::set<FullHash> expected_bad_crxs({});
1219   const std::set<FullHash> extension_ids({good_extension_id, bad_extension_id});
1220   TestExtensionClient client(expected_bad_crxs);
1221   EXPECT_FALSE(
1222       v4_local_database_manager_->CheckExtensionIDs(extension_ids, &client));
1223   EXPECT_FALSE(client.on_check_extensions_result_called());
1224   WaitForTasksOnTaskRunner();
1225   EXPECT_TRUE(client.on_check_extensions_result_called());
1226 }
1227 
TEST_F(V4LocalDatabaseManagerTest,TestCheckExtensionIDsOneIsBlacklisted)1228 TEST_F(V4LocalDatabaseManagerTest, TestCheckExtensionIDsOneIsBlacklisted) {
1229   // bad_extension_id is in the local DB and the full hash will match.
1230   const FullHash bad_extension_id("aaaabbbbccccdddd"),
1231       good_extension_id("ddddccccbbbbaaaa");
1232   FullHashInfo fhi(bad_extension_id, GetChromeExtMalwareId(), base::Time());
1233 
1234   // Setup to receive full-hash hit.
1235   ScopedFakeGetHashProtocolManagerFactory pin(FullHashInfos({fhi}));
1236 
1237   // Reset the database manager so it picks up the replacement protocol manager.
1238   ResetLocalDatabaseManager();
1239   WaitForTasksOnTaskRunner();
1240 
1241   // Put a match in the db that will cause a protocol-manager request.
1242   StoreAndHashPrefixes store_and_hash_prefixes;
1243   store_and_hash_prefixes.emplace_back(GetChromeExtMalwareId(),
1244                                        bad_extension_id);
1245   ReplaceV4Database(store_and_hash_prefixes, /* stores_available= */ true);
1246 
1247   const std::set<FullHash> expected_bad_crxs({bad_extension_id});
1248   const std::set<FullHash> extension_ids({good_extension_id, bad_extension_id});
1249   TestExtensionClient client(expected_bad_crxs);
1250   EXPECT_FALSE(
1251       v4_local_database_manager_->CheckExtensionIDs(extension_ids, &client));
1252   EXPECT_FALSE(client.on_check_extensions_result_called());
1253   WaitForTasksOnTaskRunner();
1254   EXPECT_TRUE(client.on_check_extensions_result_called());
1255 }
1256 
TEST_F(V4LocalDatabaseManagerTest,TestCheckDownloadUrlNothingBlacklisted)1257 TEST_F(V4LocalDatabaseManagerTest, TestCheckDownloadUrlNothingBlacklisted) {
1258   // Setup to receive full-hash misses.
1259   ScopedFakeGetHashProtocolManagerFactory pin(FullHashInfos({}));
1260 
1261   // Reset the database manager so it picks up the replacement protocol manager.
1262   ResetLocalDatabaseManager();
1263   WaitForTasksOnTaskRunner();
1264 
1265   // Put a match in the db that will cause a protocol-manager request.
1266   std::string url_bad_no_scheme("example.com/bad/");
1267   FullHash bad_full_hash(crypto::SHA256HashString(url_bad_no_scheme));
1268   const HashPrefix bad_hash_prefix(bad_full_hash.substr(0, 5));
1269   StoreAndHashPrefixes store_and_hash_prefixes;
1270   store_and_hash_prefixes.emplace_back(GetUrlMalBinId(), bad_hash_prefix);
1271   ReplaceV4Database(store_and_hash_prefixes, /* stores_available= */ true);
1272 
1273   const GURL url_bad("https://" + url_bad_no_scheme),
1274       url_good("https://example.com/good/");
1275   const std::vector<GURL> url_chain({url_good, url_bad});
1276 
1277   TestClient client(SB_THREAT_TYPE_SAFE, url_chain);
1278   EXPECT_FALSE(
1279       v4_local_database_manager_->CheckDownloadUrl(url_chain, &client));
1280   EXPECT_FALSE(client.on_check_download_urls_result_called());
1281   WaitForTasksOnTaskRunner();
1282   EXPECT_TRUE(client.on_check_download_urls_result_called());
1283 }
1284 
TEST_F(V4LocalDatabaseManagerTest,TestCheckDownloadUrlWithOneBlacklisted)1285 TEST_F(V4LocalDatabaseManagerTest, TestCheckDownloadUrlWithOneBlacklisted) {
1286   // Setup to receive full-hash hit.
1287   std::string url_bad_no_scheme("example.com/bad/");
1288   FullHash bad_full_hash(crypto::SHA256HashString(url_bad_no_scheme));
1289   FullHashInfo fhi(bad_full_hash, GetUrlMalBinId(), base::Time());
1290   ScopedFakeGetHashProtocolManagerFactory pin(FullHashInfos({fhi}));
1291 
1292   // Reset the database manager so it picks up the replacement protocol manager.
1293   ResetLocalDatabaseManager();
1294   WaitForTasksOnTaskRunner();
1295 
1296   const GURL url_bad("https://" + url_bad_no_scheme),
1297       url_good("https://example.com/good/");
1298   const std::vector<GURL> url_chain({url_good, url_bad});
1299 
1300   // Put a match in the db that will cause a protocol-manager request.
1301   const HashPrefix bad_hash_prefix(bad_full_hash.substr(0, 5));
1302   StoreAndHashPrefixes store_and_hash_prefixes;
1303   store_and_hash_prefixes.emplace_back(GetUrlMalBinId(), bad_hash_prefix);
1304   ReplaceV4Database(store_and_hash_prefixes, /* stores_available= */ true);
1305 
1306   TestClient client(SB_THREAT_TYPE_URL_BINARY_MALWARE, url_chain);
1307   EXPECT_FALSE(
1308       v4_local_database_manager_->CheckDownloadUrl(url_chain, &client));
1309   EXPECT_FALSE(client.on_check_download_urls_result_called());
1310   WaitForTasksOnTaskRunner();
1311   EXPECT_TRUE(client.on_check_download_urls_result_called());
1312 }
1313 
TEST_F(V4LocalDatabaseManagerTest,NotificationOnUpdate)1314 TEST_F(V4LocalDatabaseManagerTest, NotificationOnUpdate) {
1315   base::RunLoop run_loop;
1316   auto callback_subscription =
1317       v4_local_database_manager_->RegisterDatabaseUpdatedCallback(
1318           run_loop.QuitClosure());
1319 
1320   // Creates and associates a V4Database instance.
1321   StoreAndHashPrefixes store_and_hash_prefixes;
1322   ReplaceV4Database(store_and_hash_prefixes);
1323 
1324   v4_local_database_manager_->DatabaseUpdated();
1325 
1326   run_loop.Run();
1327 }
1328 
TEST_F(V4LocalDatabaseManagerTest,FlagOneUrlAsPhishing)1329 TEST_F(V4LocalDatabaseManagerTest, FlagOneUrlAsPhishing) {
1330   SetupFakeManager();
1331   base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
1332       "mark_as_phishing", "https://example.com/1/");
1333   PopulateArtificialDatabase();
1334 
1335   const GURL url_bad("https://example.com/1/");
1336   EXPECT_FALSE(v4_local_database_manager_->CheckBrowseUrl(
1337       url_bad, usual_threat_types_, nullptr));
1338   // PerformFullHashCheck will not be called if there is a match within the
1339   // artificial database
1340   EXPECT_FALSE(FakeV4LocalDatabaseManager::PerformFullHashCheckCalled(
1341       v4_local_database_manager_));
1342 
1343   const GURL url_good("https://other.example.com");
1344   EXPECT_TRUE(v4_local_database_manager_->CheckBrowseUrl(
1345       url_good, usual_threat_types_, nullptr));
1346 
1347   StopLocalDatabaseManager();
1348 }
1349 
TEST_F(V4LocalDatabaseManagerTest,FlagOneUrlAsMalware)1350 TEST_F(V4LocalDatabaseManagerTest, FlagOneUrlAsMalware) {
1351   SetupFakeManager();
1352   base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
1353       "mark_as_malware", "https://example.com/1/");
1354   PopulateArtificialDatabase();
1355 
1356   const GURL url_bad("https://example.com/1/");
1357   EXPECT_FALSE(v4_local_database_manager_->CheckBrowseUrl(
1358       url_bad, usual_threat_types_, nullptr));
1359   // PerformFullHashCheck will not be called if there is a match within the
1360   // artificial database
1361   EXPECT_FALSE(FakeV4LocalDatabaseManager::PerformFullHashCheckCalled(
1362       v4_local_database_manager_));
1363 
1364   const GURL url_good("https://other.example.com");
1365   EXPECT_TRUE(v4_local_database_manager_->CheckBrowseUrl(
1366       url_good, usual_threat_types_, nullptr));
1367 
1368   StopLocalDatabaseManager();
1369 }
1370 
TEST_F(V4LocalDatabaseManagerTest,FlagOneUrlAsUWS)1371 TEST_F(V4LocalDatabaseManagerTest, FlagOneUrlAsUWS) {
1372   SetupFakeManager();
1373   base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
1374       "mark_as_uws", "https://example.com/1/");
1375   PopulateArtificialDatabase();
1376 
1377   const GURL url_bad("https://example.com/1/");
1378   EXPECT_FALSE(v4_local_database_manager_->CheckBrowseUrl(
1379       url_bad, usual_threat_types_, nullptr));
1380   // PerformFullHashCheck will not be called if there is a match within the
1381   // artificial database
1382   EXPECT_FALSE(FakeV4LocalDatabaseManager::PerformFullHashCheckCalled(
1383       v4_local_database_manager_));
1384 
1385   const GURL url_good("https://other.example.com");
1386   EXPECT_TRUE(v4_local_database_manager_->CheckBrowseUrl(
1387       url_good, usual_threat_types_, nullptr));
1388 
1389   StopLocalDatabaseManager();
1390 }
1391 
TEST_F(V4LocalDatabaseManagerTest,FlagMultipleUrls)1392 TEST_F(V4LocalDatabaseManagerTest, FlagMultipleUrls) {
1393   SetupFakeManager();
1394   base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
1395       "mark_as_phishing", "https://example.com/1/");
1396   base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
1397       "mark_as_malware", "https://2.example.com");
1398   base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
1399       "mark_as_uws", "https://example.test.com");
1400   PopulateArtificialDatabase();
1401 
1402   const GURL url_phishing("https://example.com/1/");
1403   EXPECT_FALSE(v4_local_database_manager_->CheckBrowseUrl(
1404       url_phishing, usual_threat_types_, nullptr));
1405   const GURL url_malware("https://2.example.com");
1406   EXPECT_FALSE(v4_local_database_manager_->CheckBrowseUrl(
1407       url_malware, usual_threat_types_, nullptr));
1408   const GURL url_uws("https://example.test.com");
1409   EXPECT_FALSE(v4_local_database_manager_->CheckBrowseUrl(
1410       url_uws, usual_threat_types_, nullptr));
1411   // PerformFullHashCheck will not be called if there is a match within the
1412   // artificial database
1413   EXPECT_FALSE(FakeV4LocalDatabaseManager::PerformFullHashCheckCalled(
1414       v4_local_database_manager_));
1415 
1416   const GURL url_good("https://other.example.com");
1417   EXPECT_TRUE(v4_local_database_manager_->CheckBrowseUrl(
1418       url_good, usual_threat_types_, nullptr));
1419 
1420   StopLocalDatabaseManager();
1421 }
1422 
1423 }  // namespace safe_browsing
1424