| 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 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 415 return NULL; | 415 return NULL; |
| 416 } | 416 } |
| 417 | 417 |
| 418 // static | 418 // static |
| 419 void SafeBrowsingDatabase::RecordFailure(FailureType failure_type) { | 419 void SafeBrowsingDatabase::RecordFailure(FailureType failure_type) { |
| 420 UMA_HISTOGRAM_ENUMERATION("SB2.DatabaseFailure", failure_type, | 420 UMA_HISTOGRAM_ENUMERATION("SB2.DatabaseFailure", failure_type, |
| 421 FAILURE_DATABASE_MAX); | 421 FAILURE_DATABASE_MAX); |
| 422 } | 422 } |
| 423 | 423 |
| 424 SafeBrowsingDatabaseNew::SafeBrowsingDatabaseNew() | 424 SafeBrowsingDatabaseNew::SafeBrowsingDatabaseNew() |
| 425 : creation_loop_(MessageLoop::current()), | 425 : creation_loop_(base::MessageLoop::current()), |
| 426 browse_store_(new SafeBrowsingStoreFile), | 426 browse_store_(new SafeBrowsingStoreFile), |
| 427 download_store_(NULL), | 427 download_store_(NULL), |
| 428 csd_whitelist_store_(NULL), | 428 csd_whitelist_store_(NULL), |
| 429 download_whitelist_store_(NULL), | 429 download_whitelist_store_(NULL), |
| 430 ALLOW_THIS_IN_INITIALIZER_LIST(reset_factory_(this)), | 430 ALLOW_THIS_IN_INITIALIZER_LIST(reset_factory_(this)), |
| 431 corruption_detected_(false), | 431 corruption_detected_(false), |
| 432 change_detected_(false) { | 432 change_detected_(false) { |
| 433 DCHECK(browse_store_.get()); | 433 DCHECK(browse_store_.get()); |
| 434 DCHECK(!download_store_.get()); | 434 DCHECK(!download_store_.get()); |
| 435 DCHECK(!csd_whitelist_store_.get()); | 435 DCHECK(!csd_whitelist_store_.get()); |
| 436 DCHECK(!download_whitelist_store_.get()); | 436 DCHECK(!download_whitelist_store_.get()); |
| 437 DCHECK(!extension_blacklist_store_.get()); | 437 DCHECK(!extension_blacklist_store_.get()); |
| 438 } | 438 } |
| 439 | 439 |
| 440 SafeBrowsingDatabaseNew::SafeBrowsingDatabaseNew( | 440 SafeBrowsingDatabaseNew::SafeBrowsingDatabaseNew( |
| 441 SafeBrowsingStore* browse_store, | 441 SafeBrowsingStore* browse_store, |
| 442 SafeBrowsingStore* download_store, | 442 SafeBrowsingStore* download_store, |
| 443 SafeBrowsingStore* csd_whitelist_store, | 443 SafeBrowsingStore* csd_whitelist_store, |
| 444 SafeBrowsingStore* download_whitelist_store, | 444 SafeBrowsingStore* download_whitelist_store, |
| 445 SafeBrowsingStore* extension_blacklist_store) | 445 SafeBrowsingStore* extension_blacklist_store) |
| 446 : creation_loop_(MessageLoop::current()), | 446 : creation_loop_(base::MessageLoop::current()), |
| 447 browse_store_(browse_store), | 447 browse_store_(browse_store), |
| 448 download_store_(download_store), | 448 download_store_(download_store), |
| 449 csd_whitelist_store_(csd_whitelist_store), | 449 csd_whitelist_store_(csd_whitelist_store), |
| 450 download_whitelist_store_(download_whitelist_store), | 450 download_whitelist_store_(download_whitelist_store), |
| 451 extension_blacklist_store_(extension_blacklist_store), | 451 extension_blacklist_store_(extension_blacklist_store), |
| 452 ALLOW_THIS_IN_INITIALIZER_LIST(reset_factory_(this)), | 452 ALLOW_THIS_IN_INITIALIZER_LIST(reset_factory_(this)), |
| 453 corruption_detected_(false) { | 453 corruption_detected_(false) { |
| 454 DCHECK(browse_store_.get()); | 454 DCHECK(browse_store_.get()); |
| 455 } | 455 } |
| 456 | 456 |
| 457 SafeBrowsingDatabaseNew::~SafeBrowsingDatabaseNew() { | 457 SafeBrowsingDatabaseNew::~SafeBrowsingDatabaseNew() { |
| 458 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 458 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
| 459 } | 459 } |
| 460 | 460 |
| 461 void SafeBrowsingDatabaseNew::Init(const base::FilePath& filename_base) { | 461 void SafeBrowsingDatabaseNew::Init(const base::FilePath& filename_base) { |
| 462 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 462 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
| 463 // Ensure we haven't been run before. | 463 // Ensure we haven't been run before. |
| 464 DCHECK(browse_filename_.empty()); | 464 DCHECK(browse_filename_.empty()); |
| 465 DCHECK(download_filename_.empty()); | 465 DCHECK(download_filename_.empty()); |
| 466 DCHECK(csd_whitelist_filename_.empty()); | 466 DCHECK(csd_whitelist_filename_.empty()); |
| 467 DCHECK(download_whitelist_filename_.empty()); | 467 DCHECK(download_whitelist_filename_.empty()); |
| 468 DCHECK(extension_blacklist_filename_.empty()); | 468 DCHECK(extension_blacklist_filename_.empty()); |
| 469 | 469 |
| 470 browse_filename_ = BrowseDBFilename(filename_base); | 470 browse_filename_ = BrowseDBFilename(filename_base); |
| 471 prefix_set_filename_ = PrefixSetForFilename(browse_filename_); | 471 prefix_set_filename_ = PrefixSetForFilename(browse_filename_); |
| 472 | 472 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 536 extension_blacklist_store_->Init( | 536 extension_blacklist_store_->Init( |
| 537 extension_blacklist_filename_, | 537 extension_blacklist_filename_, |
| 538 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, | 538 base::Bind(&SafeBrowsingDatabaseNew::HandleCorruptDatabase, |
| 539 base::Unretained(this))); | 539 base::Unretained(this))); |
| 540 DVLOG(1) << "Init extension blacklist store: " | 540 DVLOG(1) << "Init extension blacklist store: " |
| 541 << extension_blacklist_filename_.value(); | 541 << extension_blacklist_filename_.value(); |
| 542 } | 542 } |
| 543 } | 543 } |
| 544 | 544 |
| 545 bool SafeBrowsingDatabaseNew::ResetDatabase() { | 545 bool SafeBrowsingDatabaseNew::ResetDatabase() { |
| 546 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 546 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
| 547 | 547 |
| 548 // Delete files on disk. | 548 // Delete files on disk. |
| 549 // TODO(shess): Hard to see where one might want to delete without a | 549 // TODO(shess): Hard to see where one might want to delete without a |
| 550 // reset. Perhaps inline |Delete()|? | 550 // reset. Perhaps inline |Delete()|? |
| 551 if (!Delete()) | 551 if (!Delete()) |
| 552 return false; | 552 return false; |
| 553 | 553 |
| 554 // Reset objects in memory. | 554 // Reset objects in memory. |
| 555 { | 555 { |
| 556 base::AutoLock locked(lookup_lock_); | 556 base::AutoLock locked(lookup_lock_); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 615 GetCachedFullHashesForBrowse(*prefix_hits, full_browse_hashes_, | 615 GetCachedFullHashesForBrowse(*prefix_hits, full_browse_hashes_, |
| 616 full_hits, last_update); | 616 full_hits, last_update); |
| 617 GetCachedFullHashesForBrowse(*prefix_hits, pending_browse_hashes_, | 617 GetCachedFullHashesForBrowse(*prefix_hits, pending_browse_hashes_, |
| 618 full_hits, last_update); | 618 full_hits, last_update); |
| 619 return true; | 619 return true; |
| 620 } | 620 } |
| 621 | 621 |
| 622 bool SafeBrowsingDatabaseNew::ContainsDownloadUrl( | 622 bool SafeBrowsingDatabaseNew::ContainsDownloadUrl( |
| 623 const std::vector<GURL>& urls, | 623 const std::vector<GURL>& urls, |
| 624 std::vector<SBPrefix>* prefix_hits) { | 624 std::vector<SBPrefix>* prefix_hits) { |
| 625 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 625 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
| 626 | 626 |
| 627 // Ignore this check when download checking is not enabled. | 627 // Ignore this check when download checking is not enabled. |
| 628 if (!download_store_.get()) | 628 if (!download_store_.get()) |
| 629 return false; | 629 return false; |
| 630 | 630 |
| 631 std::vector<SBPrefix> prefixes; | 631 std::vector<SBPrefix> prefixes; |
| 632 GetDownloadUrlPrefixes(urls, &prefixes); | 632 GetDownloadUrlPrefixes(urls, &prefixes); |
| 633 return MatchAddPrefixes(download_store_.get(), | 633 return MatchAddPrefixes(download_store_.get(), |
| 634 safe_browsing_util::BINURL % 2, | 634 safe_browsing_util::BINURL % 2, |
| 635 prefixes, | 635 prefixes, |
| 636 prefix_hits); | 636 prefix_hits); |
| 637 } | 637 } |
| 638 | 638 |
| 639 bool SafeBrowsingDatabaseNew::ContainsDownloadHashPrefix( | 639 bool SafeBrowsingDatabaseNew::ContainsDownloadHashPrefix( |
| 640 const SBPrefix& prefix) { | 640 const SBPrefix& prefix) { |
| 641 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 641 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
| 642 | 642 |
| 643 // Ignore this check when download store is not available. | 643 // Ignore this check when download store is not available. |
| 644 if (!download_store_.get()) | 644 if (!download_store_.get()) |
| 645 return false; | 645 return false; |
| 646 | 646 |
| 647 std::vector<SBPrefix> prefix_hits; | 647 std::vector<SBPrefix> prefix_hits; |
| 648 return MatchAddPrefixes(download_store_.get(), | 648 return MatchAddPrefixes(download_store_.get(), |
| 649 safe_browsing_util::BINHASH % 2, | 649 safe_browsing_util::BINHASH % 2, |
| 650 std::vector<SBPrefix>(1, prefix), | 650 std::vector<SBPrefix>(1, prefix), |
| 651 &prefix_hits); | 651 &prefix_hits); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 662 | 662 |
| 663 bool SafeBrowsingDatabaseNew::ContainsDownloadWhitelistedUrl(const GURL& url) { | 663 bool SafeBrowsingDatabaseNew::ContainsDownloadWhitelistedUrl(const GURL& url) { |
| 664 std::vector<SBFullHash> full_hashes; | 664 std::vector<SBFullHash> full_hashes; |
| 665 BrowseFullHashesToCheck(url, true, &full_hashes); | 665 BrowseFullHashesToCheck(url, true, &full_hashes); |
| 666 return ContainsWhitelistedHashes(download_whitelist_, full_hashes); | 666 return ContainsWhitelistedHashes(download_whitelist_, full_hashes); |
| 667 } | 667 } |
| 668 | 668 |
| 669 bool SafeBrowsingDatabaseNew::ContainsExtensionPrefixes( | 669 bool SafeBrowsingDatabaseNew::ContainsExtensionPrefixes( |
| 670 const std::vector<SBPrefix>& prefixes, | 670 const std::vector<SBPrefix>& prefixes, |
| 671 std::vector<SBPrefix>* prefix_hits) { | 671 std::vector<SBPrefix>* prefix_hits) { |
| 672 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 672 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
| 673 if (!extension_blacklist_store_) | 673 if (!extension_blacklist_store_) |
| 674 return false; | 674 return false; |
| 675 | 675 |
| 676 return MatchAddPrefixes(extension_blacklist_store_.get(), | 676 return MatchAddPrefixes(extension_blacklist_store_.get(), |
| 677 safe_browsing_util::EXTENSIONBLACKLIST % 2, | 677 safe_browsing_util::EXTENSIONBLACKLIST % 2, |
| 678 prefixes, | 678 prefixes, |
| 679 prefix_hits); | 679 prefix_hits); |
| 680 } | 680 } |
| 681 | 681 |
| 682 bool SafeBrowsingDatabaseNew::ContainsDownloadWhitelistedString( | 682 bool SafeBrowsingDatabaseNew::ContainsDownloadWhitelistedString( |
| (...skipping 16 matching lines...) Expand all Loading... |
| 699 if (std::binary_search(whitelist.first.begin(), whitelist.first.end(), *it)) | 699 if (std::binary_search(whitelist.first.begin(), whitelist.first.end(), *it)) |
| 700 return true; | 700 return true; |
| 701 } | 701 } |
| 702 return false; | 702 return false; |
| 703 } | 703 } |
| 704 | 704 |
| 705 // Helper to insert entries for all of the prefixes or full hashes in | 705 // Helper to insert entries for all of the prefixes or full hashes in |
| 706 // |entry| into the store. | 706 // |entry| into the store. |
| 707 void SafeBrowsingDatabaseNew::InsertAdd(int chunk_id, SBPrefix host, | 707 void SafeBrowsingDatabaseNew::InsertAdd(int chunk_id, SBPrefix host, |
| 708 const SBEntry* entry, int list_id) { | 708 const SBEntry* entry, int list_id) { |
| 709 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 709 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
| 710 | 710 |
| 711 SafeBrowsingStore* store = GetStore(list_id); | 711 SafeBrowsingStore* store = GetStore(list_id); |
| 712 if (!store) return; | 712 if (!store) return; |
| 713 | 713 |
| 714 STATS_COUNTER("SB.HostInsert", 1); | 714 STATS_COUNTER("SB.HostInsert", 1); |
| 715 const int encoded_chunk_id = EncodeChunkId(chunk_id, list_id); | 715 const int encoded_chunk_id = EncodeChunkId(chunk_id, list_id); |
| 716 const int count = entry->prefix_count(); | 716 const int count = entry->prefix_count(); |
| 717 | 717 |
| 718 DCHECK(!entry->IsSub()); | 718 DCHECK(!entry->IsSub()); |
| 719 if (!count) { | 719 if (!count) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 741 store->WriteAddHash(encoded_chunk_id, receive_time, full_hash); | 741 store->WriteAddHash(encoded_chunk_id, receive_time, full_hash); |
| 742 } | 742 } |
| 743 } | 743 } |
| 744 } | 744 } |
| 745 | 745 |
| 746 // Helper to iterate over all the entries in the hosts in |chunks| and | 746 // Helper to iterate over all the entries in the hosts in |chunks| and |
| 747 // add them to the store. | 747 // add them to the store. |
| 748 void SafeBrowsingDatabaseNew::InsertAddChunks( | 748 void SafeBrowsingDatabaseNew::InsertAddChunks( |
| 749 const safe_browsing_util::ListType list_id, | 749 const safe_browsing_util::ListType list_id, |
| 750 const SBChunkList& chunks) { | 750 const SBChunkList& chunks) { |
| 751 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 751 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
| 752 | 752 |
| 753 SafeBrowsingStore* store = GetStore(list_id); | 753 SafeBrowsingStore* store = GetStore(list_id); |
| 754 if (!store) return; | 754 if (!store) return; |
| 755 | 755 |
| 756 for (SBChunkList::const_iterator citer = chunks.begin(); | 756 for (SBChunkList::const_iterator citer = chunks.begin(); |
| 757 citer != chunks.end(); ++citer) { | 757 citer != chunks.end(); ++citer) { |
| 758 const int chunk_id = citer->chunk_number; | 758 const int chunk_id = citer->chunk_number; |
| 759 | 759 |
| 760 // The server can give us a chunk that we already have because | 760 // The server can give us a chunk that we already have because |
| 761 // it's part of a range. Don't add it again. | 761 // it's part of a range. Don't add it again. |
| 762 const int encoded_chunk_id = EncodeChunkId(chunk_id, list_id); | 762 const int encoded_chunk_id = EncodeChunkId(chunk_id, list_id); |
| 763 if (store->CheckAddChunk(encoded_chunk_id)) | 763 if (store->CheckAddChunk(encoded_chunk_id)) |
| 764 continue; | 764 continue; |
| 765 | 765 |
| 766 store->SetAddChunk(encoded_chunk_id); | 766 store->SetAddChunk(encoded_chunk_id); |
| 767 for (std::deque<SBChunkHost>::const_iterator hiter = citer->hosts.begin(); | 767 for (std::deque<SBChunkHost>::const_iterator hiter = citer->hosts.begin(); |
| 768 hiter != citer->hosts.end(); ++hiter) { | 768 hiter != citer->hosts.end(); ++hiter) { |
| 769 // NOTE: Could pass |encoded_chunk_id|, but then inserting add | 769 // NOTE: Could pass |encoded_chunk_id|, but then inserting add |
| 770 // chunks would look different from inserting sub chunks. | 770 // chunks would look different from inserting sub chunks. |
| 771 InsertAdd(chunk_id, hiter->host, hiter->entry, list_id); | 771 InsertAdd(chunk_id, hiter->host, hiter->entry, list_id); |
| 772 } | 772 } |
| 773 } | 773 } |
| 774 } | 774 } |
| 775 | 775 |
| 776 // Helper to insert entries for all of the prefixes or full hashes in | 776 // Helper to insert entries for all of the prefixes or full hashes in |
| 777 // |entry| into the store. | 777 // |entry| into the store. |
| 778 void SafeBrowsingDatabaseNew::InsertSub(int chunk_id, SBPrefix host, | 778 void SafeBrowsingDatabaseNew::InsertSub(int chunk_id, SBPrefix host, |
| 779 const SBEntry* entry, int list_id) { | 779 const SBEntry* entry, int list_id) { |
| 780 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 780 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
| 781 | 781 |
| 782 SafeBrowsingStore* store = GetStore(list_id); | 782 SafeBrowsingStore* store = GetStore(list_id); |
| 783 if (!store) return; | 783 if (!store) return; |
| 784 | 784 |
| 785 STATS_COUNTER("SB.HostDelete", 1); | 785 STATS_COUNTER("SB.HostDelete", 1); |
| 786 const int encoded_chunk_id = EncodeChunkId(chunk_id, list_id); | 786 const int encoded_chunk_id = EncodeChunkId(chunk_id, list_id); |
| 787 const int count = entry->prefix_count(); | 787 const int count = entry->prefix_count(); |
| 788 | 788 |
| 789 DCHECK(entry->IsSub()); | 789 DCHECK(entry->IsSub()); |
| 790 if (!count) { | 790 if (!count) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 816 store->WriteSubHash(encoded_chunk_id, add_chunk_id, full_hash); | 816 store->WriteSubHash(encoded_chunk_id, add_chunk_id, full_hash); |
| 817 } | 817 } |
| 818 } | 818 } |
| 819 } | 819 } |
| 820 | 820 |
| 821 // Helper to iterate over all the entries in the hosts in |chunks| and | 821 // Helper to iterate over all the entries in the hosts in |chunks| and |
| 822 // add them to the store. | 822 // add them to the store. |
| 823 void SafeBrowsingDatabaseNew::InsertSubChunks( | 823 void SafeBrowsingDatabaseNew::InsertSubChunks( |
| 824 safe_browsing_util::ListType list_id, | 824 safe_browsing_util::ListType list_id, |
| 825 const SBChunkList& chunks) { | 825 const SBChunkList& chunks) { |
| 826 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 826 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
| 827 | 827 |
| 828 SafeBrowsingStore* store = GetStore(list_id); | 828 SafeBrowsingStore* store = GetStore(list_id); |
| 829 if (!store) return; | 829 if (!store) return; |
| 830 | 830 |
| 831 for (SBChunkList::const_iterator citer = chunks.begin(); | 831 for (SBChunkList::const_iterator citer = chunks.begin(); |
| 832 citer != chunks.end(); ++citer) { | 832 citer != chunks.end(); ++citer) { |
| 833 const int chunk_id = citer->chunk_number; | 833 const int chunk_id = citer->chunk_number; |
| 834 | 834 |
| 835 // The server can give us a chunk that we already have because | 835 // The server can give us a chunk that we already have because |
| 836 // it's part of a range. Don't add it again. | 836 // it's part of a range. Don't add it again. |
| 837 const int encoded_chunk_id = EncodeChunkId(chunk_id, list_id); | 837 const int encoded_chunk_id = EncodeChunkId(chunk_id, list_id); |
| 838 if (store->CheckSubChunk(encoded_chunk_id)) | 838 if (store->CheckSubChunk(encoded_chunk_id)) |
| 839 continue; | 839 continue; |
| 840 | 840 |
| 841 store->SetSubChunk(encoded_chunk_id); | 841 store->SetSubChunk(encoded_chunk_id); |
| 842 for (std::deque<SBChunkHost>::const_iterator hiter = citer->hosts.begin(); | 842 for (std::deque<SBChunkHost>::const_iterator hiter = citer->hosts.begin(); |
| 843 hiter != citer->hosts.end(); ++hiter) { | 843 hiter != citer->hosts.end(); ++hiter) { |
| 844 InsertSub(chunk_id, hiter->host, hiter->entry, list_id); | 844 InsertSub(chunk_id, hiter->host, hiter->entry, list_id); |
| 845 } | 845 } |
| 846 } | 846 } |
| 847 } | 847 } |
| 848 | 848 |
| 849 void SafeBrowsingDatabaseNew::InsertChunks(const std::string& list_name, | 849 void SafeBrowsingDatabaseNew::InsertChunks(const std::string& list_name, |
| 850 const SBChunkList& chunks) { | 850 const SBChunkList& chunks) { |
| 851 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 851 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
| 852 | 852 |
| 853 if (corruption_detected_ || chunks.empty()) | 853 if (corruption_detected_ || chunks.empty()) |
| 854 return; | 854 return; |
| 855 | 855 |
| 856 const base::TimeTicks before = base::TimeTicks::Now(); | 856 const base::TimeTicks before = base::TimeTicks::Now(); |
| 857 | 857 |
| 858 const safe_browsing_util::ListType list_id = | 858 const safe_browsing_util::ListType list_id = |
| 859 safe_browsing_util::GetListId(list_name); | 859 safe_browsing_util::GetListId(list_name); |
| 860 DVLOG(2) << list_name << ": " << list_id; | 860 DVLOG(2) << list_name << ": " << list_id; |
| 861 | 861 |
| 862 SafeBrowsingStore* store = GetStore(list_id); | 862 SafeBrowsingStore* store = GetStore(list_id); |
| 863 if (!store) return; | 863 if (!store) return; |
| 864 | 864 |
| 865 change_detected_ = true; | 865 change_detected_ = true; |
| 866 | 866 |
| 867 store->BeginChunk(); | 867 store->BeginChunk(); |
| 868 if (chunks.front().is_add) { | 868 if (chunks.front().is_add) { |
| 869 InsertAddChunks(list_id, chunks); | 869 InsertAddChunks(list_id, chunks); |
| 870 } else { | 870 } else { |
| 871 InsertSubChunks(list_id, chunks); | 871 InsertSubChunks(list_id, chunks); |
| 872 } | 872 } |
| 873 store->FinishChunk(); | 873 store->FinishChunk(); |
| 874 | 874 |
| 875 UMA_HISTOGRAM_TIMES("SB2.ChunkInsert", base::TimeTicks::Now() - before); | 875 UMA_HISTOGRAM_TIMES("SB2.ChunkInsert", base::TimeTicks::Now() - before); |
| 876 } | 876 } |
| 877 | 877 |
| 878 void SafeBrowsingDatabaseNew::DeleteChunks( | 878 void SafeBrowsingDatabaseNew::DeleteChunks( |
| 879 const std::vector<SBChunkDelete>& chunk_deletes) { | 879 const std::vector<SBChunkDelete>& chunk_deletes) { |
| 880 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 880 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
| 881 | 881 |
| 882 if (corruption_detected_ || chunk_deletes.empty()) | 882 if (corruption_detected_ || chunk_deletes.empty()) |
| 883 return; | 883 return; |
| 884 | 884 |
| 885 const std::string& list_name = chunk_deletes.front().list_name; | 885 const std::string& list_name = chunk_deletes.front().list_name; |
| 886 const safe_browsing_util::ListType list_id = | 886 const safe_browsing_util::ListType list_id = |
| 887 safe_browsing_util::GetListId(list_name); | 887 safe_browsing_util::GetListId(list_name); |
| 888 | 888 |
| 889 SafeBrowsingStore* store = GetStore(list_id); | 889 SafeBrowsingStore* store = GetStore(list_id); |
| 890 if (!store) return; | 890 if (!store) return; |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 934 std::vector<SBAddFullHash>::iterator | 934 std::vector<SBAddFullHash>::iterator |
| 935 orig_end = pending_browse_hashes_.begin() + orig_size; | 935 orig_end = pending_browse_hashes_.begin() + orig_size; |
| 936 std::sort(orig_end, pending_browse_hashes_.end(), SBAddFullHashPrefixLess); | 936 std::sort(orig_end, pending_browse_hashes_.end(), SBAddFullHashPrefixLess); |
| 937 std::inplace_merge(pending_browse_hashes_.begin(), | 937 std::inplace_merge(pending_browse_hashes_.begin(), |
| 938 orig_end, pending_browse_hashes_.end(), | 938 orig_end, pending_browse_hashes_.end(), |
| 939 SBAddFullHashPrefixLess); | 939 SBAddFullHashPrefixLess); |
| 940 } | 940 } |
| 941 | 941 |
| 942 bool SafeBrowsingDatabaseNew::UpdateStarted( | 942 bool SafeBrowsingDatabaseNew::UpdateStarted( |
| 943 std::vector<SBListChunkRanges>* lists) { | 943 std::vector<SBListChunkRanges>* lists) { |
| 944 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 944 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
| 945 DCHECK(lists); | 945 DCHECK(lists); |
| 946 | 946 |
| 947 // If |BeginUpdate()| fails, reset the database. | 947 // If |BeginUpdate()| fails, reset the database. |
| 948 if (!browse_store_->BeginUpdate()) { | 948 if (!browse_store_->BeginUpdate()) { |
| 949 RecordFailure(FAILURE_BROWSE_DATABASE_UPDATE_BEGIN); | 949 RecordFailure(FAILURE_BROWSE_DATABASE_UPDATE_BEGIN); |
| 950 HandleCorruptDatabase(); | 950 HandleCorruptDatabase(); |
| 951 return false; | 951 return false; |
| 952 } | 952 } |
| 953 | 953 |
| 954 if (download_store_.get() && !download_store_->BeginUpdate()) { | 954 if (download_store_.get() && !download_store_->BeginUpdate()) { |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1031 std::vector<std::string>(1, safe_browsing_util::kExtensionBlacklist), | 1031 std::vector<std::string>(1, safe_browsing_util::kExtensionBlacklist), |
| 1032 lists); | 1032 lists); |
| 1033 } | 1033 } |
| 1034 | 1034 |
| 1035 corruption_detected_ = false; | 1035 corruption_detected_ = false; |
| 1036 change_detected_ = false; | 1036 change_detected_ = false; |
| 1037 return true; | 1037 return true; |
| 1038 } | 1038 } |
| 1039 | 1039 |
| 1040 void SafeBrowsingDatabaseNew::UpdateFinished(bool update_succeeded) { | 1040 void SafeBrowsingDatabaseNew::UpdateFinished(bool update_succeeded) { |
| 1041 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 1041 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
| 1042 | 1042 |
| 1043 // The update may have failed due to corrupt storage (for instance, | 1043 // The update may have failed due to corrupt storage (for instance, |
| 1044 // an excessive number of invalid add_chunks and sub_chunks). | 1044 // an excessive number of invalid add_chunks and sub_chunks). |
| 1045 // Double-check that the databases are valid. | 1045 // Double-check that the databases are valid. |
| 1046 // TODO(shess): Providing a checksum for the add_chunk and sub_chunk | 1046 // TODO(shess): Providing a checksum for the add_chunk and sub_chunk |
| 1047 // sections would allow throwing a corruption error in | 1047 // sections would allow throwing a corruption error in |
| 1048 // UpdateStarted(). | 1048 // UpdateStarted(). |
| 1049 if (!update_succeeded) { | 1049 if (!update_succeeded) { |
| 1050 if (!browse_store_->CheckValidity()) | 1050 if (!browse_store_->CheckValidity()) |
| 1051 DLOG(ERROR) << "Safe-browsing browse database corrupt."; | 1051 DLOG(ERROR) << "Safe-browsing browse database corrupt."; |
| (...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1284 #if defined(OS_MACOSX) | 1284 #if defined(OS_MACOSX) |
| 1285 base::mac::SetFileBackupExclusion(browse_filename_); | 1285 base::mac::SetFileBackupExclusion(browse_filename_); |
| 1286 #endif | 1286 #endif |
| 1287 } | 1287 } |
| 1288 | 1288 |
| 1289 void SafeBrowsingDatabaseNew::HandleCorruptDatabase() { | 1289 void SafeBrowsingDatabaseNew::HandleCorruptDatabase() { |
| 1290 // Reset the database after the current task has unwound (but only | 1290 // Reset the database after the current task has unwound (but only |
| 1291 // reset once within the scope of a given task). | 1291 // reset once within the scope of a given task). |
| 1292 if (!reset_factory_.HasWeakPtrs()) { | 1292 if (!reset_factory_.HasWeakPtrs()) { |
| 1293 RecordFailure(FAILURE_DATABASE_CORRUPT); | 1293 RecordFailure(FAILURE_DATABASE_CORRUPT); |
| 1294 MessageLoop::current()->PostTask(FROM_HERE, | 1294 base::MessageLoop::current()->PostTask( |
| 1295 FROM_HERE, |
| 1295 base::Bind(&SafeBrowsingDatabaseNew::OnHandleCorruptDatabase, | 1296 base::Bind(&SafeBrowsingDatabaseNew::OnHandleCorruptDatabase, |
| 1296 reset_factory_.GetWeakPtr())); | 1297 reset_factory_.GetWeakPtr())); |
| 1297 } | 1298 } |
| 1298 } | 1299 } |
| 1299 | 1300 |
| 1300 void SafeBrowsingDatabaseNew::OnHandleCorruptDatabase() { | 1301 void SafeBrowsingDatabaseNew::OnHandleCorruptDatabase() { |
| 1301 RecordFailure(FAILURE_DATABASE_CORRUPT_HANDLER); | 1302 RecordFailure(FAILURE_DATABASE_CORRUPT_HANDLER); |
| 1302 corruption_detected_ = true; // Stop updating the database. | 1303 corruption_detected_ = true; // Stop updating the database. |
| 1303 ResetDatabase(); | 1304 ResetDatabase(); |
| 1304 DLOG(FATAL) << "SafeBrowsing database was corrupt and reset"; | 1305 DLOG(FATAL) << "SafeBrowsing database was corrupt and reset"; |
| 1305 } | 1306 } |
| 1306 | 1307 |
| 1307 // TODO(shess): I'm not clear why this code doesn't have any | 1308 // TODO(shess): I'm not clear why this code doesn't have any |
| 1308 // real error-handling. | 1309 // real error-handling. |
| 1309 void SafeBrowsingDatabaseNew::LoadPrefixSet() { | 1310 void SafeBrowsingDatabaseNew::LoadPrefixSet() { |
| 1310 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 1311 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
| 1311 DCHECK(!prefix_set_filename_.empty()); | 1312 DCHECK(!prefix_set_filename_.empty()); |
| 1312 | 1313 |
| 1313 // If there is no database, the filter cannot be used. | 1314 // If there is no database, the filter cannot be used. |
| 1314 base::PlatformFileInfo db_info; | 1315 base::PlatformFileInfo db_info; |
| 1315 if (!file_util::GetFileInfo(browse_filename_, &db_info) || db_info.size == 0) | 1316 if (!file_util::GetFileInfo(browse_filename_, &db_info) || db_info.size == 0) |
| 1316 return; | 1317 return; |
| 1317 | 1318 |
| 1318 // Cleanup any stale bloom filter (no longer used). | 1319 // Cleanup any stale bloom filter (no longer used). |
| 1319 // TODO(shess): Track failure to delete? | 1320 // TODO(shess): Track failure to delete? |
| 1320 base::FilePath bloom_filter_filename = | 1321 base::FilePath bloom_filter_filename = |
| 1321 BloomFilterForFilename(browse_filename_); | 1322 BloomFilterForFilename(browse_filename_); |
| 1322 file_util::Delete(bloom_filter_filename, false); | 1323 file_util::Delete(bloom_filter_filename, false); |
| 1323 | 1324 |
| 1324 const base::TimeTicks before = base::TimeTicks::Now(); | 1325 const base::TimeTicks before = base::TimeTicks::Now(); |
| 1325 prefix_set_.reset(safe_browsing::PrefixSet::LoadFile(prefix_set_filename_)); | 1326 prefix_set_.reset(safe_browsing::PrefixSet::LoadFile(prefix_set_filename_)); |
| 1326 DVLOG(1) << "SafeBrowsingDatabaseNew read prefix set in " | 1327 DVLOG(1) << "SafeBrowsingDatabaseNew read prefix set in " |
| 1327 << (base::TimeTicks::Now() - before).InMilliseconds() << " ms"; | 1328 << (base::TimeTicks::Now() - before).InMilliseconds() << " ms"; |
| 1328 UMA_HISTOGRAM_TIMES("SB2.PrefixSetLoad", base::TimeTicks::Now() - before); | 1329 UMA_HISTOGRAM_TIMES("SB2.PrefixSetLoad", base::TimeTicks::Now() - before); |
| 1329 | 1330 |
| 1330 if (!prefix_set_.get()) | 1331 if (!prefix_set_.get()) |
| 1331 RecordFailure(FAILURE_DATABASE_PREFIX_SET_READ); | 1332 RecordFailure(FAILURE_DATABASE_PREFIX_SET_READ); |
| 1332 } | 1333 } |
| 1333 | 1334 |
| 1334 bool SafeBrowsingDatabaseNew::Delete() { | 1335 bool SafeBrowsingDatabaseNew::Delete() { |
| 1335 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 1336 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
| 1336 | 1337 |
| 1337 const bool r1 = browse_store_->Delete(); | 1338 const bool r1 = browse_store_->Delete(); |
| 1338 if (!r1) | 1339 if (!r1) |
| 1339 RecordFailure(FAILURE_DATABASE_STORE_DELETE); | 1340 RecordFailure(FAILURE_DATABASE_STORE_DELETE); |
| 1340 | 1341 |
| 1341 const bool r2 = download_store_.get() ? download_store_->Delete() : true; | 1342 const bool r2 = download_store_.get() ? download_store_->Delete() : true; |
| 1342 if (!r2) | 1343 if (!r2) |
| 1343 RecordFailure(FAILURE_DATABASE_STORE_DELETE); | 1344 RecordFailure(FAILURE_DATABASE_STORE_DELETE); |
| 1344 | 1345 |
| 1345 const bool r3 = csd_whitelist_store_.get() ? | 1346 const bool r3 = csd_whitelist_store_.get() ? |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1363 RecordFailure(FAILURE_DATABASE_PREFIX_SET_DELETE); | 1364 RecordFailure(FAILURE_DATABASE_PREFIX_SET_DELETE); |
| 1364 | 1365 |
| 1365 const bool r7 = file_util::Delete(extension_blacklist_filename_, false); | 1366 const bool r7 = file_util::Delete(extension_blacklist_filename_, false); |
| 1366 if (!r7) | 1367 if (!r7) |
| 1367 RecordFailure(FAILURE_EXTENSION_BLACKLIST_DELETE); | 1368 RecordFailure(FAILURE_EXTENSION_BLACKLIST_DELETE); |
| 1368 | 1369 |
| 1369 return r1 && r2 && r3 && r4 && r5 && r6 && r7; | 1370 return r1 && r2 && r3 && r4 && r5 && r6 && r7; |
| 1370 } | 1371 } |
| 1371 | 1372 |
| 1372 void SafeBrowsingDatabaseNew::WritePrefixSet() { | 1373 void SafeBrowsingDatabaseNew::WritePrefixSet() { |
| 1373 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 1374 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
| 1374 | 1375 |
| 1375 if (!prefix_set_.get()) | 1376 if (!prefix_set_.get()) |
| 1376 return; | 1377 return; |
| 1377 | 1378 |
| 1378 const base::TimeTicks before = base::TimeTicks::Now(); | 1379 const base::TimeTicks before = base::TimeTicks::Now(); |
| 1379 const bool write_ok = prefix_set_->WriteFile(prefix_set_filename_); | 1380 const bool write_ok = prefix_set_->WriteFile(prefix_set_filename_); |
| 1380 DVLOG(1) << "SafeBrowsingDatabaseNew wrote prefix set in " | 1381 DVLOG(1) << "SafeBrowsingDatabaseNew wrote prefix set in " |
| 1381 << (base::TimeTicks::Now() - before).InMilliseconds() << " ms"; | 1382 << (base::TimeTicks::Now() - before).InMilliseconds() << " ms"; |
| 1382 UMA_HISTOGRAM_TIMES("SB2.PrefixSetWrite", base::TimeTicks::Now() - before); | 1383 UMA_HISTOGRAM_TIMES("SB2.PrefixSetWrite", base::TimeTicks::Now() - before); |
| 1383 | 1384 |
| 1384 if (!write_ok) | 1385 if (!write_ok) |
| 1385 RecordFailure(FAILURE_DATABASE_PREFIX_SET_WRITE); | 1386 RecordFailure(FAILURE_DATABASE_PREFIX_SET_WRITE); |
| 1386 | 1387 |
| 1387 #if defined(OS_MACOSX) | 1388 #if defined(OS_MACOSX) |
| 1388 base::mac::SetFileBackupExclusion(prefix_set_filename_); | 1389 base::mac::SetFileBackupExclusion(prefix_set_filename_); |
| 1389 #endif | 1390 #endif |
| 1390 } | 1391 } |
| 1391 | 1392 |
| 1392 void SafeBrowsingDatabaseNew::WhitelistEverything(SBWhitelist* whitelist) { | 1393 void SafeBrowsingDatabaseNew::WhitelistEverything(SBWhitelist* whitelist) { |
| 1393 base::AutoLock locked(lookup_lock_); | 1394 base::AutoLock locked(lookup_lock_); |
| 1394 whitelist->second = true; | 1395 whitelist->second = true; |
| 1395 whitelist->first.clear(); | 1396 whitelist->first.clear(); |
| 1396 } | 1397 } |
| 1397 | 1398 |
| 1398 void SafeBrowsingDatabaseNew::LoadWhitelist( | 1399 void SafeBrowsingDatabaseNew::LoadWhitelist( |
| 1399 const std::vector<SBAddFullHash>& full_hashes, | 1400 const std::vector<SBAddFullHash>& full_hashes, |
| 1400 SBWhitelist* whitelist) { | 1401 SBWhitelist* whitelist) { |
| 1401 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 1402 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
| 1402 if (full_hashes.size() > kMaxWhitelistSize) { | 1403 if (full_hashes.size() > kMaxWhitelistSize) { |
| 1403 WhitelistEverything(whitelist); | 1404 WhitelistEverything(whitelist); |
| 1404 return; | 1405 return; |
| 1405 } | 1406 } |
| 1406 | 1407 |
| 1407 std::vector<SBFullHash> new_whitelist; | 1408 std::vector<SBFullHash> new_whitelist; |
| 1408 new_whitelist.reserve(full_hashes.size()); | 1409 new_whitelist.reserve(full_hashes.size()); |
| 1409 for (std::vector<SBAddFullHash>::const_iterator it = full_hashes.begin(); | 1410 for (std::vector<SBAddFullHash>::const_iterator it = full_hashes.begin(); |
| 1410 it != full_hashes.end(); ++it) { | 1411 it != full_hashes.end(); ++it) { |
| 1411 new_whitelist.push_back(it->full_hash); | 1412 new_whitelist.push_back(it->full_hash); |
| 1412 } | 1413 } |
| 1413 std::sort(new_whitelist.begin(), new_whitelist.end()); | 1414 std::sort(new_whitelist.begin(), new_whitelist.end()); |
| 1414 | 1415 |
| 1415 SBFullHash kill_switch; | 1416 SBFullHash kill_switch; |
| 1416 crypto::SHA256HashString(kWhitelistKillSwitchUrl, &kill_switch, | 1417 crypto::SHA256HashString(kWhitelistKillSwitchUrl, &kill_switch, |
| 1417 sizeof(kill_switch)); | 1418 sizeof(kill_switch)); |
| 1418 if (std::binary_search(new_whitelist.begin(), new_whitelist.end(), | 1419 if (std::binary_search(new_whitelist.begin(), new_whitelist.end(), |
| 1419 kill_switch)) { | 1420 kill_switch)) { |
| 1420 // The kill switch is whitelisted hence we whitelist all URLs. | 1421 // The kill switch is whitelisted hence we whitelist all URLs. |
| 1421 WhitelistEverything(whitelist); | 1422 WhitelistEverything(whitelist); |
| 1422 } else { | 1423 } else { |
| 1423 base::AutoLock locked(lookup_lock_); | 1424 base::AutoLock locked(lookup_lock_); |
| 1424 whitelist->second = false; | 1425 whitelist->second = false; |
| 1425 whitelist->first.swap(new_whitelist); | 1426 whitelist->first.swap(new_whitelist); |
| 1426 } | 1427 } |
| 1427 } | 1428 } |
| OLD | NEW |