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