| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "base/base64.h" | 5 #include "base/base64.h" |
| 6 #include "base/bind.h" | 6 #include "base/bind.h" |
| 7 #include "base/files/file_util.h" | 7 #include "base/files/file_util.h" |
| 8 #include "base/memory/ptr_util.h" | 8 #include "base/memory/ptr_util.h" |
| 9 #include "base/metrics/histogram_macros.h" | 9 #include "base/metrics/histogram_macros.h" |
| 10 #include "base/metrics/sparse_histogram.h" | 10 #include "base/metrics/sparse_histogram.h" |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 212 | 212 |
| 213 ApplyUpdateResult V4Store::ProcessPartialUpdateAndWriteToDisk( | 213 ApplyUpdateResult V4Store::ProcessPartialUpdateAndWriteToDisk( |
| 214 const std::string& metric, | 214 const std::string& metric, |
| 215 const HashPrefixMap& hash_prefix_map_old, | 215 const HashPrefixMap& hash_prefix_map_old, |
| 216 std::unique_ptr<ListUpdateResponse> response) { | 216 std::unique_ptr<ListUpdateResponse> response) { |
| 217 DCHECK(response->has_response_type()); | 217 DCHECK(response->has_response_type()); |
| 218 DCHECK_EQ(ListUpdateResponse::PARTIAL_UPDATE, response->response_type()); | 218 DCHECK_EQ(ListUpdateResponse::PARTIAL_UPDATE, response->response_type()); |
| 219 | 219 |
| 220 ApplyUpdateResult result = | 220 ApplyUpdateResult result = |
| 221 ProcessUpdate(metric, hash_prefix_map_old, response); | 221 ProcessUpdate(metric, hash_prefix_map_old, response); |
| 222 if (result == APPLY_UPDATE_SUCCESS) { |
| 223 Checksum checksum = response->checksum(); |
| 224 response.reset(); |
| 225 RecordStoreWriteResult(WriteToDisk(checksum)); |
| 226 } |
| 222 return result; | 227 return result; |
| 223 } | 228 } |
| 224 | 229 |
| 225 ApplyUpdateResult V4Store::ProcessFullUpdateAndWriteToDisk( | 230 ApplyUpdateResult V4Store::ProcessFullUpdateAndWriteToDisk( |
| 226 const std::string& metric, | 231 const std::string& metric, |
| 227 std::unique_ptr<ListUpdateResponse> response) { | 232 std::unique_ptr<ListUpdateResponse> response) { |
| 228 ApplyUpdateResult result = ProcessFullUpdate(metric, response); | 233 ApplyUpdateResult result = ProcessFullUpdate(metric, response); |
| 229 if (result == APPLY_UPDATE_SUCCESS) { | 234 if (result == APPLY_UPDATE_SUCCESS) { |
| 230 RecordStoreWriteResult(WriteToDisk(std::move(response))); | 235 Checksum checksum = response->checksum(); |
| 236 response.reset(); |
| 237 RecordStoreWriteResult(WriteToDisk(checksum)); |
| 231 } | 238 } |
| 232 return result; | 239 return result; |
| 233 } | 240 } |
| 234 | 241 |
| 235 ApplyUpdateResult V4Store::ProcessFullUpdate( | 242 ApplyUpdateResult V4Store::ProcessFullUpdate( |
| 236 const std::string& metric, | 243 const std::string& metric, |
| 237 const std::unique_ptr<ListUpdateResponse>& response) { | 244 const std::unique_ptr<ListUpdateResponse>& response) { |
| 238 DCHECK(response->has_response_type()); | 245 DCHECK(response->has_response_type()); |
| 239 DCHECK_EQ(ListUpdateResponse::FULL_UPDATE, response->response_type()); | 246 DCHECK_EQ(ListUpdateResponse::FULL_UPDATE, response->response_type()); |
| 240 // TODO(vakh): For a full update, we don't need to process the update in | 247 // TODO(vakh): For a full update, we don't need to process the update in |
| (...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 620 } | 627 } |
| 621 } | 628 } |
| 622 } | 629 } |
| 623 | 630 |
| 624 return APPLY_UPDATE_SUCCESS; | 631 return APPLY_UPDATE_SUCCESS; |
| 625 } | 632 } |
| 626 | 633 |
| 627 StoreReadResult V4Store::ReadFromDisk() { | 634 StoreReadResult V4Store::ReadFromDisk() { |
| 628 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 635 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 629 | 636 |
| 637 V4StoreFileFormat file_format; |
| 630 TimeTicks before = TimeTicks::Now(); | 638 TimeTicks before = TimeTicks::Now(); |
| 631 std::string contents; | 639 { |
| 632 bool read_success = base::ReadFileToString(store_path_, &contents); | 640 // A temporary scope to make sure that |contents| get destroyed as soon as |
| 633 if (!read_success) { | 641 // we are doing using it. |
| 634 return FILE_UNREADABLE_FAILURE; | 642 std::string contents; |
| 635 } | 643 bool read_success = base::ReadFileToString(store_path_, &contents); |
| 644 if (!read_success) { |
| 645 return FILE_UNREADABLE_FAILURE; |
| 646 } |
| 636 | 647 |
| 637 if (contents.empty()) { | 648 if (contents.empty()) { |
| 638 return FILE_EMPTY_FAILURE; | 649 return FILE_EMPTY_FAILURE; |
| 639 } | 650 } |
| 640 | 651 |
| 641 V4StoreFileFormat file_format; | 652 if (!file_format.ParseFromString(contents)) { |
| 642 if (!file_format.ParseFromString(contents)) { | 653 return PROTO_PARSING_FAILURE; |
| 643 return PROTO_PARSING_FAILURE; | 654 } |
| 644 } | 655 } |
| 645 | 656 |
| 646 if (file_format.magic_number() != kFileMagic) { | 657 if (file_format.magic_number() != kFileMagic) { |
| 647 return UNEXPECTED_MAGIC_NUMBER_FAILURE; | 658 return UNEXPECTED_MAGIC_NUMBER_FAILURE; |
| 648 } | 659 } |
| 649 | 660 |
| 650 UMA_HISTOGRAM_SPARSE_SLOWLY("SafeBrowsing.V4StoreVersionRead", | 661 UMA_HISTOGRAM_SPARSE_SLOWLY("SafeBrowsing.V4StoreVersionRead", |
| 651 file_format.version_number()); | 662 file_format.version_number()); |
| 652 if (file_format.version_number() != kFileVersion) { | 663 if (file_format.version_number() != kFileVersion) { |
| 653 return FILE_VERSION_INCOMPATIBLE_FAILURE; | 664 return FILE_VERSION_INCOMPATIBLE_FAILURE; |
| (...skipping 10 matching lines...) Expand all Loading... |
| 664 RecordApplyUpdateResult(kReadFromDisk, apply_update_result, store_path_); | 675 RecordApplyUpdateResult(kReadFromDisk, apply_update_result, store_path_); |
| 665 if (apply_update_result != APPLY_UPDATE_SUCCESS) { | 676 if (apply_update_result != APPLY_UPDATE_SUCCESS) { |
| 666 hash_prefix_map_.clear(); | 677 hash_prefix_map_.clear(); |
| 667 return HASH_PREFIX_MAP_GENERATION_FAILURE; | 678 return HASH_PREFIX_MAP_GENERATION_FAILURE; |
| 668 } | 679 } |
| 669 RecordApplyUpdateTime(kReadFromDisk, TimeTicks::Now() - before, store_path_); | 680 RecordApplyUpdateTime(kReadFromDisk, TimeTicks::Now() - before, store_path_); |
| 670 | 681 |
| 671 return READ_SUCCESS; | 682 return READ_SUCCESS; |
| 672 } | 683 } |
| 673 | 684 |
| 674 StoreWriteResult V4Store::WriteToDisk( | 685 StoreWriteResult V4Store::WriteToDisk(const Checksum& checksum) const { |
| 675 std::unique_ptr<ListUpdateResponse> response) const { | 686 V4StoreFileFormat file_format; |
| 676 // Do not write partial updates to the disk. | 687 ListUpdateResponse* lur = file_format.mutable_list_update_response(); |
| 677 // After merging the updates, the ListUpdateResponse passed to this method | 688 *(lur->mutable_checksum()) = checksum; |
| 678 // should be a FULL_UPDATE. | 689 lur->set_new_client_state(state_); |
| 679 if (!response->has_response_type() || | 690 lur->set_response_type(ListUpdateResponse::FULL_UPDATE); |
| 680 response->response_type() != ListUpdateResponse::FULL_UPDATE) { | 691 for (auto map_iter : hash_prefix_map_) { |
| 681 DVLOG(1) << "Failure: response->has_response_type(): " | 692 ThreatEntrySet* additions = lur->add_additions(); |
| 682 << response->has_response_type() | 693 // TODO(vakh): Write RICE encoded hash prefixes on disk. Not doing so |
| 683 << " : response->response_type(): " << response->response_type(); | 694 // currently since it takes a long time to decode them on startup, which |
| 684 return INVALID_RESPONSE_TYPE_FAILURE; | 695 // blocks resource load. See: http://crbug.com/654819 |
| 696 additions->set_compression_type(RAW); |
| 697 additions->mutable_raw_hashes()->set_prefix_size(map_iter.first); |
| 698 additions->mutable_raw_hashes()->set_raw_hashes(map_iter.second); |
| 685 } | 699 } |
| 686 | 700 |
| 687 // Attempt writing to a temporary file first and at the end, swap the files. | 701 // Attempt writing to a temporary file first and at the end, swap the files. |
| 688 const base::FilePath new_filename = TemporaryFileForFilename(store_path_); | 702 const base::FilePath new_filename = TemporaryFileForFilename(store_path_); |
| 689 | 703 |
| 690 V4StoreFileFormat file_format; | |
| 691 file_format.set_magic_number(kFileMagic); | 704 file_format.set_magic_number(kFileMagic); |
| 692 file_format.set_version_number(kFileVersion); | 705 file_format.set_version_number(kFileVersion); |
| 693 ListUpdateResponse* response_to_write = | |
| 694 file_format.mutable_list_update_response(); | |
| 695 response_to_write->Swap(response.get()); | |
| 696 std::string file_format_string; | 706 std::string file_format_string; |
| 697 file_format.SerializeToString(&file_format_string); | 707 file_format.SerializeToString(&file_format_string); |
| 698 size_t written = base::WriteFile(new_filename, file_format_string.data(), | 708 size_t written = base::WriteFile(new_filename, file_format_string.data(), |
| 699 file_format_string.size()); | 709 file_format_string.size()); |
| 700 DCHECK_EQ(file_format_string.size(), written); | 710 DCHECK_EQ(file_format_string.size(), written); |
| 701 | 711 |
| 702 if (!base::Move(new_filename, store_path_)) { | 712 if (!base::Move(new_filename, store_path_)) { |
| 703 return UNABLE_TO_RENAME_FAILURE; | 713 return UNABLE_TO_RENAME_FAILURE; |
| 704 } | 714 } |
| 705 | 715 |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 794 << "; expected: " << expected_checksum_b64 | 804 << "; expected: " << expected_checksum_b64 |
| 795 << "; store: " << *this; | 805 << "; store: " << *this; |
| 796 #endif | 806 #endif |
| 797 return false; | 807 return false; |
| 798 } | 808 } |
| 799 } | 809 } |
| 800 return true; | 810 return true; |
| 801 } | 811 } |
| 802 | 812 |
| 803 } // namespace safe_browsing | 813 } // namespace safe_browsing |
| OLD | NEW |