Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(187)

Side by Side Diff: components/domain_reliability/context.cc

Issue 252613002: Domain Reliability: More security review. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: ;_; Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/domain_reliability/context.h" 5 #include "components/domain_reliability/context.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/json/json_writer.h" 10 #include "base/json/json_writer.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/metrics/histogram.h" 12 #include "base/metrics/histogram.h"
13 #include "base/metrics/sparse_histogram.h" 13 #include "base/metrics/sparse_histogram.h"
14 #include "base/values.h" 14 #include "base/values.h"
15 #include "components/domain_reliability/beacon.h"
15 #include "components/domain_reliability/dispatcher.h" 16 #include "components/domain_reliability/dispatcher.h"
16 #include "net/base/net_errors.h" 17 #include "net/base/net_errors.h"
17 #include "net/url_request/url_request_context_getter.h" 18 #include "net/url_request/url_request_context_getter.h"
18 19
19 using base::DictionaryValue; 20 using base::DictionaryValue;
20 using base::ListValue; 21 using base::ListValue;
21 using base::Value; 22 using base::Value;
22 23
23 namespace domain_reliability { 24 namespace domain_reliability {
24 25
25 namespace { 26 namespace {
26 const char* kReporter = "chrome";
27 typedef std::deque<DomainReliabilityBeacon> BeaconDeque; 27 typedef std::deque<DomainReliabilityBeacon> BeaconDeque;
28 typedef BeaconDeque::iterator BeaconIterator; 28 typedef BeaconDeque::iterator BeaconIterator;
29 typedef BeaconDeque::const_iterator BeaconConstIterator; 29 typedef BeaconDeque::const_iterator BeaconConstIterator;
30 } // namespace 30 } // namespace
31 31
32 const int DomainReliabilityContext::kMaxQueuedBeacons = 150; 32 class DomainReliabilityContext::ResourceState {
33 public:
34 ResourceState(DomainReliabilityContext* context,
35 const DomainReliabilityConfig::Resource* config)
36 : context(context),
37 config(config),
38 successful_requests(0),
39 failed_requests(0) {}
40 ~ResourceState() {}
41
42 scoped_ptr<base::Value> ToValue(base::TimeTicks upload_time) const {
43 ListValue* beacons_value = new ListValue();
44 for (BeaconConstIterator it = beacons.begin(); it != beacons.end(); ++it)
45 beacons_value->Append(it->ToValue(upload_time));
46
47 DictionaryValue* resource_value = new DictionaryValue();
48 resource_value->SetString("resource_name", config->name);
49 resource_value->SetInteger("successful_requests", successful_requests);
50 resource_value->SetInteger("failed_requests", failed_requests);
51 resource_value->Set("beacons", beacons_value);
52
53 return scoped_ptr<Value>(resource_value);
54 }
55
56 // Remembers the current state of the resource data when an upload starts.
57 void MarkUpload() {
58 uploading_beacons_size = beacons.size();
59 uploading_successful_requests = successful_requests;
60 uploading_failed_requests = failed_requests;
61 }
62
63 // Uses the state remembered by |MarkUpload| to remove successfully uploaded
64 // data but keep beacons and request counts added after the upload started.
65 void CommitUpload() {
66 BeaconIterator begin = beacons.begin();
67 BeaconIterator end = begin + uploading_beacons_size;
68 beacons.erase(begin, end);
69 successful_requests -= uploading_successful_requests;
70 failed_requests -= uploading_failed_requests;
71 }
72
73 // Gets the start time of the oldest beacon, if there are any. Returns true
74 // and sets |oldest_start_out| if so; otherwise, returns false.
75 bool GetOldestBeaconStart(base::TimeTicks* oldest_start_out) const {
76 if (beacons.empty())
77 return false;
78 *oldest_start_out = beacons[0].start_time;
79 return true;
80 }
81
82 // Removes the oldest beacon. DCHECKs if there isn't one.
83 void RemoveOldestBeacon() {
84 DCHECK(!beacons.empty());
85 beacons.erase(beacons.begin());
86 // If that just removed a beacon counted in uploading_beacons_size,
87 // decrement
88 // that.
89 if (uploading_beacons_size > 0)
90 --uploading_beacons_size;
91 }
92
93 DomainReliabilityContext* context;
94 const DomainReliabilityConfig::Resource* config;
95
96 std::deque<DomainReliabilityBeacon> beacons;
97 uint32 successful_requests;
98 uint32 failed_requests;
99
100 // State saved during uploads; if an upload succeeds, these are used to
101 // remove uploaded data from the beacon list and request counters.
102 size_t uploading_beacons_size;
103 uint32 uploading_successful_requests;
104 uint32 uploading_failed_requests;
105
106 private:
107 DISALLOW_COPY_AND_ASSIGN(ResourceState);
108 };
109
110 // static
111 const size_t DomainReliabilityContext::kMaxQueuedBeacons = 150;
33 112
34 DomainReliabilityContext::DomainReliabilityContext( 113 DomainReliabilityContext::DomainReliabilityContext(
35 MockableTime* time, 114 MockableTime* time,
36 const DomainReliabilityScheduler::Params& scheduler_params, 115 const DomainReliabilityScheduler::Params& scheduler_params,
116 const std::string& upload_reporter_string,
37 DomainReliabilityDispatcher* dispatcher, 117 DomainReliabilityDispatcher* dispatcher,
38 DomainReliabilityUploader* uploader, 118 DomainReliabilityUploader* uploader,
39 scoped_ptr<const DomainReliabilityConfig> config) 119 scoped_ptr<const DomainReliabilityConfig> config)
40 : config_(config.Pass()), 120 : config_(config.Pass()),
41 time_(time), 121 time_(time),
42 scheduler_(time, config_->collectors.size(), scheduler_params, 122 upload_reporter_string_(upload_reporter_string),
123 scheduler_(time,
124 config_->collectors.size(),
125 scheduler_params,
43 base::Bind(&DomainReliabilityContext::ScheduleUpload, 126 base::Bind(&DomainReliabilityContext::ScheduleUpload,
44 base::Unretained(this))), 127 base::Unretained(this))),
45 dispatcher_(dispatcher), 128 dispatcher_(dispatcher),
46 uploader_(uploader), 129 uploader_(uploader),
47 beacon_count_(0), 130 beacon_count_(0),
48 weak_factory_(this) { 131 weak_factory_(this) {
49 InitializeResourceStates(); 132 InitializeResourceStates();
50 } 133 }
51 134
52 DomainReliabilityContext::~DomainReliabilityContext() {} 135 DomainReliabilityContext::~DomainReliabilityContext() {}
53 136
54 void DomainReliabilityContext::AddBeacon( 137 void DomainReliabilityContext::OnBeacon(const GURL& url,
55 const DomainReliabilityBeacon& beacon, 138 const DomainReliabilityBeacon& beacon) {
56 const GURL& url) { 139 size_t index = config_->GetResourceIndexForUrl(url);
57 int index = config_->GetResourceIndexForUrl(url); 140 if (index == DomainReliabilityConfig::kInvalidResourceIndex)
58 if (index < 0)
59 return; 141 return;
60 DCHECK_GT(states_.size(), static_cast<size_t>(index)); 142 DCHECK_GT(states_.size(), index);
61 143
62 ResourceState* state = states_[index]; 144 ResourceState* state = states_[index];
63 bool success = beacon.http_response_code >= 200 && 145 bool success = beacon.http_response_code >= 200 &&
64 beacon.http_response_code < 400; 146 beacon.http_response_code < 400;
65 if (success) 147 if (success)
66 ++state->successful_requests; 148 ++state->successful_requests;
67 else 149 else
68 ++state->failed_requests; 150 ++state->failed_requests;
69 151
70 VLOG(1) << "Received Beacon: "
71 << state->config->name << " "
72 << beacon.status << " "
73 << beacon.chrome_error << " "
74 << beacon.http_response_code << " "
75 << beacon.server_ip << " "
76 << beacon.elapsed.InMilliseconds() << "ms";
77
78 bool reported = false; 152 bool reported = false;
79 bool evicted = false; 153 bool evicted = false;
80 if (state->config->DecideIfShouldReportRequest(success)) { 154 if (state->config->DecideIfShouldReportRequest(success)) {
81 state->beacons.push_back(beacon); 155 state->beacons.push_back(beacon);
82 ++beacon_count_; 156 ++beacon_count_;
83 if (beacon_count_ > kMaxQueuedBeacons) { 157 if (beacon_count_ > kMaxQueuedBeacons) {
84 RemoveOldestBeacon(); 158 RemoveOldestBeacon();
85 evicted = true; 159 evicted = true;
86 } 160 }
87 scheduler_.OnBeaconAdded(); 161 scheduler_.OnBeaconAdded();
88 reported = true; 162 reported = true;
89 UMA_HISTOGRAM_SPARSE_SLOWLY("DomainReliability.ReportedBeaconError", 163 UMA_HISTOGRAM_SPARSE_SLOWLY("DomainReliability.ReportedBeaconError",
90 -beacon.chrome_error); 164 -beacon.chrome_error);
91 // TODO(ttuttle): Histogram HTTP response code? 165 // TODO(ttuttle): Histogram HTTP response code?
92 } 166 }
93 167
94 UMA_HISTOGRAM_BOOLEAN("DomainReliability.BeaconReported", reported); 168 UMA_HISTOGRAM_BOOLEAN("DomainReliability.BeaconReported", reported);
95 UMA_HISTOGRAM_BOOLEAN("DomainReliability.AddBeaconDidEvict", evicted); 169 UMA_HISTOGRAM_BOOLEAN("DomainReliability.OnBeaconDidEvict", evicted);
96 } 170 }
97 171
98 void DomainReliabilityContext::GetQueuedDataForTesting( 172 void DomainReliabilityContext::GetQueuedDataForTesting(
99 int resource_index, 173 size_t resource_index,
100 std::vector<DomainReliabilityBeacon>* beacons_out, 174 std::vector<DomainReliabilityBeacon>* beacons_out,
101 int* successful_requests_out, 175 uint32* successful_requests_out,
102 int* failed_requests_out) const { 176 uint32* failed_requests_out) const {
103 DCHECK_LE(0, resource_index); 177 DCHECK_NE(DomainReliabilityConfig::kInvalidResourceIndex, resource_index);
104 DCHECK_GT(static_cast<int>(states_.size()), resource_index); 178 DCHECK_GT(states_.size(), resource_index);
105 const ResourceState& state = *states_[resource_index]; 179 const ResourceState& state = *states_[resource_index];
106 if (beacons_out) { 180 if (beacons_out)
107 beacons_out->resize(state.beacons.size()); 181 beacons_out->assign(state.beacons.begin(), state.beacons.end());
108 std::copy(state.beacons.begin(), state.beacons.end(), beacons_out->begin());
109 }
110 if (successful_requests_out) 182 if (successful_requests_out)
111 *successful_requests_out = state.successful_requests; 183 *successful_requests_out = state.successful_requests;
112 if (failed_requests_out) 184 if (failed_requests_out)
113 *failed_requests_out = state.failed_requests; 185 *failed_requests_out = state.failed_requests;
114 } 186 }
115 187
116 DomainReliabilityContext::ResourceState::ResourceState(
117 DomainReliabilityContext* context,
118 const DomainReliabilityConfig::Resource* config)
119 : context(context),
120 config(config),
121 successful_requests(0),
122 failed_requests(0) {}
123
124 DomainReliabilityContext::ResourceState::~ResourceState() {}
125
126 scoped_ptr<Value> DomainReliabilityContext::ResourceState::ToValue(
127 base::TimeTicks upload_time) const {
128 ListValue* beacons_value = new ListValue();
129 for (BeaconConstIterator it = beacons.begin(); it != beacons.end(); ++it)
130 beacons_value->Append(it->ToValue(upload_time));
131
132 DictionaryValue* resource_value = new DictionaryValue();
133 resource_value->SetString("resource_name", config->name);
134 resource_value->SetInteger("successful_requests", successful_requests);
135 resource_value->SetInteger("failed_requests", failed_requests);
136 resource_value->Set("beacons", beacons_value);
137
138 return scoped_ptr<Value>(resource_value);
139 }
140
141 void DomainReliabilityContext::ResourceState::MarkUpload() {
142 uploading_beacons_size = beacons.size();
143 uploading_successful_requests = successful_requests;
144 uploading_failed_requests = failed_requests;
145 }
146
147 void DomainReliabilityContext::ResourceState::CommitUpload() {
148 BeaconIterator begin = beacons.begin();
149 BeaconIterator end = begin + uploading_beacons_size;
150 beacons.erase(begin, end);
151 successful_requests -= uploading_successful_requests;
152 failed_requests -= uploading_failed_requests;
153 }
154
155 bool DomainReliabilityContext::ResourceState::GetOldestBeaconStart(
156 base::TimeTicks* oldest_start_out) const {
157 if (beacons.empty())
158 return false;
159
160 *oldest_start_out = beacons[0].start_time;
161 return true;
162 }
163
164 void DomainReliabilityContext::ResourceState::RemoveOldestBeacon() {
165 DCHECK(!beacons.empty());
166 beacons.erase(beacons.begin());
167 // If that just removed a beacon counted in uploading_beacons_size, decrement
168 // that.
169 if (uploading_beacons_size > 0)
170 --uploading_beacons_size;
171 }
172
173 void DomainReliabilityContext::InitializeResourceStates() { 188 void DomainReliabilityContext::InitializeResourceStates() {
174 ScopedVector<DomainReliabilityConfig::Resource>::const_iterator it; 189 ScopedVector<DomainReliabilityConfig::Resource>::const_iterator it;
175 for (it = config_->resources.begin(); it != config_->resources.end(); ++it) 190 for (it = config_->resources.begin(); it != config_->resources.end(); ++it)
176 states_.push_back(new ResourceState(this, *it)); 191 states_.push_back(new ResourceState(this, *it));
177 } 192 }
178 193
179 void DomainReliabilityContext::ScheduleUpload( 194 void DomainReliabilityContext::ScheduleUpload(
180 base::TimeDelta min_delay, 195 base::TimeDelta min_delay,
181 base::TimeDelta max_delay) { 196 base::TimeDelta max_delay) {
182 dispatcher_->ScheduleTask( 197 dispatcher_->ScheduleTask(
183 base::Bind( 198 base::Bind(
184 &DomainReliabilityContext::StartUpload, 199 &DomainReliabilityContext::StartUpload,
185 weak_factory_.GetWeakPtr()), 200 weak_factory_.GetWeakPtr()),
186 min_delay, 201 min_delay,
187 max_delay); 202 max_delay);
188 } 203 }
189 204
190 void DomainReliabilityContext::StartUpload() { 205 void DomainReliabilityContext::StartUpload() {
191 MarkUpload(); 206 MarkUpload();
192 207
193 DCHECK(upload_time_.is_null()); 208 DCHECK(upload_time_.is_null());
194 upload_time_ = time_->NowTicks(); 209 upload_time_ = time_->NowTicks();
195 std::string report_json; 210 std::string report_json;
196 scoped_ptr<const Value> report_value(CreateReport(upload_time_)); 211 scoped_ptr<const Value> report_value(CreateReport(upload_time_));
197 base::JSONWriter::Write(report_value.get(), &report_json); 212 base::JSONWriter::Write(report_value.get(), &report_json);
198 report_value.reset(); 213 report_value.reset();
199 214
200 int collector_index; 215 size_t collector_index = scheduler_.OnUploadStart();
201 scheduler_.OnUploadStart(&collector_index);
202 216
203 uploader_->UploadReport( 217 uploader_->UploadReport(
204 report_json, 218 report_json,
205 config_->collectors[collector_index]->upload_url, 219 config_->collectors[collector_index]->upload_url,
206 base::Bind( 220 base::Bind(
207 &DomainReliabilityContext::OnUploadComplete, 221 &DomainReliabilityContext::OnUploadComplete,
208 weak_factory_.GetWeakPtr())); 222 weak_factory_.GetWeakPtr()));
209 223
210 UMA_HISTOGRAM_BOOLEAN("DomainReliability.UploadFailover", 224 UMA_HISTOGRAM_BOOLEAN("DomainReliability.UploadFailover",
211 collector_index > 0); 225 collector_index > 0);
(...skipping 15 matching lines...) Expand all
227 upload_time_ = base::TimeTicks(); 241 upload_time_ = base::TimeTicks();
228 } 242 }
229 243
230 scoped_ptr<const Value> DomainReliabilityContext::CreateReport( 244 scoped_ptr<const Value> DomainReliabilityContext::CreateReport(
231 base::TimeTicks upload_time) const { 245 base::TimeTicks upload_time) const {
232 ListValue* resources_value = new ListValue(); 246 ListValue* resources_value = new ListValue();
233 for (ResourceStateIterator it = states_.begin(); it != states_.end(); ++it) 247 for (ResourceStateIterator it = states_.begin(); it != states_.end(); ++it)
234 resources_value->Append((*it)->ToValue(upload_time).release()); 248 resources_value->Append((*it)->ToValue(upload_time).release());
235 249
236 DictionaryValue* report_value = new DictionaryValue(); 250 DictionaryValue* report_value = new DictionaryValue();
237 report_value->SetString("reporter", kReporter); 251 report_value->SetString("reporter", upload_reporter_string_);
238 report_value->Set("resource_reports", resources_value); 252 report_value->Set("resource_reports", resources_value);
239 253
240 return scoped_ptr<const Value>(report_value); 254 return scoped_ptr<const Value>(report_value);
241 } 255 }
242 256
243 void DomainReliabilityContext::MarkUpload() { 257 void DomainReliabilityContext::MarkUpload() {
244 for (ResourceStateIterator it = states_.begin(); it != states_.end(); ++it) 258 for (ResourceStateIterator it = states_.begin(); it != states_.end(); ++it)
245 (*it)->MarkUpload(); 259 (*it)->MarkUpload();
246 uploading_beacon_count_ = beacon_count_; 260 uploading_beacon_count_ = beacon_count_;
247 } 261 }
248 262
249 void DomainReliabilityContext::CommitUpload() { 263 void DomainReliabilityContext::CommitUpload() {
250 for (ResourceStateIterator it = states_.begin(); it != states_.end(); ++it) 264 for (ResourceStateIterator it = states_.begin(); it != states_.end(); ++it)
251 (*it)->CommitUpload(); 265 (*it)->CommitUpload();
252 beacon_count_ -= uploading_beacon_count_; 266 beacon_count_ -= uploading_beacon_count_;
253 } 267 }
254 268
255 void DomainReliabilityContext::RemoveOldestBeacon() { 269 void DomainReliabilityContext::RemoveOldestBeacon() {
256 DCHECK_LT(0, beacon_count_); 270 DCHECK_LT(0u, beacon_count_);
257 271
258 base::TimeTicks min_time; 272 base::TimeTicks min_time;
259 ResourceState* min_resource = NULL; 273 ResourceState* min_resource = NULL;
260 for (ResourceStateIterator it = states_.begin(); it != states_.end(); ++it) { 274 for (ResourceStateIterator it = states_.begin(); it != states_.end(); ++it) {
261 base::TimeTicks oldest; 275 base::TimeTicks oldest;
262 if ((*it)->GetOldestBeaconStart(&oldest)) { 276 if ((*it)->GetOldestBeaconStart(&oldest)) {
263 if (!min_resource || oldest < min_time) { 277 if (!min_resource || oldest < min_time) {
264 min_time = oldest; 278 min_time = oldest;
265 min_resource = *it; 279 min_resource = *it;
266 } 280 }
267 } 281 }
268 } 282 }
269 DCHECK(min_resource); 283 DCHECK(min_resource);
270 284
271 VLOG(1) << "Removing oldest beacon from " << min_resource->config->name; 285 VLOG(1) << "Beacon queue for " << config().domain << " full; "
286 << "removing oldest beacon from " << min_resource->config->name;
272 287
273 min_resource->RemoveOldestBeacon(); 288 min_resource->RemoveOldestBeacon();
274 --beacon_count_; 289 --beacon_count_;
275 // If that just removed a beacon counted in uploading_beacon_count_, decrement 290 // If that just removed a beacon counted in uploading_beacon_count_, decrement
276 // that. 291 // that.
277 if (uploading_beacon_count_ > 0) 292 if (uploading_beacon_count_ > 0)
278 --uploading_beacon_count_; 293 --uploading_beacon_count_;
279 } 294 }
280 295
281 } // namespace domain_reliability 296 } // namespace domain_reliability
OLDNEW
« no previous file with comments | « components/domain_reliability/context.h ('k') | components/domain_reliability/context_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698