Home | History | Annotate | Download | only in loader
      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 
     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 
     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 
     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 
     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 
    115 void ResourceLoader::CancelRequest(bool from_renderer) {
    116   CancelRequestInternal(net::ERR_ABORTED, from_renderer);
    117 }
    118 
    119 void ResourceLoader::CancelAndIgnore() {
    120   ResourceRequestInfoImpl* info = GetRequestInfo();
    121   info->set_was_ignored_by_handler(true);
    122   CancelRequest(false);
    123 }
    124 
    125 void ResourceLoader::CancelWithError(int error_code) {
    126   CancelRequestInternal(error_code, false);
    127 }
    128 
    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 
    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 
    174 void ResourceLoader::CompleteTransfer() {
    175   DCHECK_EQ(DEFERRED_READ, deferred_stage_);
    176 
    177   is_transferring_ = false;
    178   GetRequestInfo()->cross_site_handler()->ResumeResponse();
    179 }
    180 
    181 ResourceRequestInfoImpl* ResourceLoader::GetRequestInfo() {
    182   return ResourceRequestInfoImpl::ForRequest(request_.get());
    183 }
    184 
    185 void ResourceLoader::ClearLoginDelegate() {
    186   login_delegate_ = NULL;
    187 }
    188 
    189 void ResourceLoader::ClearSSLClientAuthHandler() {
    190   ssl_client_auth_handler_ = NULL;
    191 }
    192 
    193 void ResourceLoader::OnUploadProgressACK() {
    194   waiting_for_upload_progress_ack_ = false;
    195 }
    196 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    422 void ResourceLoader::Cancel() {
    423   CancelRequest(false);
    424 }
    425 
    426 void ResourceLoader::StartRequestInternal() {
    427   DCHECK(!request_->is_pending());
    428   request_->Start();
    429 
    430   delegate_->DidStartRequest(this);
    431 }
    432 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    640 void ResourceLoader::CallDidFinishLoading() {
    641   delegate_->DidFinishLoading(this);
    642 }
    643 
    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