| 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 <stddef.h> | 7 #include <stddef.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 #include <algorithm> | 9 #include <algorithm> |
| 10 #include <iterator> | 10 #include <iterator> |
| 11 #include <utility> | 11 #include <utility> |
| 12 | 12 |
| 13 #include "base/trace_event/trace_event.h" |
| 13 #include "base/bind.h" | 14 #include "base/bind.h" |
| 14 #include "base/files/file_util.h" | 15 #include "base/files/file_util.h" |
| 15 #include "base/macros.h" | 16 #include "base/macros.h" |
| 16 #include "base/message_loop/message_loop.h" | 17 #include "base/message_loop/message_loop.h" |
| 17 #include "base/metrics/histogram.h" | 18 #include "base/metrics/histogram.h" |
| 18 #include "base/process/process_handle.h" | 19 #include "base/process/process_handle.h" |
| 19 #include "base/process/process_metrics.h" | 20 #include "base/process/process_metrics.h" |
| 20 #include "base/sha1.h" | 21 #include "base/sha1.h" |
| 21 #include "base/strings/string_number_conversions.h" | 22 #include "base/strings/string_number_conversions.h" |
| 22 #include "base/strings/string_util.h" | 23 #include "base/strings/string_util.h" |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 234 } | 235 } |
| 235 | 236 |
| 236 // Helper for PrefixSetContainsUrlHashes(). Returns true if an un-expired match | 237 // Helper for PrefixSetContainsUrlHashes(). Returns true if an un-expired match |
| 237 // for |full_hash| is found in |cache|, with any matches appended to |results| | 238 // for |full_hash| is found in |cache|, with any matches appended to |results| |
| 238 // (true can be returned with zero matches). |expire_base| is used to check the | 239 // (true can be returned with zero matches). |expire_base| is used to check the |
| 239 // cache lifetime of matches, expired matches will be discarded from |cache|. | 240 // cache lifetime of matches, expired matches will be discarded from |cache|. |
| 240 bool GetCachedFullHash(std::map<SBPrefix, SBCachedFullHashResult>* cache, | 241 bool GetCachedFullHash(std::map<SBPrefix, SBCachedFullHashResult>* cache, |
| 241 const SBFullHash& full_hash, | 242 const SBFullHash& full_hash, |
| 242 const base::Time& expire_base, | 243 const base::Time& expire_base, |
| 243 std::vector<SBFullHashResult>* results) { | 244 std::vector<SBFullHashResult>* results) { |
| 245 TRACE_EVENT0("toplevel", "SafeBrowsingDatabaseNew::GetCachedFullHash"); |
| 246 |
| 244 // First check if there is a valid cached result for this prefix. | 247 // First check if there is a valid cached result for this prefix. |
| 245 std::map<SBPrefix, SBCachedFullHashResult>::iterator citer = | 248 std::map<SBPrefix, SBCachedFullHashResult>::iterator citer = |
| 246 cache->find(full_hash.prefix); | 249 cache->find(full_hash.prefix); |
| 247 if (citer == cache->end()) | 250 if (citer == cache->end()) |
| 248 return false; | 251 return false; |
| 249 | 252 |
| 250 // Remove expired entries. | 253 // Remove expired entries. |
| 251 SBCachedFullHashResult& cached_result = citer->second; | 254 SBCachedFullHashResult& cached_result = citer->second; |
| 252 if (cached_result.expire_after <= expire_base) { | 255 if (cached_result.expire_after <= expire_base) { |
| 253 cache->erase(citer); | 256 cache->erase(citer); |
| (...skipping 229 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 483 case PrefixSetId::BROWSE: | 486 case PrefixSetId::BROWSE: |
| 484 return outer_->browse_prefix_set_.get(); | 487 return outer_->browse_prefix_set_.get(); |
| 485 case PrefixSetId::UNWANTED_SOFTWARE: | 488 case PrefixSetId::UNWANTED_SOFTWARE: |
| 486 return outer_->unwanted_software_prefix_set_.get(); | 489 return outer_->unwanted_software_prefix_set_.get(); |
| 487 } | 490 } |
| 488 NOTREACHED(); | 491 NOTREACHED(); |
| 489 return nullptr; | 492 return nullptr; |
| 490 } | 493 } |
| 491 | 494 |
| 492 PrefixGetHashCache* prefix_gethash_cache() { | 495 PrefixGetHashCache* prefix_gethash_cache() { |
| 496 TRACE_EVENT0("toplevel", |
| 497 "SafeBrowsingDatabaseNew::ThreadSafeStateManager::" |
| 498 "ReadTransaction::prefix_gethash_cache"); |
| 493 // The cache is special: it is read/write on all threads. Access to it | 499 // The cache is special: it is read/write on all threads. Access to it |
| 494 // therefore requires a LOCK'ed transaction (i.e. it can't benefit from | 500 // therefore requires a LOCK'ed transaction (i.e. it can't benefit from |
| 495 // DONT_LOCK_ON_MAIN_THREAD). | 501 // DONT_LOCK_ON_MAIN_THREAD). |
| 496 DCHECK(transaction_lock_); | 502 DCHECK(transaction_lock_); |
| 497 return &outer_->prefix_gethash_cache_; | 503 return &outer_->prefix_gethash_cache_; |
| 498 } | 504 } |
| 499 | 505 |
| 500 private: | 506 private: |
| 501 // Only ThreadSafeStateManager is allowed to build a ReadTransaction. | 507 // Only ThreadSafeStateManager is allowed to build a ReadTransaction. |
| 502 friend class ThreadSafeStateManager; | 508 friend class ThreadSafeStateManager; |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 603 SafeBrowsingDatabaseNew::DatabaseStateManager::DatabaseStateManager( | 609 SafeBrowsingDatabaseNew::DatabaseStateManager::DatabaseStateManager( |
| 604 const scoped_refptr<const base::SequencedTaskRunner>& db_task_runner) | 610 const scoped_refptr<const base::SequencedTaskRunner>& db_task_runner) |
| 605 : db_task_runner_(db_task_runner), | 611 : db_task_runner_(db_task_runner), |
| 606 corruption_detected_(false), | 612 corruption_detected_(false), |
| 607 change_detected_(false) {} | 613 change_detected_(false) {} |
| 608 | 614 |
| 609 SafeBrowsingDatabaseNew::DatabaseStateManager::~DatabaseStateManager() {} | 615 SafeBrowsingDatabaseNew::DatabaseStateManager::~DatabaseStateManager() {} |
| 610 | 616 |
| 611 scoped_ptr<SafeBrowsingDatabaseNew::ReadTransaction> | 617 scoped_ptr<SafeBrowsingDatabaseNew::ReadTransaction> |
| 612 SafeBrowsingDatabaseNew::ThreadSafeStateManager::BeginReadTransaction() { | 618 SafeBrowsingDatabaseNew::ThreadSafeStateManager::BeginReadTransaction() { |
| 619 TRACE_EVENT0( |
| 620 "toplevel", |
| 621 "SafeBrowsingDatabaseNew::ThreadSafeStateManager::BeginReadTransaction"); |
| 613 return make_scoped_ptr( | 622 return make_scoped_ptr( |
| 614 new ReadTransaction(this, ReadTransaction::AutoLockRequirement::LOCK)); | 623 new ReadTransaction(this, ReadTransaction::AutoLockRequirement::LOCK)); |
| 615 } | 624 } |
| 616 | 625 |
| 617 scoped_ptr<SafeBrowsingDatabaseNew::ReadTransaction> SafeBrowsingDatabaseNew:: | 626 scoped_ptr<SafeBrowsingDatabaseNew::ReadTransaction> SafeBrowsingDatabaseNew:: |
| 618 ThreadSafeStateManager::BeginReadTransactionNoLockOnMainTaskRunner() { | 627 ThreadSafeStateManager::BeginReadTransactionNoLockOnMainTaskRunner() { |
| 619 return make_scoped_ptr(new ReadTransaction( | 628 return make_scoped_ptr(new ReadTransaction( |
| 620 this, | 629 this, |
| 621 ReadTransaction::AutoLockRequirement::DONT_LOCK_ON_MAIN_TASK_RUNNER)); | 630 ReadTransaction::AutoLockRequirement::DONT_LOCK_ON_MAIN_TASK_RUNNER)); |
| 622 } | 631 } |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 841 txn->clear_ip_blacklist(); | 850 txn->clear_ip_blacklist(); |
| 842 txn->WhitelistEverything(SBWhitelistId::CSD); | 851 txn->WhitelistEverything(SBWhitelistId::CSD); |
| 843 txn->WhitelistEverything(SBWhitelistId::DOWNLOAD); | 852 txn->WhitelistEverything(SBWhitelistId::DOWNLOAD); |
| 844 return true; | 853 return true; |
| 845 } | 854 } |
| 846 | 855 |
| 847 bool SafeBrowsingDatabaseNew::ContainsBrowseUrl( | 856 bool SafeBrowsingDatabaseNew::ContainsBrowseUrl( |
| 848 const GURL& url, | 857 const GURL& url, |
| 849 std::vector<SBPrefix>* prefix_hits, | 858 std::vector<SBPrefix>* prefix_hits, |
| 850 std::vector<SBFullHashResult>* cache_hits) { | 859 std::vector<SBFullHashResult>* cache_hits) { |
| 860 TRACE_EVENT0("toplevel", "SafeBrowsingDatabaseNew::ContainsBrowseUrl"); |
| 851 return PrefixSetContainsUrl(url, PrefixSetId::BROWSE, prefix_hits, | 861 return PrefixSetContainsUrl(url, PrefixSetId::BROWSE, prefix_hits, |
| 852 cache_hits); | 862 cache_hits); |
| 853 } | 863 } |
| 854 | 864 |
| 855 bool SafeBrowsingDatabaseNew::ContainsBrowseHashes( | 865 bool SafeBrowsingDatabaseNew::ContainsBrowseHashes( |
| 856 const std::vector<SBFullHash>& full_hashes, | 866 const std::vector<SBFullHash>& full_hashes, |
| 857 std::vector<SBPrefix>* prefix_hits, | 867 std::vector<SBPrefix>* prefix_hits, |
| 858 std::vector<SBFullHashResult>* cache_hits) { | 868 std::vector<SBFullHashResult>* cache_hits) { |
| 859 return PrefixSetContainsUrlHashes(full_hashes, PrefixSetId::BROWSE, | 869 return PrefixSetContainsUrlHashes(full_hashes, PrefixSetId::BROWSE, |
| 860 prefix_hits, cache_hits); | 870 prefix_hits, cache_hits); |
| 861 } | 871 } |
| 862 | 872 |
| 863 bool SafeBrowsingDatabaseNew::ContainsUnwantedSoftwareUrl( | 873 bool SafeBrowsingDatabaseNew::ContainsUnwantedSoftwareUrl( |
| 864 const GURL& url, | 874 const GURL& url, |
| 865 std::vector<SBPrefix>* prefix_hits, | 875 std::vector<SBPrefix>* prefix_hits, |
| 866 std::vector<SBFullHashResult>* cache_hits) { | 876 std::vector<SBFullHashResult>* cache_hits) { |
| 877 TRACE_EVENT0("toplevel", |
| 878 "SafeBrowsingDatabaseNew::ContainsUnwantedSoftwareUrl"); |
| 879 |
| 867 return PrefixSetContainsUrl(url, PrefixSetId::UNWANTED_SOFTWARE, prefix_hits, | 880 return PrefixSetContainsUrl(url, PrefixSetId::UNWANTED_SOFTWARE, prefix_hits, |
| 868 cache_hits); | 881 cache_hits); |
| 869 } | 882 } |
| 870 | 883 |
| 871 bool SafeBrowsingDatabaseNew::ContainsUnwantedSoftwareHashes( | 884 bool SafeBrowsingDatabaseNew::ContainsUnwantedSoftwareHashes( |
| 872 const std::vector<SBFullHash>& full_hashes, | 885 const std::vector<SBFullHash>& full_hashes, |
| 873 std::vector<SBPrefix>* prefix_hits, | 886 std::vector<SBPrefix>* prefix_hits, |
| 874 std::vector<SBFullHashResult>* cache_hits) { | 887 std::vector<SBFullHashResult>* cache_hits) { |
| 875 return PrefixSetContainsUrlHashes(full_hashes, PrefixSetId::UNWANTED_SOFTWARE, | 888 return PrefixSetContainsUrlHashes(full_hashes, PrefixSetId::UNWANTED_SOFTWARE, |
| 876 prefix_hits, cache_hits); | 889 prefix_hits, cache_hits); |
| 877 } | 890 } |
| 878 | 891 |
| 879 bool SafeBrowsingDatabaseNew::PrefixSetContainsUrl( | 892 bool SafeBrowsingDatabaseNew::PrefixSetContainsUrl( |
| 880 const GURL& url, | 893 const GURL& url, |
| 881 PrefixSetId prefix_set_id, | 894 PrefixSetId prefix_set_id, |
| 882 std::vector<SBPrefix>* prefix_hits, | 895 std::vector<SBPrefix>* prefix_hits, |
| 883 std::vector<SBFullHashResult>* cache_hits) { | 896 std::vector<SBFullHashResult>* cache_hits) { |
| 897 TRACE_EVENT0("toplevel", "SafeBrowsingDatabaseNew::PrefixSetContainsUrl"); |
| 884 std::vector<SBFullHash> full_hashes; | 898 std::vector<SBFullHash> full_hashes; |
| 885 UrlToFullHashes(url, false, &full_hashes); | 899 UrlToFullHashes(url, false, &full_hashes); |
| 886 return PrefixSetContainsUrlHashes(full_hashes, prefix_set_id, prefix_hits, | 900 return PrefixSetContainsUrlHashes(full_hashes, prefix_set_id, prefix_hits, |
| 887 cache_hits); | 901 cache_hits); |
| 888 } | 902 } |
| 889 | 903 |
| 890 bool SafeBrowsingDatabaseNew::PrefixSetContainsUrlHashes( | 904 bool SafeBrowsingDatabaseNew::PrefixSetContainsUrlHashes( |
| 891 const std::vector<SBFullHash>& full_hashes, | 905 const std::vector<SBFullHash>& full_hashes, |
| 892 PrefixSetId prefix_set_id, | 906 PrefixSetId prefix_set_id, |
| 893 std::vector<SBPrefix>* prefix_hits, | 907 std::vector<SBPrefix>* prefix_hits, |
| 894 std::vector<SBFullHashResult>* cache_hits) { | 908 std::vector<SBFullHashResult>* cache_hits) { |
| 895 // Clear the results first. | 909 // Clear the results first. |
| 896 prefix_hits->clear(); | 910 prefix_hits->clear(); |
| 897 cache_hits->clear(); | 911 cache_hits->clear(); |
| 898 | 912 |
| 899 if (full_hashes.empty()) | 913 if (full_hashes.empty()) |
| 900 return false; | 914 return false; |
| 901 | 915 |
| 902 // Used to determine cache expiration. | 916 // Used to determine cache expiration. |
| 903 const base::Time now = base::Time::Now(); | 917 const base::Time now = base::Time::Now(); |
| 904 | 918 |
| 905 { | 919 { |
| 920 TRACE_EVENT0("toplevel", |
| 921 "SafeBrowsingDatabaseNew::PrefixSetContainsUrlHashes"); |
| 906 scoped_ptr<ReadTransaction> txn = state_manager_.BeginReadTransaction(); | 922 scoped_ptr<ReadTransaction> txn = state_manager_.BeginReadTransaction(); |
| 907 | 923 |
| 908 // |prefix_set| is empty until it is either read from disk, or the first | 924 // |prefix_set| is empty until it is either read from disk, or the first |
| 909 // update populates it. Bail out without a hit if not yet available. | 925 // update populates it. Bail out without a hit if not yet available. |
| 910 const PrefixSet* prefix_set = txn->GetPrefixSet(prefix_set_id); | 926 const PrefixSet* prefix_set = txn->GetPrefixSet(prefix_set_id); |
| 911 if (!prefix_set) | 927 if (!prefix_set) |
| 912 return false; | 928 return false; |
| 913 | 929 |
| 914 for (size_t i = 0; i < full_hashes.size(); ++i) { | 930 { |
| 915 if (!GetCachedFullHash(txn->prefix_gethash_cache(), full_hashes[i], now, | 931 TRACE_EVENT0( |
| 916 cache_hits)) { | 932 "toplevel", |
| 917 // No valid cached result, check the database. | 933 "SafeBrowsingDatabaseNew::PrefixSetContainsUrlHashes::ForLoop"); |
| 918 if (prefix_set->Exists(full_hashes[i])) | 934 for (size_t i = 0; i < full_hashes.size(); ++i) { |
| 919 prefix_hits->push_back(full_hashes[i].prefix); | 935 if (!GetCachedFullHash(txn->prefix_gethash_cache(), full_hashes[i], now, |
| 936 cache_hits)) { |
| 937 // No valid cached result, check the database. |
| 938 if (prefix_set->Exists(full_hashes[i])) |
| 939 prefix_hits->push_back(full_hashes[i].prefix); |
| 940 } |
| 920 } | 941 } |
| 921 } | 942 } |
| 922 } | 943 } |
| 923 | 944 |
| 924 // Multiple full hashes could share prefix, remove duplicates. | 945 { |
| 925 std::sort(prefix_hits->begin(), prefix_hits->end()); | 946 TRACE_EVENT0( |
| 926 prefix_hits->erase(std::unique(prefix_hits->begin(), prefix_hits->end()), | 947 "toplevel", |
| 927 prefix_hits->end()); | 948 "SafeBrowsingDatabaseNew::PrefixSetContainsUrlHashes::SortAndErase"); |
| 949 // Multiple full hashes could share prefix, remove duplicates. |
| 950 std::sort(prefix_hits->begin(), prefix_hits->end()); |
| 951 prefix_hits->erase(std::unique(prefix_hits->begin(), prefix_hits->end()), |
| 952 prefix_hits->end()); |
| 953 } |
| 928 | 954 |
| 929 return !prefix_hits->empty() || !cache_hits->empty(); | 955 return !prefix_hits->empty() || !cache_hits->empty(); |
| 930 } | 956 } |
| 931 | 957 |
| 932 bool SafeBrowsingDatabaseNew::ContainsDownloadUrlPrefixes( | 958 bool SafeBrowsingDatabaseNew::ContainsDownloadUrlPrefixes( |
| 933 const std::vector<SBPrefix>& prefixes, | 959 const std::vector<SBPrefix>& prefixes, |
| 934 std::vector<SBPrefix>* prefix_hits) { | 960 std::vector<SBPrefix>* prefix_hits) { |
| 935 DCHECK(db_task_runner_->RunsTasksOnCurrentThread()); | 961 DCHECK(db_task_runner_->RunsTasksOnCurrentThread()); |
| 936 | 962 |
| 937 // Ignore this check when download checking is not enabled. | 963 // Ignore this check when download checking is not enabled. |
| (...skipping 976 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1914 | 1940 |
| 1915 // Histogram properties as in UMA_HISTOGRAM_COUNTS macro. | 1941 // Histogram properties as in UMA_HISTOGRAM_COUNTS macro. |
| 1916 base::HistogramBase* histogram_pointer = base::Histogram::FactoryGet( | 1942 base::HistogramBase* histogram_pointer = base::Histogram::FactoryGet( |
| 1917 histogram_name, 1, 1000000, 50, | 1943 histogram_name, 1, 1000000, 50, |
| 1918 base::HistogramBase::kUmaTargetedHistogramFlag); | 1944 base::HistogramBase::kUmaTargetedHistogramFlag); |
| 1919 | 1945 |
| 1920 histogram_pointer->Add(file_size_kilobytes); | 1946 histogram_pointer->Add(file_size_kilobytes); |
| 1921 } | 1947 } |
| 1922 | 1948 |
| 1923 } // namespace safe_browsing | 1949 } // namespace safe_browsing |
| OLD | NEW |