blob: 451f5ba394da5ee93c49214d6f8a5c06ae4a957b [file] [log] [blame]
[email protected]fecef222012-01-05 02:26:151// Copyright (c) 2012 The Chromium Authors. All rights reserved.
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit586acc5fe2008-07-26 22:42:524
[email protected]175adac2008-07-30 17:28:045#include "net/url_request/url_request_http_job.h"
initial.commit586acc5fe2008-07-26 22:42:526
mmenked3a02b32016-11-16 20:21:327#include <vector>
8
[email protected]4ed2755f2008-12-15 09:01:339#include "base/base_switches.h"
[email protected]4f9e5c82011-11-17 16:04:5610#include "base/bind.h"
[email protected]084262c2011-12-01 21:12:4711#include "base/bind_helpers.h"
[email protected]4ed2755f2008-12-15 09:01:3312#include "base/command_line.h"
[email protected]39ce5c02008-08-22 04:03:4413#include "base/compiler_specific.h"
[email protected]60889422008-09-23 01:18:1614#include "base/file_version_info.h"
skyostil4891b25b2015-06-11 11:43:4515#include "base/location.h"
Avi Drissman13fc8932015-12-20 04:40:4616#include "base/macros.h"
[email protected]8684a8812011-03-22 13:59:3817#include "base/metrics/field_trial.h"
Devdeep Ray0c6966d2017-07-14 00:58:2218#include "base/metrics/histogram_functions.h"
asvitkinec3c93722015-06-17 14:48:3719#include "base/metrics/histogram_macros.h"
[email protected]5b90b5d2009-04-30 23:06:0120#include "base/rand_util.h"
skyostil4891b25b2015-06-11 11:43:4521#include "base/single_thread_task_runner.h"
[email protected]4dc3ad4f2013-06-11 07:15:5022#include "base/strings/string_util.h"
Devdeep Ray0c6966d2017-07-14 00:58:2223#include "base/strings/stringprintf.h"
gabf767595f2016-05-11 18:50:3524#include "base/threading/thread_task_runner_handle.h"
[email protected]f002abb2013-06-28 02:30:2125#include "base/time/time.h"
ssid6d6b40102016-04-05 18:59:5626#include "base/trace_event/trace_event.h"
estade5e5529d2015-05-21 20:59:1127#include "base/values.h"
mmenkefd9d15c2017-06-29 13:45:5428#include "build/buildflag.h"
[email protected]6d81b482011-02-22 19:47:1929#include "net/base/host_port_pair.h"
[email protected]b8430722008-09-17 20:05:4430#include "net/base/load_flags.h"
initial.commit586acc5fe2008-07-26 22:42:5231#include "net/base/net_errors.h"
[email protected]636eccd2011-06-28 12:28:0132#include "net/base/network_delegate.h"
mkwstf71d0bd2016-03-21 14:15:2433#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
xunjieli0b7f5b62016-12-06 20:43:4834#include "net/base/trace_constants.h"
tfarina7a4a7fd2016-01-20 14:23:4435#include "net/base/url_util.h"
[email protected]6e7845ae2013-03-29 21:48:1136#include "net/cert/cert_status_flags.h"
Emily Stark8b411de02017-11-23 20:21:2737#include "net/cert/ct_policy_status.h"
Ryan Sleevi19a7bde2017-11-22 06:51:3938#include "net/cert/known_roots.h"
Randy Smithe23356c22017-11-14 01:41:5039#include "net/cookies/canonical_cookie.h"
[email protected]dc8313a2014-03-24 21:38:1440#include "net/cookies/cookie_store.h"
xunjieli28a18772016-10-25 15:30:0641#include "net/filter/brotli_source_stream.h"
42#include "net/filter/filter_source_stream.h"
43#include "net/filter/gzip_source_stream.h"
xunjieli28a18772016-10-25 15:30:0644#include "net/filter/source_stream.h"
[email protected]262191712014-03-22 00:46:5745#include "net/http/http_content_disposition.h"
[email protected]7a299a92012-10-24 23:54:5046#include "net/http/http_network_session.h"
[email protected]8c76ae22010-04-20 22:15:4347#include "net/http/http_request_headers.h"
[email protected]319d9e6f2009-02-18 19:47:2148#include "net/http/http_response_headers.h"
initial.commit586acc5fe2008-07-26 22:42:5249#include "net/http/http_response_info.h"
[email protected]9094b602012-02-27 21:44:5850#include "net/http/http_status_code.h"
initial.commit586acc5fe2008-07-26 22:42:5251#include "net/http/http_transaction.h"
52#include "net/http/http_transaction_factory.h"
[email protected]0757e7702009-03-27 04:00:2253#include "net/http/http_util.h"
mikecirone8b85c432016-09-08 19:11:0054#include "net/log/net_log_event_type.h"
mikecironef22f9812016-10-04 03:40:1955#include "net/log/net_log_with_source.h"
mmenkefd9d15c2017-06-29 13:45:5456#include "net/net_features.h"
tbansalca83c002016-04-28 20:56:2857#include "net/nqe/network_quality_estimator.h"
Lily Houghton582d4622018-01-22 22:43:4058#include "net/proxy_resolution/proxy_info.h"
59#include "net/proxy_resolution/proxy_retry_info.h"
60#include "net/proxy_resolution/proxy_service.h"
nharper5babb5e62016-03-09 18:58:0761#include "net/ssl/channel_id_service.h"
[email protected]536fd0b2013-03-14 17:41:5762#include "net/ssl/ssl_cert_request_info.h"
63#include "net/ssl/ssl_config_service.h"
[email protected]ee4c30d2012-11-07 15:08:4364#include "net/url_request/http_user_agent_settings.h"
initial.commit586acc5fe2008-07-26 22:42:5265#include "net/url_request/url_request.h"
[email protected]319d9e6f2009-02-18 19:47:2166#include "net/url_request/url_request_context.h"
initial.commit586acc5fe2008-07-26 22:42:5267#include "net/url_request/url_request_error_job.h"
[email protected]e0f35c92013-05-08 16:04:3468#include "net/url_request/url_request_job_factory.h"
[email protected]06965e02009-09-04 21:36:4269#include "net/url_request/url_request_redirect_job.h"
[email protected]6b3f9642010-11-25 02:29:0670#include "net/url_request/url_request_throttler_manager.h"
[email protected]f4533ba2013-11-28 09:35:4171#include "net/websockets/websocket_handshake_stream_base.h"
mkwst8241a122015-10-20 07:15:1072#include "url/origin.h"
initial.commit586acc5fe2008-07-26 22:42:5273
mgershd21d6d142016-12-14 23:06:3674#if defined(OS_ANDROID)
75#include "net/android/network_library.h"
76#endif
77
mmenkefd9d15c2017-06-29 13:45:5478#if BUILDFLAG(ENABLE_REPORTING)
juliatuttle667c0bb2017-07-06 15:17:1379#include "net/reporting/reporting_header_parser.h"
mmenkefd9d15c2017-06-29 13:45:5480#include "net/reporting/reporting_service.h"
Julia Tuttle3f9acac2017-11-20 22:06:3081#include "net/url_request/network_error_logging_delegate.h"
mmenkefd9d15c2017-06-29 13:45:5482#endif // BUILDFLAG(ENABLE_REPORTING)
83
mkwst202534e32016-01-15 16:07:1584namespace {
85
Ryan Sleevi19a7bde2017-11-22 06:51:3986// Records details about the most-specific trust anchor in |spki_hashes|,
87// which is expected to be ordered with the leaf cert first and the root cert
88// last. This complements the per-verification histogram
89// Net.Certificate.TrustAnchor.Verify
90void LogTrustAnchor(const net::HashValueVector& spki_hashes) {
Ryan Sleevid756c2d2017-12-01 02:07:4891 // Don't record metrics if there are no hashes; this is true if the HTTP
92 // load did not come from an active network connection, such as the disk
93 // cache or a synthesized response.
94 if (spki_hashes.empty())
95 return;
96
Ryan Sleevi19a7bde2017-11-22 06:51:3997 int32_t id = 0;
98 for (const auto& hash : spki_hashes) {
99 id = net::GetNetTrustAnchorHistogramIdForSPKI(hash);
100 if (id != 0)
101 break;
102 }
Ilya Sherman0eb39802017-12-08 20:58:18103 base::UmaHistogramSparse("Net.Certificate.TrustAnchor.Request", id);
Ryan Sleevi19a7bde2017-11-22 06:51:39104}
105
Emily Stark8b411de02017-11-23 20:21:27106// Records per-request histograms relating to Certificate Transparency
107// compliance.
108void RecordCTHistograms(const net::SSLInfo& ssl_info) {
Emily Stark9676ea82017-11-29 08:10:08109 if (ssl_info.ct_policy_compliance ==
110 net::ct::CTPolicyCompliance::CT_POLICY_COMPLIANCE_DETAILS_NOT_AVAILABLE) {
Emily Stark8b411de02017-11-23 20:21:27111 return;
Emily Stark9676ea82017-11-29 08:10:08112 }
Emily Stark8b411de02017-11-23 20:21:27113 if (!ssl_info.is_issued_by_known_root)
114 return;
115
116 // Connections with major errors other than CERTIFICATE_TRANSPARENCY_REQUIRED
117 // would have failed anyway, so do not record these histograms for such
118 // requests.
119 net::CertStatus other_errors =
120 ssl_info.cert_status &
121 ~net::CERT_STATUS_CERTIFICATE_TRANSPARENCY_REQUIRED;
122 if (net::IsCertStatusError(other_errors) &&
123 !net::IsCertStatusMinorError(other_errors)) {
124 return;
125 }
126
127 // Record the CT compliance of each request, to give a picture of the
128 // percentage of overall requests that are CT-compliant.
129 UMA_HISTOGRAM_ENUMERATION(
130 "Net.CertificateTransparency.RequestComplianceStatus",
Emily Stark627238f2017-11-29 03:29:54131 ssl_info.ct_policy_compliance,
132 net::ct::CTPolicyCompliance::CT_POLICY_MAX);
Emily Stark8b411de02017-11-23 20:21:27133 // Record the CT compliance of each request which was required to be CT
134 // compliant. This gives a picture of the sites that are supposed to be
135 // compliant and how well they do at actually being compliant.
136 if (ssl_info.ct_policy_compliance_required) {
137 UMA_HISTOGRAM_ENUMERATION(
138 "Net.CertificateTransparency.CTRequiredRequestComplianceStatus",
Emily Stark627238f2017-11-29 03:29:54139 ssl_info.ct_policy_compliance,
140 net::ct::CTPolicyCompliance::CT_POLICY_MAX);
Emily Stark8b411de02017-11-23 20:21:27141 }
142}
143
nharper3876dd562016-03-29 22:52:32144// Logs whether the CookieStore used for this request matches the
145// ChannelIDService used when establishing the connection that this request is
146// sent over. This logging is only done for requests to accounts.google.com, and
147// only for requests where Channel ID was sent when establishing the connection.
nharper79234722016-03-22 20:28:47148void LogChannelIDAndCookieStores(const GURL& url,
149 const net::URLRequestContext* context,
nharper5babb5e62016-03-09 18:58:07150 const net::SSLInfo& ssl_info) {
nharper79234722016-03-22 20:28:47151 if (url.host() != "accounts.google.com" || !ssl_info.channel_id_sent)
nharper5babb5e62016-03-09 18:58:07152 return;
153 // This enum is used for an UMA histogram - don't reuse or renumber entries.
154 enum {
nharper09ccd502016-03-10 01:54:28155 // Value 0 was removed (CID_EPHEMERAL_COOKIE_EPHEMERAL)
nharper3876dd562016-03-29 22:52:32156 // ChannelIDStore is ephemeral, but CookieStore is persistent.
nharper5babb5e62016-03-09 18:58:07157 CID_EPHEMERAL_COOKIE_PERSISTENT = 1,
nharper3876dd562016-03-29 22:52:32158 // ChannelIDStore is persistent, but CookieStore is ephemeral.
nharper5babb5e62016-03-09 18:58:07159 CID_PERSISTENT_COOKIE_EPHEMERAL = 2,
nharper09ccd502016-03-10 01:54:28160 // Value 3 was removed (CID_PERSISTENT_COOKIE_PERSISTENT)
nharper3876dd562016-03-29 22:52:32161 // There is no CookieStore for this request.
nharper5babb5e62016-03-09 18:58:07162 NO_COOKIE_STORE = 4,
nharper3876dd562016-03-29 22:52:32163 // There is no ChannelIDStore for this request. This should never happen,
164 // because we only log if Channel ID was sent.
nharper5babb5e62016-03-09 18:58:07165 NO_CHANNEL_ID_STORE = 5,
nharper015b9e42016-06-29 01:41:52166 // Value 6 was removed (KNOWN_MISMATCH).
nharper3876dd562016-03-29 22:52:32167 // Both stores are ephemeral, and the ChannelIDService used when
168 // establishing the connection is the same one that the CookieStore was
169 // created to be used with.
nharper09ccd502016-03-10 01:54:28170 EPHEMERAL_MATCH = 7,
nharper3876dd562016-03-29 22:52:32171 // Both stores are ephemeral, but a different CookieStore should have been
172 // used on this request.
nharper09ccd502016-03-10 01:54:28173 EPHEMERAL_MISMATCH = 8,
nharper3876dd562016-03-29 22:52:32174 // Both stores are persistent, and the ChannelIDService used when
175 // establishing the connection is the same one that the CookieStore was
176 // created to be used with.
nharper09ccd502016-03-10 01:54:28177 PERSISTENT_MATCH = 9,
nharper3876dd562016-03-29 22:52:32178 // Both stores are persistent, but a different CookieStore should have been
179 // used on this request.
nharper09ccd502016-03-10 01:54:28180 PERSISTENT_MISMATCH = 10,
nharper3876dd562016-03-29 22:52:32181 // Both stores are ephemeral, but it was never recorded in the CookieStore
182 // which ChannelIDService it was created for, so it is unknown whether the
183 // stores match.
184 EPHEMERAL_UNKNOWN = 11,
185 // Both stores are persistent, but it was never recorded in the CookieStore
186 // which ChannelIDService it was created for, so it is unknown whether the
187 // stores match.
188 PERSISTENT_UNKNOWN = 12,
nharper5babb5e62016-03-09 18:58:07189 EPHEMERALITY_MAX
190 } ephemerality;
mmenke6ddfbea2017-05-31 21:48:41191 const net::HttpNetworkSession::Context* session_context =
192 context->GetNetworkSessionContext();
nharper5babb5e62016-03-09 18:58:07193 net::CookieStore* cookie_store = context->cookie_store();
mmenke6ddfbea2017-05-31 21:48:41194 if (session_context == nullptr ||
195 session_context->channel_id_service == nullptr) {
nharper5babb5e62016-03-09 18:58:07196 ephemerality = NO_CHANNEL_ID_STORE;
197 } else if (cookie_store == nullptr) {
198 ephemerality = NO_COOKIE_STORE;
mmenke6ddfbea2017-05-31 21:48:41199 } else if (session_context->channel_id_service->GetChannelIDStore()
200 ->IsEphemeral()) {
nharper5babb5e62016-03-09 18:58:07201 if (cookie_store->IsEphemeral()) {
nharper3876dd562016-03-29 22:52:32202 if (cookie_store->GetChannelIDServiceID() == -1) {
203 ephemerality = EPHEMERAL_UNKNOWN;
204 } else if (cookie_store->GetChannelIDServiceID() ==
mmenke6ddfbea2017-05-31 21:48:41205 session_context->channel_id_service->GetUniqueID()) {
nharper09ccd502016-03-10 01:54:28206 ephemerality = EPHEMERAL_MATCH;
207 } else {
nharper3876dd562016-03-29 22:52:32208 NOTREACHED();
nharper09ccd502016-03-10 01:54:28209 ephemerality = EPHEMERAL_MISMATCH;
210 }
nharper5babb5e62016-03-09 18:58:07211 } else {
nharper3876dd562016-03-29 22:52:32212 NOTREACHED();
nharper5babb5e62016-03-09 18:58:07213 ephemerality = CID_EPHEMERAL_COOKIE_PERSISTENT;
214 }
215 } else if (cookie_store->IsEphemeral()) {
nharper49122482016-04-29 18:00:58216 NOTREACHED();
nharper5babb5e62016-03-09 18:58:07217 ephemerality = CID_PERSISTENT_COOKIE_EPHEMERAL;
nharper3876dd562016-03-29 22:52:32218 } else if (cookie_store->GetChannelIDServiceID() == -1) {
219 ephemerality = PERSISTENT_UNKNOWN;
220 } else if (cookie_store->GetChannelIDServiceID() ==
mmenke6ddfbea2017-05-31 21:48:41221 session_context->channel_id_service->GetUniqueID()) {
nharper09ccd502016-03-10 01:54:28222 ephemerality = PERSISTENT_MATCH;
nharper5babb5e62016-03-09 18:58:07223 } else {
nharper3876dd562016-03-29 22:52:32224 NOTREACHED();
nharper09ccd502016-03-10 01:54:28225 ephemerality = PERSISTENT_MISMATCH;
nharper5babb5e62016-03-09 18:58:07226 }
227 UMA_HISTOGRAM_ENUMERATION("Net.TokenBinding.StoreEphemerality", ephemerality,
228 EPHEMERALITY_MAX);
229}
230
Mike West86149882017-07-28 10:41:49231void LogCookieAgeForNonSecureRequest(const net::CookieList& cookie_list,
232 const net::URLRequest& request) {
233 base::Time oldest = base::Time::Max();
234 for (const auto& cookie : cookie_list)
235 oldest = std::min(cookie.CreationDate(), oldest);
236 base::TimeDelta delta = base::Time::Now() - oldest;
237
238 if (net::registry_controlled_domains::SameDomainOrHost(
Mike Westb85da8ed2017-08-10 14:16:46239 request.url(), request.site_for_cookies(),
Mike West86149882017-07-28 10:41:49240 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) {
241 UMA_HISTOGRAM_COUNTS_1000("Cookie.AgeForNonSecureSameSiteRequest",
242 delta.InDays());
243 } else {
244 UMA_HISTOGRAM_COUNTS_1000("Cookie.AgeForNonSecureCrossSiteRequest",
245 delta.InDays());
246 }
247}
248
mkwst202534e32016-01-15 16:07:15249} // namespace
250
[email protected]4f5656c62010-12-13 10:47:09251namespace net {
252
initial.commit586acc5fe2008-07-26 22:42:52253// TODO(darin): make sure the port blocking code is not lost
initial.commit586acc5fe2008-07-26 22:42:52254// static
[email protected]4f5656c62010-12-13 10:47:09255URLRequestJob* URLRequestHttpJob::Factory(URLRequest* request,
[email protected]9f170462012-08-24 01:06:58256 NetworkDelegate* network_delegate,
[email protected]4f5656c62010-12-13 10:47:09257 const std::string& scheme) {
[email protected]f4533ba2013-11-28 09:35:41258 DCHECK(scheme == "http" || scheme == "https" || scheme == "ws" ||
259 scheme == "wss");
initial.commit586acc5fe2008-07-26 22:42:52260
[email protected]81293f482012-08-13 19:35:45261 if (!request->context()->http_transaction_factory()) {
initial.commit586acc5fe2008-07-26 22:42:52262 NOTREACHED() << "requires a valid context";
[email protected]9f170462012-08-24 01:06:58263 return new URLRequestErrorJob(
264 request, network_delegate, ERR_INVALID_ARGUMENT);
initial.commit586acc5fe2008-07-26 22:42:52265 }
266
mgershd21d6d142016-12-14 23:06:36267 const GURL& url = request->url();
268
269 // Check for reasons not to return a URLRequestHttpJob. These don't apply to
270 // https and wss requests.
271 if (!url.SchemeIsCryptographic()) {
272 // Check for HSTS upgrade.
273 TransportSecurityState* hsts =
274 request->context()->transport_security_state();
275 if (hsts && hsts->ShouldUpgradeToSSL(url.host())) {
276 GURL::Replacements replacements;
277 replacements.SetSchemeStr(
Mike West86149882017-07-28 10:41:49278
mgershd21d6d142016-12-14 23:06:36279 url.SchemeIs(url::kHttpScheme) ? url::kHttpsScheme : url::kWssScheme);
280 return new URLRequestRedirectJob(
281 request, network_delegate, url.ReplaceComponents(replacements),
282 // Use status code 307 to preserve the method, so POST requests work.
283 URLRequestRedirectJob::REDIRECT_307_TEMPORARY_REDIRECT, "HSTS");
284 }
285
286#if defined(OS_ANDROID)
287 // Check whether the app allows cleartext traffic to this host, and return
mgersh072720a2016-12-15 16:33:34288 // ERR_CLEARTEXT_NOT_PERMITTED if not.
mgershd21d6d142016-12-14 23:06:36289 if (request->context()->check_cleartext_permitted() &&
290 !android::IsCleartextPermitted(url.host())) {
291 return new URLRequestErrorJob(request, network_delegate,
292 ERR_CLEARTEXT_NOT_PERMITTED);
293 }
294#endif
295 }
mkwst549a5c632016-06-20 14:17:03296
[email protected]ee4c30d2012-11-07 15:08:43297 return new URLRequestHttpJob(request,
298 network_delegate,
299 request->context()->http_user_agent_settings());
initial.commit586acc5fe2008-07-26 22:42:52300}
301
[email protected]ee4c30d2012-11-07 15:08:43302URLRequestHttpJob::URLRequestHttpJob(
303 URLRequest* request,
304 NetworkDelegate* network_delegate,
305 const HttpUserAgentSettings* http_user_agent_settings)
[email protected]9f170462012-08-24 01:06:58306 : URLRequestJob(request, network_delegate),
[email protected]5033ab82013-03-22 20:17:46307 priority_(DEFAULT_PRIORITY),
mmenke54e82af2016-02-16 23:06:30308 response_info_(nullptr),
[email protected]4f5656c62010-12-13 10:47:09309 proxy_auth_state_(AUTH_STATE_DONT_NEED_AUTH),
310 server_auth_state_(AUTH_STATE_DONT_NEED_AUTH),
[email protected]3589e552008-08-20 23:11:34311 read_in_progress_(false),
mmenke54e82af2016-02-16 23:06:30312 throttling_entry_(nullptr),
[email protected]00e48bf2010-12-03 06:15:42313 is_cached_content_(false),
[email protected]dd29bcd72011-03-24 00:03:44314 packet_timing_enabled_(false),
[email protected]bbaea8f2011-06-24 00:11:01315 done_(false),
[email protected]dd29bcd72011-03-24 00:03:44316 bytes_observed_in_packets_(0),
[email protected]5a07c192012-07-30 20:18:22317 awaiting_callback_(false),
[email protected]09812102014-05-24 00:04:11318 http_user_agent_settings_(http_user_agent_settings),
sclittlece72c482015-08-24 20:20:59319 total_received_bytes_from_previous_transactions_(0),
sclittlefb249892015-09-10 21:33:22320 total_sent_bytes_from_previous_transactions_(0),
[email protected]09812102014-05-24 00:04:11321 weak_factory_(this) {
[email protected]a73a2802012-05-02 19:20:15322 URLRequestThrottlerManager* manager = request->context()->throttler_manager();
323 if (manager)
324 throttling_entry_ = manager->RegisterRequestUrl(request->url());
325
[email protected]ec23f522011-02-22 21:01:38326 ResetTimer();
initial.commit586acc5fe2008-07-26 22:42:52327}
328
[email protected]5033ab82013-03-22 20:17:46329URLRequestHttpJob::~URLRequestHttpJob() {
330 CHECK(!awaiting_callback_);
331
[email protected]5033ab82013-03-22 20:17:46332 DoneWithRequest(ABORTED);
333}
334
335void URLRequestHttpJob::SetPriority(RequestPriority priority) {
336 priority_ = priority;
337 if (transaction_)
338 transaction_->SetPriority(priority_);
339}
340
341void URLRequestHttpJob::Start() {
[email protected]5033ab82013-03-22 20:17:46342 DCHECK(!transaction_.get());
343
[email protected]99ecf6e2013-04-10 22:46:13344 // URLRequest::SetReferrer ensures that we do not send username and password
345 // fields in the referrer.
346 GURL referrer(request_->referrer());
[email protected]5033ab82013-03-22 20:17:46347
348 request_info_.url = request_->url();
349 request_info_.method = request_->method();
350 request_info_.load_flags = request_->load_flags();
[email protected]e6d017652013-05-17 18:01:40351 // Enable privacy mode if cookie settings or flags tell us not send or
352 // save cookies.
353 bool enable_privacy_mode =
354 (request_info_.load_flags & LOAD_DO_NOT_SEND_COOKIES) ||
355 (request_info_.load_flags & LOAD_DO_NOT_SAVE_COOKIES) ||
356 CanEnablePrivacyMode();
mkwste3e95992016-02-23 17:45:41357 // Privacy mode could still be disabled in SetCookieHeaderAndStart if we are
358 // going to send previously saved cookies.
[email protected]e6d017652013-05-17 18:01:40359 request_info_.privacy_mode = enable_privacy_mode ?
[email protected]314b03992014-04-01 01:28:53360 PRIVACY_MODE_ENABLED : PRIVACY_MODE_DISABLED;
[email protected]5033ab82013-03-22 20:17:46361
362 // Strip Referer from request_info_.extra_headers to prevent, e.g., plugins
363 // from overriding headers that are controlled using other means. Otherwise a
364 // plugin could set a referrer although sending the referrer is inhibited.
365 request_info_.extra_headers.RemoveHeader(HttpRequestHeaders::kReferer);
366
rdsmith81f607562014-11-21 18:35:16367 // Our consumer should have made sure that this is a safe referrer. See for
[email protected]5033ab82013-03-22 20:17:46368 // instance WebCore::FrameLoader::HideReferrer.
369 if (referrer.is_valid()) {
370 request_info_.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
371 referrer.spec());
372 }
373
nharperd6e65822016-03-30 23:05:48374 request_info_.token_binding_referrer = request_->token_binding_referrer();
375
[email protected]5033ab82013-03-22 20:17:46376 request_info_.extra_headers.SetHeaderIfMissing(
377 HttpRequestHeaders::kUserAgent,
378 http_user_agent_settings_ ?
[email protected]aa051272014-03-10 05:56:56379 http_user_agent_settings_->GetUserAgent() : std::string());
[email protected]5033ab82013-03-22 20:17:46380
381 AddExtraHeaders();
382 AddCookieHeaderAndStart();
383}
384
385void URLRequestHttpJob::Kill() {
[email protected]5033ab82013-03-22 20:17:46386 weak_factory_.InvalidateWeakPtrs();
mmenke2281f3762015-11-02 20:38:17387 if (transaction_)
388 DestroyTransaction();
[email protected]5033ab82013-03-22 20:17:46389 URLRequestJob::Kill();
390}
391
ttuttle3ae06922015-05-11 23:41:52392void URLRequestHttpJob::GetConnectionAttempts(ConnectionAttempts* out) const {
393 if (transaction_)
394 transaction_->GetConnectionAttempts(out);
395 else
396 out->clear();
397}
398
ryansturm49a8cb12016-06-15 16:51:09399void URLRequestHttpJob::NotifyBeforeSendHeadersCallback(
[email protected]1252d42f2014-07-01 21:20:20400 const ProxyInfo& proxy_info,
401 HttpRequestHeaders* request_headers) {
402 DCHECK(request_headers);
[email protected]597a1ab2014-06-26 08:12:27403 DCHECK_NE(URLRequestStatus::CANCELED, GetStatus().status());
Tarun Bansal4dcebd42017-10-12 20:12:30404 if (proxy_info.is_empty()) {
405 SetProxyServer(ProxyServer::Direct());
406 } else {
407 SetProxyServer(proxy_info.proxy_server());
408 }
[email protected]597a1ab2014-06-26 08:12:27409 if (network_delegate()) {
ryansturm49a8cb12016-06-15 16:51:09410 network_delegate()->NotifyBeforeSendHeaders(
411 request_, proxy_info,
Lily Houghton8c2f97d2018-01-22 05:06:59412 request_->context()->proxy_resolution_service()->proxy_retry_info(),
[email protected]1252d42f2014-07-01 21:20:20413 request_headers);
[email protected]597a1ab2014-06-26 08:12:27414 }
415}
416
[email protected]175adac2008-07-30 17:28:04417void URLRequestHttpJob::NotifyHeadersComplete() {
initial.commit586acc5fe2008-07-26 22:42:52418 DCHECK(!response_info_);
419
420 response_info_ = transaction_->GetResponseInfo();
421
[email protected]d8fd5132009-05-15 01:06:53422 // Save boolean, as we'll need this info at destruction time, and filters may
423 // also need this info.
424 is_cached_content_ = response_info_->was_cached;
425
xunjieli041e9392015-05-19 21:51:33426 if (!is_cached_content_ && throttling_entry_.get())
427 throttling_entry_->UpdateWithResponse(GetResponseCode());
[email protected]6b3f9642010-11-25 02:29:06428
[email protected]fecef222012-01-05 02:26:15429 // The ordering of these calls is not important.
[email protected]77f6fb432009-09-05 14:21:09430 ProcessStrictTransportSecurityHeader();
[email protected]fecef222012-01-05 02:26:15431 ProcessPublicKeyPinsHeader();
estark1614475f2016-03-10 03:46:47432 ProcessExpectCTHeader();
Julia Tuttle3f9acac2017-11-20 22:06:30433#if BUILDFLAG(ENABLE_REPORTING)
juliatuttle2b8dd2d12017-04-12 21:27:41434 ProcessReportToHeader();
Julia Tuttlef9b74062017-07-27 14:44:05435 ProcessNetworkErrorLoggingHeader();
Julia Tuttle3f9acac2017-11-20 22:06:30436#endif // BUILDFLAG(ENABLE_REPORTING)
[email protected]a9cea7542009-05-20 04:30:23437
[email protected]0757e7702009-03-27 04:00:22438 // The HTTP transaction may be restarted several times for the purposes
439 // of sending authorization information. Each time it restarts, we get
440 // notified of the headers completion so that we can update the cookie store.
441 if (transaction_->IsReadyToRestartForAuth()) {
442 DCHECK(!response_info_->auth_challenge.get());
[email protected]87a09a92011-07-14 15:50:50443 // TODO(battre): This breaks the webrequest API for
444 // URLRequestTestHTTP.BasicAuthWithCookies
ryansturm2343cb62016-06-15 01:09:00445 // where OnBeforeStartTransaction -> OnStartTransaction ->
446 // OnBeforeStartTransaction occurs.
[email protected]f3cf9802011-10-28 18:44:58447 RestartTransactionWithAuth(AuthCredentials());
[email protected]0757e7702009-03-27 04:00:22448 return;
449 }
450
[email protected]4f5656c62010-12-13 10:47:09451 URLRequestJob::NotifyHeadersComplete();
initial.commit586acc5fe2008-07-26 22:42:52452}
453
[email protected]175adac2008-07-30 17:28:04454void URLRequestHttpJob::DestroyTransaction() {
[email protected]c6a4eb92010-03-03 23:51:19455 DCHECK(transaction_.get());
initial.commit586acc5fe2008-07-26 22:42:52456
[email protected]bbaea8f2011-06-24 00:11:01457 DoneWithRequest(ABORTED);
sclittlece72c482015-08-24 20:20:59458
459 total_received_bytes_from_previous_transactions_ +=
460 transaction_->GetTotalReceivedBytes();
sclittlefb249892015-09-10 21:33:22461 total_sent_bytes_from_previous_transactions_ +=
462 transaction_->GetTotalSentBytes();
[email protected]af4876d2008-10-21 23:10:57463 transaction_.reset();
initial.commit586acc5fe2008-07-26 22:42:52464 response_info_ = NULL;
[email protected]3b23a222013-05-15 21:33:25465 receive_headers_end_ = base::TimeTicks();
initial.commit586acc5fe2008-07-26 22:42:52466}
467
[email protected]175adac2008-07-30 17:28:04468void URLRequestHttpJob::StartTransaction() {
[email protected]cc05edc2013-03-08 18:04:41469 if (network_delegate()) {
[email protected]abe1c4a2013-10-25 19:28:51470 OnCallToDelegate();
mmenked3a02b32016-11-16 20:21:32471 // The NetworkDelegate must watch for OnRequestDestroyed and not modify
472 // |extra_headers| or invoke the callback after it's called. Not using a
473 // WeakPtr here because it's not enough, the consumer has to watch for
474 // destruction regardless, due to the headers parameter.
ryansturm2343cb62016-06-15 01:09:00475 int rv = network_delegate()->NotifyBeforeStartTransaction(
mmenked3a02b32016-11-16 20:21:32476 request_,
477 base::Bind(&URLRequestHttpJob::NotifyBeforeStartTransactionCallback,
478 base::Unretained(this)),
[email protected]636eccd2011-06-28 12:28:01479 &request_info_.extra_headers);
480 // If an extension blocks the request, we rely on the callback to
[email protected]b4438d32012-09-27 06:15:30481 // MaybeStartTransactionInternal().
[email protected]abe1c4a2013-10-25 19:28:51482 if (rv == ERR_IO_PENDING)
[email protected]636eccd2011-06-28 12:28:01483 return;
[email protected]b4438d32012-09-27 06:15:30484 MaybeStartTransactionInternal(rv);
485 return;
[email protected]636eccd2011-06-28 12:28:01486 }
487 StartTransactionInternal();
488}
489
ryansturm2343cb62016-06-15 01:09:00490void URLRequestHttpJob::NotifyBeforeStartTransactionCallback(int result) {
[email protected]9045b8822012-01-13 20:35:35491 // Check that there are no callbacks to already canceled requests.
492 DCHECK_NE(URLRequestStatus::CANCELED, GetStatus().status());
493
[email protected]b4438d32012-09-27 06:15:30494 MaybeStartTransactionInternal(result);
495}
496
497void URLRequestHttpJob::MaybeStartTransactionInternal(int result) {
[email protected]abe1c4a2013-10-25 19:28:51498 OnCallToDelegateComplete();
[email protected]636eccd2011-06-28 12:28:01499 if (result == OK) {
500 StartTransactionInternal();
501 } else {
[email protected]55b8a6c12012-06-13 22:03:42502 std::string source("delegate");
mikecirone8b85c432016-09-08 19:11:00503 request_->net_log().AddEvent(NetLogEventType::CANCELLED,
[email protected]55b8a6c12012-06-13 22:03:42504 NetLog::StringCallback("source", &source));
jamd3f5a3c2016-10-27 18:52:02505 // Don't call back synchronously to the delegate.
506 base::ThreadTaskRunnerHandle::Get()->PostTask(
507 FROM_HERE,
508 base::Bind(&URLRequestHttpJob::NotifyStartError,
509 weak_factory_.GetWeakPtr(),
510 URLRequestStatus(URLRequestStatus::FAILED, result)));
[email protected]636eccd2011-06-28 12:28:01511 }
512}
513
514void URLRequestHttpJob::StartTransactionInternal() {
mmenke4600b602015-10-28 18:52:17515 // This should only be called while the request's status is IO_PENDING.
mmenke2281f3762015-11-02 20:38:17516 DCHECK_EQ(URLRequestStatus::IO_PENDING, request_->status().status());
mmenke4600b602015-10-28 18:52:17517
initial.commit586acc5fe2008-07-26 22:42:52518 // NOTE: This method assumes that request_info_ is already setup properly.
519
[email protected]34602282010-02-03 22:14:15520 // If we already have a transaction, then we should restart the transaction
[email protected]f3cf9802011-10-28 18:44:58521 // with auth provided by auth_credentials_.
initial.commit586acc5fe2008-07-26 22:42:52522
[email protected]99c07902010-08-17 18:59:52523 int rv;
[email protected]6b3f9642010-11-25 02:29:06524
tbansal80a52162016-05-20 17:55:04525 // Notify NetworkQualityEstimator.
526 NetworkQualityEstimator* network_quality_estimator =
527 request()->context()->network_quality_estimator();
528 if (network_quality_estimator)
529 network_quality_estimator->NotifyStartTransaction(*request_);
530
[email protected]cc05edc2013-03-08 18:04:41531 if (network_delegate()) {
ryansturm2343cb62016-06-15 01:09:00532 network_delegate()->NotifyStartTransaction(request_,
533 request_info_.extra_headers);
[email protected]5796dc942011-07-14 19:26:10534 }
535
[email protected]34602282010-02-03 22:14:15536 if (transaction_.get()) {
mmenked3a02b32016-11-16 20:21:32537 rv = transaction_->RestartWithAuth(
538 auth_credentials_, base::Bind(&URLRequestHttpJob::OnStartCompleted,
539 base::Unretained(this)));
[email protected]f3cf9802011-10-28 18:44:58540 auth_credentials_ = AuthCredentials();
[email protected]34602282010-02-03 22:14:15541 } else {
[email protected]34602282010-02-03 22:14:15542 DCHECK(request_->context()->http_transaction_factory());
initial.commit586acc5fe2008-07-26 22:42:52543
[email protected]99c07902010-08-17 18:59:52544 rv = request_->context()->http_transaction_factory()->CreateTransaction(
[email protected]027bd85a2013-12-27 22:39:10545 priority_, &transaction_);
[email protected]f4533ba2013-11-28 09:35:41546
547 if (rv == OK && request_info_.url.SchemeIsWSOrWSS()) {
[email protected]f4533ba2013-11-28 09:35:41548 base::SupportsUserData::Data* data = request_->GetUserData(
549 WebSocketHandshakeStreamBase::CreateHelper::DataKey());
550 if (data) {
551 transaction_->SetWebSocketHandshakeStreamCreateHelper(
552 static_cast<WebSocketHandshakeStreamBase::CreateHelper*>(data));
553 } else {
554 rv = ERR_DISALLOWED_URL_SCHEME;
555 }
556 }
557
[email protected]4f5656c62010-12-13 10:47:09558 if (rv == OK) {
ryansturm49a8cb12016-06-15 16:51:09559 transaction_->SetBeforeHeadersSentCallback(
560 base::Bind(&URLRequestHttpJob::NotifyBeforeSendHeadersCallback,
[email protected]597a1ab2014-06-26 08:12:27561 base::Unretained(this)));
Andrey Kosyakov83a6eee2017-08-14 19:20:04562 transaction_->SetRequestHeadersCallback(request_headers_callback_);
Andrey Kosyakov2e893e62017-08-31 17:00:52563 transaction_->SetResponseHeadersCallback(response_headers_callback_);
[email protected]a45840b2014-01-10 15:40:22564
dchengc2e01e82014-08-27 00:24:42565 if (!throttling_entry_.get() ||
xunjieli41edcdd2015-06-24 14:26:40566 !throttling_entry_->ShouldRejectRequest(*request_)) {
[email protected]227b0e82011-03-25 21:11:53567 rv = transaction_->Start(
mmenked3a02b32016-11-16 20:21:32568 &request_info_, base::Bind(&URLRequestHttpJob::OnStartCompleted,
569 base::Unretained(this)),
570 request_->net_log());
[email protected]bbaea8f2011-06-24 00:11:01571 start_time_ = base::TimeTicks::Now();
[email protected]227b0e82011-03-25 21:11:53572 } else {
573 // Special error code for the exponential back-off module.
574 rv = ERR_TEMPORARILY_THROTTLED;
575 }
[email protected]34602282010-02-03 22:14:15576 }
initial.commit586acc5fe2008-07-26 22:42:52577 }
578
[email protected]4f5656c62010-12-13 10:47:09579 if (rv == ERR_IO_PENDING)
[email protected]34602282010-02-03 22:14:15580 return;
581
initial.commit586acc5fe2008-07-26 22:42:52582 // The transaction started synchronously, but we need to notify the
[email protected]4f5656c62010-12-13 10:47:09583 // URLRequest delegate via the message loop.
skyostil4891b25b2015-06-11 11:43:45584 base::ThreadTaskRunnerHandle::Get()->PostTask(
585 FROM_HERE, base::Bind(&URLRequestHttpJob::OnStartCompleted,
586 weak_factory_.GetWeakPtr(), rv));
initial.commit586acc5fe2008-07-26 22:42:52587}
588
[email protected]175adac2008-07-30 17:28:04589void URLRequestHttpJob::AddExtraHeaders() {
[email protected]c7bef94c2011-06-21 18:05:51590 if (!request_info_.extra_headers.HasHeader(
Helen Li7dd80832017-09-12 18:29:17591 HttpRequestHeaders::kAcceptEncoding)) {
eustasfbec9132015-12-30 14:56:51592 // Advertise "br" encoding only if transferred data is opaque to proxy.
593 bool advertise_brotli = false;
eustas7ff89682016-07-07 20:23:39594 if (request()->context()->enable_brotli()) {
595 if (request()->url().SchemeIsCryptographic() ||
Rob Wuf79b3ba2018-01-14 01:54:31596 IsLocalhost(request()->url())) {
eustas7ff89682016-07-07 20:23:39597 advertise_brotli = true;
598 }
599 }
eustasfbec9132015-12-30 14:56:51600
[email protected]c7bef94c2011-06-21 18:05:51601 // Supply Accept-Encoding headers first so that it is more likely that they
rdsmith81f607562014-11-21 18:35:16602 // will be in the first transmitted packet. This can sometimes make it
[email protected]c7bef94c2011-06-21 18:05:51603 // easier to filter and analyze the streams to assure that a proxy has not
rdsmith81f607562014-11-21 18:35:16604 // damaged these headers. Some proxies deliberately corrupt Accept-Encoding
[email protected]c7bef94c2011-06-21 18:05:51605 // headers.
eustasfbec9132015-12-30 14:56:51606 std::string advertised_encodings = "gzip, deflate";
eustasfbec9132015-12-30 14:56:51607 if (advertise_brotli)
608 advertised_encodings += ", br";
609 // Tell the server what compression formats are supported.
610 request_info_.extra_headers.SetHeader(HttpRequestHeaders::kAcceptEncoding,
611 advertised_encodings);
[email protected]423041b2008-10-27 17:39:28612 }
613
[email protected]ee4c30d2012-11-07 15:08:43614 if (http_user_agent_settings_) {
[email protected]84f05432013-03-15 01:00:12615 // Only add default Accept-Language if the request didn't have it
616 // specified.
[email protected]ee4c30d2012-11-07 15:08:43617 std::string accept_language =
618 http_user_agent_settings_->GetAcceptLanguage();
619 if (!accept_language.empty()) {
620 request_info_.extra_headers.SetHeaderIfMissing(
621 HttpRequestHeaders::kAcceptLanguage,
622 accept_language);
623 }
initial.commit586acc5fe2008-07-26 22:42:52624 }
initial.commit586acc5fe2008-07-26 22:42:52625}
626
[email protected]34602282010-02-03 22:14:15627void URLRequestHttpJob::AddCookieHeaderAndStart() {
davidben151423e2015-03-23 18:48:36628 CookieStore* cookie_store = request_->context()->cookie_store();
[email protected]1a6fff52011-10-20 21:00:16629 if (cookie_store && !(request_info_.load_flags & LOAD_DO_NOT_SEND_COOKIES)) {
mkwste3e95992016-02-23 17:45:41630 CookieOptions options;
631 options.set_include_httponly();
632
mkwstf71d0bd2016-03-21 14:15:24633 // Set SameSiteCookieMode according to the rules laid out in
Mike Westb85da8ed2017-08-10 14:16:46634 // https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site:
mkwstf71d0bd2016-03-21 14:15:24635 //
636 // * Include both "strict" and "lax" same-site cookies if the request's
Mike Westb85da8ed2017-08-10 14:16:46637 // |url|, |initiator|, and |site_for_cookies| all have the same
clamyfd58ca072016-12-21 17:18:32638 // registrable domain. Note: this also covers the case of a request
639 // without an initiator (only happens for browser-initiated main frame
640 // navigations).
mkwstf71d0bd2016-03-21 14:15:24641 //
642 // * Include only "lax" same-site cookies if the request's |URL| and
Mike Westb85da8ed2017-08-10 14:16:46643 // |site_for_cookies| have the same registrable domain, _and_ the
mkwstf71d0bd2016-03-21 14:15:24644 // request's |method| is "safe" ("GET" or "HEAD").
645 //
646 // Note that this will generally be the case only for cross-site requests
647 // which target a top-level browsing context.
648 //
649 // * Otherwise, do not include same-site cookies.
mkwstc5fa7762016-03-28 09:28:23650 if (registry_controlled_domains::SameDomainOrHost(
Mike Westb85da8ed2017-08-10 14:16:46651 request_->url(), request_->site_for_cookies(),
mkwstc5fa7762016-03-28 09:28:23652 registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) {
clamyfd58ca072016-12-21 17:18:32653 if (!request_->initiator() ||
csharrisond5c68c492016-12-03 00:15:27654 registry_controlled_domains::SameDomainOrHost(
655 request_->url(), request_->initiator().value().GetURL(),
mkwstf71d0bd2016-03-21 14:15:24656 registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)) {
657 options.set_same_site_cookie_mode(
658 CookieOptions::SameSiteCookieMode::INCLUDE_STRICT_AND_LAX);
tfarinadbf459732017-05-09 04:36:09659 } else if (HttpUtil::IsMethodSafe(request_->method())) {
mkwstf71d0bd2016-03-21 14:15:24660 options.set_same_site_cookie_mode(
661 CookieOptions::SameSiteCookieMode::INCLUDE_LAX);
662 }
mkwste3e95992016-02-23 17:45:41663 }
664
665 cookie_store->GetCookieListWithOptionsAsync(
666 request_->url(), options,
667 base::Bind(&URLRequestHttpJob::SetCookieHeaderAndStart,
[email protected]dc8313a2014-03-24 21:38:14668 weak_factory_.GetWeakPtr()));
[email protected]03d845f2011-07-29 19:06:26669 } else {
mmenked3a02b32016-11-16 20:21:32670 StartTransaction();
[email protected]03d845f2011-07-29 19:06:26671 }
672}
673
mkwste3e95992016-02-23 17:45:41674void URLRequestHttpJob::SetCookieHeaderAndStart(const CookieList& cookie_list) {
mmenked3a02b32016-11-16 20:21:32675 if (!cookie_list.empty() && CanGetCookies(cookie_list)) {
Mike West86149882017-07-28 10:41:49676 if (!request_info_.url.SchemeIsCryptographic())
677 LogCookieAgeForNonSecureRequest(cookie_list, *request_);
678
[email protected]54f4c9362011-07-25 21:54:46679 request_info_.extra_headers.SetHeader(
Randy Smithe23356c22017-11-14 01:41:50680 HttpRequestHeaders::kCookie,
681 CanonicalCookie::BuildCookieLine(cookie_list));
[email protected]e6d017652013-05-17 18:01:40682 // Disable privacy mode as we are sending cookies anyway.
[email protected]314b03992014-04-01 01:28:53683 request_info_.privacy_mode = PRIVACY_MODE_DISABLED;
[email protected]54f4c9362011-07-25 21:54:46684 }
mmenked3a02b32016-11-16 20:21:32685 StartTransaction();
[email protected]0757e7702009-03-27 04:00:22686}
687
[email protected]ea8141e2011-10-05 13:12:51688void URLRequestHttpJob::SaveCookiesAndNotifyHeadersComplete(int result) {
[email protected]abe1c4a2013-10-25 19:28:51689 // End of the call started in OnStartCompleted.
690 OnCallToDelegateComplete();
691
ttuttle859dc7a2015-04-23 19:42:29692 if (result != OK) {
[email protected]55b8a6c12012-06-13 22:03:42693 std::string source("delegate");
mikecirone8b85c432016-09-08 19:11:00694 request_->net_log().AddEvent(NetLogEventType::CANCELLED,
[email protected]55b8a6c12012-06-13 22:03:42695 NetLog::StringCallback("source", &source));
[email protected]ea8141e2011-10-05 13:12:51696 NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, result));
697 return;
698 }
699
mmenke54e82af2016-02-16 23:06:30700 base::Time response_date;
701 if (!GetResponseHeaders()->GetDateValue(&response_date))
702 response_date = base::Time();
[email protected]263163f2012-06-14 22:40:34703
704 if (!(request_info_.load_flags & LOAD_DO_NOT_SAVE_COOKIES) &&
mmenke54e82af2016-02-16 23:06:30705 request_->context()->cookie_store()) {
[email protected]263163f2012-06-14 22:40:34706 CookieOptions options;
707 options.set_include_httponly();
mmenke54e82af2016-02-16 23:06:30708 options.set_server_time(response_date);
jww79aceda2015-12-07 01:56:34709
mmenke54e82af2016-02-16 23:06:30710 // Set all cookies, without waiting for them to be set. Any subsequent read
711 // will see the combined result of all cookie operation.
mmenked3a02b32016-11-16 20:21:32712 const base::StringPiece name("Set-Cookie");
Victor Costan70f85512017-11-20 16:14:46713 std::string cookie_line;
mmenked3a02b32016-11-16 20:21:32714 size_t iter = 0;
715 HttpResponseHeaders* headers = GetResponseHeaders();
Victor Costan70f85512017-11-20 16:14:46716 while (headers->EnumerateHeader(&iter, name, &cookie_line)) {
717 std::unique_ptr<CanonicalCookie> cookie = net::CanonicalCookie::Create(
718 request_->url(), cookie_line, base::Time::Now(), options);
719 if (!cookie || !CanSetCookie(*cookie, &options))
mmenke54e82af2016-02-16 23:06:30720 continue;
Victor Costan70f85512017-11-20 16:14:46721 request_->context()->cookie_store()->SetCanonicalCookieAsync(
722 std::move(cookie), request_->url().SchemeIsCryptographic(),
723 !options.exclude_httponly(), net::CookieStore::SetCookiesCallback());
[email protected]263163f2012-06-14 22:40:34724 }
725 }
726
mmenke54e82af2016-02-16 23:06:30727 NotifyHeadersComplete();
[email protected]34602282010-02-03 22:14:15728}
729
[email protected]000d9df02012-01-18 20:01:46730// NOTE: |ProcessStrictTransportSecurityHeader| and
731// |ProcessPublicKeyPinsHeader| have very similar structures, by design.
[email protected]77f6fb432009-09-05 14:21:09732void URLRequestHttpJob::ProcessStrictTransportSecurityHeader() {
[email protected]a9cea7542009-05-20 04:30:23733 DCHECK(response_info_);
[email protected]6ed72be2013-01-08 22:07:33734 TransportSecurityState* security_state =
735 request_->context()->transport_security_state();
[email protected]e88006f2012-01-11 06:15:07736 const SSLInfo& ssl_info = response_info_->ssl_info;
[email protected]a9cea7542009-05-20 04:30:23737
[email protected]6ed72be2013-01-08 22:07:33738 // Only accept HSTS headers on HTTPS connections that have no
739 // certificate errors.
[email protected]e88006f2012-01-11 06:15:07740 if (!ssl_info.is_valid() || IsCertStatusError(ssl_info.cert_status) ||
mmenked3a02b32016-11-16 20:21:32741 !security_state) {
[email protected]e88006f2012-01-11 06:15:07742 return;
mmenked3a02b32016-11-16 20:21:32743 }
[email protected]326e6792009-12-11 21:04:42744
estarka5da76702015-04-09 04:00:16745 // Don't accept HSTS headers when the hostname is an IP address.
746 if (request_info_.url.HostIsIPAddress())
747 return;
748
[email protected]242d8562012-10-30 21:20:46749 // http://tools.ietf.org/html/draft-ietf-websec-strict-transport-sec:
750 //
751 // If a UA receives more than one STS header field in a HTTP response
752 // message over secure transport, then the UA MUST process only the
753 // first such header field.
[email protected]6ed72be2013-01-08 22:07:33754 HttpResponseHeaders* headers = GetResponseHeaders();
755 std::string value;
olli.raulaee489a52016-01-25 08:37:10756 if (headers->EnumerateHeader(nullptr, "Strict-Transport-Security", &value))
[email protected]6ed72be2013-01-08 22:07:33757 security_state->AddHSTSHeader(request_info_.url.host(), value);
[email protected]a9cea7542009-05-20 04:30:23758}
[email protected]4f5656c62010-12-13 10:47:09759
[email protected]fecef222012-01-05 02:26:15760void URLRequestHttpJob::ProcessPublicKeyPinsHeader() {
761 DCHECK(response_info_);
[email protected]6ed72be2013-01-08 22:07:33762 TransportSecurityState* security_state =
763 request_->context()->transport_security_state();
[email protected]fecef222012-01-05 02:26:15764 const SSLInfo& ssl_info = response_info_->ssl_info;
765
[email protected]6ed72be2013-01-08 22:07:33766 // Only accept HPKP headers on HTTPS connections that have no
[email protected]e88006f2012-01-11 06:15:07767 // certificate errors.
[email protected]fecef222012-01-05 02:26:15768 if (!ssl_info.is_valid() || IsCertStatusError(ssl_info.cert_status) ||
mmenked3a02b32016-11-16 20:21:32769 !security_state) {
[email protected]fecef222012-01-05 02:26:15770 return;
mmenked3a02b32016-11-16 20:21:32771 }
[email protected]fecef222012-01-05 02:26:15772
estarka5da76702015-04-09 04:00:16773 // Don't accept HSTS headers when the hostname is an IP address.
774 if (request_info_.url.HostIsIPAddress())
775 return;
776
estark53fee7c2015-08-03 18:31:51777 // http://tools.ietf.org/html/rfc7469:
[email protected]6ed72be2013-01-08 22:07:33778 //
779 // If a UA receives more than one PKP header field in an HTTP
780 // response message over secure transport, then the UA MUST process
781 // only the first such header field.
[email protected]fecef222012-01-05 02:26:15782 HttpResponseHeaders* headers = GetResponseHeaders();
[email protected]fecef222012-01-05 02:26:15783 std::string value;
estark53fee7c2015-08-03 18:31:51784 if (headers->EnumerateHeader(nullptr, "Public-Key-Pins", &value))
[email protected]6ed72be2013-01-08 22:07:33785 security_state->AddHPKPHeader(request_info_.url.host(), value, ssl_info);
estark53fee7c2015-08-03 18:31:51786 if (headers->EnumerateHeader(nullptr, "Public-Key-Pins-Report-Only",
787 &value)) {
788 security_state->ProcessHPKPReportOnlyHeader(
789 value, HostPortPair::FromURL(request_info_.url), ssl_info);
790 }
[email protected]fecef222012-01-05 02:26:15791}
792
estark1614475f2016-03-10 03:46:47793void URLRequestHttpJob::ProcessExpectCTHeader() {
794 DCHECK(response_info_);
795 TransportSecurityState* security_state =
796 request_->context()->transport_security_state();
797 const SSLInfo& ssl_info = response_info_->ssl_info;
798
799 // Only accept Expect CT headers on HTTPS connections that have no
800 // certificate errors.
801 if (!ssl_info.is_valid() || IsCertStatusError(ssl_info.cert_status) ||
802 !security_state) {
803 return;
804 }
805
estark1614475f2016-03-10 03:46:47806 HttpResponseHeaders* headers = GetResponseHeaders();
807 std::string value;
Emily Stark4cfecf072017-08-08 01:05:51808 if (headers->GetNormalizedHeader("Expect-CT", &value)) {
estark1614475f2016-03-10 03:46:47809 security_state->ProcessExpectCTHeader(
810 value, HostPortPair::FromURL(request_info_.url), ssl_info);
811 }
812}
813
Julia Tuttle3f9acac2017-11-20 22:06:30814#if BUILDFLAG(ENABLE_REPORTING)
juliatuttle2b8dd2d12017-04-12 21:27:41815void URLRequestHttpJob::ProcessReportToHeader() {
816 DCHECK(response_info_);
817
juliatuttle667c0bb2017-07-06 15:17:13818 HttpResponseHeaders* headers = GetResponseHeaders();
819 std::string value;
820 if (!headers->GetNormalizedHeader("Report-To", &value))
juliatuttle2b8dd2d12017-04-12 21:27:41821 return;
822
juliatuttle667c0bb2017-07-06 15:17:13823 ReportingService* service = request_->context()->reporting_service();
824 if (!service) {
825 ReportingHeaderParser::RecordHeaderDiscardedForNoReportingService();
826 return;
827 }
828
juliatuttle2b8dd2d12017-04-12 21:27:41829 // Only accept Report-To headers on HTTPS connections that have no
830 // certificate errors.
831 // TODO(juliatuttle): Do we need to check cert status?
832 const SSLInfo& ssl_info = response_info_->ssl_info;
juliatuttle667c0bb2017-07-06 15:17:13833 if (!ssl_info.is_valid()) {
834 ReportingHeaderParser::RecordHeaderDiscardedForInvalidSSLInfo();
juliatuttle2b8dd2d12017-04-12 21:27:41835 return;
juliatuttle667c0bb2017-07-06 15:17:13836 }
837 if (IsCertStatusError(ssl_info.cert_status)) {
838 ReportingHeaderParser::RecordHeaderDiscardedForCertStatusError();
juliatuttle2b8dd2d12017-04-12 21:27:41839 return;
juliatuttle667c0bb2017-07-06 15:17:13840 }
juliatuttle2b8dd2d12017-04-12 21:27:41841
842 service->ProcessHeader(request_info_.url.GetOrigin(), value);
juliatuttle2b8dd2d12017-04-12 21:27:41843}
844
Julia Tuttlef9b74062017-07-27 14:44:05845void URLRequestHttpJob::ProcessNetworkErrorLoggingHeader() {
846 DCHECK(response_info_);
847
848 HttpResponseHeaders* headers = GetResponseHeaders();
849 std::string value;
850 if (!headers->GetNormalizedHeader(NetworkErrorLoggingDelegate::kHeaderName,
851 &value)) {
852 return;
853 }
854
855 NetworkErrorLoggingDelegate* delegate =
856 request_->context()->network_error_logging_delegate();
857 if (!delegate)
858 return;
859
860 // Only accept Report-To headers on HTTPS connections that have no
861 // certificate errors.
862 const SSLInfo& ssl_info = response_info_->ssl_info;
863 if (!ssl_info.is_valid() || IsCertStatusError(ssl_info.cert_status))
864 return;
865
Daniel Cheng88186bd52017-10-20 08:14:46866 delegate->OnHeader(url::Origin::Create(request_info_.url), value);
Julia Tuttlef9b74062017-07-27 14:44:05867}
Julia Tuttle3f9acac2017-11-20 22:06:30868#endif // BUILDFLAG(ENABLE_REPORTING)
Julia Tuttlef9b74062017-07-27 14:44:05869
[email protected]5394e422011-01-20 22:07:43870void URLRequestHttpJob::OnStartCompleted(int result) {
xunjieli0b7f5b62016-12-06 20:43:48871 TRACE_EVENT0(kNetTracingCategory, "URLRequestHttpJob::OnStartCompleted");
[email protected]ec23f522011-02-22 21:01:38872 RecordTimer();
873
[email protected]80abdad2014-03-15 00:20:54874 // If the job is done (due to cancellation), can just ignore this
875 // notification.
876 if (done_)
[email protected]5394e422011-01-20 22:07:43877 return;
878
[email protected]3b23a222013-05-15 21:33:25879 receive_headers_end_ = base::TimeTicks::Now();
880
[email protected]ef2bf422012-05-11 03:27:09881 const URLRequestContext* context = request_->context();
882
Ryan Sleevi19a7bde2017-11-22 06:51:39883 if (transaction_ && transaction_->GetResponseInfo()) {
884 const SSLInfo& ssl_info = transaction_->GetResponseInfo()->ssl_info;
885 if (!IsCertificateError(result) ||
886 (IsCertStatusError(ssl_info.cert_status) &&
887 IsCertStatusMinorError(ssl_info.cert_status))) {
888 LogTrustAnchor(ssl_info.public_key_hashes);
889 }
Emily Stark8b411de02017-11-23 20:21:27890
891 RecordCTHistograms(ssl_info);
Ryan Sleevi19a7bde2017-11-22 06:51:39892 }
893
[email protected]5394e422011-01-20 22:07:43894 if (result == OK) {
[email protected]d8fc4722014-06-13 13:17:15895 if (transaction_ && transaction_->GetResponseInfo()) {
896 SetProxyServer(transaction_->GetResponseInfo()->proxy_server);
897 }
[email protected]ea8141e2011-10-05 13:12:51898 scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders();
hiroshigecb76caa4c52015-12-22 07:50:25899
[email protected]cc05edc2013-03-08 18:04:41900 if (network_delegate()) {
[email protected]ea8141e2011-10-05 13:12:51901 // Note that |this| may not be deleted until
mmenked3a02b32016-11-16 20:21:32902 // |URLRequestHttpJob::OnHeadersReceivedCallback()| or
[email protected]ea8141e2011-10-05 13:12:51903 // |NetworkDelegate::URLRequestDestroyed()| has been called.
[email protected]abe1c4a2013-10-25 19:28:51904 OnCallToDelegate();
[email protected]5f714132014-03-26 10:41:16905 allowed_unsafe_redirect_url_ = GURL();
mmenked3a02b32016-11-16 20:21:32906 // The NetworkDelegate must watch for OnRequestDestroyed and not modify
907 // any of the arguments or invoke the callback after it's called. Not
908 // using a WeakPtr here because it's not enough, the consumer has to watch
909 // for destruction regardless, due to the pointer parameters.
[email protected]cc05edc2013-03-08 18:04:41910 int error = network_delegate()->NotifyHeadersReceived(
mmenked3a02b32016-11-16 20:21:32911 request_, base::Bind(&URLRequestHttpJob::OnHeadersReceivedCallback,
912 base::Unretained(this)),
913 headers.get(), &override_response_headers_,
[email protected]5f714132014-03-26 10:41:16914 &allowed_unsafe_redirect_url_);
ttuttle859dc7a2015-04-23 19:42:29915 if (error != OK) {
916 if (error == ERR_IO_PENDING) {
[email protected]ea8141e2011-10-05 13:12:51917 awaiting_callback_ = true;
[email protected]ea8141e2011-10-05 13:12:51918 } else {
[email protected]55b8a6c12012-06-13 22:03:42919 std::string source("delegate");
mikecirone8b85c432016-09-08 19:11:00920 request_->net_log().AddEvent(
921 NetLogEventType::CANCELLED,
922 NetLog::StringCallback("source", &source));
[email protected]abe1c4a2013-10-25 19:28:51923 OnCallToDelegateComplete();
[email protected]ea8141e2011-10-05 13:12:51924 NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, error));
925 }
926 return;
927 }
928 }
nharperbafc20f2016-03-25 00:40:17929 if (transaction_ && transaction_->GetResponseInfo()) {
930 LogChannelIDAndCookieStores(request_->url(), request_->context(),
931 transaction_->GetResponseInfo()->ssl_info);
932 }
[email protected]ea8141e2011-10-05 13:12:51933
ttuttle859dc7a2015-04-23 19:42:29934 SaveCookiesAndNotifyHeadersComplete(OK);
[email protected]e5624f02011-09-27 19:43:53935 } else if (IsCertificateError(result)) {
[email protected]6061c142013-10-21 15:13:34936 // We encountered an SSL certificate error.
rsleevi9545d342016-06-21 03:17:37937 // Maybe overridable, maybe not. Ask the delegate to decide.
938 TransportSecurityState* state = context->transport_security_state();
939 NotifySSLCertificateError(
940 transaction_->GetResponseInfo()->ssl_info,
941 state->ShouldSSLErrorsBeFatal(request_info_.url.host()));
[email protected]5394e422011-01-20 22:07:43942 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
[email protected]a83dd332011-07-13 10:41:01943 NotifyCertificateRequested(
[email protected]90499482013-06-01 00:39:50944 transaction_->GetResponseInfo()->cert_request_info.get());
[email protected]5394e422011-01-20 22:07:43945 } else {
[email protected]419704c2014-01-14 11:18:06946 // Even on an error, there may be useful information in the response
947 // info (e.g. whether there's a cached copy).
948 if (transaction_.get())
949 response_info_ = transaction_->GetResponseInfo();
[email protected]5394e422011-01-20 22:07:43950 NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, result));
951 }
952}
953
[email protected]ea8141e2011-10-05 13:12:51954void URLRequestHttpJob::OnHeadersReceivedCallback(int result) {
[email protected]ea8141e2011-10-05 13:12:51955 awaiting_callback_ = false;
[email protected]9045b8822012-01-13 20:35:35956
957 // Check that there are no callbacks to already canceled requests.
958 DCHECK_NE(URLRequestStatus::CANCELED, GetStatus().status());
959
[email protected]ea8141e2011-10-05 13:12:51960 SaveCookiesAndNotifyHeadersComplete(result);
961}
962
[email protected]5394e422011-01-20 22:07:43963void URLRequestHttpJob::OnReadCompleted(int result) {
xunjieli0b7f5b62016-12-06 20:43:48964 TRACE_EVENT0(kNetTracingCategory, "URLRequestHttpJob::OnReadCompleted");
[email protected]5394e422011-01-20 22:07:43965 read_in_progress_ = false;
966
xunjieli26ede962015-11-23 19:39:13967 DCHECK_NE(ERR_IO_PENDING, result);
968
[email protected]f001bd6a2011-12-08 04:31:37969 if (ShouldFixMismatchedContentLength(result))
[email protected]5543cbb2012-04-20 16:35:23970 result = OK;
[email protected]f001bd6a2011-12-08 04:31:37971
xunjieli26ede962015-11-23 19:39:13972 // EOF or error, done with this job.
973 if (result <= 0)
974 DoneWithRequest(FINISHED);
[email protected]5394e422011-01-20 22:07:43975
xunjieli26ede962015-11-23 19:39:13976 ReadRawDataComplete(result);
[email protected]5394e422011-01-20 22:07:43977}
978
[email protected]5394e422011-01-20 22:07:43979void URLRequestHttpJob::RestartTransactionWithAuth(
[email protected]f3cf9802011-10-28 18:44:58980 const AuthCredentials& credentials) {
981 auth_credentials_ = credentials;
[email protected]5394e422011-01-20 22:07:43982
983 // These will be reset in OnStartCompleted.
984 response_info_ = NULL;
[email protected]3b23a222013-05-15 21:33:25985 receive_headers_end_ = base::TimeTicks();
[email protected]5394e422011-01-20 22:07:43986
[email protected]ec23f522011-02-22 21:01:38987 ResetTimer();
988
[email protected]5394e422011-01-20 22:07:43989 // Update the cookies, since the cookie store may have been updated from the
990 // headers in the 401/407. Since cookies were already appended to
991 // extra_headers, we need to strip them out before adding them again.
[email protected]ea8141e2011-10-05 13:12:51992 request_info_.extra_headers.RemoveHeader(HttpRequestHeaders::kCookie);
[email protected]5394e422011-01-20 22:07:43993
994 AddCookieHeaderAndStart();
995}
996
[email protected]0736d9e2012-11-28 19:50:40997void URLRequestHttpJob::SetUpload(UploadDataStream* upload) {
[email protected]5394e422011-01-20 22:07:43998 DCHECK(!transaction_.get()) << "cannot change once started";
[email protected]0736d9e2012-11-28 19:50:40999 request_info_.upload_data_stream = upload;
[email protected]5394e422011-01-20 22:07:431000}
1001
1002void URLRequestHttpJob::SetExtraRequestHeaders(
1003 const HttpRequestHeaders& headers) {
1004 DCHECK(!transaction_.get()) << "cannot change once started";
1005 request_info_.extra_headers.CopyFrom(headers);
1006}
1007
[email protected]5394e422011-01-20 22:07:431008LoadState URLRequestHttpJob::GetLoadState() const {
1009 return transaction_.get() ?
1010 transaction_->GetLoadState() : LOAD_STATE_IDLE;
1011}
1012
[email protected]5394e422011-01-20 22:07:431013bool URLRequestHttpJob::GetMimeType(std::string* mime_type) const {
1014 DCHECK(transaction_.get());
1015
1016 if (!response_info_)
1017 return false;
1018
ellyjones0e9d5e82015-02-17 23:06:281019 HttpResponseHeaders* headers = GetResponseHeaders();
1020 if (!headers)
1021 return false;
1022 return headers->GetMimeType(mime_type);
[email protected]5394e422011-01-20 22:07:431023}
1024
1025bool URLRequestHttpJob::GetCharset(std::string* charset) {
1026 DCHECK(transaction_.get());
1027
1028 if (!response_info_)
1029 return false;
1030
[email protected]ea8141e2011-10-05 13:12:511031 return GetResponseHeaders()->GetCharset(charset);
[email protected]5394e422011-01-20 22:07:431032}
1033
1034void URLRequestHttpJob::GetResponseInfo(HttpResponseInfo* info) {
[email protected]ea8141e2011-10-05 13:12:511035 if (response_info_) {
[email protected]419704c2014-01-14 11:18:061036 DCHECK(transaction_.get());
1037
[email protected]5394e422011-01-20 22:07:431038 *info = *response_info_;
[email protected]90499482013-06-01 00:39:501039 if (override_response_headers_.get())
[email protected]ea8141e2011-10-05 13:12:511040 info->headers = override_response_headers_;
1041 }
[email protected]5394e422011-01-20 22:07:431042}
1043
[email protected]58e32bb2013-01-21 18:23:251044void URLRequestHttpJob::GetLoadTimingInfo(
1045 LoadTimingInfo* load_timing_info) const {
[email protected]3b23a222013-05-15 21:33:251046 // If haven't made it far enough to receive any headers, don't return
rdsmith81f607562014-11-21 18:35:161047 // anything. This makes for more consistent behavior in the case of errors.
[email protected]3b23a222013-05-15 21:33:251048 if (!transaction_ || receive_headers_end_.is_null())
1049 return;
1050 if (transaction_->GetLoadTimingInfo(load_timing_info))
1051 load_timing_info->receive_headers_end = receive_headers_end_;
[email protected]58e32bb2013-01-21 18:23:251052}
1053
ttuttled9dbc652015-09-29 20:00:591054bool URLRequestHttpJob::GetRemoteEndpoint(IPEndPoint* endpoint) const {
1055 if (!transaction_)
1056 return false;
1057
1058 return transaction_->GetRemoteEndpoint(endpoint);
1059}
1060
[email protected]5394e422011-01-20 22:07:431061int URLRequestHttpJob::GetResponseCode() const {
1062 DCHECK(transaction_.get());
1063
1064 if (!response_info_)
1065 return -1;
1066
[email protected]ea8141e2011-10-05 13:12:511067 return GetResponseHeaders()->response_code();
[email protected]5394e422011-01-20 22:07:431068}
1069
zhongyi48704c182015-12-07 07:52:021070void URLRequestHttpJob::PopulateNetErrorDetails(
1071 NetErrorDetails* details) const {
1072 if (!transaction_)
1073 return;
1074 return transaction_->PopulateNetErrorDetails(details);
1075}
1076
xunjieli28a18772016-10-25 15:30:061077std::unique_ptr<SourceStream> URLRequestHttpJob::SetUpSourceStream() {
[email protected]5394e422011-01-20 22:07:431078 DCHECK(transaction_.get());
1079 if (!response_info_)
Bacek8f371552016-05-12 01:13:491080 return nullptr;
[email protected]5394e422011-01-20 22:07:431081
xunjieli28a18772016-10-25 15:30:061082 std::unique_ptr<SourceStream> upstream = URLRequestJob::SetUpSourceStream();
[email protected]ea8141e2011-10-05 13:12:511083 HttpResponseHeaders* headers = GetResponseHeaders();
xunjieli28a18772016-10-25 15:30:061084 std::string type;
1085 std::vector<SourceStream::SourceType> types;
olli.raulaee489a52016-01-25 08:37:101086 size_t iter = 0;
xunjieli28a18772016-10-25 15:30:061087 while (headers->EnumerateHeader(&iter, "Content-Encoding", &type)) {
eustasc7d27da2017-04-06 10:33:201088 SourceStream::SourceType source_type =
1089 FilterSourceStream::ParseEncodingType(type);
eustasc7d27da2017-04-06 10:33:201090 switch (source_type) {
1091 case SourceStream::TYPE_BROTLI:
1092 case SourceStream::TYPE_DEFLATE:
1093 case SourceStream::TYPE_GZIP:
eustasc7d27da2017-04-06 10:33:201094 types.push_back(source_type);
1095 break;
1096 case SourceStream::TYPE_NONE:
1097 // Identity encoding type. Pass through raw response body.
1098 return upstream;
Helen Li666c0682017-09-15 19:57:051099 case SourceStream::TYPE_UNKNOWN:
eustasc7d27da2017-04-06 10:33:201100 // Unknown encoding type. Pass through raw response body.
1101 // Despite of reporting to UMA, request will not be canceled; though
1102 // it is expected that user will see malformed / garbage response.
1103 FilterSourceStream::ReportContentDecodingFailed(
1104 FilterSourceStream::TYPE_UNKNOWN);
1105 return upstream;
Helen Li666c0682017-09-15 19:57:051106 case SourceStream::TYPE_GZIP_FALLBACK_DEPRECATED:
1107 case SourceStream::TYPE_SDCH_DEPRECATED:
1108 case SourceStream::TYPE_SDCH_POSSIBLE_DEPRECATED:
1109 case SourceStream::TYPE_REJECTED:
1110 case SourceStream::TYPE_INVALID:
1111 case SourceStream::TYPE_MAX:
1112 NOTREACHED();
1113 return nullptr;
eustasc7d27da2017-04-06 10:33:201114 }
[email protected]5394e422011-01-20 22:07:431115 }
1116
xunjieli28a18772016-10-25 15:30:061117 for (std::vector<SourceStream::SourceType>::reverse_iterator r_iter =
1118 types.rbegin();
1119 r_iter != types.rend(); ++r_iter) {
1120 std::unique_ptr<FilterSourceStream> downstream;
1121 SourceStream::SourceType type = *r_iter;
1122 switch (type) {
1123 case SourceStream::TYPE_BROTLI:
1124 downstream = CreateBrotliSourceStream(std::move(upstream));
1125 break;
xunjieli28a18772016-10-25 15:30:061126 case SourceStream::TYPE_GZIP:
1127 case SourceStream::TYPE_DEFLATE:
xunjieli28a18772016-10-25 15:30:061128 downstream = GzipSourceStream::Create(std::move(upstream), type);
1129 break;
Helen Li666c0682017-09-15 19:57:051130 case SourceStream::TYPE_GZIP_FALLBACK_DEPRECATED:
1131 case SourceStream::TYPE_SDCH_DEPRECATED:
1132 case SourceStream::TYPE_SDCH_POSSIBLE_DEPRECATED:
xunjieli28a18772016-10-25 15:30:061133 case SourceStream::TYPE_NONE:
1134 case SourceStream::TYPE_INVALID:
eustasc7d27da2017-04-06 10:33:201135 case SourceStream::TYPE_REJECTED:
1136 case SourceStream::TYPE_UNKNOWN:
xunjieli28a18772016-10-25 15:30:061137 case SourceStream::TYPE_MAX:
1138 NOTREACHED();
1139 return nullptr;
1140 }
1141 if (downstream == nullptr)
1142 return nullptr;
1143 upstream = std::move(downstream);
1144 }
1145
1146 return upstream;
[email protected]5394e422011-01-20 22:07:431147}
1148
[email protected]f878230e2014-04-03 15:36:141149bool URLRequestHttpJob::CopyFragmentOnRedirect(const GURL& location) const {
1150 // Allow modification of reference fragments by default, unless
1151 // |allowed_unsafe_redirect_url_| is set and equal to the redirect URL.
1152 // When this is the case, we assume that the network delegate has set the
1153 // desired redirect URL (with or without fragment), so it must not be changed
1154 // any more.
1155 return !allowed_unsafe_redirect_url_.is_valid() ||
1156 allowed_unsafe_redirect_url_ != location;
1157}
1158
[email protected]5394e422011-01-20 22:07:431159bool URLRequestHttpJob::IsSafeRedirect(const GURL& location) {
[email protected]e0f35c92013-05-08 16:04:341160 // HTTP is always safe.
1161 // TODO(pauljensen): Remove once crbug.com/146591 is fixed.
1162 if (location.is_valid() &&
1163 (location.scheme() == "http" || location.scheme() == "https")) {
[email protected]5394e422011-01-20 22:07:431164 return true;
[email protected]5394e422011-01-20 22:07:431165 }
[email protected]f878230e2014-04-03 15:36:141166 // Delegates may mark a URL as safe for redirection.
1167 if (allowed_unsafe_redirect_url_.is_valid() &&
1168 allowed_unsafe_redirect_url_ == location) {
1169 return true;
[email protected]5f714132014-03-26 10:41:161170 }
[email protected]e0f35c92013-05-08 16:04:341171 // Query URLRequestJobFactory as to whether |location| would be safe to
1172 // redirect to.
1173 return request_->context()->job_factory() &&
1174 request_->context()->job_factory()->IsSafeRedirectTarget(location);
[email protected]5394e422011-01-20 22:07:431175}
1176
1177bool URLRequestHttpJob::NeedsAuth() {
1178 int code = GetResponseCode();
1179 if (code == -1)
1180 return false;
1181
rdsmith81f607562014-11-21 18:35:161182 // Check if we need either Proxy or WWW Authentication. This could happen
[email protected]5394e422011-01-20 22:07:431183 // because we either provided no auth info, or provided incorrect info.
1184 switch (code) {
1185 case 407:
1186 if (proxy_auth_state_ == AUTH_STATE_CANCELED)
1187 return false;
1188 proxy_auth_state_ = AUTH_STATE_NEED_AUTH;
1189 return true;
1190 case 401:
1191 if (server_auth_state_ == AUTH_STATE_CANCELED)
1192 return false;
1193 server_auth_state_ = AUTH_STATE_NEED_AUTH;
1194 return true;
1195 }
1196 return false;
1197}
1198
1199void URLRequestHttpJob::GetAuthChallengeInfo(
1200 scoped_refptr<AuthChallengeInfo>* result) {
1201 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
1211 *result = response_info_->auth_challenge;
1212}
1213
[email protected]f3cf9802011-10-28 18:44:581214void URLRequestHttpJob::SetAuth(const AuthCredentials& credentials) {
[email protected]5394e422011-01-20 22:07:431215 DCHECK(transaction_.get());
1216
1217 // Proxy gets set first, then WWW.
1218 if (proxy_auth_state_ == AUTH_STATE_NEED_AUTH) {
1219 proxy_auth_state_ = AUTH_STATE_HAVE_AUTH;
1220 } else {
[email protected]dd29bcd72011-03-24 00:03:441221 DCHECK_EQ(server_auth_state_, AUTH_STATE_NEED_AUTH);
[email protected]5394e422011-01-20 22:07:431222 server_auth_state_ = AUTH_STATE_HAVE_AUTH;
1223 }
1224
[email protected]f3cf9802011-10-28 18:44:581225 RestartTransactionWithAuth(credentials);
[email protected]5394e422011-01-20 22:07:431226}
1227
1228void URLRequestHttpJob::CancelAuth() {
1229 // Proxy gets set first, then WWW.
1230 if (proxy_auth_state_ == AUTH_STATE_NEED_AUTH) {
1231 proxy_auth_state_ = AUTH_STATE_CANCELED;
1232 } else {
[email protected]dd29bcd72011-03-24 00:03:441233 DCHECK_EQ(server_auth_state_, AUTH_STATE_NEED_AUTH);
[email protected]5394e422011-01-20 22:07:431234 server_auth_state_ = AUTH_STATE_CANCELED;
1235 }
1236
1237 // These will be reset in OnStartCompleted.
1238 response_info_ = NULL;
[email protected]3b23a222013-05-15 21:33:251239 receive_headers_end_ = base::TimeTicks::Now();
[email protected]5394e422011-01-20 22:07:431240
[email protected]ec23f522011-02-22 21:01:381241 ResetTimer();
1242
[email protected]5394e422011-01-20 22:07:431243 // OK, let the consumer read the error page...
1244 //
1245 // Because we set the AUTH_STATE_CANCELED flag, NeedsAuth will return false,
1246 // which will cause the consumer to receive OnResponseStarted instead of
1247 // OnAuthRequired.
1248 //
1249 // We have to do this via InvokeLater to avoid "recursing" the consumer.
1250 //
skyostil4891b25b2015-06-11 11:43:451251 base::ThreadTaskRunnerHandle::Get()->PostTask(
1252 FROM_HERE, base::Bind(&URLRequestHttpJob::OnStartCompleted,
1253 weak_factory_.GetWeakPtr(), OK));
[email protected]5394e422011-01-20 22:07:431254}
1255
1256void URLRequestHttpJob::ContinueWithCertificate(
mattm436ccfe2017-06-19 20:24:081257 scoped_refptr<X509Certificate> client_cert,
1258 scoped_refptr<SSLPrivateKey> client_private_key) {
[email protected]5394e422011-01-20 22:07:431259 DCHECK(transaction_.get());
1260
1261 DCHECK(!response_info_) << "should not have a response yet";
[email protected]3b23a222013-05-15 21:33:251262 receive_headers_end_ = base::TimeTicks();
[email protected]5394e422011-01-20 22:07:431263
[email protected]ec23f522011-02-22 21:01:381264 ResetTimer();
1265
mmenked3a02b32016-11-16 20:21:321266 int rv = transaction_->RestartWithCertificate(
mattm436ccfe2017-06-19 20:24:081267 std::move(client_cert), std::move(client_private_key),
mmenked3a02b32016-11-16 20:21:321268 base::Bind(&URLRequestHttpJob::OnStartCompleted, base::Unretained(this)));
[email protected]5394e422011-01-20 22:07:431269 if (rv == ERR_IO_PENDING)
1270 return;
1271
1272 // The transaction started synchronously, but we need to notify the
1273 // URLRequest delegate via the message loop.
skyostil4891b25b2015-06-11 11:43:451274 base::ThreadTaskRunnerHandle::Get()->PostTask(
1275 FROM_HERE, base::Bind(&URLRequestHttpJob::OnStartCompleted,
1276 weak_factory_.GetWeakPtr(), rv));
[email protected]5394e422011-01-20 22:07:431277}
1278
1279void URLRequestHttpJob::ContinueDespiteLastError() {
1280 // If the transaction was destroyed, then the job was cancelled.
1281 if (!transaction_.get())
1282 return;
1283
1284 DCHECK(!response_info_) << "should not have a response yet";
[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
mmenked3a02b32016-11-16 20:21:321289 int rv = transaction_->RestartIgnoringLastError(
1290 base::Bind(&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(
1297 FROM_HERE, base::Bind(&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
[email protected]49639fa2011-12-20 23:22:411328 int rv = transaction_->Read(
1329 buf, buf_size,
1330 base::Bind(&URLRequestHttpJob::OnReadCompleted, base::Unretained(this)));
[email protected]85c1dce2011-07-06 12:01:291331
[email protected]f001bd6a2011-12-08 04:31:371332 if (ShouldFixMismatchedContentLength(rv))
xunjieli26ede962015-11-23 19:39:131333 rv = OK;
[email protected]f001bd6a2011-12-08 04:31:371334
xunjieli26ede962015-11-23 19:39:131335 if (rv == 0 || (rv < 0 && rv != ERR_IO_PENDING))
1336 DoneWithRequest(FINISHED);
[email protected]5394e422011-01-20 22:07:431337
xunjieli26ede962015-11-23 19:39:131338 if (rv == ERR_IO_PENDING)
[email protected]5394e422011-01-20 22:07:431339 read_in_progress_ = true;
[email protected]5394e422011-01-20 22:07:431340
xunjieli26ede962015-11-23 19:39:131341 return rv;
[email protected]5394e422011-01-20 22:07:431342}
1343
1344void URLRequestHttpJob::StopCaching() {
1345 if (transaction_.get())
1346 transaction_->StopCaching();
1347}
1348
[email protected]79e1fd62013-06-20 06:50:041349bool URLRequestHttpJob::GetFullRequestHeaders(
1350 HttpRequestHeaders* headers) const {
1351 if (!transaction_)
1352 return false;
1353
1354 return transaction_->GetFullRequestHeaders(headers);
1355}
1356
Avi Drissman13fc8932015-12-20 04:40:461357int64_t URLRequestHttpJob::GetTotalReceivedBytes() const {
sclittlece72c482015-08-24 20:20:591358 int64_t total_received_bytes =
1359 total_received_bytes_from_previous_transactions_;
1360 if (transaction_)
1361 total_received_bytes += transaction_->GetTotalReceivedBytes();
1362 return total_received_bytes;
[email protected]71e5ff8f2014-01-13 09:44:041363}
1364
sclittlefb249892015-09-10 21:33:221365int64_t URLRequestHttpJob::GetTotalSentBytes() const {
1366 int64_t total_sent_bytes = total_sent_bytes_from_previous_transactions_;
1367 if (transaction_)
1368 total_sent_bytes += transaction_->GetTotalSentBytes();
1369 return total_sent_bytes;
1370}
1371
[email protected]5c04f722011-08-12 17:52:471372void URLRequestHttpJob::DoneReading() {
[email protected]e50efea2014-03-24 18:41:001373 if (transaction_) {
[email protected]5c04f722011-08-12 17:52:471374 transaction_->DoneReading();
[email protected]e50efea2014-03-24 18:41:001375 }
1376 DoneWithRequest(FINISHED);
1377}
1378
1379void URLRequestHttpJob::DoneReadingRedirectResponse() {
1380 if (transaction_) {
1381 if (transaction_->GetResponseInfo()->headers->IsRedirect(NULL)) {
1382 // If the original headers indicate a redirect, go ahead and cache the
1383 // response, even if the |override_response_headers_| are a redirect to
1384 // another location.
1385 transaction_->DoneReading();
1386 } else {
1387 // Otherwise, |override_response_headers_| must be non-NULL and contain
1388 // bogus headers indicating a redirect.
dchengc2e01e82014-08-27 00:24:421389 DCHECK(override_response_headers_.get());
[email protected]e50efea2014-03-24 18:41:001390 DCHECK(override_response_headers_->IsRedirect(NULL));
1391 transaction_->StopCaching();
1392 }
1393 }
[email protected]5c04f722011-08-12 17:52:471394 DoneWithRequest(FINISHED);
1395}
1396
[email protected]6d81b482011-02-22 19:47:191397HostPortPair URLRequestHttpJob::GetSocketAddress() const {
1398 return response_info_ ? response_info_->socket_address : HostPortPair();
1399}
1400
[email protected]ec23f522011-02-22 21:01:381401void URLRequestHttpJob::RecordTimer() {
1402 if (request_creation_time_.is_null()) {
1403 NOTREACHED()
1404 << "The same transaction shouldn't start twice without new timing.";
1405 return;
1406 }
1407
[email protected]320a29f12011-03-21 14:47:411408 base::TimeDelta to_start = base::Time::Now() - request_creation_time_;
[email protected]ec23f522011-02-22 21:01:381409 request_creation_time_ = base::Time();
[email protected]8684a8812011-03-22 13:59:381410
[email protected]5c68d692011-08-24 04:59:411411 UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpTimeToFirstByte", to_start);
mmenke1beda3d2016-07-22 03:33:451412 if (request_info_.upload_data_stream &&
1413 request_info_.upload_data_stream->size() > 1024 * 1024) {
1414 UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpTimeToFirstByte.LargeUpload", to_start);
1415 }
[email protected]ec23f522011-02-22 21:01:381416}
1417
1418void URLRequestHttpJob::ResetTimer() {
1419 if (!request_creation_time_.is_null()) {
1420 NOTREACHED()
1421 << "The timer was reset before it was recorded.";
1422 return;
1423 }
1424 request_creation_time_ = base::Time::Now();
1425}
1426
[email protected]dd29bcd72011-03-24 00:03:441427void URLRequestHttpJob::UpdatePacketReadTimes() {
1428 if (!packet_timing_enabled_)
1429 return;
1430
mmenkebbf19be22015-04-11 02:44:481431 DCHECK_GT(prefilter_bytes_read(), bytes_observed_in_packets_);
[email protected]dd29bcd72011-03-24 00:03:441432
[email protected]006ce1a2014-07-30 14:41:231433 base::Time now(base::Time::Now());
[email protected]dd29bcd72011-03-24 00:03:441434 if (!bytes_observed_in_packets_)
[email protected]006ce1a2014-07-30 14:41:231435 request_time_snapshot_ = now;
1436 final_packet_time_ = now;
[email protected]dd29bcd72011-03-24 00:03:441437
mmenkebbf19be22015-04-11 02:44:481438 bytes_observed_in_packets_ = prefilter_bytes_read();
[email protected]dd29bcd72011-03-24 00:03:441439}
1440
Andrey Kosyakov83a6eee2017-08-14 19:20:041441void URLRequestHttpJob::SetRequestHeadersCallback(
1442 RequestHeadersCallback callback) {
1443 DCHECK(!transaction_);
1444 DCHECK(!request_headers_callback_);
1445 request_headers_callback_ = std::move(callback);
1446}
1447
Andrey Kosyakov2e893e62017-08-31 17:00:521448void URLRequestHttpJob::SetResponseHeadersCallback(
1449 ResponseHeadersCallback callback) {
1450 DCHECK(!transaction_);
1451 DCHECK(!response_headers_callback_);
1452 response_headers_callback_ = std::move(callback);
1453}
1454
[email protected]bbaea8f2011-06-24 00:11:011455void URLRequestHttpJob::RecordPerfHistograms(CompletionCause reason) {
1456 if (start_time_.is_null())
1457 return;
1458
1459 base::TimeDelta total_time = base::TimeTicks::Now() - start_time_;
1460 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTime", total_time);
1461
1462 if (reason == FINISHED) {
Devdeep Ray0c6966d2017-07-14 00:58:221463 UmaHistogramTimes(
1464 base::StringPrintf("Net.HttpJob.TotalTimeSuccess.Priority%d",
1465 request()->priority()),
1466 total_time);
[email protected]bbaea8f2011-06-24 00:11:011467 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeSuccess", total_time);
1468 } else {
1469 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeCancel", total_time);
1470 }
1471
[email protected]4b4d20242012-02-23 18:27:461472 if (response_info_) {
rtennetie55c4b72015-08-03 21:48:351473 // QUIC (by default) supports https scheme only, thus track https URLs only
1474 // for QUIC.
1475 bool is_https_google = request() && request()->url().SchemeIs("https") &&
1476 HasGoogleHost(request()->url());
rtenneti72928bb2015-04-28 18:28:131477 bool used_quic = response_info_->DidUseQuic();
rtennetie55c4b72015-08-03 21:48:351478 if (is_https_google) {
rtenneti72928bb2015-04-28 18:28:131479 if (used_quic) {
rtennetie55c4b72015-08-03 21:48:351480 UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpJob.TotalTime.Secure.Quic",
1481 total_time);
rtenneti72928bb2015-04-28 18:28:131482 } else {
rtennetie55c4b72015-08-03 21:48:351483 UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpJob.TotalTime.Secure.NotQuic",
1484 total_time);
rtenneti72928bb2015-04-28 18:28:131485 }
1486 }
jkarlinded0021b2016-12-05 16:01:061487
1488 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpJob.PrefilterBytesRead",
1489 prefilter_bytes_read(), 1, 50000000, 50);
[email protected]4b4d20242012-02-23 18:27:461490 if (response_info_->was_cached) {
1491 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeCached", total_time);
jkarlinded0021b2016-12-05 16:01:061492 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpJob.PrefilterBytesRead.Cache",
1493 prefilter_bytes_read(), 1, 50000000, 50);
1494
jkarlincc6943d2016-04-25 19:25:351495 if (response_info_->unused_since_prefetch)
Steven Holte6143e642017-06-28 19:47:381496 UMA_HISTOGRAM_COUNTS_1M("Net.Prefetch.HitBytes",
1497 prefilter_bytes_read());
jkarlincc6943d2016-04-25 19:25:351498 } else {
[email protected]4b4d20242012-02-23 18:27:461499 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeNotCached", total_time);
jkarlinded0021b2016-12-05 16:01:061500 UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpJob.PrefilterBytesRead.Net",
1501 prefilter_bytes_read(), 1, 50000000, 50);
1502
1503 if (request_info_.load_flags & LOAD_PREFETCH) {
Steven Holte6143e642017-06-28 19:47:381504 UMA_HISTOGRAM_COUNTS_1M("Net.Prefetch.PrefilterBytesReadFromNetwork",
1505 prefilter_bytes_read());
jkarlinded0021b2016-12-05 16:01:061506 }
rtennetie55c4b72015-08-03 21:48:351507 if (is_https_google) {
rtenneti72928bb2015-04-28 18:28:131508 if (used_quic) {
rtennetie55c4b72015-08-03 21:48:351509 UMA_HISTOGRAM_MEDIUM_TIMES(
1510 "Net.HttpJob.TotalTimeNotCached.Secure.Quic", total_time);
rtenneti72928bb2015-04-28 18:28:131511 } else {
rtennetie55c4b72015-08-03 21:48:351512 UMA_HISTOGRAM_MEDIUM_TIMES(
1513 "Net.HttpJob.TotalTimeNotCached.Secure.NotQuic", total_time);
rtenneti72928bb2015-04-28 18:28:131514 }
1515 }
[email protected]b73656ca2011-07-22 17:42:171516 }
[email protected]bbaea8f2011-06-24 00:11:011517 }
1518
1519 start_time_ = base::TimeTicks();
1520}
1521
1522void URLRequestHttpJob::DoneWithRequest(CompletionCause reason) {
1523 if (done_)
1524 return;
1525 done_ = true;
tbansal79ed5cd2015-08-10 18:53:561526
1527 // Notify NetworkQualityEstimator.
mmenke7ce675a2016-11-07 17:08:301528 NetworkQualityEstimator* network_quality_estimator =
1529 request()->context()->network_quality_estimator();
1530 if (network_quality_estimator) {
1531 network_quality_estimator->NotifyRequestCompleted(
1532 *request(), request_->status().error());
tbansal79ed5cd2015-08-10 18:53:561533 }
1534
[email protected]bbaea8f2011-06-24 00:11:011535 RecordPerfHistograms(reason);
mmenke7ce675a2016-11-07 17:08:301536 request()->set_received_response_content_length(prefilter_bytes_read());
[email protected]bbaea8f2011-06-24 00:11:011537}
1538
[email protected]ea8141e2011-10-05 13:12:511539HttpResponseHeaders* URLRequestHttpJob::GetResponseHeaders() const {
1540 DCHECK(transaction_.get());
1541 DCHECK(transaction_->GetResponseInfo());
1542 return override_response_headers_.get() ?
[email protected]90499482013-06-01 00:39:501543 override_response_headers_.get() :
1544 transaction_->GetResponseInfo()->headers.get();
[email protected]ea8141e2011-10-05 13:12:511545}
1546
1547void URLRequestHttpJob::NotifyURLRequestDestroyed() {
1548 awaiting_callback_ = false;
tbansal80a52162016-05-20 17:55:041549
1550 // Notify NetworkQualityEstimator.
mmenke7ce675a2016-11-07 17:08:301551 NetworkQualityEstimator* network_quality_estimator =
1552 request()->context()->network_quality_estimator();
1553 if (network_quality_estimator)
1554 network_quality_estimator->NotifyURLRequestDestroyed(*request());
[email protected]ea8141e2011-10-05 13:12:511555}
1556
[email protected]4f5656c62010-12-13 10:47:091557} // namespace net