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 2b5b2e256bcdf199691453784246ac5a14ccc20c..6676ec7a7b2bb71d8849f90c74448c340e63cfb8 100644 |
--- a/chrome/browser/safe_browsing/safe_browsing_database.cc |
+++ b/chrome/browser/safe_browsing/safe_browsing_database.cc |
@@ -185,6 +185,51 @@ bool MatchAddPrefixes(SafeBrowsingStore* store, |
return found_match; |
} |
+// Order |SBFullHash| on the prefix part. This differs from SBFullHashLess on |
+// little-endian platforms. |
+bool SBFullHashPrefixLess(const SBFullHash& a, const SBFullHash& b) { |
+ return a.prefix < b.prefix; |
+} |
+ |
+// Remove items from |full_hashes| which have no prefix match in |db_hashes|. |
+// |db_hashes| should be ordered by prefix. |
+void TrimFullHashesByPrefix( |
+ const std::vector<SBAddFullHash>& db_hashes, |
+ std::vector<SBFullHash>* full_hashes) { |
+ std::sort(full_hashes->begin(), full_hashes->end(), SBFullHashPrefixLess); |
+ |
+ // |db_iter| steps through |db_hashes|. |
+ std::vector<SBAddFullHash>::const_iterator db_iter = db_hashes.begin(); |
+ |
+ // |check_iter| steps through |full_hashes|, |out_iter| only steps forward |
+ // when retaining values. |
+ std::vector<SBFullHash>::iterator check_iter = full_hashes->begin(); |
+ std::vector<SBFullHash>::iterator out_iter = full_hashes->begin(); |
+ |
+ // Process until the end of either vector. If |db_hashes| ends first, then |
+ // the remaining elements of |full_hashes| cannot match. |
+ while (check_iter != full_hashes->end() && db_iter != db_hashes.end()) { |
+ // Bump |db_iter| forward until the first element which is not less than |
+ // |check_iter|. |
+ while (db_iter != db_hashes.end() && |
+ db_iter->full_hash.prefix < check_iter->prefix) { |
+ ++db_iter; |
+ } |
+ |
+ // Keep |check_iter| if the prefix is equal to |db_iter|. |
+ if (db_iter != db_hashes.end() && |
+ check_iter->prefix == db_iter->full_hash.prefix) { |
+ *out_iter = *check_iter; |
+ out_iter++; |
+ } |
+ |
+ check_iter++; |
+ } |
+ |
+ // Erase any elements which did not match. |
+ full_hashes->erase(out_iter, full_hashes->end()); |
+} |
+ |
// Find the entries in |full_hashes| with prefix in |prefix_hits|, and |
// add them to |full_hits| if not expired. "Not expired" is when |
// either |last_update| was recent enough, or the item has been |
@@ -704,6 +749,24 @@ bool SafeBrowsingDatabaseNew::ContainsBrowseUrl( |
} |
} |
+ // Older code injected a prefix for each fullhash, which is now stripped on |
+ // update. Temporarily inject the removed |prefix_hits| to match the previous |
+ // code's results. The prefix-set check is to allow reads from older |
+ // databases (where the set contains the prefix) to match reads from updated |
+ // databases (where the set does not contain the prefix) until this code is |
+ // replaced. |
+ // |
+ // See <http://crbug.com/361248> |
+ TrimFullHashesByPrefix(full_browse_hashes_, &full_hashes); |
+ for (size_t i = 0; i < full_hashes.size(); ++i) { |
+ const SBPrefix prefix = full_hashes[i].prefix; |
+ if (!browse_prefix_set_->Exists(prefix)) { |
+ prefix_hits->push_back(prefix); |
+ if (prefix_miss_cache_.count(prefix) > 0) |
+ ++miss_count; |
+ } |
+ } |
+ |
// If all the prefixes are cached as 'misses', don't issue a GetHash. |
if (miss_count == prefix_hits->size()) |
return false; |
@@ -879,10 +942,6 @@ void SafeBrowsingDatabaseNew::InsertAdd(int chunk_id, SBPrefix host, |
const base::Time receive_time = base::Time::Now(); |
for (int i = 0; i < count; ++i) { |
const SBFullHash full_hash = entry->FullHashAt(i); |
- const SBPrefix prefix = full_hash.prefix; |
- |
- STATS_COUNTER("SB.PrefixAdd", 1); |
- store->WriteAddPrefix(encoded_chunk_id, prefix); |
STATS_COUNTER("SB.PrefixAddFull", 1); |
store->WriteAddHash(encoded_chunk_id, receive_time, full_hash); |
@@ -956,9 +1015,6 @@ void SafeBrowsingDatabaseNew::InsertSub(int chunk_id, SBPrefix host, |
const int add_chunk_id = |
EncodeChunkId(entry->ChunkIdAtPrefix(i), list_id); |
- STATS_COUNTER("SB.PrefixSub", 1); |
- store->WriteSubPrefix(encoded_chunk_id, add_chunk_id, full_hash.prefix); |
- |
STATS_COUNTER("SB.PrefixSubFull", 1); |
store->WriteSubHash(encoded_chunk_id, add_chunk_id, full_hash); |
} |