safe_browsing_service_browsertest.cc revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
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 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 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. 206class 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. 230class 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 284int TestProtocolManager::create_count_ = 0; 285// static 286int TestProtocolManager::delete_count_ = 0; 287 288// Factory that creates TestProtocolManager instances. 289class 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 311class MockObserver : public SafeBrowsingUIManager::Observer { 312 public: 313 MockObserver() {} 314 virtual ~MockObserver() {} 315 MOCK_METHOD1(OnSafeBrowsingHit, 316 void(const SafeBrowsingUIManager::UnsafeResource&)); 317}; 318 319MATCHER_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. 325class 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 462namespace { 463 464const char kEmptyPage[] = "files/empty.html"; 465const char kMalwareFile[] = "files/downloads/dangerous/dangerous.exe"; 466const char kMalwarePage[] = "files/safe_browsing/malware.html"; 467 468// This test goes through DownloadResourceHandler. 469IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, Malware) { 470 GURL url = test_server()->GetURL(kEmptyPage); 471 g_browser_process->safe_browsing_service()-> 472 ui_manager()->AddObserver(&observer_); 473 474 // After adding the url to safebrowsing database and getfullhash result, 475 // we should see the interstitial page. 476 SBFullHashResult malware_full_hash; 477 int chunk_id = 0; 478 GenUrlFullhashResult(url, safe_browsing_util::kMalwareList, chunk_id, 479 &malware_full_hash); 480 EXPECT_CALL(observer_, OnSafeBrowsingHit(IsUnsafeResourceFor(url))).Times(1); 481 SetupResponseForUrl(url, malware_full_hash); 482 ui_test_utils::NavigateToURL(browser(), url); 483 EXPECT_TRUE(ShowingInterstitialPage()); 484 g_browser_process->safe_browsing_service()-> 485 ui_manager()->RemoveObserver(&observer_); 486} 487 488const char kPrefetchMalwarePage[] = "files/safe_browsing/prefetch_malware.html"; 489 490// This test confirms that prefetches don't themselves get the 491// interstitial treatment. 492IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, Prefetch) { 493 GURL url = test_server()->GetURL(kPrefetchMalwarePage); 494 GURL malware_url = test_server()->GetURL(kMalwarePage); 495 g_browser_process->safe_browsing_service()-> 496 ui_manager()->AddObserver(&observer_); 497 498 class SetPrefetchForTest { 499 public: 500 explicit SetPrefetchForTest(bool prefetch) 501 : old_prefetch_state_(prerender::PrerenderManager::IsPrefetchEnabled()), 502 old_prerender_mode_(prerender::PrerenderManager::GetMode()) { 503 prerender::PrerenderManager::SetIsPrefetchEnabled(prefetch); 504 prerender::PrerenderManager::SetMode( 505 prerender::PrerenderManager::PRERENDER_MODE_DISABLED); 506 } 507 508 ~SetPrefetchForTest() { 509 prerender::PrerenderManager::SetIsPrefetchEnabled(old_prefetch_state_); 510 prerender::PrerenderManager::SetMode(old_prerender_mode_); 511 } 512 private: 513 bool old_prefetch_state_; 514 prerender::PrerenderManager::PrerenderManagerMode old_prerender_mode_; 515 } set_prefetch_for_test(true); 516 517 // Even though we have added this uri to the safebrowsing database and 518 // getfullhash result, we should not see the interstitial page since the 519 // only malware was a prefetch target. 520 SBFullHashResult malware_full_hash; 521 int chunk_id = 0; 522 GenUrlFullhashResult(malware_url, safe_browsing_util::kMalwareList, 523 chunk_id, &malware_full_hash); 524 SetupResponseForUrl(malware_url, malware_full_hash); 525 ui_test_utils::NavigateToURL(browser(), url); 526 EXPECT_FALSE(ShowingInterstitialPage()); 527 Mock::VerifyAndClear(&observer_); 528 529 // However, when we navigate to the malware page, we should still get 530 // the interstitial. 531 EXPECT_CALL(observer_, OnSafeBrowsingHit(IsUnsafeResourceFor(malware_url))) 532 .Times(1); 533 ui_test_utils::NavigateToURL(browser(), malware_url); 534 EXPECT_TRUE(ShowingInterstitialPage()); 535 Mock::VerifyAndClear(&observer_); 536 g_browser_process->safe_browsing_service()-> 537 ui_manager()->RemoveObserver(&observer_); 538} 539 540} // namespace 541 542class TestSBClient 543 : public base::RefCountedThreadSafe<TestSBClient>, 544 public SafeBrowsingDatabaseManager::Client { 545 public: 546 TestSBClient() 547 : threat_type_(SB_THREAT_TYPE_SAFE), 548 safe_browsing_service_(g_browser_process->safe_browsing_service()) { 549 } 550 551 SBThreatType GetThreatType() const { 552 return threat_type_; 553 } 554 555 void CheckDownloadUrl(const std::vector<GURL>& url_chain) { 556 BrowserThread::PostTask( 557 BrowserThread::IO, FROM_HERE, 558 base::Bind(&TestSBClient::CheckDownloadUrlOnIOThread, 559 this, url_chain)); 560 content::RunMessageLoop(); // Will stop in OnCheckDownloadUrlResult. 561 } 562 563 void CheckDownloadHash(const std::string& full_hash) { 564 BrowserThread::PostTask( 565 BrowserThread::IO, FROM_HERE, 566 base::Bind(&TestSBClient::CheckDownloadHashOnIOThread, 567 this, full_hash)); 568 content::RunMessageLoop(); // Will stop in OnCheckDownloadHashResult. 569 } 570 571 private: 572 friend class base::RefCountedThreadSafe<TestSBClient>; 573 virtual ~TestSBClient() {} 574 575 void CheckDownloadUrlOnIOThread(const std::vector<GURL>& url_chain) { 576 safe_browsing_service_->database_manager()-> 577 CheckDownloadUrl(url_chain, this); 578 } 579 580 void CheckDownloadHashOnIOThread(const std::string& full_hash) { 581 safe_browsing_service_->database_manager()-> 582 CheckDownloadHash(full_hash, this); 583 } 584 585 // Called when the result of checking a download URL is known. 586 virtual void OnCheckDownloadUrlResult(const std::vector<GURL>& url_chain, 587 SBThreatType threat_type) OVERRIDE { 588 threat_type_ = threat_type; 589 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 590 base::Bind(&TestSBClient::DownloadCheckDone, this)); 591 } 592 593 // Called when the result of checking a download hash is known. 594 virtual void OnCheckDownloadHashResult(const std::string& hash, 595 SBThreatType threat_type) OVERRIDE { 596 threat_type_ = threat_type; 597 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 598 base::Bind(&TestSBClient::DownloadCheckDone, this)); 599 } 600 601 void DownloadCheckDone() { 602 base::MessageLoopForUI::current()->Quit(); 603 } 604 605 SBThreatType threat_type_; 606 SafeBrowsingService* safe_browsing_service_; 607 608 DISALLOW_COPY_AND_ASSIGN(TestSBClient); 609}; 610 611// These tests use SafeBrowsingService::Client to directly interact with 612// SafeBrowsingService. 613namespace { 614 615IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, CheckDownloadUrl) { 616 GURL badbin_url = test_server()->GetURL(kMalwareFile); 617 std::vector<GURL> badbin_urls(1, badbin_url); 618 619 scoped_refptr<TestSBClient> client(new TestSBClient); 620 client->CheckDownloadUrl(badbin_urls); 621 622 // Since badbin_url is not in database, it is considered to be safe. 623 EXPECT_EQ(SB_THREAT_TYPE_SAFE, client->GetThreatType()); 624 625 SBFullHashResult full_hash_result; 626 int chunk_id = 0; 627 GenUrlFullhashResult(badbin_url, safe_browsing_util::kBinUrlList, 628 chunk_id, &full_hash_result); 629 SetupResponseForUrl(badbin_url, full_hash_result); 630 631 client->CheckDownloadUrl(badbin_urls); 632 633 // Now, the badbin_url is not safe since it is added to download database. 634 EXPECT_EQ(SB_THREAT_TYPE_BINARY_MALWARE_URL, client->GetThreatType()); 635} 636 637IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, CheckDownloadUrlRedirects) { 638 GURL original_url = test_server()->GetURL(kEmptyPage); 639 GURL badbin_url = test_server()->GetURL(kMalwareFile); 640 GURL final_url = test_server()->GetURL(kEmptyPage); 641 std::vector<GURL> badbin_urls; 642 badbin_urls.push_back(original_url); 643 badbin_urls.push_back(badbin_url); 644 badbin_urls.push_back(final_url); 645 646 scoped_refptr<TestSBClient> client(new TestSBClient); 647 client->CheckDownloadUrl(badbin_urls); 648 649 // Since badbin_url is not in database, it is considered to be safe. 650 EXPECT_EQ(SB_THREAT_TYPE_SAFE, client->GetThreatType()); 651 652 SBFullHashResult full_hash_result; 653 int chunk_id = 0; 654 GenUrlFullhashResult(badbin_url, safe_browsing_util::kBinUrlList, 655 chunk_id, &full_hash_result); 656 SetupResponseForUrl(badbin_url, full_hash_result); 657 658 client->CheckDownloadUrl(badbin_urls); 659 660 // Now, the badbin_url is not safe since it is added to download database. 661 EXPECT_EQ(SB_THREAT_TYPE_BINARY_MALWARE_URL, client->GetThreatType()); 662} 663 664IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, CheckDownloadHash) { 665 const std::string full_hash = "12345678902234567890323456789012"; 666 667 scoped_refptr<TestSBClient> client(new TestSBClient); 668 client->CheckDownloadHash(full_hash); 669 670 // Since badbin_url is not in database, it is considered to be safe. 671 EXPECT_EQ(SB_THREAT_TYPE_SAFE, client->GetThreatType()); 672 673 SBFullHashResult full_hash_result; 674 int chunk_id = 0; 675 GenDigestFullhashResult(full_hash, safe_browsing_util::kBinHashList, 676 chunk_id, &full_hash_result); 677 SetupResponseForDigest(full_hash, full_hash_result); 678 679 client->CheckDownloadHash(full_hash); 680 681 // Now, the badbin_url is not safe since it is added to download database. 682 EXPECT_EQ(SB_THREAT_TYPE_BINARY_MALWARE_HASH, client->GetThreatType()); 683} 684 685IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, CheckDownloadUrlTimedOut) { 686 GURL badbin_url = test_server()->GetURL(kMalwareFile); 687 std::vector<GURL> badbin_urls(1, badbin_url); 688 689 scoped_refptr<TestSBClient> client(new TestSBClient); 690 SBFullHashResult full_hash_result; 691 int chunk_id = 0; 692 GenUrlFullhashResult(badbin_url, safe_browsing_util::kBinUrlList, 693 chunk_id, &full_hash_result); 694 SetupResponseForUrl(badbin_url, full_hash_result); 695 client->CheckDownloadUrl(badbin_urls); 696 697 // badbin_url is not safe since it is added to download database. 698 EXPECT_EQ(SB_THREAT_TYPE_BINARY_MALWARE_URL, client->GetThreatType()); 699 700 // 701 // Now introducing delays and we should hit timeout. 702 // 703 SafeBrowsingService* sb_service = g_browser_process->safe_browsing_service(); 704 base::TimeDelta default_urlcheck_timeout = 705 GetCheckTimeout(sb_service); 706 IntroduceGetHashDelay(base::TimeDelta::FromSeconds(1)); 707 SetCheckTimeout(sb_service, base::TimeDelta::FromMilliseconds(1)); 708 client->CheckDownloadUrl(badbin_urls); 709 710 // There should be a timeout and the hash would be considered as safe. 711 EXPECT_EQ(SB_THREAT_TYPE_SAFE, client->GetThreatType()); 712 713 // Need to set the timeout back to the default value. 714 SetCheckTimeout(sb_service, default_urlcheck_timeout); 715} 716 717IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, CheckDownloadHashTimedOut) { 718 const std::string full_hash = "12345678902234567890323456789012"; 719 720 scoped_refptr<TestSBClient> client(new TestSBClient); 721 SBFullHashResult full_hash_result; 722 int chunk_id = 0; 723 GenDigestFullhashResult(full_hash, safe_browsing_util::kBinHashList, 724 chunk_id, &full_hash_result); 725 SetupResponseForDigest(full_hash, full_hash_result); 726 client->CheckDownloadHash(full_hash); 727 728 // The badbin_url is not safe since it is added to download database. 729 EXPECT_EQ(SB_THREAT_TYPE_BINARY_MALWARE_HASH, client->GetThreatType()); 730 731 // 732 // Now introducing delays and we should hit timeout. 733 // 734 SafeBrowsingService* sb_service = g_browser_process->safe_browsing_service(); 735 base::TimeDelta default_hashcheck_timeout = 736 GetCheckTimeout(sb_service); 737 IntroduceGetHashDelay(base::TimeDelta::FromSeconds(1)); 738 SetCheckTimeout(sb_service, base::TimeDelta::FromMilliseconds(1)); 739 client->CheckDownloadHash(full_hash); 740 741 // There should be a timeout and the hash would be considered as safe. 742 EXPECT_EQ(SB_THREAT_TYPE_SAFE, client->GetThreatType()); 743 744 // Need to set the timeout back to the default value. 745 SetCheckTimeout(sb_service, default_hashcheck_timeout); 746} 747 748IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceTest, StartAndStop) { 749 CreateCSDService(); 750 SafeBrowsingService* sb_service = g_browser_process->safe_browsing_service(); 751 safe_browsing::ClientSideDetectionService* csd_service = 752 sb_service->safe_browsing_detection_service(); 753 PrefService* pref_service = browser()->profile()->GetPrefs(); 754 755 ASSERT_TRUE(sb_service != NULL); 756 ASSERT_TRUE(csd_service != NULL); 757 ASSERT_TRUE(pref_service != NULL); 758 759 EXPECT_TRUE(pref_service->GetBoolean(prefs::kSafeBrowsingEnabled)); 760 761 // SBS might still be starting, make sure this doesn't flake. 762 WaitForIOThread(); 763 EXPECT_TRUE(sb_service->enabled()); 764 EXPECT_TRUE(csd_service->enabled()); 765 766 // Add a new Profile. SBS should keep running. 767 ASSERT_TRUE(temp_profile_dir_.CreateUniqueTempDir()); 768 scoped_ptr<Profile> profile2(Profile::CreateProfile( 769 temp_profile_dir_.path(), NULL, Profile::CREATE_MODE_SYNCHRONOUS)); 770 ASSERT_TRUE(profile2.get() != NULL); 771 PrefService* pref_service2 = profile2->GetPrefs(); 772 EXPECT_TRUE(pref_service2->GetBoolean(prefs::kSafeBrowsingEnabled)); 773 // We don't expect the state to have changed, but if it did, wait for it. 774 WaitForIOThread(); 775 EXPECT_TRUE(sb_service->enabled()); 776 EXPECT_TRUE(csd_service->enabled()); 777 778 // Change one of the prefs. SBS should keep running. 779 pref_service->SetBoolean(prefs::kSafeBrowsingEnabled, false); 780 WaitForIOThread(); 781 EXPECT_TRUE(sb_service->enabled()); 782 EXPECT_TRUE(csd_service->enabled()); 783 784 // Change the other pref. SBS should stop now. 785 pref_service2->SetBoolean(prefs::kSafeBrowsingEnabled, false); 786 WaitForIOThread(); 787 EXPECT_FALSE(sb_service->enabled()); 788 EXPECT_FALSE(csd_service->enabled()); 789 790 // Turn it back on. SBS comes back. 791 pref_service2->SetBoolean(prefs::kSafeBrowsingEnabled, true); 792 WaitForIOThread(); 793 EXPECT_TRUE(sb_service->enabled()); 794 EXPECT_TRUE(csd_service->enabled()); 795 796 // Delete the Profile. SBS stops again. 797 pref_service2 = NULL; 798 profile2.reset(); 799 WaitForIOThread(); 800 EXPECT_FALSE(sb_service->enabled()); 801 EXPECT_FALSE(csd_service->enabled()); 802} 803 804} // namespace 805 806class SafeBrowsingServiceShutdownTest : public SafeBrowsingServiceTest { 807 public: 808 virtual void TearDown() OVERRIDE { 809 // Browser should be fully torn down by now, so we can safely check these 810 // counters. 811 EXPECT_EQ(1, TestProtocolManager::create_count()); 812 EXPECT_EQ(1, TestProtocolManager::delete_count()); 813 814 SafeBrowsingServiceTest::TearDown(); 815 } 816 817 // An observer that returns back to test code after a new profile is 818 // initialized. 819 void OnUnblockOnProfileCreation(Profile* profile, 820 Profile::CreateStatus status) { 821 if (status == Profile::CREATE_STATUS_INITIALIZED) { 822 profile2_ = profile; 823 base::MessageLoop::current()->Quit(); 824 } 825 } 826 827 protected: 828 Profile* profile2_; 829}; 830 831IN_PROC_BROWSER_TEST_F(SafeBrowsingServiceShutdownTest, 832 DontStartAfterShutdown) { 833 CreateCSDService(); 834 SafeBrowsingService* sb_service = g_browser_process->safe_browsing_service(); 835 safe_browsing::ClientSideDetectionService* csd_service = 836 sb_service->safe_browsing_detection_service(); 837 PrefService* pref_service = browser()->profile()->GetPrefs(); 838 839 ASSERT_TRUE(sb_service != NULL); 840 ASSERT_TRUE(csd_service != NULL); 841 ASSERT_TRUE(pref_service != NULL); 842 843 EXPECT_TRUE(pref_service->GetBoolean(prefs::kSafeBrowsingEnabled)); 844 845 // SBS might still be starting, make sure this doesn't flake. 846 WaitForIOThread(); 847 EXPECT_EQ(1, TestProtocolManager::create_count()); 848 EXPECT_EQ(0, TestProtocolManager::delete_count()); 849 850 // Create an additional profile. We need to use the ProfileManager so that 851 // the profile will get destroyed in the normal browser shutdown process. 852 ProfileManager* profile_manager = g_browser_process->profile_manager(); 853 ASSERT_TRUE(temp_profile_dir_.CreateUniqueTempDir()); 854 profile_manager->CreateProfileAsync( 855 temp_profile_dir_.path(), 856 base::Bind(&SafeBrowsingServiceShutdownTest::OnUnblockOnProfileCreation, 857 this), 858 string16(), string16(), std::string()); 859 860 // Spin to allow profile creation to take place, loop is terminated 861 // by OnUnblockOnProfileCreation when the profile is created. 862 content::RunMessageLoop(); 863 864 PrefService* pref_service2 = profile2_->GetPrefs(); 865 EXPECT_TRUE(pref_service2->GetBoolean(prefs::kSafeBrowsingEnabled)); 866 867 // We don't expect the state to have changed, but if it did, wait for it. 868 WaitForIOThread(); 869 EXPECT_EQ(1, TestProtocolManager::create_count()); 870 EXPECT_EQ(0, TestProtocolManager::delete_count()); 871 872 // End the test, shutting down the browser. 873 // SafeBrowsingServiceShutdownTest::TearDown will check the create_count and 874 // delete_count again. 875} 876 877class SafeBrowsingDatabaseManagerCookieTest : public InProcessBrowserTest { 878 public: 879 SafeBrowsingDatabaseManagerCookieTest() {} 880 881 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 882 // We need to start the test server to get the host&port in the url. 883 ASSERT_TRUE(test_server()->Start()); 884 885 // Makes sure the auto update is not triggered. This test will force the 886 // update when needed. 887 command_line->AppendSwitch(switches::kSbDisableAutoUpdate); 888 889 // Point to the testing server for all SafeBrowsing requests. 890 GURL url_prefix = test_server()->GetURL( 891 "expect-and-set-cookie?expect=a%3db" 892 "&set=c%3dd%3b%20Expires=Fri,%2001%20Jan%202038%2001:01:01%20GMT" 893 "&data=foo#"); 894 command_line->AppendSwitchASCII(switches::kSbURLPrefix, url_prefix.spec()); 895 } 896 897 virtual bool SetUpUserDataDirectory() OVERRIDE { 898 base::FilePath cookie_path( 899 SafeBrowsingService::GetCookieFilePathForTesting()); 900 EXPECT_FALSE(base::PathExists(cookie_path)); 901 902 base::FilePath test_dir; 903 if (!PathService::Get(chrome::DIR_TEST_DATA, &test_dir)) { 904 EXPECT_TRUE(false); 905 return false; 906 } 907 908 // Initialize the SafeBrowsing cookies with a pre-created cookie store. It 909 // contains a single cookie, for domain 127.0.0.1, with value a=b, and 910 // expires in 2038. 911 base::FilePath initial_cookies = test_dir.AppendASCII("safe_browsing") 912 .AppendASCII("Safe Browsing Cookies"); 913 if (!base::CopyFile(initial_cookies, cookie_path)) { 914 EXPECT_TRUE(false); 915 return false; 916 } 917 918 sql::Connection db; 919 if (!db.Open(cookie_path)) { 920 EXPECT_TRUE(false); 921 return false; 922 } 923 // Ensure the host value in the cookie file matches the test server we will 924 // be connecting to. 925 sql::Statement smt(db.GetUniqueStatement( 926 "UPDATE cookies SET host_key = ?")); 927 if (!smt.is_valid()) { 928 EXPECT_TRUE(false); 929 return false; 930 } 931 if (!smt.BindString(0, test_server()->host_port_pair().host())) { 932 EXPECT_TRUE(false); 933 return false; 934 } 935 if (!smt.Run()) { 936 EXPECT_TRUE(false); 937 return false; 938 } 939 940 return InProcessBrowserTest::SetUpUserDataDirectory(); 941 } 942 943 virtual void TearDownInProcessBrowserTestFixture() OVERRIDE { 944 InProcessBrowserTest::TearDownInProcessBrowserTestFixture(); 945 946 sql::Connection db; 947 base::FilePath cookie_path( 948 SafeBrowsingService::GetCookieFilePathForTesting()); 949 ASSERT_TRUE(db.Open(cookie_path)); 950 951 sql::Statement smt(db.GetUniqueStatement( 952 "SELECT name, value FROM cookies ORDER BY name")); 953 ASSERT_TRUE(smt.is_valid()); 954 955 ASSERT_TRUE(smt.Step()); 956 ASSERT_EQ("a", smt.ColumnString(0)); 957 ASSERT_EQ("b", smt.ColumnString(1)); 958 ASSERT_TRUE(smt.Step()); 959 ASSERT_EQ("c", smt.ColumnString(0)); 960 ASSERT_EQ("d", smt.ColumnString(1)); 961 EXPECT_FALSE(smt.Step()); 962 } 963 964 virtual void SetUpOnMainThread() OVERRIDE { 965 sb_service_ = g_browser_process->safe_browsing_service(); 966 ASSERT_TRUE(sb_service_.get() != NULL); 967 } 968 969 virtual void CleanUpOnMainThread() OVERRIDE { 970 sb_service_ = NULL; 971 } 972 973 void ForceUpdate() { 974 sb_service_->protocol_manager()->ForceScheduleNextUpdate( 975 base::TimeDelta::FromSeconds(0)); 976 } 977 978 scoped_refptr<SafeBrowsingService> sb_service_; 979 980 private: 981 DISALLOW_COPY_AND_ASSIGN(SafeBrowsingDatabaseManagerCookieTest); 982}; 983 984// Test that a Safe Browsing database update request both sends cookies and can 985// save cookies. 986IN_PROC_BROWSER_TEST_F(SafeBrowsingDatabaseManagerCookieTest, 987 TestSBUpdateCookies) { 988 content::WindowedNotificationObserver observer( 989 chrome::NOTIFICATION_SAFE_BROWSING_UPDATE_COMPLETE, 990 content::Source<SafeBrowsingDatabaseManager>( 991 sb_service_->database_manager().get())); 992 BrowserThread::PostTask( 993 BrowserThread::IO, 994 FROM_HERE, 995 base::Bind(&SafeBrowsingDatabaseManagerCookieTest::ForceUpdate, this)); 996 observer.Wait(); 997} 998