• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "content/browser/loader/resource_loader.h"
6 
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"
33 
34 using base::TimeDelta;
35 using base::TimeTicks;
36 
37 namespace content {
38 namespace {
39 
PopulateResourceResponse(net::URLRequest * request,ResourceResponse * response)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);
64 }
65 
66 }  // namespace
67 
ResourceLoader(scoped_ptr<net::URLRequest> request,scoped_ptr<ResourceHandler> handler,ResourceLoaderDelegate * delegate)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);
81 }
82 
~ResourceLoader()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();
88 
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();
92 }
93 
StartRequest()94 void ResourceLoader::StartRequest() {
95   if (delegate_->HandleExternalProtocol(this, request_->url())) {
96     CancelAndIgnore();
97     return;
98   }
99 
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;
106   }
107 
108   if (defer_start) {
109     deferred_stage_ = DEFERRED_START;
110   } else {
111     StartRequestInternal();
112   }
113 }
114 
CancelRequest(bool from_renderer)115 void ResourceLoader::CancelRequest(bool from_renderer) {
116   CancelRequestInternal(net::ERR_ABORTED, from_renderer);
117 }
118 
CancelAndIgnore()119 void ResourceLoader::CancelAndIgnore() {
120   ResourceRequestInfoImpl* info = GetRequestInfo();
121   info->set_was_ignored_by_handler(true);
122   CancelRequest(false);
123 }
124 
CancelWithError(int error_code)125 void ResourceLoader::CancelWithError(int error_code) {
126   CancelRequestInternal(error_code, false);
127 }
128 
ReportUploadProgress()129 void ResourceLoader::ReportUploadProgress() {
130   ResourceRequestInfoImpl* info = GetRequestInfo();
131 
132   if (waiting_for_upload_progress_ack_)
133     return;  // Send one progress event at a time.
134 
135   net::UploadProgress progress = request_->GetUploadProgress();
136   if (!progress.size())
137     return;  // Nothing to upload.
138 
139   if (progress.position() == last_upload_position_)
140     return;  // No progress made since last time.
141 
142   const uint64 kHalfPercentIncrements = 200;
143   const TimeDelta kOneSecond = TimeDelta::FromMilliseconds(1000);
144 
145   uint64 amt_since_last = progress.position() - last_upload_position_;
146   TimeDelta time_since_last = TimeTicks::Now() - last_upload_ticks_;
147 
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;
152 
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;
158     }
159     last_upload_ticks_ = TimeTicks::Now();
160     last_upload_position_ = progress.position();
161   }
162 }
163 
MarkAsTransferring(const GURL & target_url)164 void ResourceLoader::MarkAsTransferring(const GURL& target_url) {
165   CHECK_EQ(GetRequestInfo()->GetResourceType(), ResourceType::MAIN_FRAME)
166       << "Cannot transfer non-main frame navigations";
167   is_transferring_ = true;
168 
169   // When transferring a request to another process, the renderer doesn't get
170   // a chance to update the cookie policy URL. Do it here instead.
171   request()->set_first_party_for_cookies(target_url);
172 }
173 
CompleteTransfer()174 void ResourceLoader::CompleteTransfer() {
175   DCHECK_EQ(DEFERRED_READ, deferred_stage_);
176 
177   is_transferring_ = false;
178   GetRequestInfo()->cross_site_handler()->ResumeResponse();
179 }
180 
GetRequestInfo()181 ResourceRequestInfoImpl* ResourceLoader::GetRequestInfo() {
182   return ResourceRequestInfoImpl::ForRequest(request_.get());
183 }
184 
ClearLoginDelegate()185 void ResourceLoader::ClearLoginDelegate() {
186   login_delegate_ = NULL;
187 }
188 
ClearSSLClientAuthHandler()189 void ResourceLoader::ClearSSLClientAuthHandler() {
190   ssl_client_auth_handler_ = NULL;
191 }
192 
OnUploadProgressACK()193 void ResourceLoader::OnUploadProgressACK() {
194   waiting_for_upload_progress_ack_ = false;
195 }
196 
OnReceivedRedirect(net::URLRequest * unused,const GURL & new_url,bool * defer)197 void ResourceLoader::OnReceivedRedirect(net::URLRequest* unused,
198                                         const GURL& new_url,
199                                         bool* defer) {
200   DCHECK_EQ(request_.get(), unused);
201 
202   VLOG(1) << "OnReceivedRedirect: " << request_->url().spec();
203   DCHECK(request_->status().is_success());
204 
205   ResourceRequestInfoImpl* info = GetRequestInfo();
206 
207   if (info->process_type() != PROCESS_TYPE_PLUGIN &&
208       !ChildProcessSecurityPolicyImpl::GetInstance()->
209           CanRequestURL(info->GetChildID(), new_url)) {
210     VLOG(1) << "Denied unauthorized request for "
211             << new_url.possibly_invalid_spec();
212 
213     // Tell the renderer that this request was disallowed.
214     Cancel();
215     return;
216   }
217 
218   delegate_->DidReceiveRedirect(this, new_url);
219 
220   if (delegate_->HandleExternalProtocol(this, new_url)) {
221     // The request is complete so we can remove it.
222     CancelAndIgnore();
223     return;
224   }
225 
226   scoped_refptr<ResourceResponse> response(new ResourceResponse());
227   PopulateResourceResponse(request_.get(), response.get());
228 
229   if (!handler_->OnRequestRedirected(
230           info->GetRequestID(), new_url, response.get(), defer)) {
231     Cancel();
232   } else if (*defer) {
233     deferred_stage_ = DEFERRED_REDIRECT;  // Follow redirect when resumed.
234   }
235 }
236 
OnAuthRequired(net::URLRequest * unused,net::AuthChallengeInfo * auth_info)237 void ResourceLoader::OnAuthRequired(net::URLRequest* unused,
238                                     net::AuthChallengeInfo* auth_info) {
239   DCHECK_EQ(request_.get(), unused);
240 
241   if (request_->load_flags() & net::LOAD_DO_NOT_PROMPT_FOR_LOGIN) {
242     request_->CancelAuth();
243     return;
244   }
245 
246   if (!delegate_->AcceptAuthRequest(this, auth_info)) {
247     request_->CancelAuth();
248     return;
249   }
250 
251   // Create a login dialog on the UI thread to get authentication data, or pull
252   // from cache and continue on the IO thread.
253 
254   DCHECK(!login_delegate_.get())
255       << "OnAuthRequired called with login_delegate pending";
256   login_delegate_ = delegate_->CreateLoginDelegate(this, auth_info);
257   if (!login_delegate_.get())
258     request_->CancelAuth();
259 }
260 
OnCertificateRequested(net::URLRequest * unused,net::SSLCertRequestInfo * cert_info)261 void ResourceLoader::OnCertificateRequested(
262     net::URLRequest* unused,
263     net::SSLCertRequestInfo* cert_info) {
264   DCHECK_EQ(request_.get(), unused);
265 
266   if (!delegate_->AcceptSSLClientCertificateRequest(this, cert_info)) {
267     request_->Cancel();
268     return;
269   }
270 
271   DCHECK(!ssl_client_auth_handler_.get())
272       << "OnCertificateRequested called with ssl_client_auth_handler pending";
273   ssl_client_auth_handler_ = new SSLClientAuthHandler(
274       GetRequestInfo()->GetContext()->CreateClientCertStore(),
275       request_.get(),
276       cert_info);
277   ssl_client_auth_handler_->SelectCertificate();
278 }
279 
OnSSLCertificateError(net::URLRequest * request,const net::SSLInfo & ssl_info,bool fatal)280 void ResourceLoader::OnSSLCertificateError(net::URLRequest* request,
281                                            const net::SSLInfo& ssl_info,
282                                            bool fatal) {
283   ResourceRequestInfoImpl* info = GetRequestInfo();
284 
285   int render_process_id;
286   int render_view_id;
287   if (!info->GetAssociatedRenderView(&render_process_id, &render_view_id))
288     NOTREACHED();
289 
290   SSLManager::OnSSLCertificateError(
291       weak_ptr_factory_.GetWeakPtr(),
292       info->GetGlobalRequestID(),
293       info->GetResourceType(),
294       request_->url(),
295       render_process_id,
296       render_view_id,
297       ssl_info,
298       fatal);
299 }
300 
OnResponseStarted(net::URLRequest * unused)301 void ResourceLoader::OnResponseStarted(net::URLRequest* unused) {
302   DCHECK_EQ(request_.get(), unused);
303 
304   VLOG(1) << "OnResponseStarted: " << request_->url().spec();
305 
306   // The CanLoadPage check should take place after any server redirects have
307   // finished, at the point in time that we know a page will commit in the
308   // renderer process.
309   ResourceRequestInfoImpl* info = GetRequestInfo();
310   ChildProcessSecurityPolicyImpl* policy =
311       ChildProcessSecurityPolicyImpl::GetInstance();
312   if (!policy->CanLoadPage(info->GetChildID(),
313                            request_->url(),
314                            info->GetResourceType())) {
315     Cancel();
316     return;
317   }
318 
319   if (!request_->status().is_success()) {
320     ResponseCompleted();
321     return;
322   }
323 
324   // We want to send a final upload progress message prior to sending the
325   // response complete message even if we're waiting for an ack to to a
326   // previous upload progress message.
327   waiting_for_upload_progress_ack_ = false;
328   ReportUploadProgress();
329 
330   CompleteResponseStarted();
331 
332   if (is_deferred())
333     return;
334 
335   if (request_->status().is_success()) {
336     StartReading(false);  // Read the first chunk.
337   } else {
338     ResponseCompleted();
339   }
340 }
341 
OnReadCompleted(net::URLRequest * unused,int bytes_read)342 void ResourceLoader::OnReadCompleted(net::URLRequest* unused, int bytes_read) {
343   DCHECK_EQ(request_.get(), unused);
344   VLOG(1) << "OnReadCompleted: \"" << request_->url().spec() << "\""
345           << " bytes_read = " << bytes_read;
346 
347   // bytes_read == -1 always implies an error.
348   if (bytes_read == -1 || !request_->status().is_success()) {
349     ResponseCompleted();
350     return;
351   }
352 
353   CompleteRead(bytes_read);
354 
355   if (is_deferred())
356     return;
357 
358   if (request_->status().is_success() && bytes_read > 0) {
359     StartReading(true);  // Read the next chunk.
360   } else {
361     ResponseCompleted();
362   }
363 }
364 
CancelSSLRequest(const GlobalRequestID & id,int error,const net::SSLInfo * ssl_info)365 void ResourceLoader::CancelSSLRequest(const GlobalRequestID& id,
366                                       int error,
367                                       const net::SSLInfo* ssl_info) {
368   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
369 
370   // The request can be NULL if it was cancelled by the renderer (as the
371   // request of the user navigating to a new page from the location bar).
372   if (!request_->is_pending())
373     return;
374   DVLOG(1) << "CancelSSLRequest() url: " << request_->url().spec();
375 
376   if (ssl_info) {
377     request_->CancelWithSSLError(error, *ssl_info);
378   } else {
379     request_->CancelWithError(error);
380   }
381 }
382 
ContinueSSLRequest(const GlobalRequestID & id)383 void ResourceLoader::ContinueSSLRequest(const GlobalRequestID& id) {
384   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
385 
386   DVLOG(1) << "ContinueSSLRequest() url: " << request_->url().spec();
387 
388   request_->ContinueDespiteLastError();
389 }
390 
Resume()391 void ResourceLoader::Resume() {
392   DCHECK(!is_transferring_);
393 
394   DeferredStage stage = deferred_stage_;
395   deferred_stage_ = DEFERRED_NONE;
396   switch (stage) {
397     case DEFERRED_NONE:
398       NOTREACHED();
399       break;
400     case DEFERRED_START:
401       StartRequestInternal();
402       break;
403     case DEFERRED_REDIRECT:
404       request_->FollowDeferredRedirect();
405       break;
406     case DEFERRED_READ:
407       base::MessageLoop::current()->PostTask(
408           FROM_HERE,
409           base::Bind(&ResourceLoader::ResumeReading,
410                      weak_ptr_factory_.GetWeakPtr()));
411       break;
412     case DEFERRED_FINISH:
413       // Delay self-destruction since we don't know how we were reached.
414       base::MessageLoop::current()->PostTask(
415           FROM_HERE,
416           base::Bind(&ResourceLoader::CallDidFinishLoading,
417                      weak_ptr_factory_.GetWeakPtr()));
418       break;
419   }
420 }
421 
Cancel()422 void ResourceLoader::Cancel() {
423   CancelRequest(false);
424 }
425 
StartRequestInternal()426 void ResourceLoader::StartRequestInternal() {
427   DCHECK(!request_->is_pending());
428   request_->Start();
429 
430   delegate_->DidStartRequest(this);
431 }
432 
CancelRequestInternal(int error,bool from_renderer)433 void ResourceLoader::CancelRequestInternal(int error, bool from_renderer) {
434   VLOG(1) << "CancelRequestInternal: " << request_->url().spec();
435 
436   ResourceRequestInfoImpl* info = GetRequestInfo();
437 
438   // WebKit will send us a cancel for downloads since it no longer handles
439   // them.  In this case, ignore the cancel since we handle downloads in the
440   // browser.
441   if (from_renderer && (info->IsDownload() || info->is_stream()))
442     return;
443 
444   if (from_renderer && info->detachable_handler()) {
445     // TODO(davidben): Fix Blink handling of prefetches so they are not
446     // cancelled on navigate away and end up in the local cache.
447     info->detachable_handler()->Detach();
448     return;
449   }
450 
451   // TODO(darin): Perhaps we should really be looking to see if the status is
452   // IO_PENDING?
453   bool was_pending = request_->is_pending();
454 
455   if (login_delegate_.get()) {
456     login_delegate_->OnRequestCancelled();
457     login_delegate_ = NULL;
458   }
459   if (ssl_client_auth_handler_.get()) {
460     ssl_client_auth_handler_->OnRequestCancelled();
461     ssl_client_auth_handler_ = NULL;
462   }
463 
464   request_->CancelWithError(error);
465 
466   if (!was_pending) {
467     // If the request isn't in flight, then we won't get an asynchronous
468     // notification from the request, so we have to signal ourselves to finish
469     // this request.
470     base::MessageLoop::current()->PostTask(
471         FROM_HERE,
472         base::Bind(&ResourceLoader::ResponseCompleted,
473                    weak_ptr_factory_.GetWeakPtr()));
474   }
475 }
476 
StoreSignedCertificateTimestamps(const net::SignedCertificateTimestampAndStatusList & sct_list,int process_id,SignedCertificateTimestampIDStatusList * sct_ids)477 void ResourceLoader::StoreSignedCertificateTimestamps(
478     const net::SignedCertificateTimestampAndStatusList& sct_list,
479     int process_id,
480     SignedCertificateTimestampIDStatusList* sct_ids) {
481   SignedCertificateTimestampStore* sct_store(
482       SignedCertificateTimestampStore::GetInstance());
483 
484   for (net::SignedCertificateTimestampAndStatusList::const_iterator iter =
485        sct_list.begin(); iter != sct_list.end(); ++iter) {
486     const int sct_id(sct_store->Store(iter->sct_, process_id));
487     sct_ids->push_back(
488         SignedCertificateTimestampIDAndStatus(sct_id, iter->status_));
489   }
490 }
491 
CompleteResponseStarted()492 void ResourceLoader::CompleteResponseStarted() {
493   ResourceRequestInfoImpl* info = GetRequestInfo();
494 
495   scoped_refptr<ResourceResponse> response(new ResourceResponse());
496   PopulateResourceResponse(request_.get(), response.get());
497 
498   if (request_->ssl_info().cert.get()) {
499     int cert_id = CertStore::GetInstance()->StoreCert(
500         request_->ssl_info().cert.get(), info->GetChildID());
501 
502     SignedCertificateTimestampIDStatusList signed_certificate_timestamp_ids;
503     StoreSignedCertificateTimestamps(
504         request_->ssl_info().signed_certificate_timestamps,
505         info->GetChildID(),
506         &signed_certificate_timestamp_ids);
507 
508     response->head.security_info = SerializeSecurityInfo(
509         cert_id,
510         request_->ssl_info().cert_status,
511         request_->ssl_info().security_bits,
512         request_->ssl_info().connection_status,
513         signed_certificate_timestamp_ids);
514   } else {
515     // We should not have any SSL state.
516     DCHECK(!request_->ssl_info().cert_status &&
517            request_->ssl_info().security_bits == -1 &&
518            !request_->ssl_info().connection_status);
519   }
520 
521   delegate_->DidReceiveResponse(this);
522 
523   bool defer = false;
524   if (!handler_->OnResponseStarted(
525           info->GetRequestID(), response.get(), &defer)) {
526     Cancel();
527   } else if (defer) {
528     read_deferral_start_time_ = base::TimeTicks::Now();
529     deferred_stage_ = DEFERRED_READ;  // Read first chunk when resumed.
530   }
531 }
532 
StartReading(bool is_continuation)533 void ResourceLoader::StartReading(bool is_continuation) {
534   int bytes_read = 0;
535   ReadMore(&bytes_read);
536 
537   // If IO is pending, wait for the URLRequest to call OnReadCompleted.
538   if (request_->status().is_io_pending())
539     return;
540 
541   if (!is_continuation || bytes_read <= 0) {
542     OnReadCompleted(request_.get(), bytes_read);
543   } else {
544     // Else, trigger OnReadCompleted asynchronously to avoid starving the IO
545     // thread in case the URLRequest can provide data synchronously.
546     base::MessageLoop::current()->PostTask(
547         FROM_HERE,
548         base::Bind(&ResourceLoader::OnReadCompleted,
549                    weak_ptr_factory_.GetWeakPtr(),
550                    request_.get(),
551                    bytes_read));
552   }
553 }
554 
ResumeReading()555 void ResourceLoader::ResumeReading() {
556   DCHECK(!is_deferred());
557 
558   if (!read_deferral_start_time_.is_null()) {
559     UMA_HISTOGRAM_TIMES("Net.ResourceLoader.ReadDeferral",
560                         base::TimeTicks::Now() - read_deferral_start_time_);
561     read_deferral_start_time_ = base::TimeTicks();
562   }
563   if (request_->status().is_success()) {
564     StartReading(false);  // Read the next chunk (OK to complete synchronously).
565   } else {
566     ResponseCompleted();
567   }
568 }
569 
ReadMore(int * bytes_read)570 void ResourceLoader::ReadMore(int* bytes_read) {
571   ResourceRequestInfoImpl* info = GetRequestInfo();
572   DCHECK(!is_deferred());
573 
574   // Make sure we track the buffer in at least one place.  This ensures it gets
575   // deleted even in the case the request has already finished its job and
576   // doesn't use the buffer.
577   scoped_refptr<net::IOBuffer> buf;
578   int buf_size;
579   if (!handler_->OnWillRead(info->GetRequestID(), &buf, &buf_size, -1)) {
580     Cancel();
581     return;
582   }
583 
584   DCHECK(buf);
585   DCHECK(buf_size > 0);
586 
587   request_->Read(buf.get(), buf_size, bytes_read);
588 
589   // No need to check the return value here as we'll detect errors by
590   // inspecting the URLRequest's status.
591 }
592 
CompleteRead(int bytes_read)593 void ResourceLoader::CompleteRead(int bytes_read) {
594   DCHECK(bytes_read >= 0);
595   DCHECK(request_->status().is_success());
596 
597   ResourceRequestInfoImpl* info = GetRequestInfo();
598 
599   bool defer = false;
600   if (!handler_->OnReadCompleted(info->GetRequestID(), bytes_read, &defer)) {
601     Cancel();
602   } else if (defer) {
603     deferred_stage_ = DEFERRED_READ;  // Read next chunk when resumed.
604   }
605 }
606 
ResponseCompleted()607 void ResourceLoader::ResponseCompleted() {
608   VLOG(1) << "ResponseCompleted: " << request_->url().spec();
609   RecordHistograms();
610   ResourceRequestInfoImpl* info = GetRequestInfo();
611 
612   std::string security_info;
613   const net::SSLInfo& ssl_info = request_->ssl_info();
614   if (ssl_info.cert.get() != NULL) {
615     int cert_id = CertStore::GetInstance()->StoreCert(ssl_info.cert.get(),
616                                                       info->GetChildID());
617     SignedCertificateTimestampIDStatusList signed_certificate_timestamp_ids;
618     StoreSignedCertificateTimestamps(ssl_info.signed_certificate_timestamps,
619                                      info->GetChildID(),
620                                      &signed_certificate_timestamp_ids);
621 
622     security_info = SerializeSecurityInfo(
623         cert_id, ssl_info.cert_status, ssl_info.security_bits,
624         ssl_info.connection_status, signed_certificate_timestamp_ids);
625   }
626 
627   bool defer = false;
628   handler_->OnResponseCompleted(info->GetRequestID(), request_->status(),
629                                 security_info, &defer);
630   if (defer) {
631     // The handler is not ready to die yet.  We will call DidFinishLoading when
632     // we resume.
633     deferred_stage_ = DEFERRED_FINISH;
634   } else {
635     // This will result in our destruction.
636     CallDidFinishLoading();
637   }
638 }
639 
CallDidFinishLoading()640 void ResourceLoader::CallDidFinishLoading() {
641   delegate_->DidFinishLoading(this);
642 }
643 
RecordHistograms()644 void ResourceLoader::RecordHistograms() {
645   ResourceRequestInfoImpl* info = GetRequestInfo();
646 
647   if (info->GetResourceType() == ResourceType::PREFETCH) {
648     PrefetchStatus status = STATUS_UNDEFINED;
649     TimeDelta total_time = base::TimeTicks::Now() - request_->creation_time();
650 
651     switch (request_->status().status()) {
652       case net::URLRequestStatus::SUCCESS:
653         if (request_->was_cached()) {
654           status = STATUS_SUCCESS_FROM_CACHE;
655           UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeSpentPrefetchingFromCache",
656                               total_time);
657         } else {
658           status = STATUS_SUCCESS_FROM_NETWORK;
659           UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeSpentPrefetchingFromNetwork",
660                               total_time);
661         }
662         break;
663       case net::URLRequestStatus::CANCELED:
664         status = STATUS_CANCELED;
665         UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeBeforeCancel", total_time);
666         break;
667       case net::URLRequestStatus::IO_PENDING:
668       case net::URLRequestStatus::FAILED:
669         status = STATUS_UNDEFINED;
670         break;
671     }
672 
673     UMA_HISTOGRAM_ENUMERATION("Net.Prefetch.Pattern", status, STATUS_MAX);
674   }
675 }
676 
677 }  // namespace content
678