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