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/appcache/appcache_interceptor.h"
     12 #include "content/browser/child_process_security_policy_impl.h"
     13 #include "content/browser/loader/cross_site_resource_handler.h"
     14 #include "content/browser/loader/detachable_resource_handler.h"
     15 #include "content/browser/loader/resource_loader_delegate.h"
     16 #include "content/browser/loader/resource_request_info_impl.h"
     17 #include "content/browser/service_worker/service_worker_request_handler.h"
     18 #include "content/browser/ssl/ssl_client_auth_handler.h"
     19 #include "content/browser/ssl/ssl_manager.h"
     20 #include "content/common/ssl_status_serialization.h"
     21 #include "content/public/browser/cert_store.h"
     22 #include "content/public/browser/resource_context.h"
     23 #include "content/public/browser/resource_dispatcher_host_login_delegate.h"
     24 #include "content/public/browser/signed_certificate_timestamp_store.h"
     25 #include "content/public/common/content_client.h"
     26 #include "content/public/common/content_switches.h"
     27 #include "content/public/common/process_type.h"
     28 #include "content/public/common/resource_response.h"
     29 #include "net/base/io_buffer.h"
     30 #include "net/base/load_flags.h"
     31 #include "net/http/http_response_headers.h"
     32 #include "net/ssl/client_cert_store.h"
     33 #include "net/url_request/redirect_info.h"
     34 #include "net/url_request/url_request_status.h"
     35 
     36 using base::TimeDelta;
     37 using base::TimeTicks;
     38 
     39 namespace content {
     40 namespace {
     41 
     42 void PopulateResourceResponse(ResourceRequestInfoImpl* info,
     43                               net::URLRequest* request,
     44                               ResourceResponse* response) {
     45   response->head.request_time = request->request_time();
     46   response->head.response_time = request->response_time();
     47   response->head.headers = request->response_headers();
     48   request->GetCharset(&response->head.charset);
     49   response->head.content_length = request->GetExpectedContentSize();
     50   request->GetMimeType(&response->head.mime_type);
     51   net::HttpResponseInfo response_info = request->response_info();
     52   response->head.was_fetched_via_spdy = response_info.was_fetched_via_spdy;
     53   response->head.was_npn_negotiated = response_info.was_npn_negotiated;
     54   response->head.npn_negotiated_protocol =
     55       response_info.npn_negotiated_protocol;
     56   response->head.connection_info = response_info.connection_info;
     57   response->head.was_fetched_via_proxy = request->was_fetched_via_proxy();
     58   response->head.socket_address = request->GetSocketAddress();
     59   if (ServiceWorkerRequestHandler* handler =
     60           ServiceWorkerRequestHandler::GetHandler(request)) {
     61     handler->GetExtraResponseInfo(
     62         &response->head.was_fetched_via_service_worker,
     63         &response->head.original_url_via_service_worker,
     64         &response->head.service_worker_fetch_start,
     65         &response->head.service_worker_fetch_ready,
     66         &response->head.service_worker_fetch_end);
     67   }
     68   AppCacheInterceptor::GetExtraResponseInfo(
     69       request,
     70       &response->head.appcache_id,
     71       &response->head.appcache_manifest_url);
     72   if (info->is_load_timing_enabled())
     73     request->GetLoadTimingInfo(&response->head.load_timing);
     74 }
     75 
     76 }  // namespace
     77 
     78 ResourceLoader::ResourceLoader(scoped_ptr<net::URLRequest> request,
     79                                scoped_ptr<ResourceHandler> handler,
     80                                ResourceLoaderDelegate* delegate)
     81     : deferred_stage_(DEFERRED_NONE),
     82       request_(request.Pass()),
     83       handler_(handler.Pass()),
     84       delegate_(delegate),
     85       last_upload_position_(0),
     86       waiting_for_upload_progress_ack_(false),
     87       is_transferring_(false),
     88       weak_ptr_factory_(this) {
     89   request_->set_delegate(this);
     90   handler_->SetController(this);
     91 }
     92 
     93 ResourceLoader::~ResourceLoader() {
     94   if (login_delegate_.get())
     95     login_delegate_->OnRequestCancelled();
     96   if (ssl_client_auth_handler_.get())
     97     ssl_client_auth_handler_->OnRequestCancelled();
     98 
     99   // Run ResourceHandler destructor before we tear-down the rest of our state
    100   // as the ResourceHandler may want to inspect the URLRequest and other state.
    101   handler_.reset();
    102 }
    103 
    104 void ResourceLoader::StartRequest() {
    105   if (delegate_->HandleExternalProtocol(this, request_->url())) {
    106     CancelAndIgnore();
    107     return;
    108   }
    109 
    110   // Give the handler a chance to delay the URLRequest from being started.
    111   bool defer_start = false;
    112   if (!handler_->OnWillStart(request_->url(), &defer_start)) {
    113     Cancel();
    114     return;
    115   }
    116 
    117   if (defer_start) {
    118     deferred_stage_ = DEFERRED_START;
    119   } else {
    120     StartRequestInternal();
    121   }
    122 }
    123 
    124 void ResourceLoader::CancelRequest(bool from_renderer) {
    125   CancelRequestInternal(net::ERR_ABORTED, from_renderer);
    126 }
    127 
    128 void ResourceLoader::CancelAndIgnore() {
    129   ResourceRequestInfoImpl* info = GetRequestInfo();
    130   info->set_was_ignored_by_handler(true);
    131   CancelRequest(false);
    132 }
    133 
    134 void ResourceLoader::CancelWithError(int error_code) {
    135   CancelRequestInternal(error_code, false);
    136 }
    137 
    138 void ResourceLoader::ReportUploadProgress() {
    139   if (waiting_for_upload_progress_ack_)
    140     return;  // Send one progress event at a time.
    141 
    142   net::UploadProgress progress = request_->GetUploadProgress();
    143   if (!progress.size())
    144     return;  // Nothing to upload.
    145 
    146   if (progress.position() == last_upload_position_)
    147     return;  // No progress made since last time.
    148 
    149   const uint64 kHalfPercentIncrements = 200;
    150   const TimeDelta kOneSecond = TimeDelta::FromMilliseconds(1000);
    151 
    152   uint64 amt_since_last = progress.position() - last_upload_position_;
    153   TimeDelta time_since_last = TimeTicks::Now() - last_upload_ticks_;
    154 
    155   bool is_finished = (progress.size() == progress.position());
    156   bool enough_new_progress =
    157       (amt_since_last > (progress.size() / kHalfPercentIncrements));
    158   bool too_much_time_passed = time_since_last > kOneSecond;
    159 
    160   if (is_finished || enough_new_progress || too_much_time_passed) {
    161     if (request_->load_flags() & net::LOAD_ENABLE_UPLOAD_PROGRESS) {
    162       handler_->OnUploadProgress(progress.position(), progress.size());
    163       waiting_for_upload_progress_ack_ = true;
    164     }
    165     last_upload_ticks_ = TimeTicks::Now();
    166     last_upload_position_ = progress.position();
    167   }
    168 }
    169 
    170 void ResourceLoader::MarkAsTransferring() {
    171   CHECK(IsResourceTypeFrame(GetRequestInfo()->GetResourceType()))
    172       << "Can only transfer for navigations";
    173   is_transferring_ = true;
    174 }
    175 
    176 void ResourceLoader::CompleteTransfer() {
    177   // Although CrossSiteResourceHandler defers at OnResponseStarted
    178   // (DEFERRED_READ), it may be seeing a replay of events via
    179   // BufferedResourceHandler, and so the request itself is actually deferred at
    180   // a later read stage.
    181   DCHECK(DEFERRED_READ == deferred_stage_ ||
    182          DEFERRED_RESPONSE_COMPLETE == deferred_stage_);
    183 
    184   is_transferring_ = false;
    185   GetRequestInfo()->cross_site_handler()->ResumeResponse();
    186 }
    187 
    188 ResourceRequestInfoImpl* ResourceLoader::GetRequestInfo() {
    189   return ResourceRequestInfoImpl::ForRequest(request_.get());
    190 }
    191 
    192 void ResourceLoader::ClearLoginDelegate() {
    193   login_delegate_ = NULL;
    194 }
    195 
    196 void ResourceLoader::ClearSSLClientAuthHandler() {
    197   ssl_client_auth_handler_ = NULL;
    198 }
    199 
    200 void ResourceLoader::OnUploadProgressACK() {
    201   waiting_for_upload_progress_ack_ = false;
    202 }
    203 
    204 void ResourceLoader::OnReceivedRedirect(net::URLRequest* unused,
    205                                         const net::RedirectInfo& redirect_info,
    206                                         bool* defer) {
    207   DCHECK_EQ(request_.get(), unused);
    208 
    209   VLOG(1) << "OnReceivedRedirect: " << request_->url().spec();
    210   DCHECK(request_->status().is_success());
    211 
    212   ResourceRequestInfoImpl* info = GetRequestInfo();
    213 
    214   if (info->GetProcessType() != PROCESS_TYPE_PLUGIN &&
    215       !ChildProcessSecurityPolicyImpl::GetInstance()->
    216           CanRequestURL(info->GetChildID(), redirect_info.new_url)) {
    217     VLOG(1) << "Denied unauthorized request for "
    218             << redirect_info.new_url.possibly_invalid_spec();
    219 
    220     // Tell the renderer that this request was disallowed.
    221     Cancel();
    222     return;
    223   }
    224 
    225   delegate_->DidReceiveRedirect(this, redirect_info.new_url);
    226 
    227   if (delegate_->HandleExternalProtocol(this, redirect_info.new_url)) {
    228     // The request is complete so we can remove it.
    229     CancelAndIgnore();
    230     return;
    231   }
    232 
    233   scoped_refptr<ResourceResponse> response(new ResourceResponse());
    234   PopulateResourceResponse(info, request_.get(), response.get());
    235 
    236   if (!handler_->OnRequestRedirected(redirect_info, response.get(), defer)) {
    237     Cancel();
    238   } else if (*defer) {
    239     deferred_stage_ = DEFERRED_REDIRECT;  // Follow redirect when resumed.
    240   }
    241 }
    242 
    243 void ResourceLoader::OnAuthRequired(net::URLRequest* unused,
    244                                     net::AuthChallengeInfo* auth_info) {
    245   DCHECK_EQ(request_.get(), unused);
    246 
    247   if (request_->load_flags() & net::LOAD_DO_NOT_PROMPT_FOR_LOGIN) {
    248     request_->CancelAuth();
    249     return;
    250   }
    251 
    252   // Create a login dialog on the UI thread to get authentication data, or pull
    253   // from cache and continue on the IO thread.
    254 
    255   DCHECK(!login_delegate_.get())
    256       << "OnAuthRequired called with login_delegate pending";
    257   login_delegate_ = delegate_->CreateLoginDelegate(this, auth_info);
    258   if (!login_delegate_.get())
    259     request_->CancelAuth();
    260 }
    261 
    262 void ResourceLoader::OnCertificateRequested(
    263     net::URLRequest* unused,
    264     net::SSLCertRequestInfo* cert_info) {
    265   DCHECK_EQ(request_.get(), unused);
    266 
    267   if (request_->load_flags() & net::LOAD_PREFETCH) {
    268     request_->Cancel();
    269     return;
    270   }
    271 
    272   DCHECK(!ssl_client_auth_handler_.get())
    273       << "OnCertificateRequested called with ssl_client_auth_handler pending";
    274   ssl_client_auth_handler_ = new SSLClientAuthHandler(
    275       GetRequestInfo()->GetContext()->CreateClientCertStore(),
    276       request_.get(),
    277       cert_info);
    278   ssl_client_auth_handler_->SelectCertificate();
    279 }
    280 
    281 void ResourceLoader::OnSSLCertificateError(net::URLRequest* request,
    282                                            const net::SSLInfo& ssl_info,
    283                                            bool fatal) {
    284   ResourceRequestInfoImpl* info = GetRequestInfo();
    285 
    286   int render_process_id;
    287   int render_frame_id;
    288   if (!info->GetAssociatedRenderFrame(&render_process_id, &render_frame_id))
    289     NOTREACHED();
    290 
    291   SSLManager::OnSSLCertificateError(
    292       weak_ptr_factory_.GetWeakPtr(),
    293       info->GetGlobalRequestID(),
    294       info->GetResourceType(),
    295       request_->url(),
    296       render_process_id,
    297       render_frame_id,
    298       ssl_info,
    299       fatal);
    300 }
    301 
    302 void ResourceLoader::OnBeforeNetworkStart(net::URLRequest* unused,
    303                                           bool* defer) {
    304   DCHECK_EQ(request_.get(), unused);
    305 
    306   // Give the handler a chance to delay the URLRequest from using the network.
    307   if (!handler_->OnBeforeNetworkStart(request_->url(), defer)) {
    308     Cancel();
    309     return;
    310   } else if (*defer) {
    311     deferred_stage_ = DEFERRED_NETWORK_START;
    312   }
    313 }
    314 
    315 void ResourceLoader::OnResponseStarted(net::URLRequest* unused) {
    316   DCHECK_EQ(request_.get(), unused);
    317 
    318   VLOG(1) << "OnResponseStarted: " << request_->url().spec();
    319 
    320   // The CanLoadPage check should take place after any server redirects have
    321   // finished, at the point in time that we know a page will commit in the
    322   // renderer process.
    323   ResourceRequestInfoImpl* info = GetRequestInfo();
    324   ChildProcessSecurityPolicyImpl* policy =
    325       ChildProcessSecurityPolicyImpl::GetInstance();
    326   if (!policy->CanLoadPage(info->GetChildID(),
    327                            request_->url(),
    328                            info->GetResourceType())) {
    329     Cancel();
    330     return;
    331   }
    332 
    333   if (!request_->status().is_success()) {
    334     ResponseCompleted();
    335     return;
    336   }
    337 
    338   // We want to send a final upload progress message prior to sending the
    339   // response complete message even if we're waiting for an ack to to a
    340   // previous upload progress message.
    341   waiting_for_upload_progress_ack_ = false;
    342   ReportUploadProgress();
    343 
    344   CompleteResponseStarted();
    345 
    346   if (is_deferred())
    347     return;
    348 
    349   if (request_->status().is_success()) {
    350     StartReading(false);  // Read the first chunk.
    351   } else {
    352     ResponseCompleted();
    353   }
    354 }
    355 
    356 void ResourceLoader::OnReadCompleted(net::URLRequest* unused, int bytes_read) {
    357   DCHECK_EQ(request_.get(), unused);
    358   VLOG(1) << "OnReadCompleted: \"" << request_->url().spec() << "\""
    359           << " bytes_read = " << bytes_read;
    360 
    361   // bytes_read == -1 always implies an error.
    362   if (bytes_read == -1 || !request_->status().is_success()) {
    363     ResponseCompleted();
    364     return;
    365   }
    366 
    367   CompleteRead(bytes_read);
    368 
    369   // If the handler cancelled or deferred the request, do not continue
    370   // processing the read. If cancelled, the URLRequest has already been
    371   // cancelled and will schedule an erroring OnReadCompleted later. If deferred,
    372   // do nothing until resumed.
    373   //
    374   // Note: if bytes_read is 0 (EOF) and the handler defers, resumption will call
    375   // ResponseCompleted().
    376   if (is_deferred() || !request_->status().is_success())
    377     return;
    378 
    379   if (bytes_read > 0) {
    380     StartReading(true);  // Read the next chunk.
    381   } else {
    382     // URLRequest reported an EOF. Call ResponseCompleted.
    383     DCHECK_EQ(0, bytes_read);
    384     ResponseCompleted();
    385   }
    386 }
    387 
    388 void ResourceLoader::CancelSSLRequest(const GlobalRequestID& id,
    389                                       int error,
    390                                       const net::SSLInfo* ssl_info) {
    391   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    392 
    393   // The request can be NULL if it was cancelled by the renderer (as the
    394   // request of the user navigating to a new page from the location bar).
    395   if (!request_->is_pending())
    396     return;
    397   DVLOG(1) << "CancelSSLRequest() url: " << request_->url().spec();
    398 
    399   if (ssl_info) {
    400     request_->CancelWithSSLError(error, *ssl_info);
    401   } else {
    402     request_->CancelWithError(error);
    403   }
    404 }
    405 
    406 void ResourceLoader::ContinueSSLRequest(const GlobalRequestID& id) {
    407   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
    408 
    409   DVLOG(1) << "ContinueSSLRequest() url: " << request_->url().spec();
    410 
    411   request_->ContinueDespiteLastError();
    412 }
    413 
    414 void ResourceLoader::Resume() {
    415   DCHECK(!is_transferring_);
    416 
    417   DeferredStage stage = deferred_stage_;
    418   deferred_stage_ = DEFERRED_NONE;
    419   switch (stage) {
    420     case DEFERRED_NONE:
    421       NOTREACHED();
    422       break;
    423     case DEFERRED_START:
    424       StartRequestInternal();
    425       break;
    426     case DEFERRED_NETWORK_START:
    427       request_->ResumeNetworkStart();
    428       break;
    429     case DEFERRED_REDIRECT:
    430       request_->FollowDeferredRedirect();
    431       break;
    432     case DEFERRED_READ:
    433       base::MessageLoop::current()->PostTask(
    434           FROM_HERE,
    435           base::Bind(&ResourceLoader::ResumeReading,
    436                      weak_ptr_factory_.GetWeakPtr()));
    437       break;
    438     case DEFERRED_RESPONSE_COMPLETE:
    439       base::MessageLoop::current()->PostTask(
    440           FROM_HERE,
    441           base::Bind(&ResourceLoader::ResponseCompleted,
    442                      weak_ptr_factory_.GetWeakPtr()));
    443       break;
    444     case DEFERRED_FINISH:
    445       // Delay self-destruction since we don't know how we were reached.
    446       base::MessageLoop::current()->PostTask(
    447           FROM_HERE,
    448           base::Bind(&ResourceLoader::CallDidFinishLoading,
    449                      weak_ptr_factory_.GetWeakPtr()));
    450       break;
    451   }
    452 }
    453 
    454 void ResourceLoader::Cancel() {
    455   CancelRequest(false);
    456 }
    457 
    458 void ResourceLoader::StartRequestInternal() {
    459   DCHECK(!request_->is_pending());
    460 
    461   if (!request_->status().is_success()) {
    462     return;
    463   }
    464 
    465   request_->Start();
    466 
    467   delegate_->DidStartRequest(this);
    468 }
    469 
    470 void ResourceLoader::CancelRequestInternal(int error, bool from_renderer) {
    471   VLOG(1) << "CancelRequestInternal: " << request_->url().spec();
    472 
    473   ResourceRequestInfoImpl* info = GetRequestInfo();
    474 
    475   // WebKit will send us a cancel for downloads since it no longer handles
    476   // them.  In this case, ignore the cancel since we handle downloads in the
    477   // browser.
    478   if (from_renderer && (info->IsDownload() || info->is_stream()))
    479     return;
    480 
    481   if (from_renderer && info->detachable_handler()) {
    482     // TODO(davidben): Fix Blink handling of prefetches so they are not
    483     // cancelled on navigate away and end up in the local cache.
    484     info->detachable_handler()->Detach();
    485     return;
    486   }
    487 
    488   // TODO(darin): Perhaps we should really be looking to see if the status is
    489   // IO_PENDING?
    490   bool was_pending = request_->is_pending();
    491 
    492   if (login_delegate_.get()) {
    493     login_delegate_->OnRequestCancelled();
    494     login_delegate_ = NULL;
    495   }
    496   if (ssl_client_auth_handler_.get()) {
    497     ssl_client_auth_handler_->OnRequestCancelled();
    498     ssl_client_auth_handler_ = NULL;
    499   }
    500 
    501   request_->CancelWithError(error);
    502 
    503   if (!was_pending) {
    504     // If the request isn't in flight, then we won't get an asynchronous
    505     // notification from the request, so we have to signal ourselves to finish
    506     // this request.
    507     base::MessageLoop::current()->PostTask(
    508         FROM_HERE,
    509         base::Bind(&ResourceLoader::ResponseCompleted,
    510                    weak_ptr_factory_.GetWeakPtr()));
    511   }
    512 }
    513 
    514 void ResourceLoader::StoreSignedCertificateTimestamps(
    515     const net::SignedCertificateTimestampAndStatusList& sct_list,
    516     int process_id,
    517     SignedCertificateTimestampIDStatusList* sct_ids) {
    518   SignedCertificateTimestampStore* sct_store(
    519       SignedCertificateTimestampStore::GetInstance());
    520 
    521   for (net::SignedCertificateTimestampAndStatusList::const_iterator iter =
    522        sct_list.begin(); iter != sct_list.end(); ++iter) {
    523     const int sct_id(sct_store->Store(iter->sct.get(), process_id));
    524     sct_ids->push_back(
    525         SignedCertificateTimestampIDAndStatus(sct_id, iter->status));
    526   }
    527 }
    528 
    529 void ResourceLoader::CompleteResponseStarted() {
    530   ResourceRequestInfoImpl* info = GetRequestInfo();
    531 
    532   scoped_refptr<ResourceResponse> response(new ResourceResponse());
    533   PopulateResourceResponse(info, request_.get(), response.get());
    534 
    535   if (request_->ssl_info().cert.get()) {
    536     int cert_id = CertStore::GetInstance()->StoreCert(
    537         request_->ssl_info().cert.get(), info->GetChildID());
    538 
    539     SignedCertificateTimestampIDStatusList signed_certificate_timestamp_ids;
    540     StoreSignedCertificateTimestamps(
    541         request_->ssl_info().signed_certificate_timestamps,
    542         info->GetChildID(),
    543         &signed_certificate_timestamp_ids);
    544 
    545     response->head.security_info = SerializeSecurityInfo(
    546         cert_id,
    547         request_->ssl_info().cert_status,
    548         request_->ssl_info().security_bits,
    549         request_->ssl_info().connection_status,
    550         signed_certificate_timestamp_ids);
    551   } else {
    552     // We should not have any SSL state.
    553     DCHECK(!request_->ssl_info().cert_status &&
    554            request_->ssl_info().security_bits == -1 &&
    555            !request_->ssl_info().connection_status);
    556   }
    557 
    558   delegate_->DidReceiveResponse(this);
    559 
    560   bool defer = false;
    561   if (!handler_->OnResponseStarted(response.get(), &defer)) {
    562     Cancel();
    563   } else if (defer) {
    564     read_deferral_start_time_ = base::TimeTicks::Now();
    565     deferred_stage_ = DEFERRED_READ;  // Read first chunk when resumed.
    566   }
    567 }
    568 
    569 void ResourceLoader::StartReading(bool is_continuation) {
    570   int bytes_read = 0;
    571   ReadMore(&bytes_read);
    572 
    573   // If IO is pending, wait for the URLRequest to call OnReadCompleted.
    574   if (request_->status().is_io_pending())
    575     return;
    576 
    577   if (!is_continuation || bytes_read <= 0) {
    578     OnReadCompleted(request_.get(), bytes_read);
    579   } else {
    580     // Else, trigger OnReadCompleted asynchronously to avoid starving the IO
    581     // thread in case the URLRequest can provide data synchronously.
    582     base::MessageLoop::current()->PostTask(
    583         FROM_HERE,
    584         base::Bind(&ResourceLoader::OnReadCompleted,
    585                    weak_ptr_factory_.GetWeakPtr(),
    586                    request_.get(),
    587                    bytes_read));
    588   }
    589 }
    590 
    591 void ResourceLoader::ResumeReading() {
    592   DCHECK(!is_deferred());
    593 
    594   if (!read_deferral_start_time_.is_null()) {
    595     UMA_HISTOGRAM_TIMES("Net.ResourceLoader.ReadDeferral",
    596                         base::TimeTicks::Now() - read_deferral_start_time_);
    597     read_deferral_start_time_ = base::TimeTicks();
    598   }
    599   if (request_->status().is_success()) {
    600     StartReading(false);  // Read the next chunk (OK to complete synchronously).
    601   } else {
    602     ResponseCompleted();
    603   }
    604 }
    605 
    606 void ResourceLoader::ReadMore(int* bytes_read) {
    607   DCHECK(!is_deferred());
    608 
    609   // Make sure we track the buffer in at least one place.  This ensures it gets
    610   // deleted even in the case the request has already finished its job and
    611   // doesn't use the buffer.
    612   scoped_refptr<net::IOBuffer> buf;
    613   int buf_size;
    614   if (!handler_->OnWillRead(&buf, &buf_size, -1)) {
    615     Cancel();
    616     return;
    617   }
    618 
    619   DCHECK(buf.get());
    620   DCHECK(buf_size > 0);
    621 
    622   request_->Read(buf.get(), buf_size, bytes_read);
    623 
    624   // No need to check the return value here as we'll detect errors by
    625   // inspecting the URLRequest's status.
    626 }
    627 
    628 void ResourceLoader::CompleteRead(int bytes_read) {
    629   DCHECK(bytes_read >= 0);
    630   DCHECK(request_->status().is_success());
    631 
    632   bool defer = false;
    633   if (!handler_->OnReadCompleted(bytes_read, &defer)) {
    634     Cancel();
    635   } else if (defer) {
    636     deferred_stage_ =
    637         bytes_read > 0 ? DEFERRED_READ : DEFERRED_RESPONSE_COMPLETE;
    638   }
    639 
    640   // Note: the request may still have been cancelled while OnReadCompleted
    641   // returns true if OnReadCompleted caused request to get cancelled
    642   // out-of-band. (In AwResourceDispatcherHostDelegate::DownloadStarting, for
    643   // instance.)
    644 }
    645 
    646 void ResourceLoader::ResponseCompleted() {
    647   VLOG(1) << "ResponseCompleted: " << request_->url().spec();
    648   RecordHistograms();
    649   ResourceRequestInfoImpl* info = GetRequestInfo();
    650 
    651   std::string security_info;
    652   const net::SSLInfo& ssl_info = request_->ssl_info();
    653   if (ssl_info.cert.get() != NULL) {
    654     int cert_id = CertStore::GetInstance()->StoreCert(ssl_info.cert.get(),
    655                                                       info->GetChildID());
    656     SignedCertificateTimestampIDStatusList signed_certificate_timestamp_ids;
    657     StoreSignedCertificateTimestamps(ssl_info.signed_certificate_timestamps,
    658                                      info->GetChildID(),
    659                                      &signed_certificate_timestamp_ids);
    660 
    661     security_info = SerializeSecurityInfo(
    662         cert_id, ssl_info.cert_status, ssl_info.security_bits,
    663         ssl_info.connection_status, signed_certificate_timestamp_ids);
    664   }
    665 
    666   bool defer = false;
    667   handler_->OnResponseCompleted(request_->status(), security_info, &defer);
    668   if (defer) {
    669     // The handler is not ready to die yet.  We will call DidFinishLoading when
    670     // we resume.
    671     deferred_stage_ = DEFERRED_FINISH;
    672   } else {
    673     // This will result in our destruction.
    674     CallDidFinishLoading();
    675   }
    676 }
    677 
    678 void ResourceLoader::CallDidFinishLoading() {
    679   delegate_->DidFinishLoading(this);
    680 }
    681 
    682 void ResourceLoader::RecordHistograms() {
    683   ResourceRequestInfoImpl* info = GetRequestInfo();
    684 
    685   if (info->GetResourceType() == RESOURCE_TYPE_PREFETCH) {
    686     PrefetchStatus status = STATUS_UNDEFINED;
    687     TimeDelta total_time = base::TimeTicks::Now() - request_->creation_time();
    688 
    689     switch (request_->status().status()) {
    690       case net::URLRequestStatus::SUCCESS:
    691         if (request_->was_cached()) {
    692           status = STATUS_SUCCESS_FROM_CACHE;
    693           UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeSpentPrefetchingFromCache",
    694                               total_time);
    695         } else {
    696           status = STATUS_SUCCESS_FROM_NETWORK;
    697           UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeSpentPrefetchingFromNetwork",
    698                               total_time);
    699         }
    700         break;
    701       case net::URLRequestStatus::CANCELED:
    702         status = STATUS_CANCELED;
    703         UMA_HISTOGRAM_TIMES("Net.Prefetch.TimeBeforeCancel", total_time);
    704         break;
    705       case net::URLRequestStatus::IO_PENDING:
    706       case net::URLRequestStatus::FAILED:
    707         status = STATUS_UNDEFINED;
    708         break;
    709     }
    710 
    711     UMA_HISTOGRAM_ENUMERATION("Net.Prefetch.Pattern", status, STATUS_MAX);
    712   }
    713 }
    714 
    715 }  // namespace content
    716