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/child_process_security_policy_impl.h"
12 #include "content/browser/loader/cross_site_resource_handler.h"
13 #include "content/browser/loader/detachable_resource_handler.h"
14 #include "content/browser/loader/resource_loader_delegate.h"
15 #include "content/browser/loader/resource_request_info_impl.h"
16 #include "content/browser/ssl/ssl_client_auth_handler.h"
17 #include "content/browser/ssl/ssl_manager.h"
18 #include "content/common/ssl_status_serialization.h"
19 #include "content/public/browser/cert_store.h"
20 #include "content/public/browser/resource_context.h"
21 #include "content/public/browser/resource_dispatcher_host_login_delegate.h"
22 #include "content/public/browser/signed_certificate_timestamp_store.h"
23 #include "content/public/common/content_client.h"
24 #include "content/public/common/content_switches.h"
25 #include "content/public/common/process_type.h"
26 #include "content/public/common/resource_response.h"
27 #include "net/base/io_buffer.h"
28 #include "net/base/load_flags.h"
29 #include "net/http/http_response_headers.h"
30 #include "net/ssl/client_cert_store.h"
31 #include "net/url_request/url_request_status.h"
32 #include "webkit/browser/appcache/appcache_interceptor.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 appcache::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(GetRequestInfo()->GetRequestID(), request_
->url(),
109 deferred_stage_
= DEFERRED_START
;
111 StartRequestInternal();
115 void ResourceLoader::CancelRequest(bool from_renderer
) {
116 CancelRequestInternal(net::ERR_ABORTED
, from_renderer
);
119 void ResourceLoader::CancelAndIgnore() {
120 ResourceRequestInfoImpl
* info
= GetRequestInfo();
121 info
->set_was_ignored_by_handler(true);
122 CancelRequest(false);
125 void ResourceLoader::CancelWithError(int error_code
) {
126 CancelRequestInternal(error_code
, false);
129 void ResourceLoader::ReportUploadProgress() {
130 ResourceRequestInfoImpl
* info
= GetRequestInfo();
132 if (waiting_for_upload_progress_ack_
)
133 return; // Send one progress event at a time.
135 net::UploadProgress progress
= request_
->GetUploadProgress();
136 if (!progress
.size())
137 return; // Nothing to upload.
139 if (progress
.position() == last_upload_position_
)
140 return; // No progress made since last time.
142 const uint64 kHalfPercentIncrements
= 200;
143 const TimeDelta kOneSecond
= TimeDelta::FromMilliseconds(1000);
145 uint64 amt_since_last
= progress
.position() - last_upload_position_
;
146 TimeDelta time_since_last
= TimeTicks::Now() - last_upload_ticks_
;
148 bool is_finished
= (progress
.size() == progress
.position());
149 bool enough_new_progress
=
150 (amt_since_last
> (progress
.size() / kHalfPercentIncrements
));
151 bool too_much_time_passed
= time_since_last
> kOneSecond
;
153 if (is_finished
|| enough_new_progress
|| too_much_time_passed
) {
154 if (request_
->load_flags() & net::LOAD_ENABLE_UPLOAD_PROGRESS
) {
155 handler_
->OnUploadProgress(
156 info
->GetRequestID(), progress
.position(), progress
.size());
157 waiting_for_upload_progress_ack_
= true;
159 last_upload_ticks_
= TimeTicks::Now();
160 last_upload_position_
= progress
.position();
164 void ResourceLoader::MarkAsTransferring() {
165 CHECK(ResourceType::IsFrame(GetRequestInfo()->GetResourceType()))
166 << "Can only transfer for navigations";
167 is_transferring_
= true;
170 void ResourceLoader::CompleteTransfer() {
171 DCHECK_EQ(DEFERRED_READ
, deferred_stage_
);
173 is_transferring_
= false;
174 GetRequestInfo()->cross_site_handler()->ResumeResponse();
177 ResourceRequestInfoImpl
* ResourceLoader::GetRequestInfo() {
178 return ResourceRequestInfoImpl::ForRequest(request_
.get());
181 void ResourceLoader::ClearLoginDelegate() {
182 login_delegate_
= NULL
;
185 void ResourceLoader::ClearSSLClientAuthHandler() {
186 ssl_client_auth_handler_
= NULL
;
189 void ResourceLoader::OnUploadProgressACK() {
190 waiting_for_upload_progress_ack_
= false;
193 void ResourceLoader::OnReceivedRedirect(net::URLRequest
* unused
,
196 DCHECK_EQ(request_
.get(), unused
);
198 VLOG(1) << "OnReceivedRedirect: " << request_
->url().spec();
199 DCHECK(request_
->status().is_success());
201 ResourceRequestInfoImpl
* info
= GetRequestInfo();
203 if (info
->GetProcessType() != PROCESS_TYPE_PLUGIN
&&
204 !ChildProcessSecurityPolicyImpl::GetInstance()->
205 CanRequestURL(info
->GetChildID(), new_url
)) {
206 VLOG(1) << "Denied unauthorized request for "
207 << new_url
.possibly_invalid_spec();
209 // Tell the renderer that this request was disallowed.
214 delegate_
->DidReceiveRedirect(this, new_url
);
216 if (delegate_
->HandleExternalProtocol(this, new_url
)) {
217 // The request is complete so we can remove it.
222 scoped_refptr
<ResourceResponse
> response(new ResourceResponse());
223 PopulateResourceResponse(request_
.get(), response
.get());
225 if (!handler_
->OnRequestRedirected(
226 info
->GetRequestID(), 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(
298 GetRequestInfo()->GetRequestID(), request_
->url(), defer
)) {
302 deferred_stage_
= DEFERRED_NETWORK_START
;
306 void ResourceLoader::OnResponseStarted(net::URLRequest
* unused
) {
307 DCHECK_EQ(request_
.get(), unused
);
309 VLOG(1) << "OnResponseStarted: " << request_
->url().spec();
311 // The CanLoadPage check should take place after any server redirects have
312 // finished, at the point in time that we know a page will commit in the
314 ResourceRequestInfoImpl
* info
= GetRequestInfo();
315 ChildProcessSecurityPolicyImpl
* policy
=
316 ChildProcessSecurityPolicyImpl::GetInstance();
317 if (!policy
->CanLoadPage(info
->GetChildID(),
319 info
->GetResourceType())) {
324 if (!request_
->status().is_success()) {
329 // We want to send a final upload progress message prior to sending the
330 // response complete message even if we're waiting for an ack to to a
331 // previous upload progress message.
332 waiting_for_upload_progress_ack_
= false;
333 ReportUploadProgress();
335 CompleteResponseStarted();
340 if (request_
->status().is_success()) {
341 StartReading(false); // Read the first chunk.
347 void ResourceLoader::OnReadCompleted(net::URLRequest
* unused
, int bytes_read
) {
348 DCHECK_EQ(request_
.get(), unused
);
349 VLOG(1) << "OnReadCompleted: \"" << request_
->url().spec() << "\""
350 << " bytes_read = " << bytes_read
;
352 // bytes_read == -1 always implies an error.
353 if (bytes_read
== -1 || !request_
->status().is_success()) {
358 CompleteRead(bytes_read
);
363 if (request_
->status().is_success() && bytes_read
> 0) {
364 StartReading(true); // Read the next chunk.
370 void ResourceLoader::CancelSSLRequest(const GlobalRequestID
& id
,
372 const net::SSLInfo
* ssl_info
) {
373 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
375 // The request can be NULL if it was cancelled by the renderer (as the
376 // request of the user navigating to a new page from the location bar).
377 if (!request_
->is_pending())
379 DVLOG(1) << "CancelSSLRequest() url: " << request_
->url().spec();
382 request_
->CancelWithSSLError(error
, *ssl_info
);
384 request_
->CancelWithError(error
);
388 void ResourceLoader::ContinueSSLRequest(const GlobalRequestID
& id
) {
389 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO
));
391 DVLOG(1) << "ContinueSSLRequest() url: " << request_
->url().spec();
393 request_
->ContinueDespiteLastError();
396 void ResourceLoader::Resume() {
397 DCHECK(!is_transferring_
);
399 DeferredStage stage
= deferred_stage_
;
400 deferred_stage_
= DEFERRED_NONE
;
406 StartRequestInternal();
408 case DEFERRED_NETWORK_START
:
409 request_
->ResumeNetworkStart();
411 case DEFERRED_REDIRECT
:
412 request_
->FollowDeferredRedirect();
415 base::MessageLoop::current()->PostTask(
417 base::Bind(&ResourceLoader::ResumeReading
,
418 weak_ptr_factory_
.GetWeakPtr()));
420 case DEFERRED_FINISH
:
421 // Delay self-destruction since we don't know how we were reached.
422 base::MessageLoop::current()->PostTask(
424 base::Bind(&ResourceLoader::CallDidFinishLoading
,
425 weak_ptr_factory_
.GetWeakPtr()));
430 void ResourceLoader::Cancel() {
431 CancelRequest(false);
434 void ResourceLoader::StartRequestInternal() {
435 DCHECK(!request_
->is_pending());
437 if (!request_
->status().is_success()) {
443 delegate_
->DidStartRequest(this);
446 void ResourceLoader::CancelRequestInternal(int error
, bool from_renderer
) {
447 VLOG(1) << "CancelRequestInternal: " << request_
->url().spec();
449 ResourceRequestInfoImpl
* info
= GetRequestInfo();
451 // WebKit will send us a cancel for downloads since it no longer handles
452 // them. In this case, ignore the cancel since we handle downloads in the
454 if (from_renderer
&& (info
->IsDownload() || info
->is_stream()))
457 if (from_renderer
&& info
->detachable_handler()) {
458 // TODO(davidben): Fix Blink handling of prefetches so they are not
459 // cancelled on navigate away and end up in the local cache.
460 info
->detachable_handler()->Detach();
464 // TODO(darin): Perhaps we should really be looking to see if the status is
466 bool was_pending
= request_
->is_pending();
468 if (login_delegate_
.get()) {
469 login_delegate_
->OnRequestCancelled();
470 login_delegate_
= NULL
;
472 if (ssl_client_auth_handler_
.get()) {
473 ssl_client_auth_handler_
->OnRequestCancelled();
474 ssl_client_auth_handler_
= NULL
;
477 request_
->CancelWithError(error
);
480 // If the request isn't in flight, then we won't get an asynchronous
481 // notification from the request, so we have to signal ourselves to finish
483 base::MessageLoop::current()->PostTask(
485 base::Bind(&ResourceLoader::ResponseCompleted
,
486 weak_ptr_factory_
.GetWeakPtr()));
490 void ResourceLoader::StoreSignedCertificateTimestamps(
491 const net::SignedCertificateTimestampAndStatusList
& sct_list
,
493 SignedCertificateTimestampIDStatusList
* sct_ids
) {
494 SignedCertificateTimestampStore
* sct_store(
495 SignedCertificateTimestampStore::GetInstance());
497 for (net::SignedCertificateTimestampAndStatusList::const_iterator iter
=
498 sct_list
.begin(); iter
!= sct_list
.end(); ++iter
) {
499 const int sct_id(sct_store
->Store(iter
->sct
, process_id
));
501 SignedCertificateTimestampIDAndStatus(sct_id
, iter
->status
));
505 void ResourceLoader::CompleteResponseStarted() {
506 ResourceRequestInfoImpl
* info
= GetRequestInfo();
508 scoped_refptr
<ResourceResponse
> response(new ResourceResponse());
509 PopulateResourceResponse(request_
.get(), response
.get());
511 if (request_
->ssl_info().cert
.get()) {
512 int cert_id
= CertStore::GetInstance()->StoreCert(
513 request_
->ssl_info().cert
.get(), info
->GetChildID());
515 SignedCertificateTimestampIDStatusList signed_certificate_timestamp_ids
;
516 StoreSignedCertificateTimestamps(
517 request_
->ssl_info().signed_certificate_timestamps
,
519 &signed_certificate_timestamp_ids
);
521 response
->head
.security_info
= SerializeSecurityInfo(
523 request_
->ssl_info().cert_status
,
524 request_
->ssl_info().security_bits
,
525 request_
->ssl_info().connection_status
,
526 signed_certificate_timestamp_ids
);
528 // We should not have any SSL state.
529 DCHECK(!request_
->ssl_info().cert_status
&&
530 request_
->ssl_info().security_bits
== -1 &&
531 !request_
->ssl_info().connection_status
);
534 delegate_
->DidReceiveResponse(this);
537 if (!handler_
->OnResponseStarted(
538 info
->GetRequestID(), response
.get(), &defer
)) {
541 read_deferral_start_time_
= base::TimeTicks::Now();
542 deferred_stage_
= DEFERRED_READ
; // Read first chunk when resumed.
546 void ResourceLoader::StartReading(bool is_continuation
) {
548 ReadMore(&bytes_read
);
550 // If IO is pending, wait for the URLRequest to call OnReadCompleted.
551 if (request_
->status().is_io_pending())
554 if (!is_continuation
|| bytes_read
<= 0) {
555 OnReadCompleted(request_
.get(), bytes_read
);
557 // Else, trigger OnReadCompleted asynchronously to avoid starving the IO
558 // thread in case the URLRequest can provide data synchronously.
559 base::MessageLoop::current()->PostTask(
561 base::Bind(&ResourceLoader::OnReadCompleted
,
562 weak_ptr_factory_
.GetWeakPtr(),
568 void ResourceLoader::ResumeReading() {
569 DCHECK(!is_deferred());
571 if (!read_deferral_start_time_
.is_null()) {
572 UMA_HISTOGRAM_TIMES("Net.ResourceLoader.ReadDeferral",
573 base::TimeTicks::Now() - read_deferral_start_time_
);
574 read_deferral_start_time_
= base::TimeTicks();
576 if (request_
->status().is_success()) {
577 StartReading(false); // Read the next chunk (OK to complete synchronously).
583 void ResourceLoader::ReadMore(int* bytes_read
) {
584 ResourceRequestInfoImpl
* info
= GetRequestInfo();
585 DCHECK(!is_deferred());
587 // Make sure we track the buffer in at least one place. This ensures it gets
588 // deleted even in the case the request has already finished its job and
589 // doesn't use the buffer.
590 scoped_refptr
<net::IOBuffer
> buf
;
592 if (!handler_
->OnWillRead(info
->GetRequestID(), &buf
, &buf_size
, -1)) {
598 DCHECK(buf_size
> 0);
600 request_
->Read(buf
.get(), buf_size
, bytes_read
);
602 // No need to check the return value here as we'll detect errors by
603 // inspecting the URLRequest's status.
606 void ResourceLoader::CompleteRead(int bytes_read
) {
607 DCHECK(bytes_read
>= 0);
608 DCHECK(request_
->status().is_success());
610 ResourceRequestInfoImpl
* info
= GetRequestInfo();
613 if (!handler_
->OnReadCompleted(info
->GetRequestID(), bytes_read
, &defer
)) {
616 deferred_stage_
= DEFERRED_READ
; // Read next chunk when resumed.
620 void ResourceLoader::ResponseCompleted() {
621 VLOG(1) << "ResponseCompleted: " << request_
->url().spec();
623 ResourceRequestInfoImpl
* info
= GetRequestInfo();
625 std::string security_info
;
626 const net::SSLInfo
& ssl_info
= request_
->ssl_info();
627 if (ssl_info
.cert
.get() != NULL
) {
628 int cert_id
= CertStore::GetInstance()->StoreCert(ssl_info
.cert
.get(),
630 SignedCertificateTimestampIDStatusList signed_certificate_timestamp_ids
;
631 StoreSignedCertificateTimestamps(ssl_info
.signed_certificate_timestamps
,
633 &signed_certificate_timestamp_ids
);
635 security_info
= SerializeSecurityInfo(
636 cert_id
, ssl_info
.cert_status
, ssl_info
.security_bits
,
637 ssl_info
.connection_status
, signed_certificate_timestamp_ids
);
641 handler_
->OnResponseCompleted(info
->GetRequestID(), request_
->status(),
642 security_info
, &defer
);
644 // The handler is not ready to die yet. We will call DidFinishLoading when
646 deferred_stage_
= DEFERRED_FINISH
;
648 // This will result in our destruction.
649 CallDidFinishLoading();
653 void ResourceLoader::CallDidFinishLoading() {
654 delegate_
->DidFinishLoading(this);
657 void ResourceLoader::RecordHistograms() {
658 ResourceRequestInfoImpl
* info
= GetRequestInfo();
660 if (info
->GetResourceType() == ResourceType::PREFETCH
) {
661 PrefetchStatus status
= STATUS_UNDEFINED
;
662 TimeDelta total_time
= base::TimeTicks::Now() - request_
->creation_time();
664 switch (request_
->status().status()) {
665 case net::URLRequestStatus::SUCCESS
:
666 if (request_
->was_cached()) {
667 status
= STATUS_SUCCESS_FROM_CACHE
;
668 UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeSpentPrefetchingFromCache",
671 status
= STATUS_SUCCESS_FROM_NETWORK
;
672 UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeSpentPrefetchingFromNetwork",
676 case net::URLRequestStatus::CANCELED
:
677 status
= STATUS_CANCELED
;
678 UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeBeforeCancel", total_time
);
680 case net::URLRequestStatus::IO_PENDING
:
681 case net::URLRequestStatus::FAILED
:
682 status
= STATUS_UNDEFINED
;
686 UMA_HISTOGRAM_ENUMERATION("Net.Prefetch.Pattern", status
, STATUS_MAX
);
690 } // namespace content