resource_loader.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/loader/resource_loader.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/command_line.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/message_loop.h"
9eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/child_process_security_policy_impl.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/loader/doomed_resource_handler.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/loader/resource_loader_delegate.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/loader/resource_request_info_impl.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/ssl/ssl_client_auth_handler.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/ssl/ssl_manager.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/ssl_status_serialization.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/cert_store.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/resource_dispatcher_host_login_delegate.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/site_instance.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/content_client.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/content_switches.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/process_type.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/resource_response.h"
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/url_constants.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/load_flags.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_headers.h"
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/ssl/client_cert_store.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/ssl/client_cert_store_impl.h"
29868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "webkit/browser/appcache/appcache_interceptor.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeDelta;
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeTicks;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PopulateResourceResponse(net::URLRequest* request,
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              ResourceResponse* response) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response->head.error_code = request->status().error();
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response->head.request_time = request->request_time();
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response->head.response_time = request->response_time();
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response->head.headers = request->response_headers();
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request->GetCharset(&response->head.charset);
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response->head.content_length = request->GetExpectedContentSize();
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request->GetMimeType(&response->head.mime_type);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::HttpResponseInfo response_info = request->response_info();
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response->head.was_fetched_via_spdy = response_info.was_fetched_via_spdy;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response->head.was_npn_negotiated = response_info.was_npn_negotiated;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response->head.npn_negotiated_protocol =
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response_info.npn_negotiated_protocol;
51868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  response->head.connection_info = response_info.connection_info;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response->head.was_fetched_via_proxy = request->was_fetched_via_proxy();
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response->head.socket_address = request->GetSocketAddress();
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  appcache::AppCacheInterceptor::GetExtraResponseInfo(
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request,
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &response->head.appcache_id,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &response->head.appcache_manifest_url);
58868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(mmenke):  Figure out if LOAD_ENABLE_LOAD_TIMING is safe to remove.
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (request->load_flags() & net::LOAD_ENABLE_LOAD_TIMING)
60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    request->GetLoadTimingInfo(&response->head.load_timing);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ResourceLoader::ResourceLoader(scoped_ptr<net::URLRequest> request,
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               scoped_ptr<ResourceHandler> handler,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               ResourceLoaderDelegate* delegate)
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : weak_ptr_factory_(this) {
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<net::ClientCertStore> client_cert_store;
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(USE_OPENSSL)
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  client_cert_store.reset(new net::ClientCertStoreImpl());
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Init(request.Pass(), handler.Pass(), delegate, client_cert_store.Pass());
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ResourceLoader::~ResourceLoader() {
77868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (login_delegate_.get())
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    login_delegate_->OnRequestCancelled();
79868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (ssl_client_auth_handler_.get())
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl_client_auth_handler_->OnRequestCancelled();
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Run ResourceHandler destructor before we tear-down the rest of our state
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // as the ResourceHandler may want to inspect the URLRequest and other state.
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  handler_.reset();
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::StartRequest() {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delegate_->HandleExternalProtocol(this, request_->url())) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CancelAndIgnore();
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Give the handler a chance to delay the URLRequest from being started.
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool defer_start = false;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!handler_->OnWillStart(GetRequestInfo()->GetRequestID(), request_->url(),
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             &defer_start)) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Cancel();
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (defer_start) {
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    deferred_stage_ = DEFERRED_START;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StartRequestInternal();
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::CancelRequest(bool from_renderer) {
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CancelRequestInternal(net::ERR_ABORTED, from_renderer);
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::CancelAndIgnore() {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResourceRequestInfoImpl* info = GetRequestInfo();
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  info->set_was_ignored_by_handler(true);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CancelRequest(false);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::CancelWithError(int error_code) {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CancelRequestInternal(error_code, false);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::ReportUploadProgress() {
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResourceRequestInfoImpl* info = GetRequestInfo();
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (waiting_for_upload_progress_ack_)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // Send one progress event at a time.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::UploadProgress progress = request_->GetUploadProgress();
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!progress.size())
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // Nothing to upload.
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (progress.position() == last_upload_position_)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // No progress made since last time.
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint64 kHalfPercentIncrements = 200;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const TimeDelta kOneSecond = TimeDelta::FromMilliseconds(1000);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint64 amt_since_last = progress.position() - last_upload_position_;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeDelta time_since_last = TimeTicks::Now() - last_upload_ticks_;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_finished = (progress.size() == progress.position());
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool enough_new_progress =
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (amt_since_last > (progress.size() / kHalfPercentIncrements));
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool too_much_time_passed = time_since_last > kOneSecond;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_finished || enough_new_progress || too_much_time_passed) {
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (request_->load_flags() & net::LOAD_ENABLE_UPLOAD_PROGRESS) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      handler_->OnUploadProgress(
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          info->GetRequestID(), progress.position(), progress.size());
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      waiting_for_upload_progress_ack_ = true;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_upload_ticks_ = TimeTicks::Now();
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_upload_position_ = progress.position();
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::MarkAsTransferring() {
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_transferring_ = true;
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When an URLRequest is transferred to a new RenderViewHost, its
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ResourceHandler should not receive any notifications because it may depend
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // on the state of the old RVH. We set a ResourceHandler that only allows
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // canceling requests, because on shutdown of the RDH all pending requests
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // are canceled. The RVH of requests that are being transferred may be gone
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // by that time. In CompleteTransfer, the ResoureHandlers are substituted
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // again.
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  handler_.reset(new DoomedResourceHandler(handler_.Pass()));
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::WillCompleteTransfer() {
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  handler_.reset();
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::CompleteTransfer(scoped_ptr<ResourceHandler> new_handler) {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(DEFERRED_REDIRECT, deferred_stage_);
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!handler_.get());
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  handler_ = new_handler.Pass();
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  handler_->SetController(this);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_transferring_ = false;
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Resume();
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ResourceRequestInfoImpl* ResourceLoader::GetRequestInfo() {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ResourceRequestInfoImpl::ForRequest(request_.get());
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::ClearLoginDelegate() {
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  login_delegate_ = NULL;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::ClearSSLClientAuthHandler() {
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_client_auth_handler_ = NULL;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::OnUploadProgressACK() {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  waiting_for_upload_progress_ack_ = false;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ResourceLoader::ResourceLoader(
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<net::URLRequest> request,
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<ResourceHandler> handler,
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ResourceLoaderDelegate* delegate,
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<net::ClientCertStore> client_cert_store)
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : weak_ptr_factory_(this) {
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Init(request.Pass(), handler.Pass(), delegate, client_cert_store.Pass());
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ResourceLoader::Init(scoped_ptr<net::URLRequest> request,
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          scoped_ptr<ResourceHandler> handler,
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          ResourceLoaderDelegate* delegate,
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          scoped_ptr<net::ClientCertStore> client_cert_store) {
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  deferred_stage_ = DEFERRED_NONE;
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request_ = request.Pass();
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  handler_ = handler.Pass();
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delegate_ = delegate;
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  last_upload_position_ = 0;
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  waiting_for_upload_progress_ack_ = false;
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  is_transferring_ = false;
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  client_cert_store_ = client_cert_store.Pass();
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request_->set_delegate(this);
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  handler_->SetController(this);
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::OnReceivedRedirect(net::URLRequest* unused,
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        const GURL& new_url,
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        bool* defer) {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(request_.get(), unused);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "OnReceivedRedirect: " << request_->url().spec();
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(request_->status().is_success());
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResourceRequestInfoImpl* info = GetRequestInfo();
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (info->process_type() != PROCESS_TYPE_PLUGIN &&
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !ChildProcessSecurityPolicyImpl::GetInstance()->
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CanRequestURL(info->GetChildID(), new_url)) {
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Denied unauthorized request for "
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << new_url.possibly_invalid_spec();
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Tell the renderer that this request was disallowed.
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Cancel();
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate_->DidReceiveRedirect(this, new_url);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delegate_->HandleExternalProtocol(this, new_url)) {
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The request is complete so we can remove it.
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CancelAndIgnore();
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<ResourceResponse> response(new ResourceResponse());
257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  PopulateResourceResponse(request_.get(), response.get());
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
259868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!handler_->OnRequestRedirected(
260868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          info->GetRequestID(), new_url, response.get(), defer)) {
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Cancel();
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (*defer) {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    deferred_stage_ = DEFERRED_REDIRECT;  // Follow redirect when resumed.
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::OnAuthRequired(net::URLRequest* unused,
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    net::AuthChallengeInfo* auth_info) {
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(request_.get(), unused);
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request_->load_flags() & net::LOAD_DO_NOT_PROMPT_FOR_LOGIN) {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_->CancelAuth();
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!delegate_->AcceptAuthRequest(this, auth_info)) {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_->CancelAuth();
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a login dialog on the UI thread to get authentication data, or pull
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // from cache and continue on the IO thread.
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
284868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!login_delegate_.get())
285868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      << "OnAuthRequired called with login_delegate pending";
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  login_delegate_ = delegate_->CreateLoginDelegate(this, auth_info);
287868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!login_delegate_.get())
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_->CancelAuth();
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::OnCertificateRequested(
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* unused,
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::SSLCertRequestInfo* cert_info) {
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(request_.get(), unused);
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!delegate_->AcceptSSLClientCertificateRequest(this, cert_info)) {
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_->Cancel();
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(USE_OPENSSL)
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  client_cert_store_->GetClientCerts(*cert_info, &cert_info->client_certs);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cert_info->client_certs.empty()) {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // No need to query the user if there are no certs to choose from.
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_->ContinueWithCertificate(NULL);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!ssl_client_auth_handler_.get())
311868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      << "OnCertificateRequested called with ssl_client_auth_handler pending";
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_client_auth_handler_ = new SSLClientAuthHandler(request_.get(),
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                      cert_info);
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_client_auth_handler_->SelectCertificate();
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::OnSSLCertificateError(net::URLRequest* request,
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           const net::SSLInfo& ssl_info,
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           bool fatal) {
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResourceRequestInfoImpl* info = GetRequestInfo();
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int render_process_id;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int render_view_id;
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!info->GetAssociatedRenderView(&render_process_id, &render_view_id))
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLManager::OnSSLCertificateError(
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      weak_ptr_factory_.GetWeakPtr(),
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      info->GetGlobalRequestID(),
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      info->GetResourceType(),
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request_->url(),
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_process_id,
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_view_id,
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ssl_info,
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fatal);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::OnResponseStarted(net::URLRequest* unused) {
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(request_.get(), unused);
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "OnResponseStarted: " << request_->url().spec();
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The CanLoadPage check should take place after any server redirects have
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // finished, at the point in time that we know a page will commit in the
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // renderer process.
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ResourceRequestInfoImpl* info = GetRequestInfo();
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ChildProcessSecurityPolicyImpl* policy =
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ChildProcessSecurityPolicyImpl::GetInstance();
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!policy->CanLoadPage(info->GetChildID(),
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           request_->url(),
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           info->GetResourceType())) {
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Cancel();
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!request_->status().is_success()) {
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ResponseCompleted();
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We want to send a final upload progress message prior to sending the
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // response complete message even if we're waiting for an ack to to a
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // previous upload progress message.
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  waiting_for_upload_progress_ack_ = false;
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportUploadProgress();
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompleteResponseStarted();
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_deferred())
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request_->status().is_success()) {
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StartReading(false);  // Read the first chunk.
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ResponseCompleted();
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::OnReadCompleted(net::URLRequest* unused, int bytes_read) {
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(request_.get(), unused);
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "OnReadCompleted: \"" << request_->url().spec() << "\""
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << " bytes_read = " << bytes_read;
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // bytes_read == -1 always implies an error.
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bytes_read == -1 || !request_->status().is_success()) {
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ResponseCompleted();
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompleteRead(bytes_read);
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_deferred())
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request_->status().is_success() && bytes_read > 0) {
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StartReading(true);  // Read the next chunk.
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ResponseCompleted();
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::CancelSSLRequest(const GlobalRequestID& id,
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      int error,
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      const net::SSLInfo* ssl_info) {
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The request can be NULL if it was cancelled by the renderer (as the
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // request of the user navigating to a new page from the location bar).
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!request_->is_pending())
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "CancelSSLRequest() url: " << request_->url().spec();
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ssl_info) {
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_->CancelWithSSLError(error, *ssl_info);
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_->CancelWithError(error);
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::ContinueSSLRequest(const GlobalRequestID& id) {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "ContinueSSLRequest() url: " << request_->url().spec();
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_->ContinueDespiteLastError();
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::Resume() {
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!is_transferring_);
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeferredStage stage = deferred_stage_;
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  deferred_stage_ = DEFERRED_NONE;
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (stage) {
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case DEFERRED_NONE:
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case DEFERRED_START:
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      StartRequestInternal();
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case DEFERRED_REDIRECT:
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request_->FollowDeferredRedirect();
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case DEFERRED_READ:
444c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::MessageLoop::current()->PostTask(
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          FROM_HERE,
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&ResourceLoader::ResumeReading,
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr()));
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case DEFERRED_FINISH:
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Delay self-destruction since we don't know how we were reached.
451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::MessageLoop::current()->PostTask(
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          FROM_HERE,
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&ResourceLoader::CallDidFinishLoading,
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr()));
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::Cancel() {
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CancelRequest(false);
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::StartRequestInternal() {
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!request_->is_pending());
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_->Start();
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate_->DidStartRequest(this);
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::CancelRequestInternal(int error, bool from_renderer) {
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "CancelRequestInternal: " << request_->url().spec();
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResourceRequestInfoImpl* info = GetRequestInfo();
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // WebKit will send us a cancel for downloads since it no longer handles
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // them.  In this case, ignore the cancel since we handle downloads in the
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // browser.
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (from_renderer && (info->is_download() || info->is_stream()))
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(darin): Perhaps we should really be looking to see if the status is
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IO_PENDING?
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool was_pending = request_->is_pending();
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (login_delegate_.get()) {
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    login_delegate_->OnRequestCancelled();
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    login_delegate_ = NULL;
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
489868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (ssl_client_auth_handler_.get()) {
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl_client_auth_handler_->OnRequestCancelled();
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl_client_auth_handler_ = NULL;
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_->CancelWithError(error);
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!was_pending) {
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If the request isn't in flight, then we won't get an asynchronous
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // notification from the request, so we have to signal ourselves to finish
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // this request.
500c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::MessageLoop::current()->PostTask(
501c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        FROM_HERE,
502c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::Bind(&ResourceLoader::ResponseCompleted,
503c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::CompleteResponseStarted() {
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResourceRequestInfoImpl* info = GetRequestInfo();
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<ResourceResponse> response(new ResourceResponse());
511868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  PopulateResourceResponse(request_.get(), response.get());
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The --site-per-process flag enables an out-of-process iframes
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // prototype. It works by changing the MIME type of cross-site subframe
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // responses to a Chrome specific one. This new type causes the subframe
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // to be replaced by a <webview> tag with the same URL, which results in
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // using a renderer in a different process.
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // For prototyping purposes, we will use a small hack to ensure same site
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // iframes are not changed. We can compare the URL for the subframe
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // request with the referrer. If the two don't match, then it should be a
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // cross-site iframe.
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Also, we don't do the MIME type change for chrome:// URLs, as those
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // require different privileges and are not allowed in regular renderers.
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The usage of SiteInstance::IsSameWebSite is safe on the IO thread,
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // if the browser_context parameter is NULL. This does not work for hosted
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // apps, but should be fine for prototyping.
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(nasko): Once the SiteInstance check is fixed, ensure we do the
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // right thing here. http://crbug.com/160576
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (command_line.HasSwitch(switches::kSitePerProcess) &&
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetRequestInfo()->GetResourceType() == ResourceType::SUB_FRAME &&
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      response->head.mime_type == "text/html" &&
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      !request_->url().SchemeIs(chrome::kChromeUIScheme) &&
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      !SiteInstance::IsSameWebSite(NULL, request_->url(),
537c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                   GURL(request_->referrer()))) {
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    response->head.mime_type = "application/browser-plugin";
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
541868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (request_->ssl_info().cert.get()) {
542868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int cert_id = CertStore::GetInstance()->StoreCert(
543868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        request_->ssl_info().cert.get(), info->GetChildID());
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    response->head.security_info = SerializeSecurityInfo(
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cert_id,
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        request_->ssl_info().cert_status,
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        request_->ssl_info().security_bits,
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        request_->ssl_info().connection_status);
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We should not have any SSL state.
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!request_->ssl_info().cert_status &&
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           request_->ssl_info().security_bits == -1 &&
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           !request_->ssl_info().connection_status);
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate_->DidReceiveResponse(this);
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool defer = false;
559868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!handler_->OnResponseStarted(
560868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          info->GetRequestID(), response.get(), &defer)) {
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Cancel();
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (defer) {
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    deferred_stage_ = DEFERRED_READ;  // Read first chunk when resumed.
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::StartReading(bool is_continuation) {
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int bytes_read = 0;
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadMore(&bytes_read);
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If IO is pending, wait for the URLRequest to call OnReadCompleted.
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request_->status().is_io_pending())
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!is_continuation || bytes_read <= 0) {
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnReadCompleted(request_.get(), bytes_read);
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Else, trigger OnReadCompleted asynchronously to avoid starving the IO
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // thread in case the URLRequest can provide data synchronously.
580c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::MessageLoop::current()->PostTask(
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&ResourceLoader::OnReadCompleted,
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr(),
584c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   request_.get(),
585c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   bytes_read));
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::ResumeReading() {
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!is_deferred());
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request_->status().is_success()) {
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StartReading(false);  // Read the next chunk (OK to complete synchronously).
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ResponseCompleted();
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::ReadMore(int* bytes_read) {
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResourceRequestInfoImpl* info = GetRequestInfo();
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!is_deferred());
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::IOBuffer* buf;
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int buf_size;
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!handler_->OnWillRead(info->GetRequestID(), &buf, &buf_size, -1)) {
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Cancel();
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(buf);
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(buf_size > 0);
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_->Read(buf, buf_size, bytes_read);
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No need to check the return value here as we'll detect errors by
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // inspecting the URLRequest's status.
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::CompleteRead(int bytes_read) {
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(bytes_read >= 0);
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(request_->status().is_success());
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResourceRequestInfoImpl* info = GetRequestInfo();
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool defer = false;
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!handler_->OnReadCompleted(info->GetRequestID(), bytes_read, &defer)) {
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Cancel();
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (defer) {
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    deferred_stage_ = DEFERRED_READ;  // Read next chunk when resumed.
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::ResponseCompleted() {
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "ResponseCompleted: " << request_->url().spec();
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResourceRequestInfoImpl* info = GetRequestInfo();
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string security_info;
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const net::SSLInfo& ssl_info = request_->ssl_info();
639868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (ssl_info.cert.get() != NULL) {
640868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int cert_id = CertStore::GetInstance()->StoreCert(ssl_info.cert.get(),
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                      info->GetChildID());
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    security_info = SerializeSecurityInfo(
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cert_id, ssl_info.cert_status, ssl_info.security_bits,
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ssl_info.connection_status);
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (handler_->OnResponseCompleted(info->GetRequestID(), request_->status(),
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    security_info)) {
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This will result in our destruction.
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CallDidFinishLoading();
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The handler is not ready to die yet.  We will call DidFinishLoading when
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // we resume.
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    deferred_stage_ = DEFERRED_FINISH;
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::CallDidFinishLoading() {
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate_->DidFinishLoading(this);
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
663