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" |
11 #include "base/stl_util.h" | 11 #include "base/stl_util.h" |
12 #include "base/strings/stringprintf.h" | 12 #include "base/strings/stringprintf.h" |
13 #include "components/safe_browsing_db/v4_rice.h" | 13 #include "components/safe_browsing_db/v4_rice.h" |
14 #include "components/safe_browsing_db/v4_store.h" | 14 #include "components/safe_browsing_db/v4_store.h" |
15 #include "components/safe_browsing_db/v4_store.pb.h" | 15 #include "components/safe_browsing_db/v4_store.pb.h" |
16 #include "crypto/secure_hash.h" | 16 #include "crypto/secure_hash.h" |
17 #include "crypto/sha2.h" | 17 #include "crypto/sha2.h" |
18 | 18 |
| 19 using base::TimeTicks; |
| 20 |
19 namespace safe_browsing { | 21 namespace safe_browsing { |
20 | 22 |
21 namespace { | 23 namespace { |
| 24 |
22 const uint32_t kFileMagic = 0x600D71FE; | 25 const uint32_t kFileMagic = 0x600D71FE; |
23 | 26 |
24 const uint32_t kFileVersion = 9; | 27 const uint32_t kFileVersion = 9; |
25 | 28 |
26 void RecordStoreReadResult(StoreReadResult result) { | 29 std::string GetUmaSuffixForStore(const base::FilePath& file_path) { |
27 UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.V4StoreReadResult", result, | 30 return base::StringPrintf( |
28 STORE_READ_RESULT_MAX); | 31 ".%" PRIsFP, file_path.BaseName().RemoveExtension().value().c_str()); |
29 } | 32 } |
30 | 33 |
31 void RecordStoreWriteResult(StoreWriteResult result) { | 34 void RecordTimeWithAndWithoutStore(const std::string& metric, |
32 UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.V4StoreWriteResult", result, | 35 base::TimeDelta time, |
33 STORE_WRITE_RESULT_MAX); | 36 const base::FilePath& file_path) { |
| 37 std::string suffix = GetUmaSuffixForStore(file_path); |
| 38 |
| 39 // The histograms below are a modified expansion of the |
| 40 // UMA_HISTOGRAM_LONG_TIMES macro adapted to allow for a dynamically suffixed |
| 41 // histogram name. |
| 42 // Note: The factory creates and owns the histogram. |
| 43 const int kBucketCount = 100; |
| 44 base::HistogramBase* histogram = base::Histogram::FactoryTimeGet( |
| 45 metric, base::TimeDelta::FromMilliseconds(1), |
| 46 base::TimeDelta::FromMinutes(1), kBucketCount, |
| 47 base::HistogramBase::kUmaTargetedHistogramFlag); |
| 48 if (histogram) { |
| 49 histogram->AddTime(time); |
| 50 } |
| 51 |
| 52 base::HistogramBase* histogram_suffix = base::Histogram::FactoryTimeGet( |
| 53 metric + suffix, base::TimeDelta::FromMilliseconds(1), |
| 54 base::TimeDelta::FromMinutes(1), kBucketCount, |
| 55 base::HistogramBase::kUmaTargetedHistogramFlag); |
| 56 if (histogram_suffix) { |
| 57 histogram_suffix->AddTime(time); |
| 58 } |
| 59 } |
| 60 |
| 61 void RecordAddUnlumpedHashesTime(base::TimeDelta time) { |
| 62 UMA_HISTOGRAM_LONG_TIMES("SafeBrowsing.V4AddUnlumpedHashesTime", time); |
34 } | 63 } |
35 | 64 |
36 void RecordApplyUpdateResult(ApplyUpdateResult result) { | 65 void RecordApplyUpdateResult(ApplyUpdateResult result) { |
37 UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.V4ApplyUpdateResult", result, | 66 UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.V4ApplyUpdateResult", result, |
38 APPLY_UPDATE_RESULT_MAX); | 67 APPLY_UPDATE_RESULT_MAX); |
39 } | 68 } |
40 | 69 |
| 70 void RecordApplyUpdateResultWhenReadingFromDisk(ApplyUpdateResult result) { |
| 71 UMA_HISTOGRAM_ENUMERATION( |
| 72 "SafeBrowsing.V4ApplyUpdateResultWhenReadingFromDisk", result, |
| 73 APPLY_UPDATE_RESULT_MAX); |
| 74 } |
| 75 |
41 void RecordDecodeAdditionsResult(V4DecodeResult result) { | 76 void RecordDecodeAdditionsResult(V4DecodeResult result) { |
42 UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.V4DecodeAdditionsResult", result, | 77 UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.V4DecodeAdditionsResult", result, |
43 DECODE_RESULT_MAX); | 78 DECODE_RESULT_MAX); |
44 } | 79 } |
45 | 80 |
| 81 void RecordDecodeAdditionsTime(base::TimeDelta time, |
| 82 const base::FilePath& file_path) { |
| 83 RecordTimeWithAndWithoutStore("SafeBrowsing.V4DecodeAdditionsTime", time, |
| 84 file_path); |
| 85 } |
| 86 |
46 void RecordDecodeRemovalsResult(V4DecodeResult result) { | 87 void RecordDecodeRemovalsResult(V4DecodeResult result) { |
47 UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.V4DecodeRemovalsResult", result, | 88 UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.V4DecodeRemovalsResult", result, |
48 DECODE_RESULT_MAX); | 89 DECODE_RESULT_MAX); |
49 } | 90 } |
50 | 91 |
51 // TODO(vakh): Collect and record the metrics for time taken to process updates. | 92 void RecordDecodeRemovalsTime(base::TimeDelta time, |
| 93 const base::FilePath& file_path) { |
| 94 RecordTimeWithAndWithoutStore("SafeBrowsing.V4DecodeRemovalsTime", time, |
| 95 file_path); |
| 96 } |
52 | 97 |
53 void RecordApplyUpdateResultWhenReadingFromDisk(ApplyUpdateResult result) { | 98 void RecordMergeUpdateTime(base::TimeDelta time, |
54 UMA_HISTOGRAM_ENUMERATION( | 99 const base::FilePath& file_path) { |
55 "SafeBrowsing.V4ApplyUpdateResultWhenReadingFromDisk", result, | 100 RecordTimeWithAndWithoutStore("SafeBrowsing.V4MergeUpdateTime", time, |
56 APPLY_UPDATE_RESULT_MAX); | 101 file_path); |
| 102 } |
| 103 |
| 104 void RecordProcessFullUpdateTime(base::TimeDelta time, |
| 105 const base::FilePath& file_path) { |
| 106 RecordTimeWithAndWithoutStore("SafeBrowsing.V4ProcessFullUpdateTime", time, |
| 107 file_path); |
| 108 } |
| 109 |
| 110 void RecordProcessPartialUpdateTime(base::TimeDelta time, |
| 111 const base::FilePath& file_path) { |
| 112 RecordTimeWithAndWithoutStore("SafeBrowsing.V4ProcessPartialUpdateTime", time, |
| 113 file_path); |
| 114 } |
| 115 |
| 116 void RecordReadFromDiskTime(base::TimeDelta time, |
| 117 const base::FilePath& file_path) { |
| 118 RecordTimeWithAndWithoutStore("SafeBrowsing.V4ReadFromDiskTime", time, |
| 119 file_path); |
| 120 } |
| 121 |
| 122 void RecordStoreReadResult(StoreReadResult result) { |
| 123 UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.V4StoreReadResult", result, |
| 124 STORE_READ_RESULT_MAX); |
| 125 } |
| 126 |
| 127 void RecordStoreWriteResult(StoreWriteResult result) { |
| 128 UMA_HISTOGRAM_ENUMERATION("SafeBrowsing.V4StoreWriteResult", result, |
| 129 STORE_WRITE_RESULT_MAX); |
57 } | 130 } |
58 | 131 |
59 // Returns the name of the temporary file used to buffer data for | 132 // Returns the name of the temporary file used to buffer data for |
60 // |filename|. Exported for unit tests. | 133 // |filename|. Exported for unit tests. |
61 const base::FilePath TemporaryFileForFilename(const base::FilePath& filename) { | 134 const base::FilePath TemporaryFileForFilename(const base::FilePath& filename) { |
62 return base::FilePath(filename.value() + FILE_PATH_LITERAL("_new")); | 135 return base::FilePath(filename.value() + FILE_PATH_LITERAL("_new")); |
63 } | 136 } |
64 | 137 |
65 } // namespace | 138 } // namespace |
66 | 139 |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
108 state_ = ""; | 181 state_ = ""; |
109 return true; | 182 return true; |
110 } | 183 } |
111 | 184 |
112 ApplyUpdateResult V4Store::ProcessPartialUpdateAndWriteToDisk( | 185 ApplyUpdateResult V4Store::ProcessPartialUpdateAndWriteToDisk( |
113 const HashPrefixMap& hash_prefix_map_old, | 186 const HashPrefixMap& hash_prefix_map_old, |
114 std::unique_ptr<ListUpdateResponse> response) { | 187 std::unique_ptr<ListUpdateResponse> response) { |
115 DCHECK(response->has_response_type()); | 188 DCHECK(response->has_response_type()); |
116 DCHECK_EQ(ListUpdateResponse::PARTIAL_UPDATE, response->response_type()); | 189 DCHECK_EQ(ListUpdateResponse::PARTIAL_UPDATE, response->response_type()); |
117 | 190 |
| 191 TimeTicks before = TimeTicks::Now(); |
118 ApplyUpdateResult result = ProcessUpdate(hash_prefix_map_old, response); | 192 ApplyUpdateResult result = ProcessUpdate(hash_prefix_map_old, response); |
119 if (result == APPLY_UPDATE_SUCCESS) { | 193 if (result == APPLY_UPDATE_SUCCESS) { |
| 194 RecordProcessPartialUpdateTime(TimeTicks::Now() - before, store_path_); |
120 // TODO(vakh): Create a ListUpdateResponse containing RICE encoded | 195 // TODO(vakh): Create a ListUpdateResponse containing RICE encoded |
121 // hash prefixes and response_type as FULL_UPDATE, and write that to disk. | 196 // hash prefixes and response_type as FULL_UPDATE, and write that to disk. |
122 } | 197 } |
123 return result; | 198 return result; |
124 } | 199 } |
125 | 200 |
126 ApplyUpdateResult V4Store::ProcessFullUpdateAndWriteToDisk( | 201 ApplyUpdateResult V4Store::ProcessFullUpdateAndWriteToDisk( |
127 std::unique_ptr<ListUpdateResponse> response) { | 202 std::unique_ptr<ListUpdateResponse> response) { |
| 203 TimeTicks before = TimeTicks::Now(); |
128 ApplyUpdateResult result = ProcessFullUpdate(response); | 204 ApplyUpdateResult result = ProcessFullUpdate(response); |
129 if (result == APPLY_UPDATE_SUCCESS) { | 205 if (result == APPLY_UPDATE_SUCCESS) { |
130 RecordStoreWriteResult(WriteToDisk(std::move(response))); | 206 RecordStoreWriteResult(WriteToDisk(std::move(response))); |
| 207 RecordProcessFullUpdateTime(TimeTicks::Now() - before, store_path_); |
131 } | 208 } |
132 return result; | 209 return result; |
133 } | 210 } |
134 | 211 |
135 ApplyUpdateResult V4Store::ProcessFullUpdate( | 212 ApplyUpdateResult V4Store::ProcessFullUpdate( |
136 const std::unique_ptr<ListUpdateResponse>& response) { | 213 const std::unique_ptr<ListUpdateResponse>& response) { |
137 DCHECK(response->has_response_type()); | 214 DCHECK(response->has_response_type()); |
138 DCHECK_EQ(ListUpdateResponse::FULL_UPDATE, response->response_type()); | 215 DCHECK_EQ(ListUpdateResponse::FULL_UPDATE, response->response_type()); |
139 // TODO(vakh): For a full update, we don't need to process the update in | 216 // TODO(vakh): For a full update, we don't need to process the update in |
140 // lexographical order to store it, but we do need to do that for calculating | 217 // lexographical order to store it, but we do need to do that for calculating |
(...skipping 12 matching lines...) Expand all Loading... |
153 DCHECK_LE(removals_size, 1u); | 230 DCHECK_LE(removals_size, 1u); |
154 if (removals_size == 1) { | 231 if (removals_size == 1) { |
155 const ThreatEntrySet& removal = response->removals().Get(0); | 232 const ThreatEntrySet& removal = response->removals().Get(0); |
156 const CompressionType compression_type = removal.compression_type(); | 233 const CompressionType compression_type = removal.compression_type(); |
157 if (compression_type == RAW) { | 234 if (compression_type == RAW) { |
158 raw_removals = &removal.raw_indices().indices(); | 235 raw_removals = &removal.raw_indices().indices(); |
159 } else if (compression_type == RICE) { | 236 } else if (compression_type == RICE) { |
160 DCHECK(removal.has_rice_indices()); | 237 DCHECK(removal.has_rice_indices()); |
161 | 238 |
162 const RiceDeltaEncoding& rice_indices = removal.rice_indices(); | 239 const RiceDeltaEncoding& rice_indices = removal.rice_indices(); |
| 240 TimeTicks before = TimeTicks::Now(); |
163 V4DecodeResult decode_result = V4RiceDecoder::DecodeIntegers( | 241 V4DecodeResult decode_result = V4RiceDecoder::DecodeIntegers( |
164 rice_indices.first_value(), rice_indices.rice_parameter(), | 242 rice_indices.first_value(), rice_indices.rice_parameter(), |
165 rice_indices.num_entries(), rice_indices.encoded_data(), | 243 rice_indices.num_entries(), rice_indices.encoded_data(), |
166 &rice_removals); | 244 &rice_removals); |
| 245 |
167 RecordDecodeRemovalsResult(decode_result); | 246 RecordDecodeRemovalsResult(decode_result); |
168 if (decode_result != DECODE_SUCCESS) { | 247 if (decode_result != DECODE_SUCCESS) { |
169 return RICE_DECODING_FAILURE; | 248 return RICE_DECODING_FAILURE; |
170 } else { | |
171 raw_removals = &rice_removals; | |
172 } | 249 } |
| 250 RecordDecodeRemovalsTime(TimeTicks::Now() - before, store_path_); |
| 251 raw_removals = &rice_removals; |
173 } else { | 252 } else { |
174 NOTREACHED() << "Unexpected compression_type type: " << compression_type; | 253 NOTREACHED() << "Unexpected compression_type type: " << compression_type; |
175 return UNEXPECTED_COMPRESSION_TYPE_REMOVALS_FAILURE; | 254 return UNEXPECTED_COMPRESSION_TYPE_REMOVALS_FAILURE; |
176 } | 255 } |
177 } | 256 } |
178 | 257 |
179 HashPrefixMap hash_prefix_map; | 258 HashPrefixMap hash_prefix_map; |
180 ApplyUpdateResult apply_update_result = | 259 ApplyUpdateResult apply_update_result = |
181 UpdateHashPrefixMapFromAdditions(response->additions(), &hash_prefix_map); | 260 UpdateHashPrefixMapFromAdditions(response->additions(), &hash_prefix_map); |
182 if (apply_update_result != APPLY_UPDATE_SUCCESS) { | 261 if (apply_update_result != APPLY_UPDATE_SUCCESS) { |
183 return apply_update_result; | 262 return apply_update_result; |
184 } | 263 } |
185 | 264 |
186 std::string expected_checksum; | 265 std::string expected_checksum; |
187 if (response->has_checksum() && response->checksum().has_sha256()) { | 266 if (response->has_checksum() && response->checksum().has_sha256()) { |
188 expected_checksum = response->checksum().sha256(); | 267 expected_checksum = response->checksum().sha256(); |
189 } | 268 } |
190 | 269 |
| 270 TimeTicks before = TimeTicks::Now(); |
191 apply_update_result = MergeUpdate(hash_prefix_map_old, hash_prefix_map, | 271 apply_update_result = MergeUpdate(hash_prefix_map_old, hash_prefix_map, |
192 raw_removals, expected_checksum); | 272 raw_removals, expected_checksum); |
193 if (apply_update_result != APPLY_UPDATE_SUCCESS) { | 273 if (apply_update_result != APPLY_UPDATE_SUCCESS) { |
194 return apply_update_result; | 274 return apply_update_result; |
195 } | 275 } |
| 276 RecordMergeUpdateTime(TimeTicks::Now() - before, store_path_); |
196 | 277 |
197 state_ = response->new_client_state(); | 278 state_ = response->new_client_state(); |
198 return APPLY_UPDATE_SUCCESS; | 279 return APPLY_UPDATE_SUCCESS; |
199 } | 280 } |
200 | 281 |
201 void V4Store::ApplyUpdate( | 282 void V4Store::ApplyUpdate( |
202 std::unique_ptr<ListUpdateResponse> response, | 283 std::unique_ptr<ListUpdateResponse> response, |
203 const scoped_refptr<base::SingleThreadTaskRunner>& callback_task_runner, | 284 const scoped_refptr<base::SingleThreadTaskRunner>& callback_task_runner, |
204 UpdatedStoreReadyCallback callback) { | 285 UpdatedStoreReadyCallback callback) { |
205 std::unique_ptr<V4Store> new_store( | 286 std::unique_ptr<V4Store> new_store( |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 DCHECK(addition.raw_hashes().has_raw_hashes()); | 324 DCHECK(addition.raw_hashes().has_raw_hashes()); |
244 | 325 |
245 apply_update_result = | 326 apply_update_result = |
246 AddUnlumpedHashes(addition.raw_hashes().prefix_size(), | 327 AddUnlumpedHashes(addition.raw_hashes().prefix_size(), |
247 addition.raw_hashes().raw_hashes(), additions_map); | 328 addition.raw_hashes().raw_hashes(), additions_map); |
248 } else if (compression_type == RICE) { | 329 } else if (compression_type == RICE) { |
249 DCHECK(addition.has_rice_hashes()); | 330 DCHECK(addition.has_rice_hashes()); |
250 | 331 |
251 const RiceDeltaEncoding& rice_hashes = addition.rice_hashes(); | 332 const RiceDeltaEncoding& rice_hashes = addition.rice_hashes(); |
252 std::vector<uint32_t> raw_hashes; | 333 std::vector<uint32_t> raw_hashes; |
| 334 TimeTicks before = TimeTicks::Now(); |
253 V4DecodeResult decode_result = V4RiceDecoder::DecodePrefixes( | 335 V4DecodeResult decode_result = V4RiceDecoder::DecodePrefixes( |
254 rice_hashes.first_value(), rice_hashes.rice_parameter(), | 336 rice_hashes.first_value(), rice_hashes.rice_parameter(), |
255 rice_hashes.num_entries(), rice_hashes.encoded_data(), &raw_hashes); | 337 rice_hashes.num_entries(), rice_hashes.encoded_data(), &raw_hashes); |
256 RecordDecodeAdditionsResult(decode_result); | 338 RecordDecodeAdditionsResult(decode_result); |
257 if (decode_result != DECODE_SUCCESS) { | 339 if (decode_result != DECODE_SUCCESS) { |
258 return RICE_DECODING_FAILURE; | 340 return RICE_DECODING_FAILURE; |
259 } else { | 341 } else { |
| 342 RecordDecodeAdditionsTime(TimeTicks::Now() - before, store_path_); |
260 char* raw_hashes_start = reinterpret_cast<char*>(raw_hashes.data()); | 343 char* raw_hashes_start = reinterpret_cast<char*>(raw_hashes.data()); |
261 size_t raw_hashes_size = sizeof(uint32_t) * raw_hashes.size(); | 344 size_t raw_hashes_size = sizeof(uint32_t) * raw_hashes.size(); |
262 | 345 |
263 // Rice-Golomb encoding is used to send compressed compressed 4-byte | 346 // Rice-Golomb encoding is used to send compressed compressed 4-byte |
264 // hash prefixes. Hash prefixes longer than 4 bytes will not be | 347 // hash prefixes. Hash prefixes longer than 4 bytes will not be |
265 // compressed, and will be served in raw format instead. | 348 // compressed, and will be served in raw format instead. |
266 // Source: https://developers.google.com/safe-browsing/v4/compression | 349 // Source: https://developers.google.com/safe-browsing/v4/compression |
267 const PrefixSize kPrefixSize = 4; | 350 const PrefixSize kPrefixSize = 4; |
268 apply_update_result = AddUnlumpedHashes(kPrefixSize, raw_hashes_start, | 351 apply_update_result = AddUnlumpedHashes(kPrefixSize, raw_hashes_start, |
269 raw_hashes_size, additions_map); | 352 raw_hashes_size, additions_map); |
(...skipping 30 matching lines...) Expand all Loading... |
300 return PREFIX_SIZE_TOO_SMALL_FAILURE; | 383 return PREFIX_SIZE_TOO_SMALL_FAILURE; |
301 } | 384 } |
302 if (prefix_size > kMaxHashPrefixLength) { | 385 if (prefix_size > kMaxHashPrefixLength) { |
303 NOTREACHED(); | 386 NOTREACHED(); |
304 return PREFIX_SIZE_TOO_LARGE_FAILURE; | 387 return PREFIX_SIZE_TOO_LARGE_FAILURE; |
305 } | 388 } |
306 if (raw_hashes_length % prefix_size != 0) { | 389 if (raw_hashes_length % prefix_size != 0) { |
307 return ADDITIONS_SIZE_UNEXPECTED_FAILURE; | 390 return ADDITIONS_SIZE_UNEXPECTED_FAILURE; |
308 } | 391 } |
309 | 392 |
| 393 TimeTicks before = TimeTicks::Now(); |
310 // TODO(vakh): Figure out a way to avoid the following copy operation. | 394 // TODO(vakh): Figure out a way to avoid the following copy operation. |
311 (*additions_map)[prefix_size] = | 395 (*additions_map)[prefix_size] = |
312 std::string(raw_hashes_begin, raw_hashes_begin + raw_hashes_length); | 396 std::string(raw_hashes_begin, raw_hashes_begin + raw_hashes_length); |
| 397 RecordAddUnlumpedHashesTime(TimeTicks::Now() - before); |
313 return APPLY_UPDATE_SUCCESS; | 398 return APPLY_UPDATE_SUCCESS; |
314 } | 399 } |
315 | 400 |
316 // static | 401 // static |
317 bool V4Store::GetNextSmallestUnmergedPrefix( | 402 bool V4Store::GetNextSmallestUnmergedPrefix( |
318 const HashPrefixMap& hash_prefix_map, | 403 const HashPrefixMap& hash_prefix_map, |
319 const IteratorMap& iterator_map, | 404 const IteratorMap& iterator_map, |
320 HashPrefix* smallest_hash_prefix) { | 405 HashPrefix* smallest_hash_prefix) { |
321 HashPrefix current_hash_prefix; | 406 HashPrefix current_hash_prefix; |
322 bool has_unmerged = false; | 407 bool has_unmerged = false; |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
480 return CHECKSUM_MISMATCH_FAILURE; | 565 return CHECKSUM_MISMATCH_FAILURE; |
481 } | 566 } |
482 } | 567 } |
483 | 568 |
484 return APPLY_UPDATE_SUCCESS; | 569 return APPLY_UPDATE_SUCCESS; |
485 } | 570 } |
486 | 571 |
487 StoreReadResult V4Store::ReadFromDisk() { | 572 StoreReadResult V4Store::ReadFromDisk() { |
488 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 573 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
489 | 574 |
| 575 TimeTicks before = TimeTicks::Now(); |
490 std::string contents; | 576 std::string contents; |
491 bool read_success = base::ReadFileToString(store_path_, &contents); | 577 bool read_success = base::ReadFileToString(store_path_, &contents); |
492 if (!read_success) { | 578 if (!read_success) { |
493 return FILE_UNREADABLE_FAILURE; | 579 return FILE_UNREADABLE_FAILURE; |
494 } | 580 } |
495 | 581 |
496 if (contents.empty()) { | 582 if (contents.empty()) { |
497 return FILE_EMPTY_FAILURE; | 583 return FILE_EMPTY_FAILURE; |
498 } | 584 } |
499 | 585 |
(...skipping 17 matching lines...) Expand all Loading... |
517 } | 603 } |
518 | 604 |
519 std::unique_ptr<ListUpdateResponse> response(new ListUpdateResponse); | 605 std::unique_ptr<ListUpdateResponse> response(new ListUpdateResponse); |
520 response->Swap(file_format.mutable_list_update_response()); | 606 response->Swap(file_format.mutable_list_update_response()); |
521 ApplyUpdateResult apply_update_result = ProcessFullUpdate(response); | 607 ApplyUpdateResult apply_update_result = ProcessFullUpdate(response); |
522 RecordApplyUpdateResultWhenReadingFromDisk(apply_update_result); | 608 RecordApplyUpdateResultWhenReadingFromDisk(apply_update_result); |
523 if (apply_update_result != APPLY_UPDATE_SUCCESS) { | 609 if (apply_update_result != APPLY_UPDATE_SUCCESS) { |
524 hash_prefix_map_.clear(); | 610 hash_prefix_map_.clear(); |
525 return HASH_PREFIX_MAP_GENERATION_FAILURE; | 611 return HASH_PREFIX_MAP_GENERATION_FAILURE; |
526 } | 612 } |
| 613 RecordReadFromDiskTime(TimeTicks::Now() - before, store_path_); |
527 | 614 |
528 return READ_SUCCESS; | 615 return READ_SUCCESS; |
529 } | 616 } |
530 | 617 |
531 StoreWriteResult V4Store::WriteToDisk( | 618 StoreWriteResult V4Store::WriteToDisk( |
532 std::unique_ptr<ListUpdateResponse> response) const { | 619 std::unique_ptr<ListUpdateResponse> response) const { |
533 // Do not write partial updates to the disk. | 620 // Do not write partial updates to the disk. |
534 // After merging the updates, the ListUpdateResponse passed to this method | 621 // After merging the updates, the ListUpdateResponse passed to this method |
535 // should be a FULL_UPDATE. | 622 // should be a FULL_UPDATE. |
536 if (!response->has_response_type() || | 623 if (!response->has_response_type() || |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
597 if (result == 0) { | 684 if (result == 0) { |
598 return true; | 685 return true; |
599 } else if (result < 0) { | 686 } else if (result < 0) { |
600 return HashPrefixMatches(hash_prefix, begin, mid); | 687 return HashPrefixMatches(hash_prefix, begin, mid); |
601 } else { | 688 } else { |
602 return HashPrefixMatches(hash_prefix, mid + prefix_size, end); | 689 return HashPrefixMatches(hash_prefix, mid + prefix_size, end); |
603 } | 690 } |
604 } | 691 } |
605 | 692 |
606 } // namespace safe_browsing | 693 } // namespace safe_browsing |
OLD | NEW |