blob: ad454053477cf1198be7a7ca0528074baa7d0187 [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"
[email protected]6d81b482011-02-22 19:47:1928#include "net/base/host_port_pair.h"
[email protected]b8430722008-09-17 20:05:4429#include "net/base/load_flags.h"
initial.commit586acc5fe2008-07-26 22:42:5230#include "net/base/net_errors.h"
[email protected]636eccd2011-06-28 12:28:0131#include "net/base/network_delegate.h"
mkwstf71d0bd2016-03-21 14:15:2432#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
xunjieli0b7f5b62016-12-06 20:43:4833#include "net/base/trace_constants.h"
tfarina7a4a7fd2016-01-20 14:23:4434#include "net/base/url_util.h"
[email protected]6e7845ae2013-03-29 21:48:1135#include "net/cert/cert_status_flags.h"
Emily Stark8b411de02017-11-23 20:21:2736#include "net/cert/ct_policy_status.h"
Ryan Sleevi19a7bde2017-11-22 06:51:3937#include "net/cert/known_roots.h"
Randy Smithe23356c22017-11-14 01:41:5038#include "net/cookies/canonical_cookie.h"
[email protected]dc8313a2014-03-24 21:38:1439#include "net/cookies/cookie_store.h"
xunjieli28a18772016-10-25 15:30:0640#include "net/filter/brotli_source_stream.h"
41#include "net/filter/filter_source_stream.h"
42#include "net/filter/gzip_source_stream.h"
xunjieli28a18772016-10-25 15:30:0643#include "net/filter/source_stream.h"
[email protected]262191712014-03-22 00:46:5744#include "net/http/http_content_disposition.h"
[email protected]7a299a92012-10-24 23:54:5045#include "net/http/http_network_session.h"
[email protected]8c76ae22010-04-20 22:15:4346#include "net/http/http_request_headers.h"
[email protected]319d9e6f2009-02-18 19:47:2147#include "net/http/http_response_headers.h"
initial.commit586acc5fe2008-07-26 22:42:5248#include "net/http/http_response_info.h"
[email protected]9094b602012-02-27 21:44:5849#include "net/http/http_status_code.h"
initial.commit586acc5fe2008-07-26 22:42:5250#include "net/http/http_transaction.h"
51#include "net/http/http_transaction_factory.h"
[email protected]0757e7702009-03-27 04:00:2252#include "net/http/http_util.h"
Ryan Hamilton0bed1572018-03-02 19:58:2153#include "net/log/net_log.h"
mikecirone8b85c432016-09-08 19:11:0054#include "net/log/net_log_event_type.h"
mikecironef22f9812016-10-04 03:40:1955#include "net/log/net_log_with_source.h"
tbansalca83c002016-04-28 20:56:2856#include "net/nqe/network_quality_estimator.h"
Lily Houghton582d4622018-01-22 22:43:4057#include "net/proxy_resolution/proxy_info.h"
Lily Houghtonffe89daa02018-03-09 18:30:0358#include "net/proxy_resolution/proxy_resolution_service.h"
Lily Houghton582d4622018-01-22 22:43:4059#include "net/proxy_resolution/proxy_retry_info.h"
nharper5babb5e62016-03-09 18:58:0760#include "net/ssl/channel_id_service.h"
[email protected]536fd0b2013-03-14 17:41:5761#include "net/ssl/ssl_cert_request_info.h"
62#include "net/ssl/ssl_config_service.h"
[email protected]ee4c30d2012-11-07 15:08:4363#include "net/url_request/http_user_agent_settings.h"
initial.commit586acc5fe2008-07-26 22:42:5264#include "net/url_request/url_request.h"
[email protected]319d9e6f2009-02-18 19:47:2165#include "net/url_request/url_request_context.h"
initial.commit586acc5fe2008-07-26 22:42:5266#include "net/url_request/url_request_error_job.h"
Thiemo Nagel0793b9c532018-04-18 16:57:5867#include "net/url_request/url_request_http_job_histogram.h"
[email protected]e0f35c92013-05-08 16:04:3468#include "net/url_request/url_request_job_factory.h"
[email protected]06965e02009-09-04 21:36:4269#include "net/url_request/url_request_redirect_job.h"
[email protected]6b3f9642010-11-25 02:29:0670#include "net/url_request/url_request_throttler_manager.h"
Bence Békya5ec55e62018-03-07 14:23:2871#include "net/url_request/websocket_handshake_userdata_key.h"
mkwst8241a122015-10-20 07:15:1072#include "url/origin.h"
initial.commit586acc5fe2008-07-26 22:42:5273
mgershd21d6d142016-12-14 23:06:3674#if defined(OS_ANDROID)
75#include "net/android/network_library.h"
76#endif
77
mkwst202534e32016-01-15 16:07:1578namespace {
79
Ryan Sleevi19a7bde2017-11-22 06:51:3980// Records details about the most-specific trust anchor in |spki_hashes|,
81// which is expected to be ordered with the leaf cert first and the root cert
82// last. This complements the per-verification histogram
83// Net.Certificate.TrustAnchor.Verify
84void LogTrustAnchor(const net::HashValueVector& spki_hashes) {
Ryan Sleevid756c2d2017-12-01 02:07:4885 // Don't record metrics if there are no hashes; this is true if the HTTP
86 // load did not come from an active network connection, such as the disk
87 // cache or a synthesized response.
88 if (spki_hashes.empty())
89 return;
90
Ryan Sleevi19a7bde2017-11-22 06:51:3991 int32_t id = 0;
92 for (const auto& hash : spki_hashes) {
93 id = net::GetNetTrustAnchorHistogramIdForSPKI(hash);
94 if (id != 0)
95 break;
96 }
Ilya Sherman0eb39802017-12-08 20:58:1897 base::UmaHistogramSparse("Net.Certificate.TrustAnchor.Request", id);
Ryan Sleevi19a7bde2017-11-22 06:51:3998}
99
Emily Stark8b411de02017-11-23 20:21:27100// Records per-request histograms relating to Certificate Transparency
101// compliance.
102void RecordCTHistograms(const net::SSLInfo& ssl_info) {
Emily Stark9676ea82017-11-29 08:10:08103 if (ssl_info.ct_policy_compliance ==
104 net::ct::CTPolicyCompliance::CT_POLICY_COMPLIANCE_DETAILS_NOT_AVAILABLE) {
Emily Stark8b411de02017-11-23 20:21:27105 return;
Emily Stark9676ea82017-11-29 08:10:08106 }
Emily Stark8b411de02017-11-23 20:21:27107 if (!ssl_info.is_issued_by_known_root)
108 return;
109
110 // Connections with major errors other than CERTIFICATE_TRANSPARENCY_REQUIRED
111 // would have failed anyway, so do not record these histograms for such
112 // requests.
113 net::CertStatus other_errors =
114 ssl_info.cert_status &
115 ~net::CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED;
116 if (net::IsCertStatusError(other_errors) &&
117 !net::IsCertStatusMinorError(other_errors)) {
118 return;
119 }
120
121 // Record the CT compliance of each request, to give a picture of the
122 // percentage of overall requests that are CT-compliant.
123 UMA_HISTOGRAM_ENUMERATION(
124 "Net.CertificateTransparency.RequestComplianceStatus",
Emily Stark627238f2017-11-29 03:29:54125 ssl_info.ct_policy_compliance,
Kunihiko Sakamoto36469732018-09-27 03:33:45126 net::ct::CTPolicyCompliance::CT_POLICY_COUNT);
Emily Stark8b411de02017-11-23 20:21:27127 // Record the CT compliance of each request which was required to be CT
128 // compliant. This gives a picture of the sites that are supposed to be
129 // compliant and how well they do at actually being compliant.
130 if (ssl_info.ct_policy_compliance_required) {
131 UMA_HISTOGRAM_ENUMERATION(
132 "Net.CertificateTransparency.CTRequiredRequestComplianceStatus",
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 }
136}
137
nharper3876dd562016-03-29 22:52:32138// Logs whether the CookieStore used for this request matches the
139// ChannelIDService used when establishing the connection that this request is
140// sent over. This logging is only done for requests to accounts.google.com, and
141// only for requests where Channel ID was sent when establishing the connection.
nharper79234722016-03-22 20:28:47142void LogChannelIDAndCookieStores(const GURL& url,
143 const net::URLRequestContext* context,
nharper5babb5e62016-03-09 18:58:07144 const net::SSLInfo& ssl_info) {
nharper79234722016-03-22 20:28:47145 if (url.host() != "accounts.google.com" || !ssl_info.channel_id_sent)
nharper5babb5e62016-03-09 18:58:07146 return;
147 // This enum is used for an UMA histogram - don't reuse or renumber entries.
148 enum {
nharper09ccd502016-03-10 01:54:28149 // Value 0 was removed (CID_EPHEMERAL_COOKIE_EPHEMERAL)
nharper3876dd562016-03-29 22:52:32150 // ChannelIDStore is ephemeral, but CookieStore is persistent.
nharper5babb5e62016-03-09 18:58:07151 CID_EPHEMERAL_COOKIE_PERSISTENT = 1,
nharper3876dd562016-03-29 22:52:32152 // ChannelIDStore is persistent, but CookieStore is ephemeral.
nharper5babb5e62016-03-09 18:58:07153 CID_PERSISTENT_COOKIE_EPHEMERAL = 2,
nharper09ccd502016-03-10 01:54:28154 // Value 3 was removed (CID_PERSISTENT_COOKIE_PERSISTENT)
nharper3876dd562016-03-29 22:52:32155 // There is no CookieStore for this request.
nharper5babb5e62016-03-09 18:58:07156 NO_COOKIE_STORE = 4,
nharper3876dd562016-03-29 22:52:32157 // There is no ChannelIDStore for this request. This should never happen,
158 // because we only log if Channel ID was sent.
nharper5babb5e62016-03-09 18:58:07159 NO_CHANNEL_ID_STORE = 5,
nharper015b9e42016-06-29 01:41:52160 // Value 6 was removed (KNOWN_MISMATCH).
nharper3876dd562016-03-29 22:52:32161 // Both stores are ephemeral, and the ChannelIDService used when
162 // establishing the connection is the same one that the CookieStore was
163 // created to be used with.
nharper09ccd502016-03-10 01:54:28164 EPHEMERAL_MATCH = 7,
nharper3876dd562016-03-29 22:52:32165 // Both stores are ephemeral, but a different CookieStore should have been
166 // used on this request.
nharper09ccd502016-03-10 01:54:28167 EPHEMERAL_MISMATCH = 8,
nharper3876dd562016-03-29 22:52:32168 // Both stores are persistent, and the ChannelIDService used when
169 // establishing the connection is the same one that the CookieStore was
170 // created to be used with.
nharper09ccd502016-03-10 01:54:28171 PERSISTENT_MATCH = 9,
nharper3876dd562016-03-29 22:52:32172 // Both stores are persistent, but a different CookieStore should have been
173 // used on this request.
nharper09ccd502016-03-10 01:54:28174 PERSISTENT_MISMATCH = 10,
nharper3876dd562016-03-29 22:52:32175 // Both stores are ephemeral, but it was never recorded in the CookieStore
176 // which ChannelIDService it was created for, so it is unknown whether the
177 // stores match.
178 EPHEMERAL_UNKNOWN = 11,
179 // Both stores are persistent, but it was never recorded in the CookieStore
180 // which ChannelIDService it was created for, so it is unknown whether the
181 // stores match.
182 PERSISTENT_UNKNOWN = 12,
nharper5babb5e62016-03-09 18:58:07183 EPHEMERALITY_MAX
184 } ephemerality;
mmenke6ddfbea2017-05-31 21:48:41185 const net::HttpNetworkSession::Context* session_context =
186 context->GetNetworkSessionContext();
nharper5babb5e62016-03-09 18:58:07187 net::CookieStore* cookie_store = context->cookie_store();
mmenke6ddfbea2017-05-31 21:48:41188 if (session_context == nullptr ||
189 session_context->channel_id_service == nullptr) {
nharper5babb5e62016-03-09 18:58:07190 ephemerality = NO_CHANNEL_ID_STORE;
191 } else if (cookie_store == nullptr) {
192 ephemerality = NO_COOKIE_STORE;
mmenke6ddfbea2017-05-31 21:48:41193 } else if (session_context->channel_id_service->GetChannelIDStore()
194 ->IsEphemeral()) {
nharper5babb5e62016-03-09 18:58:07195 if (cookie_store->IsEphemeral()) {
nharper3876dd562016-03-29 22:52:32196 if (cookie_store->GetChannelIDServiceID() == -1) {
197 ephemerality = EPHEMERAL_UNKNOWN;
198 } else if (cookie_store->GetChannelIDServiceID() ==
mmenke6ddfbea2017-05-31 21:48:41199 session_context->channel_id_service->GetUniqueID()) {
nharper09ccd502016-03-10 01:54:28200 ephemerality = EPHEMERAL_MATCH;
201 } else {
nharper3876dd562016-03-29 22:52:32202 NOTREACHED();
nharper09ccd502016-03-10 01:54:28203 ephemerality = EPHEMERAL_MISMATCH;
204 }
nharper5babb5e62016-03-09 18:58:07205 } else {
nharper3876dd562016-03-29 22:52:32206 NOTREACHED();
nharper5babb5e62016-03-09 18:58:07207 ephemerality = CID_EPHEMERAL_COOKIE_PERSISTENT;
208 }
209 } else if (cookie_store->IsEphemeral()) {
nharper49122482016-04-29 18:00:58210 NOTREACHED();
nharper5babb5e62016-03-09 18:58:07211 ephemerality = CID_PERSISTENT_COOKIE_EPHEMERAL;
nharper3876dd562016-03-29 22:52:32212 } else if (cookie_store->GetChannelIDServiceID() == -1) {
213 ephemerality = PERSISTENT_UNKNOWN;
214 } else if (cookie_store->GetChannelIDServiceID() ==
mmenke6ddfbea2017-05-31 21:48:41215 session_context->channel_id_service->GetUniqueID()) {
nharper09ccd502016-03-10 01:54:28216 ephemerality = PERSISTENT_MATCH;
nharper5babb5e62016-03-09 18:58:07217 } else {
nharper3876dd562016-03-29 22:52:32218 NOTREACHED();
nharper09ccd502016-03-10 01:54:28219 ephemerality = PERSISTENT_MISMATCH;
nharper5babb5e62016-03-09 18:58:07220 }
221 UMA_HISTOGRAM_ENUMERATION("Net.TokenBinding.StoreEphemerality", ephemerality,
222 EPHEMERALITY_MAX);
223}
224
Thiemo Nagel0793b9c532018-04-18 16:57:58225net::CookieNetworkSecurity HistogramEntryForCookie(
226 const net::CanonicalCookie& cookie,
227 const net::URLRequest& request,
228 const net::HttpRequestInfo& request_info) {
229 if (!request_info.url.SchemeIsCryptographic()) {
230 return net::CookieNetworkSecurity::k1pNonsecureConnection;
231 }
232
233 if (cookie.IsSecure()) {
234 return net::CookieNetworkSecurity::k1pSecureAttribute;
235 }
236
237 net::TransportSecurityState* transport_security_state =
238 request.context()->transport_security_state();
239 net::TransportSecurityState::STSState sts_state;
240 const std::string cookie_domain =
241 cookie.IsHostCookie() ? request.url().host() : cookie.Domain().substr(1);
242 const bool hsts =
243 transport_security_state->GetSTSState(cookie_domain, &sts_state) &&
244 sts_state.ShouldUpgradeToSSL();
245 if (!hsts) {
246 return net::CookieNetworkSecurity::k1pSecureConnection;
247 }
248
249 if (cookie.IsHostCookie()) {
250 if (cookie.IsPersistent() && sts_state.expiry >= cookie.ExpiryDate()) {
251 return net::CookieNetworkSecurity::k1pHSTSHostCookie;
252 } else {
253 // Session cookies are assumed to live forever.
254 return net::CookieNetworkSecurity::k1pExpiringHSTSHostCookie;
255 }
256 }
257
258 // Domain cookies require HSTS to include subdomains to prevent spoofing.
259 if (sts_state.include_subdomains) {
260 if (cookie.IsPersistent() && sts_state.expiry >= cookie.ExpiryDate()) {
261 return net::CookieNetworkSecurity::k1pHSTSSubdomainsIncluded;
262 } else {
263 // Session cookies are assumed to live forever.
264 return net::CookieNetworkSecurity::k1pExpiringHSTSSubdomainsIncluded;
265 }
266 }
267
268 return net::CookieNetworkSecurity::k1pHSTSSpoofable;
269}
270
Thiemo Nagel6c783dbf2018-03-21 13:53:30271void LogCookieUMA(const net::CookieList& cookie_list,
272 const net::URLRequest& request,
273 const net::HttpRequestInfo& request_info) {
274 const bool secure_request = request_info.url.SchemeIsCryptographic();
275 const bool same_site = net::registry_controlled_domains::SameDomainOrHost(
276 request.url(), request.site_for_cookies(),
277 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
Mike West86149882017-07-28 10:41:49278
Thiemo Nagel6c783dbf2018-03-21 13:53:30279 const base::Time now = base::Time::Now();
280 base::Time oldest = base::Time::Max();
281 for (const auto& cookie : cookie_list) {
282 const std::string histogram_name =
283 std::string("Cookie.AllAgesFor") +
284 (secure_request ? "Secure" : "NonSecure") +
285 (same_site ? "SameSite" : "CrossSite") + "Request";
286 const int age_in_days = (now - cookie.CreationDate()).InDays();
287 base::UmaHistogramCounts1000(histogram_name, age_in_days);
Mohsen Izadiad6f7592018-04-18 15:57:10288 oldest = std::min(cookie.CreationDate(), oldest);
Thiemo Nagel0793b9c532018-04-18 16:57:58289
290 net::CookieNetworkSecurity entry =
291 HistogramEntryForCookie(cookie, request, request_info);
292 if (!same_site) {
293 entry =
294 static_cast<net::CookieNetworkSecurity>(static_cast<int>(entry) | 1);
295 }
296 UMA_HISTOGRAM_ENUMERATION("Cookie.NetworkSecurity", entry,
297 net::CookieNetworkSecurity::kCount);
Mike West86149882017-07-28 10:41:49298 }
Thiemo Nagel6c783dbf2018-03-21 13:53:30299
300 const std::string histogram_name =
301 std::string("Cookie.AgeFor") + (secure_request ? "Secure" : "NonSecure") +
302 (same_site ? "SameSite" : "CrossSite") + "Request";
303 const int age_in_days = (now - oldest).InDays();
304 base::UmaHistogramCounts1000(histogram_name, age_in_days);
Mike West86149882017-07-28 10:41:49305}
306
mkwst202534e32016-01-15 16:07:15307} // namespace
308
[email protected]4f5656c62010-12-13 10:47:09309namespace net {
310
initial.commit586acc5fe2008-07-26 22:42:52311// TODO(darin): make sure the port blocking code is not lost
initial.commit586acc5fe2008-07-26 22:42:52312// static
[email protected]4f5656c62010-12-13 10:47:09313URLRequestJob* URLRequestHttpJob::Factory(URLRequest* request,
[email protected]9f170462012-08-24 01:06:58314 NetworkDelegate* network_delegate,
[email protected]4f5656c62010-12-13 10:47:09315 const std::string& scheme) {
[email protected]f4533ba2013-11-28 09:35:41316 DCHECK(scheme == "http" || scheme == "https" || scheme == "ws" ||
317 scheme == "wss");
initial.commit586acc5fe2008-07-26 22:42:52318
[email protected]81293f482012-08-13 19:35:45319 if (!request->context()->http_transaction_factory()) {
initial.commit586acc5fe2008-07-26 22:42:52320 NOTREACHED() << "requires a valid context";
[email protected]9f170462012-08-24 01:06:58321 return new URLRequestErrorJob(
322 request, network_delegate, ERR_INVALID_ARGUMENT);
initial.commit586acc5fe2008-07-26 22:42:52323 }
324
mgershd21d6d142016-12-14 23:06:36325 const GURL& url = request->url();
326
327 // Check for reasons not to return a URLRequestHttpJob. These don't apply to
328 // https and wss requests.
329 if (!url.SchemeIsCryptographic()) {
330 // Check for HSTS upgrade.
331 TransportSecurityState* hsts =
332 request->context()->transport_security_state();
333 if (hsts && hsts->ShouldUpgradeToSSL(url.host())) {
334 GURL::Replacements replacements;
335 replacements.SetSchemeStr(
Mike West86149882017-07-28 10:41:49336
mgershd21d6d142016-12-14 23:06:36337 url.SchemeIs(url::kHttpScheme) ? url::kHttpsScheme : url::kWssScheme);
338 return new URLRequestRedirectJob(
339 request, network_delegate, url.ReplaceComponents(replacements),
340 // Use status code 307 to preserve the method, so POST requests work.
341 URLRequestRedirectJob::REDIRECT_307_TEMPORARY_REDIRECT, "HSTS");
342 }
343
344#if defined(OS_ANDROID)
345 // Check whether the app allows cleartext traffic to this host, and return
mgersh072720a2016-12-15 16:33:34346 // ERR_CLEARTEXT_NOT_PERMITTED if not.
mgershd21d6d142016-12-14 23:06:36347 if (request->context()->check_cleartext_permitted() &&
348 !android::IsCleartextPermitted(url.host())) {
349 return new URLRequestErrorJob(request, network_delegate,
350 ERR_CLEARTEXT_NOT_PERMITTED);
351 }
352#endif
353 }
mkwst549a5c632016-06-20 14:17:03354
[email protected]ee4c30d2012-11-07 15:08:43355 return new URLRequestHttpJob(request,
356 network_delegate,
357 request->context()->http_user_agent_settings());
initial.commit586acc5fe2008-07-26 22:42:52358}
359
[email protected]ee4c30d2012-11-07 15:08:43360URLRequestHttpJob::URLRequestHttpJob(
361 URLRequest* request,
362 NetworkDelegate* network_delegate,
363 const HttpUserAgentSettings* http_user_agent_settings)
[email protected]9f170462012-08-24 01:06:58364 : URLRequestJob(request, network_delegate),
[email protected]5033ab82013-03-22 20:17:46365 priority_(DEFAULT_PRIORITY),
mmenke54e82af2016-02-16 23:06:30366 response_info_(nullptr),
[email protected]4f5656c62010-12-13 10:47:09367 proxy_auth_state_(AUTH_STATE_DONT_NEED_AUTH),
368 server_auth_state_(AUTH_STATE_DONT_NEED_AUTH),
[email protected]3589e552008-08-20 23:11:34369 read_in_progress_(false),
mmenke54e82af2016-02-16 23:06:30370 throttling_entry_(nullptr),
[email protected]00e48bf2010-12-03 06:15:42371 is_cached_content_(false),
[email protected]dd29bcd72011-03-24 00:03:44372 packet_timing_enabled_(false),
[email protected]bbaea8f2011-06-24 00:11:01373 done_(false),
[email protected]dd29bcd72011-03-24 00:03:44374 bytes_observed_in_packets_(0),
[email protected]5a07c192012-07-30 20:18:22375 awaiting_callback_(false),
[email protected]09812102014-05-24 00:04:11376 http_user_agent_settings_(http_user_agent_settings),
sclittlece72c482015-08-24 20:20:59377 total_received_bytes_from_previous_transactions_(0),
sclittlefb249892015-09-10 21:33:22378 total_sent_bytes_from_previous_transactions_(0),
[email protected]09812102014-05-24 00:04:11379 weak_factory_(this) {
[email protected]a73a2802012-05-02 19:20:15380 URLRequestThrottlerManager* manager = request->context()->throttler_manager();
381 if (manager)
382 throttling_entry_ = manager->RegisterRequestUrl(request->url());
383
[email protected]ec23f522011-02-22 21:01:38384 ResetTimer();
initial.commit586acc5fe2008-07-26 22:42:52385}
386
[email protected]5033ab82013-03-22 20:17:46387URLRequestHttpJob::~URLRequestHttpJob() {
388 CHECK(!awaiting_callback_);
389
[email protected]5033ab82013-03-22 20:17:46390 DoneWithRequest(ABORTED);
391}
392
393void URLRequestHttpJob::SetPriority(RequestPriority priority) {
394 priority_ = priority;
395 if (transaction_)
396 transaction_->SetPriority(priority_);
397}
398
399void URLRequestHttpJob::Start() {
400 DCHECK(!transaction_.get());
401
[email protected]99ecf6e2013-04-10 22:46:13402 // URLRequest::SetReferrer ensures that we do not send username and password
403 // fields in the referrer.
404 GURL referrer(request_->referrer());
[email protected]5033ab82013-03-22 20:17:46405
406 request_info_.url = request_->url();
407 request_info_.method = request_->method();
Josh Karlinf3caee1642018-12-10 22:54:27408 request_info_.top_frame_origin = request_->top_frame_origin();
[email protected]5033ab82013-03-22 20:17:46409 request_info_.load_flags = request_->load_flags();
Ramin Halavatib5e433e62018-02-07 07:41:10410 request_info_.traffic_annotation =
411 net::MutableNetworkTrafficAnnotationTag(request_->traffic_annotation());
Paul Jensen60e45532018-02-19 16:04:18412 request_info_.socket_tag = request_->socket_tag();
Douglas Creageref5eecdc2018-11-09 20:50:36413#if BUILDFLAG(ENABLE_REPORTING)
414 request_info_.reporting_upload_depth = request_->reporting_upload_depth();
415#endif
Ramin Halavatib5e433e62018-02-07 07:41:10416
mkwste3e95992016-02-23 17:45:41417 // Privacy mode could still be disabled in SetCookieHeaderAndStart if we are
418 // going to send previously saved cookies.
Matt Menke7ad78edc2018-11-21 19:22:57419 request_info_.privacy_mode = privacy_mode();
[email protected]5033ab82013-03-22 20:17:46420
421 // Strip Referer from request_info_.extra_headers to prevent, e.g., plugins
422 // from overriding headers that are controlled using other means. Otherwise a
423 // plugin could set a referrer although sending the referrer is inhibited.
424 request_info_.extra_headers.RemoveHeader(HttpRequestHeaders::kReferer);
425
rdsmith81f607562014-11-21 18:35:16426 // Our consumer should have made sure that this is a safe referrer. See for
[email protected]5033ab82013-03-22 20:17:46427 // instance WebCore::FrameLoader::HideReferrer.
428 if (referrer.is_valid()) {
429 request_info_.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
430 referrer.spec());
431 }
432
[email protected]5033ab82013-03-22 20:17:46433 request_info_.extra_headers.SetHeaderIfMissing(
434 HttpRequestHeaders::kUserAgent,
435 http_user_agent_settings_ ?
[email protected]aa051272014-03-10 05:56:56436 http_user_agent_settings_->GetUserAgent() : std::string());
[email protected]5033ab82013-03-22 20:17:46437
438 AddExtraHeaders();
439 AddCookieHeaderAndStart();
440}
441
442void URLRequestHttpJob::Kill() {
[email protected]5033ab82013-03-22 20:17:46443 weak_factory_.InvalidateWeakPtrs();
mmenke2281f3762015-11-02 20:38:17444 if (transaction_)
445 DestroyTransaction();
[email protected]5033ab82013-03-22 20:17:46446 URLRequestJob::Kill();
447}
448
ttuttle3ae06922015-05-11 23:41:52449void URLRequestHttpJob::GetConnectionAttempts(ConnectionAttempts* out) const {
450 if (transaction_)
451 transaction_->GetConnectionAttempts(out);
452 else
453 out->clear();
454}
455
ryansturm49a8cb12016-06-15 16:51:09456void URLRequestHttpJob::NotifyBeforeSendHeadersCallback(
[email protected]1252d42f2014-07-01 21:20:20457 const ProxyInfo& proxy_info,
458 HttpRequestHeaders* request_headers) {
459 DCHECK(request_headers);
[email protected]597a1ab2014-06-26 08:12:27460 DCHECK_NE(URLRequestStatus::CANCELED, GetStatus().status());
Tarun Bansal4dcebd42017-10-12 20:12:30461 if (proxy_info.is_empty()) {
462 SetProxyServer(ProxyServer::Direct());
463 } else {
464 SetProxyServer(proxy_info.proxy_server());
465 }
[email protected]597a1ab2014-06-26 08:12:27466 if (network_delegate()) {
ryansturm49a8cb12016-06-15 16:51:09467 network_delegate()->NotifyBeforeSendHeaders(
468 request_, proxy_info,
Lily Houghton8c2f97d2018-01-22 05:06:59469 request_->context()->proxy_resolution_service()->proxy_retry_info(),
[email protected]1252d42f2014-07-01 21:20:20470 request_headers);
[email protected]597a1ab2014-06-26 08:12:27471 }
472}
473
[email protected]175adac2008-07-30 17:28:04474void URLRequestHttpJob::NotifyHeadersComplete() {
initial.commit586acc5fe2008-07-26 22:42:52475 DCHECK(!response_info_);
476
477 response_info_ = transaction_->GetResponseInfo();
478
[email protected]d8fd5132009-05-15 01:06:53479 // Save boolean, as we'll need this info at destruction time, and filters may
480 // also need this info.
481 is_cached_content_ = response_info_->was_cached;
482
xunjieli041e9392015-05-19 21:51:33483 if (!is_cached_content_ && throttling_entry_.get())
484 throttling_entry_->UpdateWithResponse(GetResponseCode());
[email protected]6b3f9642010-11-25 02:29:06485
[email protected]fecef222012-01-05 02:26:15486 // The ordering of these calls is not important.
[email protected]77f6fb432009-09-05 14:21:09487 ProcessStrictTransportSecurityHeader();
estark1614475f2016-03-10 03:46:47488 ProcessExpectCTHeader();
[email protected]a9cea7542009-05-20 04:30:23489
[email protected]0757e7702009-03-27 04:00:22490 // The HTTP transaction may be restarted several times for the purposes
491 // of sending authorization information. Each time it restarts, we get
492 // notified of the headers completion so that we can update the cookie store.
493 if (transaction_->IsReadyToRestartForAuth()) {
494 DCHECK(!response_info_->auth_challenge.get());
[email protected]87a09a92011-07-14 15:50:50495 // TODO(battre): This breaks the webrequest API for
496 // URLRequestTestHTTP.BasicAuthWithCookies
ryansturm2343cb62016-06-15 01:09:00497 // where OnBeforeStartTransaction -> OnStartTransaction ->
498 // OnBeforeStartTransaction occurs.
[email protected]f3cf9802011-10-28 18:44:58499 RestartTransactionWithAuth(AuthCredentials());
[email protected]0757e7702009-03-27 04:00:22500 return;
501 }
502
[email protected]4f5656c62010-12-13 10:47:09503 URLRequestJob::NotifyHeadersComplete();
initial.commit586acc5fe2008-07-26 22:42:52504}
505
[email protected]175adac2008-07-30 17:28:04506void URLRequestHttpJob::DestroyTransaction() {
[email protected]c6a4eb92010-03-03 23:51:19507 DCHECK(transaction_.get());
initial.commit586acc5fe2008-07-26 22:42:52508
[email protected]bbaea8f2011-06-24 00:11:01509 DoneWithRequest(ABORTED);
sclittlece72c482015-08-24 20:20:59510
511 total_received_bytes_from_previous_transactions_ +=
512 transaction_->GetTotalReceivedBytes();
sclittlefb249892015-09-10 21:33:22513 total_sent_bytes_from_previous_transactions_ +=
514 transaction_->GetTotalSentBytes();
[email protected]af4876d2008-10-21 23:10:57515 transaction_.reset();
David Benjamin0bda12f2018-02-07 19:58:45516 response_info_ = nullptr;
517 override_response_headers_ = nullptr;
[email protected]3b23a222013-05-15 21:33:25518 receive_headers_end_ = base::TimeTicks();
initial.commit586acc5fe2008-07-26 22:42:52519}
520
[email protected]175adac2008-07-30 17:28:04521void URLRequestHttpJob::StartTransaction() {
[email protected]cc05edc2013-03-08 18:04:41522 if (network_delegate()) {
David Benjamin9776ca22018-06-13 00:00:15523 OnCallToDelegate(
524 NetLogEventType::NETWORK_DELEGATE_BEFORE_START_TRANSACTION);
mmenked3a02b32016-11-16 20:21:32525 // The NetworkDelegate must watch for OnRequestDestroyed and not modify
526 // |extra_headers| or invoke the callback after it's called. Not using a
527 // WeakPtr here because it's not enough, the consumer has to watch for
528 // destruction regardless, due to the headers parameter.
ryansturm2343cb62016-06-15 01:09:00529 int rv = network_delegate()->NotifyBeforeStartTransaction(
mmenked3a02b32016-11-16 20:21:32530 request_,
David Benjamind1f287bf2018-06-12 01:57:20531 base::BindOnce(&URLRequestHttpJob::NotifyBeforeStartTransactionCallback,
532 base::Unretained(this)),
[email protected]636eccd2011-06-28 12:28:01533 &request_info_.extra_headers);
534 // If an extension blocks the request, we rely on the callback to
[email protected]b4438d32012-09-27 06:15:30535 // MaybeStartTransactionInternal().
[email protected]abe1c4a2013-10-25 19:28:51536 if (rv == ERR_IO_PENDING)
[email protected]636eccd2011-06-28 12:28:01537 return;
[email protected]b4438d32012-09-27 06:15:30538 MaybeStartTransactionInternal(rv);
539 return;
[email protected]636eccd2011-06-28 12:28:01540 }
541 StartTransactionInternal();
542}
543
ryansturm2343cb62016-06-15 01:09:00544void URLRequestHttpJob::NotifyBeforeStartTransactionCallback(int result) {
[email protected]9045b8822012-01-13 20:35:35545 // Check that there are no callbacks to already canceled requests.
546 DCHECK_NE(URLRequestStatus::CANCELED, GetStatus().status());
547
[email protected]b4438d32012-09-27 06:15:30548 MaybeStartTransactionInternal(result);
549}
550
551void URLRequestHttpJob::MaybeStartTransactionInternal(int result) {
[email protected]abe1c4a2013-10-25 19:28:51552 OnCallToDelegateComplete();
[email protected]636eccd2011-06-28 12:28:01553 if (result == OK) {
554 StartTransactionInternal();
555 } else {
[email protected]55b8a6c12012-06-13 22:03:42556 std::string source("delegate");
mikecirone8b85c432016-09-08 19:11:00557 request_->net_log().AddEvent(NetLogEventType::CANCELLED,
[email protected]55b8a6c12012-06-13 22:03:42558 NetLog::StringCallback("source", &source));
jamd3f5a3c2016-10-27 18:52:02559 // Don't call back synchronously to the delegate.
560 base::ThreadTaskRunnerHandle::Get()->PostTask(
561 FROM_HERE,
kylecharf4fe5172019-02-15 18:53:49562 base::BindOnce(&URLRequestHttpJob::NotifyStartError,
563 weak_factory_.GetWeakPtr(),
564 URLRequestStatus(URLRequestStatus::FAILED, result)));
[email protected]636eccd2011-06-28 12:28:01565 }
566}
567
568void URLRequestHttpJob::StartTransactionInternal() {
mmenke4600b602015-10-28 18:52:17569 // This should only be called while the request's status is IO_PENDING.
mmenke2281f3762015-11-02 20:38:17570 DCHECK_EQ(URLRequestStatus::IO_PENDING, request_->status().status());
David Benjamin0bda12f2018-02-07 19:58:45571 DCHECK(!override_response_headers_);
mmenke4600b602015-10-28 18:52:17572
initial.commit586acc5fe2008-07-26 22:42:52573 // NOTE: This method assumes that request_info_ is already setup properly.
574
[email protected]34602282010-02-03 22:14:15575 // If we already have a transaction, then we should restart the transaction
[email protected]f3cf9802011-10-28 18:44:58576 // with auth provided by auth_credentials_.
initial.commit586acc5fe2008-07-26 22:42:52577
[email protected]99c07902010-08-17 18:59:52578 int rv;
[email protected]6b3f9642010-11-25 02:29:06579
tbansal80a52162016-05-20 17:55:04580 // Notify NetworkQualityEstimator.
581 NetworkQualityEstimator* network_quality_estimator =
582 request()->context()->network_quality_estimator();
583 if (network_quality_estimator)
584 network_quality_estimator->NotifyStartTransaction(*request_);
585
[email protected]cc05edc2013-03-08 18:04:41586 if (network_delegate()) {
ryansturm2343cb62016-06-15 01:09:00587 network_delegate()->NotifyStartTransaction(request_,
588 request_info_.extra_headers);
[email protected]5796dc942011-07-14 19:26:10589 }
590
[email protected]34602282010-02-03 22:14:15591 if (transaction_.get()) {
mmenked3a02b32016-11-16 20:21:32592 rv = transaction_->RestartWithAuth(
593 auth_credentials_, base::Bind(&URLRequestHttpJob::OnStartCompleted,
594 base::Unretained(this)));
[email protected]f3cf9802011-10-28 18:44:58595 auth_credentials_ = AuthCredentials();
[email protected]34602282010-02-03 22:14:15596 } else {
[email protected]34602282010-02-03 22:14:15597 DCHECK(request_->context()->http_transaction_factory());
initial.commit586acc5fe2008-07-26 22:42:52598
[email protected]99c07902010-08-17 18:59:52599 rv = request_->context()->http_transaction_factory()->CreateTransaction(
[email protected]027bd85a2013-12-27 22:39:10600 priority_, &transaction_);
[email protected]f4533ba2013-11-28 09:35:41601
602 if (rv == OK && request_info_.url.SchemeIsWSOrWSS()) {
Bence Békya5ec55e62018-03-07 14:23:28603 base::SupportsUserData::Data* data =
604 request_->GetUserData(kWebSocketHandshakeUserDataKey);
[email protected]f4533ba2013-11-28 09:35:41605 if (data) {
606 transaction_->SetWebSocketHandshakeStreamCreateHelper(
607 static_cast<WebSocketHandshakeStreamBase::CreateHelper*>(data));
608 } else {
609 rv = ERR_DISALLOWED_URL_SCHEME;
610 }
611 }
612
[email protected]4f5656c62010-12-13 10:47:09613 if (rv == OK) {
ryansturm49a8cb12016-06-15 16:51:09614 transaction_->SetBeforeHeadersSentCallback(
615 base::Bind(&URLRequestHttpJob::NotifyBeforeSendHeadersCallback,
[email protected]597a1ab2014-06-26 08:12:27616 base::Unretained(this)));
Andrey Kosyakov83a6eee2017-08-14 19:20:04617 transaction_->SetRequestHeadersCallback(request_headers_callback_);
Andrey Kosyakov2e893e62017-08-31 17:00:52618 transaction_->SetResponseHeadersCallback(response_headers_callback_);
[email protected]a45840b2014-01-10 15:40:22619
dchengc2e01e82014-08-27 00:24:42620 if (!throttling_entry_.get() ||
xunjieli41edcdd2015-06-24 14:26:40621 !throttling_entry_->ShouldRejectRequest(*request_)) {
[email protected]227b0e82011-03-25 21:11:53622 rv = transaction_->Start(
mmenked3a02b32016-11-16 20:21:32623 &request_info_, base::Bind(&URLRequestHttpJob::OnStartCompleted,
624 base::Unretained(this)),
625 request_->net_log());
[email protected]bbaea8f2011-06-24 00:11:01626 start_time_ = base::TimeTicks::Now();
[email protected]227b0e82011-03-25 21:11:53627 } else {
628 // Special error code for the exponential back-off module.
629 rv = ERR_TEMPORARILY_THROTTLED;
630 }
[email protected]34602282010-02-03 22:14:15631 }
initial.commit586acc5fe2008-07-26 22:42:52632 }
633
[email protected]4f5656c62010-12-13 10:47:09634 if (rv == ERR_IO_PENDING)
[email protected]34602282010-02-03 22:14:15635 return;
636
initial.commit586acc5fe2008-07-26 22:42:52637 // The transaction started synchronously, but we need to notify the
[email protected]4f5656c62010-12-13 10:47:09638 // URLRequest delegate via the message loop.
skyostil4891b25b2015-06-11 11:43:45639 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf4fe5172019-02-15 18:53:49640 FROM_HERE, base::BindOnce(&URLRequestHttpJob::OnStartCompleted,
641 weak_factory_.GetWeakPtr(), rv));
initial.commit586acc5fe2008-07-26 22:42:52642}
643
[email protected]175adac2008-07-30 17:28:04644void URLRequestHttpJob::AddExtraHeaders() {
[email protected]c7bef94c2011-06-21 18:05:51645 if (!request_info_.extra_headers.HasHeader(
Helen Li7dd80832017-09-12 18:29:17646 HttpRequestHeaders::kAcceptEncoding)) {
Aaron Tagliaboschi6c652aa2018-11-30 22:13:41647 // If a range is specifically requested, set the "Accepted Encoding" header
648 // to "identity"
649 if (request_info_.extra_headers.HasHeader(HttpRequestHeaders::kRange)) {
650 request_info_.extra_headers.SetHeader(HttpRequestHeaders::kAcceptEncoding,
651 "identity");
652 } else {
653 // Advertise "br" encoding only if transferred data is opaque to proxy.
654 bool advertise_brotli = false;
655 if (request()->context()->enable_brotli()) {
656 if (request()->url().SchemeIsCryptographic() ||
657 IsLocalhost(request()->url())) {
658 advertise_brotli = true;
659 }
eustas7ff89682016-07-07 20:23:39660 }
eustasfbec9132015-12-30 14:56:51661
Aaron Tagliaboschi6c652aa2018-11-30 22:13:41662 // Supply Accept-Encoding headers first so that it is more likely that
663 // they will be in the first transmitted packet. This can sometimes make
664 // it easier to filter and analyze the streams to assure that a proxy has
665 // not damaged these headers. Some proxies deliberately corrupt
666 // Accept-Encoding headers.
667 std::string advertised_encodings = "gzip, deflate";
668 if (advertise_brotli)
669 advertised_encodings += ", br";
670 // Tell the server what compression formats are supported.
671 request_info_.extra_headers.SetHeader(HttpRequestHeaders::kAcceptEncoding,
672 advertised_encodings);
673 }
[email protected]423041b2008-10-27 17:39:28674 }
675
[email protected]ee4c30d2012-11-07 15:08:43676 if (http_user_agent_settings_) {
[email protected]84f05432013-03-15 01:00:12677 // Only add default Accept-Language if the request didn't have it
678 // specified.
[email protected]ee4c30d2012-11-07 15:08:43679 std::string accept_language =
680 http_user_agent_settings_->GetAcceptLanguage();
681 if (!accept_language.empty()) {
682 request_info_.extra_headers.SetHeaderIfMissing(
683 HttpRequestHeaders::kAcceptLanguage,
684 accept_language);
685 }
initial.commit586acc5fe2008-07-26 22:42:52686 }
initial.commit586acc5fe2008-07-26 22:42:52687}
688
[email protected]34602282010-02-03 22:14:15689void URLRequestHttpJob::AddCookieHeaderAndStart() {
davidben151423e2015-03-23 18:48:36690 CookieStore* cookie_store = request_->context()->cookie_store();
[email protected]1a6fff52011-10-20 21:00:16691 if (cookie_store && !(request_info_.load_flags & LOAD_DO_NOT_SEND_COOKIES)) {
mkwste3e95992016-02-23 17:45:41692 CookieOptions options;
693 options.set_include_httponly();
694
mkwstf71d0bd2016-03-21 14:15:24695 // Set SameSiteCookieMode according to the rules laid out in
Mike Westb85da8ed2017-08-10 14:16:46696 // https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site:
mkwstf71d0bd2016-03-21 14:15:24697 //
698 // * Include both "strict" and "lax" same-site cookies if the request's
Mike Westb85da8ed2017-08-10 14:16:46699 // |url|, |initiator|, and |site_for_cookies| all have the same
clamyfd58ca072016-12-21 17:18:32700 // registrable domain. Note: this also covers the case of a request
701 // without an initiator (only happens for browser-initiated main frame
702 // navigations).
mkwstf71d0bd2016-03-21 14:15:24703 //
704 // * Include only "lax" same-site cookies if the request's |URL| and
Mike Westb85da8ed2017-08-10 14:16:46705 // |site_for_cookies| have the same registrable domain, _and_ the
mkwstf71d0bd2016-03-21 14:15:24706 // request's |method| is "safe" ("GET" or "HEAD").
707 //
708 // Note that this will generally be the case only for cross-site requests
709 // which target a top-level browsing context.
710 //
Nasko Oskov13105d42018-03-23 22:02:08711 // * Include both "strict" and "lax" same-site cookies if the request is
712 // tagged with a flag allowing it.
713 // Note that this can be the case for requests initiated by extensions,
714 // which need to behave as though they are made by the document itself,
715 // but appear like cross-site ones.
716 //
mkwstf71d0bd2016-03-21 14:15:24717 // * Otherwise, do not include same-site cookies.
mkwstc5fa7762016-03-28 09:28:23718 if (registry_controlled_domains::SameDomainOrHost(
Mike Westb85da8ed2017-08-10 14:16:46719 request_->url(), request_->site_for_cookies(),
mkwstc5fa7762016-03-28 09:28:23720 registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) {
clamyfd58ca072016-12-21 17:18:32721 if (!request_->initiator() ||
csharrisond5c68c492016-12-03 00:15:27722 registry_controlled_domains::SameDomainOrHost(
723 request_->url(), request_->initiator().value().GetURL(),
Nasko Oskov13105d42018-03-23 22:02:08724 registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES) ||
725 request_->attach_same_site_cookies()) {
mkwstf71d0bd2016-03-21 14:15:24726 options.set_same_site_cookie_mode(
727 CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
tfarinadbf459732017-05-09 04:36:09728 } else if (HttpUtil::IsMethodSafe(request_->method())) {
mkwstf71d0bd2016-03-21 14:15:24729 options.set_same_site_cookie_mode(
730 CookieOptions::SameSiteCookieMode::INCLUDE_LAX);
731 }
mkwste3e95992016-02-23 17:45:41732 }
733
734 cookie_store->GetCookieListWithOptionsAsync(
735 request_->url(), options,
736 base::Bind(&URLRequestHttpJob::SetCookieHeaderAndStart,
[email protected]dc8313a2014-03-24 21:38:14737 weak_factory_.GetWeakPtr()));
[email protected]03d845f2011-07-29 19:06:26738 } else {
mmenked3a02b32016-11-16 20:21:32739 StartTransaction();
[email protected]03d845f2011-07-29 19:06:26740 }
741}
742
Aaron Tagliaboschia4c64b52019-01-25 03:28:49743void URLRequestHttpJob::SetCookieHeaderAndStart(
744 const CookieList& cookie_list,
745 const CookieStatusList& excluded_list) {
mmenked3a02b32016-11-16 20:21:32746 if (!cookie_list.empty() && CanGetCookies(cookie_list)) {
Thiemo Nagel6c783dbf2018-03-21 13:53:30747 LogCookieUMA(cookie_list, *request_, request_info_);
Mike West86149882017-07-28 10:41:49748
Mike West7c8c2ad2018-02-10 07:08:49749 std::string cookie_line = CanonicalCookie::BuildCookieLine(cookie_list);
750 UMA_HISTOGRAM_COUNTS_10000("Cookie.HeaderLength", cookie_line.length());
751 request_info_.extra_headers.SetHeader(HttpRequestHeaders::kCookie,
752 cookie_line);
753
[email protected]e6d017652013-05-17 18:01:40754 // Disable privacy mode as we are sending cookies anyway.
[email protected]314b03992014-04-01 01:28:53755 request_info_.privacy_mode = PRIVACY_MODE_DISABLED;
[email protected]54f4c9362011-07-25 21:54:46756 }
mmenked3a02b32016-11-16 20:21:32757 StartTransaction();
[email protected]0757e7702009-03-27 04:00:22758}
759
[email protected]ea8141e2011-10-05 13:12:51760void URLRequestHttpJob::SaveCookiesAndNotifyHeadersComplete(int result) {
[email protected]abe1c4a2013-10-25 19:28:51761 // End of the call started in OnStartCompleted.
762 OnCallToDelegateComplete();
763
ttuttle859dc7a2015-04-23 19:42:29764 if (result != OK) {
[email protected]55b8a6c12012-06-13 22:03:42765 std::string source("delegate");
mikecirone8b85c432016-09-08 19:11:00766 request_->net_log().AddEvent(NetLogEventType::CANCELLED,
[email protected]55b8a6c12012-06-13 22:03:42767 NetLog::StringCallback("source", &source));
[email protected]ea8141e2011-10-05 13:12:51768 NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, result));
769 return;
770 }
771
mmenke54e82af2016-02-16 23:06:30772 base::Time response_date;
773 if (!GetResponseHeaders()->GetDateValue(&response_date))
774 response_date = base::Time();
[email protected]263163f2012-06-14 22:40:34775
776 if (!(request_info_.load_flags & LOAD_DO_NOT_SAVE_COOKIES) &&
mmenke54e82af2016-02-16 23:06:30777 request_->context()->cookie_store()) {
[email protected]263163f2012-06-14 22:40:34778 CookieOptions options;
779 options.set_include_httponly();
mmenke54e82af2016-02-16 23:06:30780 options.set_server_time(response_date);
jww79aceda2015-12-07 01:56:34781
mmenke54e82af2016-02-16 23:06:30782 // Set all cookies, without waiting for them to be set. Any subsequent read
783 // will see the combined result of all cookie operation.
mmenked3a02b32016-11-16 20:21:32784 const base::StringPiece name("Set-Cookie");
Victor Costan70f85512017-11-20 16:14:46785 std::string cookie_line;
mmenked3a02b32016-11-16 20:21:32786 size_t iter = 0;
787 HttpResponseHeaders* headers = GetResponseHeaders();
Victor Costan70f85512017-11-20 16:14:46788 while (headers->EnumerateHeader(&iter, name, &cookie_line)) {
789 std::unique_ptr<CanonicalCookie> cookie = net::CanonicalCookie::Create(
790 request_->url(), cookie_line, base::Time::Now(), options);
791 if (!cookie || !CanSetCookie(*cookie, &options))
mmenke54e82af2016-02-16 23:06:30792 continue;
Randy Smithe6515d6a2018-01-27 03:57:32793 request_->context()->cookie_store()->SetCookieWithOptionsAsync(
794 request_->url(), cookie_line, options,
795 CookieStore::SetCookiesCallback());
[email protected]263163f2012-06-14 22:40:34796 }
797 }
798
mmenke54e82af2016-02-16 23:06:30799 NotifyHeadersComplete();
[email protected]34602282010-02-03 22:14:15800}
801
[email protected]77f6fb432009-09-05 14:21:09802void URLRequestHttpJob::ProcessStrictTransportSecurityHeader() {
[email protected]a9cea7542009-05-20 04:30:23803 DCHECK(response_info_);
[email protected]6ed72be2013-01-08 22:07:33804 TransportSecurityState* security_state =
805 request_->context()->transport_security_state();
[email protected]e88006f2012-01-11 06:15:07806 const SSLInfo& ssl_info = response_info_->ssl_info;
[email protected]a9cea7542009-05-20 04:30:23807
[email protected]6ed72be2013-01-08 22:07:33808 // Only accept HSTS headers on HTTPS connections that have no
809 // certificate errors.
[email protected]e88006f2012-01-11 06:15:07810 if (!ssl_info.is_valid() || IsCertStatusError(ssl_info.cert_status) ||
mmenked3a02b32016-11-16 20:21:32811 !security_state) {
[email protected]e88006f2012-01-11 06:15:07812 return;
mmenked3a02b32016-11-16 20:21:32813 }
[email protected]326e6792009-12-11 21:04:42814
estarka5da76702015-04-09 04:00:16815 // Don't accept HSTS headers when the hostname is an IP address.
816 if (request_info_.url.HostIsIPAddress())
817 return;
818
[email protected]242d8562012-10-30 21:20:46819 // http://tools.ietf.org/html/draft-ietf-websec-strict-transport-sec:
820 //
821 // If a UA receives more than one STS header field in a HTTP response
822 // message over secure transport, then the UA MUST process only the
823 // first such header field.
[email protected]6ed72be2013-01-08 22:07:33824 HttpResponseHeaders* headers = GetResponseHeaders();
825 std::string value;
olli.raulaee489a52016-01-25 08:37:10826 if (headers->EnumerateHeader(nullptr, "Strict-Transport-Security", &value))
[email protected]6ed72be2013-01-08 22:07:33827 security_state->AddHSTSHeader(request_info_.url.host(), value);
[email protected]a9cea7542009-05-20 04:30:23828}
[email protected]4f5656c62010-12-13 10:47:09829
estark1614475f2016-03-10 03:46:47830void URLRequestHttpJob::ProcessExpectCTHeader() {
831 DCHECK(response_info_);
832 TransportSecurityState* security_state =
833 request_->context()->transport_security_state();
834 const SSLInfo& ssl_info = response_info_->ssl_info;
835
836 // Only accept Expect CT headers on HTTPS connections that have no
837 // certificate errors.
838 if (!ssl_info.is_valid() || IsCertStatusError(ssl_info.cert_status) ||
839 !security_state) {
840 return;
841 }
842
estark1614475f2016-03-10 03:46:47843 HttpResponseHeaders* headers = GetResponseHeaders();
844 std::string value;
Emily Stark4cfecf072017-08-08 01:05:51845 if (headers->GetNormalizedHeader("Expect-CT", &value)) {
estark1614475f2016-03-10 03:46:47846 security_state->ProcessExpectCTHeader(
847 value, HostPortPair::FromURL(request_info_.url), ssl_info);
848 }
849}
850
[email protected]5394e422011-01-20 22:07:43851void URLRequestHttpJob::OnStartCompleted(int result) {
Alexandr Ilin33126632018-11-14 14:48:17852 TRACE_EVENT0(NetTracingCategory(), "URLRequestHttpJob::OnStartCompleted");
[email protected]ec23f522011-02-22 21:01:38853 RecordTimer();
854
[email protected]80abdad2014-03-15 00:20:54855 // If the job is done (due to cancellation), can just ignore this
856 // notification.
857 if (done_)
[email protected]5394e422011-01-20 22:07:43858 return;
859
[email protected]3b23a222013-05-15 21:33:25860 receive_headers_end_ = base::TimeTicks::Now();
861
[email protected]ef2bf422012-05-11 03:27:09862 const URLRequestContext* context = request_->context();
863
Ryan Sleevi19a7bde2017-11-22 06:51:39864 if (transaction_ && transaction_->GetResponseInfo()) {
865 const SSLInfo& ssl_info = transaction_->GetResponseInfo()->ssl_info;
866 if (!IsCertificateError(result) ||
867 (IsCertStatusError(ssl_info.cert_status) &&
868 IsCertStatusMinorError(ssl_info.cert_status))) {
869 LogTrustAnchor(ssl_info.public_key_hashes);
870 }
Emily Stark8b411de02017-11-23 20:21:27871
872 RecordCTHistograms(ssl_info);
Ryan Sleevi19a7bde2017-11-22 06:51:39873 }
874
[email protected]5394e422011-01-20 22:07:43875 if (result == OK) {
[email protected]d8fc4722014-06-13 13:17:15876 if (transaction_ && transaction_->GetResponseInfo()) {
877 SetProxyServer(transaction_->GetResponseInfo()->proxy_server);
878 }
[email protected]ea8141e2011-10-05 13:12:51879 scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders();
hiroshigecb76caa4c52015-12-22 07:50:25880
[email protected]cc05edc2013-03-08 18:04:41881 if (network_delegate()) {
[email protected]ea8141e2011-10-05 13:12:51882 // Note that |this| may not be deleted until
mmenked3a02b32016-11-16 20:21:32883 // |URLRequestHttpJob::OnHeadersReceivedCallback()| or
[email protected]ea8141e2011-10-05 13:12:51884 // |NetworkDelegate::URLRequestDestroyed()| has been called.
David Benjamin9776ca22018-06-13 00:00:15885 OnCallToDelegate(NetLogEventType::NETWORK_DELEGATE_HEADERS_RECEIVED);
[email protected]5f714132014-03-26 10:41:16886 allowed_unsafe_redirect_url_ = GURL();
mmenked3a02b32016-11-16 20:21:32887 // The NetworkDelegate must watch for OnRequestDestroyed and not modify
888 // any of the arguments or invoke the callback after it's called. Not
889 // using a WeakPtr here because it's not enough, the consumer has to watch
890 // for destruction regardless, due to the pointer parameters.
[email protected]cc05edc2013-03-08 18:04:41891 int error = network_delegate()->NotifyHeadersReceived(
David Benjamind1f287bf2018-06-12 01:57:20892 request_,
893 base::BindOnce(&URLRequestHttpJob::OnHeadersReceivedCallback,
894 base::Unretained(this)),
mmenked3a02b32016-11-16 20:21:32895 headers.get(), &override_response_headers_,
[email protected]5f714132014-03-26 10:41:16896 &allowed_unsafe_redirect_url_);
ttuttle859dc7a2015-04-23 19:42:29897 if (error != OK) {
898 if (error == ERR_IO_PENDING) {
[email protected]ea8141e2011-10-05 13:12:51899 awaiting_callback_ = true;
[email protected]ea8141e2011-10-05 13:12:51900 } else {
[email protected]55b8a6c12012-06-13 22:03:42901 std::string source("delegate");
mikecirone8b85c432016-09-08 19:11:00902 request_->net_log().AddEvent(
903 NetLogEventType::CANCELLED,
904 NetLog::StringCallback("source", &source));
[email protected]abe1c4a2013-10-25 19:28:51905 OnCallToDelegateComplete();
[email protected]ea8141e2011-10-05 13:12:51906 NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, error));
907 }
908 return;
909 }
910 }
nharperbafc20f2016-03-25 00:40:17911 if (transaction_ && transaction_->GetResponseInfo()) {
912 LogChannelIDAndCookieStores(request_->url(), request_->context(),
913 transaction_->GetResponseInfo()->ssl_info);
914 }
[email protected]ea8141e2011-10-05 13:12:51915
ttuttle859dc7a2015-04-23 19:42:29916 SaveCookiesAndNotifyHeadersComplete(OK);
[email protected]e5624f02011-09-27 19:43:53917 } else if (IsCertificateError(result)) {
[email protected]6061c142013-10-21 15:13:34918 // We encountered an SSL certificate error.
rsleevi9545d342016-06-21 03:17:37919 // Maybe overridable, maybe not. Ask the delegate to decide.
920 TransportSecurityState* state = context->transport_security_state();
921 NotifySSLCertificateError(
922 transaction_->GetResponseInfo()->ssl_info,
923 state->ShouldSSLErrorsBeFatal(request_info_.url.host()));
[email protected]5394e422011-01-20 22:07:43924 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
[email protected]a83dd332011-07-13 10:41:01925 NotifyCertificateRequested(
[email protected]90499482013-06-01 00:39:50926 transaction_->GetResponseInfo()->cert_request_info.get());
[email protected]5394e422011-01-20 22:07:43927 } else {
[email protected]419704c2014-01-14 11:18:06928 // Even on an error, there may be useful information in the response
929 // info (e.g. whether there's a cached copy).
930 if (transaction_.get())
931 response_info_ = transaction_->GetResponseInfo();
[email protected]5394e422011-01-20 22:07:43932 NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, result));
933 }
934}
935
[email protected]ea8141e2011-10-05 13:12:51936void URLRequestHttpJob::OnHeadersReceivedCallback(int result) {
[email protected]ea8141e2011-10-05 13:12:51937 awaiting_callback_ = false;
[email protected]9045b8822012-01-13 20:35:35938
939 // Check that there are no callbacks to already canceled requests.
940 DCHECK_NE(URLRequestStatus::CANCELED, GetStatus().status());
941
[email protected]ea8141e2011-10-05 13:12:51942 SaveCookiesAndNotifyHeadersComplete(result);
943}
944
[email protected]5394e422011-01-20 22:07:43945void URLRequestHttpJob::OnReadCompleted(int result) {
Alexandr Ilin33126632018-11-14 14:48:17946 TRACE_EVENT0(NetTracingCategory(), "URLRequestHttpJob::OnReadCompleted");
[email protected]5394e422011-01-20 22:07:43947 read_in_progress_ = false;
948
xunjieli26ede962015-11-23 19:39:13949 DCHECK_NE(ERR_IO_PENDING, result);
950
[email protected]f001bd6a2011-12-08 04:31:37951 if (ShouldFixMismatchedContentLength(result))
[email protected]5543cbb2012-04-20 16:35:23952 result = OK;
[email protected]f001bd6a2011-12-08 04:31:37953
xunjieli26ede962015-11-23 19:39:13954 // EOF or error, done with this job.
955 if (result <= 0)
956 DoneWithRequest(FINISHED);
[email protected]5394e422011-01-20 22:07:43957
xunjieli26ede962015-11-23 19:39:13958 ReadRawDataComplete(result);
[email protected]5394e422011-01-20 22:07:43959}
960
[email protected]5394e422011-01-20 22:07:43961void URLRequestHttpJob::RestartTransactionWithAuth(
[email protected]f3cf9802011-10-28 18:44:58962 const AuthCredentials& credentials) {
963 auth_credentials_ = credentials;
[email protected]5394e422011-01-20 22:07:43964
965 // These will be reset in OnStartCompleted.
David Benjamin0bda12f2018-02-07 19:58:45966 response_info_ = nullptr;
967 override_response_headers_ = nullptr; // See https://crbug.com/801237.
[email protected]3b23a222013-05-15 21:33:25968 receive_headers_end_ = base::TimeTicks();
[email protected]5394e422011-01-20 22:07:43969
[email protected]ec23f522011-02-22 21:01:38970 ResetTimer();
971
[email protected]5394e422011-01-20 22:07:43972 // Update the cookies, since the cookie store may have been updated from the
973 // headers in the 401/407. Since cookies were already appended to
974 // extra_headers, we need to strip them out before adding them again.
[email protected]ea8141e2011-10-05 13:12:51975 request_info_.extra_headers.RemoveHeader(HttpRequestHeaders::kCookie);
[email protected]5394e422011-01-20 22:07:43976
977 AddCookieHeaderAndStart();
978}
979
[email protected]0736d9e2012-11-28 19:50:40980void URLRequestHttpJob::SetUpload(UploadDataStream* upload) {
[email protected]5394e422011-01-20 22:07:43981 DCHECK(!transaction_.get()) << "cannot change once started";
[email protected]0736d9e2012-11-28 19:50:40982 request_info_.upload_data_stream = upload;
[email protected]5394e422011-01-20 22:07:43983}
984
985void URLRequestHttpJob::SetExtraRequestHeaders(
986 const HttpRequestHeaders& headers) {
987 DCHECK(!transaction_.get()) << "cannot change once started";
988 request_info_.extra_headers.CopyFrom(headers);
989}
990
[email protected]5394e422011-01-20 22:07:43991LoadState URLRequestHttpJob::GetLoadState() const {
992 return transaction_.get() ?
993 transaction_->GetLoadState() : LOAD_STATE_IDLE;
994}
995
[email protected]5394e422011-01-20 22:07:43996bool URLRequestHttpJob::GetMimeType(std::string* mime_type) const {
997 DCHECK(transaction_.get());
998
999 if (!response_info_)
1000 return false;
1001
ellyjones0e9d5e82015-02-17 23:06:281002 HttpResponseHeaders* headers = GetResponseHeaders();
1003 if (!headers)
1004 return false;
1005 return headers->GetMimeType(mime_type);
[email protected]5394e422011-01-20 22:07:431006}
1007
1008bool URLRequestHttpJob::GetCharset(std::string* charset) {
1009 DCHECK(transaction_.get());
1010
1011 if (!response_info_)
1012 return false;
1013
[email protected]ea8141e2011-10-05 13:12:511014 return GetResponseHeaders()->GetCharset(charset);
[email protected]5394e422011-01-20 22:07:431015}
1016
1017void URLRequestHttpJob::GetResponseInfo(HttpResponseInfo* info) {
[email protected]ea8141e2011-10-05 13:12:511018 if (response_info_) {
[email protected]419704c2014-01-14 11:18:061019 DCHECK(transaction_.get());
1020
[email protected]5394e422011-01-20 22:07:431021 *info = *response_info_;
[email protected]90499482013-06-01 00:39:501022 if (override_response_headers_.get())
[email protected]ea8141e2011-10-05 13:12:511023 info->headers = override_response_headers_;
1024 }
[email protected]5394e422011-01-20 22:07:431025}
1026
[email protected]58e32bb2013-01-21 18:23:251027void URLRequestHttpJob::GetLoadTimingInfo(
1028 LoadTimingInfo* load_timing_info) const {
[email protected]3b23a222013-05-15 21:33:251029 // If haven't made it far enough to receive any headers, don't return
rdsmith81f607562014-11-21 18:35:161030 // anything. This makes for more consistent behavior in the case of errors.
[email protected]3b23a222013-05-15 21:33:251031 if (!transaction_ || receive_headers_end_.is_null())
1032 return;
1033 if (transaction_->GetLoadTimingInfo(load_timing_info))
1034 load_timing_info->receive_headers_end = receive_headers_end_;
[email protected]58e32bb2013-01-21 18:23:251035}
1036
Tsuyoshi Horo01faed62019-02-20 22:11:371037bool URLRequestHttpJob::GetTransactionRemoteEndpoint(
1038 IPEndPoint* endpoint) const {
ttuttled9dbc652015-09-29 20:00:591039 if (!transaction_)
1040 return false;
1041
1042 return transaction_->GetRemoteEndpoint(endpoint);
1043}
1044
[email protected]5394e422011-01-20 22:07:431045int URLRequestHttpJob::GetResponseCode() const {
1046 DCHECK(transaction_.get());
1047
1048 if (!response_info_)
1049 return -1;
1050
[email protected]ea8141e2011-10-05 13:12:511051 return GetResponseHeaders()->response_code();
[email protected]5394e422011-01-20 22:07:431052}
1053
zhongyi48704c182015-12-07 07:52:021054void URLRequestHttpJob::PopulateNetErrorDetails(
1055 NetErrorDetails* details) const {
1056 if (!transaction_)
1057 return;
1058 return transaction_->PopulateNetErrorDetails(details);
1059}
1060
xunjieli28a18772016-10-25 15:30:061061std::unique_ptr<SourceStream> URLRequestHttpJob::SetUpSourceStream() {
[email protected]5394e422011-01-20 22:07:431062 DCHECK(transaction_.get());
1063 if (!response_info_)
Bacek8f371552016-05-12 01:13:491064 return nullptr;
[email protected]5394e422011-01-20 22:07:431065
xunjieli28a18772016-10-25 15:30:061066 std::unique_ptr<SourceStream> upstream = URLRequestJob::SetUpSourceStream();
[email protected]ea8141e2011-10-05 13:12:511067 HttpResponseHeaders* headers = GetResponseHeaders();
xunjieli28a18772016-10-25 15:30:061068 std::string type;
1069 std::vector<SourceStream::SourceType> types;
olli.raulaee489a52016-01-25 08:37:101070 size_t iter = 0;
xunjieli28a18772016-10-25 15:30:061071 while (headers->EnumerateHeader(&iter, "Content-Encoding", &type)) {
eustasc7d27da2017-04-06 10:33:201072 SourceStream::SourceType source_type =
1073 FilterSourceStream::ParseEncodingType(type);
eustasc7d27da2017-04-06 10:33:201074 switch (source_type) {
1075 case SourceStream::TYPE_BROTLI:
1076 case SourceStream::TYPE_DEFLATE:
1077 case SourceStream::TYPE_GZIP:
eustasc7d27da2017-04-06 10:33:201078 types.push_back(source_type);
1079 break;
1080 case SourceStream::TYPE_NONE:
1081 // Identity encoding type. Pass through raw response body.
1082 return upstream;
Helen Li666c0682017-09-15 19:57:051083 case SourceStream::TYPE_UNKNOWN:
eustasc7d27da2017-04-06 10:33:201084 // Unknown encoding type. Pass through raw response body.
1085 // Despite of reporting to UMA, request will not be canceled; though
1086 // it is expected that user will see malformed / garbage response.
1087 FilterSourceStream::ReportContentDecodingFailed(
1088 FilterSourceStream::TYPE_UNKNOWN);
1089 return upstream;
Helen Li666c0682017-09-15 19:57:051090 case SourceStream::TYPE_GZIP_FALLBACK_DEPRECATED:
1091 case SourceStream::TYPE_SDCH_DEPRECATED:
1092 case SourceStream::TYPE_SDCH_POSSIBLE_DEPRECATED:
1093 case SourceStream::TYPE_REJECTED:
1094 case SourceStream::TYPE_INVALID:
1095 case SourceStream::TYPE_MAX:
1096 NOTREACHED();
1097 return nullptr;
eustasc7d27da2017-04-06 10:33:201098 }
[email protected]5394e422011-01-20 22:07:431099 }
1100
jdoerrie22a91d8b92018-10-05 08:43:261101 for (auto r_iter = types.rbegin(); r_iter != types.rend(); ++r_iter) {
xunjieli28a18772016-10-25 15:30:061102 std::unique_ptr<FilterSourceStream> downstream;
1103 SourceStream::SourceType type = *r_iter;
1104 switch (type) {
1105 case SourceStream::TYPE_BROTLI:
1106 downstream = CreateBrotliSourceStream(std::move(upstream));
1107 break;
xunjieli28a18772016-10-25 15:30:061108 case SourceStream::TYPE_GZIP:
1109 case SourceStream::TYPE_DEFLATE:
xunjieli28a18772016-10-25 15:30:061110 downstream = GzipSourceStream::Create(std::move(upstream), type);
1111 break;
Helen Li666c0682017-09-15 19:57:051112 case SourceStream::TYPE_GZIP_FALLBACK_DEPRECATED:
1113 case SourceStream::TYPE_SDCH_DEPRECATED:
1114 case SourceStream::TYPE_SDCH_POSSIBLE_DEPRECATED:
xunjieli28a18772016-10-25 15:30:061115 case SourceStream::TYPE_NONE:
1116 case SourceStream::TYPE_INVALID:
eustasc7d27da2017-04-06 10:33:201117 case SourceStream::TYPE_REJECTED:
1118 case SourceStream::TYPE_UNKNOWN:
xunjieli28a18772016-10-25 15:30:061119 case SourceStream::TYPE_MAX:
1120 NOTREACHED();
1121 return nullptr;
1122 }
1123 if (downstream == nullptr)
1124 return nullptr;
1125 upstream = std::move(downstream);
1126 }
1127
1128 return upstream;
[email protected]5394e422011-01-20 22:07:431129}
1130
[email protected]f878230e2014-04-03 15:36:141131bool URLRequestHttpJob::CopyFragmentOnRedirect(const GURL& location) const {
1132 // Allow modification of reference fragments by default, unless
1133 // |allowed_unsafe_redirect_url_| is set and equal to the redirect URL.
1134 // When this is the case, we assume that the network delegate has set the
1135 // desired redirect URL (with or without fragment), so it must not be changed
1136 // any more.
1137 return !allowed_unsafe_redirect_url_.is_valid() ||
1138 allowed_unsafe_redirect_url_ != location;
1139}
1140
[email protected]5394e422011-01-20 22:07:431141bool URLRequestHttpJob::IsSafeRedirect(const GURL& location) {
[email protected]e0f35c92013-05-08 16:04:341142 // HTTP is always safe.
1143 // TODO(pauljensen): Remove once crbug.com/146591 is fixed.
1144 if (location.is_valid() &&
1145 (location.scheme() == "http" || location.scheme() == "https")) {
[email protected]5394e422011-01-20 22:07:431146 return true;
[email protected]5394e422011-01-20 22:07:431147 }
[email protected]f878230e2014-04-03 15:36:141148 // Delegates may mark a URL as safe for redirection.
1149 if (allowed_unsafe_redirect_url_.is_valid() &&
1150 allowed_unsafe_redirect_url_ == location) {
1151 return true;
[email protected]5f714132014-03-26 10:41:161152 }
[email protected]e0f35c92013-05-08 16:04:341153 // Query URLRequestJobFactory as to whether |location| would be safe to
1154 // redirect to.
1155 return request_->context()->job_factory() &&
1156 request_->context()->job_factory()->IsSafeRedirectTarget(location);
[email protected]5394e422011-01-20 22:07:431157}
1158
1159bool URLRequestHttpJob::NeedsAuth() {
1160 int code = GetResponseCode();
1161 if (code == -1)
1162 return false;
1163
rdsmith81f607562014-11-21 18:35:161164 // Check if we need either Proxy or WWW Authentication. This could happen
[email protected]5394e422011-01-20 22:07:431165 // because we either provided no auth info, or provided incorrect info.
1166 switch (code) {
1167 case 407:
1168 if (proxy_auth_state_ == AUTH_STATE_CANCELED)
1169 return false;
1170 proxy_auth_state_ = AUTH_STATE_NEED_AUTH;
1171 return true;
1172 case 401:
1173 if (server_auth_state_ == AUTH_STATE_CANCELED)
1174 return false;
1175 server_auth_state_ = AUTH_STATE_NEED_AUTH;
1176 return true;
1177 }
1178 return false;
1179}
1180
1181void URLRequestHttpJob::GetAuthChallengeInfo(
1182 scoped_refptr<AuthChallengeInfo>* result) {
1183 DCHECK(transaction_.get());
1184 DCHECK(response_info_);
1185
1186 // sanity checks:
1187 DCHECK(proxy_auth_state_ == AUTH_STATE_NEED_AUTH ||
1188 server_auth_state_ == AUTH_STATE_NEED_AUTH);
[email protected]9094b602012-02-27 21:44:581189 DCHECK((GetResponseHeaders()->response_code() == HTTP_UNAUTHORIZED) ||
1190 (GetResponseHeaders()->response_code() ==
1191 HTTP_PROXY_AUTHENTICATION_REQUIRED));
[email protected]5394e422011-01-20 22:07:431192
1193 *result = response_info_->auth_challenge;
1194}
1195
[email protected]f3cf9802011-10-28 18:44:581196void URLRequestHttpJob::SetAuth(const AuthCredentials& credentials) {
[email protected]5394e422011-01-20 22:07:431197 DCHECK(transaction_.get());
1198
1199 // Proxy gets set first, then WWW.
1200 if (proxy_auth_state_ == AUTH_STATE_NEED_AUTH) {
1201 proxy_auth_state_ = AUTH_STATE_HAVE_AUTH;
1202 } else {
[email protected]dd29bcd72011-03-24 00:03:441203 DCHECK_EQ(server_auth_state_, AUTH_STATE_NEED_AUTH);
[email protected]5394e422011-01-20 22:07:431204 server_auth_state_ = AUTH_STATE_HAVE_AUTH;
1205 }
1206
[email protected]f3cf9802011-10-28 18:44:581207 RestartTransactionWithAuth(credentials);
[email protected]5394e422011-01-20 22:07:431208}
1209
1210void URLRequestHttpJob::CancelAuth() {
1211 // Proxy gets set first, then WWW.
1212 if (proxy_auth_state_ == AUTH_STATE_NEED_AUTH) {
1213 proxy_auth_state_ = AUTH_STATE_CANCELED;
1214 } else {
[email protected]dd29bcd72011-03-24 00:03:441215 DCHECK_EQ(server_auth_state_, AUTH_STATE_NEED_AUTH);
[email protected]5394e422011-01-20 22:07:431216 server_auth_state_ = AUTH_STATE_CANCELED;
1217 }
1218
1219 // These will be reset in OnStartCompleted.
1220 response_info_ = NULL;
[email protected]3b23a222013-05-15 21:33:251221 receive_headers_end_ = base::TimeTicks::Now();
David Benjamin0bda12f2018-02-07 19:58:451222 // TODO(davidben,mmenke): We should either reset override_response_headers_
1223 // here or not call NotifyHeadersReceived a second time on the same response
1224 // headers. See https://crbug.com/810063.
[email protected]5394e422011-01-20 22:07:431225
[email protected]ec23f522011-02-22 21:01:381226 ResetTimer();
1227
[email protected]5394e422011-01-20 22:07:431228 // OK, let the consumer read the error page...
1229 //
1230 // Because we set the AUTH_STATE_CANCELED flag, NeedsAuth will return false,
1231 // which will cause the consumer to receive OnResponseStarted instead of
1232 // OnAuthRequired.
1233 //
1234 // We have to do this via InvokeLater to avoid "recursing" the consumer.
1235 //
skyostil4891b25b2015-06-11 11:43:451236 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf4fe5172019-02-15 18:53:491237 FROM_HERE, base::BindOnce(&URLRequestHttpJob::OnStartCompleted,
1238 weak_factory_.GetWeakPtr(), OK));
[email protected]5394e422011-01-20 22:07:431239}
1240
1241void URLRequestHttpJob::ContinueWithCertificate(
mattm436ccfe2017-06-19 20:24:081242 scoped_refptr<X509Certificate> client_cert,
1243 scoped_refptr<SSLPrivateKey> client_private_key) {
David Benjamin0bda12f2018-02-07 19:58:451244 DCHECK(transaction_);
[email protected]5394e422011-01-20 22:07:431245
1246 DCHECK(!response_info_) << "should not have a response yet";
David Benjamin0bda12f2018-02-07 19:58:451247 DCHECK(!override_response_headers_);
[email protected]3b23a222013-05-15 21:33:251248 receive_headers_end_ = base::TimeTicks();
[email protected]5394e422011-01-20 22:07:431249
[email protected]ec23f522011-02-22 21:01:381250 ResetTimer();
1251
mmenked3a02b32016-11-16 20:21:321252 int rv = transaction_->RestartWithCertificate(
mattm436ccfe2017-06-19 20:24:081253 std::move(client_cert), std::move(client_private_key),
mmenked3a02b32016-11-16 20:21:321254 base::Bind(&URLRequestHttpJob::OnStartCompleted, base::Unretained(this)));
[email protected]5394e422011-01-20 22:07:431255 if (rv == ERR_IO_PENDING)
1256 return;
1257
1258 // The transaction started synchronously, but we need to notify the
1259 // URLRequest delegate via the message loop.
skyostil4891b25b2015-06-11 11:43:451260 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf4fe5172019-02-15 18:53:491261 FROM_HERE, base::BindOnce(&URLRequestHttpJob::OnStartCompleted,
1262 weak_factory_.GetWeakPtr(), rv));
[email protected]5394e422011-01-20 22:07:431263}
1264
1265void URLRequestHttpJob::ContinueDespiteLastError() {
1266 // If the transaction was destroyed, then the job was cancelled.
1267 if (!transaction_.get())
1268 return;
1269
1270 DCHECK(!response_info_) << "should not have a response yet";
David Benjamin0bda12f2018-02-07 19:58:451271 DCHECK(!override_response_headers_);
[email protected]3b23a222013-05-15 21:33:251272 receive_headers_end_ = base::TimeTicks();
[email protected]5394e422011-01-20 22:07:431273
[email protected]ec23f522011-02-22 21:01:381274 ResetTimer();
1275
mmenked3a02b32016-11-16 20:21:321276 int rv = transaction_->RestartIgnoringLastError(
1277 base::Bind(&URLRequestHttpJob::OnStartCompleted, base::Unretained(this)));
[email protected]5394e422011-01-20 22:07:431278 if (rv == ERR_IO_PENDING)
1279 return;
1280
1281 // The transaction started synchronously, but we need to notify the
1282 // URLRequest delegate via the message loop.
skyostil4891b25b2015-06-11 11:43:451283 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf4fe5172019-02-15 18:53:491284 FROM_HERE, base::BindOnce(&URLRequestHttpJob::OnStartCompleted,
1285 weak_factory_.GetWeakPtr(), rv));
[email protected]5394e422011-01-20 22:07:431286}
1287
[email protected]f001bd6a2011-12-08 04:31:371288bool URLRequestHttpJob::ShouldFixMismatchedContentLength(int rv) const {
1289 // Some servers send the body compressed, but specify the content length as
rdsmith81f607562014-11-21 18:35:161290 // the uncompressed size. Although this violates the HTTP spec we want to
[email protected]f001bd6a2011-12-08 04:31:371291 // support it (as IE and FireFox do), but *only* for an exact match.
1292 // See http://crbug.com/79694.
ttuttle859dc7a2015-04-23 19:42:291293 if (rv == ERR_CONTENT_LENGTH_MISMATCH ||
1294 rv == ERR_INCOMPLETE_CHUNKED_ENCODING) {
mmenked3a02b32016-11-16 20:21:321295 if (request_->response_headers()) {
Avi Drissman13fc8932015-12-20 04:40:461296 int64_t expected_length =
1297 request_->response_headers()->GetContentLength();
pkastingf5279482016-07-27 02:18:201298 VLOG(1) << __func__ << "() \"" << request_->url().spec() << "\""
[email protected]f001bd6a2011-12-08 04:31:371299 << " content-length = " << expected_length
1300 << " pre total = " << prefilter_bytes_read()
1301 << " post total = " << postfilter_bytes_read();
1302 if (postfilter_bytes_read() == expected_length) {
1303 // Clear the error.
1304 return true;
1305 }
1306 }
1307 }
1308 return false;
1309}
1310
xunjieli26ede962015-11-23 19:39:131311int URLRequestHttpJob::ReadRawData(IOBuffer* buf, int buf_size) {
[email protected]5394e422011-01-20 22:07:431312 DCHECK_NE(buf_size, 0);
[email protected]5394e422011-01-20 22:07:431313 DCHECK(!read_in_progress_);
1314
[email protected]49639fa2011-12-20 23:22:411315 int rv = transaction_->Read(
1316 buf, buf_size,
1317 base::Bind(&URLRequestHttpJob::OnReadCompleted, base::Unretained(this)));
[email protected]85c1dce2011-07-06 12:01:291318
[email protected]f001bd6a2011-12-08 04:31:371319 if (ShouldFixMismatchedContentLength(rv))
xunjieli26ede962015-11-23 19:39:131320 rv = OK;
[email protected]f001bd6a2011-12-08 04:31:371321
xunjieli26ede962015-11-23 19:39:131322 if (rv == 0 || (rv < 0 && rv != ERR_IO_PENDING))
1323 DoneWithRequest(FINISHED);
[email protected]5394e422011-01-20 22:07:431324
xunjieli26ede962015-11-23 19:39:131325 if (rv == ERR_IO_PENDING)
[email protected]5394e422011-01-20 22:07:431326 read_in_progress_ = true;
[email protected]5394e422011-01-20 22:07:431327
xunjieli26ede962015-11-23 19:39:131328 return rv;
[email protected]5394e422011-01-20 22:07:431329}
1330
1331void URLRequestHttpJob::StopCaching() {
1332 if (transaction_.get())
1333 transaction_->StopCaching();
1334}
1335
[email protected]79e1fd62013-06-20 06:50:041336bool URLRequestHttpJob::GetFullRequestHeaders(
1337 HttpRequestHeaders* headers) const {
1338 if (!transaction_)
1339 return false;
1340
1341 return transaction_->GetFullRequestHeaders(headers);
1342}
1343
Avi Drissman13fc8932015-12-20 04:40:461344int64_t URLRequestHttpJob::GetTotalReceivedBytes() const {
sclittlece72c482015-08-24 20:20:591345 int64_t total_received_bytes =
1346 total_received_bytes_from_previous_transactions_;
1347 if (transaction_)
1348 total_received_bytes += transaction_->GetTotalReceivedBytes();
1349 return total_received_bytes;
[email protected]71e5ff8f2014-01-13 09:44:041350}
1351
sclittlefb249892015-09-10 21:33:221352int64_t URLRequestHttpJob::GetTotalSentBytes() const {
1353 int64_t total_sent_bytes = total_sent_bytes_from_previous_transactions_;
1354 if (transaction_)
1355 total_sent_bytes += transaction_->GetTotalSentBytes();
1356 return total_sent_bytes;
1357}
1358
[email protected]5c04f722011-08-12 17:52:471359void URLRequestHttpJob::DoneReading() {
[email protected]e50efea2014-03-24 18:41:001360 if (transaction_) {
[email protected]5c04f722011-08-12 17:52:471361 transaction_->DoneReading();
[email protected]e50efea2014-03-24 18:41:001362 }
1363 DoneWithRequest(FINISHED);
1364}
1365
1366void URLRequestHttpJob::DoneReadingRedirectResponse() {
1367 if (transaction_) {
1368 if (transaction_->GetResponseInfo()->headers->IsRedirect(NULL)) {
1369 // If the original headers indicate a redirect, go ahead and cache the
1370 // response, even if the |override_response_headers_| are a redirect to
1371 // another location.
1372 transaction_->DoneReading();
1373 } else {
1374 // Otherwise, |override_response_headers_| must be non-NULL and contain
1375 // bogus headers indicating a redirect.
dchengc2e01e82014-08-27 00:24:421376 DCHECK(override_response_headers_.get());
[email protected]e50efea2014-03-24 18:41:001377 DCHECK(override_response_headers_->IsRedirect(NULL));
1378 transaction_->StopCaching();
1379 }
1380 }
[email protected]5c04f722011-08-12 17:52:471381 DoneWithRequest(FINISHED);
1382}
1383
Tsuyoshi Horo01faed62019-02-20 22:11:371384IPEndPoint URLRequestHttpJob::GetResponseRemoteEndpoint() const {
1385 return response_info_ ? response_info_->remote_endpoint : IPEndPoint();
[email protected]6d81b482011-02-22 19:47:191386}
1387
[email protected]ec23f522011-02-22 21:01:381388void URLRequestHttpJob::RecordTimer() {
1389 if (request_creation_time_.is_null()) {
1390 NOTREACHED()
1391 << "The same transaction shouldn't start twice without new timing.";
1392 return;
1393 }
1394
[email protected]320a29f12011-03-21 14:47:411395 base::TimeDelta to_start = base::Time::Now() - request_creation_time_;
[email protected]ec23f522011-02-22 21:01:381396 request_creation_time_ = base::Time();
[email protected]8684a8812011-03-22 13:59:381397
[email protected]5c68d692011-08-24 04:59:411398 UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpTimeToFirstByte", to_start);
mmenke1beda3d2016-07-22 03:33:451399 if (request_info_.upload_data_stream &&
1400 request_info_.upload_data_stream->size() > 1024 * 1024) {
1401 UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpTimeToFirstByte.LargeUpload", to_start);
1402 }
[email protected]ec23f522011-02-22 21:01:381403}
1404
1405void URLRequestHttpJob::ResetTimer() {
1406 if (!request_creation_time_.is_null()) {
1407 NOTREACHED()
1408 << "The timer was reset before it was recorded.";
1409 return;
1410 }
1411 request_creation_time_ = base::Time::Now();
1412}
1413
[email protected]dd29bcd72011-03-24 00:03:441414void URLRequestHttpJob::UpdatePacketReadTimes() {
1415 if (!packet_timing_enabled_)
1416 return;
1417
mmenkebbf19be22015-04-11 02:44:481418 DCHECK_GT(prefilter_bytes_read(), bytes_observed_in_packets_);
[email protected]dd29bcd72011-03-24 00:03:441419
[email protected]006ce1a2014-07-30 14:41:231420 base::Time now(base::Time::Now());
[email protected]dd29bcd72011-03-24 00:03:441421 if (!bytes_observed_in_packets_)
[email protected]006ce1a2014-07-30 14:41:231422 request_time_snapshot_ = now;
1423 final_packet_time_ = now;
[email protected]dd29bcd72011-03-24 00:03:441424
mmenkebbf19be22015-04-11 02:44:481425 bytes_observed_in_packets_ = prefilter_bytes_read();
[email protected]dd29bcd72011-03-24 00:03:441426}
1427
Andrey Kosyakov83a6eee2017-08-14 19:20:041428void URLRequestHttpJob::SetRequestHeadersCallback(
1429 RequestHeadersCallback callback) {
1430 DCHECK(!transaction_);
1431 DCHECK(!request_headers_callback_);
1432 request_headers_callback_ = std::move(callback);
1433}
1434
Andrey Kosyakov2e893e62017-08-31 17:00:521435void URLRequestHttpJob::SetResponseHeadersCallback(
1436 ResponseHeadersCallback callback) {
1437 DCHECK(!transaction_);
1438 DCHECK(!response_headers_callback_);
1439 response_headers_callback_ = std::move(callback);
1440}
1441
[email protected]bbaea8f2011-06-24 00:11:011442void URLRequestHttpJob::RecordPerfHistograms(CompletionCause reason) {
1443 if (start_time_.is_null())
1444 return;
1445
1446 base::TimeDelta total_time = base::TimeTicks::Now() - start_time_;
1447 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTime", total_time);
1448
1449 if (reason == FINISHED) {
Devdeep Ray0c6966d2017-07-14 00:58:221450 UmaHistogramTimes(
1451 base::StringPrintf("Net.HttpJob.TotalTimeSuccess.Priority%d",
1452 request()->priority()),
1453 total_time);
[email protected]bbaea8f2011-06-24 00:11:011454 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeSuccess", total_time);
1455 } else {
1456 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeCancel", total_time);
1457 }
1458
[email protected]4b4d20242012-02-23 18:27:461459 if (response_info_) {
rtennetie55c4b72015-08-03 21:48:351460 // QUIC (by default) supports https scheme only, thus track https URLs only
1461 // for QUIC.
1462 bool is_https_google = request() && request()->url().SchemeIs("https") &&
1463 HasGoogleHost(request()->url());
rtenneti72928bb2015-04-28 18:28:131464 bool used_quic = response_info_->DidUseQuic();
rtennetie55c4b72015-08-03 21:48:351465 if (is_https_google) {
rtenneti72928bb2015-04-28 18:28:131466 if (used_quic) {
rtennetie55c4b72015-08-03 21:48:351467 UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpJob.TotalTime.Secure.Quic",
1468 total_time);
rtenneti72928bb2015-04-28 18:28:131469 }
1470 }
jkarlinded0021b2016-12-05 16:01:061471
1472 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpJob.PrefilterBytesRead",
1473 prefilter_bytes_read(), 1, 50000000, 50);
[email protected]4b4d20242012-02-23 18:27:461474 if (response_info_->was_cached) {
1475 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeCached", total_time);
jkarlinded0021b2016-12-05 16:01:061476 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpJob.PrefilterBytesRead.Cache",
1477 prefilter_bytes_read(), 1, 50000000, 50);
1478
jkarlincc6943d2016-04-25 19:25:351479 if (response_info_->unused_since_prefetch)
Steven Holte6143e642017-06-28 19:47:381480 UMA_HISTOGRAM_COUNTS_1M("Net.Prefetch.HitBytes",
1481 prefilter_bytes_read());
jkarlincc6943d2016-04-25 19:25:351482 } else {
[email protected]4b4d20242012-02-23 18:27:461483 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeNotCached", total_time);
jkarlinded0021b2016-12-05 16:01:061484 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpJob.PrefilterBytesRead.Net",
1485 prefilter_bytes_read(), 1, 50000000, 50);
1486
1487 if (request_info_.load_flags & LOAD_PREFETCH) {
Steven Holte6143e642017-06-28 19:47:381488 UMA_HISTOGRAM_COUNTS_1M("Net.Prefetch.PrefilterBytesReadFromNetwork",
1489 prefilter_bytes_read());
jkarlinded0021b2016-12-05 16:01:061490 }
rtennetie55c4b72015-08-03 21:48:351491 if (is_https_google) {
rtenneti72928bb2015-04-28 18:28:131492 if (used_quic) {
rtennetie55c4b72015-08-03 21:48:351493 UMA_HISTOGRAM_MEDIUM_TIMES(
1494 "Net.HttpJob.TotalTimeNotCached.Secure.Quic", total_time);
rtenneti72928bb2015-04-28 18:28:131495 } else {
rtennetie55c4b72015-08-03 21:48:351496 UMA_HISTOGRAM_MEDIUM_TIMES(
1497 "Net.HttpJob.TotalTimeNotCached.Secure.NotQuic", total_time);
rtenneti72928bb2015-04-28 18:28:131498 }
1499 }
[email protected]b73656ca2011-07-22 17:42:171500 }
[email protected]bbaea8f2011-06-24 00:11:011501 }
1502
1503 start_time_ = base::TimeTicks();
1504}
1505
1506void URLRequestHttpJob::DoneWithRequest(CompletionCause reason) {
1507 if (done_)
1508 return;
1509 done_ = true;
tbansal79ed5cd2015-08-10 18:53:561510
1511 // Notify NetworkQualityEstimator.
mmenke7ce675a2016-11-07 17:08:301512 NetworkQualityEstimator* network_quality_estimator =
1513 request()->context()->network_quality_estimator();
1514 if (network_quality_estimator) {
1515 network_quality_estimator->NotifyRequestCompleted(
1516 *request(), request_->status().error());
tbansal79ed5cd2015-08-10 18:53:561517 }
1518
[email protected]bbaea8f2011-06-24 00:11:011519 RecordPerfHistograms(reason);
mmenke7ce675a2016-11-07 17:08:301520 request()->set_received_response_content_length(prefilter_bytes_read());
[email protected]bbaea8f2011-06-24 00:11:011521}
1522
[email protected]ea8141e2011-10-05 13:12:511523HttpResponseHeaders* URLRequestHttpJob::GetResponseHeaders() const {
1524 DCHECK(transaction_.get());
1525 DCHECK(transaction_->GetResponseInfo());
1526 return override_response_headers_.get() ?
[email protected]90499482013-06-01 00:39:501527 override_response_headers_.get() :
1528 transaction_->GetResponseInfo()->headers.get();
[email protected]ea8141e2011-10-05 13:12:511529}
1530
1531void URLRequestHttpJob::NotifyURLRequestDestroyed() {
1532 awaiting_callback_ = false;
tbansal80a52162016-05-20 17:55:041533
1534 // Notify NetworkQualityEstimator.
mmenke7ce675a2016-11-07 17:08:301535 NetworkQualityEstimator* network_quality_estimator =
1536 request()->context()->network_quality_estimator();
1537 if (network_quality_estimator)
1538 network_quality_estimator->NotifyURLRequestDestroyed(*request());
[email protected]ea8141e2011-10-05 13:12:511539}
1540
[email protected]4f5656c62010-12-13 10:47:091541} // namespace net