Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/safe_browsing/safe_browsing_database.h" | 5 #include "chrome/browser/safe_browsing/safe_browsing_database.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <iterator> | 8 #include <iterator> |
| 9 | 9 |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 23 #include "content/public/browser/browser_thread.h" | 23 #include "content/public/browser/browser_thread.h" |
| 24 #include "crypto/sha2.h" | 24 #include "crypto/sha2.h" |
| 25 #include "net/base/net_util.h" | 25 #include "net/base/net_util.h" |
| 26 #include "url/gurl.h" | 26 #include "url/gurl.h" |
| 27 | 27 |
| 28 #if defined(OS_MACOSX) | 28 #if defined(OS_MACOSX) |
| 29 #include "base/mac/mac_util.h" | 29 #include "base/mac/mac_util.h" |
| 30 #endif | 30 #endif |
| 31 | 31 |
| 32 using content::BrowserThread; | 32 using content::BrowserThread; |
| 33 using safe_browsing::PrefixSet; | |
| 34 using safe_browsing::PrefixSetBuilder; | |
| 33 | 35 |
| 34 namespace { | 36 namespace { |
| 35 | 37 |
| 36 // Filename suffix for the bloom filter. | 38 // Filename suffix for the bloom filter. |
| 37 const base::FilePath::CharType kBloomFilterFile[] = | 39 const base::FilePath::CharType kBloomFilterFile[] = |
| 38 FILE_PATH_LITERAL(" Filter 2"); | 40 FILE_PATH_LITERAL(" Filter 2"); |
| 39 // Filename suffix for the prefix set. | 41 // Filename suffix for the prefix set. |
| 40 const base::FilePath::CharType kPrefixSetFile[] = | 42 const base::FilePath::CharType kPrefixSetFile[] = |
| 41 FILE_PATH_LITERAL(" Prefix Set"); | 43 FILE_PATH_LITERAL(" Prefix Set"); |
| 42 // Filename suffix for download store. | 44 // Filename suffix for download store. |
| (...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 425 return base::FilePath(db_filename.value() + kIPBlacklistDBFile); | 427 return base::FilePath(db_filename.value() + kIPBlacklistDBFile); |
| 426 } | 428 } |
| 427 | 429 |
| 428 // static | 430 // static |
| 429 base::FilePath SafeBrowsingDatabase::UnwantedSoftwareDBFilename( | 431 base::FilePath SafeBrowsingDatabase::UnwantedSoftwareDBFilename( |
| 430 const base::FilePath& db_filename) { | 432 const base::FilePath& db_filename) { |
| 431 return base::FilePath(db_filename.value() + kUnwantedSoftwareDBFile); | 433 return base::FilePath(db_filename.value() + kUnwantedSoftwareDBFile); |
| 432 } | 434 } |
| 433 | 435 |
| 434 SafeBrowsingStore* SafeBrowsingDatabaseNew::GetStore(const int list_id) { | 436 SafeBrowsingStore* SafeBrowsingDatabaseNew::GetStore(const int list_id) { |
| 435 // Stores are not thread safe. | |
| 436 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 437 | |
| 438 if (list_id == safe_browsing_util::PHISH || | 437 if (list_id == safe_browsing_util::PHISH || |
| 439 list_id == safe_browsing_util::MALWARE) { | 438 list_id == safe_browsing_util::MALWARE) { |
| 440 return browse_store_.get(); | 439 return browse_store_.get(); |
| 441 } else if (list_id == safe_browsing_util::BINURL) { | 440 } else if (list_id == safe_browsing_util::BINURL) { |
| 442 return download_store_.get(); | 441 return download_store_.get(); |
| 443 } else if (list_id == safe_browsing_util::CSDWHITELIST) { | 442 } else if (list_id == safe_browsing_util::CSDWHITELIST) { |
| 444 return csd_whitelist_store_.get(); | 443 return csd_whitelist_store_.get(); |
| 445 } else if (list_id == safe_browsing_util::DOWNLOADWHITELIST) { | 444 } else if (list_id == safe_browsing_util::DOWNLOADWHITELIST) { |
| 446 return download_whitelist_store_.get(); | 445 return download_whitelist_store_.get(); |
| 447 } else if (list_id == safe_browsing_util::EXTENSIONBLACKLIST) { | 446 } else if (list_id == safe_browsing_util::EXTENSIONBLACKLIST) { |
| 448 return extension_blacklist_store_.get(); | 447 return extension_blacklist_store_.get(); |
| 449 } else if (list_id == safe_browsing_util::SIDEEFFECTFREEWHITELIST) { | 448 } else if (list_id == safe_browsing_util::SIDEEFFECTFREEWHITELIST) { |
| 450 return side_effect_free_whitelist_store_.get(); | 449 return side_effect_free_whitelist_store_.get(); |
| 451 } else if (list_id == safe_browsing_util::IPBLACKLIST) { | 450 } else if (list_id == safe_browsing_util::IPBLACKLIST) { |
| 452 return ip_blacklist_store_.get(); | 451 return ip_blacklist_store_.get(); |
| 453 } else if (list_id == safe_browsing_util::UNWANTEDURL) { | 452 } else if (list_id == safe_browsing_util::UNWANTEDURL) { |
| 454 return unwanted_software_store_.get(); | 453 return unwanted_software_store_.get(); |
| 455 } | 454 } |
| 456 return NULL; | 455 return NULL; |
| 457 } | 456 } |
| 458 | 457 |
| 459 // static | 458 // static |
| 460 void SafeBrowsingDatabase::RecordFailure(FailureType failure_type) { | 459 void SafeBrowsingDatabase::RecordFailure(FailureType failure_type) { |
| 461 UMA_HISTOGRAM_ENUMERATION("SB2.DatabaseFailure", failure_type, | 460 UMA_HISTOGRAM_ENUMERATION("SB2.DatabaseFailure", failure_type, |
| 462 FAILURE_DATABASE_MAX); | 461 FAILURE_DATABASE_MAX); |
| 463 } | 462 } |
| 464 | 463 |
| 464 class SafeBrowsingDatabaseNew::ThreadSafeStateManager::ReadTransaction { | |
| 465 public: | |
| 466 enum class AutoLockRequirement { | |
| 467 LOCK, | |
| 468 // SBWhitelist's, IPBlacklist's, and PrefixSet's (not caches) are only | |
| 469 // ever written to on the main thread (as enforced by | |
| 470 // ThreadSafeStateManager) and can therefore be read on the main thread | |
| 471 // without first acquiring |lock_|. | |
| 472 DONT_LOCK_ON_MAIN_THREAD | |
| 473 }; | |
| 474 | |
| 475 ReadTransaction(ThreadSafeStateManager* outer, | |
|
mattm
2014/12/12 23:20:30
Maybe ReadTransaction can take a const pointer to
gab
2014/12/15 23:02:30
It could but |prefix_gethash_cache_| would also ha
mattm
2014/12/23 02:09:45
Hm, good point. It kinda seems like prefix_gethash
gab
2014/12/23 21:39:54
Agree that it's kind-of weird to write to the cach
mattm
2014/12/24 00:29:53
Not coming up with anything.. I guess this is okay
| |
| 476 AutoLockRequirement auto_lock_requirement) | |
| 477 : outer_(outer) { | |
| 478 if (auto_lock_requirement == AutoLockRequirement::LOCK) | |
| 479 transaction_lock_.reset(new base::AutoLock(outer_->lock_)); | |
| 480 else | |
| 481 DCHECK(outer_->thread_checker_.CalledOnValidThread()); | |
| 482 } | |
| 483 | |
| 484 const SBWhitelist* GetSBWhitelist(SBWhitelistId id) { | |
| 485 switch (id) { | |
| 486 case SBWhitelistId::CSD: | |
| 487 return &outer_->csd_whitelist_; | |
| 488 case SBWhitelistId::DOWNLOAD: | |
| 489 return &outer_->download_whitelist_; | |
| 490 } | |
| 491 NOTREACHED(); | |
| 492 return nullptr; | |
| 493 } | |
| 494 | |
| 495 const IPBlacklist* ip_blacklist() { return &outer_->ip_blacklist_; } | |
| 496 | |
| 497 const PrefixSet* GetPrefixSet(PrefixSetId id) { | |
| 498 switch (id) { | |
| 499 case PrefixSetId::BROWSE: | |
| 500 return outer_->browse_prefix_set_.get(); | |
| 501 case PrefixSetId::SIDE_EFFECT_FREE_WHITELIST: | |
| 502 return outer_->side_effect_free_whitelist_prefix_set_.get(); | |
| 503 case PrefixSetId::UNWANTED_SOFTWARE: | |
| 504 return outer_->unwanted_software_prefix_set_.get(); | |
| 505 } | |
| 506 NOTREACHED(); | |
| 507 return nullptr; | |
| 508 } | |
| 509 | |
| 510 PrefixGetHashCache* prefix_gethash_cache() { | |
| 511 // The cache is special: it is read/write on all threads. Access to it | |
| 512 // therefore requires a LOCK'ed transaction (i.e. it can't benefit from | |
| 513 // DONT_LOCK_ON_MAIN_THREAD). | |
| 514 DCHECK(transaction_lock_); | |
| 515 return &outer_->prefix_gethash_cache_; | |
| 516 } | |
| 517 | |
| 518 private: | |
| 519 ThreadSafeStateManager* outer_; | |
| 520 scoped_ptr<base::AutoLock> transaction_lock_; | |
| 521 | |
| 522 DISALLOW_COPY_AND_ASSIGN(ReadTransaction); | |
| 523 }; | |
| 524 | |
| 525 class SafeBrowsingDatabaseNew::ThreadSafeStateManager::WriteTransaction { | |
| 526 public: | |
| 527 explicit WriteTransaction(ThreadSafeStateManager* outer) | |
| 528 : outer_(outer), transaction_lock_(outer_->lock_) { | |
| 529 DCHECK(outer_->thread_checker_.CalledOnValidThread()); | |
| 530 } | |
| 531 | |
| 532 SBWhitelist* GetWritableSBWhitelist(SBWhitelistId id) { | |
| 533 switch (id) { | |
| 534 case SBWhitelistId::CSD: | |
| 535 return &outer_->csd_whitelist_; | |
| 536 case SBWhitelistId::DOWNLOAD: | |
| 537 return &outer_->download_whitelist_; | |
| 538 } | |
| 539 NOTREACHED(); | |
| 540 return nullptr; | |
| 541 } | |
| 542 | |
| 543 IPBlacklist* writable_ip_blacklist() { return &outer_->ip_blacklist_; } | |
| 544 | |
| 545 void SwapPrefixSet(PrefixSetId id, | |
| 546 scoped_ptr<const PrefixSet> new_prefix_set) { | |
| 547 switch (id) { | |
| 548 case PrefixSetId::BROWSE: | |
| 549 outer_->browse_prefix_set_.swap(new_prefix_set); | |
| 550 break; | |
| 551 case PrefixSetId::SIDE_EFFECT_FREE_WHITELIST: | |
| 552 outer_->side_effect_free_whitelist_prefix_set_.swap(new_prefix_set); | |
| 553 break; | |
| 554 case PrefixSetId::UNWANTED_SOFTWARE: | |
| 555 outer_->unwanted_software_prefix_set_.swap(new_prefix_set); | |
| 556 break; | |
| 557 } | |
| 558 } | |
| 559 | |
| 560 void clear_prefix_gethash_cache() { outer_->prefix_gethash_cache_.clear(); } | |
| 561 | |
| 562 private: | |
| 563 ThreadSafeStateManager* outer_; | |
| 564 base::AutoLock transaction_lock_; | |
| 565 | |
| 566 DISALLOW_COPY_AND_ASSIGN(WriteTransaction); | |
| 567 }; | |
| 568 | |
| 569 SafeBrowsingDatabaseNew::ThreadSafeStateManager::ThreadSafeStateManager() { | |
| 570 } | |
| 571 SafeBrowsingDatabaseNew::ThreadSafeStateManager::~ThreadSafeStateManager() { | |
| 572 } | |
| 573 | |
| 574 scoped_ptr<SafeBrowsingDatabaseNew::ReadTransaction> | |
| 575 SafeBrowsingDatabaseNew::ThreadSafeStateManager::BeginReadTransaction() { | |
| 576 return make_scoped_ptr( | |
| 577 new ReadTransaction(this, ReadTransaction::AutoLockRequirement::LOCK)); | |
| 578 } | |
| 579 | |
| 580 scoped_ptr<SafeBrowsingDatabaseNew::ReadTransaction> SafeBrowsingDatabaseNew:: | |
| 581 ThreadSafeStateManager::BeginReadTransactionNoLockOnMainThread() { | |
| 582 return make_scoped_ptr(new ReadTransaction( | |
| 583 this, ReadTransaction::AutoLockRequirement::DONT_LOCK_ON_MAIN_THREAD)); | |
| 584 } | |
| 585 | |
| 586 scoped_ptr<SafeBrowsingDatabaseNew::WriteTransaction> | |
| 587 SafeBrowsingDatabaseNew::ThreadSafeStateManager::BeginWriteTransaction() { | |
| 588 return make_scoped_ptr(new WriteTransaction(this)); | |
| 589 } | |
| 590 | |
| 465 SafeBrowsingDatabaseNew::SafeBrowsingDatabaseNew() | 591 SafeBrowsingDatabaseNew::SafeBrowsingDatabaseNew() |
| 466 : SafeBrowsingDatabaseNew(new SafeBrowsingStoreFile, | 592 : SafeBrowsingDatabaseNew(new SafeBrowsingStoreFile, |
| 467 NULL, | 593 NULL, |
| 468 NULL, | 594 NULL, |
| 469 NULL, | 595 NULL, |
| 470 NULL, | 596 NULL, |
| 471 NULL, | 597 NULL, |
| 472 NULL, | 598 NULL, |
| 473 NULL) { | 599 NULL) { |
| 474 DCHECK(browse_store_.get()); | 600 DCHECK(browse_store_.get()); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 498 side_effect_free_whitelist_store_(side_effect_free_whitelist_store), | 624 side_effect_free_whitelist_store_(side_effect_free_whitelist_store), |
| 499 ip_blacklist_store_(ip_blacklist_store), | 625 ip_blacklist_store_(ip_blacklist_store), |
| 500 unwanted_software_store_(unwanted_software_store), | 626 unwanted_software_store_(unwanted_software_store), |
| 501 corruption_detected_(false), | 627 corruption_detected_(false), |
| 502 change_detected_(false), | 628 change_detected_(false), |
| 503 reset_factory_(this) { | 629 reset_factory_(this) { |
| 504 DCHECK(browse_store_.get()); | 630 DCHECK(browse_store_.get()); |
| 505 } | 631 } |
| 506 | 632 |
| 507 SafeBrowsingDatabaseNew::~SafeBrowsingDatabaseNew() { | 633 SafeBrowsingDatabaseNew::~SafeBrowsingDatabaseNew() { |
| 508 // The DCHECK is disabled due to crbug.com/338486 . | |
| 509 // DCHECK(thread_checker_.CalledOnValidThread()); | |
|
gab
2014/12/11 19:39:20
This DCHECK is still covered by making SafeBrowsin
| |
| 510 } | 634 } |
| 511 | 635 |
| 512 void SafeBrowsingDatabaseNew::Init(const base::FilePath& filename_base) { | 636 void SafeBrowsingDatabaseNew::Init(const base::FilePath& filename_base) { |
| 513 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 514 | |
| 515 // This should not be run multiple times. | 637 // This should not be run multiple times. |
| 516 DCHECK(filename_base_.empty()); | 638 DCHECK(filename_base_.empty()); |
| 517 | 639 |
| 518 filename_base_ = filename_base; | 640 filename_base_ = filename_base; |
| 519 | 641 |
| 520 // TODO(shess): The various stores are really only necessary while doing | 642 // TODO(shess): The various stores are really only necessary while doing |
| 521 // updates (see |UpdateFinished()|) or when querying a store directly (see | 643 // updates (see |UpdateFinished()|) or when querying a store directly (see |
| 522 // |ContainsDownloadUrl()|). | 644 // |ContainsDownloadUrl()|). |
| 523 // The store variables are also tested to see if a list is enabled. Perhaps | 645 // The store variables are also tested to see if a list is enabled. Perhaps |
| 524 // the stores could be refactored into an update object so that they are only | 646 // the stores could be refactored into an update object so that they are only |
| 525 // live in memory while being actively used. The sense of enabled probably | 647 // live in memory while being actively used. The sense of enabled probably |
| 526 // belongs in protocol_manager or database_manager. | 648 // belongs in protocol_manager or database_manager. |
| 527 | 649 |
| 528 browse_store_->Init( | 650 { |
| 529 BrowseDBFilename(filename_base_), | 651 // NOTE: A transaction here is overkill as there are no pointers to this |
| 530 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, | 652 // class on other threads until this function returns, but it's also |
| 531 base::Unretained(this))); | 653 // harmless as that also means there is no possibility of contention on the |
| 654 // lock. | |
| 655 scoped_ptr<WriteTransaction> txn = state_manager_.BeginWriteTransaction(); | |
| 532 | 656 |
| 533 if (unwanted_software_store_.get()) { | 657 txn->clear_prefix_gethash_cache(); |
| 534 unwanted_software_store_->Init( | 658 |
| 535 UnwantedSoftwareDBFilename(filename_base_), | 659 browse_store_->Init( |
| 660 BrowseDBFilename(filename_base_), | |
| 536 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, | 661 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, |
| 537 base::Unretained(this))); | 662 base::Unretained(this))); |
| 538 } | |
| 539 | 663 |
| 540 { | |
| 541 // NOTE: There is no need to grab the lock in this function, since | |
| 542 // until it returns, there are no pointers to this class on other | |
| 543 // threads. Then again, that means there is no possibility of | |
| 544 // contention on the lock... | |
| 545 base::AutoLock locked(lookup_lock_); | |
| 546 prefix_gethash_cache_.clear(); | |
| 547 LoadPrefixSet(BrowseDBFilename(filename_base_), | |
| 548 &browse_prefix_set_, | |
| 549 FAILURE_BROWSE_PREFIX_SET_READ); | |
| 550 if (unwanted_software_store_.get()) { | 664 if (unwanted_software_store_.get()) { |
| 551 LoadPrefixSet(UnwantedSoftwareDBFilename(filename_base_), | 665 unwanted_software_store_->Init( |
| 552 &unwanted_software_prefix_set_, | 666 UnwantedSoftwareDBFilename(filename_base_), |
| 667 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, | |
| 668 base::Unretained(this))); | |
| 669 } | |
| 670 LoadPrefixSet(BrowseDBFilename(filename_base_), txn.get(), | |
| 671 PrefixSetId::BROWSE, FAILURE_BROWSE_PREFIX_SET_READ); | |
| 672 if (unwanted_software_store_.get()) { | |
| 673 LoadPrefixSet(UnwantedSoftwareDBFilename(filename_base_), txn.get(), | |
| 674 PrefixSetId::UNWANTED_SOFTWARE, | |
| 553 FAILURE_UNWANTED_SOFTWARE_PREFIX_SET_READ); | 675 FAILURE_UNWANTED_SOFTWARE_PREFIX_SET_READ); |
| 554 } | 676 } |
| 677 | |
| 678 if (side_effect_free_whitelist_store_.get()) { | |
| 679 const base::FilePath side_effect_free_whitelist_filename = | |
| 680 SideEffectFreeWhitelistDBFilename(filename_base_); | |
| 681 side_effect_free_whitelist_store_->Init( | |
| 682 side_effect_free_whitelist_filename, | |
| 683 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, | |
| 684 base::Unretained(this))); | |
| 685 | |
| 686 LoadPrefixSet(side_effect_free_whitelist_filename, txn.get(), | |
| 687 PrefixSetId::SIDE_EFFECT_FREE_WHITELIST, | |
| 688 FAILURE_SIDE_EFFECT_FREE_WHITELIST_PREFIX_SET_READ); | |
| 689 } else { | |
| 690 // Delete any files of the side-effect free sidelist that may be around | |
| 691 // from when it was previously enabled. | |
| 692 SafeBrowsingStoreFile::DeleteStore( | |
| 693 SideEffectFreeWhitelistDBFilename(filename_base_)); | |
| 694 base::DeleteFile(PrefixSetForFilename( | |
| 695 SideEffectFreeWhitelistDBFilename(filename_base_)), | |
| 696 false); | |
| 697 } | |
| 555 } | 698 } |
| 699 // Note: End the transaction early because LoadWhiteList() and | |
| 700 // WhitelistEverything() manage their own transactions. | |
| 556 | 701 |
| 557 if (download_store_.get()) { | 702 if (download_store_.get()) { |
| 558 download_store_->Init( | 703 download_store_->Init( |
| 559 DownloadDBFilename(filename_base_), | 704 DownloadDBFilename(filename_base_), |
| 560 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, | 705 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, |
| 561 base::Unretained(this))); | 706 base::Unretained(this))); |
| 562 } | 707 } |
| 563 | 708 |
| 564 if (csd_whitelist_store_.get()) { | 709 if (csd_whitelist_store_.get()) { |
| 565 csd_whitelist_store_->Init( | 710 csd_whitelist_store_->Init( |
| 566 CsdWhitelistDBFilename(filename_base_), | 711 CsdWhitelistDBFilename(filename_base_), |
| 567 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, | 712 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, |
| 568 base::Unretained(this))); | 713 base::Unretained(this))); |
| 569 | 714 |
| 570 std::vector<SBAddFullHash> full_hashes; | 715 std::vector<SBAddFullHash> full_hashes; |
| 571 if (csd_whitelist_store_->GetAddFullHashes(&full_hashes)) { | 716 if (csd_whitelist_store_->GetAddFullHashes(&full_hashes)) { |
| 572 LoadWhitelist(full_hashes, &csd_whitelist_); | 717 LoadWhitelist(full_hashes, SBWhitelistId::CSD); |
| 573 } else { | 718 } else { |
| 574 WhitelistEverything(&csd_whitelist_); | 719 WhitelistEverything(SBWhitelistId::CSD); |
| 575 } | 720 } |
| 576 } else { | 721 } else { |
| 577 WhitelistEverything(&csd_whitelist_); // Just to be safe. | 722 WhitelistEverything(SBWhitelistId::CSD); // Just to be safe. |
| 578 } | 723 } |
| 579 | 724 |
| 580 if (download_whitelist_store_.get()) { | 725 if (download_whitelist_store_.get()) { |
| 581 download_whitelist_store_->Init( | 726 download_whitelist_store_->Init( |
| 582 DownloadWhitelistDBFilename(filename_base_), | 727 DownloadWhitelistDBFilename(filename_base_), |
| 583 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, | 728 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, |
| 584 base::Unretained(this))); | 729 base::Unretained(this))); |
| 585 | 730 |
| 586 std::vector<SBAddFullHash> full_hashes; | 731 std::vector<SBAddFullHash> full_hashes; |
| 587 if (download_whitelist_store_->GetAddFullHashes(&full_hashes)) { | 732 if (download_whitelist_store_->GetAddFullHashes(&full_hashes)) { |
| 588 LoadWhitelist(full_hashes, &download_whitelist_); | 733 LoadWhitelist(full_hashes, SBWhitelistId::DOWNLOAD); |
| 589 } else { | 734 } else { |
| 590 WhitelistEverything(&download_whitelist_); | 735 WhitelistEverything(SBWhitelistId::DOWNLOAD); |
| 591 } | 736 } |
| 592 } else { | 737 } else { |
| 593 WhitelistEverything(&download_whitelist_); // Just to be safe. | 738 WhitelistEverything(SBWhitelistId::DOWNLOAD); // Just to be safe. |
| 594 } | 739 } |
| 595 | 740 |
| 596 if (extension_blacklist_store_.get()) { | 741 if (extension_blacklist_store_.get()) { |
| 597 extension_blacklist_store_->Init( | 742 extension_blacklist_store_->Init( |
| 598 ExtensionBlacklistDBFilename(filename_base_), | 743 ExtensionBlacklistDBFilename(filename_base_), |
| 599 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, | 744 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, |
| 600 base::Unretained(this))); | 745 base::Unretained(this))); |
| 601 } | 746 } |
| 602 | 747 |
| 603 if (side_effect_free_whitelist_store_.get()) { | |
| 604 const base::FilePath side_effect_free_whitelist_filename = | |
| 605 SideEffectFreeWhitelistDBFilename(filename_base_); | |
| 606 side_effect_free_whitelist_store_->Init( | |
| 607 side_effect_free_whitelist_filename, | |
| 608 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, | |
| 609 base::Unretained(this))); | |
| 610 | |
| 611 LoadPrefixSet(side_effect_free_whitelist_filename, | |
| 612 &side_effect_free_whitelist_prefix_set_, | |
| 613 FAILURE_SIDE_EFFECT_FREE_WHITELIST_PREFIX_SET_READ); | |
| 614 } else { | |
| 615 // Delete any files of the side-effect free sidelist that may be around | |
| 616 // from when it was previously enabled. | |
| 617 SafeBrowsingStoreFile::DeleteStore( | |
| 618 SideEffectFreeWhitelistDBFilename(filename_base_)); | |
| 619 base::DeleteFile( | |
| 620 PrefixSetForFilename(SideEffectFreeWhitelistDBFilename(filename_base_)), | |
| 621 false); | |
| 622 } | |
| 623 | |
| 624 if (ip_blacklist_store_.get()) { | 748 if (ip_blacklist_store_.get()) { |
| 625 ip_blacklist_store_->Init( | 749 ip_blacklist_store_->Init( |
| 626 IpBlacklistDBFilename(filename_base_), | 750 IpBlacklistDBFilename(filename_base_), |
| 627 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, | 751 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, |
| 628 base::Unretained(this))); | 752 base::Unretained(this))); |
| 629 | 753 |
| 630 std::vector<SBAddFullHash> full_hashes; | 754 std::vector<SBAddFullHash> full_hashes; |
| 631 if (ip_blacklist_store_->GetAddFullHashes(&full_hashes)) { | 755 if (ip_blacklist_store_->GetAddFullHashes(&full_hashes)) { |
| 632 LoadIpBlacklist(full_hashes); | 756 LoadIpBlacklist(full_hashes); |
| 633 } else { | 757 } else { |
| 634 LoadIpBlacklist(std::vector<SBAddFullHash>()); // Clear the list. | 758 LoadIpBlacklist(std::vector<SBAddFullHash>()); // Clear the list. |
| 635 } | 759 } |
| 636 } | 760 } |
| 637 } | 761 } |
| 638 | 762 |
| 639 bool SafeBrowsingDatabaseNew::ResetDatabase() { | 763 bool SafeBrowsingDatabaseNew::ResetDatabase() { |
| 640 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 641 | |
| 642 // Delete files on disk. | 764 // Delete files on disk. |
| 643 // TODO(shess): Hard to see where one might want to delete without a | 765 // TODO(shess): Hard to see where one might want to delete without a |
| 644 // reset. Perhaps inline |Delete()|? | 766 // reset. Perhaps inline |Delete()|? |
| 645 if (!Delete()) | 767 if (!Delete()) |
| 646 return false; | 768 return false; |
| 647 | 769 |
| 648 // Reset objects in memory. | 770 // Reset objects in memory. |
| 649 { | 771 { |
| 650 base::AutoLock locked(lookup_lock_); | 772 scoped_ptr<WriteTransaction> txn = state_manager_.BeginWriteTransaction(); |
| 651 prefix_gethash_cache_.clear(); | 773 txn->clear_prefix_gethash_cache(); |
| 652 browse_prefix_set_.reset(); | 774 txn->SwapPrefixSet(PrefixSetId::BROWSE, nullptr); |
| 653 side_effect_free_whitelist_prefix_set_.reset(); | 775 txn->SwapPrefixSet(PrefixSetId::SIDE_EFFECT_FREE_WHITELIST, nullptr); |
| 654 ip_blacklist_.clear(); | 776 txn->SwapPrefixSet(PrefixSetId::UNWANTED_SOFTWARE, nullptr); |
| 655 unwanted_software_prefix_set_.reset(); | 777 txn->writable_ip_blacklist()->clear(); |
| 656 } | 778 } |
| 657 // Wants to acquire the lock itself. | 779 // Wants to acquire the lock itself. |
|
mattm
2014/12/12 23:20:31
Why not make WhitelistEverything a method on Write
gab
2014/12/15 23:02:30
I debated that in lengths while writing this and h
mattm
2014/12/23 02:09:45
Well, you could one-line it like
state_manager_.Be
gab
2014/12/23 21:39:54
Actually, I kind of like that and used it for a fe
| |
| 658 WhitelistEverything(&csd_whitelist_); | 780 WhitelistEverything(SBWhitelistId::CSD); |
| 659 WhitelistEverything(&download_whitelist_); | 781 WhitelistEverything(SBWhitelistId::DOWNLOAD); |
| 660 return true; | 782 return true; |
| 661 } | 783 } |
| 662 | 784 |
| 663 bool SafeBrowsingDatabaseNew::ContainsBrowseUrl( | 785 bool SafeBrowsingDatabaseNew::ContainsBrowseUrl( |
| 664 const GURL& url, | 786 const GURL& url, |
| 665 std::vector<SBPrefix>* prefix_hits, | 787 std::vector<SBPrefix>* prefix_hits, |
| 666 std::vector<SBFullHashResult>* cache_hits) { | 788 std::vector<SBFullHashResult>* cache_hits) { |
| 667 // This method is theoretically thread-safe but document that it is currently | 789 return PrefixSetContainsUrl(url, PrefixSetId::BROWSE, prefix_hits, |
| 668 // only expected to be called on the IO thread. | 790 cache_hits); |
| 669 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 670 | |
| 671 return PrefixSetContainsUrl( | |
| 672 url, &browse_prefix_set_, prefix_hits, cache_hits); | |
| 673 } | 791 } |
| 674 | 792 |
| 675 bool SafeBrowsingDatabaseNew::ContainsUnwantedSoftwareUrl( | 793 bool SafeBrowsingDatabaseNew::ContainsUnwantedSoftwareUrl( |
| 676 const GURL& url, | 794 const GURL& url, |
| 677 std::vector<SBPrefix>* prefix_hits, | 795 std::vector<SBPrefix>* prefix_hits, |
| 678 std::vector<SBFullHashResult>* cache_hits) { | 796 std::vector<SBFullHashResult>* cache_hits) { |
| 679 // This method is theoretically thread-safe but document that it is currently | 797 return PrefixSetContainsUrl(url, PrefixSetId::UNWANTED_SOFTWARE, prefix_hits, |
| 680 // only expected to be called on the IO thread. | 798 cache_hits); |
| 681 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 682 | |
| 683 return PrefixSetContainsUrl( | |
| 684 url, &unwanted_software_prefix_set_, prefix_hits, cache_hits); | |
| 685 } | 799 } |
| 686 | 800 |
| 687 bool SafeBrowsingDatabaseNew::PrefixSetContainsUrl( | 801 bool SafeBrowsingDatabaseNew::PrefixSetContainsUrl( |
| 688 const GURL& url, | 802 const GURL& url, |
| 689 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set_getter, | 803 PrefixSetId prefix_set_id, |
| 690 std::vector<SBPrefix>* prefix_hits, | 804 std::vector<SBPrefix>* prefix_hits, |
| 691 std::vector<SBFullHashResult>* cache_hits) { | 805 std::vector<SBFullHashResult>* cache_hits) { |
| 692 // This method is theoretically thread-safe but document that it is currently | |
| 693 // only expected to be called on the IO thread. | |
| 694 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 695 | |
| 696 // Clear the results first. | 806 // Clear the results first. |
| 697 prefix_hits->clear(); | 807 prefix_hits->clear(); |
| 698 cache_hits->clear(); | 808 cache_hits->clear(); |
| 699 | 809 |
| 700 std::vector<SBFullHash> full_hashes; | 810 std::vector<SBFullHash> full_hashes; |
| 701 UrlToFullHashes(url, false, &full_hashes); | 811 UrlToFullHashes(url, false, &full_hashes); |
| 702 if (full_hashes.empty()) | 812 if (full_hashes.empty()) |
| 703 return false; | 813 return false; |
| 704 | 814 |
| 705 return PrefixSetContainsUrlHashes( | 815 return PrefixSetContainsUrlHashes(full_hashes, prefix_set_id, prefix_hits, |
| 706 full_hashes, prefix_set_getter, prefix_hits, cache_hits); | 816 cache_hits); |
| 707 } | 817 } |
| 708 | 818 |
| 709 bool SafeBrowsingDatabaseNew::ContainsBrowseUrlHashesForTesting( | 819 bool SafeBrowsingDatabaseNew::ContainsBrowseUrlHashesForTesting( |
| 710 const std::vector<SBFullHash>& full_hashes, | 820 const std::vector<SBFullHash>& full_hashes, |
| 711 std::vector<SBPrefix>* prefix_hits, | 821 std::vector<SBPrefix>* prefix_hits, |
| 712 std::vector<SBFullHashResult>* cache_hits) { | 822 std::vector<SBFullHashResult>* cache_hits) { |
| 713 return PrefixSetContainsUrlHashes( | 823 return PrefixSetContainsUrlHashes(full_hashes, PrefixSetId::BROWSE, |
| 714 full_hashes, &browse_prefix_set_, prefix_hits, cache_hits); | 824 prefix_hits, cache_hits); |
| 715 } | 825 } |
| 716 | 826 |
| 717 bool SafeBrowsingDatabaseNew::PrefixSetContainsUrlHashes( | 827 bool SafeBrowsingDatabaseNew::PrefixSetContainsUrlHashes( |
| 718 const std::vector<SBFullHash>& full_hashes, | 828 const std::vector<SBFullHash>& full_hashes, |
| 719 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set_getter, | 829 PrefixSetId prefix_set_id, |
| 720 std::vector<SBPrefix>* prefix_hits, | 830 std::vector<SBPrefix>* prefix_hits, |
| 721 std::vector<SBFullHashResult>* cache_hits) { | 831 std::vector<SBFullHashResult>* cache_hits) { |
| 722 // This method is theoretically thread-safe but document that it is currently | |
| 723 // only expected to be called on the IO thread. | |
| 724 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 725 | |
| 726 // Used to determine cache expiration. | 832 // Used to determine cache expiration. |
| 727 const base::Time now = base::Time::Now(); | 833 const base::Time now = base::Time::Now(); |
| 728 | 834 |
| 729 base::AutoLock locked(lookup_lock_); | 835 { |
| 836 scoped_ptr<ReadTransaction> txn = state_manager_.BeginReadTransaction(); | |
| 730 | 837 |
| 731 // |prefix_set| is empty until it is either read from disk, or the first | 838 // |prefix_set| is empty until it is either read from disk, or the first |
| 732 // update populates it. Bail out without a hit if not yet available. | 839 // update populates it. Bail out without a hit if not yet available. |
| 733 // |prefix_set_getter| can only be accessed while holding |lookup_lock_| hence | 840 const PrefixSet* prefix_set = txn->GetPrefixSet(prefix_set_id); |
| 734 // why it is passed as a parameter rather than passing the |prefix_set| | 841 if (!prefix_set) |
| 735 // directly. | 842 return false; |
| 736 const safe_browsing::PrefixSet* prefix_set = prefix_set_getter->get(); | |
| 737 if (!prefix_set) | |
| 738 return false; | |
| 739 | 843 |
| 740 for (size_t i = 0; i < full_hashes.size(); ++i) { | 844 for (size_t i = 0; i < full_hashes.size(); ++i) { |
| 741 if (!GetCachedFullHash( | 845 if (!GetCachedFullHash(txn->prefix_gethash_cache(), full_hashes[i], now, |
| 742 &prefix_gethash_cache_, full_hashes[i], now, cache_hits)) { | 846 cache_hits)) { |
| 743 // No valid cached result, check the database. | 847 // No valid cached result, check the database. |
| 744 if (prefix_set->Exists(full_hashes[i])) | 848 if (prefix_set->Exists(full_hashes[i])) |
| 745 prefix_hits->push_back(full_hashes[i].prefix); | 849 prefix_hits->push_back(full_hashes[i].prefix); |
| 850 } | |
| 746 } | 851 } |
| 747 } | 852 } |
| 748 | 853 |
| 749 // Multiple full hashes could share prefix, remove duplicates. | 854 // Multiple full hashes could share prefix, remove duplicates. |
| 750 std::sort(prefix_hits->begin(), prefix_hits->end()); | 855 std::sort(prefix_hits->begin(), prefix_hits->end()); |
| 751 prefix_hits->erase(std::unique(prefix_hits->begin(), prefix_hits->end()), | 856 prefix_hits->erase(std::unique(prefix_hits->begin(), prefix_hits->end()), |
| 752 prefix_hits->end()); | 857 prefix_hits->end()); |
| 753 | 858 |
| 754 return !prefix_hits->empty() || !cache_hits->empty(); | 859 return !prefix_hits->empty() || !cache_hits->empty(); |
| 755 } | 860 } |
| 756 | 861 |
| 757 bool SafeBrowsingDatabaseNew::ContainsDownloadUrl( | 862 bool SafeBrowsingDatabaseNew::ContainsDownloadUrl( |
| 758 const std::vector<GURL>& urls, | 863 const std::vector<GURL>& urls, |
| 759 std::vector<SBPrefix>* prefix_hits) { | 864 std::vector<SBPrefix>* prefix_hits) { |
| 760 DCHECK(thread_checker_.CalledOnValidThread()); | |
|
mattm
2014/12/12 23:20:31
Why are all these removed?
gab
2014/12/15 23:02:30
Because |thread_checker_| moved to ThreadSafeState
| |
| 761 | |
| 762 // Ignore this check when download checking is not enabled. | 865 // Ignore this check when download checking is not enabled. |
| 763 if (!download_store_.get()) | 866 if (!download_store_.get()) |
| 764 return false; | 867 return false; |
| 765 | 868 |
| 766 std::vector<SBPrefix> prefixes; | 869 std::vector<SBPrefix> prefixes; |
| 767 GetDownloadUrlPrefixes(urls, &prefixes); | 870 GetDownloadUrlPrefixes(urls, &prefixes); |
| 768 return MatchAddPrefixes(download_store_.get(), | 871 return MatchAddPrefixes(download_store_.get(), |
| 769 safe_browsing_util::BINURL % 2, | 872 safe_browsing_util::BINURL % 2, |
| 770 prefixes, | 873 prefixes, |
| 771 prefix_hits); | 874 prefix_hits); |
| 772 } | 875 } |
| 773 | 876 |
| 774 bool SafeBrowsingDatabaseNew::ContainsCsdWhitelistedUrl(const GURL& url) { | 877 bool SafeBrowsingDatabaseNew::ContainsCsdWhitelistedUrl(const GURL& url) { |
| 775 // This method is theoretically thread-safe but document that it is currently | |
| 776 // only expected to be called on the IO thread. | |
| 777 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 778 | |
| 779 std::vector<SBFullHash> full_hashes; | 878 std::vector<SBFullHash> full_hashes; |
| 780 UrlToFullHashes(url, true, &full_hashes); | 879 UrlToFullHashes(url, true, &full_hashes); |
| 781 return ContainsWhitelistedHashes(csd_whitelist_, full_hashes); | 880 return ContainsWhitelistedHashes(SBWhitelistId::CSD, full_hashes); |
| 782 } | 881 } |
| 783 | 882 |
| 784 bool SafeBrowsingDatabaseNew::ContainsDownloadWhitelistedUrl(const GURL& url) { | 883 bool SafeBrowsingDatabaseNew::ContainsDownloadWhitelistedUrl(const GURL& url) { |
| 785 std::vector<SBFullHash> full_hashes; | 884 std::vector<SBFullHash> full_hashes; |
| 786 UrlToFullHashes(url, true, &full_hashes); | 885 UrlToFullHashes(url, true, &full_hashes); |
| 787 return ContainsWhitelistedHashes(download_whitelist_, full_hashes); | 886 return ContainsWhitelistedHashes(SBWhitelistId::DOWNLOAD, full_hashes); |
| 788 } | 887 } |
| 789 | 888 |
| 790 bool SafeBrowsingDatabaseNew::ContainsExtensionPrefixes( | 889 bool SafeBrowsingDatabaseNew::ContainsExtensionPrefixes( |
| 791 const std::vector<SBPrefix>& prefixes, | 890 const std::vector<SBPrefix>& prefixes, |
| 792 std::vector<SBPrefix>* prefix_hits) { | 891 std::vector<SBPrefix>* prefix_hits) { |
| 793 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 794 | |
| 795 if (!extension_blacklist_store_) | 892 if (!extension_blacklist_store_) |
| 796 return false; | 893 return false; |
| 797 | 894 |
| 798 return MatchAddPrefixes(extension_blacklist_store_.get(), | 895 return MatchAddPrefixes(extension_blacklist_store_.get(), |
| 799 safe_browsing_util::EXTENSIONBLACKLIST % 2, | 896 safe_browsing_util::EXTENSIONBLACKLIST % 2, |
| 800 prefixes, | 897 prefixes, |
| 801 prefix_hits); | 898 prefix_hits); |
| 802 } | 899 } |
| 803 | 900 |
| 804 bool SafeBrowsingDatabaseNew::ContainsSideEffectFreeWhitelistUrl( | 901 bool SafeBrowsingDatabaseNew::ContainsSideEffectFreeWhitelistUrl( |
| 805 const GURL& url) { | 902 const GURL& url) { |
| 806 // This method is theoretically thread-safe but document that it is currently | |
| 807 // only expected to be called on the UI thread. | |
| 808 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 809 | |
| 810 std::string host; | 903 std::string host; |
| 811 std::string path; | 904 std::string path; |
| 812 std::string query; | 905 std::string query; |
| 813 safe_browsing_util::CanonicalizeUrl(url, &host, &path, &query); | 906 safe_browsing_util::CanonicalizeUrl(url, &host, &path, &query); |
| 814 std::string url_to_check = host + path; | 907 std::string url_to_check = host + path; |
| 815 if (!query.empty()) | 908 if (!query.empty()) |
| 816 url_to_check += "?" + query; | 909 url_to_check += "?" + query; |
| 817 SBFullHash full_hash = SBFullHashForString(url_to_check); | 910 SBFullHash full_hash = SBFullHashForString(url_to_check); |
| 818 | 911 |
| 819 base::AutoLock locked(lookup_lock_); | 912 scoped_ptr<ReadTransaction> txn = state_manager_.BeginReadTransaction(); |
| 913 | |
| 914 const PrefixSet* side_effect_free_whitelist_prefix_set = | |
| 915 txn->GetPrefixSet(PrefixSetId::SIDE_EFFECT_FREE_WHITELIST); | |
| 820 | 916 |
| 821 // |side_effect_free_whitelist_prefix_set_| is empty until it is either read | 917 // |side_effect_free_whitelist_prefix_set_| is empty until it is either read |
| 822 // from disk, or the first update populates it. Bail out without a hit if | 918 // from disk, or the first update populates it. Bail out without a hit if |
| 823 // not yet available. | 919 // not yet available. |
| 824 if (!side_effect_free_whitelist_prefix_set_.get()) | 920 if (!side_effect_free_whitelist_prefix_set) |
| 825 return false; | 921 return false; |
| 826 | 922 |
| 827 return side_effect_free_whitelist_prefix_set_->Exists(full_hash); | 923 return side_effect_free_whitelist_prefix_set->Exists(full_hash); |
| 828 } | 924 } |
| 829 | 925 |
| 830 bool SafeBrowsingDatabaseNew::ContainsMalwareIP(const std::string& ip_address) { | 926 bool SafeBrowsingDatabaseNew::ContainsMalwareIP(const std::string& ip_address) { |
| 831 // This method is theoretically thread-safe but document that it is currently | |
| 832 // only expected to be called on the IO thread. | |
| 833 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 834 | |
| 835 net::IPAddressNumber ip_number; | 927 net::IPAddressNumber ip_number; |
| 836 if (!net::ParseIPLiteralToNumber(ip_address, &ip_number)) | 928 if (!net::ParseIPLiteralToNumber(ip_address, &ip_number)) |
| 837 return false; | 929 return false; |
| 838 if (ip_number.size() == net::kIPv4AddressSize) | 930 if (ip_number.size() == net::kIPv4AddressSize) |
| 839 ip_number = net::ConvertIPv4NumberToIPv6Number(ip_number); | 931 ip_number = net::ConvertIPv4NumberToIPv6Number(ip_number); |
| 840 if (ip_number.size() != net::kIPv6AddressSize) | 932 if (ip_number.size() != net::kIPv6AddressSize) |
| 841 return false; // better safe than sorry. | 933 return false; // better safe than sorry. |
| 842 | 934 |
| 843 base::AutoLock locked(lookup_lock_); | 935 scoped_ptr<ReadTransaction> txn = state_manager_.BeginReadTransaction(); |
| 844 for (IPBlacklist::const_iterator it = ip_blacklist_.begin(); | 936 const IPBlacklist* ip_blacklist = txn->ip_blacklist(); |
| 845 it != ip_blacklist_.end(); | 937 for (IPBlacklist::const_iterator it = ip_blacklist->begin(); |
| 846 ++it) { | 938 it != ip_blacklist->end(); ++it) { |
| 847 const std::string& mask = it->first; | 939 const std::string& mask = it->first; |
| 848 DCHECK_EQ(mask.size(), ip_number.size()); | 940 DCHECK_EQ(mask.size(), ip_number.size()); |
| 849 std::string subnet(net::kIPv6AddressSize, '\0'); | 941 std::string subnet(net::kIPv6AddressSize, '\0'); |
| 850 for (size_t i = 0; i < net::kIPv6AddressSize; ++i) { | 942 for (size_t i = 0; i < net::kIPv6AddressSize; ++i) { |
| 851 subnet[i] = ip_number[i] & mask[i]; | 943 subnet[i] = ip_number[i] & mask[i]; |
| 852 } | 944 } |
| 853 const std::string hash = base::SHA1HashString(subnet); | 945 const std::string hash = base::SHA1HashString(subnet); |
| 854 DVLOG(2) << "Lookup Malware IP: " | 946 DVLOG(2) << "Lookup Malware IP: " |
| 855 << " ip:" << ip_address | 947 << " ip:" << ip_address |
| 856 << " mask:" << base::HexEncode(mask.data(), mask.size()) | 948 << " mask:" << base::HexEncode(mask.data(), mask.size()) |
| 857 << " subnet:" << base::HexEncode(subnet.data(), subnet.size()) | 949 << " subnet:" << base::HexEncode(subnet.data(), subnet.size()) |
| 858 << " hash:" << base::HexEncode(hash.data(), hash.size()); | 950 << " hash:" << base::HexEncode(hash.data(), hash.size()); |
| 859 if (it->second.count(hash) > 0) { | 951 if (it->second.count(hash) > 0) { |
| 860 return true; | 952 return true; |
| 861 } | 953 } |
| 862 } | 954 } |
| 863 return false; | 955 return false; |
| 864 } | 956 } |
| 865 | 957 |
| 866 bool SafeBrowsingDatabaseNew::ContainsDownloadWhitelistedString( | 958 bool SafeBrowsingDatabaseNew::ContainsDownloadWhitelistedString( |
| 867 const std::string& str) { | 959 const std::string& str) { |
| 868 // This method is theoretically thread-safe but document that it is currently | |
| 869 // only expected to be called on the IO thread. | |
| 870 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 871 | |
| 872 std::vector<SBFullHash> hashes; | 960 std::vector<SBFullHash> hashes; |
| 873 hashes.push_back(SBFullHashForString(str)); | 961 hashes.push_back(SBFullHashForString(str)); |
| 874 return ContainsWhitelistedHashes(download_whitelist_, hashes); | 962 return ContainsWhitelistedHashes(SBWhitelistId::DOWNLOAD, hashes); |
| 875 } | 963 } |
| 876 | 964 |
| 877 bool SafeBrowsingDatabaseNew::ContainsWhitelistedHashes( | 965 bool SafeBrowsingDatabaseNew::ContainsWhitelistedHashes( |
| 878 const SBWhitelist& whitelist, | 966 SBWhitelistId whitelist_id, |
| 879 const std::vector<SBFullHash>& hashes) { | 967 const std::vector<SBFullHash>& hashes) { |
| 880 // This method is theoretically thread-safe but document that it is currently | 968 scoped_ptr<ReadTransaction> txn = state_manager_.BeginReadTransaction(); |
| 881 // only expected to be called on the IO thread. | 969 const SBWhitelist* whitelist = txn->GetSBWhitelist(whitelist_id); |
| 882 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 970 if (whitelist->second) |
| 883 | |
| 884 base::AutoLock l(lookup_lock_); | |
| 885 if (whitelist.second) | |
| 886 return true; | 971 return true; |
| 887 for (std::vector<SBFullHash>::const_iterator it = hashes.begin(); | 972 for (std::vector<SBFullHash>::const_iterator it = hashes.begin(); |
| 888 it != hashes.end(); ++it) { | 973 it != hashes.end(); ++it) { |
| 889 if (std::binary_search(whitelist.first.begin(), whitelist.first.end(), | 974 if (std::binary_search(whitelist->first.begin(), whitelist->first.end(), |
| 890 *it, SBFullHashLess)) { | 975 *it, SBFullHashLess)) { |
| 891 return true; | 976 return true; |
| 892 } | 977 } |
| 893 } | 978 } |
| 894 return false; | 979 return false; |
| 895 } | 980 } |
| 896 | 981 |
| 897 // Helper to insert add-chunk entries. | 982 // Helper to insert add-chunk entries. |
| 898 void SafeBrowsingDatabaseNew::InsertAddChunk( | 983 void SafeBrowsingDatabaseNew::InsertAddChunk( |
| 899 SafeBrowsingStore* store, | 984 SafeBrowsingStore* store, |
| 900 const safe_browsing_util::ListType list_id, | 985 const safe_browsing_util::ListType list_id, |
| 901 const SBChunkData& chunk_data) { | 986 const SBChunkData& chunk_data) { |
| 902 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 903 DCHECK(store); | 987 DCHECK(store); |
| 904 | 988 |
| 905 // The server can give us a chunk that we already have because | 989 // The server can give us a chunk that we already have because |
| 906 // it's part of a range. Don't add it again. | 990 // it's part of a range. Don't add it again. |
| 907 const int chunk_id = chunk_data.ChunkNumber(); | 991 const int chunk_id = chunk_data.ChunkNumber(); |
| 908 const int encoded_chunk_id = EncodeChunkId(chunk_id, list_id); | 992 const int encoded_chunk_id = EncodeChunkId(chunk_id, list_id); |
| 909 if (store->CheckAddChunk(encoded_chunk_id)) | 993 if (store->CheckAddChunk(encoded_chunk_id)) |
| 910 return; | 994 return; |
| 911 | 995 |
| 912 store->SetAddChunk(encoded_chunk_id); | 996 store->SetAddChunk(encoded_chunk_id); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 923 store->WriteAddHash(encoded_chunk_id, chunk_data.FullHashAt(i)); | 1007 store->WriteAddHash(encoded_chunk_id, chunk_data.FullHashAt(i)); |
| 924 } | 1008 } |
| 925 } | 1009 } |
| 926 } | 1010 } |
| 927 | 1011 |
| 928 // Helper to insert sub-chunk entries. | 1012 // Helper to insert sub-chunk entries. |
| 929 void SafeBrowsingDatabaseNew::InsertSubChunk( | 1013 void SafeBrowsingDatabaseNew::InsertSubChunk( |
| 930 SafeBrowsingStore* store, | 1014 SafeBrowsingStore* store, |
| 931 const safe_browsing_util::ListType list_id, | 1015 const safe_browsing_util::ListType list_id, |
| 932 const SBChunkData& chunk_data) { | 1016 const SBChunkData& chunk_data) { |
| 933 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 934 DCHECK(store); | 1017 DCHECK(store); |
| 935 | 1018 |
| 936 // The server can give us a chunk that we already have because | 1019 // The server can give us a chunk that we already have because |
| 937 // it's part of a range. Don't add it again. | 1020 // it's part of a range. Don't add it again. |
| 938 const int chunk_id = chunk_data.ChunkNumber(); | 1021 const int chunk_id = chunk_data.ChunkNumber(); |
| 939 const int encoded_chunk_id = EncodeChunkId(chunk_id, list_id); | 1022 const int encoded_chunk_id = EncodeChunkId(chunk_id, list_id); |
| 940 if (store->CheckSubChunk(encoded_chunk_id)) | 1023 if (store->CheckSubChunk(encoded_chunk_id)) |
| 941 return; | 1024 return; |
| 942 | 1025 |
| 943 store->SetSubChunk(encoded_chunk_id); | 1026 store->SetSubChunk(encoded_chunk_id); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 958 const int encoded_add_chunk_id = EncodeChunkId(add_chunk_id, list_id); | 1041 const int encoded_add_chunk_id = EncodeChunkId(add_chunk_id, list_id); |
| 959 store->WriteSubHash(encoded_chunk_id, encoded_add_chunk_id, | 1042 store->WriteSubHash(encoded_chunk_id, encoded_add_chunk_id, |
| 960 chunk_data.FullHashAt(i)); | 1043 chunk_data.FullHashAt(i)); |
| 961 } | 1044 } |
| 962 } | 1045 } |
| 963 } | 1046 } |
| 964 | 1047 |
| 965 void SafeBrowsingDatabaseNew::InsertChunks( | 1048 void SafeBrowsingDatabaseNew::InsertChunks( |
| 966 const std::string& list_name, | 1049 const std::string& list_name, |
| 967 const std::vector<SBChunkData*>& chunks) { | 1050 const std::vector<SBChunkData*>& chunks) { |
| 968 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 969 | |
| 970 if (corruption_detected_ || chunks.empty()) | 1051 if (corruption_detected_ || chunks.empty()) |
| 971 return; | 1052 return; |
| 972 | 1053 |
| 973 const base::TimeTicks before = base::TimeTicks::Now(); | 1054 const base::TimeTicks before = base::TimeTicks::Now(); |
| 974 | 1055 |
| 975 // TODO(shess): The caller should just pass list_id. | 1056 // TODO(shess): The caller should just pass list_id. |
| 976 const safe_browsing_util::ListType list_id = | 1057 const safe_browsing_util::ListType list_id = |
| 977 safe_browsing_util::GetListId(list_name); | 1058 safe_browsing_util::GetListId(list_name); |
| 978 | 1059 |
| 979 SafeBrowsingStore* store = GetStore(list_id); | 1060 SafeBrowsingStore* store = GetStore(list_id); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 993 NOTREACHED(); | 1074 NOTREACHED(); |
| 994 } | 1075 } |
| 995 } | 1076 } |
| 996 store->FinishChunk(); | 1077 store->FinishChunk(); |
| 997 | 1078 |
| 998 UMA_HISTOGRAM_TIMES("SB2.ChunkInsert", base::TimeTicks::Now() - before); | 1079 UMA_HISTOGRAM_TIMES("SB2.ChunkInsert", base::TimeTicks::Now() - before); |
| 999 } | 1080 } |
| 1000 | 1081 |
| 1001 void SafeBrowsingDatabaseNew::DeleteChunks( | 1082 void SafeBrowsingDatabaseNew::DeleteChunks( |
| 1002 const std::vector<SBChunkDelete>& chunk_deletes) { | 1083 const std::vector<SBChunkDelete>& chunk_deletes) { |
| 1003 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 1004 | |
| 1005 if (corruption_detected_ || chunk_deletes.empty()) | 1084 if (corruption_detected_ || chunk_deletes.empty()) |
| 1006 return; | 1085 return; |
| 1007 | 1086 |
| 1008 const std::string& list_name = chunk_deletes.front().list_name; | 1087 const std::string& list_name = chunk_deletes.front().list_name; |
| 1009 const safe_browsing_util::ListType list_id = | 1088 const safe_browsing_util::ListType list_id = |
| 1010 safe_browsing_util::GetListId(list_name); | 1089 safe_browsing_util::GetListId(list_name); |
| 1011 | 1090 |
| 1012 SafeBrowsingStore* store = GetStore(list_id); | 1091 SafeBrowsingStore* store = GetStore(list_id); |
| 1013 if (!store) return; | 1092 if (!store) return; |
| 1014 | 1093 |
| 1015 change_detected_ = true; | 1094 change_detected_ = true; |
| 1016 | 1095 |
| 1017 for (size_t i = 0; i < chunk_deletes.size(); ++i) { | 1096 for (size_t i = 0; i < chunk_deletes.size(); ++i) { |
| 1018 std::vector<int> chunk_numbers; | 1097 std::vector<int> chunk_numbers; |
| 1019 RangesToChunks(chunk_deletes[i].chunk_del, &chunk_numbers); | 1098 RangesToChunks(chunk_deletes[i].chunk_del, &chunk_numbers); |
| 1020 for (size_t j = 0; j < chunk_numbers.size(); ++j) { | 1099 for (size_t j = 0; j < chunk_numbers.size(); ++j) { |
| 1021 const int encoded_chunk_id = EncodeChunkId(chunk_numbers[j], list_id); | 1100 const int encoded_chunk_id = EncodeChunkId(chunk_numbers[j], list_id); |
| 1022 if (chunk_deletes[i].is_sub_del) | 1101 if (chunk_deletes[i].is_sub_del) |
| 1023 store->DeleteSubChunk(encoded_chunk_id); | 1102 store->DeleteSubChunk(encoded_chunk_id); |
| 1024 else | 1103 else |
| 1025 store->DeleteAddChunk(encoded_chunk_id); | 1104 store->DeleteAddChunk(encoded_chunk_id); |
| 1026 } | 1105 } |
| 1027 } | 1106 } |
| 1028 } | 1107 } |
| 1029 | 1108 |
| 1030 void SafeBrowsingDatabaseNew::CacheHashResults( | 1109 void SafeBrowsingDatabaseNew::CacheHashResults( |
| 1031 const std::vector<SBPrefix>& prefixes, | 1110 const std::vector<SBPrefix>& prefixes, |
| 1032 const std::vector<SBFullHashResult>& full_hits, | 1111 const std::vector<SBFullHashResult>& full_hits, |
| 1033 const base::TimeDelta& cache_lifetime) { | 1112 const base::TimeDelta& cache_lifetime) { |
| 1034 // This method is theoretically thread-safe but document that it is currently | |
| 1035 // only expected to be called on the IO thread. | |
| 1036 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 1037 | |
| 1038 const base::Time expire_after = base::Time::Now() + cache_lifetime; | 1113 const base::Time expire_after = base::Time::Now() + cache_lifetime; |
| 1039 | 1114 |
| 1040 base::AutoLock locked(lookup_lock_); | 1115 scoped_ptr<ReadTransaction> txn = state_manager_.BeginReadTransaction(); |
| 1116 PrefixGetHashCache* prefix_gethash_cache = txn->prefix_gethash_cache(); | |
| 1041 | 1117 |
| 1042 // Create or reset all cached results for these prefixes. | 1118 // Create or reset all cached results for these prefixes. |
| 1043 for (size_t i = 0; i < prefixes.size(); ++i) { | 1119 for (size_t i = 0; i < prefixes.size(); ++i) { |
| 1044 prefix_gethash_cache_[prefixes[i]] = SBCachedFullHashResult(expire_after); | 1120 (*prefix_gethash_cache)[prefixes[i]] = SBCachedFullHashResult(expire_after); |
| 1045 } | 1121 } |
| 1046 | 1122 |
| 1047 // Insert any fullhash hits. Note that there may be one, multiple, or no | 1123 // Insert any fullhash hits. Note that there may be one, multiple, or no |
| 1048 // fullhashes for any given entry in |prefixes|. | 1124 // fullhashes for any given entry in |prefixes|. |
| 1049 for (size_t i = 0; i < full_hits.size(); ++i) { | 1125 for (size_t i = 0; i < full_hits.size(); ++i) { |
| 1050 const SBPrefix prefix = full_hits[i].hash.prefix; | 1126 const SBPrefix prefix = full_hits[i].hash.prefix; |
| 1051 prefix_gethash_cache_[prefix].full_hashes.push_back(full_hits[i]); | 1127 (*prefix_gethash_cache)[prefix].full_hashes.push_back(full_hits[i]); |
| 1052 } | 1128 } |
| 1053 } | 1129 } |
| 1054 | 1130 |
| 1055 bool SafeBrowsingDatabaseNew::UpdateStarted( | 1131 bool SafeBrowsingDatabaseNew::UpdateStarted( |
| 1056 std::vector<SBListChunkRanges>* lists) { | 1132 std::vector<SBListChunkRanges>* lists) { |
| 1057 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 1058 DCHECK(lists); | 1133 DCHECK(lists); |
| 1059 | 1134 |
| 1060 // If |BeginUpdate()| fails, reset the database. | 1135 // If |BeginUpdate()| fails, reset the database. |
| 1061 if (!browse_store_->BeginUpdate()) { | 1136 if (!browse_store_->BeginUpdate()) { |
| 1062 RecordFailure(FAILURE_BROWSE_DATABASE_UPDATE_BEGIN); | 1137 RecordFailure(FAILURE_BROWSE_DATABASE_UPDATE_BEGIN); |
| 1063 HandleCorruptDatabase(); | 1138 HandleCorruptDatabase(); |
| 1064 return false; | 1139 return false; |
| 1065 } | 1140 } |
| 1066 | 1141 |
| 1067 if (download_store_.get() && !download_store_->BeginUpdate()) { | 1142 if (download_store_.get() && !download_store_->BeginUpdate()) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1103 return false; | 1178 return false; |
| 1104 } | 1179 } |
| 1105 | 1180 |
| 1106 if (unwanted_software_store_ && !unwanted_software_store_->BeginUpdate()) { | 1181 if (unwanted_software_store_ && !unwanted_software_store_->BeginUpdate()) { |
| 1107 RecordFailure(FAILURE_UNWANTED_SOFTWARE_DATABASE_UPDATE_BEGIN); | 1182 RecordFailure(FAILURE_UNWANTED_SOFTWARE_DATABASE_UPDATE_BEGIN); |
| 1108 HandleCorruptDatabase(); | 1183 HandleCorruptDatabase(); |
| 1109 return false; | 1184 return false; |
| 1110 } | 1185 } |
| 1111 | 1186 |
| 1112 { | 1187 { |
| 1113 base::AutoLock locked(lookup_lock_); | 1188 scoped_ptr<WriteTransaction> txn = state_manager_.BeginWriteTransaction(); |
| 1114 // Cached fullhash results must be cleared on every database update (whether | 1189 // Cached fullhash results must be cleared on every database update (whether |
| 1115 // successful or not.) | 1190 // successful or not). |
| 1116 prefix_gethash_cache_.clear(); | 1191 txn->clear_prefix_gethash_cache(); |
| 1117 } | 1192 } |
| 1118 | 1193 |
| 1119 UpdateChunkRangesForLists(browse_store_.get(), | 1194 UpdateChunkRangesForLists(browse_store_.get(), |
| 1120 safe_browsing_util::kMalwareList, | 1195 safe_browsing_util::kMalwareList, |
| 1121 safe_browsing_util::kPhishingList, | 1196 safe_browsing_util::kPhishingList, |
| 1122 lists); | 1197 lists); |
| 1123 | 1198 |
| 1124 // NOTE(shess): |download_store_| used to contain kBinHashList, which has been | 1199 // NOTE(shess): |download_store_| used to contain kBinHashList, which has been |
| 1125 // deprecated. Code to delete the list from the store shows ~15k hits/day as | 1200 // deprecated. Code to delete the list from the store shows ~15k hits/day as |
| 1126 // of Feb 2014, so it has been removed. Everything _should_ be resilient to | 1201 // of Feb 2014, so it has been removed. Everything _should_ be resilient to |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 1146 UpdateChunkRangesForList(unwanted_software_store_.get(), | 1221 UpdateChunkRangesForList(unwanted_software_store_.get(), |
| 1147 safe_browsing_util::kUnwantedUrlList, | 1222 safe_browsing_util::kUnwantedUrlList, |
| 1148 lists); | 1223 lists); |
| 1149 | 1224 |
| 1150 corruption_detected_ = false; | 1225 corruption_detected_ = false; |
| 1151 change_detected_ = false; | 1226 change_detected_ = false; |
| 1152 return true; | 1227 return true; |
| 1153 } | 1228 } |
| 1154 | 1229 |
| 1155 void SafeBrowsingDatabaseNew::UpdateFinished(bool update_succeeded) { | 1230 void SafeBrowsingDatabaseNew::UpdateFinished(bool update_succeeded) { |
| 1156 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 1157 | |
| 1158 // The update may have failed due to corrupt storage (for instance, | 1231 // The update may have failed due to corrupt storage (for instance, |
| 1159 // an excessive number of invalid add_chunks and sub_chunks). | 1232 // an excessive number of invalid add_chunks and sub_chunks). |
| 1160 // Double-check that the databases are valid. | 1233 // Double-check that the databases are valid. |
| 1161 // TODO(shess): Providing a checksum for the add_chunk and sub_chunk | 1234 // TODO(shess): Providing a checksum for the add_chunk and sub_chunk |
| 1162 // sections would allow throwing a corruption error in | 1235 // sections would allow throwing a corruption error in |
| 1163 // UpdateStarted(). | 1236 // UpdateStarted(). |
| 1164 if (!update_succeeded) { | 1237 if (!update_succeeded) { |
| 1165 if (!browse_store_->CheckValidity()) | 1238 if (!browse_store_->CheckValidity()) |
| 1166 DLOG(ERROR) << "Safe-browsing browse database corrupt."; | 1239 DLOG(ERROR) << "Safe-browsing browse database corrupt."; |
| 1167 | 1240 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1229 int64 size_bytes = UpdateHashPrefixStore( | 1302 int64 size_bytes = UpdateHashPrefixStore( |
| 1230 DownloadDBFilename(filename_base_), | 1303 DownloadDBFilename(filename_base_), |
| 1231 download_store_.get(), | 1304 download_store_.get(), |
| 1232 FAILURE_DOWNLOAD_DATABASE_UPDATE_FINISH); | 1305 FAILURE_DOWNLOAD_DATABASE_UPDATE_FINISH); |
| 1233 UMA_HISTOGRAM_COUNTS("SB2.DownloadDatabaseKilobytes", | 1306 UMA_HISTOGRAM_COUNTS("SB2.DownloadDatabaseKilobytes", |
| 1234 static_cast<int>(size_bytes / 1024)); | 1307 static_cast<int>(size_bytes / 1024)); |
| 1235 } | 1308 } |
| 1236 | 1309 |
| 1237 UpdatePrefixSetUrlStore(BrowseDBFilename(filename_base_), | 1310 UpdatePrefixSetUrlStore(BrowseDBFilename(filename_base_), |
| 1238 browse_store_.get(), | 1311 browse_store_.get(), |
| 1239 &browse_prefix_set_, | 1312 PrefixSetId::BROWSE, |
| 1240 FAILURE_BROWSE_DATABASE_UPDATE_FINISH, | 1313 FAILURE_BROWSE_DATABASE_UPDATE_FINISH, |
| 1241 FAILURE_BROWSE_PREFIX_SET_WRITE, | 1314 FAILURE_BROWSE_PREFIX_SET_WRITE, |
| 1242 true); | 1315 true); |
| 1243 | 1316 |
| 1244 UpdateWhitelistStore(CsdWhitelistDBFilename(filename_base_), | 1317 UpdateWhitelistStore(CsdWhitelistDBFilename(filename_base_), |
| 1245 csd_whitelist_store_.get(), | 1318 csd_whitelist_store_.get(), |
| 1246 &csd_whitelist_); | 1319 SBWhitelistId::CSD); |
| 1247 UpdateWhitelistStore(DownloadWhitelistDBFilename(filename_base_), | 1320 UpdateWhitelistStore(DownloadWhitelistDBFilename(filename_base_), |
| 1248 download_whitelist_store_.get(), | 1321 download_whitelist_store_.get(), |
| 1249 &download_whitelist_); | 1322 SBWhitelistId::DOWNLOAD); |
| 1250 | 1323 |
| 1251 if (extension_blacklist_store_) { | 1324 if (extension_blacklist_store_) { |
| 1252 int64 size_bytes = UpdateHashPrefixStore( | 1325 int64 size_bytes = UpdateHashPrefixStore( |
| 1253 ExtensionBlacklistDBFilename(filename_base_), | 1326 ExtensionBlacklistDBFilename(filename_base_), |
| 1254 extension_blacklist_store_.get(), | 1327 extension_blacklist_store_.get(), |
| 1255 FAILURE_EXTENSION_BLACKLIST_UPDATE_FINISH); | 1328 FAILURE_EXTENSION_BLACKLIST_UPDATE_FINISH); |
| 1256 UMA_HISTOGRAM_COUNTS("SB2.ExtensionBlacklistKilobytes", | 1329 UMA_HISTOGRAM_COUNTS("SB2.ExtensionBlacklistKilobytes", |
| 1257 static_cast<int>(size_bytes / 1024)); | 1330 static_cast<int>(size_bytes / 1024)); |
| 1258 } | 1331 } |
| 1259 | 1332 |
| 1260 if (side_effect_free_whitelist_store_) { | 1333 if (side_effect_free_whitelist_store_) { |
| 1261 UpdatePrefixSetUrlStore(SideEffectFreeWhitelistDBFilename(filename_base_), | 1334 UpdatePrefixSetUrlStore(SideEffectFreeWhitelistDBFilename(filename_base_), |
| 1262 side_effect_free_whitelist_store_.get(), | 1335 side_effect_free_whitelist_store_.get(), |
| 1263 &side_effect_free_whitelist_prefix_set_, | 1336 PrefixSetId::SIDE_EFFECT_FREE_WHITELIST, |
| 1264 FAILURE_SIDE_EFFECT_FREE_WHITELIST_UPDATE_FINISH, | 1337 FAILURE_SIDE_EFFECT_FREE_WHITELIST_UPDATE_FINISH, |
| 1265 FAILURE_SIDE_EFFECT_FREE_WHITELIST_PREFIX_SET_WRITE, | 1338 FAILURE_SIDE_EFFECT_FREE_WHITELIST_PREFIX_SET_WRITE, |
| 1266 false); | 1339 false); |
| 1267 } | 1340 } |
| 1268 | 1341 |
| 1269 if (ip_blacklist_store_) | 1342 if (ip_blacklist_store_) |
| 1270 UpdateIpBlacklistStore(); | 1343 UpdateIpBlacklistStore(); |
| 1271 | 1344 |
| 1272 if (unwanted_software_store_) { | 1345 if (unwanted_software_store_) { |
| 1273 UpdatePrefixSetUrlStore(UnwantedSoftwareDBFilename(filename_base_), | 1346 UpdatePrefixSetUrlStore(UnwantedSoftwareDBFilename(filename_base_), |
| 1274 unwanted_software_store_.get(), | 1347 unwanted_software_store_.get(), |
| 1275 &unwanted_software_prefix_set_, | 1348 PrefixSetId::UNWANTED_SOFTWARE, |
| 1276 FAILURE_UNWANTED_SOFTWARE_DATABASE_UPDATE_FINISH, | 1349 FAILURE_UNWANTED_SOFTWARE_DATABASE_UPDATE_FINISH, |
| 1277 FAILURE_UNWANTED_SOFTWARE_PREFIX_SET_WRITE, | 1350 FAILURE_UNWANTED_SOFTWARE_PREFIX_SET_WRITE, |
| 1278 true); | 1351 true); |
| 1279 } | 1352 } |
| 1280 } | 1353 } |
| 1281 | 1354 |
| 1282 void SafeBrowsingDatabaseNew::UpdateWhitelistStore( | 1355 void SafeBrowsingDatabaseNew::UpdateWhitelistStore( |
| 1283 const base::FilePath& store_filename, | 1356 const base::FilePath& store_filename, |
| 1284 SafeBrowsingStore* store, | 1357 SafeBrowsingStore* store, |
| 1285 SBWhitelist* whitelist) { | 1358 SBWhitelistId whitelist_id) { |
| 1286 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 1287 | |
| 1288 if (!store) | 1359 if (!store) |
| 1289 return; | 1360 return; |
| 1290 | 1361 |
| 1291 // Note: |builder| will not be empty. The current data store implementation | 1362 // Note: |builder| will not be empty. The current data store implementation |
| 1292 // stores all full-length hashes as both full and prefix hashes. | 1363 // stores all full-length hashes as both full and prefix hashes. |
| 1293 safe_browsing::PrefixSetBuilder builder; | 1364 PrefixSetBuilder builder; |
| 1294 std::vector<SBAddFullHash> full_hashes; | 1365 std::vector<SBAddFullHash> full_hashes; |
| 1295 if (!store->FinishUpdate(&builder, &full_hashes)) { | 1366 if (!store->FinishUpdate(&builder, &full_hashes)) { |
| 1296 RecordFailure(FAILURE_WHITELIST_DATABASE_UPDATE_FINISH); | 1367 RecordFailure(FAILURE_WHITELIST_DATABASE_UPDATE_FINISH); |
| 1297 WhitelistEverything(whitelist); | 1368 WhitelistEverything(whitelist_id); |
| 1298 return; | 1369 return; |
| 1299 } | 1370 } |
| 1300 | 1371 |
| 1301 #if defined(OS_MACOSX) | 1372 #if defined(OS_MACOSX) |
| 1302 base::mac::SetFileBackupExclusion(store_filename); | 1373 base::mac::SetFileBackupExclusion(store_filename); |
| 1303 #endif | 1374 #endif |
| 1304 | 1375 |
| 1305 LoadWhitelist(full_hashes, whitelist); | 1376 LoadWhitelist(full_hashes, whitelist_id); |
| 1306 } | 1377 } |
| 1307 | 1378 |
| 1308 int64 SafeBrowsingDatabaseNew::UpdateHashPrefixStore( | 1379 int64 SafeBrowsingDatabaseNew::UpdateHashPrefixStore( |
| 1309 const base::FilePath& store_filename, | 1380 const base::FilePath& store_filename, |
| 1310 SafeBrowsingStore* store, | 1381 SafeBrowsingStore* store, |
| 1311 FailureType failure_type) { | 1382 FailureType failure_type) { |
| 1312 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 1313 | |
| 1314 // These results are not used after this call. Simply ignore the | 1383 // These results are not used after this call. Simply ignore the |
| 1315 // returned value after FinishUpdate(...). | 1384 // returned value after FinishUpdate(...). |
| 1316 safe_browsing::PrefixSetBuilder builder; | 1385 PrefixSetBuilder builder; |
| 1317 std::vector<SBAddFullHash> add_full_hashes_result; | 1386 std::vector<SBAddFullHash> add_full_hashes_result; |
| 1318 | 1387 |
| 1319 if (!store->FinishUpdate(&builder, &add_full_hashes_result)) | 1388 if (!store->FinishUpdate(&builder, &add_full_hashes_result)) |
| 1320 RecordFailure(failure_type); | 1389 RecordFailure(failure_type); |
| 1321 | 1390 |
| 1322 #if defined(OS_MACOSX) | 1391 #if defined(OS_MACOSX) |
| 1323 base::mac::SetFileBackupExclusion(store_filename); | 1392 base::mac::SetFileBackupExclusion(store_filename); |
| 1324 #endif | 1393 #endif |
| 1325 | 1394 |
| 1326 return GetFileSizeOrZero(store_filename); | 1395 return GetFileSizeOrZero(store_filename); |
| 1327 } | 1396 } |
| 1328 | 1397 |
| 1329 void SafeBrowsingDatabaseNew::UpdatePrefixSetUrlStore( | 1398 void SafeBrowsingDatabaseNew::UpdatePrefixSetUrlStore( |
| 1330 const base::FilePath& db_filename, | 1399 const base::FilePath& db_filename, |
| 1331 SafeBrowsingStore* url_store, | 1400 SafeBrowsingStore* url_store, |
| 1332 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set, | 1401 PrefixSetId prefix_set_id, |
| 1333 FailureType finish_failure_type, | 1402 FailureType finish_failure_type, |
| 1334 FailureType write_failure_type, | 1403 FailureType write_failure_type, |
| 1335 bool store_full_hashes_in_prefix_set) { | 1404 bool store_full_hashes_in_prefix_set) { |
| 1336 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 1337 DCHECK(url_store); | 1405 DCHECK(url_store); |
| 1338 DCHECK(prefix_set); | |
| 1339 | 1406 |
| 1340 // Measure the amount of IO during the filter build. | 1407 // Measure the amount of IO during the filter build. |
| 1341 base::IoCounters io_before, io_after; | 1408 base::IoCounters io_before, io_after; |
| 1342 base::ProcessHandle handle = base::GetCurrentProcessHandle(); | 1409 base::ProcessHandle handle = base::GetCurrentProcessHandle(); |
| 1343 scoped_ptr<base::ProcessMetrics> metric( | 1410 scoped_ptr<base::ProcessMetrics> metric( |
| 1344 #if !defined(OS_MACOSX) | 1411 #if !defined(OS_MACOSX) |
| 1345 base::ProcessMetrics::CreateProcessMetrics(handle) | 1412 base::ProcessMetrics::CreateProcessMetrics(handle) |
| 1346 #else | 1413 #else |
| 1347 // Getting stats only for the current process is enough, so NULL is fine. | 1414 // Getting stats only for the current process is enough, so NULL is fine. |
| 1348 base::ProcessMetrics::CreateProcessMetrics(handle, NULL) | 1415 base::ProcessMetrics::CreateProcessMetrics(handle, NULL) |
| 1349 #endif | 1416 #endif |
| 1350 ); | 1417 ); |
| 1351 | 1418 |
| 1352 // IoCounters are currently not supported on Mac, and may not be | 1419 // IoCounters are currently not supported on Mac, and may not be |
| 1353 // available for Linux, so we check the result and only show IO | 1420 // available for Linux, so we check the result and only show IO |
| 1354 // stats if they are available. | 1421 // stats if they are available. |
| 1355 const bool got_counters = metric->GetIOCounters(&io_before); | 1422 const bool got_counters = metric->GetIOCounters(&io_before); |
| 1356 | 1423 |
| 1357 const base::TimeTicks before = base::TimeTicks::Now(); | 1424 const base::TimeTicks before = base::TimeTicks::Now(); |
| 1358 | 1425 |
| 1359 // TODO(shess): Perhaps refactor to let builder accumulate full hashes on the | 1426 // TODO(shess): Perhaps refactor to let builder accumulate full hashes on the |
| 1360 // fly? Other clients use the SBAddFullHash vector, but AFAICT they only use | 1427 // fly? Other clients use the SBAddFullHash vector, but AFAICT they only use |
| 1361 // the SBFullHash portion. It would need an accessor on PrefixSet. | 1428 // the SBFullHash portion. It would need an accessor on PrefixSet. |
| 1362 safe_browsing::PrefixSetBuilder builder; | 1429 PrefixSetBuilder builder; |
| 1363 std::vector<SBAddFullHash> add_full_hashes; | 1430 std::vector<SBAddFullHash> add_full_hashes; |
| 1364 if (!url_store->FinishUpdate(&builder, &add_full_hashes)) { | 1431 if (!url_store->FinishUpdate(&builder, &add_full_hashes)) { |
| 1365 RecordFailure(finish_failure_type); | 1432 RecordFailure(finish_failure_type); |
| 1366 return; | 1433 return; |
| 1367 } | 1434 } |
| 1368 | 1435 |
| 1369 scoped_ptr<const safe_browsing::PrefixSet> new_prefix_set; | 1436 scoped_ptr<const PrefixSet> new_prefix_set; |
| 1370 if (store_full_hashes_in_prefix_set) { | 1437 if (store_full_hashes_in_prefix_set) { |
| 1371 std::vector<SBFullHash> full_hash_results; | 1438 std::vector<SBFullHash> full_hash_results; |
| 1372 for (size_t i = 0; i < add_full_hashes.size(); ++i) { | 1439 for (size_t i = 0; i < add_full_hashes.size(); ++i) { |
| 1373 full_hash_results.push_back(add_full_hashes[i].full_hash); | 1440 full_hash_results.push_back(add_full_hashes[i].full_hash); |
| 1374 } | 1441 } |
| 1375 | 1442 |
| 1376 new_prefix_set = builder.GetPrefixSet(full_hash_results); | 1443 new_prefix_set = builder.GetPrefixSet(full_hash_results); |
| 1377 } else { | 1444 } else { |
| 1378 new_prefix_set = builder.GetPrefixSetNoHashes(); | 1445 new_prefix_set = builder.GetPrefixSetNoHashes(); |
| 1379 } | 1446 } |
| 1380 | 1447 |
| 1381 // Swap in the newly built filter. | 1448 // Swap in the newly built filter. |
| 1382 { | 1449 { |
| 1383 base::AutoLock locked(lookup_lock_); | 1450 scoped_ptr<WriteTransaction> txn = state_manager_.BeginWriteTransaction(); |
| 1384 prefix_set->swap(new_prefix_set); | 1451 txn->SwapPrefixSet(prefix_set_id, new_prefix_set.Pass()); |
| 1385 } | 1452 } |
| 1386 | 1453 |
| 1387 UMA_HISTOGRAM_LONG_TIMES("SB2.BuildFilter", base::TimeTicks::Now() - before); | 1454 UMA_HISTOGRAM_LONG_TIMES("SB2.BuildFilter", base::TimeTicks::Now() - before); |
| 1388 | 1455 |
| 1389 // Persist the prefix set to disk. Note: there is no need to lock since the | 1456 { |
| 1390 // only write to |*prefix_set| is on this thread (in the swap() above). | 1457 // Persist the prefix set to disk. Do not grab the lock to avoid contention |
| 1391 WritePrefixSet(db_filename, prefix_set->get(), write_failure_type); | 1458 // while writing to disk. This is safe as only this thread can ever modify |
| 1459 // |state_manager_|'s prefix sets anyways. | |
| 1460 scoped_ptr<ReadTransaction> txn = | |
| 1461 state_manager_.BeginReadTransactionNoLockOnMainThread(); | |
| 1462 WritePrefixSet(db_filename, txn->GetPrefixSet(prefix_set_id), | |
| 1463 write_failure_type); | |
| 1464 } | |
| 1392 | 1465 |
| 1393 // Gather statistics. | 1466 // Gather statistics. |
| 1394 if (got_counters && metric->GetIOCounters(&io_after)) { | 1467 if (got_counters && metric->GetIOCounters(&io_after)) { |
| 1395 UMA_HISTOGRAM_COUNTS("SB2.BuildReadKilobytes", | 1468 UMA_HISTOGRAM_COUNTS("SB2.BuildReadKilobytes", |
| 1396 static_cast<int>(io_after.ReadTransferCount - | 1469 static_cast<int>(io_after.ReadTransferCount - |
| 1397 io_before.ReadTransferCount) / 1024); | 1470 io_before.ReadTransferCount) / 1024); |
| 1398 UMA_HISTOGRAM_COUNTS("SB2.BuildWriteKilobytes", | 1471 UMA_HISTOGRAM_COUNTS("SB2.BuildWriteKilobytes", |
| 1399 static_cast<int>(io_after.WriteTransferCount - | 1472 static_cast<int>(io_after.WriteTransferCount - |
| 1400 io_before.WriteTransferCount) / 1024); | 1473 io_before.WriteTransferCount) / 1024); |
| 1401 UMA_HISTOGRAM_COUNTS("SB2.BuildReadOperations", | 1474 UMA_HISTOGRAM_COUNTS("SB2.BuildReadOperations", |
| 1402 static_cast<int>(io_after.ReadOperationCount - | 1475 static_cast<int>(io_after.ReadOperationCount - |
| 1403 io_before.ReadOperationCount)); | 1476 io_before.ReadOperationCount)); |
| 1404 UMA_HISTOGRAM_COUNTS("SB2.BuildWriteOperations", | 1477 UMA_HISTOGRAM_COUNTS("SB2.BuildWriteOperations", |
| 1405 static_cast<int>(io_after.WriteOperationCount - | 1478 static_cast<int>(io_after.WriteOperationCount - |
| 1406 io_before.WriteOperationCount)); | 1479 io_before.WriteOperationCount)); |
| 1407 } | 1480 } |
| 1408 | 1481 |
| 1409 const int64 file_size = GetFileSizeOrZero(db_filename); | 1482 const int64 file_size = GetFileSizeOrZero(db_filename); |
| 1410 UMA_HISTOGRAM_COUNTS("SB2.DatabaseKilobytes", | 1483 UMA_HISTOGRAM_COUNTS("SB2.DatabaseKilobytes", |
| 1411 static_cast<int>(file_size / 1024)); | 1484 static_cast<int>(file_size / 1024)); |
| 1412 | 1485 |
| 1413 #if defined(OS_MACOSX) | 1486 #if defined(OS_MACOSX) |
| 1414 base::mac::SetFileBackupExclusion(db_filename); | 1487 base::mac::SetFileBackupExclusion(db_filename); |
| 1415 #endif | 1488 #endif |
| 1416 } | 1489 } |
| 1417 | 1490 |
| 1418 void SafeBrowsingDatabaseNew::UpdateIpBlacklistStore() { | 1491 void SafeBrowsingDatabaseNew::UpdateIpBlacklistStore() { |
| 1419 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 1420 | |
| 1421 // Note: prefixes will not be empty. The current data store implementation | 1492 // Note: prefixes will not be empty. The current data store implementation |
| 1422 // stores all full-length hashes as both full and prefix hashes. | 1493 // stores all full-length hashes as both full and prefix hashes. |
| 1423 safe_browsing::PrefixSetBuilder builder; | 1494 PrefixSetBuilder builder; |
| 1424 std::vector<SBAddFullHash> full_hashes; | 1495 std::vector<SBAddFullHash> full_hashes; |
| 1425 if (!ip_blacklist_store_->FinishUpdate(&builder, &full_hashes)) { | 1496 if (!ip_blacklist_store_->FinishUpdate(&builder, &full_hashes)) { |
| 1426 RecordFailure(FAILURE_IP_BLACKLIST_UPDATE_FINISH); | 1497 RecordFailure(FAILURE_IP_BLACKLIST_UPDATE_FINISH); |
| 1427 LoadIpBlacklist(std::vector<SBAddFullHash>()); // Clear the list. | 1498 LoadIpBlacklist(std::vector<SBAddFullHash>()); // Clear the list. |
| 1428 return; | 1499 return; |
| 1429 } | 1500 } |
| 1430 | 1501 |
| 1431 #if defined(OS_MACOSX) | 1502 #if defined(OS_MACOSX) |
| 1432 base::mac::SetFileBackupExclusion(IpBlacklistDBFilename(filename_base_)); | 1503 base::mac::SetFileBackupExclusion(IpBlacklistDBFilename(filename_base_)); |
| 1433 #endif | 1504 #endif |
| 1434 | 1505 |
| 1435 LoadIpBlacklist(full_hashes); | 1506 LoadIpBlacklist(full_hashes); |
| 1436 } | 1507 } |
| 1437 | 1508 |
| 1438 void SafeBrowsingDatabaseNew::HandleCorruptDatabase() { | 1509 void SafeBrowsingDatabaseNew::HandleCorruptDatabase() { |
| 1439 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 1440 | |
| 1441 // Reset the database after the current task has unwound (but only | 1510 // Reset the database after the current task has unwound (but only |
| 1442 // reset once within the scope of a given task). | 1511 // reset once within the scope of a given task). |
| 1443 if (!reset_factory_.HasWeakPtrs()) { | 1512 if (!reset_factory_.HasWeakPtrs()) { |
| 1444 RecordFailure(FAILURE_DATABASE_CORRUPT); | 1513 RecordFailure(FAILURE_DATABASE_CORRUPT); |
| 1445 base::MessageLoop::current()->PostTask(FROM_HERE, | 1514 base::MessageLoop::current()->PostTask(FROM_HERE, |
| 1446 base::Bind(&SafeBrowsingDatabaseNew::OnHandleCorruptDatabase, | 1515 base::Bind(&SafeBrowsingDatabaseNew::OnHandleCorruptDatabase, |
| 1447 reset_factory_.GetWeakPtr())); | 1516 reset_factory_.GetWeakPtr())); |
| 1448 } | 1517 } |
| 1449 } | 1518 } |
| 1450 | 1519 |
| 1451 void SafeBrowsingDatabaseNew::OnHandleCorruptDatabase() { | 1520 void SafeBrowsingDatabaseNew::OnHandleCorruptDatabase() { |
| 1452 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 1453 | |
| 1454 RecordFailure(FAILURE_DATABASE_CORRUPT_HANDLER); | 1521 RecordFailure(FAILURE_DATABASE_CORRUPT_HANDLER); |
| 1455 corruption_detected_ = true; // Stop updating the database. | 1522 corruption_detected_ = true; // Stop updating the database. |
| 1456 ResetDatabase(); | 1523 ResetDatabase(); |
| 1457 | 1524 |
| 1458 // NOTE(shess): ResetDatabase() should remove the corruption, so this should | 1525 // NOTE(shess): ResetDatabase() should remove the corruption, so this should |
| 1459 // only happen once. If you are here because you are hitting this after a | 1526 // only happen once. If you are here because you are hitting this after a |
| 1460 // restart, then I would be very interested in working with you to figure out | 1527 // restart, then I would be very interested in working with you to figure out |
| 1461 // what is happening, since it may affect real users. | 1528 // what is happening, since it may affect real users. |
| 1462 DLOG(FATAL) << "SafeBrowsing database was corrupt and reset"; | 1529 DLOG(FATAL) << "SafeBrowsing database was corrupt and reset"; |
| 1463 } | 1530 } |
| 1464 | 1531 |
| 1465 // TODO(shess): I'm not clear why this code doesn't have any | 1532 // TODO(shess): I'm not clear why this code doesn't have any |
| 1466 // real error-handling. | 1533 // real error-handling. |
| 1467 void SafeBrowsingDatabaseNew::LoadPrefixSet( | 1534 void SafeBrowsingDatabaseNew::LoadPrefixSet(const base::FilePath& db_filename, |
| 1468 const base::FilePath& db_filename, | 1535 WriteTransaction* txn, |
| 1469 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set, | 1536 PrefixSetId prefix_set_id, |
| 1470 FailureType read_failure_type) { | 1537 FailureType read_failure_type) { |
| 1471 DCHECK(thread_checker_.CalledOnValidThread()); | 1538 DCHECK(txn); |
| 1472 | |
| 1473 if (!prefix_set) | |
| 1474 return; | |
| 1475 | |
| 1476 DCHECK(!filename_base_.empty()); | 1539 DCHECK(!filename_base_.empty()); |
| 1477 | 1540 |
| 1478 const base::FilePath prefix_set_filename = PrefixSetForFilename(db_filename); | |
| 1479 | |
| 1480 // Only use the prefix set if database is present and non-empty. | 1541 // Only use the prefix set if database is present and non-empty. |
| 1481 if (!GetFileSizeOrZero(db_filename)) | 1542 if (!GetFileSizeOrZero(db_filename)) |
| 1482 return; | 1543 return; |
| 1483 | 1544 |
| 1484 // Cleanup any stale bloom filter (no longer used). | 1545 // Cleanup any stale bloom filter (no longer used). |
| 1485 // TODO(shess): Track existence to drive removal of this code? | 1546 // TODO(shess): Track existence to drive removal of this code? |
| 1486 const base::FilePath bloom_filter_filename = | 1547 const base::FilePath bloom_filter_filename = |
| 1487 BloomFilterForFilename(db_filename); | 1548 BloomFilterForFilename(db_filename); |
| 1488 base::DeleteFile(bloom_filter_filename, false); | 1549 base::DeleteFile(bloom_filter_filename, false); |
| 1489 | 1550 |
| 1490 const base::TimeTicks before = base::TimeTicks::Now(); | 1551 const base::TimeTicks before = base::TimeTicks::Now(); |
| 1491 *prefix_set = safe_browsing::PrefixSet::LoadFile(prefix_set_filename); | 1552 scoped_ptr<const PrefixSet> new_prefix_set = |
| 1553 PrefixSet::LoadFile(PrefixSetForFilename(db_filename)); | |
| 1554 if (!new_prefix_set.get()) | |
| 1555 RecordFailure(read_failure_type); | |
| 1556 txn->SwapPrefixSet(prefix_set_id, new_prefix_set.Pass()); | |
| 1492 UMA_HISTOGRAM_TIMES("SB2.PrefixSetLoad", base::TimeTicks::Now() - before); | 1557 UMA_HISTOGRAM_TIMES("SB2.PrefixSetLoad", base::TimeTicks::Now() - before); |
| 1493 | |
| 1494 if (!prefix_set->get()) | |
| 1495 RecordFailure(read_failure_type); | |
| 1496 } | 1558 } |
| 1497 | 1559 |
| 1498 bool SafeBrowsingDatabaseNew::Delete() { | 1560 bool SafeBrowsingDatabaseNew::Delete() { |
| 1499 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 1500 DCHECK(!filename_base_.empty()); | 1561 DCHECK(!filename_base_.empty()); |
| 1501 | 1562 |
| 1502 // TODO(shess): This is a mess. SafeBrowsingFileStore::Delete() closes the | 1563 // TODO(shess): This is a mess. SafeBrowsingFileStore::Delete() closes the |
| 1503 // store before calling DeleteStore(). DeleteStore() deletes transient files | 1564 // store before calling DeleteStore(). DeleteStore() deletes transient files |
| 1504 // in addition to the main file. Probably all of these should be converted to | 1565 // in addition to the main file. Probably all of these should be converted to |
| 1505 // a helper which calls Delete() if the store exists, else DeleteStore() on | 1566 // a helper which calls Delete() if the store exists, else DeleteStore() on |
| 1506 // the generated filename. | 1567 // the generated filename. |
| 1507 | 1568 |
| 1508 // TODO(shess): Determine if the histograms are useful in any way. I cannot | 1569 // TODO(shess): Determine if the histograms are useful in any way. I cannot |
| 1509 // recall any action taken as a result of their values, in which case it might | 1570 // recall any action taken as a result of their values, in which case it might |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1568 RecordFailure(FAILURE_IP_BLACKLIST_DELETE); | 1629 RecordFailure(FAILURE_IP_BLACKLIST_DELETE); |
| 1569 | 1630 |
| 1570 const bool r11 = | 1631 const bool r11 = |
| 1571 base::DeleteFile(UnwantedSoftwareDBFilename(filename_base_), false); | 1632 base::DeleteFile(UnwantedSoftwareDBFilename(filename_base_), false); |
| 1572 if (!r11) | 1633 if (!r11) |
| 1573 RecordFailure(FAILURE_UNWANTED_SOFTWARE_PREFIX_SET_DELETE); | 1634 RecordFailure(FAILURE_UNWANTED_SOFTWARE_PREFIX_SET_DELETE); |
| 1574 | 1635 |
| 1575 return r1 && r2 && r3 && r4 && r5 && r6 && r7 && r8 && r9 && r10 && r11; | 1636 return r1 && r2 && r3 && r4 && r5 && r6 && r7 && r8 && r9 && r10 && r11; |
| 1576 } | 1637 } |
| 1577 | 1638 |
| 1578 void SafeBrowsingDatabaseNew::WritePrefixSet( | 1639 void SafeBrowsingDatabaseNew::WritePrefixSet(const base::FilePath& db_filename, |
| 1579 const base::FilePath& db_filename, | 1640 const PrefixSet* prefix_set, |
| 1580 const safe_browsing::PrefixSet* prefix_set, | 1641 FailureType write_failure_type) { |
| 1581 FailureType write_failure_type) { | |
| 1582 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 1583 | |
| 1584 if (!prefix_set) | 1642 if (!prefix_set) |
| 1585 return; | 1643 return; |
| 1586 | 1644 |
| 1587 const base::FilePath prefix_set_filename = PrefixSetForFilename(db_filename); | 1645 const base::FilePath prefix_set_filename = PrefixSetForFilename(db_filename); |
| 1588 | 1646 |
| 1589 const base::TimeTicks before = base::TimeTicks::Now(); | 1647 const base::TimeTicks before = base::TimeTicks::Now(); |
| 1590 const bool write_ok = prefix_set->WriteFile(prefix_set_filename); | 1648 const bool write_ok = prefix_set->WriteFile(prefix_set_filename); |
| 1591 UMA_HISTOGRAM_TIMES("SB2.PrefixSetWrite", base::TimeTicks::Now() - before); | 1649 UMA_HISTOGRAM_TIMES("SB2.PrefixSetWrite", base::TimeTicks::Now() - before); |
| 1592 | 1650 |
| 1593 const int64 file_size = GetFileSizeOrZero(prefix_set_filename); | 1651 const int64 file_size = GetFileSizeOrZero(prefix_set_filename); |
| 1594 UMA_HISTOGRAM_COUNTS("SB2.PrefixSetKilobytes", | 1652 UMA_HISTOGRAM_COUNTS("SB2.PrefixSetKilobytes", |
| 1595 static_cast<int>(file_size / 1024)); | 1653 static_cast<int>(file_size / 1024)); |
| 1596 | 1654 |
| 1597 if (!write_ok) | 1655 if (!write_ok) |
| 1598 RecordFailure(write_failure_type); | 1656 RecordFailure(write_failure_type); |
| 1599 | 1657 |
| 1600 #if defined(OS_MACOSX) | 1658 #if defined(OS_MACOSX) |
| 1601 base::mac::SetFileBackupExclusion(prefix_set_filename); | 1659 base::mac::SetFileBackupExclusion(prefix_set_filename); |
| 1602 #endif | 1660 #endif |
| 1603 } | 1661 } |
| 1604 | 1662 |
| 1605 void SafeBrowsingDatabaseNew::WhitelistEverything(SBWhitelist* whitelist) { | 1663 void SafeBrowsingDatabaseNew::WhitelistEverything(SBWhitelistId whitelist_id) { |
| 1606 DCHECK(thread_checker_.CalledOnValidThread()); | 1664 scoped_ptr<WriteTransaction> txn = state_manager_.BeginWriteTransaction(); |
| 1607 base::AutoLock locked(lookup_lock_); | 1665 SBWhitelist* whitelist = txn->GetWritableSBWhitelist(whitelist_id); |
| 1608 whitelist->second = true; | 1666 whitelist->second = true; |
| 1609 whitelist->first.clear(); | 1667 whitelist->first.clear(); |
| 1610 } | 1668 } |
| 1611 | 1669 |
| 1612 void SafeBrowsingDatabaseNew::LoadWhitelist( | 1670 void SafeBrowsingDatabaseNew::LoadWhitelist( |
| 1613 const std::vector<SBAddFullHash>& full_hashes, | 1671 const std::vector<SBAddFullHash>& full_hashes, |
| 1614 SBWhitelist* whitelist) { | 1672 SBWhitelistId whitelist_id) { |
| 1615 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 1616 | |
| 1617 if (full_hashes.size() > kMaxWhitelistSize) { | 1673 if (full_hashes.size() > kMaxWhitelistSize) { |
| 1618 WhitelistEverything(whitelist); | 1674 WhitelistEverything(whitelist_id); |
| 1619 return; | 1675 return; |
| 1620 } | 1676 } |
| 1621 | 1677 |
| 1622 std::vector<SBFullHash> new_whitelist; | 1678 std::vector<SBFullHash> new_whitelist; |
| 1623 new_whitelist.reserve(full_hashes.size()); | 1679 new_whitelist.reserve(full_hashes.size()); |
| 1624 for (std::vector<SBAddFullHash>::const_iterator it = full_hashes.begin(); | 1680 for (std::vector<SBAddFullHash>::const_iterator it = full_hashes.begin(); |
| 1625 it != full_hashes.end(); ++it) { | 1681 it != full_hashes.end(); ++it) { |
| 1626 new_whitelist.push_back(it->full_hash); | 1682 new_whitelist.push_back(it->full_hash); |
| 1627 } | 1683 } |
| 1628 std::sort(new_whitelist.begin(), new_whitelist.end(), SBFullHashLess); | 1684 std::sort(new_whitelist.begin(), new_whitelist.end(), SBFullHashLess); |
| 1629 | 1685 |
| 1630 SBFullHash kill_switch = SBFullHashForString(kWhitelistKillSwitchUrl); | 1686 SBFullHash kill_switch = SBFullHashForString(kWhitelistKillSwitchUrl); |
| 1631 if (std::binary_search(new_whitelist.begin(), new_whitelist.end(), | 1687 if (std::binary_search(new_whitelist.begin(), new_whitelist.end(), |
| 1632 kill_switch, SBFullHashLess)) { | 1688 kill_switch, SBFullHashLess)) { |
| 1633 // The kill switch is whitelisted hence we whitelist all URLs. | 1689 // The kill switch is whitelisted hence we whitelist all URLs. |
| 1634 WhitelistEverything(whitelist); | 1690 WhitelistEverything(whitelist_id); |
| 1635 } else { | 1691 } else { |
| 1636 base::AutoLock locked(lookup_lock_); | 1692 scoped_ptr<WriteTransaction> txn = state_manager_.BeginWriteTransaction(); |
| 1693 SBWhitelist* whitelist = txn->GetWritableSBWhitelist(whitelist_id); | |
| 1637 whitelist->second = false; | 1694 whitelist->second = false; |
| 1638 whitelist->first.swap(new_whitelist); | 1695 whitelist->first.swap(new_whitelist); |
| 1639 } | 1696 } |
| 1640 } | 1697 } |
| 1641 | 1698 |
| 1642 void SafeBrowsingDatabaseNew::LoadIpBlacklist( | 1699 void SafeBrowsingDatabaseNew::LoadIpBlacklist( |
| 1643 const std::vector<SBAddFullHash>& full_hashes) { | 1700 const std::vector<SBAddFullHash>& full_hashes) { |
| 1644 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 1645 | |
| 1646 IPBlacklist new_blacklist; | 1701 IPBlacklist new_blacklist; |
| 1647 for (std::vector<SBAddFullHash>::const_iterator it = full_hashes.begin(); | 1702 for (std::vector<SBAddFullHash>::const_iterator it = full_hashes.begin(); |
| 1648 it != full_hashes.end(); | 1703 it != full_hashes.end(); |
| 1649 ++it) { | 1704 ++it) { |
| 1650 const char* full_hash = it->full_hash.full_hash; | 1705 const char* full_hash = it->full_hash.full_hash; |
| 1651 DCHECK_EQ(crypto::kSHA256Length, arraysize(it->full_hash.full_hash)); | 1706 DCHECK_EQ(crypto::kSHA256Length, arraysize(it->full_hash.full_hash)); |
| 1652 // The format of the IP blacklist is: | 1707 // The format of the IP blacklist is: |
| 1653 // SHA-1(IPv6 prefix) + uint8(prefix size) + 11 unused bytes. | 1708 // SHA-1(IPv6 prefix) + uint8(prefix size) + 11 unused bytes. |
| 1654 std::string hashed_ip_prefix(full_hash, base::kSHA1Length); | 1709 std::string hashed_ip_prefix(full_hash, base::kSHA1Length); |
| 1655 size_t prefix_size = static_cast<uint8>(full_hash[base::kSHA1Length]); | 1710 size_t prefix_size = static_cast<uint8>(full_hash[base::kSHA1Length]); |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 1669 } | 1724 } |
| 1670 DVLOG(2) << "Inserting malicious IP: " | 1725 DVLOG(2) << "Inserting malicious IP: " |
| 1671 << " raw:" << base::HexEncode(full_hash, crypto::kSHA256Length) | 1726 << " raw:" << base::HexEncode(full_hash, crypto::kSHA256Length) |
| 1672 << " mask:" << base::HexEncode(mask.data(), mask.size()) | 1727 << " mask:" << base::HexEncode(mask.data(), mask.size()) |
| 1673 << " prefix_size:" << prefix_size | 1728 << " prefix_size:" << prefix_size |
| 1674 << " hashed_ip:" << base::HexEncode(hashed_ip_prefix.data(), | 1729 << " hashed_ip:" << base::HexEncode(hashed_ip_prefix.data(), |
| 1675 hashed_ip_prefix.size()); | 1730 hashed_ip_prefix.size()); |
| 1676 new_blacklist[mask].insert(hashed_ip_prefix); | 1731 new_blacklist[mask].insert(hashed_ip_prefix); |
| 1677 } | 1732 } |
| 1678 | 1733 |
| 1679 base::AutoLock locked(lookup_lock_); | 1734 scoped_ptr<WriteTransaction> txn = state_manager_.BeginWriteTransaction(); |
| 1680 ip_blacklist_.swap(new_blacklist); | 1735 txn->writable_ip_blacklist()->swap(new_blacklist); |
| 1681 } | 1736 } |
| 1682 | 1737 |
| 1683 bool SafeBrowsingDatabaseNew::IsMalwareIPMatchKillSwitchOn() { | 1738 bool SafeBrowsingDatabaseNew::IsMalwareIPMatchKillSwitchOn() { |
| 1684 // This method is theoretically thread-safe but document that it is currently | |
| 1685 // only expected to be called on the IO thread. | |
| 1686 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 1687 | |
| 1688 SBFullHash malware_kill_switch = SBFullHashForString(kMalwareIPKillSwitchUrl); | 1739 SBFullHash malware_kill_switch = SBFullHashForString(kMalwareIPKillSwitchUrl); |
| 1689 std::vector<SBFullHash> full_hashes; | 1740 std::vector<SBFullHash> full_hashes; |
| 1690 full_hashes.push_back(malware_kill_switch); | 1741 full_hashes.push_back(malware_kill_switch); |
| 1691 return ContainsWhitelistedHashes(csd_whitelist_, full_hashes); | 1742 return ContainsWhitelistedHashes(SBWhitelistId::CSD, full_hashes); |
| 1692 } | 1743 } |
| 1693 | 1744 |
| 1694 bool SafeBrowsingDatabaseNew::IsCsdWhitelistKillSwitchOn() { | 1745 bool SafeBrowsingDatabaseNew::IsCsdWhitelistKillSwitchOn() { |
| 1695 // This method is theoretically thread-safe but document that it is currently | 1746 scoped_ptr<ReadTransaction> txn = state_manager_.BeginReadTransaction(); |
| 1696 // only expected to be called on the IO thread. | 1747 return txn->GetSBWhitelist(SBWhitelistId::CSD)->second; |
| 1697 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 1748 } |
| 1698 | 1749 |
| 1699 base::AutoLock locked(lookup_lock_); | 1750 SafeBrowsingDatabaseNew::PrefixGetHashCache* |
| 1700 return csd_whitelist_.second; | 1751 SafeBrowsingDatabaseNew::GetUnsynchronizedPrefixGetHashCacheForTesting() { |
| 1752 scoped_ptr<ReadTransaction> txn = state_manager_.BeginReadTransaction(); | |
| 1753 return txn->prefix_gethash_cache(); | |
| 1701 } | 1754 } |
| OLD | NEW |