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 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
229 return a.full_hash.prefix < b.full_hash.prefix; | 229 return a.full_hash.prefix < b.full_hash.prefix; |
230 } | 230 } |
231 | 231 |
232 // As compared to the bloom filter, PrefixSet should have these | 232 // As compared to the bloom filter, PrefixSet should have these |
233 // properties: | 233 // properties: |
234 // - Any bloom filter miss should be a prefix set miss. | 234 // - Any bloom filter miss should be a prefix set miss. |
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 PREFIX_SET_EVENT_HIT, | 239 // Hits to prefix set and bloom filter. |
240 PREFIX_SET_EVENT_BLOOM_HIT, | 240 PREFIX_SET_HIT, |
241 PREFIX_SET_EVENT_BLOOM_MISS_PREFIX_HIT, | 241 PREFIX_SET_BLOOM_HIT, |
242 PREFIX_SET_EVENT_BLOOM_MISS_PREFIX_HIT_INVALID, | 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 |
| 244 // the prefix set. _INVALID was never hit. |
| 245 PREFIX_SET_BLOOM_MISS_PREFIX_SET_HIT, |
| 246 PREFIX_SET_BLOOM_MISS_PREFIX_SET_HIT_INVALID_OBSOLETE, |
| 247 // GetPrefixes() after creation failed to get the same prefixes. |
243 PREFIX_SET_GETPREFIXES_BROKEN, | 248 PREFIX_SET_GETPREFIXES_BROKEN, |
244 PREFIX_SET_GETPREFIXES_BROKEN_SIZE, | 249 // Fine-grained tests which didn't provide any good direction. |
245 PREFIX_SET_GETPREFIXES_FIRST_BROKEN, | 250 PREFIX_SET_GETPREFIXES_BROKEN_SIZE_OBSOLETE, |
246 PREFIX_SET_SBPREFIX_WAS_BROKEN, | 251 PREFIX_SET_GETPREFIXES_FIRST_BROKEN_OBSOLETE, |
247 PREFIX_SET_GETPREFIXES_BROKEN_SORTING, | 252 PREFIX_SET_SBPREFIX_WAS_BROKEN_OBSOLETE, |
248 PREFIX_SET_GETPREFIXES_BROKEN_DUPLICATION, | 253 PREFIX_SET_GETPREFIXES_BROKEN_SORTING_OBSOLETE, |
249 PREFIX_SET_GETPREFIX_UNSORTED_IS_DELTA, | 254 PREFIX_SET_GETPREFIXES_BROKEN_DUPLICATION_OBSOLETE, |
250 PREFIX_SET_GETPREFIX_UNSORTED_IS_INDEX, | 255 PREFIX_SET_GETPREFIXES_UNSORTED_IS_DELTA_OBSOLETE, |
251 PREFIX_SET_GETPREFIX_CHECKSUM_MISMATCH, | 256 PREFIX_SET_GETPREFIXES_UNSORTED_IS_INDEX_OBSOLETE, |
| 257 // Failed checksum when creating prefix set. |
| 258 PREFIX_SET_CREATE_PREFIX_SET_CHECKSUM, |
252 | 259 |
253 // Memory space for histograms is determined by the max. ALWAYS ADD | 260 // Memory space for histograms is determined by the max. ALWAYS ADD |
254 // NEW VALUES BEFORE THIS ONE. | 261 // NEW VALUES BEFORE THIS ONE. |
255 PREFIX_SET_EVENT_MAX | 262 PREFIX_SET_EVENT_MAX |
256 }; | 263 }; |
257 | 264 |
258 void RecordPrefixSetInfo(PrefixSetEvent event_type) { | 265 void RecordPrefixSetInfo(PrefixSetEvent event_type) { |
259 UMA_HISTOGRAM_ENUMERATION("SB2.PrefixSetEvent", event_type, | 266 UMA_HISTOGRAM_ENUMERATION("SB2.PrefixSetEvent", event_type, |
260 PREFIX_SET_EVENT_MAX); | 267 PREFIX_SET_EVENT_MAX); |
261 } | 268 } |
262 | 269 |
| 270 // Helper to reduce code duplication. |
| 271 safe_browsing::PrefixSet* CreateEmptyPrefixSet() { |
| 272 return new safe_browsing::PrefixSet(std::vector<SBPrefix>()); |
| 273 } |
| 274 |
263 // Generate a |PrefixSet| instance from the contents of | 275 // Generate a |PrefixSet| instance from the contents of |
264 // |add_prefixes|. Additionally performs various checks to make sure | 276 // |add_prefixes|. Additionally performs various checks to make sure |
265 // that the resulting prefix set is valid, so that the | 277 // that the resulting prefix set is valid, so that histograms in |
266 // PREFIX_SET_EVENT_BLOOM_MISS_PREFIX_HIT_INVALID histogram in | |
267 // ContainsBrowseUrl() can be trustworthy. | 278 // ContainsBrowseUrl() can be trustworthy. |
268 safe_browsing::PrefixSet* PrefixSetFromAddPrefixes( | 279 safe_browsing::PrefixSet* PrefixSetFromAddPrefixes( |
269 const SBAddPrefixes& add_prefixes) { | 280 const SBAddPrefixes& add_prefixes) { |
270 // TODO(shess): If |add_prefixes| were sorted by the prefix, it | 281 // TODO(shess): If |add_prefixes| were sorted by the prefix, it |
271 // could be passed directly to |PrefixSet()|, removing the need for | 282 // could be passed directly to |PrefixSet()|, removing the need for |
272 // |prefixes|. For now, |prefixes| is useful while debugging | 283 // |prefixes|. For now, |prefixes| is useful while debugging |
273 // things. | 284 // things. |
274 std::vector<SBPrefix> prefixes; | 285 std::vector<SBPrefix> prefixes; |
275 prefixes.reserve(add_prefixes.size()); | 286 prefixes.reserve(add_prefixes.size()); |
276 for (SBAddPrefixes::const_iterator iter = add_prefixes.begin(); | 287 for (SBAddPrefixes::const_iterator iter = add_prefixes.begin(); |
277 iter != add_prefixes.end(); ++iter) { | 288 iter != add_prefixes.end(); ++iter) { |
278 prefixes.push_back(iter->prefix); | 289 prefixes.push_back(iter->prefix); |
279 } | 290 } |
280 | 291 |
281 std::sort(prefixes.begin(), prefixes.end()); | 292 std::sort(prefixes.begin(), prefixes.end()); |
282 prefixes.erase(std::unique(prefixes.begin(), prefixes.end()), | 293 prefixes.erase(std::unique(prefixes.begin(), prefixes.end()), |
283 prefixes.end()); | 294 prefixes.end()); |
284 | 295 |
285 scoped_ptr<safe_browsing::PrefixSet> | 296 scoped_ptr<safe_browsing::PrefixSet> |
286 prefix_set(new safe_browsing::PrefixSet(prefixes)); | 297 prefix_set(new safe_browsing::PrefixSet(prefixes)); |
287 | 298 |
288 std::vector<SBPrefix> restored; | 299 std::vector<SBPrefix> restored; |
289 prefix_set->GetPrefixes(&restored); | 300 prefix_set->GetPrefixes(&restored); |
290 | 301 |
291 // Expect them to be equal. | 302 // Expect them to be equal. |
292 if (restored.size() == prefixes.size() && | 303 if (restored.size() == prefixes.size() && |
293 std::equal(prefixes.begin(), prefixes.end(), restored.begin())) | 304 std::equal(prefixes.begin(), prefixes.end(), restored.begin())) |
294 return prefix_set.release(); | 305 return prefix_set.release(); |
295 | 306 |
296 // Log BROKEN for continuity with previous release, and SIZE to | 307 // NOTE(shess): Past histograms have indicated that in a given day, |
297 // distinguish which test failed. | 308 // about 1 in 100,000 updates result in a PrefixSet which was |
| 309 // inconsistent relative to the BloomFilter. Windows is about 5x |
| 310 // more likely to build an inconsistent PrefixSet than Mac. A |
| 311 // number of developers have reviewed the code, and I ran extensive |
| 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. |
298 NOTREACHED(); | 326 NOTREACHED(); |
299 RecordPrefixSetInfo(PREFIX_SET_GETPREFIXES_BROKEN); | 327 RecordPrefixSetInfo(PREFIX_SET_GETPREFIXES_BROKEN); |
300 if (restored.size() != prefixes.size()) | |
301 RecordPrefixSetInfo(PREFIX_SET_GETPREFIXES_BROKEN_SIZE); | |
302 | 328 |
303 // Try to distinguish between updates from one broken user and a | 329 // Broken because internal memory was corrupted during construction. |
304 // distributed problem. | 330 if (!prefix_set->CheckChecksum()) |
305 static bool logged_broken = false; | 331 RecordPrefixSetInfo(PREFIX_SET_CREATE_PREFIX_SET_CHECKSUM); |
306 if (!logged_broken) { | |
307 RecordPrefixSetInfo(PREFIX_SET_GETPREFIXES_FIRST_BROKEN); | |
308 logged_broken = true; | |
309 } | |
310 | 332 |
311 // This seems so very very unlikely. But if it ever were true, then | 333 // TODO(shess): Test whether |prefixes| changed during construction. |
312 // it could explain why GetPrefixes() seemed broken. | |
313 if (sizeof(int) != sizeof(int32)) | |
314 RecordPrefixSetInfo(PREFIX_SET_SBPREFIX_WAS_BROKEN); | |
315 | 334 |
316 // Check if memory was corrupted during construction. | 335 return CreateEmptyPrefixSet(); |
317 if (!prefix_set->CheckChecksum()) | |
318 RecordPrefixSetInfo(PREFIX_SET_GETPREFIX_CHECKSUM_MISMATCH); | |
319 | |
320 // Check whether |restored| is unsorted, or has duplication. | |
321 if (restored.size()) { | |
322 size_t unsorted_count = 0; | |
323 bool duplicates = false; | |
324 SBPrefix prev = restored[0]; | |
325 for (size_t i = 0; i < restored.size(); prev = restored[i], ++i) { | |
326 if (prev > restored[i]) { | |
327 unsorted_count++; | |
328 UMA_HISTOGRAM_COUNTS("SB2.PrefixSetUnsortedDifference", | |
329 prev - restored[i]); | |
330 | |
331 // When unsorted, how big is the set, and how far are we into | |
332 // it. If the set is very small or large, that might inform | |
333 // pursuit of a degenerate case. If the percentage is close | |
334 // to 0%, 100%, or 50%, then there might be an interesting | |
335 // degenerate case to explore. | |
336 UMA_HISTOGRAM_COUNTS("SB2.PrefixSetUnsortedSize", restored.size()); | |
337 UMA_HISTOGRAM_PERCENTAGE("SB2.PrefixSetUnsortedPercent", | |
338 i * 100 / restored.size()); | |
339 | |
340 if (prefix_set->IsDeltaAt(i)) { | |
341 RecordPrefixSetInfo(PREFIX_SET_GETPREFIX_UNSORTED_IS_DELTA); | |
342 | |
343 // Histograms require memory on the order of the number of | |
344 // buckets, making high-precision logging expensive. For | |
345 // now aim for a sense of the range of the problem. | |
346 UMA_HISTOGRAM_CUSTOM_COUNTS("SB2.PrefixSetUnsortedDelta", | |
347 prefix_set->DeltaAt(i), 1, 0xFFFF, 50); | |
348 } else { | |
349 RecordPrefixSetInfo(PREFIX_SET_GETPREFIX_UNSORTED_IS_INDEX); | |
350 } | |
351 } | |
352 if (prev == restored[i]) | |
353 duplicates = true; | |
354 } | |
355 | |
356 // Record findings. | |
357 if (unsorted_count) { | |
358 RecordPrefixSetInfo(PREFIX_SET_GETPREFIXES_BROKEN_SORTING); | |
359 UMA_HISTOGRAM_COUNTS_100("SB2.PrefixSetUnsorted", unsorted_count); | |
360 } | |
361 if (duplicates) | |
362 RecordPrefixSetInfo(PREFIX_SET_GETPREFIXES_BROKEN_DUPLICATION); | |
363 | |
364 // Fix the problems noted. If |restored| was unsorted, then | |
365 // |duplicates| may give a false negative. | |
366 if (unsorted_count) | |
367 std::sort(restored.begin(), restored.end()); | |
368 if (unsorted_count || duplicates) | |
369 restored.erase(std::unique(restored.begin(), restored.end()), | |
370 restored.end()); | |
371 } | |
372 | |
373 // NOTE(shess): The following could be done using a single | |
374 // uber-loop, but it's complicated by needing multiple parallel | |
375 // iterators. Didn't seem worthwhile for something that will only | |
376 // live for a short period and only fires for one in a million | |
377 // updates. | |
378 | |
379 // Find elements in |restored| which are not in |prefixes|. | |
380 std::vector<SBPrefix> difference; | |
381 std::set_difference(restored.begin(), restored.end(), | |
382 prefixes.begin(), prefixes.end(), | |
383 std::back_inserter(difference)); | |
384 if (difference.size()) | |
385 UMA_HISTOGRAM_COUNTS_100("SB2.PrefixSetRestoredExcess", difference.size()); | |
386 | |
387 // Find elements in |prefixes| which are not in |restored|. | |
388 difference.clear(); | |
389 std::set_difference(prefixes.begin(), prefixes.end(), | |
390 restored.begin(), restored.end(), | |
391 std::back_inserter(difference)); | |
392 if (difference.size()) | |
393 UMA_HISTOGRAM_COUNTS_100("SB2.PrefixSetRestoredShortfall", | |
394 difference.size()); | |
395 | |
396 return prefix_set.release(); | |
397 } | 336 } |
398 | 337 |
399 } // namespace | 338 } // namespace |
400 | 339 |
401 // The default SafeBrowsingDatabaseFactory. | 340 // The default SafeBrowsingDatabaseFactory. |
402 class SafeBrowsingDatabaseFactoryImpl : public SafeBrowsingDatabaseFactory { | 341 class SafeBrowsingDatabaseFactoryImpl : public SafeBrowsingDatabaseFactory { |
403 public: | 342 public: |
404 virtual SafeBrowsingDatabase* CreateSafeBrowsingDatabase( | 343 virtual SafeBrowsingDatabase* CreateSafeBrowsingDatabase( |
405 bool enable_download_protection, | 344 bool enable_download_protection, |
406 bool enable_client_side_whitelist, | 345 bool enable_client_side_whitelist, |
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
609 { | 548 { |
610 base::AutoLock locked(lookup_lock_); | 549 base::AutoLock locked(lookup_lock_); |
611 full_browse_hashes_.clear(); | 550 full_browse_hashes_.clear(); |
612 pending_browse_hashes_.clear(); | 551 pending_browse_hashes_.clear(); |
613 prefix_miss_cache_.clear(); | 552 prefix_miss_cache_.clear(); |
614 // TODO(shess): This could probably be |bloom_filter_.reset()|. | 553 // TODO(shess): This could probably be |bloom_filter_.reset()|. |
615 browse_bloom_filter_ = new BloomFilter(BloomFilter::kBloomFilterMinSize * | 554 browse_bloom_filter_ = new BloomFilter(BloomFilter::kBloomFilterMinSize * |
616 BloomFilter::kBloomFilterSizeRatio); | 555 BloomFilter::kBloomFilterSizeRatio); |
617 // TODO(shess): It is simpler for the code to assume that presence | 556 // TODO(shess): It is simpler for the code to assume that presence |
618 // of a bloom filter always implies presence of a prefix set. | 557 // of a bloom filter always implies presence of a prefix set. |
619 prefix_set_.reset(new safe_browsing::PrefixSet(std::vector<SBPrefix>())); | 558 prefix_set_.reset(CreateEmptyPrefixSet()); |
620 } | 559 } |
621 // Wants to acquire the lock itself. | 560 // Wants to acquire the lock itself. |
622 WhitelistEverything(&csd_whitelist_); | 561 WhitelistEverything(&csd_whitelist_); |
623 WhitelistEverything(&download_whitelist_); | 562 WhitelistEverything(&download_whitelist_); |
624 | 563 |
625 return true; | 564 return true; |
626 } | 565 } |
627 | 566 |
628 // TODO(lzheng): Remove matching_list, it is not used anywhere. | 567 // TODO(lzheng): Remove matching_list, it is not used anywhere. |
629 bool SafeBrowsingDatabaseNew::ContainsBrowseUrl( | 568 bool SafeBrowsingDatabaseNew::ContainsBrowseUrl( |
(...skipping 17 matching lines...) Expand all Loading... |
647 base::AutoLock locked(lookup_lock_); | 586 base::AutoLock locked(lookup_lock_); |
648 | 587 |
649 if (!browse_bloom_filter_.get()) | 588 if (!browse_bloom_filter_.get()) |
650 return false; | 589 return false; |
651 DCHECK(prefix_set_.get()); | 590 DCHECK(prefix_set_.get()); |
652 | 591 |
653 // |prefix_set_| is empty until the first update, only log info if | 592 // |prefix_set_| is empty until the first update, only log info if |
654 // not empty. | 593 // not empty. |
655 const bool prefix_set_empty = !prefix_set_->GetSize(); | 594 const bool prefix_set_empty = !prefix_set_->GetSize(); |
656 | 595 |
657 // Used to double-check in case of a hit mis-match. | |
658 std::vector<SBPrefix> restored; | |
659 | |
660 size_t miss_count = 0; | 596 size_t miss_count = 0; |
661 for (size_t i = 0; i < full_hashes.size(); ++i) { | 597 for (size_t i = 0; i < full_hashes.size(); ++i) { |
662 bool found = prefix_set_->Exists(full_hashes[i].prefix); | 598 bool found = prefix_set_->Exists(full_hashes[i].prefix); |
663 | 599 |
664 if (browse_bloom_filter_->Exists(full_hashes[i].prefix)) { | 600 if (browse_bloom_filter_->Exists(full_hashes[i].prefix)) { |
665 if (!prefix_set_empty) { | 601 if (!prefix_set_empty) { |
666 RecordPrefixSetInfo(PREFIX_SET_EVENT_BLOOM_HIT); | 602 RecordPrefixSetInfo(PREFIX_SET_BLOOM_HIT); |
| 603 // This should be less than PREFIX_SET_BLOOM_HIT by the |
| 604 // false positive rate. |
667 if (found) | 605 if (found) |
668 RecordPrefixSetInfo(PREFIX_SET_EVENT_HIT); | 606 RecordPrefixSetInfo(PREFIX_SET_HIT); |
669 } | 607 } |
670 prefix_hits->push_back(full_hashes[i].prefix); | 608 prefix_hits->push_back(full_hashes[i].prefix); |
671 if (prefix_miss_cache_.count(full_hashes[i].prefix) > 0) | 609 if (prefix_miss_cache_.count(full_hashes[i].prefix) > 0) |
672 ++miss_count; | 610 ++miss_count; |
673 } else { | 611 } else { |
674 // Bloom filter misses should never be in prefix set. Re-create | 612 // Bloom filter misses should never be in prefix set. |
675 // the original prefixes and manually search for it, to check if | |
676 // there's a bug with how |Exists()| is implemented. | |
677 // |UpdateBrowseStore()| previously verified that | |
678 // |GetPrefixes()| returns the same prefixes as were passed to | |
679 // the constructor. | |
680 DCHECK(!found); | 613 DCHECK(!found); |
681 if (found && !prefix_set_empty) { | 614 if (found) |
682 if (restored.empty()) | 615 RecordPrefixSetInfo(PREFIX_SET_BLOOM_MISS_PREFIX_SET_HIT); |
683 prefix_set_->GetPrefixes(&restored); | |
684 | |
685 // If the item is not in the re-created list, then there is an | |
686 // error in |PrefixSet::Exists()|. If the item is in the | |
687 // re-created list, then the bloom filter was wrong. | |
688 if (std::binary_search(restored.begin(), restored.end(), | |
689 full_hashes[i].prefix)) { | |
690 RecordPrefixSetInfo(PREFIX_SET_EVENT_BLOOM_MISS_PREFIX_HIT); | |
691 } else { | |
692 RecordPrefixSetInfo(PREFIX_SET_EVENT_BLOOM_MISS_PREFIX_HIT_INVALID); | |
693 } | |
694 } | |
695 } | 616 } |
696 } | 617 } |
697 | 618 |
698 // If all the prefixes are cached as 'misses', don't issue a GetHash. | 619 // If all the prefixes are cached as 'misses', don't issue a GetHash. |
699 if (miss_count == prefix_hits->size()) | 620 if (miss_count == prefix_hits->size()) |
700 return false; | 621 return false; |
701 | 622 |
702 // Find the matching full-hash results. |full_browse_hashes_| are from the | 623 // Find the matching full-hash results. |full_browse_hashes_| are from the |
703 // database, |pending_browse_hashes_| are from GetHash requests between | 624 // database, |pending_browse_hashes_| are from GetHash requests between |
704 // updates. | 625 // updates. |
(...skipping 674 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1379 | 1300 |
1380 const base::TimeTicks before = base::TimeTicks::Now(); | 1301 const base::TimeTicks before = base::TimeTicks::Now(); |
1381 browse_bloom_filter_ = BloomFilter::LoadFile(bloom_filter_filename_); | 1302 browse_bloom_filter_ = BloomFilter::LoadFile(bloom_filter_filename_); |
1382 DVLOG(1) << "SafeBrowsingDatabaseNew read bloom filter in " | 1303 DVLOG(1) << "SafeBrowsingDatabaseNew read bloom filter in " |
1383 << (base::TimeTicks::Now() - before).InMilliseconds() << " ms"; | 1304 << (base::TimeTicks::Now() - before).InMilliseconds() << " ms"; |
1384 | 1305 |
1385 if (!browse_bloom_filter_.get()) | 1306 if (!browse_bloom_filter_.get()) |
1386 RecordFailure(FAILURE_DATABASE_FILTER_READ); | 1307 RecordFailure(FAILURE_DATABASE_FILTER_READ); |
1387 | 1308 |
1388 // Use an empty prefix set until the first update. | 1309 // Use an empty prefix set until the first update. |
1389 prefix_set_.reset(new safe_browsing::PrefixSet(std::vector<SBPrefix>())); | 1310 prefix_set_.reset(CreateEmptyPrefixSet()); |
1390 } | 1311 } |
1391 | 1312 |
1392 bool SafeBrowsingDatabaseNew::Delete() { | 1313 bool SafeBrowsingDatabaseNew::Delete() { |
1393 DCHECK_EQ(creation_loop_, MessageLoop::current()); | 1314 DCHECK_EQ(creation_loop_, MessageLoop::current()); |
1394 | 1315 |
1395 const bool r1 = browse_store_->Delete(); | 1316 const bool r1 = browse_store_->Delete(); |
1396 if (!r1) | 1317 if (!r1) |
1397 RecordFailure(FAILURE_DATABASE_STORE_DELETE); | 1318 RecordFailure(FAILURE_DATABASE_STORE_DELETE); |
1398 | 1319 |
1399 const bool r2 = download_store_.get() ? download_store_->Delete() : true; | 1320 const bool r2 = download_store_.get() ? download_store_->Delete() : true; |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1464 if (std::binary_search(new_whitelist.begin(), new_whitelist.end(), | 1385 if (std::binary_search(new_whitelist.begin(), new_whitelist.end(), |
1465 kill_switch)) { | 1386 kill_switch)) { |
1466 // The kill switch is whitelisted hence we whitelist all URLs. | 1387 // The kill switch is whitelisted hence we whitelist all URLs. |
1467 WhitelistEverything(whitelist); | 1388 WhitelistEverything(whitelist); |
1468 } else { | 1389 } else { |
1469 base::AutoLock locked(lookup_lock_); | 1390 base::AutoLock locked(lookup_lock_); |
1470 whitelist->second = false; | 1391 whitelist->second = false; |
1471 whitelist->first.swap(new_whitelist); | 1392 whitelist->first.swap(new_whitelist); |
1472 } | 1393 } |
1473 } | 1394 } |
OLD | NEW |