blob: 6238b25d02db73ae96b2ca7d0606737a630c7a25 [file] [log] [blame]
[email protected]56f0b082012-06-14 07:12:321// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]678c0362012-12-05 08:02:445#include "content/browser/loader/resource_loader.h"
[email protected]56f0b082012-06-14 07:12:326
[email protected]bbdd1b20b2012-12-11 21:24:137#include "base/command_line.h"
skyostil95082a62015-06-05 19:53:078#include "base/location.h"
[email protected]5e3183482013-08-09 11:05:199#include "base/metrics/histogram.h"
vadimt81ef0df2014-11-18 19:42:3110#include "base/profiler/scoped_tracker.h"
skyostil95082a62015-06-05 19:53:0711#include "base/single_thread_task_runner.h"
12#include "base/thread_task_runner_handle.h"
[email protected]a43858f2013-06-28 15:18:3713#include "base/time/time.h"
[email protected]db3678052014-04-01 16:08:0314#include "content/browser/appcache/appcache_interceptor.h"
[email protected]56f0b082012-06-14 07:12:3215#include "content/browser/child_process_security_policy_impl.h"
[email protected]fc6c1872013-10-03 01:22:3516#include "content/browser/loader/cross_site_resource_handler.h"
[email protected]146b8b22013-11-20 03:59:1817#include "content/browser/loader/detachable_resource_handler.h"
[email protected]678c0362012-12-05 08:02:4418#include "content/browser/loader/resource_loader_delegate.h"
19#include "content/browser/loader/resource_request_info_impl.h"
[email protected]6ee72da12014-07-22 04:39:1020#include "content/browser/service_worker/service_worker_request_handler.h"
[email protected]56f0b082012-06-14 07:12:3221#include "content/browser/ssl/ssl_client_auth_handler.h"
22#include "content/browser/ssl/ssl_manager.h"
estark294fbd92015-07-31 18:36:2423#include "content/browser/ssl/ssl_policy.h"
[email protected]56f0b082012-06-14 07:12:3224#include "content/common/ssl_status_serialization.h"
25#include "content/public/browser/cert_store.h"
[email protected]1ccb6992013-10-30 04:46:2026#include "content/public/browser/resource_context.h"
[email protected]56f0b082012-06-14 07:12:3227#include "content/public/browser/resource_dispatcher_host_login_delegate.h"
[email protected]0bbd63b2013-11-29 00:02:1228#include "content/public/browser/signed_certificate_timestamp_store.h"
[email protected]bbdd1b20b2012-12-11 21:24:1329#include "content/public/common/content_client.h"
30#include "content/public/common/content_switches.h"
[email protected]f3b357692013-03-22 05:16:1331#include "content/public/common/process_type.h"
[email protected]56f0b082012-06-14 07:12:3232#include "content/public/common/resource_response.h"
estark294fbd92015-07-31 18:36:2433#include "content/public/common/security_style.h"
[email protected]fc6c1872013-10-03 01:22:3534#include "net/base/io_buffer.h"
[email protected]56f0b082012-06-14 07:12:3235#include "net/base/load_flags.h"
36#include "net/http/http_response_headers.h"
[email protected]536fd0b2013-03-14 17:41:5737#include "net/ssl/client_cert_store.h"
svaldez7872fd02015-11-19 21:10:5438#include "net/ssl/ssl_platform_key.h"
39#include "net/ssl/ssl_private_key.h"
[email protected]cba24642014-08-15 20:49:5940#include "net/url_request/redirect_info.h"
[email protected]3ed84722013-11-01 17:17:0741#include "net/url_request/url_request_status.h"
[email protected]56f0b082012-06-14 07:12:3242
43using base::TimeDelta;
44using base::TimeTicks;
45
46namespace content {
47namespace {
48
estark294fbd92015-07-31 18:36:2449void StoreSignedCertificateTimestamps(
50 const net::SignedCertificateTimestampAndStatusList& sct_list,
51 int process_id,
52 SignedCertificateTimestampIDStatusList* sct_ids) {
53 SignedCertificateTimestampStore* sct_store(
54 SignedCertificateTimestampStore::GetInstance());
55
56 for (auto iter = sct_list.begin(); iter != sct_list.end(); ++iter) {
57 const int sct_id(sct_store->Store(iter->sct.get(), process_id));
58 sct_ids->push_back(
59 SignedCertificateTimestampIDAndStatus(sct_id, iter->status));
60 }
61}
62
63void GetSSLStatusForRequest(const GURL& url,
64 const net::SSLInfo& ssl_info,
65 int child_id,
66 SSLStatus* ssl_status) {
67 DCHECK(ssl_info.cert);
68
69 int cert_id =
70 CertStore::GetInstance()->StoreCert(ssl_info.cert.get(), child_id);
71
72 SignedCertificateTimestampIDStatusList signed_certificate_timestamp_ids;
73 StoreSignedCertificateTimestamps(ssl_info.signed_certificate_timestamps,
74 child_id, &signed_certificate_timestamp_ids);
75
estarkced641ec2015-09-12 02:17:3176 *ssl_status = SSLStatus(SSLPolicy::GetSecurityStyleForResource(
77 url, cert_id, ssl_info.cert_status),
78 cert_id, signed_certificate_timestamp_ids, ssl_info);
estark294fbd92015-07-31 18:36:2479}
80
estarka7140bc2015-08-12 17:29:3781void PopulateResourceResponse(ResourceRequestInfoImpl* info,
82 net::URLRequest* request,
83 ResourceResponse* response) {
84 response->head.request_time = request->request_time();
85 response->head.response_time = request->response_time();
86 response->head.headers = request->response_headers();
87 request->GetCharset(&response->head.charset);
88 response->head.content_length = request->GetExpectedContentSize();
89 request->GetMimeType(&response->head.mime_type);
90 net::HttpResponseInfo response_info = request->response_info();
91 response->head.was_fetched_via_spdy = response_info.was_fetched_via_spdy;
92 response->head.was_npn_negotiated = response_info.was_npn_negotiated;
93 response->head.npn_negotiated_protocol =
94 response_info.npn_negotiated_protocol;
95 response->head.connection_info = response_info.connection_info;
96 response->head.was_fetched_via_proxy = request->was_fetched_via_proxy();
97 response->head.proxy_server = response_info.proxy_server;
98 response->head.socket_address = request->GetSocketAddress();
megjablond5ac7d52015-10-22 23:56:1299 const content::ResourceRequestInfo* request_info =
100 content::ResourceRequestInfo::ForRequest(request);
101 if (request_info)
102 response->head.is_using_lofi = request_info->IsUsingLoFi();
estarka7140bc2015-08-12 17:29:37103 if (ServiceWorkerRequestHandler* handler =
104 ServiceWorkerRequestHandler::GetHandler(request)) {
105 handler->GetExtraResponseInfo(&response->head);
106 }
107 AppCacheInterceptor::GetExtraResponseInfo(
108 request, &response->head.appcache_id,
109 &response->head.appcache_manifest_url);
110 if (info->is_load_timing_enabled())
111 request->GetLoadTimingInfo(&response->head.load_timing);
112
113 if (request->ssl_info().cert.get()) {
114 SSLStatus ssl_status;
115 GetSSLStatusForRequest(request->url(), request->ssl_info(),
116 info->GetChildID(), &ssl_status);
117 response->head.security_info = SerializeSecurityInfo(ssl_status);
estarka7140bc2015-08-12 17:29:37118 } else {
119 // We should not have any SSL state.
sigbjorn79cf3722015-09-18 09:15:20120 DCHECK(!request->ssl_info().cert_status);
121 DCHECK_EQ(request->ssl_info().security_bits, -1);
122 DCHECK_EQ(request->ssl_info().key_exchange_info, 0);
123 DCHECK(!request->ssl_info().connection_status);
estarka7140bc2015-08-12 17:29:37124 }
125}
126
[email protected]56f0b082012-06-14 07:12:32127} // namespace
128
129ResourceLoader::ResourceLoader(scoped_ptr<net::URLRequest> request,
130 scoped_ptr<ResourceHandler> handler,
131 ResourceLoaderDelegate* delegate)
[email protected]1ccb6992013-10-30 04:46:20132 : deferred_stage_(DEFERRED_NONE),
133 request_(request.Pass()),
134 handler_(handler.Pass()),
135 delegate_(delegate),
[email protected]1ccb6992013-10-30 04:46:20136 is_transferring_(false),
mmenkee0b2bd622015-06-24 20:23:10137 times_cancelled_before_request_start_(0),
138 started_request_(false),
139 times_cancelled_after_request_start_(0),
[email protected]1ccb6992013-10-30 04:46:20140 weak_ptr_factory_(this) {
141 request_->set_delegate(this);
142 handler_->SetController(this);
[email protected]56f0b082012-06-14 07:12:32143}
144
145ResourceLoader::~ResourceLoader() {
[email protected]fc72bb12013-06-02 21:13:46146 if (login_delegate_.get())
[email protected]56f0b082012-06-14 07:12:32147 login_delegate_->OnRequestCancelled();
davidben6cd57dd2014-12-12 19:23:57148 ssl_client_auth_handler_.reset();
[email protected]56f0b082012-06-14 07:12:32149
150 // Run ResourceHandler destructor before we tear-down the rest of our state
151 // as the ResourceHandler may want to inspect the URLRequest and other state.
152 handler_.reset();
153}
154
155void ResourceLoader::StartRequest() {
156 if (delegate_->HandleExternalProtocol(this, request_->url())) {
[email protected]2756a8e2012-09-07 18:24:29157 CancelAndIgnore();
[email protected]56f0b082012-06-14 07:12:32158 return;
159 }
160
161 // Give the handler a chance to delay the URLRequest from being started.
162 bool defer_start = false;
pkasting941842c2015-04-11 01:51:30163 if (!handler_->OnWillStart(request_->url(), &defer_start)) {
164 Cancel();
165 return;
[email protected]56f0b082012-06-14 07:12:32166 }
167
168 if (defer_start) {
169 deferred_stage_ = DEFERRED_START;
170 } else {
171 StartRequestInternal();
172 }
173}
174
175void ResourceLoader::CancelRequest(bool from_renderer) {
176 CancelRequestInternal(net::ERR_ABORTED, from_renderer);
177}
178
[email protected]2756a8e2012-09-07 18:24:29179void ResourceLoader::CancelAndIgnore() {
180 ResourceRequestInfoImpl* info = GetRequestInfo();
181 info->set_was_ignored_by_handler(true);
182 CancelRequest(false);
183}
184
[email protected]af3d4962012-10-19 10:57:26185void ResourceLoader::CancelWithError(int error_code) {
186 CancelRequestInternal(error_code, false);
187}
188
[email protected]f820d9c52013-12-18 18:42:36189void ResourceLoader::MarkAsTransferring() {
[email protected]6c1e05212014-07-31 00:59:40190 CHECK(IsResourceTypeFrame(GetRequestInfo()->GetResourceType()))
[email protected]46c704762013-12-18 18:10:24191 << "Can only transfer for navigations";
[email protected]56f0b082012-06-14 07:12:32192 is_transferring_ = true;
michaelnbfea6ec2014-12-09 23:16:13193
194 int child_id = GetRequestInfo()->GetChildID();
195 AppCacheInterceptor::PrepareForCrossSiteTransfer(request(), child_id);
196 ServiceWorkerRequestHandler* handler =
197 ServiceWorkerRequestHandler::GetHandler(request());
198 if (handler)
199 handler->PrepareForCrossSiteTransfer(child_id);
[email protected]56f0b082012-06-14 07:12:32200}
201
[email protected]1f291cd2013-09-25 22:05:14202void ResourceLoader::CompleteTransfer() {
[email protected]17b674e02014-05-10 04:30:02203 // Although CrossSiteResourceHandler defers at OnResponseStarted
204 // (DEFERRED_READ), it may be seeing a replay of events via
mmenke664a8fd2015-06-13 00:08:51205 // MimeTypeResourceHandler, and so the request itself is actually deferred
206 // at a later read stage.
[email protected]17b674e02014-05-10 04:30:02207 DCHECK(DEFERRED_READ == deferred_stage_ ||
208 DEFERRED_RESPONSE_COMPLETE == deferred_stage_);
michaelnbfea6ec2014-12-09 23:16:13209 DCHECK(is_transferring_);
210
211 // In some cases, a process transfer doesn't really happen and the
212 // request is resumed in the original process. Real transfers to a new process
213 // are completed via ResourceDispatcherHostImpl::UpdateRequestForTransfer.
214 int child_id = GetRequestInfo()->GetChildID();
215 AppCacheInterceptor::MaybeCompleteCrossSiteTransferInOldProcess(
216 request(), child_id);
217 ServiceWorkerRequestHandler* handler =
218 ServiceWorkerRequestHandler::GetHandler(request());
219 if (handler)
220 handler->MaybeCompleteCrossSiteTransferInOldProcess(child_id);
[email protected]56f0b082012-06-14 07:12:32221
[email protected]56f0b082012-06-14 07:12:32222 is_transferring_ = false;
[email protected]fc6c1872013-10-03 01:22:35223 GetRequestInfo()->cross_site_handler()->ResumeResponse();
[email protected]56f0b082012-06-14 07:12:32224}
225
226ResourceRequestInfoImpl* ResourceLoader::GetRequestInfo() {
227 return ResourceRequestInfoImpl::ForRequest(request_.get());
228}
229
230void ResourceLoader::ClearLoginDelegate() {
231 login_delegate_ = NULL;
232}
233
[email protected]56f0b082012-06-14 07:12:32234void ResourceLoader::OnReceivedRedirect(net::URLRequest* unused,
[email protected]cba24642014-08-15 20:49:59235 const net::RedirectInfo& redirect_info,
[email protected]56f0b082012-06-14 07:12:32236 bool* defer) {
237 DCHECK_EQ(request_.get(), unused);
238
mostynb0e79091bb2015-06-15 16:18:25239 DVLOG(1) << "OnReceivedRedirect: " << request_->url().spec();
[email protected]56f0b082012-06-14 07:12:32240 DCHECK(request_->status().is_success());
241
242 ResourceRequestInfoImpl* info = GetRequestInfo();
243
[email protected]2d09a702014-01-19 23:41:24244 if (info->GetProcessType() != PROCESS_TYPE_PLUGIN &&
[email protected]56f0b082012-06-14 07:12:32245 !ChildProcessSecurityPolicyImpl::GetInstance()->
[email protected]cba24642014-08-15 20:49:59246 CanRequestURL(info->GetChildID(), redirect_info.new_url)) {
mostynb0e79091bb2015-06-15 16:18:25247 DVLOG(1) << "Denied unauthorized request for "
248 << redirect_info.new_url.possibly_invalid_spec();
[email protected]56f0b082012-06-14 07:12:32249
250 // Tell the renderer that this request was disallowed.
251 Cancel();
252 return;
253 }
254
[email protected]cba24642014-08-15 20:49:59255 delegate_->DidReceiveRedirect(this, redirect_info.new_url);
[email protected]56f0b082012-06-14 07:12:32256
[email protected]cba24642014-08-15 20:49:59257 if (delegate_->HandleExternalProtocol(this, redirect_info.new_url)) {
[email protected]56f0b082012-06-14 07:12:32258 // The request is complete so we can remove it.
[email protected]2756a8e2012-09-07 18:24:29259 CancelAndIgnore();
[email protected]56f0b082012-06-14 07:12:32260 return;
261 }
262
263 scoped_refptr<ResourceResponse> response(new ResourceResponse());
[email protected]3821f7a2014-08-13 16:40:08264 PopulateResourceResponse(info, request_.get(), response.get());
[email protected]cba24642014-08-15 20:49:59265 if (!handler_->OnRequestRedirected(redirect_info, response.get(), defer)) {
[email protected]56f0b082012-06-14 07:12:32266 Cancel();
[email protected]926360f2012-06-29 04:45:02267 } else if (*defer) {
268 deferred_stage_ = DEFERRED_REDIRECT; // Follow redirect when resumed.
[email protected]56f0b082012-06-14 07:12:32269 }
[email protected]56f0b082012-06-14 07:12:32270}
271
272void ResourceLoader::OnAuthRequired(net::URLRequest* unused,
273 net::AuthChallengeInfo* auth_info) {
274 DCHECK_EQ(request_.get(), unused);
275
baranovich1b32ffb2015-01-15 14:44:52276 ResourceRequestInfoImpl* info = GetRequestInfo();
277 if (info->do_not_prompt_for_login()) {
[email protected]56f0b082012-06-14 07:12:32278 request_->CancelAuth();
279 return;
280 }
281
[email protected]56f0b082012-06-14 07:12:32282 // Create a login dialog on the UI thread to get authentication data, or pull
283 // from cache and continue on the IO thread.
284
[email protected]fc72bb12013-06-02 21:13:46285 DCHECK(!login_delegate_.get())
286 << "OnAuthRequired called with login_delegate pending";
[email protected]56f0b082012-06-14 07:12:32287 login_delegate_ = delegate_->CreateLoginDelegate(this, auth_info);
[email protected]fc72bb12013-06-02 21:13:46288 if (!login_delegate_.get())
[email protected]56f0b082012-06-14 07:12:32289 request_->CancelAuth();
290}
291
292void ResourceLoader::OnCertificateRequested(
293 net::URLRequest* unused,
294 net::SSLCertRequestInfo* cert_info) {
295 DCHECK_EQ(request_.get(), unused);
296
[email protected]294084d2014-01-06 22:22:02297 if (request_->load_flags() & net::LOAD_PREFETCH) {
[email protected]56f0b082012-06-14 07:12:32298 request_->Cancel();
299 return;
300 }
301
davidben6cd57dd2014-12-12 19:23:57302 DCHECK(!ssl_client_auth_handler_)
[email protected]fc72bb12013-06-02 21:13:46303 << "OnCertificateRequested called with ssl_client_auth_handler pending";
davidben6cd57dd2014-12-12 19:23:57304 ssl_client_auth_handler_.reset(new SSLClientAuthHandler(
305 GetRequestInfo()->GetContext()->CreateClientCertStore(), request_.get(),
davidben3b8455ae72015-03-11 19:42:19306 cert_info, this));
[email protected]56f0b082012-06-14 07:12:32307 ssl_client_auth_handler_->SelectCertificate();
308}
309
310void ResourceLoader::OnSSLCertificateError(net::URLRequest* request,
311 const net::SSLInfo& ssl_info,
312 bool fatal) {
313 ResourceRequestInfoImpl* info = GetRequestInfo();
314
[email protected]56f0b082012-06-14 07:12:32315 SSLManager::OnSSLCertificateError(
clamy0d32d6d2015-11-24 11:16:26316 weak_ptr_factory_.GetWeakPtr(), info->GetResourceType(), request_->url(),
clamyb830cae2015-12-02 14:09:30317 info->GetWebContentsGetterForRequest(), ssl_info, fatal);
[email protected]56f0b082012-06-14 07:12:32318}
319
[email protected]5584eab2014-01-09 22:16:15320void ResourceLoader::OnBeforeNetworkStart(net::URLRequest* unused,
321 bool* defer) {
322 DCHECK_EQ(request_.get(), unused);
323
324 // Give the handler a chance to delay the URLRequest from using the network.
[email protected]d22e800e2014-05-28 21:55:57325 if (!handler_->OnBeforeNetworkStart(request_->url(), defer)) {
[email protected]5584eab2014-01-09 22:16:15326 Cancel();
327 return;
328 } else if (*defer) {
329 deferred_stage_ = DEFERRED_NETWORK_START;
330 }
331}
332
[email protected]56f0b082012-06-14 07:12:32333void ResourceLoader::OnResponseStarted(net::URLRequest* unused) {
334 DCHECK_EQ(request_.get(), unused);
335
mostynb0e79091bb2015-06-15 16:18:25336 DVLOG(1) << "OnResponseStarted: " << request_->url().spec();
[email protected]56f0b082012-06-14 07:12:32337
[email protected]926360f2012-06-29 04:45:02338 if (!request_->status().is_success()) {
339 ResponseCompleted();
340 return;
341 }
342
[email protected]926360f2012-06-29 04:45:02343 CompleteResponseStarted();
344
345 if (is_deferred())
346 return;
347
pkasting941842c2015-04-11 01:51:30348 if (request_->status().is_success())
[email protected]926360f2012-06-29 04:45:02349 StartReading(false); // Read the first chunk.
pkasting941842c2015-04-11 01:51:30350 else
[email protected]56f0b082012-06-14 07:12:32351 ResponseCompleted();
[email protected]56f0b082012-06-14 07:12:32352}
353
354void ResourceLoader::OnReadCompleted(net::URLRequest* unused, int bytes_read) {
355 DCHECK_EQ(request_.get(), unused);
mostynb0e79091bb2015-06-15 16:18:25356 DVLOG(1) << "OnReadCompleted: \"" << request_->url().spec() << "\""
357 << " bytes_read = " << bytes_read;
[email protected]56f0b082012-06-14 07:12:32358
[email protected]926360f2012-06-29 04:45:02359 // bytes_read == -1 always implies an error.
360 if (bytes_read == -1 || !request_->status().is_success()) {
[email protected]56f0b082012-06-14 07:12:32361 ResponseCompleted();
362 return;
363 }
364
[email protected]218d9d372014-04-16 18:34:55365 CompleteRead(bytes_read);
366
[email protected]d1222a62014-04-14 20:27:32367 // If the handler cancelled or deferred the request, do not continue
368 // processing the read. If cancelled, the URLRequest has already been
369 // cancelled and will schedule an erroring OnReadCompleted later. If deferred,
370 // do nothing until resumed.
371 //
372 // Note: if bytes_read is 0 (EOF) and the handler defers, resumption will call
[email protected]17b674e02014-05-10 04:30:02373 // ResponseCompleted().
[email protected]218d9d372014-04-16 18:34:55374 if (is_deferred() || !request_->status().is_success())
[email protected]56f0b082012-06-14 07:12:32375 return;
[email protected]56f0b082012-06-14 07:12:32376
[email protected]d1222a62014-04-14 20:27:32377 if (bytes_read > 0) {
[email protected]926360f2012-06-29 04:45:02378 StartReading(true); // Read the next chunk.
379 } else {
pkasting941842c2015-04-11 01:51:30380 // TODO(darin): Remove ScopedTracker below once crbug.com/475761 is fixed.
381 tracked_objects::ScopedTracker tracking_profile(
382 FROM_HERE_WITH_EXPLICIT_FUNCTION("475761 ResponseCompleted()"));
vadimt2df40b372014-11-27 02:01:41383
[email protected]d1222a62014-04-14 20:27:32384 // URLRequest reported an EOF. Call ResponseCompleted.
385 DCHECK_EQ(0, bytes_read);
[email protected]56f0b082012-06-14 07:12:32386 ResponseCompleted();
[email protected]926360f2012-06-29 04:45:02387 }
[email protected]56f0b082012-06-14 07:12:32388}
389
davidben21163ec2014-10-01 23:05:23390void ResourceLoader::CancelSSLRequest(int error,
[email protected]56f0b082012-06-14 07:12:32391 const net::SSLInfo* ssl_info) {
mostynb4c27d042015-03-18 21:47:47392 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]56f0b082012-06-14 07:12:32393
394 // The request can be NULL if it was cancelled by the renderer (as the
395 // request of the user navigating to a new page from the location bar).
396 if (!request_->is_pending())
397 return;
398 DVLOG(1) << "CancelSSLRequest() url: " << request_->url().spec();
399
400 if (ssl_info) {
401 request_->CancelWithSSLError(error, *ssl_info);
402 } else {
403 request_->CancelWithError(error);
404 }
405}
406
davidben21163ec2014-10-01 23:05:23407void ResourceLoader::ContinueSSLRequest() {
mostynb4c27d042015-03-18 21:47:47408 DCHECK_CURRENTLY_ON(BrowserThread::IO);
[email protected]56f0b082012-06-14 07:12:32409
410 DVLOG(1) << "ContinueSSLRequest() url: " << request_->url().spec();
411
412 request_->ContinueDespiteLastError();
413}
414
davidben3b8455ae72015-03-11 19:42:19415void ResourceLoader::ContinueWithCertificate(net::X509Certificate* cert) {
416 DCHECK(ssl_client_auth_handler_);
417 ssl_client_auth_handler_.reset();
svaldez7872fd02015-11-19 21:10:54418 if (!cert) {
419 request_->ContinueWithCertificate(nullptr, nullptr);
420 return;
421 }
422 scoped_refptr<net::SSLPrivateKey> private_key =
423 net::FetchClientCertPrivateKey(cert);
424 request_->ContinueWithCertificate(cert, private_key.get());
davidben3b8455ae72015-03-11 19:42:19425}
426
427void ResourceLoader::CancelCertificateSelection() {
428 DCHECK(ssl_client_auth_handler_);
429 ssl_client_auth_handler_.reset();
430 request_->CancelWithError(net::ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
431}
432
[email protected]56f0b082012-06-14 07:12:32433void ResourceLoader::Resume() {
434 DCHECK(!is_transferring_);
435
436 DeferredStage stage = deferred_stage_;
437 deferred_stage_ = DEFERRED_NONE;
438 switch (stage) {
439 case DEFERRED_NONE:
440 NOTREACHED();
441 break;
442 case DEFERRED_START:
443 StartRequestInternal();
444 break;
[email protected]5584eab2014-01-09 22:16:15445 case DEFERRED_NETWORK_START:
446 request_->ResumeNetworkStart();
447 break;
[email protected]56f0b082012-06-14 07:12:32448 case DEFERRED_REDIRECT:
449 request_->FollowDeferredRedirect();
450 break;
[email protected]56f0b082012-06-14 07:12:32451 case DEFERRED_READ:
skyostil95082a62015-06-05 19:53:07452 base::ThreadTaskRunnerHandle::Get()->PostTask(
453 FROM_HERE, base::Bind(&ResourceLoader::ResumeReading,
454 weak_ptr_factory_.GetWeakPtr()));
[email protected]56f0b082012-06-14 07:12:32455 break;
[email protected]17b674e02014-05-10 04:30:02456 case DEFERRED_RESPONSE_COMPLETE:
skyostil95082a62015-06-05 19:53:07457 base::ThreadTaskRunnerHandle::Get()->PostTask(
458 FROM_HERE, base::Bind(&ResourceLoader::ResponseCompleted,
459 weak_ptr_factory_.GetWeakPtr()));
[email protected]17b674e02014-05-10 04:30:02460 break;
[email protected]56f0b082012-06-14 07:12:32461 case DEFERRED_FINISH:
462 // Delay self-destruction since we don't know how we were reached.
skyostil95082a62015-06-05 19:53:07463 base::ThreadTaskRunnerHandle::Get()->PostTask(
464 FROM_HERE, base::Bind(&ResourceLoader::CallDidFinishLoading,
465 weak_ptr_factory_.GetWeakPtr()));
[email protected]56f0b082012-06-14 07:12:32466 break;
467 }
468}
469
470void ResourceLoader::Cancel() {
471 CancelRequest(false);
472}
473
474void ResourceLoader::StartRequestInternal() {
475 DCHECK(!request_->is_pending());
[email protected]4c4092112014-02-26 23:29:12476
477 if (!request_->status().is_success()) {
478 return;
479 }
480
mmenkee0b2bd622015-06-24 20:23:10481 started_request_ = true;
[email protected]56f0b082012-06-14 07:12:32482 request_->Start();
483
484 delegate_->DidStartRequest(this);
485}
486
487void ResourceLoader::CancelRequestInternal(int error, bool from_renderer) {
mostynb0e79091bb2015-06-15 16:18:25488 DVLOG(1) << "CancelRequestInternal: " << request_->url().spec();
[email protected]56f0b082012-06-14 07:12:32489
490 ResourceRequestInfoImpl* info = GetRequestInfo();
491
492 // WebKit will send us a cancel for downloads since it no longer handles
493 // them. In this case, ignore the cancel since we handle downloads in the
494 // browser.
[email protected]70983822013-11-27 14:33:59495 if (from_renderer && (info->IsDownload() || info->is_stream()))
[email protected]56f0b082012-06-14 07:12:32496 return;
497
[email protected]146b8b22013-11-20 03:59:18498 if (from_renderer && info->detachable_handler()) {
499 // TODO(davidben): Fix Blink handling of prefetches so they are not
500 // cancelled on navigate away and end up in the local cache.
501 info->detachable_handler()->Detach();
502 return;
503 }
504
[email protected]926360f2012-06-29 04:45:02505 // TODO(darin): Perhaps we should really be looking to see if the status is
506 // IO_PENDING?
[email protected]56f0b082012-06-14 07:12:32507 bool was_pending = request_->is_pending();
508
[email protected]fc72bb12013-06-02 21:13:46509 if (login_delegate_.get()) {
[email protected]56f0b082012-06-14 07:12:32510 login_delegate_->OnRequestCancelled();
511 login_delegate_ = NULL;
512 }
davidben6cd57dd2014-12-12 19:23:57513 ssl_client_auth_handler_.reset();
[email protected]56f0b082012-06-14 07:12:32514
mmenkee0b2bd622015-06-24 20:23:10515 if (!started_request_) {
516 times_cancelled_before_request_start_++;
517 } else {
518 times_cancelled_after_request_start_++;
519 }
520
[email protected]56f0b082012-06-14 07:12:32521 request_->CancelWithError(error);
522
523 if (!was_pending) {
524 // If the request isn't in flight, then we won't get an asynchronous
525 // notification from the request, so we have to signal ourselves to finish
526 // this request.
skyostil95082a62015-06-05 19:53:07527 base::ThreadTaskRunnerHandle::Get()->PostTask(
528 FROM_HERE, base::Bind(&ResourceLoader::ResponseCompleted,
529 weak_ptr_factory_.GetWeakPtr()));
[email protected]56f0b082012-06-14 07:12:32530 }
531}
532
[email protected]926360f2012-06-29 04:45:02533void ResourceLoader::CompleteResponseStarted() {
[email protected]56f0b082012-06-14 07:12:32534 ResourceRequestInfoImpl* info = GetRequestInfo();
[email protected]56f0b082012-06-14 07:12:32535 scoped_refptr<ResourceResponse> response(new ResourceResponse());
[email protected]3821f7a2014-08-13 16:40:08536 PopulateResourceResponse(info, request_.get(), response.get());
[email protected]56f0b082012-06-14 07:12:32537
[email protected]56f0b082012-06-14 07:12:32538 delegate_->DidReceiveResponse(this);
[email protected]56f0b082012-06-14 07:12:32539
pkasting941842c2015-04-11 01:51:30540 // TODO(darin): Remove ScopedTracker below once crbug.com/475761 is fixed.
vadimt81ef0df2014-11-18 19:42:31541 tracked_objects::ScopedTracker tracking_profile(
pkasting941842c2015-04-11 01:51:30542 FROM_HERE_WITH_EXPLICIT_FUNCTION("475761 OnResponseStarted()"));
vadimt81ef0df2014-11-18 19:42:31543
[email protected]56f0b082012-06-14 07:12:32544 bool defer = false;
[email protected]d22e800e2014-05-28 21:55:57545 if (!handler_->OnResponseStarted(response.get(), &defer)) {
[email protected]926360f2012-06-29 04:45:02546 Cancel();
547 } else if (defer) {
[email protected]5e3183482013-08-09 11:05:19548 read_deferral_start_time_ = base::TimeTicks::Now();
[email protected]926360f2012-06-29 04:45:02549 deferred_stage_ = DEFERRED_READ; // Read first chunk when resumed.
[email protected]56f0b082012-06-14 07:12:32550 }
[email protected]56f0b082012-06-14 07:12:32551}
552
[email protected]926360f2012-06-29 04:45:02553void ResourceLoader::StartReading(bool is_continuation) {
[email protected]56f0b082012-06-14 07:12:32554 int bytes_read = 0;
[email protected]926360f2012-06-29 04:45:02555 ReadMore(&bytes_read);
556
557 // If IO is pending, wait for the URLRequest to call OnReadCompleted.
558 if (request_->status().is_io_pending())
559 return;
560
561 if (!is_continuation || bytes_read <= 0) {
[email protected]56f0b082012-06-14 07:12:32562 OnReadCompleted(request_.get(), bytes_read);
[email protected]926360f2012-06-29 04:45:02563 } else {
564 // Else, trigger OnReadCompleted asynchronously to avoid starving the IO
565 // thread in case the URLRequest can provide data synchronously.
skyostil95082a62015-06-05 19:53:07566 base::ThreadTaskRunnerHandle::Get()->PostTask(
[email protected]926360f2012-06-29 04:45:02567 FROM_HERE,
[email protected]5c1d3e52012-08-01 05:14:27568 base::Bind(&ResourceLoader::OnReadCompleted,
skyostil95082a62015-06-05 19:53:07569 weak_ptr_factory_.GetWeakPtr(), request_.get(), bytes_read));
[email protected]926360f2012-06-29 04:45:02570 }
571}
572
573void ResourceLoader::ResumeReading() {
574 DCHECK(!is_deferred());
575
[email protected]5e3183482013-08-09 11:05:19576 if (!read_deferral_start_time_.is_null()) {
577 UMA_HISTOGRAM_TIMES("Net.ResourceLoader.ReadDeferral",
578 base::TimeTicks::Now() - read_deferral_start_time_);
579 read_deferral_start_time_ = base::TimeTicks();
580 }
[email protected]926360f2012-06-29 04:45:02581 if (request_->status().is_success()) {
582 StartReading(false); // Read the next chunk (OK to complete synchronously).
583 } else {
[email protected]56f0b082012-06-14 07:12:32584 ResponseCompleted();
585 }
586}
587
[email protected]926360f2012-06-29 04:45:02588void ResourceLoader::ReadMore(int* bytes_read) {
[email protected]926360f2012-06-29 04:45:02589 DCHECK(!is_deferred());
[email protected]56f0b082012-06-14 07:12:32590
[email protected]ef5306e2013-10-15 19:38:18591 // Make sure we track the buffer in at least one place. This ensures it gets
592 // deleted even in the case the request has already finished its job and
593 // doesn't use the buffer.
594 scoped_refptr<net::IOBuffer> buf;
[email protected]56f0b082012-06-14 07:12:32595 int buf_size;
vadimt81ef0df2014-11-18 19:42:31596 {
pkasting941842c2015-04-11 01:51:30597 // TODO(darin): Remove ScopedTracker below once crbug.com/475761 is fixed.
vadimt394300b02014-12-02 04:38:41598 tracked_objects::ScopedTracker tracking_profile2(
pkasting941842c2015-04-11 01:51:30599 FROM_HERE_WITH_EXPLICIT_FUNCTION("475761 OnWillRead()"));
vadimt81ef0df2014-11-18 19:42:31600
601 if (!handler_->OnWillRead(&buf, &buf_size, -1)) {
602 Cancel();
603 return;
604 }
[email protected]926360f2012-06-29 04:45:02605 }
[email protected]56f0b082012-06-14 07:12:32606
dcheng67769df52014-08-26 19:43:51607 DCHECK(buf.get());
[email protected]56f0b082012-06-14 07:12:32608 DCHECK(buf_size > 0);
609
[email protected]ef5306e2013-10-15 19:38:18610 request_->Read(buf.get(), buf_size, bytes_read);
[email protected]926360f2012-06-29 04:45:02611
612 // No need to check the return value here as we'll detect errors by
613 // inspecting the URLRequest's status.
[email protected]56f0b082012-06-14 07:12:32614}
615
[email protected]218d9d372014-04-16 18:34:55616void ResourceLoader::CompleteRead(int bytes_read) {
[email protected]926360f2012-06-29 04:45:02617 DCHECK(bytes_read >= 0);
618 DCHECK(request_->status().is_success());
[email protected]56f0b082012-06-14 07:12:32619
pkasting941842c2015-04-11 01:51:30620 // TODO(darin): Remove ScopedTracker below once crbug.com/475761 is fixed.
vadimt81ef0df2014-11-18 19:42:31621 tracked_objects::ScopedTracker tracking_profile(
pkasting941842c2015-04-11 01:51:30622 FROM_HERE_WITH_EXPLICIT_FUNCTION("475761 OnReadCompleted()"));
vadimt81ef0df2014-11-18 19:42:31623
[email protected]56f0b082012-06-14 07:12:32624 bool defer = false;
[email protected]d22e800e2014-05-28 21:55:57625 if (!handler_->OnReadCompleted(bytes_read, &defer)) {
[email protected]56f0b082012-06-14 07:12:32626 Cancel();
[email protected]926360f2012-06-29 04:45:02627 } else if (defer) {
[email protected]17b674e02014-05-10 04:30:02628 deferred_stage_ =
629 bytes_read > 0 ? DEFERRED_READ : DEFERRED_RESPONSE_COMPLETE;
[email protected]56f0b082012-06-14 07:12:32630 }
[email protected]218d9d372014-04-16 18:34:55631
632 // Note: the request may still have been cancelled while OnReadCompleted
633 // returns true if OnReadCompleted caused request to get cancelled
634 // out-of-band. (In AwResourceDispatcherHostDelegate::DownloadStarting, for
635 // instance.)
[email protected]56f0b082012-06-14 07:12:32636}
637
638void ResourceLoader::ResponseCompleted() {
mostynb0e79091bb2015-06-15 16:18:25639 DVLOG(1) << "ResponseCompleted: " << request_->url().spec();
[email protected]3ed84722013-11-01 17:17:07640 RecordHistograms();
[email protected]56f0b082012-06-14 07:12:32641 ResourceRequestInfoImpl* info = GetRequestInfo();
642
643 std::string security_info;
644 const net::SSLInfo& ssl_info = request_->ssl_info();
[email protected]fc72bb12013-06-02 21:13:46645 if (ssl_info.cert.get() != NULL) {
estark294fbd92015-07-31 18:36:24646 SSLStatus ssl_status;
647 GetSSLStatusForRequest(request_->url(), ssl_info, info->GetChildID(),
648 &ssl_status);
[email protected]0bbd63b2013-11-29 00:02:12649
estark294fbd92015-07-31 18:36:24650 security_info = SerializeSecurityInfo(ssl_status);
[email protected]56f0b082012-06-14 07:12:32651 }
652
[email protected]3780874a2013-11-18 05:49:03653 bool defer = false;
vadimt81ef0df2014-11-18 19:42:31654 {
pkasting941842c2015-04-11 01:51:30655 // TODO(darin): Remove ScopedTracker below once crbug.com/475761 is fixed.
vadimt81ef0df2014-11-18 19:42:31656 tracked_objects::ScopedTracker tracking_profile(
pkasting941842c2015-04-11 01:51:30657 FROM_HERE_WITH_EXPLICIT_FUNCTION("475761 OnResponseCompleted()"));
vadimt81ef0df2014-11-18 19:42:31658
659 handler_->OnResponseCompleted(request_->status(), security_info, &defer);
660 }
[email protected]3780874a2013-11-18 05:49:03661 if (defer) {
[email protected]56f0b082012-06-14 07:12:32662 // The handler is not ready to die yet. We will call DidFinishLoading when
663 // we resume.
664 deferred_stage_ = DEFERRED_FINISH;
[email protected]3780874a2013-11-18 05:49:03665 } else {
666 // This will result in our destruction.
667 CallDidFinishLoading();
[email protected]56f0b082012-06-14 07:12:32668 }
669}
670
[email protected]56f0b082012-06-14 07:12:32671void ResourceLoader::CallDidFinishLoading() {
672 delegate_->DidFinishLoading(this);
673}
674
[email protected]3ed84722013-11-01 17:17:07675void ResourceLoader::RecordHistograms() {
bnc3d8d8d32015-10-28 15:45:56676 if (request_->response_info().network_accessed) {
677 UMA_HISTOGRAM_ENUMERATION("Net.HttpResponseInfo.ConnectionInfo",
678 request_->response_info().connection_info,
679 net::HttpResponseInfo::NUM_OF_CONNECTION_INFOS);
680 }
681
[email protected]3ed84722013-11-01 17:17:07682 ResourceRequestInfoImpl* info = GetRequestInfo();
683
[email protected]6c1e05212014-07-31 00:59:40684 if (info->GetResourceType() == RESOURCE_TYPE_PREFETCH) {
[email protected]3ed84722013-11-01 17:17:07685 PrefetchStatus status = STATUS_UNDEFINED;
686 TimeDelta total_time = base::TimeTicks::Now() - request_->creation_time();
687
688 switch (request_->status().status()) {
689 case net::URLRequestStatus::SUCCESS:
690 if (request_->was_cached()) {
691 status = STATUS_SUCCESS_FROM_CACHE;
692 UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeSpentPrefetchingFromCache",
693 total_time);
694 } else {
695 status = STATUS_SUCCESS_FROM_NETWORK;
696 UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeSpentPrefetchingFromNetwork",
697 total_time);
698 }
699 break;
700 case net::URLRequestStatus::CANCELED:
701 status = STATUS_CANCELED;
702 UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeBeforeCancel", total_time);
703 break;
704 case net::URLRequestStatus::IO_PENDING:
705 case net::URLRequestStatus::FAILED:
706 status = STATUS_UNDEFINED;
707 break;
708 }
709
710 UMA_HISTOGRAM_ENUMERATION("Net.Prefetch.Pattern", status, STATUS_MAX);
711 }
712}
713
[email protected]56f0b082012-06-14 07:12:32714} // namespace content