1 // 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.
5 #include "content/browser/loader/resource_loader.h"
7 #include "base/command_line.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/metrics/histogram.h"
10 #include "base/time/time.h"
11 #include "content/browser/appcache/appcache_interceptor.h"
12 #include "content/browser/child_process_security_policy_impl.h"
13 #include "content/browser/loader/cross_site_resource_handler.h"
14 #include "content/browser/loader/detachable_resource_handler.h"
15 #include "content/browser/loader/resource_loader_delegate.h"
16 #include "content/browser/loader/resource_request_info_impl.h"
17 #include "content/browser/ssl/ssl_client_auth_handler.h"
18 #include "content/browser/ssl/ssl_manager.h"
19 #include "content/common/ssl_status_serialization.h"
20 #include "content/public/browser/cert_store.h"
21 #include "content/public/browser/resource_context.h"
22 #include "content/public/browser/resource_dispatcher_host_login_delegate.h"
23 #include "content/public/browser/signed_certificate_timestamp_store.h"
24 #include "content/public/common/content_client.h"
25 #include "content/public/common/content_switches.h"
26 #include "content/public/common/process_type.h"
27 #include "content/public/common/resource_response.h"
28 #include "net/base/io_buffer.h"
29 #include "net/base/load_flags.h"
30 #include "net/http/http_response_headers.h"
31 #include "net/ssl/client_cert_store.h"
32 #include "net/url_request/url_request_status.h"
34 using base::TimeDelta
;
35 using base::TimeTicks
;
40 void PopulateResourceResponse(net::URLRequest
* request
,
41 ResourceResponse
* response
) {
42 response
->head
.error_code
= request
->status().error();
43 response
->head
.request_time
= request
->request_time();
44 response
->head
.response_time
= request
->response_time();
45 response
->head
.headers
= request
->response_headers();
46 request
->GetCharset(&response
->head
.charset
);
47 response
->head
.content_length
= request
->GetExpectedContentSize();
48 request
->GetMimeType(&response
->head
.mime_type
);
49 net::HttpResponseInfo response_info
= request
->response_info();
50 response
->head
.was_fetched_via_spdy
= response_info
.was_fetched_via_spdy
;
51 response
->head
.was_npn_negotiated
= response_info
.was_npn_negotiated
;
52 response
->head
.npn_negotiated_protocol
=
53 response_info
.npn_negotiated_protocol
;
54 response
->head
.connection_info
= response_info
.connection_info
;
55 response
->head
.was_fetched_via_proxy
= request
->was_fetched_via_proxy();
56 response
->head
.socket_address
= request
->GetSocketAddress();
57 AppCacheInterceptor::GetExtraResponseInfo(
59 &response
->head
.appcache_id
,
60 &response
->head
.appcache_manifest_url
);
61 // TODO(mmenke): Figure out if LOAD_ENABLE_LOAD_TIMING is safe to remove.
62 if (request
->load_flags() & net::LOAD_ENABLE_LOAD_TIMING
)
63 request
->GetLoadTimingInfo(&response
->head
.load_timing
);
68 ResourceLoader::ResourceLoader(scoped_ptr
<net::URLRequest
> request
,
69 scoped_ptr
<ResourceHandler
> handler
,
70 ResourceLoaderDelegate
* delegate
)
71 : deferred_stage_(DEFERRED_NONE
),
72 request_(request
.Pass()),
73 handler_(handler
.Pass()),
75 last_upload_position_(0),
76 waiting_for_upload_progress_ack_(false),
77 is_transferring_(false),
78 weak_ptr_factory_(this) {
79 request_
->set_delegate(this);
80 handler_
->SetController(this);
83 ResourceLoader::~ResourceLoader() {
84 if (login_delegate_
.get())
85 login_delegate_
->OnRequestCancelled();
86 if (ssl_client_auth_handler_
.get())
87 ssl_client_auth_handler_
->OnRequestCancelled();
89 // Run ResourceHandler destructor before we tear-down the rest of our state
90 // as the ResourceHandler may want to inspect the URLRequest and other state.
94 void ResourceLoader::StartRequest() {
95 if (delegate_
->HandleExternalProtocol(this, request_
->url())) {
100 // Give the handler a chance to delay the URLRequest from being started.
101 bool defer_start
= false;
102 if (!handler_
->OnWillStart(request_
->url(), &defer_start
)) {
108 deferred_stage_
= DEFERRED_START
;
110 StartRequestInternal();
114 void ResourceLoader::CancelRequest(bool from_renderer
) {
115 CancelRequestInternal(net::ERR_ABORTED
, from_renderer
);
118 void ResourceLoader::CancelAndIgnore() {
119 ResourceRequestInfoImpl
* info
= GetRequestInfo();
120 info
->set_was_ignored_by_handler(true);
121 CancelRequest(false);
124 void ResourceLoader::CancelWithError(int error_code
) {
125 CancelRequestInternal(error_code
, false);
128 void ResourceLoader::ReportUploadProgress() {
129 if (waiting_for_upload_progress_ack_
)
130 return; // Send one progress event at a time.
132 net::UploadProgress progress
= request_
->GetUploadProgress();
133 if (!progress
.size())
134 return; // Nothing to upload.
136 if (progress
.position() == last_upload_position_
)
137 return; // No progress made since last time.
139 const uint64 kHalfPercentIncrements
= 200;
140 const TimeDelta kOneSecond
= TimeDelta::FromMilliseconds(1000);
142 uint64 amt_since_last
= progress
.position() - last_upload_position_
;
143 TimeDelta time_since_last
= TimeTicks::Now() - last_upload_ticks_
;
145 bool is_finished
= (progress
.size() == progress
.position());
146 bool enough_new_progress
=
147 (amt_since_last
> (progress
.size() / kHalfPercentIncrements
));
148 bool too_much_time_passed
= time_since_last
> kOneSecond
;
150 if (is_finished
|| enough_new_progress
|| too_much_time_passed
) {
151 if (request_
->load_flags() & net::LOAD_ENABLE_UPLOAD_PROGRESS
) {
152 handler_
->OnUploadProgress(progress
.position(), progress
.size());
153 waiting_for_upload_progress_ack_
= true;
155 last_upload_ticks_
= TimeTicks::Now();
156 last_upload_position_
= progress
.position();
160 void ResourceLoader::MarkAsTransferring() {
161 CHECK(ResourceType::IsFrame(GetRequestInfo()->GetResourceType()))
162 << "Can only transfer for navigations";
163 is_transferring_
= true;
166 void ResourceLoader::CompleteTransfer() {
167 // Although CrossSiteResourceHandler defers at OnResponseStarted
168 // (DEFERRED_READ), it may be seeing a replay of events via
169 // BufferedResourceHandler, and so the request itself is actually deferred at
170 // a later read stage.
171 DCHECK(DEFERRED_READ
== deferred_stage_
||
172 DEFERRED_RESPONSE_COMPLETE
== deferred_stage_
);
174 is_transferring_
= false;
175 GetRequestInfo()->cross_site_handler()->ResumeResponse();
178 ResourceRequestInfoImpl
* ResourceLoader::GetRequestInfo() {
179 return ResourceRequestInfoImpl::ForRequest(request_
.get());
182 void ResourceLoader::ClearLoginDelegate() {
183 login_delegate_
= NULL
;
186 void ResourceLoader::ClearSSLClientAuthHandler() {
187 ssl_client_auth_handler_
= NULL
;
190 void ResourceLoader::OnUploadProgressACK() {
191 waiting_for_upload_progress_ack_
= false;
194 void ResourceLoader::OnReceivedRedirect(net::URLRequest
* unused
,
197 DCHECK_EQ(request_
.get(), unused
);
199 VLOG(1) << "OnReceivedRedirect: " << request_
->url().spec();
200 DCHECK(request_
->status().is_success());
202 ResourceRequestInfoImpl
* info
= GetRequestInfo();
204 if (info
->GetProcessType() != PROCESS_TYPE_PLUGIN
&&
205 !ChildProcessSecurityPolicyImpl::GetInstance()->
206 CanRequestURL(info
->GetChildID(), new_url
)) {
207 VLOG(1) << "Denied unauthorized request for "
208 << new_url
.possibly_invalid_spec();
210 // Tell the renderer that this request was disallowed.
215 delegate_
->DidReceiveRedirect(this, new_url
);
217 if (delegate_
->HandleExternalProtocol(this, new_url
)) {
218 // The request is complete so we can remove it.
223 scoped_refptr
<ResourceResponse
> response(new ResourceResponse());
224 PopulateResourceResponse(request_
.get(), response
.get());
226 if (!handler_
->OnRequestRedirected(new_url
, response
.get(), defer
)) {
229 deferred_stage_
= DEFERRED_REDIRECT
; // Follow redirect when resumed.
233 void ResourceLoader::OnAuthRequired(net::URLRequest
* unused
,
234 net::AuthChallengeInfo
* auth_info
) {
235 DCHECK_EQ(request_
.get(), unused
);
237 if (request_
->load_flags() & net::LOAD_DO_NOT_PROMPT_FOR_LOGIN
) {
238 request_
->CancelAuth();
242 // Create a login dialog on the UI thread to get authentication data, or pull
243 // from cache and continue on the IO thread.
245 DCHECK(!login_delegate_
.get())
246 << "OnAuthRequired called with login_delegate pending";
247 login_delegate_
= delegate_
->CreateLoginDelegate(this, auth_info
);
248 if (!login_delegate_
.get())
249 request_
->CancelAuth();
252 void ResourceLoader::OnCertificateRequested(
253 net::URLRequest
* unused
,
254 net::SSLCertRequestInfo
* cert_info
) {
255 DCHECK_EQ(request_
.get(), unused
);
257 if (request_
->load_flags() & net::LOAD_PREFETCH
) {
262 DCHECK(!ssl_client_auth_handler_
.get())
263 << "OnCertificateRequested called with ssl_client_auth_handler pending";
264 ssl_client_auth_handler_
= new SSLClientAuthHandler(
265 GetRequestInfo()->GetContext()->CreateClientCertStore(),
268 ssl_client_auth_handler_
->SelectCertificate();
271 void ResourceLoader::OnSSLCertificateError(net::URLRequest
* request
,
272 const net::SSLInfo
& ssl_info
,
274 ResourceRequestInfoImpl
* info
= GetRequestInfo();
276 int render_process_id
;
278 if (!info
->GetAssociatedRenderFrame(&render_process_id
, &render_frame_id
))
281 SSLManager::OnSSLCertificateError(
282 weak_ptr_factory_
.GetWeakPtr(),
283 info
->GetGlobalRequestID(),
284 info
->GetResourceType(),
292 void ResourceLoader::OnBeforeNetworkStart(net::URLRequest
* unused
,
294 DCHECK_EQ(request_
.get(), unused
);
296 // Give the handler a chance to delay the URLRequest from using the network.
297 if (!handler_
->OnBeforeNetworkStart(request_
->url(), defer
)) {
301 deferred_stage_
= DEFERRED_NETWORK_START
;
305 void ResourceLoader::OnResponseStarted(net::URLRequest
* unused
) {
306 DCHECK_EQ(request_
.get(), unused
);
308 VLOG(1) << "OnResponseStarted: " << request_
->url().spec();
310 // The CanLoadPage check should take place after any server redirects have
311 // finished, at the point in time that we know a page will commit in the
313 ResourceRequestInfoImpl
* info
= GetRequestInfo();
314 ChildProcessSecurityPolicyImpl
* policy
=
315 ChildProcessSecurityPolicyImpl::GetInstance();
316 if (!policy
->CanLoadPage(info
->GetChildID(),
318 info
->GetResourceType())) {
323 if (!request_
->status().is_success()) {
328 // We want to send a final upload progress message prior to sending the
329 // response complete message even if we're waiting for an ack to to a
330 // previous upload progress message.
331 waiting_for_upload_progress_ack_
= false;
332 ReportUploadProgress();
334 CompleteResponseStarted();
339 if (request_
->status().is_success()) {
340 StartReading(false); // Read the first chunk.
346 void ResourceLoader::OnReadCompleted(net::URLRequest
* unused
, int bytes_read
) {
347 DCHECK_EQ(request_
.get(), unused
);
348 VLOG(1) << "OnReadCompleted: \"" << request_
->url().spec() << "\""
349 << " bytes_read = " << bytes_read
;
351 // bytes_read == -1 always implies an error.
352 if (bytes_read
== -1 || !request_
->status().is_success()) {
357 CompleteRead(bytes_read
);
359 // If the handler cancelled or deferred the request, do not continue
360 // processing the read. If cancelled, the URLRequest has already been
361 // cancelled and will schedule an erroring OnReadCompleted later. If deferred,
362 // do nothing until resumed.
364 // Note: if bytes_read is 0 (EOF) and the handler defers, resumption will call
365 // ResponseCompleted().
366 if (is_deferred() || !request_
->status().is_success())
369 if (bytes_read
> 0) {
370 StartReading(true); // Read the next chunk.
372 // URLRequest reported an EOF. Call ResponseCompleted.
373 DCHECK_EQ(0, bytes_read
);
378 void ResourceLoader::CancelSSLRequest(const GlobalRequestID
& id
,
380 const net::SSLInfo
* ssl_info
) {
381 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
383 // The request can be NULL if it was cancelled by the renderer (as the
384 // request of the user navigating to a new page from the location bar).
385 if (!request_
->is_pending())
387 DVLOG(1) << "CancelSSLRequest() url: " << request_
->url().spec();
390 request_
->CancelWithSSLError(error
, *ssl_info
);
392 request_
->CancelWithError(error
);
396 void ResourceLoader::ContinueSSLRequest(const GlobalRequestID
& id
) {
397 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
399 DVLOG(1) << "ContinueSSLRequest() url: " << request_
->url().spec();
401 request_
->ContinueDespiteLastError();
404 void ResourceLoader::Resume() {
405 DCHECK(!is_transferring_
);
407 DeferredStage stage
= deferred_stage_
;
408 deferred_stage_
= DEFERRED_NONE
;
414 StartRequestInternal();
416 case DEFERRED_NETWORK_START
:
417 request_
->ResumeNetworkStart();
419 case DEFERRED_REDIRECT
:
420 request_
->FollowDeferredRedirect();
423 base::MessageLoop::current()->PostTask(
425 base::Bind(&ResourceLoader::ResumeReading
,
426 weak_ptr_factory_
.GetWeakPtr()));
428 case DEFERRED_RESPONSE_COMPLETE
:
429 base::MessageLoop::current()->PostTask(
431 base::Bind(&ResourceLoader::ResponseCompleted
,
432 weak_ptr_factory_
.GetWeakPtr()));
434 case DEFERRED_FINISH
:
435 // Delay self-destruction since we don't know how we were reached.
436 base::MessageLoop::current()->PostTask(
438 base::Bind(&ResourceLoader::CallDidFinishLoading
,
439 weak_ptr_factory_
.GetWeakPtr()));
444 void ResourceLoader::Cancel() {
445 CancelRequest(false);
448 void ResourceLoader::StartRequestInternal() {
449 DCHECK(!request_
->is_pending());
451 if (!request_
->status().is_success()) {
457 delegate_
->DidStartRequest(this);
460 void ResourceLoader::CancelRequestInternal(int error
, bool from_renderer
) {
461 VLOG(1) << "CancelRequestInternal: " << request_
->url().spec();
463 ResourceRequestInfoImpl
* info
= GetRequestInfo();
465 // WebKit will send us a cancel for downloads since it no longer handles
466 // them. In this case, ignore the cancel since we handle downloads in the
468 if (from_renderer
&& (info
->IsDownload() || info
->is_stream()))
471 if (from_renderer
&& info
->detachable_handler()) {
472 // TODO(davidben): Fix Blink handling of prefetches so they are not
473 // cancelled on navigate away and end up in the local cache.
474 info
->detachable_handler()->Detach();
478 // TODO(darin): Perhaps we should really be looking to see if the status is
480 bool was_pending
= request_
->is_pending();
482 if (login_delegate_
.get()) {
483 login_delegate_
->OnRequestCancelled();
484 login_delegate_
= NULL
;
486 if (ssl_client_auth_handler_
.get()) {
487 ssl_client_auth_handler_
->OnRequestCancelled();
488 ssl_client_auth_handler_
= NULL
;
491 request_
->CancelWithError(error
);
494 // If the request isn't in flight, then we won't get an asynchronous
495 // notification from the request, so we have to signal ourselves to finish
497 base::MessageLoop::current()->PostTask(
499 base::Bind(&ResourceLoader::ResponseCompleted
,
500 weak_ptr_factory_
.GetWeakPtr()));
504 void ResourceLoader::StoreSignedCertificateTimestamps(
505 const net::SignedCertificateTimestampAndStatusList
& sct_list
,
507 SignedCertificateTimestampIDStatusList
* sct_ids
) {
508 SignedCertificateTimestampStore
* sct_store(
509 SignedCertificateTimestampStore::GetInstance());
511 for (net::SignedCertificateTimestampAndStatusList::const_iterator iter
=
512 sct_list
.begin(); iter
!= sct_list
.end(); ++iter
) {
513 const int sct_id(sct_store
->Store(iter
->sct
, process_id
));
515 SignedCertificateTimestampIDAndStatus(sct_id
, iter
->status
));
519 void ResourceLoader::CompleteResponseStarted() {
520 ResourceRequestInfoImpl
* info
= GetRequestInfo();
522 scoped_refptr
<ResourceResponse
> response(new ResourceResponse());
523 PopulateResourceResponse(request_
.get(), response
.get());
525 if (request_
->ssl_info().cert
.get()) {
526 int cert_id
= CertStore::GetInstance()->StoreCert(
527 request_
->ssl_info().cert
.get(), info
->GetChildID());
529 SignedCertificateTimestampIDStatusList signed_certificate_timestamp_ids
;
530 StoreSignedCertificateTimestamps(
531 request_
->ssl_info().signed_certificate_timestamps
,
533 &signed_certificate_timestamp_ids
);
535 response
->head
.security_info
= SerializeSecurityInfo(
537 request_
->ssl_info().cert_status
,
538 request_
->ssl_info().security_bits
,
539 request_
->ssl_info().connection_status
,
540 signed_certificate_timestamp_ids
);
542 // We should not have any SSL state.
543 DCHECK(!request_
->ssl_info().cert_status
&&
544 request_
->ssl_info().security_bits
== -1 &&
545 !request_
->ssl_info().connection_status
);
548 delegate_
->DidReceiveResponse(this);
551 if (!handler_
->OnResponseStarted(response
.get(), &defer
)) {
554 read_deferral_start_time_
= base::TimeTicks::Now();
555 deferred_stage_
= DEFERRED_READ
; // Read first chunk when resumed.
559 void ResourceLoader::StartReading(bool is_continuation
) {
561 ReadMore(&bytes_read
);
563 // If IO is pending, wait for the URLRequest to call OnReadCompleted.
564 if (request_
->status().is_io_pending())
567 if (!is_continuation
|| bytes_read
<= 0) {
568 OnReadCompleted(request_
.get(), bytes_read
);
570 // Else, trigger OnReadCompleted asynchronously to avoid starving the IO
571 // thread in case the URLRequest can provide data synchronously.
572 base::MessageLoop::current()->PostTask(
574 base::Bind(&ResourceLoader::OnReadCompleted
,
575 weak_ptr_factory_
.GetWeakPtr(),
581 void ResourceLoader::ResumeReading() {
582 DCHECK(!is_deferred());
584 if (!read_deferral_start_time_
.is_null()) {
585 UMA_HISTOGRAM_TIMES("Net.ResourceLoader.ReadDeferral",
586 base::TimeTicks::Now() - read_deferral_start_time_
);
587 read_deferral_start_time_
= base::TimeTicks();
589 if (request_
->status().is_success()) {
590 StartReading(false); // Read the next chunk (OK to complete synchronously).
596 void ResourceLoader::ReadMore(int* bytes_read
) {
597 DCHECK(!is_deferred());
599 // Make sure we track the buffer in at least one place. This ensures it gets
600 // deleted even in the case the request has already finished its job and
601 // doesn't use the buffer.
602 scoped_refptr
<net::IOBuffer
> buf
;
604 if (!handler_
->OnWillRead(&buf
, &buf_size
, -1)) {
610 DCHECK(buf_size
> 0);
612 request_
->Read(buf
.get(), buf_size
, bytes_read
);
614 // No need to check the return value here as we'll detect errors by
615 // inspecting the URLRequest's status.
618 void ResourceLoader::CompleteRead(int bytes_read
) {
619 DCHECK(bytes_read
>= 0);
620 DCHECK(request_
->status().is_success());
623 if (!handler_
->OnReadCompleted(bytes_read
, &defer
)) {
627 bytes_read
> 0 ? DEFERRED_READ
: DEFERRED_RESPONSE_COMPLETE
;
630 // Note: the request may still have been cancelled while OnReadCompleted
631 // returns true if OnReadCompleted caused request to get cancelled
632 // out-of-band. (In AwResourceDispatcherHostDelegate::DownloadStarting, for
636 void ResourceLoader::ResponseCompleted() {
637 VLOG(1) << "ResponseCompleted: " << request_
->url().spec();
639 ResourceRequestInfoImpl
* info
= GetRequestInfo();
641 std::string security_info
;
642 const net::SSLInfo
& ssl_info
= request_
->ssl_info();
643 if (ssl_info
.cert
.get() != NULL
) {
644 int cert_id
= CertStore::GetInstance()->StoreCert(ssl_info
.cert
.get(),
646 SignedCertificateTimestampIDStatusList signed_certificate_timestamp_ids
;
647 StoreSignedCertificateTimestamps(ssl_info
.signed_certificate_timestamps
,
649 &signed_certificate_timestamp_ids
);
651 security_info
= SerializeSecurityInfo(
652 cert_id
, ssl_info
.cert_status
, ssl_info
.security_bits
,
653 ssl_info
.connection_status
, signed_certificate_timestamp_ids
);
657 handler_
->OnResponseCompleted(request_
->status(), security_info
, &defer
);
659 // The handler is not ready to die yet. We will call DidFinishLoading when
661 deferred_stage_
= DEFERRED_FINISH
;
663 // This will result in our destruction.
664 CallDidFinishLoading();
668 void ResourceLoader::CallDidFinishLoading() {
669 delegate_
->DidFinishLoading(this);
672 void ResourceLoader::RecordHistograms() {
673 ResourceRequestInfoImpl
* info
= GetRequestInfo();
675 if (info
->GetResourceType() == ResourceType::PREFETCH
) {
676 PrefetchStatus status
= STATUS_UNDEFINED
;
677 TimeDelta total_time
= base::TimeTicks::Now() - request_
->creation_time();
679 switch (request_
->status().status()) {
680 case net::URLRequestStatus::SUCCESS
:
681 if (request_
->was_cached()) {
682 status
= STATUS_SUCCESS_FROM_CACHE
;
683 UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeSpentPrefetchingFromCache",
686 status
= STATUS_SUCCESS_FROM_NETWORK
;
687 UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeSpentPrefetchingFromNetwork",
691 case net::URLRequestStatus::CANCELED
:
692 status
= STATUS_CANCELED
;
693 UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeBeforeCancel", total_time
);
695 case net::URLRequestStatus::IO_PENDING
:
696 case net::URLRequestStatus::FAILED
:
697 status
= STATUS_UNDEFINED
;
701 UMA_HISTOGRAM_ENUMERATION("Net.Prefetch.Pattern", status
, STATUS_MAX
);
705 } // namespace content