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