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