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