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 678 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
689 // This method is theoretically thread-safe but document that it is currently | 689 // This method is theoretically thread-safe but document that it is currently |
690 // only expected to be called on the IO thread. | 690 // only expected to be called on the IO thread. |
691 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 691 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
692 | 692 |
693 return PrefixSetContainsUrl( | 693 return PrefixSetContainsUrl( |
694 url, &unwanted_software_prefix_set_, prefix_hits, cache_hits); | 694 url, &unwanted_software_prefix_set_, prefix_hits, cache_hits); |
695 } | 695 } |
696 | 696 |
697 bool SafeBrowsingDatabaseNew::PrefixSetContainsUrl( | 697 bool SafeBrowsingDatabaseNew::PrefixSetContainsUrl( |
698 const GURL& url, | 698 const GURL& url, |
699 scoped_ptr<safe_browsing::PrefixSet>* prefix_set_getter, | 699 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set_getter, |
700 std::vector<SBPrefix>* prefix_hits, | 700 std::vector<SBPrefix>* prefix_hits, |
701 std::vector<SBFullHashResult>* cache_hits) { | 701 std::vector<SBFullHashResult>* cache_hits) { |
702 // This method is theoretically thread-safe but document that it is currently | 702 // This method is theoretically thread-safe but document that it is currently |
703 // only expected to be called on the IO thread. | 703 // only expected to be called on the IO thread. |
704 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 704 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
705 | 705 |
706 // Clear the results first. | 706 // Clear the results first. |
707 prefix_hits->clear(); | 707 prefix_hits->clear(); |
708 cache_hits->clear(); | 708 cache_hits->clear(); |
709 | 709 |
710 std::vector<SBFullHash> full_hashes; | 710 std::vector<SBFullHash> full_hashes; |
711 UrlToFullHashes(url, false, &full_hashes); | 711 UrlToFullHashes(url, false, &full_hashes); |
712 if (full_hashes.empty()) | 712 if (full_hashes.empty()) |
713 return false; | 713 return false; |
714 | 714 |
715 return PrefixSetContainsUrlHashes( | 715 return PrefixSetContainsUrlHashes( |
716 full_hashes, prefix_set_getter, prefix_hits, cache_hits); | 716 full_hashes, prefix_set_getter, prefix_hits, cache_hits); |
717 } | 717 } |
718 | 718 |
719 bool SafeBrowsingDatabaseNew::ContainsBrowseUrlHashesForTesting( | 719 bool SafeBrowsingDatabaseNew::ContainsBrowseUrlHashesForTesting( |
720 const std::vector<SBFullHash>& full_hashes, | 720 const std::vector<SBFullHash>& full_hashes, |
721 std::vector<SBPrefix>* prefix_hits, | 721 std::vector<SBPrefix>* prefix_hits, |
722 std::vector<SBFullHashResult>* cache_hits) { | 722 std::vector<SBFullHashResult>* cache_hits) { |
723 return PrefixSetContainsUrlHashes( | 723 return PrefixSetContainsUrlHashes( |
724 full_hashes, &browse_prefix_set_, prefix_hits, cache_hits); | 724 full_hashes, &browse_prefix_set_, prefix_hits, cache_hits); |
725 } | 725 } |
726 | 726 |
727 bool SafeBrowsingDatabaseNew::PrefixSetContainsUrlHashes( | 727 bool SafeBrowsingDatabaseNew::PrefixSetContainsUrlHashes( |
728 const std::vector<SBFullHash>& full_hashes, | 728 const std::vector<SBFullHash>& full_hashes, |
729 scoped_ptr<safe_browsing::PrefixSet>* prefix_set_getter, | 729 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set_getter, |
730 std::vector<SBPrefix>* prefix_hits, | 730 std::vector<SBPrefix>* prefix_hits, |
731 std::vector<SBFullHashResult>* cache_hits) { | 731 std::vector<SBFullHashResult>* cache_hits) { |
732 // This method is theoretically thread-safe but document that it is currently | 732 // This method is theoretically thread-safe but document that it is currently |
733 // only expected to be called on the IO thread. | 733 // only expected to be called on the IO thread. |
734 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 734 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
735 | 735 |
736 // Used to determine cache expiration. | 736 // Used to determine cache expiration. |
737 const base::Time now = base::Time::Now(); | 737 const base::Time now = base::Time::Now(); |
738 | 738 |
739 base::AutoLock locked(lookup_lock_); | 739 base::AutoLock locked(lookup_lock_); |
740 | 740 |
741 // |prefix_set| is empty until it is either read from disk, or the first | 741 // |prefix_set| is empty until it is either read from disk, or the first |
742 // update populates it. Bail out without a hit if not yet available. | 742 // update populates it. Bail out without a hit if not yet available. |
743 // |prefix_set_getter| can only be accessed while holding |lookup_lock_| hence | 743 // |prefix_set_getter| can only be accessed while holding |lookup_lock_| hence |
744 // why it is passed as a parameter rather than passing the |prefix_set| | 744 // why it is passed as a parameter rather than passing the |prefix_set| |
745 // directly. | 745 // directly. |
746 safe_browsing::PrefixSet* prefix_set = prefix_set_getter->get(); | 746 const safe_browsing::PrefixSet* prefix_set = prefix_set_getter->get(); |
747 if (!prefix_set) | 747 if (!prefix_set) |
748 return false; | 748 return false; |
749 | 749 |
750 for (size_t i = 0; i < full_hashes.size(); ++i) { | 750 for (size_t i = 0; i < full_hashes.size(); ++i) { |
751 if (!GetCachedFullHash( | 751 if (!GetCachedFullHash( |
752 &prefix_gethash_cache_, full_hashes[i], now, cache_hits)) { | 752 &prefix_gethash_cache_, full_hashes[i], now, cache_hits)) { |
753 // No valid cached result, check the database. | 753 // No valid cached result, check the database. |
754 if (prefix_set->Exists(full_hashes[i])) | 754 if (prefix_set->Exists(full_hashes[i])) |
755 prefix_hits->push_back(full_hashes[i].prefix); | 755 prefix_hits->push_back(full_hashes[i].prefix); |
756 } | 756 } |
(...skipping 566 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1323 #if defined(OS_MACOSX) | 1323 #if defined(OS_MACOSX) |
1324 base::mac::SetFileBackupExclusion(store_filename); | 1324 base::mac::SetFileBackupExclusion(store_filename); |
1325 #endif | 1325 #endif |
1326 | 1326 |
1327 return GetFileSizeOrZero(store_filename); | 1327 return GetFileSizeOrZero(store_filename); |
1328 } | 1328 } |
1329 | 1329 |
1330 void SafeBrowsingDatabaseNew::UpdatePrefixSetUrlStore( | 1330 void SafeBrowsingDatabaseNew::UpdatePrefixSetUrlStore( |
1331 const base::FilePath& db_filename, | 1331 const base::FilePath& db_filename, |
1332 SafeBrowsingStore* url_store, | 1332 SafeBrowsingStore* url_store, |
1333 scoped_ptr<safe_browsing::PrefixSet>* prefix_set, | 1333 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set, |
1334 FailureType finish_failure_type, | 1334 FailureType finish_failure_type, |
1335 FailureType write_failure_type) { | 1335 FailureType write_failure_type) { |
1336 DCHECK(thread_checker_.CalledOnValidThread()); | 1336 DCHECK(thread_checker_.CalledOnValidThread()); |
1337 | 1337 |
1338 // Measure the amount of IO during the filter build. | 1338 // Measure the amount of IO during the filter build. |
1339 base::IoCounters io_before, io_after; | 1339 base::IoCounters io_before, io_after; |
1340 base::ProcessHandle handle = base::GetCurrentProcessHandle(); | 1340 base::ProcessHandle handle = base::GetCurrentProcessHandle(); |
1341 scoped_ptr<base::ProcessMetrics> metric( | 1341 scoped_ptr<base::ProcessMetrics> metric( |
1342 #if !defined(OS_MACOSX) | 1342 #if !defined(OS_MACOSX) |
1343 base::ProcessMetrics::CreateProcessMetrics(handle) | 1343 base::ProcessMetrics::CreateProcessMetrics(handle) |
(...skipping 18 matching lines...) Expand all Loading... |
1362 if (!url_store->FinishUpdate(&builder, &add_full_hashes)) { | 1362 if (!url_store->FinishUpdate(&builder, &add_full_hashes)) { |
1363 RecordFailure(finish_failure_type); | 1363 RecordFailure(finish_failure_type); |
1364 return; | 1364 return; |
1365 } | 1365 } |
1366 | 1366 |
1367 std::vector<SBFullHash> full_hash_results; | 1367 std::vector<SBFullHash> full_hash_results; |
1368 for (size_t i = 0; i < add_full_hashes.size(); ++i) { | 1368 for (size_t i = 0; i < add_full_hashes.size(); ++i) { |
1369 full_hash_results.push_back(add_full_hashes[i].full_hash); | 1369 full_hash_results.push_back(add_full_hashes[i].full_hash); |
1370 } | 1370 } |
1371 | 1371 |
1372 scoped_ptr<safe_browsing::PrefixSet> new_prefix_set( | 1372 scoped_ptr<const safe_browsing::PrefixSet> new_prefix_set( |
1373 builder.GetPrefixSet(full_hash_results)); | 1373 builder.GetPrefixSet(full_hash_results)); |
1374 | 1374 |
1375 // Swap in the newly built filter. | 1375 // Swap in the newly built filter. |
1376 { | 1376 { |
1377 base::AutoLock locked(lookup_lock_); | 1377 base::AutoLock locked(lookup_lock_); |
1378 prefix_set->swap(new_prefix_set); | 1378 prefix_set->swap(new_prefix_set); |
1379 } | 1379 } |
1380 | 1380 |
1381 UMA_HISTOGRAM_LONG_TIMES("SB2.BuildFilter", base::TimeTicks::Now() - before); | 1381 UMA_HISTOGRAM_LONG_TIMES("SB2.BuildFilter", base::TimeTicks::Now() - before); |
1382 | 1382 |
1383 // Persist the prefix set to disk. Note: there is no need to lock since the | 1383 // Persist the prefix set to disk. Note: there is no need to lock since the |
1384 // only write to |*prefix_set| is on this thread (in the swap() above). | 1384 // only write to |*prefix_set| is on this thread (in the swap() above). |
1385 // TODO(gab): Strengthen this requirement by design (const pointers) rather | |
1386 // than assumptions. | |
1387 WritePrefixSet(db_filename, prefix_set->get(), write_failure_type); | 1385 WritePrefixSet(db_filename, prefix_set->get(), write_failure_type); |
1388 | 1386 |
1389 // Gather statistics. | 1387 // Gather statistics. |
1390 if (got_counters && metric->GetIOCounters(&io_after)) { | 1388 if (got_counters && metric->GetIOCounters(&io_after)) { |
1391 UMA_HISTOGRAM_COUNTS("SB2.BuildReadKilobytes", | 1389 UMA_HISTOGRAM_COUNTS("SB2.BuildReadKilobytes", |
1392 static_cast<int>(io_after.ReadTransferCount - | 1390 static_cast<int>(io_after.ReadTransferCount - |
1393 io_before.ReadTransferCount) / 1024); | 1391 io_before.ReadTransferCount) / 1024); |
1394 UMA_HISTOGRAM_COUNTS("SB2.BuildWriteKilobytes", | 1392 UMA_HISTOGRAM_COUNTS("SB2.BuildWriteKilobytes", |
1395 static_cast<int>(io_after.WriteTransferCount - | 1393 static_cast<int>(io_after.WriteTransferCount - |
1396 io_before.WriteTransferCount) / 1024); | 1394 io_before.WriteTransferCount) / 1024); |
(...skipping 18 matching lines...) Expand all Loading... |
1415 DCHECK(thread_checker_.CalledOnValidThread()); | 1413 DCHECK(thread_checker_.CalledOnValidThread()); |
1416 | 1414 |
1417 safe_browsing::PrefixSetBuilder builder; | 1415 safe_browsing::PrefixSetBuilder builder; |
1418 std::vector<SBAddFullHash> add_full_hashes_result; | 1416 std::vector<SBAddFullHash> add_full_hashes_result; |
1419 | 1417 |
1420 if (!side_effect_free_whitelist_store_->FinishUpdate( | 1418 if (!side_effect_free_whitelist_store_->FinishUpdate( |
1421 &builder, &add_full_hashes_result)) { | 1419 &builder, &add_full_hashes_result)) { |
1422 RecordFailure(FAILURE_SIDE_EFFECT_FREE_WHITELIST_UPDATE_FINISH); | 1420 RecordFailure(FAILURE_SIDE_EFFECT_FREE_WHITELIST_UPDATE_FINISH); |
1423 return; | 1421 return; |
1424 } | 1422 } |
1425 scoped_ptr<safe_browsing::PrefixSet> | 1423 scoped_ptr<const safe_browsing::PrefixSet> new_prefix_set( |
1426 prefix_set(builder.GetPrefixSetNoHashes()); | 1424 builder.GetPrefixSetNoHashes()); |
1427 | 1425 |
1428 // Swap in the newly built prefix set. | 1426 // Swap in the newly built prefix set. |
1429 { | 1427 { |
1430 base::AutoLock locked(lookup_lock_); | 1428 base::AutoLock locked(lookup_lock_); |
1431 side_effect_free_whitelist_prefix_set_.swap(prefix_set); | 1429 side_effect_free_whitelist_prefix_set_.swap(new_prefix_set); |
1432 } | 1430 } |
1433 | 1431 |
1434 const base::FilePath side_effect_free_whitelist_filename = | 1432 const base::FilePath side_effect_free_whitelist_filename = |
1435 SideEffectFreeWhitelistDBFilename(filename_base_); | 1433 SideEffectFreeWhitelistDBFilename(filename_base_); |
1436 const base::FilePath side_effect_free_whitelist_prefix_set_filename = | 1434 const base::FilePath side_effect_free_whitelist_prefix_set_filename = |
1437 PrefixSetForFilename(side_effect_free_whitelist_filename); | 1435 PrefixSetForFilename(side_effect_free_whitelist_filename); |
1438 const base::TimeTicks before = base::TimeTicks::Now(); | 1436 const base::TimeTicks before = base::TimeTicks::Now(); |
1439 const bool write_ok = side_effect_free_whitelist_prefix_set_->WriteFile( | 1437 const bool write_ok = side_effect_free_whitelist_prefix_set_->WriteFile( |
1440 side_effect_free_whitelist_prefix_set_filename); | 1438 side_effect_free_whitelist_prefix_set_filename); |
1441 UMA_HISTOGRAM_TIMES("SB2.SideEffectFreePrefixSetWrite", | 1439 UMA_HISTOGRAM_TIMES("SB2.SideEffectFreePrefixSetWrite", |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1504 // only happen once. If you are here because you are hitting this after a | 1502 // only happen once. If you are here because you are hitting this after a |
1505 // restart, then I would be very interested in working with you to figure out | 1503 // restart, then I would be very interested in working with you to figure out |
1506 // what is happening, since it may affect real users. | 1504 // what is happening, since it may affect real users. |
1507 DLOG(FATAL) << "SafeBrowsing database was corrupt and reset"; | 1505 DLOG(FATAL) << "SafeBrowsing database was corrupt and reset"; |
1508 } | 1506 } |
1509 | 1507 |
1510 // TODO(shess): I'm not clear why this code doesn't have any | 1508 // TODO(shess): I'm not clear why this code doesn't have any |
1511 // real error-handling. | 1509 // real error-handling. |
1512 void SafeBrowsingDatabaseNew::LoadPrefixSet( | 1510 void SafeBrowsingDatabaseNew::LoadPrefixSet( |
1513 const base::FilePath& db_filename, | 1511 const base::FilePath& db_filename, |
1514 scoped_ptr<safe_browsing::PrefixSet>* prefix_set, | 1512 scoped_ptr<const safe_browsing::PrefixSet>* prefix_set, |
1515 FailureType read_failure_type) { | 1513 FailureType read_failure_type) { |
1516 DCHECK(thread_checker_.CalledOnValidThread()); | 1514 DCHECK(thread_checker_.CalledOnValidThread()); |
1517 | 1515 |
1518 if (!prefix_set) | 1516 if (!prefix_set) |
1519 return; | 1517 return; |
1520 | 1518 |
1521 DCHECK(!filename_base_.empty()); | 1519 DCHECK(!filename_base_.empty()); |
1522 | 1520 |
1523 const base::FilePath prefix_set_filename = PrefixSetForFilename(db_filename); | 1521 const base::FilePath prefix_set_filename = PrefixSetForFilename(db_filename); |
1524 | 1522 |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1615 const bool r11 = | 1613 const bool r11 = |
1616 base::DeleteFile(UnwantedSoftwareDBFilename(filename_base_), false); | 1614 base::DeleteFile(UnwantedSoftwareDBFilename(filename_base_), false); |
1617 if (!r11) | 1615 if (!r11) |
1618 RecordFailure(FAILURE_UNWANTED_SOFTWARE_PREFIX_SET_DELETE); | 1616 RecordFailure(FAILURE_UNWANTED_SOFTWARE_PREFIX_SET_DELETE); |
1619 | 1617 |
1620 return r1 && r2 && r3 && r4 && r5 && r6 && r7 && r8 && r9 && r10 && r11; | 1618 return r1 && r2 && r3 && r4 && r5 && r6 && r7 && r8 && r9 && r10 && r11; |
1621 } | 1619 } |
1622 | 1620 |
1623 void SafeBrowsingDatabaseNew::WritePrefixSet( | 1621 void SafeBrowsingDatabaseNew::WritePrefixSet( |
1624 const base::FilePath& db_filename, | 1622 const base::FilePath& db_filename, |
1625 safe_browsing::PrefixSet* prefix_set, | 1623 const safe_browsing::PrefixSet* prefix_set, |
1626 FailureType write_failure_type) { | 1624 FailureType write_failure_type) { |
1627 DCHECK(thread_checker_.CalledOnValidThread()); | 1625 DCHECK(thread_checker_.CalledOnValidThread()); |
1628 | 1626 |
1629 if (!prefix_set) | 1627 if (!prefix_set) |
1630 return; | 1628 return; |
1631 | 1629 |
1632 const base::FilePath prefix_set_filename = PrefixSetForFilename(db_filename); | 1630 const base::FilePath prefix_set_filename = PrefixSetForFilename(db_filename); |
1633 | 1631 |
1634 const base::TimeTicks before = base::TimeTicks::Now(); | 1632 const base::TimeTicks before = base::TimeTicks::Now(); |
1635 const bool write_ok = prefix_set->WriteFile(prefix_set_filename); | 1633 const bool write_ok = prefix_set->WriteFile(prefix_set_filename); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1736 return ContainsWhitelistedHashes(csd_whitelist_, full_hashes); | 1734 return ContainsWhitelistedHashes(csd_whitelist_, full_hashes); |
1737 } | 1735 } |
1738 | 1736 |
1739 bool SafeBrowsingDatabaseNew::IsCsdWhitelistKillSwitchOn() { | 1737 bool SafeBrowsingDatabaseNew::IsCsdWhitelistKillSwitchOn() { |
1740 // This method is theoretically thread-safe but document that it is currently | 1738 // This method is theoretically thread-safe but document that it is currently |
1741 // only expected to be called on the IO thread. | 1739 // only expected to be called on the IO thread. |
1742 DCHECK_CURRENTLY_ON(BrowserThread::IO); | 1740 DCHECK_CURRENTLY_ON(BrowserThread::IO); |
1743 | 1741 |
1744 return csd_whitelist_.second; | 1742 return csd_whitelist_.second; |
1745 } | 1743 } |
OLD | NEW |