blob: e8ea6840ab6893f93a83c4e4ede2ac931e02f94a [file] [log] [blame]
[email protected]0a0b2542012-01-03 08:25:221// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]e3c404b2008-12-23 01:07:322// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]678c0362012-12-05 08:02:445#include "content/browser/loader/buffered_resource_handler.h"
[email protected]e3c404b2008-12-23 01:07:326
[email protected]dd9b5462009-09-25 17:22:237#include <vector>
8
[email protected]d33e7cc2011-09-23 01:43:569#include "base/bind.h"
[email protected]5203e6002009-07-29 03:42:0010#include "base/logging.h"
[email protected]835d7c82010-10-14 04:38:3811#include "base/metrics/histogram.h"
[email protected]348fbaac2013-06-11 06:31:5112#include "base/strings/string_util.h"
[email protected]254ed742011-08-16 18:45:2713#include "content/browser/download/download_resource_handler.h"
[email protected]14365e32012-01-24 01:12:2214#include "content/browser/download/download_stats.h"
[email protected]3b455502012-12-11 18:22:5815#include "content/browser/loader/certificate_resource_handler.h"
[email protected]678c0362012-12-05 08:02:4416#include "content/browser/loader/resource_dispatcher_host_impl.h"
17#include "content/browser/loader/resource_request_info_impl.h"
[email protected]e67385f2011-12-21 06:00:5618#include "content/browser/plugin_service_impl.h"
[email protected]87f3c082011-10-19 18:07:4419#include "content/public/browser/content_browser_client.h"
[email protected]530047e2013-07-12 17:02:2520#include "content/public/browser/download_item.h"
[email protected]29a5ffc82012-03-13 19:35:5821#include "content/public/browser/download_save_info.h"
[email protected]530047e2013-07-12 17:02:2522#include "content/public/browser/download_url_parameters.h"
[email protected]ce967862012-02-09 22:47:0523#include "content/public/browser/resource_context.h"
[email protected]1bd0ef12011-10-20 05:24:1724#include "content/public/browser/resource_dispatcher_host_delegate.h"
[email protected]2336ffe2011-11-24 01:23:3425#include "content/public/common/resource_response.h"
[email protected]d7bd3e52013-07-21 04:29:2026#include "content/public/common/webplugininfo.h"
[email protected]dd9b5462009-09-25 17:22:2327#include "net/base/io_buffer.h"
[email protected]9dea9e1f2009-01-29 00:30:4728#include "net/base/mime_sniffer.h"
[email protected]35fa6a22009-08-15 00:04:0129#include "net/base/mime_util.h"
[email protected]dd9b5462009-09-25 17:22:2330#include "net/base/net_errors.h"
[email protected]28ca9fb2012-01-28 14:50:2431#include "net/http/http_content_disposition.h"
[email protected]319d9e6f2009-02-18 19:47:2132#include "net/http/http_response_headers.h"
[email protected]e3c404b2008-12-23 01:07:3233
[email protected]d18720a2012-01-06 09:53:5534namespace content {
35
[email protected]306291392009-01-17 19:15:3636namespace {
37
38void RecordSnifferMetrics(bool sniffing_blocked,
39 bool we_would_like_to_sniff,
40 const std::string& mime_type) {
[email protected]de415552013-01-23 04:12:1741 static base::HistogramBase* nosniff_usage(NULL);
[email protected]81ce9f3b2011-04-05 04:48:5342 if (!nosniff_usage)
43 nosniff_usage = base::BooleanHistogram::FactoryGet(
[email protected]de415552013-01-23 04:12:1744 "nosniff.usage", base::HistogramBase::kUmaTargetedHistogramFlag);
[email protected]e8829a192009-12-06 00:09:3745 nosniff_usage->AddBoolean(sniffing_blocked);
[email protected]306291392009-01-17 19:15:3646
47 if (sniffing_blocked) {
[email protected]de415552013-01-23 04:12:1748 static base::HistogramBase* nosniff_otherwise(NULL);
[email protected]81ce9f3b2011-04-05 04:48:5349 if (!nosniff_otherwise)
50 nosniff_otherwise = base::BooleanHistogram::FactoryGet(
[email protected]de415552013-01-23 04:12:1751 "nosniff.otherwise", base::HistogramBase::kUmaTargetedHistogramFlag);
[email protected]e8829a192009-12-06 00:09:3752 nosniff_otherwise->AddBoolean(we_would_like_to_sniff);
[email protected]306291392009-01-17 19:15:3653
[email protected]de415552013-01-23 04:12:1754 static base::HistogramBase* nosniff_empty_mime_type(NULL);
[email protected]81ce9f3b2011-04-05 04:48:5355 if (!nosniff_empty_mime_type)
56 nosniff_empty_mime_type = base::BooleanHistogram::FactoryGet(
57 "nosniff.empty_mime_type",
[email protected]de415552013-01-23 04:12:1758 base::HistogramBase::kUmaTargetedHistogramFlag);
[email protected]e8829a192009-12-06 00:09:3759 nosniff_empty_mime_type->AddBoolean(mime_type.empty());
[email protected]306291392009-01-17 19:15:3660 }
61}
62
[email protected]926360f2012-06-29 04:45:0263// Used to write into an existing IOBuffer at a given offset.
64class DependentIOBuffer : public net::WrappedIOBuffer {
65 public:
66 DependentIOBuffer(net::IOBuffer* buf, int offset)
67 : net::WrappedIOBuffer(buf->data() + offset),
68 buf_(buf) {
69 }
70
71 private:
[email protected]c3e35892013-02-12 02:08:0172 virtual ~DependentIOBuffer() {}
[email protected]926360f2012-06-29 04:45:0273
74 scoped_refptr<net::IOBuffer> buf_;
75};
76
[email protected]306291392009-01-17 19:15:3677} // namespace
78
[email protected]ea114722012-03-12 01:11:2579BufferedResourceHandler::BufferedResourceHandler(
[email protected]d651cbc2012-05-31 21:33:0580 scoped_ptr<ResourceHandler> next_handler,
[email protected]ea114722012-03-12 01:11:2581 ResourceDispatcherHostImpl* host,
82 net::URLRequest* request)
[email protected]ef5306e2013-10-15 19:38:1883 : LayeredResourceHandler(request, next_handler.Pass()),
[email protected]926360f2012-06-29 04:45:0284 state_(STATE_STARTING),
[email protected]e3c404b2008-12-23 01:07:3285 host_(host),
[email protected]dd9b5462009-09-25 17:22:2386 read_buffer_size_(0),
[email protected]e3c404b2008-12-23 01:07:3287 bytes_read_(0),
[email protected]926360f2012-06-29 04:45:0288 must_download_(false),
[email protected]5c1d3e52012-08-01 05:14:2789 must_download_is_set_(false),
90 weak_ptr_factory_(this) {
[email protected]926360f2012-06-29 04:45:0291}
92
93BufferedResourceHandler::~BufferedResourceHandler() {
94}
95
96void BufferedResourceHandler::SetController(ResourceController* controller) {
97 ResourceHandler::SetController(controller);
98
99 // Downstream handlers see us as their ResourceController, which allows us to
100 // consume part or all of the resource response, and then later replay it to
101 // downstream handler.
102 DCHECK(next_handler_.get());
103 next_handler_->SetController(this);
[email protected]e3c404b2008-12-23 01:07:32104}
105
[email protected]d22e800e2014-05-28 21:55:57106bool BufferedResourceHandler::OnResponseStarted(ResourceResponse* response,
107 bool* defer) {
[email protected]e3c404b2008-12-23 01:07:32108 response_ = response;
[email protected]22b305442012-05-21 18:02:59109
[email protected]926360f2012-06-29 04:45:02110 // TODO(darin): It is very odd to special-case 304 responses at this level.
111 // We do so only because the code always has, see r24977 and r29355. The
112 // fact that 204 is no longer special-cased this way suggests that 304 need
113 // not be special-cased either.
114 //
115 // The network stack only forwards 304 responses that were not received in
116 // response to a conditional request (i.e., If-Modified-Since). Other 304
117 // responses end up being translated to 200 or whatever the cached response
118 // code happens to be. It should be very rare to see a 304 at this level.
[email protected]22b305442012-05-21 18:02:59119
[email protected]fc72bb12013-06-02 21:13:46120 if (!(response_->head.headers.get() &&
[email protected]926360f2012-06-29 04:45:02121 response_->head.headers->response_code() == 304)) {
122 if (ShouldSniffContent()) {
123 state_ = STATE_BUFFERING;
124 return true;
125 }
126
127 if (response_->head.mime_type.empty()) {
128 // Ugg. The server told us not to sniff the content but didn't give us
129 // a mime type. What's a browser to do? Turns out, we're supposed to
130 // treat the response as "text/plain". This is the most secure option.
131 response_->head.mime_type.assign("text/plain");
132 }
[email protected]3ff679262012-10-12 23:40:05133
134 // Treat feed types as text/plain.
135 if (response_->head.mime_type == "application/rss+xml" ||
136 response_->head.mime_type == "application/atom+xml") {
137 response_->head.mime_type.assign("text/plain");
138 }
[email protected]22b305442012-05-21 18:02:59139 }
[email protected]926360f2012-06-29 04:45:02140
141 state_ = STATE_PROCESSING;
142 return ProcessResponse(defer);
[email protected]e3c404b2008-12-23 01:07:32143}
144
[email protected]e3c404b2008-12-23 01:07:32145// We'll let the original event handler provide a buffer, and reuse it for
146// subsequent reads until we're done buffering.
[email protected]d22e800e2014-05-28 21:55:57147bool BufferedResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
[email protected]ef5306e2013-10-15 19:38:18148 int* buf_size,
149 int min_size) {
[email protected]926360f2012-06-29 04:45:02150 if (state_ == STATE_STREAMING)
[email protected]d22e800e2014-05-28 21:55:57151 return next_handler_->OnWillRead(buf, buf_size, min_size);
[email protected]926360f2012-06-29 04:45:02152
153 DCHECK_EQ(-1, min_size);
154
[email protected]fc72bb12013-06-02 21:13:46155 if (read_buffer_.get()) {
[email protected]926360f2012-06-29 04:45:02156 CHECK_LT(bytes_read_, read_buffer_size_);
[email protected]fc72bb12013-06-02 21:13:46157 *buf = new DependentIOBuffer(read_buffer_.get(), bytes_read_);
[email protected]926360f2012-06-29 04:45:02158 *buf_size = read_buffer_size_ - bytes_read_;
159 } else {
[email protected]d22e800e2014-05-28 21:55:57160 if (!next_handler_->OnWillRead(buf, buf_size, min_size))
[email protected]926360f2012-06-29 04:45:02161 return false;
162
163 read_buffer_ = *buf;
164 read_buffer_size_ = *buf_size;
165 DCHECK_GE(read_buffer_size_, net::kMaxBytesToSniff * 2);
[email protected]e3c404b2008-12-23 01:07:32166 }
[email protected]67199052009-06-12 21:15:33167 return true;
[email protected]e3c404b2008-12-23 01:07:32168}
169
[email protected]d22e800e2014-05-28 21:55:57170bool BufferedResourceHandler::OnReadCompleted(int bytes_read, bool* defer) {
[email protected]926360f2012-06-29 04:45:02171 if (state_ == STATE_STREAMING)
[email protected]d22e800e2014-05-28 21:55:57172 return next_handler_->OnReadCompleted(bytes_read, defer);
[email protected]e3c404b2008-12-23 01:07:32173
[email protected]926360f2012-06-29 04:45:02174 DCHECK_EQ(state_, STATE_BUFFERING);
175 bytes_read_ += bytes_read;
[email protected]e3c404b2008-12-23 01:07:32176
[email protected]926360f2012-06-29 04:45:02177 if (!DetermineMimeType() && (bytes_read > 0))
178 return true; // Needs more data, so keep buffering.
179
180 state_ = STATE_PROCESSING;
181 return ProcessResponse(defer);
182}
183
[email protected]3780874a2013-11-18 05:49:03184void BufferedResourceHandler::OnResponseCompleted(
[email protected]926360f2012-06-29 04:45:02185 const net::URLRequestStatus& status,
[email protected]3780874a2013-11-18 05:49:03186 const std::string& security_info,
187 bool* defer) {
[email protected]926360f2012-06-29 04:45:02188 // Upon completion, act like a pass-through handler in case the downstream
189 // handler defers OnResponseCompleted.
190 state_ = STATE_STREAMING;
191
[email protected]d22e800e2014-05-28 21:55:57192 next_handler_->OnResponseCompleted(status, security_info, defer);
[email protected]926360f2012-06-29 04:45:02193}
194
195void BufferedResourceHandler::Resume() {
196 switch (state_) {
197 case STATE_BUFFERING:
198 case STATE_PROCESSING:
199 NOTREACHED();
200 break;
201 case STATE_REPLAYING:
[email protected]dd32b1272013-05-04 14:17:11202 base::MessageLoop::current()->PostTask(
[email protected]926360f2012-06-29 04:45:02203 FROM_HERE,
204 base::Bind(&BufferedResourceHandler::CallReplayReadCompleted,
[email protected]5c1d3e52012-08-01 05:14:27205 weak_ptr_factory_.GetWeakPtr()));
[email protected]926360f2012-06-29 04:45:02206 break;
207 case STATE_STARTING:
208 case STATE_STREAMING:
209 controller()->Resume();
210 break;
211 }
212}
213
214void BufferedResourceHandler::Cancel() {
215 controller()->Cancel();
216}
217
[email protected]2756a8e2012-09-07 18:24:29218void BufferedResourceHandler::CancelAndIgnore() {
219 controller()->CancelAndIgnore();
220}
221
[email protected]af3d4962012-10-19 10:57:26222void BufferedResourceHandler::CancelWithError(int error_code) {
223 controller()->CancelWithError(error_code);
224}
225
[email protected]926360f2012-06-29 04:45:02226bool BufferedResourceHandler::ProcessResponse(bool* defer) {
227 DCHECK_EQ(STATE_PROCESSING, state_);
228
229 // TODO(darin): Stop special-casing 304 responses.
[email protected]fc72bb12013-06-02 21:13:46230 if (!(response_->head.headers.get() &&
[email protected]926360f2012-06-29 04:45:02231 response_->head.headers->response_code() == 304)) {
232 if (!SelectNextHandler(defer))
[email protected]e3c404b2008-12-23 01:07:32233 return false;
[email protected]22b305442012-05-21 18:02:59234 if (*defer)
[email protected]98d6f152011-09-29 19:35:51235 return true;
[email protected]926360f2012-06-29 04:45:02236 }
237
238 state_ = STATE_REPLAYING;
239
[email protected]d22e800e2014-05-28 21:55:57240 if (!next_handler_->OnResponseStarted(response_.get(), defer))
[email protected]926360f2012-06-29 04:45:02241 return false;
242
[email protected]fc72bb12013-06-02 21:13:46243 if (!read_buffer_.get()) {
[email protected]926360f2012-06-29 04:45:02244 state_ = STATE_STREAMING;
[email protected]35fa6a22009-08-15 00:04:01245 return true;
[email protected]e3c404b2008-12-23 01:07:32246 }
247
[email protected]926360f2012-06-29 04:45:02248 if (!*defer)
249 return ReplayReadCompleted(defer);
[email protected]5e5e0c82012-01-25 09:12:29250
[email protected]926360f2012-06-29 04:45:02251 return true;
[email protected]e3c404b2008-12-23 01:07:32252}
253
[email protected]926360f2012-06-29 04:45:02254bool BufferedResourceHandler::ShouldSniffContent() {
255 const std::string& mime_type = response_->head.mime_type;
[email protected]e3c404b2008-12-23 01:07:32256
257 std::string content_type_options;
[email protected]ef5306e2013-10-15 19:38:18258 request()->GetResponseHeaderByName("x-content-type-options",
259 &content_type_options);
[email protected]306291392009-01-17 19:15:36260
[email protected]926360f2012-06-29 04:45:02261 bool sniffing_blocked =
[email protected]423bd5b842009-01-23 17:30:50262 LowerCaseEqualsASCII(content_type_options, "nosniff");
[email protected]926360f2012-06-29 04:45:02263 bool we_would_like_to_sniff =
[email protected]ef5306e2013-10-15 19:38:18264 net::ShouldSniffMimeType(request()->url(), mime_type);
[email protected]306291392009-01-17 19:15:36265
266 RecordSnifferMetrics(sniffing_blocked, we_would_like_to_sniff, mime_type);
267
268 if (!sniffing_blocked && we_would_like_to_sniff) {
[email protected]e3c404b2008-12-23 01:07:32269 // We're going to look at the data before deciding what the content type
270 // is. That means we need to delay sending the ResponseStarted message
271 // over the IPC channel.
[email protected]ef5306e2013-10-15 19:38:18272 VLOG(1) << "To buffer: " << request()->url().spec();
[email protected]e3c404b2008-12-23 01:07:32273 return true;
274 }
275
[email protected]e3c404b2008-12-23 01:07:32276 return false;
277}
278
[email protected]926360f2012-06-29 04:45:02279bool BufferedResourceHandler::DetermineMimeType() {
280 DCHECK_EQ(STATE_BUFFERING, state_);
[email protected]35fa6a22009-08-15 00:04:01281
[email protected]926360f2012-06-29 04:45:02282 const std::string& type_hint = response_->head.mime_type;
283
284 std::string new_type;
285 bool made_final_decision =
[email protected]ef5306e2013-10-15 19:38:18286 net::SniffMimeType(read_buffer_->data(), bytes_read_, request()->url(),
[email protected]926360f2012-06-29 04:45:02287 type_hint, &new_type);
288
289 // SniffMimeType() returns false if there is not enough data to determine
290 // the mime type. However, even if it returns false, it returns a new type
291 // that is probably better than the current one.
292 response_->head.mime_type.assign(new_type);
293
294 return made_final_decision;
[email protected]35fa6a22009-08-15 00:04:01295}
296
[email protected]926360f2012-06-29 04:45:02297bool BufferedResourceHandler::SelectNextHandler(bool* defer) {
298 DCHECK(!response_->head.mime_type.empty());
[email protected]e3c404b2008-12-23 01:07:32299
[email protected]ef5306e2013-10-15 19:38:18300 ResourceRequestInfoImpl* info = GetRequestInfo();
[email protected]926360f2012-06-29 04:45:02301 const std::string& mime_type = response_->head.mime_type;
[email protected]a755e1072009-10-23 16:58:37302
[email protected]3b455502012-12-11 18:22:58303 if (net::IsSupportedCertificateMimeType(mime_type)) {
304 // Install certificate file.
[email protected]6f3ac602014-02-13 21:38:05305 info->set_is_download(true);
[email protected]d651cbc2012-05-31 21:33:05306 scoped_ptr<ResourceHandler> handler(
[email protected]ef5306e2013-10-15 19:38:18307 new CertificateResourceHandler(request()));
[email protected]926360f2012-06-29 04:45:02308 return UseAlternateNextHandler(handler.Pass());
[email protected]5a9d58fa2012-05-29 15:15:04309 }
310
[email protected]926360f2012-06-29 04:45:02311 if (!info->allow_download())
[email protected]5e5e0c82012-01-25 09:12:29312 return true;
313
[email protected]3ca004f72012-12-18 10:35:21314 bool must_download = MustDownload();
315 if (!must_download) {
[email protected]926360f2012-06-29 04:45:02316 if (net::IsSupportedMimeType(mime_type))
[email protected]35fa6a22009-08-15 00:04:01317 return true;
[email protected]35fa6a22009-08-15 00:04:01318
[email protected]646889822013-03-20 00:26:45319 scoped_ptr<ResourceHandler> handler(
[email protected]ef5306e2013-10-15 19:38:18320 host_->MaybeInterceptAsStream(request(), response_.get()));
[email protected]646889822013-03-20 00:26:45321 if (handler)
322 return UseAlternateNextHandler(handler.Pass());
323
[email protected]ebd71962012-12-20 02:56:55324#if defined(ENABLE_PLUGINS)
[email protected]926360f2012-06-29 04:45:02325 bool stale;
326 bool has_plugin = HasSupportingPlugin(&stale);
[email protected]68598072011-07-29 08:21:28327 if (stale) {
[email protected]926360f2012-06-29 04:45:02328 // Refresh the plugins asynchronously.
329 PluginServiceImpl::GetInstance()->GetPlugins(
[email protected]5c1d3e52012-08-01 05:14:27330 base::Bind(&BufferedResourceHandler::OnPluginsLoaded,
331 weak_ptr_factory_.GetWeakPtr()));
[email protected]ae9c0922014-02-13 22:40:23332 request()->LogBlockedBy("BufferedResourceHandler");
[email protected]926360f2012-06-29 04:45:02333 *defer = true;
[email protected]35fa6a22009-08-15 00:04:01334 return true;
335 }
[email protected]926360f2012-06-29 04:45:02336 if (has_plugin)
337 return true;
[email protected]ebd71962012-12-20 02:56:55338#endif
[email protected]35fa6a22009-08-15 00:04:01339 }
340
[email protected]926360f2012-06-29 04:45:02341 // Install download handler
342 info->set_is_download(true);
343 scoped_ptr<ResourceHandler> handler(
344 host_->CreateResourceHandlerForDownload(
[email protected]ef5306e2013-10-15 19:38:18345 request(),
[email protected]926360f2012-06-29 04:45:02346 true, // is_content_initiated
[email protected]3ca004f72012-12-18 10:35:21347 must_download,
[email protected]530047e2013-07-12 17:02:25348 content::DownloadItem::kInvalidId,
[email protected]c873c862012-10-17 15:32:12349 scoped_ptr<DownloadSaveInfo>(new DownloadSaveInfo()),
[email protected]530047e2013-07-12 17:02:25350 DownloadUrlParameters::OnStartedCallback()));
[email protected]926360f2012-06-29 04:45:02351 return UseAlternateNextHandler(handler.Pass());
[email protected]35fa6a22009-08-15 00:04:01352}
353
[email protected]926360f2012-06-29 04:45:02354bool BufferedResourceHandler::UseAlternateNextHandler(
355 scoped_ptr<ResourceHandler> new_handler) {
[email protected]fc72bb12013-06-02 21:13:46356 if (response_->head.headers.get() && // Can be NULL if FTP.
[email protected]926360f2012-06-29 04:45:02357 response_->head.headers->response_code() / 100 != 2) {
358 // The response code indicates that this is an error page, but we don't
359 // know how to display the content. We follow Firefox here and show our
360 // own error page instead of triggering a download.
361 // TODO(abarth): We should abstract the response_code test, but this kind
362 // of check is scattered throughout our codebase.
[email protected]550cddd72014-02-20 02:29:09363 request()->CancelWithError(net::ERR_INVALID_RESPONSE);
[email protected]926360f2012-06-29 04:45:02364 return false;
365 }
366
[email protected]0dc72bbe2010-04-08 15:29:17367 // Inform the original ResourceHandler that this will be handled entirely by
368 // the new ResourceHandler.
[email protected]5e5e0c82012-01-25 09:12:29369 // TODO(darin): We should probably check the return values of these.
[email protected]22b305442012-05-21 18:02:59370 bool defer_ignored = false;
[email protected]d22e800e2014-05-28 21:55:57371 next_handler_->OnResponseStarted(response_.get(), &defer_ignored);
[email protected]6f3ac602014-02-13 21:38:05372 // Although deferring OnResponseStarted is legal, the only downstream handler
373 // which does so is CrossSiteResourceHandler. Cross-site transitions should
374 // not trigger when switching handlers.
[email protected]22b305442012-05-21 18:02:59375 DCHECK(!defer_ignored);
[email protected]2756a8e2012-09-07 18:24:29376 net::URLRequestStatus status(net::URLRequestStatus::CANCELED,
377 net::ERR_ABORTED);
[email protected]d22e800e2014-05-28 21:55:57378 next_handler_->OnResponseCompleted(status, std::string(), &defer_ignored);
[email protected]3780874a2013-11-18 05:49:03379 DCHECK(!defer_ignored);
[email protected]0dc72bbe2010-04-08 15:29:17380
381 // This is handled entirely within the new ResourceHandler, so just reset the
382 // original ResourceHandler.
[email protected]926360f2012-06-29 04:45:02383 next_handler_ = new_handler.Pass();
384 next_handler_->SetController(this);
[email protected]5e5e0c82012-01-25 09:12:29385
[email protected]d22e800e2014-05-28 21:55:57386 return CopyReadBufferToNextHandler();
[email protected]5e5e0c82012-01-25 09:12:29387}
388
[email protected]926360f2012-06-29 04:45:02389bool BufferedResourceHandler::ReplayReadCompleted(bool* defer) {
[email protected]fc72bb12013-06-02 21:13:46390 DCHECK(read_buffer_.get());
[email protected]5e5e0c82012-01-25 09:12:29391
[email protected]d22e800e2014-05-28 21:55:57392 bool result = next_handler_->OnReadCompleted(bytes_read_, defer);
[email protected]926360f2012-06-29 04:45:02393
394 read_buffer_ = NULL;
395 read_buffer_size_ = 0;
396 bytes_read_ = 0;
397
398 state_ = STATE_STREAMING;
399
400 return result;
[email protected]5e5e0c82012-01-25 09:12:29401}
402
[email protected]926360f2012-06-29 04:45:02403void BufferedResourceHandler::CallReplayReadCompleted() {
404 bool defer = false;
405 if (!ReplayReadCompleted(&defer)) {
406 controller()->Cancel();
407 } else if (!defer) {
408 state_ = STATE_STREAMING;
409 controller()->Resume();
410 }
411}
412
413bool BufferedResourceHandler::MustDownload() {
414 if (must_download_is_set_)
415 return must_download_;
416
417 must_download_is_set_ = true;
418
419 std::string disposition;
[email protected]ef5306e2013-10-15 19:38:18420 request()->GetResponseHeaderByName("content-disposition", &disposition);
[email protected]926360f2012-06-29 04:45:02421 if (!disposition.empty() &&
422 net::HttpContentDisposition(disposition, std::string()).is_attachment()) {
423 must_download_ = true;
424 } else if (host_->delegate() &&
425 host_->delegate()->ShouldForceDownloadResource(
[email protected]ef5306e2013-10-15 19:38:18426 request()->url(), response_->head.mime_type)) {
[email protected]926360f2012-06-29 04:45:02427 must_download_ = true;
428 } else {
429 must_download_ = false;
430 }
431
432 return must_download_;
433}
434
435bool BufferedResourceHandler::HasSupportingPlugin(bool* stale) {
[email protected]012a1712013-11-18 05:29:41436#if defined(ENABLE_PLUGINS)
[email protected]ef5306e2013-10-15 19:38:18437 ResourceRequestInfoImpl* info = GetRequestInfo();
[email protected]926360f2012-06-29 04:45:02438
439 bool allow_wildcard = false;
[email protected]d7bd3e52013-07-21 04:29:20440 WebPluginInfo plugin;
[email protected]926360f2012-06-29 04:45:02441 return PluginServiceImpl::GetInstance()->GetPluginInfo(
[email protected]60eca4eb2013-12-06 00:02:16442 info->GetChildID(), info->GetRenderFrameID(), info->GetContext(),
[email protected]ef5306e2013-10-15 19:38:18443 request()->url(), GURL(), response_->head.mime_type, allow_wildcard,
[email protected]926360f2012-06-29 04:45:02444 stale, &plugin, NULL);
[email protected]012a1712013-11-18 05:29:41445#else
446 if (stale)
447 *stale = false;
448 return false;
449#endif
[email protected]926360f2012-06-29 04:45:02450}
451
[email protected]d22e800e2014-05-28 21:55:57452bool BufferedResourceHandler::CopyReadBufferToNextHandler() {
[email protected]17b674e02014-05-10 04:30:02453 if (!read_buffer_.get())
[email protected]926360f2012-06-29 04:45:02454 return true;
[email protected]5e5e0c82012-01-25 09:12:29455
[email protected]ef5306e2013-10-15 19:38:18456 scoped_refptr<net::IOBuffer> buf;
[email protected]5e5e0c82012-01-25 09:12:29457 int buf_len = 0;
[email protected]d22e800e2014-05-28 21:55:57458 if (!next_handler_->OnWillRead(&buf, &buf_len, bytes_read_))
[email protected]926360f2012-06-29 04:45:02459 return false;
460
461 CHECK((buf_len >= bytes_read_) && (bytes_read_ >= 0));
462 memcpy(buf->data(), read_buffer_->data(), bytes_read_);
463 return true;
[email protected]0dc72bbe2010-04-08 15:29:17464}
465
[email protected]d33e7cc2011-09-23 01:43:56466void BufferedResourceHandler::OnPluginsLoaded(
[email protected]d7bd3e52013-07-21 04:29:20467 const std::vector<WebPluginInfo>& plugins) {
[email protected]ae9c0922014-02-13 22:40:23468 request()->LogUnblocked();
[email protected]22b305442012-05-21 18:02:59469 bool defer = false;
[email protected]926360f2012-06-29 04:45:02470 if (!ProcessResponse(&defer)) {
[email protected]56f0b082012-06-14 07:12:32471 controller()->Cancel();
[email protected]926360f2012-06-29 04:45:02472 } else if (!defer) {
[email protected]56f0b082012-06-14 07:12:32473 controller()->Resume();
[email protected]22b305442012-05-21 18:02:59474 }
[email protected]e3c404b2008-12-23 01:07:32475}
[email protected]d18720a2012-01-06 09:53:55476
477} // namespace content