OLD | NEW |
---|---|
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/monitor.h" | 5 #include "components/domain_reliability/monitor.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/profiler/scoped_tracker.h" | 9 #include "base/profiler/scoped_tracker.h" |
10 #include "base/single_thread_task_runner.h" | 10 #include "base/single_thread_task_runner.h" |
11 #include "base/task_runner.h" | 11 #include "base/task_runner.h" |
12 #include "base/time/time.h" | 12 #include "base/time/time.h" |
13 #include "components/domain_reliability/baked_in_configs.h" | 13 #include "components/domain_reliability/baked_in_configs.h" |
14 #include "net/base/ip_endpoint.h" | |
14 #include "net/base/load_flags.h" | 15 #include "net/base/load_flags.h" |
16 #include "net/base/net_errors.h" | |
17 #include "net/base/net_util.h" | |
15 #include "net/http/http_response_headers.h" | 18 #include "net/http/http_response_headers.h" |
16 #include "net/url_request/url_request.h" | 19 #include "net/url_request/url_request.h" |
17 #include "net/url_request/url_request_context.h" | 20 #include "net/url_request/url_request_context.h" |
18 #include "net/url_request/url_request_context_getter.h" | 21 #include "net/url_request/url_request_context_getter.h" |
19 | 22 |
20 namespace domain_reliability { | 23 namespace domain_reliability { |
21 | 24 |
25 namespace { | |
26 | |
27 int URLRequestStatusToNetError(const net::URLRequestStatus& status) { | |
davidben
2015/05/15 18:36:50
[Not your fault, but we really need to get rid of
Deprecated (see juliatuttle)
2015/05/15 19:08:45
Yup.
| |
28 switch (status.status()) { | |
29 case net::URLRequestStatus::SUCCESS: | |
30 return net::OK; | |
31 case net::URLRequestStatus::IO_PENDING: | |
32 return net::ERR_IO_PENDING; | |
33 case net::URLRequestStatus::CANCELED: | |
34 return net::ERR_ABORTED; | |
35 case net::URLRequestStatus::FAILED: | |
36 return status.error(); | |
37 default: | |
38 NOTREACHED(); | |
39 return net::ERR_UNEXPECTED; | |
40 } | |
41 } | |
42 | |
davidben
2015/05/15 18:36:50
This function is confusing since it intentionally
Deprecated (see juliatuttle)
2015/05/15 19:08:45
Done.
| |
43 bool FillBeaconFromAttempt( | |
44 DomainReliabilityBeacon* beacon, | |
45 const net::ConnectionAttempt& attempt) { | |
46 if (!GetDomainReliabilityBeaconStatus( | |
47 attempt.result, | |
48 beacon->http_response_code, | |
49 &beacon->status)) { | |
davidben
2015/05/15 18:36:50
Mind doing a git cl format pass? I'm not sure that
Deprecated (see juliatuttle)
2015/05/15 19:08:45
Done.
| |
50 return false; | |
51 } | |
52 beacon->chrome_error = attempt.result; | |
53 if (!attempt.endpoint.address().empty()) | |
54 beacon->server_ip = attempt.endpoint.ToString(); | |
55 else | |
56 beacon->server_ip = ""; | |
57 return true; | |
58 } | |
59 | |
60 // TODO(ttuttle): This function is absurd. See if |socket_address| in | |
61 // HttpResponseInfo can become an IPEndPoint. | |
62 bool ConvertHostPortPairToIPEndPoint(const net::HostPortPair& host_port_pair, | |
63 net::IPEndPoint* ip_endpoint_out) { | |
64 net::IPAddressNumber ip_address_number; | |
65 if (!net::ParseIPLiteralToNumber(host_port_pair.host(), &ip_address_number)) | |
davidben
2015/05/15 18:36:50
Are you sure this is correct? When an IPv6 address
Deprecated (see juliatuttle)
2015/05/15 19:08:45
Yep, it's correct. HostPortPair eventually uses ur
davidben
2015/05/15 19:46:18
Acknowledged.
| |
66 return false; | |
67 *ip_endpoint_out = net::IPEndPoint(ip_address_number, host_port_pair.port()); | |
68 return true; | |
69 } | |
70 | |
71 } // namespace | |
72 | |
22 DomainReliabilityMonitor::DomainReliabilityMonitor( | 73 DomainReliabilityMonitor::DomainReliabilityMonitor( |
23 const std::string& upload_reporter_string, | 74 const std::string& upload_reporter_string, |
24 const scoped_refptr<base::SingleThreadTaskRunner>& pref_thread, | 75 const scoped_refptr<base::SingleThreadTaskRunner>& pref_thread, |
25 const scoped_refptr<base::SingleThreadTaskRunner>& network_thread) | 76 const scoped_refptr<base::SingleThreadTaskRunner>& network_thread) |
26 : time_(new ActualTime()), | 77 : time_(new ActualTime()), |
27 upload_reporter_string_(upload_reporter_string), | 78 upload_reporter_string_(upload_reporter_string), |
28 scheduler_params_( | 79 scheduler_params_( |
29 DomainReliabilityScheduler::Params::GetFromFieldTrialsOrDefaults()), | 80 DomainReliabilityScheduler::Params::GetFromFieldTrialsOrDefaults()), |
30 dispatcher_(time_.get()), | 81 dispatcher_(time_.get()), |
31 context_manager_(this), | 82 context_manager_(this), |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
143 } | 194 } |
144 | 195 |
145 void DomainReliabilityMonitor::OnCompleted(net::URLRequest* request, | 196 void DomainReliabilityMonitor::OnCompleted(net::URLRequest* request, |
146 bool started) { | 197 bool started) { |
147 DCHECK(OnNetworkThread()); | 198 DCHECK(OnNetworkThread()); |
148 DCHECK(discard_uploads_set_); | 199 DCHECK(discard_uploads_set_); |
149 | 200 |
150 if (!started) | 201 if (!started) |
151 return; | 202 return; |
152 RequestInfo request_info(*request); | 203 RequestInfo request_info(*request); |
153 if (request_info.AccessedNetwork()) { | 204 OnRequestLegComplete(request_info); |
154 OnRequestLegComplete(request_info); | 205 |
206 if (request_info.response_info.network_accessed) { | |
155 // A request was just using the network, so now is a good time to run any | 207 // A request was just using the network, so now is a good time to run any |
156 // pending and eligible uploads. | 208 // pending and eligible uploads. |
157 dispatcher_.RunEligibleTasks(); | 209 dispatcher_.RunEligibleTasks(); |
158 } | 210 } |
159 } | 211 } |
160 | 212 |
161 void DomainReliabilityMonitor::OnNetworkChanged( | 213 void DomainReliabilityMonitor::OnNetworkChanged( |
162 net::NetworkChangeNotifier::ConnectionType type) { | 214 net::NetworkChangeNotifier::ConnectionType type) { |
163 last_network_change_time_ = time_->NowTicks(); | 215 last_network_change_time_ = time_->NowTicks(); |
164 } | 216 } |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
214 DomainReliabilityMonitor::RequestInfo::RequestInfo() {} | 266 DomainReliabilityMonitor::RequestInfo::RequestInfo() {} |
215 | 267 |
216 DomainReliabilityMonitor::RequestInfo::RequestInfo( | 268 DomainReliabilityMonitor::RequestInfo::RequestInfo( |
217 const net::URLRequest& request) | 269 const net::URLRequest& request) |
218 : url(request.url()), | 270 : url(request.url()), |
219 status(request.status()), | 271 status(request.status()), |
220 response_info(request.response_info()), | 272 response_info(request.response_info()), |
221 load_flags(request.load_flags()), | 273 load_flags(request.load_flags()), |
222 is_upload(DomainReliabilityUploader::URLRequestIsUpload(request)) { | 274 is_upload(DomainReliabilityUploader::URLRequestIsUpload(request)) { |
223 request.GetLoadTimingInfo(&load_timing_info); | 275 request.GetLoadTimingInfo(&load_timing_info); |
276 request.GetConnectionAttempts(&connection_attempts); | |
224 } | 277 } |
225 | 278 |
226 DomainReliabilityMonitor::RequestInfo::~RequestInfo() {} | 279 DomainReliabilityMonitor::RequestInfo::~RequestInfo() {} |
227 | 280 |
228 bool DomainReliabilityMonitor::RequestInfo::AccessedNetwork() const { | 281 // static |
229 return status.status() != net::URLRequestStatus::CANCELED && | 282 bool DomainReliabilityMonitor::RequestInfo::ShouldReportRequest( |
230 response_info.network_accessed; | 283 const DomainReliabilityMonitor::RequestInfo& request) { |
284 if (request.is_upload) | |
285 return false; | |
286 if (request.load_flags & net::LOAD_DO_NOT_SEND_COOKIES) | |
287 return false; | |
288 if (request.response_info.network_accessed) | |
289 return true; | |
290 if (URLRequestStatusToNetError(request.status) != net::OK) | |
291 return true; | |
davidben
2015/05/15 18:36:50
This is a change from the current behavior. Before
Deprecated (see juliatuttle)
2015/05/15 19:08:45
I moved a bunch of the logic into this function --
davidben
2015/05/15 19:46:18
Right, and that one didn't change in behavior. The
| |
292 return false; | |
231 } | 293 } |
232 | 294 |
233 void DomainReliabilityMonitor::OnRequestLegComplete( | 295 void DomainReliabilityMonitor::OnRequestLegComplete( |
234 const RequestInfo& request) { | 296 const RequestInfo& request) { |
235 // Check these again because unit tests call this directly. | 297 // Check these again because unit tests call this directly. |
236 DCHECK(OnNetworkThread()); | 298 DCHECK(OnNetworkThread()); |
237 DCHECK(discard_uploads_set_); | 299 DCHECK(discard_uploads_set_); |
238 | 300 |
301 if (!RequestInfo::ShouldReportRequest(request)) | |
302 return; | |
303 | |
239 int response_code; | 304 int response_code; |
240 if (request.response_info.headers.get()) | 305 if (request.response_info.headers.get()) |
241 response_code = request.response_info.headers->response_code(); | 306 response_code = request.response_info.headers->response_code(); |
242 else | 307 else |
243 response_code = -1; | 308 response_code = -1; |
244 std::string beacon_status; | |
245 | 309 |
246 int error_code = net::OK; | 310 net::IPEndPoint url_request_endpoint; |
247 if (request.status.status() == net::URLRequestStatus::FAILED) | 311 // If response was cached, socket address will be from the serialized |
248 error_code = request.status.error(); | 312 // response info in the cache, so don't report it. |
249 | 313 // TODO(ttuttle): Plumb out the "current" socket address so we can always |
250 // Ignore requests where: | 314 // report it. |
251 // 1. The request did not access the network. | 315 if (!request.response_info.was_cached && |
252 // 2. The request is not supposed to send cookies (to avoid associating the | 316 !request.response_info.was_fetched_via_proxy) { |
253 // request with any potentially unique data in the config). | 317 ConvertHostPortPairToIPEndPoint(request.response_info.socket_address, |
254 // 3. The request was itself a Domain Reliability upload (to avoid loops). | 318 &url_request_endpoint); |
255 // 4. There is no matching beacon status for the error or HTTP response code | |
256 // (to avoid leaking network-local errors). | |
257 if (!request.AccessedNetwork() || | |
258 (request.load_flags & net::LOAD_DO_NOT_SEND_COOKIES) || | |
259 request.is_upload || | |
260 !GetDomainReliabilityBeaconStatus( | |
261 error_code, response_code, &beacon_status)) { | |
262 return; | |
263 } | 319 } |
264 | 320 |
321 net::ConnectionAttempt url_request_attempt( | |
322 url_request_endpoint, | |
323 URLRequestStatusToNetError(request.status)); | |
324 | |
265 DomainReliabilityBeacon beacon; | 325 DomainReliabilityBeacon beacon; |
266 beacon.status = beacon_status; | |
267 beacon.chrome_error = error_code; | |
268 // If the response was cached, the socket address was the address that the | |
269 // response was originally received from, so it shouldn't be copied into the | |
270 // beacon. | |
271 // | |
272 // TODO(ttuttle): Wire up a way to get the real socket address in that case. | |
273 if (!request.response_info.was_cached && | |
274 !request.response_info.was_fetched_via_proxy) { | |
275 beacon.server_ip = request.response_info.socket_address.host(); | |
276 } | |
277 beacon.protocol = GetDomainReliabilityProtocol( | 326 beacon.protocol = GetDomainReliabilityProtocol( |
278 request.response_info.connection_info, | 327 request.response_info.connection_info, |
279 request.response_info.ssl_info.is_valid()); | 328 request.response_info.ssl_info.is_valid()); |
280 beacon.http_response_code = response_code; | 329 beacon.http_response_code = response_code; |
281 beacon.start_time = request.load_timing_info.request_start; | 330 beacon.start_time = request.load_timing_info.request_start; |
282 beacon.elapsed = time_->NowTicks() - beacon.start_time; | 331 beacon.elapsed = time_->NowTicks() - beacon.start_time; |
283 beacon.was_proxied = request.response_info.was_fetched_via_proxy; | 332 beacon.was_proxied = request.response_info.was_fetched_via_proxy; |
284 beacon.domain = request.url.host(); | 333 beacon.domain = request.url.host(); |
334 | |
335 bool url_request_attempt_is_duplicate = false; | |
336 for (const auto& attempt : request.connection_attempts) { | |
337 if (attempt.result == url_request_attempt.result) | |
338 url_request_attempt_is_duplicate = true; | |
davidben
2015/05/15 18:36:50
When does this happen? This seems like the Connect
Deprecated (see juliatuttle)
2015/05/15 19:08:45
It is well-defined, but it doesn't cover some erro
| |
339 if (!FillBeaconFromAttempt(&beacon, attempt)) | |
340 continue; | |
341 context_manager_.RouteBeacon(request.url, beacon); | |
342 } | |
343 | |
344 if (url_request_attempt_is_duplicate) | |
345 return; | |
346 if (!FillBeaconFromAttempt(&beacon, url_request_attempt)) | |
347 return; | |
285 context_manager_.RouteBeacon(request.url, beacon); | 348 context_manager_.RouteBeacon(request.url, beacon); |
286 } | 349 } |
287 | 350 |
288 base::WeakPtr<DomainReliabilityMonitor> | 351 base::WeakPtr<DomainReliabilityMonitor> |
289 DomainReliabilityMonitor::MakeWeakPtr() { | 352 DomainReliabilityMonitor::MakeWeakPtr() { |
290 return weak_factory_.GetWeakPtr(); | 353 return weak_factory_.GetWeakPtr(); |
291 } | 354 } |
292 | 355 |
293 } // namespace domain_reliability | 356 } // namespace domain_reliability |
OLD | NEW |