Chromium Code Reviews| 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 |