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"
89ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
94311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch#include "base/metrics/histogram.h"
10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/child_process_security_policy_impl.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/loader/doomed_resource_handler.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/loader/resource_loader_delegate.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/loader/resource_request_info_impl.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/ssl/ssl_client_auth_handler.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/ssl/ssl_manager.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/common/ssl_status_serialization.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/cert_store.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/resource_dispatcher_host_login_delegate.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/site_instance.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/content_client.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/content_switches.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/process_type.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/resource_response.h"
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/common/url_constants.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/load_flags.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_headers.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/ssl/client_cert_store.h"
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/ssl/client_cert_store_impl.h"
30868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "webkit/browser/appcache/appcache_interceptor.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeDelta;
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeTicks;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PopulateResourceResponse(net::URLRequest* request,
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              ResourceResponse* response) {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response->head.error_code = request->status().error();
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response->head.request_time = request->request_time();
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response->head.response_time = request->response_time();
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response->head.headers = request->response_headers();
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request->GetCharset(&response->head.charset);
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response->head.content_length = request->GetExpectedContentSize();
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request->GetMimeType(&response->head.mime_type);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::HttpResponseInfo response_info = request->response_info();
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response->head.was_fetched_via_spdy = response_info.was_fetched_via_spdy;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response->head.was_npn_negotiated = response_info.was_npn_negotiated;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response->head.npn_negotiated_protocol =
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response_info.npn_negotiated_protocol;
52868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  response->head.connection_info = response_info.connection_info;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response->head.was_fetched_via_proxy = request->was_fetched_via_proxy();
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response->head.socket_address = request->GetSocketAddress();
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  appcache::AppCacheInterceptor::GetExtraResponseInfo(
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request,
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &response->head.appcache_id,
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &response->head.appcache_manifest_url);
59868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // TODO(mmenke):  Figure out if LOAD_ENABLE_LOAD_TIMING is safe to remove.
60868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (request->load_flags() & net::LOAD_ENABLE_LOAD_TIMING)
61868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    request->GetLoadTimingInfo(&response->head.load_timing);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ResourceLoader::ResourceLoader(scoped_ptr<net::URLRequest> request,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               scoped_ptr<ResourceHandler> handler,
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               ResourceLoaderDelegate* delegate)
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : weak_ptr_factory_(this) {
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<net::ClientCertStore> client_cert_store;
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(USE_OPENSSL)
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  client_cert_store.reset(new net::ClientCertStoreImpl());
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Init(request.Pass(), handler.Pass(), delegate, client_cert_store.Pass());
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ResourceLoader::~ResourceLoader() {
78868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (login_delegate_.get())
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    login_delegate_->OnRequestCancelled();
80868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (ssl_client_auth_handler_.get())
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl_client_auth_handler_->OnRequestCancelled();
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Run ResourceHandler destructor before we tear-down the rest of our state
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // as the ResourceHandler may want to inspect the URLRequest and other state.
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  handler_.reset();
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::StartRequest() {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delegate_->HandleExternalProtocol(this, request_->url())) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CancelAndIgnore();
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Give the handler a chance to delay the URLRequest from being started.
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool defer_start = false;
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!handler_->OnWillStart(GetRequestInfo()->GetRequestID(), request_->url(),
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             &defer_start)) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Cancel();
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (defer_start) {
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    deferred_stage_ = DEFERRED_START;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StartRequestInternal();
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::CancelRequest(bool from_renderer) {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CancelRequestInternal(net::ERR_ABORTED, from_renderer);
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::CancelAndIgnore() {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResourceRequestInfoImpl* info = GetRequestInfo();
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  info->set_was_ignored_by_handler(true);
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CancelRequest(false);
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::CancelWithError(int error_code) {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CancelRequestInternal(error_code, false);
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::ReportUploadProgress() {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResourceRequestInfoImpl* info = GetRequestInfo();
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (waiting_for_upload_progress_ack_)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // Send one progress event at a time.
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::UploadProgress progress = request_->GetUploadProgress();
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!progress.size())
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // Nothing to upload.
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (progress.position() == last_upload_position_)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // No progress made since last time.
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint64 kHalfPercentIncrements = 200;
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const TimeDelta kOneSecond = TimeDelta::FromMilliseconds(1000);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint64 amt_since_last = progress.position() - last_upload_position_;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeDelta time_since_last = TimeTicks::Now() - last_upload_ticks_;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_finished = (progress.size() == progress.position());
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool enough_new_progress =
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (amt_since_last > (progress.size() / kHalfPercentIncrements));
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool too_much_time_passed = time_since_last > kOneSecond;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_finished || enough_new_progress || too_much_time_passed) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (request_->load_flags() & net::LOAD_ENABLE_UPLOAD_PROGRESS) {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      handler_->OnUploadProgress(
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          info->GetRequestID(), progress.position(), progress.size());
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      waiting_for_upload_progress_ack_ = true;
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_upload_ticks_ = TimeTicks::Now();
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    last_upload_position_ = progress.position();
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
158f968bfd8e7e7331d11d96f3ef27f3d9212e92c39Ben Murdochvoid ResourceLoader::MarkAsTransferring(const GURL& target_url) {
159f968bfd8e7e7331d11d96f3ef27f3d9212e92c39Ben Murdoch  CHECK_EQ(GetRequestInfo()->GetResourceType(), ResourceType::MAIN_FRAME)
160f968bfd8e7e7331d11d96f3ef27f3d9212e92c39Ben Murdoch      << "Cannot transfer non-main frame navigations";
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_transferring_ = true;
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
163f968bfd8e7e7331d11d96f3ef27f3d9212e92c39Ben Murdoch  // When transferring a request to another process, the renderer doesn't get
164f968bfd8e7e7331d11d96f3ef27f3d9212e92c39Ben Murdoch  // a chance to update the cookie policy URL. Do it here instead.
165f968bfd8e7e7331d11d96f3ef27f3d9212e92c39Ben Murdoch  request()->set_first_party_for_cookies(target_url);
166f968bfd8e7e7331d11d96f3ef27f3d9212e92c39Ben Murdoch
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When an URLRequest is transferred to a new RenderViewHost, its
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ResourceHandler should not receive any notifications because it may depend
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // on the state of the old RVH. We set a ResourceHandler that only allows
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // canceling requests, because on shutdown of the RDH all pending requests
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // are canceled. The RVH of requests that are being transferred may be gone
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // by that time. In CompleteTransfer, the ResoureHandlers are substituted
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // again.
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  handler_.reset(new DoomedResourceHandler(handler_.Pass()));
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::WillCompleteTransfer() {
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  handler_.reset();
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::CompleteTransfer(scoped_ptr<ResourceHandler> new_handler) {
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(DEFERRED_REDIRECT, deferred_stage_);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!handler_.get());
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  handler_ = new_handler.Pass();
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  handler_->SetController(this);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  is_transferring_ = false;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Resume();
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ResourceRequestInfoImpl* ResourceLoader::GetRequestInfo() {
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ResourceRequestInfoImpl::ForRequest(request_.get());
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::ClearLoginDelegate() {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  login_delegate_ = NULL;
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::ClearSSLClientAuthHandler() {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_client_auth_handler_ = NULL;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::OnUploadProgressACK() {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  waiting_for_upload_progress_ack_ = false;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ResourceLoader::ResourceLoader(
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<net::URLRequest> request,
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<ResourceHandler> handler,
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ResourceLoaderDelegate* delegate,
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<net::ClientCertStore> client_cert_store)
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : weak_ptr_factory_(this) {
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Init(request.Pass(), handler.Pass(), delegate, client_cert_store.Pass());
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ResourceLoader::Init(scoped_ptr<net::URLRequest> request,
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          scoped_ptr<ResourceHandler> handler,
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          ResourceLoaderDelegate* delegate,
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          scoped_ptr<net::ClientCertStore> client_cert_store) {
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  deferred_stage_ = DEFERRED_NONE;
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request_ = request.Pass();
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  handler_ = handler.Pass();
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  delegate_ = delegate;
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  last_upload_position_ = 0;
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  waiting_for_upload_progress_ack_ = false;
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  is_transferring_ = false;
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  client_cert_store_ = client_cert_store.Pass();
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request_->set_delegate(this);
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  handler_->SetController(this);
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::OnReceivedRedirect(net::URLRequest* unused,
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        const GURL& new_url,
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        bool* defer) {
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(request_.get(), unused);
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "OnReceivedRedirect: " << request_->url().spec();
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(request_->status().is_success());
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResourceRequestInfoImpl* info = GetRequestInfo();
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (info->process_type() != PROCESS_TYPE_PLUGIN &&
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !ChildProcessSecurityPolicyImpl::GetInstance()->
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          CanRequestURL(info->GetChildID(), new_url)) {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    VLOG(1) << "Denied unauthorized request for "
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            << new_url.possibly_invalid_spec();
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Tell the renderer that this request was disallowed.
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Cancel();
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate_->DidReceiveRedirect(this, new_url);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (delegate_->HandleExternalProtocol(this, new_url)) {
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The request is complete so we can remove it.
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CancelAndIgnore();
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<ResourceResponse> response(new ResourceResponse());
264868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  PopulateResourceResponse(request_.get(), response.get());
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
266868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!handler_->OnRequestRedirected(
267868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          info->GetRequestID(), new_url, response.get(), defer)) {
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Cancel();
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (*defer) {
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    deferred_stage_ = DEFERRED_REDIRECT;  // Follow redirect when resumed.
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::OnAuthRequired(net::URLRequest* unused,
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    net::AuthChallengeInfo* auth_info) {
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(request_.get(), unused);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request_->load_flags() & net::LOAD_DO_NOT_PROMPT_FOR_LOGIN) {
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_->CancelAuth();
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!delegate_->AcceptAuthRequest(this, auth_info)) {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_->CancelAuth();
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a login dialog on the UI thread to get authentication data, or pull
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // from cache and continue on the IO thread.
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
291868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!login_delegate_.get())
292868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      << "OnAuthRequired called with login_delegate pending";
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  login_delegate_ = delegate_->CreateLoginDelegate(this, auth_info);
294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!login_delegate_.get())
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_->CancelAuth();
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::OnCertificateRequested(
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* unused,
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::SSLCertRequestInfo* cert_info) {
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(request_.get(), unused);
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!delegate_->AcceptSSLClientCertificateRequest(this, cert_info)) {
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_->Cancel();
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(USE_OPENSSL)
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  client_cert_store_->GetClientCerts(*cert_info, &cert_info->client_certs);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cert_info->client_certs.empty()) {
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // No need to query the user if there are no certs to choose from.
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_->ContinueWithCertificate(NULL);
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
317868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!ssl_client_auth_handler_.get())
318868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      << "OnCertificateRequested called with ssl_client_auth_handler pending";
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_client_auth_handler_ = new SSLClientAuthHandler(request_.get(),
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                      cert_info);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ssl_client_auth_handler_->SelectCertificate();
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::OnSSLCertificateError(net::URLRequest* request,
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           const net::SSLInfo& ssl_info,
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           bool fatal) {
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResourceRequestInfoImpl* info = GetRequestInfo();
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int render_process_id;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int render_view_id;
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!info->GetAssociatedRenderView(&render_process_id, &render_view_id))
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SSLManager::OnSSLCertificateError(
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      weak_ptr_factory_.GetWeakPtr(),
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      info->GetGlobalRequestID(),
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      info->GetResourceType(),
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request_->url(),
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_process_id,
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      render_view_id,
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ssl_info,
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      fatal);
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::OnResponseStarted(net::URLRequest* unused) {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(request_.get(), unused);
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "OnResponseStarted: " << request_->url().spec();
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The CanLoadPage check should take place after any server redirects have
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // finished, at the point in time that we know a page will commit in the
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // renderer process.
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ResourceRequestInfoImpl* info = GetRequestInfo();
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ChildProcessSecurityPolicyImpl* policy =
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ChildProcessSecurityPolicyImpl::GetInstance();
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!policy->CanLoadPage(info->GetChildID(),
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           request_->url(),
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           info->GetResourceType())) {
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Cancel();
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!request_->status().is_success()) {
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ResponseCompleted();
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We want to send a final upload progress message prior to sending the
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // response complete message even if we're waiting for an ack to to a
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // previous upload progress message.
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  waiting_for_upload_progress_ack_ = false;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReportUploadProgress();
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompleteResponseStarted();
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_deferred())
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request_->status().is_success()) {
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StartReading(false);  // Read the first chunk.
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ResponseCompleted();
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::OnReadCompleted(net::URLRequest* unused, int bytes_read) {
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(request_.get(), unused);
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "OnReadCompleted: \"" << request_->url().spec() << "\""
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          << " bytes_read = " << bytes_read;
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // bytes_read == -1 always implies an error.
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bytes_read == -1 || !request_->status().is_success()) {
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ResponseCompleted();
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CompleteRead(bytes_read);
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_deferred())
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request_->status().is_success() && bytes_read > 0) {
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StartReading(true);  // Read the next chunk.
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ResponseCompleted();
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::CancelSSLRequest(const GlobalRequestID& id,
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      int error,
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      const net::SSLInfo* ssl_info) {
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The request can be NULL if it was cancelled by the renderer (as the
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // request of the user navigating to a new page from the location bar).
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!request_->is_pending())
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "CancelSSLRequest() url: " << request_->url().spec();
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ssl_info) {
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_->CancelWithSSLError(error, *ssl_info);
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    request_->CancelWithError(error);
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::ContinueSSLRequest(const GlobalRequestID& id) {
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DVLOG(1) << "ContinueSSLRequest() url: " << request_->url().spec();
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_->ContinueDespiteLastError();
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::Resume() {
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!is_transferring_);
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeferredStage stage = deferred_stage_;
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  deferred_stage_ = DEFERRED_NONE;
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (stage) {
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case DEFERRED_NONE:
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case DEFERRED_START:
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      StartRequestInternal();
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case DEFERRED_REDIRECT:
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      request_->FollowDeferredRedirect();
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case DEFERRED_READ:
451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::MessageLoop::current()->PostTask(
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          FROM_HERE,
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&ResourceLoader::ResumeReading,
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr()));
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case DEFERRED_FINISH:
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Delay self-destruction since we don't know how we were reached.
458c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::MessageLoop::current()->PostTask(
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          FROM_HERE,
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&ResourceLoader::CallDidFinishLoading,
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr()));
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::Cancel() {
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CancelRequest(false);
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::StartRequestInternal() {
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!request_->is_pending());
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_->Start();
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate_->DidStartRequest(this);
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::CancelRequestInternal(int error, bool from_renderer) {
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "CancelRequestInternal: " << request_->url().spec();
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResourceRequestInfoImpl* info = GetRequestInfo();
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // WebKit will send us a cancel for downloads since it no longer handles
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // them.  In this case, ignore the cancel since we handle downloads in the
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // browser.
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (from_renderer && (info->is_download() || info->is_stream()))
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(darin): Perhaps we should really be looking to see if the status is
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IO_PENDING?
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool was_pending = request_->is_pending();
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
492868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (login_delegate_.get()) {
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    login_delegate_->OnRequestCancelled();
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    login_delegate_ = NULL;
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
496868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (ssl_client_auth_handler_.get()) {
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl_client_auth_handler_->OnRequestCancelled();
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ssl_client_auth_handler_ = NULL;
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_->CancelWithError(error);
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!was_pending) {
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If the request isn't in flight, then we won't get an asynchronous
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // notification from the request, so we have to signal ourselves to finish
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // this request.
507c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::MessageLoop::current()->PostTask(
508c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        FROM_HERE,
509c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        base::Bind(&ResourceLoader::ResponseCompleted,
510c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr()));
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::CompleteResponseStarted() {
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResourceRequestInfoImpl* info = GetRequestInfo();
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<ResourceResponse> response(new ResourceResponse());
518868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  PopulateResourceResponse(request_.get(), response.get());
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The --site-per-process flag enables an out-of-process iframes
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // prototype. It works by changing the MIME type of cross-site subframe
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // responses to a Chrome specific one. This new type causes the subframe
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // to be replaced by a <webview> tag with the same URL, which results in
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // using a renderer in a different process.
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // For prototyping purposes, we will use a small hack to ensure same site
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // iframes are not changed. We can compare the URL for the subframe
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // request with the referrer. If the two don't match, then it should be a
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // cross-site iframe.
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Also, we don't do the MIME type change for chrome:// URLs, as those
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // require different privileges and are not allowed in regular renderers.
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The usage of SiteInstance::IsSameWebSite is safe on the IO thread,
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // if the browser_context parameter is NULL. This does not work for hosted
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // apps, but should be fine for prototyping.
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(nasko): Once the SiteInstance check is fixed, ensure we do the
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // right thing here. http://crbug.com/160576
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const CommandLine& command_line = *CommandLine::ForCurrentProcess();
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (command_line.HasSwitch(switches::kSitePerProcess) &&
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetRequestInfo()->GetResourceType() == ResourceType::SUB_FRAME &&
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      response->head.mime_type == "text/html" &&
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      !request_->url().SchemeIs(chrome::kChromeUIScheme) &&
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      !SiteInstance::IsSameWebSite(NULL, request_->url(),
544c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                   GURL(request_->referrer()))) {
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    response->head.mime_type = "application/browser-plugin";
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
548868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (request_->ssl_info().cert.get()) {
549868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int cert_id = CertStore::GetInstance()->StoreCert(
550868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        request_->ssl_info().cert.get(), info->GetChildID());
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    response->head.security_info = SerializeSecurityInfo(
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cert_id,
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        request_->ssl_info().cert_status,
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        request_->ssl_info().security_bits,
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        request_->ssl_info().connection_status);
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We should not have any SSL state.
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!request_->ssl_info().cert_status &&
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           request_->ssl_info().security_bits == -1 &&
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           !request_->ssl_info().connection_status);
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate_->DidReceiveResponse(this);
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool defer = false;
566868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!handler_->OnResponseStarted(
567868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          info->GetRequestID(), response.get(), &defer)) {
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Cancel();
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (defer) {
5704311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch    read_deferral_start_time_ = base::TimeTicks::Now();
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    deferred_stage_ = DEFERRED_READ;  // Read first chunk when resumed.
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::StartReading(bool is_continuation) {
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int bytes_read = 0;
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ReadMore(&bytes_read);
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If IO is pending, wait for the URLRequest to call OnReadCompleted.
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request_->status().is_io_pending())
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!is_continuation || bytes_read <= 0) {
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OnReadCompleted(request_.get(), bytes_read);
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Else, trigger OnReadCompleted asynchronously to avoid starving the IO
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // thread in case the URLRequest can provide data synchronously.
588c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::MessageLoop::current()->PostTask(
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FROM_HERE,
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&ResourceLoader::OnReadCompleted,
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   weak_ptr_factory_.GetWeakPtr(),
592c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   request_.get(),
593c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                   bytes_read));
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::ResumeReading() {
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!is_deferred());
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6004311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  if (!read_deferral_start_time_.is_null()) {
6014311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch    UMA_HISTOGRAM_TIMES("Net.ResourceLoader.ReadDeferral",
6024311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch                        base::TimeTicks::Now() - read_deferral_start_time_);
6034311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch    read_deferral_start_time_ = base::TimeTicks();
6044311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  }
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (request_->status().is_success()) {
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StartReading(false);  // Read the next chunk (OK to complete synchronously).
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ResponseCompleted();
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::ReadMore(int* bytes_read) {
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResourceRequestInfoImpl* info = GetRequestInfo();
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!is_deferred());
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::IOBuffer* buf;
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int buf_size;
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!handler_->OnWillRead(info->GetRequestID(), &buf, &buf_size, -1)) {
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Cancel();
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(buf);
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(buf_size > 0);
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  request_->Read(buf, buf_size, bytes_read);
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No need to check the return value here as we'll detect errors by
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // inspecting the URLRequest's status.
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::CompleteRead(int bytes_read) {
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(bytes_read >= 0);
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(request_->status().is_success());
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResourceRequestInfoImpl* info = GetRequestInfo();
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool defer = false;
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!handler_->OnReadCompleted(info->GetRequestID(), bytes_read, &defer)) {
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Cancel();
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (defer) {
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    deferred_stage_ = DEFERRED_READ;  // Read next chunk when resumed.
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::ResponseCompleted() {
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  VLOG(1) << "ResponseCompleted: " << request_->url().spec();
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResourceRequestInfoImpl* info = GetRequestInfo();
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string security_info;
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const net::SSLInfo& ssl_info = request_->ssl_info();
652868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (ssl_info.cert.get() != NULL) {
653868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    int cert_id = CertStore::GetInstance()->StoreCert(ssl_info.cert.get(),
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                      info->GetChildID());
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    security_info = SerializeSecurityInfo(
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        cert_id, ssl_info.cert_status, ssl_info.security_bits,
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ssl_info.connection_status);
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (handler_->OnResponseCompleted(info->GetRequestID(), request_->status(),
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    security_info)) {
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This will result in our destruction.
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CallDidFinishLoading();
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The handler is not ready to die yet.  We will call DidFinishLoading when
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // we resume.
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    deferred_stage_ = DEFERRED_FINISH;
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ResourceLoader::CallDidFinishLoading() {
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delegate_->DidFinishLoading(this);
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
676