blob: dc5c2d9ab617b4b1eefb91cd4d827a44fec9187b [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>
cfredric59f8a8452021-06-08 15:27:118#include <iterator>
Eric Orthcd71ede2021-09-14 18:18:509#include <memory>
Eric Lawrencef814f5b22019-10-04 01:52:4310#include <utility>
mmenked3a02b32016-11-16 20:21:3211#include <vector>
12
[email protected]4ed2755f2008-12-15 09:01:3313#include "base/base_switches.h"
[email protected]4f9e5c82011-11-17 16:04:5614#include "base/bind.h"
danakjdb9ae7942020-11-11 16:01:3515#include "base/callback_helpers.h"
Eric Orthcd71ede2021-09-14 18:18:5016#include "base/check_op.h"
[email protected]4ed2755f2008-12-15 09:01:3317#include "base/command_line.h"
[email protected]39ce5c02008-08-22 04:03:4418#include "base/compiler_specific.h"
[email protected]60889422008-09-23 01:18:1619#include "base/file_version_info.h"
skyostil4891b25b2015-06-11 11:43:4520#include "base/location.h"
danakj9eb5b722020-11-07 03:03:0921#include "base/memory/ptr_util.h"
[email protected]8684a8812011-03-22 13:59:3822#include "base/metrics/field_trial.h"
Devdeep Ray0c6966d2017-07-14 00:58:2223#include "base/metrics/histogram_functions.h"
asvitkinec3c93722015-06-17 14:48:3724#include "base/metrics/histogram_macros.h"
Mike Westfbd44112019-05-08 18:23:3725#include "base/numerics/safe_conversions.h"
[email protected]5b90b5d2009-04-30 23:06:0126#include "base/rand_util.h"
[email protected]4dc3ad4f2013-06-11 07:15:5027#include "base/strings/string_util.h"
Devdeep Ray0c6966d2017-07-14 00:58:2228#include "base/strings/stringprintf.h"
Patrick Monette643cdf62021-10-15 19:13:4229#include "base/task/single_thread_task_runner.h"
gabf767595f2016-05-11 18:50:3530#include "base/threading/thread_task_runner_handle.h"
[email protected]f002abb2013-06-28 02:30:2131#include "base/time/time.h"
ssid6d6b40102016-04-05 18:59:5632#include "base/trace_event/trace_event.h"
estade5e5529d2015-05-21 20:59:1133#include "base/values.h"
cfredric362c4a02021-07-09 22:40:4034#include "build/build_config.h"
Mike Westfbd44112019-05-08 18:23:3735#include "net/base/features.h"
[email protected]6d81b482011-02-22 19:47:1936#include "net/base/host_port_pair.h"
Matt Menked732ea42019-03-08 12:05:0037#include "net/base/http_user_agent_settings.h"
[email protected]b8430722008-09-17 20:05:4438#include "net/base/load_flags.h"
initial.commit586acc5fe2008-07-26 22:42:5239#include "net/base/net_errors.h"
[email protected]636eccd2011-06-28 12:28:0140#include "net/base/network_delegate.h"
Shivani Sharmad81bdd42019-05-23 17:19:5641#include "net/base/network_isolation_key.h"
mkwstf71d0bd2016-03-21 14:15:2442#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
xunjieli0b7f5b62016-12-06 20:43:4843#include "net/base/trace_constants.h"
tfarina7a4a7fd2016-01-20 14:23:4444#include "net/base/url_util.h"
[email protected]6e7845ae2013-03-29 21:48:1145#include "net/cert/cert_status_flags.h"
Emily Stark8b411de02017-11-23 20:21:2746#include "net/cert/ct_policy_status.h"
Ryan Sleevi19a7bde2017-11-22 06:51:3947#include "net/cert/known_roots.h"
Randy Smithe23356c22017-11-14 01:41:5048#include "net/cookies/canonical_cookie.h"
Shuran Huang9faced62021-01-05 23:19:5549#include "net/cookies/cookie_access_delegate.h"
cfredric176f9e232021-05-12 20:20:1450#include "net/cookies/cookie_constants.h"
[email protected]dc8313a2014-03-24 21:38:1451#include "net/cookies/cookie_store.h"
Maks Orlovich64e2913d2019-03-05 14:42:5652#include "net/cookies/cookie_util.h"
cfredric362c4a02021-07-09 22:40:4053#include "net/cookies/same_party_context.h"
xunjieli28a18772016-10-25 15:30:0654#include "net/filter/brotli_source_stream.h"
55#include "net/filter/filter_source_stream.h"
56#include "net/filter/gzip_source_stream.h"
xunjieli28a18772016-10-25 15:30:0657#include "net/filter/source_stream.h"
[email protected]262191712014-03-22 00:46:5758#include "net/http/http_content_disposition.h"
Eric Orthcd71ede2021-09-14 18:18:5059#include "net/http/http_log_util.h"
[email protected]7a299a92012-10-24 23:54:5060#include "net/http/http_network_session.h"
[email protected]8c76ae22010-04-20 22:15:4361#include "net/http/http_request_headers.h"
[email protected]319d9e6f2009-02-18 19:47:2162#include "net/http/http_response_headers.h"
initial.commit586acc5fe2008-07-26 22:42:5263#include "net/http/http_response_info.h"
[email protected]9094b602012-02-27 21:44:5864#include "net/http/http_status_code.h"
initial.commit586acc5fe2008-07-26 22:42:5265#include "net/http/http_transaction.h"
66#include "net/http/http_transaction_factory.h"
[email protected]0757e7702009-03-27 04:00:2267#include "net/http/http_util.h"
Matt Menkece5d765372021-08-17 18:24:1268#include "net/http/transport_security_state.h"
Ryan Hamilton0bed1572018-03-02 19:58:2169#include "net/log/net_log.h"
mikecirone8b85c432016-09-08 19:11:0070#include "net/log/net_log_event_type.h"
Imam Mohammad Bokhary374b339a2019-09-27 16:35:1971#include "net/log/net_log_values.h"
mikecironef22f9812016-10-04 03:40:1972#include "net/log/net_log_with_source.h"
tbansalca83c002016-04-28 20:56:2873#include "net/nqe/network_quality_estimator.h"
Lily Houghton582d4622018-01-22 22:43:4074#include "net/proxy_resolution/proxy_info.h"
Nicolas Arciniega8ec5bfa2020-03-20 05:07:2675#include "net/proxy_resolution/proxy_resolution_service.h"
Lily Houghton582d4622018-01-22 22:43:4076#include "net/proxy_resolution/proxy_retry_info.h"
[email protected]536fd0b2013-03-14 17:41:5777#include "net/ssl/ssl_cert_request_info.h"
78#include "net/ssl/ssl_config_service.h"
David Benjaminb3125022021-05-10 19:57:0879#include "net/ssl/ssl_connection_status_flags.h"
Eric Orthcd71ede2021-09-14 18:18:5080#include "net/url_request/redirect_util.h"
initial.commit586acc5fe2008-07-26 22:42:5281#include "net/url_request/url_request.h"
[email protected]319d9e6f2009-02-18 19:47:2182#include "net/url_request/url_request_context.h"
initial.commit586acc5fe2008-07-26 22:42:5283#include "net/url_request/url_request_error_job.h"
[email protected]e0f35c92013-05-08 16:04:3484#include "net/url_request/url_request_job_factory.h"
[email protected]06965e02009-09-04 21:36:4285#include "net/url_request/url_request_redirect_job.h"
[email protected]6b3f9642010-11-25 02:29:0686#include "net/url_request/url_request_throttler_manager.h"
Bence Békya5ec55e62018-03-07 14:23:2887#include "net/url_request/websocket_handshake_userdata_key.h"
Anton Bikineev068d2912021-05-15 20:43:5288#include "third_party/abseil-cpp/absl/types/optional.h"
Eric Orthcd71ede2021-09-14 18:18:5089#include "url/gurl.h"
mkwst8241a122015-10-20 07:15:1090#include "url/origin.h"
Eric Orthcd71ede2021-09-14 18:18:5091#include "url/url_constants.h"
initial.commit586acc5fe2008-07-26 22:42:5292
mgershd21d6d142016-12-14 23:06:3693#if defined(OS_ANDROID)
94#include "net/android/network_library.h"
95#endif
96
mkwst202534e32016-01-15 16:07:1597namespace {
98
Lily Chen201128342019-12-11 21:17:0399base::Value CookieInclusionStatusNetLogParams(
100 const std::string& operation,
101 const std::string& cookie_name,
102 const std::string& cookie_domain,
103 const std::string& cookie_path,
Jihwan Marc Kim3e132f12020-05-20 17:33:19104 const net::CookieInclusionStatus& status,
Lily Chen201128342019-12-11 21:17:03105 net::NetLogCaptureMode capture_mode) {
Eric Lawrencef814f5b22019-10-04 01:52:43106 base::Value dict(base::Value::Type::DICTIONARY);
107 dict.SetStringKey("operation", operation);
Lily Chen201128342019-12-11 21:17:03108 dict.SetStringKey("status", status.GetDebugString());
Lily Chende9f12c2019-12-10 22:08:15109 if (net::NetLogCaptureIncludesSensitive(capture_mode)) {
110 if (!cookie_name.empty())
111 dict.SetStringKey("name", cookie_name);
112 if (!cookie_domain.empty())
113 dict.SetStringKey("domain", cookie_domain);
114 if (!cookie_path.empty())
115 dict.SetStringKey("path", cookie_path);
Eric Lawrencef814f5b22019-10-04 01:52:43116 }
117 return dict;
118}
119
Ryan Sleevi19a7bde2017-11-22 06:51:39120// Records details about the most-specific trust anchor in |spki_hashes|,
121// which is expected to be ordered with the leaf cert first and the root cert
122// last. This complements the per-verification histogram
123// Net.Certificate.TrustAnchor.Verify
124void LogTrustAnchor(const net::HashValueVector& spki_hashes) {
Ryan Sleevid756c2d2017-12-01 02:07:48125 // Don't record metrics if there are no hashes; this is true if the HTTP
126 // load did not come from an active network connection, such as the disk
127 // cache or a synthesized response.
128 if (spki_hashes.empty())
129 return;
130
Ryan Sleevi19a7bde2017-11-22 06:51:39131 int32_t id = 0;
132 for (const auto& hash : spki_hashes) {
133 id = net::GetNetTrustAnchorHistogramIdForSPKI(hash);
134 if (id != 0)
135 break;
136 }
Ilya Sherman0eb39802017-12-08 20:58:18137 base::UmaHistogramSparse("Net.Certificate.TrustAnchor.Request", id);
Ryan Sleevi19a7bde2017-11-22 06:51:39138}
139
Shuran Huang57f97b22020-11-11 14:53:49140net::CookieOptions CreateCookieOptions(
Shuran Huang9faced62021-01-05 23:19:55141 net::CookieOptions::SameSiteCookieContext same_site_context,
cfredric362c4a02021-07-09 22:40:40142 const net::SamePartyContext& same_party_context,
cfredric908f7392021-01-12 05:56:54143 const net::IsolationInfo& isolation_info,
144 bool is_in_nontrivial_first_party_set) {
Shuran Huang57f97b22020-11-11 14:53:49145 net::CookieOptions options;
146 options.set_return_excluded_cookies();
147 options.set_include_httponly();
Shuran Huang9faced62021-01-05 23:19:55148 options.set_same_site_cookie_context(same_site_context);
cfredric362c4a02021-07-09 22:40:40149 options.set_same_party_context(same_party_context);
Shuran Huang9faced62021-01-05 23:19:55150 if (isolation_info.party_context().has_value()) {
151 // Count the top-frame site since it's not in the party_context.
152 options.set_full_party_context_size(isolation_info.party_context()->size() +
153 1);
154 }
cfredric908f7392021-01-12 05:56:54155 options.set_is_in_nontrivial_first_party_set(
156 is_in_nontrivial_first_party_set);
Shuran Huang57f97b22020-11-11 14:53:49157 return options;
158}
159
David Benjaminb3125022021-05-10 19:57:08160bool IsTLS13OverTCP(const net::HttpResponseInfo& response_info) {
161 // Although IETF QUIC also uses TLS 1.3, our QUIC connections report
162 // SSL_CONNECTION_VERSION_QUIC.
163 return net::SSLConnectionStatusToVersion(
164 response_info.ssl_info.connection_status) ==
165 net::SSL_CONNECTION_VERSION_TLS1_3;
166}
167
Eric Orthcd71ede2021-09-14 18:18:50168GURL UpgradeSchemeToCryptographic(const GURL& insecure_url) {
169 DCHECK(!insecure_url.SchemeIsCryptographic());
170 DCHECK(insecure_url.SchemeIs(url::kHttpScheme) ||
171 insecure_url.SchemeIs(url::kWsScheme));
172
173 GURL::Replacements replacements;
174 replacements.SetSchemeStr(insecure_url.SchemeIs(url::kHttpScheme)
175 ? url::kHttpsScheme
176 : url::kWssScheme);
177
178 GURL secure_url = insecure_url.ReplaceComponents(replacements);
179 DCHECK(secure_url.SchemeIsCryptographic());
180
181 return secure_url;
182}
183
mkwst202534e32016-01-15 16:07:15184} // namespace
185
[email protected]4f5656c62010-12-13 10:47:09186namespace net {
187
Matt Menkefd978852020-09-15 16:00:57188std::unique_ptr<URLRequestJob> URLRequestHttpJob::Create(URLRequest* request) {
mgershd21d6d142016-12-14 23:06:36189 const GURL& url = request->url();
190
Matt Menkeef60ff72020-09-14 11:21:17191 // URLRequestContext must have been initialized.
192 DCHECK(request->context()->http_transaction_factory());
193 DCHECK(url.SchemeIsHTTPOrHTTPS() || url.SchemeIsWSOrWSS());
194
mgershd21d6d142016-12-14 23:06:36195 // Check for reasons not to return a URLRequestHttpJob. These don't apply to
196 // https and wss requests.
197 if (!url.SchemeIsCryptographic()) {
198 // Check for HSTS upgrade.
199 TransportSecurityState* hsts =
200 request->context()->transport_security_state();
201 if (hsts && hsts->ShouldUpgradeToSSL(url.host())) {
Matt Menkeef60ff72020-09-14 11:21:17202 return std::make_unique<URLRequestRedirectJob>(
Eric Orthcd71ede2021-09-14 18:18:50203 request, UpgradeSchemeToCryptographic(url),
mgershd21d6d142016-12-14 23:06:36204 // Use status code 307 to preserve the method, so POST requests work.
Eric Orthcd71ede2021-09-14 18:18:50205 RedirectUtil::ResponseCode::REDIRECT_307_TEMPORARY_REDIRECT, "HSTS");
mgershd21d6d142016-12-14 23:06:36206 }
207
208#if defined(OS_ANDROID)
209 // Check whether the app allows cleartext traffic to this host, and return
mgersh072720a2016-12-15 16:33:34210 // ERR_CLEARTEXT_NOT_PERMITTED if not.
mgershd21d6d142016-12-14 23:06:36211 if (request->context()->check_cleartext_permitted() &&
212 !android::IsCleartextPermitted(url.host())) {
Matt Menkefd978852020-09-15 16:00:57213 return std::make_unique<URLRequestErrorJob>(request,
Matt Menkeef60ff72020-09-14 11:21:17214 ERR_CLEARTEXT_NOT_PERMITTED);
mgershd21d6d142016-12-14 23:06:36215 }
216#endif
217 }
mkwst549a5c632016-06-20 14:17:03218
Matt Menkefd978852020-09-15 16:00:57219 return base::WrapUnique<URLRequestJob>(new URLRequestHttpJob(
220 request, request->context()->http_user_agent_settings()));
initial.commit586acc5fe2008-07-26 22:42:52221}
222
[email protected]ee4c30d2012-11-07 15:08:43223URLRequestHttpJob::URLRequestHttpJob(
224 URLRequest* request,
[email protected]ee4c30d2012-11-07 15:08:43225 const HttpUserAgentSettings* http_user_agent_settings)
Matt Menkefd978852020-09-15 16:00:57226 : URLRequestJob(request),
Aaron Tagliaboschi028009e2019-03-07 16:28:06227 num_cookie_lines_left_(0),
[email protected]5033ab82013-03-22 20:17:46228 priority_(DEFAULT_PRIORITY),
mmenke54e82af2016-02-16 23:06:30229 response_info_(nullptr),
[email protected]4f5656c62010-12-13 10:47:09230 proxy_auth_state_(AUTH_STATE_DONT_NEED_AUTH),
231 server_auth_state_(AUTH_STATE_DONT_NEED_AUTH),
[email protected]3589e552008-08-20 23:11:34232 read_in_progress_(false),
mmenke54e82af2016-02-16 23:06:30233 throttling_entry_(nullptr),
[email protected]bbaea8f2011-06-24 00:11:01234 done_(false),
[email protected]5a07c192012-07-30 20:18:22235 awaiting_callback_(false),
[email protected]09812102014-05-24 00:04:11236 http_user_agent_settings_(http_user_agent_settings),
sclittlece72c482015-08-24 20:20:59237 total_received_bytes_from_previous_transactions_(0),
Jeremy Romand54000b22019-07-08 18:40:16238 total_sent_bytes_from_previous_transactions_(0) {
[email protected]a73a2802012-05-02 19:20:15239 URLRequestThrottlerManager* manager = request->context()->throttler_manager();
240 if (manager)
241 throttling_entry_ = manager->RegisterRequestUrl(request->url());
242
[email protected]ec23f522011-02-22 21:01:38243 ResetTimer();
Dylan Cutler69a51c92021-12-08 16:32:01244 ComputeCookiePartitionKey();
initial.commit586acc5fe2008-07-26 22:42:52245}
246
[email protected]5033ab82013-03-22 20:17:46247URLRequestHttpJob::~URLRequestHttpJob() {
248 CHECK(!awaiting_callback_);
249
[email protected]5033ab82013-03-22 20:17:46250 DoneWithRequest(ABORTED);
251}
252
253void URLRequestHttpJob::SetPriority(RequestPriority priority) {
254 priority_ = priority;
255 if (transaction_)
256 transaction_->SetPriority(priority_);
257}
258
259void URLRequestHttpJob::Start() {
260 DCHECK(!transaction_.get());
261
[email protected]99ecf6e2013-04-10 22:46:13262 // URLRequest::SetReferrer ensures that we do not send username and password
263 // fields in the referrer.
264 GURL referrer(request_->referrer());
[email protected]5033ab82013-03-22 20:17:46265
266 request_info_.url = request_->url();
267 request_info_.method = request_->method();
Shivani Sharmad81bdd42019-05-23 17:19:56268
Matt Menke3ab9c7b2020-04-01 22:39:57269 request_info_.network_isolation_key =
270 request_->isolation_info().network_isolation_key();
Matt Menkee6e4f392020-10-08 11:41:29271 request_info_.possibly_top_frame_origin =
272 request_->isolation_info().top_frame_origin();
shivanigithubc688ced2020-11-04 19:46:15273 request_info_.is_subframe_document_resource =
274 request_->isolation_info().request_type() ==
275 net::IsolationInfo::RequestType::kSubFrame;
[email protected]5033ab82013-03-22 20:17:46276 request_info_.load_flags = request_->load_flags();
Ben Schwartz3ff4dc1e62021-04-27 21:15:23277 request_info_.secure_dns_policy = request_->secure_dns_policy();
Ramin Halavatib5e433e62018-02-07 07:41:10278 request_info_.traffic_annotation =
279 net::MutableNetworkTrafficAnnotationTag(request_->traffic_annotation());
Paul Jensen60e45532018-02-19 16:04:18280 request_info_.socket_tag = request_->socket_tag();
Yu Su2d738bb2020-10-30 02:23:55281 request_info_.idempotency = request_->GetIdempotency();
Douglas Creageref5eecdc2018-11-09 20:50:36282#if BUILDFLAG(ENABLE_REPORTING)
283 request_info_.reporting_upload_depth = request_->reporting_upload_depth();
284#endif
Ramin Halavatib5e433e62018-02-07 07:41:10285
mkwste3e95992016-02-23 17:45:41286 // Privacy mode could still be disabled in SetCookieHeaderAndStart if we are
287 // going to send previously saved cookies.
Dylan Cutler7e818502021-11-11 15:23:08288 request_info_.privacy_mode = request_->privacy_mode();
[email protected]5033ab82013-03-22 20:17:46289
290 // Strip Referer from request_info_.extra_headers to prevent, e.g., plugins
291 // from overriding headers that are controlled using other means. Otherwise a
292 // plugin could set a referrer although sending the referrer is inhibited.
293 request_info_.extra_headers.RemoveHeader(HttpRequestHeaders::kReferer);
294
David Van Cleve09c1e8882020-06-24 17:05:50295 // Our consumer should have made sure that this is a safe referrer (e.g. via
296 // URLRequestJob::ComputeReferrerForPolicy).
[email protected]5033ab82013-03-22 20:17:46297 if (referrer.is_valid()) {
Mike Westfbd44112019-05-08 18:23:37298 std::string referer_value = referrer.spec();
[email protected]5033ab82013-03-22 20:17:46299 request_info_.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
Mike Westfbd44112019-05-08 18:23:37300 referer_value);
[email protected]5033ab82013-03-22 20:17:46301 }
302
303 request_info_.extra_headers.SetHeaderIfMissing(
304 HttpRequestHeaders::kUserAgent,
305 http_user_agent_settings_ ?
[email protected]aa051272014-03-10 05:56:56306 http_user_agent_settings_->GetUserAgent() : std::string());
[email protected]5033ab82013-03-22 20:17:46307
308 AddExtraHeaders();
309 AddCookieHeaderAndStart();
310}
311
312void URLRequestHttpJob::Kill() {
[email protected]5033ab82013-03-22 20:17:46313 weak_factory_.InvalidateWeakPtrs();
mmenke2281f3762015-11-02 20:38:17314 if (transaction_)
315 DestroyTransaction();
[email protected]5033ab82013-03-22 20:17:46316 URLRequestJob::Kill();
317}
318
ttuttle3ae06922015-05-11 23:41:52319void URLRequestHttpJob::GetConnectionAttempts(ConnectionAttempts* out) const {
320 if (transaction_)
321 transaction_->GetConnectionAttempts(out);
322 else
323 out->clear();
324}
325
Matt Menke2451c8b2020-12-08 22:42:51326void URLRequestHttpJob::CloseConnectionOnDestruction() {
327 DCHECK(transaction_);
328 transaction_->CloseConnectionOnDestruction();
329}
330
Aaron Tagliaboschib35cc402021-03-10 22:23:32331int URLRequestHttpJob::NotifyConnectedCallback(
332 const TransportInfo& info,
333 CompletionOnceCallback callback) {
334 return URLRequestJob::NotifyConnected(info, std::move(callback));
Titouan Rigoudy78af7da2020-07-07 14:30:12335}
336
[email protected]175adac2008-07-30 17:28:04337void URLRequestHttpJob::NotifyHeadersComplete() {
initial.commit586acc5fe2008-07-26 22:42:52338 DCHECK(!response_info_);
Aaron Tagliaboschi028009e2019-03-07 16:28:06339 DCHECK_EQ(0, num_cookie_lines_left_);
Maks Orlovich15714232019-06-16 23:14:09340 DCHECK(request_->maybe_stored_cookies().empty());
initial.commit586acc5fe2008-07-26 22:42:52341
Eric Orthcd71ede2021-09-14 18:18:50342 if (override_response_info_) {
343 DCHECK(!transaction_);
344 response_info_ = override_response_info_.get();
345 } else {
346 response_info_ = transaction_->GetResponseInfo();
347 }
initial.commit586acc5fe2008-07-26 22:42:52348
Matt Menke5dca1bb2019-09-13 20:43:12349 if (!response_info_->was_cached && throttling_entry_.get())
xunjieli041e9392015-05-19 21:51:33350 throttling_entry_->UpdateWithResponse(GetResponseCode());
[email protected]6b3f9642010-11-25 02:29:06351
[email protected]fecef222012-01-05 02:26:15352 // The ordering of these calls is not important.
[email protected]77f6fb432009-09-05 14:21:09353 ProcessStrictTransportSecurityHeader();
estark1614475f2016-03-10 03:46:47354 ProcessExpectCTHeader();
[email protected]a9cea7542009-05-20 04:30:23355
Ayu Ishii2e3998902020-07-14 18:22:30356 // Clear |set_cookie_access_result_list_| after any processing in case
Aaron Tagliaboschi028009e2019-03-07 16:28:06357 // SaveCookiesAndNotifyHeadersComplete is called again.
Ayu Ishii2e3998902020-07-14 18:22:30358 request_->set_maybe_stored_cookies(std::move(set_cookie_access_result_list_));
Aaron Tagliaboschi028009e2019-03-07 16:28:06359
[email protected]0757e7702009-03-27 04:00:22360 // The HTTP transaction may be restarted several times for the purposes
361 // of sending authorization information. Each time it restarts, we get
362 // notified of the headers completion so that we can update the cookie store.
Eric Orthcd71ede2021-09-14 18:18:50363 if (transaction_ && transaction_->IsReadyToRestartForAuth()) {
[email protected]87a09a92011-07-14 15:50:50364 // TODO(battre): This breaks the webrequest API for
365 // URLRequestTestHTTP.BasicAuthWithCookies
ryansturm2343cb62016-06-15 01:09:00366 // where OnBeforeStartTransaction -> OnStartTransaction ->
367 // OnBeforeStartTransaction occurs.
[email protected]f3cf9802011-10-28 18:44:58368 RestartTransactionWithAuth(AuthCredentials());
[email protected]0757e7702009-03-27 04:00:22369 return;
370 }
371
[email protected]4f5656c62010-12-13 10:47:09372 URLRequestJob::NotifyHeadersComplete();
initial.commit586acc5fe2008-07-26 22:42:52373}
374
[email protected]175adac2008-07-30 17:28:04375void URLRequestHttpJob::DestroyTransaction() {
[email protected]c6a4eb92010-03-03 23:51:19376 DCHECK(transaction_.get());
initial.commit586acc5fe2008-07-26 22:42:52377
[email protected]bbaea8f2011-06-24 00:11:01378 DoneWithRequest(ABORTED);
sclittlece72c482015-08-24 20:20:59379
380 total_received_bytes_from_previous_transactions_ +=
381 transaction_->GetTotalReceivedBytes();
sclittlefb249892015-09-10 21:33:22382 total_sent_bytes_from_previous_transactions_ +=
383 transaction_->GetTotalSentBytes();
[email protected]af4876d2008-10-21 23:10:57384 transaction_.reset();
David Benjamin0bda12f2018-02-07 19:58:45385 response_info_ = nullptr;
386 override_response_headers_ = nullptr;
[email protected]3b23a222013-05-15 21:33:25387 receive_headers_end_ = base::TimeTicks();
initial.commit586acc5fe2008-07-26 22:42:52388}
389
[email protected]175adac2008-07-30 17:28:04390void URLRequestHttpJob::StartTransaction() {
Eric Orthcd71ede2021-09-14 18:18:50391 DCHECK(!override_response_info_);
392
Matt Menkefd978852020-09-15 16:00:57393 NetworkDelegate* network_delegate = request()->network_delegate();
394 if (network_delegate) {
David Benjamin9776ca22018-06-13 00:00:15395 OnCallToDelegate(
396 NetLogEventType::NETWORK_DELEGATE_BEFORE_START_TRANSACTION);
Matt Menkefd978852020-09-15 16:00:57397 int rv = network_delegate->NotifyBeforeStartTransaction(
Clark DuVallc06b3922021-07-27 01:33:49398 request_, request_info_.extra_headers,
David Benjamind1f287bf2018-06-12 01:57:20399 base::BindOnce(&URLRequestHttpJob::NotifyBeforeStartTransactionCallback,
Clark DuVallc06b3922021-07-27 01:33:49400 weak_factory_.GetWeakPtr()));
[email protected]636eccd2011-06-28 12:28:01401 // If an extension blocks the request, we rely on the callback to
[email protected]b4438d32012-09-27 06:15:30402 // MaybeStartTransactionInternal().
[email protected]abe1c4a2013-10-25 19:28:51403 if (rv == ERR_IO_PENDING)
[email protected]636eccd2011-06-28 12:28:01404 return;
[email protected]b4438d32012-09-27 06:15:30405 MaybeStartTransactionInternal(rv);
406 return;
[email protected]636eccd2011-06-28 12:28:01407 }
408 StartTransactionInternal();
409}
410
Clark DuVallc06b3922021-07-27 01:33:49411void URLRequestHttpJob::NotifyBeforeStartTransactionCallback(
412 int result,
413 const absl::optional<HttpRequestHeaders>& headers) {
Matt Menkef47e1202020-04-27 21:03:39414 // The request should not have been cancelled or have already completed.
415 DCHECK(!is_done());
[email protected]9045b8822012-01-13 20:35:35416
Clark DuVallc06b3922021-07-27 01:33:49417 if (headers)
418 request_info_.extra_headers = headers.value();
[email protected]b4438d32012-09-27 06:15:30419 MaybeStartTransactionInternal(result);
420}
421
422void URLRequestHttpJob::MaybeStartTransactionInternal(int result) {
[email protected]abe1c4a2013-10-25 19:28:51423 OnCallToDelegateComplete();
[email protected]636eccd2011-06-28 12:28:01424 if (result == OK) {
425 StartTransactionInternal();
426 } else {
Eric Roman06bd9742019-07-13 15:19:13427 request_->net_log().AddEventWithStringParams(NetLogEventType::CANCELLED,
428 "source", "delegate");
jamd3f5a3c2016-10-27 18:52:02429 // Don't call back synchronously to the delegate.
430 base::ThreadTaskRunnerHandle::Get()->PostTask(
Matt Menke2b4d7c8b2020-04-27 23:35:07431 FROM_HERE, base::BindOnce(&URLRequestHttpJob::NotifyStartError,
432 weak_factory_.GetWeakPtr(), result));
[email protected]636eccd2011-06-28 12:28:01433 }
434}
435
436void URLRequestHttpJob::StartTransactionInternal() {
David Benjamin0bda12f2018-02-07 19:58:45437 DCHECK(!override_response_headers_);
mmenke4600b602015-10-28 18:52:17438
initial.commit586acc5fe2008-07-26 22:42:52439 // NOTE: This method assumes that request_info_ is already setup properly.
440
[email protected]34602282010-02-03 22:14:15441 // If we already have a transaction, then we should restart the transaction
[email protected]f3cf9802011-10-28 18:44:58442 // with auth provided by auth_credentials_.
initial.commit586acc5fe2008-07-26 22:42:52443
[email protected]99c07902010-08-17 18:59:52444 int rv;
[email protected]6b3f9642010-11-25 02:29:06445
tbansal80a52162016-05-20 17:55:04446 // Notify NetworkQualityEstimator.
447 NetworkQualityEstimator* network_quality_estimator =
448 request()->context()->network_quality_estimator();
449 if (network_quality_estimator)
450 network_quality_estimator->NotifyStartTransaction(*request_);
451
[email protected]34602282010-02-03 22:14:15452 if (transaction_.get()) {
mmenked3a02b32016-11-16 20:21:32453 rv = transaction_->RestartWithAuth(
Yannic Bonenbergercc716d42019-09-04 17:05:36454 auth_credentials_, base::BindOnce(&URLRequestHttpJob::OnStartCompleted,
455 base::Unretained(this)));
[email protected]f3cf9802011-10-28 18:44:58456 auth_credentials_ = AuthCredentials();
[email protected]34602282010-02-03 22:14:15457 } else {
[email protected]34602282010-02-03 22:14:15458 DCHECK(request_->context()->http_transaction_factory());
initial.commit586acc5fe2008-07-26 22:42:52459
[email protected]99c07902010-08-17 18:59:52460 rv = request_->context()->http_transaction_factory()->CreateTransaction(
[email protected]027bd85a2013-12-27 22:39:10461 priority_, &transaction_);
[email protected]f4533ba2013-11-28 09:35:41462
463 if (rv == OK && request_info_.url.SchemeIsWSOrWSS()) {
Bence Békya5ec55e62018-03-07 14:23:28464 base::SupportsUserData::Data* data =
465 request_->GetUserData(kWebSocketHandshakeUserDataKey);
[email protected]f4533ba2013-11-28 09:35:41466 if (data) {
467 transaction_->SetWebSocketHandshakeStreamCreateHelper(
468 static_cast<WebSocketHandshakeStreamBase::CreateHelper*>(data));
469 } else {
470 rv = ERR_DISALLOWED_URL_SCHEME;
471 }
472 }
473
[email protected]4f5656c62010-12-13 10:47:09474 if (rv == OK) {
Titouan Rigoudy78af7da2020-07-07 14:30:12475 transaction_->SetConnectedCallback(base::BindRepeating(
476 &URLRequestHttpJob::NotifyConnectedCallback, base::Unretained(this)));
Andrey Kosyakov83a6eee2017-08-14 19:20:04477 transaction_->SetRequestHeadersCallback(request_headers_callback_);
Kenichi Ishibashi74155532021-03-13 01:38:06478 transaction_->SetEarlyResponseHeadersCallback(
479 early_response_headers_callback_);
Andrey Kosyakov2e893e62017-08-31 17:00:52480 transaction_->SetResponseHeadersCallback(response_headers_callback_);
[email protected]a45840b2014-01-10 15:40:22481
dchengc2e01e82014-08-27 00:24:42482 if (!throttling_entry_.get() ||
xunjieli41edcdd2015-06-24 14:26:40483 !throttling_entry_->ShouldRejectRequest(*request_)) {
[email protected]227b0e82011-03-25 21:11:53484 rv = transaction_->Start(
Yannic Bonenbergercc716d42019-09-04 17:05:36485 &request_info_,
486 base::BindOnce(&URLRequestHttpJob::OnStartCompleted,
487 base::Unretained(this)),
mmenked3a02b32016-11-16 20:21:32488 request_->net_log());
[email protected]bbaea8f2011-06-24 00:11:01489 start_time_ = base::TimeTicks::Now();
[email protected]227b0e82011-03-25 21:11:53490 } else {
491 // Special error code for the exponential back-off module.
492 rv = ERR_TEMPORARILY_THROTTLED;
493 }
[email protected]34602282010-02-03 22:14:15494 }
initial.commit586acc5fe2008-07-26 22:42:52495 }
496
[email protected]4f5656c62010-12-13 10:47:09497 if (rv == ERR_IO_PENDING)
[email protected]34602282010-02-03 22:14:15498 return;
499
initial.commit586acc5fe2008-07-26 22:42:52500 // The transaction started synchronously, but we need to notify the
[email protected]4f5656c62010-12-13 10:47:09501 // URLRequest delegate via the message loop.
skyostil4891b25b2015-06-11 11:43:45502 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf4fe5172019-02-15 18:53:49503 FROM_HERE, base::BindOnce(&URLRequestHttpJob::OnStartCompleted,
504 weak_factory_.GetWeakPtr(), rv));
initial.commit586acc5fe2008-07-26 22:42:52505}
506
[email protected]175adac2008-07-30 17:28:04507void URLRequestHttpJob::AddExtraHeaders() {
[email protected]c7bef94c2011-06-21 18:05:51508 if (!request_info_.extra_headers.HasHeader(
Helen Li7dd80832017-09-12 18:29:17509 HttpRequestHeaders::kAcceptEncoding)) {
Aaron Tagliaboschi6c652aa2018-11-30 22:13:41510 // If a range is specifically requested, set the "Accepted Encoding" header
511 // to "identity"
512 if (request_info_.extra_headers.HasHeader(HttpRequestHeaders::kRange)) {
513 request_info_.extra_headers.SetHeader(HttpRequestHeaders::kAcceptEncoding,
514 "identity");
515 } else {
Aaron Tagliaboschi6c652aa2018-11-30 22:13:41516 // Supply Accept-Encoding headers first so that it is more likely that
517 // they will be in the first transmitted packet. This can sometimes make
518 // it easier to filter and analyze the streams to assure that a proxy has
519 // not damaged these headers. Some proxies deliberately corrupt
520 // Accept-Encoding headers.
Alex Rudenkocf7014a2021-03-22 12:55:19521 std::vector<std::string> advertised_encoding_names;
522 if (request_->Supports(SourceStream::SourceType::TYPE_GZIP)) {
523 advertised_encoding_names.push_back("gzip");
524 }
525 if (request_->Supports(SourceStream::SourceType::TYPE_DEFLATE)) {
526 advertised_encoding_names.push_back("deflate");
527 }
528 // Advertise "br" encoding only if transferred data is opaque to proxy.
529 if (request()->context()->enable_brotli() &&
530 request_->Supports(SourceStream::SourceType::TYPE_BROTLI)) {
531 if (request()->url().SchemeIsCryptographic() ||
532 IsLocalhost(request()->url())) {
533 advertised_encoding_names.push_back("br");
534 }
535 }
536 if (!advertised_encoding_names.empty()) {
537 // Tell the server what compression formats are supported.
538 request_info_.extra_headers.SetHeader(
539 HttpRequestHeaders::kAcceptEncoding,
540 base::JoinString(base::make_span(advertised_encoding_names), ", "));
541 }
Aaron Tagliaboschi6c652aa2018-11-30 22:13:41542 }
[email protected]423041b2008-10-27 17:39:28543 }
544
[email protected]ee4c30d2012-11-07 15:08:43545 if (http_user_agent_settings_) {
[email protected]84f05432013-03-15 01:00:12546 // Only add default Accept-Language if the request didn't have it
547 // specified.
[email protected]ee4c30d2012-11-07 15:08:43548 std::string accept_language =
549 http_user_agent_settings_->GetAcceptLanguage();
Yao Xiao90833e5b2019-05-09 16:19:41550 if (base::FeatureList::IsEnabled(features::kAcceptLanguageHeader) &&
551 !accept_language.empty()) {
[email protected]ee4c30d2012-11-07 15:08:43552 request_info_.extra_headers.SetHeaderIfMissing(
553 HttpRequestHeaders::kAcceptLanguage,
554 accept_language);
555 }
initial.commit586acc5fe2008-07-26 22:42:52556 }
initial.commit586acc5fe2008-07-26 22:42:52557}
558
[email protected]34602282010-02-03 22:14:15559void URLRequestHttpJob::AddCookieHeaderAndStart() {
davidben151423e2015-03-23 18:48:36560 CookieStore* cookie_store = request_->context()->cookie_store();
Matt Menke25eaa432020-08-25 00:10:00561 // Read cookies whenever allow_credentials() is true, even if the PrivacyMode
562 // is being overridden by NetworkDelegate and will eventually block them, as
563 // blocked cookies still need to be logged in that case.
564 if (cookie_store && request_->allow_credentials()) {
Lily Chen19cf9ee72020-04-23 21:14:23565 bool force_ignore_site_for_cookies =
566 request_->force_ignore_site_for_cookies();
Lily Chen0db055b2019-11-15 20:29:02567 if (cookie_store->cookie_access_delegate() &&
568 cookie_store->cookie_access_delegate()
569 ->ShouldIgnoreSameSiteRestrictions(request_->url(),
570 request_->site_for_cookies())) {
Lily Chen19cf9ee72020-04-23 21:14:23571 force_ignore_site_for_cookies = true;
Lily Chen0db055b2019-11-15 20:29:02572 }
Ben Kelly2d916562021-10-29 21:19:29573 bool is_main_frame_navigation =
574 IsolationInfo::RequestType::kMainFrame ==
575 request_->isolation_info().request_type() ||
576 request_->force_main_frame_for_same_site_cookies();
Shuran Huang57f97b22020-11-11 14:53:49577 CookieOptions::SameSiteCookieContext same_site_context =
Maks Orlovich64e2913d2019-03-05 14:42:56578 net::cookie_util::ComputeSameSiteContextForRequest(
Lily Chen306b8fb2021-03-08 22:31:23579 request_->method(), request_->url_chain(),
580 request_->site_for_cookies(), request_->initiator(),
581 is_main_frame_navigation, force_ignore_site_for_cookies);
Shuran Huang57f97b22020-11-11 14:53:49582
cfredric908f7392021-01-12 05:56:54583 net::SchemefulSite request_site(request_->url());
cfredric908f7392021-01-12 05:56:54584 const CookieAccessDelegate* delegate =
585 cookie_store->cookie_access_delegate();
586
cfredric908f7392021-01-12 05:56:54587 bool is_in_nontrivial_first_party_set =
588 delegate && delegate->IsInNontrivialFirstPartySet(request_site);
Shuran Huang9faced62021-01-05 23:19:55589 CookieOptions options = CreateCookieOptions(
cfredric362c4a02021-07-09 22:40:40590 same_site_context, request_->same_party_context(),
cfredricdacd9ca2021-05-17 20:42:08591 request_->isolation_info(), is_in_nontrivial_first_party_set);
Shuran Huang57f97b22020-11-11 14:53:49592
cfredric176f9e232021-05-12 20:20:14593 UMA_HISTOGRAM_ENUMERATION(
594 "Cookie.FirstPartySetsContextType.HTTP.Read",
595 net::cookie_util::ComputeFirstPartySetsContextType(
596 request_site, request_->isolation_info(), delegate,
597 request_->force_ignore_top_frame_party_for_cookies()));
598
mkwste3e95992016-02-23 17:45:41599 cookie_store->GetCookieListWithOptionsAsync(
Dylan Cutler20561622021-09-14 16:30:40600 request_->url(), options,
Aykut Bulut244341e2021-12-09 15:57:25601 CookiePartitionKeyCollection::FromOptional(cookie_partition_key_),
Yannic Bonenbergercc716d42019-09-04 17:05:36602 base::BindOnce(&URLRequestHttpJob::SetCookieHeaderAndStart,
603 weak_factory_.GetWeakPtr(), options));
[email protected]03d845f2011-07-29 19:06:26604 } else {
mmenked3a02b32016-11-16 20:21:32605 StartTransaction();
[email protected]03d845f2011-07-29 19:06:26606 }
607}
608
Aaron Tagliaboschia4c64b52019-01-25 03:28:49609void URLRequestHttpJob::SetCookieHeaderAndStart(
Lily Chen3ac7cf42019-05-30 23:29:29610 const CookieOptions& options,
Ayu Ishiibc6fdb0a2020-06-08 22:59:19611 const CookieAccessResultList& cookies_with_access_result_list,
612 const CookieAccessResultList& excluded_list) {
Maks Orlovich15714232019-06-16 23:14:09613 DCHECK(request_->maybe_sent_cookies().empty());
Aaron Tagliaboschifd4f3f012019-05-30 23:05:54614
cfredric59f8a8452021-06-08 15:27:11615 CookieAccessResultList maybe_included_cookies =
616 cookies_with_access_result_list;
617 CookieAccessResultList excluded_cookies = excluded_list;
Mike West7c8c2ad2018-02-10 07:08:49618
cfredric59f8a8452021-06-08 15:27:11619 if (request_info_.privacy_mode != PRIVACY_MODE_DISABLED) {
620 // If cookies are blocked (without our needing to consult the delegate), we
621 // move them to `excluded_cookies` and ensure that they have the correct
622 // exclusion reason.
623 excluded_cookies.insert(
624 excluded_cookies.end(),
625 std::make_move_iterator(maybe_included_cookies.begin()),
626 std::make_move_iterator(maybe_included_cookies.end()));
627 maybe_included_cookies.clear();
628 for (auto& cookie : excluded_cookies) {
629 cookie.access_result.status.AddExclusionReason(
630 CookieInclusionStatus::EXCLUDE_USER_PREFERENCES);
631 }
632 } else {
633 AnnotateAndMoveUserBlockedCookies(maybe_included_cookies, excluded_cookies);
634 if (!maybe_included_cookies.empty()) {
635 std::string cookie_line =
636 CanonicalCookie::BuildCookieLine(maybe_included_cookies);
637 UMA_HISTOGRAM_COUNTS_10000("Cookie.HeaderLength", cookie_line.length());
638 request_info_.extra_headers.SetHeader(HttpRequestHeaders::kCookie,
639 cookie_line);
Steven Bingler8693d2f2019-12-06 22:41:50640
cfredric59f8a8452021-06-08 15:27:11641 // TODO(crbug.com/1031664): Reduce the number of times the cookie list
642 // is iterated over. Get metrics for every cookie which is included.
643 for (const auto& c : maybe_included_cookies) {
644 bool request_is_secure = request_->url().SchemeIsCryptographic();
645 net::CookieSourceScheme cookie_scheme = c.cookie.SourceScheme();
646 CookieRequestScheme cookie_request_schemes;
Steven Bingler8693d2f2019-12-06 22:41:50647
cfredric59f8a8452021-06-08 15:27:11648 switch (cookie_scheme) {
649 case net::CookieSourceScheme::kSecure:
650 cookie_request_schemes =
651 request_is_secure
652 ? CookieRequestScheme::kSecureSetSecureRequest
653 : CookieRequestScheme::kSecureSetNonsecureRequest;
654 break;
Steven Bingler8693d2f2019-12-06 22:41:50655
cfredric59f8a8452021-06-08 15:27:11656 case net::CookieSourceScheme::kNonSecure:
657 cookie_request_schemes =
658 request_is_secure
659 ? CookieRequestScheme::kNonsecureSetSecureRequest
660 : CookieRequestScheme::kNonsecureSetNonsecureRequest;
661 break;
662
663 case net::CookieSourceScheme::kUnset:
664 cookie_request_schemes = CookieRequestScheme::kUnsetCookieScheme;
665 break;
666 }
667
668 UMA_HISTOGRAM_ENUMERATION("Cookie.CookieSchemeRequestScheme",
669 cookie_request_schemes);
Steven Bingler8693d2f2019-12-06 22:41:50670 }
Steven Bingler8693d2f2019-12-06 22:41:50671 }
[email protected]54f4c9362011-07-25 21:54:46672 }
Aaron Tagliaboschi41bfbec2019-03-12 19:23:48673
cfredric59f8a8452021-06-08 15:27:11674 CookieAccessResultList maybe_sent_cookies = std::move(excluded_cookies);
675 maybe_sent_cookies.insert(
676 maybe_sent_cookies.end(),
677 std::make_move_iterator(maybe_included_cookies.begin()),
678 std::make_move_iterator(maybe_included_cookies.end()));
679 maybe_included_cookies.clear();
Piotr Zarycki7fad80062020-05-28 19:51:20680
Lily Chen0e079b732019-10-01 19:48:40681 if (request_->net_log().IsCapturing()) {
Ayu Ishiibc6fdb0a2020-06-08 22:59:19682 for (const auto& cookie_with_access_result : maybe_sent_cookies) {
Lily Chen201128342019-12-11 21:17:03683 request_->net_log().AddEvent(
684 NetLogEventType::COOKIE_INCLUSION_STATUS,
685 [&](NetLogCaptureMode capture_mode) {
686 return CookieInclusionStatusNetLogParams(
Ayu Ishiibc6fdb0a2020-06-08 22:59:19687 "send", cookie_with_access_result.cookie.Name(),
688 cookie_with_access_result.cookie.Domain(),
689 cookie_with_access_result.cookie.Path(),
690 cookie_with_access_result.access_result.status, capture_mode);
Lily Chen201128342019-12-11 21:17:03691 });
Lily Chen0e079b732019-10-01 19:48:40692 }
693 }
694
Maks Orlovich15714232019-06-16 23:14:09695 request_->set_maybe_sent_cookies(std::move(maybe_sent_cookies));
Aaron Tagliaboschifd4f3f012019-05-30 23:05:54696
mmenked3a02b32016-11-16 20:21:32697 StartTransaction();
[email protected]0757e7702009-03-27 04:00:22698}
699
[email protected]ea8141e2011-10-05 13:12:51700void URLRequestHttpJob::SaveCookiesAndNotifyHeadersComplete(int result) {
Ayu Ishii2e3998902020-07-14 18:22:30701 DCHECK(set_cookie_access_result_list_.empty());
Yutaka Hirano115df8a02021-06-25 15:43:54702 // TODO(crbug.com/1186863): Turn this CHECK into DCHECK once the investigation
703 // is done.
704 CHECK_EQ(0, num_cookie_lines_left_);
Aaron Tagliaboschi028009e2019-03-07 16:28:06705
[email protected]abe1c4a2013-10-25 19:28:51706 // End of the call started in OnStartCompleted.
707 OnCallToDelegateComplete();
708
ttuttle859dc7a2015-04-23 19:42:29709 if (result != OK) {
Eric Roman06bd9742019-07-13 15:19:13710 request_->net_log().AddEventWithStringParams(NetLogEventType::CANCELLED,
711 "source", "delegate");
Matt Menke2b4d7c8b2020-04-27 23:35:07712 NotifyStartError(result);
[email protected]ea8141e2011-10-05 13:12:51713 return;
714 }
715
Lily Chen0db055b2019-11-15 20:29:02716 CookieStore* cookie_store = request_->context()->cookie_store();
717
718 if ((request_info_.load_flags & LOAD_DO_NOT_SAVE_COOKIES) || !cookie_store) {
Aaron Tagliaboschi028009e2019-03-07 16:28:06719 NotifyHeadersComplete();
720 return;
721 }
722
mmenke54e82af2016-02-16 23:06:30723 base::Time response_date;
Anton Bikineev068d2912021-05-15 20:43:52724 absl::optional<base::Time> server_time = absl::nullopt;
Lily Chenb851acc2019-08-07 15:54:44725 if (GetResponseHeaders()->GetDateValue(&response_date))
Anton Bikineev068d2912021-05-15 20:43:52726 server_time = absl::make_optional(response_date);
[email protected]263163f2012-06-14 22:40:34727
Lily Chen19cf9ee72020-04-23 21:14:23728 bool force_ignore_site_for_cookies =
729 request_->force_ignore_site_for_cookies();
Lily Chen0db055b2019-11-15 20:29:02730 if (cookie_store->cookie_access_delegate() &&
731 cookie_store->cookie_access_delegate()->ShouldIgnoreSameSiteRestrictions(
732 request_->url(), request_->site_for_cookies())) {
Lily Chen19cf9ee72020-04-23 21:14:23733 force_ignore_site_for_cookies = true;
Lily Chen0db055b2019-11-15 20:29:02734 }
Lily Chenb332c5602021-02-05 23:00:29735 bool is_main_frame_navigation = IsolationInfo::RequestType::kMainFrame ==
736 request_->isolation_info().request_type();
Shuran Huang57f97b22020-11-11 14:53:49737 CookieOptions::SameSiteCookieContext same_site_context =
Maks Orlovich3637afd22019-05-06 20:37:20738 net::cookie_util::ComputeSameSiteContextForResponse(
Lily Chen306b8fb2021-03-08 22:31:23739 request_->url_chain(), request_->site_for_cookies(),
740 request_->initiator(), is_main_frame_navigation,
741 force_ignore_site_for_cookies);
jww79aceda2015-12-07 01:56:34742
cfredric908f7392021-01-12 05:56:54743 const CookieAccessDelegate* delegate = cookie_store->cookie_access_delegate();
744 net::SchemefulSite request_site(request_->url());
Shuran Huangdbacc142021-01-14 21:08:23745
cfredric908f7392021-01-12 05:56:54746 bool is_in_nontrivial_first_party_set =
747 delegate && delegate->IsInNontrivialFirstPartySet(request_site);
Shuran Huang9faced62021-01-05 23:19:55748 CookieOptions options = CreateCookieOptions(
cfredric362c4a02021-07-09 22:40:40749 same_site_context, request_->same_party_context(),
cfredricdacd9ca2021-05-17 20:42:08750 request_->isolation_info(), is_in_nontrivial_first_party_set);
Shuran Huang9faced62021-01-05 23:19:55751
cfredric176f9e232021-05-12 20:20:14752 UMA_HISTOGRAM_ENUMERATION(
753 "Cookie.FirstPartySetsContextType.HTTP.Write",
754 net::cookie_util::ComputeFirstPartySetsContextType(
755 request_site, request_->isolation_info(), delegate,
756 request_->force_ignore_top_frame_party_for_cookies()));
757
Shuran Huang9faced62021-01-05 23:19:55758 // Set all cookies, without waiting for them to be set. Any subsequent
759 // read will see the combined result of all cookie operation.
Aaron Tagliaboschi028009e2019-03-07 16:28:06760 const base::StringPiece name("Set-Cookie");
761 std::string cookie_string;
762 size_t iter = 0;
763 HttpResponseHeaders* headers = GetResponseHeaders();
764
765 // NotifyHeadersComplete needs to be called once and only once after the
766 // list has been fully processed, and it can either be called in the
767 // callback or after the loop is called, depending on how the last element
768 // was handled. |num_cookie_lines_left_| keeps track of how many async
Shuran Huang9faced62021-01-05 23:19:55769 // callbacks are currently out (starting from 1 to make sure the loop runs
770 // all the way through before trying to exit). If there are any callbacks
771 // still waiting when the loop ends, then NotifyHeadersComplete will be
772 // called when it reaches 0 in the callback itself.
Aaron Tagliaboschi028009e2019-03-07 16:28:06773 num_cookie_lines_left_ = 1;
774 while (headers->EnumerateHeader(&iter, name, &cookie_string)) {
Jihwan Marc Kim3e132f12020-05-20 17:33:19775 CookieInclusionStatus returned_status;
Aaron Tagliaboschi028009e2019-03-07 16:28:06776
777 num_cookie_lines_left_++;
778
779 std::unique_ptr<CanonicalCookie> cookie = net::CanonicalCookie::Create(
Lily Chenb851acc2019-08-07 15:54:44780 request_->url(), cookie_string, base::Time::Now(), server_time,
Dylan Cutler69a51c92021-12-08 16:32:01781 cookie_partition_key_, &returned_status);
Aaron Tagliaboschi028009e2019-03-07 16:28:06782
Anton Bikineev068d2912021-05-15 20:43:52783 absl::optional<CanonicalCookie> cookie_to_return = absl::nullopt;
Lily Chenf53dfbcd2019-08-30 01:42:10784 if (returned_status.IsInclude()) {
785 DCHECK(cookie);
786 // Make a copy of the cookie if we successfully made one.
787 cookie_to_return = *cookie;
788 }
789 if (cookie && !CanSetCookie(*cookie, &options)) {
790 returned_status.AddExclusionReason(
Jihwan Marc Kim3e132f12020-05-20 17:33:19791 CookieInclusionStatus::EXCLUDE_USER_PREFERENCES);
Lily Chenf53dfbcd2019-08-30 01:42:10792 }
793 if (!returned_status.IsInclude()) {
794 OnSetCookieResult(options, cookie_to_return, std::move(cookie_string),
Ayu Ishiif3966ca2020-07-08 17:35:12795 CookieAccessResult(returned_status));
Aaron Tagliaboschi028009e2019-03-07 16:28:06796 continue;
[email protected]263163f2012-06-14 22:40:34797 }
Lily Chen0f208ea2019-08-08 23:37:53798
Shuran Huangaa9d5552020-12-10 16:25:06799 cookie_store->SetCanonicalCookieAsync(
Lily Chen96f29a132020-04-15 17:59:36800 std::move(cookie), request_->url(), options,
Lily Chen3ac7cf42019-05-30 23:29:29801 base::BindOnce(&URLRequestHttpJob::OnSetCookieResult,
Lily Chenf53dfbcd2019-08-30 01:42:10802 weak_factory_.GetWeakPtr(), options, cookie_to_return,
Lily Chen3ac7cf42019-05-30 23:29:29803 cookie_string));
Aaron Tagliaboschi028009e2019-03-07 16:28:06804 }
805 // Removing the 1 that |num_cookie_lines_left| started with, signifing that
806 // loop has been exited.
807 num_cookie_lines_left_--;
808
Lily Chen14708712020-11-19 16:17:42809 if (num_cookie_lines_left_ == 0)
Aaron Tagliaboschi028009e2019-03-07 16:28:06810 NotifyHeadersComplete();
811}
812
813void URLRequestHttpJob::OnSetCookieResult(
Lily Chen3ac7cf42019-05-30 23:29:29814 const CookieOptions& options,
Anton Bikineev068d2912021-05-15 20:43:52815 absl::optional<CanonicalCookie> cookie,
Aaron Tagliaboschi028009e2019-03-07 16:28:06816 std::string cookie_string,
Ayu Ishiif3966ca2020-07-08 17:35:12817 CookieAccessResult access_result) {
Lily Chen201128342019-12-11 21:17:03818 if (request_->net_log().IsCapturing()) {
Ayu Ishiif3966ca2020-07-08 17:35:12819 request_->net_log().AddEvent(NetLogEventType::COOKIE_INCLUSION_STATUS,
820 [&](NetLogCaptureMode capture_mode) {
821 return CookieInclusionStatusNetLogParams(
822 "store",
823 cookie ? cookie.value().Name() : "",
824 cookie ? cookie.value().Domain() : "",
825 cookie ? cookie.value().Path() : "",
826 access_result.status, capture_mode);
827 });
Lily Chen0e079b732019-10-01 19:48:40828 }
Lily Chenef77a172021-02-22 22:42:26829
Ayu Ishii2e3998902020-07-14 18:22:30830 set_cookie_access_result_list_.emplace_back(
831 std::move(cookie), std::move(cookie_string), access_result);
Aaron Tagliaboschi028009e2019-03-07 16:28:06832
833 num_cookie_lines_left_--;
834
Ayu Ishii2e3998902020-07-14 18:22:30835 // If all the cookie lines have been handled, |set_cookie_access_result_list_|
836 // now reflects the result of all Set-Cookie lines, and the request can be
Lily Chenf53dfbcd2019-08-30 01:42:10837 // continued.
Lily Chen14708712020-11-19 16:17:42838 if (num_cookie_lines_left_ == 0)
Aaron Tagliaboschi028009e2019-03-07 16:28:06839 NotifyHeadersComplete();
[email protected]34602282010-02-03 22:14:15840}
841
[email protected]77f6fb432009-09-05 14:21:09842void URLRequestHttpJob::ProcessStrictTransportSecurityHeader() {
[email protected]a9cea7542009-05-20 04:30:23843 DCHECK(response_info_);
[email protected]6ed72be2013-01-08 22:07:33844 TransportSecurityState* security_state =
845 request_->context()->transport_security_state();
[email protected]e88006f2012-01-11 06:15:07846 const SSLInfo& ssl_info = response_info_->ssl_info;
[email protected]a9cea7542009-05-20 04:30:23847
[email protected]6ed72be2013-01-08 22:07:33848 // Only accept HSTS headers on HTTPS connections that have no
849 // certificate errors.
[email protected]e88006f2012-01-11 06:15:07850 if (!ssl_info.is_valid() || IsCertStatusError(ssl_info.cert_status) ||
mmenked3a02b32016-11-16 20:21:32851 !security_state) {
[email protected]e88006f2012-01-11 06:15:07852 return;
mmenked3a02b32016-11-16 20:21:32853 }
[email protected]326e6792009-12-11 21:04:42854
estarka5da76702015-04-09 04:00:16855 // Don't accept HSTS headers when the hostname is an IP address.
856 if (request_info_.url.HostIsIPAddress())
857 return;
858
[email protected]242d8562012-10-30 21:20:46859 // http://tools.ietf.org/html/draft-ietf-websec-strict-transport-sec:
860 //
861 // If a UA receives more than one STS header field in a HTTP response
862 // message over secure transport, then the UA MUST process only the
863 // first such header field.
[email protected]6ed72be2013-01-08 22:07:33864 HttpResponseHeaders* headers = GetResponseHeaders();
865 std::string value;
olli.raulaee489a52016-01-25 08:37:10866 if (headers->EnumerateHeader(nullptr, "Strict-Transport-Security", &value))
[email protected]6ed72be2013-01-08 22:07:33867 security_state->AddHSTSHeader(request_info_.url.host(), value);
[email protected]a9cea7542009-05-20 04:30:23868}
[email protected]4f5656c62010-12-13 10:47:09869
estark1614475f2016-03-10 03:46:47870void URLRequestHttpJob::ProcessExpectCTHeader() {
871 DCHECK(response_info_);
872 TransportSecurityState* security_state =
873 request_->context()->transport_security_state();
874 const SSLInfo& ssl_info = response_info_->ssl_info;
875
876 // Only accept Expect CT headers on HTTPS connections that have no
877 // certificate errors.
878 if (!ssl_info.is_valid() || IsCertStatusError(ssl_info.cert_status) ||
879 !security_state) {
880 return;
881 }
882
estark1614475f2016-03-10 03:46:47883 HttpResponseHeaders* headers = GetResponseHeaders();
884 std::string value;
Emily Starkf4bc0b82021-07-28 00:30:20885 bool has_expect_ct_header = headers->GetNormalizedHeader("Expect-CT", &value);
886 base::UmaHistogramBoolean("Net.ExpectCT.HeaderPresentOnResponse",
887 has_expect_ct_header);
888 if (has_expect_ct_header) {
estark1614475f2016-03-10 03:46:47889 security_state->ProcessExpectCTHeader(
Matt Menke78e9f6e2020-05-29 21:31:01890 value, HostPortPair::FromURL(request_info_.url), ssl_info,
891 request_->isolation_info().network_isolation_key());
estark1614475f2016-03-10 03:46:47892 }
893}
894
[email protected]5394e422011-01-20 22:07:43895void URLRequestHttpJob::OnStartCompleted(int result) {
Alexandr Ilin33126632018-11-14 14:48:17896 TRACE_EVENT0(NetTracingCategory(), "URLRequestHttpJob::OnStartCompleted");
[email protected]ec23f522011-02-22 21:01:38897 RecordTimer();
898
[email protected]80abdad2014-03-15 00:20:54899 // If the job is done (due to cancellation), can just ignore this
900 // notification.
901 if (done_)
[email protected]5394e422011-01-20 22:07:43902 return;
903
[email protected]3b23a222013-05-15 21:33:25904 receive_headers_end_ = base::TimeTicks::Now();
905
[email protected]ef2bf422012-05-11 03:27:09906 const URLRequestContext* context = request_->context();
907
Ryan Sleevi19a7bde2017-11-22 06:51:39908 if (transaction_ && transaction_->GetResponseInfo()) {
909 const SSLInfo& ssl_info = transaction_->GetResponseInfo()->ssl_info;
Matt Mueller936511442019-09-03 18:15:12910 if (!IsCertificateError(result)) {
Ryan Sleevi19a7bde2017-11-22 06:51:39911 LogTrustAnchor(ssl_info.public_key_hashes);
912 }
913 }
914
Wojciech Dzierżanowskiabdeeaf2019-04-01 20:16:22915 if (transaction_ && transaction_->GetResponseInfo()) {
916 SetProxyServer(transaction_->GetResponseInfo()->proxy_server);
917 }
918
[email protected]5394e422011-01-20 22:07:43919 if (result == OK) {
[email protected]ea8141e2011-10-05 13:12:51920 scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders();
hiroshigecb76caa4c52015-12-22 07:50:25921
Matt Menkefd978852020-09-15 16:00:57922 NetworkDelegate* network_delegate = request()->network_delegate();
923 if (network_delegate) {
[email protected]ea8141e2011-10-05 13:12:51924 // Note that |this| may not be deleted until
mmenked3a02b32016-11-16 20:21:32925 // |URLRequestHttpJob::OnHeadersReceivedCallback()| or
[email protected]ea8141e2011-10-05 13:12:51926 // |NetworkDelegate::URLRequestDestroyed()| has been called.
David Benjamin9776ca22018-06-13 00:00:15927 OnCallToDelegate(NetLogEventType::NETWORK_DELEGATE_HEADERS_RECEIVED);
Anton Bikineev068d2912021-05-15 20:43:52928 preserve_fragment_on_redirect_url_ = absl::nullopt;
Yutaka Hirano832c8902019-10-16 10:04:34929 IPEndPoint endpoint;
930 if (transaction_)
931 transaction_->GetRemoteEndpoint(&endpoint);
mmenked3a02b32016-11-16 20:21:32932 // The NetworkDelegate must watch for OnRequestDestroyed and not modify
Matt Muellerbe9d8e82019-03-15 21:38:44933 // any of the arguments after it's called.
934 // TODO(mattm): change the API to remove the out-params and take the
935 // results as params of the callback.
Matt Menkefd978852020-09-15 16:00:57936 int error = network_delegate->NotifyHeadersReceived(
David Benjamind1f287bf2018-06-12 01:57:20937 request_,
938 base::BindOnce(&URLRequestHttpJob::OnHeadersReceivedCallback,
Matt Muellerbe9d8e82019-03-15 21:38:44939 weak_factory_.GetWeakPtr()),
Yutaka Hirano832c8902019-10-16 10:04:34940 headers.get(), &override_response_headers_, endpoint,
Matt Menkeeed1a242019-10-23 21:26:06941 &preserve_fragment_on_redirect_url_);
ttuttle859dc7a2015-04-23 19:42:29942 if (error != OK) {
943 if (error == ERR_IO_PENDING) {
[email protected]ea8141e2011-10-05 13:12:51944 awaiting_callback_ = true;
[email protected]ea8141e2011-10-05 13:12:51945 } else {
Eric Roman06bd9742019-07-13 15:19:13946 request_->net_log().AddEventWithStringParams(
947 NetLogEventType::CANCELLED, "source", "delegate");
[email protected]abe1c4a2013-10-25 19:28:51948 OnCallToDelegateComplete();
Matt Menke2b4d7c8b2020-04-27 23:35:07949 NotifyStartError(error);
[email protected]ea8141e2011-10-05 13:12:51950 }
951 return;
952 }
953 }
954
ttuttle859dc7a2015-04-23 19:42:29955 SaveCookiesAndNotifyHeadersComplete(OK);
[email protected]e5624f02011-09-27 19:43:53956 } else if (IsCertificateError(result)) {
[email protected]6061c142013-10-21 15:13:34957 // We encountered an SSL certificate error.
rsleevi9545d342016-06-21 03:17:37958 // Maybe overridable, maybe not. Ask the delegate to decide.
959 TransportSecurityState* state = context->transport_security_state();
960 NotifySSLCertificateError(
Emily Stark79fba5842019-04-25 04:59:36961 result, transaction_->GetResponseInfo()->ssl_info,
Ryan Sleevi54fe7662019-11-21 01:31:58962 state->ShouldSSLErrorsBeFatal(request_info_.url.host()) &&
963 result != ERR_CERT_KNOWN_INTERCEPTION_BLOCKED);
[email protected]5394e422011-01-20 22:07:43964 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
[email protected]a83dd332011-07-13 10:41:01965 NotifyCertificateRequested(
[email protected]90499482013-06-01 00:39:50966 transaction_->GetResponseInfo()->cert_request_info.get());
Eric Orthcd71ede2021-09-14 18:18:50967 } else if (result == ERR_DNS_NAME_HTTPS_ONLY) {
968 // If DNS indicated the name is HTTPS-only, synthesize a redirect to either
969 // HTTPS or WSS.
970 DCHECK(features::kUseDnsHttpsSvcbHttpUpgrade.Get());
971 DCHECK(!request_->url().SchemeIsCryptographic());
972
973 base::Time request_time =
974 transaction_ && transaction_->GetResponseInfo()
975 ? transaction_->GetResponseInfo()->request_time
976 : base::Time::Now();
977 DestroyTransaction();
978 override_response_info_ = std::make_unique<HttpResponseInfo>();
979 override_response_info_->request_time = request_time;
980
981 override_response_info_->headers = RedirectUtil::SynthesizeRedirectHeaders(
982 UpgradeSchemeToCryptographic(request_->url()),
983 RedirectUtil::ResponseCode::REDIRECT_307_TEMPORARY_REDIRECT, "DNS",
984 request_->extra_request_headers());
985 NetLogResponseHeaders(
986 request_->net_log(),
987 NetLogEventType::URL_REQUEST_FAKE_RESPONSE_HEADERS_CREATED,
988 override_response_info_->headers.get());
989
990 NotifyHeadersComplete();
[email protected]5394e422011-01-20 22:07:43991 } else {
[email protected]419704c2014-01-14 11:18:06992 // Even on an error, there may be useful information in the response
993 // info (e.g. whether there's a cached copy).
994 if (transaction_.get())
995 response_info_ = transaction_->GetResponseInfo();
Matt Menke2b4d7c8b2020-04-27 23:35:07996 NotifyStartError(result);
[email protected]5394e422011-01-20 22:07:43997 }
998}
999
[email protected]ea8141e2011-10-05 13:12:511000void URLRequestHttpJob::OnHeadersReceivedCallback(int result) {
Matt Menkef47e1202020-04-27 21:03:391001 // The request should not have been cancelled or have already completed.
1002 DCHECK(!is_done());
[email protected]9045b8822012-01-13 20:35:351003
Matt Menkef47e1202020-04-27 21:03:391004 awaiting_callback_ = false;
[email protected]9045b8822012-01-13 20:35:351005
[email protected]ea8141e2011-10-05 13:12:511006 SaveCookiesAndNotifyHeadersComplete(result);
1007}
1008
[email protected]5394e422011-01-20 22:07:431009void URLRequestHttpJob::OnReadCompleted(int result) {
Alexandr Ilin33126632018-11-14 14:48:171010 TRACE_EVENT0(NetTracingCategory(), "URLRequestHttpJob::OnReadCompleted");
[email protected]5394e422011-01-20 22:07:431011 read_in_progress_ = false;
1012
xunjieli26ede962015-11-23 19:39:131013 DCHECK_NE(ERR_IO_PENDING, result);
1014
[email protected]f001bd6a2011-12-08 04:31:371015 if (ShouldFixMismatchedContentLength(result))
[email protected]5543cbb2012-04-20 16:35:231016 result = OK;
[email protected]f001bd6a2011-12-08 04:31:371017
xunjieli26ede962015-11-23 19:39:131018 // EOF or error, done with this job.
1019 if (result <= 0)
1020 DoneWithRequest(FINISHED);
[email protected]5394e422011-01-20 22:07:431021
xunjieli26ede962015-11-23 19:39:131022 ReadRawDataComplete(result);
[email protected]5394e422011-01-20 22:07:431023}
1024
[email protected]5394e422011-01-20 22:07:431025void URLRequestHttpJob::RestartTransactionWithAuth(
[email protected]f3cf9802011-10-28 18:44:581026 const AuthCredentials& credentials) {
Eric Orthcd71ede2021-09-14 18:18:501027 DCHECK(!override_response_info_);
1028
[email protected]f3cf9802011-10-28 18:44:581029 auth_credentials_ = credentials;
[email protected]5394e422011-01-20 22:07:431030
1031 // These will be reset in OnStartCompleted.
David Benjamin0bda12f2018-02-07 19:58:451032 response_info_ = nullptr;
1033 override_response_headers_ = nullptr; // See https://crbug.com/801237.
[email protected]3b23a222013-05-15 21:33:251034 receive_headers_end_ = base::TimeTicks();
[email protected]5394e422011-01-20 22:07:431035
[email protected]ec23f522011-02-22 21:01:381036 ResetTimer();
1037
[email protected]5394e422011-01-20 22:07:431038 // Update the cookies, since the cookie store may have been updated from the
1039 // headers in the 401/407. Since cookies were already appended to
1040 // extra_headers, we need to strip them out before adding them again.
[email protected]ea8141e2011-10-05 13:12:511041 request_info_.extra_headers.RemoveHeader(HttpRequestHeaders::kCookie);
[email protected]5394e422011-01-20 22:07:431042
Aaron Tagliaboschifd4f3f012019-05-30 23:05:541043 // TODO(https://crbug.com/968327/): This is weird, as all other clearing is at
1044 // the URLRequest layer. Should this call into URLRequest so it can share
1045 // logic at that layer with SetAuth()?
Maks Orlovich15714232019-06-16 23:14:091046 request_->set_maybe_sent_cookies({});
1047 request_->set_maybe_stored_cookies({});
Aaron Tagliaboschifd4f3f012019-05-30 23:05:541048
[email protected]5394e422011-01-20 22:07:431049 AddCookieHeaderAndStart();
1050}
1051
[email protected]0736d9e2012-11-28 19:50:401052void URLRequestHttpJob::SetUpload(UploadDataStream* upload) {
Eric Orthcd71ede2021-09-14 18:18:501053 DCHECK(!transaction_.get() && !override_response_info_)
1054 << "cannot change once started";
[email protected]0736d9e2012-11-28 19:50:401055 request_info_.upload_data_stream = upload;
[email protected]5394e422011-01-20 22:07:431056}
1057
1058void URLRequestHttpJob::SetExtraRequestHeaders(
1059 const HttpRequestHeaders& headers) {
Eric Orthcd71ede2021-09-14 18:18:501060 DCHECK(!transaction_.get() && !override_response_info_)
1061 << "cannot change once started";
[email protected]5394e422011-01-20 22:07:431062 request_info_.extra_headers.CopyFrom(headers);
1063}
1064
[email protected]5394e422011-01-20 22:07:431065LoadState URLRequestHttpJob::GetLoadState() const {
1066 return transaction_.get() ?
1067 transaction_->GetLoadState() : LOAD_STATE_IDLE;
1068}
1069
[email protected]5394e422011-01-20 22:07:431070bool URLRequestHttpJob::GetMimeType(std::string* mime_type) const {
Eric Orthcd71ede2021-09-14 18:18:501071 DCHECK(transaction_.get() || override_response_info_);
[email protected]5394e422011-01-20 22:07:431072
1073 if (!response_info_)
1074 return false;
1075
ellyjones0e9d5e82015-02-17 23:06:281076 HttpResponseHeaders* headers = GetResponseHeaders();
1077 if (!headers)
1078 return false;
1079 return headers->GetMimeType(mime_type);
[email protected]5394e422011-01-20 22:07:431080}
1081
1082bool URLRequestHttpJob::GetCharset(std::string* charset) {
Eric Orthcd71ede2021-09-14 18:18:501083 DCHECK(transaction_.get() || override_response_info_);
[email protected]5394e422011-01-20 22:07:431084
1085 if (!response_info_)
1086 return false;
1087
[email protected]ea8141e2011-10-05 13:12:511088 return GetResponseHeaders()->GetCharset(charset);
[email protected]5394e422011-01-20 22:07:431089}
1090
1091void URLRequestHttpJob::GetResponseInfo(HttpResponseInfo* info) {
Eric Orthcd71ede2021-09-14 18:18:501092 if (override_response_info_) {
1093 DCHECK(!transaction_.get());
1094 *info = *override_response_info_;
1095 return;
1096 }
1097
[email protected]ea8141e2011-10-05 13:12:511098 if (response_info_) {
[email protected]419704c2014-01-14 11:18:061099 DCHECK(transaction_.get());
1100
[email protected]5394e422011-01-20 22:07:431101 *info = *response_info_;
[email protected]90499482013-06-01 00:39:501102 if (override_response_headers_.get())
[email protected]ea8141e2011-10-05 13:12:511103 info->headers = override_response_headers_;
1104 }
[email protected]5394e422011-01-20 22:07:431105}
1106
[email protected]58e32bb2013-01-21 18:23:251107void URLRequestHttpJob::GetLoadTimingInfo(
1108 LoadTimingInfo* load_timing_info) const {
[email protected]3b23a222013-05-15 21:33:251109 // If haven't made it far enough to receive any headers, don't return
rdsmith81f607562014-11-21 18:35:161110 // anything. This makes for more consistent behavior in the case of errors.
[email protected]3b23a222013-05-15 21:33:251111 if (!transaction_ || receive_headers_end_.is_null())
1112 return;
1113 if (transaction_->GetLoadTimingInfo(load_timing_info))
1114 load_timing_info->receive_headers_end = receive_headers_end_;
[email protected]58e32bb2013-01-21 18:23:251115}
1116
Tsuyoshi Horo01faed62019-02-20 22:11:371117bool URLRequestHttpJob::GetTransactionRemoteEndpoint(
1118 IPEndPoint* endpoint) const {
ttuttled9dbc652015-09-29 20:00:591119 if (!transaction_)
1120 return false;
1121
1122 return transaction_->GetRemoteEndpoint(endpoint);
1123}
1124
[email protected]5394e422011-01-20 22:07:431125int URLRequestHttpJob::GetResponseCode() const {
1126 DCHECK(transaction_.get());
1127
1128 if (!response_info_)
1129 return -1;
1130
[email protected]ea8141e2011-10-05 13:12:511131 return GetResponseHeaders()->response_code();
[email protected]5394e422011-01-20 22:07:431132}
1133
zhongyi48704c182015-12-07 07:52:021134void URLRequestHttpJob::PopulateNetErrorDetails(
1135 NetErrorDetails* details) const {
1136 if (!transaction_)
1137 return;
1138 return transaction_->PopulateNetErrorDetails(details);
1139}
1140
xunjieli28a18772016-10-25 15:30:061141std::unique_ptr<SourceStream> URLRequestHttpJob::SetUpSourceStream() {
[email protected]5394e422011-01-20 22:07:431142 DCHECK(transaction_.get());
1143 if (!response_info_)
Bacek8f371552016-05-12 01:13:491144 return nullptr;
[email protected]5394e422011-01-20 22:07:431145
xunjieli28a18772016-10-25 15:30:061146 std::unique_ptr<SourceStream> upstream = URLRequestJob::SetUpSourceStream();
[email protected]ea8141e2011-10-05 13:12:511147 HttpResponseHeaders* headers = GetResponseHeaders();
xunjieli28a18772016-10-25 15:30:061148 std::vector<SourceStream::SourceType> types;
olli.raulaee489a52016-01-25 08:37:101149 size_t iter = 0;
Peter Kastingd039b772021-08-18 00:06:201150 for (std::string type;
1151 headers->EnumerateHeader(&iter, "Content-Encoding", &type);) {
eustasc7d27da2017-04-06 10:33:201152 SourceStream::SourceType source_type =
1153 FilterSourceStream::ParseEncodingType(type);
eustasc7d27da2017-04-06 10:33:201154 switch (source_type) {
1155 case SourceStream::TYPE_BROTLI:
1156 case SourceStream::TYPE_DEFLATE:
1157 case SourceStream::TYPE_GZIP:
Alex Rudenkocf7014a2021-03-22 12:55:191158 if (request_->accepted_stream_types() &&
1159 !request_->accepted_stream_types()->contains(source_type)) {
1160 // If the source type is disabled, we treat it
1161 // in the same way as SourceStream::TYPE_UNKNOWN.
1162 return upstream;
1163 }
eustasc7d27da2017-04-06 10:33:201164 types.push_back(source_type);
1165 break;
1166 case SourceStream::TYPE_NONE:
1167 // Identity encoding type. Pass through raw response body.
1168 return upstream;
Helen Li666c0682017-09-15 19:57:051169 case SourceStream::TYPE_UNKNOWN:
eustasc7d27da2017-04-06 10:33:201170 // Unknown encoding type. Pass through raw response body.
Paul Jensene85e8152019-07-01 15:38:001171 // Request will not be canceled; though
eustasc7d27da2017-04-06 10:33:201172 // it is expected that user will see malformed / garbage response.
eustasc7d27da2017-04-06 10:33:201173 return upstream;
1174 }
[email protected]5394e422011-01-20 22:07:431175 }
1176
jdoerrie22a91d8b92018-10-05 08:43:261177 for (auto r_iter = types.rbegin(); r_iter != types.rend(); ++r_iter) {
xunjieli28a18772016-10-25 15:30:061178 std::unique_ptr<FilterSourceStream> downstream;
1179 SourceStream::SourceType type = *r_iter;
1180 switch (type) {
1181 case SourceStream::TYPE_BROTLI:
1182 downstream = CreateBrotliSourceStream(std::move(upstream));
1183 break;
xunjieli28a18772016-10-25 15:30:061184 case SourceStream::TYPE_GZIP:
1185 case SourceStream::TYPE_DEFLATE:
xunjieli28a18772016-10-25 15:30:061186 downstream = GzipSourceStream::Create(std::move(upstream), type);
1187 break;
1188 case SourceStream::TYPE_NONE:
eustasc7d27da2017-04-06 10:33:201189 case SourceStream::TYPE_UNKNOWN:
xunjieli28a18772016-10-25 15:30:061190 NOTREACHED();
1191 return nullptr;
1192 }
1193 if (downstream == nullptr)
1194 return nullptr;
1195 upstream = std::move(downstream);
1196 }
1197
1198 return upstream;
[email protected]5394e422011-01-20 22:07:431199}
1200
[email protected]f878230e2014-04-03 15:36:141201bool URLRequestHttpJob::CopyFragmentOnRedirect(const GURL& location) const {
1202 // Allow modification of reference fragments by default, unless
Matt Menkeeed1a242019-10-23 21:26:061203 // |preserve_fragment_on_redirect_url_| is set and equal to the redirect URL.
1204 return !preserve_fragment_on_redirect_url_.has_value() ||
1205 preserve_fragment_on_redirect_url_ != location;
[email protected]f878230e2014-04-03 15:36:141206}
1207
[email protected]5394e422011-01-20 22:07:431208bool URLRequestHttpJob::IsSafeRedirect(const GURL& location) {
[email protected]e0f35c92013-05-08 16:04:341209 // HTTP is always safe.
1210 // TODO(pauljensen): Remove once crbug.com/146591 is fixed.
1211 if (location.is_valid() &&
1212 (location.scheme() == "http" || location.scheme() == "https")) {
[email protected]5394e422011-01-20 22:07:431213 return true;
[email protected]5394e422011-01-20 22:07:431214 }
[email protected]e0f35c92013-05-08 16:04:341215 // Query URLRequestJobFactory as to whether |location| would be safe to
1216 // redirect to.
1217 return request_->context()->job_factory() &&
1218 request_->context()->job_factory()->IsSafeRedirectTarget(location);
[email protected]5394e422011-01-20 22:07:431219}
1220
1221bool URLRequestHttpJob::NeedsAuth() {
1222 int code = GetResponseCode();
1223 if (code == -1)
1224 return false;
1225
rdsmith81f607562014-11-21 18:35:161226 // Check if we need either Proxy or WWW Authentication. This could happen
[email protected]5394e422011-01-20 22:07:431227 // because we either provided no auth info, or provided incorrect info.
1228 switch (code) {
1229 case 407:
1230 if (proxy_auth_state_ == AUTH_STATE_CANCELED)
1231 return false;
1232 proxy_auth_state_ = AUTH_STATE_NEED_AUTH;
1233 return true;
1234 case 401:
1235 if (server_auth_state_ == AUTH_STATE_CANCELED)
1236 return false;
1237 server_auth_state_ = AUTH_STATE_NEED_AUTH;
1238 return true;
1239 }
1240 return false;
1241}
1242
Emily Starkf2c9bbd2019-04-09 17:08:581243std::unique_ptr<AuthChallengeInfo> URLRequestHttpJob::GetAuthChallengeInfo() {
[email protected]5394e422011-01-20 22:07:431244 DCHECK(transaction_.get());
1245 DCHECK(response_info_);
1246
1247 // sanity checks:
1248 DCHECK(proxy_auth_state_ == AUTH_STATE_NEED_AUTH ||
1249 server_auth_state_ == AUTH_STATE_NEED_AUTH);
[email protected]9094b602012-02-27 21:44:581250 DCHECK((GetResponseHeaders()->response_code() == HTTP_UNAUTHORIZED) ||
1251 (GetResponseHeaders()->response_code() ==
1252 HTTP_PROXY_AUTHENTICATION_REQUIRED));
[email protected]5394e422011-01-20 22:07:431253
Emily Starkf2c9bbd2019-04-09 17:08:581254 if (!response_info_->auth_challenge.has_value())
1255 return nullptr;
1256 return std::make_unique<AuthChallengeInfo>(
1257 response_info_->auth_challenge.value());
[email protected]5394e422011-01-20 22:07:431258}
1259
[email protected]f3cf9802011-10-28 18:44:581260void URLRequestHttpJob::SetAuth(const AuthCredentials& credentials) {
[email protected]5394e422011-01-20 22:07:431261 DCHECK(transaction_.get());
1262
1263 // Proxy gets set first, then WWW.
1264 if (proxy_auth_state_ == AUTH_STATE_NEED_AUTH) {
1265 proxy_auth_state_ = AUTH_STATE_HAVE_AUTH;
1266 } else {
[email protected]dd29bcd72011-03-24 00:03:441267 DCHECK_EQ(server_auth_state_, AUTH_STATE_NEED_AUTH);
[email protected]5394e422011-01-20 22:07:431268 server_auth_state_ = AUTH_STATE_HAVE_AUTH;
1269 }
1270
[email protected]f3cf9802011-10-28 18:44:581271 RestartTransactionWithAuth(credentials);
[email protected]5394e422011-01-20 22:07:431272}
1273
1274void URLRequestHttpJob::CancelAuth() {
[email protected]5394e422011-01-20 22:07:431275 if (proxy_auth_state_ == AUTH_STATE_NEED_AUTH) {
1276 proxy_auth_state_ = AUTH_STATE_CANCELED;
1277 } else {
[email protected]dd29bcd72011-03-24 00:03:441278 DCHECK_EQ(server_auth_state_, AUTH_STATE_NEED_AUTH);
[email protected]5394e422011-01-20 22:07:431279 server_auth_state_ = AUTH_STATE_CANCELED;
1280 }
1281
Matt Menke0743e342019-06-11 20:48:101282 // The above lines should ensure this is the case.
1283 DCHECK(!NeedsAuth());
[email protected]5394e422011-01-20 22:07:431284
Matt Menke0743e342019-06-11 20:48:101285 // Let the consumer read the HTTP error page. NeedsAuth() should now return
1286 // false, so NotifyHeadersComplete() should not request auth from the client
1287 // again.
[email protected]5394e422011-01-20 22:07:431288 //
Matt Menke0743e342019-06-11 20:48:101289 // Have to do this via PostTask to avoid re-entrantly calling into the
1290 // consumer.
skyostil4891b25b2015-06-11 11:43:451291 base::ThreadTaskRunnerHandle::Get()->PostTask(
Matt Menke0743e342019-06-11 20:48:101292 FROM_HERE, base::BindOnce(&URLRequestHttpJob::NotifyFinalHeadersReceived,
1293 weak_factory_.GetWeakPtr()));
[email protected]5394e422011-01-20 22:07:431294}
1295
1296void URLRequestHttpJob::ContinueWithCertificate(
mattm436ccfe2017-06-19 20:24:081297 scoped_refptr<X509Certificate> client_cert,
1298 scoped_refptr<SSLPrivateKey> client_private_key) {
David Benjamin0bda12f2018-02-07 19:58:451299 DCHECK(transaction_);
[email protected]5394e422011-01-20 22:07:431300
1301 DCHECK(!response_info_) << "should not have a response yet";
David Benjamin0bda12f2018-02-07 19:58:451302 DCHECK(!override_response_headers_);
[email protected]3b23a222013-05-15 21:33:251303 receive_headers_end_ = base::TimeTicks();
[email protected]5394e422011-01-20 22:07:431304
[email protected]ec23f522011-02-22 21:01:381305 ResetTimer();
1306
mmenked3a02b32016-11-16 20:21:321307 int rv = transaction_->RestartWithCertificate(
mattm436ccfe2017-06-19 20:24:081308 std::move(client_cert), std::move(client_private_key),
Yannic Bonenbergercc716d42019-09-04 17:05:361309 base::BindOnce(&URLRequestHttpJob::OnStartCompleted,
1310 base::Unretained(this)));
[email protected]5394e422011-01-20 22:07:431311 if (rv == ERR_IO_PENDING)
1312 return;
1313
1314 // The transaction started synchronously, but we need to notify the
1315 // URLRequest delegate via the message loop.
skyostil4891b25b2015-06-11 11:43:451316 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf4fe5172019-02-15 18:53:491317 FROM_HERE, base::BindOnce(&URLRequestHttpJob::OnStartCompleted,
1318 weak_factory_.GetWeakPtr(), rv));
[email protected]5394e422011-01-20 22:07:431319}
1320
1321void URLRequestHttpJob::ContinueDespiteLastError() {
1322 // If the transaction was destroyed, then the job was cancelled.
1323 if (!transaction_.get())
1324 return;
1325
1326 DCHECK(!response_info_) << "should not have a response yet";
David Benjamin0bda12f2018-02-07 19:58:451327 DCHECK(!override_response_headers_);
[email protected]3b23a222013-05-15 21:33:251328 receive_headers_end_ = base::TimeTicks();
[email protected]5394e422011-01-20 22:07:431329
[email protected]ec23f522011-02-22 21:01:381330 ResetTimer();
1331
Yannic Bonenbergercc716d42019-09-04 17:05:361332 int rv = transaction_->RestartIgnoringLastError(base::BindOnce(
1333 &URLRequestHttpJob::OnStartCompleted, base::Unretained(this)));
[email protected]5394e422011-01-20 22:07:431334 if (rv == ERR_IO_PENDING)
1335 return;
1336
1337 // The transaction started synchronously, but we need to notify the
1338 // URLRequest delegate via the message loop.
skyostil4891b25b2015-06-11 11:43:451339 base::ThreadTaskRunnerHandle::Get()->PostTask(
kylecharf4fe5172019-02-15 18:53:491340 FROM_HERE, base::BindOnce(&URLRequestHttpJob::OnStartCompleted,
1341 weak_factory_.GetWeakPtr(), rv));
[email protected]5394e422011-01-20 22:07:431342}
1343
[email protected]f001bd6a2011-12-08 04:31:371344bool URLRequestHttpJob::ShouldFixMismatchedContentLength(int rv) const {
1345 // Some servers send the body compressed, but specify the content length as
rdsmith81f607562014-11-21 18:35:161346 // the uncompressed size. Although this violates the HTTP spec we want to
[email protected]f001bd6a2011-12-08 04:31:371347 // support it (as IE and FireFox do), but *only* for an exact match.
1348 // See http://crbug.com/79694.
ttuttle859dc7a2015-04-23 19:42:291349 if (rv == ERR_CONTENT_LENGTH_MISMATCH ||
1350 rv == ERR_INCOMPLETE_CHUNKED_ENCODING) {
mmenked3a02b32016-11-16 20:21:321351 if (request_->response_headers()) {
Avi Drissman13fc8932015-12-20 04:40:461352 int64_t expected_length =
1353 request_->response_headers()->GetContentLength();
pkastingf5279482016-07-27 02:18:201354 VLOG(1) << __func__ << "() \"" << request_->url().spec() << "\""
[email protected]f001bd6a2011-12-08 04:31:371355 << " content-length = " << expected_length
1356 << " pre total = " << prefilter_bytes_read()
1357 << " post total = " << postfilter_bytes_read();
1358 if (postfilter_bytes_read() == expected_length) {
1359 // Clear the error.
1360 return true;
1361 }
1362 }
1363 }
1364 return false;
1365}
1366
xunjieli26ede962015-11-23 19:39:131367int URLRequestHttpJob::ReadRawData(IOBuffer* buf, int buf_size) {
[email protected]5394e422011-01-20 22:07:431368 DCHECK_NE(buf_size, 0);
[email protected]5394e422011-01-20 22:07:431369 DCHECK(!read_in_progress_);
1370
Yannic Bonenbergercc716d42019-09-04 17:05:361371 int rv =
1372 transaction_->Read(buf, buf_size,
1373 base::BindOnce(&URLRequestHttpJob::OnReadCompleted,
1374 base::Unretained(this)));
[email protected]85c1dce2011-07-06 12:01:291375
[email protected]f001bd6a2011-12-08 04:31:371376 if (ShouldFixMismatchedContentLength(rv))
xunjieli26ede962015-11-23 19:39:131377 rv = OK;
[email protected]f001bd6a2011-12-08 04:31:371378
xunjieli26ede962015-11-23 19:39:131379 if (rv == 0 || (rv < 0 && rv != ERR_IO_PENDING))
1380 DoneWithRequest(FINISHED);
[email protected]5394e422011-01-20 22:07:431381
xunjieli26ede962015-11-23 19:39:131382 if (rv == ERR_IO_PENDING)
[email protected]5394e422011-01-20 22:07:431383 read_in_progress_ = true;
[email protected]5394e422011-01-20 22:07:431384
xunjieli26ede962015-11-23 19:39:131385 return rv;
[email protected]5394e422011-01-20 22:07:431386}
1387
Avi Drissman13fc8932015-12-20 04:40:461388int64_t URLRequestHttpJob::GetTotalReceivedBytes() const {
sclittlece72c482015-08-24 20:20:591389 int64_t total_received_bytes =
1390 total_received_bytes_from_previous_transactions_;
1391 if (transaction_)
1392 total_received_bytes += transaction_->GetTotalReceivedBytes();
1393 return total_received_bytes;
[email protected]71e5ff8f2014-01-13 09:44:041394}
1395
sclittlefb249892015-09-10 21:33:221396int64_t URLRequestHttpJob::GetTotalSentBytes() const {
1397 int64_t total_sent_bytes = total_sent_bytes_from_previous_transactions_;
1398 if (transaction_)
1399 total_sent_bytes += transaction_->GetTotalSentBytes();
1400 return total_sent_bytes;
1401}
1402
[email protected]5c04f722011-08-12 17:52:471403void URLRequestHttpJob::DoneReading() {
[email protected]e50efea2014-03-24 18:41:001404 if (transaction_) {
[email protected]5c04f722011-08-12 17:52:471405 transaction_->DoneReading();
[email protected]e50efea2014-03-24 18:41:001406 }
1407 DoneWithRequest(FINISHED);
1408}
1409
1410void URLRequestHttpJob::DoneReadingRedirectResponse() {
1411 if (transaction_) {
Eric Orthcd71ede2021-09-14 18:18:501412 DCHECK(!override_response_info_);
Raul Tambre94493c652019-03-11 17:18:351413 if (transaction_->GetResponseInfo()->headers->IsRedirect(nullptr)) {
[email protected]e50efea2014-03-24 18:41:001414 // If the original headers indicate a redirect, go ahead and cache the
1415 // response, even if the |override_response_headers_| are a redirect to
1416 // another location.
1417 transaction_->DoneReading();
1418 } else {
1419 // Otherwise, |override_response_headers_| must be non-NULL and contain
1420 // bogus headers indicating a redirect.
dchengc2e01e82014-08-27 00:24:421421 DCHECK(override_response_headers_.get());
Raul Tambre94493c652019-03-11 17:18:351422 DCHECK(override_response_headers_->IsRedirect(nullptr));
[email protected]e50efea2014-03-24 18:41:001423 transaction_->StopCaching();
1424 }
1425 }
[email protected]5c04f722011-08-12 17:52:471426 DoneWithRequest(FINISHED);
1427}
1428
Tsuyoshi Horo01faed62019-02-20 22:11:371429IPEndPoint URLRequestHttpJob::GetResponseRemoteEndpoint() const {
1430 return response_info_ ? response_info_->remote_endpoint : IPEndPoint();
[email protected]6d81b482011-02-22 19:47:191431}
1432
[email protected]ec23f522011-02-22 21:01:381433void URLRequestHttpJob::RecordTimer() {
1434 if (request_creation_time_.is_null()) {
1435 NOTREACHED()
1436 << "The same transaction shouldn't start twice without new timing.";
1437 return;
1438 }
1439
[email protected]320a29f12011-03-21 14:47:411440 base::TimeDelta to_start = base::Time::Now() - request_creation_time_;
[email protected]ec23f522011-02-22 21:01:381441 request_creation_time_ = base::Time();
[email protected]8684a8812011-03-22 13:59:381442
[email protected]5c68d692011-08-24 04:59:411443 UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpTimeToFirstByte", to_start);
David Benjaminb3125022021-05-10 19:57:081444
1445 // Record additional metrics for TLS 1.3 servers. This is to help measure the
1446 // impact of enabling 0-RTT. The effects of 0-RTT will be muted because not
1447 // all TLS 1.3 servers enable 0-RTT, and only the first round-trip on a
1448 // connection makes use of 0-RTT. However, 0-RTT can affect how requests are
1449 // bound to connections and which connections offer resumption. We look at all
1450 // TLS 1.3 responses for an apples-to-apples comparison.
1451 //
David Benjamin924cedad2021-06-21 20:36:351452 // Additionally record metrics for Google hosts. Most Google hosts are known
1453 // to implement 0-RTT, so this gives more targeted metrics as we initially
1454 // roll out client support.
1455 //
David Benjaminb3125022021-05-10 19:57:081456 // TODO(https://crbug.com/641225): Remove these metrics after launching 0-RTT.
1457 if (transaction_ && transaction_->GetResponseInfo() &&
1458 IsTLS13OverTCP(*transaction_->GetResponseInfo())) {
1459 base::UmaHistogramMediumTimes("Net.HttpTimeToFirstByte.TLS13", to_start);
David Benjamin924cedad2021-06-21 20:36:351460 if (HasGoogleHost(request()->url())) {
1461 base::UmaHistogramMediumTimes("Net.HttpTimeToFirstByte.TLS13.Google",
1462 to_start);
1463 }
David Benjaminb3125022021-05-10 19:57:081464 }
[email protected]ec23f522011-02-22 21:01:381465}
1466
1467void URLRequestHttpJob::ResetTimer() {
1468 if (!request_creation_time_.is_null()) {
1469 NOTREACHED()
1470 << "The timer was reset before it was recorded.";
1471 return;
1472 }
1473 request_creation_time_ = base::Time::Now();
1474}
1475
Andrey Kosyakov83a6eee2017-08-14 19:20:041476void URLRequestHttpJob::SetRequestHeadersCallback(
1477 RequestHeadersCallback callback) {
1478 DCHECK(!transaction_);
1479 DCHECK(!request_headers_callback_);
1480 request_headers_callback_ = std::move(callback);
1481}
1482
Kenichi Ishibashi74155532021-03-13 01:38:061483void URLRequestHttpJob::SetEarlyResponseHeadersCallback(
1484 ResponseHeadersCallback callback) {
1485 DCHECK(!transaction_);
1486 DCHECK(!early_response_headers_callback_);
1487 early_response_headers_callback_ = std::move(callback);
1488}
1489
Andrey Kosyakov2e893e62017-08-31 17:00:521490void URLRequestHttpJob::SetResponseHeadersCallback(
1491 ResponseHeadersCallback callback) {
1492 DCHECK(!transaction_);
1493 DCHECK(!response_headers_callback_);
1494 response_headers_callback_ = std::move(callback);
1495}
1496
David Benjaminb3125022021-05-10 19:57:081497void URLRequestHttpJob::RecordCompletionHistograms(CompletionCause reason) {
[email protected]bbaea8f2011-06-24 00:11:011498 if (start_time_.is_null())
1499 return;
1500
1501 base::TimeDelta total_time = base::TimeTicks::Now() - start_time_;
1502 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTime", total_time);
1503
1504 if (reason == FINISHED) {
Devdeep Ray0c6966d2017-07-14 00:58:221505 UmaHistogramTimes(
1506 base::StringPrintf("Net.HttpJob.TotalTimeSuccess.Priority%d",
1507 request()->priority()),
1508 total_time);
[email protected]bbaea8f2011-06-24 00:11:011509 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeSuccess", total_time);
1510 } else {
1511 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeCancel", total_time);
1512 }
1513
[email protected]4b4d20242012-02-23 18:27:461514 if (response_info_) {
rtennetie55c4b72015-08-03 21:48:351515 // QUIC (by default) supports https scheme only, thus track https URLs only
1516 // for QUIC.
1517 bool is_https_google = request() && request()->url().SchemeIs("https") &&
1518 HasGoogleHost(request()->url());
rtenneti72928bb2015-04-28 18:28:131519 bool used_quic = response_info_->DidUseQuic();
rtennetie55c4b72015-08-03 21:48:351520 if (is_https_google) {
rtenneti72928bb2015-04-28 18:28:131521 if (used_quic) {
rtennetie55c4b72015-08-03 21:48:351522 UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpJob.TotalTime.Secure.Quic",
1523 total_time);
rtenneti72928bb2015-04-28 18:28:131524 }
1525 }
jkarlinded0021b2016-12-05 16:01:061526
David Benjaminb3125022021-05-10 19:57:081527 // Record metrics for TLS 1.3 to measure the impact of 0-RTT. See comment in
1528 // RecordTimer().
1529 //
1530 // TODO(https://crbug.com/641225): Remove these metrics after launching
1531 // 0-RTT.
1532 if (IsTLS13OverTCP(*response_info_)) {
1533 base::UmaHistogramTimes("Net.HttpJob.TotalTime.TLS13", total_time);
David Benjamin924cedad2021-06-21 20:36:351534 if (is_https_google) {
1535 base::UmaHistogramTimes("Net.HttpJob.TotalTime.TLS13.Google",
1536 total_time);
1537 }
David Benjaminb3125022021-05-10 19:57:081538 }
1539
jkarlinded0021b2016-12-05 16:01:061540 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpJob.PrefilterBytesRead",
1541 prefilter_bytes_read(), 1, 50000000, 50);
[email protected]4b4d20242012-02-23 18:27:461542 if (response_info_->was_cached) {
1543 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeCached", total_time);
jkarlinded0021b2016-12-05 16:01:061544 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpJob.PrefilterBytesRead.Cache",
1545 prefilter_bytes_read(), 1, 50000000, 50);
1546
jkarlincc6943d2016-04-25 19:25:351547 if (response_info_->unused_since_prefetch)
Steven Holte6143e642017-06-28 19:47:381548 UMA_HISTOGRAM_COUNTS_1M("Net.Prefetch.HitBytes",
1549 prefilter_bytes_read());
jkarlincc6943d2016-04-25 19:25:351550 } else {
[email protected]4b4d20242012-02-23 18:27:461551 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeNotCached", total_time);
jkarlinded0021b2016-12-05 16:01:061552 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpJob.PrefilterBytesRead.Net",
1553 prefilter_bytes_read(), 1, 50000000, 50);
1554
1555 if (request_info_.load_flags & LOAD_PREFETCH) {
Steven Holte6143e642017-06-28 19:47:381556 UMA_HISTOGRAM_COUNTS_1M("Net.Prefetch.PrefilterBytesReadFromNetwork",
1557 prefilter_bytes_read());
jkarlinded0021b2016-12-05 16:01:061558 }
rtennetie55c4b72015-08-03 21:48:351559 if (is_https_google) {
rtenneti72928bb2015-04-28 18:28:131560 if (used_quic) {
rtennetie55c4b72015-08-03 21:48:351561 UMA_HISTOGRAM_MEDIUM_TIMES(
1562 "Net.HttpJob.TotalTimeNotCached.Secure.Quic", total_time);
rtenneti72928bb2015-04-28 18:28:131563 } else {
rtennetie55c4b72015-08-03 21:48:351564 UMA_HISTOGRAM_MEDIUM_TIMES(
1565 "Net.HttpJob.TotalTimeNotCached.Secure.NotQuic", total_time);
rtenneti72928bb2015-04-28 18:28:131566 }
1567 }
[email protected]b73656ca2011-07-22 17:42:171568 }
[email protected]bbaea8f2011-06-24 00:11:011569 }
1570
1571 start_time_ = base::TimeTicks();
1572}
1573
1574void URLRequestHttpJob::DoneWithRequest(CompletionCause reason) {
1575 if (done_)
1576 return;
1577 done_ = true;
tbansal79ed5cd2015-08-10 18:53:561578
1579 // Notify NetworkQualityEstimator.
mmenke7ce675a2016-11-07 17:08:301580 NetworkQualityEstimator* network_quality_estimator =
1581 request()->context()->network_quality_estimator();
1582 if (network_quality_estimator) {
Matt Menke68813f02019-12-17 02:19:361583 network_quality_estimator->NotifyRequestCompleted(*request());
tbansal79ed5cd2015-08-10 18:53:561584 }
1585
David Benjaminb3125022021-05-10 19:57:081586 RecordCompletionHistograms(reason);
mmenke7ce675a2016-11-07 17:08:301587 request()->set_received_response_content_length(prefilter_bytes_read());
[email protected]bbaea8f2011-06-24 00:11:011588}
1589
[email protected]ea8141e2011-10-05 13:12:511590HttpResponseHeaders* URLRequestHttpJob::GetResponseHeaders() const {
Eric Orthcd71ede2021-09-14 18:18:501591 if (override_response_info_) {
1592 DCHECK(!transaction_.get());
1593 return override_response_info_->headers.get();
1594 }
1595
[email protected]ea8141e2011-10-05 13:12:511596 DCHECK(transaction_.get());
1597 DCHECK(transaction_->GetResponseInfo());
Eric Orthcd71ede2021-09-14 18:18:501598
[email protected]ea8141e2011-10-05 13:12:511599 return override_response_headers_.get() ?
[email protected]90499482013-06-01 00:39:501600 override_response_headers_.get() :
1601 transaction_->GetResponseInfo()->headers.get();
[email protected]ea8141e2011-10-05 13:12:511602}
1603
1604void URLRequestHttpJob::NotifyURLRequestDestroyed() {
1605 awaiting_callback_ = false;
tbansal80a52162016-05-20 17:55:041606
1607 // Notify NetworkQualityEstimator.
mmenke7ce675a2016-11-07 17:08:301608 NetworkQualityEstimator* network_quality_estimator =
1609 request()->context()->network_quality_estimator();
1610 if (network_quality_estimator)
1611 network_quality_estimator->NotifyURLRequestDestroyed(*request());
[email protected]ea8141e2011-10-05 13:12:511612}
1613
Dylan Cutler69a51c92021-12-08 16:32:011614void URLRequestHttpJob::ComputeCookiePartitionKey() {
1615 const CookieStore* cookie_store = request_->context()->cookie_store();
1616 if (!cookie_store) {
1617 cookie_partition_key_ = absl::nullopt;
1618 return;
1619 }
1620 cookie_partition_key_ = CookieAccessDelegate::CreateCookiePartitionKey(
1621 cookie_store->cookie_access_delegate(),
1622 request_->isolation_info().network_isolation_key());
1623}
1624
[email protected]4f5656c62010-12-13 10:47:091625} // namespace net