blob: 3f6b4762d632a58b2c54aaa07fbe1273e4403a84 [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]1d8a3d1f2011-02-19 07:11:525#include "content/browser/renderer_host/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]319d9e6f2009-02-18 19:47:2112#include "base/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]f6c2b5312011-11-16 22:31:3915#include "content/browser/download/download_types.h"
[email protected]e67385f2011-12-21 06:00:5616#include "content/browser/plugin_service_impl.h"
[email protected]1d8a3d1f2011-02-19 07:11:5217#include "content/browser/renderer_host/resource_dispatcher_host.h"
18#include "content/browser/renderer_host/resource_dispatcher_host_request_info.h"
19#include "content/browser/renderer_host/x509_user_cert_resource_handler.h"
[email protected]eda58402011-09-21 19:32:0220#include "content/browser/resource_context.h"
[email protected]c38831a12011-10-28 12:44:4921#include "content/public/browser/browser_thread.h"
[email protected]87f3c082011-10-19 18:07:4422#include "content/public/browser/content_browser_client.h"
[email protected]1bd0ef12011-10-20 05:24:1723#include "content/public/browser/resource_dispatcher_host_delegate.h"
[email protected]2336ffe2011-11-24 01:23:3424#include "content/public/common/resource_response.h"
[email protected]dd9b5462009-09-25 17:22:2325#include "net/base/io_buffer.h"
[email protected]9dea9e1f2009-01-29 00:30:4726#include "net/base/mime_sniffer.h"
[email protected]35fa6a22009-08-15 00:04:0127#include "net/base/mime_util.h"
[email protected]dd9b5462009-09-25 17:22:2328#include "net/base/net_errors.h"
[email protected]28ca9fb2012-01-28 14:50:2429#include "net/http/http_content_disposition.h"
[email protected]319d9e6f2009-02-18 19:47:2130#include "net/http/http_response_headers.h"
[email protected]d33e7cc2011-09-23 01:43:5631#include "webkit/plugins/webplugininfo.h"
[email protected]e3c404b2008-12-23 01:07:3232
[email protected]d18720a2012-01-06 09:53:5533namespace content {
34
[email protected]306291392009-01-17 19:15:3635namespace {
36
37void RecordSnifferMetrics(bool sniffing_blocked,
38 bool we_would_like_to_sniff,
39 const std::string& mime_type) {
[email protected]81ce9f3b2011-04-05 04:48:5340 static base::Histogram* nosniff_usage(NULL);
41 if (!nosniff_usage)
42 nosniff_usage = base::BooleanHistogram::FactoryGet(
43 "nosniff.usage", base::Histogram::kUmaTargetedHistogramFlag);
[email protected]e8829a192009-12-06 00:09:3744 nosniff_usage->AddBoolean(sniffing_blocked);
[email protected]306291392009-01-17 19:15:3645
46 if (sniffing_blocked) {
[email protected]81ce9f3b2011-04-05 04:48:5347 static base::Histogram* nosniff_otherwise(NULL);
48 if (!nosniff_otherwise)
49 nosniff_otherwise = base::BooleanHistogram::FactoryGet(
50 "nosniff.otherwise", base::Histogram::kUmaTargetedHistogramFlag);
[email protected]e8829a192009-12-06 00:09:3751 nosniff_otherwise->AddBoolean(we_would_like_to_sniff);
[email protected]306291392009-01-17 19:15:3652
[email protected]81ce9f3b2011-04-05 04:48:5353 static base::Histogram* nosniff_empty_mime_type(NULL);
54 if (!nosniff_empty_mime_type)
55 nosniff_empty_mime_type = base::BooleanHistogram::FactoryGet(
56 "nosniff.empty_mime_type",
57 base::Histogram::kUmaTargetedHistogramFlag);
[email protected]e8829a192009-12-06 00:09:3758 nosniff_empty_mime_type->AddBoolean(mime_type.empty());
[email protected]306291392009-01-17 19:15:3659 }
60}
61
62} // namespace
63
[email protected]e3c404b2008-12-23 01:07:3264BufferedResourceHandler::BufferedResourceHandler(ResourceHandler* handler,
65 ResourceDispatcherHost* host,
[email protected]6981d9632010-11-30 21:34:0266 net::URLRequest* request)
[email protected]d18720a2012-01-06 09:53:5567 : LayeredResourceHandler(handler),
[email protected]e3c404b2008-12-23 01:07:3268 host_(host),
69 request_(request),
[email protected]dd9b5462009-09-25 17:22:2370 read_buffer_size_(0),
[email protected]e3c404b2008-12-23 01:07:3271 bytes_read_(0),
72 sniff_content_(false),
[email protected]35fa6a22009-08-15 00:04:0173 wait_for_plugins_(false),
[email protected]e3c404b2008-12-23 01:07:3274 buffering_(false),
[email protected]5e5e0c82012-01-25 09:12:2975 next_handler_needs_response_started_(false),
76 next_handler_needs_will_read_(false),
[email protected]e3c404b2008-12-23 01:07:3277 finished_(false) {
78}
79
[email protected]2336ffe2011-11-24 01:23:3480bool BufferedResourceHandler::OnResponseStarted(
81 int request_id,
[email protected]d18720a2012-01-06 09:53:5582 ResourceResponse* response) {
[email protected]e3c404b2008-12-23 01:07:3283 response_ = response;
84 if (!DelayResponse())
[email protected]0a0b2542012-01-03 08:25:2285 return CompleteResponseStarted(request_id);
[email protected]e3c404b2008-12-23 01:07:3286 return true;
87}
88
[email protected]35fa6a22009-08-15 00:04:0189void BufferedResourceHandler::OnRequestClosed() {
90 request_ = NULL;
[email protected]d18720a2012-01-06 09:53:5591 next_handler_->OnRequestClosed();
[email protected]afd832c2010-03-02 04:53:3192}
93
[email protected]e3c404b2008-12-23 01:07:3294// We'll let the original event handler provide a buffer, and reuse it for
95// subsequent reads until we're done buffering.
[email protected]9dea9e1f2009-01-29 00:30:4796bool BufferedResourceHandler::OnWillRead(int request_id, net::IOBuffer** buf,
97 int* buf_size, int min_size) {
[email protected]e3c404b2008-12-23 01:07:3298 if (buffering_) {
[email protected]9dea9e1f2009-01-29 00:30:4799 DCHECK(!my_buffer_.get());
[email protected]2e7aff62010-03-16 06:34:56100 my_buffer_ = new net::IOBuffer(net::kMaxBytesToSniff);
[email protected]9dea9e1f2009-01-29 00:30:47101 *buf = my_buffer_.get();
[email protected]2e7aff62010-03-16 06:34:56102 *buf_size = net::kMaxBytesToSniff;
[email protected]e3c404b2008-12-23 01:07:32103 return true;
104 }
105
106 if (finished_)
107 return false;
108
[email protected]d18720a2012-01-06 09:53:55109 if (!next_handler_->OnWillRead(request_id, buf, buf_size, min_size)) {
[email protected]67199052009-06-12 21:15:33110 return false;
111 }
[email protected]e3c404b2008-12-23 01:07:32112 read_buffer_ = *buf;
113 read_buffer_size_ = *buf_size;
[email protected]2e7aff62010-03-16 06:34:56114 DCHECK_GE(read_buffer_size_, net::kMaxBytesToSniff * 2);
[email protected]e3c404b2008-12-23 01:07:32115 bytes_read_ = 0;
[email protected]67199052009-06-12 21:15:33116 return true;
[email protected]e3c404b2008-12-23 01:07:32117}
118
119bool BufferedResourceHandler::OnReadCompleted(int request_id, int* bytes_read) {
[email protected]5e5e0c82012-01-25 09:12:29120 ResourceDispatcherHostRequestInfo* info =
121 ResourceDispatcherHost::InfoForRequest(request_);
122
[email protected]216c17f4d2011-05-17 06:00:55123 if (sniff_content_) {
[email protected]e3c404b2008-12-23 01:07:32124 if (KeepBuffering(*bytes_read))
125 return true;
126
[email protected]e3c404b2008-12-23 01:07:32127 *bytes_read = bytes_read_;
128
129 // Done buffering, send the pending ResponseStarted event.
[email protected]0a0b2542012-01-03 08:25:22130 if (!CompleteResponseStarted(request_id))
[email protected]e3c404b2008-12-23 01:07:32131 return false;
[email protected]98d6f152011-09-29 19:35:51132
133 // The next handler might have paused the request in OnResponseStarted.
[email protected]98d6f152011-09-29 19:35:51134 if (info->pause_count())
135 return true;
[email protected]35fa6a22009-08-15 00:04:01136 } else if (wait_for_plugins_) {
137 return true;
[email protected]e3c404b2008-12-23 01:07:32138 }
139
[email protected]5e5e0c82012-01-25 09:12:29140 if (!ForwardPendingEventsToNextHandler(request_id))
141 return false;
142 if (info->pause_count())
143 return true;
144
[email protected]9dea9e1f2009-01-29 00:30:47145 // Release the reference that we acquired at OnWillRead.
146 read_buffer_ = NULL;
[email protected]d18720a2012-01-06 09:53:55147 return next_handler_->OnReadCompleted(request_id, bytes_read);
[email protected]e3c404b2008-12-23 01:07:32148}
149
[email protected]38e08982010-10-22 17:28:43150BufferedResourceHandler::~BufferedResourceHandler() {}
151
[email protected]e3c404b2008-12-23 01:07:32152bool BufferedResourceHandler::DelayResponse() {
153 std::string mime_type;
154 request_->GetMimeType(&mime_type);
155
156 std::string content_type_options;
157 request_->GetResponseHeaderByName("x-content-type-options",
158 &content_type_options);
[email protected]306291392009-01-17 19:15:36159
[email protected]423bd5b842009-01-23 17:30:50160 const bool sniffing_blocked =
161 LowerCaseEqualsASCII(content_type_options, "nosniff");
[email protected]e19d7132009-10-16 23:33:57162 const bool not_modified_status =
[email protected]2336ffe2011-11-24 01:23:34163 response_->headers && response_->headers->response_code() == 304;
[email protected]e19d7132009-10-16 23:33:57164 const bool we_would_like_to_sniff = not_modified_status ?
165 false : net::ShouldSniffMimeType(request_->url(), mime_type);
[email protected]306291392009-01-17 19:15:36166
167 RecordSnifferMetrics(sniffing_blocked, we_would_like_to_sniff, mime_type);
168
169 if (!sniffing_blocked && we_would_like_to_sniff) {
[email protected]e3c404b2008-12-23 01:07:32170 // We're going to look at the data before deciding what the content type
171 // is. That means we need to delay sending the ResponseStarted message
172 // over the IPC channel.
173 sniff_content_ = true;
[email protected]238667042010-10-23 01:40:00174 VLOG(1) << "To buffer: " << request_->url().spec();
[email protected]e3c404b2008-12-23 01:07:32175 return true;
176 }
177
[email protected]e19d7132009-10-16 23:33:57178 if (sniffing_blocked && mime_type.empty() && !not_modified_status) {
[email protected]423bd5b842009-01-23 17:30:50179 // Ugg. The server told us not to sniff the content but didn't give us a
180 // mime type. What's a browser to do? Turns out, we're supposed to treat
181 // the response as "text/plain". This is the most secure option.
182 mime_type.assign("text/plain");
[email protected]2336ffe2011-11-24 01:23:34183 response_->mime_type.assign(mime_type);
[email protected]423bd5b842009-01-23 17:30:50184 }
185
[email protected]b4599a12009-09-07 23:09:58186 if (mime_type == "application/rss+xml" ||
187 mime_type == "application/atom+xml") {
188 // Sad face. The server told us that they wanted us to treat the response
189 // as RSS or Atom. Unfortunately, we don't have a built-in feed previewer
190 // like other browsers. We can't just render the content as XML because
191 // web sites let third parties inject arbitrary script into their RSS
192 // feeds. That leaves us with little choice but to practically ignore the
193 // response. In the future, when we have an RSS feed previewer, we can
194 // remove this logic.
195 mime_type.assign("text/plain");
[email protected]2336ffe2011-11-24 01:23:34196 response_->mime_type.assign(mime_type);
[email protected]b4599a12009-09-07 23:09:58197 }
198
[email protected]e19d7132009-10-16 23:33:57199 if (!not_modified_status && ShouldWaitForPlugins()) {
[email protected]35fa6a22009-08-15 00:04:01200 wait_for_plugins_ = true;
201 return true;
202 }
203
[email protected]e3c404b2008-12-23 01:07:32204 return false;
205}
206
[email protected]35fa6a22009-08-15 00:04:01207bool BufferedResourceHandler::DidBufferEnough(int bytes_read) {
208 const int kRequiredLength = 256;
209
210 return bytes_read >= kRequiredLength;
211}
212
[email protected]e3c404b2008-12-23 01:07:32213bool BufferedResourceHandler::KeepBuffering(int bytes_read) {
214 DCHECK(read_buffer_);
[email protected]9dea9e1f2009-01-29 00:30:47215 if (my_buffer_) {
216 // We are using our own buffer to read, update the main buffer.
[email protected]c0dac3272010-07-28 08:04:45217 // TODO(darin): We should handle the case where read_buffer_size_ is small!
218 // See RedirectToFileResourceHandler::BufIsFull to see how this impairs
219 // downstream ResourceHandler implementations.
[email protected]2e7aff62010-03-16 06:34:56220 CHECK_LT(bytes_read + bytes_read_, read_buffer_size_);
[email protected]9dea9e1f2009-01-29 00:30:47221 memcpy(read_buffer_->data() + bytes_read_, my_buffer_->data(), bytes_read);
222 my_buffer_ = NULL;
223 }
[email protected]e3c404b2008-12-23 01:07:32224 bytes_read_ += bytes_read;
225 finished_ = (bytes_read == 0);
226
227 if (sniff_content_) {
228 std::string type_hint, new_type;
229 request_->GetMimeType(&type_hint);
230
[email protected]9dea9e1f2009-01-29 00:30:47231 if (!net::SniffMimeType(read_buffer_->data(), bytes_read_,
232 request_->url(), type_hint, &new_type)) {
[email protected]e3c404b2008-12-23 01:07:32233 // SniffMimeType() returns false if there is not enough data to determine
234 // the mime type. However, even if it returns false, it returns a new type
235 // that is probably better than the current one.
[email protected]2e7aff62010-03-16 06:34:56236 DCHECK_LT(bytes_read_, net::kMaxBytesToSniff);
[email protected]e3c404b2008-12-23 01:07:32237 if (!finished_) {
238 buffering_ = true;
239 return true;
240 }
241 }
242 sniff_content_ = false;
[email protected]2336ffe2011-11-24 01:23:34243 response_->mime_type.assign(new_type);
[email protected]e3c404b2008-12-23 01:07:32244
245 // We just sniffed the mime type, maybe there is a doctype to process.
[email protected]35fa6a22009-08-15 00:04:01246 if (ShouldWaitForPlugins())
247 wait_for_plugins_ = true;
[email protected]e3c404b2008-12-23 01:07:32248 }
[email protected]35fa6a22009-08-15 00:04:01249
[email protected]e3c404b2008-12-23 01:07:32250 buffering_ = false;
[email protected]35fa6a22009-08-15 00:04:01251
252 if (wait_for_plugins_)
253 return true;
254
[email protected]e3c404b2008-12-23 01:07:32255 return false;
256}
257
[email protected]0a0b2542012-01-03 08:25:22258bool BufferedResourceHandler::CompleteResponseStarted(int request_id) {
[email protected]347867b72009-09-02 00:35:58259 ResourceDispatcherHostRequestInfo* info =
260 ResourceDispatcherHost::InfoForRequest(request_);
[email protected]a755e1072009-10-23 16:58:37261 std::string mime_type;
262 request_->GetMimeType(&mime_type);
263
264 // Check if this is an X.509 certificate, if yes, let it be handled
265 // by X509UserCertResourceHandler.
266 if (mime_type == "application/x-x509-user-cert") {
[email protected]60651f7d2012-02-06 07:46:18267 // This is entirely similar to how DownloadResourceThrottle works except we
268 // are doing it for an X.509 client certificates.
269 // TODO(darin): This does not belong here!
[email protected]a755e1072009-10-23 16:58:37270
[email protected]2336ffe2011-11-24 01:23:34271 if (response_->headers && // Can be NULL if FTP.
272 response_->headers->response_code() / 100 != 2) {
[email protected]a755e1072009-10-23 16:58:37273 // The response code indicates that this is an error page, but we are
274 // expecting an X.509 user certificate. We follow Firefox here and show
275 // our own error page instead of handling the error page as a
276 // certificate.
277 // TODO(abarth): We should abstract the response_code test, but this kind
278 // of check is scattered throughout our codebase.
279 request_->SimulateError(net::ERR_FILE_NOT_FOUND);
280 return false;
281 }
282
[email protected]0dc72bbe2010-04-08 15:29:17283 X509UserCertResourceHandler* x509_cert_handler =
[email protected]4a729ae72010-08-02 21:26:11284 new X509UserCertResourceHandler(host_, request_,
285 info->child_id(), info->route_id());
[email protected]5e5e0c82012-01-25 09:12:29286 if (!UseAlternateResourceHandler(request_id, x509_cert_handler))
287 return false;
[email protected]a755e1072009-10-23 16:58:37288 }
[email protected]e3c404b2008-12-23 01:07:32289
[email protected]0dc72bbe2010-04-08 15:29:17290 // Check to see if we should forward the data from this request to the
291 // download thread.
292 // TODO(paulg): Only download if the context from the renderer allows it.
[email protected]347867b72009-09-02 00:35:58293 if (info->allow_download() && ShouldDownload(NULL)) {
[email protected]2336ffe2011-11-24 01:23:34294 if (response_->headers && // Can be NULL if FTP.
295 response_->headers->response_code() / 100 != 2) {
[email protected]e3c404b2008-12-23 01:07:32296 // The response code indicates that this is an error page, but we don't
297 // know how to display the content. We follow Firefox here and show our
298 // own error page instead of triggering a download.
299 // TODO(abarth): We should abstract the response_code test, but this kind
300 // of check is scattered throughout our codebase.
[email protected]c4891b32009-03-08 07:41:31301 request_->SimulateError(net::ERR_FILE_NOT_FOUND);
[email protected]e3c404b2008-12-23 01:07:32302 return false;
303 }
304
[email protected]347867b72009-09-02 00:35:58305 info->set_is_download(true);
[email protected]e3c404b2008-12-23 01:07:32306
[email protected]254ed742011-08-16 18:45:27307 scoped_refptr<ResourceHandler> handler(
[email protected]60651f7d2012-02-06 07:46:18308 host_->CreateResourceHandlerForDownload(
309 request_,
310 *info->context(),
311 info->child_id(),
312 info->route_id(),
313 info->request_id(),
314 DownloadSaveInfo(),
315 DownloadResourceHandler::OnStartedCallback()));
[email protected]254ed742011-08-16 18:45:27316
[email protected]5e5e0c82012-01-25 09:12:29317 if (!UseAlternateResourceHandler(request_id, handler))
318 return false;
[email protected]e3c404b2008-12-23 01:07:32319 }
[email protected]5e5e0c82012-01-25 09:12:29320
321 if (info->pause_count())
322 return true;
323
[email protected]d18720a2012-01-06 09:53:55324 return next_handler_->OnResponseStarted(request_id, response_);
[email protected]e3c404b2008-12-23 01:07:32325}
326
[email protected]35fa6a22009-08-15 00:04:01327bool BufferedResourceHandler::ShouldWaitForPlugins() {
328 bool need_plugin_list;
329 if (!ShouldDownload(&need_plugin_list) || !need_plugin_list)
330 return false;
[email protected]e3c404b2008-12-23 01:07:32331
[email protected]35fa6a22009-08-15 00:04:01332 // We don't want to keep buffering as our buffer will fill up.
[email protected]347867b72009-09-02 00:35:58333 ResourceDispatcherHostRequestInfo* info =
334 ResourceDispatcherHost::InfoForRequest(request_);
335 host_->PauseRequest(info->child_id(), info->request_id(), true);
[email protected]35fa6a22009-08-15 00:04:01336
[email protected]d33e7cc2011-09-23 01:43:56337 // Get the plugins asynchronously.
[email protected]e67385f2011-12-21 06:00:56338 PluginServiceImpl::GetInstance()->GetPlugins(
[email protected]d33e7cc2011-09-23 01:43:56339 base::Bind(&BufferedResourceHandler::OnPluginsLoaded, this));
[email protected]35fa6a22009-08-15 00:04:01340 return true;
341}
342
343// This test mirrors the decision that WebKit makes in
344// WebFrameLoaderClient::dispatchDecidePolicyForMIMEType.
345bool BufferedResourceHandler::ShouldDownload(bool* need_plugin_list) {
346 if (need_plugin_list)
347 *need_plugin_list = false;
[email protected]2336ffe2011-11-24 01:23:34348 std::string type = StringToLowerASCII(response_->mime_type);
[email protected]28ca9fb2012-01-28 14:50:24349
350 // First, examine Content-Disposition.
[email protected]35fa6a22009-08-15 00:04:01351 std::string disposition;
352 request_->GetResponseHeaderByName("content-disposition", &disposition);
[email protected]35fa6a22009-08-15 00:04:01353 if (!disposition.empty()) {
[email protected]28ca9fb2012-01-28 14:50:24354 net::HttpContentDisposition parsed_disposition(disposition, std::string());
355 if (parsed_disposition.is_attachment())
[email protected]35fa6a22009-08-15 00:04:01356 return true;
357 }
358
[email protected]9f3fba52011-06-08 20:37:19359 if (host_->delegate() &&
360 host_->delegate()->ShouldForceDownloadResource(request_->url(), type))
[email protected]6657afa62009-11-04 02:15:20361 return true;
362
[email protected]35fa6a22009-08-15 00:04:01363 // MIME type checking.
364 if (net::IsSupportedMimeType(type))
365 return false;
366
[email protected]68598072011-07-29 08:21:28367 // Finally, check the plugin list.
368 bool allow_wildcard = false;
[email protected]dfba8762011-09-02 12:49:54369 ResourceDispatcherHostRequestInfo* info =
370 ResourceDispatcherHost::InfoForRequest(request_);
[email protected]68598072011-07-29 08:21:28371 bool stale = false;
[email protected]dfba8762011-09-02 12:49:54372 webkit::WebPluginInfo plugin;
[email protected]e67385f2011-12-21 06:00:56373 bool found = PluginServiceImpl::GetInstance()->GetPluginInfo(
[email protected]dfba8762011-09-02 12:49:54374 info->child_id(), info->route_id(), *info->context(),
375 request_->url(), GURL(), type, allow_wildcard,
376 &stale, &plugin, NULL);
377
[email protected]35fa6a22009-08-15 00:04:01378 if (need_plugin_list) {
[email protected]68598072011-07-29 08:21:28379 if (stale) {
[email protected]35fa6a22009-08-15 00:04:01380 *need_plugin_list = true;
381 return true;
382 }
383 } else {
[email protected]68598072011-07-29 08:21:28384 DCHECK(!stale);
[email protected]35fa6a22009-08-15 00:04:01385 }
386
[email protected]dfba8762011-09-02 12:49:54387 return !found;
[email protected]35fa6a22009-08-15 00:04:01388}
389
[email protected]5e5e0c82012-01-25 09:12:29390bool BufferedResourceHandler::UseAlternateResourceHandler(
[email protected]0dc72bbe2010-04-08 15:29:17391 int request_id,
392 ResourceHandler* handler) {
[email protected]0dc72bbe2010-04-08 15:29:17393 // Inform the original ResourceHandler that this will be handled entirely by
394 // the new ResourceHandler.
[email protected]5e5e0c82012-01-25 09:12:29395 // TODO(darin): We should probably check the return values of these.
396 next_handler_->OnResponseStarted(request_id, response_);
[email protected]f90bf0d92011-01-13 02:12:44397 net::URLRequestStatus status(net::URLRequestStatus::HANDLED_EXTERNALLY, 0);
[email protected]5e5e0c82012-01-25 09:12:29398 next_handler_->OnResponseCompleted(request_id, status, std::string());
[email protected]0dc72bbe2010-04-08 15:29:17399
[email protected]11149bd2010-06-10 16:31:04400 // Remove the non-owning pointer to the CrossSiteResourceHandler, if any,
401 // from the extra request info because the CrossSiteResourceHandler (part of
402 // the original ResourceHandler chain) will be deleted by the next statement.
[email protected]5e5e0c82012-01-25 09:12:29403 ResourceDispatcherHostRequestInfo* info =
404 ResourceDispatcherHost::InfoForRequest(request_);
[email protected]11149bd2010-06-10 16:31:04405 info->set_cross_site_handler(NULL);
406
[email protected]0dc72bbe2010-04-08 15:29:17407 // This is handled entirely within the new ResourceHandler, so just reset the
408 // original ResourceHandler.
[email protected]d18720a2012-01-06 09:53:55409 next_handler_ = handler;
[email protected]5e5e0c82012-01-25 09:12:29410
411 next_handler_needs_response_started_ = true;
412 next_handler_needs_will_read_ = true;
413
414 return ForwardPendingEventsToNextHandler(request_id);
415}
416
417bool BufferedResourceHandler::ForwardPendingEventsToNextHandler(
418 int request_id) {
419 ResourceDispatcherHostRequestInfo* info =
420 ResourceDispatcherHost::InfoForRequest(request_);
421 if (info->pause_count())
422 return true;
423
424 if (next_handler_needs_response_started_) {
425 if (!next_handler_->OnResponseStarted(request_id, response_))
426 return false;
427 // If the request was paused during OnResponseStarted, we need to avoid
428 // calling OnResponseStarted again.
429 next_handler_needs_response_started_ = false;
430 if (info->pause_count())
431 return true;
432 }
433
434 if (next_handler_needs_will_read_) {
435 CopyReadBufferToNextHandler(request_id);
436 // If the request was paused during OnWillRead, we need to be sure to try
437 // calling OnWillRead again.
438 if (info->pause_count())
439 return true;
440 next_handler_needs_will_read_ = false;
441 }
442 return true;
443}
444
445void BufferedResourceHandler::CopyReadBufferToNextHandler(int request_id) {
446 if (!bytes_read_)
447 return;
448
449 net::IOBuffer* buf = NULL;
450 int buf_len = 0;
451 if (next_handler_->OnWillRead(request_id, &buf, &buf_len, bytes_read_)) {
452 CHECK((buf_len >= bytes_read_) && (bytes_read_ >= 0));
453 memcpy(buf->data(), read_buffer_->data(), bytes_read_);
454 }
[email protected]0dc72bbe2010-04-08 15:29:17455}
456
[email protected]d33e7cc2011-09-23 01:43:56457void BufferedResourceHandler::OnPluginsLoaded(
458 const std::vector<webkit::WebPluginInfo>& plugins) {
[email protected]5658a602009-11-03 23:12:52459 wait_for_plugins_ = false;
[email protected]7f2e792e2009-11-30 23:18:29460 if (!request_)
461 return;
[email protected]5658a602009-11-03 23:12:52462
[email protected]7f2e792e2009-11-30 23:18:29463 ResourceDispatcherHostRequestInfo* info =
464 ResourceDispatcherHost::InfoForRequest(request_);
465 host_->PauseRequest(info->child_id(), info->request_id(), false);
[email protected]0a0b2542012-01-03 08:25:22466 if (!CompleteResponseStarted(info->request_id()))
[email protected]7f2e792e2009-11-30 23:18:29467 host_->CancelRequest(info->child_id(), info->request_id(), false);
[email protected]e3c404b2008-12-23 01:07:32468}
[email protected]d18720a2012-01-06 09:53:55469
470} // namespace content