blob: 4277ca41b234e1245303b098138f96d18fe913cf [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
Eric Lawrencef814f5b22019-10-04 01:52:437#include <algorithm>
8#include <utility>
mmenked3a02b32016-11-16 20:21:329#include <vector>
10
[email protected]4ed2755f2008-12-15 09:01:3311#include "base/base_switches.h"
[email protected]4f9e5c82011-11-17 16:04:5612#include "base/bind.h"
[email protected]084262c2011-12-01 21:12:4713#include "base/bind_helpers.h"
[email protected]4ed2755f2008-12-15 09:01:3314#include "base/command_line.h"
[email protected]39ce5c02008-08-22 04:03:4415#include "base/compiler_specific.h"
[email protected]60889422008-09-23 01:18:1616#include "base/file_version_info.h"
skyostil4891b25b2015-06-11 11:43:4517#include "base/location.h"
Avi Drissman13fc8932015-12-20 04:40:4618#include "base/macros.h"
[email protected]8684a8812011-03-22 13:59:3819#include "base/metrics/field_trial.h"
Devdeep Ray0c6966d2017-07-14 00:58:2220#include "base/metrics/histogram_functions.h"
asvitkinec3c93722015-06-17 14:48:3721#include "base/metrics/histogram_macros.h"
Mike Westfbd44112019-05-08 18:23:3722#include "base/numerics/safe_conversions.h"
Lily Chenb851acc2019-08-07 15:54:4423#include "base/optional.h"
[email protected]5b90b5d2009-04-30 23:06:0124#include "base/rand_util.h"
skyostil4891b25b2015-06-11 11:43:4525#include "base/single_thread_task_runner.h"
[email protected]4dc3ad4f2013-06-11 07:15:5026#include "base/strings/string_util.h"
Devdeep Ray0c6966d2017-07-14 00:58:2227#include "base/strings/stringprintf.h"
gabf767595f2016-05-11 18:50:3528#include "base/threading/thread_task_runner_handle.h"
[email protected]f002abb2013-06-28 02:30:2129#include "base/time/time.h"
ssid6d6b40102016-04-05 18:59:5630#include "base/trace_event/trace_event.h"
estade5e5529d2015-05-21 20:59:1131#include "base/values.h"
Mike Westfbd44112019-05-08 18:23:3732#include "net/base/features.h"
[email protected]6d81b482011-02-22 19:47:1933#include "net/base/host_port_pair.h"
Matt Menked732ea42019-03-08 12:05:0034#include "net/base/http_user_agent_settings.h"
[email protected]b8430722008-09-17 20:05:4435#include "net/base/load_flags.h"
initial.commit586acc5fe2008-07-26 22:42:5236#include "net/base/net_errors.h"
[email protected]636eccd2011-06-28 12:28:0137#include "net/base/network_delegate.h"
Shivani Sharmad81bdd42019-05-23 17:19:5638#include "net/base/network_isolation_key.h"
mkwstf71d0bd2016-03-21 14:15:2439#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
xunjieli0b7f5b62016-12-06 20:43:4840#include "net/base/trace_constants.h"
tfarina7a4a7fd2016-01-20 14:23:4441#include "net/base/url_util.h"
[email protected]6e7845ae2013-03-29 21:48:1142#include "net/cert/cert_status_flags.h"
Emily Stark8b411de02017-11-23 20:21:2743#include "net/cert/ct_policy_status.h"
Ryan Sleevi19a7bde2017-11-22 06:51:3944#include "net/cert/known_roots.h"
Randy Smithe23356c22017-11-14 01:41:5045#include "net/cookies/canonical_cookie.h"
[email protected]dc8313a2014-03-24 21:38:1446#include "net/cookies/cookie_store.h"
Maks Orlovich64e2913d2019-03-05 14:42:5647#include "net/cookies/cookie_util.h"
xunjieli28a18772016-10-25 15:30:0648#include "net/filter/brotli_source_stream.h"
49#include "net/filter/filter_source_stream.h"
50#include "net/filter/gzip_source_stream.h"
xunjieli28a18772016-10-25 15:30:0651#include "net/filter/source_stream.h"
[email protected]262191712014-03-22 00:46:5752#include "net/http/http_content_disposition.h"
[email protected]7a299a92012-10-24 23:54:5053#include "net/http/http_network_session.h"
[email protected]8c76ae22010-04-20 22:15:4354#include "net/http/http_request_headers.h"
[email protected]319d9e6f2009-02-18 19:47:2155#include "net/http/http_response_headers.h"
initial.commit586acc5fe2008-07-26 22:42:5256#include "net/http/http_response_info.h"
[email protected]9094b602012-02-27 21:44:5857#include "net/http/http_status_code.h"
initial.commit586acc5fe2008-07-26 22:42:5258#include "net/http/http_transaction.h"
59#include "net/http/http_transaction_factory.h"
[email protected]0757e7702009-03-27 04:00:2260#include "net/http/http_util.h"
Ryan Hamilton0bed1572018-03-02 19:58:2161#include "net/log/net_log.h"
mikecirone8b85c432016-09-08 19:11:0062#include "net/log/net_log_event_type.h"
Imam Mohammad Bokhary374b339a2019-09-27 16:35:1963#include "net/log/net_log_values.h"
mikecironef22f9812016-10-04 03:40:1964#include "net/log/net_log_with_source.h"
tbansalca83c002016-04-28 20:56:2865#include "net/nqe/network_quality_estimator.h"
Lily Houghton582d4622018-01-22 22:43:4066#include "net/proxy_resolution/proxy_info.h"
Lily Houghtonffe89daa02018-03-09 18:30:0367#include "net/proxy_resolution/proxy_resolution_service.h"
Lily Houghton582d4622018-01-22 22:43:4068#include "net/proxy_resolution/proxy_retry_info.h"
[email protected]536fd0b2013-03-14 17:41:5769#include "net/ssl/ssl_cert_request_info.h"
70#include "net/ssl/ssl_config_service.h"
initial.commit586acc5fe2008-07-26 22:42:5271#include "net/url_request/url_request.h"
[email protected]319d9e6f2009-02-18 19:47:2172#include "net/url_request/url_request_context.h"
initial.commit586acc5fe2008-07-26 22:42:5273#include "net/url_request/url_request_error_job.h"
Thiemo Nagel0793b9c532018-04-18 16:57:5874#include "net/url_request/url_request_http_job_histogram.h"
[email protected]e0f35c92013-05-08 16:04:3475#include "net/url_request/url_request_job_factory.h"
[email protected]06965e02009-09-04 21:36:4276#include "net/url_request/url_request_redirect_job.h"
[email protected]6b3f9642010-11-25 02:29:0677#include "net/url_request/url_request_throttler_manager.h"
Bence Békya5ec55e62018-03-07 14:23:2878#include "net/url_request/websocket_handshake_userdata_key.h"
mkwst8241a122015-10-20 07:15:1079#include "url/origin.h"
initial.commit586acc5fe2008-07-26 22:42:5280
mgershd21d6d142016-12-14 23:06:3681#if defined(OS_ANDROID)
82#include "net/android/network_library.h"
83#endif
84
mkwst202534e32016-01-15 16:07:1585namespace {
86
Eric Lawrencef814f5b22019-10-04 01:52:4387base::Value CookieExcludedNetLogParams(const std::string& operation,
88 const std::string& cookie_name,
89 const std::string& exclusion_reason,
90 net::NetLogCaptureMode capture_mode) {
91 base::Value dict(base::Value::Type::DICTIONARY);
92 dict.SetStringKey("operation", operation);
93 dict.SetStringKey("exclusion_reason", exclusion_reason);
94 if (net::NetLogCaptureIncludesSensitive(capture_mode) &&
95 !cookie_name.empty()) {
96 dict.SetStringKey("name", cookie_name);
97 }
98 return dict;
99}
100
Ryan Sleevi19a7bde2017-11-22 06:51:39101// Records details about the most-specific trust anchor in |spki_hashes|,
102// which is expected to be ordered with the leaf cert first and the root cert
103// last. This complements the per-verification histogram
104// Net.Certificate.TrustAnchor.Verify
105void LogTrustAnchor(const net::HashValueVector& spki_hashes) {
Ryan Sleevid756c2d2017-12-01 02:07:48106 // Don't record metrics if there are no hashes; this is true if the HTTP
107 // load did not come from an active network connection, such as the disk
108 // cache or a synthesized response.
109 if (spki_hashes.empty())
110 return;
111
Ryan Sleevi19a7bde2017-11-22 06:51:39112 int32_t id = 0;
113 for (const auto& hash : spki_hashes) {
114 id = net::GetNetTrustAnchorHistogramIdForSPKI(hash);
115 if (id != 0)
116 break;
117 }
Ilya Sherman0eb39802017-12-08 20:58:18118 base::UmaHistogramSparse("Net.Certificate.TrustAnchor.Request", id);
Ryan Sleevi19a7bde2017-11-22 06:51:39119}
120
Emily Stark8b411de02017-11-23 20:21:27121// Records per-request histograms relating to Certificate Transparency
122// compliance.
123void RecordCTHistograms(const net::SSLInfo& ssl_info) {
Emily Stark9676ea82017-11-29 08:10:08124 if (ssl_info.ct_policy_compliance ==
125 net::ct::CTPolicyCompliance::CT_POLICY_COMPLIANCE_DETAILS_NOT_AVAILABLE) {
Emily Stark8b411de02017-11-23 20:21:27126 return;
Emily Stark9676ea82017-11-29 08:10:08127 }
Emily Stark8b411de02017-11-23 20:21:27128 if (!ssl_info.is_issued_by_known_root)
129 return;
130
131 // Connections with major errors other than CERTIFICATE_TRANSPARENCY_REQUIRED
132 // would have failed anyway, so do not record these histograms for such
133 // requests.
134 net::CertStatus other_errors =
135 ssl_info.cert_status &
136 ~net::CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED;
Matt Mueller936511442019-09-03 18:15:12137 if (net::IsCertStatusError(other_errors))
Emily Stark8b411de02017-11-23 20:21:27138 return;
Emily Stark8b411de02017-11-23 20:21:27139
140 // Record the CT compliance of each request, to give a picture of the
141 // percentage of overall requests that are CT-compliant.
142 UMA_HISTOGRAM_ENUMERATION(
143 "Net.CertificateTransparency.RequestComplianceStatus",
Emily Stark627238f2017-11-29 03:29:54144 ssl_info.ct_policy_compliance,
Kunihiko Sakamoto36469732018-09-27 03:33:45145 net::ct::CTPolicyCompliance::CT_POLICY_COUNT);
Emily Stark8b411de02017-11-23 20:21:27146 // Record the CT compliance of each request which was required to be CT
147 // compliant. This gives a picture of the sites that are supposed to be
148 // compliant and how well they do at actually being compliant.
149 if (ssl_info.ct_policy_compliance_required) {
150 UMA_HISTOGRAM_ENUMERATION(
151 "Net.CertificateTransparency.CTRequiredRequestComplianceStatus",
Emily Stark627238f2017-11-29 03:29:54152 ssl_info.ct_policy_compliance,
Kunihiko Sakamoto36469732018-09-27 03:33:45153 net::ct::CTPolicyCompliance::CT_POLICY_COUNT);
Emily Stark8b411de02017-11-23 20:21:27154 }
155}
156
Thiemo Nagel0793b9c532018-04-18 16:57:58157net::CookieNetworkSecurity HistogramEntryForCookie(
158 const net::CanonicalCookie& cookie,
159 const net::URLRequest& request,
160 const net::HttpRequestInfo& request_info) {
161 if (!request_info.url.SchemeIsCryptographic()) {
162 return net::CookieNetworkSecurity::k1pNonsecureConnection;
163 }
164
165 if (cookie.IsSecure()) {
166 return net::CookieNetworkSecurity::k1pSecureAttribute;
167 }
168
169 net::TransportSecurityState* transport_security_state =
170 request.context()->transport_security_state();
171 net::TransportSecurityState::STSState sts_state;
172 const std::string cookie_domain =
173 cookie.IsHostCookie() ? request.url().host() : cookie.Domain().substr(1);
174 const bool hsts =
175 transport_security_state->GetSTSState(cookie_domain, &sts_state) &&
176 sts_state.ShouldUpgradeToSSL();
177 if (!hsts) {
178 return net::CookieNetworkSecurity::k1pSecureConnection;
179 }
180
181 if (cookie.IsHostCookie()) {
182 if (cookie.IsPersistent() && sts_state.expiry >= cookie.ExpiryDate()) {
183 return net::CookieNetworkSecurity::k1pHSTSHostCookie;
184 } else {
185 // Session cookies are assumed to live forever.
186 return net::CookieNetworkSecurity::k1pExpiringHSTSHostCookie;
187 }
188 }
189
190 // Domain cookies require HSTS to include subdomains to prevent spoofing.
191 if (sts_state.include_subdomains) {
192 if (cookie.IsPersistent() && sts_state.expiry >= cookie.ExpiryDate()) {
193 return net::CookieNetworkSecurity::k1pHSTSSubdomainsIncluded;
194 } else {
195 // Session cookies are assumed to live forever.
196 return net::CookieNetworkSecurity::k1pExpiringHSTSSubdomainsIncluded;
197 }
198 }
199
200 return net::CookieNetworkSecurity::k1pHSTSSpoofable;
201}
202
Thiemo Nagel6c783dbf2018-03-21 13:53:30203void LogCookieUMA(const net::CookieList& cookie_list,
204 const net::URLRequest& request,
205 const net::HttpRequestInfo& request_info) {
206 const bool secure_request = request_info.url.SchemeIsCryptographic();
207 const bool same_site = net::registry_controlled_domains::SameDomainOrHost(
208 request.url(), request.site_for_cookies(),
209 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES);
Mike West86149882017-07-28 10:41:49210
Thiemo Nagel6c783dbf2018-03-21 13:53:30211 const base::Time now = base::Time::Now();
212 base::Time oldest = base::Time::Max();
213 for (const auto& cookie : cookie_list) {
214 const std::string histogram_name =
215 std::string("Cookie.AllAgesFor") +
216 (secure_request ? "Secure" : "NonSecure") +
217 (same_site ? "SameSite" : "CrossSite") + "Request";
218 const int age_in_days = (now - cookie.CreationDate()).InDays();
219 base::UmaHistogramCounts1000(histogram_name, age_in_days);
Mohsen Izadiad6f7592018-04-18 15:57:10220 oldest = std::min(cookie.CreationDate(), oldest);
Thiemo Nagel0793b9c532018-04-18 16:57:58221
222 net::CookieNetworkSecurity entry =
223 HistogramEntryForCookie(cookie, request, request_info);
224 if (!same_site) {
225 entry =
226 static_cast<net::CookieNetworkSecurity>(static_cast<int>(entry) | 1);
227 }
228 UMA_HISTOGRAM_ENUMERATION("Cookie.NetworkSecurity", entry,
229 net::CookieNetworkSecurity::kCount);
Mike West86149882017-07-28 10:41:49230 }
Thiemo Nagel6c783dbf2018-03-21 13:53:30231
232 const std::string histogram_name =
233 std::string("Cookie.AgeFor") + (secure_request ? "Secure" : "NonSecure") +
234 (same_site ? "SameSite" : "CrossSite") + "Request";
235 const int age_in_days = (now - oldest).InDays();
236 base::UmaHistogramCounts1000(histogram_name, age_in_days);
Mike West86149882017-07-28 10:41:49237}
238
mkwst202534e32016-01-15 16:07:15239} // namespace
240
[email protected]4f5656c62010-12-13 10:47:09241namespace net {
242
initial.commit586acc5fe2008-07-26 22:42:52243// TODO(darin): make sure the port blocking code is not lost
initial.commit586acc5fe2008-07-26 22:42:52244// static
[email protected]4f5656c62010-12-13 10:47:09245URLRequestJob* URLRequestHttpJob::Factory(URLRequest* request,
[email protected]9f170462012-08-24 01:06:58246 NetworkDelegate* network_delegate,
[email protected]4f5656c62010-12-13 10:47:09247 const std::string& scheme) {
[email protected]f4533ba2013-11-28 09:35:41248 DCHECK(scheme == "http" || scheme == "https" || scheme == "ws" ||
249 scheme == "wss");
initial.commit586acc5fe2008-07-26 22:42:52250
[email protected]81293f482012-08-13 19:35:45251 if (!request->context()->http_transaction_factory()) {
initial.commit586acc5fe2008-07-26 22:42:52252 NOTREACHED() << "requires a valid context";
[email protected]9f170462012-08-24 01:06:58253 return new URLRequestErrorJob(
254 request, network_delegate, ERR_INVALID_ARGUMENT);
initial.commit586acc5fe2008-07-26 22:42:52255 }
256
mgershd21d6d142016-12-14 23:06:36257 const GURL& url = request->url();
258
259 // Check for reasons not to return a URLRequestHttpJob. These don't apply to
260 // https and wss requests.
261 if (!url.SchemeIsCryptographic()) {
262 // Check for HSTS upgrade.
263 TransportSecurityState* hsts =
264 request->context()->transport_security_state();
265 if (hsts && hsts->ShouldUpgradeToSSL(url.host())) {
266 GURL::Replacements replacements;
267 replacements.SetSchemeStr(
Mike West86149882017-07-28 10:41:49268
mgershd21d6d142016-12-14 23:06:36269 url.SchemeIs(url::kHttpScheme) ? url::kHttpsScheme : url::kWssScheme);
270 return new URLRequestRedirectJob(
271 request, network_delegate, url.ReplaceComponents(replacements),
272 // Use status code 307 to preserve the method, so POST requests work.
273 URLRequestRedirectJob::REDIRECT_307_TEMPORARY_REDIRECT, "HSTS");
274 }
275
276#if defined(OS_ANDROID)
277 // Check whether the app allows cleartext traffic to this host, and return
mgersh072720a2016-12-15 16:33:34278 // ERR_CLEARTEXT_NOT_PERMITTED if not.
mgershd21d6d142016-12-14 23:06:36279 if (request->context()->check_cleartext_permitted() &&
280 !android::IsCleartextPermitted(url.host())) {
281 return new URLRequestErrorJob(request, network_delegate,
282 ERR_CLEARTEXT_NOT_PERMITTED);
283 }
284#endif
285 }
mkwst549a5c632016-06-20 14:17:03286
[email protected]ee4c30d2012-11-07 15:08:43287 return new URLRequestHttpJob(request,
288 network_delegate,
289 request->context()->http_user_agent_settings());
initial.commit586acc5fe2008-07-26 22:42:52290}
291
[email protected]ee4c30d2012-11-07 15:08:43292URLRequestHttpJob::URLRequestHttpJob(
293 URLRequest* request,
294 NetworkDelegate* network_delegate,
295 const HttpUserAgentSettings* http_user_agent_settings)
[email protected]9f170462012-08-24 01:06:58296 : URLRequestJob(request, network_delegate),
Aaron Tagliaboschi028009e2019-03-07 16:28:06297 num_cookie_lines_left_(0),
[email protected]5033ab82013-03-22 20:17:46298 priority_(DEFAULT_PRIORITY),
mmenke54e82af2016-02-16 23:06:30299 response_info_(nullptr),
[email protected]4f5656c62010-12-13 10:47:09300 proxy_auth_state_(AUTH_STATE_DONT_NEED_AUTH),
301 server_auth_state_(AUTH_STATE_DONT_NEED_AUTH),
[email protected]3589e552008-08-20 23:11:34302 read_in_progress_(false),
mmenke54e82af2016-02-16 23:06:30303 throttling_entry_(nullptr),
[email protected]bbaea8f2011-06-24 00:11:01304 done_(false),
[email protected]5a07c192012-07-30 20:18:22305 awaiting_callback_(false),
[email protected]09812102014-05-24 00:04:11306 http_user_agent_settings_(http_user_agent_settings),
sclittlece72c482015-08-24 20:20:59307 total_received_bytes_from_previous_transactions_(0),
Jeremy Romand54000b22019-07-08 18:40:16308 total_sent_bytes_from_previous_transactions_(0) {
[email protected]a73a2802012-05-02 19:20:15309 URLRequestThrottlerManager* manager = request->context()->throttler_manager();
310 if (manager)
311 throttling_entry_ = manager->RegisterRequestUrl(request->url());
312
[email protected]ec23f522011-02-22 21:01:38313 ResetTimer();
initial.commit586acc5fe2008-07-26 22:42:52314}
315
[email protected]5033ab82013-03-22 20:17:46316URLRequestHttpJob::~URLRequestHttpJob() {
317 CHECK(!awaiting_callback_);
318
[email protected]5033ab82013-03-22 20:17:46319 DoneWithRequest(ABORTED);
320}
321
322void URLRequestHttpJob::SetPriority(RequestPriority priority) {
323 priority_ = priority;
324 if (transaction_)
325 transaction_->SetPriority(priority_);
326}
327
328void URLRequestHttpJob::Start() {
329 DCHECK(!transaction_.get());
330
[email protected]99ecf6e2013-04-10 22:46:13331 // URLRequest::SetReferrer ensures that we do not send username and password
332 // fields in the referrer.
333 GURL referrer(request_->referrer());
[email protected]5033ab82013-03-22 20:17:46334
335 request_info_.url = request_->url();
336 request_info_.method = request_->method();
Shivani Sharmad81bdd42019-05-23 17:19:56337
Shivani Sharma11c23f552019-06-11 18:18:39338 request_info_.network_isolation_key = request_->network_isolation_key();
[email protected]5033ab82013-03-22 20:17:46339 request_info_.load_flags = request_->load_flags();
dalyk7084d3cd2019-10-15 19:49:36340 request_info_.disable_secure_dns = request_->disable_secure_dns();
Ramin Halavatib5e433e62018-02-07 07:41:10341 request_info_.traffic_annotation =
342 net::MutableNetworkTrafficAnnotationTag(request_->traffic_annotation());
Paul Jensen60e45532018-02-19 16:04:18343 request_info_.socket_tag = request_->socket_tag();
Douglas Creageref5eecdc2018-11-09 20:50:36344#if BUILDFLAG(ENABLE_REPORTING)
345 request_info_.reporting_upload_depth = request_->reporting_upload_depth();
346#endif
Ramin Halavatib5e433e62018-02-07 07:41:10347
mkwste3e95992016-02-23 17:45:41348 // Privacy mode could still be disabled in SetCookieHeaderAndStart if we are
349 // going to send previously saved cookies.
Matt Menke7ad78edc2018-11-21 19:22:57350 request_info_.privacy_mode = privacy_mode();
[email protected]5033ab82013-03-22 20:17:46351
352 // Strip Referer from request_info_.extra_headers to prevent, e.g., plugins
353 // from overriding headers that are controlled using other means. Otherwise a
354 // plugin could set a referrer although sending the referrer is inhibited.
355 request_info_.extra_headers.RemoveHeader(HttpRequestHeaders::kReferer);
356
rdsmith81f607562014-11-21 18:35:16357 // Our consumer should have made sure that this is a safe referrer. See for
[email protected]5033ab82013-03-22 20:17:46358 // instance WebCore::FrameLoader::HideReferrer.
359 if (referrer.is_valid()) {
Mike Westfbd44112019-05-08 18:23:37360 std::string referer_value = referrer.spec();
361 UMA_HISTOGRAM_COUNTS_10000("Referrer.HeaderLength", referer_value.length());
362 if (base::FeatureList::IsEnabled(features::kCapRefererHeaderLength) &&
363 base::saturated_cast<int>(referer_value.length()) >
364 features::kMaxRefererHeaderLength.Get()) {
365 // Strip the referrer down to its origin, but ensure that it's serialized
366 // as a URL (e.g. retaining a trailing `/` character).
367 referer_value = url::Origin::Create(referrer).GetURL().spec();
368 }
[email protected]5033ab82013-03-22 20:17:46369 request_info_.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
Mike Westfbd44112019-05-08 18:23:37370 referer_value);
[email protected]5033ab82013-03-22 20:17:46371 }
372
373 request_info_.extra_headers.SetHeaderIfMissing(
374 HttpRequestHeaders::kUserAgent,
375 http_user_agent_settings_ ?
[email protected]aa051272014-03-10 05:56:56376 http_user_agent_settings_->GetUserAgent() : std::string());
[email protected]5033ab82013-03-22 20:17:46377
378 AddExtraHeaders();
379 AddCookieHeaderAndStart();
380}
381
382void URLRequestHttpJob::Kill() {
[email protected]5033ab82013-03-22 20:17:46383 weak_factory_.InvalidateWeakPtrs();
mmenke2281f3762015-11-02 20:38:17384 if (transaction_)
385 DestroyTransaction();
[email protected]5033ab82013-03-22 20:17:46386 URLRequestJob::Kill();
387}
388
ttuttle3ae06922015-05-11 23:41:52389void URLRequestHttpJob::GetConnectionAttempts(ConnectionAttempts* out) const {
390 if (transaction_)
391 transaction_->GetConnectionAttempts(out);
392 else
393 out->clear();
394}
395
ryansturm49a8cb12016-06-15 16:51:09396void URLRequestHttpJob::NotifyBeforeSendHeadersCallback(
[email protected]1252d42f2014-07-01 21:20:20397 const ProxyInfo& proxy_info,
398 HttpRequestHeaders* request_headers) {
399 DCHECK(request_headers);
[email protected]597a1ab2014-06-26 08:12:27400 DCHECK_NE(URLRequestStatus::CANCELED, GetStatus().status());
Tarun Bansal4dcebd42017-10-12 20:12:30401 if (proxy_info.is_empty()) {
402 SetProxyServer(ProxyServer::Direct());
403 } else {
404 SetProxyServer(proxy_info.proxy_server());
405 }
[email protected]597a1ab2014-06-26 08:12:27406 if (network_delegate()) {
ryansturm49a8cb12016-06-15 16:51:09407 network_delegate()->NotifyBeforeSendHeaders(
408 request_, proxy_info,
Lily Houghton8c2f97d2018-01-22 05:06:59409 request_->context()->proxy_resolution_service()->proxy_retry_info(),
[email protected]1252d42f2014-07-01 21:20:20410 request_headers);
[email protected]597a1ab2014-06-26 08:12:27411 }
412}
413
[email protected]175adac2008-07-30 17:28:04414void URLRequestHttpJob::NotifyHeadersComplete() {
initial.commit586acc5fe2008-07-26 22:42:52415 DCHECK(!response_info_);
Aaron Tagliaboschi028009e2019-03-07 16:28:06416 DCHECK_EQ(0, num_cookie_lines_left_);
Maks Orlovich15714232019-06-16 23:14:09417 DCHECK(request_->maybe_stored_cookies().empty());
initial.commit586acc5fe2008-07-26 22:42:52418
419 response_info_ = transaction_->GetResponseInfo();
420
Matt Menke5dca1bb2019-09-13 20:43:12421 if (!response_info_->was_cached && throttling_entry_.get())
xunjieli041e9392015-05-19 21:51:33422 throttling_entry_->UpdateWithResponse(GetResponseCode());
[email protected]6b3f9642010-11-25 02:29:06423
[email protected]fecef222012-01-05 02:26:15424 // The ordering of these calls is not important.
[email protected]77f6fb432009-09-05 14:21:09425 ProcessStrictTransportSecurityHeader();
estark1614475f2016-03-10 03:46:47426 ProcessExpectCTHeader();
[email protected]a9cea7542009-05-20 04:30:23427
Lily Chenf53dfbcd2019-08-30 01:42:10428 // Clear |set_cookie_status_list_| after any processing in case
Aaron Tagliaboschi028009e2019-03-07 16:28:06429 // SaveCookiesAndNotifyHeadersComplete is called again.
Lily Chenf53dfbcd2019-08-30 01:42:10430 request_->set_maybe_stored_cookies(std::move(set_cookie_status_list_));
Aaron Tagliaboschi028009e2019-03-07 16:28:06431
[email protected]0757e7702009-03-27 04:00:22432 // The HTTP transaction may be restarted several times for the purposes
433 // of sending authorization information. Each time it restarts, we get
434 // notified of the headers completion so that we can update the cookie store.
435 if (transaction_->IsReadyToRestartForAuth()) {
[email protected]87a09a92011-07-14 15:50:50436 // TODO(battre): This breaks the webrequest API for
437 // URLRequestTestHTTP.BasicAuthWithCookies
ryansturm2343cb62016-06-15 01:09:00438 // where OnBeforeStartTransaction -> OnStartTransaction ->
439 // OnBeforeStartTransaction occurs.
[email protected]f3cf9802011-10-28 18:44:58440 RestartTransactionWithAuth(AuthCredentials());
[email protected]0757e7702009-03-27 04:00:22441 return;
442 }
443
[email protected]4f5656c62010-12-13 10:47:09444 URLRequestJob::NotifyHeadersComplete();
initial.commit586acc5fe2008-07-26 22:42:52445}
446
[email protected]175adac2008-07-30 17:28:04447void URLRequestHttpJob::DestroyTransaction() {
[email protected]c6a4eb92010-03-03 23:51:19448 DCHECK(transaction_.get());
initial.commit586acc5fe2008-07-26 22:42:52449
[email protected]bbaea8f2011-06-24 00:11:01450 DoneWithRequest(ABORTED);
sclittlece72c482015-08-24 20:20:59451
452 total_received_bytes_from_previous_transactions_ +=
453 transaction_->GetTotalReceivedBytes();
sclittlefb249892015-09-10 21:33:22454 total_sent_bytes_from_previous_transactions_ +=
455 transaction_->GetTotalSentBytes();
[email protected]af4876d2008-10-21 23:10:57456 transaction_.reset();
David Benjamin0bda12f2018-02-07 19:58:45457 response_info_ = nullptr;
458 override_response_headers_ = nullptr;
[email protected]3b23a222013-05-15 21:33:25459 receive_headers_end_ = base::TimeTicks();
initial.commit586acc5fe2008-07-26 22:42:52460}
461
[email protected]175adac2008-07-30 17:28:04462void URLRequestHttpJob::StartTransaction() {
[email protected]cc05edc2013-03-08 18:04:41463 if (network_delegate()) {
David Benjamin9776ca22018-06-13 00:00:15464 OnCallToDelegate(
465 NetLogEventType::NETWORK_DELEGATE_BEFORE_START_TRANSACTION);
mmenked3a02b32016-11-16 20:21:32466 // The NetworkDelegate must watch for OnRequestDestroyed and not modify
Matt Mueller22372d432019-04-12 20:45:24467 // |extra_headers| after it's called.
468 // TODO(mattm): change the API to remove the out-params and take the
469 // results as params of the callback.
ryansturm2343cb62016-06-15 01:09:00470 int rv = network_delegate()->NotifyBeforeStartTransaction(
mmenked3a02b32016-11-16 20:21:32471 request_,
David Benjamind1f287bf2018-06-12 01:57:20472 base::BindOnce(&URLRequestHttpJob::NotifyBeforeStartTransactionCallback,
Matt Mueller22372d432019-04-12 20:45:24473 weak_factory_.GetWeakPtr()),
[email protected]636eccd2011-06-28 12:28:01474 &request_info_.extra_headers);
475 // If an extension blocks the request, we rely on the callback to
[email protected]b4438d32012-09-27 06:15:30476 // MaybeStartTransactionInternal().
[email protected]abe1c4a2013-10-25 19:28:51477 if (rv == ERR_IO_PENDING)
[email protected]636eccd2011-06-28 12:28:01478 return;
[email protected]b4438d32012-09-27 06:15:30479 MaybeStartTransactionInternal(rv);
480 return;
[email protected]636eccd2011-06-28 12:28:01481 }
482 StartTransactionInternal();
483}
484
ryansturm2343cb62016-06-15 01:09:00485void URLRequestHttpJob::NotifyBeforeStartTransactionCallback(int result) {
[email protected]9045b8822012-01-13 20:35:35486 // Check that there are no callbacks to already canceled requests.
487 DCHECK_NE(URLRequestStatus::CANCELED, GetStatus().status());
488
[email protected]b4438d32012-09-27 06:15:30489 MaybeStartTransactionInternal(result);
490}
491
492void URLRequestHttpJob::MaybeStartTransactionInternal(int result) {
[email protected]abe1c4a2013-10-25 19:28:51493 OnCallToDelegateComplete();
[email protected]636eccd2011-06-28 12:28:01494 if (result == OK) {
495 StartTransactionInternal();
496 } else {
Eric Roman06bd9742019-07-13 15:19:13497 request_->net_log().AddEventWithStringParams(NetLogEventType::CANCELLED,
498 "source", "delegate");
jamd3f5a3c2016-10-27 18:52:02499 // Don't call back synchronously to the delegate.
500 base::ThreadTaskRunnerHandle::Get()->PostTask(
501 FROM_HERE,
kylecharf4fe5172019-02-15 18:53:49502 base::BindOnce(&URLRequestHttpJob::NotifyStartError,
503 weak_factory_.GetWeakPtr(),
504 URLRequestStatus(URLRequestStatus::FAILED, result)));
[email protected]636eccd2011-06-28 12:28:01505 }
506}
507
508void URLRequestHttpJob::StartTransactionInternal() {
mmenke4600b602015-10-28 18:52:17509 // This should only be called while the request's status is IO_PENDING.
mmenke2281f3762015-11-02 20:38:17510 DCHECK_EQ(URLRequestStatus::IO_PENDING, request_->status().status());
David Benjamin0bda12f2018-02-07 19:58:45511 DCHECK(!override_response_headers_);
mmenke4600b602015-10-28 18:52:17512
initial.commit586acc5fe2008-07-26 22:42:52513 // NOTE: This method assumes that request_info_ is already setup properly.
514
[email protected]34602282010-02-03 22:14:15515 // If we already have a transaction, then we should restart the transaction
[email protected]f3cf9802011-10-28 18:44:58516 // with auth provided by auth_credentials_.
initial.commit586acc5fe2008-07-26 22:42:52517
[email protected]99c07902010-08-17 18:59:52518 int rv;
[email protected]6b3f9642010-11-25 02:29:06519
tbansal80a52162016-05-20 17:55:04520 // Notify NetworkQualityEstimator.
521 NetworkQualityEstimator* network_quality_estimator =
522 request()->context()->network_quality_estimator();
523 if (network_quality_estimator)
524 network_quality_estimator->NotifyStartTransaction(*request_);
525
[email protected]34602282010-02-03 22:14:15526 if (transaction_.get()) {
mmenked3a02b32016-11-16 20:21:32527 rv = transaction_->RestartWithAuth(
Yannic Bonenbergercc716d42019-09-04 17:05:36528 auth_credentials_, base::BindOnce(&URLRequestHttpJob::OnStartCompleted,
529 base::Unretained(this)));
[email protected]f3cf9802011-10-28 18:44:58530 auth_credentials_ = AuthCredentials();
[email protected]34602282010-02-03 22:14:15531 } else {
[email protected]34602282010-02-03 22:14:15532 DCHECK(request_->context()->http_transaction_factory());
initial.commit586acc5fe2008-07-26 22:42:52533
[email protected]99c07902010-08-17 18:59:52534 rv = request_->context()->http_transaction_factory()->CreateTransaction(
[email protected]027bd85a2013-12-27 22:39:10535 priority_, &transaction_);
[email protected]f4533ba2013-11-28 09:35:41536
537 if (rv == OK && request_info_.url.SchemeIsWSOrWSS()) {
Bence Békya5ec55e62018-03-07 14:23:28538 base::SupportsUserData::Data* data =
539 request_->GetUserData(kWebSocketHandshakeUserDataKey);
[email protected]f4533ba2013-11-28 09:35:41540 if (data) {
541 transaction_->SetWebSocketHandshakeStreamCreateHelper(
542 static_cast<WebSocketHandshakeStreamBase::CreateHelper*>(data));
543 } else {
544 rv = ERR_DISALLOWED_URL_SCHEME;
545 }
546 }
547
[email protected]4f5656c62010-12-13 10:47:09548 if (rv == OK) {
ryansturm49a8cb12016-06-15 16:51:09549 transaction_->SetBeforeHeadersSentCallback(
550 base::Bind(&URLRequestHttpJob::NotifyBeforeSendHeadersCallback,
[email protected]597a1ab2014-06-26 08:12:27551 base::Unretained(this)));
Andrey Kosyakov83a6eee2017-08-14 19:20:04552 transaction_->SetRequestHeadersCallback(request_headers_callback_);
Andrey Kosyakov2e893e62017-08-31 17:00:52553 transaction_->SetResponseHeadersCallback(response_headers_callback_);
[email protected]a45840b2014-01-10 15:40:22554
dchengc2e01e82014-08-27 00:24:42555 if (!throttling_entry_.get() ||
xunjieli41edcdd2015-06-24 14:26:40556 !throttling_entry_->ShouldRejectRequest(*request_)) {
[email protected]227b0e82011-03-25 21:11:53557 rv = transaction_->Start(
Yannic Bonenbergercc716d42019-09-04 17:05:36558 &request_info_,
559 base::BindOnce(&URLRequestHttpJob::OnStartCompleted,
560 base::Unretained(this)),
mmenked3a02b32016-11-16 20:21:32561 request_->net_log());
[email protected]bbaea8f2011-06-24 00:11:01562 start_time_ = base::TimeTicks::Now();
[email protected]227b0e82011-03-25 21:11:53563 } else {
564 // Special error code for the exponential back-off module.
565 rv = ERR_TEMPORARILY_THROTTLED;
566 }
[email protected]34602282010-02-03 22:14:15567 }
initial.commit586acc5fe2008-07-26 22:42:52568 }
569
[email protected]4f5656c62010-12-13 10:47:09570 if (rv == ERR_IO_PENDING)
[email protected]34602282010-02-03 22:14:15571 return;
572
initial.commit586acc5fe2008-07-26 22:42:52573 // The transaction started synchronously, but we need to notify the
[email protected]4f5656c62010-12-13 10:47:09574 // URLRequest delegate via the message loop.
skyostil4891b25b2015-06-11 11:43:45575 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf4fe5172019-02-15 18:53:49576 FROM_HERE, base::BindOnce(&URLRequestHttpJob::OnStartCompleted,
577 weak_factory_.GetWeakPtr(), rv));
initial.commit586acc5fe2008-07-26 22:42:52578}
579
[email protected]175adac2008-07-30 17:28:04580void URLRequestHttpJob::AddExtraHeaders() {
[email protected]c7bef94c2011-06-21 18:05:51581 if (!request_info_.extra_headers.HasHeader(
Helen Li7dd80832017-09-12 18:29:17582 HttpRequestHeaders::kAcceptEncoding)) {
Aaron Tagliaboschi6c652aa2018-11-30 22:13:41583 // If a range is specifically requested, set the "Accepted Encoding" header
584 // to "identity"
585 if (request_info_.extra_headers.HasHeader(HttpRequestHeaders::kRange)) {
586 request_info_.extra_headers.SetHeader(HttpRequestHeaders::kAcceptEncoding,
587 "identity");
588 } else {
589 // Advertise "br" encoding only if transferred data is opaque to proxy.
590 bool advertise_brotli = false;
591 if (request()->context()->enable_brotli()) {
592 if (request()->url().SchemeIsCryptographic() ||
593 IsLocalhost(request()->url())) {
594 advertise_brotli = true;
595 }
eustas7ff89682016-07-07 20:23:39596 }
eustasfbec9132015-12-30 14:56:51597
Aaron Tagliaboschi6c652aa2018-11-30 22:13:41598 // Supply Accept-Encoding headers first so that it is more likely that
599 // they will be in the first transmitted packet. This can sometimes make
600 // it easier to filter and analyze the streams to assure that a proxy has
601 // not damaged these headers. Some proxies deliberately corrupt
602 // Accept-Encoding headers.
603 std::string advertised_encodings = "gzip, deflate";
604 if (advertise_brotli)
605 advertised_encodings += ", br";
606 // Tell the server what compression formats are supported.
607 request_info_.extra_headers.SetHeader(HttpRequestHeaders::kAcceptEncoding,
608 advertised_encodings);
609 }
[email protected]423041b2008-10-27 17:39:28610 }
611
[email protected]ee4c30d2012-11-07 15:08:43612 if (http_user_agent_settings_) {
[email protected]84f05432013-03-15 01:00:12613 // Only add default Accept-Language if the request didn't have it
614 // specified.
[email protected]ee4c30d2012-11-07 15:08:43615 std::string accept_language =
616 http_user_agent_settings_->GetAcceptLanguage();
Yao Xiao90833e5b2019-05-09 16:19:41617 if (base::FeatureList::IsEnabled(features::kAcceptLanguageHeader) &&
618 !accept_language.empty()) {
[email protected]ee4c30d2012-11-07 15:08:43619 request_info_.extra_headers.SetHeaderIfMissing(
620 HttpRequestHeaders::kAcceptLanguage,
621 accept_language);
622 }
initial.commit586acc5fe2008-07-26 22:42:52623 }
initial.commit586acc5fe2008-07-26 22:42:52624}
625
[email protected]34602282010-02-03 22:14:15626void URLRequestHttpJob::AddCookieHeaderAndStart() {
davidben151423e2015-03-23 18:48:36627 CookieStore* cookie_store = request_->context()->cookie_store();
[email protected]1a6fff52011-10-20 21:00:16628 if (cookie_store && !(request_info_.load_flags & LOAD_DO_NOT_SEND_COOKIES)) {
mkwste3e95992016-02-23 17:45:41629 CookieOptions options;
Aaron Tagliaboschifd4f3f012019-05-30 23:05:54630 options.set_return_excluded_cookies();
mkwste3e95992016-02-23 17:45:41631 options.set_include_httponly();
Maks Orlovich64e2913d2019-03-05 14:42:56632 options.set_same_site_cookie_context(
633 net::cookie_util::ComputeSameSiteContextForRequest(
634 request_->method(), request_->url(), request_->site_for_cookies(),
635 request_->initiator(), request_->attach_same_site_cookies()));
mkwste3e95992016-02-23 17:45:41636 cookie_store->GetCookieListWithOptionsAsync(
637 request_->url(), options,
Yannic Bonenbergercc716d42019-09-04 17:05:36638 base::BindOnce(&URLRequestHttpJob::SetCookieHeaderAndStart,
639 weak_factory_.GetWeakPtr(), options));
[email protected]03d845f2011-07-29 19:06:26640 } else {
mmenked3a02b32016-11-16 20:21:32641 StartTransaction();
[email protected]03d845f2011-07-29 19:06:26642 }
643}
644
Aaron Tagliaboschia4c64b52019-01-25 03:28:49645void URLRequestHttpJob::SetCookieHeaderAndStart(
Lily Chen3ac7cf42019-05-30 23:29:29646 const CookieOptions& options,
Lily Chenf068a762019-08-21 21:10:50647 const CookieStatusList& cookies_with_status_list,
Aaron Tagliaboschia4c64b52019-01-25 03:28:49648 const CookieStatusList& excluded_list) {
Maks Orlovich15714232019-06-16 23:14:09649 DCHECK(request_->maybe_sent_cookies().empty());
Aaron Tagliaboschifd4f3f012019-05-30 23:05:54650
Lily Chenf53dfbcd2019-08-30 01:42:10651 // TODO(chlily): This is just for passing to CanGetCookies(), however the
652 // CookieList parameter of CanGetCookies(), which eventually gets passed to
653 // the NetworkDelegate, never actually gets used anywhere except in tests. The
654 // parameter should be removed.
Lily Chenf068a762019-08-21 21:10:50655 CookieList cookie_list =
656 net::cookie_util::StripStatuses(cookies_with_status_list);
657
Lily Chenf53dfbcd2019-08-30 01:42:10658 bool can_get_cookies = CanGetCookies(cookie_list);
659 if (!cookies_with_status_list.empty() && can_get_cookies) {
Maks Orlovich15714232019-06-16 23:14:09660 LogCookieUMA(cookie_list, *request_, request_info_);
Mike West86149882017-07-28 10:41:49661
Lily Chenf53dfbcd2019-08-30 01:42:10662 std::string cookie_line =
663 CanonicalCookie::BuildCookieLine(cookies_with_status_list);
Maks Orlovich15714232019-06-16 23:14:09664 UMA_HISTOGRAM_COUNTS_10000("Cookie.HeaderLength", cookie_line.length());
665 request_info_.extra_headers.SetHeader(HttpRequestHeaders::kCookie,
666 cookie_line);
Mike West7c8c2ad2018-02-10 07:08:49667
Maks Orlovich15714232019-06-16 23:14:09668 // Disable privacy mode as we are sending cookies anyway.
669 request_info_.privacy_mode = PRIVACY_MODE_DISABLED;
[email protected]54f4c9362011-07-25 21:54:46670 }
Aaron Tagliaboschi41bfbec2019-03-12 19:23:48671
Lily Chenf53dfbcd2019-08-30 01:42:10672 // Report status for things in |excluded_list| and |cookies_with_status_list|
673 // after the delegate got a chance to block them.
674 CookieStatusList maybe_sent_cookies = excluded_list;
675 // CanGetCookies only looks at the fields of the URLRequest, not the cookies
676 // it is passed, so if CanGetCookies(cookie_list) is false, then
677 // CanGetCookies(excluded_list) would also be false, so tag also the
678 // excluded cookies as having been blocked by user preferences.
679 if (!can_get_cookies) {
680 for (CookieStatusList::iterator it = maybe_sent_cookies.begin();
681 it != maybe_sent_cookies.end(); ++it) {
682 it->status.AddExclusionReason(
683 CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES);
Lily Chen3ac7cf42019-05-30 23:29:29684 }
685 }
Lily Chenf53dfbcd2019-08-30 01:42:10686 for (const auto& cookie_with_status : cookies_with_status_list) {
687 CanonicalCookie::CookieInclusionStatus status = cookie_with_status.status;
688 if (!can_get_cookies) {
689 status.AddExclusionReason(
690 CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES);
691 }
692 maybe_sent_cookies.push_back({cookie_with_status.cookie, status});
693 }
Lily Chen3ac7cf42019-05-30 23:29:29694
Lily Chen0e079b732019-10-01 19:48:40695 if (request_->net_log().IsCapturing()) {
696 for (const auto& cookie_and_status : maybe_sent_cookies) {
697 if (!cookie_and_status.status.IsInclude()) {
Eric Lawrencef814f5b22019-10-04 01:52:43698 request_->net_log().AddEvent(
699 NetLogEventType::COOKIE_INCLUSION_STATUS,
700 [&](NetLogCaptureMode capture_mode) {
701 return CookieExcludedNetLogParams(
702 "send", cookie_and_status.cookie.Name(),
703 cookie_and_status.status.GetDebugString(), capture_mode);
704 });
Lily Chen0e079b732019-10-01 19:48:40705 }
706 }
707 }
708
Maks Orlovich15714232019-06-16 23:14:09709 request_->set_maybe_sent_cookies(std::move(maybe_sent_cookies));
Aaron Tagliaboschifd4f3f012019-05-30 23:05:54710
mmenked3a02b32016-11-16 20:21:32711 StartTransaction();
[email protected]0757e7702009-03-27 04:00:22712}
713
[email protected]ea8141e2011-10-05 13:12:51714void URLRequestHttpJob::SaveCookiesAndNotifyHeadersComplete(int result) {
Lily Chenf53dfbcd2019-08-30 01:42:10715 DCHECK(set_cookie_status_list_.empty());
Aaron Tagliaboschi028009e2019-03-07 16:28:06716 DCHECK_EQ(0, num_cookie_lines_left_);
717
[email protected]abe1c4a2013-10-25 19:28:51718 // End of the call started in OnStartCompleted.
719 OnCallToDelegateComplete();
720
ttuttle859dc7a2015-04-23 19:42:29721 if (result != OK) {
Eric Roman06bd9742019-07-13 15:19:13722 request_->net_log().AddEventWithStringParams(NetLogEventType::CANCELLED,
723 "source", "delegate");
[email protected]ea8141e2011-10-05 13:12:51724 NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, result));
725 return;
726 }
727
Aaron Tagliaboschi028009e2019-03-07 16:28:06728 if ((request_info_.load_flags & LOAD_DO_NOT_SAVE_COOKIES) ||
729 !request_->context()->cookie_store()) {
730 NotifyHeadersComplete();
731 return;
732 }
733
mmenke54e82af2016-02-16 23:06:30734 base::Time response_date;
Lily Chenb851acc2019-08-07 15:54:44735 base::Optional<base::Time> server_time = base::nullopt;
736 if (GetResponseHeaders()->GetDateValue(&response_date))
737 server_time = base::make_optional(response_date);
[email protected]263163f2012-06-14 22:40:34738
Aaron Tagliaboschi028009e2019-03-07 16:28:06739 CookieOptions options;
740 options.set_include_httponly();
Maks Orlovichfdbc8be2019-03-18 18:34:52741 options.set_same_site_cookie_context(
Maks Orlovich3637afd22019-05-06 20:37:20742 net::cookie_util::ComputeSameSiteContextForResponse(
743 request_->url(), request_->site_for_cookies(),
744 request_->initiator()));
jww79aceda2015-12-07 01:56:34745
Aaron Tagliaboschifd4f3f012019-05-30 23:05:54746 options.set_return_excluded_cookies();
747
Aaron Tagliaboschi028009e2019-03-07 16:28:06748 // Set all cookies, without waiting for them to be set. Any subsequent read
749 // will see the combined result of all cookie operation.
750 const base::StringPiece name("Set-Cookie");
751 std::string cookie_string;
752 size_t iter = 0;
753 HttpResponseHeaders* headers = GetResponseHeaders();
754
755 // NotifyHeadersComplete needs to be called once and only once after the
756 // list has been fully processed, and it can either be called in the
757 // callback or after the loop is called, depending on how the last element
758 // was handled. |num_cookie_lines_left_| keeps track of how many async
759 // callbacks are currently out (starting from 1 to make sure the loop runs all
760 // the way through before trying to exit). If there are any callbacks still
761 // waiting when the loop ends, then NotifyHeadersComplete will be called when
762 // it reaches 0 in the callback itself.
763 num_cookie_lines_left_ = 1;
764 while (headers->EnumerateHeader(&iter, name, &cookie_string)) {
765 CanonicalCookie::CookieInclusionStatus returned_status;
766
767 num_cookie_lines_left_++;
768
769 std::unique_ptr<CanonicalCookie> cookie = net::CanonicalCookie::Create(
Lily Chenb851acc2019-08-07 15:54:44770 request_->url(), cookie_string, base::Time::Now(), server_time,
Aaron Tagliaboschi028009e2019-03-07 16:28:06771 &returned_status);
772
Lily Chenf53dfbcd2019-08-30 01:42:10773 base::Optional<CanonicalCookie> cookie_to_return = base::nullopt;
774 if (returned_status.IsInclude()) {
775 DCHECK(cookie);
776 // Make a copy of the cookie if we successfully made one.
777 cookie_to_return = *cookie;
778 }
779 if (cookie && !CanSetCookie(*cookie, &options)) {
780 returned_status.AddExclusionReason(
781 CanonicalCookie::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES);
782 }
783 if (!returned_status.IsInclude()) {
784 OnSetCookieResult(options, cookie_to_return, std::move(cookie_string),
Aaron Tagliaboschifd4f3f012019-05-30 23:05:54785 returned_status);
Aaron Tagliaboschi028009e2019-03-07 16:28:06786 continue;
[email protected]263163f2012-06-14 22:40:34787 }
Lily Chen0f208ea2019-08-08 23:37:53788
789 request_->context()->cookie_store()->SetCanonicalCookieAsync(
790 std::move(cookie), request_->url().scheme(), options,
Lily Chen3ac7cf42019-05-30 23:29:29791 base::BindOnce(&URLRequestHttpJob::OnSetCookieResult,
Lily Chenf53dfbcd2019-08-30 01:42:10792 weak_factory_.GetWeakPtr(), options, cookie_to_return,
Lily Chen3ac7cf42019-05-30 23:29:29793 cookie_string));
Aaron Tagliaboschi028009e2019-03-07 16:28:06794 }
795 // Removing the 1 that |num_cookie_lines_left| started with, signifing that
796 // loop has been exited.
797 num_cookie_lines_left_--;
798
799 if (num_cookie_lines_left_ == 0)
800 NotifyHeadersComplete();
801}
802
803void URLRequestHttpJob::OnSetCookieResult(
Lily Chen3ac7cf42019-05-30 23:29:29804 const CookieOptions& options,
Aaron Tagliaboschifd4f3f012019-05-30 23:05:54805 base::Optional<CanonicalCookie> cookie,
Aaron Tagliaboschi028009e2019-03-07 16:28:06806 std::string cookie_string,
807 CanonicalCookie::CookieInclusionStatus status) {
Lily Chen0e079b732019-10-01 19:48:40808 if (!status.IsInclude() && request_->net_log().IsCapturing()) {
Eric Lawrencef814f5b22019-10-04 01:52:43809 request_->net_log().AddEvent(NetLogEventType::COOKIE_INCLUSION_STATUS,
810 [&](NetLogCaptureMode capture_mode) {
811 return CookieExcludedNetLogParams(
812 "store",
813 cookie ? cookie.value().Name() : "",
814 status.GetDebugString(), capture_mode);
815 });
Lily Chen0e079b732019-10-01 19:48:40816 }
Lily Chenf53dfbcd2019-08-30 01:42:10817 set_cookie_status_list_.emplace_back(std::move(cookie),
818 std::move(cookie_string), status);
Aaron Tagliaboschi028009e2019-03-07 16:28:06819
820 num_cookie_lines_left_--;
821
Lily Chenf53dfbcd2019-08-30 01:42:10822 // If all the cookie lines have been handled, |set_cookie_status_list_| now
823 // reflects the result of all Set-Cookie lines, and the request can be
824 // continued.
Aaron Tagliaboschi028009e2019-03-07 16:28:06825 if (num_cookie_lines_left_ == 0)
826 NotifyHeadersComplete();
[email protected]34602282010-02-03 22:14:15827}
828
[email protected]77f6fb432009-09-05 14:21:09829void URLRequestHttpJob::ProcessStrictTransportSecurityHeader() {
[email protected]a9cea7542009-05-20 04:30:23830 DCHECK(response_info_);
[email protected]6ed72be2013-01-08 22:07:33831 TransportSecurityState* security_state =
832 request_->context()->transport_security_state();
[email protected]e88006f2012-01-11 06:15:07833 const SSLInfo& ssl_info = response_info_->ssl_info;
[email protected]a9cea7542009-05-20 04:30:23834
[email protected]6ed72be2013-01-08 22:07:33835 // Only accept HSTS headers on HTTPS connections that have no
836 // certificate errors.
[email protected]e88006f2012-01-11 06:15:07837 if (!ssl_info.is_valid() || IsCertStatusError(ssl_info.cert_status) ||
mmenked3a02b32016-11-16 20:21:32838 !security_state) {
[email protected]e88006f2012-01-11 06:15:07839 return;
mmenked3a02b32016-11-16 20:21:32840 }
[email protected]326e6792009-12-11 21:04:42841
estarka5da76702015-04-09 04:00:16842 // Don't accept HSTS headers when the hostname is an IP address.
843 if (request_info_.url.HostIsIPAddress())
844 return;
845
[email protected]242d8562012-10-30 21:20:46846 // http://tools.ietf.org/html/draft-ietf-websec-strict-transport-sec:
847 //
848 // If a UA receives more than one STS header field in a HTTP response
849 // message over secure transport, then the UA MUST process only the
850 // first such header field.
[email protected]6ed72be2013-01-08 22:07:33851 HttpResponseHeaders* headers = GetResponseHeaders();
852 std::string value;
olli.raulaee489a52016-01-25 08:37:10853 if (headers->EnumerateHeader(nullptr, "Strict-Transport-Security", &value))
[email protected]6ed72be2013-01-08 22:07:33854 security_state->AddHSTSHeader(request_info_.url.host(), value);
[email protected]a9cea7542009-05-20 04:30:23855}
[email protected]4f5656c62010-12-13 10:47:09856
estark1614475f2016-03-10 03:46:47857void URLRequestHttpJob::ProcessExpectCTHeader() {
858 DCHECK(response_info_);
859 TransportSecurityState* security_state =
860 request_->context()->transport_security_state();
861 const SSLInfo& ssl_info = response_info_->ssl_info;
862
863 // Only accept Expect CT headers on HTTPS connections that have no
864 // certificate errors.
865 if (!ssl_info.is_valid() || IsCertStatusError(ssl_info.cert_status) ||
866 !security_state) {
867 return;
868 }
869
estark1614475f2016-03-10 03:46:47870 HttpResponseHeaders* headers = GetResponseHeaders();
871 std::string value;
Emily Stark4cfecf072017-08-08 01:05:51872 if (headers->GetNormalizedHeader("Expect-CT", &value)) {
estark1614475f2016-03-10 03:46:47873 security_state->ProcessExpectCTHeader(
874 value, HostPortPair::FromURL(request_info_.url), ssl_info);
875 }
876}
877
[email protected]5394e422011-01-20 22:07:43878void URLRequestHttpJob::OnStartCompleted(int result) {
Alexandr Ilin33126632018-11-14 14:48:17879 TRACE_EVENT0(NetTracingCategory(), "URLRequestHttpJob::OnStartCompleted");
[email protected]ec23f522011-02-22 21:01:38880 RecordTimer();
881
[email protected]80abdad2014-03-15 00:20:54882 // If the job is done (due to cancellation), can just ignore this
883 // notification.
884 if (done_)
[email protected]5394e422011-01-20 22:07:43885 return;
886
[email protected]3b23a222013-05-15 21:33:25887 receive_headers_end_ = base::TimeTicks::Now();
888
[email protected]ef2bf422012-05-11 03:27:09889 const URLRequestContext* context = request_->context();
890
Ryan Sleevi19a7bde2017-11-22 06:51:39891 if (transaction_ && transaction_->GetResponseInfo()) {
892 const SSLInfo& ssl_info = transaction_->GetResponseInfo()->ssl_info;
Matt Mueller936511442019-09-03 18:15:12893 if (!IsCertificateError(result)) {
Ryan Sleevi19a7bde2017-11-22 06:51:39894 LogTrustAnchor(ssl_info.public_key_hashes);
895 }
Emily Stark8b411de02017-11-23 20:21:27896
897 RecordCTHistograms(ssl_info);
Ryan Sleevi19a7bde2017-11-22 06:51:39898 }
899
Wojciech Dzierżanowskiabdeeaf2019-04-01 20:16:22900 if (transaction_ && transaction_->GetResponseInfo()) {
901 SetProxyServer(transaction_->GetResponseInfo()->proxy_server);
902 }
903
[email protected]5394e422011-01-20 22:07:43904 if (result == OK) {
[email protected]ea8141e2011-10-05 13:12:51905 scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders();
hiroshigecb76caa4c52015-12-22 07:50:25906
[email protected]cc05edc2013-03-08 18:04:41907 if (network_delegate()) {
[email protected]ea8141e2011-10-05 13:12:51908 // Note that |this| may not be deleted until
mmenked3a02b32016-11-16 20:21:32909 // |URLRequestHttpJob::OnHeadersReceivedCallback()| or
[email protected]ea8141e2011-10-05 13:12:51910 // |NetworkDelegate::URLRequestDestroyed()| has been called.
David Benjamin9776ca22018-06-13 00:00:15911 OnCallToDelegate(NetLogEventType::NETWORK_DELEGATE_HEADERS_RECEIVED);
Matt Menkeeed1a242019-10-23 21:26:06912 preserve_fragment_on_redirect_url_ = base::nullopt;
Yutaka Hirano832c8902019-10-16 10:04:34913 IPEndPoint endpoint;
914 if (transaction_)
915 transaction_->GetRemoteEndpoint(&endpoint);
mmenked3a02b32016-11-16 20:21:32916 // The NetworkDelegate must watch for OnRequestDestroyed and not modify
Matt Muellerbe9d8e82019-03-15 21:38:44917 // any of the arguments after it's called.
918 // TODO(mattm): change the API to remove the out-params and take the
919 // results as params of the callback.
[email protected]cc05edc2013-03-08 18:04:41920 int error = network_delegate()->NotifyHeadersReceived(
David Benjamind1f287bf2018-06-12 01:57:20921 request_,
922 base::BindOnce(&URLRequestHttpJob::OnHeadersReceivedCallback,
Matt Muellerbe9d8e82019-03-15 21:38:44923 weak_factory_.GetWeakPtr()),
Yutaka Hirano832c8902019-10-16 10:04:34924 headers.get(), &override_response_headers_, endpoint,
Matt Menkeeed1a242019-10-23 21:26:06925 &preserve_fragment_on_redirect_url_);
ttuttle859dc7a2015-04-23 19:42:29926 if (error != OK) {
927 if (error == ERR_IO_PENDING) {
[email protected]ea8141e2011-10-05 13:12:51928 awaiting_callback_ = true;
[email protected]ea8141e2011-10-05 13:12:51929 } else {
Eric Roman06bd9742019-07-13 15:19:13930 request_->net_log().AddEventWithStringParams(
931 NetLogEventType::CANCELLED, "source", "delegate");
[email protected]abe1c4a2013-10-25 19:28:51932 OnCallToDelegateComplete();
[email protected]ea8141e2011-10-05 13:12:51933 NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, error));
934 }
935 return;
936 }
937 }
938
ttuttle859dc7a2015-04-23 19:42:29939 SaveCookiesAndNotifyHeadersComplete(OK);
[email protected]e5624f02011-09-27 19:43:53940 } else if (IsCertificateError(result)) {
[email protected]6061c142013-10-21 15:13:34941 // We encountered an SSL certificate error.
rsleevi9545d342016-06-21 03:17:37942 // Maybe overridable, maybe not. Ask the delegate to decide.
943 TransportSecurityState* state = context->transport_security_state();
944 NotifySSLCertificateError(
Emily Stark79fba5842019-04-25 04:59:36945 result, transaction_->GetResponseInfo()->ssl_info,
rsleevi9545d342016-06-21 03:17:37946 state->ShouldSSLErrorsBeFatal(request_info_.url.host()));
[email protected]5394e422011-01-20 22:07:43947 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
[email protected]a83dd332011-07-13 10:41:01948 NotifyCertificateRequested(
[email protected]90499482013-06-01 00:39:50949 transaction_->GetResponseInfo()->cert_request_info.get());
[email protected]5394e422011-01-20 22:07:43950 } else {
[email protected]419704c2014-01-14 11:18:06951 // Even on an error, there may be useful information in the response
952 // info (e.g. whether there's a cached copy).
953 if (transaction_.get())
954 response_info_ = transaction_->GetResponseInfo();
[email protected]5394e422011-01-20 22:07:43955 NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, result));
956 }
957}
958
[email protected]ea8141e2011-10-05 13:12:51959void URLRequestHttpJob::OnHeadersReceivedCallback(int result) {
[email protected]ea8141e2011-10-05 13:12:51960 awaiting_callback_ = false;
[email protected]9045b8822012-01-13 20:35:35961
962 // Check that there are no callbacks to already canceled requests.
963 DCHECK_NE(URLRequestStatus::CANCELED, GetStatus().status());
964
[email protected]ea8141e2011-10-05 13:12:51965 SaveCookiesAndNotifyHeadersComplete(result);
966}
967
[email protected]5394e422011-01-20 22:07:43968void URLRequestHttpJob::OnReadCompleted(int result) {
Alexandr Ilin33126632018-11-14 14:48:17969 TRACE_EVENT0(NetTracingCategory(), "URLRequestHttpJob::OnReadCompleted");
[email protected]5394e422011-01-20 22:07:43970 read_in_progress_ = false;
971
xunjieli26ede962015-11-23 19:39:13972 DCHECK_NE(ERR_IO_PENDING, result);
973
[email protected]f001bd6a2011-12-08 04:31:37974 if (ShouldFixMismatchedContentLength(result))
[email protected]5543cbb2012-04-20 16:35:23975 result = OK;
[email protected]f001bd6a2011-12-08 04:31:37976
xunjieli26ede962015-11-23 19:39:13977 // EOF or error, done with this job.
978 if (result <= 0)
979 DoneWithRequest(FINISHED);
[email protected]5394e422011-01-20 22:07:43980
xunjieli26ede962015-11-23 19:39:13981 ReadRawDataComplete(result);
[email protected]5394e422011-01-20 22:07:43982}
983
[email protected]5394e422011-01-20 22:07:43984void URLRequestHttpJob::RestartTransactionWithAuth(
[email protected]f3cf9802011-10-28 18:44:58985 const AuthCredentials& credentials) {
986 auth_credentials_ = credentials;
[email protected]5394e422011-01-20 22:07:43987
988 // These will be reset in OnStartCompleted.
David Benjamin0bda12f2018-02-07 19:58:45989 response_info_ = nullptr;
990 override_response_headers_ = nullptr; // See https://crbug.com/801237.
[email protected]3b23a222013-05-15 21:33:25991 receive_headers_end_ = base::TimeTicks();
[email protected]5394e422011-01-20 22:07:43992
[email protected]ec23f522011-02-22 21:01:38993 ResetTimer();
994
[email protected]5394e422011-01-20 22:07:43995 // Update the cookies, since the cookie store may have been updated from the
996 // headers in the 401/407. Since cookies were already appended to
997 // extra_headers, we need to strip them out before adding them again.
[email protected]ea8141e2011-10-05 13:12:51998 request_info_.extra_headers.RemoveHeader(HttpRequestHeaders::kCookie);
[email protected]5394e422011-01-20 22:07:43999
Aaron Tagliaboschifd4f3f012019-05-30 23:05:541000 // TODO(https://crbug.com/968327/): This is weird, as all other clearing is at
1001 // the URLRequest layer. Should this call into URLRequest so it can share
1002 // logic at that layer with SetAuth()?
Maks Orlovich15714232019-06-16 23:14:091003 request_->set_maybe_sent_cookies({});
1004 request_->set_maybe_stored_cookies({});
Aaron Tagliaboschifd4f3f012019-05-30 23:05:541005
[email protected]5394e422011-01-20 22:07:431006 AddCookieHeaderAndStart();
1007}
1008
[email protected]0736d9e2012-11-28 19:50:401009void URLRequestHttpJob::SetUpload(UploadDataStream* upload) {
[email protected]5394e422011-01-20 22:07:431010 DCHECK(!transaction_.get()) << "cannot change once started";
[email protected]0736d9e2012-11-28 19:50:401011 request_info_.upload_data_stream = upload;
[email protected]5394e422011-01-20 22:07:431012}
1013
1014void URLRequestHttpJob::SetExtraRequestHeaders(
1015 const HttpRequestHeaders& headers) {
1016 DCHECK(!transaction_.get()) << "cannot change once started";
1017 request_info_.extra_headers.CopyFrom(headers);
1018}
1019
[email protected]5394e422011-01-20 22:07:431020LoadState URLRequestHttpJob::GetLoadState() const {
1021 return transaction_.get() ?
1022 transaction_->GetLoadState() : LOAD_STATE_IDLE;
1023}
1024
[email protected]5394e422011-01-20 22:07:431025bool URLRequestHttpJob::GetMimeType(std::string* mime_type) const {
1026 DCHECK(transaction_.get());
1027
1028 if (!response_info_)
1029 return false;
1030
ellyjones0e9d5e82015-02-17 23:06:281031 HttpResponseHeaders* headers = GetResponseHeaders();
1032 if (!headers)
1033 return false;
1034 return headers->GetMimeType(mime_type);
[email protected]5394e422011-01-20 22:07:431035}
1036
1037bool URLRequestHttpJob::GetCharset(std::string* charset) {
1038 DCHECK(transaction_.get());
1039
1040 if (!response_info_)
1041 return false;
1042
[email protected]ea8141e2011-10-05 13:12:511043 return GetResponseHeaders()->GetCharset(charset);
[email protected]5394e422011-01-20 22:07:431044}
1045
1046void URLRequestHttpJob::GetResponseInfo(HttpResponseInfo* info) {
[email protected]ea8141e2011-10-05 13:12:511047 if (response_info_) {
[email protected]419704c2014-01-14 11:18:061048 DCHECK(transaction_.get());
1049
[email protected]5394e422011-01-20 22:07:431050 *info = *response_info_;
[email protected]90499482013-06-01 00:39:501051 if (override_response_headers_.get())
[email protected]ea8141e2011-10-05 13:12:511052 info->headers = override_response_headers_;
1053 }
[email protected]5394e422011-01-20 22:07:431054}
1055
[email protected]58e32bb2013-01-21 18:23:251056void URLRequestHttpJob::GetLoadTimingInfo(
1057 LoadTimingInfo* load_timing_info) const {
[email protected]3b23a222013-05-15 21:33:251058 // If haven't made it far enough to receive any headers, don't return
rdsmith81f607562014-11-21 18:35:161059 // anything. This makes for more consistent behavior in the case of errors.
[email protected]3b23a222013-05-15 21:33:251060 if (!transaction_ || receive_headers_end_.is_null())
1061 return;
1062 if (transaction_->GetLoadTimingInfo(load_timing_info))
1063 load_timing_info->receive_headers_end = receive_headers_end_;
[email protected]58e32bb2013-01-21 18:23:251064}
1065
Tsuyoshi Horo01faed62019-02-20 22:11:371066bool URLRequestHttpJob::GetTransactionRemoteEndpoint(
1067 IPEndPoint* endpoint) const {
ttuttled9dbc652015-09-29 20:00:591068 if (!transaction_)
1069 return false;
1070
1071 return transaction_->GetRemoteEndpoint(endpoint);
1072}
1073
[email protected]5394e422011-01-20 22:07:431074int URLRequestHttpJob::GetResponseCode() const {
1075 DCHECK(transaction_.get());
1076
1077 if (!response_info_)
1078 return -1;
1079
[email protected]ea8141e2011-10-05 13:12:511080 return GetResponseHeaders()->response_code();
[email protected]5394e422011-01-20 22:07:431081}
1082
zhongyi48704c182015-12-07 07:52:021083void URLRequestHttpJob::PopulateNetErrorDetails(
1084 NetErrorDetails* details) const {
1085 if (!transaction_)
1086 return;
1087 return transaction_->PopulateNetErrorDetails(details);
1088}
1089
xunjieli28a18772016-10-25 15:30:061090std::unique_ptr<SourceStream> URLRequestHttpJob::SetUpSourceStream() {
[email protected]5394e422011-01-20 22:07:431091 DCHECK(transaction_.get());
1092 if (!response_info_)
Bacek8f371552016-05-12 01:13:491093 return nullptr;
[email protected]5394e422011-01-20 22:07:431094
xunjieli28a18772016-10-25 15:30:061095 std::unique_ptr<SourceStream> upstream = URLRequestJob::SetUpSourceStream();
[email protected]ea8141e2011-10-05 13:12:511096 HttpResponseHeaders* headers = GetResponseHeaders();
xunjieli28a18772016-10-25 15:30:061097 std::string type;
1098 std::vector<SourceStream::SourceType> types;
olli.raulaee489a52016-01-25 08:37:101099 size_t iter = 0;
xunjieli28a18772016-10-25 15:30:061100 while (headers->EnumerateHeader(&iter, "Content-Encoding", &type)) {
eustasc7d27da2017-04-06 10:33:201101 SourceStream::SourceType source_type =
1102 FilterSourceStream::ParseEncodingType(type);
eustasc7d27da2017-04-06 10:33:201103 switch (source_type) {
1104 case SourceStream::TYPE_BROTLI:
1105 case SourceStream::TYPE_DEFLATE:
1106 case SourceStream::TYPE_GZIP:
eustasc7d27da2017-04-06 10:33:201107 types.push_back(source_type);
1108 break;
1109 case SourceStream::TYPE_NONE:
1110 // Identity encoding type. Pass through raw response body.
1111 return upstream;
Helen Li666c0682017-09-15 19:57:051112 case SourceStream::TYPE_UNKNOWN:
eustasc7d27da2017-04-06 10:33:201113 // Unknown encoding type. Pass through raw response body.
Paul Jensene85e8152019-07-01 15:38:001114 // Request will not be canceled; though
eustasc7d27da2017-04-06 10:33:201115 // it is expected that user will see malformed / garbage response.
eustasc7d27da2017-04-06 10:33:201116 return upstream;
Helen Li666c0682017-09-15 19:57:051117 case SourceStream::TYPE_GZIP_FALLBACK_DEPRECATED:
1118 case SourceStream::TYPE_SDCH_DEPRECATED:
1119 case SourceStream::TYPE_SDCH_POSSIBLE_DEPRECATED:
1120 case SourceStream::TYPE_REJECTED:
1121 case SourceStream::TYPE_INVALID:
1122 case SourceStream::TYPE_MAX:
1123 NOTREACHED();
1124 return nullptr;
eustasc7d27da2017-04-06 10:33:201125 }
[email protected]5394e422011-01-20 22:07:431126 }
1127
jdoerrie22a91d8b92018-10-05 08:43:261128 for (auto r_iter = types.rbegin(); r_iter != types.rend(); ++r_iter) {
xunjieli28a18772016-10-25 15:30:061129 std::unique_ptr<FilterSourceStream> downstream;
1130 SourceStream::SourceType type = *r_iter;
1131 switch (type) {
1132 case SourceStream::TYPE_BROTLI:
1133 downstream = CreateBrotliSourceStream(std::move(upstream));
1134 break;
xunjieli28a18772016-10-25 15:30:061135 case SourceStream::TYPE_GZIP:
1136 case SourceStream::TYPE_DEFLATE:
xunjieli28a18772016-10-25 15:30:061137 downstream = GzipSourceStream::Create(std::move(upstream), type);
1138 break;
Helen Li666c0682017-09-15 19:57:051139 case SourceStream::TYPE_GZIP_FALLBACK_DEPRECATED:
1140 case SourceStream::TYPE_SDCH_DEPRECATED:
1141 case SourceStream::TYPE_SDCH_POSSIBLE_DEPRECATED:
xunjieli28a18772016-10-25 15:30:061142 case SourceStream::TYPE_NONE:
1143 case SourceStream::TYPE_INVALID:
eustasc7d27da2017-04-06 10:33:201144 case SourceStream::TYPE_REJECTED:
1145 case SourceStream::TYPE_UNKNOWN:
xunjieli28a18772016-10-25 15:30:061146 case SourceStream::TYPE_MAX:
1147 NOTREACHED();
1148 return nullptr;
1149 }
1150 if (downstream == nullptr)
1151 return nullptr;
1152 upstream = std::move(downstream);
1153 }
1154
1155 return upstream;
[email protected]5394e422011-01-20 22:07:431156}
1157
[email protected]f878230e2014-04-03 15:36:141158bool URLRequestHttpJob::CopyFragmentOnRedirect(const GURL& location) const {
1159 // Allow modification of reference fragments by default, unless
Matt Menkeeed1a242019-10-23 21:26:061160 // |preserve_fragment_on_redirect_url_| is set and equal to the redirect URL.
1161 return !preserve_fragment_on_redirect_url_.has_value() ||
1162 preserve_fragment_on_redirect_url_ != location;
[email protected]f878230e2014-04-03 15:36:141163}
1164
[email protected]5394e422011-01-20 22:07:431165bool URLRequestHttpJob::IsSafeRedirect(const GURL& location) {
[email protected]e0f35c92013-05-08 16:04:341166 // HTTP is always safe.
1167 // TODO(pauljensen): Remove once crbug.com/146591 is fixed.
1168 if (location.is_valid() &&
1169 (location.scheme() == "http" || location.scheme() == "https")) {
[email protected]5394e422011-01-20 22:07:431170 return true;
[email protected]5394e422011-01-20 22:07:431171 }
[email protected]e0f35c92013-05-08 16:04:341172 // Query URLRequestJobFactory as to whether |location| would be safe to
1173 // redirect to.
1174 return request_->context()->job_factory() &&
1175 request_->context()->job_factory()->IsSafeRedirectTarget(location);
[email protected]5394e422011-01-20 22:07:431176}
1177
1178bool URLRequestHttpJob::NeedsAuth() {
1179 int code = GetResponseCode();
1180 if (code == -1)
1181 return false;
1182
rdsmith81f607562014-11-21 18:35:161183 // Check if we need either Proxy or WWW Authentication. This could happen
[email protected]5394e422011-01-20 22:07:431184 // because we either provided no auth info, or provided incorrect info.
1185 switch (code) {
1186 case 407:
1187 if (proxy_auth_state_ == AUTH_STATE_CANCELED)
1188 return false;
1189 proxy_auth_state_ = AUTH_STATE_NEED_AUTH;
1190 return true;
1191 case 401:
1192 if (server_auth_state_ == AUTH_STATE_CANCELED)
1193 return false;
1194 server_auth_state_ = AUTH_STATE_NEED_AUTH;
1195 return true;
1196 }
1197 return false;
1198}
1199
Emily Starkf2c9bbd2019-04-09 17:08:581200std::unique_ptr<AuthChallengeInfo> URLRequestHttpJob::GetAuthChallengeInfo() {
[email protected]5394e422011-01-20 22:07:431201 DCHECK(transaction_.get());
1202 DCHECK(response_info_);
1203
1204 // sanity checks:
1205 DCHECK(proxy_auth_state_ == AUTH_STATE_NEED_AUTH ||
1206 server_auth_state_ == AUTH_STATE_NEED_AUTH);
[email protected]9094b602012-02-27 21:44:581207 DCHECK((GetResponseHeaders()->response_code() == HTTP_UNAUTHORIZED) ||
1208 (GetResponseHeaders()->response_code() ==
1209 HTTP_PROXY_AUTHENTICATION_REQUIRED));
[email protected]5394e422011-01-20 22:07:431210
Emily Starkf2c9bbd2019-04-09 17:08:581211 if (!response_info_->auth_challenge.has_value())
1212 return nullptr;
1213 return std::make_unique<AuthChallengeInfo>(
1214 response_info_->auth_challenge.value());
[email protected]5394e422011-01-20 22:07:431215}
1216
[email protected]f3cf9802011-10-28 18:44:581217void URLRequestHttpJob::SetAuth(const AuthCredentials& credentials) {
[email protected]5394e422011-01-20 22:07:431218 DCHECK(transaction_.get());
1219
1220 // Proxy gets set first, then WWW.
1221 if (proxy_auth_state_ == AUTH_STATE_NEED_AUTH) {
1222 proxy_auth_state_ = AUTH_STATE_HAVE_AUTH;
1223 } else {
[email protected]dd29bcd72011-03-24 00:03:441224 DCHECK_EQ(server_auth_state_, AUTH_STATE_NEED_AUTH);
[email protected]5394e422011-01-20 22:07:431225 server_auth_state_ = AUTH_STATE_HAVE_AUTH;
1226 }
1227
[email protected]f3cf9802011-10-28 18:44:581228 RestartTransactionWithAuth(credentials);
[email protected]5394e422011-01-20 22:07:431229}
1230
1231void URLRequestHttpJob::CancelAuth() {
[email protected]5394e422011-01-20 22:07:431232 if (proxy_auth_state_ == AUTH_STATE_NEED_AUTH) {
1233 proxy_auth_state_ = AUTH_STATE_CANCELED;
1234 } else {
[email protected]dd29bcd72011-03-24 00:03:441235 DCHECK_EQ(server_auth_state_, AUTH_STATE_NEED_AUTH);
[email protected]5394e422011-01-20 22:07:431236 server_auth_state_ = AUTH_STATE_CANCELED;
1237 }
1238
Matt Menke0743e342019-06-11 20:48:101239 // The above lines should ensure this is the case.
1240 DCHECK(!NeedsAuth());
[email protected]5394e422011-01-20 22:07:431241
Matt Menke0743e342019-06-11 20:48:101242 // Let the consumer read the HTTP error page. NeedsAuth() should now return
1243 // false, so NotifyHeadersComplete() should not request auth from the client
1244 // again.
[email protected]5394e422011-01-20 22:07:431245 //
Matt Menke0743e342019-06-11 20:48:101246 // Have to do this via PostTask to avoid re-entrantly calling into the
1247 // consumer.
skyostil4891b25b2015-06-11 11:43:451248 base::ThreadTaskRunnerHandle::Get()->PostTask(
Matt Menke0743e342019-06-11 20:48:101249 FROM_HERE, base::BindOnce(&URLRequestHttpJob::NotifyFinalHeadersReceived,
1250 weak_factory_.GetWeakPtr()));
[email protected]5394e422011-01-20 22:07:431251}
1252
1253void URLRequestHttpJob::ContinueWithCertificate(
mattm436ccfe2017-06-19 20:24:081254 scoped_refptr<X509Certificate> client_cert,
1255 scoped_refptr<SSLPrivateKey> client_private_key) {
David Benjamin0bda12f2018-02-07 19:58:451256 DCHECK(transaction_);
[email protected]5394e422011-01-20 22:07:431257
1258 DCHECK(!response_info_) << "should not have a response yet";
David Benjamin0bda12f2018-02-07 19:58:451259 DCHECK(!override_response_headers_);
[email protected]3b23a222013-05-15 21:33:251260 receive_headers_end_ = base::TimeTicks();
[email protected]5394e422011-01-20 22:07:431261
[email protected]ec23f522011-02-22 21:01:381262 ResetTimer();
1263
mmenked3a02b32016-11-16 20:21:321264 int rv = transaction_->RestartWithCertificate(
mattm436ccfe2017-06-19 20:24:081265 std::move(client_cert), std::move(client_private_key),
Yannic Bonenbergercc716d42019-09-04 17:05:361266 base::BindOnce(&URLRequestHttpJob::OnStartCompleted,
1267 base::Unretained(this)));
[email protected]5394e422011-01-20 22:07:431268 if (rv == ERR_IO_PENDING)
1269 return;
1270
1271 // The transaction started synchronously, but we need to notify the
1272 // URLRequest delegate via the message loop.
skyostil4891b25b2015-06-11 11:43:451273 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf4fe5172019-02-15 18:53:491274 FROM_HERE, base::BindOnce(&URLRequestHttpJob::OnStartCompleted,
1275 weak_factory_.GetWeakPtr(), rv));
[email protected]5394e422011-01-20 22:07:431276}
1277
1278void URLRequestHttpJob::ContinueDespiteLastError() {
1279 // If the transaction was destroyed, then the job was cancelled.
1280 if (!transaction_.get())
1281 return;
1282
1283 DCHECK(!response_info_) << "should not have a response yet";
David Benjamin0bda12f2018-02-07 19:58:451284 DCHECK(!override_response_headers_);
[email protected]3b23a222013-05-15 21:33:251285 receive_headers_end_ = base::TimeTicks();
[email protected]5394e422011-01-20 22:07:431286
[email protected]ec23f522011-02-22 21:01:381287 ResetTimer();
1288
Yannic Bonenbergercc716d42019-09-04 17:05:361289 int rv = transaction_->RestartIgnoringLastError(base::BindOnce(
1290 &URLRequestHttpJob::OnStartCompleted, base::Unretained(this)));
[email protected]5394e422011-01-20 22:07:431291 if (rv == ERR_IO_PENDING)
1292 return;
1293
1294 // The transaction started synchronously, but we need to notify the
1295 // URLRequest delegate via the message loop.
skyostil4891b25b2015-06-11 11:43:451296 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf4fe5172019-02-15 18:53:491297 FROM_HERE, base::BindOnce(&URLRequestHttpJob::OnStartCompleted,
1298 weak_factory_.GetWeakPtr(), rv));
[email protected]5394e422011-01-20 22:07:431299}
1300
[email protected]f001bd6a2011-12-08 04:31:371301bool URLRequestHttpJob::ShouldFixMismatchedContentLength(int rv) const {
1302 // Some servers send the body compressed, but specify the content length as
rdsmith81f607562014-11-21 18:35:161303 // the uncompressed size. Although this violates the HTTP spec we want to
[email protected]f001bd6a2011-12-08 04:31:371304 // support it (as IE and FireFox do), but *only* for an exact match.
1305 // See http://crbug.com/79694.
ttuttle859dc7a2015-04-23 19:42:291306 if (rv == ERR_CONTENT_LENGTH_MISMATCH ||
1307 rv == ERR_INCOMPLETE_CHUNKED_ENCODING) {
mmenked3a02b32016-11-16 20:21:321308 if (request_->response_headers()) {
Avi Drissman13fc8932015-12-20 04:40:461309 int64_t expected_length =
1310 request_->response_headers()->GetContentLength();
pkastingf5279482016-07-27 02:18:201311 VLOG(1) << __func__ << "() \"" << request_->url().spec() << "\""
[email protected]f001bd6a2011-12-08 04:31:371312 << " content-length = " << expected_length
1313 << " pre total = " << prefilter_bytes_read()
1314 << " post total = " << postfilter_bytes_read();
1315 if (postfilter_bytes_read() == expected_length) {
1316 // Clear the error.
1317 return true;
1318 }
1319 }
1320 }
1321 return false;
1322}
1323
xunjieli26ede962015-11-23 19:39:131324int URLRequestHttpJob::ReadRawData(IOBuffer* buf, int buf_size) {
[email protected]5394e422011-01-20 22:07:431325 DCHECK_NE(buf_size, 0);
[email protected]5394e422011-01-20 22:07:431326 DCHECK(!read_in_progress_);
1327
Yannic Bonenbergercc716d42019-09-04 17:05:361328 int rv =
1329 transaction_->Read(buf, buf_size,
1330 base::BindOnce(&URLRequestHttpJob::OnReadCompleted,
1331 base::Unretained(this)));
[email protected]85c1dce2011-07-06 12:01:291332
[email protected]f001bd6a2011-12-08 04:31:371333 if (ShouldFixMismatchedContentLength(rv))
xunjieli26ede962015-11-23 19:39:131334 rv = OK;
[email protected]f001bd6a2011-12-08 04:31:371335
xunjieli26ede962015-11-23 19:39:131336 if (rv == 0 || (rv < 0 && rv != ERR_IO_PENDING))
1337 DoneWithRequest(FINISHED);
[email protected]5394e422011-01-20 22:07:431338
xunjieli26ede962015-11-23 19:39:131339 if (rv == ERR_IO_PENDING)
[email protected]5394e422011-01-20 22:07:431340 read_in_progress_ = true;
[email protected]5394e422011-01-20 22:07:431341
xunjieli26ede962015-11-23 19:39:131342 return rv;
[email protected]5394e422011-01-20 22:07:431343}
1344
Avi Drissman13fc8932015-12-20 04:40:461345int64_t URLRequestHttpJob::GetTotalReceivedBytes() const {
sclittlece72c482015-08-24 20:20:591346 int64_t total_received_bytes =
1347 total_received_bytes_from_previous_transactions_;
1348 if (transaction_)
1349 total_received_bytes += transaction_->GetTotalReceivedBytes();
1350 return total_received_bytes;
[email protected]71e5ff8f2014-01-13 09:44:041351}
1352
sclittlefb249892015-09-10 21:33:221353int64_t URLRequestHttpJob::GetTotalSentBytes() const {
1354 int64_t total_sent_bytes = total_sent_bytes_from_previous_transactions_;
1355 if (transaction_)
1356 total_sent_bytes += transaction_->GetTotalSentBytes();
1357 return total_sent_bytes;
1358}
1359
[email protected]5c04f722011-08-12 17:52:471360void URLRequestHttpJob::DoneReading() {
[email protected]e50efea2014-03-24 18:41:001361 if (transaction_) {
[email protected]5c04f722011-08-12 17:52:471362 transaction_->DoneReading();
[email protected]e50efea2014-03-24 18:41:001363 }
1364 DoneWithRequest(FINISHED);
1365}
1366
1367void URLRequestHttpJob::DoneReadingRedirectResponse() {
1368 if (transaction_) {
Raul Tambre94493c652019-03-11 17:18:351369 if (transaction_->GetResponseInfo()->headers->IsRedirect(nullptr)) {
[email protected]e50efea2014-03-24 18:41:001370 // If the original headers indicate a redirect, go ahead and cache the
1371 // response, even if the |override_response_headers_| are a redirect to
1372 // another location.
1373 transaction_->DoneReading();
1374 } else {
1375 // Otherwise, |override_response_headers_| must be non-NULL and contain
1376 // bogus headers indicating a redirect.
dchengc2e01e82014-08-27 00:24:421377 DCHECK(override_response_headers_.get());
Raul Tambre94493c652019-03-11 17:18:351378 DCHECK(override_response_headers_->IsRedirect(nullptr));
[email protected]e50efea2014-03-24 18:41:001379 transaction_->StopCaching();
1380 }
1381 }
[email protected]5c04f722011-08-12 17:52:471382 DoneWithRequest(FINISHED);
1383}
1384
Tsuyoshi Horo01faed62019-02-20 22:11:371385IPEndPoint URLRequestHttpJob::GetResponseRemoteEndpoint() const {
1386 return response_info_ ? response_info_->remote_endpoint : IPEndPoint();
[email protected]6d81b482011-02-22 19:47:191387}
1388
[email protected]ec23f522011-02-22 21:01:381389void URLRequestHttpJob::RecordTimer() {
1390 if (request_creation_time_.is_null()) {
1391 NOTREACHED()
1392 << "The same transaction shouldn't start twice without new timing.";
1393 return;
1394 }
1395
[email protected]320a29f12011-03-21 14:47:411396 base::TimeDelta to_start = base::Time::Now() - request_creation_time_;
[email protected]ec23f522011-02-22 21:01:381397 request_creation_time_ = base::Time();
[email protected]8684a8812011-03-22 13:59:381398
[email protected]5c68d692011-08-24 04:59:411399 UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpTimeToFirstByte", to_start);
[email protected]ec23f522011-02-22 21:01:381400}
1401
1402void URLRequestHttpJob::ResetTimer() {
1403 if (!request_creation_time_.is_null()) {
1404 NOTREACHED()
1405 << "The timer was reset before it was recorded.";
1406 return;
1407 }
1408 request_creation_time_ = base::Time::Now();
1409}
1410
Andrey Kosyakov83a6eee2017-08-14 19:20:041411void URLRequestHttpJob::SetRequestHeadersCallback(
1412 RequestHeadersCallback callback) {
1413 DCHECK(!transaction_);
1414 DCHECK(!request_headers_callback_);
1415 request_headers_callback_ = std::move(callback);
1416}
1417
Andrey Kosyakov2e893e62017-08-31 17:00:521418void URLRequestHttpJob::SetResponseHeadersCallback(
1419 ResponseHeadersCallback callback) {
1420 DCHECK(!transaction_);
1421 DCHECK(!response_headers_callback_);
1422 response_headers_callback_ = std::move(callback);
1423}
1424
[email protected]bbaea8f2011-06-24 00:11:011425void URLRequestHttpJob::RecordPerfHistograms(CompletionCause reason) {
1426 if (start_time_.is_null())
1427 return;
1428
1429 base::TimeDelta total_time = base::TimeTicks::Now() - start_time_;
1430 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTime", total_time);
1431
1432 if (reason == FINISHED) {
Devdeep Ray0c6966d2017-07-14 00:58:221433 UmaHistogramTimes(
1434 base::StringPrintf("Net.HttpJob.TotalTimeSuccess.Priority%d",
1435 request()->priority()),
1436 total_time);
[email protected]bbaea8f2011-06-24 00:11:011437 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeSuccess", total_time);
1438 } else {
1439 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeCancel", total_time);
1440 }
1441
[email protected]4b4d20242012-02-23 18:27:461442 if (response_info_) {
rtennetie55c4b72015-08-03 21:48:351443 // QUIC (by default) supports https scheme only, thus track https URLs only
1444 // for QUIC.
1445 bool is_https_google = request() && request()->url().SchemeIs("https") &&
1446 HasGoogleHost(request()->url());
rtenneti72928bb2015-04-28 18:28:131447 bool used_quic = response_info_->DidUseQuic();
rtennetie55c4b72015-08-03 21:48:351448 if (is_https_google) {
rtenneti72928bb2015-04-28 18:28:131449 if (used_quic) {
rtennetie55c4b72015-08-03 21:48:351450 UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpJob.TotalTime.Secure.Quic",
1451 total_time);
rtenneti72928bb2015-04-28 18:28:131452 }
1453 }
jkarlinded0021b2016-12-05 16:01:061454
1455 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpJob.PrefilterBytesRead",
1456 prefilter_bytes_read(), 1, 50000000, 50);
[email protected]4b4d20242012-02-23 18:27:461457 if (response_info_->was_cached) {
1458 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeCached", total_time);
jkarlinded0021b2016-12-05 16:01:061459 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpJob.PrefilterBytesRead.Cache",
1460 prefilter_bytes_read(), 1, 50000000, 50);
1461
jkarlincc6943d2016-04-25 19:25:351462 if (response_info_->unused_since_prefetch)
Steven Holte6143e642017-06-28 19:47:381463 UMA_HISTOGRAM_COUNTS_1M("Net.Prefetch.HitBytes",
1464 prefilter_bytes_read());
jkarlincc6943d2016-04-25 19:25:351465 } else {
[email protected]4b4d20242012-02-23 18:27:461466 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeNotCached", total_time);
jkarlinded0021b2016-12-05 16:01:061467 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpJob.PrefilterBytesRead.Net",
1468 prefilter_bytes_read(), 1, 50000000, 50);
1469
1470 if (request_info_.load_flags & LOAD_PREFETCH) {
Steven Holte6143e642017-06-28 19:47:381471 UMA_HISTOGRAM_COUNTS_1M("Net.Prefetch.PrefilterBytesReadFromNetwork",
1472 prefilter_bytes_read());
jkarlinded0021b2016-12-05 16:01:061473 }
rtennetie55c4b72015-08-03 21:48:351474 if (is_https_google) {
rtenneti72928bb2015-04-28 18:28:131475 if (used_quic) {
rtennetie55c4b72015-08-03 21:48:351476 UMA_HISTOGRAM_MEDIUM_TIMES(
1477 "Net.HttpJob.TotalTimeNotCached.Secure.Quic", total_time);
rtenneti72928bb2015-04-28 18:28:131478 } else {
rtennetie55c4b72015-08-03 21:48:351479 UMA_HISTOGRAM_MEDIUM_TIMES(
1480 "Net.HttpJob.TotalTimeNotCached.Secure.NotQuic", total_time);
rtenneti72928bb2015-04-28 18:28:131481 }
1482 }
[email protected]b73656ca2011-07-22 17:42:171483 }
[email protected]bbaea8f2011-06-24 00:11:011484 }
1485
1486 start_time_ = base::TimeTicks();
1487}
1488
1489void URLRequestHttpJob::DoneWithRequest(CompletionCause reason) {
1490 if (done_)
1491 return;
1492 done_ = true;
tbansal79ed5cd2015-08-10 18:53:561493
1494 // Notify NetworkQualityEstimator.
mmenke7ce675a2016-11-07 17:08:301495 NetworkQualityEstimator* network_quality_estimator =
1496 request()->context()->network_quality_estimator();
1497 if (network_quality_estimator) {
1498 network_quality_estimator->NotifyRequestCompleted(
1499 *request(), request_->status().error());
tbansal79ed5cd2015-08-10 18:53:561500 }
1501
[email protected]bbaea8f2011-06-24 00:11:011502 RecordPerfHistograms(reason);
mmenke7ce675a2016-11-07 17:08:301503 request()->set_received_response_content_length(prefilter_bytes_read());
[email protected]bbaea8f2011-06-24 00:11:011504}
1505
[email protected]ea8141e2011-10-05 13:12:511506HttpResponseHeaders* URLRequestHttpJob::GetResponseHeaders() const {
1507 DCHECK(transaction_.get());
1508 DCHECK(transaction_->GetResponseInfo());
1509 return override_response_headers_.get() ?
[email protected]90499482013-06-01 00:39:501510 override_response_headers_.get() :
1511 transaction_->GetResponseInfo()->headers.get();
[email protected]ea8141e2011-10-05 13:12:511512}
1513
1514void URLRequestHttpJob::NotifyURLRequestDestroyed() {
1515 awaiting_callback_ = false;
tbansal80a52162016-05-20 17:55:041516
1517 // Notify NetworkQualityEstimator.
mmenke7ce675a2016-11-07 17:08:301518 NetworkQualityEstimator* network_quality_estimator =
1519 request()->context()->network_quality_estimator();
1520 if (network_quality_estimator)
1521 network_quality_estimator->NotifyURLRequestDestroyed(*request());
[email protected]ea8141e2011-10-05 13:12:511522}
1523
[email protected]4f5656c62010-12-13 10:47:091524} // namespace net