| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 "base/file_util.h" | 7 #include "base/file_util.h" |
| 8 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
| 9 #include "base/metrics/stats_counters.h" | 9 #include "base/metrics/stats_counters.h" |
| 10 #include "base/time.h" | 10 #include "base/time.h" |
| (...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 280 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 280 DCHECK_EQ(creation_loop_, MessageLoop::current()); |
| 281 } | 281 } |
| 282 | 282 |
| 283 void SafeBrowsingDatabaseNew::Init(const FilePath& filename_base) { | 283 void SafeBrowsingDatabaseNew::Init(const FilePath& filename_base) { |
| 284 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 284 DCHECK_EQ(creation_loop_, MessageLoop::current()); |
| 285 | 285 |
| 286 // NOTE: There is no need to grab the lock in this function, since | 286 // NOTE: There is no need to grab the lock in this function, since |
| 287 // until it returns, there are no pointers to this class on other | 287 // until it returns, there are no pointers to this class on other |
| 288 // threads. Then again, that means there is no possibility of | 288 // threads. Then again, that means there is no possibility of |
| 289 // contention on the lock... | 289 // contention on the lock... |
| 290 AutoLock locked(lookup_lock_); | 290 base::AutoLock locked(lookup_lock_); |
| 291 | 291 |
| 292 DCHECK(browse_filename_.empty()); // Ensure we haven't been run before. | 292 DCHECK(browse_filename_.empty()); // Ensure we haven't been run before. |
| 293 DCHECK(download_filename_.empty()); // Ensure we haven't been run before. | 293 DCHECK(download_filename_.empty()); // Ensure we haven't been run before. |
| 294 | 294 |
| 295 browse_filename_ = BrowseDBFilename(filename_base); | 295 browse_filename_ = BrowseDBFilename(filename_base); |
| 296 browse_store_->Init( | 296 browse_store_->Init( |
| 297 browse_filename_, | 297 browse_filename_, |
| 298 NewCallback(this, &SafeBrowsingDatabaseNew::HandleCorruptDatabase)); | 298 NewCallback(this, &SafeBrowsingDatabaseNew::HandleCorruptDatabase)); |
| 299 | 299 |
| 300 full_browse_hashes_.clear(); | 300 full_browse_hashes_.clear(); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 317 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 317 DCHECK_EQ(creation_loop_, MessageLoop::current()); |
| 318 | 318 |
| 319 // Delete files on disk. | 319 // Delete files on disk. |
| 320 // TODO(shess): Hard to see where one might want to delete without a | 320 // TODO(shess): Hard to see where one might want to delete without a |
| 321 // reset. Perhaps inline |Delete()|? | 321 // reset. Perhaps inline |Delete()|? |
| 322 if (!Delete()) | 322 if (!Delete()) |
| 323 return false; | 323 return false; |
| 324 | 324 |
| 325 // Reset objects in memory. | 325 // Reset objects in memory. |
| 326 { | 326 { |
| 327 AutoLock locked(lookup_lock_); | 327 base::AutoLock locked(lookup_lock_); |
| 328 full_browse_hashes_.clear(); | 328 full_browse_hashes_.clear(); |
| 329 pending_browse_hashes_.clear(); | 329 pending_browse_hashes_.clear(); |
| 330 prefix_miss_cache_.clear(); | 330 prefix_miss_cache_.clear(); |
| 331 // TODO(shess): This could probably be |bloom_filter_.reset()|. | 331 // TODO(shess): This could probably be |bloom_filter_.reset()|. |
| 332 browse_bloom_filter_ = new BloomFilter(BloomFilter::kBloomFilterMinSize * | 332 browse_bloom_filter_ = new BloomFilter(BloomFilter::kBloomFilterMinSize * |
| 333 BloomFilter::kBloomFilterSizeRatio); | 333 BloomFilter::kBloomFilterSizeRatio); |
| 334 } | 334 } |
| 335 | 335 |
| 336 return true; | 336 return true; |
| 337 } | 337 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 348 prefix_hits->clear(); | 348 prefix_hits->clear(); |
| 349 full_hits->clear(); | 349 full_hits->clear(); |
| 350 | 350 |
| 351 std::vector<SBPrefix> prefixes; | 351 std::vector<SBPrefix> prefixes; |
| 352 BrowsePrefixesToCheck(url, &prefixes); | 352 BrowsePrefixesToCheck(url, &prefixes); |
| 353 if (prefixes.empty()) | 353 if (prefixes.empty()) |
| 354 return false; | 354 return false; |
| 355 | 355 |
| 356 // This function is called on the I/O thread, prevent changes to | 356 // This function is called on the I/O thread, prevent changes to |
| 357 // bloom filter and caches. | 357 // bloom filter and caches. |
| 358 AutoLock locked(lookup_lock_); | 358 base::AutoLock locked(lookup_lock_); |
| 359 | 359 |
| 360 if (!browse_bloom_filter_.get()) | 360 if (!browse_bloom_filter_.get()) |
| 361 return false; | 361 return false; |
| 362 | 362 |
| 363 size_t miss_count = 0; | 363 size_t miss_count = 0; |
| 364 for (size_t i = 0; i < prefixes.size(); ++i) { | 364 for (size_t i = 0; i < prefixes.size(); ++i) { |
| 365 if (browse_bloom_filter_->Exists(prefixes[i])) { | 365 if (browse_bloom_filter_->Exists(prefixes[i])) { |
| 366 prefix_hits->push_back(prefixes[i]); | 366 prefix_hits->push_back(prefixes[i]); |
| 367 if (prefix_miss_cache_.count(prefixes[i]) > 0) | 367 if (prefix_miss_cache_.count(prefixes[i]) > 0) |
| 368 ++miss_count; | 368 ++miss_count; |
| (...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 600 else | 600 else |
| 601 store->DeleteAddChunk(encoded_chunk_id); | 601 store->DeleteAddChunk(encoded_chunk_id); |
| 602 } | 602 } |
| 603 } | 603 } |
| 604 } | 604 } |
| 605 | 605 |
| 606 void SafeBrowsingDatabaseNew::CacheHashResults( | 606 void SafeBrowsingDatabaseNew::CacheHashResults( |
| 607 const std::vector<SBPrefix>& prefixes, | 607 const std::vector<SBPrefix>& prefixes, |
| 608 const std::vector<SBFullHashResult>& full_hits) { | 608 const std::vector<SBFullHashResult>& full_hits) { |
| 609 // This is called on the I/O thread, lock against updates. | 609 // This is called on the I/O thread, lock against updates. |
| 610 AutoLock locked(lookup_lock_); | 610 base::AutoLock locked(lookup_lock_); |
| 611 | 611 |
| 612 if (full_hits.empty()) { | 612 if (full_hits.empty()) { |
| 613 prefix_miss_cache_.insert(prefixes.begin(), prefixes.end()); | 613 prefix_miss_cache_.insert(prefixes.begin(), prefixes.end()); |
| 614 return; | 614 return; |
| 615 } | 615 } |
| 616 | 616 |
| 617 // TODO(shess): SBFullHashResult and SBAddFullHash are very similar. | 617 // TODO(shess): SBFullHashResult and SBAddFullHash are very similar. |
| 618 // Refactor to make them identical. | 618 // Refactor to make them identical. |
| 619 const base::Time now = base::Time::Now(); | 619 const base::Time now = base::Time::Now(); |
| 620 const size_t orig_size = pending_browse_hashes_.size(); | 620 const size_t orig_size = pending_browse_hashes_.size(); |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 722 &add_full_hashes_result)) | 722 &add_full_hashes_result)) |
| 723 RecordFailure(FAILURE_DOWNLOAD_DATABASE_UPDATE_FINISH); | 723 RecordFailure(FAILURE_DOWNLOAD_DATABASE_UPDATE_FINISH); |
| 724 return; | 724 return; |
| 725 } | 725 } |
| 726 | 726 |
| 727 void SafeBrowsingDatabaseNew::UpdateBrowseStore() { | 727 void SafeBrowsingDatabaseNew::UpdateBrowseStore() { |
| 728 // Copy out the pending add hashes. Copy rather than swapping in | 728 // Copy out the pending add hashes. Copy rather than swapping in |
| 729 // case |ContainsBrowseURL()| is called before the new filter is complete. | 729 // case |ContainsBrowseURL()| is called before the new filter is complete. |
| 730 std::vector<SBAddFullHash> pending_add_hashes; | 730 std::vector<SBAddFullHash> pending_add_hashes; |
| 731 { | 731 { |
| 732 AutoLock locked(lookup_lock_); | 732 base::AutoLock locked(lookup_lock_); |
| 733 pending_add_hashes.insert(pending_add_hashes.end(), | 733 pending_add_hashes.insert(pending_add_hashes.end(), |
| 734 pending_browse_hashes_.begin(), | 734 pending_browse_hashes_.begin(), |
| 735 pending_browse_hashes_.end()); | 735 pending_browse_hashes_.end()); |
| 736 } | 736 } |
| 737 | 737 |
| 738 // Measure the amount of IO during the bloom filter build. | 738 // Measure the amount of IO during the bloom filter build. |
| 739 base::IoCounters io_before, io_after; | 739 base::IoCounters io_before, io_after; |
| 740 base::ProcessHandle handle = base::Process::Current().handle(); | 740 base::ProcessHandle handle = base::Process::Current().handle(); |
| 741 scoped_ptr<base::ProcessMetrics> metric( | 741 scoped_ptr<base::ProcessMetrics> metric( |
| 742 #if !defined(OS_MACOSX) | 742 #if !defined(OS_MACOSX) |
| (...skipping 28 matching lines...) Expand all Loading... |
| 771 for (size_t i = 0; i < add_prefixes.size(); ++i) { | 771 for (size_t i = 0; i < add_prefixes.size(); ++i) { |
| 772 filter->Insert(add_prefixes[i].prefix); | 772 filter->Insert(add_prefixes[i].prefix); |
| 773 } | 773 } |
| 774 | 774 |
| 775 // This needs to be in sorted order by prefix for efficient access. | 775 // This needs to be in sorted order by prefix for efficient access. |
| 776 std::sort(add_full_hashes.begin(), add_full_hashes.end(), | 776 std::sort(add_full_hashes.begin(), add_full_hashes.end(), |
| 777 SBAddFullHashPrefixLess); | 777 SBAddFullHashPrefixLess); |
| 778 | 778 |
| 779 // Swap in the newly built filter and cache. | 779 // Swap in the newly built filter and cache. |
| 780 { | 780 { |
| 781 AutoLock locked(lookup_lock_); | 781 base::AutoLock locked(lookup_lock_); |
| 782 full_browse_hashes_.swap(add_full_hashes); | 782 full_browse_hashes_.swap(add_full_hashes); |
| 783 | 783 |
| 784 // TODO(shess): If |CacheHashResults()| is posted between the | 784 // TODO(shess): If |CacheHashResults()| is posted between the |
| 785 // earlier lock and this clear, those pending hashes will be lost. | 785 // earlier lock and this clear, those pending hashes will be lost. |
| 786 // It could be fixed by only removing hashes which were collected | 786 // It could be fixed by only removing hashes which were collected |
| 787 // at the earlier point. I believe that is fail-safe as-is (the | 787 // at the earlier point. I believe that is fail-safe as-is (the |
| 788 // hash will be fetched again). | 788 // hash will be fetched again). |
| 789 pending_browse_hashes_.clear(); | 789 pending_browse_hashes_.clear(); |
| 790 prefix_miss_cache_.clear(); | 790 prefix_miss_cache_.clear(); |
| 791 browse_bloom_filter_.swap(filter); | 791 browse_bloom_filter_.swap(filter); |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 898 return; | 898 return; |
| 899 | 899 |
| 900 const base::TimeTicks before = base::TimeTicks::Now(); | 900 const base::TimeTicks before = base::TimeTicks::Now(); |
| 901 const bool write_ok = browse_bloom_filter_->WriteFile(bloom_filter_filename_); | 901 const bool write_ok = browse_bloom_filter_->WriteFile(bloom_filter_filename_); |
| 902 DVLOG(1) << "SafeBrowsingDatabaseNew wrote bloom filter in " | 902 DVLOG(1) << "SafeBrowsingDatabaseNew wrote bloom filter in " |
| 903 << (base::TimeTicks::Now() - before).InMilliseconds() << " ms"; | 903 << (base::TimeTicks::Now() - before).InMilliseconds() << " ms"; |
| 904 | 904 |
| 905 if (!write_ok) | 905 if (!write_ok) |
| 906 RecordFailure(FAILURE_DATABASE_FILTER_WRITE); | 906 RecordFailure(FAILURE_DATABASE_FILTER_WRITE); |
| 907 } | 907 } |
| OLD | NEW |