1// Copyright (c) 2011 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// This test creates a safebrowsing service using test safebrowsing database
6// and a test protocol manager. It is used to test logics in safebrowsing
7// service.
8
9#include "base/command_line.h"
10#include "base/memory/ref_counted.h"
11#include "base/metrics/histogram.h"
12#include "crypto/sha2.h"
13#include "chrome/browser/browser_process.h"
14#include "chrome/browser/safe_browsing/safe_browsing_database.h"
15#include "chrome/browser/safe_browsing/safe_browsing_service.h"
16#include "chrome/browser/safe_browsing/safe_browsing_util.h"
17#include "chrome/browser/safe_browsing/protocol_manager.h"
18#include "chrome/browser/ui/browser.h"
19#include "chrome/common/chrome_switches.h"
20#include "chrome/test/in_process_browser_test.h"
21#include "chrome/test/ui_test_utils.h"
22#include "content/browser/browser_thread.h"
23#include "content/browser/renderer_host/resource_dispatcher_host.h"
24#include "content/browser/tab_contents/tab_contents.h"
25#include "content/browser/tab_contents/tab_contents_view.h"
26
27using base::Histogram;
28using base::StatisticsRecorder;
29
30// A SafeBrowingDatabase class that allows us to inject the malicious URLs.
31class TestSafeBrowsingDatabase :  public SafeBrowsingDatabase {
32 public:
33  TestSafeBrowsingDatabase() {}
34
35  virtual ~TestSafeBrowsingDatabase() {}
36
37  // Initializes the database with the given filename.
38  virtual void Init(const FilePath& filename) {}
39
40  // Deletes the current database and creates a new one.
41  virtual bool ResetDatabase() {
42    badurls_.clear();
43    return true;
44  }
45
46  // Called on the IO thread to check if the given URL is safe or not.  If we
47  // can synchronously determine that the URL is safe, CheckUrl returns true,
48  // otherwise it returns false.
49  virtual bool ContainsBrowseUrl(const GURL& url,
50                                 std::string* matching_list,
51                                 std::vector<SBPrefix>* prefix_hits,
52                                 std::vector<SBFullHashResult>* full_hits,
53                                 base::Time last_update) {
54    std::vector<GURL> urls(1, url);
55    return ContainsUrl(safe_browsing_util::kMalwareList,
56                       safe_browsing_util::kPhishingList,
57                       urls, prefix_hits, full_hits);
58  }
59  virtual bool ContainsDownloadUrl(const std::vector<GURL>& urls,
60                                   std::vector<SBPrefix>* prefix_hits) {
61    std::vector<SBFullHashResult> full_hits;
62    bool found = ContainsUrl(safe_browsing_util::kBinUrlList,
63                             safe_browsing_util::kBinHashList,
64                             urls, prefix_hits, &full_hits);
65    if (!found)
66      return false;
67    DCHECK_LE(1U, prefix_hits->size());
68    return true;
69  }
70  virtual bool ContainsDownloadHashPrefix(const SBPrefix& prefix) {
71    return download_digest_prefix_.count(prefix) > 0;
72  }
73  virtual bool ContainsCsdWhitelistedUrl(const GURL& url) {
74    return true;
75  }
76  virtual bool UpdateStarted(std::vector<SBListChunkRanges>* lists) {
77    ADD_FAILURE() << "Not implemented.";
78    return false;
79  }
80  virtual void InsertChunks(const std::string& list_name,
81                            const SBChunkList& chunks) {
82    ADD_FAILURE() << "Not implemented.";
83  }
84  virtual void DeleteChunks(const std::vector<SBChunkDelete>& chunk_deletes) {
85    ADD_FAILURE() << "Not implemented.";
86  }
87  virtual void UpdateFinished(bool update_succeeded) {
88    ADD_FAILURE() << "Not implemented.";
89  }
90  virtual void CacheHashResults(const std::vector<SBPrefix>& prefixes,
91      const std::vector<SBFullHashResult>& full_hits) {
92    // Do nothing for the cache.
93    return;
94  }
95
96  // Fill up the database with test URL.
97  void AddUrl(const GURL& url,
98              const std::string& list_name,
99              const std::vector<SBPrefix>& prefix_hits,
100              const std::vector<SBFullHashResult>& full_hits) {
101    badurls_[url.spec()].list_name = list_name;
102    badurls_[url.spec()].prefix_hits = prefix_hits;
103    badurls_[url.spec()].full_hits = full_hits;
104  }
105
106  // Fill up the database with test hash digest.
107  void AddDownloadPrefix(SBPrefix prefix) {
108    download_digest_prefix_.insert(prefix);
109  }
110
111 private:
112  struct Hits {
113    std::string list_name;
114    std::vector<SBPrefix> prefix_hits;
115    std::vector<SBFullHashResult> full_hits;
116  };
117
118  bool ContainsUrl(const std::string& list_name0,
119                   const std::string& list_name1,
120                   const std::vector<GURL>& urls,
121                   std::vector<SBPrefix>* prefix_hits,
122                   std::vector<SBFullHashResult>* full_hits) {
123    bool hit = false;
124    for (size_t i = 0; i < urls.size(); ++i) {
125      const GURL& url = urls[i];
126      base::hash_map<std::string, Hits>::const_iterator
127          badurls_it = badurls_.find(url.spec());
128
129      if (badurls_it == badurls_.end())
130        continue;
131
132      if (badurls_it->second.list_name == list_name0 ||
133          badurls_it->second.list_name == list_name1) {
134        prefix_hits->insert(prefix_hits->end(),
135                            badurls_it->second.prefix_hits.begin(),
136                            badurls_it->second.prefix_hits.end());
137        full_hits->insert(full_hits->end(),
138                          badurls_it->second.full_hits.begin(),
139                          badurls_it->second.full_hits.end());
140        hit = true;
141      }
142
143    }
144    return hit;
145  }
146
147  base::hash_map<std::string, Hits> badurls_;
148  base::hash_set<SBPrefix> download_digest_prefix_;
149};
150
151// Factory that creates TestSafeBrowsingDatabase instances.
152class TestSafeBrowsingDatabaseFactory : public SafeBrowsingDatabaseFactory {
153 public:
154  TestSafeBrowsingDatabaseFactory() : db_(NULL) {}
155  virtual ~TestSafeBrowsingDatabaseFactory() {}
156
157  virtual SafeBrowsingDatabase* CreateSafeBrowsingDatabase(
158      bool enable_download_protection,
159      bool enable_client_side_whitelist) {
160    db_ = new TestSafeBrowsingDatabase();
161    return db_;
162  }
163  TestSafeBrowsingDatabase* GetDb() {
164    return db_;
165  }
166 private:
167  // Owned by the SafebrowsingService.
168  TestSafeBrowsingDatabase* db_;
169};
170
171// A TestProtocolManager that could return fixed responses from
172// safebrowsing server for testing purpose.
173class TestProtocolManager :  public SafeBrowsingProtocolManager {
174 public:
175  TestProtocolManager(SafeBrowsingService* sb_service,
176                      const std::string& client_name,
177                      const std::string& client_key,
178                      const std::string& wrapped_key,
179                      net::URLRequestContextGetter* request_context_getter,
180                      const std::string& info_url_prefix,
181                      const std::string& mackey_url_prefix,
182                      bool disable_auto_update)
183      : SafeBrowsingProtocolManager(sb_service, client_name, client_key,
184                                    wrapped_key, request_context_getter,
185                                    info_url_prefix, mackey_url_prefix,
186                                    disable_auto_update),
187        sb_service_(sb_service),
188        delay_ms_(0) {
189  }
190
191  // This function is called when there is a prefix hit in local safebrowsing
192  // database and safebrowsing service issues a get hash request to backends.
193  // We return a result from the prefilled full_hashes_ hash_map to simulate
194  // server's response. At the same time, latency is added to simulate real
195  // life network issues.
196  virtual void GetFullHash(SafeBrowsingService::SafeBrowsingCheck* check,
197                           const std::vector<SBPrefix>& prefixes) {
198    // When we get a valid response, always cache the result.
199    bool cancache = true;
200    BrowserThread::PostDelayedTask(
201        BrowserThread::IO, FROM_HERE,
202        NewRunnableMethod(
203            sb_service_, &SafeBrowsingService::HandleGetHashResults,
204            check, full_hashes_, cancache),
205        delay_ms_);
206  }
207
208  // Prepare the GetFullHash results for the next request.
209  void SetGetFullHashResponse(const SBFullHashResult& full_hash_result) {
210    full_hashes_.clear();
211    full_hashes_.push_back(full_hash_result);
212  }
213
214  void IntroduceDelay(int64 ms) {
215    delay_ms_ = ms;
216  }
217
218 private:
219  std::vector<SBFullHashResult> full_hashes_;
220  SafeBrowsingService* sb_service_;
221  int64 delay_ms_;
222};
223
224// Factory that creates TestProtocolManager instances.
225class TestSBProtocolManagerFactory : public SBProtocolManagerFactory {
226 public:
227  TestSBProtocolManagerFactory() : pm_(NULL) {}
228  virtual ~TestSBProtocolManagerFactory() {}
229
230  virtual SafeBrowsingProtocolManager* CreateProtocolManager(
231      SafeBrowsingService* sb_service,
232      const std::string& client_name,
233      const std::string& client_key,
234      const std::string& wrapped_key,
235      net::URLRequestContextGetter* request_context_getter,
236      const std::string& info_url_prefix,
237      const std::string& mackey_url_prefix,
238      bool disable_auto_update) {
239    pm_ = new TestProtocolManager(
240        sb_service, client_name, client_key, wrapped_key,
241        request_context_getter, info_url_prefix, mackey_url_prefix,
242        disable_auto_update);
243    return pm_;
244  }
245  TestProtocolManager* GetProtocolManager() {
246    return pm_;
247  }
248 private:
249  // Owned by the SafebrowsingService.
250  TestProtocolManager* pm_;
251};
252
253// Tests the safe browsing blocking page in a browser.
254class SafeBrowsingServiceTest : public InProcessBrowserTest {
255 public:
256  SafeBrowsingServiceTest() {
257  }
258
259  static void GenUrlFullhashResult(const GURL& url,
260                                   const std::string& list_name,
261                                   int add_chunk_id,
262                                   SBFullHashResult* full_hash) {
263    std::string host;
264    std::string path;
265    safe_browsing_util::CanonicalizeUrl(url, &host, &path, NULL);
266    crypto::SHA256HashString(host + path, &full_hash->hash,
267                             sizeof(SBFullHash));
268    full_hash->list_name = list_name;
269    full_hash->add_chunk_id = add_chunk_id;
270  }
271
272  static void GenDigestFullhashResult(const std::string& full_digest,
273                                      const std::string& list_name,
274                                      int add_chunk_id,
275                                      SBFullHashResult* full_hash) {
276    safe_browsing_util::StringToSBFullHash(full_digest, &full_hash->hash);
277    full_hash->list_name = list_name;
278    full_hash->add_chunk_id = add_chunk_id;
279  }
280
281  virtual void SetUp() {
282    // InProcessBrowserTest::SetUp() intantiates SafebrowsingService and
283    // RegisterFactory has to be called before SafeBrowsingService is created.
284    SafeBrowsingDatabase::RegisterFactory(&db_factory_);
285    SafeBrowsingProtocolManager::RegisterFactory(&pm_factory_);
286    InProcessBrowserTest::SetUp();
287  }
288
289  virtual void TearDown() {
290    InProcessBrowserTest::TearDown();
291
292    // Unregister test factories after InProcessBrowserTest::TearDown
293    // (which destructs SafeBrowsingService).
294    SafeBrowsingDatabase::RegisterFactory(NULL);
295    SafeBrowsingProtocolManager::RegisterFactory(NULL);
296  }
297
298  virtual void SetUpCommandLine(CommandLine* command_line) {
299    // Makes sure the auto update is not triggered during the test.
300    // This test will fill up the database using testing prefixes
301    // and urls.
302    command_line->AppendSwitch(switches::kSbDisableAutoUpdate);
303  }
304
305  virtual void SetUpInProcessBrowserTestFixture() {
306    ASSERT_TRUE(test_server()->Start());
307  }
308
309  // This will setup the "url" prefix in database and prepare protocol manager
310  // to response with |full_hash| for get full hash request.
311  void SetupResponseForUrl(const GURL& url, const SBFullHashResult& full_hash) {
312    std::vector<SBPrefix> prefix_hits;
313    prefix_hits.push_back(full_hash.hash.prefix);
314
315    // Make sure the full hits is empty unless we need to test the
316    // full hash is hit in database's local cache.
317    std::vector<SBFullHashResult> empty_full_hits;
318    TestSafeBrowsingDatabase* db = db_factory_.GetDb();
319    db->AddUrl(url, full_hash.list_name, prefix_hits, empty_full_hits);
320
321    TestProtocolManager* pm = pm_factory_.GetProtocolManager();
322    pm->SetGetFullHashResponse(full_hash);
323  }
324
325  // This will setup the binary digest prefix in database and prepare protocol
326  // manager to response with |full_hash| for get full hash request.
327  void SetupResponseForDigest(const std::string& digest,
328                              const SBFullHashResult& hash_result) {
329    TestSafeBrowsingDatabase* db = db_factory_.GetDb();
330    SBFullHash full_hash;
331    safe_browsing_util::StringToSBFullHash(digest, &full_hash);
332    db->AddDownloadPrefix(full_hash.prefix);
333
334    TestProtocolManager* pm = pm_factory_.GetProtocolManager();
335    pm->SetGetFullHashResponse(hash_result);
336  }
337
338  bool ShowingInterstitialPage() {
339    TabContents* contents = browser()->GetSelectedTabContents();
340    InterstitialPage* interstitial_page = contents->interstitial_page();
341    return interstitial_page != NULL;
342  }
343
344  void IntroduceGetHashDelay(int64 ms) {
345    pm_factory_.GetProtocolManager()->IntroduceDelay(ms);
346  }
347
348  int64 DownloadUrlCheckTimeout(SafeBrowsingService* sb_service) {
349    return sb_service->download_urlcheck_timeout_ms_;
350  }
351
352  int64 DownloadHashCheckTimeout(SafeBrowsingService* sb_service) {
353    return sb_service->download_hashcheck_timeout_ms_;
354  }
355
356  void SetDownloadUrlCheckTimeout(SafeBrowsingService* sb_service, int64 ms) {
357    sb_service->download_urlcheck_timeout_ms_ = ms;
358  }
359
360  void SetDownloadHashCheckTimeout(SafeBrowsingService* sb_service, int64 ms) {
361    sb_service->download_hashcheck_timeout_ms_ = ms;
362  }
363
364 private:
365  TestSafeBrowsingDatabaseFactory db_factory_;
366  TestSBProtocolManagerFactory pm_factory_;
367
368  DISALLOW_COPY_AND_ASSIGN(SafeBrowsingServiceTest);
369};
370
371namespace {
372
373const char kEmptyPage[] = "files/empty.html";
374const char kMalwareFile[] = "files/downloads/dangerous/dangerous.exe";
375const char kMalwareIframe[] = "files/safe_browsing/malware_iframe.html";
376const char kMalwarePage[] = "files/safe_browsing/malware.html";
377
378// This test goes through DownloadResourceHandler.
379IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, Malware) {
380  GURL url = test_server()->GetURL(kEmptyPage);
381
382  // After adding the url to safebrowsing database and getfullhash result,
383  // we should see the interstitial page.
384  SBFullHashResult malware_full_hash;
385  int chunk_id = 0;
386  GenUrlFullhashResult(url, safe_browsing_util::kMalwareList, chunk_id,
387                       &malware_full_hash);
388  SetupResponseForUrl(url, malware_full_hash);
389  ui_test_utils::NavigateToURL(browser(), url);
390  EXPECT_TRUE(ShowingInterstitialPage());
391}
392
393const char kPrefetchMalwarePage[] = "files/safe_browsing/prefetch_malware.html";
394
395// This test confirms that prefetches don't themselves get the
396// interstitial treatment.
397IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, Prefetch) {
398  GURL url = test_server()->GetURL(kPrefetchMalwarePage);
399  GURL malware_url = test_server()->GetURL(kMalwarePage);
400
401  class SetPrefetchForTest {
402   public:
403    explicit SetPrefetchForTest(bool prefetch)
404        : old_prefetch_state_(ResourceDispatcherHost::is_prefetch_enabled()) {
405      ResourceDispatcherHost::set_is_prefetch_enabled(prefetch);
406    }
407
408    ~SetPrefetchForTest() {
409      ResourceDispatcherHost::set_is_prefetch_enabled(old_prefetch_state_);
410    }
411   private:
412    bool old_prefetch_state_;
413  } set_prefetch_for_test(true);
414
415  // Even though we have added this uri to the safebrowsing database and
416  // getfullhash result, we should not see the interstitial page since the
417  // only malware was a prefetch target.
418  SBFullHashResult malware_full_hash;
419  int chunk_id = 0;
420  GenUrlFullhashResult(malware_url, safe_browsing_util::kMalwareList,
421                       chunk_id, &malware_full_hash);
422  SetupResponseForUrl(malware_url, malware_full_hash);
423  ui_test_utils::NavigateToURL(browser(), url);
424  EXPECT_FALSE(ShowingInterstitialPage());
425
426  // However, when we navigate to the malware page, we should still get
427  // the interstitial.
428  ui_test_utils::NavigateToURL(browser(), malware_url);
429  EXPECT_TRUE(ShowingInterstitialPage());
430}
431
432}  // namespace
433
434class TestSBClient
435    : public base::RefCountedThreadSafe<TestSBClient>,
436      public SafeBrowsingService::Client {
437 public:
438  TestSBClient() : result_(SafeBrowsingService::SAFE),
439                   safe_browsing_service_(g_browser_process->
440                                          resource_dispatcher_host()->
441                                          safe_browsing_service()) {
442  }
443
444  int GetResult() {
445    return result_;
446  }
447
448  void CheckDownloadUrl(const std::vector<GURL>& url_chain) {
449    BrowserThread::PostTask(
450        BrowserThread::IO, FROM_HERE,
451        NewRunnableMethod(this,
452                          &TestSBClient::CheckDownloadUrlOnIOThread,
453                          url_chain));
454    ui_test_utils::RunMessageLoop();  // Will stop in OnDownloadUrlCheckResult.
455  }
456
457  void CheckDownloadHash(const std::string& full_hash) {
458    BrowserThread::PostTask(
459        BrowserThread::IO, FROM_HERE,
460        NewRunnableMethod(this,
461                          &TestSBClient::CheckDownloadHashOnIOThread,
462                          full_hash));
463    ui_test_utils::RunMessageLoop();  // Will stop in OnDownloadHashCheckResult.
464  }
465
466 private:
467  void CheckDownloadUrlOnIOThread(const std::vector<GURL>& url_chain) {
468    safe_browsing_service_->CheckDownloadUrl(url_chain, this);
469  }
470
471  void CheckDownloadHashOnIOThread(const std::string& full_hash) {
472    safe_browsing_service_->CheckDownloadHash(full_hash, this);
473  }
474
475  // Called when the result of checking a download URL is known.
476  void OnDownloadUrlCheckResult(const std::vector<GURL>& url_chain,
477                                SafeBrowsingService::UrlCheckResult result) {
478    result_ = result;
479    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
480      NewRunnableMethod(this, &TestSBClient::DownloadCheckDone));
481  }
482
483  // Called when the result of checking a download hash is known.
484  void OnDownloadHashCheckResult(const std::string& hash,
485                                 SafeBrowsingService::UrlCheckResult result) {
486    result_ = result;
487    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
488      NewRunnableMethod(this, &TestSBClient::DownloadCheckDone));
489  }
490
491  void DownloadCheckDone() {
492    MessageLoopForUI::current()->Quit();
493  }
494
495  SafeBrowsingService::UrlCheckResult result_;
496  SafeBrowsingService* safe_browsing_service_;
497
498  DISALLOW_COPY_AND_ASSIGN(TestSBClient);
499};
500
501// These tests use SafeBrowsingService::Client to directly interact with
502// SafeBrowsingService.
503namespace {
504
505IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, CheckDownloadUrl) {
506  GURL badbin_url = test_server()->GetURL(kMalwareFile);
507  std::vector<GURL> badbin_urls(1, badbin_url);
508
509  scoped_refptr<TestSBClient> client(new TestSBClient);
510  client->CheckDownloadUrl(badbin_urls);
511
512  // Since badbin_url is not in database, it is considered to be safe.
513  EXPECT_EQ(SafeBrowsingService::SAFE, client->GetResult());
514
515  SBFullHashResult full_hash_result;
516  int chunk_id = 0;
517  GenUrlFullhashResult(badbin_url, safe_browsing_util::kBinUrlList,
518                       chunk_id, &full_hash_result);
519  SetupResponseForUrl(badbin_url, full_hash_result);
520
521  client->CheckDownloadUrl(badbin_urls);
522
523  // Now, the badbin_url is not safe since it is added to download database.
524  EXPECT_EQ(SafeBrowsingService::BINARY_MALWARE_URL, client->GetResult());
525}
526
527IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, CheckDownloadUrlRedirects) {
528  GURL original_url = test_server()->GetURL(kEmptyPage);
529  GURL badbin_url = test_server()->GetURL(kMalwareFile);
530  GURL final_url = test_server()->GetURL(kEmptyPage);
531  std::vector<GURL> badbin_urls;
532  badbin_urls.push_back(original_url);
533  badbin_urls.push_back(badbin_url);
534  badbin_urls.push_back(final_url);
535
536  scoped_refptr<TestSBClient> client(new TestSBClient);
537  client->CheckDownloadUrl(badbin_urls);
538
539  // Since badbin_url is not in database, it is considered to be safe.
540  EXPECT_EQ(SafeBrowsingService::SAFE, client->GetResult());
541
542  SBFullHashResult full_hash_result;
543  int chunk_id = 0;
544  GenUrlFullhashResult(badbin_url, safe_browsing_util::kBinUrlList,
545                       chunk_id, &full_hash_result);
546  SetupResponseForUrl(badbin_url, full_hash_result);
547
548  client->CheckDownloadUrl(badbin_urls);
549
550  // Now, the badbin_url is not safe since it is added to download database.
551  EXPECT_EQ(SafeBrowsingService::BINARY_MALWARE_URL, client->GetResult());
552}
553
554IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, CheckDownloadHash) {
555  const std::string full_hash = "12345678902234567890323456789012";
556
557  scoped_refptr<TestSBClient> client(new TestSBClient);
558  client->CheckDownloadHash(full_hash);
559
560  // Since badbin_url is not in database, it is considered to be safe.
561  EXPECT_EQ(SafeBrowsingService::SAFE, client->GetResult());
562
563  SBFullHashResult full_hash_result;
564  int chunk_id = 0;
565  GenDigestFullhashResult(full_hash, safe_browsing_util::kBinHashList,
566                          chunk_id, &full_hash_result);
567  SetupResponseForDigest(full_hash, full_hash_result);
568
569  client->CheckDownloadHash(full_hash);
570
571  // Now, the badbin_url is not safe since it is added to download database.
572  EXPECT_EQ(SafeBrowsingService::BINARY_MALWARE_HASH, client->GetResult());
573}
574
575IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, CheckDownloadUrlTimedOut) {
576  GURL badbin_url = test_server()->GetURL(kMalwareFile);
577  std::vector<GURL> badbin_urls(1, badbin_url);
578
579  scoped_refptr<TestSBClient> client(new TestSBClient);
580  SBFullHashResult full_hash_result;
581  int chunk_id = 0;
582  GenUrlFullhashResult(badbin_url, safe_browsing_util::kBinUrlList,
583                       chunk_id, &full_hash_result);
584  SetupResponseForUrl(badbin_url, full_hash_result);
585  client->CheckDownloadUrl(badbin_urls);
586
587  // badbin_url is not safe since it is added to download database.
588  EXPECT_EQ(SafeBrowsingService::BINARY_MALWARE_URL, client->GetResult());
589
590  //
591  // Now introducing delays and we should hit timeout.
592  //
593  SafeBrowsingService* sb_service =
594      g_browser_process->resource_dispatcher_host()->safe_browsing_service();
595  const int64 kOneSec = 1000;
596  const int64 kOneMs = 1;
597  int64 default_urlcheck_timeout = DownloadUrlCheckTimeout(sb_service);
598  IntroduceGetHashDelay(kOneSec);
599  SetDownloadUrlCheckTimeout(sb_service, kOneMs);
600  client->CheckDownloadUrl(badbin_urls);
601
602  // There should be a timeout and the hash would be considered as safe.
603  EXPECT_EQ(SafeBrowsingService::SAFE, client->GetResult());
604
605  // Need to set the timeout back to the default value.
606  SetDownloadHashCheckTimeout(sb_service, default_urlcheck_timeout);
607}
608
609IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, CheckDownloadHashTimedOut) {
610  const std::string full_hash = "12345678902234567890323456789012";
611
612  scoped_refptr<TestSBClient> client(new TestSBClient);
613  SBFullHashResult full_hash_result;
614  int chunk_id = 0;
615  GenDigestFullhashResult(full_hash, safe_browsing_util::kBinHashList,
616                          chunk_id, &full_hash_result);
617  SetupResponseForDigest(full_hash, full_hash_result);
618  client->CheckDownloadHash(full_hash);
619
620  // The badbin_url is not safe since it is added to download database.
621  EXPECT_EQ(SafeBrowsingService::BINARY_MALWARE_HASH, client->GetResult());
622
623  //
624  // Now introducing delays and we should hit timeout.
625  //
626  SafeBrowsingService* sb_service =
627      g_browser_process->resource_dispatcher_host()->safe_browsing_service();
628  const int64 kOneSec = 1000;
629  const int64 kOneMs = 1;
630  int64 default_hashcheck_timeout = DownloadHashCheckTimeout(sb_service);
631  IntroduceGetHashDelay(kOneSec);
632  SetDownloadHashCheckTimeout(sb_service, kOneMs);
633  client->CheckDownloadHash(full_hash);
634
635  // There should be a timeout and the hash would be considered as safe.
636  EXPECT_EQ(SafeBrowsingService::SAFE, client->GetResult());
637
638  // Need to set the timeout back to the default value.
639  SetDownloadHashCheckTimeout(sb_service, default_hashcheck_timeout);
640}
641
642}  // namespace
643