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 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
431 return NULL; | 431 return NULL; |
432 } | 432 } |
433 | 433 |
434 // static | 434 // static |
435 void SafeBrowsingDatabase::RecordFailure(FailureType failure_type) { | 435 void SafeBrowsingDatabase::RecordFailure(FailureType failure_type) { |
436 UMA_HISTOGRAM_ENUMERATION("SB2.DatabaseFailure", failure_type, | 436 UMA_HISTOGRAM_ENUMERATION("SB2.DatabaseFailure", failure_type, |
437 FAILURE_DATABASE_MAX); | 437 FAILURE_DATABASE_MAX); |
438 } | 438 } |
439 | 439 |
440 SafeBrowsingDatabaseNew::SafeBrowsingDatabaseNew() | 440 SafeBrowsingDatabaseNew::SafeBrowsingDatabaseNew() |
441 : creation_loop_(MessageLoop::current()), | 441 : creation_loop_(base::MessageLoop::current()), |
442 browse_store_(new SafeBrowsingStoreFile), | 442 browse_store_(new SafeBrowsingStoreFile), |
443 download_store_(NULL), | 443 download_store_(NULL), |
444 csd_whitelist_store_(NULL), | 444 csd_whitelist_store_(NULL), |
445 download_whitelist_store_(NULL), | 445 download_whitelist_store_(NULL), |
446 reset_factory_(this), | 446 reset_factory_(this), |
447 corruption_detected_(false), | 447 corruption_detected_(false), |
448 change_detected_(false) { | 448 change_detected_(false) { |
449 DCHECK(browse_store_.get()); | 449 DCHECK(browse_store_.get()); |
450 DCHECK(!download_store_.get()); | 450 DCHECK(!download_store_.get()); |
451 DCHECK(!csd_whitelist_store_.get()); | 451 DCHECK(!csd_whitelist_store_.get()); |
452 DCHECK(!download_whitelist_store_.get()); | 452 DCHECK(!download_whitelist_store_.get()); |
453 DCHECK(!extension_blacklist_store_.get()); | 453 DCHECK(!extension_blacklist_store_.get()); |
454 DCHECK(!side_effect_free_whitelist_store_.get()); | 454 DCHECK(!side_effect_free_whitelist_store_.get()); |
455 } | 455 } |
456 | 456 |
457 SafeBrowsingDatabaseNew::SafeBrowsingDatabaseNew( | 457 SafeBrowsingDatabaseNew::SafeBrowsingDatabaseNew( |
458 SafeBrowsingStore* browse_store, | 458 SafeBrowsingStore* browse_store, |
459 SafeBrowsingStore* download_store, | 459 SafeBrowsingStore* download_store, |
460 SafeBrowsingStore* csd_whitelist_store, | 460 SafeBrowsingStore* csd_whitelist_store, |
461 SafeBrowsingStore* download_whitelist_store, | 461 SafeBrowsingStore* download_whitelist_store, |
462 SafeBrowsingStore* extension_blacklist_store, | 462 SafeBrowsingStore* extension_blacklist_store, |
463 SafeBrowsingStore* side_effect_free_whitelist_store) | 463 SafeBrowsingStore* side_effect_free_whitelist_store) |
464 : creation_loop_(MessageLoop::current()), | 464 : creation_loop_(base::MessageLoop::current()), |
465 browse_store_(browse_store), | 465 browse_store_(browse_store), |
466 download_store_(download_store), | 466 download_store_(download_store), |
467 csd_whitelist_store_(csd_whitelist_store), | 467 csd_whitelist_store_(csd_whitelist_store), |
468 download_whitelist_store_(download_whitelist_store), | 468 download_whitelist_store_(download_whitelist_store), |
469 extension_blacklist_store_(extension_blacklist_store), | 469 extension_blacklist_store_(extension_blacklist_store), |
470 side_effect_free_whitelist_store_(side_effect_free_whitelist_store), | 470 side_effect_free_whitelist_store_(side_effect_free_whitelist_store), |
471 reset_factory_(this), | 471 reset_factory_(this), |
472 corruption_detected_(false) { | 472 corruption_detected_(false) { |
473 DCHECK(browse_store_.get()); | 473 DCHECK(browse_store_.get()); |
474 } | 474 } |
475 | 475 |
476 SafeBrowsingDatabaseNew::~SafeBrowsingDatabaseNew() { | 476 SafeBrowsingDatabaseNew::~SafeBrowsingDatabaseNew() { |
477 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 477 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
478 } | 478 } |
479 | 479 |
480 void SafeBrowsingDatabaseNew::Init(const base::FilePath& filename_base) { | 480 void SafeBrowsingDatabaseNew::Init(const base::FilePath& filename_base) { |
481 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 481 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
482 // Ensure we haven't been run before. | 482 // Ensure we haven't been run before. |
483 DCHECK(browse_filename_.empty()); | 483 DCHECK(browse_filename_.empty()); |
484 DCHECK(download_filename_.empty()); | 484 DCHECK(download_filename_.empty()); |
485 DCHECK(csd_whitelist_filename_.empty()); | 485 DCHECK(csd_whitelist_filename_.empty()); |
486 DCHECK(download_whitelist_filename_.empty()); | 486 DCHECK(download_whitelist_filename_.empty()); |
487 DCHECK(extension_blacklist_filename_.empty()); | 487 DCHECK(extension_blacklist_filename_.empty()); |
488 DCHECK(side_effect_free_whitelist_filename_.empty()); | 488 DCHECK(side_effect_free_whitelist_filename_.empty()); |
489 | 489 |
490 browse_filename_ = BrowseDBFilename(filename_base); | 490 browse_filename_ = BrowseDBFilename(filename_base); |
491 browse_prefix_set_filename_ = PrefixSetForFilename(browse_filename_); | 491 browse_prefix_set_filename_ = PrefixSetForFilename(browse_filename_); |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
591 } | 591 } |
592 } else { | 592 } else { |
593 // Delete any files of the side-effect free sidelist that may be around | 593 // Delete any files of the side-effect free sidelist that may be around |
594 // from when it was previously enabled. | 594 // from when it was previously enabled. |
595 SafeBrowsingStoreFile::DeleteStore( | 595 SafeBrowsingStoreFile::DeleteStore( |
596 SideEffectFreeWhitelistDBFilename(filename_base)); | 596 SideEffectFreeWhitelistDBFilename(filename_base)); |
597 } | 597 } |
598 } | 598 } |
599 | 599 |
600 bool SafeBrowsingDatabaseNew::ResetDatabase() { | 600 bool SafeBrowsingDatabaseNew::ResetDatabase() { |
601 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 601 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
602 | 602 |
603 // Delete files on disk. | 603 // Delete files on disk. |
604 // TODO(shess): Hard to see where one might want to delete without a | 604 // TODO(shess): Hard to see where one might want to delete without a |
605 // reset. Perhaps inline |Delete()|? | 605 // reset. Perhaps inline |Delete()|? |
606 if (!Delete()) | 606 if (!Delete()) |
607 return false; | 607 return false; |
608 | 608 |
609 // Reset objects in memory. | 609 // Reset objects in memory. |
610 { | 610 { |
611 base::AutoLock locked(lookup_lock_); | 611 base::AutoLock locked(lookup_lock_); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
671 GetCachedFullHashesForBrowse(*prefix_hits, full_browse_hashes_, | 671 GetCachedFullHashesForBrowse(*prefix_hits, full_browse_hashes_, |
672 full_hits, last_update); | 672 full_hits, last_update); |
673 GetCachedFullHashesForBrowse(*prefix_hits, pending_browse_hashes_, | 673 GetCachedFullHashesForBrowse(*prefix_hits, pending_browse_hashes_, |
674 full_hits, last_update); | 674 full_hits, last_update); |
675 return true; | 675 return true; |
676 } | 676 } |
677 | 677 |
678 bool SafeBrowsingDatabaseNew::ContainsDownloadUrl( | 678 bool SafeBrowsingDatabaseNew::ContainsDownloadUrl( |
679 const std::vector<GURL>& urls, | 679 const std::vector<GURL>& urls, |
680 std::vector<SBPrefix>* prefix_hits) { | 680 std::vector<SBPrefix>* prefix_hits) { |
681 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 681 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
682 | 682 |
683 // Ignore this check when download checking is not enabled. | 683 // Ignore this check when download checking is not enabled. |
684 if (!download_store_.get()) | 684 if (!download_store_.get()) |
685 return false; | 685 return false; |
686 | 686 |
687 std::vector<SBPrefix> prefixes; | 687 std::vector<SBPrefix> prefixes; |
688 GetDownloadUrlPrefixes(urls, &prefixes); | 688 GetDownloadUrlPrefixes(urls, &prefixes); |
689 return MatchAddPrefixes(download_store_.get(), | 689 return MatchAddPrefixes(download_store_.get(), |
690 safe_browsing_util::BINURL % 2, | 690 safe_browsing_util::BINURL % 2, |
691 prefixes, | 691 prefixes, |
692 prefix_hits); | 692 prefix_hits); |
693 } | 693 } |
694 | 694 |
695 bool SafeBrowsingDatabaseNew::ContainsDownloadHashPrefix( | 695 bool SafeBrowsingDatabaseNew::ContainsDownloadHashPrefix( |
696 const SBPrefix& prefix) { | 696 const SBPrefix& prefix) { |
697 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 697 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
698 | 698 |
699 // Ignore this check when download store is not available. | 699 // Ignore this check when download store is not available. |
700 if (!download_store_.get()) | 700 if (!download_store_.get()) |
701 return false; | 701 return false; |
702 | 702 |
703 std::vector<SBPrefix> prefix_hits; | 703 std::vector<SBPrefix> prefix_hits; |
704 return MatchAddPrefixes(download_store_.get(), | 704 return MatchAddPrefixes(download_store_.get(), |
705 safe_browsing_util::BINHASH % 2, | 705 safe_browsing_util::BINHASH % 2, |
706 std::vector<SBPrefix>(1, prefix), | 706 std::vector<SBPrefix>(1, prefix), |
707 &prefix_hits); | 707 &prefix_hits); |
(...skipping 10 matching lines...) Expand all Loading... |
718 | 718 |
719 bool SafeBrowsingDatabaseNew::ContainsDownloadWhitelistedUrl(const GURL& url) { | 719 bool SafeBrowsingDatabaseNew::ContainsDownloadWhitelistedUrl(const GURL& url) { |
720 std::vector<SBFullHash> full_hashes; | 720 std::vector<SBFullHash> full_hashes; |
721 BrowseFullHashesToCheck(url, true, &full_hashes); | 721 BrowseFullHashesToCheck(url, true, &full_hashes); |
722 return ContainsWhitelistedHashes(download_whitelist_, full_hashes); | 722 return ContainsWhitelistedHashes(download_whitelist_, full_hashes); |
723 } | 723 } |
724 | 724 |
725 bool SafeBrowsingDatabaseNew::ContainsExtensionPrefixes( | 725 bool SafeBrowsingDatabaseNew::ContainsExtensionPrefixes( |
726 const std::vector<SBPrefix>& prefixes, | 726 const std::vector<SBPrefix>& prefixes, |
727 std::vector<SBPrefix>* prefix_hits) { | 727 std::vector<SBPrefix>* prefix_hits) { |
728 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 728 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
729 if (!extension_blacklist_store_) | 729 if (!extension_blacklist_store_) |
730 return false; | 730 return false; |
731 | 731 |
732 return MatchAddPrefixes(extension_blacklist_store_.get(), | 732 return MatchAddPrefixes(extension_blacklist_store_.get(), |
733 safe_browsing_util::EXTENSIONBLACKLIST % 2, | 733 safe_browsing_util::EXTENSIONBLACKLIST % 2, |
734 prefixes, | 734 prefixes, |
735 prefix_hits); | 735 prefix_hits); |
736 } | 736 } |
737 | 737 |
738 bool SafeBrowsingDatabaseNew::ContainsSideEffectFreeWhitelistUrl( | 738 bool SafeBrowsingDatabaseNew::ContainsSideEffectFreeWhitelistUrl( |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
779 if (std::binary_search(whitelist.first.begin(), whitelist.first.end(), *it)) | 779 if (std::binary_search(whitelist.first.begin(), whitelist.first.end(), *it)) |
780 return true; | 780 return true; |
781 } | 781 } |
782 return false; | 782 return false; |
783 } | 783 } |
784 | 784 |
785 // Helper to insert entries for all of the prefixes or full hashes in | 785 // Helper to insert entries for all of the prefixes or full hashes in |
786 // |entry| into the store. | 786 // |entry| into the store. |
787 void SafeBrowsingDatabaseNew::InsertAdd(int chunk_id, SBPrefix host, | 787 void SafeBrowsingDatabaseNew::InsertAdd(int chunk_id, SBPrefix host, |
788 const SBEntry* entry, int list_id) { | 788 const SBEntry* entry, int list_id) { |
789 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 789 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
790 | 790 |
791 SafeBrowsingStore* store = GetStore(list_id); | 791 SafeBrowsingStore* store = GetStore(list_id); |
792 if (!store) return; | 792 if (!store) return; |
793 | 793 |
794 STATS_COUNTER("SB.HostInsert", 1); | 794 STATS_COUNTER("SB.HostInsert", 1); |
795 const int encoded_chunk_id = EncodeChunkId(chunk_id, list_id); | 795 const int encoded_chunk_id = EncodeChunkId(chunk_id, list_id); |
796 const int count = entry->prefix_count(); | 796 const int count = entry->prefix_count(); |
797 | 797 |
798 DCHECK(!entry->IsSub()); | 798 DCHECK(!entry->IsSub()); |
799 if (!count) { | 799 if (!count) { |
(...skipping 21 matching lines...) Expand all Loading... |
821 store->WriteAddHash(encoded_chunk_id, receive_time, full_hash); | 821 store->WriteAddHash(encoded_chunk_id, receive_time, full_hash); |
822 } | 822 } |
823 } | 823 } |
824 } | 824 } |
825 | 825 |
826 // Helper to iterate over all the entries in the hosts in |chunks| and | 826 // Helper to iterate over all the entries in the hosts in |chunks| and |
827 // add them to the store. | 827 // add them to the store. |
828 void SafeBrowsingDatabaseNew::InsertAddChunks( | 828 void SafeBrowsingDatabaseNew::InsertAddChunks( |
829 const safe_browsing_util::ListType list_id, | 829 const safe_browsing_util::ListType list_id, |
830 const SBChunkList& chunks) { | 830 const SBChunkList& chunks) { |
831 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 831 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
832 | 832 |
833 SafeBrowsingStore* store = GetStore(list_id); | 833 SafeBrowsingStore* store = GetStore(list_id); |
834 if (!store) return; | 834 if (!store) return; |
835 | 835 |
836 for (SBChunkList::const_iterator citer = chunks.begin(); | 836 for (SBChunkList::const_iterator citer = chunks.begin(); |
837 citer != chunks.end(); ++citer) { | 837 citer != chunks.end(); ++citer) { |
838 const int chunk_id = citer->chunk_number; | 838 const int chunk_id = citer->chunk_number; |
839 | 839 |
840 // The server can give us a chunk that we already have because | 840 // The server can give us a chunk that we already have because |
841 // it's part of a range. Don't add it again. | 841 // it's part of a range. Don't add it again. |
842 const int encoded_chunk_id = EncodeChunkId(chunk_id, list_id); | 842 const int encoded_chunk_id = EncodeChunkId(chunk_id, list_id); |
843 if (store->CheckAddChunk(encoded_chunk_id)) | 843 if (store->CheckAddChunk(encoded_chunk_id)) |
844 continue; | 844 continue; |
845 | 845 |
846 store->SetAddChunk(encoded_chunk_id); | 846 store->SetAddChunk(encoded_chunk_id); |
847 for (std::deque<SBChunkHost>::const_iterator hiter = citer->hosts.begin(); | 847 for (std::deque<SBChunkHost>::const_iterator hiter = citer->hosts.begin(); |
848 hiter != citer->hosts.end(); ++hiter) { | 848 hiter != citer->hosts.end(); ++hiter) { |
849 // NOTE: Could pass |encoded_chunk_id|, but then inserting add | 849 // NOTE: Could pass |encoded_chunk_id|, but then inserting add |
850 // chunks would look different from inserting sub chunks. | 850 // chunks would look different from inserting sub chunks. |
851 InsertAdd(chunk_id, hiter->host, hiter->entry, list_id); | 851 InsertAdd(chunk_id, hiter->host, hiter->entry, list_id); |
852 } | 852 } |
853 } | 853 } |
854 } | 854 } |
855 | 855 |
856 // Helper to insert entries for all of the prefixes or full hashes in | 856 // Helper to insert entries for all of the prefixes or full hashes in |
857 // |entry| into the store. | 857 // |entry| into the store. |
858 void SafeBrowsingDatabaseNew::InsertSub(int chunk_id, SBPrefix host, | 858 void SafeBrowsingDatabaseNew::InsertSub(int chunk_id, SBPrefix host, |
859 const SBEntry* entry, int list_id) { | 859 const SBEntry* entry, int list_id) { |
860 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 860 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
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 STATS_COUNTER("SB.HostDelete", 1); | 865 STATS_COUNTER("SB.HostDelete", 1); |
866 const int encoded_chunk_id = EncodeChunkId(chunk_id, list_id); | 866 const int encoded_chunk_id = EncodeChunkId(chunk_id, list_id); |
867 const int count = entry->prefix_count(); | 867 const int count = entry->prefix_count(); |
868 | 868 |
869 DCHECK(entry->IsSub()); | 869 DCHECK(entry->IsSub()); |
870 if (!count) { | 870 if (!count) { |
(...skipping 25 matching lines...) Expand all Loading... |
896 store->WriteSubHash(encoded_chunk_id, add_chunk_id, full_hash); | 896 store->WriteSubHash(encoded_chunk_id, add_chunk_id, full_hash); |
897 } | 897 } |
898 } | 898 } |
899 } | 899 } |
900 | 900 |
901 // Helper to iterate over all the entries in the hosts in |chunks| and | 901 // Helper to iterate over all the entries in the hosts in |chunks| and |
902 // add them to the store. | 902 // add them to the store. |
903 void SafeBrowsingDatabaseNew::InsertSubChunks( | 903 void SafeBrowsingDatabaseNew::InsertSubChunks( |
904 safe_browsing_util::ListType list_id, | 904 safe_browsing_util::ListType list_id, |
905 const SBChunkList& chunks) { | 905 const SBChunkList& chunks) { |
906 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 906 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
907 | 907 |
908 SafeBrowsingStore* store = GetStore(list_id); | 908 SafeBrowsingStore* store = GetStore(list_id); |
909 if (!store) return; | 909 if (!store) return; |
910 | 910 |
911 for (SBChunkList::const_iterator citer = chunks.begin(); | 911 for (SBChunkList::const_iterator citer = chunks.begin(); |
912 citer != chunks.end(); ++citer) { | 912 citer != chunks.end(); ++citer) { |
913 const int chunk_id = citer->chunk_number; | 913 const int chunk_id = citer->chunk_number; |
914 | 914 |
915 // The server can give us a chunk that we already have because | 915 // The server can give us a chunk that we already have because |
916 // it's part of a range. Don't add it again. | 916 // it's part of a range. Don't add it again. |
917 const int encoded_chunk_id = EncodeChunkId(chunk_id, list_id); | 917 const int encoded_chunk_id = EncodeChunkId(chunk_id, list_id); |
918 if (store->CheckSubChunk(encoded_chunk_id)) | 918 if (store->CheckSubChunk(encoded_chunk_id)) |
919 continue; | 919 continue; |
920 | 920 |
921 store->SetSubChunk(encoded_chunk_id); | 921 store->SetSubChunk(encoded_chunk_id); |
922 for (std::deque<SBChunkHost>::const_iterator hiter = citer->hosts.begin(); | 922 for (std::deque<SBChunkHost>::const_iterator hiter = citer->hosts.begin(); |
923 hiter != citer->hosts.end(); ++hiter) { | 923 hiter != citer->hosts.end(); ++hiter) { |
924 InsertSub(chunk_id, hiter->host, hiter->entry, list_id); | 924 InsertSub(chunk_id, hiter->host, hiter->entry, list_id); |
925 } | 925 } |
926 } | 926 } |
927 } | 927 } |
928 | 928 |
929 void SafeBrowsingDatabaseNew::InsertChunks(const std::string& list_name, | 929 void SafeBrowsingDatabaseNew::InsertChunks(const std::string& list_name, |
930 const SBChunkList& chunks) { | 930 const SBChunkList& chunks) { |
931 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 931 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
932 | 932 |
933 if (corruption_detected_ || chunks.empty()) | 933 if (corruption_detected_ || chunks.empty()) |
934 return; | 934 return; |
935 | 935 |
936 const base::TimeTicks before = base::TimeTicks::Now(); | 936 const base::TimeTicks before = base::TimeTicks::Now(); |
937 | 937 |
938 const safe_browsing_util::ListType list_id = | 938 const safe_browsing_util::ListType list_id = |
939 safe_browsing_util::GetListId(list_name); | 939 safe_browsing_util::GetListId(list_name); |
940 DVLOG(2) << list_name << ": " << list_id; | 940 DVLOG(2) << list_name << ": " << list_id; |
941 | 941 |
942 SafeBrowsingStore* store = GetStore(list_id); | 942 SafeBrowsingStore* store = GetStore(list_id); |
943 if (!store) return; | 943 if (!store) return; |
944 | 944 |
945 change_detected_ = true; | 945 change_detected_ = true; |
946 | 946 |
947 store->BeginChunk(); | 947 store->BeginChunk(); |
948 if (chunks.front().is_add) { | 948 if (chunks.front().is_add) { |
949 InsertAddChunks(list_id, chunks); | 949 InsertAddChunks(list_id, chunks); |
950 } else { | 950 } else { |
951 InsertSubChunks(list_id, chunks); | 951 InsertSubChunks(list_id, chunks); |
952 } | 952 } |
953 store->FinishChunk(); | 953 store->FinishChunk(); |
954 | 954 |
955 UMA_HISTOGRAM_TIMES("SB2.ChunkInsert", base::TimeTicks::Now() - before); | 955 UMA_HISTOGRAM_TIMES("SB2.ChunkInsert", base::TimeTicks::Now() - before); |
956 } | 956 } |
957 | 957 |
958 void SafeBrowsingDatabaseNew::DeleteChunks( | 958 void SafeBrowsingDatabaseNew::DeleteChunks( |
959 const std::vector<SBChunkDelete>& chunk_deletes) { | 959 const std::vector<SBChunkDelete>& chunk_deletes) { |
960 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 960 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
961 | 961 |
962 if (corruption_detected_ || chunk_deletes.empty()) | 962 if (corruption_detected_ || chunk_deletes.empty()) |
963 return; | 963 return; |
964 | 964 |
965 const std::string& list_name = chunk_deletes.front().list_name; | 965 const std::string& list_name = chunk_deletes.front().list_name; |
966 const safe_browsing_util::ListType list_id = | 966 const safe_browsing_util::ListType list_id = |
967 safe_browsing_util::GetListId(list_name); | 967 safe_browsing_util::GetListId(list_name); |
968 | 968 |
969 SafeBrowsingStore* store = GetStore(list_id); | 969 SafeBrowsingStore* store = GetStore(list_id); |
970 if (!store) return; | 970 if (!store) return; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1014 std::vector<SBAddFullHash>::iterator | 1014 std::vector<SBAddFullHash>::iterator |
1015 orig_end = pending_browse_hashes_.begin() + orig_size; | 1015 orig_end = pending_browse_hashes_.begin() + orig_size; |
1016 std::sort(orig_end, pending_browse_hashes_.end(), SBAddFullHashPrefixLess); | 1016 std::sort(orig_end, pending_browse_hashes_.end(), SBAddFullHashPrefixLess); |
1017 std::inplace_merge(pending_browse_hashes_.begin(), | 1017 std::inplace_merge(pending_browse_hashes_.begin(), |
1018 orig_end, pending_browse_hashes_.end(), | 1018 orig_end, pending_browse_hashes_.end(), |
1019 SBAddFullHashPrefixLess); | 1019 SBAddFullHashPrefixLess); |
1020 } | 1020 } |
1021 | 1021 |
1022 bool SafeBrowsingDatabaseNew::UpdateStarted( | 1022 bool SafeBrowsingDatabaseNew::UpdateStarted( |
1023 std::vector<SBListChunkRanges>* lists) { | 1023 std::vector<SBListChunkRanges>* lists) { |
1024 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 1024 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
1025 DCHECK(lists); | 1025 DCHECK(lists); |
1026 | 1026 |
1027 // If |BeginUpdate()| fails, reset the database. | 1027 // If |BeginUpdate()| fails, reset the database. |
1028 if (!browse_store_->BeginUpdate()) { | 1028 if (!browse_store_->BeginUpdate()) { |
1029 RecordFailure(FAILURE_BROWSE_DATABASE_UPDATE_BEGIN); | 1029 RecordFailure(FAILURE_BROWSE_DATABASE_UPDATE_BEGIN); |
1030 HandleCorruptDatabase(); | 1030 HandleCorruptDatabase(); |
1031 return false; | 1031 return false; |
1032 } | 1032 } |
1033 | 1033 |
1034 if (download_store_.get() && !download_store_->BeginUpdate()) { | 1034 if (download_store_.get() && !download_store_->BeginUpdate()) { |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1126 1, safe_browsing_util::kSideEffectFreeWhitelist), | 1126 1, safe_browsing_util::kSideEffectFreeWhitelist), |
1127 lists); | 1127 lists); |
1128 } | 1128 } |
1129 | 1129 |
1130 corruption_detected_ = false; | 1130 corruption_detected_ = false; |
1131 change_detected_ = false; | 1131 change_detected_ = false; |
1132 return true; | 1132 return true; |
1133 } | 1133 } |
1134 | 1134 |
1135 void SafeBrowsingDatabaseNew::UpdateFinished(bool update_succeeded) { | 1135 void SafeBrowsingDatabaseNew::UpdateFinished(bool update_succeeded) { |
1136 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 1136 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
1137 | 1137 |
1138 // The update may have failed due to corrupt storage (for instance, | 1138 // The update may have failed due to corrupt storage (for instance, |
1139 // an excessive number of invalid add_chunks and sub_chunks). | 1139 // an excessive number of invalid add_chunks and sub_chunks). |
1140 // Double-check that the databases are valid. | 1140 // Double-check that the databases are valid. |
1141 // TODO(shess): Providing a checksum for the add_chunk and sub_chunk | 1141 // TODO(shess): Providing a checksum for the add_chunk and sub_chunk |
1142 // sections would allow throwing a corruption error in | 1142 // sections would allow throwing a corruption error in |
1143 // UpdateStarted(). | 1143 // UpdateStarted(). |
1144 if (!update_succeeded) { | 1144 if (!update_succeeded) { |
1145 if (!browse_store_->CheckValidity()) | 1145 if (!browse_store_->CheckValidity()) |
1146 DLOG(ERROR) << "Safe-browsing browse database corrupt."; | 1146 DLOG(ERROR) << "Safe-browsing browse database corrupt."; |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1454 base::mac::SetFileBackupExclusion( | 1454 base::mac::SetFileBackupExclusion( |
1455 side_effect_free_whitelist_prefix_set_filename_); | 1455 side_effect_free_whitelist_prefix_set_filename_); |
1456 #endif | 1456 #endif |
1457 } | 1457 } |
1458 | 1458 |
1459 void SafeBrowsingDatabaseNew::HandleCorruptDatabase() { | 1459 void SafeBrowsingDatabaseNew::HandleCorruptDatabase() { |
1460 // Reset the database after the current task has unwound (but only | 1460 // Reset the database after the current task has unwound (but only |
1461 // reset once within the scope of a given task). | 1461 // reset once within the scope of a given task). |
1462 if (!reset_factory_.HasWeakPtrs()) { | 1462 if (!reset_factory_.HasWeakPtrs()) { |
1463 RecordFailure(FAILURE_DATABASE_CORRUPT); | 1463 RecordFailure(FAILURE_DATABASE_CORRUPT); |
1464 MessageLoop::current()->PostTask(FROM_HERE, | 1464 base::MessageLoop::current()->PostTask(FROM_HERE, |
1465 base::Bind(&SafeBrowsingDatabaseNew::OnHandleCorruptDatabase, | 1465 base::Bind(&SafeBrowsingDatabaseNew::OnHandleCorruptDatabase, |
1466 reset_factory_.GetWeakPtr())); | 1466 reset_factory_.GetWeakPtr())); |
1467 } | 1467 } |
1468 } | 1468 } |
1469 | 1469 |
1470 void SafeBrowsingDatabaseNew::OnHandleCorruptDatabase() { | 1470 void SafeBrowsingDatabaseNew::OnHandleCorruptDatabase() { |
1471 RecordFailure(FAILURE_DATABASE_CORRUPT_HANDLER); | 1471 RecordFailure(FAILURE_DATABASE_CORRUPT_HANDLER); |
1472 corruption_detected_ = true; // Stop updating the database. | 1472 corruption_detected_ = true; // Stop updating the database. |
1473 ResetDatabase(); | 1473 ResetDatabase(); |
1474 DLOG(FATAL) << "SafeBrowsing database was corrupt and reset"; | 1474 DLOG(FATAL) << "SafeBrowsing database was corrupt and reset"; |
1475 } | 1475 } |
1476 | 1476 |
1477 // TODO(shess): I'm not clear why this code doesn't have any | 1477 // TODO(shess): I'm not clear why this code doesn't have any |
1478 // real error-handling. | 1478 // real error-handling. |
1479 void SafeBrowsingDatabaseNew::LoadPrefixSet() { | 1479 void SafeBrowsingDatabaseNew::LoadPrefixSet() { |
1480 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 1480 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
1481 DCHECK(!browse_prefix_set_filename_.empty()); | 1481 DCHECK(!browse_prefix_set_filename_.empty()); |
1482 | 1482 |
1483 // If there is no database, the filter cannot be used. | 1483 // If there is no database, the filter cannot be used. |
1484 base::PlatformFileInfo db_info; | 1484 base::PlatformFileInfo db_info; |
1485 if (!file_util::GetFileInfo(browse_filename_, &db_info) || db_info.size == 0) | 1485 if (!file_util::GetFileInfo(browse_filename_, &db_info) || db_info.size == 0) |
1486 return; | 1486 return; |
1487 | 1487 |
1488 // Cleanup any stale bloom filter (no longer used). | 1488 // Cleanup any stale bloom filter (no longer used). |
1489 // TODO(shess): Track failure to delete? | 1489 // TODO(shess): Track failure to delete? |
1490 base::FilePath bloom_filter_filename = | 1490 base::FilePath bloom_filter_filename = |
1491 BloomFilterForFilename(browse_filename_); | 1491 BloomFilterForFilename(browse_filename_); |
1492 file_util::Delete(bloom_filter_filename, false); | 1492 file_util::Delete(bloom_filter_filename, false); |
1493 | 1493 |
1494 const base::TimeTicks before = base::TimeTicks::Now(); | 1494 const base::TimeTicks before = base::TimeTicks::Now(); |
1495 browse_prefix_set_.reset(safe_browsing::PrefixSet::LoadFile( | 1495 browse_prefix_set_.reset(safe_browsing::PrefixSet::LoadFile( |
1496 browse_prefix_set_filename_)); | 1496 browse_prefix_set_filename_)); |
1497 DVLOG(1) << "SafeBrowsingDatabaseNew read prefix set in " | 1497 DVLOG(1) << "SafeBrowsingDatabaseNew read prefix set in " |
1498 << (base::TimeTicks::Now() - before).InMilliseconds() << " ms"; | 1498 << (base::TimeTicks::Now() - before).InMilliseconds() << " ms"; |
1499 UMA_HISTOGRAM_TIMES("SB2.PrefixSetLoad", base::TimeTicks::Now() - before); | 1499 UMA_HISTOGRAM_TIMES("SB2.PrefixSetLoad", base::TimeTicks::Now() - before); |
1500 | 1500 |
1501 if (!browse_prefix_set_.get()) | 1501 if (!browse_prefix_set_.get()) |
1502 RecordFailure(FAILURE_BROWSE_PREFIX_SET_READ); | 1502 RecordFailure(FAILURE_BROWSE_PREFIX_SET_READ); |
1503 } | 1503 } |
1504 | 1504 |
1505 bool SafeBrowsingDatabaseNew::Delete() { | 1505 bool SafeBrowsingDatabaseNew::Delete() { |
1506 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 1506 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
1507 | 1507 |
1508 const bool r1 = browse_store_->Delete(); | 1508 const bool r1 = browse_store_->Delete(); |
1509 if (!r1) | 1509 if (!r1) |
1510 RecordFailure(FAILURE_DATABASE_STORE_DELETE); | 1510 RecordFailure(FAILURE_DATABASE_STORE_DELETE); |
1511 | 1511 |
1512 const bool r2 = download_store_.get() ? download_store_->Delete() : true; | 1512 const bool r2 = download_store_.get() ? download_store_->Delete() : true; |
1513 if (!r2) | 1513 if (!r2) |
1514 RecordFailure(FAILURE_DATABASE_STORE_DELETE); | 1514 RecordFailure(FAILURE_DATABASE_STORE_DELETE); |
1515 | 1515 |
1516 const bool r3 = csd_whitelist_store_.get() ? | 1516 const bool r3 = csd_whitelist_store_.get() ? |
(...skipping 28 matching lines...) Expand all Loading... |
1545 const bool r9 = file_util::Delete( | 1545 const bool r9 = file_util::Delete( |
1546 side_effect_free_whitelist_prefix_set_filename_, | 1546 side_effect_free_whitelist_prefix_set_filename_, |
1547 false); | 1547 false); |
1548 if (!r9) | 1548 if (!r9) |
1549 RecordFailure(FAILURE_SIDE_EFFECT_FREE_WHITELIST_PREFIX_SET_DELETE); | 1549 RecordFailure(FAILURE_SIDE_EFFECT_FREE_WHITELIST_PREFIX_SET_DELETE); |
1550 | 1550 |
1551 return r1 && r2 && r3 && r4 && r5 && r6 && r7 && r8 && r9; | 1551 return r1 && r2 && r3 && r4 && r5 && r6 && r7 && r8 && r9; |
1552 } | 1552 } |
1553 | 1553 |
1554 void SafeBrowsingDatabaseNew::WritePrefixSet() { | 1554 void SafeBrowsingDatabaseNew::WritePrefixSet() { |
1555 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 1555 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
1556 | 1556 |
1557 if (!browse_prefix_set_.get()) | 1557 if (!browse_prefix_set_.get()) |
1558 return; | 1558 return; |
1559 | 1559 |
1560 const base::TimeTicks before = base::TimeTicks::Now(); | 1560 const base::TimeTicks before = base::TimeTicks::Now(); |
1561 const bool write_ok = browse_prefix_set_->WriteFile( | 1561 const bool write_ok = browse_prefix_set_->WriteFile( |
1562 browse_prefix_set_filename_); | 1562 browse_prefix_set_filename_); |
1563 DVLOG(1) << "SafeBrowsingDatabaseNew wrote prefix set in " | 1563 DVLOG(1) << "SafeBrowsingDatabaseNew wrote prefix set in " |
1564 << (base::TimeTicks::Now() - before).InMilliseconds() << " ms"; | 1564 << (base::TimeTicks::Now() - before).InMilliseconds() << " ms"; |
1565 UMA_HISTOGRAM_TIMES("SB2.PrefixSetWrite", base::TimeTicks::Now() - before); | 1565 UMA_HISTOGRAM_TIMES("SB2.PrefixSetWrite", base::TimeTicks::Now() - before); |
1566 | 1566 |
1567 if (!write_ok) | 1567 if (!write_ok) |
1568 RecordFailure(FAILURE_BROWSE_PREFIX_SET_WRITE); | 1568 RecordFailure(FAILURE_BROWSE_PREFIX_SET_WRITE); |
1569 | 1569 |
1570 #if defined(OS_MACOSX) | 1570 #if defined(OS_MACOSX) |
1571 base::mac::SetFileBackupExclusion(browse_prefix_set_filename_); | 1571 base::mac::SetFileBackupExclusion(browse_prefix_set_filename_); |
1572 #endif | 1572 #endif |
1573 } | 1573 } |
1574 | 1574 |
1575 void SafeBrowsingDatabaseNew::WhitelistEverything(SBWhitelist* whitelist) { | 1575 void SafeBrowsingDatabaseNew::WhitelistEverything(SBWhitelist* whitelist) { |
1576 base::AutoLock locked(lookup_lock_); | 1576 base::AutoLock locked(lookup_lock_); |
1577 whitelist->second = true; | 1577 whitelist->second = true; |
1578 whitelist->first.clear(); | 1578 whitelist->first.clear(); |
1579 } | 1579 } |
1580 | 1580 |
1581 void SafeBrowsingDatabaseNew::LoadWhitelist( | 1581 void SafeBrowsingDatabaseNew::LoadWhitelist( |
1582 const std::vector<SBAddFullHash>& full_hashes, | 1582 const std::vector<SBAddFullHash>& full_hashes, |
1583 SBWhitelist* whitelist) { | 1583 SBWhitelist* whitelist) { |
1584 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 1584 DCHECK_EQ(creation_loop_, base::MessageLoop::current()); |
1585 if (full_hashes.size() > kMaxWhitelistSize) { | 1585 if (full_hashes.size() > kMaxWhitelistSize) { |
1586 WhitelistEverything(whitelist); | 1586 WhitelistEverything(whitelist); |
1587 return; | 1587 return; |
1588 } | 1588 } |
1589 | 1589 |
1590 std::vector<SBFullHash> new_whitelist; | 1590 std::vector<SBFullHash> new_whitelist; |
1591 new_whitelist.reserve(full_hashes.size()); | 1591 new_whitelist.reserve(full_hashes.size()); |
1592 for (std::vector<SBAddFullHash>::const_iterator it = full_hashes.begin(); | 1592 for (std::vector<SBAddFullHash>::const_iterator it = full_hashes.begin(); |
1593 it != full_hashes.end(); ++it) { | 1593 it != full_hashes.end(); ++it) { |
1594 new_whitelist.push_back(it->full_hash); | 1594 new_whitelist.push_back(it->full_hash); |
1595 } | 1595 } |
1596 std::sort(new_whitelist.begin(), new_whitelist.end()); | 1596 std::sort(new_whitelist.begin(), new_whitelist.end()); |
1597 | 1597 |
1598 SBFullHash kill_switch; | 1598 SBFullHash kill_switch; |
1599 crypto::SHA256HashString(kWhitelistKillSwitchUrl, &kill_switch, | 1599 crypto::SHA256HashString(kWhitelistKillSwitchUrl, &kill_switch, |
1600 sizeof(kill_switch)); | 1600 sizeof(kill_switch)); |
1601 if (std::binary_search(new_whitelist.begin(), new_whitelist.end(), | 1601 if (std::binary_search(new_whitelist.begin(), new_whitelist.end(), |
1602 kill_switch)) { | 1602 kill_switch)) { |
1603 // The kill switch is whitelisted hence we whitelist all URLs. | 1603 // The kill switch is whitelisted hence we whitelist all URLs. |
1604 WhitelistEverything(whitelist); | 1604 WhitelistEverything(whitelist); |
1605 } else { | 1605 } else { |
1606 base::AutoLock locked(lookup_lock_); | 1606 base::AutoLock locked(lookup_lock_); |
1607 whitelist->second = false; | 1607 whitelist->second = false; |
1608 whitelist->first.swap(new_whitelist); | 1608 whitelist->first.swap(new_whitelist); |
1609 } | 1609 } |
1610 } | 1610 } |
OLD | NEW |