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