juliatuttle | add0a38 | 2017-04-03 16:27:15 | [diff] [blame] | 1 | // Copyright 2017 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. |
| 4 | |
| 5 | #include "net/reporting/reporting_endpoint_manager.h" |
| 6 | |
juliatuttle | 3d2b053 | 2017-06-05 18:45:46 | [diff] [blame] | 7 | #include <map> |
| 8 | #include <set> |
juliatuttle | add0a38 | 2017-04-03 16:27:15 | [diff] [blame] | 9 | #include <string> |
Matt Menke | 515136d | 2019-10-05 00:27:09 | [diff] [blame] | 10 | #include <utility> |
juliatuttle | add0a38 | 2017-04-03 16:27:15 | [diff] [blame] | 11 | #include <vector> |
| 12 | |
Hans Wennborg | 0924470b | 2020-04-27 21:08:05 | [diff] [blame] | 13 | #include "base/check.h" |
Matt Menke | 67f3376 | 2019-10-11 01:24:32 | [diff] [blame] | 14 | #include "base/containers/mru_cache.h" |
juliatuttle | 3d2b053 | 2017-06-05 18:45:46 | [diff] [blame] | 15 | #include "base/macros.h" |
Hans Wennborg | 0924470b | 2020-04-27 21:08:05 | [diff] [blame] | 16 | #include "base/notreached.h" |
juliatuttle | add0a38 | 2017-04-03 16:27:15 | [diff] [blame] | 17 | #include "base/rand_util.h" |
| 18 | #include "base/stl_util.h" |
| 19 | #include "base/time/tick_clock.h" |
| 20 | #include "net/base/backoff_entry.h" |
Matt Menke | 515136d | 2019-10-05 00:27:09 | [diff] [blame] | 21 | #include "net/base/network_isolation_key.h" |
Julia Tuttle | d56350d | 2017-12-07 19:11:17 | [diff] [blame] | 22 | #include "net/base/rand_callback.h" |
juliatuttle | add0a38 | 2017-04-03 16:27:15 | [diff] [blame] | 23 | #include "net/reporting/reporting_cache.h" |
juliatuttle | 58754891 | 2017-05-23 14:17:21 | [diff] [blame] | 24 | #include "net/reporting/reporting_delegate.h" |
Lily Chen | fc92ff4 | 2019-05-06 22:59:10 | [diff] [blame] | 25 | #include "net/reporting/reporting_endpoint.h" |
juliatuttle | ee4b55e | 2017-04-07 17:09:45 | [diff] [blame] | 26 | #include "net/reporting/reporting_policy.h" |
juliatuttle | add0a38 | 2017-04-03 16:27:15 | [diff] [blame] | 27 | #include "url/gurl.h" |
| 28 | #include "url/origin.h" |
| 29 | |
| 30 | namespace net { |
| 31 | |
juliatuttle | 3d2b053 | 2017-06-05 18:45:46 | [diff] [blame] | 32 | namespace { |
| 33 | |
| 34 | class ReportingEndpointManagerImpl : public ReportingEndpointManager { |
| 35 | public: |
Matt Menke | 515136d | 2019-10-05 00:27:09 | [diff] [blame] | 36 | ReportingEndpointManagerImpl(const ReportingPolicy* policy, |
| 37 | const base::TickClock* tick_clock, |
| 38 | const ReportingDelegate* delegate, |
| 39 | ReportingCache* cache, |
Julia Tuttle | d56350d | 2017-12-07 19:11:17 | [diff] [blame] | 40 | const RandIntCallback& rand_callback) |
Matt Menke | 515136d | 2019-10-05 00:27:09 | [diff] [blame] | 41 | : policy_(policy), |
| 42 | tick_clock_(tick_clock), |
| 43 | delegate_(delegate), |
| 44 | cache_(cache), |
Matt Menke | 67f3376 | 2019-10-11 01:24:32 | [diff] [blame] | 45 | rand_callback_(rand_callback), |
| 46 | endpoint_backoff_(kMaxEndpointBackoffCacheSize) { |
Matt Menke | 515136d | 2019-10-05 00:27:09 | [diff] [blame] | 47 | DCHECK(policy); |
| 48 | DCHECK(tick_clock); |
| 49 | DCHECK(delegate); |
| 50 | DCHECK(cache); |
| 51 | } |
juliatuttle | 3d2b053 | 2017-06-05 18:45:46 | [diff] [blame] | 52 | |
Chris Watkins | 806691b | 2017-12-01 06:01:22 | [diff] [blame] | 53 | ~ReportingEndpointManagerImpl() override = default; |
juliatuttle | 3d2b053 | 2017-06-05 18:45:46 | [diff] [blame] | 54 | |
Lily Chen | fc92ff4 | 2019-05-06 22:59:10 | [diff] [blame] | 55 | const ReportingEndpoint FindEndpointForDelivery( |
Lily Chen | ad5dd080 | 2020-03-10 21:58:09 | [diff] [blame] | 56 | const ReportingEndpointGroupKey& group_key) override { |
Lily Chen | efb6fcf | 2019-04-19 04:17:54 | [diff] [blame] | 57 | // Get unexpired endpoints that apply to a delivery to |origin| and |group|. |
| 58 | // May have been configured by a superdomain of |origin|. |
Lily Chen | fc92ff4 | 2019-05-06 22:59:10 | [diff] [blame] | 59 | std::vector<ReportingEndpoint> endpoints = |
Lily Chen | ad5dd080 | 2020-03-10 21:58:09 | [diff] [blame] | 60 | cache_->GetCandidateEndpointsForDelivery(group_key); |
juliatuttle | 3d2b053 | 2017-06-05 18:45:46 | [diff] [blame] | 61 | |
Lily Chen | efb6fcf | 2019-04-19 04:17:54 | [diff] [blame] | 62 | // Highest-priority endpoint(s) that are not expired, failing, or |
Julia Tuttle | d56350d | 2017-12-07 19:11:17 | [diff] [blame] | 63 | // forbidden for use by the ReportingDelegate. |
Lily Chen | fc92ff4 | 2019-05-06 22:59:10 | [diff] [blame] | 64 | std::vector<ReportingEndpoint> available_endpoints; |
Lily Chen | efb6fcf | 2019-04-19 04:17:54 | [diff] [blame] | 65 | // Total weight of endpoints in |available_endpoints|. |
Julia Tuttle | d56350d | 2017-12-07 19:11:17 | [diff] [blame] | 66 | int total_weight = 0; |
| 67 | |
Nico Weber | 6dcde5b | 2020-02-22 20:49:20 | [diff] [blame] | 68 | for (const ReportingEndpoint& endpoint : endpoints) { |
Matt Menke | 515136d | 2019-10-05 00:27:09 | [diff] [blame] | 69 | if (!delegate_->CanUseClient(endpoint.group_key.origin, |
| 70 | endpoint.info.url)) { |
juliatuttle | 3d2b053 | 2017-06-05 18:45:46 | [diff] [blame] | 71 | continue; |
Lily Chen | efb6fcf | 2019-04-19 04:17:54 | [diff] [blame] | 72 | } |
Julia Tuttle | d56350d | 2017-12-07 19:11:17 | [diff] [blame] | 73 | |
| 74 | // If this client is lower priority than the ones we've found, skip it. |
Lily Chen | efb6fcf | 2019-04-19 04:17:54 | [diff] [blame] | 75 | if (!available_endpoints.empty() && |
| 76 | endpoint.info.priority > available_endpoints[0].info.priority) { |
Julia Tuttle | d56350d | 2017-12-07 19:11:17 | [diff] [blame] | 77 | continue; |
| 78 | } |
| 79 | |
Matt Menke | 67f3376 | 2019-10-11 01:24:32 | [diff] [blame] | 80 | // This brings each match to the front of the MRU cache, so if an entry |
| 81 | // frequently matches requests, it's more likely to stay in the cache. |
Lily Chen | ad5dd080 | 2020-03-10 21:58:09 | [diff] [blame] | 82 | auto endpoint_backoff_it = endpoint_backoff_.Get(EndpointBackoffKey( |
| 83 | group_key.network_isolation_key, endpoint.info.url)); |
Matt Menke | 67f3376 | 2019-10-11 01:24:32 | [diff] [blame] | 84 | if (endpoint_backoff_it != endpoint_backoff_.end() && |
| 85 | endpoint_backoff_it->second->ShouldRejectRequest()) { |
| 86 | continue; |
| 87 | } |
| 88 | |
Julia Tuttle | d56350d | 2017-12-07 19:11:17 | [diff] [blame] | 89 | // If this client is higher priority than the ones we've found (or we |
| 90 | // haven't found any), forget about those ones and remember this one. |
Lily Chen | efb6fcf | 2019-04-19 04:17:54 | [diff] [blame] | 91 | if (available_endpoints.empty() || |
| 92 | endpoint.info.priority < available_endpoints[0].info.priority) { |
| 93 | available_endpoints.clear(); |
Julia Tuttle | d56350d | 2017-12-07 19:11:17 | [diff] [blame] | 94 | total_weight = 0; |
| 95 | } |
| 96 | |
Lily Chen | efb6fcf | 2019-04-19 04:17:54 | [diff] [blame] | 97 | available_endpoints.push_back(endpoint); |
| 98 | total_weight += endpoint.info.weight; |
juliatuttle | 3d2b053 | 2017-06-05 18:45:46 | [diff] [blame] | 99 | } |
| 100 | |
Lily Chen | efb6fcf | 2019-04-19 04:17:54 | [diff] [blame] | 101 | if (available_endpoints.empty()) { |
Lily Chen | fc92ff4 | 2019-05-06 22:59:10 | [diff] [blame] | 102 | return ReportingEndpoint(); |
juliatuttle | 3d2b053 | 2017-06-05 18:45:46 | [diff] [blame] | 103 | } |
| 104 | |
Sam Burnett | 148e526 | 2019-05-09 01:13:48 | [diff] [blame] | 105 | if (total_weight == 0) { |
| 106 | int random_index = rand_callback_.Run(0, available_endpoints.size() - 1); |
| 107 | return available_endpoints[random_index]; |
| 108 | } |
| 109 | |
Julia Tuttle | d56350d | 2017-12-07 19:11:17 | [diff] [blame] | 110 | int random_index = rand_callback_.Run(0, total_weight - 1); |
| 111 | int weight_so_far = 0; |
Lily Chen | efb6fcf | 2019-04-19 04:17:54 | [diff] [blame] | 112 | for (size_t i = 0; i < available_endpoints.size(); ++i) { |
Lily Chen | fc92ff4 | 2019-05-06 22:59:10 | [diff] [blame] | 113 | const ReportingEndpoint& endpoint = available_endpoints[i]; |
Lily Chen | efb6fcf | 2019-04-19 04:17:54 | [diff] [blame] | 114 | weight_so_far += endpoint.info.weight; |
Julia Tuttle | d56350d | 2017-12-07 19:11:17 | [diff] [blame] | 115 | if (random_index < weight_so_far) { |
Lily Chen | efb6fcf | 2019-04-19 04:17:54 | [diff] [blame] | 116 | return endpoint; |
Julia Tuttle | d56350d | 2017-12-07 19:11:17 | [diff] [blame] | 117 | } |
| 118 | } |
| 119 | |
| 120 | // TODO(juliatuttle): Can we reach this in some weird overflow case? |
| 121 | NOTREACHED(); |
Lily Chen | fc92ff4 | 2019-05-06 22:59:10 | [diff] [blame] | 122 | return ReportingEndpoint(); |
juliatuttle | 3d2b053 | 2017-06-05 18:45:46 | [diff] [blame] | 123 | } |
| 124 | |
Matt Menke | 515136d | 2019-10-05 00:27:09 | [diff] [blame] | 125 | void InformOfEndpointRequest(const NetworkIsolationKey& network_isolation_key, |
| 126 | const GURL& endpoint, |
| 127 | bool succeeded) override { |
| 128 | EndpointBackoffKey endpoint_backoff_key(network_isolation_key, endpoint); |
Matt Menke | 67f3376 | 2019-10-11 01:24:32 | [diff] [blame] | 129 | // This will bring the entry to the front of the cache, if it exists. |
| 130 | auto endpoint_backoff_it = endpoint_backoff_.Get(endpoint_backoff_key); |
Matt Menke | 515136d | 2019-10-05 00:27:09 | [diff] [blame] | 131 | if (endpoint_backoff_it == endpoint_backoff_.end()) { |
Matt Menke | 67f3376 | 2019-10-11 01:24:32 | [diff] [blame] | 132 | endpoint_backoff_it = endpoint_backoff_.Put( |
| 133 | std::move(endpoint_backoff_key), |
| 134 | std::make_unique<BackoffEntry>(&policy_->endpoint_backoff_policy, |
| 135 | tick_clock_)); |
juliatuttle | 3d2b053 | 2017-06-05 18:45:46 | [diff] [blame] | 136 | } |
Matt Menke | 515136d | 2019-10-05 00:27:09 | [diff] [blame] | 137 | endpoint_backoff_it->second->InformOfRequest(succeeded); |
juliatuttle | 3d2b053 | 2017-06-05 18:45:46 | [diff] [blame] | 138 | } |
| 139 | |
| 140 | private: |
Matt Menke | 515136d | 2019-10-05 00:27:09 | [diff] [blame] | 141 | using EndpointBackoffKey = std::pair<NetworkIsolationKey, GURL>; |
juliatuttle | 3d2b053 | 2017-06-05 18:45:46 | [diff] [blame] | 142 | |
Matt Menke | 515136d | 2019-10-05 00:27:09 | [diff] [blame] | 143 | const ReportingPolicy* const policy_; |
| 144 | const base::TickClock* const tick_clock_; |
| 145 | const ReportingDelegate* const delegate_; |
| 146 | ReportingCache* const cache_; |
juliatuttle | 3d2b053 | 2017-06-05 18:45:46 | [diff] [blame] | 147 | |
Julia Tuttle | d56350d | 2017-12-07 19:11:17 | [diff] [blame] | 148 | RandIntCallback rand_callback_; |
| 149 | |
juliatuttle | 3d2b053 | 2017-06-05 18:45:46 | [diff] [blame] | 150 | // Note: Currently the ReportingBrowsingDataRemover does not clear this data |
| 151 | // because it's not persisted to disk. If it's ever persisted, it will need |
| 152 | // to be cleared as well. |
Lily Chen | efb6fcf | 2019-04-19 04:17:54 | [diff] [blame] | 153 | // TODO(chlily): clear this data when endpoints are deleted to avoid unbounded |
| 154 | // growth of this map. |
Matt Menke | 67f3376 | 2019-10-11 01:24:32 | [diff] [blame] | 155 | base::MRUCache<EndpointBackoffKey, std::unique_ptr<net::BackoffEntry>> |
Matt Menke | 515136d | 2019-10-05 00:27:09 | [diff] [blame] | 156 | endpoint_backoff_; |
juliatuttle | 3d2b053 | 2017-06-05 18:45:46 | [diff] [blame] | 157 | |
| 158 | DISALLOW_COPY_AND_ASSIGN(ReportingEndpointManagerImpl); |
| 159 | }; |
| 160 | |
| 161 | } // namespace |
| 162 | |
| 163 | // static |
| 164 | std::unique_ptr<ReportingEndpointManager> ReportingEndpointManager::Create( |
Matt Menke | 515136d | 2019-10-05 00:27:09 | [diff] [blame] | 165 | const ReportingPolicy* policy, |
| 166 | const base::TickClock* tick_clock, |
| 167 | const ReportingDelegate* delegate, |
| 168 | ReportingCache* cache, |
Julia Tuttle | d56350d | 2017-12-07 19:11:17 | [diff] [blame] | 169 | const RandIntCallback& rand_callback) { |
Matt Menke | 515136d | 2019-10-05 00:27:09 | [diff] [blame] | 170 | return std::make_unique<ReportingEndpointManagerImpl>( |
| 171 | policy, tick_clock, delegate, cache, rand_callback); |
juliatuttle | 3d2b053 | 2017-06-05 18:45:46 | [diff] [blame] | 172 | } |
juliatuttle | add0a38 | 2017-04-03 16:27:15 | [diff] [blame] | 173 | |
Chris Watkins | 806691b | 2017-12-01 06:01:22 | [diff] [blame] | 174 | ReportingEndpointManager::~ReportingEndpointManager() = default; |
juliatuttle | add0a38 | 2017-04-03 16:27:15 | [diff] [blame] | 175 | |
juliatuttle | add0a38 | 2017-04-03 16:27:15 | [diff] [blame] | 176 | } // namespace net |