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