Chromium Code Reviews| 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 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 79 | 79 |
| 80 // Enumerate different format-change events for histogramming | 80 // Enumerate different format-change events for histogramming |
| 81 // purposes. DO NOT CHANGE THE ORDERING OF THESE VALUES. | 81 // purposes. DO NOT CHANGE THE ORDERING OF THESE VALUES. |
| 82 enum FormatEventType { | 82 enum FormatEventType { |
| 83 // Corruption detected, broken down by file format. | 83 // Corruption detected, broken down by file format. |
| 84 FORMAT_EVENT_FILE_CORRUPT, | 84 FORMAT_EVENT_FILE_CORRUPT, |
| 85 FORMAT_EVENT_SQLITE_CORRUPT, // Obsolete | 85 FORMAT_EVENT_SQLITE_CORRUPT, // Obsolete |
| 86 | 86 |
| 87 // The type of format found in the file. The expected case (new | 87 // The type of format found in the file. The expected case (new |
| 88 // file format) is intentionally not covered. | 88 // file format) is intentionally not covered. |
| 89 FORMAT_EVENT_FOUND_SQLITE, | 89 FORMAT_EVENT_FOUND_SQLITE, // Obsolete |
| 90 FORMAT_EVENT_FOUND_UNKNOWN, | 90 FORMAT_EVENT_FOUND_UNKNOWN, // magic does not match. |
| 91 | 91 |
| 92 // The number of SQLite-format files deleted should be the same as | 92 // The number of SQLite-format files deleted should be the same as |
| 93 // FORMAT_EVENT_FOUND_SQLITE. It can differ if the delete fails, | 93 // FORMAT_EVENT_FOUND_SQLITE. It can differ if the delete fails, |
| 94 // or if a failure prevents the update from succeeding. | 94 // or if a failure prevents the update from succeeding. |
| 95 FORMAT_EVENT_SQLITE_DELETED, // Obsolete | 95 FORMAT_EVENT_SQLITE_DELETED, // Obsolete |
| 96 FORMAT_EVENT_SQLITE_DELETE_FAILED, // Obsolete | 96 FORMAT_EVENT_SQLITE_DELETE_FAILED, // Obsolete |
| 97 | 97 |
| 98 // Found and deleted (or failed to delete) the ancient "Safe | 98 // Found and deleted (or failed to delete) the ancient "Safe |
| 99 // Browsing" file. | 99 // Browsing" file. |
| 100 FORMAT_EVENT_DELETED_ORIGINAL, | 100 FORMAT_EVENT_DELETED_ORIGINAL, // Obsolete |
| 101 FORMAT_EVENT_DELETED_ORIGINAL_FAILED, | 101 FORMAT_EVENT_DELETED_ORIGINAL_FAILED, // Obsolete |
| 102 | 102 |
| 103 // The checksum did not check out in CheckValidity() or in | 103 // The checksum did not check out in CheckValidity() or in |
| 104 // FinishUpdate(). This most likely indicates that the machine | 104 // FinishUpdate(). This most likely indicates that the machine |
| 105 // crashed before the file was fully sync'ed to disk. | 105 // crashed before the file was fully sync'ed to disk. |
| 106 FORMAT_EVENT_VALIDITY_CHECKSUM_FAILURE, | 106 FORMAT_EVENT_VALIDITY_CHECKSUM_FAILURE, |
| 107 FORMAT_EVENT_UPDATE_CHECKSUM_FAILURE, | 107 FORMAT_EVENT_UPDATE_CHECKSUM_FAILURE, |
| 108 | 108 |
| 109 // The header checksum was incorrect in ReadAndVerifyHeader(). Likely | 109 // The header checksum was incorrect in ReadAndVerifyHeader(). Likely |
| 110 // indicates that the system crashed while writing an update. | 110 // indicates that the system crashed while writing an update. |
| 111 FORMAT_EVENT_HEADER_CHECKSUM_FAILURE, | 111 FORMAT_EVENT_HEADER_CHECKSUM_FAILURE, |
| 112 | 112 |
| 113 FORMAT_EVENT_FOUND_DEPRECATED, // version too old. | |
| 114 | |
| 113 // Memory space for histograms is determined by the max. ALWAYS | 115 // Memory space for histograms is determined by the max. ALWAYS |
| 114 // ADD NEW VALUES BEFORE THIS ONE. | 116 // ADD NEW VALUES BEFORE THIS ONE. |
| 115 FORMAT_EVENT_MAX | 117 FORMAT_EVENT_MAX |
| 116 }; | 118 }; |
| 117 | 119 |
| 118 void RecordFormatEvent(FormatEventType event_type) { | 120 void RecordFormatEvent(FormatEventType event_type) { |
| 119 UMA_HISTOGRAM_ENUMERATION("SB2.FormatEvent", event_type, FORMAT_EVENT_MAX); | 121 UMA_HISTOGRAM_ENUMERATION("SB2.FormatEvent", event_type, FORMAT_EVENT_MAX); |
| 120 } | 122 } |
| 121 | 123 |
| 122 // Rewind the file. Using fseek(2) because rewind(3) errors are | 124 // Rewind the file. Using fseek(2) because rewind(3) errors are |
| (...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 623 | 625 |
| 624 int64 size = 0; | 626 int64 size = 0; |
| 625 if (!base::GetFileSize(filename, &size)) | 627 if (!base::GetFileSize(filename, &size)) |
| 626 return false; | 628 return false; |
| 627 | 629 |
| 628 return static_cast<int64>(ftell(file.get())) == size; | 630 return static_cast<int64>(ftell(file.get())) == size; |
| 629 } | 631 } |
| 630 | 632 |
| 631 } // namespace | 633 } // namespace |
| 632 | 634 |
| 633 // static | |
| 634 void SafeBrowsingStoreFile::CheckForOriginalAndDelete( | |
| 635 const base::FilePath& current_filename) { | |
| 636 const base::FilePath original_filename( | |
| 637 current_filename.DirName().AppendASCII("Safe Browsing")); | |
| 638 if (base::PathExists(original_filename)) { | |
| 639 int64 size = 0; | |
| 640 if (base::GetFileSize(original_filename, &size)) { | |
| 641 UMA_HISTOGRAM_COUNTS("SB2.OldDatabaseKilobytes", | |
|
Alexei Svitkine (slow)
2014/07/23 14:41:16
Can you mark this histogram with an <obsolete> tag
Scott Hess - ex-Googler
2014/07/23 17:18:19
Done.
| |
| 642 static_cast<int>(size / 1024)); | |
| 643 } | |
| 644 | |
| 645 if (base::DeleteFile(original_filename, false)) { | |
| 646 RecordFormatEvent(FORMAT_EVENT_DELETED_ORIGINAL); | |
| 647 } else { | |
| 648 RecordFormatEvent(FORMAT_EVENT_DELETED_ORIGINAL_FAILED); | |
| 649 } | |
| 650 | |
| 651 // Just best-effort on the journal file, don't want to get lost in | |
| 652 // the weeds. | |
| 653 const base::FilePath journal_filename( | |
| 654 current_filename.DirName().AppendASCII("Safe Browsing-journal")); | |
| 655 base::DeleteFile(journal_filename, false); | |
| 656 } | |
| 657 } | |
| 658 | |
| 659 SafeBrowsingStoreFile::SafeBrowsingStoreFile() | 635 SafeBrowsingStoreFile::SafeBrowsingStoreFile() |
| 660 : chunks_written_(0), empty_(false), corruption_seen_(false) {} | 636 : chunks_written_(0), empty_(false), corruption_seen_(false) {} |
| 661 | 637 |
| 662 SafeBrowsingStoreFile::~SafeBrowsingStoreFile() { | 638 SafeBrowsingStoreFile::~SafeBrowsingStoreFile() { |
| 663 Close(); | 639 Close(); |
| 664 } | 640 } |
| 665 | 641 |
| 666 bool SafeBrowsingStoreFile::Delete() { | 642 bool SafeBrowsingStoreFile::Delete() { |
| 667 // The database should not be open at this point. But, just in | 643 // The database should not be open at this point. But, just in |
| 668 // case, close everything before deleting. | 644 // case, close everything before deleting. |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 810 DCHECK(add_chunks_cache_.empty()); | 786 DCHECK(add_chunks_cache_.empty()); |
| 811 DCHECK(sub_chunks_cache_.empty()); | 787 DCHECK(sub_chunks_cache_.empty()); |
| 812 DCHECK(add_del_cache_.empty()); | 788 DCHECK(add_del_cache_.empty()); |
| 813 DCHECK(sub_del_cache_.empty()); | 789 DCHECK(sub_del_cache_.empty()); |
| 814 DCHECK(add_prefixes_.empty()); | 790 DCHECK(add_prefixes_.empty()); |
| 815 DCHECK(sub_prefixes_.empty()); | 791 DCHECK(sub_prefixes_.empty()); |
| 816 DCHECK(add_hashes_.empty()); | 792 DCHECK(add_hashes_.empty()); |
| 817 DCHECK(sub_hashes_.empty()); | 793 DCHECK(sub_hashes_.empty()); |
| 818 DCHECK_EQ(chunks_written_, 0); | 794 DCHECK_EQ(chunks_written_, 0); |
| 819 | 795 |
| 820 // Since the following code will already hit the profile looking for | |
| 821 // database files, this is a reasonable to time delete any old | |
| 822 // files. | |
| 823 CheckForOriginalAndDelete(filename_); | |
| 824 | |
| 825 corruption_seen_ = false; | 796 corruption_seen_ = false; |
| 826 | 797 |
| 827 const base::FilePath new_filename = TemporaryFileForFilename(filename_); | 798 const base::FilePath new_filename = TemporaryFileForFilename(filename_); |
| 828 base::ScopedFILE new_file(base::OpenFile(new_filename, "wb+")); | 799 base::ScopedFILE new_file(base::OpenFile(new_filename, "wb+")); |
| 829 if (new_file.get() == NULL) | 800 if (new_file.get() == NULL) |
| 830 return false; | 801 return false; |
| 831 | 802 |
| 832 base::ScopedFILE file(base::OpenFile(filename_, "rb")); | 803 base::ScopedFILE file(base::OpenFile(filename_, "rb")); |
| 833 empty_ = (file.get() == NULL); | 804 empty_ = (file.get() == NULL); |
| 834 if (empty_) { | 805 if (empty_) { |
| 835 // If the file exists but cannot be opened, try to delete it (not | 806 // If the file exists but cannot be opened, try to delete it (not |
| 836 // deleting directly, the bloom filter needs to be deleted, too). | 807 // deleting directly, the bloom filter needs to be deleted, too). |
| 837 if (base::PathExists(filename_)) | 808 if (base::PathExists(filename_)) |
| 838 return OnCorruptDatabase(); | 809 return OnCorruptDatabase(); |
| 839 | 810 |
| 840 new_file_.swap(new_file); | 811 new_file_.swap(new_file); |
| 841 return true; | 812 return true; |
| 842 } | 813 } |
| 843 | 814 |
| 844 base::MD5Context context; | 815 base::MD5Context context; |
| 845 FileHeader header; | 816 FileHeader header; |
| 846 const int version = | 817 const int version = |
| 847 ReadAndVerifyHeader(filename_, &header, | 818 ReadAndVerifyHeader(filename_, &header, |
| 848 &add_chunks_cache_, &sub_chunks_cache_, | 819 &add_chunks_cache_, &sub_chunks_cache_, |
| 849 file.get(), &context); | 820 file.get(), &context); |
| 850 if (version == kInvalidVersion) { | 821 if (version == kInvalidVersion) { |
| 851 FileHeaderV8 retry_header; | 822 FileHeaderV8 retry_header; |
| 852 if (FileRewind(file.get()) && ReadItem(&retry_header, file.get(), NULL) && | 823 if (FileRewind(file.get()) && ReadItem(&retry_header, file.get(), NULL)) { |
| 853 (retry_header.magic != kFileMagic || | 824 if (retry_header.magic == kFileMagic && retry_header.version < 7) { |
| 854 (retry_header.version != 8 && retry_header.version != 7))) { | 825 RecordFormatEvent(FORMAT_EVENT_FOUND_DEPRECATED); |
| 855 // TODO(shess): Think on whether these histograms are generating any | |
| 856 // actionable data. I kid you not, SQLITE happens many thousands of times | |
| 857 // per day, UNKNOWN about 3x higher than that. | |
| 858 if (!strcmp(reinterpret_cast<char*>(&retry_header.magic), | |
| 859 "SQLite format 3")) { | |
| 860 RecordFormatEvent(FORMAT_EVENT_FOUND_SQLITE); | |
| 861 } else { | 826 } else { |
| 862 RecordFormatEvent(FORMAT_EVENT_FOUND_UNKNOWN); | 827 RecordFormatEvent(FORMAT_EVENT_FOUND_UNKNOWN); |
| 863 } | 828 } |
| 864 } | 829 } |
| 865 | 830 |
| 866 // Close the file so that it can be deleted. | 831 // Close the file so that it can be deleted. |
| 867 file.reset(); | 832 file.reset(); |
| 868 | 833 |
| 869 return OnCorruptDatabase(); | 834 return OnCorruptDatabase(); |
| 870 } | 835 } |
| (...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1243 // With SQLite support gone, one way to get to this code is if the | 1208 // With SQLite support gone, one way to get to this code is if the |
| 1244 // existing file is a SQLite file. Make sure the journal file is | 1209 // existing file is a SQLite file. Make sure the journal file is |
| 1245 // also removed. | 1210 // also removed. |
| 1246 const base::FilePath journal_filename( | 1211 const base::FilePath journal_filename( |
| 1247 basename.value() + FILE_PATH_LITERAL("-journal")); | 1212 basename.value() + FILE_PATH_LITERAL("-journal")); |
| 1248 if (base::PathExists(journal_filename)) | 1213 if (base::PathExists(journal_filename)) |
| 1249 base::DeleteFile(journal_filename, false); | 1214 base::DeleteFile(journal_filename, false); |
| 1250 | 1215 |
| 1251 return true; | 1216 return true; |
| 1252 } | 1217 } |
| OLD | NEW |