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.
5 #include "components/domain_reliability/util.h"
7 #include "base/callback.h"
8 #include "base/logging.h"
9 #include "base/memory/weak_ptr.h"
10 #include "base/time/time.h"
11 #include "base/timer/timer.h"
12 #include "net/base/net_errors.h"
14 namespace domain_reliability
{
18 const struct NetErrorMapping
{
20 const char* beacon_status
;
23 { net::ERR_ABORTED
, "aborted" },
24 { net::ERR_TIMED_OUT
, "tcp.connection.timed_out" },
25 { net::ERR_CONNECTION_CLOSED
, "tcp.connection.closed" },
26 { net::ERR_CONNECTION_RESET
, "tcp.connection.reset" },
27 { net::ERR_CONNECTION_REFUSED
, "tcp.connection.refused" },
28 { net::ERR_CONNECTION_ABORTED
, "tcp.connection.aborted" },
29 { net::ERR_CONNECTION_FAILED
, "tcp.connection.failed" },
30 { net::ERR_NAME_NOT_RESOLVED
, "dns" },
31 { net::ERR_SSL_PROTOCOL_ERROR
, "ssl.protocol.error" },
32 { net::ERR_ADDRESS_INVALID
, "tcp.connection.address_invalid" },
33 { net::ERR_ADDRESS_UNREACHABLE
, "tcp.connection.address_unreachable" },
34 { net::ERR_CONNECTION_TIMED_OUT
, "tcp.connection.timed_out" },
35 { net::ERR_NAME_RESOLUTION_FAILED
, "dns" },
36 { net::ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN
,
37 "ssl.cert.pinned_key_not_in_cert_chain" },
38 { net::ERR_CERT_COMMON_NAME_INVALID
, "ssl.cert.name_invalid" },
39 { net::ERR_CERT_DATE_INVALID
, "ssl.cert.date_invalid" },
40 { net::ERR_CERT_AUTHORITY_INVALID
, "ssl.cert.authority_invalid" },
41 { net::ERR_CERT_REVOKED
, "ssl.cert.revoked" },
42 { net::ERR_CERT_INVALID
, "ssl.cert.invalid" },
43 { net::ERR_EMPTY_RESPONSE
, "http.response.empty" },
44 { net::ERR_SPDY_PING_FAILED
, "spdy.ping_failed" },
45 { net::ERR_SPDY_PROTOCOL_ERROR
, "spdy.protocol" },
46 { net::ERR_QUIC_PROTOCOL_ERROR
, "quic.protocol" },
47 { net::ERR_DNS_MALFORMED_RESPONSE
, "dns.protocol" },
48 { net::ERR_DNS_SERVER_FAILED
, "dns.server" },
49 { net::ERR_DNS_TIMED_OUT
, "dns.timed_out" },
50 { net::ERR_INSECURE_RESPONSE
, "ssl" },
51 { net::ERR_CONTENT_LENGTH_MISMATCH
, "http.response.content_length_mismatch" },
52 { net::ERR_INCOMPLETE_CHUNKED_ENCODING
,
53 "http.response.incomplete_chunked_encoding" },
54 { net::ERR_SSL_VERSION_OR_CIPHER_MISMATCH
,
55 "ssl.version_or_cipher_mismatch" },
56 { net::ERR_BAD_SSL_CLIENT_AUTH_CERT
, "ssl.bad_client_auth_cert" },
57 { net::ERR_INVALID_CHUNKED_ENCODING
,
58 "http.response.invalid_chunked_encoding" },
59 { net::ERR_RESPONSE_HEADERS_TRUNCATED
, "http.response.headers.truncated" },
60 { net::ERR_REQUEST_RANGE_NOT_SATISFIABLE
,
61 "http.request.range_not_satisfiable" },
62 { net::ERR_INVALID_RESPONSE
, "http.response.invalid" },
63 { net::ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_DISPOSITION
,
64 "http.response.headers.multiple_content_disposition" },
65 { net::ERR_RESPONSE_HEADERS_MULTIPLE_CONTENT_LENGTH
,
66 "http.response.headers.multiple_content_length" },
67 { net::ERR_SSL_UNRECOGNIZED_NAME_ALERT
, "ssl.unrecognized_name_alert" }
73 bool GetDomainReliabilityBeaconStatus(
75 int http_response_code
,
76 std::string
* beacon_status_out
) {
77 if (net_error
== net::OK
) {
78 if (http_response_code
>= 400 && http_response_code
< 600)
79 *beacon_status_out
= "http.error";
81 *beacon_status_out
= "ok";
85 // TODO(ttuttle): Consider sorting and using binary search?
86 for (size_t i
= 0; i
< arraysize(net_error_map
); i
++) {
87 if (net_error_map
[i
].net_error
== net_error
) {
88 *beacon_status_out
= net_error_map
[i
].beacon_status
;
95 // TODO(ttuttle): Consider using NPN/ALPN instead, if there's a good way to
96 // differentiate HTTP and HTTPS.
97 std::string
GetDomainReliabilityProtocol(
98 net::HttpResponseInfo::ConnectionInfo connection_info
,
99 bool ssl_info_populated
) {
100 switch (connection_info
) {
101 case net::HttpResponseInfo::CONNECTION_INFO_UNKNOWN
:
103 case net::HttpResponseInfo::CONNECTION_INFO_HTTP1
:
104 return ssl_info_populated
? "HTTPS" : "HTTP";
105 case net::HttpResponseInfo::CONNECTION_INFO_DEPRECATED_SPDY2
:
106 case net::HttpResponseInfo::CONNECTION_INFO_SPDY3
:
107 case net::HttpResponseInfo::CONNECTION_INFO_HTTP2_14
:
108 case net::HttpResponseInfo::CONNECTION_INFO_HTTP2_15
:
109 case net::HttpResponseInfo::CONNECTION_INFO_HTTP2
:
111 case net::HttpResponseInfo::CONNECTION_INFO_QUIC1_SPDY3
:
113 case net::HttpResponseInfo::NUM_OF_CONNECTION_INFOS
:
121 int GetNetErrorFromURLRequestStatus(const net::URLRequestStatus
& status
) {
122 switch (status
.status()) {
123 case net::URLRequestStatus::SUCCESS
:
125 case net::URLRequestStatus::CANCELED
:
126 return net::ERR_ABORTED
;
127 case net::URLRequestStatus::FAILED
:
128 return status
.error();
131 return net::ERR_FAILED
;
135 void GetUploadResultFromResponseDetails(
137 int http_response_code
,
138 base::TimeDelta retry_after
,
139 DomainReliabilityUploader::UploadResult
* result
) {
140 if (net_error
== net::OK
&& http_response_code
== 200) {
141 result
->status
= DomainReliabilityUploader::UploadResult::SUCCESS
;
145 if (net_error
== net::OK
&&
146 http_response_code
== 503 &&
147 retry_after
!= base::TimeDelta()) {
148 result
->status
= DomainReliabilityUploader::UploadResult::RETRY_AFTER
;
149 result
->retry_after
= retry_after
;
153 result
->status
= DomainReliabilityUploader::UploadResult::FAILURE
;
159 class ActualTimer
: public MockableTime::Timer
{
161 // Initialize base timer with retain_user_info and is_repeating false.
162 ActualTimer() : base_timer_(false, false) {}
164 ~ActualTimer() override
{}
166 // MockableTime::Timer implementation:
167 void Start(const tracked_objects::Location
& posted_from
,
168 base::TimeDelta delay
,
169 const base::Closure
& user_task
) override
{
170 base_timer_
.Start(posted_from
, delay
, user_task
);
173 void Stop() override
{ base_timer_
.Stop(); }
175 bool IsRunning() override
{ return base_timer_
.IsRunning(); }
178 base::Timer base_timer_
;
183 MockableTime::Timer::~Timer() {}
184 MockableTime::Timer::Timer() {}
186 MockableTime::~MockableTime() {}
187 MockableTime::MockableTime() {}
189 ActualTime::ActualTime() {}
190 ActualTime::~ActualTime() {}
192 base::Time
ActualTime::Now() { return base::Time::Now(); }
193 base::TimeTicks
ActualTime::NowTicks() { return base::TimeTicks::Now(); }
195 scoped_ptr
<MockableTime::Timer
> ActualTime::CreateTimer() {
196 return scoped_ptr
<MockableTime::Timer
>(new ActualTimer());
199 MockableTimeBackoffEntry::MockableTimeBackoffEntry(
200 const net::BackoffEntry::Policy
* const policy
,
202 : net::BackoffEntry(policy
),
206 MockableTimeBackoffEntry::~MockableTimeBackoffEntry() {}
208 base::TimeTicks
MockableTimeBackoffEntry::ImplGetTimeNow() const {
209 return time_
->NowTicks();
212 } // namespace domain_reliability