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