[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 1 | // Copyright 2014 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 "components/domain_reliability/context.h" |
| 6 | |
| 7 | #include <algorithm> |
dcheng | 5160635 | 2015-12-26 21:16:23 | [diff] [blame] | 8 | #include <utility> |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 9 | |
| 10 | #include "base/bind.h" |
| 11 | #include "base/json/json_writer.h" |
| 12 | #include "base/logging.h" |
asvitkine | 3033081 | 2016-08-30 04:01:08 | [diff] [blame] | 13 | #include "base/metrics/histogram_macros.h" |
[email protected] | d9df3b8 | 2014-04-08 23:44:00 | [diff] [blame] | 14 | #include "base/metrics/sparse_histogram.h" |
ttuttle | ccc4ffa | 2015-12-10 20:08:46 | [diff] [blame] | 15 | #include "base/rand_util.h" |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 16 | #include "base/values.h" |
[email protected] | bda8e36 | 2014-03-24 18:21:03 | [diff] [blame] | 17 | #include "components/domain_reliability/dispatcher.h" |
[email protected] | b5c2b74 | 2014-06-14 22:21:42 | [diff] [blame] | 18 | #include "components/domain_reliability/uploader.h" |
| 19 | #include "components/domain_reliability/util.h" |
[email protected] | d9df3b8 | 2014-04-08 23:44:00 | [diff] [blame] | 20 | #include "net/base/net_errors.h" |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 21 | #include "net/url_request/url_request_context_getter.h" |
| 22 | |
| 23 | using base::DictionaryValue; |
| 24 | using base::ListValue; |
| 25 | using base::Value; |
| 26 | |
| 27 | namespace domain_reliability { |
| 28 | |
ttuttle | 42144d8a | 2015-12-01 23:57:37 | [diff] [blame] | 29 | // static |
| 30 | const int DomainReliabilityContext::kMaxUploadDepthToSchedule = 1; |
| 31 | |
ttuttle | ca1ac31 | 2015-03-12 17:07:00 | [diff] [blame] | 32 | DomainReliabilityContext::Factory::~Factory() { |
| 33 | } |
| 34 | |
[email protected] | 84d2a49 | 2014-05-09 22:18:50 | [diff] [blame] | 35 | // static |
| 36 | const size_t DomainReliabilityContext::kMaxQueuedBeacons = 150; |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 37 | |
| 38 | DomainReliabilityContext::DomainReliabilityContext( |
| 39 | MockableTime* time, |
[email protected] | bda8e36 | 2014-03-24 18:21:03 | [diff] [blame] | 40 | const DomainReliabilityScheduler::Params& scheduler_params, |
[email protected] | 84d2a49 | 2014-05-09 22:18:50 | [diff] [blame] | 41 | const std::string& upload_reporter_string, |
ttuttle | 743f4ae | 2014-11-04 20:22:32 | [diff] [blame] | 42 | const base::TimeTicks* last_network_change_time, |
Julia Tuttle | 30b16965 | 2017-10-16 20:19:08 | [diff] [blame] | 43 | const UploadAllowedCallback& upload_allowed_callback, |
[email protected] | bda8e36 | 2014-03-24 18:21:03 | [diff] [blame] | 44 | DomainReliabilityDispatcher* dispatcher, |
| 45 | DomainReliabilityUploader* uploader, |
dcheng | 04a35cd | 2016-04-22 15:07:24 | [diff] [blame] | 46 | std::unique_ptr<const DomainReliabilityConfig> config) |
dcheng | 5160635 | 2015-12-26 21:16:23 | [diff] [blame] | 47 | : config_(std::move(config)), |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 48 | time_(time), |
[email protected] | 84d2a49 | 2014-05-09 22:18:50 | [diff] [blame] | 49 | upload_reporter_string_(upload_reporter_string), |
| 50 | scheduler_(time, |
| 51 | config_->collectors.size(), |
| 52 | scheduler_params, |
[email protected] | bda8e36 | 2014-03-24 18:21:03 | [diff] [blame] | 53 | base::Bind(&DomainReliabilityContext::ScheduleUpload, |
| 54 | base::Unretained(this))), |
| 55 | dispatcher_(dispatcher), |
| 56 | uploader_(uploader), |
[email protected] | f3589bf | 2014-07-31 03:54:16 | [diff] [blame] | 57 | uploading_beacons_size_(0), |
ttuttle | 743f4ae | 2014-11-04 20:22:32 | [diff] [blame] | 58 | last_network_change_time_(last_network_change_time), |
Julia Tuttle | 30b16965 | 2017-10-16 20:19:08 | [diff] [blame] | 59 | upload_allowed_callback_(upload_allowed_callback), |
dcheng | 5160635 | 2015-12-26 21:16:23 | [diff] [blame] | 60 | weak_factory_(this) {} |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 61 | |
ttuttle | ccdd6cc5 | 2015-11-22 06:09:40 | [diff] [blame] | 62 | DomainReliabilityContext::~DomainReliabilityContext() { |
| 63 | ClearBeacons(); |
| 64 | } |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 65 | |
Julia Tuttle | 17d6a41 | 2017-11-14 18:18:46 | [diff] [blame] | 66 | void DomainReliabilityContext::OnBeacon( |
dcheng | 04a35cd | 2016-04-22 15:07:24 | [diff] [blame] | 67 | std::unique_ptr<DomainReliabilityBeacon> beacon) { |
ttuttle | ccdd6cc5 | 2015-11-22 06:09:40 | [diff] [blame] | 68 | bool success = (beacon->status == "ok"); |
zhongyi | 93fa5a9 | 2016-03-14 18:10:57 | [diff] [blame] | 69 | double sample_rate = beacon->details.quic_port_migration_detected |
| 70 | ? 1.0 |
| 71 | : config().GetSampleRate(success); |
Julia Tuttle | 17d6a41 | 2017-11-14 18:18:46 | [diff] [blame] | 72 | if (base::RandDouble() >= sample_rate) |
| 73 | return; |
ttuttle | ccc4ffa | 2015-12-10 20:08:46 | [diff] [blame] | 74 | beacon->sample_rate = sample_rate; |
[email protected] | d9df3b8 | 2014-04-08 23:44:00 | [diff] [blame] | 75 | |
ttuttle | d89375a | 2015-12-09 20:54:57 | [diff] [blame] | 76 | // Allow beacons about reports, but don't schedule an upload for more than |
| 77 | // one layer of recursion, to avoid infinite report loops. |
ttuttle | 42144d8a | 2015-12-01 23:57:37 | [diff] [blame] | 78 | if (beacon->upload_depth <= kMaxUploadDepthToSchedule) |
| 79 | scheduler_.OnBeaconAdded(); |
avi | 12ce31d | 2016-08-30 16:38:05 | [diff] [blame] | 80 | beacons_.push_back(std::move(beacon)); |
ttuttle | ccc4ffa | 2015-12-10 20:08:46 | [diff] [blame] | 81 | bool should_evict = beacons_.size() > kMaxQueuedBeacons; |
| 82 | if (should_evict) |
ttuttle | ccdd6cc5 | 2015-11-22 06:09:40 | [diff] [blame] | 83 | RemoveOldestBeacon(); |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 84 | } |
| 85 | |
[email protected] | 9b203403 | 2014-05-11 18:10:31 | [diff] [blame] | 86 | void DomainReliabilityContext::ClearBeacons() { |
[email protected] | f3589bf | 2014-07-31 03:54:16 | [diff] [blame] | 87 | beacons_.clear(); |
| 88 | uploading_beacons_size_ = 0; |
[email protected] | 9b203403 | 2014-05-11 18:10:31 | [diff] [blame] | 89 | } |
| 90 | |
dcheng | 04a35cd | 2016-04-22 15:07:24 | [diff] [blame] | 91 | std::unique_ptr<Value> DomainReliabilityContext::GetWebUIData() const { |
ttuttle | ccdd6cc5 | 2015-11-22 06:09:40 | [diff] [blame] | 92 | DictionaryValue* context_value = new DictionaryValue(); |
[email protected] | a6093f41 | 2014-07-10 00:57:09 | [diff] [blame] | 93 | |
ttuttle | ccdd6cc5 | 2015-11-22 06:09:40 | [diff] [blame] | 94 | context_value->SetString("origin", config().origin.spec()); |
[email protected] | f3589bf | 2014-07-31 03:54:16 | [diff] [blame] | 95 | context_value->SetInteger("beacon_count", static_cast<int>(beacons_.size())); |
[email protected] | a6093f41 | 2014-07-10 00:57:09 | [diff] [blame] | 96 | context_value->SetInteger("uploading_beacon_count", |
[email protected] | f3589bf | 2014-07-31 03:54:16 | [diff] [blame] | 97 | static_cast<int>(uploading_beacons_size_)); |
[email protected] | a6093f41 | 2014-07-10 00:57:09 | [diff] [blame] | 98 | context_value->Set("scheduler", scheduler_.GetWebUIData()); |
| 99 | |
dcheng | 04a35cd | 2016-04-22 15:07:24 | [diff] [blame] | 100 | return std::unique_ptr<Value>(context_value); |
[email protected] | a6093f41 | 2014-07-10 00:57:09 | [diff] [blame] | 101 | } |
| 102 | |
[email protected] | f3589bf | 2014-07-31 03:54:16 | [diff] [blame] | 103 | void DomainReliabilityContext::GetQueuedBeaconsForTesting( |
ttuttle | ccdd6cc5 | 2015-11-22 06:09:40 | [diff] [blame] | 104 | std::vector<const DomainReliabilityBeacon*>* beacons_out) const { |
| 105 | DCHECK(this); |
| 106 | DCHECK(beacons_out); |
avi | 12ce31d | 2016-08-30 16:38:05 | [diff] [blame] | 107 | beacons_out->clear(); |
| 108 | for (const auto& beacon : beacons_) |
| 109 | beacons_out->push_back(beacon.get()); |
[email protected] | f3589bf | 2014-07-31 03:54:16 | [diff] [blame] | 110 | } |
| 111 | |
[email protected] | bda8e36 | 2014-03-24 18:21:03 | [diff] [blame] | 112 | void DomainReliabilityContext::ScheduleUpload( |
| 113 | base::TimeDelta min_delay, |
| 114 | base::TimeDelta max_delay) { |
| 115 | dispatcher_->ScheduleTask( |
Julia Tuttle | 30b16965 | 2017-10-16 20:19:08 | [diff] [blame] | 116 | base::Bind(&DomainReliabilityContext::CallUploadAllowedCallback, |
| 117 | weak_factory_.GetWeakPtr()), |
| 118 | min_delay, max_delay); |
| 119 | } |
| 120 | |
| 121 | void DomainReliabilityContext::CallUploadAllowedCallback() { |
| 122 | RemoveExpiredBeacons(); |
| 123 | if (beacons_.empty()) |
| 124 | return; |
| 125 | |
| 126 | upload_allowed_callback_.Run( |
| 127 | config().origin, |
tzik | 2bcf8e4 | 2018-07-31 11:22:15 | [diff] [blame] | 128 | base::BindOnce(&DomainReliabilityContext::OnUploadAllowedCallbackComplete, |
| 129 | weak_factory_.GetWeakPtr())); |
Julia Tuttle | 30b16965 | 2017-10-16 20:19:08 | [diff] [blame] | 130 | } |
| 131 | |
| 132 | void DomainReliabilityContext::OnUploadAllowedCallbackComplete(bool allowed) { |
| 133 | if (allowed) |
| 134 | StartUpload(); |
[email protected] | bda8e36 | 2014-03-24 18:21:03 | [diff] [blame] | 135 | } |
| 136 | |
| 137 | void DomainReliabilityContext::StartUpload() { |
juliatuttle | 619e356 | 2016-11-04 23:10:46 | [diff] [blame] | 138 | RemoveExpiredBeacons(); |
| 139 | if (beacons_.empty()) |
| 140 | return; |
| 141 | |
[email protected] | bda8e36 | 2014-03-24 18:21:03 | [diff] [blame] | 142 | MarkUpload(); |
| 143 | |
[email protected] | 84d2a49 | 2014-05-09 22:18:50 | [diff] [blame] | 144 | size_t collector_index = scheduler_.OnUploadStart(); |
ttuttle | ccdd6cc5 | 2015-11-22 06:09:40 | [diff] [blame] | 145 | const GURL& collector_url = *config().collectors[collector_index]; |
| 146 | |
ttuttle | 42144d8a | 2015-12-01 23:57:37 | [diff] [blame] | 147 | DCHECK(upload_time_.is_null()); |
| 148 | upload_time_ = time_->NowTicks(); |
| 149 | std::string report_json = "{}"; |
| 150 | int max_upload_depth = -1; |
| 151 | bool wrote = base::JSONWriter::Write( |
| 152 | *CreateReport(upload_time_, |
| 153 | collector_url, |
| 154 | &max_upload_depth), |
| 155 | &report_json); |
| 156 | DCHECK(wrote); |
| 157 | DCHECK_NE(-1, max_upload_depth); |
[email protected] | bda8e36 | 2014-03-24 18:21:03 | [diff] [blame] | 158 | |
| 159 | uploader_->UploadReport( |
ttuttle | 42144d8a | 2015-12-01 23:57:37 | [diff] [blame] | 160 | report_json, |
| 161 | max_upload_depth, |
| 162 | collector_url, |
| 163 | base::Bind( |
| 164 | &DomainReliabilityContext::OnUploadComplete, |
| 165 | weak_factory_.GetWeakPtr())); |
[email protected] | bda8e36 | 2014-03-24 18:21:03 | [diff] [blame] | 166 | } |
| 167 | |
ttuttle | 280a73d | 2014-11-13 21:38:04 | [diff] [blame] | 168 | void DomainReliabilityContext::OnUploadComplete( |
| 169 | const DomainReliabilityUploader::UploadResult& result) { |
| 170 | if (result.is_success()) |
[email protected] | bda8e36 | 2014-03-24 18:21:03 | [diff] [blame] | 171 | CommitUpload(); |
[email protected] | f3589bf | 2014-07-31 03:54:16 | [diff] [blame] | 172 | else |
| 173 | RollbackUpload(); |
ttuttle | 17d1302 | 2015-02-11 22:17:35 | [diff] [blame] | 174 | base::TimeTicks first_beacon_time = scheduler_.first_beacon_time(); |
ttuttle | 280a73d | 2014-11-13 21:38:04 | [diff] [blame] | 175 | scheduler_.OnUploadComplete(result); |
| 176 | UMA_HISTOGRAM_BOOLEAN("DomainReliability.UploadSuccess", |
| 177 | result.is_success()); |
ttuttle | 17d1302 | 2015-02-11 22:17:35 | [diff] [blame] | 178 | base::TimeTicks now = time_->NowTicks(); |
| 179 | UMA_HISTOGRAM_LONG_TIMES("DomainReliability.UploadLatency", |
| 180 | now - first_beacon_time); |
[email protected] | d9df3b8 | 2014-04-08 23:44:00 | [diff] [blame] | 181 | DCHECK(!upload_time_.is_null()); |
| 182 | UMA_HISTOGRAM_MEDIUM_TIMES("DomainReliability.UploadDuration", |
ttuttle | 17d1302 | 2015-02-11 22:17:35 | [diff] [blame] | 183 | now - upload_time_); |
[email protected] | d9df3b8 | 2014-04-08 23:44:00 | [diff] [blame] | 184 | last_upload_time_ = upload_time_; |
| 185 | upload_time_ = base::TimeTicks(); |
[email protected] | bda8e36 | 2014-03-24 18:21:03 | [diff] [blame] | 186 | } |
| 187 | |
dcheng | 04a35cd | 2016-04-22 15:07:24 | [diff] [blame] | 188 | std::unique_ptr<const Value> DomainReliabilityContext::CreateReport( |
ttuttle | ccdd6cc5 | 2015-11-22 06:09:40 | [diff] [blame] | 189 | base::TimeTicks upload_time, |
ttuttle | 42144d8a | 2015-12-01 23:57:37 | [diff] [blame] | 190 | const GURL& collector_url, |
| 191 | int* max_upload_depth_out) const { |
| 192 | int max_upload_depth = 0; |
| 193 | |
dcheng | 04a35cd | 2016-04-22 15:07:24 | [diff] [blame] | 194 | std::unique_ptr<ListValue> beacons_value(new ListValue()); |
avi | 12ce31d | 2016-08-30 16:38:05 | [diff] [blame] | 195 | for (const auto& beacon : beacons_) { |
ttuttle | ccdd6cc5 | 2015-11-22 06:09:40 | [diff] [blame] | 196 | beacons_value->Append(beacon->ToValue(upload_time, |
| 197 | *last_network_change_time_, |
| 198 | collector_url, |
| 199 | config().path_prefixes)); |
ttuttle | 42144d8a | 2015-12-01 23:57:37 | [diff] [blame] | 200 | if (beacon->upload_depth > max_upload_depth) |
| 201 | max_upload_depth = beacon->upload_depth; |
[email protected] | 90c0333 | 2014-05-16 17:35:18 | [diff] [blame] | 202 | } |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 203 | |
dcheng | 04a35cd | 2016-04-22 15:07:24 | [diff] [blame] | 204 | std::unique_ptr<DictionaryValue> report_value(new DictionaryValue()); |
[email protected] | 84d2a49 | 2014-05-09 22:18:50 | [diff] [blame] | 205 | report_value->SetString("reporter", upload_reporter_string_); |
jdoerrie | c1a515d | 2017-06-02 09:44:38 | [diff] [blame] | 206 | report_value->Set("entries", std::move(beacons_value)); |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 207 | |
ttuttle | 42144d8a | 2015-12-01 23:57:37 | [diff] [blame] | 208 | *max_upload_depth_out = max_upload_depth; |
dcheng | 5160635 | 2015-12-26 21:16:23 | [diff] [blame] | 209 | return std::move(report_value); |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 210 | } |
| 211 | |
| 212 | void DomainReliabilityContext::MarkUpload() { |
[email protected] | f3589bf | 2014-07-31 03:54:16 | [diff] [blame] | 213 | DCHECK_EQ(0u, uploading_beacons_size_); |
| 214 | uploading_beacons_size_ = beacons_.size(); |
| 215 | DCHECK_NE(0u, uploading_beacons_size_); |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 216 | } |
| 217 | |
| 218 | void DomainReliabilityContext::CommitUpload() { |
ttuttle | ccdd6cc5 | 2015-11-22 06:09:40 | [diff] [blame] | 219 | auto begin = beacons_.begin(); |
| 220 | auto end = begin + uploading_beacons_size_; |
[email protected] | f3589bf | 2014-07-31 03:54:16 | [diff] [blame] | 221 | beacons_.erase(begin, end); |
| 222 | DCHECK_NE(0u, uploading_beacons_size_); |
| 223 | uploading_beacons_size_ = 0; |
| 224 | } |
| 225 | |
| 226 | void DomainReliabilityContext::RollbackUpload() { |
[email protected] | f3589bf | 2014-07-31 03:54:16 | [diff] [blame] | 227 | DCHECK_NE(0u, uploading_beacons_size_); |
| 228 | uploading_beacons_size_ = 0; |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 229 | } |
| 230 | |
| 231 | void DomainReliabilityContext::RemoveOldestBeacon() { |
[email protected] | f3589bf | 2014-07-31 03:54:16 | [diff] [blame] | 232 | DCHECK(!beacons_.empty()); |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 233 | |
Misha Efimov | 99c53bcf | 2018-11-14 20:26:23 | [diff] [blame] | 234 | DVLOG(1) << "Beacon queue for " << config().origin << " full; " |
| 235 | << "removing oldest beacon"; |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 236 | |
[email protected] | f3589bf | 2014-07-31 03:54:16 | [diff] [blame] | 237 | beacons_.pop_front(); |
| 238 | |
| 239 | // If that just removed a beacon counted in uploading_beacons_size_, decrement |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 240 | // that. |
[email protected] | f3589bf | 2014-07-31 03:54:16 | [diff] [blame] | 241 | if (uploading_beacons_size_ > 0) |
| 242 | --uploading_beacons_size_; |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 243 | } |
| 244 | |
juliatuttle | 619e356 | 2016-11-04 23:10:46 | [diff] [blame] | 245 | void DomainReliabilityContext::RemoveExpiredBeacons() { |
| 246 | base::TimeTicks now = time_->NowTicks(); |
| 247 | const base::TimeDelta kMaxAge = base::TimeDelta::FromHours(1); |
| 248 | while (!beacons_.empty() && now - beacons_.front()->start_time >= kMaxAge) |
| 249 | beacons_.pop_front(); |
| 250 | } |
| 251 | |
[email protected] | 45de676a | 2014-03-18 23:52:02 | [diff] [blame] | 252 | } // namespace domain_reliability |