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