Index: chrome/browser/safe_browsing/safe_browsing_database.cc |
diff --git a/chrome/browser/safe_browsing/safe_browsing_database.cc b/chrome/browser/safe_browsing/safe_browsing_database.cc |
index c54d38fa62353d3ecdf3eebb32ce695f2cebdace..87814a342ae474c83a201a645af19536ef66dd00 100644 |
--- a/chrome/browser/safe_browsing/safe_browsing_database.cc |
+++ b/chrome/browser/safe_browsing/safe_browsing_database.cc |
@@ -217,6 +217,8 @@ enum PrefixSetEvent { |
PREFIX_SET_GETPREFIXES_BROKEN_SIZE, |
PREFIX_SET_GETPREFIXES_FIRST_BROKEN, |
PREFIX_SET_SBPREFIX_WAS_BROKEN, |
+ PREFIX_SET_GETPREFIXES_BROKEN_SORTING, |
+ PREFIX_SET_GETPREFIXES_BROKEN_DUPLICATION, |
// Memory space for histograms is determined by the max. ALWAYS ADD |
// NEW VALUES BEFORE THIS ONE. |
@@ -279,6 +281,56 @@ safe_browsing::PrefixSet* PrefixSetFromAddPrefixes( |
if (sizeof(int) != sizeof(int32)) |
RecordPrefixSetInfo(PREFIX_SET_SBPREFIX_WAS_BROKEN); |
+ // Check whether |restored| is unsorted, or has duplication. |
+ if (restored.size()) { |
+ bool unsorted = false; |
+ bool duplicates = false; |
+ std::vector<SBPrefix>::const_iterator prev = restored.begin(); |
+ for (std::vector<SBPrefix>::const_iterator iter = prev + 1; |
+ iter != restored.end(); prev = iter, ++iter) { |
+ if (*prev > *iter) |
+ unsorted = true; |
+ if (*prev == *iter) |
+ duplicates = true; |
+ } |
+ |
+ // Record findings. |
+ if (unsorted) |
+ RecordPrefixSetInfo(PREFIX_SET_GETPREFIXES_BROKEN_SORTING); |
+ if (duplicates) |
+ RecordPrefixSetInfo(PREFIX_SET_GETPREFIXES_BROKEN_DUPLICATION); |
+ |
+ // Fix the problems noted. If |restored| was unsorted, then |
+ // |duplicates| may give a false negative. |
+ if (unsorted) |
+ std::sort(restored.begin(), restored.end()); |
+ if (unsorted || duplicates) |
+ restored.erase(std::unique(restored.begin(), restored.end()), |
+ restored.end()); |
+ } |
+ |
+ // NOTE(shess): The following could be done using a single |
+ // uber-loop, but it's complicated by needing multiple parallel |
+ // iterators. Didn't seem worthwhile for something that will only |
+ // live for a short period and only fires for one in a million |
+ // updates. |
+ |
+ // Find elements in |restored| which are not in |prefixes|. |
+ std::vector<SBPrefix> difference; |
+ std::set_difference(restored.begin(), restored.end(), |
+ prefixes.begin(), prefixes.end(), |
+ std::back_inserter(difference)); |
+ if (difference.size()) |
+ UMA_HISTOGRAM_COUNTS_100("SB2.PrefixSetRestoredExcess", difference.size()); |
+ |
+ // Find elements in |prefixes| which are not in |restored|. |
+ difference.clear(); |
+ std::set_difference(prefixes.begin(), prefixes.end(), |
+ restored.begin(), restored.end(), |
+ std::back_inserter(difference)); |
+ if (difference.size()) |
+ UMA_HISTOGRAM_COUNTS_100("SB2.PrefixSetRestoredShortfall", |
+ difference.size()); |
return prefix_set.release(); |
} |