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/buffered_resource_handler.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/download/download_resource_handler.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/download/download_stats.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/loader/certificate_resource_handler.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/loader/resource_dispatcher_host_impl.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/browser/loader/resource_request_info_impl.h"
18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "content/browser/loader/stream_resource_handler.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/content_browser_client.h"
207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "content/public/browser/download_item.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/download_save_info.h"
227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "content/public/browser/download_url_parameters.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/resource_context.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/resource_dispatcher_host_delegate.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/resource_response.h"
26ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "content/public/common/webplugininfo.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/io_buffer.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/mime_sniffer.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/mime_util.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_content_disposition.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_headers.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(ENABLE_PLUGINS)
351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/browser/plugin_service_impl.h"
361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void RecordSnifferMetrics(bool sniffing_blocked,
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          bool we_would_like_to_sniff,
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          const std::string& mime_type) {
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static base::HistogramBase* nosniff_usage(NULL);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!nosniff_usage)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nosniff_usage = base::BooleanHistogram::FactoryGet(
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        "nosniff.usage", base::HistogramBase::kUmaTargetedHistogramFlag);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  nosniff_usage->AddBoolean(sniffing_blocked);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (sniffing_blocked) {
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    static base::HistogramBase* nosniff_otherwise(NULL);
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!nosniff_otherwise)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nosniff_otherwise = base::BooleanHistogram::FactoryGet(
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          "nosniff.otherwise", base::HistogramBase::kUmaTargetedHistogramFlag);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nosniff_otherwise->AddBoolean(we_would_like_to_sniff);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    static base::HistogramBase* nosniff_empty_mime_type(NULL);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!nosniff_empty_mime_type)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      nosniff_empty_mime_type = base::BooleanHistogram::FactoryGet(
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "nosniff.empty_mime_type",
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::HistogramBase::kUmaTargetedHistogramFlag);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    nosniff_empty_mime_type->AddBoolean(mime_type.empty());
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Used to write into an existing IOBuffer at a given offset.
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DependentIOBuffer : public net::WrappedIOBuffer {
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DependentIOBuffer(net::IOBuffer* buf, int offset)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : net::WrappedIOBuffer(buf->data() + offset),
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        buf_(buf) {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~DependentIOBuffer() {}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<net::IOBuffer> buf_;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BufferedResourceHandler::BufferedResourceHandler(
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<ResourceHandler> next_handler,
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ResourceDispatcherHostImpl* host,
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    net::URLRequest* request)
874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    : LayeredResourceHandler(request, next_handler.Pass()),
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      state_(STATE_STARTING),
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      host_(host),
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      read_buffer_size_(0),
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bytes_read_(0),
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      must_download_(false),
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      must_download_is_set_(false),
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      weak_ptr_factory_(this) {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)BufferedResourceHandler::~BufferedResourceHandler() {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedResourceHandler::SetController(ResourceController* controller) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResourceHandler::SetController(controller);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Downstream handlers see us as their ResourceController, which allows us to
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // consume part or all of the resource response, and then later replay it to
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // downstream handler.
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(next_handler_.get());
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_handler_->SetController(this);
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool BufferedResourceHandler::OnResponseStarted(ResourceResponse* response,
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                                bool* defer) {
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response_ = response;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(darin): It is very odd to special-case 304 responses at this level.
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We do so only because the code always has, see r24977 and r29355.  The
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // fact that 204 is no longer special-cased this way suggests that 304 need
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // not be special-cased either.
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The network stack only forwards 304 responses that were not received in
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // response to a conditional request (i.e., If-Modified-Since).  Other 304
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // responses end up being translated to 200 or whatever the cached response
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // code happens to be.  It should be very rare to see a 304 at this level.
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
124868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!(response_->head.headers.get() &&
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        response_->head.headers->response_code() == 304)) {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ShouldSniffContent()) {
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      state_ = STATE_BUFFERING;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (response_->head.mime_type.empty()) {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Ugg.  The server told us not to sniff the content but didn't give us
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // a mime type.  What's a browser to do?  Turns out, we're supposed to
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // treat the response as "text/plain".  This is the most secure option.
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response_->head.mime_type.assign("text/plain");
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Treat feed types as text/plain.
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (response_->head.mime_type == "application/rss+xml" ||
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        response_->head.mime_type == "application/atom+xml") {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response_->head.mime_type.assign("text/plain");
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_ = STATE_PROCESSING;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ProcessResponse(defer);
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We'll let the original event handler provide a buffer, and reuse it for
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// subsequent reads until we're done buffering.
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool BufferedResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
1524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                         int* buf_size,
1534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                         int min_size) {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state_ == STATE_STREAMING)
155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return next_handler_->OnWillRead(buf, buf_size, min_size);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(-1, min_size);
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (read_buffer_.get()) {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK_LT(bytes_read_, read_buffer_size_);
161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    *buf = new DependentIOBuffer(read_buffer_.get(), bytes_read_);
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *buf_size = read_buffer_size_ - bytes_read_;
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!next_handler_->OnWillRead(buf, buf_size, min_size))
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    read_buffer_ = *buf;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    read_buffer_size_ = *buf_size;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_GE(read_buffer_size_, net::kMaxBytesToSniff * 2);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool BufferedResourceHandler::OnReadCompleted(int bytes_read, bool* defer) {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (state_ == STATE_STREAMING)
176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return next_handler_->OnReadCompleted(bytes_read, defer);
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(state_, STATE_BUFFERING);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bytes_read_ += bytes_read;
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!DetermineMimeType() && (bytes_read > 0))
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;  // Needs more data, so keep buffering.
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_ = STATE_PROCESSING;
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ProcessResponse(defer);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
188f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void BufferedResourceHandler::OnResponseCompleted(
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const net::URLRequestStatus& status,
190f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const std::string& security_info,
191f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool* defer) {
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Upon completion, act like a pass-through handler in case the downstream
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // handler defers OnResponseCompleted.
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_ = STATE_STREAMING;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  next_handler_->OnResponseCompleted(status, security_info, defer);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedResourceHandler::Resume() {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (state_) {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case STATE_BUFFERING:
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case STATE_PROCESSING:
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case STATE_REPLAYING:
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::MessageLoop::current()->PostTask(
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          FROM_HERE,
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&BufferedResourceHandler::CallReplayReadCompleted,
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr()));
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case STATE_STARTING:
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case STATE_STREAMING:
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      controller()->Resume();
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedResourceHandler::Cancel() {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  controller()->Cancel();
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedResourceHandler::CancelAndIgnore() {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  controller()->CancelAndIgnore();
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedResourceHandler::CancelWithError(int error_code) {
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  controller()->CancelWithError(error_code);
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BufferedResourceHandler::ProcessResponse(bool* defer) {
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_PROCESSING, state_);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(darin): Stop special-casing 304 responses.
234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!(response_->head.headers.get() &&
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        response_->head.headers->response_code() == 304)) {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!SelectNextHandler(defer))
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (*defer)
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_ = STATE_REPLAYING;
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!next_handler_->OnResponseStarted(response_.get(), defer))
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!read_buffer_.get()) {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    state_ = STATE_STREAMING;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!*defer)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ReplayReadCompleted(defer);
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BufferedResourceHandler::ShouldSniffContent() {
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string& mime_type = response_->head.mime_type;
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string content_type_options;
2624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  request()->GetResponseHeaderByName("x-content-type-options",
2634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                     &content_type_options);
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool sniffing_blocked =
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      LowerCaseEqualsASCII(content_type_options, "nosniff");
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool we_would_like_to_sniff =
2684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      net::ShouldSniffMimeType(request()->url(), mime_type);
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RecordSnifferMetrics(sniffing_blocked, we_would_like_to_sniff, mime_type);
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!sniffing_blocked && we_would_like_to_sniff) {
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We're going to look at the data before deciding what the content type
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // is.  That means we need to delay sending the ResponseStarted message
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // over the IPC channel.
2764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    VLOG(1) << "To buffer: " << request()->url().spec();
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BufferedResourceHandler::DetermineMimeType() {
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(STATE_BUFFERING, state_);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string& type_hint = response_->head.mime_type;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string new_type;
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool made_final_decision =
2904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      net::SniffMimeType(read_buffer_->data(), bytes_read_, request()->url(),
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         type_hint, &new_type);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SniffMimeType() returns false if there is not enough data to determine
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the mime type. However, even if it returns false, it returns a new type
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that is probably better than the current one.
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  response_->head.mime_type.assign(new_type);
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return made_final_decision;
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BufferedResourceHandler::SelectNextHandler(bool* defer) {
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!response_->head.mime_type.empty());
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ResourceRequestInfoImpl* info = GetRequestInfo();
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string& mime_type = response_->head.mime_type;
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (net::IsSupportedCertificateMimeType(mime_type)) {
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Install certificate file.
3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    info->set_is_download(true);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<ResourceHandler> handler(
3114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)        new CertificateResourceHandler(request()));
312f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return UseAlternateNextHandler(handler.Pass(), std::string());
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!info->allow_download())
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool must_download = MustDownload();
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!must_download) {
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (net::IsSupportedMimeType(mime_type))
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
323f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    std::string payload;
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    scoped_ptr<ResourceHandler> handler(
325f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        host_->MaybeInterceptAsStream(request(), response_.get(), &payload));
326f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (handler) {
327f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      return UseAlternateNextHandler(handler.Pass(), payload);
328f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(ENABLE_PLUGINS)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool stale;
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool has_plugin = HasSupportingPlugin(&stale);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (stale) {
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Refresh the plugins asynchronously.
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PluginServiceImpl::GetInstance()->GetPlugins(
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          base::Bind(&BufferedResourceHandler::OnPluginsLoaded,
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     weak_ptr_factory_.GetWeakPtr()));
3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      request()->LogBlockedBy("BufferedResourceHandler");
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *defer = true;
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (has_plugin)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Install download handler
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  info->set_is_download(true);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<ResourceHandler> handler(
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      host_->CreateResourceHandlerForDownload(
3514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)          request(),
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          true,  // is_content_initiated
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          must_download,
3541320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          DownloadItem::kInvalidId,
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          scoped_ptr<DownloadSaveInfo>(new DownloadSaveInfo()),
3567dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch          DownloadUrlParameters::OnStartedCallback()));
357f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return UseAlternateNextHandler(handler.Pass(), std::string());
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BufferedResourceHandler::UseAlternateNextHandler(
361f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    scoped_ptr<ResourceHandler> new_handler,
362f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    const std::string& payload_for_old_handler) {
363868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (response_->head.headers.get() &&  // Can be NULL if FTP.
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      response_->head.headers->response_code() / 100 != 2) {
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The response code indicates that this is an error page, but we don't
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // know how to display the content.  We follow Firefox here and show our
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // own error page instead of triggering a download.
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(abarth): We should abstract the response_code test, but this kind
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //               of check is scattered throughout our codebase.
370a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    request()->CancelWithError(net::ERR_INVALID_RESPONSE);
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Inform the original ResourceHandler that this will be handled entirely by
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the new ResourceHandler.
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(darin): We should probably check the return values of these.
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool defer_ignored = false;
378cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  next_handler_->OnResponseStarted(response_.get(), &defer_ignored);
3795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Although deferring OnResponseStarted is legal, the only downstream handler
3805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // which does so is CrossSiteResourceHandler. Cross-site transitions should
3815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // not trigger when switching handlers.
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!defer_ignored);
383f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (payload_for_old_handler.empty()) {
384f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    net::URLRequestStatus status(net::URLRequestStatus::CANCELED,
385f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                 net::ERR_ABORTED);
386f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    next_handler_->OnResponseCompleted(status, std::string(), &defer_ignored);
387f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    DCHECK(!defer_ignored);
388f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  } else {
389f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    scoped_refptr<net::IOBuffer> buf;
390f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    int size = 0;
391f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
3926d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    next_handler_->OnWillRead(&buf, &size, -1);
393f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    CHECK_GE(size, static_cast<int>(payload_for_old_handler.length()));
394f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
395f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    memcpy(buf->data(), payload_for_old_handler.c_str(),
396f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           payload_for_old_handler.length());
397f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
398f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    next_handler_->OnReadCompleted(payload_for_old_handler.length(),
399f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                   &defer_ignored);
400f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    DCHECK(!defer_ignored);
401f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
402f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
403f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    next_handler_->OnResponseCompleted(status, std::string(), &defer_ignored);
404f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    DCHECK(!defer_ignored);
405f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is handled entirely within the new ResourceHandler, so just reset the
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // original ResourceHandler.
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_handler_ = new_handler.Pass();
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  next_handler_->SetController(this);
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
412cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return CopyReadBufferToNextHandler();
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BufferedResourceHandler::ReplayReadCompleted(bool* defer) {
416868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(read_buffer_.get());
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
418cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool result = next_handler_->OnReadCompleted(bytes_read_, defer);
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_buffer_ = NULL;
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  read_buffer_size_ = 0;
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bytes_read_ = 0;
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  state_ = STATE_STREAMING;
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedResourceHandler::CallReplayReadCompleted() {
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool defer = false;
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ReplayReadCompleted(&defer)) {
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    controller()->Cancel();
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (!defer) {
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    state_ = STATE_STREAMING;
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    controller()->Resume();
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BufferedResourceHandler::MustDownload() {
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (must_download_is_set_)
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return must_download_;
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  must_download_is_set_ = true;
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string disposition;
4464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  request()->GetResponseHeaderByName("content-disposition", &disposition);
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!disposition.empty() &&
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      net::HttpContentDisposition(disposition, std::string()).is_attachment()) {
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    must_download_ = true;
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (host_->delegate() &&
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             host_->delegate()->ShouldForceDownloadResource(
4524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                 request()->url(), response_->head.mime_type)) {
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    must_download_ = true;
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    must_download_ = false;
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return must_download_;
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool BufferedResourceHandler::HasSupportingPlugin(bool* stale) {
462f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#if defined(ENABLE_PLUGINS)
4634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  ResourceRequestInfoImpl* info = GetRequestInfo();
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool allow_wildcard = false;
466ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  WebPluginInfo plugin;
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return PluginServiceImpl::GetInstance()->GetPluginInfo(
468a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      info->GetChildID(), info->GetRenderFrameID(), info->GetContext(),
4694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)      request()->url(), GURL(), response_->head.mime_type, allow_wildcard,
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      stale, &plugin, NULL);
471f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#else
472f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  if (stale)
473f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    *stale = false;
474f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  return false;
475f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
478cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool BufferedResourceHandler::CopyReadBufferToNextHandler() {
479cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!read_buffer_.get())
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  scoped_refptr<net::IOBuffer> buf;
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int buf_len = 0;
484cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!next_handler_->OnWillRead(&buf, &buf_len, bytes_read_))
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK((buf_len >= bytes_read_) && (bytes_read_ >= 0));
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memcpy(buf->data(), read_buffer_->data(), bytes_read_);
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void BufferedResourceHandler::OnPluginsLoaded(
493ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const std::vector<WebPluginInfo>& plugins) {
4945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  request()->LogUnblocked();
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool defer = false;
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ProcessResponse(&defer)) {
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    controller()->Cancel();
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (!defer) {
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    controller()->Resume();
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
504