blob: a38eaa915ea449de9272b85d1356ff658b9f41ec [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]6edb64882014-06-12 22:57:5418#include "content/browser/loader/stream_resource_handler.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"
raymes65f5da42014-11-25 00:30:3423#include "content/public/browser/plugin_service.h"
[email protected]ce967862012-02-09 22:47:0524#include "content/public/browser/resource_context.h"
[email protected]1bd0ef12011-10-20 05:24:1725#include "content/public/browser/resource_dispatcher_host_delegate.h"
[email protected]2336ffe2011-11-24 01:23:3426#include "content/public/common/resource_response.h"
[email protected]d7bd3e52013-07-21 04:29:2027#include "content/public/common/webplugininfo.h"
[email protected]dd9b5462009-09-25 17:22:2328#include "net/base/io_buffer.h"
[email protected]9dea9e1f2009-01-29 00:30:4729#include "net/base/mime_sniffer.h"
[email protected]35fa6a22009-08-15 00:04:0130#include "net/base/mime_util.h"
[email protected]dd9b5462009-09-25 17:22:2331#include "net/base/net_errors.h"
[email protected]28ca9fb2012-01-28 14:50:2432#include "net/http/http_content_disposition.h"
[email protected]319d9e6f2009-02-18 19:47:2133#include "net/http/http_response_headers.h"
[email protected]e3c404b2008-12-23 01:07:3234
[email protected]d18720a2012-01-06 09:53:5535namespace content {
36
[email protected]306291392009-01-17 19:15:3637namespace {
38
39void RecordSnifferMetrics(bool sniffing_blocked,
40 bool we_would_like_to_sniff,
41 const std::string& mime_type) {
[email protected]de415552013-01-23 04:12:1742 static base::HistogramBase* nosniff_usage(NULL);
[email protected]81ce9f3b2011-04-05 04:48:5343 if (!nosniff_usage)
44 nosniff_usage = base::BooleanHistogram::FactoryGet(
[email protected]de415552013-01-23 04:12:1745 "nosniff.usage", base::HistogramBase::kUmaTargetedHistogramFlag);
[email protected]e8829a192009-12-06 00:09:3746 nosniff_usage->AddBoolean(sniffing_blocked);
[email protected]306291392009-01-17 19:15:3647
48 if (sniffing_blocked) {
[email protected]de415552013-01-23 04:12:1749 static base::HistogramBase* nosniff_otherwise(NULL);
[email protected]81ce9f3b2011-04-05 04:48:5350 if (!nosniff_otherwise)
51 nosniff_otherwise = base::BooleanHistogram::FactoryGet(
[email protected]de415552013-01-23 04:12:1752 "nosniff.otherwise", base::HistogramBase::kUmaTargetedHistogramFlag);
[email protected]e8829a192009-12-06 00:09:3753 nosniff_otherwise->AddBoolean(we_would_like_to_sniff);
[email protected]306291392009-01-17 19:15:3654
[email protected]de415552013-01-23 04:12:1755 static base::HistogramBase* nosniff_empty_mime_type(NULL);
[email protected]81ce9f3b2011-04-05 04:48:5356 if (!nosniff_empty_mime_type)
57 nosniff_empty_mime_type = base::BooleanHistogram::FactoryGet(
58 "nosniff.empty_mime_type",
[email protected]de415552013-01-23 04:12:1759 base::HistogramBase::kUmaTargetedHistogramFlag);
[email protected]e8829a192009-12-06 00:09:3760 nosniff_empty_mime_type->AddBoolean(mime_type.empty());
[email protected]306291392009-01-17 19:15:3661 }
62}
63
[email protected]926360f2012-06-29 04:45:0264// Used to write into an existing IOBuffer at a given offset.
65class DependentIOBuffer : public net::WrappedIOBuffer {
66 public:
67 DependentIOBuffer(net::IOBuffer* buf, int offset)
68 : net::WrappedIOBuffer(buf->data() + offset),
69 buf_(buf) {
70 }
71
72 private:
dchengc2282aa2014-10-21 12:07:5873 ~DependentIOBuffer() override {}
[email protected]926360f2012-06-29 04:45:0274
75 scoped_refptr<net::IOBuffer> buf_;
76};
77
[email protected]306291392009-01-17 19:15:3678} // namespace
79
[email protected]ea114722012-03-12 01:11:2580BufferedResourceHandler::BufferedResourceHandler(
[email protected]d651cbc2012-05-31 21:33:0581 scoped_ptr<ResourceHandler> next_handler,
[email protected]ea114722012-03-12 01:11:2582 ResourceDispatcherHostImpl* host,
raymes65f5da42014-11-25 00:30:3483 PluginService* plugin_service,
[email protected]ea114722012-03-12 01:11:2584 net::URLRequest* request)
[email protected]ef5306e2013-10-15 19:38:1885 : LayeredResourceHandler(request, next_handler.Pass()),
[email protected]926360f2012-06-29 04:45:0286 state_(STATE_STARTING),
[email protected]e3c404b2008-12-23 01:07:3287 host_(host),
raymes65f5da42014-11-25 00:30:3488 plugin_service_(plugin_service),
[email protected]dd9b5462009-09-25 17:22:2389 read_buffer_size_(0),
[email protected]e3c404b2008-12-23 01:07:3290 bytes_read_(0),
[email protected]926360f2012-06-29 04:45:0291 must_download_(false),
[email protected]5c1d3e52012-08-01 05:14:2792 must_download_is_set_(false),
93 weak_ptr_factory_(this) {
[email protected]926360f2012-06-29 04:45:0294}
95
96BufferedResourceHandler::~BufferedResourceHandler() {
97}
98
99void BufferedResourceHandler::SetController(ResourceController* controller) {
100 ResourceHandler::SetController(controller);
101
102 // Downstream handlers see us as their ResourceController, which allows us to
103 // consume part or all of the resource response, and then later replay it to
104 // downstream handler.
105 DCHECK(next_handler_.get());
106 next_handler_->SetController(this);
[email protected]e3c404b2008-12-23 01:07:32107}
108
[email protected]d22e800e2014-05-28 21:55:57109bool BufferedResourceHandler::OnResponseStarted(ResourceResponse* response,
110 bool* defer) {
[email protected]e3c404b2008-12-23 01:07:32111 response_ = response;
[email protected]22b305442012-05-21 18:02:59112
ricea68c95ddb22015-04-13 16:41:03113 // A 304 response should not contain a Content-Type header (RFC 7232 section
114 // 4.1). The following code may incorrectly attempt to add a Content-Type to
115 // the response, and so must be skipped for 304 responses.
[email protected]fc72bb12013-06-02 21:13:46116 if (!(response_->head.headers.get() &&
[email protected]926360f2012-06-29 04:45:02117 response_->head.headers->response_code() == 304)) {
118 if (ShouldSniffContent()) {
119 state_ = STATE_BUFFERING;
120 return true;
121 }
122
123 if (response_->head.mime_type.empty()) {
124 // Ugg. The server told us not to sniff the content but didn't give us
125 // a mime type. What's a browser to do? Turns out, we're supposed to
126 // treat the response as "text/plain". This is the most secure option.
127 response_->head.mime_type.assign("text/plain");
128 }
[email protected]3ff679262012-10-12 23:40:05129
130 // Treat feed types as text/plain.
131 if (response_->head.mime_type == "application/rss+xml" ||
132 response_->head.mime_type == "application/atom+xml") {
133 response_->head.mime_type.assign("text/plain");
134 }
[email protected]22b305442012-05-21 18:02:59135 }
[email protected]926360f2012-06-29 04:45:02136
137 state_ = STATE_PROCESSING;
138 return ProcessResponse(defer);
[email protected]e3c404b2008-12-23 01:07:32139}
140
[email protected]e3c404b2008-12-23 01:07:32141// We'll let the original event handler provide a buffer, and reuse it for
142// subsequent reads until we're done buffering.
[email protected]d22e800e2014-05-28 21:55:57143bool BufferedResourceHandler::OnWillRead(scoped_refptr<net::IOBuffer>* buf,
[email protected]ef5306e2013-10-15 19:38:18144 int* buf_size,
145 int min_size) {
[email protected]926360f2012-06-29 04:45:02146 if (state_ == STATE_STREAMING)
[email protected]d22e800e2014-05-28 21:55:57147 return next_handler_->OnWillRead(buf, buf_size, min_size);
[email protected]926360f2012-06-29 04:45:02148
149 DCHECK_EQ(-1, min_size);
150
[email protected]fc72bb12013-06-02 21:13:46151 if (read_buffer_.get()) {
[email protected]926360f2012-06-29 04:45:02152 CHECK_LT(bytes_read_, read_buffer_size_);
[email protected]fc72bb12013-06-02 21:13:46153 *buf = new DependentIOBuffer(read_buffer_.get(), bytes_read_);
[email protected]926360f2012-06-29 04:45:02154 *buf_size = read_buffer_size_ - bytes_read_;
155 } else {
[email protected]d22e800e2014-05-28 21:55:57156 if (!next_handler_->OnWillRead(buf, buf_size, min_size))
[email protected]926360f2012-06-29 04:45:02157 return false;
158
159 read_buffer_ = *buf;
160 read_buffer_size_ = *buf_size;
161 DCHECK_GE(read_buffer_size_, net::kMaxBytesToSniff * 2);
[email protected]e3c404b2008-12-23 01:07:32162 }
[email protected]67199052009-06-12 21:15:33163 return true;
[email protected]e3c404b2008-12-23 01:07:32164}
165
[email protected]d22e800e2014-05-28 21:55:57166bool BufferedResourceHandler::OnReadCompleted(int bytes_read, bool* defer) {
[email protected]926360f2012-06-29 04:45:02167 if (state_ == STATE_STREAMING)
[email protected]d22e800e2014-05-28 21:55:57168 return next_handler_->OnReadCompleted(bytes_read, defer);
[email protected]e3c404b2008-12-23 01:07:32169
[email protected]926360f2012-06-29 04:45:02170 DCHECK_EQ(state_, STATE_BUFFERING);
171 bytes_read_ += bytes_read;
[email protected]e3c404b2008-12-23 01:07:32172
[email protected]926360f2012-06-29 04:45:02173 if (!DetermineMimeType() && (bytes_read > 0))
174 return true; // Needs more data, so keep buffering.
175
176 state_ = STATE_PROCESSING;
177 return ProcessResponse(defer);
178}
179
[email protected]3780874a2013-11-18 05:49:03180void BufferedResourceHandler::OnResponseCompleted(
[email protected]926360f2012-06-29 04:45:02181 const net::URLRequestStatus& status,
[email protected]3780874a2013-11-18 05:49:03182 const std::string& security_info,
183 bool* defer) {
[email protected]926360f2012-06-29 04:45:02184 // Upon completion, act like a pass-through handler in case the downstream
185 // handler defers OnResponseCompleted.
186 state_ = STATE_STREAMING;
187
[email protected]d22e800e2014-05-28 21:55:57188 next_handler_->OnResponseCompleted(status, security_info, defer);
[email protected]926360f2012-06-29 04:45:02189}
190
191void BufferedResourceHandler::Resume() {
192 switch (state_) {
193 case STATE_BUFFERING:
194 case STATE_PROCESSING:
195 NOTREACHED();
196 break;
197 case STATE_REPLAYING:
[email protected]dd32b1272013-05-04 14:17:11198 base::MessageLoop::current()->PostTask(
[email protected]926360f2012-06-29 04:45:02199 FROM_HERE,
200 base::Bind(&BufferedResourceHandler::CallReplayReadCompleted,
[email protected]5c1d3e52012-08-01 05:14:27201 weak_ptr_factory_.GetWeakPtr()));
[email protected]926360f2012-06-29 04:45:02202 break;
203 case STATE_STARTING:
204 case STATE_STREAMING:
205 controller()->Resume();
206 break;
207 }
208}
209
210void BufferedResourceHandler::Cancel() {
211 controller()->Cancel();
212}
213
[email protected]2756a8e2012-09-07 18:24:29214void BufferedResourceHandler::CancelAndIgnore() {
215 controller()->CancelAndIgnore();
216}
217
[email protected]af3d4962012-10-19 10:57:26218void BufferedResourceHandler::CancelWithError(int error_code) {
219 controller()->CancelWithError(error_code);
220}
221
[email protected]926360f2012-06-29 04:45:02222bool BufferedResourceHandler::ProcessResponse(bool* defer) {
223 DCHECK_EQ(STATE_PROCESSING, state_);
224
225 // TODO(darin): Stop special-casing 304 responses.
[email protected]fc72bb12013-06-02 21:13:46226 if (!(response_->head.headers.get() &&
[email protected]926360f2012-06-29 04:45:02227 response_->head.headers->response_code() == 304)) {
228 if (!SelectNextHandler(defer))
[email protected]e3c404b2008-12-23 01:07:32229 return false;
[email protected]22b305442012-05-21 18:02:59230 if (*defer)
[email protected]98d6f152011-09-29 19:35:51231 return true;
[email protected]926360f2012-06-29 04:45:02232 }
233
234 state_ = STATE_REPLAYING;
235
[email protected]d22e800e2014-05-28 21:55:57236 if (!next_handler_->OnResponseStarted(response_.get(), defer))
[email protected]926360f2012-06-29 04:45:02237 return false;
238
[email protected]fc72bb12013-06-02 21:13:46239 if (!read_buffer_.get()) {
[email protected]926360f2012-06-29 04:45:02240 state_ = STATE_STREAMING;
[email protected]35fa6a22009-08-15 00:04:01241 return true;
[email protected]e3c404b2008-12-23 01:07:32242 }
243
[email protected]926360f2012-06-29 04:45:02244 if (!*defer)
245 return ReplayReadCompleted(defer);
[email protected]5e5e0c82012-01-25 09:12:29246
[email protected]926360f2012-06-29 04:45:02247 return true;
[email protected]e3c404b2008-12-23 01:07:32248}
249
[email protected]926360f2012-06-29 04:45:02250bool BufferedResourceHandler::ShouldSniffContent() {
251 const std::string& mime_type = response_->head.mime_type;
[email protected]e3c404b2008-12-23 01:07:32252
253 std::string content_type_options;
[email protected]ef5306e2013-10-15 19:38:18254 request()->GetResponseHeaderByName("x-content-type-options",
255 &content_type_options);
[email protected]306291392009-01-17 19:15:36256
[email protected]926360f2012-06-29 04:45:02257 bool sniffing_blocked =
[email protected]df807042014-08-13 16:48:41258 LowerCaseEqualsASCII(content_type_options, "nosniff");
[email protected]926360f2012-06-29 04:45:02259 bool we_would_like_to_sniff =
[email protected]ef5306e2013-10-15 19:38:18260 net::ShouldSniffMimeType(request()->url(), mime_type);
[email protected]306291392009-01-17 19:15:36261
262 RecordSnifferMetrics(sniffing_blocked, we_would_like_to_sniff, mime_type);
263
264 if (!sniffing_blocked && we_would_like_to_sniff) {
[email protected]e3c404b2008-12-23 01:07:32265 // We're going to look at the data before deciding what the content type
266 // is. That means we need to delay sending the ResponseStarted message
267 // over the IPC channel.
[email protected]ef5306e2013-10-15 19:38:18268 VLOG(1) << "To buffer: " << request()->url().spec();
[email protected]e3c404b2008-12-23 01:07:32269 return true;
270 }
271
[email protected]e3c404b2008-12-23 01:07:32272 return false;
273}
274
[email protected]926360f2012-06-29 04:45:02275bool BufferedResourceHandler::DetermineMimeType() {
276 DCHECK_EQ(STATE_BUFFERING, state_);
[email protected]35fa6a22009-08-15 00:04:01277
[email protected]926360f2012-06-29 04:45:02278 const std::string& type_hint = response_->head.mime_type;
279
280 std::string new_type;
281 bool made_final_decision =
[email protected]ef5306e2013-10-15 19:38:18282 net::SniffMimeType(read_buffer_->data(), bytes_read_, request()->url(),
[email protected]926360f2012-06-29 04:45:02283 type_hint, &new_type);
284
285 // SniffMimeType() returns false if there is not enough data to determine
286 // the mime type. However, even if it returns false, it returns a new type
287 // that is probably better than the current one.
288 response_->head.mime_type.assign(new_type);
289
290 return made_final_decision;
[email protected]35fa6a22009-08-15 00:04:01291}
292
[email protected]926360f2012-06-29 04:45:02293bool BufferedResourceHandler::SelectNextHandler(bool* defer) {
294 DCHECK(!response_->head.mime_type.empty());
[email protected]e3c404b2008-12-23 01:07:32295
[email protected]ef5306e2013-10-15 19:38:18296 ResourceRequestInfoImpl* info = GetRequestInfo();
[email protected]926360f2012-06-29 04:45:02297 const std::string& mime_type = response_->head.mime_type;
[email protected]a755e1072009-10-23 16:58:37298
[email protected]3b455502012-12-11 18:22:58299 if (net::IsSupportedCertificateMimeType(mime_type)) {
300 // Install certificate file.
[email protected]6f3ac602014-02-13 21:38:05301 info->set_is_download(true);
[email protected]d651cbc2012-05-31 21:33:05302 scoped_ptr<ResourceHandler> handler(
[email protected]ef5306e2013-10-15 19:38:18303 new CertificateResourceHandler(request()));
[email protected]6edb64882014-06-12 22:57:54304 return UseAlternateNextHandler(handler.Pass(), std::string());
[email protected]5a9d58fa2012-05-29 15:15:04305 }
306
raymes9325d7ca32014-11-21 01:02:42307 // Allow requests for object/embed tags to be intercepted as streams.
308 if (info->GetResourceType() == content::RESOURCE_TYPE_OBJECT) {
309 DCHECK(!info->allow_download());
deepak.m1e3557dd2015-04-13 13:09:08310 std::string payload;
311 scoped_ptr<ResourceHandler> handler(
312 host_->MaybeInterceptAsStream(request(), response_.get(), &payload));
313 if (handler) {
314 DCHECK(!net::IsSupportedMimeType(mime_type));
315 return UseAlternateNextHandler(handler.Pass(), payload);
316 }
raymes9325d7ca32014-11-21 01:02:42317 }
318
[email protected]926360f2012-06-29 04:45:02319 if (!info->allow_download())
[email protected]5e5e0c82012-01-25 09:12:29320 return true;
321
raymes9325d7ca32014-11-21 01:02:42322 // info->allow_download() == true implies
323 // info->GetResourceType() == RESOURCE_TYPE_MAIN_FRAME or
324 // info->GetResourceType() == RESOURCE_TYPE_SUB_FRAME.
325 DCHECK(info->GetResourceType() == RESOURCE_TYPE_MAIN_FRAME ||
326 info->GetResourceType() == RESOURCE_TYPE_SUB_FRAME);
327
[email protected]3ca004f72012-12-18 10:35:21328 bool must_download = MustDownload();
329 if (!must_download) {
[email protected]926360f2012-06-29 04:45:02330 if (net::IsSupportedMimeType(mime_type))
[email protected]35fa6a22009-08-15 00:04:01331 return true;
[email protected]35fa6a22009-08-15 00:04:01332
deepak.m1e3557dd2015-04-13 13:09:08333 std::string payload;
334 scoped_ptr<ResourceHandler> handler(
335 host_->MaybeInterceptAsStream(request(), response_.get(), &payload));
336 if (handler) {
337 return UseAlternateNextHandler(handler.Pass(), payload);
338 }
339
340#if defined(ENABLE_PLUGINS)
341 bool stale;
342 bool has_plugin = HasSupportingPlugin(&stale);
343 if (stale) {
344 // Refresh the plugins asynchronously.
345 plugin_service_->GetPlugins(
346 base::Bind(&BufferedResourceHandler::OnPluginsLoaded,
347 weak_ptr_factory_.GetWeakPtr()));
348 request()->LogBlockedBy("BufferedResourceHandler");
349 *defer = true;
[email protected]35fa6a22009-08-15 00:04:01350 return true;
deepak.m1e3557dd2015-04-13 13:09:08351 }
352 if (has_plugin)
353 return true;
354#endif
[email protected]35fa6a22009-08-15 00:04:01355 }
356
[email protected]926360f2012-06-29 04:45:02357 // Install download handler
358 info->set_is_download(true);
359 scoped_ptr<ResourceHandler> handler(
360 host_->CreateResourceHandlerForDownload(
[email protected]ef5306e2013-10-15 19:38:18361 request(),
[email protected]926360f2012-06-29 04:45:02362 true, // is_content_initiated
[email protected]3ca004f72012-12-18 10:35:21363 must_download,
thestigc4cac8f2014-09-04 21:17:50364 DownloadItem::kInvalidId,
[email protected]c873c862012-10-17 15:32:12365 scoped_ptr<DownloadSaveInfo>(new DownloadSaveInfo()),
[email protected]530047e2013-07-12 17:02:25366 DownloadUrlParameters::OnStartedCallback()));
[email protected]6edb64882014-06-12 22:57:54367 return UseAlternateNextHandler(handler.Pass(), std::string());
[email protected]35fa6a22009-08-15 00:04:01368}
369
[email protected]926360f2012-06-29 04:45:02370bool BufferedResourceHandler::UseAlternateNextHandler(
[email protected]6edb64882014-06-12 22:57:54371 scoped_ptr<ResourceHandler> new_handler,
372 const std::string& payload_for_old_handler) {
[email protected]fc72bb12013-06-02 21:13:46373 if (response_->head.headers.get() && // Can be NULL if FTP.
[email protected]926360f2012-06-29 04:45:02374 response_->head.headers->response_code() / 100 != 2) {
375 // The response code indicates that this is an error page, but we don't
376 // know how to display the content. We follow Firefox here and show our
377 // own error page instead of triggering a download.
378 // TODO(abarth): We should abstract the response_code test, but this kind
379 // of check is scattered throughout our codebase.
[email protected]550cddd72014-02-20 02:29:09380 request()->CancelWithError(net::ERR_INVALID_RESPONSE);
[email protected]926360f2012-06-29 04:45:02381 return false;
382 }
383
[email protected]0dc72bbe2010-04-08 15:29:17384 // Inform the original ResourceHandler that this will be handled entirely by
385 // the new ResourceHandler.
[email protected]5e5e0c82012-01-25 09:12:29386 // TODO(darin): We should probably check the return values of these.
[email protected]22b305442012-05-21 18:02:59387 bool defer_ignored = false;
[email protected]d22e800e2014-05-28 21:55:57388 next_handler_->OnResponseStarted(response_.get(), &defer_ignored);
[email protected]6f3ac602014-02-13 21:38:05389 // Although deferring OnResponseStarted is legal, the only downstream handler
390 // which does so is CrossSiteResourceHandler. Cross-site transitions should
391 // not trigger when switching handlers.
[email protected]22b305442012-05-21 18:02:59392 DCHECK(!defer_ignored);
[email protected]6edb64882014-06-12 22:57:54393 if (payload_for_old_handler.empty()) {
394 net::URLRequestStatus status(net::URLRequestStatus::CANCELED,
395 net::ERR_ABORTED);
396 next_handler_->OnResponseCompleted(status, std::string(), &defer_ignored);
397 DCHECK(!defer_ignored);
398 } else {
399 scoped_refptr<net::IOBuffer> buf;
400 int size = 0;
401
[email protected]1b5cd522014-06-20 08:20:19402 next_handler_->OnWillRead(&buf, &size, -1);
[email protected]6edb64882014-06-12 22:57:54403 CHECK_GE(size, static_cast<int>(payload_for_old_handler.length()));
404
405 memcpy(buf->data(), payload_for_old_handler.c_str(),
406 payload_for_old_handler.length());
407
408 next_handler_->OnReadCompleted(payload_for_old_handler.length(),
409 &defer_ignored);
410 DCHECK(!defer_ignored);
411
412 net::URLRequestStatus status(net::URLRequestStatus::SUCCESS, 0);
413 next_handler_->OnResponseCompleted(status, std::string(), &defer_ignored);
414 DCHECK(!defer_ignored);
415 }
[email protected]0dc72bbe2010-04-08 15:29:17416
417 // This is handled entirely within the new ResourceHandler, so just reset the
418 // original ResourceHandler.
[email protected]926360f2012-06-29 04:45:02419 next_handler_ = new_handler.Pass();
420 next_handler_->SetController(this);
[email protected]5e5e0c82012-01-25 09:12:29421
[email protected]d22e800e2014-05-28 21:55:57422 return CopyReadBufferToNextHandler();
[email protected]5e5e0c82012-01-25 09:12:29423}
424
[email protected]926360f2012-06-29 04:45:02425bool BufferedResourceHandler::ReplayReadCompleted(bool* defer) {
[email protected]fc72bb12013-06-02 21:13:46426 DCHECK(read_buffer_.get());
[email protected]5e5e0c82012-01-25 09:12:29427
[email protected]d22e800e2014-05-28 21:55:57428 bool result = next_handler_->OnReadCompleted(bytes_read_, defer);
[email protected]926360f2012-06-29 04:45:02429
430 read_buffer_ = NULL;
431 read_buffer_size_ = 0;
432 bytes_read_ = 0;
433
434 state_ = STATE_STREAMING;
435
436 return result;
[email protected]5e5e0c82012-01-25 09:12:29437}
438
[email protected]926360f2012-06-29 04:45:02439void BufferedResourceHandler::CallReplayReadCompleted() {
440 bool defer = false;
441 if (!ReplayReadCompleted(&defer)) {
442 controller()->Cancel();
443 } else if (!defer) {
444 state_ = STATE_STREAMING;
445 controller()->Resume();
446 }
447}
448
449bool BufferedResourceHandler::MustDownload() {
450 if (must_download_is_set_)
451 return must_download_;
452
453 must_download_is_set_ = true;
454
455 std::string disposition;
[email protected]ef5306e2013-10-15 19:38:18456 request()->GetResponseHeaderByName("content-disposition", &disposition);
[email protected]926360f2012-06-29 04:45:02457 if (!disposition.empty() &&
458 net::HttpContentDisposition(disposition, std::string()).is_attachment()) {
459 must_download_ = true;
460 } else if (host_->delegate() &&
461 host_->delegate()->ShouldForceDownloadResource(
[email protected]ef5306e2013-10-15 19:38:18462 request()->url(), response_->head.mime_type)) {
[email protected]926360f2012-06-29 04:45:02463 must_download_ = true;
464 } else {
465 must_download_ = false;
466 }
467
468 return must_download_;
469}
470
deepak.m1e3557dd2015-04-13 13:09:08471bool BufferedResourceHandler::HasSupportingPlugin(bool* stale) {
472#if defined(ENABLE_PLUGINS)
473 ResourceRequestInfoImpl* info = GetRequestInfo();
474
475 bool allow_wildcard = false;
476 WebPluginInfo plugin;
477 return plugin_service_->GetPluginInfo(
478 info->GetChildID(), info->GetRenderFrameID(), info->GetContext(),
479 request()->url(), GURL(), response_->head.mime_type, allow_wildcard,
480 stale, &plugin, NULL);
481#else
482 if (stale)
483 *stale = false;
484 return false;
485#endif
486}
487
[email protected]d22e800e2014-05-28 21:55:57488bool BufferedResourceHandler::CopyReadBufferToNextHandler() {
[email protected]17b674e02014-05-10 04:30:02489 if (!read_buffer_.get())
[email protected]926360f2012-06-29 04:45:02490 return true;
[email protected]5e5e0c82012-01-25 09:12:29491
[email protected]ef5306e2013-10-15 19:38:18492 scoped_refptr<net::IOBuffer> buf;
[email protected]5e5e0c82012-01-25 09:12:29493 int buf_len = 0;
[email protected]d22e800e2014-05-28 21:55:57494 if (!next_handler_->OnWillRead(&buf, &buf_len, bytes_read_))
[email protected]926360f2012-06-29 04:45:02495 return false;
496
497 CHECK((buf_len >= bytes_read_) && (bytes_read_ >= 0));
498 memcpy(buf->data(), read_buffer_->data(), bytes_read_);
499 return true;
[email protected]0dc72bbe2010-04-08 15:29:17500}
501
[email protected]d33e7cc2011-09-23 01:43:56502void BufferedResourceHandler::OnPluginsLoaded(
[email protected]d7bd3e52013-07-21 04:29:20503 const std::vector<WebPluginInfo>& plugins) {
[email protected]ae9c0922014-02-13 22:40:23504 request()->LogUnblocked();
[email protected]22b305442012-05-21 18:02:59505 bool defer = false;
[email protected]926360f2012-06-29 04:45:02506 if (!ProcessResponse(&defer)) {
[email protected]56f0b082012-06-14 07:12:32507 controller()->Cancel();
[email protected]926360f2012-06-29 04:45:02508 } else if (!defer) {
[email protected]56f0b082012-06-14 07:12:32509 controller()->Resume();
[email protected]22b305442012-05-21 18:02:59510 }
[email protected]e3c404b2008-12-23 01:07:32511}
[email protected]d18720a2012-01-06 09:53:55512
513} // namespace content