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_store_file.h" | 5 #include "chrome/browser/safe_browsing/safe_browsing_store_file.h" |
6 | 6 |
7 #include "base/file_util.h" | 7 #include "base/file_util.h" |
8 #include "base/files/scoped_file.h" | 8 #include "base/files/scoped_file.h" |
9 #include "base/md5.h" | 9 #include "base/md5.h" |
10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
387 // Helper to find the next shard boundary. | 387 // Helper to find the next shard boundary. |
388 template <class T> | 388 template <class T> |
389 bool prefix_bounder(SBPrefix val, const T& elt) { | 389 bool prefix_bounder(SBPrefix val, const T& elt) { |
390 return val < elt.GetAddPrefix(); | 390 return val < elt.GetAddPrefix(); |
391 } | 391 } |
392 | 392 |
393 // Container for partial database state. Includes add/sub prefixes/hashes, plus | 393 // Container for partial database state. Includes add/sub prefixes/hashes, plus |
394 // aggregate operations on same. | 394 // aggregate operations on same. |
395 class StateInternal { | 395 class StateInternal { |
396 public: | 396 public: |
397 explicit StateInternal(const std::vector<SBAddFullHash>& pending_adds) | |
398 : add_full_hashes_(pending_adds.begin(), pending_adds.end()) { | |
399 } | |
400 | |
401 StateInternal() {} | 397 StateInternal() {} |
402 | 398 |
403 // Append indicated amount of data from |fp|. | 399 // Append indicated amount of data from |fp|. |
404 bool AppendData(size_t add_prefix_count, size_t sub_prefix_count, | 400 bool AppendData(size_t add_prefix_count, size_t sub_prefix_count, |
405 size_t add_hash_count, size_t sub_hash_count, | 401 size_t add_hash_count, size_t sub_hash_count, |
406 FILE* fp, base::MD5Context* context) { | 402 FILE* fp, base::MD5Context* context) { |
407 return | 403 return |
408 ReadToContainer(&add_prefixes_, add_prefix_count, fp, context) && | 404 ReadToContainer(&add_prefixes_, add_prefix_count, fp, context) && |
409 ReadToContainer(&sub_prefixes_, sub_prefix_count, fp, context) && | 405 ReadToContainer(&sub_prefixes_, sub_prefix_count, fp, context) && |
410 ReadToContainer(&add_full_hashes_, add_hash_count, fp, context) && | 406 ReadToContainer(&add_full_hashes_, add_hash_count, fp, context) && |
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
729 | 725 |
730 StateInternal db_state; | 726 StateInternal db_state; |
731 if (!ReadDbStateHelper(filename_, &db_state)) | 727 if (!ReadDbStateHelper(filename_, &db_state)) |
732 return OnCorruptDatabase(); | 728 return OnCorruptDatabase(); |
733 | 729 |
734 add_full_hashes->swap(db_state.add_full_hashes_); | 730 add_full_hashes->swap(db_state.add_full_hashes_); |
735 return true; | 731 return true; |
736 } | 732 } |
737 | 733 |
738 bool SafeBrowsingStoreFile::WriteAddHash(int32 chunk_id, | 734 bool SafeBrowsingStoreFile::WriteAddHash(int32 chunk_id, |
739 base::Time receive_time, | |
740 const SBFullHash& full_hash) { | 735 const SBFullHash& full_hash) { |
741 add_hashes_.push_back(SBAddFullHash(chunk_id, receive_time, full_hash)); | 736 add_hashes_.push_back(SBAddFullHash(chunk_id, full_hash)); |
742 return true; | 737 return true; |
743 } | 738 } |
744 | 739 |
745 bool SafeBrowsingStoreFile::WriteSubPrefix(int32 chunk_id, | 740 bool SafeBrowsingStoreFile::WriteSubPrefix(int32 chunk_id, |
746 int32 add_chunk_id, | 741 int32 add_chunk_id, |
747 SBPrefix prefix) { | 742 SBPrefix prefix) { |
748 sub_prefixes_.push_back(SBSubPrefix(chunk_id, add_chunk_id, prefix)); | 743 sub_prefixes_.push_back(SBSubPrefix(chunk_id, add_chunk_id, prefix)); |
749 return true; | 744 return true; |
750 } | 745 } |
751 | 746 |
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
865 !WriteContainer(sub_hashes_, new_file_.get(), NULL)) | 860 !WriteContainer(sub_hashes_, new_file_.get(), NULL)) |
866 return false; | 861 return false; |
867 | 862 |
868 ++chunks_written_; | 863 ++chunks_written_; |
869 | 864 |
870 // Clear everything to save memory. | 865 // Clear everything to save memory. |
871 return ClearChunkBuffers(); | 866 return ClearChunkBuffers(); |
872 } | 867 } |
873 | 868 |
874 bool SafeBrowsingStoreFile::DoUpdate( | 869 bool SafeBrowsingStoreFile::DoUpdate( |
875 const std::vector<SBAddFullHash>& pending_adds, | |
876 safe_browsing::PrefixSetBuilder* builder, | 870 safe_browsing::PrefixSetBuilder* builder, |
877 std::vector<SBAddFullHash>* add_full_hashes_result) { | 871 std::vector<SBAddFullHash>* add_full_hashes_result) { |
878 DCHECK(file_.get() || empty_); | 872 DCHECK(file_.get() || empty_); |
879 DCHECK(new_file_.get()); | 873 DCHECK(new_file_.get()); |
880 CHECK(builder); | 874 CHECK(builder); |
881 CHECK(add_full_hashes_result); | 875 CHECK(add_full_hashes_result); |
882 | 876 |
883 // Rewind the temporary storage. | 877 // Rewind the temporary storage. |
884 if (!FileRewind(new_file_.get())) | 878 if (!FileRewind(new_file_.get())) |
885 return false; | 879 return false; |
886 | 880 |
887 // Get chunk file's size for validating counts. | 881 // Get chunk file's size for validating counts. |
888 int64 update_size = 0; | 882 int64 update_size = 0; |
889 if (!base::GetFileSize(TemporaryFileForFilename(filename_), &update_size)) | 883 if (!base::GetFileSize(TemporaryFileForFilename(filename_), &update_size)) |
890 return OnCorruptDatabase(); | 884 return OnCorruptDatabase(); |
891 | 885 |
892 // Track update size to answer questions at http://crbug.com/72216 . | 886 // Track update size to answer questions at http://crbug.com/72216 . |
893 // Log small updates as 1k so that the 0 (underflow) bucket can be | 887 // Log small updates as 1k so that the 0 (underflow) bucket can be |
894 // used for "empty" in SafeBrowsingDatabase. | 888 // used for "empty" in SafeBrowsingDatabase. |
895 UMA_HISTOGRAM_COUNTS("SB2.DatabaseUpdateKilobytes", | 889 UMA_HISTOGRAM_COUNTS("SB2.DatabaseUpdateKilobytes", |
896 std::max(static_cast<int>(update_size / 1024), 1)); | 890 std::max(static_cast<int>(update_size / 1024), 1)); |
897 | 891 |
898 // Chunk updates to integrate. | 892 // Chunk updates to integrate. |
899 StateInternal new_state(pending_adds); | 893 StateInternal new_state; |
900 | 894 |
901 // Read update chunks. | 895 // Read update chunks. |
902 for (int i = 0; i < chunks_written_; ++i) { | 896 for (int i = 0; i < chunks_written_; ++i) { |
903 ChunkHeader header; | 897 ChunkHeader header; |
904 | 898 |
905 int64 ofs = ftell(new_file_.get()); | 899 int64 ofs = ftell(new_file_.get()); |
906 if (ofs == -1) | 900 if (ofs == -1) |
907 return false; | 901 return false; |
908 | 902 |
909 if (!ReadItem(&header, new_file_.get(), NULL)) | 903 if (!ReadItem(&header, new_file_.get(), NULL)) |
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1129 return false; | 1123 return false; |
1130 | 1124 |
1131 // Record counts before swapping to caller. | 1125 // Record counts before swapping to caller. |
1132 UMA_HISTOGRAM_COUNTS("SB2.AddPrefixes", add_prefix_count); | 1126 UMA_HISTOGRAM_COUNTS("SB2.AddPrefixes", add_prefix_count); |
1133 UMA_HISTOGRAM_COUNTS("SB2.SubPrefixes", sub_prefix_count); | 1127 UMA_HISTOGRAM_COUNTS("SB2.SubPrefixes", sub_prefix_count); |
1134 | 1128 |
1135 return true; | 1129 return true; |
1136 } | 1130 } |
1137 | 1131 |
1138 bool SafeBrowsingStoreFile::FinishUpdate( | 1132 bool SafeBrowsingStoreFile::FinishUpdate( |
1139 const std::vector<SBAddFullHash>& pending_adds, | |
1140 safe_browsing::PrefixSetBuilder* builder, | 1133 safe_browsing::PrefixSetBuilder* builder, |
1141 std::vector<SBAddFullHash>* add_full_hashes_result) { | 1134 std::vector<SBAddFullHash>* add_full_hashes_result) { |
1142 DCHECK(builder); | 1135 DCHECK(builder); |
1143 DCHECK(add_full_hashes_result); | 1136 DCHECK(add_full_hashes_result); |
1144 | 1137 |
1145 if (!DoUpdate(pending_adds, builder, add_full_hashes_result)) { | 1138 if (!DoUpdate(builder, add_full_hashes_result)) { |
1146 CancelUpdate(); | 1139 CancelUpdate(); |
1147 return false; | 1140 return false; |
1148 } | 1141 } |
1149 | 1142 |
1150 DCHECK(!new_file_.get()); | 1143 DCHECK(!new_file_.get()); |
1151 DCHECK(!file_.get()); | 1144 DCHECK(!file_.get()); |
1152 | 1145 |
1153 return Close(); | 1146 return Close(); |
1154 } | 1147 } |
1155 | 1148 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1209 // With SQLite support gone, one way to get to this code is if the | 1202 // With SQLite support gone, one way to get to this code is if the |
1210 // existing file is a SQLite file. Make sure the journal file is | 1203 // existing file is a SQLite file. Make sure the journal file is |
1211 // also removed. | 1204 // also removed. |
1212 const base::FilePath journal_filename( | 1205 const base::FilePath journal_filename( |
1213 basename.value() + FILE_PATH_LITERAL("-journal")); | 1206 basename.value() + FILE_PATH_LITERAL("-journal")); |
1214 if (base::PathExists(journal_filename)) | 1207 if (base::PathExists(journal_filename)) |
1215 base::DeleteFile(journal_filename, false); | 1208 base::DeleteFile(journal_filename, false); |
1216 | 1209 |
1217 return true; | 1210 return true; |
1218 } | 1211 } |
OLD | NEW |