blob: 4b43691d4913b319250a41d495d3f1d989959893 [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]e67385f2011-12-21 06:00:5615#include "content/browser/plugin_service_impl.h"
[email protected]ea114722012-03-12 01:11:2516#include "content/browser/renderer_host/resource_dispatcher_host_impl.h"
[email protected]60cf2db2012-03-07 21:24:1817#include "content/browser/renderer_host/resource_request_info_impl.h"
[email protected]1d8a3d1f2011-02-19 07:11:5218#include "content/browser/renderer_host/x509_user_cert_resource_handler.h"
[email protected]c38831a12011-10-28 12:44:4919#include "content/public/browser/browser_thread.h"
[email protected]87f3c082011-10-19 18:07:4420#include "content/public/browser/content_browser_client.h"
[email protected]29a5ffc82012-03-13 19:35:5821#include "content/public/browser/download_save_info.h"
[email protected]ce967862012-02-09 22:47:0522#include "content/public/browser/resource_context.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]ea114722012-03-12 01:11:2564BufferedResourceHandler::BufferedResourceHandler(
[email protected]d651cbc2012-05-31 21:33:0565 scoped_ptr<ResourceHandler> next_handler,
[email protected]ea114722012-03-12 01:11:2566 ResourceDispatcherHostImpl* host,
67 net::URLRequest* request)
[email protected]d651cbc2012-05-31 21:33:0568 : LayeredResourceHandler(next_handler.Pass()),
[email protected]e3c404b2008-12-23 01:07:3269 host_(host),
70 request_(request),
[email protected]dd9b5462009-09-25 17:22:2371 read_buffer_size_(0),
[email protected]e3c404b2008-12-23 01:07:3272 bytes_read_(0),
73 sniff_content_(false),
[email protected]35fa6a22009-08-15 00:04:0174 wait_for_plugins_(false),
[email protected]22b305442012-05-21 18:02:5975 deferred_waiting_for_plugins_(false),
[email protected]e3c404b2008-12-23 01:07:3276 buffering_(false),
[email protected]5e5e0c82012-01-25 09:12:2977 next_handler_needs_response_started_(false),
78 next_handler_needs_will_read_(false),
[email protected]e3c404b2008-12-23 01:07:3279 finished_(false) {
80}
81
[email protected]2336ffe2011-11-24 01:23:3482bool BufferedResourceHandler::OnResponseStarted(
83 int request_id,
[email protected]22b305442012-05-21 18:02:5984 ResourceResponse* response,
85 bool* defer) {
[email protected]e3c404b2008-12-23 01:07:3286 response_ = response;
[email protected]22b305442012-05-21 18:02:5987
[email protected]e3c404b2008-12-23 01:07:3288 if (!DelayResponse())
[email protected]22b305442012-05-21 18:02:5989 return CompleteResponseStarted(request_id, defer);
90
91 if (wait_for_plugins_) {
92 deferred_waiting_for_plugins_ = true;
93 *defer = true;
94 }
[email protected]e3c404b2008-12-23 01:07:3295 return true;
96}
97
[email protected]e3c404b2008-12-23 01:07:3298// We'll let the original event handler provide a buffer, and reuse it for
99// subsequent reads until we're done buffering.
[email protected]9dea9e1f2009-01-29 00:30:47100bool BufferedResourceHandler::OnWillRead(int request_id, net::IOBuffer** buf,
101 int* buf_size, int min_size) {
[email protected]e3c404b2008-12-23 01:07:32102 if (buffering_) {
[email protected]9dea9e1f2009-01-29 00:30:47103 DCHECK(!my_buffer_.get());
[email protected]2e7aff62010-03-16 06:34:56104 my_buffer_ = new net::IOBuffer(net::kMaxBytesToSniff);
[email protected]9dea9e1f2009-01-29 00:30:47105 *buf = my_buffer_.get();
[email protected]2e7aff62010-03-16 06:34:56106 *buf_size = net::kMaxBytesToSniff;
[email protected]e3c404b2008-12-23 01:07:32107 return true;
108 }
109
110 if (finished_)
111 return false;
112
[email protected]22b305442012-05-21 18:02:59113 if (!next_handler_->OnWillRead(request_id, buf, buf_size, min_size))
[email protected]67199052009-06-12 21:15:33114 return false;
[email protected]22b305442012-05-21 18:02:59115
[email protected]e3c404b2008-12-23 01:07:32116 read_buffer_ = *buf;
117 read_buffer_size_ = *buf_size;
[email protected]2e7aff62010-03-16 06:34:56118 DCHECK_GE(read_buffer_size_, net::kMaxBytesToSniff * 2);
[email protected]e3c404b2008-12-23 01:07:32119 bytes_read_ = 0;
[email protected]67199052009-06-12 21:15:33120 return true;
[email protected]e3c404b2008-12-23 01:07:32121}
122
[email protected]22b305442012-05-21 18:02:59123bool BufferedResourceHandler::OnReadCompleted(int request_id, int* bytes_read,
124 bool* defer) {
[email protected]216c17f4d2011-05-17 06:00:55125 if (sniff_content_) {
[email protected]22b305442012-05-21 18:02:59126 if (KeepBuffering(*bytes_read)) {
127 if (wait_for_plugins_)
128 *defer = deferred_waiting_for_plugins_ = true;
[email protected]e3c404b2008-12-23 01:07:32129 return true;
[email protected]22b305442012-05-21 18:02:59130 }
[email protected]e3c404b2008-12-23 01:07:32131
[email protected]e3c404b2008-12-23 01:07:32132 *bytes_read = bytes_read_;
133
134 // Done buffering, send the pending ResponseStarted event.
[email protected]22b305442012-05-21 18:02:59135 if (!CompleteResponseStarted(request_id, defer))
[email protected]e3c404b2008-12-23 01:07:32136 return false;
[email protected]22b305442012-05-21 18:02:59137 if (*defer)
[email protected]98d6f152011-09-29 19:35:51138 return true;
[email protected]35fa6a22009-08-15 00:04:01139 } else if (wait_for_plugins_) {
[email protected]22b305442012-05-21 18:02:59140 *defer = deferred_waiting_for_plugins_ = true;
[email protected]35fa6a22009-08-15 00:04:01141 return true;
[email protected]e3c404b2008-12-23 01:07:32142 }
143
[email protected]22b305442012-05-21 18:02:59144 if (!ForwardPendingEventsToNextHandler(request_id, defer))
[email protected]5e5e0c82012-01-25 09:12:29145 return false;
[email protected]22b305442012-05-21 18:02:59146 if (*defer)
[email protected]5e5e0c82012-01-25 09:12:29147 return true;
148
[email protected]9dea9e1f2009-01-29 00:30:47149 // Release the reference that we acquired at OnWillRead.
150 read_buffer_ = NULL;
[email protected]22b305442012-05-21 18:02:59151 return next_handler_->OnReadCompleted(request_id, bytes_read, defer);
[email protected]e3c404b2008-12-23 01:07:32152}
153
[email protected]38e08982010-10-22 17:28:43154BufferedResourceHandler::~BufferedResourceHandler() {}
155
[email protected]e3c404b2008-12-23 01:07:32156bool BufferedResourceHandler::DelayResponse() {
157 std::string mime_type;
158 request_->GetMimeType(&mime_type);
159
160 std::string content_type_options;
161 request_->GetResponseHeaderByName("x-content-type-options",
162 &content_type_options);
[email protected]306291392009-01-17 19:15:36163
[email protected]423bd5b842009-01-23 17:30:50164 const bool sniffing_blocked =
165 LowerCaseEqualsASCII(content_type_options, "nosniff");
[email protected]e19d7132009-10-16 23:33:57166 const bool not_modified_status =
[email protected]2336ffe2011-11-24 01:23:34167 response_->headers && response_->headers->response_code() == 304;
[email protected]e19d7132009-10-16 23:33:57168 const bool we_would_like_to_sniff = not_modified_status ?
169 false : net::ShouldSniffMimeType(request_->url(), mime_type);
[email protected]306291392009-01-17 19:15:36170
171 RecordSnifferMetrics(sniffing_blocked, we_would_like_to_sniff, mime_type);
172
173 if (!sniffing_blocked && we_would_like_to_sniff) {
[email protected]e3c404b2008-12-23 01:07:32174 // We're going to look at the data before deciding what the content type
175 // is. That means we need to delay sending the ResponseStarted message
176 // over the IPC channel.
177 sniff_content_ = true;
[email protected]238667042010-10-23 01:40:00178 VLOG(1) << "To buffer: " << request_->url().spec();
[email protected]e3c404b2008-12-23 01:07:32179 return true;
180 }
181
[email protected]e19d7132009-10-16 23:33:57182 if (sniffing_blocked && mime_type.empty() && !not_modified_status) {
[email protected]423bd5b842009-01-23 17:30:50183 // Ugg. The server told us not to sniff the content but didn't give us a
184 // mime type. What's a browser to do? Turns out, we're supposed to treat
185 // the response as "text/plain". This is the most secure option.
186 mime_type.assign("text/plain");
[email protected]2336ffe2011-11-24 01:23:34187 response_->mime_type.assign(mime_type);
[email protected]423bd5b842009-01-23 17:30:50188 }
189
[email protected]e19d7132009-10-16 23:33:57190 if (!not_modified_status && ShouldWaitForPlugins()) {
[email protected]35fa6a22009-08-15 00:04:01191 wait_for_plugins_ = true;
192 return true;
193 }
194
[email protected]e3c404b2008-12-23 01:07:32195 return false;
196}
197
[email protected]35fa6a22009-08-15 00:04:01198bool BufferedResourceHandler::DidBufferEnough(int bytes_read) {
199 const int kRequiredLength = 256;
200
201 return bytes_read >= kRequiredLength;
202}
203
[email protected]e3c404b2008-12-23 01:07:32204bool BufferedResourceHandler::KeepBuffering(int bytes_read) {
205 DCHECK(read_buffer_);
[email protected]9dea9e1f2009-01-29 00:30:47206 if (my_buffer_) {
207 // We are using our own buffer to read, update the main buffer.
[email protected]c0dac3272010-07-28 08:04:45208 // TODO(darin): We should handle the case where read_buffer_size_ is small!
209 // See RedirectToFileResourceHandler::BufIsFull to see how this impairs
210 // downstream ResourceHandler implementations.
[email protected]2e7aff62010-03-16 06:34:56211 CHECK_LT(bytes_read + bytes_read_, read_buffer_size_);
[email protected]9dea9e1f2009-01-29 00:30:47212 memcpy(read_buffer_->data() + bytes_read_, my_buffer_->data(), bytes_read);
213 my_buffer_ = NULL;
214 }
[email protected]e3c404b2008-12-23 01:07:32215 bytes_read_ += bytes_read;
216 finished_ = (bytes_read == 0);
217
218 if (sniff_content_) {
219 std::string type_hint, new_type;
220 request_->GetMimeType(&type_hint);
221
[email protected]9dea9e1f2009-01-29 00:30:47222 if (!net::SniffMimeType(read_buffer_->data(), bytes_read_,
223 request_->url(), type_hint, &new_type)) {
[email protected]e3c404b2008-12-23 01:07:32224 // SniffMimeType() returns false if there is not enough data to determine
225 // the mime type. However, even if it returns false, it returns a new type
226 // that is probably better than the current one.
[email protected]2e7aff62010-03-16 06:34:56227 DCHECK_LT(bytes_read_, net::kMaxBytesToSniff);
[email protected]e3c404b2008-12-23 01:07:32228 if (!finished_) {
229 buffering_ = true;
230 return true;
231 }
232 }
233 sniff_content_ = false;
[email protected]2336ffe2011-11-24 01:23:34234 response_->mime_type.assign(new_type);
[email protected]e3c404b2008-12-23 01:07:32235
236 // We just sniffed the mime type, maybe there is a doctype to process.
[email protected]35fa6a22009-08-15 00:04:01237 if (ShouldWaitForPlugins())
238 wait_for_plugins_ = true;
[email protected]e3c404b2008-12-23 01:07:32239 }
[email protected]35fa6a22009-08-15 00:04:01240
[email protected]e3c404b2008-12-23 01:07:32241 buffering_ = false;
[email protected]35fa6a22009-08-15 00:04:01242
243 if (wait_for_plugins_)
244 return true;
245
[email protected]e3c404b2008-12-23 01:07:32246 return false;
247}
248
[email protected]22b305442012-05-21 18:02:59249bool BufferedResourceHandler::CompleteResponseStarted(int request_id,
250 bool* defer) {
[email protected]60cf2db2012-03-07 21:24:18251 ResourceRequestInfoImpl* info =
[email protected]ea114722012-03-12 01:11:25252 ResourceRequestInfoImpl::ForRequest(request_);
[email protected]a755e1072009-10-23 16:58:37253 std::string mime_type;
254 request_->GetMimeType(&mime_type);
255
[email protected]a755e1072009-10-23 16:58:37256 if (mime_type == "application/x-x509-user-cert") {
[email protected]22b305442012-05-21 18:02:59257 // Let X.509 certs be handled by the X509UserCertResourceHandler.
258
259 // This is entirely similar to how DownloadResourceHandler works except we
[email protected]60651f7d2012-02-06 07:46:18260 // are doing it for an X.509 client certificates.
261 // TODO(darin): This does not belong here!
[email protected]a755e1072009-10-23 16:58:37262
[email protected]2336ffe2011-11-24 01:23:34263 if (response_->headers && // Can be NULL if FTP.
264 response_->headers->response_code() / 100 != 2) {
[email protected]a755e1072009-10-23 16:58:37265 // The response code indicates that this is an error page, but we are
266 // expecting an X.509 user certificate. We follow Firefox here and show
267 // our own error page instead of handling the error page as a
268 // certificate.
269 // TODO(abarth): We should abstract the response_code test, but this kind
270 // of check is scattered throughout our codebase.
[email protected]4a5aebb2012-03-13 23:57:27271 request_->CancelWithError(net::ERR_FILE_NOT_FOUND);
[email protected]a755e1072009-10-23 16:58:37272 return false;
273 }
274
[email protected]d651cbc2012-05-31 21:33:05275 scoped_ptr<ResourceHandler> handler(
[email protected]ea114722012-03-12 01:11:25276 new X509UserCertResourceHandler(request_,
277 info->GetChildID(),
[email protected]d651cbc2012-05-31 21:33:05278 info->GetRouteID()));
[email protected]5a9d58fa2012-05-29 15:15:04279
[email protected]d651cbc2012-05-31 21:33:05280 return UseAlternateResourceHandler(request_id, handler.Pass(), defer);
[email protected]5a9d58fa2012-05-29 15:15:04281 }
282
283 if (info->allow_download() && ShouldDownload(NULL)) {
[email protected]22b305442012-05-21 18:02:59284 // Forward the data to the download thread.
[email protected]e3c404b2008-12-23 01:07:32285
[email protected]2336ffe2011-11-24 01:23:34286 if (response_->headers && // Can be NULL if FTP.
287 response_->headers->response_code() / 100 != 2) {
[email protected]e3c404b2008-12-23 01:07:32288 // The response code indicates that this is an error page, but we don't
289 // know how to display the content. We follow Firefox here and show our
290 // own error page instead of triggering a download.
291 // TODO(abarth): We should abstract the response_code test, but this kind
292 // of check is scattered throughout our codebase.
[email protected]4a5aebb2012-03-13 23:57:27293 request_->CancelWithError(net::ERR_FILE_NOT_FOUND);
[email protected]e3c404b2008-12-23 01:07:32294 return false;
295 }
296
[email protected]347867b72009-09-02 00:35:58297 info->set_is_download(true);
[email protected]e3c404b2008-12-23 01:07:32298
[email protected]d651cbc2012-05-31 21:33:05299 scoped_ptr<ResourceHandler> handler(
[email protected]60651f7d2012-02-06 07:46:18300 host_->CreateResourceHandlerForDownload(
301 request_,
[email protected]60cf2db2012-03-07 21:24:18302 info->GetContext(),
303 info->GetChildID(),
304 info->GetRouteID(),
305 info->GetRequestID(),
[email protected]a53e2f92012-05-15 15:27:06306 true, // is_content_initiated
[email protected]60651f7d2012-02-06 07:46:18307 DownloadSaveInfo(),
308 DownloadResourceHandler::OnStartedCallback()));
[email protected]254ed742011-08-16 18:45:27309
[email protected]d651cbc2012-05-31 21:33:05310 return UseAlternateResourceHandler(request_id, handler.Pass(), defer);
[email protected]e3c404b2008-12-23 01:07:32311 }
[email protected]5e5e0c82012-01-25 09:12:29312
[email protected]22b305442012-05-21 18:02:59313 if (*defer)
[email protected]5e5e0c82012-01-25 09:12:29314 return true;
315
[email protected]22b305442012-05-21 18:02:59316 return next_handler_->OnResponseStarted(request_id, response_, defer);
[email protected]e3c404b2008-12-23 01:07:32317}
318
[email protected]35fa6a22009-08-15 00:04:01319bool BufferedResourceHandler::ShouldWaitForPlugins() {
320 bool need_plugin_list;
321 if (!ShouldDownload(&need_plugin_list) || !need_plugin_list)
322 return false;
[email protected]e3c404b2008-12-23 01:07:32323
[email protected]d33e7cc2011-09-23 01:43:56324 // Get the plugins asynchronously.
[email protected]e67385f2011-12-21 06:00:56325 PluginServiceImpl::GetInstance()->GetPlugins(
[email protected]d651cbc2012-05-31 21:33:05326 base::Bind(&BufferedResourceHandler::OnPluginsLoaded, AsWeakPtr()));
[email protected]35fa6a22009-08-15 00:04:01327 return true;
328}
329
330// This test mirrors the decision that WebKit makes in
331// WebFrameLoaderClient::dispatchDecidePolicyForMIMEType.
332bool BufferedResourceHandler::ShouldDownload(bool* need_plugin_list) {
333 if (need_plugin_list)
334 *need_plugin_list = false;
[email protected]2336ffe2011-11-24 01:23:34335 std::string type = StringToLowerASCII(response_->mime_type);
[email protected]28ca9fb2012-01-28 14:50:24336
337 // First, examine Content-Disposition.
[email protected]35fa6a22009-08-15 00:04:01338 std::string disposition;
339 request_->GetResponseHeaderByName("content-disposition", &disposition);
[email protected]35fa6a22009-08-15 00:04:01340 if (!disposition.empty()) {
[email protected]28ca9fb2012-01-28 14:50:24341 net::HttpContentDisposition parsed_disposition(disposition, std::string());
342 if (parsed_disposition.is_attachment())
[email protected]35fa6a22009-08-15 00:04:01343 return true;
344 }
345
[email protected]9f3fba52011-06-08 20:37:19346 if (host_->delegate() &&
347 host_->delegate()->ShouldForceDownloadResource(request_->url(), type))
[email protected]6657afa62009-11-04 02:15:20348 return true;
349
[email protected]35fa6a22009-08-15 00:04:01350 // MIME type checking.
351 if (net::IsSupportedMimeType(type))
352 return false;
353
[email protected]68598072011-07-29 08:21:28354 // Finally, check the plugin list.
355 bool allow_wildcard = false;
[email protected]60cf2db2012-03-07 21:24:18356 ResourceRequestInfoImpl* info =
[email protected]ea114722012-03-12 01:11:25357 ResourceRequestInfoImpl::ForRequest(request_);
[email protected]68598072011-07-29 08:21:28358 bool stale = false;
[email protected]dfba8762011-09-02 12:49:54359 webkit::WebPluginInfo plugin;
[email protected]e67385f2011-12-21 06:00:56360 bool found = PluginServiceImpl::GetInstance()->GetPluginInfo(
[email protected]60cf2db2012-03-07 21:24:18361 info->GetChildID(), info->GetRouteID(), info->GetContext(),
[email protected]dfba8762011-09-02 12:49:54362 request_->url(), GURL(), type, allow_wildcard,
363 &stale, &plugin, NULL);
364
[email protected]35fa6a22009-08-15 00:04:01365 if (need_plugin_list) {
[email protected]68598072011-07-29 08:21:28366 if (stale) {
[email protected]35fa6a22009-08-15 00:04:01367 *need_plugin_list = true;
368 return true;
369 }
370 } else {
[email protected]68598072011-07-29 08:21:28371 DCHECK(!stale);
[email protected]35fa6a22009-08-15 00:04:01372 }
373
[email protected]dfba8762011-09-02 12:49:54374 return !found;
[email protected]35fa6a22009-08-15 00:04:01375}
376
[email protected]5e5e0c82012-01-25 09:12:29377bool BufferedResourceHandler::UseAlternateResourceHandler(
[email protected]0dc72bbe2010-04-08 15:29:17378 int request_id,
[email protected]d651cbc2012-05-31 21:33:05379 scoped_ptr<ResourceHandler> handler,
[email protected]22b305442012-05-21 18:02:59380 bool* defer) {
[email protected]0dc72bbe2010-04-08 15:29:17381 // Inform the original ResourceHandler that this will be handled entirely by
382 // the new ResourceHandler.
[email protected]5e5e0c82012-01-25 09:12:29383 // TODO(darin): We should probably check the return values of these.
[email protected]22b305442012-05-21 18:02:59384 bool defer_ignored = false;
385 next_handler_->OnResponseStarted(request_id, response_, &defer_ignored);
386 DCHECK(!defer_ignored);
[email protected]f90bf0d92011-01-13 02:12:44387 net::URLRequestStatus status(net::URLRequestStatus::HANDLED_EXTERNALLY, 0);
[email protected]5e5e0c82012-01-25 09:12:29388 next_handler_->OnResponseCompleted(request_id, status, std::string());
[email protected]0dc72bbe2010-04-08 15:29:17389
[email protected]11149bd2010-06-10 16:31:04390 // Remove the non-owning pointer to the CrossSiteResourceHandler, if any,
391 // from the extra request info because the CrossSiteResourceHandler (part of
392 // the original ResourceHandler chain) will be deleted by the next statement.
[email protected]60cf2db2012-03-07 21:24:18393 ResourceRequestInfoImpl* info =
[email protected]ea114722012-03-12 01:11:25394 ResourceRequestInfoImpl::ForRequest(request_);
[email protected]11149bd2010-06-10 16:31:04395 info->set_cross_site_handler(NULL);
396
[email protected]0dc72bbe2010-04-08 15:29:17397 // This is handled entirely within the new ResourceHandler, so just reset the
398 // original ResourceHandler.
[email protected]d651cbc2012-05-31 21:33:05399 next_handler_ = handler.Pass();
[email protected]5e5e0c82012-01-25 09:12:29400
401 next_handler_needs_response_started_ = true;
402 next_handler_needs_will_read_ = true;
403
[email protected]22b305442012-05-21 18:02:59404 return ForwardPendingEventsToNextHandler(request_id, defer);
[email protected]5e5e0c82012-01-25 09:12:29405}
406
[email protected]22b305442012-05-21 18:02:59407bool BufferedResourceHandler::ForwardPendingEventsToNextHandler(int request_id,
408 bool* defer) {
[email protected]5e5e0c82012-01-25 09:12:29409 if (next_handler_needs_response_started_) {
[email protected]22b305442012-05-21 18:02:59410 if (!next_handler_->OnResponseStarted(request_id, response_, defer))
[email protected]5e5e0c82012-01-25 09:12:29411 return false;
[email protected]22b305442012-05-21 18:02:59412 // If the request was deferred during OnResponseStarted, we need to avoid
[email protected]5e5e0c82012-01-25 09:12:29413 // calling OnResponseStarted again.
414 next_handler_needs_response_started_ = false;
[email protected]22b305442012-05-21 18:02:59415 if (*defer)
[email protected]5e5e0c82012-01-25 09:12:29416 return true;
417 }
418
419 if (next_handler_needs_will_read_) {
420 CopyReadBufferToNextHandler(request_id);
[email protected]5e5e0c82012-01-25 09:12:29421 next_handler_needs_will_read_ = false;
422 }
423 return true;
424}
425
426void BufferedResourceHandler::CopyReadBufferToNextHandler(int request_id) {
427 if (!bytes_read_)
428 return;
429
430 net::IOBuffer* buf = NULL;
431 int buf_len = 0;
432 if (next_handler_->OnWillRead(request_id, &buf, &buf_len, bytes_read_)) {
433 CHECK((buf_len >= bytes_read_) && (bytes_read_ >= 0));
434 memcpy(buf->data(), read_buffer_->data(), bytes_read_);
435 }
[email protected]0dc72bbe2010-04-08 15:29:17436}
437
[email protected]d33e7cc2011-09-23 01:43:56438void BufferedResourceHandler::OnPluginsLoaded(
439 const std::vector<webkit::WebPluginInfo>& plugins) {
[email protected]22b305442012-05-21 18:02:59440 bool needs_resume = deferred_waiting_for_plugins_;
441 deferred_waiting_for_plugins_ = false;
442
[email protected]5658a602009-11-03 23:12:52443 wait_for_plugins_ = false;
[email protected]7f2e792e2009-11-30 23:18:29444 if (!request_)
445 return;
[email protected]5658a602009-11-03 23:12:52446
[email protected]60cf2db2012-03-07 21:24:18447 ResourceRequestInfoImpl* info =
[email protected]ea114722012-03-12 01:11:25448 ResourceRequestInfoImpl::ForRequest(request_);
[email protected]60cf2db2012-03-07 21:24:18449 int child_id = info->GetChildID();
450 int request_id = info->GetRequestID();
451
[email protected]22b305442012-05-21 18:02:59452 bool defer = false;
453 if (!CompleteResponseStarted(request_id, &defer)) {
[email protected]60cf2db2012-03-07 21:24:18454 host_->CancelRequest(child_id, request_id, false);
[email protected]22b305442012-05-21 18:02:59455 } else if (!defer && needs_resume) {
456 host_->ResumeDeferredRequest(child_id, request_id);
457 }
[email protected]e3c404b2008-12-23 01:07:32458}
[email protected]d18720a2012-01-06 09:53:55459
460} // namespace content