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
PopulateResourceResponse(ResourceRequestInfoImpl * info,net::URLRequest * request,ResourceResponse * response)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
ResourceLoader(scoped_ptr<net::URLRequest> request,scoped_ptr<ResourceHandler> handler,ResourceLoaderDelegate * delegate)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
~ResourceLoader()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
StartRequest()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
CancelRequest(bool from_renderer)124 void ResourceLoader::CancelRequest(bool from_renderer) {
125 CancelRequestInternal(net::ERR_ABORTED, from_renderer);
126 }
127
CancelAndIgnore()128 void ResourceLoader::CancelAndIgnore() {
129 ResourceRequestInfoImpl* info = GetRequestInfo();
130 info->set_was_ignored_by_handler(true);
131 CancelRequest(false);
132 }
133
CancelWithError(int error_code)134 void ResourceLoader::CancelWithError(int error_code) {
135 CancelRequestInternal(error_code, false);
136 }
137
ReportUploadProgress()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
MarkAsTransferring()170 void ResourceLoader::MarkAsTransferring() {
171 CHECK(IsResourceTypeFrame(GetRequestInfo()->GetResourceType()))
172 << "Can only transfer for navigations";
173 is_transferring_ = true;
174 }
175
CompleteTransfer()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
GetRequestInfo()188 ResourceRequestInfoImpl* ResourceLoader::GetRequestInfo() {
189 return ResourceRequestInfoImpl::ForRequest(request_.get());
190 }
191
ClearLoginDelegate()192 void ResourceLoader::ClearLoginDelegate() {
193 login_delegate_ = NULL;
194 }
195
ClearSSLClientAuthHandler()196 void ResourceLoader::ClearSSLClientAuthHandler() {
197 ssl_client_auth_handler_ = NULL;
198 }
199
OnUploadProgressACK()200 void ResourceLoader::OnUploadProgressACK() {
201 waiting_for_upload_progress_ack_ = false;
202 }
203
OnReceivedRedirect(net::URLRequest * unused,const net::RedirectInfo & redirect_info,bool * defer)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
OnAuthRequired(net::URLRequest * unused,net::AuthChallengeInfo * auth_info)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
OnCertificateRequested(net::URLRequest * unused,net::SSLCertRequestInfo * cert_info)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
OnSSLCertificateError(net::URLRequest * request,const net::SSLInfo & ssl_info,bool fatal)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
OnBeforeNetworkStart(net::URLRequest * unused,bool * defer)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
OnResponseStarted(net::URLRequest * unused)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
OnReadCompleted(net::URLRequest * unused,int bytes_read)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
CancelSSLRequest(const GlobalRequestID & id,int error,const net::SSLInfo * ssl_info)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
ContinueSSLRequest(const GlobalRequestID & id)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
Resume()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
Cancel()454 void ResourceLoader::Cancel() {
455 CancelRequest(false);
456 }
457
StartRequestInternal()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
CancelRequestInternal(int error,bool from_renderer)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
StoreSignedCertificateTimestamps(const net::SignedCertificateTimestampAndStatusList & sct_list,int process_id,SignedCertificateTimestampIDStatusList * sct_ids)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
CompleteResponseStarted()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
StartReading(bool is_continuation)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
ResumeReading()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
ReadMore(int * bytes_read)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
CompleteRead(int bytes_read)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
ResponseCompleted()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
CallDidFinishLoading()678 void ResourceLoader::CallDidFinishLoading() {
679 delegate_->DidFinishLoading(this);
680 }
681
RecordHistograms()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