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