Remove PlatformFile from profile_browsertest
[chromium-blink-merge.git] / content / browser / loader / resource_loader.cc
blob02e9a1c1b32692720b9a0598823bdf1c1a769343
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;
37 namespace content {
38 namespace {
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(
58 request,
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);
66 } // namespace
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()),
74 delegate_(delegate),
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.
91 handler_.reset();
94 void ResourceLoader::StartRequest() {
95 if (delegate_->HandleExternalProtocol(this, request_->url())) {
96 CancelAndIgnore();
97 return;
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(),
103 &defer_start)) {
104 Cancel();
105 return;
108 if (defer_start) {
109 deferred_stage_ = DEFERRED_START;
110 } else {
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,
194 const GURL& new_url,
195 bool* defer) {
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.
210 Cancel();
211 return;
214 delegate_->DidReceiveRedirect(this, new_url);
216 if (delegate_->HandleExternalProtocol(this, new_url)) {
217 // The request is complete so we can remove it.
218 CancelAndIgnore();
219 return;
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)) {
227 Cancel();
228 } else if (*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();
239 return;
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) {
258 request_->Cancel();
259 return;
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(),
266 request_.get(),
267 cert_info);
268 ssl_client_auth_handler_->SelectCertificate();
271 void ResourceLoader::OnSSLCertificateError(net::URLRequest* request,
272 const net::SSLInfo& ssl_info,
273 bool fatal) {
274 ResourceRequestInfoImpl* info = GetRequestInfo();
276 int render_process_id;
277 int render_frame_id;
278 if (!info->GetAssociatedRenderFrame(&render_process_id, &render_frame_id))
279 NOTREACHED();
281 SSLManager::OnSSLCertificateError(
282 weak_ptr_factory_.GetWeakPtr(),
283 info->GetGlobalRequestID(),
284 info->GetResourceType(),
285 request_->url(),
286 render_process_id,
287 render_frame_id,
288 ssl_info,
289 fatal);
292 void ResourceLoader::OnBeforeNetworkStart(net::URLRequest* unused,
293 bool* defer) {
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)) {
299 Cancel();
300 return;
301 } else if (*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
313 // renderer process.
314 ResourceRequestInfoImpl* info = GetRequestInfo();
315 ChildProcessSecurityPolicyImpl* policy =
316 ChildProcessSecurityPolicyImpl::GetInstance();
317 if (!policy->CanLoadPage(info->GetChildID(),
318 request_->url(),
319 info->GetResourceType())) {
320 Cancel();
321 return;
324 if (!request_->status().is_success()) {
325 ResponseCompleted();
326 return;
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();
337 if (is_deferred())
338 return;
340 if (request_->status().is_success()) {
341 StartReading(false); // Read the first chunk.
342 } else {
343 ResponseCompleted();
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()) {
354 ResponseCompleted();
355 return;
358 CompleteRead(bytes_read);
360 if (is_deferred())
361 return;
363 if (request_->status().is_success() && bytes_read > 0) {
364 StartReading(true); // Read the next chunk.
365 } else {
366 ResponseCompleted();
370 void ResourceLoader::CancelSSLRequest(const GlobalRequestID& id,
371 int error,
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())
378 return;
379 DVLOG(1) << "CancelSSLRequest() url: " << request_->url().spec();
381 if (ssl_info) {
382 request_->CancelWithSSLError(error, *ssl_info);
383 } else {
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;
401 switch (stage) {
402 case DEFERRED_NONE:
403 NOTREACHED();
404 break;
405 case DEFERRED_START:
406 StartRequestInternal();
407 break;
408 case DEFERRED_NETWORK_START:
409 request_->ResumeNetworkStart();
410 break;
411 case DEFERRED_REDIRECT:
412 request_->FollowDeferredRedirect();
413 break;
414 case DEFERRED_READ:
415 base::MessageLoop::current()->PostTask(
416 FROM_HERE,
417 base::Bind(&ResourceLoader::ResumeReading,
418 weak_ptr_factory_.GetWeakPtr()));
419 break;
420 case DEFERRED_FINISH:
421 // Delay self-destruction since we don't know how we were reached.
422 base::MessageLoop::current()->PostTask(
423 FROM_HERE,
424 base::Bind(&ResourceLoader::CallDidFinishLoading,
425 weak_ptr_factory_.GetWeakPtr()));
426 break;
430 void ResourceLoader::Cancel() {
431 CancelRequest(false);
434 void ResourceLoader::StartRequestInternal() {
435 DCHECK(!request_->is_pending());
437 if (!request_->status().is_success()) {
438 return;
441 request_->Start();
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
453 // browser.
454 if (from_renderer && (info->IsDownload() || info->is_stream()))
455 return;
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();
461 return;
464 // TODO(darin): Perhaps we should really be looking to see if the status is
465 // IO_PENDING?
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);
479 if (!was_pending) {
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
482 // this request.
483 base::MessageLoop::current()->PostTask(
484 FROM_HERE,
485 base::Bind(&ResourceLoader::ResponseCompleted,
486 weak_ptr_factory_.GetWeakPtr()));
490 void ResourceLoader::StoreSignedCertificateTimestamps(
491 const net::SignedCertificateTimestampAndStatusList& sct_list,
492 int process_id,
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));
500 sct_ids->push_back(
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,
518 info->GetChildID(),
519 &signed_certificate_timestamp_ids);
521 response->head.security_info = SerializeSecurityInfo(
522 cert_id,
523 request_->ssl_info().cert_status,
524 request_->ssl_info().security_bits,
525 request_->ssl_info().connection_status,
526 signed_certificate_timestamp_ids);
527 } else {
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);
536 bool defer = false;
537 if (!handler_->OnResponseStarted(
538 info->GetRequestID(), response.get(), &defer)) {
539 Cancel();
540 } else if (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) {
547 int bytes_read = 0;
548 ReadMore(&bytes_read);
550 // If IO is pending, wait for the URLRequest to call OnReadCompleted.
551 if (request_->status().is_io_pending())
552 return;
554 if (!is_continuation || bytes_read <= 0) {
555 OnReadCompleted(request_.get(), bytes_read);
556 } else {
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(
560 FROM_HERE,
561 base::Bind(&ResourceLoader::OnReadCompleted,
562 weak_ptr_factory_.GetWeakPtr(),
563 request_.get(),
564 bytes_read));
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).
578 } else {
579 ResponseCompleted();
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;
591 int buf_size;
592 if (!handler_->OnWillRead(info->GetRequestID(), &buf, &buf_size, -1)) {
593 Cancel();
594 return;
597 DCHECK(buf);
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();
612 bool defer = false;
613 if (!handler_->OnReadCompleted(info->GetRequestID(), bytes_read, &defer)) {
614 Cancel();
615 } else if (defer) {
616 deferred_stage_ = DEFERRED_READ; // Read next chunk when resumed.
620 void ResourceLoader::ResponseCompleted() {
621 VLOG(1) << "ResponseCompleted: " << request_->url().spec();
622 RecordHistograms();
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(),
629 info->GetChildID());
630 SignedCertificateTimestampIDStatusList signed_certificate_timestamp_ids;
631 StoreSignedCertificateTimestamps(ssl_info.signed_certificate_timestamps,
632 info->GetChildID(),
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);
640 bool defer = false;
641 handler_->OnResponseCompleted(info->GetRequestID(), request_->status(),
642 security_info, &defer);
643 if (defer) {
644 // The handler is not ready to die yet. We will call DidFinishLoading when
645 // we resume.
646 deferred_stage_ = DEFERRED_FINISH;
647 } else {
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",
669 total_time);
670 } else {
671 status = STATUS_SUCCESS_FROM_NETWORK;
672 UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeSpentPrefetchingFromNetwork",
673 total_time);
675 break;
676 case net::URLRequestStatus::CANCELED:
677 status = STATUS_CANCELED;
678 UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeBeforeCancel", total_time);
679 break;
680 case net::URLRequestStatus::IO_PENDING:
681 case net::URLRequestStatus::FAILED:
682 status = STATUS_UNDEFINED;
683 break;
686 UMA_HISTOGRAM_ENUMERATION("Net.Prefetch.Pattern", status, STATUS_MAX);
690 } // namespace content