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 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 425 return base::FilePath(db_filename.value() + kIPBlacklistDBFile); | 425 return base::FilePath(db_filename.value() + kIPBlacklistDBFile); |
| 426 } | 426 } |
| 427 | 427 |
| 428 // static | 428 // static |
| 429 base::FilePath SafeBrowsingDatabase::UnwantedSoftwareDBFilename( | 429 base::FilePath SafeBrowsingDatabase::UnwantedSoftwareDBFilename( |
| 430 const base::FilePath& db_filename) { | 430 const base::FilePath& db_filename) { |
| 431 return base::FilePath(db_filename.value() + kUnwantedSoftwareDBFile); | 431 return base::FilePath(db_filename.value() + kUnwantedSoftwareDBFile); |
| 432 } | 432 } |
| 433 | 433 |
| 434 SafeBrowsingStore* SafeBrowsingDatabaseNew::GetStore(const int list_id) { | 434 SafeBrowsingStore* SafeBrowsingDatabaseNew::GetStore(const int list_id) { |
| 435 // Stores are not thread safe. | |
| 436 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 437 | |
| 435 if (list_id == safe_browsing_util::PHISH || | 438 if (list_id == safe_browsing_util::PHISH || |
| 436 list_id == safe_browsing_util::MALWARE) { | 439 list_id == safe_browsing_util::MALWARE) { |
| 437 return browse_store_.get(); | 440 return browse_store_.get(); |
| 438 } else if (list_id == safe_browsing_util::BINURL) { | 441 } else if (list_id == safe_browsing_util::BINURL) { |
| 439 return download_store_.get(); | 442 return download_store_.get(); |
| 440 } else if (list_id == safe_browsing_util::CSDWHITELIST) { | 443 } else if (list_id == safe_browsing_util::CSDWHITELIST) { |
| 441 return csd_whitelist_store_.get(); | 444 return csd_whitelist_store_.get(); |
| 442 } else if (list_id == safe_browsing_util::DOWNLOADWHITELIST) { | 445 } else if (list_id == safe_browsing_util::DOWNLOADWHITELIST) { |
| 443 return download_whitelist_store_.get(); | 446 return download_whitelist_store_.get(); |
| 444 } else if (list_id == safe_browsing_util::EXTENSIONBLACKLIST) { | 447 } else if (list_id == safe_browsing_util::EXTENSIONBLACKLIST) { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 480 | 483 |
| 481 SafeBrowsingDatabaseNew::SafeBrowsingDatabaseNew( | 484 SafeBrowsingDatabaseNew::SafeBrowsingDatabaseNew( |
| 482 SafeBrowsingStore* browse_store, | 485 SafeBrowsingStore* browse_store, |
| 483 SafeBrowsingStore* download_store, | 486 SafeBrowsingStore* download_store, |
| 484 SafeBrowsingStore* csd_whitelist_store, | 487 SafeBrowsingStore* csd_whitelist_store, |
| 485 SafeBrowsingStore* download_whitelist_store, | 488 SafeBrowsingStore* download_whitelist_store, |
| 486 SafeBrowsingStore* extension_blacklist_store, | 489 SafeBrowsingStore* extension_blacklist_store, |
| 487 SafeBrowsingStore* side_effect_free_whitelist_store, | 490 SafeBrowsingStore* side_effect_free_whitelist_store, |
| 488 SafeBrowsingStore* ip_blacklist_store, | 491 SafeBrowsingStore* ip_blacklist_store, |
| 489 SafeBrowsingStore* unwanted_software_store) | 492 SafeBrowsingStore* unwanted_software_store) |
| 490 : creation_loop_(base::MessageLoop::current()), | 493 : browse_store_(browse_store), |
| 491 browse_store_(browse_store), | |
| 492 download_store_(download_store), | 494 download_store_(download_store), |
| 493 csd_whitelist_store_(csd_whitelist_store), | 495 csd_whitelist_store_(csd_whitelist_store), |
| 494 download_whitelist_store_(download_whitelist_store), | 496 download_whitelist_store_(download_whitelist_store), |
| 495 extension_blacklist_store_(extension_blacklist_store), | 497 extension_blacklist_store_(extension_blacklist_store), |
| 496 side_effect_free_whitelist_store_(side_effect_free_whitelist_store), | 498 side_effect_free_whitelist_store_(side_effect_free_whitelist_store), |
| 497 ip_blacklist_store_(ip_blacklist_store), | 499 ip_blacklist_store_(ip_blacklist_store), |
| 498 unwanted_software_store_(unwanted_software_store), | 500 unwanted_software_store_(unwanted_software_store), |
| 499 corruption_detected_(false), | 501 corruption_detected_(false), |
| 500 change_detected_(false), | 502 change_detected_(false), |
| 501 reset_factory_(this) { | 503 reset_factory_(this) { |
| 502 DCHECK(browse_store_.get()); | 504 DCHECK(browse_store_.get()); |
| 503 } | 505 } |
| 504 | 506 |
| 505 SafeBrowsingDatabaseNew::~SafeBrowsingDatabaseNew() { | 507 SafeBrowsingDatabaseNew::~SafeBrowsingDatabaseNew() { |
| 506 // The DCHECK is disabled due to crbug.com/338486 . | 508 // The DCHECK is disabled due to crbug.com/338486 . |
| 507 // DCHECK_EQ(creation_loop_, base::MessageLoop::current()); | 509 // DCHECK(thread_checker_.CalledOnValidThread()); |
| 508 } | 510 } |
| 509 | 511 |
| 510 void SafeBrowsingDatabaseNew::Init(const base::FilePath& filename_base) { | 512 void SafeBrowsingDatabaseNew::Init(const base::FilePath& filename_base) { |
| 511 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); | 513 DCHECK(thread_checker_.CalledOnValidThread()); |
| 512 | 514 |
| 513 // This should not be run multiple times. | 515 // This should not be run multiple times. |
| 514 DCHECK(filename_base_.empty()); | 516 DCHECK(filename_base_.empty()); |
| 515 | 517 |
| 516 filename_base_ = filename_base; | 518 filename_base_ = filename_base; |
| 517 | 519 |
| 518 // TODO(shess): The various stores are really only necessary while doing | 520 // TODO(shess): The various stores are really only necessary while doing |
| 519 // updates (see |UpdateFinished()|) or when querying a store directly (see | 521 // updates (see |UpdateFinished()|) or when querying a store directly (see |
| 520 // |ContainsDownloadUrl()|). | 522 // |ContainsDownloadUrl()|). |
| 521 // The store variables are also tested to see if a list is enabled. Perhaps | 523 // The store variables are also tested to see if a list is enabled. Perhaps |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 628 std::vector<SBAddFullHash> full_hashes; | 630 std::vector<SBAddFullHash> full_hashes; |
| 629 if (ip_blacklist_store_->GetAddFullHashes(&full_hashes)) { | 631 if (ip_blacklist_store_->GetAddFullHashes(&full_hashes)) { |
| 630 LoadIpBlacklist(full_hashes); | 632 LoadIpBlacklist(full_hashes); |
| 631 } else { | 633 } else { |
| 632 LoadIpBlacklist(std::vector<SBAddFullHash>()); // Clear the list. | 634 LoadIpBlacklist(std::vector<SBAddFullHash>()); // Clear the list. |
| 633 } | 635 } |
| 634 } | 636 } |
| 635 } | 637 } |
| 636 | 638 |
| 637 bool SafeBrowsingDatabaseNew::ResetDatabase() { | 639 bool SafeBrowsingDatabaseNew::ResetDatabase() { |
| 638 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); | 640 DCHECK(thread_checker_.CalledOnValidThread()); |
| 639 | 641 |
| 640 // Delete files on disk. | 642 // Delete files on disk. |
| 641 // TODO(shess): Hard to see where one might want to delete without a | 643 // TODO(shess): Hard to see where one might want to delete without a |
| 642 // reset. Perhaps inline |Delete()|? | 644 // reset. Perhaps inline |Delete()|? |
| 643 if (!Delete()) | 645 if (!Delete()) |
| 644 return false; | 646 return false; |
| 645 | 647 |
| 646 // Reset objects in memory. | 648 // Reset objects in memory. |
| 647 { | 649 { |
| 648 base::AutoLock locked(lookup_lock_); | 650 base::AutoLock locked(lookup_lock_); |
| 649 prefix_gethash_cache_.clear(); | 651 prefix_gethash_cache_.clear(); |
| 650 browse_prefix_set_.reset(); | 652 browse_prefix_set_.reset(); |
| 651 side_effect_free_whitelist_prefix_set_.reset(); | 653 side_effect_free_whitelist_prefix_set_.reset(); |
| 652 ip_blacklist_.clear(); | 654 ip_blacklist_.clear(); |
| 653 unwanted_software_prefix_set_.reset(); | 655 unwanted_software_prefix_set_.reset(); |
| 654 } | 656 } |
| 655 // Wants to acquire the lock itself. | 657 // Wants to acquire the lock itself. |
| 656 WhitelistEverything(&csd_whitelist_); | 658 WhitelistEverything(&csd_whitelist_); |
| 657 WhitelistEverything(&download_whitelist_); | 659 WhitelistEverything(&download_whitelist_); |
| 658 return true; | 660 return true; |
| 659 } | 661 } |
| 660 | 662 |
| 661 bool SafeBrowsingDatabaseNew::ContainsBrowseUrl( | 663 bool SafeBrowsingDatabaseNew::ContainsBrowseUrl( |
| 662 const GURL& url, | 664 const GURL& url, |
| 663 std::vector<SBPrefix>* prefix_hits, | 665 std::vector<SBPrefix>* prefix_hits, |
| 664 std::vector<SBFullHashResult>* cache_hits) { | 666 std::vector<SBFullHashResult>* cache_hits) { |
| 667 // This method is theoretically thread-safe but document that it is currently | |
| 668 // only expected to be called on the IO thread. | |
| 669 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
|
mattm
2014/12/12 23:50:44
Think I still don't see the benefit of these docum
gab
2014/12/15 22:05:37
Ok, agreed, they mostly helped me understanding ho
| |
| 670 | |
| 665 return PrefixSetContainsUrl( | 671 return PrefixSetContainsUrl( |
| 666 url, &browse_prefix_set_, prefix_hits, cache_hits); | 672 url, &browse_prefix_set_, prefix_hits, cache_hits); |
| 667 } | 673 } |
| 668 | 674 |
| 669 bool SafeBrowsingDatabaseNew::ContainsUnwantedSoftwareUrl( | 675 bool SafeBrowsingDatabaseNew::ContainsUnwantedSoftwareUrl( |
| 670 const GURL& url, | 676 const GURL& url, |
| 671 std::vector<SBPrefix>* prefix_hits, | 677 std::vector<SBPrefix>* prefix_hits, |
| 672 std::vector<SBFullHashResult>* cache_hits) { | 678 std::vector<SBFullHashResult>* cache_hits) { |
| 679 // This method is theoretically thread-safe but document that it is currently | |
| 680 // only expected to be called on the IO thread. | |
| 681 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 682 | |
| 673 return PrefixSetContainsUrl( | 683 return PrefixSetContainsUrl( |
| 674 url, &unwanted_software_prefix_set_, prefix_hits, cache_hits); | 684 url, &unwanted_software_prefix_set_, prefix_hits, cache_hits); |
| 675 } | 685 } |
| 676 | 686 |
| 677 bool SafeBrowsingDatabaseNew::PrefixSetContainsUrl( | 687 bool SafeBrowsingDatabaseNew::PrefixSetContainsUrl( |
| 678 const GURL& url, | 688 const GURL& url, |
| 679 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set_getter, | 689 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set_getter, |
| 680 std::vector<SBPrefix>* prefix_hits, | 690 std::vector<SBPrefix>* prefix_hits, |
| 681 std::vector<SBFullHashResult>* cache_hits) { | 691 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 | |
| 682 // Clear the results first. | 696 // Clear the results first. |
| 683 prefix_hits->clear(); | 697 prefix_hits->clear(); |
| 684 cache_hits->clear(); | 698 cache_hits->clear(); |
| 685 | 699 |
| 686 std::vector<SBFullHash> full_hashes; | 700 std::vector<SBFullHash> full_hashes; |
| 687 UrlToFullHashes(url, false, &full_hashes); | 701 UrlToFullHashes(url, false, &full_hashes); |
| 688 if (full_hashes.empty()) | 702 if (full_hashes.empty()) |
| 689 return false; | 703 return false; |
| 690 | 704 |
| 691 return PrefixSetContainsUrlHashes( | 705 return PrefixSetContainsUrlHashes( |
| 692 full_hashes, prefix_set_getter, prefix_hits, cache_hits); | 706 full_hashes, prefix_set_getter, prefix_hits, cache_hits); |
| 693 } | 707 } |
| 694 | 708 |
| 695 bool SafeBrowsingDatabaseNew::ContainsBrowseUrlHashesForTesting( | 709 bool SafeBrowsingDatabaseNew::ContainsBrowseUrlHashesForTesting( |
| 696 const std::vector<SBFullHash>& full_hashes, | 710 const std::vector<SBFullHash>& full_hashes, |
| 697 std::vector<SBPrefix>* prefix_hits, | 711 std::vector<SBPrefix>* prefix_hits, |
| 698 std::vector<SBFullHashResult>* cache_hits) { | 712 std::vector<SBFullHashResult>* cache_hits) { |
| 699 return PrefixSetContainsUrlHashes( | 713 return PrefixSetContainsUrlHashes( |
| 700 full_hashes, &browse_prefix_set_, prefix_hits, cache_hits); | 714 full_hashes, &browse_prefix_set_, prefix_hits, cache_hits); |
| 701 } | 715 } |
| 702 | 716 |
| 703 bool SafeBrowsingDatabaseNew::PrefixSetContainsUrlHashes( | 717 bool SafeBrowsingDatabaseNew::PrefixSetContainsUrlHashes( |
| 704 const std::vector<SBFullHash>& full_hashes, | 718 const std::vector<SBFullHash>& full_hashes, |
| 705 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set_getter, | 719 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set_getter, |
| 706 std::vector<SBPrefix>* prefix_hits, | 720 std::vector<SBPrefix>* prefix_hits, |
| 707 std::vector<SBFullHashResult>* cache_hits) { | 721 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 | |
| 708 // Used to determine cache expiration. | 726 // Used to determine cache expiration. |
| 709 const base::Time now = base::Time::Now(); | 727 const base::Time now = base::Time::Now(); |
| 710 | 728 |
| 711 // This function is called on the I/O thread, prevent changes to | |
| 712 // filter and caches. | |
| 713 base::AutoLock locked(lookup_lock_); | 729 base::AutoLock locked(lookup_lock_); |
| 714 | 730 |
| 715 // |prefix_set| is empty until it is either read from disk, or the first | 731 // |prefix_set| is empty until it is either read from disk, or the first |
| 716 // update populates it. Bail out without a hit if not yet available. | 732 // update populates it. Bail out without a hit if not yet available. |
| 717 // |prefix_set_getter| can only be accessed while holding |lookup_lock_| hence | 733 // |prefix_set_getter| can only be accessed while holding |lookup_lock_| hence |
| 718 // why it is passed as a parameter rather than passing the |prefix_set| | 734 // why it is passed as a parameter rather than passing the |prefix_set| |
| 719 // directly. | 735 // directly. |
| 720 const safe_browsing::PrefixSet* prefix_set = prefix_set_getter->get(); | 736 const safe_browsing::PrefixSet* prefix_set = prefix_set_getter->get(); |
| 721 if (!prefix_set) | 737 if (!prefix_set) |
| 722 return false; | 738 return false; |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 734 std::sort(prefix_hits->begin(), prefix_hits->end()); | 750 std::sort(prefix_hits->begin(), prefix_hits->end()); |
| 735 prefix_hits->erase(std::unique(prefix_hits->begin(), prefix_hits->end()), | 751 prefix_hits->erase(std::unique(prefix_hits->begin(), prefix_hits->end()), |
| 736 prefix_hits->end()); | 752 prefix_hits->end()); |
| 737 | 753 |
| 738 return !prefix_hits->empty() || !cache_hits->empty(); | 754 return !prefix_hits->empty() || !cache_hits->empty(); |
| 739 } | 755 } |
| 740 | 756 |
| 741 bool SafeBrowsingDatabaseNew::ContainsDownloadUrl( | 757 bool SafeBrowsingDatabaseNew::ContainsDownloadUrl( |
| 742 const std::vector<GURL>& urls, | 758 const std::vector<GURL>& urls, |
| 743 std::vector<SBPrefix>* prefix_hits) { | 759 std::vector<SBPrefix>* prefix_hits) { |
| 744 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); | 760 DCHECK(thread_checker_.CalledOnValidThread()); |
| 745 | 761 |
| 746 // Ignore this check when download checking is not enabled. | 762 // Ignore this check when download checking is not enabled. |
| 747 if (!download_store_.get()) | 763 if (!download_store_.get()) |
| 748 return false; | 764 return false; |
| 749 | 765 |
| 750 std::vector<SBPrefix> prefixes; | 766 std::vector<SBPrefix> prefixes; |
| 751 GetDownloadUrlPrefixes(urls, &prefixes); | 767 GetDownloadUrlPrefixes(urls, &prefixes); |
| 752 return MatchAddPrefixes(download_store_.get(), | 768 return MatchAddPrefixes(download_store_.get(), |
| 753 safe_browsing_util::BINURL % 2, | 769 safe_browsing_util::BINURL % 2, |
| 754 prefixes, | 770 prefixes, |
| 755 prefix_hits); | 771 prefix_hits); |
| 756 } | 772 } |
| 757 | 773 |
| 758 bool SafeBrowsingDatabaseNew::ContainsCsdWhitelistedUrl(const GURL& url) { | 774 bool SafeBrowsingDatabaseNew::ContainsCsdWhitelistedUrl(const GURL& url) { |
| 759 // This method is theoretically thread-safe but we expect all calls to | 775 // This method is theoretically thread-safe but document that it is currently |
| 760 // originate from the IO thread. | 776 // only expected to be called on the IO thread. |
| 761 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 777 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
| 778 | |
| 762 std::vector<SBFullHash> full_hashes; | 779 std::vector<SBFullHash> full_hashes; |
| 763 UrlToFullHashes(url, true, &full_hashes); | 780 UrlToFullHashes(url, true, &full_hashes); |
| 764 return ContainsWhitelistedHashes(csd_whitelist_, full_hashes); | 781 return ContainsWhitelistedHashes(csd_whitelist_, full_hashes); |
| 765 } | 782 } |
| 766 | 783 |
| 767 bool SafeBrowsingDatabaseNew::ContainsDownloadWhitelistedUrl(const GURL& url) { | 784 bool SafeBrowsingDatabaseNew::ContainsDownloadWhitelistedUrl(const GURL& url) { |
| 768 std::vector<SBFullHash> full_hashes; | 785 std::vector<SBFullHash> full_hashes; |
| 769 UrlToFullHashes(url, true, &full_hashes); | 786 UrlToFullHashes(url, true, &full_hashes); |
| 770 return ContainsWhitelistedHashes(download_whitelist_, full_hashes); | 787 return ContainsWhitelistedHashes(download_whitelist_, full_hashes); |
| 771 } | 788 } |
| 772 | 789 |
| 773 bool SafeBrowsingDatabaseNew::ContainsExtensionPrefixes( | 790 bool SafeBrowsingDatabaseNew::ContainsExtensionPrefixes( |
| 774 const std::vector<SBPrefix>& prefixes, | 791 const std::vector<SBPrefix>& prefixes, |
| 775 std::vector<SBPrefix>* prefix_hits) { | 792 std::vector<SBPrefix>* prefix_hits) { |
| 776 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); | 793 DCHECK(thread_checker_.CalledOnValidThread()); |
| 794 | |
| 777 if (!extension_blacklist_store_) | 795 if (!extension_blacklist_store_) |
| 778 return false; | 796 return false; |
| 779 | 797 |
| 780 return MatchAddPrefixes(extension_blacklist_store_.get(), | 798 return MatchAddPrefixes(extension_blacklist_store_.get(), |
| 781 safe_browsing_util::EXTENSIONBLACKLIST % 2, | 799 safe_browsing_util::EXTENSIONBLACKLIST % 2, |
| 782 prefixes, | 800 prefixes, |
| 783 prefix_hits); | 801 prefix_hits); |
| 784 } | 802 } |
| 785 | 803 |
| 786 bool SafeBrowsingDatabaseNew::ContainsSideEffectFreeWhitelistUrl( | 804 bool SafeBrowsingDatabaseNew::ContainsSideEffectFreeWhitelistUrl( |
| 787 const GURL& url) { | 805 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 | |
| 788 std::string host; | 810 std::string host; |
| 789 std::string path; | 811 std::string path; |
| 790 std::string query; | 812 std::string query; |
| 791 safe_browsing_util::CanonicalizeUrl(url, &host, &path, &query); | 813 safe_browsing_util::CanonicalizeUrl(url, &host, &path, &query); |
| 792 std::string url_to_check = host + path; | 814 std::string url_to_check = host + path; |
| 793 if (!query.empty()) | 815 if (!query.empty()) |
| 794 url_to_check += "?" + query; | 816 url_to_check += "?" + query; |
| 795 SBFullHash full_hash = SBFullHashForString(url_to_check); | 817 SBFullHash full_hash = SBFullHashForString(url_to_check); |
| 796 | 818 |
| 797 // This function can be called on any thread, so lock against any changes | |
| 798 base::AutoLock locked(lookup_lock_); | 819 base::AutoLock locked(lookup_lock_); |
| 799 | 820 |
| 800 // |side_effect_free_whitelist_prefix_set_| is empty until it is either read | 821 // |side_effect_free_whitelist_prefix_set_| is empty until it is either read |
| 801 // from disk, or the first update populates it. Bail out without a hit if | 822 // from disk, or the first update populates it. Bail out without a hit if |
| 802 // not yet available. | 823 // not yet available. |
| 803 if (!side_effect_free_whitelist_prefix_set_.get()) | 824 if (!side_effect_free_whitelist_prefix_set_.get()) |
| 804 return false; | 825 return false; |
| 805 | 826 |
| 806 return side_effect_free_whitelist_prefix_set_->Exists(full_hash); | 827 return side_effect_free_whitelist_prefix_set_->Exists(full_hash); |
| 807 } | 828 } |
| 808 | 829 |
| 809 bool SafeBrowsingDatabaseNew::ContainsMalwareIP(const std::string& ip_address) { | 830 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 | |
| 810 net::IPAddressNumber ip_number; | 835 net::IPAddressNumber ip_number; |
| 811 if (!net::ParseIPLiteralToNumber(ip_address, &ip_number)) | 836 if (!net::ParseIPLiteralToNumber(ip_address, &ip_number)) |
| 812 return false; | 837 return false; |
| 813 if (ip_number.size() == net::kIPv4AddressSize) | 838 if (ip_number.size() == net::kIPv4AddressSize) |
| 814 ip_number = net::ConvertIPv4NumberToIPv6Number(ip_number); | 839 ip_number = net::ConvertIPv4NumberToIPv6Number(ip_number); |
| 815 if (ip_number.size() != net::kIPv6AddressSize) | 840 if (ip_number.size() != net::kIPv6AddressSize) |
| 816 return false; // better safe than sorry. | 841 return false; // better safe than sorry. |
| 817 | 842 |
| 818 // This function can be called from any thread. | |
| 819 base::AutoLock locked(lookup_lock_); | 843 base::AutoLock locked(lookup_lock_); |
| 820 for (IPBlacklist::const_iterator it = ip_blacklist_.begin(); | 844 for (IPBlacklist::const_iterator it = ip_blacklist_.begin(); |
| 821 it != ip_blacklist_.end(); | 845 it != ip_blacklist_.end(); |
| 822 ++it) { | 846 ++it) { |
| 823 const std::string& mask = it->first; | 847 const std::string& mask = it->first; |
| 824 DCHECK_EQ(mask.size(), ip_number.size()); | 848 DCHECK_EQ(mask.size(), ip_number.size()); |
| 825 std::string subnet(net::kIPv6AddressSize, '\0'); | 849 std::string subnet(net::kIPv6AddressSize, '\0'); |
| 826 for (size_t i = 0; i < net::kIPv6AddressSize; ++i) { | 850 for (size_t i = 0; i < net::kIPv6AddressSize; ++i) { |
| 827 subnet[i] = ip_number[i] & mask[i]; | 851 subnet[i] = ip_number[i] & mask[i]; |
| 828 } | 852 } |
| 829 const std::string hash = base::SHA1HashString(subnet); | 853 const std::string hash = base::SHA1HashString(subnet); |
| 830 DVLOG(2) << "Lookup Malware IP: " | 854 DVLOG(2) << "Lookup Malware IP: " |
| 831 << " ip:" << ip_address | 855 << " ip:" << ip_address |
| 832 << " mask:" << base::HexEncode(mask.data(), mask.size()) | 856 << " mask:" << base::HexEncode(mask.data(), mask.size()) |
| 833 << " subnet:" << base::HexEncode(subnet.data(), subnet.size()) | 857 << " subnet:" << base::HexEncode(subnet.data(), subnet.size()) |
| 834 << " hash:" << base::HexEncode(hash.data(), hash.size()); | 858 << " hash:" << base::HexEncode(hash.data(), hash.size()); |
| 835 if (it->second.count(hash) > 0) { | 859 if (it->second.count(hash) > 0) { |
| 836 return true; | 860 return true; |
| 837 } | 861 } |
| 838 } | 862 } |
| 839 return false; | 863 return false; |
| 840 } | 864 } |
| 841 | 865 |
| 842 bool SafeBrowsingDatabaseNew::ContainsDownloadWhitelistedString( | 866 bool SafeBrowsingDatabaseNew::ContainsDownloadWhitelistedString( |
| 843 const std::string& str) { | 867 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 | |
| 844 std::vector<SBFullHash> hashes; | 872 std::vector<SBFullHash> hashes; |
| 845 hashes.push_back(SBFullHashForString(str)); | 873 hashes.push_back(SBFullHashForString(str)); |
| 846 return ContainsWhitelistedHashes(download_whitelist_, hashes); | 874 return ContainsWhitelistedHashes(download_whitelist_, hashes); |
| 847 } | 875 } |
| 848 | 876 |
| 849 bool SafeBrowsingDatabaseNew::ContainsWhitelistedHashes( | 877 bool SafeBrowsingDatabaseNew::ContainsWhitelistedHashes( |
| 850 const SBWhitelist& whitelist, | 878 const SBWhitelist& whitelist, |
| 851 const std::vector<SBFullHash>& hashes) { | 879 const std::vector<SBFullHash>& hashes) { |
| 880 // This method is theoretically thread-safe but document that it is currently | |
| 881 // only expected to be called on the IO thread. | |
| 882 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 883 | |
| 852 base::AutoLock l(lookup_lock_); | 884 base::AutoLock l(lookup_lock_); |
| 853 if (whitelist.second) | 885 if (whitelist.second) |
| 854 return true; | 886 return true; |
| 855 for (std::vector<SBFullHash>::const_iterator it = hashes.begin(); | 887 for (std::vector<SBFullHash>::const_iterator it = hashes.begin(); |
| 856 it != hashes.end(); ++it) { | 888 it != hashes.end(); ++it) { |
| 857 if (std::binary_search(whitelist.first.begin(), whitelist.first.end(), | 889 if (std::binary_search(whitelist.first.begin(), whitelist.first.end(), |
| 858 *it, SBFullHashLess)) { | 890 *it, SBFullHashLess)) { |
| 859 return true; | 891 return true; |
| 860 } | 892 } |
| 861 } | 893 } |
| 862 return false; | 894 return false; |
| 863 } | 895 } |
| 864 | 896 |
| 865 // Helper to insert add-chunk entries. | 897 // Helper to insert add-chunk entries. |
| 866 void SafeBrowsingDatabaseNew::InsertAddChunk( | 898 void SafeBrowsingDatabaseNew::InsertAddChunk( |
| 867 SafeBrowsingStore* store, | 899 SafeBrowsingStore* store, |
| 868 const safe_browsing_util::ListType list_id, | 900 const safe_browsing_util::ListType list_id, |
| 869 const SBChunkData& chunk_data) { | 901 const SBChunkData& chunk_data) { |
| 870 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); | 902 DCHECK(thread_checker_.CalledOnValidThread()); |
| 871 DCHECK(store); | 903 DCHECK(store); |
| 872 | 904 |
| 873 // The server can give us a chunk that we already have because | 905 // The server can give us a chunk that we already have because |
| 874 // it's part of a range. Don't add it again. | 906 // it's part of a range. Don't add it again. |
| 875 const int chunk_id = chunk_data.ChunkNumber(); | 907 const int chunk_id = chunk_data.ChunkNumber(); |
| 876 const int encoded_chunk_id = EncodeChunkId(chunk_id, list_id); | 908 const int encoded_chunk_id = EncodeChunkId(chunk_id, list_id); |
| 877 if (store->CheckAddChunk(encoded_chunk_id)) | 909 if (store->CheckAddChunk(encoded_chunk_id)) |
| 878 return; | 910 return; |
| 879 | 911 |
| 880 store->SetAddChunk(encoded_chunk_id); | 912 store->SetAddChunk(encoded_chunk_id); |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 891 store->WriteAddHash(encoded_chunk_id, chunk_data.FullHashAt(i)); | 923 store->WriteAddHash(encoded_chunk_id, chunk_data.FullHashAt(i)); |
| 892 } | 924 } |
| 893 } | 925 } |
| 894 } | 926 } |
| 895 | 927 |
| 896 // Helper to insert sub-chunk entries. | 928 // Helper to insert sub-chunk entries. |
| 897 void SafeBrowsingDatabaseNew::InsertSubChunk( | 929 void SafeBrowsingDatabaseNew::InsertSubChunk( |
| 898 SafeBrowsingStore* store, | 930 SafeBrowsingStore* store, |
| 899 const safe_browsing_util::ListType list_id, | 931 const safe_browsing_util::ListType list_id, |
| 900 const SBChunkData& chunk_data) { | 932 const SBChunkData& chunk_data) { |
| 901 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); | 933 DCHECK(thread_checker_.CalledOnValidThread()); |
| 902 DCHECK(store); | 934 DCHECK(store); |
| 903 | 935 |
| 904 // The server can give us a chunk that we already have because | 936 // The server can give us a chunk that we already have because |
| 905 // it's part of a range. Don't add it again. | 937 // it's part of a range. Don't add it again. |
| 906 const int chunk_id = chunk_data.ChunkNumber(); | 938 const int chunk_id = chunk_data.ChunkNumber(); |
| 907 const int encoded_chunk_id = EncodeChunkId(chunk_id, list_id); | 939 const int encoded_chunk_id = EncodeChunkId(chunk_id, list_id); |
| 908 if (store->CheckSubChunk(encoded_chunk_id)) | 940 if (store->CheckSubChunk(encoded_chunk_id)) |
| 909 return; | 941 return; |
| 910 | 942 |
| 911 store->SetSubChunk(encoded_chunk_id); | 943 store->SetSubChunk(encoded_chunk_id); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 926 const int encoded_add_chunk_id = EncodeChunkId(add_chunk_id, list_id); | 958 const int encoded_add_chunk_id = EncodeChunkId(add_chunk_id, list_id); |
| 927 store->WriteSubHash(encoded_chunk_id, encoded_add_chunk_id, | 959 store->WriteSubHash(encoded_chunk_id, encoded_add_chunk_id, |
| 928 chunk_data.FullHashAt(i)); | 960 chunk_data.FullHashAt(i)); |
| 929 } | 961 } |
| 930 } | 962 } |
| 931 } | 963 } |
| 932 | 964 |
| 933 void SafeBrowsingDatabaseNew::InsertChunks( | 965 void SafeBrowsingDatabaseNew::InsertChunks( |
| 934 const std::string& list_name, | 966 const std::string& list_name, |
| 935 const std::vector<SBChunkData*>& chunks) { | 967 const std::vector<SBChunkData*>& chunks) { |
| 936 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); | 968 DCHECK(thread_checker_.CalledOnValidThread()); |
| 937 | 969 |
| 938 if (corruption_detected_ || chunks.empty()) | 970 if (corruption_detected_ || chunks.empty()) |
| 939 return; | 971 return; |
| 940 | 972 |
| 941 const base::TimeTicks before = base::TimeTicks::Now(); | 973 const base::TimeTicks before = base::TimeTicks::Now(); |
| 942 | 974 |
| 943 // TODO(shess): The caller should just pass list_id. | 975 // TODO(shess): The caller should just pass list_id. |
| 944 const safe_browsing_util::ListType list_id = | 976 const safe_browsing_util::ListType list_id = |
| 945 safe_browsing_util::GetListId(list_name); | 977 safe_browsing_util::GetListId(list_name); |
| 946 | 978 |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 961 NOTREACHED(); | 993 NOTREACHED(); |
| 962 } | 994 } |
| 963 } | 995 } |
| 964 store->FinishChunk(); | 996 store->FinishChunk(); |
| 965 | 997 |
| 966 UMA_HISTOGRAM_TIMES("SB2.ChunkInsert", base::TimeTicks::Now() - before); | 998 UMA_HISTOGRAM_TIMES("SB2.ChunkInsert", base::TimeTicks::Now() - before); |
| 967 } | 999 } |
| 968 | 1000 |
| 969 void SafeBrowsingDatabaseNew::DeleteChunks( | 1001 void SafeBrowsingDatabaseNew::DeleteChunks( |
| 970 const std::vector<SBChunkDelete>& chunk_deletes) { | 1002 const std::vector<SBChunkDelete>& chunk_deletes) { |
| 971 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); | 1003 DCHECK(thread_checker_.CalledOnValidThread()); |
| 972 | 1004 |
| 973 if (corruption_detected_ || chunk_deletes.empty()) | 1005 if (corruption_detected_ || chunk_deletes.empty()) |
| 974 return; | 1006 return; |
| 975 | 1007 |
| 976 const std::string& list_name = chunk_deletes.front().list_name; | 1008 const std::string& list_name = chunk_deletes.front().list_name; |
| 977 const safe_browsing_util::ListType list_id = | 1009 const safe_browsing_util::ListType list_id = |
| 978 safe_browsing_util::GetListId(list_name); | 1010 safe_browsing_util::GetListId(list_name); |
| 979 | 1011 |
| 980 SafeBrowsingStore* store = GetStore(list_id); | 1012 SafeBrowsingStore* store = GetStore(list_id); |
| 981 if (!store) return; | 1013 if (!store) return; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 992 else | 1024 else |
| 993 store->DeleteAddChunk(encoded_chunk_id); | 1025 store->DeleteAddChunk(encoded_chunk_id); |
| 994 } | 1026 } |
| 995 } | 1027 } |
| 996 } | 1028 } |
| 997 | 1029 |
| 998 void SafeBrowsingDatabaseNew::CacheHashResults( | 1030 void SafeBrowsingDatabaseNew::CacheHashResults( |
| 999 const std::vector<SBPrefix>& prefixes, | 1031 const std::vector<SBPrefix>& prefixes, |
| 1000 const std::vector<SBFullHashResult>& full_hits, | 1032 const std::vector<SBFullHashResult>& full_hits, |
| 1001 const base::TimeDelta& cache_lifetime) { | 1033 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 | |
| 1002 const base::Time expire_after = base::Time::Now() + cache_lifetime; | 1038 const base::Time expire_after = base::Time::Now() + cache_lifetime; |
| 1003 | 1039 |
| 1004 // This is called on the I/O thread, lock against updates. | |
| 1005 base::AutoLock locked(lookup_lock_); | 1040 base::AutoLock locked(lookup_lock_); |
| 1006 | 1041 |
| 1007 // Create or reset all cached results for these prefixes. | 1042 // Create or reset all cached results for these prefixes. |
| 1008 for (size_t i = 0; i < prefixes.size(); ++i) { | 1043 for (size_t i = 0; i < prefixes.size(); ++i) { |
| 1009 prefix_gethash_cache_[prefixes[i]] = SBCachedFullHashResult(expire_after); | 1044 prefix_gethash_cache_[prefixes[i]] = SBCachedFullHashResult(expire_after); |
| 1010 } | 1045 } |
| 1011 | 1046 |
| 1012 // Insert any fullhash hits. Note that there may be one, multiple, or no | 1047 // Insert any fullhash hits. Note that there may be one, multiple, or no |
| 1013 // fullhashes for any given entry in |prefixes|. | 1048 // fullhashes for any given entry in |prefixes|. |
| 1014 for (size_t i = 0; i < full_hits.size(); ++i) { | 1049 for (size_t i = 0; i < full_hits.size(); ++i) { |
| 1015 const SBPrefix prefix = full_hits[i].hash.prefix; | 1050 const SBPrefix prefix = full_hits[i].hash.prefix; |
| 1016 prefix_gethash_cache_[prefix].full_hashes.push_back(full_hits[i]); | 1051 prefix_gethash_cache_[prefix].full_hashes.push_back(full_hits[i]); |
| 1017 } | 1052 } |
| 1018 } | 1053 } |
| 1019 | 1054 |
| 1020 bool SafeBrowsingDatabaseNew::UpdateStarted( | 1055 bool SafeBrowsingDatabaseNew::UpdateStarted( |
| 1021 std::vector<SBListChunkRanges>* lists) { | 1056 std::vector<SBListChunkRanges>* lists) { |
| 1022 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); | 1057 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1023 DCHECK(lists); | 1058 DCHECK(lists); |
| 1024 | 1059 |
| 1025 // If |BeginUpdate()| fails, reset the database. | 1060 // If |BeginUpdate()| fails, reset the database. |
| 1026 if (!browse_store_->BeginUpdate()) { | 1061 if (!browse_store_->BeginUpdate()) { |
| 1027 RecordFailure(FAILURE_BROWSE_DATABASE_UPDATE_BEGIN); | 1062 RecordFailure(FAILURE_BROWSE_DATABASE_UPDATE_BEGIN); |
| 1028 HandleCorruptDatabase(); | 1063 HandleCorruptDatabase(); |
| 1029 return false; | 1064 return false; |
| 1030 } | 1065 } |
| 1031 | 1066 |
| 1032 if (download_store_.get() && !download_store_->BeginUpdate()) { | 1067 if (download_store_.get() && !download_store_->BeginUpdate()) { |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1111 UpdateChunkRangesForList(unwanted_software_store_.get(), | 1146 UpdateChunkRangesForList(unwanted_software_store_.get(), |
| 1112 safe_browsing_util::kUnwantedUrlList, | 1147 safe_browsing_util::kUnwantedUrlList, |
| 1113 lists); | 1148 lists); |
| 1114 | 1149 |
| 1115 corruption_detected_ = false; | 1150 corruption_detected_ = false; |
| 1116 change_detected_ = false; | 1151 change_detected_ = false; |
| 1117 return true; | 1152 return true; |
| 1118 } | 1153 } |
| 1119 | 1154 |
| 1120 void SafeBrowsingDatabaseNew::UpdateFinished(bool update_succeeded) { | 1155 void SafeBrowsingDatabaseNew::UpdateFinished(bool update_succeeded) { |
| 1121 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); | 1156 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1122 | 1157 |
| 1123 // The update may have failed due to corrupt storage (for instance, | 1158 // The update may have failed due to corrupt storage (for instance, |
| 1124 // an excessive number of invalid add_chunks and sub_chunks). | 1159 // an excessive number of invalid add_chunks and sub_chunks). |
| 1125 // Double-check that the databases are valid. | 1160 // Double-check that the databases are valid. |
| 1126 // TODO(shess): Providing a checksum for the add_chunk and sub_chunk | 1161 // TODO(shess): Providing a checksum for the add_chunk and sub_chunk |
| 1127 // sections would allow throwing a corruption error in | 1162 // sections would allow throwing a corruption error in |
| 1128 // UpdateStarted(). | 1163 // UpdateStarted(). |
| 1129 if (!update_succeeded) { | 1164 if (!update_succeeded) { |
| 1130 if (!browse_store_->CheckValidity()) | 1165 if (!browse_store_->CheckValidity()) |
| 1131 DLOG(ERROR) << "Safe-browsing browse database corrupt."; | 1166 DLOG(ERROR) << "Safe-browsing browse database corrupt."; |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1241 FAILURE_UNWANTED_SOFTWARE_DATABASE_UPDATE_FINISH, | 1276 FAILURE_UNWANTED_SOFTWARE_DATABASE_UPDATE_FINISH, |
| 1242 FAILURE_UNWANTED_SOFTWARE_PREFIX_SET_WRITE, | 1277 FAILURE_UNWANTED_SOFTWARE_PREFIX_SET_WRITE, |
| 1243 true); | 1278 true); |
| 1244 } | 1279 } |
| 1245 } | 1280 } |
| 1246 | 1281 |
| 1247 void SafeBrowsingDatabaseNew::UpdateWhitelistStore( | 1282 void SafeBrowsingDatabaseNew::UpdateWhitelistStore( |
| 1248 const base::FilePath& store_filename, | 1283 const base::FilePath& store_filename, |
| 1249 SafeBrowsingStore* store, | 1284 SafeBrowsingStore* store, |
| 1250 SBWhitelist* whitelist) { | 1285 SBWhitelist* whitelist) { |
| 1286 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 1287 | |
| 1251 if (!store) | 1288 if (!store) |
| 1252 return; | 1289 return; |
| 1253 | 1290 |
| 1254 // Note: |builder| will not be empty. The current data store implementation | 1291 // Note: |builder| will not be empty. The current data store implementation |
| 1255 // stores all full-length hashes as both full and prefix hashes. | 1292 // stores all full-length hashes as both full and prefix hashes. |
| 1256 safe_browsing::PrefixSetBuilder builder; | 1293 safe_browsing::PrefixSetBuilder builder; |
| 1257 std::vector<SBAddFullHash> full_hashes; | 1294 std::vector<SBAddFullHash> full_hashes; |
| 1258 if (!store->FinishUpdate(&builder, &full_hashes)) { | 1295 if (!store->FinishUpdate(&builder, &full_hashes)) { |
| 1259 RecordFailure(FAILURE_WHITELIST_DATABASE_UPDATE_FINISH); | 1296 RecordFailure(FAILURE_WHITELIST_DATABASE_UPDATE_FINISH); |
| 1260 WhitelistEverything(whitelist); | 1297 WhitelistEverything(whitelist); |
| 1261 return; | 1298 return; |
| 1262 } | 1299 } |
| 1263 | 1300 |
| 1264 #if defined(OS_MACOSX) | 1301 #if defined(OS_MACOSX) |
| 1265 base::mac::SetFileBackupExclusion(store_filename); | 1302 base::mac::SetFileBackupExclusion(store_filename); |
| 1266 #endif | 1303 #endif |
| 1267 | 1304 |
| 1268 LoadWhitelist(full_hashes, whitelist); | 1305 LoadWhitelist(full_hashes, whitelist); |
| 1269 } | 1306 } |
| 1270 | 1307 |
| 1271 int64 SafeBrowsingDatabaseNew::UpdateHashPrefixStore( | 1308 int64 SafeBrowsingDatabaseNew::UpdateHashPrefixStore( |
| 1272 const base::FilePath& store_filename, | 1309 const base::FilePath& store_filename, |
| 1273 SafeBrowsingStore* store, | 1310 SafeBrowsingStore* store, |
| 1274 FailureType failure_type) { | 1311 FailureType failure_type) { |
| 1312 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 1313 | |
| 1275 // These results are not used after this call. Simply ignore the | 1314 // These results are not used after this call. Simply ignore the |
| 1276 // returned value after FinishUpdate(...). | 1315 // returned value after FinishUpdate(...). |
| 1277 safe_browsing::PrefixSetBuilder builder; | 1316 safe_browsing::PrefixSetBuilder builder; |
| 1278 std::vector<SBAddFullHash> add_full_hashes_result; | 1317 std::vector<SBAddFullHash> add_full_hashes_result; |
| 1279 | 1318 |
| 1280 if (!store->FinishUpdate(&builder, &add_full_hashes_result)) | 1319 if (!store->FinishUpdate(&builder, &add_full_hashes_result)) |
| 1281 RecordFailure(failure_type); | 1320 RecordFailure(failure_type); |
| 1282 | 1321 |
| 1283 #if defined(OS_MACOSX) | 1322 #if defined(OS_MACOSX) |
| 1284 base::mac::SetFileBackupExclusion(store_filename); | 1323 base::mac::SetFileBackupExclusion(store_filename); |
| 1285 #endif | 1324 #endif |
| 1286 | 1325 |
| 1287 return GetFileSizeOrZero(store_filename); | 1326 return GetFileSizeOrZero(store_filename); |
| 1288 } | 1327 } |
| 1289 | 1328 |
| 1290 void SafeBrowsingDatabaseNew::UpdatePrefixSetUrlStore( | 1329 void SafeBrowsingDatabaseNew::UpdatePrefixSetUrlStore( |
| 1291 const base::FilePath& db_filename, | 1330 const base::FilePath& db_filename, |
| 1292 SafeBrowsingStore* url_store, | 1331 SafeBrowsingStore* url_store, |
| 1293 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set, | 1332 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set, |
| 1294 FailureType finish_failure_type, | 1333 FailureType finish_failure_type, |
| 1295 FailureType write_failure_type, | 1334 FailureType write_failure_type, |
| 1296 bool store_full_hashes_in_prefix_set) { | 1335 bool store_full_hashes_in_prefix_set) { |
| 1336 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 1297 DCHECK(url_store); | 1337 DCHECK(url_store); |
| 1298 DCHECK(prefix_set); | 1338 DCHECK(prefix_set); |
| 1299 | 1339 |
| 1300 // Measure the amount of IO during the filter build. | 1340 // Measure the amount of IO during the filter build. |
| 1301 base::IoCounters io_before, io_after; | 1341 base::IoCounters io_before, io_after; |
| 1302 base::ProcessHandle handle = base::GetCurrentProcessHandle(); | 1342 base::ProcessHandle handle = base::GetCurrentProcessHandle(); |
| 1303 scoped_ptr<base::ProcessMetrics> metric( | 1343 scoped_ptr<base::ProcessMetrics> metric( |
| 1304 #if !defined(OS_MACOSX) | 1344 #if !defined(OS_MACOSX) |
| 1305 base::ProcessMetrics::CreateProcessMetrics(handle) | 1345 base::ProcessMetrics::CreateProcessMetrics(handle) |
| 1306 #else | 1346 #else |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1369 const int64 file_size = GetFileSizeOrZero(db_filename); | 1409 const int64 file_size = GetFileSizeOrZero(db_filename); |
| 1370 UMA_HISTOGRAM_COUNTS("SB2.DatabaseKilobytes", | 1410 UMA_HISTOGRAM_COUNTS("SB2.DatabaseKilobytes", |
| 1371 static_cast<int>(file_size / 1024)); | 1411 static_cast<int>(file_size / 1024)); |
| 1372 | 1412 |
| 1373 #if defined(OS_MACOSX) | 1413 #if defined(OS_MACOSX) |
| 1374 base::mac::SetFileBackupExclusion(db_filename); | 1414 base::mac::SetFileBackupExclusion(db_filename); |
| 1375 #endif | 1415 #endif |
| 1376 } | 1416 } |
| 1377 | 1417 |
| 1378 void SafeBrowsingDatabaseNew::UpdateIpBlacklistStore() { | 1418 void SafeBrowsingDatabaseNew::UpdateIpBlacklistStore() { |
| 1419 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 1420 | |
| 1379 // Note: prefixes will not be empty. The current data store implementation | 1421 // Note: prefixes will not be empty. The current data store implementation |
| 1380 // stores all full-length hashes as both full and prefix hashes. | 1422 // stores all full-length hashes as both full and prefix hashes. |
| 1381 safe_browsing::PrefixSetBuilder builder; | 1423 safe_browsing::PrefixSetBuilder builder; |
| 1382 std::vector<SBAddFullHash> full_hashes; | 1424 std::vector<SBAddFullHash> full_hashes; |
| 1383 if (!ip_blacklist_store_->FinishUpdate(&builder, &full_hashes)) { | 1425 if (!ip_blacklist_store_->FinishUpdate(&builder, &full_hashes)) { |
| 1384 RecordFailure(FAILURE_IP_BLACKLIST_UPDATE_FINISH); | 1426 RecordFailure(FAILURE_IP_BLACKLIST_UPDATE_FINISH); |
| 1385 LoadIpBlacklist(std::vector<SBAddFullHash>()); // Clear the list. | 1427 LoadIpBlacklist(std::vector<SBAddFullHash>()); // Clear the list. |
| 1386 return; | 1428 return; |
| 1387 } | 1429 } |
| 1388 | 1430 |
| 1389 #if defined(OS_MACOSX) | 1431 #if defined(OS_MACOSX) |
| 1390 base::mac::SetFileBackupExclusion(IpBlacklistDBFilename(filename_base_)); | 1432 base::mac::SetFileBackupExclusion(IpBlacklistDBFilename(filename_base_)); |
| 1391 #endif | 1433 #endif |
| 1392 | 1434 |
| 1393 LoadIpBlacklist(full_hashes); | 1435 LoadIpBlacklist(full_hashes); |
| 1394 } | 1436 } |
| 1395 | 1437 |
| 1396 void SafeBrowsingDatabaseNew::HandleCorruptDatabase() { | 1438 void SafeBrowsingDatabaseNew::HandleCorruptDatabase() { |
| 1439 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 1440 | |
| 1397 // Reset the database after the current task has unwound (but only | 1441 // Reset the database after the current task has unwound (but only |
| 1398 // reset once within the scope of a given task). | 1442 // reset once within the scope of a given task). |
| 1399 if (!reset_factory_.HasWeakPtrs()) { | 1443 if (!reset_factory_.HasWeakPtrs()) { |
| 1400 RecordFailure(FAILURE_DATABASE_CORRUPT); | 1444 RecordFailure(FAILURE_DATABASE_CORRUPT); |
| 1401 base::MessageLoop::current()->PostTask(FROM_HERE, | 1445 base::MessageLoop::current()->PostTask(FROM_HERE, |
| 1402 base::Bind(&SafeBrowsingDatabaseNew::OnHandleCorruptDatabase, | 1446 base::Bind(&SafeBrowsingDatabaseNew::OnHandleCorruptDatabase, |
| 1403 reset_factory_.GetWeakPtr())); | 1447 reset_factory_.GetWeakPtr())); |
| 1404 } | 1448 } |
| 1405 } | 1449 } |
| 1406 | 1450 |
| 1407 void SafeBrowsingDatabaseNew::OnHandleCorruptDatabase() { | 1451 void SafeBrowsingDatabaseNew::OnHandleCorruptDatabase() { |
| 1452 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 1453 | |
| 1408 RecordFailure(FAILURE_DATABASE_CORRUPT_HANDLER); | 1454 RecordFailure(FAILURE_DATABASE_CORRUPT_HANDLER); |
| 1409 corruption_detected_ = true; // Stop updating the database. | 1455 corruption_detected_ = true; // Stop updating the database. |
| 1410 ResetDatabase(); | 1456 ResetDatabase(); |
| 1411 | 1457 |
| 1412 // NOTE(shess): ResetDatabase() should remove the corruption, so this should | 1458 // NOTE(shess): ResetDatabase() should remove the corruption, so this should |
| 1413 // only happen once. If you are here because you are hitting this after a | 1459 // only happen once. If you are here because you are hitting this after a |
| 1414 // restart, then I would be very interested in working with you to figure out | 1460 // restart, then I would be very interested in working with you to figure out |
| 1415 // what is happening, since it may affect real users. | 1461 // what is happening, since it may affect real users. |
| 1416 DLOG(FATAL) << "SafeBrowsing database was corrupt and reset"; | 1462 DLOG(FATAL) << "SafeBrowsing database was corrupt and reset"; |
| 1417 } | 1463 } |
| 1418 | 1464 |
| 1419 // TODO(shess): I'm not clear why this code doesn't have any | 1465 // TODO(shess): I'm not clear why this code doesn't have any |
| 1420 // real error-handling. | 1466 // real error-handling. |
| 1421 void SafeBrowsingDatabaseNew::LoadPrefixSet( | 1467 void SafeBrowsingDatabaseNew::LoadPrefixSet( |
| 1422 const base::FilePath& db_filename, | 1468 const base::FilePath& db_filename, |
| 1423 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set, | 1469 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set, |
| 1424 FailureType read_failure_type) { | 1470 FailureType read_failure_type) { |
| 1471 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 1472 | |
| 1425 if (!prefix_set) | 1473 if (!prefix_set) |
| 1426 return; | 1474 return; |
| 1427 | 1475 |
| 1428 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); | |
| 1429 DCHECK(!filename_base_.empty()); | 1476 DCHECK(!filename_base_.empty()); |
| 1430 | 1477 |
| 1431 const base::FilePath prefix_set_filename = PrefixSetForFilename(db_filename); | 1478 const base::FilePath prefix_set_filename = PrefixSetForFilename(db_filename); |
| 1432 | 1479 |
| 1433 // Only use the prefix set if database is present and non-empty. | 1480 // Only use the prefix set if database is present and non-empty. |
| 1434 if (!GetFileSizeOrZero(db_filename)) | 1481 if (!GetFileSizeOrZero(db_filename)) |
| 1435 return; | 1482 return; |
| 1436 | 1483 |
| 1437 // Cleanup any stale bloom filter (no longer used). | 1484 // Cleanup any stale bloom filter (no longer used). |
| 1438 // TODO(shess): Track existence to drive removal of this code? | 1485 // TODO(shess): Track existence to drive removal of this code? |
| 1439 const base::FilePath bloom_filter_filename = | 1486 const base::FilePath bloom_filter_filename = |
| 1440 BloomFilterForFilename(db_filename); | 1487 BloomFilterForFilename(db_filename); |
| 1441 base::DeleteFile(bloom_filter_filename, false); | 1488 base::DeleteFile(bloom_filter_filename, false); |
| 1442 | 1489 |
| 1443 const base::TimeTicks before = base::TimeTicks::Now(); | 1490 const base::TimeTicks before = base::TimeTicks::Now(); |
| 1444 *prefix_set = safe_browsing::PrefixSet::LoadFile(prefix_set_filename); | 1491 *prefix_set = safe_browsing::PrefixSet::LoadFile(prefix_set_filename); |
| 1445 UMA_HISTOGRAM_TIMES("SB2.PrefixSetLoad", base::TimeTicks::Now() - before); | 1492 UMA_HISTOGRAM_TIMES("SB2.PrefixSetLoad", base::TimeTicks::Now() - before); |
| 1446 | 1493 |
| 1447 if (!prefix_set->get()) | 1494 if (!prefix_set->get()) |
| 1448 RecordFailure(read_failure_type); | 1495 RecordFailure(read_failure_type); |
| 1449 } | 1496 } |
| 1450 | 1497 |
| 1451 bool SafeBrowsingDatabaseNew::Delete() { | 1498 bool SafeBrowsingDatabaseNew::Delete() { |
| 1452 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); | 1499 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1453 DCHECK(!filename_base_.empty()); | 1500 DCHECK(!filename_base_.empty()); |
| 1454 | 1501 |
| 1455 // TODO(shess): This is a mess. SafeBrowsingFileStore::Delete() closes the | 1502 // TODO(shess): This is a mess. SafeBrowsingFileStore::Delete() closes the |
| 1456 // store before calling DeleteStore(). DeleteStore() deletes transient files | 1503 // store before calling DeleteStore(). DeleteStore() deletes transient files |
| 1457 // in addition to the main file. Probably all of these should be converted to | 1504 // in addition to the main file. Probably all of these should be converted to |
| 1458 // a helper which calls Delete() if the store exists, else DeleteStore() on | 1505 // a helper which calls Delete() if the store exists, else DeleteStore() on |
| 1459 // the generated filename. | 1506 // the generated filename. |
| 1460 | 1507 |
| 1461 // TODO(shess): Determine if the histograms are useful in any way. I cannot | 1508 // TODO(shess): Determine if the histograms are useful in any way. I cannot |
| 1462 // recall any action taken as a result of their values, in which case it might | 1509 // recall any action taken as a result of their values, in which case it might |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1525 if (!r11) | 1572 if (!r11) |
| 1526 RecordFailure(FAILURE_UNWANTED_SOFTWARE_PREFIX_SET_DELETE); | 1573 RecordFailure(FAILURE_UNWANTED_SOFTWARE_PREFIX_SET_DELETE); |
| 1527 | 1574 |
| 1528 return r1 && r2 && r3 && r4 && r5 && r6 && r7 && r8 && r9 && r10 && r11; | 1575 return r1 && r2 && r3 && r4 && r5 && r6 && r7 && r8 && r9 && r10 && r11; |
| 1529 } | 1576 } |
| 1530 | 1577 |
| 1531 void SafeBrowsingDatabaseNew::WritePrefixSet( | 1578 void SafeBrowsingDatabaseNew::WritePrefixSet( |
| 1532 const base::FilePath& db_filename, | 1579 const base::FilePath& db_filename, |
| 1533 const safe_browsing::PrefixSet* prefix_set, | 1580 const safe_browsing::PrefixSet* prefix_set, |
| 1534 FailureType write_failure_type) { | 1581 FailureType write_failure_type) { |
| 1535 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); | 1582 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1536 | 1583 |
| 1537 if (!prefix_set) | 1584 if (!prefix_set) |
| 1538 return; | 1585 return; |
| 1539 | 1586 |
| 1540 const base::FilePath prefix_set_filename = PrefixSetForFilename(db_filename); | 1587 const base::FilePath prefix_set_filename = PrefixSetForFilename(db_filename); |
| 1541 | 1588 |
| 1542 const base::TimeTicks before = base::TimeTicks::Now(); | 1589 const base::TimeTicks before = base::TimeTicks::Now(); |
| 1543 const bool write_ok = prefix_set->WriteFile(prefix_set_filename); | 1590 const bool write_ok = prefix_set->WriteFile(prefix_set_filename); |
| 1544 UMA_HISTOGRAM_TIMES("SB2.PrefixSetWrite", base::TimeTicks::Now() - before); | 1591 UMA_HISTOGRAM_TIMES("SB2.PrefixSetWrite", base::TimeTicks::Now() - before); |
| 1545 | 1592 |
| 1546 const int64 file_size = GetFileSizeOrZero(prefix_set_filename); | 1593 const int64 file_size = GetFileSizeOrZero(prefix_set_filename); |
| 1547 UMA_HISTOGRAM_COUNTS("SB2.PrefixSetKilobytes", | 1594 UMA_HISTOGRAM_COUNTS("SB2.PrefixSetKilobytes", |
| 1548 static_cast<int>(file_size / 1024)); | 1595 static_cast<int>(file_size / 1024)); |
| 1549 | 1596 |
| 1550 if (!write_ok) | 1597 if (!write_ok) |
| 1551 RecordFailure(write_failure_type); | 1598 RecordFailure(write_failure_type); |
| 1552 | 1599 |
| 1553 #if defined(OS_MACOSX) | 1600 #if defined(OS_MACOSX) |
| 1554 base::mac::SetFileBackupExclusion(prefix_set_filename); | 1601 base::mac::SetFileBackupExclusion(prefix_set_filename); |
| 1555 #endif | 1602 #endif |
| 1556 } | 1603 } |
| 1557 | 1604 |
| 1558 void SafeBrowsingDatabaseNew::WhitelistEverything(SBWhitelist* whitelist) { | 1605 void SafeBrowsingDatabaseNew::WhitelistEverything(SBWhitelist* whitelist) { |
| 1606 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 1559 base::AutoLock locked(lookup_lock_); | 1607 base::AutoLock locked(lookup_lock_); |
| 1560 whitelist->second = true; | 1608 whitelist->second = true; |
| 1561 whitelist->first.clear(); | 1609 whitelist->first.clear(); |
| 1562 } | 1610 } |
| 1563 | 1611 |
| 1564 void SafeBrowsingDatabaseNew::LoadWhitelist( | 1612 void SafeBrowsingDatabaseNew::LoadWhitelist( |
| 1565 const std::vector<SBAddFullHash>& full_hashes, | 1613 const std::vector<SBAddFullHash>& full_hashes, |
| 1566 SBWhitelist* whitelist) { | 1614 SBWhitelist* whitelist) { |
| 1567 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); | 1615 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1616 | |
| 1568 if (full_hashes.size() > kMaxWhitelistSize) { | 1617 if (full_hashes.size() > kMaxWhitelistSize) { |
| 1569 WhitelistEverything(whitelist); | 1618 WhitelistEverything(whitelist); |
| 1570 return; | 1619 return; |
| 1571 } | 1620 } |
| 1572 | 1621 |
| 1573 std::vector<SBFullHash> new_whitelist; | 1622 std::vector<SBFullHash> new_whitelist; |
| 1574 new_whitelist.reserve(full_hashes.size()); | 1623 new_whitelist.reserve(full_hashes.size()); |
| 1575 for (std::vector<SBAddFullHash>::const_iterator it = full_hashes.begin(); | 1624 for (std::vector<SBAddFullHash>::const_iterator it = full_hashes.begin(); |
| 1576 it != full_hashes.end(); ++it) { | 1625 it != full_hashes.end(); ++it) { |
| 1577 new_whitelist.push_back(it->full_hash); | 1626 new_whitelist.push_back(it->full_hash); |
| 1578 } | 1627 } |
| 1579 std::sort(new_whitelist.begin(), new_whitelist.end(), SBFullHashLess); | 1628 std::sort(new_whitelist.begin(), new_whitelist.end(), SBFullHashLess); |
| 1580 | 1629 |
| 1581 SBFullHash kill_switch = SBFullHashForString(kWhitelistKillSwitchUrl); | 1630 SBFullHash kill_switch = SBFullHashForString(kWhitelistKillSwitchUrl); |
| 1582 if (std::binary_search(new_whitelist.begin(), new_whitelist.end(), | 1631 if (std::binary_search(new_whitelist.begin(), new_whitelist.end(), |
| 1583 kill_switch, SBFullHashLess)) { | 1632 kill_switch, SBFullHashLess)) { |
| 1584 // The kill switch is whitelisted hence we whitelist all URLs. | 1633 // The kill switch is whitelisted hence we whitelist all URLs. |
| 1585 WhitelistEverything(whitelist); | 1634 WhitelistEverything(whitelist); |
| 1586 } else { | 1635 } else { |
| 1587 base::AutoLock locked(lookup_lock_); | 1636 base::AutoLock locked(lookup_lock_); |
| 1588 whitelist->second = false; | 1637 whitelist->second = false; |
| 1589 whitelist->first.swap(new_whitelist); | 1638 whitelist->first.swap(new_whitelist); |
| 1590 } | 1639 } |
| 1591 } | 1640 } |
| 1592 | 1641 |
| 1593 void SafeBrowsingDatabaseNew::LoadIpBlacklist( | 1642 void SafeBrowsingDatabaseNew::LoadIpBlacklist( |
| 1594 const std::vector<SBAddFullHash>& full_hashes) { | 1643 const std::vector<SBAddFullHash>& full_hashes) { |
| 1595 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); | 1644 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1645 | |
| 1596 IPBlacklist new_blacklist; | 1646 IPBlacklist new_blacklist; |
| 1597 for (std::vector<SBAddFullHash>::const_iterator it = full_hashes.begin(); | 1647 for (std::vector<SBAddFullHash>::const_iterator it = full_hashes.begin(); |
| 1598 it != full_hashes.end(); | 1648 it != full_hashes.end(); |
| 1599 ++it) { | 1649 ++it) { |
| 1600 const char* full_hash = it->full_hash.full_hash; | 1650 const char* full_hash = it->full_hash.full_hash; |
| 1601 DCHECK_EQ(crypto::kSHA256Length, arraysize(it->full_hash.full_hash)); | 1651 DCHECK_EQ(crypto::kSHA256Length, arraysize(it->full_hash.full_hash)); |
| 1602 // The format of the IP blacklist is: | 1652 // The format of the IP blacklist is: |
| 1603 // SHA-1(IPv6 prefix) + uint8(prefix size) + 11 unused bytes. | 1653 // SHA-1(IPv6 prefix) + uint8(prefix size) + 11 unused bytes. |
| 1604 std::string hashed_ip_prefix(full_hash, base::kSHA1Length); | 1654 std::string hashed_ip_prefix(full_hash, base::kSHA1Length); |
| 1605 size_t prefix_size = static_cast<uint8>(full_hash[base::kSHA1Length]); | 1655 size_t prefix_size = static_cast<uint8>(full_hash[base::kSHA1Length]); |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 1624 << " hashed_ip:" << base::HexEncode(hashed_ip_prefix.data(), | 1674 << " hashed_ip:" << base::HexEncode(hashed_ip_prefix.data(), |
| 1625 hashed_ip_prefix.size()); | 1675 hashed_ip_prefix.size()); |
| 1626 new_blacklist[mask].insert(hashed_ip_prefix); | 1676 new_blacklist[mask].insert(hashed_ip_prefix); |
| 1627 } | 1677 } |
| 1628 | 1678 |
| 1629 base::AutoLock locked(lookup_lock_); | 1679 base::AutoLock locked(lookup_lock_); |
| 1630 ip_blacklist_.swap(new_blacklist); | 1680 ip_blacklist_.swap(new_blacklist); |
| 1631 } | 1681 } |
| 1632 | 1682 |
| 1633 bool SafeBrowsingDatabaseNew::IsMalwareIPMatchKillSwitchOn() { | 1683 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 | |
| 1634 SBFullHash malware_kill_switch = SBFullHashForString(kMalwareIPKillSwitchUrl); | 1688 SBFullHash malware_kill_switch = SBFullHashForString(kMalwareIPKillSwitchUrl); |
| 1635 std::vector<SBFullHash> full_hashes; | 1689 std::vector<SBFullHash> full_hashes; |
| 1636 full_hashes.push_back(malware_kill_switch); | 1690 full_hashes.push_back(malware_kill_switch); |
| 1637 return ContainsWhitelistedHashes(csd_whitelist_, full_hashes); | 1691 return ContainsWhitelistedHashes(csd_whitelist_, full_hashes); |
| 1638 } | 1692 } |
| 1639 | 1693 |
| 1640 bool SafeBrowsingDatabaseNew::IsCsdWhitelistKillSwitchOn() { | 1694 bool SafeBrowsingDatabaseNew::IsCsdWhitelistKillSwitchOn() { |
| 1695 // This method is theoretically thread-safe but document that it is currently | |
| 1696 // only expected to be called on the IO thread. | |
| 1697 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 1698 | |
| 1699 base::AutoLock locked(lookup_lock_); | |
| 1641 return csd_whitelist_.second; | 1700 return csd_whitelist_.second; |
| 1642 } | 1701 } |
| OLD | NEW |