safe_browsing_service_browsertest.cc revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
1// Copyright (c) 2012 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 <algorithm>
10
11#include "base/bind.h"
12#include "base/command_line.h"
13#include "base/files/file_path.h"
14#include "base/files/scoped_temp_dir.h"
15#include "base/memory/ref_counted.h"
16#include "base/path_service.h"
17#include "base/prefs/pref_service.h"
18#include "base/strings/string_split.h"
19#include "base/test/thread_test_helper.h"
20#include "base/time/time.h"
21#include "chrome/browser/browser_process.h"
22#include "chrome/browser/chrome_notification_types.h"
23#include "chrome/browser/prerender/prerender_manager.h"
24#include "chrome/browser/profiles/profile.h"
25#include "chrome/browser/profiles/profile_manager.h"
26#include "chrome/browser/safe_browsing/client_side_detection_service.h"
27#include "chrome/browser/safe_browsing/database_manager.h"
28#include "chrome/browser/safe_browsing/protocol_manager.h"
29#include "chrome/browser/safe_browsing/safe_browsing_database.h"
30#include "chrome/browser/safe_browsing/safe_browsing_service.h"
31#include "chrome/browser/safe_browsing/safe_browsing_util.h"
32#include "chrome/browser/safe_browsing/ui_manager.h"
33#include "chrome/browser/ui/browser.h"
34#include "chrome/browser/ui/tabs/tab_strip_model.h"
35#include "chrome/common/chrome_paths.h"
36#include "chrome/common/chrome_switches.h"
37#include "chrome/common/pref_names.h"
38#include "chrome/test/base/in_process_browser_test.h"
39#include "chrome/test/base/ui_test_utils.h"
40#include "content/public/browser/web_contents.h"
41#include "content/public/browser/web_contents_view.h"
42#include "crypto/sha2.h"
43#include "net/cookies/cookie_store.h"
44#include "sql/connection.h"
45#include "sql/statement.h"
46#include "testing/gmock/include/gmock/gmock.h"
47
48using content::BrowserThread;
49using content::InterstitialPage;
50using content::WebContents;
51using ::testing::_;
52using ::testing::Mock;
53using ::testing::StrictMock;
54
55namespace {
56
57void InvokeFullHashCallback(
58    SafeBrowsingProtocolManager::FullHashCallback callback,
59    const std::vector<SBFullHashResult>& result) {
60  callback.Run(result, true);
61}
62
63}  // namespace
64
65// A SafeBrowingDatabase class that allows us to inject the malicious URLs.
66class TestSafeBrowsingDatabase :  public SafeBrowsingDatabase {
67 public:
68  TestSafeBrowsingDatabase() {}
69
70  virtual ~TestSafeBrowsingDatabase() {}
71
72  // Initializes the database with the given filename.
73  virtual void Init(const base::FilePath& filename) OVERRIDE {}
74
75  // Deletes the current database and creates a new one.
76  virtual bool ResetDatabase() OVERRIDE {
77    badurls_.clear();
78    return true;
79  }
80
81  // Called on the IO thread to check if the given URL is safe or not.  If we
82  // can synchronously determine that the URL is safe, CheckUrl returns true,
83  // otherwise it returns false.
84  virtual bool ContainsBrowseUrl(const GURL& url,
85                                 std::string* matching_list,
86                                 std::vector<SBPrefix>* prefix_hits,
87                                 std::vector<SBFullHashResult>* full_hits,
88                                 base::Time last_update) OVERRIDE {
89    std::vector<GURL> urls(1, url);
90    return ContainsUrl(safe_browsing_util::kMalwareList,
91                       safe_browsing_util::kPhishingList,
92                       urls, prefix_hits, full_hits);
93  }
94  virtual bool ContainsDownloadUrl(
95      const std::vector<GURL>& urls,
96      std::vector<SBPrefix>* prefix_hits) OVERRIDE {
97    std::vector<SBFullHashResult> full_hits;
98    bool found = ContainsUrl(safe_browsing_util::kBinUrlList,
99                             safe_browsing_util::kBinHashList,
100                             urls, prefix_hits, &full_hits);
101    if (!found)
102      return false;
103    DCHECK_LE(1U, prefix_hits->size());
104    return true;
105  }
106  virtual bool ContainsDownloadHashPrefix(const SBPrefix& prefix) OVERRIDE {
107    return download_digest_prefix_.count(prefix) > 0;
108  }
109  virtual bool ContainsCsdWhitelistedUrl(const GURL& url) OVERRIDE {
110    return true;
111  }
112  virtual bool ContainsDownloadWhitelistedString(
113      const std::string& str) OVERRIDE {
114    return true;
115  }
116  virtual bool ContainsDownloadWhitelistedUrl(const GURL& url) OVERRIDE {
117    return true;
118  }
119  virtual bool ContainsExtensionPrefixes(
120      const std::vector<SBPrefix>& prefixes,
121      std::vector<SBPrefix>* prefix_hits) OVERRIDE {
122    return true;
123  }
124  virtual bool ContainsSideEffectFreeWhitelistUrl(const GURL& url) OVERRIDE {
125    return true;
126  }
127  virtual bool UpdateStarted(std::vector<SBListChunkRanges>* lists) OVERRIDE {
128    ADD_FAILURE() << "Not implemented.";
129    return false;
130  }
131  virtual void InsertChunks(const std::string& list_name,
132                            const SBChunkList& chunks) OVERRIDE {
133    ADD_FAILURE() << "Not implemented.";
134  }
135  virtual void DeleteChunks(
136      const std::vector<SBChunkDelete>& chunk_deletes) OVERRIDE {
137    ADD_FAILURE() << "Not implemented.";
138  }
139  virtual void UpdateFinished(bool update_succeeded) OVERRIDE {
140    ADD_FAILURE() << "Not implemented.";
141  }
142  virtual void CacheHashResults(const std::vector<SBPrefix>& prefixes,
143      const std::vector<SBFullHashResult>& full_hits) OVERRIDE {
144    // Do nothing for the cache.
145  }
146  virtual bool IsMalwareIPMatchKillSwitchOn() OVERRIDE {
147    return false;
148  }
149
150  // Fill up the database with test URL.
151  void AddUrl(const GURL& url,
152              const std::string& list_name,
153              const std::vector<SBPrefix>& prefix_hits,
154              const std::vector<SBFullHashResult>& full_hits) {
155    badurls_[url.spec()].list_name = list_name;
156    badurls_[url.spec()].prefix_hits = prefix_hits;
157    badurls_[url.spec()].full_hits = full_hits;
158  }
159
160  // Fill up the database with test hash digest.
161  void AddDownloadPrefix(SBPrefix prefix) {
162    download_digest_prefix_.insert(prefix);
163  }
164
165 private:
166  struct Hits {
167    std::string list_name;
168    std::vector<SBPrefix> prefix_hits;
169    std::vector<SBFullHashResult> full_hits;
170  };
171
172  bool ContainsUrl(const std::string& list_name0,
173                   const std::string& list_name1,
174                   const std::vector<GURL>& urls,
175                   std::vector<SBPrefix>* prefix_hits,
176                   std::vector<SBFullHashResult>* full_hits) {
177    bool hit = false;
178    for (size_t i = 0; i < urls.size(); ++i) {
179      const GURL& url = urls[i];
180      base::hash_map<std::string, Hits>::const_iterator
181          badurls_it = badurls_.find(url.spec());
182
183      if (badurls_it == badurls_.end())
184        continue;
185
186      if (badurls_it->second.list_name == list_name0 ||
187          badurls_it->second.list_name == list_name1) {
188        prefix_hits->insert(prefix_hits->end(),
189                            badurls_it->second.prefix_hits.begin(),
190                            badurls_it->second.prefix_hits.end());
191        full_hits->insert(full_hits->end(),
192                          badurls_it->second.full_hits.begin(),
193                          badurls_it->second.full_hits.end());
194        hit = true;
195      }
196
197    }
198    return hit;
199  }
200
201  base::hash_map<std::string, Hits> badurls_;
202  base::hash_set<SBPrefix> download_digest_prefix_;
203};
204
205// Factory that creates TestSafeBrowsingDatabase instances.
206class TestSafeBrowsingDatabaseFactory : public SafeBrowsingDatabaseFactory {
207 public:
208  TestSafeBrowsingDatabaseFactory() : db_(NULL) {}
209  virtual ~TestSafeBrowsingDatabaseFactory() {}
210
211  virtual SafeBrowsingDatabase* CreateSafeBrowsingDatabase(
212      bool enable_download_protection,
213      bool enable_client_side_whitelist,
214      bool enable_download_whitelist,
215      bool enable_extension_blacklist,
216      bool enable_side_effect_free_whitelist) OVERRIDE {
217    db_ = new TestSafeBrowsingDatabase();
218    return db_;
219  }
220  TestSafeBrowsingDatabase* GetDb() {
221    return db_;
222  }
223 private:
224  // Owned by the SafebrowsingService.
225  TestSafeBrowsingDatabase* db_;
226};
227
228// A TestProtocolManager that could return fixed responses from
229// safebrowsing server for testing purpose.
230class TestProtocolManager :  public SafeBrowsingProtocolManager {
231 public:
232  TestProtocolManager(SafeBrowsingProtocolManagerDelegate* delegate,
233                      net::URLRequestContextGetter* request_context_getter,
234                      const SafeBrowsingProtocolConfig& config)
235      : SafeBrowsingProtocolManager(delegate, request_context_getter, config) {
236    create_count_++;
237  }
238
239  virtual ~TestProtocolManager() {
240    delete_count_++;
241  }
242
243  // This function is called when there is a prefix hit in local safebrowsing
244  // database and safebrowsing service issues a get hash request to backends.
245  // We return a result from the prefilled full_hashes_ hash_map to simulate
246  // server's response. At the same time, latency is added to simulate real
247  // life network issues.
248  virtual void GetFullHash(
249      const std::vector<SBPrefix>& prefixes,
250      SafeBrowsingProtocolManager::FullHashCallback callback,
251      bool is_download) OVERRIDE {
252    BrowserThread::PostDelayedTask(
253        BrowserThread::IO, FROM_HERE,
254        base::Bind(InvokeFullHashCallback, callback, full_hashes_),
255        delay_);
256  }
257
258  // Prepare the GetFullHash results for the next request.
259  void SetGetFullHashResponse(const SBFullHashResult& full_hash_result) {
260    full_hashes_.clear();
261    full_hashes_.push_back(full_hash_result);
262  }
263
264  void IntroduceDelay(const base::TimeDelta& delay) {
265    delay_ = delay;
266  }
267
268  static int create_count() {
269    return create_count_;
270  }
271
272  static int delete_count() {
273    return delete_count_;
274  }
275
276 private:
277  std::vector<SBFullHashResult> full_hashes_;
278  base::TimeDelta delay_;
279  static int create_count_;
280  static int delete_count_;
281};
282
283// static
284int TestProtocolManager::create_count_ = 0;
285// static
286int TestProtocolManager::delete_count_ = 0;
287
288// Factory that creates TestProtocolManager instances.
289class TestSBProtocolManagerFactory : public SBProtocolManagerFactory {
290 public:
291  TestSBProtocolManagerFactory() : pm_(NULL) {}
292  virtual ~TestSBProtocolManagerFactory() {}
293
294  virtual SafeBrowsingProtocolManager* CreateProtocolManager(
295      SafeBrowsingProtocolManagerDelegate* delegate,
296      net::URLRequestContextGetter* request_context_getter,
297      const SafeBrowsingProtocolConfig& config) OVERRIDE {
298    pm_ = new TestProtocolManager(delegate, request_context_getter, config);
299    return pm_;
300  }
301
302  TestProtocolManager* GetProtocolManager() {
303    return pm_;
304  }
305
306 private:
307  // Owned by the SafebrowsingService.
308  TestProtocolManager* pm_;
309};
310
311class MockObserver : public SafeBrowsingUIManager::Observer {
312 public:
313  MockObserver() {}
314  virtual ~MockObserver() {}
315  MOCK_METHOD1(OnSafeBrowsingHit,
316               void(const SafeBrowsingUIManager::UnsafeResource&));
317};
318
319MATCHER_P(IsUnsafeResourceFor, url, "") {
320  return (arg.url.spec() == url.spec() &&
321          arg.threat_type != SB_THREAT_TYPE_SAFE);
322}
323
324// Tests the safe browsing blocking page in a browser.
325class SafeBrowsingServiceTest : public InProcessBrowserTest {
326 public:
327  SafeBrowsingServiceTest() {
328  }
329
330  static void GenUrlFullhashResult(const GURL& url,
331                                   const std::string& list_name,
332                                   int add_chunk_id,
333                                   SBFullHashResult* full_hash) {
334    std::string host;
335    std::string path;
336    safe_browsing_util::CanonicalizeUrl(url, &host, &path, NULL);
337    crypto::SHA256HashString(host + path, &full_hash->hash,
338                             sizeof(SBFullHash));
339    full_hash->list_name = list_name;
340    full_hash->add_chunk_id = add_chunk_id;
341  }
342
343  static void GenDigestFullhashResult(const std::string& full_digest,
344                                      const std::string& list_name,
345                                      int add_chunk_id,
346                                      SBFullHashResult* full_hash) {
347    full_hash->hash = safe_browsing_util::StringToSBFullHash(full_digest);
348    full_hash->list_name = list_name;
349    full_hash->add_chunk_id = add_chunk_id;
350  }
351
352  virtual void SetUp() {
353    // InProcessBrowserTest::SetUp() instantiates SafebrowsingService and
354    // RegisterFactory has to be called before SafeBrowsingService is created.
355    SafeBrowsingDatabase::RegisterFactory(&db_factory_);
356    SafeBrowsingProtocolManager::RegisterFactory(&pm_factory_);
357    InProcessBrowserTest::SetUp();
358  }
359
360  virtual void TearDown() {
361    InProcessBrowserTest::TearDown();
362
363    // Unregister test factories after InProcessBrowserTest::TearDown
364    // (which destructs SafeBrowsingService).
365    SafeBrowsingDatabase::RegisterFactory(NULL);
366    SafeBrowsingProtocolManager::RegisterFactory(NULL);
367  }
368
369  virtual void SetUpCommandLine(CommandLine* command_line) {
370    // Makes sure the auto update is not triggered during the test.
371    // This test will fill up the database using testing prefixes
372    // and urls.
373    command_line->AppendSwitch(switches::kSbDisableAutoUpdate);
374  }
375
376  virtual void SetUpInProcessBrowserTestFixture() {
377    ASSERT_TRUE(test_server()->Start());
378  }
379
380  // This will setup the "url" prefix in database and prepare protocol manager
381  // to response with |full_hash| for get full hash request.
382  void SetupResponseForUrl(const GURL& url, const SBFullHashResult& full_hash) {
383    std::vector<SBPrefix> prefix_hits;
384    prefix_hits.push_back(full_hash.hash.prefix);
385
386    // Make sure the full hits is empty unless we need to test the
387    // full hash is hit in database's local cache.
388    std::vector<SBFullHashResult> empty_full_hits;
389    TestSafeBrowsingDatabase* db = db_factory_.GetDb();
390    db->AddUrl(url, full_hash.list_name, prefix_hits, empty_full_hits);
391
392    TestProtocolManager* pm = pm_factory_.GetProtocolManager();
393    pm->SetGetFullHashResponse(full_hash);
394  }
395
396  // This will setup the binary digest prefix in database and prepare protocol
397  // manager to respond with the result hash.
398  void SetupResponseForDigest(const std::string& digest,
399                              const SBFullHashResult& hash_result) {
400    TestSafeBrowsingDatabase* db = db_factory_.GetDb();
401    db->AddDownloadPrefix(
402        safe_browsing_util::StringToSBFullHash(digest).prefix);
403
404    TestProtocolManager* pm = pm_factory_.GetProtocolManager();
405    pm->SetGetFullHashResponse(hash_result);
406  }
407
408  bool ShowingInterstitialPage() {
409    WebContents* contents =
410        browser()->tab_strip_model()->GetActiveWebContents();
411    InterstitialPage* interstitial_page = contents->GetInterstitialPage();
412    return interstitial_page != NULL;
413  }
414
415  void IntroduceGetHashDelay(const base::TimeDelta& delay) {
416    pm_factory_.GetProtocolManager()->IntroduceDelay(delay);
417  }
418
419  base::TimeDelta GetCheckTimeout(SafeBrowsingService* sb_service) {
420    return sb_service->database_manager()->check_timeout_;
421  }
422
423  void SetCheckTimeout(SafeBrowsingService* sb_service,
424                       const base::TimeDelta& delay) {
425    sb_service->database_manager()->check_timeout_ = delay;
426  }
427
428  void CreateCSDService() {
429    safe_browsing::ClientSideDetectionService* csd_service =
430        safe_browsing::ClientSideDetectionService::Create(NULL);
431    SafeBrowsingService* sb_service =
432        g_browser_process->safe_browsing_service();
433    sb_service->csd_service_.reset(csd_service);
434    sb_service->RefreshState();
435  }
436
437 protected:
438  StrictMock<MockObserver> observer_;
439
440  // Temporary profile dir for test cases that create a second profile.  This is
441  // owned by the SafeBrowsingServiceTest object so that it will not get
442  // destructed until after the test Browser has been torn down, since the
443  // ImportantFileWriter may still be modifying it after the Profile object has
444  // been destroyed.
445  base::ScopedTempDir temp_profile_dir_;
446
447  // Waits for pending tasks on the IO thread to complete. This is useful
448  // to wait for the SafeBrowsingService to finish loading/stopping.
449  void WaitForIOThread() {
450    scoped_refptr<base::ThreadTestHelper> io_helper(new base::ThreadTestHelper(
451        BrowserThread::GetMessageLoopProxyForThread(BrowserThread::IO).get()));
452    ASSERT_TRUE(io_helper->Run());
453  }
454
455 private:
456  TestSafeBrowsingDatabaseFactory db_factory_;
457  TestSBProtocolManagerFactory pm_factory_;
458
459  DISALLOW_COPY_AND_ASSIGN(SafeBrowsingServiceTest);
460};
461
462namespace {
463
464const char kEmptyPage[] = "files/empty.html";
465const char kMalwareFile[] = "files/downloads/dangerous/dangerous.exe";
466const char kMalwarePage[] = "files/safe_browsing/malware.html";
467
468// This test goes through DownloadResourceHandler.
469IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, Malware) {
470  GURL url = test_server()->GetURL(kEmptyPage);
471  g_browser_process->safe_browsing_service()->
472      ui_manager()->AddObserver(&observer_);
473
474  // After adding the url to safebrowsing database and getfullhash result,
475  // we should see the interstitial page.
476  SBFullHashResult malware_full_hash;
477  int chunk_id = 0;
478  GenUrlFullhashResult(url, safe_browsing_util::kMalwareList, chunk_id,
479                       &malware_full_hash);
480  EXPECT_CALL(observer_, OnSafeBrowsingHit(IsUnsafeResourceFor(url))).Times(1);
481  SetupResponseForUrl(url, malware_full_hash);
482  ui_test_utils::NavigateToURL(browser(), url);
483  EXPECT_TRUE(ShowingInterstitialPage());
484  g_browser_process->safe_browsing_service()->
485      ui_manager()->RemoveObserver(&observer_);
486}
487
488const char kPrefetchMalwarePage[] = "files/safe_browsing/prefetch_malware.html";
489
490// This test confirms that prefetches don't themselves get the
491// interstitial treatment.
492IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, Prefetch) {
493  GURL url = test_server()->GetURL(kPrefetchMalwarePage);
494  GURL malware_url = test_server()->GetURL(kMalwarePage);
495  g_browser_process->safe_browsing_service()->
496      ui_manager()->AddObserver(&observer_);
497
498  class SetPrefetchForTest {
499   public:
500    explicit SetPrefetchForTest(bool prefetch)
501        : old_prefetch_state_(prerender::PrerenderManager::IsPrefetchEnabled()),
502          old_prerender_mode_(prerender::PrerenderManager::GetMode()) {
503      prerender::PrerenderManager::SetIsPrefetchEnabled(prefetch);
504      prerender::PrerenderManager::SetMode(
505          prerender::PrerenderManager::PRERENDER_MODE_DISABLED);
506    }
507
508    ~SetPrefetchForTest() {
509      prerender::PrerenderManager::SetIsPrefetchEnabled(old_prefetch_state_);
510      prerender::PrerenderManager::SetMode(old_prerender_mode_);
511    }
512   private:
513    bool old_prefetch_state_;
514    prerender::PrerenderManager::PrerenderManagerMode old_prerender_mode_;
515  } set_prefetch_for_test(true);
516
517  // Even though we have added this uri to the safebrowsing database and
518  // getfullhash result, we should not see the interstitial page since the
519  // only malware was a prefetch target.
520  SBFullHashResult malware_full_hash;
521  int chunk_id = 0;
522  GenUrlFullhashResult(malware_url, safe_browsing_util::kMalwareList,
523                       chunk_id, &malware_full_hash);
524  SetupResponseForUrl(malware_url, malware_full_hash);
525  ui_test_utils::NavigateToURL(browser(), url);
526  EXPECT_FALSE(ShowingInterstitialPage());
527  Mock::VerifyAndClear(&observer_);
528
529  // However, when we navigate to the malware page, we should still get
530  // the interstitial.
531  EXPECT_CALL(observer_, OnSafeBrowsingHit(IsUnsafeResourceFor(malware_url)))
532      .Times(1);
533  ui_test_utils::NavigateToURL(browser(), malware_url);
534  EXPECT_TRUE(ShowingInterstitialPage());
535  Mock::VerifyAndClear(&observer_);
536  g_browser_process->safe_browsing_service()->
537      ui_manager()->RemoveObserver(&observer_);
538}
539
540}  // namespace
541
542class TestSBClient
543    : public base::RefCountedThreadSafe<TestSBClient>,
544      public SafeBrowsingDatabaseManager::Client {
545 public:
546  TestSBClient()
547    : threat_type_(SB_THREAT_TYPE_SAFE),
548      safe_browsing_service_(g_browser_process->safe_browsing_service()) {
549  }
550
551  SBThreatType GetThreatType() const {
552    return threat_type_;
553  }
554
555  void CheckDownloadUrl(const std::vector<GURL>& url_chain) {
556    BrowserThread::PostTask(
557        BrowserThread::IO, FROM_HERE,
558        base::Bind(&TestSBClient::CheckDownloadUrlOnIOThread,
559                   this, url_chain));
560    content::RunMessageLoop();  // Will stop in OnCheckDownloadUrlResult.
561  }
562
563  void CheckDownloadHash(const std::string& full_hash) {
564    BrowserThread::PostTask(
565        BrowserThread::IO, FROM_HERE,
566        base::Bind(&TestSBClient::CheckDownloadHashOnIOThread,
567                   this, full_hash));
568    content::RunMessageLoop();  // Will stop in OnCheckDownloadHashResult.
569  }
570
571 private:
572  friend class base::RefCountedThreadSafe<TestSBClient>;
573  virtual ~TestSBClient() {}
574
575  void CheckDownloadUrlOnIOThread(const std::vector<GURL>& url_chain) {
576    safe_browsing_service_->database_manager()->
577        CheckDownloadUrl(url_chain, this);
578  }
579
580  void CheckDownloadHashOnIOThread(const std::string& full_hash) {
581    safe_browsing_service_->database_manager()->
582        CheckDownloadHash(full_hash, this);
583  }
584
585  // Called when the result of checking a download URL is known.
586  virtual void OnCheckDownloadUrlResult(const std::vector<GURL>& url_chain,
587                                        SBThreatType threat_type) OVERRIDE {
588    threat_type_ = threat_type;
589    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
590                            base::Bind(&TestSBClient::DownloadCheckDone, this));
591  }
592
593  // Called when the result of checking a download hash is known.
594  virtual void OnCheckDownloadHashResult(const std::string& hash,
595                                         SBThreatType threat_type) OVERRIDE {
596    threat_type_ = threat_type;
597    BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
598                            base::Bind(&TestSBClient::DownloadCheckDone, this));
599  }
600
601  void DownloadCheckDone() {
602    base::MessageLoopForUI::current()->Quit();
603  }
604
605  SBThreatType threat_type_;
606  SafeBrowsingService* safe_browsing_service_;
607
608  DISALLOW_COPY_AND_ASSIGN(TestSBClient);
609};
610
611// These tests use SafeBrowsingService::Client to directly interact with
612// SafeBrowsingService.
613namespace {
614
615IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, CheckDownloadUrl) {
616  GURL badbin_url = test_server()->GetURL(kMalwareFile);
617  std::vector<GURL> badbin_urls(1, badbin_url);
618
619  scoped_refptr<TestSBClient> client(new TestSBClient);
620  client->CheckDownloadUrl(badbin_urls);
621
622  // Since badbin_url is not in database, it is considered to be safe.
623  EXPECT_EQ(SB_THREAT_TYPE_SAFE, client->GetThreatType());
624
625  SBFullHashResult full_hash_result;
626  int chunk_id = 0;
627  GenUrlFullhashResult(badbin_url, safe_browsing_util::kBinUrlList,
628                       chunk_id, &full_hash_result);
629  SetupResponseForUrl(badbin_url, full_hash_result);
630
631  client->CheckDownloadUrl(badbin_urls);
632
633  // Now, the badbin_url is not safe since it is added to download database.
634  EXPECT_EQ(SB_THREAT_TYPE_BINARY_MALWARE_URL, client->GetThreatType());
635}
636
637IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, CheckDownloadUrlRedirects) {
638  GURL original_url = test_server()->GetURL(kEmptyPage);
639  GURL badbin_url = test_server()->GetURL(kMalwareFile);
640  GURL final_url = test_server()->GetURL(kEmptyPage);
641  std::vector<GURL> badbin_urls;
642  badbin_urls.push_back(original_url);
643  badbin_urls.push_back(badbin_url);
644  badbin_urls.push_back(final_url);
645
646  scoped_refptr<TestSBClient> client(new TestSBClient);
647  client->CheckDownloadUrl(badbin_urls);
648
649  // Since badbin_url is not in database, it is considered to be safe.
650  EXPECT_EQ(SB_THREAT_TYPE_SAFE, client->GetThreatType());
651
652  SBFullHashResult full_hash_result;
653  int chunk_id = 0;
654  GenUrlFullhashResult(badbin_url, safe_browsing_util::kBinUrlList,
655                       chunk_id, &full_hash_result);
656  SetupResponseForUrl(badbin_url, full_hash_result);
657
658  client->CheckDownloadUrl(badbin_urls);
659
660  // Now, the badbin_url is not safe since it is added to download database.
661  EXPECT_EQ(SB_THREAT_TYPE_BINARY_MALWARE_URL, client->GetThreatType());
662}
663
664IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, CheckDownloadHash) {
665  const std::string full_hash = "12345678902234567890323456789012";
666
667  scoped_refptr<TestSBClient> client(new TestSBClient);
668  client->CheckDownloadHash(full_hash);
669
670  // Since badbin_url is not in database, it is considered to be safe.
671  EXPECT_EQ(SB_THREAT_TYPE_SAFE, client->GetThreatType());
672
673  SBFullHashResult full_hash_result;
674  int chunk_id = 0;
675  GenDigestFullhashResult(full_hash, safe_browsing_util::kBinHashList,
676                          chunk_id, &full_hash_result);
677  SetupResponseForDigest(full_hash, full_hash_result);
678
679  client->CheckDownloadHash(full_hash);
680
681  // Now, the badbin_url is not safe since it is added to download database.
682  EXPECT_EQ(SB_THREAT_TYPE_BINARY_MALWARE_HASH, client->GetThreatType());
683}
684
685IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, CheckDownloadUrlTimedOut) {
686  GURL badbin_url = test_server()->GetURL(kMalwareFile);
687  std::vector<GURL> badbin_urls(1, badbin_url);
688
689  scoped_refptr<TestSBClient> client(new TestSBClient);
690  SBFullHashResult full_hash_result;
691  int chunk_id = 0;
692  GenUrlFullhashResult(badbin_url, safe_browsing_util::kBinUrlList,
693                       chunk_id, &full_hash_result);
694  SetupResponseForUrl(badbin_url, full_hash_result);
695  client->CheckDownloadUrl(badbin_urls);
696
697  // badbin_url is not safe since it is added to download database.
698  EXPECT_EQ(SB_THREAT_TYPE_BINARY_MALWARE_URL, client->GetThreatType());
699
700  //
701  // Now introducing delays and we should hit timeout.
702  //
703  SafeBrowsingService* sb_service = g_browser_process->safe_browsing_service();
704  base::TimeDelta default_urlcheck_timeout =
705      GetCheckTimeout(sb_service);
706  IntroduceGetHashDelay(base::TimeDelta::FromSeconds(1));
707  SetCheckTimeout(sb_service, base::TimeDelta::FromMilliseconds(1));
708  client->CheckDownloadUrl(badbin_urls);
709
710  // There should be a timeout and the hash would be considered as safe.
711  EXPECT_EQ(SB_THREAT_TYPE_SAFE, client->GetThreatType());
712
713  // Need to set the timeout back to the default value.
714  SetCheckTimeout(sb_service, default_urlcheck_timeout);
715}
716
717IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, CheckDownloadHashTimedOut) {
718  const std::string full_hash = "12345678902234567890323456789012";
719
720  scoped_refptr<TestSBClient> client(new TestSBClient);
721  SBFullHashResult full_hash_result;
722  int chunk_id = 0;
723  GenDigestFullhashResult(full_hash, safe_browsing_util::kBinHashList,
724                          chunk_id, &full_hash_result);
725  SetupResponseForDigest(full_hash, full_hash_result);
726  client->CheckDownloadHash(full_hash);
727
728  // The badbin_url is not safe since it is added to download database.
729  EXPECT_EQ(SB_THREAT_TYPE_BINARY_MALWARE_HASH, client->GetThreatType());
730
731  //
732  // Now introducing delays and we should hit timeout.
733  //
734  SafeBrowsingService* sb_service = g_browser_process->safe_browsing_service();
735  base::TimeDelta default_hashcheck_timeout =
736      GetCheckTimeout(sb_service);
737  IntroduceGetHashDelay(base::TimeDelta::FromSeconds(1));
738  SetCheckTimeout(sb_service, base::TimeDelta::FromMilliseconds(1));
739  client->CheckDownloadHash(full_hash);
740
741  // There should be a timeout and the hash would be considered as safe.
742  EXPECT_EQ(SB_THREAT_TYPE_SAFE, client->GetThreatType());
743
744  // Need to set the timeout back to the default value.
745  SetCheckTimeout(sb_service, default_hashcheck_timeout);
746}
747
748IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, StartAndStop) {
749  CreateCSDService();
750  SafeBrowsingService* sb_service = g_browser_process->safe_browsing_service();
751  safe_browsing::ClientSideDetectionService* csd_service =
752      sb_service->safe_browsing_detection_service();
753  PrefService* pref_service = browser()->profile()->GetPrefs();
754
755  ASSERT_TRUE(sb_service != NULL);
756  ASSERT_TRUE(csd_service != NULL);
757  ASSERT_TRUE(pref_service != NULL);
758
759  EXPECT_TRUE(pref_service->GetBoolean(prefs::kSafeBrowsingEnabled));
760
761  // SBS might still be starting, make sure this doesn't flake.
762  WaitForIOThread();
763  EXPECT_TRUE(sb_service->enabled());
764  EXPECT_TRUE(csd_service->enabled());
765
766  // Add a new Profile. SBS should keep running.
767  ASSERT_TRUE(temp_profile_dir_.CreateUniqueTempDir());
768  scoped_ptr<Profile> profile2(Profile::CreateProfile(
769      temp_profile_dir_.path(), NULL, Profile::CREATE_MODE_SYNCHRONOUS));
770  ASSERT_TRUE(profile2.get() != NULL);
771  PrefService* pref_service2 = profile2->GetPrefs();
772  EXPECT_TRUE(pref_service2->GetBoolean(prefs::kSafeBrowsingEnabled));
773  // We don't expect the state to have changed, but if it did, wait for it.
774  WaitForIOThread();
775  EXPECT_TRUE(sb_service->enabled());
776  EXPECT_TRUE(csd_service->enabled());
777
778  // Change one of the prefs. SBS should keep running.
779  pref_service->SetBoolean(prefs::kSafeBrowsingEnabled, false);
780  WaitForIOThread();
781  EXPECT_TRUE(sb_service->enabled());
782  EXPECT_TRUE(csd_service->enabled());
783
784  // Change the other pref. SBS should stop now.
785  pref_service2->SetBoolean(prefs::kSafeBrowsingEnabled, false);
786  WaitForIOThread();
787  EXPECT_FALSE(sb_service->enabled());
788  EXPECT_FALSE(csd_service->enabled());
789
790  // Turn it back on. SBS comes back.
791  pref_service2->SetBoolean(prefs::kSafeBrowsingEnabled, true);
792  WaitForIOThread();
793  EXPECT_TRUE(sb_service->enabled());
794  EXPECT_TRUE(csd_service->enabled());
795
796  // Delete the Profile. SBS stops again.
797  pref_service2 = NULL;
798  profile2.reset();
799  WaitForIOThread();
800  EXPECT_FALSE(sb_service->enabled());
801  EXPECT_FALSE(csd_service->enabled());
802}
803
804}  // namespace
805
806class SafeBrowsingServiceShutdownTest : public SafeBrowsingServiceTest {
807 public:
808  virtual void TearDown() OVERRIDE {
809    // Browser should be fully torn down by now, so we can safely check these
810    // counters.
811    EXPECT_EQ(1, TestProtocolManager::create_count());
812    EXPECT_EQ(1, TestProtocolManager::delete_count());
813
814    SafeBrowsingServiceTest::TearDown();
815  }
816
817  // An observer that returns back to test code after a new profile is
818  // initialized.
819  void OnUnblockOnProfileCreation(Profile* profile,
820                                  Profile::CreateStatus status) {
821    if (status == Profile::CREATE_STATUS_INITIALIZED) {
822      profile2_ = profile;
823      base::MessageLoop::current()->Quit();
824    }
825  }
826
827 protected:
828  Profile* profile2_;
829};
830
831IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceShutdownTest,
832                       DontStartAfterShutdown) {
833  CreateCSDService();
834  SafeBrowsingService* sb_service = g_browser_process->safe_browsing_service();
835  safe_browsing::ClientSideDetectionService* csd_service =
836      sb_service->safe_browsing_detection_service();
837  PrefService* pref_service = browser()->profile()->GetPrefs();
838
839  ASSERT_TRUE(sb_service != NULL);
840  ASSERT_TRUE(csd_service != NULL);
841  ASSERT_TRUE(pref_service != NULL);
842
843  EXPECT_TRUE(pref_service->GetBoolean(prefs::kSafeBrowsingEnabled));
844
845  // SBS might still be starting, make sure this doesn't flake.
846  WaitForIOThread();
847  EXPECT_EQ(1, TestProtocolManager::create_count());
848  EXPECT_EQ(0, TestProtocolManager::delete_count());
849
850  // Create an additional profile.  We need to use the ProfileManager so that
851  // the profile will get destroyed in the normal browser shutdown process.
852  ProfileManager* profile_manager = g_browser_process->profile_manager();
853  ASSERT_TRUE(temp_profile_dir_.CreateUniqueTempDir());
854  profile_manager->CreateProfileAsync(
855      temp_profile_dir_.path(),
856      base::Bind(&SafeBrowsingServiceShutdownTest::OnUnblockOnProfileCreation,
857                 this),
858      string16(), string16(), std::string());
859
860  // Spin to allow profile creation to take place, loop is terminated
861  // by OnUnblockOnProfileCreation when the profile is created.
862  content::RunMessageLoop();
863
864  PrefService* pref_service2 = profile2_->GetPrefs();
865  EXPECT_TRUE(pref_service2->GetBoolean(prefs::kSafeBrowsingEnabled));
866
867  // We don't expect the state to have changed, but if it did, wait for it.
868  WaitForIOThread();
869  EXPECT_EQ(1, TestProtocolManager::create_count());
870  EXPECT_EQ(0, TestProtocolManager::delete_count());
871
872  // End the test, shutting down the browser.
873  // SafeBrowsingServiceShutdownTest::TearDown will check the create_count and
874  // delete_count again.
875}
876
877class SafeBrowsingDatabaseManagerCookieTest : public InProcessBrowserTest {
878 public:
879  SafeBrowsingDatabaseManagerCookieTest() {}
880
881  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
882    // We need to start the test server to get the host&port in the url.
883    ASSERT_TRUE(test_server()->Start());
884
885    // Makes sure the auto update is not triggered. This test will force the
886    // update when needed.
887    command_line->AppendSwitch(switches::kSbDisableAutoUpdate);
888
889    // Point to the testing server for all SafeBrowsing requests.
890    GURL url_prefix = test_server()->GetURL(
891        "expect-and-set-cookie?expect=a%3db"
892        "&set=c%3dd%3b%20Expires=Fri,%2001%20Jan%202038%2001:01:01%20GMT"
893        "&data=foo#");
894    command_line->AppendSwitchASCII(switches::kSbURLPrefix, url_prefix.spec());
895  }
896
897  virtual bool SetUpUserDataDirectory() OVERRIDE {
898    base::FilePath cookie_path(
899        SafeBrowsingService::GetCookieFilePathForTesting());
900    EXPECT_FALSE(base::PathExists(cookie_path));
901
902    base::FilePath test_dir;
903    if (!PathService::Get(chrome::DIR_TEST_DATA, &test_dir)) {
904      EXPECT_TRUE(false);
905      return false;
906    }
907
908    // Initialize the SafeBrowsing cookies with a pre-created cookie store.  It
909    // contains a single cookie, for domain 127.0.0.1, with value a=b, and
910    // expires in 2038.
911    base::FilePath initial_cookies = test_dir.AppendASCII("safe_browsing")
912        .AppendASCII("Safe Browsing Cookies");
913    if (!base::CopyFile(initial_cookies, cookie_path)) {
914      EXPECT_TRUE(false);
915      return false;
916    }
917
918    sql::Connection db;
919    if (!db.Open(cookie_path)) {
920      EXPECT_TRUE(false);
921      return false;
922    }
923    // Ensure the host value in the cookie file matches the test server we will
924    // be connecting to.
925    sql::Statement smt(db.GetUniqueStatement(
926        "UPDATE cookies SET host_key = ?"));
927    if (!smt.is_valid()) {
928      EXPECT_TRUE(false);
929      return false;
930    }
931    if (!smt.BindString(0, test_server()->host_port_pair().host())) {
932      EXPECT_TRUE(false);
933      return false;
934    }
935    if (!smt.Run()) {
936      EXPECT_TRUE(false);
937      return false;
938    }
939
940    return InProcessBrowserTest::SetUpUserDataDirectory();
941  }
942
943  virtual void TearDownInProcessBrowserTestFixture() OVERRIDE {
944    InProcessBrowserTest::TearDownInProcessBrowserTestFixture();
945
946    sql::Connection db;
947    base::FilePath cookie_path(
948        SafeBrowsingService::GetCookieFilePathForTesting());
949    ASSERT_TRUE(db.Open(cookie_path));
950
951    sql::Statement smt(db.GetUniqueStatement(
952        "SELECT name, value FROM cookies ORDER BY name"));
953    ASSERT_TRUE(smt.is_valid());
954
955    ASSERT_TRUE(smt.Step());
956    ASSERT_EQ("a", smt.ColumnString(0));
957    ASSERT_EQ("b", smt.ColumnString(1));
958    ASSERT_TRUE(smt.Step());
959    ASSERT_EQ("c", smt.ColumnString(0));
960    ASSERT_EQ("d", smt.ColumnString(1));
961    EXPECT_FALSE(smt.Step());
962  }
963
964  virtual void SetUpOnMainThread() OVERRIDE {
965    sb_service_ = g_browser_process->safe_browsing_service();
966    ASSERT_TRUE(sb_service_.get() != NULL);
967  }
968
969  virtual void CleanUpOnMainThread() OVERRIDE {
970    sb_service_ = NULL;
971  }
972
973  void ForceUpdate() {
974    sb_service_->protocol_manager()->ForceScheduleNextUpdate(
975        base::TimeDelta::FromSeconds(0));
976  }
977
978  scoped_refptr<SafeBrowsingService> sb_service_;
979
980 private:
981  DISALLOW_COPY_AND_ASSIGN(SafeBrowsingDatabaseManagerCookieTest);
982};
983
984// Test that a Safe Browsing database update request both sends cookies and can
985// save cookies.
986IN_PROC_BROWSER_TEST_F(SafeBrowsingDatabaseManagerCookieTest,
987                       TestSBUpdateCookies) {
988  content::WindowedNotificationObserver observer(
989      chrome::NOTIFICATION_SAFE_BROWSING_UPDATE_COMPLETE,
990      content::Source<SafeBrowsingDatabaseManager>(
991          sb_service_->database_manager().get()));
992  BrowserThread::PostTask(
993      BrowserThread::IO,
994      FROM_HERE,
995      base::Bind(&SafeBrowsingDatabaseManagerCookieTest::ForceUpdate, this));
996  observer.Wait();
997}
998