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