Add domain request detection to incident reporting service.
[chromium-blink-merge.git] / chrome / browser / safe_browsing / safe_browsing_store.cc
blobe4c15e74b5da2bd9d9d38a2fed561f335f9b3303
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/safe_browsing/safe_browsing_store.h"
7 #include <algorithm>
9 #include "base/logging.h"
11 namespace {
13 // Return |true| if the range is sorted by the given comparator.
14 template <typename CTI, typename LESS>
15 bool sorted(CTI beg, CTI end, LESS less) {
16 while ((end - beg) > 2) {
17 CTI n = beg++;
18 if (less(*beg, *n))
19 return false;
21 return true;
24 // Find items matching between |subs| and |adds|, and remove them. To minimize
25 // copies, the inputs are processing in parallel, so |subs| and |adds| should be
26 // compatibly ordered (either by SBAddPrefixLess or SBAddPrefixHashLess).
28 // |predAddSub| provides add < sub, |predSubAdd| provides sub < add, for the
29 // tightest compare appropriate (see calls in SBProcessSubs).
30 template <typename SubsT, typename AddsT,
31 typename PredAddSubT, typename PredSubAddT>
32 void KnockoutSubs(SubsT* subs, AddsT* adds,
33 PredAddSubT predAddSub, PredSubAddT predSubAdd) {
34 // Keep a pair of output iterators for writing kept items. Due to
35 // deletions, these may lag the main iterators. Using erase() on
36 // individual items would result in O(N^2) copies. Using std::list
37 // would work around that, at double or triple the memory cost.
38 typename AddsT::iterator add_out = adds->begin();
39 typename SubsT::iterator sub_out = subs->begin();
41 // Current location in containers.
42 // TODO(shess): I want these to be const_iterator, but then
43 // std::copy() gets confused. Could snag a const_iterator add_end,
44 // or write an inline std::copy(), but it seems like I'm doing
45 // something wrong.
46 typename AddsT::iterator add_iter = adds->begin();
47 typename SubsT::iterator sub_iter = subs->begin();
49 while (add_iter != adds->end() && sub_iter != subs->end()) {
50 // If |*sub_iter| < |*add_iter|, retain the sub.
51 if (predSubAdd(*sub_iter, *add_iter)) {
52 *sub_out = *sub_iter;
53 ++sub_out;
54 ++sub_iter;
56 // If |*add_iter| < |*sub_iter|, retain the add.
57 } else if (predAddSub(*add_iter, *sub_iter)) {
58 *add_out = *add_iter;
59 ++add_out;
60 ++add_iter;
62 // Drop equal items.
63 } else {
64 ++add_iter;
65 ++sub_iter;
69 // Erase any leftover gap.
70 adds->erase(add_out, add_iter);
71 subs->erase(sub_out, sub_iter);
74 // Remove deleted items (|chunk_id| in |del_set|) from the container.
75 template <typename ItemsT>
76 void RemoveDeleted(ItemsT* items, const base::hash_set<int32>& del_set) {
77 DCHECK(items);
79 // Move items from |iter| to |end_iter|, skipping items in |del_set|.
80 typename ItemsT::iterator end_iter = items->begin();
81 for (typename ItemsT::iterator iter = end_iter;
82 iter != items->end(); ++iter) {
83 if (del_set.count(iter->chunk_id) == 0) {
84 *end_iter = *iter;
85 ++end_iter;
88 items->erase(end_iter, items->end());
91 } // namespace
93 void SBProcessSubs(SBAddPrefixes* add_prefixes,
94 SBSubPrefixes* sub_prefixes,
95 std::vector<SBAddFullHash>* add_full_hashes,
96 std::vector<SBSubFullHash>* sub_full_hashes,
97 const base::hash_set<int32>& add_chunks_deleted,
98 const base::hash_set<int32>& sub_chunks_deleted) {
99 // It is possible to structure templates and template
100 // specializations such that the following calls work without having
101 // to qualify things. It becomes very arbitrary, though, and less
102 // clear how things are working.
104 // Make sure things are sorted appropriately.
105 DCHECK(sorted(add_prefixes->begin(), add_prefixes->end(),
106 SBAddPrefixLess<SBAddPrefix,SBAddPrefix>));
107 DCHECK(sorted(sub_prefixes->begin(), sub_prefixes->end(),
108 SBAddPrefixLess<SBSubPrefix,SBSubPrefix>));
109 DCHECK(sorted(add_full_hashes->begin(), add_full_hashes->end(),
110 SBAddPrefixHashLess<SBAddFullHash,SBAddFullHash>));
111 DCHECK(sorted(sub_full_hashes->begin(), sub_full_hashes->end(),
112 SBAddPrefixHashLess<SBSubFullHash,SBSubFullHash>));
114 // Factor out the prefix subs.
115 KnockoutSubs(sub_prefixes, add_prefixes,
116 SBAddPrefixLess<SBAddPrefix,SBSubPrefix>,
117 SBAddPrefixLess<SBSubPrefix,SBAddPrefix>);
119 // Factor out the full-hash subs.
120 KnockoutSubs(sub_full_hashes, add_full_hashes,
121 SBAddPrefixHashLess<SBAddFullHash,SBSubFullHash>,
122 SBAddPrefixHashLess<SBSubFullHash,SBAddFullHash>);
124 // Remove items from the deleted chunks. This is done after other
125 // processing to allow subs to knock out adds (and be removed) even
126 // if the add's chunk is deleted.
127 RemoveDeleted(add_prefixes, add_chunks_deleted);
128 RemoveDeleted(sub_prefixes, sub_chunks_deleted);
129 RemoveDeleted(add_full_hashes, add_chunks_deleted);
130 RemoveDeleted(sub_full_hashes, sub_chunks_deleted);