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 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
235 // - Any prefix set hit should be a bloom filter hit. | 235 // - Any prefix set hit should be a bloom filter hit. |
236 // - Bloom filter false positives are prefix set misses. | 236 // - Bloom filter false positives are prefix set misses. |
237 // The following is to log actual performance to verify this. | 237 // The following is to log actual performance to verify this. |
238 enum PrefixSetEvent { | 238 enum PrefixSetEvent { |
239 // Hits to prefix set and bloom filter. | 239 // Hits to prefix set and bloom filter. |
240 PREFIX_SET_HIT, | 240 PREFIX_SET_HIT, |
241 PREFIX_SET_BLOOM_HIT, | 241 PREFIX_SET_BLOOM_HIT, |
242 // These were to track bloom misses which hit the prefix set, with | 242 // These were to track bloom misses which hit the prefix set, with |
243 // _INVALID to track where the item didn't appear to actually be in | 243 // _INVALID to track where the item didn't appear to actually be in |
244 // the prefix set. _INVALID was never hit. | 244 // the prefix set. _INVALID was never hit. |
245 PREFIX_SET_BLOOM_MISS_PREFIX_SET_HIT, | 245 PREFIX_SET_BLOOM_MISS_PREFIX_SET_HIT_OBSOLETE, |
246 PREFIX_SET_BLOOM_MISS_PREFIX_SET_HIT_INVALID_OBSOLETE, | 246 PREFIX_SET_BLOOM_MISS_PREFIX_SET_HIT_INVALID_OBSOLETE, |
247 // GetPrefixes() after creation failed to get the same prefixes. | 247 // GetPrefixes() after creation failed to get the same prefixes. |
248 PREFIX_SET_GETPREFIXES_BROKEN, | 248 PREFIX_SET_GETPREFIXES_BROKEN, |
249 // Fine-grained tests which didn't provide any good direction. | 249 // Fine-grained tests which didn't provide any good direction. |
250 PREFIX_SET_GETPREFIXES_BROKEN_SIZE_OBSOLETE, | 250 PREFIX_SET_GETPREFIXES_BROKEN_SIZE_OBSOLETE, |
251 PREFIX_SET_GETPREFIXES_FIRST_BROKEN_OBSOLETE, | 251 PREFIX_SET_GETPREFIXES_FIRST_BROKEN_OBSOLETE, |
252 PREFIX_SET_SBPREFIX_WAS_BROKEN_OBSOLETE, | 252 PREFIX_SET_SBPREFIX_WAS_BROKEN_OBSOLETE, |
253 PREFIX_SET_GETPREFIXES_BROKEN_SORTING_OBSOLETE, | 253 PREFIX_SET_GETPREFIXES_BROKEN_SORTING_OBSOLETE, |
254 PREFIX_SET_GETPREFIXES_BROKEN_DUPLICATION_OBSOLETE, | 254 PREFIX_SET_GETPREFIXES_BROKEN_DUPLICATION_OBSOLETE, |
255 PREFIX_SET_GETPREFIXES_UNSORTED_IS_DELTA_OBSOLETE, | 255 PREFIX_SET_GETPREFIXES_UNSORTED_IS_DELTA_OBSOLETE, |
256 PREFIX_SET_GETPREFIXES_UNSORTED_IS_INDEX_OBSOLETE, | 256 PREFIX_SET_GETPREFIXES_UNSORTED_IS_INDEX_OBSOLETE, |
257 // Failed checksum when creating prefix set. | 257 // Failed checksums when creating filters. |
258 PREFIX_SET_CREATE_PREFIX_SET_CHECKSUM, | 258 PREFIX_SET_CREATE_PREFIX_SET_CHECKSUM, |
| 259 PREFIX_SET_CREATE_BLOOM_FILTER_CHECKSUM, |
| 260 PREFIX_SET_CREATE_ADD_PREFIXES_CHECKSUM, |
| 261 PREFIX_SET_CREATE_PREFIXES_CHECKSUM, |
| 262 PREFIX_SET_CREATE_GET_PREFIXES_CHECKSUM, |
| 263 // Failed checksums when probing the filters. |
| 264 PREFIX_SET_MISMATCH_PREFIX_SET_CHECKSUM, |
| 265 PREFIX_SET_MISMATCH_BLOOM_FILTER_CHECKSUM, |
| 266 |
| 267 // Recorded once per update if the impossible occurs. |
| 268 PREFIX_SET_BLOOM_MISS_PREFIX_HIT, |
259 | 269 |
260 // Memory space for histograms is determined by the max. ALWAYS ADD | 270 // Memory space for histograms is determined by the max. ALWAYS ADD |
261 // NEW VALUES BEFORE THIS ONE. | 271 // NEW VALUES BEFORE THIS ONE. |
262 PREFIX_SET_EVENT_MAX | 272 PREFIX_SET_EVENT_MAX |
263 }; | 273 }; |
264 | 274 |
265 void RecordPrefixSetInfo(PrefixSetEvent event_type) { | 275 void RecordPrefixSetInfo(PrefixSetEvent event_type) { |
266 UMA_HISTOGRAM_ENUMERATION("SB2.PrefixSetEvent", event_type, | 276 UMA_HISTOGRAM_ENUMERATION("SB2.PrefixSetEvent", event_type, |
267 PREFIX_SET_EVENT_MAX); | 277 PREFIX_SET_EVENT_MAX); |
268 } | 278 } |
269 | 279 |
270 // Helper to reduce code duplication. | 280 // Helper to reduce code duplication. |
271 safe_browsing::PrefixSet* CreateEmptyPrefixSet() { | 281 safe_browsing::PrefixSet* CreateEmptyPrefixSet() { |
272 return new safe_browsing::PrefixSet(std::vector<SBPrefix>()); | 282 return new safe_browsing::PrefixSet(std::vector<SBPrefix>()); |
273 } | 283 } |
274 | 284 |
275 // Generate a |PrefixSet| instance from the contents of | 285 // Generate xor "checksum" of SBPrefix part of add prefixes. Pass 0 |
276 // |add_prefixes|. Additionally performs various checks to make sure | 286 // for |seed| will return a checksum, passing a previous checksum for |
277 // that the resulting prefix set is valid, so that histograms in | 287 // |seed| will return 0 (if it checks out). Coded this way in hopes |
278 // ContainsBrowseUrl() can be trustworthy. | 288 // that the compiler won't optimize separate runs into a single |
279 safe_browsing::PrefixSet* PrefixSetFromAddPrefixes( | 289 // temporary. |
280 const SBAddPrefixes& add_prefixes) { | 290 SBPrefix ChecksumAddPrefixes(SBPrefix seed, |
| 291 const SBAddPrefixes& add_prefixes) { |
| 292 SBPrefix checksum = seed; |
| 293 for (SBAddPrefixes::const_iterator iter = add_prefixes.begin(); |
| 294 iter != add_prefixes.end(); ++iter) { |
| 295 checksum ^= iter->prefix; |
| 296 } |
| 297 return checksum; |
| 298 } |
| 299 |
| 300 // Generate xor "checksum" of prefixes. |
| 301 SBPrefix ChecksumPrefixes(SBPrefix seed, |
| 302 const std::vector<SBPrefix>& prefixes) { |
| 303 SBPrefix checksum = seed; |
| 304 for (std::vector<SBPrefix>::const_iterator iter = prefixes.begin(); |
| 305 iter != prefixes.end(); ++iter) { |
| 306 checksum ^= *iter; |
| 307 } |
| 308 return checksum; |
| 309 } |
| 310 |
| 311 // Prefix set doesn't store duplicates, making it hard to verify that |
| 312 // checksums match. Also hard is verifying that nothing was corrupted |
| 313 // while removing duplicates from a vector. So this generates a |
| 314 // checksum of only the unique elements. |
| 315 SBPrefix ChecksumUniquePrefixes(const std::vector<SBPrefix>& prefixes) { |
| 316 // Handle edge case up front. |
| 317 if (prefixes.size() == 0) |
| 318 return 0; |
| 319 |
| 320 std::vector<SBPrefix>::const_iterator iter = prefixes.begin(); |
| 321 SBPrefix checksum = *iter++; |
| 322 while (iter != prefixes.end()) { |
| 323 if (*(iter - 1) != *iter) |
| 324 checksum ^= *iter; |
| 325 iter++; |
| 326 } |
| 327 return checksum; |
| 328 } |
| 329 |
| 330 // NOTE(shess): Past histograms have indicated that in a given day, |
| 331 // about 1 in 100,000 updates result in a PrefixSet which was |
| 332 // inconsistent relative to the BloomFilter. Windows is about 5x more |
| 333 // likely to build an inconsistent PrefixSet than Mac. A number of |
| 334 // developers have reviewed the code, and I ran extensive fuzzing with |
| 335 // random data, so at this point I'm trying to demonstrate memory |
| 336 // corruption. |
| 337 // |
| 338 // Other findings from past instrumentation: |
| 339 // - half of one percent of brokenness cases implied duplicate items |
| 340 // in |prefixes|. Per the code above, this should not be possible. |
| 341 // - about 1/20 of broken cases happened more than once for a given |
| 342 // user. Note that empty updates generally don't hit this code at |
| 343 // all, so that may not imply a specific input pattern breaking |
| 344 // things. |
| 345 // - about 1/3 of broken cases show a checksum mismatch between the |
| 346 // checksum calculated while creating |prefix_set| and the checksum |
| 347 // calculated immediately after creation. This is almost certainly |
| 348 // memory corruption. |
| 349 |
| 350 // Generate |PrefixSet| and |BloomFilter| instances from the contents |
| 351 // of |add_prefixes|. Verify that the results are internally |
| 352 // consistent, and that the input maintained consistence while |
| 353 // constructing (which should assure that they are mutually |
| 354 // consistent). Returns an empty prefix set if any of the checks |
| 355 // fail. |
| 356 void FiltersFromAddPrefixes( |
| 357 const SBAddPrefixes& add_prefixes, |
| 358 scoped_refptr<BloomFilter>* bloom_filter, |
| 359 scoped_ptr<safe_browsing::PrefixSet>* prefix_set) { |
| 360 const int filter_size = |
| 361 BloomFilter::FilterSizeForKeyCount(add_prefixes.size()); |
| 362 *bloom_filter = new BloomFilter(filter_size); |
| 363 if (add_prefixes.empty()) { |
| 364 prefix_set->reset(CreateEmptyPrefixSet()); |
| 365 return; |
| 366 } |
| 367 |
| 368 const SBPrefix add_prefixes_checksum = ChecksumAddPrefixes(0, add_prefixes); |
| 369 |
281 // TODO(shess): If |add_prefixes| were sorted by the prefix, it | 370 // TODO(shess): If |add_prefixes| were sorted by the prefix, it |
282 // could be passed directly to |PrefixSet()|, removing the need for | 371 // could be passed directly to |PrefixSet()|, removing the need for |
283 // |prefixes|. For now, |prefixes| is useful while debugging | 372 // |prefixes|. |
284 // things. | |
285 std::vector<SBPrefix> prefixes; | 373 std::vector<SBPrefix> prefixes; |
286 prefixes.reserve(add_prefixes.size()); | 374 prefixes.reserve(add_prefixes.size()); |
287 for (SBAddPrefixes::const_iterator iter = add_prefixes.begin(); | 375 for (SBAddPrefixes::const_iterator iter = add_prefixes.begin(); |
288 iter != add_prefixes.end(); ++iter) { | 376 iter != add_prefixes.end(); ++iter) { |
289 prefixes.push_back(iter->prefix); | 377 prefixes.push_back(iter->prefix); |
290 } | 378 } |
| 379 std::sort(prefixes.begin(), prefixes.end()); |
291 | 380 |
292 std::sort(prefixes.begin(), prefixes.end()); | 381 const SBPrefix unique_prefixes_checksum = ChecksumUniquePrefixes(prefixes); |
293 prefixes.erase(std::unique(prefixes.begin(), prefixes.end()), | |
294 prefixes.end()); | |
295 | 382 |
296 scoped_ptr<safe_browsing::PrefixSet> | 383 for (std::vector<SBPrefix>::const_iterator iter = prefixes.begin(); |
297 prefix_set(new safe_browsing::PrefixSet(prefixes)); | 384 iter != prefixes.end(); ++iter) { |
| 385 bloom_filter->get()->Insert(*iter); |
| 386 } |
298 | 387 |
299 std::vector<SBPrefix> restored; | 388 prefix_set->reset(new safe_browsing::PrefixSet(prefixes)); |
300 prefix_set->GetPrefixes(&restored); | |
301 | 389 |
302 // Expect them to be equal. | 390 // "unit test" for ChecksumUniquePrefixes() and GetPrefixesChecksum(). |
303 if (restored.size() == prefixes.size() && | 391 if (DCHECK_IS_ON()) { |
304 std::equal(prefixes.begin(), prefixes.end(), restored.begin())) | 392 std::vector<SBPrefix> unique(prefixes); |
305 return prefix_set.release(); | 393 unique.erase(std::unique(unique.begin(), unique.end()), unique.end()); |
| 394 DCHECK_EQ(0, ChecksumPrefixes(unique_prefixes_checksum, unique)); |
306 | 395 |
307 // NOTE(shess): Past histograms have indicated that in a given day, | 396 std::vector<SBPrefix> restored; |
308 // about 1 in 100,000 updates result in a PrefixSet which was | 397 prefix_set->get()->GetPrefixes(&restored); |
309 // inconsistent relative to the BloomFilter. Windows is about 5x | 398 DCHECK_EQ(0, ChecksumPrefixes(prefix_set->get()->GetPrefixesChecksum(), |
310 // more likely to build an inconsistent PrefixSet than Mac. A | 399 restored)); |
311 // number of developers have reviewed the code, and I ran extensive | 400 } |
312 // fuzzing with random data, so at this point I'm trying to | |
313 // demonstrate memory corruption. | |
314 // | |
315 // Other findings from past instrumentation: | |
316 // - half of one percent of brokenness cases implied duplicate items | |
317 // in |prefixes|. Per the code above, this should not be | |
318 // possible. | |
319 // - about 1/20 of broken cases happened more than once for a given | |
320 // user. Note that empty updates generally don't hit this code at | |
321 // all, so that may not imply a specific input pattern breaking things. | |
322 // - about 1/3 of broken cases show a checksum mismatch between the | |
323 // checksum calculated while creating |prefix_set| and the | |
324 // checksum calculated immediately after creation. This is almost | |
325 // certainly memory corruption. | |
326 NOTREACHED(); | |
327 RecordPrefixSetInfo(PREFIX_SET_GETPREFIXES_BROKEN); | |
328 | 401 |
329 // Broken because internal memory was corrupted during construction. | 402 // TODO(shess): Need a barrier to prevent ordering checks above here |
330 if (!prefix_set->CheckChecksum()) | 403 // or construction below here? |
| 404 |
| 405 bool get_prefixes_broken = |
| 406 (unique_prefixes_checksum != prefix_set->get()->GetPrefixesChecksum()); |
| 407 bool prefix_set_broken = !prefix_set->get()->CheckChecksum(); |
| 408 bool bloom_filter_broken = !bloom_filter->get()->CheckChecksum(); |
| 409 bool prefixes_input_broken = |
| 410 (0 != ChecksumPrefixes(add_prefixes_checksum, prefixes)); |
| 411 bool add_prefixes_input_broken = |
| 412 (0 != ChecksumAddPrefixes(add_prefixes_checksum, add_prefixes)); |
| 413 |
| 414 if (add_prefixes_input_broken) { |
| 415 RecordPrefixSetInfo(PREFIX_SET_CREATE_ADD_PREFIXES_CHECKSUM); |
| 416 } else if (prefixes_input_broken) { |
| 417 RecordPrefixSetInfo(PREFIX_SET_CREATE_PREFIXES_CHECKSUM); |
| 418 } |
| 419 |
| 420 if (prefix_set_broken) |
331 RecordPrefixSetInfo(PREFIX_SET_CREATE_PREFIX_SET_CHECKSUM); | 421 RecordPrefixSetInfo(PREFIX_SET_CREATE_PREFIX_SET_CHECKSUM); |
332 | 422 |
333 // TODO(shess): Test whether |prefixes| changed during construction. | 423 // TODO(shess): Obviously this is a problem for operation of the |
| 424 // bloom filter! But for purposes of checking prefix set operation, |
| 425 // all that matters is not messing up the histograms recorded later. |
| 426 if (bloom_filter_broken) |
| 427 RecordPrefixSetInfo(PREFIX_SET_CREATE_BLOOM_FILTER_CHECKSUM); |
334 | 428 |
335 return CreateEmptyPrefixSet(); | 429 // Attempt to isolate the case where the output of GetPrefixes() |
| 430 // would differ from the input presented. This case implies that |
| 431 // PrefixSet has an actual implementation flaw, and may in the |
| 432 // future warrant more aggressive action, such as somehow dumping |
| 433 // |prefixes| up to the crash server. |
| 434 if (get_prefixes_broken && !prefix_set_broken && !prefixes_input_broken) |
| 435 RecordPrefixSetInfo(PREFIX_SET_CREATE_GET_PREFIXES_CHECKSUM); |
| 436 |
| 437 // If anything broke, clear the prefix set to prevent pollution of |
| 438 // histograms generated later. |
| 439 if (get_prefixes_broken || prefix_set_broken || bloom_filter_broken || |
| 440 prefixes_input_broken || add_prefixes_input_broken) { |
| 441 DCHECK(!get_prefixes_broken); |
| 442 DCHECK(!prefix_set_broken); |
| 443 DCHECK(!bloom_filter_broken); |
| 444 DCHECK(!prefixes_input_broken); |
| 445 DCHECK(!add_prefixes_input_broken); |
| 446 prefix_set->reset(CreateEmptyPrefixSet()); |
| 447 } |
336 } | 448 } |
337 | 449 |
338 } // namespace | 450 } // namespace |
339 | 451 |
340 // The default SafeBrowsingDatabaseFactory. | 452 // The default SafeBrowsingDatabaseFactory. |
341 class SafeBrowsingDatabaseFactoryImpl : public SafeBrowsingDatabaseFactory { | 453 class SafeBrowsingDatabaseFactoryImpl : public SafeBrowsingDatabaseFactory { |
342 public: | 454 public: |
343 virtual SafeBrowsingDatabase* CreateSafeBrowsingDatabase( | 455 virtual SafeBrowsingDatabase* CreateSafeBrowsingDatabase( |
344 bool enable_download_protection, | 456 bool enable_download_protection, |
345 bool enable_client_side_whitelist, | 457 bool enable_client_side_whitelist, |
(...skipping 240 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
586 base::AutoLock locked(lookup_lock_); | 698 base::AutoLock locked(lookup_lock_); |
587 | 699 |
588 if (!browse_bloom_filter_.get()) | 700 if (!browse_bloom_filter_.get()) |
589 return false; | 701 return false; |
590 DCHECK(prefix_set_.get()); | 702 DCHECK(prefix_set_.get()); |
591 | 703 |
592 // |prefix_set_| is empty until the first update, only log info if | 704 // |prefix_set_| is empty until the first update, only log info if |
593 // not empty. | 705 // not empty. |
594 const bool prefix_set_empty = !prefix_set_->GetSize(); | 706 const bool prefix_set_empty = !prefix_set_->GetSize(); |
595 | 707 |
| 708 // Track cases where the filters were not consistent with each other. |
| 709 bool bloom_hit_prefix_miss = false; |
| 710 bool bloom_miss_prefix_hit = false; |
| 711 |
596 size_t miss_count = 0; | 712 size_t miss_count = 0; |
597 for (size_t i = 0; i < full_hashes.size(); ++i) { | 713 for (size_t i = 0; i < full_hashes.size(); ++i) { |
598 bool found = prefix_set_->Exists(full_hashes[i].prefix); | 714 bool found = prefix_set_->Exists(full_hashes[i].prefix); |
599 | 715 |
600 if (browse_bloom_filter_->Exists(full_hashes[i].prefix)) { | 716 if (browse_bloom_filter_->Exists(full_hashes[i].prefix)) { |
601 if (!prefix_set_empty) { | 717 if (!prefix_set_empty) { |
602 RecordPrefixSetInfo(PREFIX_SET_BLOOM_HIT); | 718 RecordPrefixSetInfo(PREFIX_SET_BLOOM_HIT); |
603 // This should be less than PREFIX_SET_BLOOM_HIT by the | 719 // This should be less than PREFIX_SET_BLOOM_HIT by the |
604 // false positive rate. | 720 // false positive rate. |
605 if (found) | 721 if (found) { |
606 RecordPrefixSetInfo(PREFIX_SET_HIT); | 722 RecordPrefixSetInfo(PREFIX_SET_HIT); |
| 723 } else { |
| 724 // Could be false positive, but _could_ be corruption. |
| 725 bloom_hit_prefix_miss = true; |
| 726 } |
607 } | 727 } |
608 prefix_hits->push_back(full_hashes[i].prefix); | 728 prefix_hits->push_back(full_hashes[i].prefix); |
609 if (prefix_miss_cache_.count(full_hashes[i].prefix) > 0) | 729 if (prefix_miss_cache_.count(full_hashes[i].prefix) > 0) |
610 ++miss_count; | 730 ++miss_count; |
611 } else { | 731 } else { |
612 // Bloom filter misses should never be in prefix set. | 732 // Bloom filter misses should never be in prefix set. Check |
| 733 // to see if the prefix set or bloom filter have changed since |
| 734 // being created. |
613 DCHECK(!found); | 735 DCHECK(!found); |
614 if (found) | 736 if (found && !prefix_set_empty) |
615 RecordPrefixSetInfo(PREFIX_SET_BLOOM_MISS_PREFIX_SET_HIT); | 737 bloom_miss_prefix_hit = true; |
616 } | 738 } |
617 } | 739 } |
618 | 740 |
| 741 // In case of inconsistent results, verify the checksums and record |
| 742 // failures (in case of corruption inconsistencies would be |
| 743 // expected). In case of corruption clear out |prefix_set_|, once |
| 744 // we've noticed corruption there is no point to future comparisons. |
| 745 if (bloom_miss_prefix_hit || bloom_hit_prefix_miss) { |
| 746 if (!prefix_set_->CheckChecksum()) { |
| 747 RecordPrefixSetInfo(PREFIX_SET_MISMATCH_PREFIX_SET_CHECKSUM); |
| 748 prefix_set_.reset(CreateEmptyPrefixSet()); |
| 749 } else if (!browse_bloom_filter_->CheckChecksum()) { |
| 750 RecordPrefixSetInfo(PREFIX_SET_MISMATCH_BLOOM_FILTER_CHECKSUM); |
| 751 prefix_set_.reset(CreateEmptyPrefixSet()); |
| 752 } else if (bloom_miss_prefix_hit) { |
| 753 // This case should be impossible if the filters are both valid. |
| 754 RecordPrefixSetInfo(PREFIX_SET_BLOOM_MISS_PREFIX_HIT); |
| 755 } |
| 756 } |
| 757 |
619 // If all the prefixes are cached as 'misses', don't issue a GetHash. | 758 // If all the prefixes are cached as 'misses', don't issue a GetHash. |
620 if (miss_count == prefix_hits->size()) | 759 if (miss_count == prefix_hits->size()) |
621 return false; | 760 return false; |
622 | 761 |
623 // Find the matching full-hash results. |full_browse_hashes_| are from the | 762 // Find the matching full-hash results. |full_browse_hashes_| are from the |
624 // database, |pending_browse_hashes_| are from GetHash requests between | 763 // database, |pending_browse_hashes_| are from GetHash requests between |
625 // updates. | 764 // updates. |
626 std::sort(prefix_hits->begin(), prefix_hits->end()); | 765 std::sort(prefix_hits->begin(), prefix_hits->end()); |
627 | 766 |
628 GetCachedFullHashesForBrowse(*prefix_hits, full_browse_hashes_, | 767 GetCachedFullHashesForBrowse(*prefix_hits, full_browse_hashes_, |
(...skipping 552 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1181 const base::Time before = base::Time::Now(); | 1320 const base::Time before = base::Time::Now(); |
1182 | 1321 |
1183 SBAddPrefixes add_prefixes; | 1322 SBAddPrefixes add_prefixes; |
1184 std::vector<SBAddFullHash> add_full_hashes; | 1323 std::vector<SBAddFullHash> add_full_hashes; |
1185 if (!browse_store_->FinishUpdate(pending_add_hashes, prefix_miss_cache_, | 1324 if (!browse_store_->FinishUpdate(pending_add_hashes, prefix_miss_cache_, |
1186 &add_prefixes, &add_full_hashes)) { | 1325 &add_prefixes, &add_full_hashes)) { |
1187 RecordFailure(FAILURE_BROWSE_DATABASE_UPDATE_FINISH); | 1326 RecordFailure(FAILURE_BROWSE_DATABASE_UPDATE_FINISH); |
1188 return; | 1327 return; |
1189 } | 1328 } |
1190 | 1329 |
1191 // Create and populate |filter| from |add_prefixes|. | 1330 scoped_refptr<BloomFilter> bloom_filter; |
1192 // TODO(shess): The bloom filter doesn't need to be a | 1331 scoped_ptr<safe_browsing::PrefixSet> prefix_set; |
1193 // scoped_refptr<> for this code. Refactor that away. | 1332 FiltersFromAddPrefixes(add_prefixes, &bloom_filter, &prefix_set); |
1194 const int filter_size = | |
1195 BloomFilter::FilterSizeForKeyCount(add_prefixes.size()); | |
1196 scoped_refptr<BloomFilter> filter(new BloomFilter(filter_size)); | |
1197 for (SBAddPrefixes::const_iterator iter = add_prefixes.begin(); | |
1198 iter != add_prefixes.end(); ++iter) { | |
1199 filter->Insert(iter->prefix); | |
1200 } | |
1201 | |
1202 scoped_ptr<safe_browsing::PrefixSet> | |
1203 prefix_set(PrefixSetFromAddPrefixes(add_prefixes)); | |
1204 | 1333 |
1205 // This needs to be in sorted order by prefix for efficient access. | 1334 // This needs to be in sorted order by prefix for efficient access. |
1206 std::sort(add_full_hashes.begin(), add_full_hashes.end(), | 1335 std::sort(add_full_hashes.begin(), add_full_hashes.end(), |
1207 SBAddFullHashPrefixLess); | 1336 SBAddFullHashPrefixLess); |
1208 | 1337 |
1209 // Swap in the newly built filter and cache. | 1338 // Swap in the newly built filter and cache. |
1210 { | 1339 { |
1211 base::AutoLock locked(lookup_lock_); | 1340 base::AutoLock locked(lookup_lock_); |
1212 full_browse_hashes_.swap(add_full_hashes); | 1341 full_browse_hashes_.swap(add_full_hashes); |
1213 | 1342 |
1214 // TODO(shess): If |CacheHashResults()| is posted between the | 1343 // TODO(shess): If |CacheHashResults()| is posted between the |
1215 // earlier lock and this clear, those pending hashes will be lost. | 1344 // earlier lock and this clear, those pending hashes will be lost. |
1216 // It could be fixed by only removing hashes which were collected | 1345 // It could be fixed by only removing hashes which were collected |
1217 // at the earlier point. I believe that is fail-safe as-is (the | 1346 // at the earlier point. I believe that is fail-safe as-is (the |
1218 // hash will be fetched again). | 1347 // hash will be fetched again). |
1219 pending_browse_hashes_.clear(); | 1348 pending_browse_hashes_.clear(); |
1220 prefix_miss_cache_.clear(); | 1349 prefix_miss_cache_.clear(); |
1221 browse_bloom_filter_.swap(filter); | 1350 browse_bloom_filter_.swap(bloom_filter); |
1222 prefix_set_.swap(prefix_set); | 1351 prefix_set_.swap(prefix_set); |
1223 } | 1352 } |
1224 | 1353 |
1225 const base::TimeDelta bloom_gen = base::Time::Now() - before; | 1354 const base::TimeDelta bloom_gen = base::Time::Now() - before; |
1226 | 1355 |
1227 // Persist the bloom filter to disk. Since only this thread changes | 1356 // Persist the bloom filter to disk. Since only this thread changes |
1228 // |browse_bloom_filter_|, there is no need to lock. | 1357 // |browse_bloom_filter_|, there is no need to lock. |
1229 WriteBloomFilter(); | 1358 WriteBloomFilter(); |
1230 | 1359 |
1231 // Gather statistics. | 1360 // Gather statistics. |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1385 if (std::binary_search(new_whitelist.begin(), new_whitelist.end(), | 1514 if (std::binary_search(new_whitelist.begin(), new_whitelist.end(), |
1386 kill_switch)) { | 1515 kill_switch)) { |
1387 // The kill switch is whitelisted hence we whitelist all URLs. | 1516 // The kill switch is whitelisted hence we whitelist all URLs. |
1388 WhitelistEverything(whitelist); | 1517 WhitelistEverything(whitelist); |
1389 } else { | 1518 } else { |
1390 base::AutoLock locked(lookup_lock_); | 1519 base::AutoLock locked(lookup_lock_); |
1391 whitelist->second = false; | 1520 whitelist->second = false; |
1392 whitelist->first.swap(new_whitelist); | 1521 whitelist->first.swap(new_whitelist); |
1393 } | 1522 } |
1394 } | 1523 } |
OLD | NEW |