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