blob: 39a4a41b4879f021e3b2caf5f34183ad62ba6ca8 [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
[email protected]4ed2755f2008-12-15 09:01:337#include "base/base_switches.h"
[email protected]4f9e5c82011-11-17 16:04:568#include "base/bind.h"
[email protected]084262c2011-12-01 21:12:479#include "base/bind_helpers.h"
[email protected]4ed2755f2008-12-15 09:01:3310#include "base/command_line.h"
[email protected]39ce5c02008-08-22 04:03:4411#include "base/compiler_specific.h"
[email protected]60889422008-09-23 01:18:1612#include "base/file_version_info.h"
skyostil4891b25b2015-06-11 11:43:4513#include "base/location.h"
Avi Drissman13fc8932015-12-20 04:40:4614#include "base/macros.h"
[email protected]8684a8812011-03-22 13:59:3815#include "base/metrics/field_trial.h"
asvitkinec3c93722015-06-17 14:48:3716#include "base/metrics/histogram_macros.h"
vadimt29494d82014-11-04 20:06:2617#include "base/profiler/scoped_tracker.h"
[email protected]5b90b5d2009-04-30 23:06:0118#include "base/rand_util.h"
skyostil4891b25b2015-06-11 11:43:4519#include "base/single_thread_task_runner.h"
[email protected]4dc3ad4f2013-06-11 07:15:5020#include "base/strings/string_util.h"
skyostil4891b25b2015-06-11 11:43:4521#include "base/thread_task_runner_handle.h"
[email protected]f002abb2013-06-28 02:30:2122#include "base/time/time.h"
estade5e5529d2015-05-21 20:59:1123#include "base/values.h"
[email protected]6d81b482011-02-22 19:47:1924#include "net/base/host_port_pair.h"
[email protected]b8430722008-09-17 20:05:4425#include "net/base/load_flags.h"
initial.commit586acc5fe2008-07-26 22:42:5226#include "net/base/net_errors.h"
[email protected]636eccd2011-06-28 12:28:0127#include "net/base/network_delegate.h"
tbansal79ed5cd2015-08-10 18:53:5628#include "net/base/network_quality_estimator.h"
[email protected]60889422008-09-23 01:18:1629#include "net/base/sdch_manager.h"
baranovichc5e38652014-11-14 03:08:1530#include "net/base/sdch_net_log_params.h"
tfarina7a4a7fd2016-01-20 14:23:4431#include "net/base/url_util.h"
[email protected]6e7845ae2013-03-29 21:48:1132#include "net/cert/cert_status_flags.h"
[email protected]dc8313a2014-03-24 21:38:1433#include "net/cookies/cookie_store.h"
[email protected]262191712014-03-22 00:46:5734#include "net/http/http_content_disposition.h"
[email protected]7a299a92012-10-24 23:54:5035#include "net/http/http_network_session.h"
[email protected]8c76ae22010-04-20 22:15:4336#include "net/http/http_request_headers.h"
[email protected]319d9e6f2009-02-18 19:47:2137#include "net/http/http_response_headers.h"
initial.commit586acc5fe2008-07-26 22:42:5238#include "net/http/http_response_info.h"
[email protected]9094b602012-02-27 21:44:5839#include "net/http/http_status_code.h"
initial.commit586acc5fe2008-07-26 22:42:5240#include "net/http/http_transaction.h"
41#include "net/http/http_transaction_factory.h"
[email protected]0757e7702009-03-27 04:00:2242#include "net/http/http_util.h"
[email protected]597a1ab2014-06-26 08:12:2743#include "net/proxy/proxy_info.h"
nharper5babb5e62016-03-09 18:58:0744#include "net/ssl/channel_id_service.h"
[email protected]536fd0b2013-03-14 17:41:5745#include "net/ssl/ssl_cert_request_info.h"
46#include "net/ssl/ssl_config_service.h"
[email protected]ee4c30d2012-11-07 15:08:4347#include "net/url_request/http_user_agent_settings.h"
initial.commit586acc5fe2008-07-26 22:42:5248#include "net/url_request/url_request.h"
xunjieli3bb781a2015-07-22 22:40:3449#include "net/url_request/url_request_backoff_manager.h"
[email protected]319d9e6f2009-02-18 19:47:2150#include "net/url_request/url_request_context.h"
initial.commit586acc5fe2008-07-26 22:42:5251#include "net/url_request/url_request_error_job.h"
[email protected]e0f35c92013-05-08 16:04:3452#include "net/url_request/url_request_job_factory.h"
[email protected]06965e02009-09-04 21:36:4253#include "net/url_request/url_request_redirect_job.h"
[email protected]6b3f9642010-11-25 02:29:0654#include "net/url_request/url_request_throttler_manager.h"
[email protected]f4533ba2013-11-28 09:35:4155#include "net/websockets/websocket_handshake_stream_base.h"
mkwst8241a122015-10-20 07:15:1056#include "url/origin.h"
initial.commit586acc5fe2008-07-26 22:42:5257
[email protected]8c76ae22010-04-20 22:15:4358static const char kAvailDictionaryHeader[] = "Avail-Dictionary";
59
mkwst202534e32016-01-15 16:07:1560namespace {
61
62// True if the request method is "safe" (per section 4.2.1 of RFC 7231).
63bool IsMethodSafe(const std::string& method) {
64 return method == "GET" || method == "HEAD" || method == "OPTIONS" ||
65 method == "TRACE";
66}
67
nharper5babb5e62016-03-09 18:58:0768void LogChannelIDAndCookieStores(const net::URLRequestContext* context,
69 const net::SSLInfo& ssl_info) {
70 if (!ssl_info.channel_id_sent)
71 return;
72 // This enum is used for an UMA histogram - don't reuse or renumber entries.
73 enum {
nharper09ccd502016-03-10 01:54:2874 // Value 0 was removed (CID_EPHEMERAL_COOKIE_EPHEMERAL)
nharper5babb5e62016-03-09 18:58:0775 CID_EPHEMERAL_COOKIE_PERSISTENT = 1,
76 CID_PERSISTENT_COOKIE_EPHEMERAL = 2,
nharper09ccd502016-03-10 01:54:2877 // Value 3 was removed (CID_PERSISTENT_COOKIE_PERSISTENT)
nharper5babb5e62016-03-09 18:58:0778 NO_COOKIE_STORE = 4,
79 NO_CHANNEL_ID_STORE = 5,
80 KNOWN_MISMATCH = 6,
nharper09ccd502016-03-10 01:54:2881 EPHEMERAL_MATCH = 7,
82 EPHEMERAL_MISMATCH = 8,
83 PERSISTENT_MATCH = 9,
84 PERSISTENT_MISMATCH = 10,
nharper5babb5e62016-03-09 18:58:0785 EPHEMERALITY_MAX
86 } ephemerality;
87 const net::HttpNetworkSession::Params* params =
88 context->GetNetworkSessionParams();
89 net::CookieStore* cookie_store = context->cookie_store();
90 if (params == nullptr || params->channel_id_service == nullptr) {
91 ephemerality = NO_CHANNEL_ID_STORE;
92 } else if (cookie_store == nullptr) {
93 ephemerality = NO_COOKIE_STORE;
94 } else if (params->channel_id_service->GetChannelIDStore()->IsEphemeral()) {
95 if (cookie_store->IsEphemeral()) {
nharper09ccd502016-03-10 01:54:2896 if (context->channel_id_service() &&
97 params->channel_id_service->GetUniqueID() ==
98 context->channel_id_service()->GetUniqueID()) {
99 ephemerality = EPHEMERAL_MATCH;
100 } else {
101 ephemerality = EPHEMERAL_MISMATCH;
102 }
nharper5babb5e62016-03-09 18:58:07103 } else if (context->has_known_mismatched_cookie_store()) {
104 ephemerality = KNOWN_MISMATCH;
105 } else {
106 ephemerality = CID_EPHEMERAL_COOKIE_PERSISTENT;
107 }
108 } else if (cookie_store->IsEphemeral()) {
109 ephemerality = CID_PERSISTENT_COOKIE_EPHEMERAL;
nharper09ccd502016-03-10 01:54:28110 } else if (context->channel_id_service() &&
111 params->channel_id_service->GetUniqueID() ==
112 context->channel_id_service()->GetUniqueID()) {
113 ephemerality = PERSISTENT_MATCH;
nharper5babb5e62016-03-09 18:58:07114 } else {
nharper09ccd502016-03-10 01:54:28115 ephemerality = PERSISTENT_MISMATCH;
nharper5babb5e62016-03-09 18:58:07116 }
117 UMA_HISTOGRAM_ENUMERATION("Net.TokenBinding.StoreEphemerality", ephemerality,
118 EPHEMERALITY_MAX);
119}
120
mkwst202534e32016-01-15 16:07:15121} // namespace
122
[email protected]4f5656c62010-12-13 10:47:09123namespace net {
124
[email protected]2e92354c2011-03-25 20:49:53125class URLRequestHttpJob::HttpFilterContext : public FilterContext {
126 public:
127 explicit HttpFilterContext(URLRequestHttpJob* job);
dchengb03027d2014-10-21 12:00:20128 ~HttpFilterContext() override;
[email protected]2e92354c2011-03-25 20:49:53129
130 // FilterContext implementation.
dchengb03027d2014-10-21 12:00:20131 bool GetMimeType(std::string* mime_type) const override;
132 bool GetURL(GURL* gurl) const override;
dchengb03027d2014-10-21 12:00:20133 base::Time GetRequestTime() const override;
134 bool IsCachedContent() const override;
rdsmith81f607562014-11-21 18:35:16135 SdchManager::DictionarySet* SdchDictionariesAdvertised() const override;
Avi Drissman13fc8932015-12-20 04:40:46136 int64_t GetByteReadCount() const override;
dchengb03027d2014-10-21 12:00:20137 int GetResponseCode() const override;
138 const URLRequestContext* GetURLRequestContext() const override;
139 void RecordPacketStats(StatisticSelector statistic) const override;
baranovichc5e38652014-11-14 03:08:15140 const BoundNetLog& GetNetLog() const override;
[email protected]2e92354c2011-03-25 20:49:53141
142 private:
143 URLRequestHttpJob* job_;
144
baranovichc5e38652014-11-14 03:08:15145 // URLRequestHttpJob may be detached from URLRequest, but we still need to
146 // return something.
147 BoundNetLog dummy_log_;
148
[email protected]2e92354c2011-03-25 20:49:53149 DISALLOW_COPY_AND_ASSIGN(HttpFilterContext);
150};
151
[email protected]fc01f232011-03-17 19:06:01152URLRequestHttpJob::HttpFilterContext::HttpFilterContext(URLRequestHttpJob* job)
153 : job_(job) {
154 DCHECK(job_);
155}
156
157URLRequestHttpJob::HttpFilterContext::~HttpFilterContext() {
158}
159
160bool URLRequestHttpJob::HttpFilterContext::GetMimeType(
161 std::string* mime_type) const {
162 return job_->GetMimeType(mime_type);
163}
164
165bool URLRequestHttpJob::HttpFilterContext::GetURL(GURL* gurl) const {
166 if (!job_->request())
167 return false;
168 *gurl = job_->request()->url();
169 return true;
170}
171
172base::Time URLRequestHttpJob::HttpFilterContext::GetRequestTime() const {
173 return job_->request() ? job_->request()->request_time() : base::Time();
174}
175
176bool URLRequestHttpJob::HttpFilterContext::IsCachedContent() const {
[email protected]dd29bcd72011-03-24 00:03:44177 return job_->is_cached_content_;
[email protected]fc01f232011-03-17 19:06:01178}
179
rdsmith81f607562014-11-21 18:35:16180SdchManager::DictionarySet*
181URLRequestHttpJob::HttpFilterContext::SdchDictionariesAdvertised() const {
182 return job_->dictionaries_advertised_.get();
[email protected]fc01f232011-03-17 19:06:01183}
184
Avi Drissman13fc8932015-12-20 04:40:46185int64_t URLRequestHttpJob::HttpFilterContext::GetByteReadCount() const {
mmenkebbf19be22015-04-11 02:44:48186 return job_->prefilter_bytes_read();
[email protected]fc01f232011-03-17 19:06:01187}
188
189int URLRequestHttpJob::HttpFilterContext::GetResponseCode() const {
190 return job_->GetResponseCode();
191}
192
[email protected]6a586762014-06-15 16:02:22193const URLRequestContext*
194URLRequestHttpJob::HttpFilterContext::GetURLRequestContext() const {
195 return job_->request() ? job_->request()->context() : NULL;
196}
197
[email protected]fc01f232011-03-17 19:06:01198void URLRequestHttpJob::HttpFilterContext::RecordPacketStats(
199 StatisticSelector statistic) const {
200 job_->RecordPacketStats(statistic);
201}
202
baranovichc5e38652014-11-14 03:08:15203const BoundNetLog& URLRequestHttpJob::HttpFilterContext::GetNetLog() const {
204 return job_->request() ? job_->request()->net_log() : dummy_log_;
205}
206
initial.commit586acc5fe2008-07-26 22:42:52207// TODO(darin): make sure the port blocking code is not lost
initial.commit586acc5fe2008-07-26 22:42:52208// static
[email protected]4f5656c62010-12-13 10:47:09209URLRequestJob* URLRequestHttpJob::Factory(URLRequest* request,
[email protected]9f170462012-08-24 01:06:58210 NetworkDelegate* network_delegate,
[email protected]4f5656c62010-12-13 10:47:09211 const std::string& scheme) {
[email protected]f4533ba2013-11-28 09:35:41212 DCHECK(scheme == "http" || scheme == "https" || scheme == "ws" ||
213 scheme == "wss");
initial.commit586acc5fe2008-07-26 22:42:52214
[email protected]81293f482012-08-13 19:35:45215 if (!request->context()->http_transaction_factory()) {
initial.commit586acc5fe2008-07-26 22:42:52216 NOTREACHED() << "requires a valid context";
[email protected]9f170462012-08-24 01:06:58217 return new URLRequestErrorJob(
218 request, network_delegate, ERR_INVALID_ARGUMENT);
initial.commit586acc5fe2008-07-26 22:42:52219 }
220
[email protected]ce572df2012-05-04 19:47:17221 GURL redirect_url;
[email protected]8ccc69f2012-11-28 19:52:14222 if (request->GetHSTSRedirect(&redirect_url)) {
223 return new URLRequestRedirectJob(
224 request, network_delegate, redirect_url,
225 // Use status code 307 to preserve the method, so POST requests work.
[email protected]7983c4a2014-03-12 01:47:09226 URLRequestRedirectJob::REDIRECT_307_TEMPORARY_REDIRECT, "HSTS");
[email protected]8ccc69f2012-11-28 19:52:14227 }
[email protected]ee4c30d2012-11-07 15:08:43228 return new URLRequestHttpJob(request,
229 network_delegate,
230 request->context()->http_user_agent_settings());
initial.commit586acc5fe2008-07-26 22:42:52231}
232
[email protected]ee4c30d2012-11-07 15:08:43233URLRequestHttpJob::URLRequestHttpJob(
234 URLRequest* request,
235 NetworkDelegate* network_delegate,
236 const HttpUserAgentSettings* http_user_agent_settings)
[email protected]9f170462012-08-24 01:06:58237 : URLRequestJob(request, network_delegate),
[email protected]5033ab82013-03-22 20:17:46238 priority_(DEFAULT_PRIORITY),
mmenke54e82af2016-02-16 23:06:30239 response_info_(nullptr),
[email protected]4f5656c62010-12-13 10:47:09240 proxy_auth_state_(AUTH_STATE_DONT_NEED_AUTH),
241 server_auth_state_(AUTH_STATE_DONT_NEED_AUTH),
[email protected]dd946bb2013-06-12 22:53:01242 start_callback_(base::Bind(&URLRequestHttpJob::OnStartCompleted,
243 base::Unretained(this))),
244 notify_before_headers_sent_callback_(
245 base::Bind(&URLRequestHttpJob::NotifyBeforeSendHeadersCallback,
246 base::Unretained(this))),
[email protected]3589e552008-08-20 23:11:34247 read_in_progress_(false),
mmenke54e82af2016-02-16 23:06:30248 throttling_entry_(nullptr),
[email protected]5b90b5d2009-04-30 23:06:01249 sdch_test_activated_(false),
[email protected]d8fd5132009-05-15 01:06:53250 sdch_test_control_(false),
[email protected]00e48bf2010-12-03 06:15:42251 is_cached_content_(false),
[email protected]ec23f522011-02-22 21:01:38252 request_creation_time_(),
[email protected]dd29bcd72011-03-24 00:03:44253 packet_timing_enabled_(false),
[email protected]bbaea8f2011-06-24 00:11:01254 done_(false),
[email protected]dd29bcd72011-03-24 00:03:44255 bytes_observed_in_packets_(0),
[email protected]dd29bcd72011-03-24 00:03:44256 request_time_snapshot_(),
257 final_packet_time_(),
[email protected]aa249b52013-04-30 01:04:32258 filter_context_(new HttpFilterContext(this)),
[email protected]dd946bb2013-06-12 22:53:01259 on_headers_received_callback_(
260 base::Bind(&URLRequestHttpJob::OnHeadersReceivedCallback,
261 base::Unretained(this))),
[email protected]5a07c192012-07-30 20:18:22262 awaiting_callback_(false),
[email protected]09812102014-05-24 00:04:11263 http_user_agent_settings_(http_user_agent_settings),
xunjieli3bb781a2015-07-22 22:40:34264 backoff_manager_(request->context()->backoff_manager()),
sclittlece72c482015-08-24 20:20:59265 total_received_bytes_from_previous_transactions_(0),
sclittlefb249892015-09-10 21:33:22266 total_sent_bytes_from_previous_transactions_(0),
[email protected]09812102014-05-24 00:04:11267 weak_factory_(this) {
[email protected]a73a2802012-05-02 19:20:15268 URLRequestThrottlerManager* manager = request->context()->throttler_manager();
269 if (manager)
270 throttling_entry_ = manager->RegisterRequestUrl(request->url());
271
[email protected]ec23f522011-02-22 21:01:38272 ResetTimer();
initial.commit586acc5fe2008-07-26 22:42:52273}
274
[email protected]5033ab82013-03-22 20:17:46275URLRequestHttpJob::~URLRequestHttpJob() {
276 CHECK(!awaiting_callback_);
277
278 DCHECK(!sdch_test_control_ || !sdch_test_activated_);
279 if (!is_cached_content_) {
280 if (sdch_test_control_)
281 RecordPacketStats(FilterContext::SDCH_EXPERIMENT_HOLDBACK);
282 if (sdch_test_activated_)
283 RecordPacketStats(FilterContext::SDCH_EXPERIMENT_DECODE);
284 }
285 // Make sure SDCH filters are told to emit histogram data while
286 // filter_context_ is still alive.
287 DestroyFilters();
288
[email protected]5033ab82013-03-22 20:17:46289 DoneWithRequest(ABORTED);
290}
291
292void URLRequestHttpJob::SetPriority(RequestPriority priority) {
293 priority_ = priority;
294 if (transaction_)
295 transaction_->SetPriority(priority_);
296}
297
298void URLRequestHttpJob::Start() {
mmenke833437d2015-04-23 20:56:54299 // TODO(mmenke): Remove ScopedTracker below once crbug.com/456327 is fixed.
300 tracked_objects::ScopedTracker tracking_profile(
301 FROM_HERE_WITH_EXPLICIT_FUNCTION("456327 URLRequestHttpJob::Start"));
302
[email protected]5033ab82013-03-22 20:17:46303 DCHECK(!transaction_.get());
304
[email protected]99ecf6e2013-04-10 22:46:13305 // URLRequest::SetReferrer ensures that we do not send username and password
306 // fields in the referrer.
307 GURL referrer(request_->referrer());
[email protected]5033ab82013-03-22 20:17:46308
309 request_info_.url = request_->url();
310 request_info_.method = request_->method();
311 request_info_.load_flags = request_->load_flags();
[email protected]e6d017652013-05-17 18:01:40312 // Enable privacy mode if cookie settings or flags tell us not send or
313 // save cookies.
314 bool enable_privacy_mode =
315 (request_info_.load_flags & LOAD_DO_NOT_SEND_COOKIES) ||
316 (request_info_.load_flags & LOAD_DO_NOT_SAVE_COOKIES) ||
317 CanEnablePrivacyMode();
mkwste3e95992016-02-23 17:45:41318 // Privacy mode could still be disabled in SetCookieHeaderAndStart if we are
319 // going to send previously saved cookies.
[email protected]e6d017652013-05-17 18:01:40320 request_info_.privacy_mode = enable_privacy_mode ?
[email protected]314b03992014-04-01 01:28:53321 PRIVACY_MODE_ENABLED : PRIVACY_MODE_DISABLED;
[email protected]5033ab82013-03-22 20:17:46322
323 // Strip Referer from request_info_.extra_headers to prevent, e.g., plugins
324 // from overriding headers that are controlled using other means. Otherwise a
325 // plugin could set a referrer although sending the referrer is inhibited.
326 request_info_.extra_headers.RemoveHeader(HttpRequestHeaders::kReferer);
327
rdsmith81f607562014-11-21 18:35:16328 // Our consumer should have made sure that this is a safe referrer. See for
[email protected]5033ab82013-03-22 20:17:46329 // instance WebCore::FrameLoader::HideReferrer.
330 if (referrer.is_valid()) {
331 request_info_.extra_headers.SetHeader(HttpRequestHeaders::kReferer,
332 referrer.spec());
333 }
334
335 request_info_.extra_headers.SetHeaderIfMissing(
336 HttpRequestHeaders::kUserAgent,
337 http_user_agent_settings_ ?
[email protected]aa051272014-03-10 05:56:56338 http_user_agent_settings_->GetUserAgent() : std::string());
[email protected]5033ab82013-03-22 20:17:46339
340 AddExtraHeaders();
341 AddCookieHeaderAndStart();
342}
343
344void URLRequestHttpJob::Kill() {
[email protected]5033ab82013-03-22 20:17:46345 weak_factory_.InvalidateWeakPtrs();
mmenke2281f3762015-11-02 20:38:17346 if (transaction_)
347 DestroyTransaction();
[email protected]5033ab82013-03-22 20:17:46348 URLRequestJob::Kill();
349}
350
ttuttle3ae06922015-05-11 23:41:52351void URLRequestHttpJob::GetConnectionAttempts(ConnectionAttempts* out) const {
352 if (transaction_)
353 transaction_->GetConnectionAttempts(out);
354 else
355 out->clear();
356}
357
[email protected]597a1ab2014-06-26 08:12:27358void URLRequestHttpJob::NotifyBeforeSendProxyHeadersCallback(
[email protected]1252d42f2014-07-01 21:20:20359 const ProxyInfo& proxy_info,
360 HttpRequestHeaders* request_headers) {
361 DCHECK(request_headers);
[email protected]597a1ab2014-06-26 08:12:27362 DCHECK_NE(URLRequestStatus::CANCELED, GetStatus().status());
363 if (network_delegate()) {
364 network_delegate()->NotifyBeforeSendProxyHeaders(
365 request_,
366 proxy_info,
[email protected]1252d42f2014-07-01 21:20:20367 request_headers);
[email protected]597a1ab2014-06-26 08:12:27368 }
369}
370
xunjieli3bb781a2015-07-22 22:40:34371void URLRequestHttpJob::NotifyBeforeNetworkStart(bool* defer) {
372 if (!request_)
373 return;
374 if (backoff_manager_) {
xunjieli33550b842015-09-24 22:26:58375 if ((request_->load_flags() & LOAD_MAYBE_USER_GESTURE) == 0 &&
376 backoff_manager_->ShouldRejectRequest(request()->url(),
xunjieli3bb781a2015-07-22 22:40:34377 request()->request_time())) {
378 *defer = true;
379 base::MessageLoop::current()->PostTask(
380 FROM_HERE,
381 base::Bind(&URLRequestHttpJob::OnStartCompleted,
382 weak_factory_.GetWeakPtr(), ERR_TEMPORARY_BACKOFF));
383 return;
384 }
385 }
386 URLRequestJob::NotifyBeforeNetworkStart(defer);
387}
388
[email protected]175adac2008-07-30 17:28:04389void URLRequestHttpJob::NotifyHeadersComplete() {
initial.commit586acc5fe2008-07-26 22:42:52390 DCHECK(!response_info_);
391
392 response_info_ = transaction_->GetResponseInfo();
393
[email protected]d8fd5132009-05-15 01:06:53394 // Save boolean, as we'll need this info at destruction time, and filters may
395 // also need this info.
396 is_cached_content_ = response_info_->was_cached;
397
xunjieli041e9392015-05-19 21:51:33398 if (!is_cached_content_ && throttling_entry_.get())
399 throttling_entry_->UpdateWithResponse(GetResponseCode());
[email protected]6b3f9642010-11-25 02:29:06400
xunjieli3bb781a2015-07-22 22:40:34401 if (!is_cached_content_)
402 ProcessBackoffHeader();
403
[email protected]fecef222012-01-05 02:26:15404 // The ordering of these calls is not important.
[email protected]77f6fb432009-09-05 14:21:09405 ProcessStrictTransportSecurityHeader();
[email protected]fecef222012-01-05 02:26:15406 ProcessPublicKeyPinsHeader();
[email protected]a9cea7542009-05-20 04:30:23407
rdsmith81f607562014-11-21 18:35:16408 // Handle the server notification of a new SDCH dictionary.
[email protected]6a586762014-06-15 16:02:22409 SdchManager* sdch_manager(request()->context()->sdch_manager());
baranovichc5e38652014-11-14 03:08:15410 if (sdch_manager) {
411 SdchProblemCode rv = sdch_manager->IsInSupportedDomain(request()->url());
412 if (rv != SDCH_OK) {
ellyjones085ac462015-08-18 12:02:53413 SdchManager::SdchErrorRecovery(rv);
414 request()->net_log().AddEvent(
415 NetLog::TYPE_SDCH_DECODING_ERROR,
416 base::Bind(&NetLogSdchResourceProblemCallback, rv));
baranovichc5e38652014-11-14 03:08:15417 } else {
418 const std::string name = "Get-Dictionary";
419 std::string url_text;
olli.raulaee489a52016-01-25 08:37:10420 size_t iter = 0;
baranovichc5e38652014-11-14 03:08:15421 // TODO(jar): We need to not fetch dictionaries the first time they are
422 // seen, but rather wait until we can justify their usefulness.
423 // For now, we will only fetch the first dictionary, which will at least
424 // require multiple suggestions before we get additional ones for this
425 // site. Eventually we should wait until a dictionary is requested
426 // several times
427 // before we even download it (so that we don't waste memory or
428 // bandwidth).
429 if (GetResponseHeaders()->EnumerateHeader(&iter, name, &url_text)) {
430 // Resolve suggested URL relative to request url.
431 GURL sdch_dictionary_url = request_->url().Resolve(url_text);
Bacek41dc425d2016-01-28 22:45:35432 // Don't try to download Dictionary for cached responses. It's either
433 // useless or too late.
434 if (sdch_dictionary_url.is_valid() && !is_cached_content_) {
baranovichc5e38652014-11-14 03:08:15435 rv = sdch_manager->OnGetDictionary(request_->url(),
436 sdch_dictionary_url);
437 if (rv != SDCH_OK) {
438 SdchManager::SdchErrorRecovery(rv);
439 request_->net_log().AddEvent(
440 NetLog::TYPE_SDCH_DICTIONARY_ERROR,
441 base::Bind(&NetLogSdchDictionaryFetchProblemCallback, rv,
442 sdch_dictionary_url, false));
443 }
444 }
[email protected]6a586762014-06-15 16:02:22445 }
[email protected]60889422008-09-23 01:18:16446 }
447 }
448
rdsmith81f607562014-11-21 18:35:16449 // Handle the server signalling no SDCH encoding.
450 if (dictionaries_advertised_) {
451 // We are wary of proxies that discard or damage SDCH encoding. If a server
452 // explicitly states that this is not SDCH content, then we can correct our
453 // assumption that this is an SDCH response, and avoid the need to recover
454 // as though the content is corrupted (when we discover it is not SDCH
455 // encoded).
456 std::string sdch_response_status;
olli.raulaee489a52016-01-25 08:37:10457 size_t iter = 0;
rdsmith81f607562014-11-21 18:35:16458 while (GetResponseHeaders()->EnumerateHeader(&iter, "X-Sdch-Encode",
459 &sdch_response_status)) {
460 if (sdch_response_status == "0") {
461 dictionaries_advertised_.reset();
462 break;
463 }
464 }
465 }
466
[email protected]0757e7702009-03-27 04:00:22467 // The HTTP transaction may be restarted several times for the purposes
468 // of sending authorization information. Each time it restarts, we get
469 // notified of the headers completion so that we can update the cookie store.
470 if (transaction_->IsReadyToRestartForAuth()) {
471 DCHECK(!response_info_->auth_challenge.get());
[email protected]87a09a92011-07-14 15:50:50472 // TODO(battre): This breaks the webrequest API for
473 // URLRequestTestHTTP.BasicAuthWithCookies
[email protected]5796dc942011-07-14 19:26:10474 // where OnBeforeSendHeaders -> OnSendHeaders -> OnBeforeSendHeaders
[email protected]87a09a92011-07-14 15:50:50475 // occurs.
[email protected]f3cf9802011-10-28 18:44:58476 RestartTransactionWithAuth(AuthCredentials());
[email protected]0757e7702009-03-27 04:00:22477 return;
478 }
479
[email protected]4f5656c62010-12-13 10:47:09480 URLRequestJob::NotifyHeadersComplete();
initial.commit586acc5fe2008-07-26 22:42:52481}
482
[email protected]175adac2008-07-30 17:28:04483void URLRequestHttpJob::DestroyTransaction() {
[email protected]c6a4eb92010-03-03 23:51:19484 DCHECK(transaction_.get());
initial.commit586acc5fe2008-07-26 22:42:52485
[email protected]bbaea8f2011-06-24 00:11:01486 DoneWithRequest(ABORTED);
sclittlece72c482015-08-24 20:20:59487
488 total_received_bytes_from_previous_transactions_ +=
489 transaction_->GetTotalReceivedBytes();
sclittlefb249892015-09-10 21:33:22490 total_sent_bytes_from_previous_transactions_ +=
491 transaction_->GetTotalSentBytes();
[email protected]af4876d2008-10-21 23:10:57492 transaction_.reset();
initial.commit586acc5fe2008-07-26 22:42:52493 response_info_ = NULL;
[email protected]3b23a222013-05-15 21:33:25494 receive_headers_end_ = base::TimeTicks();
initial.commit586acc5fe2008-07-26 22:42:52495}
496
[email protected]175adac2008-07-30 17:28:04497void URLRequestHttpJob::StartTransaction() {
mmenke833437d2015-04-23 20:56:54498 // TODO(mmenke): Remove ScopedTracker below once crbug.com/456327 is fixed.
499 tracked_objects::ScopedTracker tracking_profile(
500 FROM_HERE_WITH_EXPLICIT_FUNCTION(
501 "456327 URLRequestHttpJob::StartTransaction"));
502
[email protected]cc05edc2013-03-08 18:04:41503 if (network_delegate()) {
[email protected]abe1c4a2013-10-25 19:28:51504 OnCallToDelegate();
[email protected]cc05edc2013-03-08 18:04:41505 int rv = network_delegate()->NotifyBeforeSendHeaders(
[email protected]084262c2011-12-01 21:12:47506 request_, notify_before_headers_sent_callback_,
[email protected]636eccd2011-06-28 12:28:01507 &request_info_.extra_headers);
508 // If an extension blocks the request, we rely on the callback to
[email protected]b4438d32012-09-27 06:15:30509 // MaybeStartTransactionInternal().
[email protected]abe1c4a2013-10-25 19:28:51510 if (rv == ERR_IO_PENDING)
[email protected]636eccd2011-06-28 12:28:01511 return;
[email protected]b4438d32012-09-27 06:15:30512 MaybeStartTransactionInternal(rv);
513 return;
[email protected]636eccd2011-06-28 12:28:01514 }
515 StartTransactionInternal();
516}
517
518void URLRequestHttpJob::NotifyBeforeSendHeadersCallback(int result) {
[email protected]9045b8822012-01-13 20:35:35519 // Check that there are no callbacks to already canceled requests.
520 DCHECK_NE(URLRequestStatus::CANCELED, GetStatus().status());
521
[email protected]b4438d32012-09-27 06:15:30522 MaybeStartTransactionInternal(result);
523}
524
525void URLRequestHttpJob::MaybeStartTransactionInternal(int result) {
mmenke833437d2015-04-23 20:56:54526 // TODO(mmenke): Remove ScopedTracker below once crbug.com/456327 is fixed.
527 tracked_objects::ScopedTracker tracking_profile(
528 FROM_HERE_WITH_EXPLICIT_FUNCTION(
529 "456327 URLRequestHttpJob::MaybeStartTransactionInternal"));
530
[email protected]abe1c4a2013-10-25 19:28:51531 OnCallToDelegateComplete();
[email protected]636eccd2011-06-28 12:28:01532 if (result == OK) {
533 StartTransactionInternal();
534 } else {
[email protected]55b8a6c12012-06-13 22:03:42535 std::string source("delegate");
[email protected]636eccd2011-06-28 12:28:01536 request_->net_log().AddEvent(NetLog::TYPE_CANCELLED,
[email protected]55b8a6c12012-06-13 22:03:42537 NetLog::StringCallback("source", &source));
[email protected]b4438d32012-09-27 06:15:30538 NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, result));
[email protected]636eccd2011-06-28 12:28:01539 }
540}
541
542void URLRequestHttpJob::StartTransactionInternal() {
mmenke4600b602015-10-28 18:52:17543 // This should only be called while the request's status is IO_PENDING.
mmenke2281f3762015-11-02 20:38:17544 DCHECK_EQ(URLRequestStatus::IO_PENDING, request_->status().status());
mmenke4600b602015-10-28 18:52:17545
initial.commit586acc5fe2008-07-26 22:42:52546 // NOTE: This method assumes that request_info_ is already setup properly.
547
[email protected]34602282010-02-03 22:14:15548 // If we already have a transaction, then we should restart the transaction
[email protected]f3cf9802011-10-28 18:44:58549 // with auth provided by auth_credentials_.
initial.commit586acc5fe2008-07-26 22:42:52550
hiroshigecb76caa4c52015-12-22 07:50:25551 bool invalid_header_values_in_rfc7230 = false;
552 for (HttpRequestHeaders::Iterator it(request_info_.extra_headers);
553 it.GetNext();) {
554 if (!HttpUtil::IsValidHeaderValueRFC7230(it.value())) {
555 invalid_header_values_in_rfc7230 = true;
556 break;
557 }
558 }
559 UMA_HISTOGRAM_BOOLEAN("Net.HttpRequest.ContainsInvalidHeaderValuesInRFC7230",
560 invalid_header_values_in_rfc7230);
561
[email protected]99c07902010-08-17 18:59:52562 int rv;
[email protected]6b3f9642010-11-25 02:29:06563
[email protected]cc05edc2013-03-08 18:04:41564 if (network_delegate()) {
565 network_delegate()->NotifySendHeaders(
[email protected]5796dc942011-07-14 19:26:10566 request_, request_info_.extra_headers);
567 }
568
[email protected]34602282010-02-03 22:14:15569 if (transaction_.get()) {
[email protected]49639fa2011-12-20 23:22:41570 rv = transaction_->RestartWithAuth(auth_credentials_, start_callback_);
[email protected]f3cf9802011-10-28 18:44:58571 auth_credentials_ = AuthCredentials();
[email protected]34602282010-02-03 22:14:15572 } else {
[email protected]34602282010-02-03 22:14:15573 DCHECK(request_->context()->http_transaction_factory());
initial.commit586acc5fe2008-07-26 22:42:52574
[email protected]99c07902010-08-17 18:59:52575 rv = request_->context()->http_transaction_factory()->CreateTransaction(
[email protected]027bd85a2013-12-27 22:39:10576 priority_, &transaction_);
[email protected]f4533ba2013-11-28 09:35:41577
578 if (rv == OK && request_info_.url.SchemeIsWSOrWSS()) {
[email protected]f4533ba2013-11-28 09:35:41579 base::SupportsUserData::Data* data = request_->GetUserData(
580 WebSocketHandshakeStreamBase::CreateHelper::DataKey());
581 if (data) {
582 transaction_->SetWebSocketHandshakeStreamCreateHelper(
583 static_cast<WebSocketHandshakeStreamBase::CreateHelper*>(data));
584 } else {
585 rv = ERR_DISALLOWED_URL_SCHEME;
586 }
587 }
588
[email protected]4f5656c62010-12-13 10:47:09589 if (rv == OK) {
[email protected]a45840b2014-01-10 15:40:22590 transaction_->SetBeforeNetworkStartCallback(
591 base::Bind(&URLRequestHttpJob::NotifyBeforeNetworkStart,
592 base::Unretained(this)));
[email protected]597a1ab2014-06-26 08:12:27593 transaction_->SetBeforeProxyHeadersSentCallback(
594 base::Bind(&URLRequestHttpJob::NotifyBeforeSendProxyHeadersCallback,
595 base::Unretained(this)));
[email protected]a45840b2014-01-10 15:40:22596
dchengc2e01e82014-08-27 00:24:42597 if (!throttling_entry_.get() ||
xunjieli41edcdd2015-06-24 14:26:40598 !throttling_entry_->ShouldRejectRequest(*request_)) {
[email protected]227b0e82011-03-25 21:11:53599 rv = transaction_->Start(
[email protected]49639fa2011-12-20 23:22:41600 &request_info_, start_callback_, request_->net_log());
[email protected]bbaea8f2011-06-24 00:11:01601 start_time_ = base::TimeTicks::Now();
[email protected]227b0e82011-03-25 21:11:53602 } else {
603 // Special error code for the exponential back-off module.
604 rv = ERR_TEMPORARILY_THROTTLED;
605 }
[email protected]34602282010-02-03 22:14:15606 }
initial.commit586acc5fe2008-07-26 22:42:52607 }
608
[email protected]4f5656c62010-12-13 10:47:09609 if (rv == ERR_IO_PENDING)
[email protected]34602282010-02-03 22:14:15610 return;
611
initial.commit586acc5fe2008-07-26 22:42:52612 // The transaction started synchronously, but we need to notify the
[email protected]4f5656c62010-12-13 10:47:09613 // URLRequest delegate via the message loop.
skyostil4891b25b2015-06-11 11:43:45614 base::ThreadTaskRunnerHandle::Get()->PostTask(
615 FROM_HERE, base::Bind(&URLRequestHttpJob::OnStartCompleted,
616 weak_factory_.GetWeakPtr(), rv));
initial.commit586acc5fe2008-07-26 22:42:52617}
618
[email protected]175adac2008-07-30 17:28:04619void URLRequestHttpJob::AddExtraHeaders() {
[email protected]6a586762014-06-15 16:02:22620 SdchManager* sdch_manager = request()->context()->sdch_manager();
621
[email protected]c7bef94c2011-06-21 18:05:51622 // Supply Accept-Encoding field only if it is not already provided.
623 // It should be provided IF the content is known to have restrictions on
624 // potential encoding, such as streaming multi-media.
625 // For details see bug 47381.
626 // TODO(jar, enal): jpeg files etc. should set up a request header if
627 // possible. Right now it is done only by buffered_resource_loader and
628 // simple_data_source.
629 if (!request_info_.extra_headers.HasHeader(
630 HttpRequestHeaders::kAcceptEncoding)) {
baranovichc5e38652014-11-14 03:08:15631 // We don't support SDCH responses to POST as there is a possibility
632 // of having SDCH encoded responses returned (e.g. by the cache)
633 // which we cannot decode, and in those situations, we will need
634 // to retransmit the request without SDCH, which is illegal for a POST.
635 bool advertise_sdch = sdch_manager != NULL && request()->method() != "POST";
636 if (advertise_sdch) {
637 SdchProblemCode rv = sdch_manager->IsInSupportedDomain(request()->url());
638 if (rv != SDCH_OK) {
639 advertise_sdch = false;
ellyjones085ac462015-08-18 12:02:53640 SdchManager::SdchErrorRecovery(rv);
641 request()->net_log().AddEvent(
642 NetLog::TYPE_SDCH_DECODING_ERROR,
643 base::Bind(&NetLogSdchResourceProblemCallback, rv));
baranovichc5e38652014-11-14 03:08:15644 }
645 }
[email protected]c7bef94c2011-06-21 18:05:51646 if (advertise_sdch) {
rdsmith81f607562014-11-21 18:35:16647 dictionaries_advertised_ =
648 sdch_manager->GetDictionarySet(request_->url());
649 }
[email protected]5b90b5d2009-04-30 23:06:01650
rdsmith81f607562014-11-21 18:35:16651 // The AllowLatencyExperiment() is only true if we've successfully done a
652 // full SDCH compression recently in this browser session for this host.
653 // Note that for this path, there might be no applicable dictionaries,
654 // and hence we can't participate in the experiment.
655 if (dictionaries_advertised_ &&
656 sdch_manager->AllowLatencyExperiment(request_->url())) {
657 // We are participating in the test (or control), and hence we'll
658 // eventually record statistics via either SDCH_EXPERIMENT_DECODE or
659 // SDCH_EXPERIMENT_HOLDBACK, and we'll need some packet timing data.
660 packet_timing_enabled_ = true;
661 if (base::RandDouble() < .01) {
662 sdch_test_control_ = true; // 1% probability.
663 dictionaries_advertised_.reset();
664 advertise_sdch = false;
665 } else {
666 sdch_test_activated_ = true;
[email protected]5b90b5d2009-04-30 23:06:01667 }
668 }
[email protected]5b90b5d2009-04-30 23:06:01669
eustasfbec9132015-12-30 14:56:51670 // Advertise "br" encoding only if transferred data is opaque to proxy.
671 bool advertise_brotli = false;
672 const HttpNetworkSession::Params* network_session_params =
673 request()->context()->GetNetworkSessionParams();
674 if (network_session_params && network_session_params->enable_brotli)
675 advertise_brotli = request()->url().SchemeIsCryptographic();
676
[email protected]c7bef94c2011-06-21 18:05:51677 // Supply Accept-Encoding headers first so that it is more likely that they
rdsmith81f607562014-11-21 18:35:16678 // will be in the first transmitted packet. This can sometimes make it
[email protected]c7bef94c2011-06-21 18:05:51679 // easier to filter and analyze the streams to assure that a proxy has not
rdsmith81f607562014-11-21 18:35:16680 // damaged these headers. Some proxies deliberately corrupt Accept-Encoding
[email protected]c7bef94c2011-06-21 18:05:51681 // headers.
eustasfbec9132015-12-30 14:56:51682 std::string advertised_encodings = "gzip, deflate";
683 if (advertise_sdch)
684 advertised_encodings += ", sdch";
685 if (advertise_brotli)
686 advertised_encodings += ", br";
687 // Tell the server what compression formats are supported.
688 request_info_.extra_headers.SetHeader(HttpRequestHeaders::kAcceptEncoding,
689 advertised_encodings);
690
691 if (dictionaries_advertised_) {
[email protected]8c76ae22010-04-20 22:15:43692 request_info_.extra_headers.SetHeader(
eustasfbec9132015-12-30 14:56:51693 kAvailDictionaryHeader,
694 dictionaries_advertised_->GetDictionaryClientHashList());
695 // Since we're tagging this transaction as advertising a dictionary,
696 // we'll definitely employ an SDCH filter (or tentative sdch filter)
697 // when we get a response. When done, we'll record histograms via
698 // SDCH_DECODE or SDCH_PASSTHROUGH. Hence we need to record packet
699 // arrival times.
700 packet_timing_enabled_ = true;
[email protected]423041b2008-10-27 17:39:28701 }
[email protected]423041b2008-10-27 17:39:28702 }
703
[email protected]ee4c30d2012-11-07 15:08:43704 if (http_user_agent_settings_) {
[email protected]84f05432013-03-15 01:00:12705 // Only add default Accept-Language if the request didn't have it
706 // specified.
[email protected]ee4c30d2012-11-07 15:08:43707 std::string accept_language =
708 http_user_agent_settings_->GetAcceptLanguage();
709 if (!accept_language.empty()) {
710 request_info_.extra_headers.SetHeaderIfMissing(
711 HttpRequestHeaders::kAcceptLanguage,
712 accept_language);
713 }
initial.commit586acc5fe2008-07-26 22:42:52714 }
initial.commit586acc5fe2008-07-26 22:42:52715}
716
[email protected]34602282010-02-03 22:14:15717void URLRequestHttpJob::AddCookieHeaderAndStart() {
[email protected]ed24fad2011-05-10 22:44:01718 // If the request was destroyed, then there is no more work to do.
719 if (!request_)
720 return;
[email protected]34602282010-02-03 22:14:15721
davidben151423e2015-03-23 18:48:36722 CookieStore* cookie_store = request_->context()->cookie_store();
[email protected]1a6fff52011-10-20 21:00:16723 if (cookie_store && !(request_info_.load_flags & LOAD_DO_NOT_SEND_COOKIES)) {
mkwste3e95992016-02-23 17:45:41724 CookieOptions options;
725 options.set_include_httponly();
726
727 // TODO(mkwst): If same-site cookies aren't enabled, pretend the request is
728 // same-site regardless, in order to include all cookies. Drop this check
729 // once we decide whether or not we're shipping this feature:
730 // https://crbug.com/459154
731 url::Origin requested_origin(request_->url());
732 if (!network_delegate() ||
733 !network_delegate()->AreExperimentalCookieFeaturesEnabled()) {
734 options.set_include_same_site();
735 } else if (requested_origin.IsSameOriginWith(
736 url::Origin(request_->first_party_for_cookies())) &&
737 (IsMethodSafe(request_->method()) ||
738 requested_origin.IsSameOriginWith(request_->initiator()))) {
739 options.set_include_same_site();
740 }
741
742 cookie_store->GetCookieListWithOptionsAsync(
743 request_->url(), options,
744 base::Bind(&URLRequestHttpJob::SetCookieHeaderAndStart,
[email protected]dc8313a2014-03-24 21:38:14745 weak_factory_.GetWeakPtr()));
[email protected]03d845f2011-07-29 19:06:26746 } else {
747 DoStartTransaction();
748 }
749}
750
mkwste3e95992016-02-23 17:45:41751void URLRequestHttpJob::SetCookieHeaderAndStart(const CookieList& cookie_list) {
752 if (cookie_list.size() && CanGetCookies(cookie_list)) {
[email protected]54f4c9362011-07-25 21:54:46753 request_info_.extra_headers.SetHeader(
mkwste3e95992016-02-23 17:45:41754 HttpRequestHeaders::kCookie, CookieStore::BuildCookieLine(cookie_list));
[email protected]e6d017652013-05-17 18:01:40755 // Disable privacy mode as we are sending cookies anyway.
[email protected]314b03992014-04-01 01:28:53756 request_info_.privacy_mode = PRIVACY_MODE_DISABLED;
[email protected]54f4c9362011-07-25 21:54:46757 }
[email protected]54f4c9362011-07-25 21:54:46758 DoStartTransaction();
759}
760
761void URLRequestHttpJob::DoStartTransaction() {
[email protected]03d845f2011-07-29 19:06:26762 // We may have been canceled while retrieving cookies.
[email protected]9025016c2011-05-12 15:51:23763 if (GetStatus().is_success()) {
764 StartTransaction();
765 } else {
766 NotifyCanceled();
767 }
[email protected]0757e7702009-03-27 04:00:22768}
769
[email protected]ea8141e2011-10-05 13:12:51770void URLRequestHttpJob::SaveCookiesAndNotifyHeadersComplete(int result) {
[email protected]abe1c4a2013-10-25 19:28:51771 // End of the call started in OnStartCompleted.
772 OnCallToDelegateComplete();
773
ttuttle859dc7a2015-04-23 19:42:29774 if (result != OK) {
[email protected]55b8a6c12012-06-13 22:03:42775 std::string source("delegate");
[email protected]ea8141e2011-10-05 13:12:51776 request_->net_log().AddEvent(NetLog::TYPE_CANCELLED,
[email protected]55b8a6c12012-06-13 22:03:42777 NetLog::StringCallback("source", &source));
[email protected]ea8141e2011-10-05 13:12:51778 NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, result));
779 return;
780 }
781
mmenke54e82af2016-02-16 23:06:30782 std::vector<std::string> response_cookies;
783 FetchResponseCookies(&response_cookies);
initial.commit586acc5fe2008-07-26 22:42:52784
mmenke54e82af2016-02-16 23:06:30785 base::Time response_date;
786 if (!GetResponseHeaders()->GetDateValue(&response_date))
787 response_date = base::Time();
[email protected]263163f2012-06-14 22:40:34788
789 if (!(request_info_.load_flags & LOAD_DO_NOT_SAVE_COOKIES) &&
mmenke54e82af2016-02-16 23:06:30790 request_->context()->cookie_store()) {
[email protected]263163f2012-06-14 22:40:34791 CookieOptions options;
792 options.set_include_httponly();
mmenke54e82af2016-02-16 23:06:30793 options.set_server_time(response_date);
jww79aceda2015-12-07 01:56:34794
estarkf1dc4442015-12-01 19:31:15795 if (network_delegate() &&
jww79aceda2015-12-07 01:56:34796 network_delegate()->AreStrictSecureCookiesEnabled()) {
797 options.set_enforce_strict_secure();
798 }
799
mmenke54e82af2016-02-16 23:06:30800 // Set all cookies, without waiting for them to be set. Any subsequent read
801 // will see the combined result of all cookie operation.
802 for (const std::string& cookie : response_cookies) {
803 if (!CanSetCookie(cookie, &options))
804 continue;
805 request_->context()->cookie_store()->SetCookieWithOptionsAsync(
806 request_->url(), cookie, options, CookieStore::SetCookiesCallback());
[email protected]263163f2012-06-14 22:40:34807 }
808 }
809
mmenke54e82af2016-02-16 23:06:30810 NotifyHeadersComplete();
[email protected]34602282010-02-03 22:14:15811}
812
813void URLRequestHttpJob::FetchResponseCookies(
[email protected]34602282010-02-03 22:14:15814 std::vector<std::string>* cookies) {
[email protected]264300242011-11-07 06:03:30815 const std::string name = "Set-Cookie";
initial.commit586acc5fe2008-07-26 22:42:52816 std::string value;
817
olli.raulaee489a52016-01-25 08:37:10818 size_t iter = 0;
[email protected]ea8141e2011-10-05 13:12:51819 HttpResponseHeaders* headers = GetResponseHeaders();
820 while (headers->EnumerateHeader(&iter, name, &value)) {
[email protected]2adf2882010-09-27 08:30:37821 if (!value.empty())
822 cookies->push_back(value);
823 }
initial.commit586acc5fe2008-07-26 22:42:52824}
[email protected]a9cea7542009-05-20 04:30:23825
xunjieli3bb781a2015-07-22 22:40:34826void URLRequestHttpJob::ProcessBackoffHeader() {
827 DCHECK(response_info_);
828
829 if (!backoff_manager_)
830 return;
831
832 TransportSecurityState* security_state =
833 request_->context()->transport_security_state();
834 const SSLInfo& ssl_info = response_info_->ssl_info;
835
836 // Only accept Backoff headers on HTTPS connections that have no
837 // certificate errors.
838 if (!ssl_info.is_valid() || IsCertStatusError(ssl_info.cert_status) ||
839 !security_state)
840 return;
841
842 backoff_manager_->UpdateWithResponse(request()->url(), GetResponseHeaders(),
843 base::Time::Now());
844}
845
[email protected]000d9df02012-01-18 20:01:46846// NOTE: |ProcessStrictTransportSecurityHeader| and
847// |ProcessPublicKeyPinsHeader| have very similar structures, by design.
[email protected]77f6fb432009-09-05 14:21:09848void URLRequestHttpJob::ProcessStrictTransportSecurityHeader() {
[email protected]a9cea7542009-05-20 04:30:23849 DCHECK(response_info_);
[email protected]6ed72be2013-01-08 22:07:33850 TransportSecurityState* security_state =
851 request_->context()->transport_security_state();
[email protected]e88006f2012-01-11 06:15:07852 const SSLInfo& ssl_info = response_info_->ssl_info;
[email protected]a9cea7542009-05-20 04:30:23853
[email protected]6ed72be2013-01-08 22:07:33854 // Only accept HSTS headers on HTTPS connections that have no
855 // certificate errors.
[email protected]e88006f2012-01-11 06:15:07856 if (!ssl_info.is_valid() || IsCertStatusError(ssl_info.cert_status) ||
[email protected]6ed72be2013-01-08 22:07:33857 !security_state)
[email protected]e88006f2012-01-11 06:15:07858 return;
[email protected]326e6792009-12-11 21:04:42859
estarka5da76702015-04-09 04:00:16860 // Don't accept HSTS headers when the hostname is an IP address.
861 if (request_info_.url.HostIsIPAddress())
862 return;
863
[email protected]242d8562012-10-30 21:20:46864 // http://tools.ietf.org/html/draft-ietf-websec-strict-transport-sec:
865 //
866 // If a UA receives more than one STS header field in a HTTP response
867 // message over secure transport, then the UA MUST process only the
868 // first such header field.
[email protected]6ed72be2013-01-08 22:07:33869 HttpResponseHeaders* headers = GetResponseHeaders();
870 std::string value;
olli.raulaee489a52016-01-25 08:37:10871 if (headers->EnumerateHeader(nullptr, "Strict-Transport-Security", &value))
[email protected]6ed72be2013-01-08 22:07:33872 security_state->AddHSTSHeader(request_info_.url.host(), value);
[email protected]a9cea7542009-05-20 04:30:23873}
[email protected]4f5656c62010-12-13 10:47:09874
[email protected]fecef222012-01-05 02:26:15875void URLRequestHttpJob::ProcessPublicKeyPinsHeader() {
876 DCHECK(response_info_);
[email protected]6ed72be2013-01-08 22:07:33877 TransportSecurityState* security_state =
878 request_->context()->transport_security_state();
[email protected]fecef222012-01-05 02:26:15879 const SSLInfo& ssl_info = response_info_->ssl_info;
880
[email protected]6ed72be2013-01-08 22:07:33881 // Only accept HPKP headers on HTTPS connections that have no
[email protected]e88006f2012-01-11 06:15:07882 // certificate errors.
[email protected]fecef222012-01-05 02:26:15883 if (!ssl_info.is_valid() || IsCertStatusError(ssl_info.cert_status) ||
[email protected]6ed72be2013-01-08 22:07:33884 !security_state)
[email protected]fecef222012-01-05 02:26:15885 return;
[email protected]fecef222012-01-05 02:26:15886
estarka5da76702015-04-09 04:00:16887 // Don't accept HSTS headers when the hostname is an IP address.
888 if (request_info_.url.HostIsIPAddress())
889 return;
890
estark53fee7c2015-08-03 18:31:51891 // http://tools.ietf.org/html/rfc7469:
[email protected]6ed72be2013-01-08 22:07:33892 //
893 // If a UA receives more than one PKP header field in an HTTP
894 // response message over secure transport, then the UA MUST process
895 // only the first such header field.
[email protected]fecef222012-01-05 02:26:15896 HttpResponseHeaders* headers = GetResponseHeaders();
[email protected]fecef222012-01-05 02:26:15897 std::string value;
estark53fee7c2015-08-03 18:31:51898 if (headers->EnumerateHeader(nullptr, "Public-Key-Pins", &value))
[email protected]6ed72be2013-01-08 22:07:33899 security_state->AddHPKPHeader(request_info_.url.host(), value, ssl_info);
estark53fee7c2015-08-03 18:31:51900 if (headers->EnumerateHeader(nullptr, "Public-Key-Pins-Report-Only",
901 &value)) {
902 security_state->ProcessHPKPReportOnlyHeader(
903 value, HostPortPair::FromURL(request_info_.url), ssl_info);
904 }
[email protected]fecef222012-01-05 02:26:15905}
906
[email protected]5394e422011-01-20 22:07:43907void URLRequestHttpJob::OnStartCompleted(int result) {
[email protected]ec23f522011-02-22 21:01:38908 RecordTimer();
909
[email protected]5394e422011-01-20 22:07:43910 // If the request was destroyed, then there is no more work to do.
[email protected]a83dd332011-07-13 10:41:01911 if (!request_)
[email protected]5394e422011-01-20 22:07:43912 return;
913
[email protected]80abdad2014-03-15 00:20:54914 // If the job is done (due to cancellation), can just ignore this
915 // notification.
916 if (done_)
[email protected]5394e422011-01-20 22:07:43917 return;
918
[email protected]3b23a222013-05-15 21:33:25919 receive_headers_end_ = base::TimeTicks::Now();
920
[email protected]ef2bf422012-05-11 03:27:09921 const URLRequestContext* context = request_->context();
922
[email protected]5394e422011-01-20 22:07:43923 if (result == OK) {
[email protected]d8fc4722014-06-13 13:17:15924 if (transaction_ && transaction_->GetResponseInfo()) {
925 SetProxyServer(transaction_->GetResponseInfo()->proxy_server);
926 }
[email protected]ea8141e2011-10-05 13:12:51927 scoped_refptr<HttpResponseHeaders> headers = GetResponseHeaders();
hiroshigecb76caa4c52015-12-22 07:50:25928
929 if (headers) {
olli.raula33c282f2016-01-21 12:12:49930 size_t iter = 0;
hiroshigecb76caa4c52015-12-22 07:50:25931 std::string name;
932 std::string value;
933 bool invalid_header_values_in_rfc7230 = false;
934 while (headers->EnumerateHeaderLines(&iter, &name, &value)) {
935 if (!HttpUtil::IsValidHeaderValueRFC7230(value)) {
936 invalid_header_values_in_rfc7230 = true;
937 break;
938 }
939 }
940 UMA_HISTOGRAM_BOOLEAN(
941 "Net.HttpResponse.ContainsInvalidHeaderValuesInRFC7230",
942 invalid_header_values_in_rfc7230);
943 }
944
[email protected]cc05edc2013-03-08 18:04:41945 if (network_delegate()) {
[email protected]ea8141e2011-10-05 13:12:51946 // Note that |this| may not be deleted until
947 // |on_headers_received_callback_| or
948 // |NetworkDelegate::URLRequestDestroyed()| has been called.
[email protected]abe1c4a2013-10-25 19:28:51949 OnCallToDelegate();
[email protected]5f714132014-03-26 10:41:16950 allowed_unsafe_redirect_url_ = GURL();
[email protected]cc05edc2013-03-08 18:04:41951 int error = network_delegate()->NotifyHeadersReceived(
[email protected]90499482013-06-01 00:39:50952 request_,
953 on_headers_received_callback_,
954 headers.get(),
[email protected]5f714132014-03-26 10:41:16955 &override_response_headers_,
956 &allowed_unsafe_redirect_url_);
ttuttle859dc7a2015-04-23 19:42:29957 if (error != OK) {
958 if (error == ERR_IO_PENDING) {
[email protected]ea8141e2011-10-05 13:12:51959 awaiting_callback_ = true;
[email protected]ea8141e2011-10-05 13:12:51960 } else {
[email protected]55b8a6c12012-06-13 22:03:42961 std::string source("delegate");
[email protected]ea8141e2011-10-05 13:12:51962 request_->net_log().AddEvent(NetLog::TYPE_CANCELLED,
[email protected]55b8a6c12012-06-13 22:03:42963 NetLog::StringCallback("source",
964 &source));
[email protected]abe1c4a2013-10-25 19:28:51965 OnCallToDelegateComplete();
[email protected]ea8141e2011-10-05 13:12:51966 NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, error));
967 }
968 return;
969 }
970 }
nharper5babb5e62016-03-09 18:58:07971 LogChannelIDAndCookieStores(request_->context(),
972 transaction_->GetResponseInfo()->ssl_info);
[email protected]ea8141e2011-10-05 13:12:51973
ttuttle859dc7a2015-04-23 19:42:29974 SaveCookiesAndNotifyHeadersComplete(OK);
[email protected]e5624f02011-09-27 19:43:53975 } else if (IsCertificateError(result)) {
[email protected]6061c142013-10-21 15:13:34976 // We encountered an SSL certificate error.
977 if (result == ERR_SSL_WEAK_SERVER_EPHEMERAL_DH_KEY ||
978 result == ERR_SSL_PINNED_KEY_NOT_IN_CERT_CHAIN) {
979 // These are hard failures. They're handled separately and don't have
980 // the correct cert status, so set it here.
981 SSLInfo info(transaction_->GetResponseInfo()->ssl_info);
982 info.cert_status = MapNetErrorToCertStatus(result);
983 NotifySSLCertificateError(info, true);
984 } else {
985 // Maybe overridable, maybe not. Ask the delegate to decide.
[email protected]9e6968d2014-05-07 21:46:26986 TransportSecurityState* state = context->transport_security_state();
987 const bool fatal =
Adam Langley5cbb7d7a2014-09-25 23:14:12988 state && state->ShouldSSLErrorsBeFatal(request_info_.url.host());
[email protected]6061c142013-10-21 15:13:34989 NotifySSLCertificateError(
990 transaction_->GetResponseInfo()->ssl_info, fatal);
991 }
[email protected]5394e422011-01-20 22:07:43992 } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
[email protected]a83dd332011-07-13 10:41:01993 NotifyCertificateRequested(
[email protected]90499482013-06-01 00:39:50994 transaction_->GetResponseInfo()->cert_request_info.get());
[email protected]5394e422011-01-20 22:07:43995 } else {
[email protected]419704c2014-01-14 11:18:06996 // Even on an error, there may be useful information in the response
997 // info (e.g. whether there's a cached copy).
998 if (transaction_.get())
999 response_info_ = transaction_->GetResponseInfo();
[email protected]5394e422011-01-20 22:07:431000 NotifyStartError(URLRequestStatus(URLRequestStatus::FAILED, result));
1001 }
1002}
1003
[email protected]ea8141e2011-10-05 13:12:511004void URLRequestHttpJob::OnHeadersReceivedCallback(int result) {
[email protected]ea8141e2011-10-05 13:12:511005 awaiting_callback_ = false;
[email protected]9045b8822012-01-13 20:35:351006
1007 // Check that there are no callbacks to already canceled requests.
1008 DCHECK_NE(URLRequestStatus::CANCELED, GetStatus().status());
1009
[email protected]ea8141e2011-10-05 13:12:511010 SaveCookiesAndNotifyHeadersComplete(result);
1011}
1012
[email protected]5394e422011-01-20 22:07:431013void URLRequestHttpJob::OnReadCompleted(int result) {
1014 read_in_progress_ = false;
1015
xunjieli26ede962015-11-23 19:39:131016 DCHECK_NE(ERR_IO_PENDING, result);
1017
[email protected]f001bd6a2011-12-08 04:31:371018 if (ShouldFixMismatchedContentLength(result))
[email protected]5543cbb2012-04-20 16:35:231019 result = OK;
[email protected]f001bd6a2011-12-08 04:31:371020
xunjieli26ede962015-11-23 19:39:131021 // EOF or error, done with this job.
1022 if (result <= 0)
1023 DoneWithRequest(FINISHED);
[email protected]5394e422011-01-20 22:07:431024
xunjieli26ede962015-11-23 19:39:131025 ReadRawDataComplete(result);
[email protected]5394e422011-01-20 22:07:431026}
1027
[email protected]5394e422011-01-20 22:07:431028void URLRequestHttpJob::RestartTransactionWithAuth(
[email protected]f3cf9802011-10-28 18:44:581029 const AuthCredentials& credentials) {
1030 auth_credentials_ = credentials;
[email protected]5394e422011-01-20 22:07:431031
1032 // These will be reset in OnStartCompleted.
1033 response_info_ = NULL;
[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
1043 AddCookieHeaderAndStart();
1044}
1045
[email protected]0736d9e2012-11-28 19:50:401046void URLRequestHttpJob::SetUpload(UploadDataStream* upload) {
[email protected]5394e422011-01-20 22:07:431047 DCHECK(!transaction_.get()) << "cannot change once started";
[email protected]0736d9e2012-11-28 19:50:401048 request_info_.upload_data_stream = upload;
[email protected]5394e422011-01-20 22:07:431049}
1050
1051void URLRequestHttpJob::SetExtraRequestHeaders(
1052 const HttpRequestHeaders& headers) {
1053 DCHECK(!transaction_.get()) << "cannot change once started";
1054 request_info_.extra_headers.CopyFrom(headers);
1055}
1056
[email protected]5394e422011-01-20 22:07:431057LoadState URLRequestHttpJob::GetLoadState() const {
1058 return transaction_.get() ?
1059 transaction_->GetLoadState() : LOAD_STATE_IDLE;
1060}
1061
[email protected]7335ab02012-08-30 22:30:421062UploadProgress URLRequestHttpJob::GetUploadProgress() const {
1063 return transaction_.get() ?
1064 transaction_->GetUploadProgress() : UploadProgress();
[email protected]5394e422011-01-20 22:07:431065}
1066
1067bool URLRequestHttpJob::GetMimeType(std::string* mime_type) const {
1068 DCHECK(transaction_.get());
1069
1070 if (!response_info_)
1071 return false;
1072
ellyjones0e9d5e82015-02-17 23:06:281073 HttpResponseHeaders* headers = GetResponseHeaders();
1074 if (!headers)
1075 return false;
1076 return headers->GetMimeType(mime_type);
[email protected]5394e422011-01-20 22:07:431077}
1078
1079bool URLRequestHttpJob::GetCharset(std::string* charset) {
1080 DCHECK(transaction_.get());
1081
1082 if (!response_info_)
1083 return false;
1084
[email protected]ea8141e2011-10-05 13:12:511085 return GetResponseHeaders()->GetCharset(charset);
[email protected]5394e422011-01-20 22:07:431086}
1087
1088void URLRequestHttpJob::GetResponseInfo(HttpResponseInfo* info) {
1089 DCHECK(request_);
[email protected]5394e422011-01-20 22:07:431090
[email protected]ea8141e2011-10-05 13:12:511091 if (response_info_) {
[email protected]419704c2014-01-14 11:18:061092 DCHECK(transaction_.get());
1093
[email protected]5394e422011-01-20 22:07:431094 *info = *response_info_;
[email protected]90499482013-06-01 00:39:501095 if (override_response_headers_.get())
[email protected]ea8141e2011-10-05 13:12:511096 info->headers = override_response_headers_;
1097 }
[email protected]5394e422011-01-20 22:07:431098}
1099
[email protected]58e32bb2013-01-21 18:23:251100void URLRequestHttpJob::GetLoadTimingInfo(
1101 LoadTimingInfo* load_timing_info) const {
[email protected]3b23a222013-05-15 21:33:251102 // If haven't made it far enough to receive any headers, don't return
rdsmith81f607562014-11-21 18:35:161103 // anything. This makes for more consistent behavior in the case of errors.
[email protected]3b23a222013-05-15 21:33:251104 if (!transaction_ || receive_headers_end_.is_null())
1105 return;
1106 if (transaction_->GetLoadTimingInfo(load_timing_info))
1107 load_timing_info->receive_headers_end = receive_headers_end_;
[email protected]58e32bb2013-01-21 18:23:251108}
1109
ttuttled9dbc652015-09-29 20:00:591110bool URLRequestHttpJob::GetRemoteEndpoint(IPEndPoint* endpoint) const {
1111 if (!transaction_)
1112 return false;
1113
1114 return transaction_->GetRemoteEndpoint(endpoint);
1115}
1116
[email protected]ea8141e2011-10-05 13:12:511117bool URLRequestHttpJob::GetResponseCookies(std::vector<std::string>* cookies) {
[email protected]5394e422011-01-20 22:07:431118 DCHECK(transaction_.get());
1119
1120 if (!response_info_)
1121 return false;
1122
[email protected]5394e422011-01-20 22:07:431123 cookies->clear();
[email protected]ea8141e2011-10-05 13:12:511124 FetchResponseCookies(cookies);
[email protected]5394e422011-01-20 22:07:431125 return true;
1126}
1127
1128int URLRequestHttpJob::GetResponseCode() const {
1129 DCHECK(transaction_.get());
1130
1131 if (!response_info_)
1132 return -1;
1133
[email protected]ea8141e2011-10-05 13:12:511134 return GetResponseHeaders()->response_code();
[email protected]5394e422011-01-20 22:07:431135}
1136
zhongyi48704c182015-12-07 07:52:021137void URLRequestHttpJob::PopulateNetErrorDetails(
1138 NetErrorDetails* details) const {
1139 if (!transaction_)
1140 return;
1141 return transaction_->PopulateNetErrorDetails(details);
1142}
1143
[email protected]5a3b4d32011-03-17 01:24:051144Filter* URLRequestHttpJob::SetupFilter() const {
[email protected]5394e422011-01-20 22:07:431145 DCHECK(transaction_.get());
1146 if (!response_info_)
[email protected]5a3b4d32011-03-17 01:24:051147 return NULL;
[email protected]5394e422011-01-20 22:07:431148
[email protected]5a3b4d32011-03-17 01:24:051149 std::vector<Filter::FilterType> encoding_types;
[email protected]5394e422011-01-20 22:07:431150 std::string encoding_type;
[email protected]ea8141e2011-10-05 13:12:511151 HttpResponseHeaders* headers = GetResponseHeaders();
olli.raulaee489a52016-01-25 08:37:101152 size_t iter = 0;
[email protected]ea8141e2011-10-05 13:12:511153 while (headers->EnumerateHeader(&iter, "Content-Encoding", &encoding_type)) {
[email protected]5a3b4d32011-03-17 01:24:051154 encoding_types.push_back(Filter::ConvertEncodingToType(encoding_type));
[email protected]5394e422011-01-20 22:07:431155 }
1156
1157 // Even if encoding types are empty, there is a chance that we need to add
1158 // some decoding, as some proxies strip encoding completely. In such cases,
1159 // we may need to add (for example) SDCH filtering (when the context suggests
1160 // it is appropriate).
[email protected]2e92354c2011-03-25 20:49:531161 Filter::FixupEncodingTypes(*filter_context_, &encoding_types);
[email protected]5394e422011-01-20 22:07:431162
[email protected]5a3b4d32011-03-17 01:24:051163 return !encoding_types.empty()
[email protected]2e92354c2011-03-25 20:49:531164 ? Filter::Factory(encoding_types, *filter_context_) : NULL;
[email protected]5394e422011-01-20 22:07:431165}
1166
[email protected]f878230e2014-04-03 15:36:141167bool URLRequestHttpJob::CopyFragmentOnRedirect(const GURL& location) const {
1168 // Allow modification of reference fragments by default, unless
1169 // |allowed_unsafe_redirect_url_| is set and equal to the redirect URL.
1170 // When this is the case, we assume that the network delegate has set the
1171 // desired redirect URL (with or without fragment), so it must not be changed
1172 // any more.
1173 return !allowed_unsafe_redirect_url_.is_valid() ||
1174 allowed_unsafe_redirect_url_ != location;
1175}
1176
[email protected]5394e422011-01-20 22:07:431177bool URLRequestHttpJob::IsSafeRedirect(const GURL& location) {
[email protected]e0f35c92013-05-08 16:04:341178 // HTTP is always safe.
1179 // TODO(pauljensen): Remove once crbug.com/146591 is fixed.
1180 if (location.is_valid() &&
1181 (location.scheme() == "http" || location.scheme() == "https")) {
[email protected]5394e422011-01-20 22:07:431182 return true;
[email protected]5394e422011-01-20 22:07:431183 }
[email protected]f878230e2014-04-03 15:36:141184 // Delegates may mark a URL as safe for redirection.
1185 if (allowed_unsafe_redirect_url_.is_valid() &&
1186 allowed_unsafe_redirect_url_ == location) {
1187 return true;
[email protected]5f714132014-03-26 10:41:161188 }
[email protected]e0f35c92013-05-08 16:04:341189 // Query URLRequestJobFactory as to whether |location| would be safe to
1190 // redirect to.
1191 return request_->context()->job_factory() &&
1192 request_->context()->job_factory()->IsSafeRedirectTarget(location);
[email protected]5394e422011-01-20 22:07:431193}
1194
1195bool URLRequestHttpJob::NeedsAuth() {
1196 int code = GetResponseCode();
1197 if (code == -1)
1198 return false;
1199
rdsmith81f607562014-11-21 18:35:161200 // Check if we need either Proxy or WWW Authentication. This could happen
[email protected]5394e422011-01-20 22:07:431201 // because we either provided no auth info, or provided incorrect info.
1202 switch (code) {
1203 case 407:
1204 if (proxy_auth_state_ == AUTH_STATE_CANCELED)
1205 return false;
1206 proxy_auth_state_ = AUTH_STATE_NEED_AUTH;
1207 return true;
1208 case 401:
1209 if (server_auth_state_ == AUTH_STATE_CANCELED)
1210 return false;
1211 server_auth_state_ = AUTH_STATE_NEED_AUTH;
1212 return true;
1213 }
1214 return false;
1215}
1216
1217void URLRequestHttpJob::GetAuthChallengeInfo(
1218 scoped_refptr<AuthChallengeInfo>* result) {
1219 DCHECK(transaction_.get());
1220 DCHECK(response_info_);
1221
1222 // sanity checks:
1223 DCHECK(proxy_auth_state_ == AUTH_STATE_NEED_AUTH ||
1224 server_auth_state_ == AUTH_STATE_NEED_AUTH);
[email protected]9094b602012-02-27 21:44:581225 DCHECK((GetResponseHeaders()->response_code() == HTTP_UNAUTHORIZED) ||
1226 (GetResponseHeaders()->response_code() ==
1227 HTTP_PROXY_AUTHENTICATION_REQUIRED));
[email protected]5394e422011-01-20 22:07:431228
1229 *result = response_info_->auth_challenge;
1230}
1231
[email protected]f3cf9802011-10-28 18:44:581232void URLRequestHttpJob::SetAuth(const AuthCredentials& credentials) {
[email protected]5394e422011-01-20 22:07:431233 DCHECK(transaction_.get());
1234
1235 // Proxy gets set first, then WWW.
1236 if (proxy_auth_state_ == AUTH_STATE_NEED_AUTH) {
1237 proxy_auth_state_ = AUTH_STATE_HAVE_AUTH;
1238 } else {
[email protected]dd29bcd72011-03-24 00:03:441239 DCHECK_EQ(server_auth_state_, AUTH_STATE_NEED_AUTH);
[email protected]5394e422011-01-20 22:07:431240 server_auth_state_ = AUTH_STATE_HAVE_AUTH;
1241 }
1242
[email protected]f3cf9802011-10-28 18:44:581243 RestartTransactionWithAuth(credentials);
[email protected]5394e422011-01-20 22:07:431244}
1245
1246void URLRequestHttpJob::CancelAuth() {
1247 // Proxy gets set first, then WWW.
1248 if (proxy_auth_state_ == AUTH_STATE_NEED_AUTH) {
1249 proxy_auth_state_ = AUTH_STATE_CANCELED;
1250 } else {
[email protected]dd29bcd72011-03-24 00:03:441251 DCHECK_EQ(server_auth_state_, AUTH_STATE_NEED_AUTH);
[email protected]5394e422011-01-20 22:07:431252 server_auth_state_ = AUTH_STATE_CANCELED;
1253 }
1254
1255 // These will be reset in OnStartCompleted.
1256 response_info_ = NULL;
[email protected]3b23a222013-05-15 21:33:251257 receive_headers_end_ = base::TimeTicks::Now();
[email protected]5394e422011-01-20 22:07:431258
[email protected]ec23f522011-02-22 21:01:381259 ResetTimer();
1260
[email protected]5394e422011-01-20 22:07:431261 // OK, let the consumer read the error page...
1262 //
1263 // Because we set the AUTH_STATE_CANCELED flag, NeedsAuth will return false,
1264 // which will cause the consumer to receive OnResponseStarted instead of
1265 // OnAuthRequired.
1266 //
1267 // We have to do this via InvokeLater to avoid "recursing" the consumer.
1268 //
skyostil4891b25b2015-06-11 11:43:451269 base::ThreadTaskRunnerHandle::Get()->PostTask(
1270 FROM_HERE, base::Bind(&URLRequestHttpJob::OnStartCompleted,
1271 weak_factory_.GetWeakPtr(), OK));
[email protected]5394e422011-01-20 22:07:431272}
1273
1274void URLRequestHttpJob::ContinueWithCertificate(
svaldez7872fd02015-11-19 21:10:541275 X509Certificate* client_cert,
1276 SSLPrivateKey* client_private_key) {
[email protected]5394e422011-01-20 22:07:431277 DCHECK(transaction_.get());
1278
1279 DCHECK(!response_info_) << "should not have a response yet";
[email protected]3b23a222013-05-15 21:33:251280 receive_headers_end_ = base::TimeTicks();
[email protected]5394e422011-01-20 22:07:431281
[email protected]ec23f522011-02-22 21:01:381282 ResetTimer();
1283
svaldez7872fd02015-11-19 21:10:541284 int rv = transaction_->RestartWithCertificate(client_cert, client_private_key,
1285 start_callback_);
[email protected]5394e422011-01-20 22:07:431286 if (rv == ERR_IO_PENDING)
1287 return;
1288
1289 // The transaction started synchronously, but we need to notify the
1290 // URLRequest delegate via the message loop.
skyostil4891b25b2015-06-11 11:43:451291 base::ThreadTaskRunnerHandle::Get()->PostTask(
1292 FROM_HERE, base::Bind(&URLRequestHttpJob::OnStartCompleted,
1293 weak_factory_.GetWeakPtr(), rv));
[email protected]5394e422011-01-20 22:07:431294}
1295
1296void URLRequestHttpJob::ContinueDespiteLastError() {
1297 // If the transaction was destroyed, then the job was cancelled.
1298 if (!transaction_.get())
1299 return;
1300
1301 DCHECK(!response_info_) << "should not have a response yet";
[email protected]3b23a222013-05-15 21:33:251302 receive_headers_end_ = base::TimeTicks();
[email protected]5394e422011-01-20 22:07:431303
[email protected]ec23f522011-02-22 21:01:381304 ResetTimer();
1305
[email protected]49639fa2011-12-20 23:22:411306 int rv = transaction_->RestartIgnoringLastError(start_callback_);
[email protected]5394e422011-01-20 22:07:431307 if (rv == ERR_IO_PENDING)
1308 return;
1309
1310 // The transaction started synchronously, but we need to notify the
1311 // URLRequest delegate via the message loop.
skyostil4891b25b2015-06-11 11:43:451312 base::ThreadTaskRunnerHandle::Get()->PostTask(
1313 FROM_HERE, base::Bind(&URLRequestHttpJob::OnStartCompleted,
1314 weak_factory_.GetWeakPtr(), rv));
[email protected]5394e422011-01-20 22:07:431315}
1316
[email protected]1826a402014-01-08 15:40:481317void URLRequestHttpJob::ResumeNetworkStart() {
1318 DCHECK(transaction_.get());
1319 transaction_->ResumeNetworkStart();
1320}
1321
[email protected]f001bd6a2011-12-08 04:31:371322bool URLRequestHttpJob::ShouldFixMismatchedContentLength(int rv) const {
1323 // Some servers send the body compressed, but specify the content length as
rdsmith81f607562014-11-21 18:35:161324 // the uncompressed size. Although this violates the HTTP spec we want to
[email protected]f001bd6a2011-12-08 04:31:371325 // support it (as IE and FireFox do), but *only* for an exact match.
1326 // See http://crbug.com/79694.
ttuttle859dc7a2015-04-23 19:42:291327 if (rv == ERR_CONTENT_LENGTH_MISMATCH ||
1328 rv == ERR_INCOMPLETE_CHUNKED_ENCODING) {
[email protected]f001bd6a2011-12-08 04:31:371329 if (request_ && request_->response_headers()) {
Avi Drissman13fc8932015-12-20 04:40:461330 int64_t expected_length =
1331 request_->response_headers()->GetContentLength();
[email protected]f001bd6a2011-12-08 04:31:371332 VLOG(1) << __FUNCTION__ << "() "
1333 << "\"" << request_->url().spec() << "\""
1334 << " content-length = " << expected_length
1335 << " pre total = " << prefilter_bytes_read()
1336 << " post total = " << postfilter_bytes_read();
1337 if (postfilter_bytes_read() == expected_length) {
1338 // Clear the error.
1339 return true;
1340 }
1341 }
1342 }
1343 return false;
1344}
1345
xunjieli26ede962015-11-23 19:39:131346int URLRequestHttpJob::ReadRawData(IOBuffer* buf, int buf_size) {
[email protected]5394e422011-01-20 22:07:431347 DCHECK_NE(buf_size, 0);
[email protected]5394e422011-01-20 22:07:431348 DCHECK(!read_in_progress_);
1349
[email protected]49639fa2011-12-20 23:22:411350 int rv = transaction_->Read(
1351 buf, buf_size,
1352 base::Bind(&URLRequestHttpJob::OnReadCompleted, base::Unretained(this)));
[email protected]85c1dce2011-07-06 12:01:291353
[email protected]f001bd6a2011-12-08 04:31:371354 if (ShouldFixMismatchedContentLength(rv))
xunjieli26ede962015-11-23 19:39:131355 rv = OK;
[email protected]f001bd6a2011-12-08 04:31:371356
xunjieli26ede962015-11-23 19:39:131357 if (rv == 0 || (rv < 0 && rv != ERR_IO_PENDING))
1358 DoneWithRequest(FINISHED);
[email protected]5394e422011-01-20 22:07:431359
xunjieli26ede962015-11-23 19:39:131360 if (rv == ERR_IO_PENDING)
[email protected]5394e422011-01-20 22:07:431361 read_in_progress_ = true;
[email protected]5394e422011-01-20 22:07:431362
xunjieli26ede962015-11-23 19:39:131363 return rv;
[email protected]5394e422011-01-20 22:07:431364}
1365
1366void URLRequestHttpJob::StopCaching() {
1367 if (transaction_.get())
1368 transaction_->StopCaching();
1369}
1370
[email protected]79e1fd62013-06-20 06:50:041371bool URLRequestHttpJob::GetFullRequestHeaders(
1372 HttpRequestHeaders* headers) const {
1373 if (!transaction_)
1374 return false;
1375
1376 return transaction_->GetFullRequestHeaders(headers);
1377}
1378
Avi Drissman13fc8932015-12-20 04:40:461379int64_t URLRequestHttpJob::GetTotalReceivedBytes() const {
sclittlece72c482015-08-24 20:20:591380 int64_t total_received_bytes =
1381 total_received_bytes_from_previous_transactions_;
1382 if (transaction_)
1383 total_received_bytes += transaction_->GetTotalReceivedBytes();
1384 return total_received_bytes;
[email protected]71e5ff8f2014-01-13 09:44:041385}
1386
sclittlefb249892015-09-10 21:33:221387int64_t URLRequestHttpJob::GetTotalSentBytes() const {
1388 int64_t total_sent_bytes = total_sent_bytes_from_previous_transactions_;
1389 if (transaction_)
1390 total_sent_bytes += transaction_->GetTotalSentBytes();
1391 return total_sent_bytes;
1392}
1393
[email protected]5c04f722011-08-12 17:52:471394void URLRequestHttpJob::DoneReading() {
[email protected]e50efea2014-03-24 18:41:001395 if (transaction_) {
[email protected]5c04f722011-08-12 17:52:471396 transaction_->DoneReading();
[email protected]e50efea2014-03-24 18:41:001397 }
1398 DoneWithRequest(FINISHED);
1399}
1400
1401void URLRequestHttpJob::DoneReadingRedirectResponse() {
1402 if (transaction_) {
1403 if (transaction_->GetResponseInfo()->headers->IsRedirect(NULL)) {
1404 // If the original headers indicate a redirect, go ahead and cache the
1405 // response, even if the |override_response_headers_| are a redirect to
1406 // another location.
1407 transaction_->DoneReading();
1408 } else {
1409 // Otherwise, |override_response_headers_| must be non-NULL and contain
1410 // bogus headers indicating a redirect.
dchengc2e01e82014-08-27 00:24:421411 DCHECK(override_response_headers_.get());
[email protected]e50efea2014-03-24 18:41:001412 DCHECK(override_response_headers_->IsRedirect(NULL));
1413 transaction_->StopCaching();
1414 }
1415 }
[email protected]5c04f722011-08-12 17:52:471416 DoneWithRequest(FINISHED);
1417}
1418
[email protected]6d81b482011-02-22 19:47:191419HostPortPair URLRequestHttpJob::GetSocketAddress() const {
1420 return response_info_ ? response_info_->socket_address : HostPortPair();
1421}
1422
[email protected]ec23f522011-02-22 21:01:381423void URLRequestHttpJob::RecordTimer() {
1424 if (request_creation_time_.is_null()) {
1425 NOTREACHED()
1426 << "The same transaction shouldn't start twice without new timing.";
1427 return;
1428 }
1429
[email protected]320a29f12011-03-21 14:47:411430 base::TimeDelta to_start = base::Time::Now() - request_creation_time_;
[email protected]ec23f522011-02-22 21:01:381431 request_creation_time_ = base::Time();
[email protected]8684a8812011-03-22 13:59:381432
[email protected]5c68d692011-08-24 04:59:411433 UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpTimeToFirstByte", to_start);
[email protected]ec23f522011-02-22 21:01:381434}
1435
1436void URLRequestHttpJob::ResetTimer() {
1437 if (!request_creation_time_.is_null()) {
1438 NOTREACHED()
1439 << "The timer was reset before it was recorded.";
1440 return;
1441 }
1442 request_creation_time_ = base::Time::Now();
1443}
1444
[email protected]dd29bcd72011-03-24 00:03:441445void URLRequestHttpJob::UpdatePacketReadTimes() {
1446 if (!packet_timing_enabled_)
1447 return;
1448
mmenkebbf19be22015-04-11 02:44:481449 DCHECK_GT(prefilter_bytes_read(), bytes_observed_in_packets_);
[email protected]dd29bcd72011-03-24 00:03:441450
[email protected]006ce1a2014-07-30 14:41:231451 base::Time now(base::Time::Now());
[email protected]dd29bcd72011-03-24 00:03:441452 if (!bytes_observed_in_packets_)
[email protected]006ce1a2014-07-30 14:41:231453 request_time_snapshot_ = now;
1454 final_packet_time_ = now;
[email protected]dd29bcd72011-03-24 00:03:441455
mmenkebbf19be22015-04-11 02:44:481456 bytes_observed_in_packets_ = prefilter_bytes_read();
[email protected]dd29bcd72011-03-24 00:03:441457}
1458
1459void URLRequestHttpJob::RecordPacketStats(
1460 FilterContext::StatisticSelector statistic) const {
1461 if (!packet_timing_enabled_ || (final_packet_time_ == base::Time()))
1462 return;
1463
1464 base::TimeDelta duration = final_packet_time_ - request_time_snapshot_;
1465 switch (statistic) {
1466 case FilterContext::SDCH_DECODE: {
[email protected]dd29bcd72011-03-24 00:03:441467 UMA_HISTOGRAM_CUSTOM_COUNTS("Sdch3.Network_Decode_Bytes_Processed_b",
1468 static_cast<int>(bytes_observed_in_packets_), 500, 100000, 100);
[email protected]dd29bcd72011-03-24 00:03:441469 return;
1470 }
1471 case FilterContext::SDCH_PASSTHROUGH: {
1472 // Despite advertising a dictionary, we handled non-sdch compressed
1473 // content.
[email protected]dd29bcd72011-03-24 00:03:441474 return;
1475 }
1476
1477 case FilterContext::SDCH_EXPERIMENT_DECODE: {
[email protected]006ce1a2014-07-30 14:41:231478 UMA_HISTOGRAM_CUSTOM_TIMES("Sdch3.Experiment3_Decode",
[email protected]dd29bcd72011-03-24 00:03:441479 duration,
1480 base::TimeDelta::FromMilliseconds(20),
1481 base::TimeDelta::FromMinutes(10), 100);
[email protected]dd29bcd72011-03-24 00:03:441482 return;
1483 }
1484 case FilterContext::SDCH_EXPERIMENT_HOLDBACK: {
[email protected]006ce1a2014-07-30 14:41:231485 UMA_HISTOGRAM_CUSTOM_TIMES("Sdch3.Experiment3_Holdback",
[email protected]dd29bcd72011-03-24 00:03:441486 duration,
1487 base::TimeDelta::FromMilliseconds(20),
1488 base::TimeDelta::FromMinutes(10), 100);
[email protected]dd29bcd72011-03-24 00:03:441489 return;
1490 }
1491 default:
1492 NOTREACHED();
1493 return;
1494 }
1495}
1496
[email protected]bbaea8f2011-06-24 00:11:011497void URLRequestHttpJob::RecordPerfHistograms(CompletionCause reason) {
1498 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) {
1505 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeSuccess", total_time);
1506 } else {
1507 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeCancel", total_time);
1508 }
1509
[email protected]4b4d20242012-02-23 18:27:461510 if (response_info_) {
rtennetie55c4b72015-08-03 21:48:351511 // QUIC (by default) supports https scheme only, thus track https URLs only
1512 // for QUIC.
1513 bool is_https_google = request() && request()->url().SchemeIs("https") &&
1514 HasGoogleHost(request()->url());
rtenneti72928bb2015-04-28 18:28:131515 bool used_quic = response_info_->DidUseQuic();
rtennetie55c4b72015-08-03 21:48:351516 if (is_https_google) {
rtenneti72928bb2015-04-28 18:28:131517 if (used_quic) {
rtennetie55c4b72015-08-03 21:48:351518 UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpJob.TotalTime.Secure.Quic",
1519 total_time);
rtenneti72928bb2015-04-28 18:28:131520 } else {
rtennetie55c4b72015-08-03 21:48:351521 UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpJob.TotalTime.Secure.NotQuic",
1522 total_time);
rtenneti72928bb2015-04-28 18:28:131523 }
1524 }
[email protected]4b4d20242012-02-23 18:27:461525 if (response_info_->was_cached) {
1526 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeCached", total_time);
rtennetie55c4b72015-08-03 21:48:351527 if (is_https_google) {
rtenneti72928bb2015-04-28 18:28:131528 if (used_quic) {
rtennetie55c4b72015-08-03 21:48:351529 UMA_HISTOGRAM_MEDIUM_TIMES("Net.HttpJob.TotalTimeCached.Secure.Quic",
rtenneti72928bb2015-04-28 18:28:131530 total_time);
1531 } else {
rtennetie55c4b72015-08-03 21:48:351532 UMA_HISTOGRAM_MEDIUM_TIMES(
1533 "Net.HttpJob.TotalTimeCached.Secure.NotQuic", total_time);
rtenneti72928bb2015-04-28 18:28:131534 }
1535 }
[email protected]4b4d20242012-02-23 18:27:461536 } else {
1537 UMA_HISTOGRAM_TIMES("Net.HttpJob.TotalTimeNotCached", total_time);
rtennetie55c4b72015-08-03 21:48:351538 if (is_https_google) {
rtenneti72928bb2015-04-28 18:28:131539 if (used_quic) {
rtennetie55c4b72015-08-03 21:48:351540 UMA_HISTOGRAM_MEDIUM_TIMES(
1541 "Net.HttpJob.TotalTimeNotCached.Secure.Quic", total_time);
rtenneti72928bb2015-04-28 18:28:131542 } else {
rtennetie55c4b72015-08-03 21:48:351543 UMA_HISTOGRAM_MEDIUM_TIMES(
1544 "Net.HttpJob.TotalTimeNotCached.Secure.NotQuic", total_time);
rtenneti72928bb2015-04-28 18:28:131545 }
1546 }
[email protected]b73656ca2011-07-22 17:42:171547 }
[email protected]bbaea8f2011-06-24 00:11:011548 }
1549
[email protected]3ed84722013-11-01 17:17:071550 if (request_info_.load_flags & LOAD_PREFETCH && !request_->was_cached())
1551 UMA_HISTOGRAM_COUNTS("Net.Prefetch.PrefilterBytesReadFromNetwork",
1552 prefilter_bytes_read());
1553
[email protected]bbaea8f2011-06-24 00:11:011554 start_time_ = base::TimeTicks();
1555}
1556
1557void URLRequestHttpJob::DoneWithRequest(CompletionCause reason) {
1558 if (done_)
1559 return;
1560 done_ = true;
tbansal79ed5cd2015-08-10 18:53:561561
1562 // Notify NetworkQualityEstimator.
1563 if (request() && (reason == FINISHED || reason == ABORTED)) {
1564 NetworkQualityEstimator* network_quality_estimator =
1565 request()->context()->network_quality_estimator();
1566 if (network_quality_estimator)
1567 network_quality_estimator->NotifyRequestCompleted(*request());
1568 }
1569
[email protected]bbaea8f2011-06-24 00:11:011570 RecordPerfHistograms(reason);
kundajib8c0d102015-07-27 21:47:411571 if (request_)
[email protected]7a299a92012-10-24 23:54:501572 request_->set_received_response_content_length(prefilter_bytes_read());
[email protected]bbaea8f2011-06-24 00:11:011573}
1574
[email protected]ea8141e2011-10-05 13:12:511575HttpResponseHeaders* URLRequestHttpJob::GetResponseHeaders() const {
1576 DCHECK(transaction_.get());
1577 DCHECK(transaction_->GetResponseInfo());
1578 return override_response_headers_.get() ?
[email protected]90499482013-06-01 00:39:501579 override_response_headers_.get() :
1580 transaction_->GetResponseInfo()->headers.get();
[email protected]ea8141e2011-10-05 13:12:511581}
1582
1583void URLRequestHttpJob::NotifyURLRequestDestroyed() {
1584 awaiting_callback_ = false;
1585}
1586
[email protected]4f5656c62010-12-13 10:47:091587} // namespace net