blob: 729775e7b6d8ac0e7d7572839f9709de2ad9536c [file] [log] [blame]
[email protected]fecef222012-01-05 02:26:151// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit586acc5fe2008-07-26 22:42:524
[email protected]175adac2008-07-30 17:28:045#include "net/url_request/url_request_http_job.h"
initial.commit586acc5fe2008-07-26 22:42:526
mmenked3a02b32016-11-16 20:21:327#include <vector>
8
[email protected]4ed2755f2008-12-15 09:01:339#include "base/base_switches.h"
[email protected]4f9e5c82011-11-17 16:04:5610#include "base/bind.h"
[email protected]084262c2011-12-01 21:12:4711#include "base/bind_helpers.h"
[email protected]4ed2755f2008-12-15 09:01:3312#include "base/command_line.h"
[email protected]39ce5c02008-08-22 04:03:4413#include "base/compiler_specific.h"
[email protected]60889422008-09-23 01:18:1614#include "base/file_version_info.h"
skyostil4891b25b2015-06-11 11:43:4515#include "base/location.h"
Avi Drissman13fc8932015-12-20 04:40:4616#include "base/macros.h"
[email protected]8684a8812011-03-22 13:59:3817#include "base/metrics/field_trial.h"
Devdeep Ray0c6966d2017-07-14 00:58:2218#include "base/metrics/histogram_functions.h"
asvitkinec3c93722015-06-17 14:48:3719#include "base/metrics/histogram_macros.h"
[email protected]5b90b5d2009-04-30 23:06:0120#include "base/rand_util.h"
skyostil4891b25b2015-06-11 11:43:4521#include "base/single_thread_task_runner.h"
[email protected]4dc3ad4f2013-06-11 07:15:5022#include "base/strings/string_util.h"
Devdeep Ray0c6966d2017-07-14 00:58:2223#include "base/strings/stringprintf.h"
gabf767595f2016-05-11 18:50:3524#include "base/threading/thread_task_runner_handle.h"
[email protected]f002abb2013-06-28 02:30:2125#include "base/time/time.h"
ssid6d6b40102016-04-05 18:59:5626#include "base/trace_event/trace_event.h"
estade5e5529d2015-05-21 20:59:1127#include "base/values.h"
mmenkefd9d15c2017-06-29 13:45:5428#include "build/buildflag.h"
[email protected]6d81b482011-02-22 19:47:1929#include "net/base/host_port_pair.h"
[email protected]b8430722008-09-17 20:05:4430#include "net/base/load_flags.h"
initial.commit586acc5fe2008-07-26 22:42:5231#include "net/base/net_errors.h"
[email protected]636eccd2011-06-28 12:28:0132#include "net/base/network_delegate.h"
mkwstf71d0bd2016-03-21 14:15:2433#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
xunjieli0b7f5b62016-12-06 20:43:4834#include "net/base/trace_constants.h"
tfarina7a4a7fd2016-01-20 14:23:4435#include "net/base/url_util.h"
[email protected]6e7845ae2013-03-29 21:48:1136#include "net/cert/cert_status_flags.h"
Emily Stark8b411de02017-11-23 20:21:2737#include "net/cert/ct_policy_status.h"
Ryan Sleevi19a7bde2017-11-22 06:51:3938#include "net/cert/known_roots.h"
Randy Smithe23356c22017-11-14 01:41:5039#include "net/cookies/canonical_cookie.h"
[email protected]dc8313a2014-03-24 21:38:1440#include "net/cookies/cookie_store.h"
xunjieli28a18772016-10-25 15:30:0641#include "net/filter/brotli_source_stream.h"
42#include "net/filter/filter_source_stream.h"
43#include "net/filter/gzip_source_stream.h"
xunjieli28a18772016-10-25 15:30:0644#include "net/filter/source_stream.h"
[email protected]262191712014-03-22 00:46:5745#include "net/http/http_content_disposition.h"
[email protected]7a299a92012-10-24 23:54:5046#include "net/http/http_network_session.h"
[email protected]8c76ae22010-04-20 22:15:4347#include "net/http/http_request_headers.h"
[email protected]319d9e6f2009-02-18 19:47:2148#include "net/http/http_response_headers.h"
initial.commit586acc5fe2008-07-26 22:42:5249#include "net/http/http_response_info.h"
[email protected]9094b602012-02-27 21:44:5850#include "net/http/http_status_code.h"
initial.commit586acc5fe2008-07-26 22:42:5251#include "net/http/http_transaction.h"
52#include "net/http/http_transaction_factory.h"
[email protected]0757e7702009-03-27 04:00:2253#include "net/http/http_util.h"
Ryan Hamilton0bed1572018-03-02 19:58:2154#include "net/log/net_log.h"
mikecirone8b85c432016-09-08 19:11:0055#include "net/log/net_log_event_type.h"
mikecironef22f9812016-10-04 03:40:1956#include "net/log/net_log_with_source.h"
Scott Violet0caaaf432018-03-24 00:43:5957#include "net/net_buildflags.h"
tbansalca83c002016-04-28 20:56:2858#include "net/nqe/network_quality_estimator.h"
Lily Houghton582d4622018-01-22 22:43:4059#include "net/proxy_resolution/proxy_info.h"
Lily Houghtonffe89daa02018-03-09 18:30:0360#include "net/proxy_resolution/proxy_resolution_service.h"
Lily Houghton582d4622018-01-22 22:43:4061#include "net/proxy_resolution/proxy_retry_info.h"
nharper5babb5e62016-03-09 18:58:0762#include "net/ssl/channel_id_service.h"
[email protected]536fd0b2013-03-14 17:41:5763#include "net/ssl/ssl_cert_request_info.h"
64#include "net/ssl/ssl_config_service.h"
[email protected]ee4c30d2012-11-07 15:08:4365#include "net/url_request/http_user_agent_settings.h"
initial.commit586acc5fe2008-07-26 22:42:5266#include "net/url_request/url_request.h"
[email protected]319d9e6f2009-02-18 19:47:2167#include "net/url_request/url_request_context.h"
initial.commit586acc5fe2008-07-26 22:42:5268#include "net/url_request/url_request_error_job.h"
Thiemo Nagel0793b9c532018-04-18 16:57:5869#include "net/url_request/url_request_http_job_histogram.h"
[email protected]e0f35c92013-05-08 16:04:3470#include "net/url_request/url_request_job_factory.h"
[email protected]06965e02009-09-04 21:36:4271#include "net/url_request/url_request_redirect_job.h"
[email protected]6b3f9642010-11-25 02:29:0672#include "net/url_request/url_request_throttler_manager.h"
Bence Békya5ec55e62018-03-07 14:23:2873#include "net/url_request/websocket_handshake_userdata_key.h"
mkwst8241a122015-10-20 07:15:1074#include "url/origin.h"
initial.commit586acc5fe2008-07-26 22:42:5275
mgershd21d6d142016-12-14 23:06:3676#if defined(OS_ANDROID)
77#include "net/android/network_library.h"
78#endif
79
mmenkefd9d15c2017-06-29 13:45:5480#if BUILDFLAG(ENABLE_REPORTING)
Julia Tuttlecba7d222018-02-23 19:37:2781#include "net/network_error_logging/network_error_logging_service.h"
juliatuttle667c0bb2017-07-06 15:17:1382#include "net/reporting/reporting_header_parser.h"
mmenkefd9d15c2017-06-29 13:45:5483#include "net/reporting/reporting_service.h"
84#endif // BUILDFLAG(ENABLE_REPORTING)
85
mkwst202534e32016-01-15 16:07:1586namespace {
87
Ryan Sleevi19a7bde2017-11-22 06:51:3988// Records details about the most-specific trust anchor in |spki_hashes|,
89// which is expected to be ordered with the leaf cert first and the root cert
90// last. This complements the per-verification histogram
91// Net.Certificate.TrustAnchor.Verify
92void LogTrustAnchor(const net::HashValueVector& spki_hashes) {
Ryan Sleevid756c2d2017-12-01 02:07:4893 // Don't record metrics if there are no hashes; this is true if the HTTP
94 // load did not come from an active network connection, such as the disk
95 // cache or a synthesized response.
96 if (spki_hashes.empty())
97 return;
98
Ryan Sleevi19a7bde2017-11-22 06:51:3999 int32_t id = 0;
100 for (const auto& hash : spki_hashes) {
101 id = net::GetNetTrustAnchorHistogramIdForSPKI(hash);
102 if (id != 0)
103 break;
104 }
Ilya Sherman0eb39802017-12-08 20:58:18105 base::UmaHistogramSparse("Net.Certificate.TrustAnchor.Request", id);
Ryan Sleevi19a7bde2017-11-22 06:51:39106}
107
Emily Stark8b411de02017-11-23 20:21:27108// Records per-request histograms relating to Certificate Transparency
109// compliance.
110void RecordCTHistograms(const net::SSLInfo& ssl_info) {
Emily Stark9676ea82017-11-29 08:10:08111 if (ssl_info.ct_policy_compliance ==
112 net::ct::CTPolicyCompliance::CT_POLICY_COMPLIANCE_DETAILS_NOT_AVAILABLE) {
Emily Stark8b411de02017-11-23 20:21:27113 return;
Emily Stark9676ea82017-11-29 08:10:08114 }
Emily Stark8b411de02017-11-23 20:21:27115 if (!ssl_info.is_issued_by_known_root)
116 return;
117
118 // Connections with major errors other than CERTIFICATE_TRANSPARENCY_REQUIRED
119 // would have failed anyway, so do not record these histograms for such
120 // requests.
121 net::CertStatus other_errors =
122 ssl_info.cert_status &
123 ~net::CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED;
124 if (net::IsCertStatusError(other_errors) &&
125 !net::IsCertStatusMinorError(other_errors)) {
126 return;
127 }
128
129 // Record the CT compliance of each request, to give a picture of the
130 // percentage of overall requests that are CT-compliant.
131 UMA_HISTOGRAM_ENUMERATION(
132 "Net.CertificateTransparency.RequestComplianceStatus",
Emily Stark627238f2017-11-29 03:29:54133 ssl_info.ct_policy_compliance,
Kunihiko Sakamoto36469732018-09-27 03:33:45134 net::ct::CTPolicyCompliance::CT_POLICY_COUNT);
Emily Stark8b411de02017-11-23 20:21:27135 // Record the CT compliance of each request which was required to be CT
136 // compliant. This gives a picture of the sites that are supposed to be
137 // compliant and how well they do at actually being compliant.
138 if (ssl_info.ct_policy_compliance_required) {
139 UMA_HISTOGRAM_ENUMERATION(
140 "Net.CertificateTransparency.CTRequiredRequestComplianceStatus",
Emily Stark627238f2017-11-29 03:29:54141 ssl_info.ct_policy_compliance,
Kunihiko Sakamoto36469732018-09-27 03:33:45142 net::ct::CTPolicyCompliance::CT_POLICY_COUNT);
Emily Stark8b411de02017-11-23 20:21:27143 }
144}
145
nharper3876dd562016-03-29 22:52:32146// Logs whether the CookieStore used for this request matches the
147// ChannelIDService used when establishing the connection that this request is
148// sent over. This logging is only done for requests to accounts.google.com, and
149// only for requests where Channel ID was sent when establishing the connection.
nharper79234722016-03-22 20:28:47150void LogChannelIDAndCookieStores(const GURL& url,
151 const net::URLRequestContext* context,
nharper5babb5e62016-03-09 18:58:07152 const net::SSLInfo& ssl_info) {
nharper79234722016-03-22 20:28:47153 if (url.host() != "accounts.google.com" || !ssl_info.channel_id_sent)
nharper5babb5e62016-03-09 18:58:07154 return;
155 // This enum is used for an UMA histogram - don't reuse or renumber entries.
156 enum {
nharper09ccd502016-03-10 01:54:28157 // Value 0 was removed (CID_EPHEMERAL_COOKIE_EPHEMERAL)
nharper3876dd562016-03-29 22:52:32158 // ChannelIDStore is ephemeral, but CookieStore is persistent.
nharper5babb5e62016-03-09 18:58:07159 CID_EPHEMERAL_COOKIE_PERSISTENT = 1,
nharper3876dd562016-03-29 22:52:32160 // ChannelIDStore is persistent, but CookieStore is ephemeral.
nharper5babb5e62016-03-09 18:58:07161 CID_PERSISTENT_COOKIE_EPHEMERAL = 2,
nharper09ccd502016-03-10 01:54:28162 // Value 3 was removed (CID_PERSISTENT_COOKIE_PERSISTENT)
nharper3876dd562016-03-29 22:52:32163 // There is no CookieStore for this request.
nharper5babb5e62016-03-09 18:58:07164 NO_COOKIE_STORE = 4,
nharper3876dd562016-03-29 22:52:32165 // There is no ChannelIDStore for this request. This should never happen,
166 // because we only log if Channel ID was sent.
nharper5babb5e62016-03-09 18:58:07167 NO_CHANNEL_ID_STORE = 5,
nharper015b9e42016-06-29 01:41:52168 // Value 6 was removed (KNOWN_MISMATCH).
nharper3876dd562016-03-29 22:52:32169 // Both stores are ephemeral, and the ChannelIDService used when
170 // establishing the connection is the same one that the CookieStore was
171 // created to be used with.
nharper09ccd502016-03-10 01:54:28172 EPHEMERAL_MATCH = 7,
nharper3876dd562016-03-29 22:52:32173 // Both stores are ephemeral, but a different CookieStore should have been
174 // used on this request.
nharper09ccd502016-03-10 01:54:28175 EPHEMERAL_MISMATCH = 8,
nharper3876dd562016-03-29 22:52:32176 // Both stores are persistent, and the ChannelIDService used when
177 // establishing the connection is the same one that the CookieStore was
178 // created to be used with.
nharper09ccd502016-03-10 01:54:28179 PERSISTENT_MATCH = 9,
nharper3876dd562016-03-29 22:52:32180 // Both stores are persistent, but a different CookieStore should have been
181 // used on this request.
nharper09ccd502016-03-10 01:54:28182 PERSISTENT_MISMATCH = 10,
nharper3876dd562016-03-29 22:52:32183 // Both stores are ephemeral, but it was never recorded in the CookieStore
184 // which ChannelIDService it was created for, so it is unknown whether the
185 // stores match.
186 EPHEMERAL_UNKNOWN = 11,
187 // Both stores are persistent, but it was never recorded in the CookieStore
188 // which ChannelIDService it was created for, so it is unknown whether the
189 // stores match.
190 PERSISTENT_UNKNOWN = 12,
nharper5babb5e62016-03-09 18:58:07191 EPHEMERALITY_MAX
192 } ephemerality;
mmenke6ddfbea2017-05-31 21:48:41193 const net::HttpNetworkSession::Context* session_context =
194 context->GetNetworkSessionContext();
nharper5babb5e62016-03-09 18:58:07195 net::CookieStore* cookie_store = context->cookie_store();
mmenke6ddfbea2017-05-31 21:48:41196 if (session_context == nullptr ||
197 session_context->channel_id_service == nullptr) {
nharper5babb5e62016-03-09 18:58:07198 ephemerality = NO_CHANNEL_ID_STORE;
199 } else if (cookie_store == nullptr) {
200 ephemerality = NO_COOKIE_STORE;
mmenke6ddfbea2017-05-31 21:48:41201 } else if (session_context->channel_id_service->GetChannelIDStore()
202 ->IsEphemeral()) {
nharper5babb5e62016-03-09 18:58:07203 if (cookie_store->IsEphemeral()) {
nharper3876dd562016-03-29 22:52:32204 if (cookie_store->GetChannelIDServiceID() == -1) {
205 ephemerality = EPHEMERAL_UNKNOWN;
206 } else if (cookie_store->GetChannelIDServiceID() ==
mmenke6ddfbea2017-05-31 21:48:41207 session_context->channel_id_service->GetUniqueID()) {
nharper09ccd502016-03-10 01:54:28208 ephemerality = EPHEMERAL_MATCH;
209 } else {
nharper3876dd562016-03-29 22:52:32210 NOTREACHED();
nharper09ccd502016-03-10 01:54:28211 ephemerality = EPHEMERAL_MISMATCH;
212 }
nharper5babb5e62016-03-09 18:58:07213 } else {
nharper3876dd562016-03-29 22:52:32214 NOTREACHED();
nharper5babb5e62016-03-09 18:58:07215 ephemerality = CID_EPHEMERAL_COOKIE_PERSISTENT;
216 }
217 } else if (cookie_store->IsEphemeral()) {
nharper49122482016-04-29 18:00:58218 NOTREACHED();
nharper5babb5e62016-03-09 18:58:07219 ephemerality = CID_PERSISTENT_COOKIE_EPHEMERAL;
nharper3876dd562016-03-29 22:52:32220 } else if (cookie_store->GetChannelIDServiceID() == -1) {
221 ephemerality = PERSISTENT_UNKNOWN;
222 } else if (cookie_store->GetChannelIDServiceID() ==
mmenke6ddfbea2017-05-31 21:48:41223 session_context->channel_id_service->GetUniqueID()) {
nharper09ccd502016-03-10 01:54:28224 ephemerality = PERSISTENT_MATCH;
nharper5babb5e62016-03-09 18:58:07225 } else {
nharper3876dd562016-03-29 22:52:32226 NOTREACHED();
nharper09ccd502016-03-10 01:54:28227 ephemerality = PERSISTENT_MISMATCH;
nharper5babb5e62016-03-09 18:58:07228 }
229 UMA_HISTOGRAM_ENUMERATION("Net.TokenBinding.StoreEphemerality", ephemerality,
230 EPHEMERALITY_MAX);
231}
232
Thiemo Nagel0793b9c532018-04-18 16:57:58233net::CookieNetworkSecurity HistogramEntryForCookie(
234 const net::CanonicalCookie& cookie,
235 const net::URLRequest& request,
236 const net::HttpRequestInfo& request_info) {
237 if (!request_info.url.SchemeIsCryptographic()) {
238 return net::CookieNetworkSecurity::k1pNonsecureConnection;
239 }
240
241 if (cookie.IsSecure()) {
242 return net::CookieNetworkSecurity::k1pSecureAttribute;
243 }
244
245 net::TransportSecurityState* transport_security_state =
246 request.context()->transport_security_state();
247 net::TransportSecurityState::STSState sts_state;
248 const std::string cookie_domain =
249 cookie.IsHostCookie() ? request.url().host() : cookie.Domain().substr(1);
250 const bool hsts =
251 transport_security_state->GetSTSState(cookie_domain, &sts_state) &&
252 sts_state.ShouldUpgradeToSSL();
253 if (!hsts) {
254 return net::CookieNetworkSecurity::k1pSecureConnection;
255 }
256
257 if (cookie.IsHostCookie()) {
258 if (cookie.IsPersistent() && sts_state.expiry >= cookie.ExpiryDate()) {
259 return net::CookieNetworkSecurity::k1pHSTSHostCookie;
260 } else {
261 // Session cookies are assumed to live forever.
262 return net::CookieNetworkSecurity::k1pExpiringHSTSHostCookie;
263 }
264 }
265
266 // Domain cookies require HSTS to include subdomains to prevent spoofing.
267 if (sts_state.include_subdomains) {
268 if (cookie.IsPersistent() && sts_state.expiry >= cookie.ExpiryDate()) {
269 return net::CookieNetworkSecurity::k1pHSTSSubdomainsIncluded;
270 } else {
271 // Session cookies are assumed to live forever.
272 return net::CookieNetworkSecurity::k1pExpiringHSTSSubdomainsIncluded;
273 }
274 }
275
276 return net::CookieNetworkSecurity::k1pHSTSSpoofable;
277}
278
Thiemo Nagel6c783dbf2018-03-21 13:53:30279void LogCookieUMA(const net::CookieList& cookie_list,
280 const net::URLRequest& request,
281 const net::HttpRequestInfo& request_info) {
282 const bool secure_request = request_info.url.SchemeIsCryptographic();
283 const bool same_site = net::registry_controlled_domains::SameDomainOrHost(
284 request.url(), request.site_for_cookies(),
285 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
Mike West86149882017-07-28 10:41:49286
Thiemo Nagel6c783dbf2018-03-21 13:53:30287 const base::Time now = base::Time::Now();
288 base::Time oldest = base::Time::Max();
289 for (const auto& cookie : cookie_list) {
290 const std::string histogram_name =
291 std::string("Cookie.AllAgesFor") +
292 (secure_request ? "Secure" : "NonSecure") +
293 (same_site ? "SameSite" : "CrossSite") + "Request";
294 const int age_in_days = (now - cookie.CreationDate()).InDays();
295 base::UmaHistogramCounts1000(histogram_name, age_in_days);
Mohsen Izadiad6f7592018-04-18 15:57:10296 oldest = std::min(cookie.CreationDate(), oldest);
Thiemo Nagel0793b9c532018-04-18 16:57:58297
298 net::CookieNetworkSecurity entry =
299 HistogramEntryForCookie(cookie, request, request_info);
300 if (!same_site) {
301 entry =
302 static_cast<net::CookieNetworkSecurity>(static_cast<int>(entry) | 1);
303 }
304 UMA_HISTOGRAM_ENUMERATION("Cookie.NetworkSecurity", entry,
305 net::CookieNetworkSecurity::kCount);
Mike West86149882017-07-28 10:41:49306 }
Thiemo Nagel6c783dbf2018-03-21 13:53:30307
308 const std::string histogram_name =
309 std::string("Cookie.AgeFor") + (secure_request ? "Secure" : "NonSecure") +
310 (same_site ? "SameSite" : "CrossSite") + "Request";
311 const int age_in_days = (now - oldest).InDays();
312 base::UmaHistogramCounts1000(histogram_name, age_in_days);
Mike West86149882017-07-28 10:41:49313}
314
mkwst202534e32016-01-15 16:07:15315} // namespace
316
[email protected]4f5656c62010-12-13 10:47:09317namespace net {
318
initial.commit586acc5fe2008-07-26 22:42:52319// TODO(darin): make sure the port blocking code is not lost
initial.commit586acc5fe2008-07-26 22:42:52320// static
[email protected]4f5656c62010-12-13 10:47:09321URLRequestJob* URLRequestHttpJob::Factory(URLRequest* request,
[email protected]9f170462012-08-24 01:06:58322 NetworkDelegate* network_delegate,
[email protected]4f5656c62010-12-13 10:47:09323 const std::string& scheme) {
[email protected]f4533ba2013-11-28 09:35:41324 DCHECK(scheme == "http" || scheme == "https" || scheme == "ws" ||
325 scheme == "wss");
initial.commit586acc5fe2008-07-26 22:42:52326
[email protected]81293f482012-08-13 19:35:45327 if (!request->context()->http_transaction_factory()) {
initial.commit586acc5fe2008-07-26 22:42:52328 NOTREACHED() << "requires a valid context";
[email protected]9f170462012-08-24 01:06:58329 return new URLRequestErrorJob(
330 request, network_delegate, ERR_INVALID_ARGUMENT);
initial.commit586acc5fe2008-07-26 22:42:52331 }
332
mgershd21d6d142016-12-14 23:06:36333 const GURL& url = request->url();
334
335 // Check for reasons not to return a URLRequestHttpJob. These don't apply to
336 // https and wss requests.
337 if (!url.SchemeIsCryptographic()) {
338 // Check for HSTS upgrade.
339 TransportSecurityState* hsts =
340 request->context()->transport_security_state();
341 if (hsts && hsts->ShouldUpgradeToSSL(url.host())) {
342 GURL::Replacements replacements;
343 replacements.SetSchemeStr(
Mike West86149882017-07-28 10:41:49344
mgershd21d6d142016-12-14 23:06:36345 url.SchemeIs(url::kHttpScheme) ? url::kHttpsScheme : url::kWssScheme);
346 return new URLRequestRedirectJob(
347 request, network_delegate, url.ReplaceComponents(replacements),
348 // Use status code 307 to preserve the method, so POST requests work.
349 URLRequestRedirectJob::REDIRECT_307_TEMPORARY_REDIRECT, "HSTS");
350 }
351
352#if defined(OS_ANDROID)
353 // Check whether the app allows cleartext traffic to this host, and return
mgersh072720a2016-12-15 16:33:34354 // ERR_CLEARTEXT_NOT_PERMITTED if not.
mgershd21d6d142016-12-14 23:06:36355 if (request->context()->check_cleartext_permitted() &&
356 !android::IsCleartextPermitted(url.host())) {
357 return new URLRequestErrorJob(request, network_delegate,
358 ERR_CLEARTEXT_NOT_PERMITTED);
359 }
360#endif
361 }
mkwst549a5c632016-06-20 14:17:03362
[email protected]ee4c30d2012-11-07 15:08:43363 return new URLRequestHttpJob(request,
364 network_delegate,
365 request->context()->http_user_agent_settings());
initial.commit586acc5fe2008-07-26 22:42:52366}
367
[email protected]ee4c30d2012-11-07 15:08:43368URLRequestHttpJob::URLRequestHttpJob(
369 URLRequest* request,
370 NetworkDelegate* network_delegate,
371 const HttpUserAgentSettings* http_user_agent_settings)
[email protected]9f170462012-08-24 01:06:58372 : URLRequestJob(request, network_delegate),
[email protected]5033ab82013-03-22 20:17:46373 priority_(DEFAULT_PRIORITY),
mmenke54e82af2016-02-16 23:06:30374 response_info_(nullptr),
[email protected]4f5656c62010-12-13 10:47:09375 proxy_auth_state_(AUTH_STATE_DONT_NEED_AUTH),
376 server_auth_state_(AUTH_STATE_DONT_NEED_AUTH),
[email protected]3589e552008-08-20 23:11:34377 read_in_progress_(false),
mmenke54e82af2016-02-16 23:06:30378 throttling_entry_(nullptr),
[email protected]00e48bf2010-12-03 06:15:42379 is_cached_content_(false),
[email protected]dd29bcd72011-03-24 00:03:44380 packet_timing_enabled_(false),
[email protected]bbaea8f2011-06-24 00:11:01381 done_(false),
[email protected]dd29bcd72011-03-24 00:03:44382 bytes_observed_in_packets_(0),
[email protected]5a07c192012-07-30 20:18:22383 awaiting_callback_(false),
[email protected]09812102014-05-24 00:04:11384 http_user_agent_settings_(http_user_agent_settings),
sclittlece72c482015-08-24 20:20:59385 total_received_bytes_from_previous_transactions_(0),
sclittlefb249892015-09-10 21:33:22386 total_sent_bytes_from_previous_transactions_(0),
[email protected]09812102014-05-24 00:04:11387 weak_factory_(this) {
[email protected]a73a2802012-05-02 19:20:15388 URLRequestThrottlerManager* manager = request->context()->throttler_manager();
389 if (manager)
390 throttling_entry_ = manager->RegisterRequestUrl(request->url());
391
[email protected]ec23f522011-02-22 21:01:38392 ResetTimer();
initial.commit586acc5fe2008-07-26 22:42:52393}
394
[email protected]5033ab82013-03-22 20:17:46395URLRequestHttpJob::~URLRequestHttpJob() {
396 CHECK(!awaiting_callback_);
397
[email protected]5033ab82013-03-22 20:17:46398 DoneWithRequest(ABORTED);
399}
400
401void URLRequestHttpJob::SetPriority(RequestPriority priority) {
402 priority_ = priority;
403 if (transaction_)
404 transaction_->SetPriority(priority_);
405}
406
407void URLRequestHttpJob::Start() {
408 DCHECK(!transaction_.get());
409
[email protected]99ecf6e2013-04-10 22:46:13410 // URLRequest::SetReferrer ensures that we do not send username and password
411 // fields in the referrer.
412 GURL referrer(request_->referrer());
[email protected]5033ab82013-03-22 20:17:46413
414 request_info_.url = request_->url();
415 request_info_.method = request_->method();
416 request_info_.load_flags = request_->load_flags();
Ramin Halavatib5e433e62018-02-07 07:41:10417 request_info_.traffic_annotation =
418 net::MutableNetworkTrafficAnnotationTag(request_->traffic_annotation());
Paul Jensen60e45532018-02-19 16:04:18419 request_info_.socket_tag = request_->socket_tag();
Ramin Halavatib5e433e62018-02-07 07:41:10420
[email protected]e6d017652013-05-17 18:01:40421 // Enable privacy mode if cookie settings or flags tell us not send or
422 // save cookies.
423 bool enable_privacy_mode =
424 (request_info_.load_flags & LOAD_DO_NOT_SEND_COOKIES) ||
425 (request_info_.load_flags & LOAD_DO_NOT_SAVE_COOKIES) ||
426 CanEnablePrivacyMode();
mkwste3e95992016-02-23 17:45:41427 // Privacy mode could still be disabled in SetCookieHeaderAndStart if we are
428 // going to send previously saved cookies.
[email protected]e6d017652013-05-17 18:01:40429 request_info_.privacy_mode = enable_privacy_mode ?
[email protected]314b03992014-04-01 01:28:53430 PRIVACY_MODE_ENABLED : PRIVACY_MODE_DISABLED;
[email protected]5033ab82013-03-22 20:17:46431
432 // Strip Referer from request_info_.extra_headers to prevent, e.g., plugins
433 // from overriding headers that are controlled using other means. Otherwise a
434 // plugin could set a referrer although sending the referrer is inhibited.
435 request_info_.extra_headers.RemoveHeader(HttpRequestHeaders::kReferer);
436
rdsmith81f607562014-11-21 18:35:16437 // Our consumer should have made sure that this is a safe referrer. See for
[email protected]5033ab82013-03-22 20:17:46438 // instance WebCore::FrameLoader::HideReferrer.
439 if (referrer.is_valid()) {
440 request_info_.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
441 referrer.spec());
442 }
443
nharperd6e65822016-03-30 23:05:48444 request_info_.token_binding_referrer = request_->token_binding_referrer();
445
Douglas Creagerf6cb49f72018-07-19 20:14:53446 // This should be kept in sync with the corresponding code in
447 // URLRequest::GetUserAgent.
[email protected]5033ab82013-03-22 20:17:46448 request_info_.extra_headers.SetHeaderIfMissing(
449 HttpRequestHeaders::kUserAgent,
450 http_user_agent_settings_ ?
[email protected]aa051272014-03-10 05:56:56451 http_user_agent_settings_->GetUserAgent() : std::string());
[email protected]5033ab82013-03-22 20:17:46452
453 AddExtraHeaders();
454 AddCookieHeaderAndStart();
455}
456
457void URLRequestHttpJob::Kill() {
[email protected]5033ab82013-03-22 20:17:46458 weak_factory_.InvalidateWeakPtrs();
mmenke2281f3762015-11-02 20:38:17459 if (transaction_)
460 DestroyTransaction();
[email protected]5033ab82013-03-22 20:17:46461 URLRequestJob::Kill();
462}
463
ttuttle3ae06922015-05-11 23:41:52464void URLRequestHttpJob::GetConnectionAttempts(ConnectionAttempts* out) const {
465 if (transaction_)
466 transaction_->GetConnectionAttempts(out);
467 else
468 out->clear();
469}
470
ryansturm49a8cb12016-06-15 16:51:09471void URLRequestHttpJob::NotifyBeforeSendHeadersCallback(
[email protected]1252d42f2014-07-01 21:20:20472 const ProxyInfo& proxy_info,
473 HttpRequestHeaders* request_headers) {
474 DCHECK(request_headers);
[email protected]597a1ab2014-06-26 08:12:27475 DCHECK_NE(URLRequestStatus::CANCELED, GetStatus().status());
Tarun Bansal4dcebd42017-10-12 20:12:30476 if (proxy_info.is_empty()) {
477 SetProxyServer(ProxyServer::Direct());
478 } else {
479 SetProxyServer(proxy_info.proxy_server());
480 }
[email protected]597a1ab2014-06-26 08:12:27481 if (network_delegate()) {
ryansturm49a8cb12016-06-15 16:51:09482 network_delegate()->NotifyBeforeSendHeaders(
483 request_, proxy_info,
Lily Houghton8c2f97d2018-01-22 05:06:59484 request_->context()->proxy_resolution_service()->proxy_retry_info(),
[email protected]1252d42f2014-07-01 21:20:20485 request_headers);
[email protected]597a1ab2014-06-26 08:12:27486 }
487}
488
[email protected]175adac2008-07-30 17:28:04489void URLRequestHttpJob::NotifyHeadersComplete() {
initial.commit586acc5fe2008-07-26 22:42:52490 DCHECK(!response_info_);
491
492 response_info_ = transaction_->GetResponseInfo();
493
[email protected]d8fd5132009-05-15 01:06:53494 // Save boolean, as we'll need this info at destruction time, and filters may
495 // also need this info.
496 is_cached_content_ = response_info_->was_cached;
497
xunjieli041e9392015-05-19 21:51:33498 if (!is_cached_content_ && throttling_entry_.get())
499 throttling_entry_->UpdateWithResponse(GetResponseCode());
[email protected]6b3f9642010-11-25 02:29:06500
[email protected]fecef222012-01-05 02:26:15501 // The ordering of these calls is not important.
[email protected]77f6fb432009-09-05 14:21:09502 ProcessStrictTransportSecurityHeader();
[email protected]fecef222012-01-05 02:26:15503 ProcessPublicKeyPinsHeader();
estark1614475f2016-03-10 03:46:47504 ProcessExpectCTHeader();
Julia Tuttle3f9acac2017-11-20 22:06:30505#if BUILDFLAG(ENABLE_REPORTING)
juliatuttle2b8dd2d12017-04-12 21:27:41506 ProcessReportToHeader();
Julia Tuttlef9b74062017-07-27 14:44:05507 ProcessNetworkErrorLoggingHeader();
Julia Tuttle3f9acac2017-11-20 22:06:30508#endif // BUILDFLAG(ENABLE_REPORTING)
[email protected]a9cea7542009-05-20 04:30:23509
[email protected]0757e7702009-03-27 04:00:22510 // The HTTP transaction may be restarted several times for the purposes
511 // of sending authorization information. Each time it restarts, we get
512 // notified of the headers completion so that we can update the cookie store.
513 if (transaction_->IsReadyToRestartForAuth()) {
514 DCHECK(!response_info_->auth_challenge.get());
[email protected]87a09a92011-07-14 15:50:50515 // TODO(battre): This breaks the webrequest API for
516 // URLRequestTestHTTP.BasicAuthWithCookies
ryansturm2343cb62016-06-15 01:09:00517 // where OnBeforeStartTransaction -> OnStartTransaction ->
518 // OnBeforeStartTransaction occurs.
[email protected]f3cf9802011-10-28 18:44:58519 RestartTransactionWithAuth(AuthCredentials());
[email protected]0757e7702009-03-27 04:00:22520 return;
521 }
522
[email protected]4f5656c62010-12-13 10:47:09523 URLRequestJob::NotifyHeadersComplete();
initial.commit586acc5fe2008-07-26 22:42:52524}
525
[email protected]175adac2008-07-30 17:28:04526void URLRequestHttpJob::DestroyTransaction() {
[email protected]c6a4eb92010-03-03 23:51:19527 DCHECK(transaction_.get());
initial.commit586acc5fe2008-07-26 22:42:52528
[email protected]bbaea8f2011-06-24 00:11:01529 DoneWithRequest(ABORTED);
sclittlece72c482015-08-24 20:20:59530
531 total_received_bytes_from_previous_transactions_ +=
532 transaction_->GetTotalReceivedBytes();
sclittlefb249892015-09-10 21:33:22533 total_sent_bytes_from_previous_transactions_ +=
534 transaction_->GetTotalSentBytes();
[email protected]af4876d2008-10-21 23:10:57535 transaction_.reset();
David Benjamin0bda12f2018-02-07 19:58:45536 response_info_ = nullptr;
537 override_response_headers_ = nullptr;
[email protected]3b23a222013-05-15 21:33:25538 receive_headers_end_ = base::TimeTicks();
initial.commit586acc5fe2008-07-26 22:42:52539}
540
[email protected]175adac2008-07-30 17:28:04541void URLRequestHttpJob::StartTransaction() {
[email protected]cc05edc2013-03-08 18:04:41542 if (network_delegate()) {
David Benjamin9776ca22018-06-13 00:00:15543 OnCallToDelegate(
544 NetLogEventType::NETWORK_DELEGATE_BEFORE_START_TRANSACTION);
mmenked3a02b32016-11-16 20:21:32545 // The NetworkDelegate must watch for OnRequestDestroyed and not modify
546 // |extra_headers| or invoke the callback after it's called. Not using a
547 // WeakPtr here because it's not enough, the consumer has to watch for
548 // destruction regardless, due to the headers parameter.
ryansturm2343cb62016-06-15 01:09:00549 int rv = network_delegate()->NotifyBeforeStartTransaction(
mmenked3a02b32016-11-16 20:21:32550 request_,
David Benjamind1f287bf2018-06-12 01:57:20551 base::BindOnce(&URLRequestHttpJob::NotifyBeforeStartTransactionCallback,
552 base::Unretained(this)),
[email protected]636eccd2011-06-28 12:28:01553 &request_info_.extra_headers);
554 // If an extension blocks the request, we rely on the callback to
[email protected]b4438d32012-09-27 06:15:30555 // MaybeStartTransactionInternal().
[email protected]abe1c4a2013-10-25 19:28:51556 if (rv == ERR_IO_PENDING)
[email protected]636eccd2011-06-28 12:28:01557 return;
[email protected]b4438d32012-09-27 06:15:30558 MaybeStartTransactionInternal(rv);
559 return;
[email protected]636eccd2011-06-28 12:28:01560 }
561 StartTransactionInternal();
562}
563
ryansturm2343cb62016-06-15 01:09:00564void URLRequestHttpJob::NotifyBeforeStartTransactionCallback(int result) {
[email protected]9045b8822012-01-13 20:35:35565 // Check that there are no callbacks to already canceled requests.
566 DCHECK_NE(URLRequestStatus::CANCELED, GetStatus().status());
567
[email protected]b4438d32012-09-27 06:15:30568 MaybeStartTransactionInternal(result);
569}
570
571void URLRequestHttpJob::MaybeStartTransactionInternal(int result) {
[email protected]abe1c4a2013-10-25 19:28:51572 OnCallToDelegateComplete();
[email protected]636eccd2011-06-28 12:28:01573 if (result == OK) {
574 StartTransactionInternal();
575 } else {
[email protected]55b8a6c12012-06-13 22:03:42576 std::string source("delegate");
mikecirone8b85c432016-09-08 19:11:00577 request_->net_log().AddEvent(NetLogEventType::CANCELLED,
[email protected]55b8a6c12012-06-13 22:03:42578 NetLog::StringCallback("source", &source));
jamd3f5a3c2016-10-27 18:52:02579 // Don't call back synchronously to the delegate.
580 base::ThreadTaskRunnerHandle::Get()->PostTask(
581 FROM_HERE,
582 base::Bind(&URLRequestHttpJob::NotifyStartError,
583 weak_factory_.GetWeakPtr(),
584 URLRequestStatus(URLRequestStatus::FAILED, result)));
[email protected]636eccd2011-06-28 12:28:01585 }
586}
587
588void URLRequestHttpJob::StartTransactionInternal() {
mmenke4600b602015-10-28 18:52:17589 // This should only be called while the request's status is IO_PENDING.
mmenke2281f3762015-11-02 20:38:17590 DCHECK_EQ(URLRequestStatus::IO_PENDING, request_->status().status());
David Benjamin0bda12f2018-02-07 19:58:45591 DCHECK(!override_response_headers_);
mmenke4600b602015-10-28 18:52:17592
initial.commit586acc5fe2008-07-26 22:42:52593 // NOTE: This method assumes that request_info_ is already setup properly.
594
[email protected]34602282010-02-03 22:14:15595 // If we already have a transaction, then we should restart the transaction
[email protected]f3cf9802011-10-28 18:44:58596 // with auth provided by auth_credentials_.
initial.commit586acc5fe2008-07-26 22:42:52597
[email protected]99c07902010-08-17 18:59:52598 int rv;
[email protected]6b3f9642010-11-25 02:29:06599
tbansal80a52162016-05-20 17:55:04600 // Notify NetworkQualityEstimator.
601 NetworkQualityEstimator* network_quality_estimator =
602 request()->context()->network_quality_estimator();
603 if (network_quality_estimator)
604 network_quality_estimator->NotifyStartTransaction(*request_);
605
[email protected]cc05edc2013-03-08 18:04:41606 if (network_delegate()) {
ryansturm2343cb62016-06-15 01:09:00607 network_delegate()->NotifyStartTransaction(request_,
608 request_info_.extra_headers);
[email protected]5796dc942011-07-14 19:26:10609 }
610
[email protected]34602282010-02-03 22:14:15611 if (transaction_.get()) {
mmenked3a02b32016-11-16 20:21:32612 rv = transaction_->RestartWithAuth(
613 auth_credentials_, base::Bind(&URLRequestHttpJob::OnStartCompleted,
614 base::Unretained(this)));
[email protected]f3cf9802011-10-28 18:44:58615 auth_credentials_ = AuthCredentials();
[email protected]34602282010-02-03 22:14:15616 } else {
[email protected]34602282010-02-03 22:14:15617 DCHECK(request_->context()->http_transaction_factory());
initial.commit586acc5fe2008-07-26 22:42:52618
[email protected]99c07902010-08-17 18:59:52619 rv = request_->context()->http_transaction_factory()->CreateTransaction(
[email protected]027bd85a2013-12-27 22:39:10620 priority_, &transaction_);
[email protected]f4533ba2013-11-28 09:35:41621
622 if (rv == OK && request_info_.url.SchemeIsWSOrWSS()) {
Bence Békya5ec55e62018-03-07 14:23:28623 base::SupportsUserData::Data* data =
624 request_->GetUserData(kWebSocketHandshakeUserDataKey);
[email protected]f4533ba2013-11-28 09:35:41625 if (data) {
626 transaction_->SetWebSocketHandshakeStreamCreateHelper(
627 static_cast<WebSocketHandshakeStreamBase::CreateHelper*>(data));
628 } else {
629 rv = ERR_DISALLOWED_URL_SCHEME;
630 }
631 }
632
[email protected]4f5656c62010-12-13 10:47:09633 if (rv == OK) {
ryansturm49a8cb12016-06-15 16:51:09634 transaction_->SetBeforeHeadersSentCallback(
635 base::Bind(&URLRequestHttpJob::NotifyBeforeSendHeadersCallback,
[email protected]597a1ab2014-06-26 08:12:27636 base::Unretained(this)));
Andrey Kosyakov83a6eee2017-08-14 19:20:04637 transaction_->SetRequestHeadersCallback(request_headers_callback_);
Andrey Kosyakov2e893e62017-08-31 17:00:52638 transaction_->SetResponseHeadersCallback(response_headers_callback_);
[email protected]a45840b2014-01-10 15:40:22639
dchengc2e01e82014-08-27 00:24:42640 if (!throttling_entry_.get() ||
xunjieli41edcdd2015-06-24 14:26:40641 !throttling_entry_->ShouldRejectRequest(*request_)) {
[email protected]227b0e82011-03-25 21:11:53642 rv = transaction_->Start(
mmenked3a02b32016-11-16 20:21:32643 &request_info_, base::Bind(&URLRequestHttpJob::OnStartCompleted,
644 base::Unretained(this)),
645 request_->net_log());
[email protected]bbaea8f2011-06-24 00:11:01646 start_time_ = base::TimeTicks::Now();
[email protected]227b0e82011-03-25 21:11:53647 } else {
648 // Special error code for the exponential back-off module.
649 rv = ERR_TEMPORARILY_THROTTLED;
650 }
[email protected]34602282010-02-03 22:14:15651 }
initial.commit586acc5fe2008-07-26 22:42:52652 }
653
[email protected]4f5656c62010-12-13 10:47:09654 if (rv == ERR_IO_PENDING)
[email protected]34602282010-02-03 22:14:15655 return;
656
initial.commit586acc5fe2008-07-26 22:42:52657 // The transaction started synchronously, but we need to notify the
[email protected]4f5656c62010-12-13 10:47:09658 // URLRequest delegate via the message loop.
skyostil4891b25b2015-06-11 11:43:45659 base::ThreadTaskRunnerHandle::Get()->PostTask(
660 FROM_HERE, base::Bind(&URLRequestHttpJob::OnStartCompleted,
661 weak_factory_.GetWeakPtr(), rv));
initial.commit586acc5fe2008-07-26 22:42:52662}
663
[email protected]175adac2008-07-30 17:28:04664void URLRequestHttpJob::AddExtraHeaders() {
[email protected]c7bef94c2011-06-21 18:05:51665 if (!request_info_.extra_headers.HasHeader(
Helen Li7dd80832017-09-12 18:29:17666 HttpRequestHeaders::kAcceptEncoding)) {
eustasfbec9132015-12-30 14:56:51667 // Advertise "br" encoding only if transferred data is opaque to proxy.
668 bool advertise_brotli = false;
eustas7ff89682016-07-07 20:23:39669 if (request()->context()->enable_brotli()) {
670 if (request()->url().SchemeIsCryptographic() ||
Rob Wuf79b3ba2018-01-14 01:54:31671 IsLocalhost(request()->url())) {
eustas7ff89682016-07-07 20:23:39672 advertise_brotli = true;
673 }
674 }
eustasfbec9132015-12-30 14:56:51675
[email protected]c7bef94c2011-06-21 18:05:51676 // Supply Accept-Encoding headers first so that it is more likely that they
rdsmith81f607562014-11-21 18:35:16677 // will be in the first transmitted packet. This can sometimes make it
[email protected]c7bef94c2011-06-21 18:05:51678 // easier to filter and analyze the streams to assure that a proxy has not
rdsmith81f607562014-11-21 18:35:16679 // damaged these headers. Some proxies deliberately corrupt Accept-Encoding
[email protected]c7bef94c2011-06-21 18:05:51680 // headers.
eustasfbec9132015-12-30 14:56:51681 std::string advertised_encodings = "gzip, deflate";
eustasfbec9132015-12-30 14:56:51682 if (advertise_brotli)
683 advertised_encodings += ", br";
684 // Tell the server what compression formats are supported.
685 request_info_.extra_headers.SetHeader(HttpRequestHeaders::kAcceptEncoding,
686 advertised_encodings);
[email protected]423041b2008-10-27 17:39:28687 }
688
[email protected]ee4c30d2012-11-07 15:08:43689 if (http_user_agent_settings_) {
[email protected]84f05432013-03-15 01:00:12690 // Only add default Accept-Language if the request didn't have it
691 // specified.
[email protected]ee4c30d2012-11-07 15:08:43692 std::string accept_language =
693 http_user_agent_settings_->GetAcceptLanguage();
694 if (!accept_language.empty()) {
695 request_info_.extra_headers.SetHeaderIfMissing(
696 HttpRequestHeaders::kAcceptLanguage,
697 accept_language);
698 }
initial.commit586acc5fe2008-07-26 22:42:52699 }
initial.commit586acc5fe2008-07-26 22:42:52700}
701
[email protected]34602282010-02-03 22:14:15702void URLRequestHttpJob::AddCookieHeaderAndStart() {
davidben151423e2015-03-23 18:48:36703 CookieStore* cookie_store = request_->context()->cookie_store();
[email protected]1a6fff52011-10-20 21:00:16704 if (cookie_store && !(request_info_.load_flags & LOAD_DO_NOT_SEND_COOKIES)) {
mkwste3e95992016-02-23 17:45:41705 CookieOptions options;
706 options.set_include_httponly();
707
mkwstf71d0bd2016-03-21 14:15:24708 // Set SameSiteCookieMode according to the rules laid out in
Mike Westb85da8ed2017-08-10 14:16:46709 // https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site:
mkwstf71d0bd2016-03-21 14:15:24710 //
711 // * Include both "strict" and "lax" same-site cookies if the request's
Mike Westb85da8ed2017-08-10 14:16:46712 // |url|, |initiator|, and |site_for_cookies| all have the same
clamyfd58ca072016-12-21 17:18:32713 // registrable domain. Note: this also covers the case of a request
714 // without an initiator (only happens for browser-initiated main frame
715 // navigations).
mkwstf71d0bd2016-03-21 14:15:24716 //
717 // * Include only "lax" same-site cookies if the request's |URL| and
Mike Westb85da8ed2017-08-10 14:16:46718 // |site_for_cookies| have the same registrable domain, _and_ the
mkwstf71d0bd2016-03-21 14:15:24719 // request's |method| is "safe" ("GET" or "HEAD").
720 //
721 // Note that this will generally be the case only for cross-site requests
722 // which target a top-level browsing context.
723 //
Nasko Oskov13105d42018-03-23 22:02:08724 // * Include both "strict" and "lax" same-site cookies if the request is
725 // tagged with a flag allowing it.
726 // Note that this can be the case for requests initiated by extensions,
727 // which need to behave as though they are made by the document itself,
728 // but appear like cross-site ones.
729 //
mkwstf71d0bd2016-03-21 14:15:24730 // * Otherwise, do not include same-site cookies.
mkwstc5fa7762016-03-28 09:28:23731 if (registry_controlled_domains::SameDomainOrHost(
Mike Westb85da8ed2017-08-10 14:16:46732 request_->url(), request_->site_for_cookies(),
mkwstc5fa7762016-03-28 09:28:23733 registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) {
clamyfd58ca072016-12-21 17:18:32734 if (!request_->initiator() ||
csharrisond5c68c492016-12-03 00:15:27735 registry_controlled_domains::SameDomainOrHost(
736 request_->url(), request_->initiator().value().GetURL(),
Nasko Oskov13105d42018-03-23 22:02:08737 registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES) ||
738 request_->attach_same_site_cookies()) {
mkwstf71d0bd2016-03-21 14:15:24739 options.set_same_site_cookie_mode(
740 CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
tfarinadbf459732017-05-09 04:36:09741 } else if (HttpUtil::IsMethodSafe(request_->method())) {
mkwstf71d0bd2016-03-21 14:15:24742 options.set_same_site_cookie_mode(
743 CookieOptions::SameSiteCookieMode::INCLUDE_LAX);
744 }
mkwste3e95992016-02-23 17:45:41745 }
746
747 cookie_store->GetCookieListWithOptionsAsync(
748 request_->url(), options,
749 base::Bind(&URLRequestHttpJob::SetCookieHeaderAndStart,
[email protected]dc8313a2014-03-24 21:38:14750 weak_factory_.GetWeakPtr()));
[email protected]03d845f2011-07-29 19:06:26751 } else {
mmenked3a02b32016-11-16 20:21:32752 StartTransaction();
[email protected]03d845f2011-07-29 19:06:26753 }
754}
755
mkwste3e95992016-02-23 17:45:41756void URLRequestHttpJob::SetCookieHeaderAndStart(const CookieList& cookie_list) {
mmenked3a02b32016-11-16 20:21:32757 if (!cookie_list.empty() && CanGetCookies(cookie_list)) {
Thiemo Nagel6c783dbf2018-03-21 13:53:30758 LogCookieUMA(cookie_list, *request_, request_info_);
Mike West86149882017-07-28 10:41:49759
Mike West7c8c2ad2018-02-10 07:08:49760 std::string cookie_line = CanonicalCookie::BuildCookieLine(cookie_list);
761 UMA_HISTOGRAM_COUNTS_10000("Cookie.HeaderLength", cookie_line.length());
762 request_info_.extra_headers.SetHeader(HttpRequestHeaders::kCookie,
763 cookie_line);
764
[email protected]e6d017652013-05-17 18:01:40765 // Disable privacy mode as we are sending cookies anyway.
[email protected]314b03992014-04-01 01:28:53766 request_info_.privacy_mode = PRIVACY_MODE_DISABLED;
[email protected]54f4c9362011-07-25 21:54:46767 }
mmenked3a02b32016-11-16 20:21:32768 StartTransaction();
[email protected]0757e7702009-03-27 04:00:22769}
770
[email protected]ea8141e2011-10-05 13:12:51771void URLRequestHttpJob::SaveCookiesAndNotifyHeadersComplete(int result) {
[email protected]abe1c4a2013-10-25 19:28:51772 // End of the call started in OnStartCompleted.
773 OnCallToDelegateComplete();
774
ttuttle859dc7a2015-04-23 19:42:29775 if (result != OK) {
[email protected]55b8a6c12012-06-13 22:03:42776 std::string source("delegate");
mikecirone8b85c432016-09-08 19:11:00777 request_->net_log().AddEvent(NetLogEventType::CANCELLED,
[email protected]55b8a6c12012-06-13 22:03:42778 NetLog::StringCallback("source", &source));
[email protected]ea8141e2011-10-05 13:12:51779 NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, result));
780 return;
781 }
782
mmenke54e82af2016-02-16 23:06:30783 base::Time response_date;
784 if (!GetResponseHeaders()->GetDateValue(&response_date))
785 response_date = base::Time();
[email protected]263163f2012-06-14 22:40:34786
787 if (!(request_info_.load_flags & LOAD_DO_NOT_SAVE_COOKIES) &&
mmenke54e82af2016-02-16 23:06:30788 request_->context()->cookie_store()) {
[email protected]263163f2012-06-14 22:40:34789 CookieOptions options;
790 options.set_include_httponly();
mmenke54e82af2016-02-16 23:06:30791 options.set_server_time(response_date);
jww79aceda2015-12-07 01:56:34792
mmenke54e82af2016-02-16 23:06:30793 // Set all cookies, without waiting for them to be set. Any subsequent read
794 // will see the combined result of all cookie operation.
mmenked3a02b32016-11-16 20:21:32795 const base::StringPiece name("Set-Cookie");
Victor Costan70f85512017-11-20 16:14:46796 std::string cookie_line;
mmenked3a02b32016-11-16 20:21:32797 size_t iter = 0;
798 HttpResponseHeaders* headers = GetResponseHeaders();
Victor Costan70f85512017-11-20 16:14:46799 while (headers->EnumerateHeader(&iter, name, &cookie_line)) {
800 std::unique_ptr<CanonicalCookie> cookie = net::CanonicalCookie::Create(
801 request_->url(), cookie_line, base::Time::Now(), options);
802 if (!cookie || !CanSetCookie(*cookie, &options))
mmenke54e82af2016-02-16 23:06:30803 continue;
Randy Smithe6515d6a2018-01-27 03:57:32804 request_->context()->cookie_store()->SetCookieWithOptionsAsync(
805 request_->url(), cookie_line, options,
806 CookieStore::SetCookiesCallback());
[email protected]263163f2012-06-14 22:40:34807 }
808 }
809
mmenke54e82af2016-02-16 23:06:30810 NotifyHeadersComplete();
[email protected]34602282010-02-03 22:14:15811}
812
[email protected]000d9df02012-01-18 20:01:46813// NOTE: |ProcessStrictTransportSecurityHeader| and
814// |ProcessPublicKeyPinsHeader| have very similar structures, by design.
[email protected]77f6fb432009-09-05 14:21:09815void URLRequestHttpJob::ProcessStrictTransportSecurityHeader() {
[email protected]a9cea7542009-05-20 04:30:23816 DCHECK(response_info_);
[email protected]6ed72be2013-01-08 22:07:33817 TransportSecurityState* security_state =
818 request_->context()->transport_security_state();
[email protected]e88006f2012-01-11 06:15:07819 const SSLInfo& ssl_info = response_info_->ssl_info;
[email protected]a9cea7542009-05-20 04:30:23820
[email protected]6ed72be2013-01-08 22:07:33821 // Only accept HSTS headers on HTTPS connections that have no
822 // certificate errors.
[email protected]e88006f2012-01-11 06:15:07823 if (!ssl_info.is_valid() || IsCertStatusError(ssl_info.cert_status) ||
mmenked3a02b32016-11-16 20:21:32824 !security_state) {
[email protected]e88006f2012-01-11 06:15:07825 return;
mmenked3a02b32016-11-16 20:21:32826 }
[email protected]326e6792009-12-11 21:04:42827
estarka5da76702015-04-09 04:00:16828 // Don't accept HSTS headers when the hostname is an IP address.
829 if (request_info_.url.HostIsIPAddress())
830 return;
831
[email protected]242d8562012-10-30 21:20:46832 // http://tools.ietf.org/html/draft-ietf-websec-strict-transport-sec:
833 //
834 // If a UA receives more than one STS header field in a HTTP response
835 // message over secure transport, then the UA MUST process only the
836 // first such header field.
[email protected]6ed72be2013-01-08 22:07:33837 HttpResponseHeaders* headers = GetResponseHeaders();
838 std::string value;
olli.raulaee489a52016-01-25 08:37:10839 if (headers->EnumerateHeader(nullptr, "Strict-Transport-Security", &value))
[email protected]6ed72be2013-01-08 22:07:33840 security_state->AddHSTSHeader(request_info_.url.host(), value);
[email protected]a9cea7542009-05-20 04:30:23841}
[email protected]4f5656c62010-12-13 10:47:09842
[email protected]fecef222012-01-05 02:26:15843void URLRequestHttpJob::ProcessPublicKeyPinsHeader() {
844 DCHECK(response_info_);
[email protected]6ed72be2013-01-08 22:07:33845 TransportSecurityState* security_state =
846 request_->context()->transport_security_state();
[email protected]fecef222012-01-05 02:26:15847 const SSLInfo& ssl_info = response_info_->ssl_info;
848
[email protected]6ed72be2013-01-08 22:07:33849 // Only accept HPKP headers on HTTPS connections that have no
[email protected]e88006f2012-01-11 06:15:07850 // certificate errors.
[email protected]fecef222012-01-05 02:26:15851 if (!ssl_info.is_valid() || IsCertStatusError(ssl_info.cert_status) ||
mmenked3a02b32016-11-16 20:21:32852 !security_state) {
[email protected]fecef222012-01-05 02:26:15853 return;
mmenked3a02b32016-11-16 20:21:32854 }
[email protected]fecef222012-01-05 02:26:15855
estarka5da76702015-04-09 04:00:16856 // Don't accept HSTS headers when the hostname is an IP address.
857 if (request_info_.url.HostIsIPAddress())
858 return;
859
estark53fee7c2015-08-03 18:31:51860 // http://tools.ietf.org/html/rfc7469:
[email protected]6ed72be2013-01-08 22:07:33861 //
862 // If a UA receives more than one PKP header field in an HTTP
863 // response message over secure transport, then the UA MUST process
864 // only the first such header field.
[email protected]fecef222012-01-05 02:26:15865 HttpResponseHeaders* headers = GetResponseHeaders();
[email protected]fecef222012-01-05 02:26:15866 std::string value;
estark53fee7c2015-08-03 18:31:51867 if (headers->EnumerateHeader(nullptr, "Public-Key-Pins", &value))
[email protected]6ed72be2013-01-08 22:07:33868 security_state->AddHPKPHeader(request_info_.url.host(), value, ssl_info);
estark53fee7c2015-08-03 18:31:51869 if (headers->EnumerateHeader(nullptr, "Public-Key-Pins-Report-Only",
870 &value)) {
871 security_state->ProcessHPKPReportOnlyHeader(
872 value, HostPortPair::FromURL(request_info_.url), ssl_info);
873 }
[email protected]fecef222012-01-05 02:26:15874}
875
estark1614475f2016-03-10 03:46:47876void URLRequestHttpJob::ProcessExpectCTHeader() {
877 DCHECK(response_info_);
878 TransportSecurityState* security_state =
879 request_->context()->transport_security_state();
880 const SSLInfo& ssl_info = response_info_->ssl_info;
881
882 // Only accept Expect CT headers on HTTPS connections that have no
883 // certificate errors.
884 if (!ssl_info.is_valid() || IsCertStatusError(ssl_info.cert_status) ||
885 !security_state) {
886 return;
887 }
888
estark1614475f2016-03-10 03:46:47889 HttpResponseHeaders* headers = GetResponseHeaders();
890 std::string value;
Emily Stark4cfecf072017-08-08 01:05:51891 if (headers->GetNormalizedHeader("Expect-CT", &value)) {
estark1614475f2016-03-10 03:46:47892 security_state->ProcessExpectCTHeader(
893 value, HostPortPair::FromURL(request_info_.url), ssl_info);
894 }
895}
896
Julia Tuttle3f9acac2017-11-20 22:06:30897#if BUILDFLAG(ENABLE_REPORTING)
juliatuttle2b8dd2d12017-04-12 21:27:41898void URLRequestHttpJob::ProcessReportToHeader() {
899 DCHECK(response_info_);
900
juliatuttle667c0bb2017-07-06 15:17:13901 HttpResponseHeaders* headers = GetResponseHeaders();
902 std::string value;
903 if (!headers->GetNormalizedHeader("Report-To", &value))
juliatuttle2b8dd2d12017-04-12 21:27:41904 return;
905
juliatuttle667c0bb2017-07-06 15:17:13906 ReportingService* service = request_->context()->reporting_service();
907 if (!service) {
908 ReportingHeaderParser::RecordHeaderDiscardedForNoReportingService();
909 return;
910 }
911
juliatuttle2b8dd2d12017-04-12 21:27:41912 // Only accept Report-To headers on HTTPS connections that have no
913 // certificate errors.
914 // TODO(juliatuttle): Do we need to check cert status?
915 const SSLInfo& ssl_info = response_info_->ssl_info;
juliatuttle667c0bb2017-07-06 15:17:13916 if (!ssl_info.is_valid()) {
917 ReportingHeaderParser::RecordHeaderDiscardedForInvalidSSLInfo();
juliatuttle2b8dd2d12017-04-12 21:27:41918 return;
juliatuttle667c0bb2017-07-06 15:17:13919 }
920 if (IsCertStatusError(ssl_info.cert_status)) {
921 ReportingHeaderParser::RecordHeaderDiscardedForCertStatusError();
juliatuttle2b8dd2d12017-04-12 21:27:41922 return;
juliatuttle667c0bb2017-07-06 15:17:13923 }
juliatuttle2b8dd2d12017-04-12 21:27:41924
925 service->ProcessHeader(request_info_.url.GetOrigin(), value);
926}
927
Julia Tuttlef9b74062017-07-27 14:44:05928void URLRequestHttpJob::ProcessNetworkErrorLoggingHeader() {
929 DCHECK(response_info_);
930
931 HttpResponseHeaders* headers = GetResponseHeaders();
932 std::string value;
Julia Tuttlecba7d222018-02-23 19:37:27933 if (!headers->GetNormalizedHeader(NetworkErrorLoggingService::kHeaderName,
Julia Tuttlef9b74062017-07-27 14:44:05934 &value)) {
935 return;
936 }
937
Julia Tuttlecba7d222018-02-23 19:37:27938 NetworkErrorLoggingService* service =
939 request_->context()->network_error_logging_service();
Julia Tuttle36c6dcbf2018-03-22 18:02:04940 if (!service) {
941 NetworkErrorLoggingService::
942 RecordHeaderDiscardedForNoNetworkErrorLoggingService();
Julia Tuttlef9b74062017-07-27 14:44:05943 return;
Julia Tuttle36c6dcbf2018-03-22 18:02:04944 }
Julia Tuttlef9b74062017-07-27 14:44:05945
Julia Tuttle36c6dcbf2018-03-22 18:02:04946 // Only accept NEL headers on HTTPS connections that have no certificate
947 // errors.
Julia Tuttlef9b74062017-07-27 14:44:05948 const SSLInfo& ssl_info = response_info_->ssl_info;
Julia Tuttle36c6dcbf2018-03-22 18:02:04949 if (!ssl_info.is_valid()) {
950 NetworkErrorLoggingService::RecordHeaderDiscardedForInvalidSSLInfo();
Julia Tuttlef9b74062017-07-27 14:44:05951 return;
Julia Tuttle36c6dcbf2018-03-22 18:02:04952 }
953 if (IsCertStatusError(ssl_info.cert_status)) {
954 NetworkErrorLoggingService::RecordHeaderDiscardedForCertStatusError();
955 return;
956 }
Julia Tuttlef9b74062017-07-27 14:44:05957
Douglas Creager4d1ef842018-07-16 23:42:25958 IPEndPoint endpoint;
959 if (!GetRemoteEndpoint(&endpoint)) {
960 NetworkErrorLoggingService::RecordHeaderDiscardedForMissingRemoteEndpoint();
961 return;
962 }
963
964 service->OnHeader(url::Origin::Create(request_info_.url), endpoint.address(),
965 value);
Julia Tuttlef9b74062017-07-27 14:44:05966}
Julia Tuttle3f9acac2017-11-20 22:06:30967#endif // BUILDFLAG(ENABLE_REPORTING)
Julia Tuttlef9b74062017-07-27 14:44:05968
[email protected]5394e422011-01-20 22:07:43969void URLRequestHttpJob::OnStartCompleted(int result) {
xunjieli0b7f5b62016-12-06 20:43:48970 TRACE_EVENT0(kNetTracingCategory, "URLRequestHttpJob::OnStartCompleted");
[email protected]ec23f522011-02-22 21:01:38971 RecordTimer();
972
[email protected]80abdad2014-03-15 00:20:54973 // If the job is done (due to cancellation), can just ignore this
974 // notification.
975 if (done_)
[email protected]5394e422011-01-20 22:07:43976 return;
977
[email protected]3b23a222013-05-15 21:33:25978 receive_headers_end_ = base::TimeTicks::Now();
979
[email protected]ef2bf422012-05-11 03:27:09980 const URLRequestContext* context = request_->context();
981
Ryan Sleevi19a7bde2017-11-22 06:51:39982 if (transaction_ && transaction_->GetResponseInfo()) {
983 const SSLInfo& ssl_info = transaction_->GetResponseInfo()->ssl_info;
984 if (!IsCertificateError(result) ||
985 (IsCertStatusError(ssl_info.cert_status) &&
986 IsCertStatusMinorError(ssl_info.cert_status))) {
987 LogTrustAnchor(ssl_info.public_key_hashes);
988 }
Emily Stark8b411de02017-11-23 20:21:27989
990 RecordCTHistograms(ssl_info);
Ryan Sleevi19a7bde2017-11-22 06:51:39991 }
992
[email protected]5394e422011-01-20 22:07:43993 if (result == OK) {
[email protected]d8fc4722014-06-13 13:17:15994 if (transaction_ && transaction_->GetResponseInfo()) {
995 SetProxyServer(transaction_->GetResponseInfo()->proxy_server);
996 }
[email protected]ea8141e2011-10-05 13:12:51997 scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders();
hiroshigecb76caa4c52015-12-22 07:50:25998
[email protected]cc05edc2013-03-08 18:04:41999 if (network_delegate()) {
[email protected]ea8141e2011-10-05 13:12:511000 // Note that |this| may not be deleted until
mmenked3a02b32016-11-16 20:21:321001 // |URLRequestHttpJob::OnHeadersReceivedCallback()| or
[email protected]ea8141e2011-10-05 13:12:511002 // |NetworkDelegate::URLRequestDestroyed()| has been called.
David Benjamin9776ca22018-06-13 00:00:151003 OnCallToDelegate(NetLogEventType::NETWORK_DELEGATE_HEADERS_RECEIVED);
[email protected]5f714132014-03-26 10:41:161004 allowed_unsafe_redirect_url_ = GURL();
mmenked3a02b32016-11-16 20:21:321005 // The NetworkDelegate must watch for OnRequestDestroyed and not modify
1006 // any of the arguments or invoke the callback after it's called. Not
1007 // using a WeakPtr here because it's not enough, the consumer has to watch
1008 // for destruction regardless, due to the pointer parameters.
[email protected]cc05edc2013-03-08 18:04:411009 int error = network_delegate()->NotifyHeadersReceived(
David Benjamind1f287bf2018-06-12 01:57:201010 request_,
1011 base::BindOnce(&URLRequestHttpJob::OnHeadersReceivedCallback,
1012 base::Unretained(this)),
mmenked3a02b32016-11-16 20:21:321013 headers.get(), &override_response_headers_,
[email protected]5f714132014-03-26 10:41:161014 &allowed_unsafe_redirect_url_);
ttuttle859dc7a2015-04-23 19:42:291015 if (error != OK) {
1016 if (error == ERR_IO_PENDING) {
[email protected]ea8141e2011-10-05 13:12:511017 awaiting_callback_ = true;
[email protected]ea8141e2011-10-05 13:12:511018 } else {
[email protected]55b8a6c12012-06-13 22:03:421019 std::string source("delegate");
mikecirone8b85c432016-09-08 19:11:001020 request_->net_log().AddEvent(
1021 NetLogEventType::CANCELLED,
1022 NetLog::StringCallback("source", &source));
[email protected]abe1c4a2013-10-25 19:28:511023 OnCallToDelegateComplete();
[email protected]ea8141e2011-10-05 13:12:511024 NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, error));
1025 }
1026 return;
1027 }
1028 }
nharperbafc20f2016-03-25 00:40:171029 if (transaction_ && transaction_->GetResponseInfo()) {
1030 LogChannelIDAndCookieStores(request_->url(), request_->context(),
1031 transaction_->GetResponseInfo()->ssl_info);
1032 }
[email protected]ea8141e2011-10-05 13:12:511033
ttuttle859dc7a2015-04-23 19:42:291034 SaveCookiesAndNotifyHeadersComplete(OK);
[email protected]e5624f02011-09-27 19:43:531035 } else if (IsCertificateError(result)) {
[email protected]6061c142013-10-21 15:13:341036 // We encountered an SSL certificate error.
rsleevi9545d342016-06-21 03:17:371037 // Maybe overridable, maybe not. Ask the delegate to decide.
1038 TransportSecurityState* state = context->transport_security_state();
1039 NotifySSLCertificateError(
1040 transaction_->GetResponseInfo()->ssl_info,
1041 state->ShouldSSLErrorsBeFatal(request_info_.url.host()));
[email protected]5394e422011-01-20 22:07:431042 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
[email protected]a83dd332011-07-13 10:41:011043 NotifyCertificateRequested(
[email protected]90499482013-06-01 00:39:501044 transaction_->GetResponseInfo()->cert_request_info.get());
[email protected]5394e422011-01-20 22:07:431045 } else {
[email protected]419704c2014-01-14 11:18:061046 // Even on an error, there may be useful information in the response
1047 // info (e.g. whether there's a cached copy).
1048 if (transaction_.get())
1049 response_info_ = transaction_->GetResponseInfo();
[email protected]5394e422011-01-20 22:07:431050 NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, result));
1051 }
1052}
1053
[email protected]ea8141e2011-10-05 13:12:511054void URLRequestHttpJob::OnHeadersReceivedCallback(int result) {
[email protected]ea8141e2011-10-05 13:12:511055 awaiting_callback_ = false;
[email protected]9045b8822012-01-13 20:35:351056
1057 // Check that there are no callbacks to already canceled requests.
1058 DCHECK_NE(URLRequestStatus::CANCELED, GetStatus().status());
1059
[email protected]ea8141e2011-10-05 13:12:511060 SaveCookiesAndNotifyHeadersComplete(result);
1061}
1062
[email protected]5394e422011-01-20 22:07:431063void URLRequestHttpJob::OnReadCompleted(int result) {
xunjieli0b7f5b62016-12-06 20:43:481064 TRACE_EVENT0(kNetTracingCategory, "URLRequestHttpJob::OnReadCompleted");
[email protected]5394e422011-01-20 22:07:431065 read_in_progress_ = false;
1066
xunjieli26ede962015-11-23 19:39:131067 DCHECK_NE(ERR_IO_PENDING, result);
1068
[email protected]f001bd6a2011-12-08 04:31:371069 if (ShouldFixMismatchedContentLength(result))
[email protected]5543cbb2012-04-20 16:35:231070 result = OK;
[email protected]f001bd6a2011-12-08 04:31:371071
xunjieli26ede962015-11-23 19:39:131072 // EOF or error, done with this job.
1073 if (result <= 0)
1074 DoneWithRequest(FINISHED);
[email protected]5394e422011-01-20 22:07:431075
xunjieli26ede962015-11-23 19:39:131076 ReadRawDataComplete(result);
[email protected]5394e422011-01-20 22:07:431077}
1078
[email protected]5394e422011-01-20 22:07:431079void URLRequestHttpJob::RestartTransactionWithAuth(
[email protected]f3cf9802011-10-28 18:44:581080 const AuthCredentials& credentials) {
1081 auth_credentials_ = credentials;
[email protected]5394e422011-01-20 22:07:431082
1083 // These will be reset in OnStartCompleted.
David Benjamin0bda12f2018-02-07 19:58:451084 response_info_ = nullptr;
1085 override_response_headers_ = nullptr; // See https://crbug.com/801237.
[email protected]3b23a222013-05-15 21:33:251086 receive_headers_end_ = base::TimeTicks();
[email protected]5394e422011-01-20 22:07:431087
[email protected]ec23f522011-02-22 21:01:381088 ResetTimer();
1089
[email protected]5394e422011-01-20 22:07:431090 // Update the cookies, since the cookie store may have been updated from the
1091 // headers in the 401/407. Since cookies were already appended to
1092 // extra_headers, we need to strip them out before adding them again.
[email protected]ea8141e2011-10-05 13:12:511093 request_info_.extra_headers.RemoveHeader(HttpRequestHeaders::kCookie);
[email protected]5394e422011-01-20 22:07:431094
1095 AddCookieHeaderAndStart();
1096}
1097
[email protected]0736d9e2012-11-28 19:50:401098void URLRequestHttpJob::SetUpload(UploadDataStream* upload) {
[email protected]5394e422011-01-20 22:07:431099 DCHECK(!transaction_.get()) << "cannot change once started";
[email protected]0736d9e2012-11-28 19:50:401100 request_info_.upload_data_stream = upload;
[email protected]5394e422011-01-20 22:07:431101}
1102
1103void URLRequestHttpJob::SetExtraRequestHeaders(
1104 const HttpRequestHeaders& headers) {
1105 DCHECK(!transaction_.get()) << "cannot change once started";
1106 request_info_.extra_headers.CopyFrom(headers);
1107}
1108
[email protected]5394e422011-01-20 22:07:431109LoadState URLRequestHttpJob::GetLoadState() const {
1110 return transaction_.get() ?
1111 transaction_->GetLoadState() : LOAD_STATE_IDLE;
1112}
1113
[email protected]5394e422011-01-20 22:07:431114bool URLRequestHttpJob::GetMimeType(std::string* mime_type) const {
1115 DCHECK(transaction_.get());
1116
1117 if (!response_info_)
1118 return false;
1119
ellyjones0e9d5e82015-02-17 23:06:281120 HttpResponseHeaders* headers = GetResponseHeaders();
1121 if (!headers)
1122 return false;
1123 return headers->GetMimeType(mime_type);
[email protected]5394e422011-01-20 22:07:431124}
1125
1126bool URLRequestHttpJob::GetCharset(std::string* charset) {
1127 DCHECK(transaction_.get());
1128
1129 if (!response_info_)
1130 return false;
1131
[email protected]ea8141e2011-10-05 13:12:511132 return GetResponseHeaders()->GetCharset(charset);
[email protected]5394e422011-01-20 22:07:431133}
1134
1135void URLRequestHttpJob::GetResponseInfo(HttpResponseInfo* info) {
[email protected]ea8141e2011-10-05 13:12:511136 if (response_info_) {
[email protected]419704c2014-01-14 11:18:061137 DCHECK(transaction_.get());
1138
[email protected]5394e422011-01-20 22:07:431139 *info = *response_info_;
[email protected]90499482013-06-01 00:39:501140 if (override_response_headers_.get())
[email protected]ea8141e2011-10-05 13:12:511141 info->headers = override_response_headers_;
1142 }
[email protected]5394e422011-01-20 22:07:431143}
1144
[email protected]58e32bb2013-01-21 18:23:251145void URLRequestHttpJob::GetLoadTimingInfo(
1146 LoadTimingInfo* load_timing_info) const {
[email protected]3b23a222013-05-15 21:33:251147 // If haven't made it far enough to receive any headers, don't return
rdsmith81f607562014-11-21 18:35:161148 // anything. This makes for more consistent behavior in the case of errors.
[email protected]3b23a222013-05-15 21:33:251149 if (!transaction_ || receive_headers_end_.is_null())
1150 return;
1151 if (transaction_->GetLoadTimingInfo(load_timing_info))
1152 load_timing_info->receive_headers_end = receive_headers_end_;
[email protected]58e32bb2013-01-21 18:23:251153}
1154
ttuttled9dbc652015-09-29 20:00:591155bool URLRequestHttpJob::GetRemoteEndpoint(IPEndPoint* endpoint) const {
1156 if (!transaction_)
1157 return false;
1158
1159 return transaction_->GetRemoteEndpoint(endpoint);
1160}
1161
[email protected]5394e422011-01-20 22:07:431162int URLRequestHttpJob::GetResponseCode() const {
1163 DCHECK(transaction_.get());
1164
1165 if (!response_info_)
1166 return -1;
1167
[email protected]ea8141e2011-10-05 13:12:511168 return GetResponseHeaders()->response_code();
[email protected]5394e422011-01-20 22:07:431169}
1170
zhongyi48704c182015-12-07 07:52:021171void URLRequestHttpJob::PopulateNetErrorDetails(
1172 NetErrorDetails* details) const {
1173 if (!transaction_)
1174 return;
1175 return transaction_->PopulateNetErrorDetails(details);
1176}
1177
xunjieli28a18772016-10-25 15:30:061178std::unique_ptr<SourceStream> URLRequestHttpJob::SetUpSourceStream() {
[email protected]5394e422011-01-20 22:07:431179 DCHECK(transaction_.get());
1180 if (!response_info_)
Bacek8f371552016-05-12 01:13:491181 return nullptr;
[email protected]5394e422011-01-20 22:07:431182
xunjieli28a18772016-10-25 15:30:061183 std::unique_ptr<SourceStream> upstream = URLRequestJob::SetUpSourceStream();
[email protected]ea8141e2011-10-05 13:12:511184 HttpResponseHeaders* headers = GetResponseHeaders();
xunjieli28a18772016-10-25 15:30:061185 std::string type;
1186 std::vector<SourceStream::SourceType> types;
olli.raulaee489a52016-01-25 08:37:101187 size_t iter = 0;
xunjieli28a18772016-10-25 15:30:061188 while (headers->EnumerateHeader(&iter, "Content-Encoding", &type)) {
eustasc7d27da2017-04-06 10:33:201189 SourceStream::SourceType source_type =
1190 FilterSourceStream::ParseEncodingType(type);
eustasc7d27da2017-04-06 10:33:201191 switch (source_type) {
1192 case SourceStream::TYPE_BROTLI:
1193 case SourceStream::TYPE_DEFLATE:
1194 case SourceStream::TYPE_GZIP:
eustasc7d27da2017-04-06 10:33:201195 types.push_back(source_type);
1196 break;
1197 case SourceStream::TYPE_NONE:
1198 // Identity encoding type. Pass through raw response body.
1199 return upstream;
Helen Li666c0682017-09-15 19:57:051200 case SourceStream::TYPE_UNKNOWN:
eustasc7d27da2017-04-06 10:33:201201 // Unknown encoding type. Pass through raw response body.
1202 // Despite of reporting to UMA, request will not be canceled; though
1203 // it is expected that user will see malformed / garbage response.
1204 FilterSourceStream::ReportContentDecodingFailed(
1205 FilterSourceStream::TYPE_UNKNOWN);
1206 return upstream;
Helen Li666c0682017-09-15 19:57:051207 case SourceStream::TYPE_GZIP_FALLBACK_DEPRECATED:
1208 case SourceStream::TYPE_SDCH_DEPRECATED:
1209 case SourceStream::TYPE_SDCH_POSSIBLE_DEPRECATED:
1210 case SourceStream::TYPE_REJECTED:
1211 case SourceStream::TYPE_INVALID:
1212 case SourceStream::TYPE_MAX:
1213 NOTREACHED();
1214 return nullptr;
eustasc7d27da2017-04-06 10:33:201215 }
[email protected]5394e422011-01-20 22:07:431216 }
1217
xunjieli28a18772016-10-25 15:30:061218 for (std::vector<SourceStream::SourceType>::reverse_iterator r_iter =
1219 types.rbegin();
1220 r_iter != types.rend(); ++r_iter) {
1221 std::unique_ptr<FilterSourceStream> downstream;
1222 SourceStream::SourceType type = *r_iter;
1223 switch (type) {
1224 case SourceStream::TYPE_BROTLI:
1225 downstream = CreateBrotliSourceStream(std::move(upstream));
1226 break;
xunjieli28a18772016-10-25 15:30:061227 case SourceStream::TYPE_GZIP:
1228 case SourceStream::TYPE_DEFLATE:
xunjieli28a18772016-10-25 15:30:061229 downstream = GzipSourceStream::Create(std::move(upstream), type);
1230 break;
Helen Li666c0682017-09-15 19:57:051231 case SourceStream::TYPE_GZIP_FALLBACK_DEPRECATED:
1232 case SourceStream::TYPE_SDCH_DEPRECATED:
1233 case SourceStream::TYPE_SDCH_POSSIBLE_DEPRECATED:
xunjieli28a18772016-10-25 15:30:061234 case SourceStream::TYPE_NONE:
1235 case SourceStream::TYPE_INVALID:
eustasc7d27da2017-04-06 10:33:201236 case SourceStream::TYPE_REJECTED:
1237 case SourceStream::TYPE_UNKNOWN:
xunjieli28a18772016-10-25 15:30:061238 case SourceStream::TYPE_MAX:
1239 NOTREACHED();
1240 return nullptr;
1241 }
1242 if (downstream == nullptr)
1243 return nullptr;
1244 upstream = std::move(downstream);
1245 }
1246
1247 return upstream;
[email protected]5394e422011-01-20 22:07:431248}
1249
[email protected]f878230e2014-04-03 15:36:141250bool URLRequestHttpJob::CopyFragmentOnRedirect(const GURL& location) const {
1251 // Allow modification of reference fragments by default, unless
1252 // |allowed_unsafe_redirect_url_| is set and equal to the redirect URL.
1253 // When this is the case, we assume that the network delegate has set the
1254 // desired redirect URL (with or without fragment), so it must not be changed
1255 // any more.
1256 return !allowed_unsafe_redirect_url_.is_valid() ||
1257 allowed_unsafe_redirect_url_ != location;
1258}
1259
[email protected]5394e422011-01-20 22:07:431260bool URLRequestHttpJob::IsSafeRedirect(const GURL& location) {
[email protected]e0f35c92013-05-08 16:04:341261 // HTTP is always safe.
1262 // TODO(pauljensen): Remove once crbug.com/146591 is fixed.
1263 if (location.is_valid() &&
1264 (location.scheme() == "http" || location.scheme() == "https")) {
[email protected]5394e422011-01-20 22:07:431265 return true;
[email protected]5394e422011-01-20 22:07:431266 }
[email protected]f878230e2014-04-03 15:36:141267 // Delegates may mark a URL as safe for redirection.
1268 if (allowed_unsafe_redirect_url_.is_valid() &&
1269 allowed_unsafe_redirect_url_ == location) {
1270 return true;
[email protected]5f714132014-03-26 10:41:161271 }
[email protected]e0f35c92013-05-08 16:04:341272 // Query URLRequestJobFactory as to whether |location| would be safe to
1273 // redirect to.
1274 return request_->context()->job_factory() &&
1275 request_->context()->job_factory()->IsSafeRedirectTarget(location);
[email protected]5394e422011-01-20 22:07:431276}
1277
1278bool URLRequestHttpJob::NeedsAuth() {
1279 int code = GetResponseCode();
1280 if (code == -1)
1281 return false;
1282
rdsmith81f607562014-11-21 18:35:161283 // Check if we need either Proxy or WWW Authentication. This could happen
[email protected]5394e422011-01-20 22:07:431284 // because we either provided no auth info, or provided incorrect info.
1285 switch (code) {
1286 case 407:
1287 if (proxy_auth_state_ == AUTH_STATE_CANCELED)
1288 return false;
1289 proxy_auth_state_ = AUTH_STATE_NEED_AUTH;
1290 return true;
1291 case 401:
1292 if (server_auth_state_ == AUTH_STATE_CANCELED)
1293 return false;
1294 server_auth_state_ = AUTH_STATE_NEED_AUTH;
1295 return true;
1296 }
1297 return false;
1298}
1299
1300void URLRequestHttpJob::GetAuthChallengeInfo(
1301 scoped_refptr<AuthChallengeInfo>* result) {
1302 DCHECK(transaction_.get());
1303 DCHECK(response_info_);
1304
1305 // sanity checks:
1306 DCHECK(proxy_auth_state_ == AUTH_STATE_NEED_AUTH ||
1307 server_auth_state_ == AUTH_STATE_NEED_AUTH);
[email protected]9094b602012-02-27 21:44:581308 DCHECK((GetResponseHeaders()->response_code() == HTTP_UNAUTHORIZED) ||
1309 (GetResponseHeaders()->response_code() ==
1310 HTTP_PROXY_AUTHENTICATION_REQUIRED));
[email protected]5394e422011-01-20 22:07:431311
1312 *result = response_info_->auth_challenge;
1313}
1314
[email protected]f3cf9802011-10-28 18:44:581315void URLRequestHttpJob::SetAuth(const AuthCredentials& credentials) {
[email protected]5394e422011-01-20 22:07:431316 DCHECK(transaction_.get());
1317
1318 // Proxy gets set first, then WWW.
1319 if (proxy_auth_state_ == AUTH_STATE_NEED_AUTH) {
1320 proxy_auth_state_ = AUTH_STATE_HAVE_AUTH;
1321 } else {
[email protected]dd29bcd72011-03-24 00:03:441322 DCHECK_EQ(server_auth_state_, AUTH_STATE_NEED_AUTH);
[email protected]5394e422011-01-20 22:07:431323 server_auth_state_ = AUTH_STATE_HAVE_AUTH;
1324 }
1325
[email protected]f3cf9802011-10-28 18:44:581326 RestartTransactionWithAuth(credentials);
[email protected]5394e422011-01-20 22:07:431327}
1328
1329void URLRequestHttpJob::CancelAuth() {
1330 // Proxy gets set first, then WWW.
1331 if (proxy_auth_state_ == AUTH_STATE_NEED_AUTH) {
1332 proxy_auth_state_ = AUTH_STATE_CANCELED;
1333 } else {
[email protected]dd29bcd72011-03-24 00:03:441334 DCHECK_EQ(server_auth_state_, AUTH_STATE_NEED_AUTH);
[email protected]5394e422011-01-20 22:07:431335 server_auth_state_ = AUTH_STATE_CANCELED;
1336 }
1337
1338 // These will be reset in OnStartCompleted.
1339 response_info_ = NULL;
[email protected]3b23a222013-05-15 21:33:251340 receive_headers_end_ = base::TimeTicks::Now();
David Benjamin0bda12f2018-02-07 19:58:451341 // TODO(davidben,mmenke): We should either reset override_response_headers_
1342 // here or not call NotifyHeadersReceived a second time on the same response
1343 // headers. See https://crbug.com/810063.
[email protected]5394e422011-01-20 22:07:431344
[email protected]ec23f522011-02-22 21:01:381345 ResetTimer();
1346
[email protected]5394e422011-01-20 22:07:431347 // OK, let the consumer read the error page...
1348 //
1349 // Because we set the AUTH_STATE_CANCELED flag, NeedsAuth will return false,
1350 // which will cause the consumer to receive OnResponseStarted instead of
1351 // OnAuthRequired.
1352 //
1353 // We have to do this via InvokeLater to avoid "recursing" the consumer.
1354 //
skyostil4891b25b2015-06-11 11:43:451355 base::ThreadTaskRunnerHandle::Get()->PostTask(
1356 FROM_HERE, base::Bind(&URLRequestHttpJob::OnStartCompleted,
1357 weak_factory_.GetWeakPtr(), OK));
[email protected]5394e422011-01-20 22:07:431358}
1359
1360void URLRequestHttpJob::ContinueWithCertificate(
mattm436ccfe2017-06-19 20:24:081361 scoped_refptr<X509Certificate> client_cert,
1362 scoped_refptr<SSLPrivateKey> client_private_key) {
David Benjamin0bda12f2018-02-07 19:58:451363 DCHECK(transaction_);
[email protected]5394e422011-01-20 22:07:431364
1365 DCHECK(!response_info_) << "should not have a response yet";
David Benjamin0bda12f2018-02-07 19:58:451366 DCHECK(!override_response_headers_);
[email protected]3b23a222013-05-15 21:33:251367 receive_headers_end_ = base::TimeTicks();
[email protected]5394e422011-01-20 22:07:431368
[email protected]ec23f522011-02-22 21:01:381369 ResetTimer();
1370
mmenked3a02b32016-11-16 20:21:321371 int rv = transaction_->RestartWithCertificate(
mattm436ccfe2017-06-19 20:24:081372 std::move(client_cert), std::move(client_private_key),
mmenked3a02b32016-11-16 20:21:321373 base::Bind(&URLRequestHttpJob::OnStartCompleted, base::Unretained(this)));
[email protected]5394e422011-01-20 22:07:431374 if (rv == ERR_IO_PENDING)
1375 return;
1376
1377 // The transaction started synchronously, but we need to notify the
1378 // URLRequest delegate via the message loop.
skyostil4891b25b2015-06-11 11:43:451379 base::ThreadTaskRunnerHandle::Get()->PostTask(
1380 FROM_HERE, base::Bind(&URLRequestHttpJob::OnStartCompleted,
1381 weak_factory_.GetWeakPtr(), rv));
[email protected]5394e422011-01-20 22:07:431382}
1383
1384void URLRequestHttpJob::ContinueDespiteLastError() {
1385 // If the transaction was destroyed, then the job was cancelled.
1386 if (!transaction_.get())
1387 return;
1388
1389 DCHECK(!response_info_) << "should not have a response yet";
David Benjamin0bda12f2018-02-07 19:58:451390 DCHECK(!override_response_headers_);
[email protected]3b23a222013-05-15 21:33:251391 receive_headers_end_ = base::TimeTicks();
[email protected]5394e422011-01-20 22:07:431392
[email protected]ec23f522011-02-22 21:01:381393 ResetTimer();
1394
mmenked3a02b32016-11-16 20:21:321395 int rv = transaction_->RestartIgnoringLastError(
1396 base::Bind(&URLRequestHttpJob::OnStartCompleted, base::Unretained(this)));
[email protected]5394e422011-01-20 22:07:431397 if (rv == ERR_IO_PENDING)
1398 return;
1399
1400 // The transaction started synchronously, but we need to notify the
1401 // URLRequest delegate via the message loop.
skyostil4891b25b2015-06-11 11:43:451402 base::ThreadTaskRunnerHandle::Get()->PostTask(
1403 FROM_HERE, base::Bind(&URLRequestHttpJob::OnStartCompleted,
1404 weak_factory_.GetWeakPtr(), rv));
[email protected]5394e422011-01-20 22:07:431405}
1406
[email protected]f001bd6a2011-12-08 04:31:371407bool URLRequestHttpJob::ShouldFixMismatchedContentLength(int rv) const {
1408 // Some servers send the body compressed, but specify the content length as
rdsmith81f607562014-11-21 18:35:161409 // the uncompressed size. Although this violates the HTTP spec we want to
[email protected]f001bd6a2011-12-08 04:31:371410 // support it (as IE and FireFox do), but *only* for an exact match.
1411 // See http://crbug.com/79694.
ttuttle859dc7a2015-04-23 19:42:291412 if (rv == ERR_CONTENT_LENGTH_MISMATCH ||
1413 rv == ERR_INCOMPLETE_CHUNKED_ENCODING) {
mmenked3a02b32016-11-16 20:21:321414 if (request_->response_headers()) {
Avi Drissman13fc8932015-12-20 04:40:461415 int64_t expected_length =
1416 request_->response_headers()->GetContentLength();
pkastingf5279482016-07-27 02:18:201417 VLOG(1) << __func__ << "() \"" << request_->url().spec() << "\""
[email protected]f001bd6a2011-12-08 04:31:371418 << " content-length = " << expected_length
1419 << " pre total = " << prefilter_bytes_read()
1420 << " post total = " << postfilter_bytes_read();
1421 if (postfilter_bytes_read() == expected_length) {
1422 // Clear the error.
1423 return true;
1424 }
1425 }
1426 }
1427 return false;
1428}
1429
xunjieli26ede962015-11-23 19:39:131430int URLRequestHttpJob::ReadRawData(IOBuffer* buf, int buf_size) {
[email protected]5394e422011-01-20 22:07:431431 DCHECK_NE(buf_size, 0);
[email protected]5394e422011-01-20 22:07:431432 DCHECK(!read_in_progress_);
1433
[email protected]49639fa2011-12-20 23:22:411434 int rv = transaction_->Read(
1435 buf, buf_size,
1436 base::Bind(&URLRequestHttpJob::OnReadCompleted, base::Unretained(this)));
[email protected]85c1dce2011-07-06 12:01:291437
[email protected]f001bd6a2011-12-08 04:31:371438 if (ShouldFixMismatchedContentLength(rv))
xunjieli26ede962015-11-23 19:39:131439 rv = OK;
[email protected]f001bd6a2011-12-08 04:31:371440
xunjieli26ede962015-11-23 19:39:131441 if (rv == 0 || (rv < 0 && rv != ERR_IO_PENDING))
1442 DoneWithRequest(FINISHED);
[email protected]5394e422011-01-20 22:07:431443
xunjieli26ede962015-11-23 19:39:131444 if (rv == ERR_IO_PENDING)
[email protected]5394e422011-01-20 22:07:431445 read_in_progress_ = true;
[email protected]5394e422011-01-20 22:07:431446
xunjieli26ede962015-11-23 19:39:131447 return rv;
[email protected]5394e422011-01-20 22:07:431448}
1449
1450void URLRequestHttpJob::StopCaching() {
1451 if (transaction_.get())
1452 transaction_->StopCaching();
1453}
1454
[email protected]79e1fd62013-06-20 06:50:041455bool URLRequestHttpJob::GetFullRequestHeaders(
1456 HttpRequestHeaders* headers) const {
1457 if (!transaction_)
1458 return false;
1459
1460 return transaction_->GetFullRequestHeaders(headers);
1461}
1462
Avi Drissman13fc8932015-12-20 04:40:461463int64_t URLRequestHttpJob::GetTotalReceivedBytes() const {
sclittlece72c482015-08-24 20:20:591464 int64_t total_received_bytes =
1465 total_received_bytes_from_previous_transactions_;
1466 if (transaction_)
1467 total_received_bytes += transaction_->GetTotalReceivedBytes();
1468 return total_received_bytes;
[email protected]71e5ff8f2014-01-13 09:44:041469}
1470
sclittlefb249892015-09-10 21:33:221471int64_t URLRequestHttpJob::GetTotalSentBytes() const {
1472 int64_t total_sent_bytes = total_sent_bytes_from_previous_transactions_;
1473 if (transaction_)
1474 total_sent_bytes += transaction_->GetTotalSentBytes();
1475 return total_sent_bytes;
1476}
1477
[email protected]5c04f722011-08-12 17:52:471478void URLRequestHttpJob::DoneReading() {
[email protected]e50efea2014-03-24 18:41:001479 if (transaction_) {
[email protected]5c04f722011-08-12 17:52:471480 transaction_->DoneReading();
[email protected]e50efea2014-03-24 18:41:001481 }
1482 DoneWithRequest(FINISHED);
1483}
1484
1485void URLRequestHttpJob::DoneReadingRedirectResponse() {
1486 if (transaction_) {
1487 if (transaction_->GetResponseInfo()->headers->IsRedirect(NULL)) {
1488 // If the original headers indicate a redirect, go ahead and cache the
1489 // response, even if the |override_response_headers_| are a redirect to
1490 // another location.
1491 transaction_->DoneReading();
1492 } else {
1493 // Otherwise, |override_response_headers_| must be non-NULL and contain
1494 // bogus headers indicating a redirect.
dchengc2e01e82014-08-27 00:24:421495 DCHECK(override_response_headers_.get());
[email protected]e50efea2014-03-24 18:41:001496 DCHECK(override_response_headers_->IsRedirect(NULL));
1497 transaction_->StopCaching();
1498 }
1499 }
[email protected]5c04f722011-08-12 17:52:471500 DoneWithRequest(FINISHED);
1501}
1502
[email protected]6d81b482011-02-22 19:47:191503HostPortPair URLRequestHttpJob::GetSocketAddress() const {
1504 return response_info_ ? response_info_->socket_address : HostPortPair();
1505}
1506
[email protected]ec23f522011-02-22 21:01:381507void URLRequestHttpJob::RecordTimer() {
1508 if (request_creation_time_.is_null()) {
1509 NOTREACHED()
1510 << "The same transaction shouldn't start twice without new timing.";
1511 return;
1512 }
1513
[email protected]320a29f12011-03-21 14:47:411514 base::TimeDelta to_start = base::Time::Now() - request_creation_time_;
[email protected]ec23f522011-02-22 21:01:381515 request_creation_time_ = base::Time();
[email protected]8684a8812011-03-22 13:59:381516
[email protected]5c68d692011-08-24 04:59:411517 UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpTimeToFirstByte", to_start);
mmenke1beda3d2016-07-22 03:33:451518 if (request_info_.upload_data_stream &&
1519 request_info_.upload_data_stream->size() > 1024 * 1024) {
1520 UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpTimeToFirstByte.LargeUpload", to_start);
1521 }
[email protected]ec23f522011-02-22 21:01:381522}
1523
1524void URLRequestHttpJob::ResetTimer() {
1525 if (!request_creation_time_.is_null()) {
1526 NOTREACHED()
1527 << "The timer was reset before it was recorded.";
1528 return;
1529 }
1530 request_creation_time_ = base::Time::Now();
1531}
1532
[email protected]dd29bcd72011-03-24 00:03:441533void URLRequestHttpJob::UpdatePacketReadTimes() {
1534 if (!packet_timing_enabled_)
1535 return;
1536
mmenkebbf19be22015-04-11 02:44:481537 DCHECK_GT(prefilter_bytes_read(), bytes_observed_in_packets_);
[email protected]dd29bcd72011-03-24 00:03:441538
[email protected]006ce1a2014-07-30 14:41:231539 base::Time now(base::Time::Now());
[email protected]dd29bcd72011-03-24 00:03:441540 if (!bytes_observed_in_packets_)
[email protected]006ce1a2014-07-30 14:41:231541 request_time_snapshot_ = now;
1542 final_packet_time_ = now;
[email protected]dd29bcd72011-03-24 00:03:441543
mmenkebbf19be22015-04-11 02:44:481544 bytes_observed_in_packets_ = prefilter_bytes_read();
[email protected]dd29bcd72011-03-24 00:03:441545}
1546
Andrey Kosyakov83a6eee2017-08-14 19:20:041547void URLRequestHttpJob::SetRequestHeadersCallback(
1548 RequestHeadersCallback callback) {
1549 DCHECK(!transaction_);
1550 DCHECK(!request_headers_callback_);
1551 request_headers_callback_ = std::move(callback);
1552}
1553
Andrey Kosyakov2e893e62017-08-31 17:00:521554void URLRequestHttpJob::SetResponseHeadersCallback(
1555 ResponseHeadersCallback callback) {
1556 DCHECK(!transaction_);
1557 DCHECK(!response_headers_callback_);
1558 response_headers_callback_ = std::move(callback);
1559}
1560
[email protected]bbaea8f2011-06-24 00:11:011561void URLRequestHttpJob::RecordPerfHistograms(CompletionCause reason) {
1562 if (start_time_.is_null())
1563 return;
1564
1565 base::TimeDelta total_time = base::TimeTicks::Now() - start_time_;
1566 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTime", total_time);
1567
1568 if (reason == FINISHED) {
Devdeep Ray0c6966d2017-07-14 00:58:221569 UmaHistogramTimes(
1570 base::StringPrintf("Net.HttpJob.TotalTimeSuccess.Priority%d",
1571 request()->priority()),
1572 total_time);
[email protected]bbaea8f2011-06-24 00:11:011573 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeSuccess", total_time);
1574 } else {
1575 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeCancel", total_time);
1576 }
1577
[email protected]4b4d20242012-02-23 18:27:461578 if (response_info_) {
rtennetie55c4b72015-08-03 21:48:351579 // QUIC (by default) supports https scheme only, thus track https URLs only
1580 // for QUIC.
1581 bool is_https_google = request() && request()->url().SchemeIs("https") &&
1582 HasGoogleHost(request()->url());
rtenneti72928bb2015-04-28 18:28:131583 bool used_quic = response_info_->DidUseQuic();
rtennetie55c4b72015-08-03 21:48:351584 if (is_https_google) {
rtenneti72928bb2015-04-28 18:28:131585 if (used_quic) {
rtennetie55c4b72015-08-03 21:48:351586 UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpJob.TotalTime.Secure.Quic",
1587 total_time);
rtenneti72928bb2015-04-28 18:28:131588 }
1589 }
jkarlinded0021b2016-12-05 16:01:061590
1591 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpJob.PrefilterBytesRead",
1592 prefilter_bytes_read(), 1, 50000000, 50);
[email protected]4b4d20242012-02-23 18:27:461593 if (response_info_->was_cached) {
1594 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeCached", total_time);
jkarlinded0021b2016-12-05 16:01:061595 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpJob.PrefilterBytesRead.Cache",
1596 prefilter_bytes_read(), 1, 50000000, 50);
1597
jkarlincc6943d2016-04-25 19:25:351598 if (response_info_->unused_since_prefetch)
Steven Holte6143e642017-06-28 19:47:381599 UMA_HISTOGRAM_COUNTS_1M("Net.Prefetch.HitBytes",
1600 prefilter_bytes_read());
jkarlincc6943d2016-04-25 19:25:351601 } else {
[email protected]4b4d20242012-02-23 18:27:461602 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeNotCached", total_time);
jkarlinded0021b2016-12-05 16:01:061603 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpJob.PrefilterBytesRead.Net",
1604 prefilter_bytes_read(), 1, 50000000, 50);
1605
1606 if (request_info_.load_flags & LOAD_PREFETCH) {
Steven Holte6143e642017-06-28 19:47:381607 UMA_HISTOGRAM_COUNTS_1M("Net.Prefetch.PrefilterBytesReadFromNetwork",
1608 prefilter_bytes_read());
jkarlinded0021b2016-12-05 16:01:061609 }
rtennetie55c4b72015-08-03 21:48:351610 if (is_https_google) {
rtenneti72928bb2015-04-28 18:28:131611 if (used_quic) {
rtennetie55c4b72015-08-03 21:48:351612 UMA_HISTOGRAM_MEDIUM_TIMES(
1613 "Net.HttpJob.TotalTimeNotCached.Secure.Quic", total_time);
rtenneti72928bb2015-04-28 18:28:131614 } else {
rtennetie55c4b72015-08-03 21:48:351615 UMA_HISTOGRAM_MEDIUM_TIMES(
1616 "Net.HttpJob.TotalTimeNotCached.Secure.NotQuic", total_time);
rtenneti72928bb2015-04-28 18:28:131617 }
1618 }
[email protected]b73656ca2011-07-22 17:42:171619 }
[email protected]bbaea8f2011-06-24 00:11:011620 }
1621
1622 start_time_ = base::TimeTicks();
1623}
1624
1625void URLRequestHttpJob::DoneWithRequest(CompletionCause reason) {
1626 if (done_)
1627 return;
1628 done_ = true;
tbansal79ed5cd2015-08-10 18:53:561629
1630 // Notify NetworkQualityEstimator.
mmenke7ce675a2016-11-07 17:08:301631 NetworkQualityEstimator* network_quality_estimator =
1632 request()->context()->network_quality_estimator();
1633 if (network_quality_estimator) {
1634 network_quality_estimator->NotifyRequestCompleted(
1635 *request(), request_->status().error());
tbansal79ed5cd2015-08-10 18:53:561636 }
1637
[email protected]bbaea8f2011-06-24 00:11:011638 RecordPerfHistograms(reason);
mmenke7ce675a2016-11-07 17:08:301639 request()->set_received_response_content_length(prefilter_bytes_read());
[email protected]bbaea8f2011-06-24 00:11:011640}
1641
[email protected]ea8141e2011-10-05 13:12:511642HttpResponseHeaders* URLRequestHttpJob::GetResponseHeaders() const {
1643 DCHECK(transaction_.get());
1644 DCHECK(transaction_->GetResponseInfo());
1645 return override_response_headers_.get() ?
[email protected]90499482013-06-01 00:39:501646 override_response_headers_.get() :
1647 transaction_->GetResponseInfo()->headers.get();
[email protected]ea8141e2011-10-05 13:12:511648}
1649
1650void URLRequestHttpJob::NotifyURLRequestDestroyed() {
1651 awaiting_callback_ = false;
tbansal80a52162016-05-20 17:55:041652
1653 // Notify NetworkQualityEstimator.
mmenke7ce675a2016-11-07 17:08:301654 NetworkQualityEstimator* network_quality_estimator =
1655 request()->context()->network_quality_estimator();
1656 if (network_quality_estimator)
1657 network_quality_estimator->NotifyURLRequestDestroyed(*request());
[email protected]ea8141e2011-10-05 13:12:511658}
1659
[email protected]4f5656c62010-12-13 10:47:091660} // namespace net