blob: 026ce662afe419f1bccc53b998cb857c03a68361 [file] [log] [blame]
[email protected]f90bf0d92011-01-13 02:12:441// Copyright (c) 2011 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]5203e6002009-07-29 03:42:009#include "base/logging.h"
[email protected]835d7c82010-10-14 04:38:3810#include "base/metrics/histogram.h"
[email protected]319d9e6f2009-02-18 19:47:2111#include "base/string_util.h"
[email protected]1625ffd2011-03-01 17:51:5012#include "content/browser/browser_thread.h"
[email protected]9f3fba52011-06-08 20:37:1913#include "content/browser/content_browser_client.h"
[email protected]254ed742011-08-16 18:45:2714#include "content/browser/download/download_resource_handler.h"
[email protected]dfba8762011-09-02 12:49:5415#include "content/browser/plugin_service.h"
[email protected]1d8a3d1f2011-02-19 07:11:5216#include "content/browser/renderer_host/resource_dispatcher_host.h"
[email protected]9f3fba52011-06-08 20:37:1917#include "content/browser/renderer_host/resource_dispatcher_host_delegate.h"
[email protected]1d8a3d1f2011-02-19 07:11:5218#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]94dc971d2011-03-05 19:08:3220#include "content/common/resource_response.h"
[email protected]dd9b5462009-09-25 17:22:2321#include "net/base/io_buffer.h"
[email protected]9dea9e1f2009-01-29 00:30:4722#include "net/base/mime_sniffer.h"
[email protected]35fa6a22009-08-15 00:04:0123#include "net/base/mime_util.h"
[email protected]dd9b5462009-09-25 17:22:2324#include "net/base/net_errors.h"
[email protected]319d9e6f2009-02-18 19:47:2125#include "net/http/http_response_headers.h"
[email protected]191eb3f72010-12-21 06:27:5026#include "webkit/plugins/npapi/plugin_list.h"
[email protected]e3c404b2008-12-23 01:07:3227
[email protected]306291392009-01-17 19:15:3628namespace {
29
30void RecordSnifferMetrics(bool sniffing_blocked,
31 bool we_would_like_to_sniff,
32 const std::string& mime_type) {
[email protected]81ce9f3b2011-04-05 04:48:5333 static base::Histogram* nosniff_usage(NULL);
34 if (!nosniff_usage)
35 nosniff_usage = base::BooleanHistogram::FactoryGet(
36 "nosniff.usage", base::Histogram::kUmaTargetedHistogramFlag);
[email protected]e8829a192009-12-06 00:09:3737 nosniff_usage->AddBoolean(sniffing_blocked);
[email protected]306291392009-01-17 19:15:3638
39 if (sniffing_blocked) {
[email protected]81ce9f3b2011-04-05 04:48:5340 static base::Histogram* nosniff_otherwise(NULL);
41 if (!nosniff_otherwise)
42 nosniff_otherwise = base::BooleanHistogram::FactoryGet(
43 "nosniff.otherwise", base::Histogram::kUmaTargetedHistogramFlag);
[email protected]e8829a192009-12-06 00:09:3744 nosniff_otherwise->AddBoolean(we_would_like_to_sniff);
[email protected]306291392009-01-17 19:15:3645
[email protected]81ce9f3b2011-04-05 04:48:5346 static base::Histogram* nosniff_empty_mime_type(NULL);
47 if (!nosniff_empty_mime_type)
48 nosniff_empty_mime_type = base::BooleanHistogram::FactoryGet(
49 "nosniff.empty_mime_type",
50 base::Histogram::kUmaTargetedHistogramFlag);
[email protected]e8829a192009-12-06 00:09:3751 nosniff_empty_mime_type->AddBoolean(mime_type.empty());
[email protected]306291392009-01-17 19:15:3652 }
53}
54
55} // namespace
56
[email protected]e3c404b2008-12-23 01:07:3257BufferedResourceHandler::BufferedResourceHandler(ResourceHandler* handler,
58 ResourceDispatcherHost* host,
[email protected]6981d9632010-11-30 21:34:0259 net::URLRequest* request)
[email protected]e3c404b2008-12-23 01:07:3260 : real_handler_(handler),
61 host_(host),
62 request_(request),
[email protected]dd9b5462009-09-25 17:22:2363 read_buffer_size_(0),
[email protected]e3c404b2008-12-23 01:07:3264 bytes_read_(0),
65 sniff_content_(false),
[email protected]35fa6a22009-08-15 00:04:0166 wait_for_plugins_(false),
[email protected]e3c404b2008-12-23 01:07:3267 buffering_(false),
68 finished_(false) {
69}
70
71bool BufferedResourceHandler::OnUploadProgress(int request_id,
72 uint64 position,
73 uint64 size) {
74 return real_handler_->OnUploadProgress(request_id, position, size);
75}
76
77bool BufferedResourceHandler::OnRequestRedirected(int request_id,
[email protected]6568a9e32009-07-30 18:01:3978 const GURL& new_url,
79 ResourceResponse* response,
80 bool* defer) {
81 return real_handler_->OnRequestRedirected(
82 request_id, new_url, response, defer);
[email protected]e3c404b2008-12-23 01:07:3283}
84
85bool BufferedResourceHandler::OnResponseStarted(int request_id,
86 ResourceResponse* response) {
87 response_ = response;
88 if (!DelayResponse())
89 return CompleteResponseStarted(request_id, false);
90 return true;
91}
92
[email protected]e3c404b2008-12-23 01:07:3293bool BufferedResourceHandler::OnResponseCompleted(
[email protected]c4891b32009-03-08 07:41:3194 int request_id,
[email protected]f90bf0d92011-01-13 02:12:4495 const net::URLRequestStatus& status,
[email protected]c4891b32009-03-08 07:41:3196 const std::string& security_info) {
97 return real_handler_->OnResponseCompleted(request_id, status, security_info);
[email protected]e3c404b2008-12-23 01:07:3298}
99
[email protected]35fa6a22009-08-15 00:04:01100void BufferedResourceHandler::OnRequestClosed() {
101 request_ = NULL;
102 real_handler_->OnRequestClosed();
103}
104
[email protected]afd832c2010-03-02 04:53:31105bool BufferedResourceHandler::OnWillStart(int request_id,
106 const GURL& url,
107 bool* defer) {
108 return real_handler_->OnWillStart(request_id, url, defer);
109}
110
[email protected]e3c404b2008-12-23 01:07:32111// We'll let the original event handler provide a buffer, and reuse it for
112// subsequent reads until we're done buffering.
[email protected]9dea9e1f2009-01-29 00:30:47113bool BufferedResourceHandler::OnWillRead(int request_id, net::IOBuffer** buf,
114 int* buf_size, int min_size) {
[email protected]e3c404b2008-12-23 01:07:32115 if (buffering_) {
[email protected]9dea9e1f2009-01-29 00:30:47116 DCHECK(!my_buffer_.get());
[email protected]2e7aff62010-03-16 06:34:56117 my_buffer_ = new net::IOBuffer(net::kMaxBytesToSniff);
[email protected]9dea9e1f2009-01-29 00:30:47118 *buf = my_buffer_.get();
[email protected]2e7aff62010-03-16 06:34:56119 *buf_size = net::kMaxBytesToSniff;
[email protected]e3c404b2008-12-23 01:07:32120 return true;
121 }
122
123 if (finished_)
124 return false;
125
[email protected]67199052009-06-12 21:15:33126 if (!real_handler_->OnWillRead(request_id, buf, buf_size, min_size)) {
127 return false;
128 }
[email protected]e3c404b2008-12-23 01:07:32129 read_buffer_ = *buf;
[email protected]e3c404b2008-12-23 01:07:32130 read_buffer_size_ = *buf_size;
[email protected]2e7aff62010-03-16 06:34:56131 DCHECK_GE(read_buffer_size_, net::kMaxBytesToSniff * 2);
[email protected]e3c404b2008-12-23 01:07:32132 bytes_read_ = 0;
[email protected]67199052009-06-12 21:15:33133 return true;
[email protected]e3c404b2008-12-23 01:07:32134}
135
136bool BufferedResourceHandler::OnReadCompleted(int request_id, int* bytes_read) {
[email protected]216c17f4d2011-05-17 06:00:55137 if (sniff_content_) {
[email protected]e3c404b2008-12-23 01:07:32138 if (KeepBuffering(*bytes_read))
139 return true;
140
[email protected]e3c404b2008-12-23 01:07:32141 *bytes_read = bytes_read_;
142
143 // Done buffering, send the pending ResponseStarted event.
144 if (!CompleteResponseStarted(request_id, true))
145 return false;
[email protected]35fa6a22009-08-15 00:04:01146 } else if (wait_for_plugins_) {
147 return true;
[email protected]e3c404b2008-12-23 01:07:32148 }
149
[email protected]9dea9e1f2009-01-29 00:30:47150 // Release the reference that we acquired at OnWillRead.
151 read_buffer_ = NULL;
[email protected]e3c404b2008-12-23 01:07:32152 return real_handler_->OnReadCompleted(request_id, bytes_read);
153}
154
[email protected]38e08982010-10-22 17:28:43155BufferedResourceHandler::~BufferedResourceHandler() {}
156
[email protected]e3c404b2008-12-23 01:07:32157bool BufferedResourceHandler::DelayResponse() {
158 std::string mime_type;
159 request_->GetMimeType(&mime_type);
160
161 std::string content_type_options;
162 request_->GetResponseHeaderByName("x-content-type-options",
163 &content_type_options);
[email protected]306291392009-01-17 19:15:36164
[email protected]423bd5b842009-01-23 17:30:50165 const bool sniffing_blocked =
166 LowerCaseEqualsASCII(content_type_options, "nosniff");
[email protected]e19d7132009-10-16 23:33:57167 const bool not_modified_status =
168 response_->response_head.headers &&
169 response_->response_head.headers->response_code() == 304;
170 const bool we_would_like_to_sniff = not_modified_status ?
171 false : net::ShouldSniffMimeType(request_->url(), mime_type);
[email protected]306291392009-01-17 19:15:36172
173 RecordSnifferMetrics(sniffing_blocked, we_would_like_to_sniff, mime_type);
174
175 if (!sniffing_blocked && we_would_like_to_sniff) {
[email protected]e3c404b2008-12-23 01:07:32176 // We're going to look at the data before deciding what the content type
177 // is. That means we need to delay sending the ResponseStarted message
178 // over the IPC channel.
179 sniff_content_ = true;
[email protected]238667042010-10-23 01:40:00180 VLOG(1) << "To buffer: " << request_->url().spec();
[email protected]e3c404b2008-12-23 01:07:32181 return true;
182 }
183
[email protected]e19d7132009-10-16 23:33:57184 if (sniffing_blocked && mime_type.empty() && !not_modified_status) {
[email protected]423bd5b842009-01-23 17:30:50185 // Ugg. The server told us not to sniff the content but didn't give us a
186 // mime type. What's a browser to do? Turns out, we're supposed to treat
187 // the response as "text/plain". This is the most secure option.
188 mime_type.assign("text/plain");
189 response_->response_head.mime_type.assign(mime_type);
190 }
191
[email protected]b4599a12009-09-07 23:09:58192 if (mime_type == "application/rss+xml" ||
193 mime_type == "application/atom+xml") {
194 // Sad face. The server told us that they wanted us to treat the response
195 // as RSS or Atom. Unfortunately, we don't have a built-in feed previewer
196 // like other browsers. We can't just render the content as XML because
197 // web sites let third parties inject arbitrary script into their RSS
198 // feeds. That leaves us with little choice but to practically ignore the
199 // response. In the future, when we have an RSS feed previewer, we can
200 // remove this logic.
201 mime_type.assign("text/plain");
202 response_->response_head.mime_type.assign(mime_type);
203 }
204
[email protected]e19d7132009-10-16 23:33:57205 if (!not_modified_status && ShouldWaitForPlugins()) {
[email protected]35fa6a22009-08-15 00:04:01206 wait_for_plugins_ = true;
207 return true;
208 }
209
[email protected]e3c404b2008-12-23 01:07:32210 return false;
211}
212
[email protected]35fa6a22009-08-15 00:04:01213bool BufferedResourceHandler::DidBufferEnough(int bytes_read) {
214 const int kRequiredLength = 256;
215
216 return bytes_read >= kRequiredLength;
217}
218
[email protected]e3c404b2008-12-23 01:07:32219bool BufferedResourceHandler::KeepBuffering(int bytes_read) {
220 DCHECK(read_buffer_);
[email protected]9dea9e1f2009-01-29 00:30:47221 if (my_buffer_) {
222 // We are using our own buffer to read, update the main buffer.
[email protected]c0dac3272010-07-28 08:04:45223 // TODO(darin): We should handle the case where read_buffer_size_ is small!
224 // See RedirectToFileResourceHandler::BufIsFull to see how this impairs
225 // downstream ResourceHandler implementations.
[email protected]2e7aff62010-03-16 06:34:56226 CHECK_LT(bytes_read + bytes_read_, read_buffer_size_);
[email protected]9dea9e1f2009-01-29 00:30:47227 memcpy(read_buffer_->data() + bytes_read_, my_buffer_->data(), bytes_read);
228 my_buffer_ = NULL;
229 }
[email protected]e3c404b2008-12-23 01:07:32230 bytes_read_ += bytes_read;
231 finished_ = (bytes_read == 0);
232
233 if (sniff_content_) {
234 std::string type_hint, new_type;
235 request_->GetMimeType(&type_hint);
236
[email protected]9dea9e1f2009-01-29 00:30:47237 if (!net::SniffMimeType(read_buffer_->data(), bytes_read_,
238 request_->url(), type_hint, &new_type)) {
[email protected]e3c404b2008-12-23 01:07:32239 // SniffMimeType() returns false if there is not enough data to determine
240 // the mime type. However, even if it returns false, it returns a new type
241 // that is probably better than the current one.
[email protected]2e7aff62010-03-16 06:34:56242 DCHECK_LT(bytes_read_, net::kMaxBytesToSniff);
[email protected]e3c404b2008-12-23 01:07:32243 if (!finished_) {
244 buffering_ = true;
245 return true;
246 }
247 }
248 sniff_content_ = false;
249 response_->response_head.mime_type.assign(new_type);
250
251 // We just sniffed the mime type, maybe there is a doctype to process.
[email protected]35fa6a22009-08-15 00:04:01252 if (ShouldWaitForPlugins())
253 wait_for_plugins_ = true;
[email protected]e3c404b2008-12-23 01:07:32254 }
[email protected]35fa6a22009-08-15 00:04:01255
[email protected]e3c404b2008-12-23 01:07:32256 buffering_ = false;
[email protected]35fa6a22009-08-15 00:04:01257
258 if (wait_for_plugins_)
259 return true;
260
[email protected]e3c404b2008-12-23 01:07:32261 return false;
262}
263
264bool BufferedResourceHandler::CompleteResponseStarted(int request_id,
265 bool in_complete) {
[email protected]347867b72009-09-02 00:35:58266 ResourceDispatcherHostRequestInfo* info =
267 ResourceDispatcherHost::InfoForRequest(request_);
[email protected]a755e1072009-10-23 16:58:37268 std::string mime_type;
269 request_->GetMimeType(&mime_type);
270
271 // Check if this is an X.509 certificate, if yes, let it be handled
272 // by X509UserCertResourceHandler.
273 if (mime_type == "application/x-x509-user-cert") {
[email protected]a755e1072009-10-23 16:58:37274 // This is entirely similar to how DownloadThrottlingResourceHandler
275 // works except we are doing it for an X.509 client certificates.
276
277 if (response_->response_head.headers && // Can be NULL if FTP.
278 response_->response_head.headers->response_code() / 100 != 2) {
279 // The response code indicates that this is an error page, but we are
280 // expecting an X.509 user certificate. We follow Firefox here and show
281 // our own error page instead of handling the error page as a
282 // certificate.
283 // TODO(abarth): We should abstract the response_code test, but this kind
284 // of check is scattered throughout our codebase.
285 request_->SimulateError(net::ERR_FILE_NOT_FOUND);
286 return false;
287 }
288
[email protected]0dc72bbe2010-04-08 15:29:17289 X509UserCertResourceHandler* x509_cert_handler =
[email protected]4a729ae72010-08-02 21:26:11290 new X509UserCertResourceHandler(host_, request_,
291 info->child_id(), info->route_id());
[email protected]0dc72bbe2010-04-08 15:29:17292 UseAlternateResourceHandler(request_id, x509_cert_handler);
[email protected]a755e1072009-10-23 16:58:37293 }
[email protected]e3c404b2008-12-23 01:07:32294
[email protected]0dc72bbe2010-04-08 15:29:17295 // Check to see if we should forward the data from this request to the
296 // download thread.
297 // TODO(paulg): Only download if the context from the renderer allows it.
[email protected]347867b72009-09-02 00:35:58298 if (info->allow_download() && ShouldDownload(NULL)) {
[email protected]e3c404b2008-12-23 01:07:32299 if (response_->response_head.headers && // Can be NULL if FTP.
300 response_->response_head.headers->response_code() / 100 != 2) {
301 // The response code indicates that this is an error page, but we don't
302 // know how to display the content. We follow Firefox here and show our
303 // own error page instead of triggering a download.
304 // TODO(abarth): We should abstract the response_code test, but this kind
305 // of check is scattered throughout our codebase.
[email protected]c4891b32009-03-08 07:41:31306 request_->SimulateError(net::ERR_FILE_NOT_FOUND);
[email protected]e3c404b2008-12-23 01:07:32307 return false;
308 }
309
[email protected]347867b72009-09-02 00:35:58310 info->set_is_download(true);
[email protected]e3c404b2008-12-23 01:07:32311
[email protected]254ed742011-08-16 18:45:27312 scoped_refptr<ResourceHandler> handler(
313 new DownloadResourceHandler(host_,
314 info->child_id(),
315 info->route_id(),
316 info->request_id(),
317 request_->url(),
318 host_->download_file_manager(),
319 request_,
320 false,
321 DownloadSaveInfo()));
322
323 if (host_->delegate()) {
324 handler = host_->delegate()->DownloadStarting(
325 handler, *info->context(), request_, info->child_id(),
326 info->route_id(), info->request_id(), false, in_complete);
327 }
328
329 UseAlternateResourceHandler(request_id, handler);
[email protected]e3c404b2008-12-23 01:07:32330 }
331 return real_handler_->OnResponseStarted(request_id, response_);
332}
333
[email protected]35fa6a22009-08-15 00:04:01334bool BufferedResourceHandler::ShouldWaitForPlugins() {
335 bool need_plugin_list;
336 if (!ShouldDownload(&need_plugin_list) || !need_plugin_list)
337 return false;
[email protected]e3c404b2008-12-23 01:07:32338
[email protected]35fa6a22009-08-15 00:04:01339 // We don't want to keep buffering as our buffer will fill up.
[email protected]347867b72009-09-02 00:35:58340 ResourceDispatcherHostRequestInfo* info =
341 ResourceDispatcherHost::InfoForRequest(request_);
342 host_->PauseRequest(info->child_id(), info->request_id(), true);
[email protected]35fa6a22009-08-15 00:04:01343
[email protected]7f2e792e2009-11-30 23:18:29344 // Schedule plugin loading on the file thread.
[email protected]9a7e1502010-10-08 04:03:50345 BrowserThread::PostTask(
346 BrowserThread::FILE, FROM_HERE,
[email protected]7f2e792e2009-11-30 23:18:29347 NewRunnableMethod(this, &BufferedResourceHandler::LoadPlugins));
[email protected]35fa6a22009-08-15 00:04:01348 return true;
349}
350
351// This test mirrors the decision that WebKit makes in
352// WebFrameLoaderClient::dispatchDecidePolicyForMIMEType.
353bool BufferedResourceHandler::ShouldDownload(bool* need_plugin_list) {
354 if (need_plugin_list)
355 *need_plugin_list = false;
356 std::string type = StringToLowerASCII(response_->response_head.mime_type);
357 std::string disposition;
358 request_->GetResponseHeaderByName("content-disposition", &disposition);
359 disposition = StringToLowerASCII(disposition);
360
361 // First, examine content-disposition.
362 if (!disposition.empty()) {
363 bool should_download = true;
364
365 // Some broken sites just send ...
366 // Content-Disposition: ; filename="file"
367 // ... screen those out here.
368 if (disposition[0] == ';')
369 should_download = false;
370
371 if (disposition.compare(0, 6, "inline") == 0)
372 should_download = false;
373
374 // Some broken sites just send ...
375 // Content-Disposition: filename="file"
376 // ... without a disposition token... Screen those out.
377 if (disposition.compare(0, 8, "filename") == 0)
378 should_download = false;
379
380 // Also in use is Content-Disposition: name="file"
381 if (disposition.compare(0, 4, "name") == 0)
382 should_download = false;
383
384 // We have a content-disposition of "attachment" or unknown.
385 // RFC 2183, section 2.8 says that an unknown disposition
386 // value should be treated as "attachment".
387 if (should_download)
388 return true;
389 }
390
[email protected]9f3fba52011-06-08 20:37:19391 if (host_->delegate() &&
392 host_->delegate()->ShouldForceDownloadResource(request_->url(), type))
[email protected]6657afa62009-11-04 02:15:20393 return true;
394
[email protected]35fa6a22009-08-15 00:04:01395 // MIME type checking.
396 if (net::IsSupportedMimeType(type))
397 return false;
398
[email protected]68598072011-07-29 08:21:28399 // Finally, check the plugin list.
400 bool allow_wildcard = false;
[email protected]dfba8762011-09-02 12:49:54401 ResourceDispatcherHostRequestInfo* info =
402 ResourceDispatcherHost::InfoForRequest(request_);
[email protected]68598072011-07-29 08:21:28403 bool stale = false;
[email protected]dfba8762011-09-02 12:49:54404 webkit::WebPluginInfo plugin;
405 bool found = PluginService::GetInstance()->GetPluginInfo(
406 info->child_id(), info->route_id(), *info->context(),
407 request_->url(), GURL(), type, allow_wildcard,
408 &stale, &plugin, NULL);
409
[email protected]35fa6a22009-08-15 00:04:01410 if (need_plugin_list) {
[email protected]68598072011-07-29 08:21:28411 if (stale) {
[email protected]35fa6a22009-08-15 00:04:01412 *need_plugin_list = true;
413 return true;
414 }
415 } else {
[email protected]68598072011-07-29 08:21:28416 DCHECK(!stale);
[email protected]35fa6a22009-08-15 00:04:01417 }
418
[email protected]dfba8762011-09-02 12:49:54419 return !found;
[email protected]35fa6a22009-08-15 00:04:01420}
421
[email protected]0dc72bbe2010-04-08 15:29:17422void BufferedResourceHandler::UseAlternateResourceHandler(
423 int request_id,
424 ResourceHandler* handler) {
425 ResourceDispatcherHostRequestInfo* info =
426 ResourceDispatcherHost::InfoForRequest(request_);
427 if (bytes_read_) {
428 // A Read has already occured and we need to copy the data into the new
429 // ResourceHandler.
430 net::IOBuffer* buf = NULL;
431 int buf_len = 0;
432 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 }
436
437 // Inform the original ResourceHandler that this will be handled entirely by
438 // the new ResourceHandler.
439 real_handler_->OnResponseStarted(info->request_id(), response_);
[email protected]f90bf0d92011-01-13 02:12:44440 net::URLRequestStatus status(net::URLRequestStatus::HANDLED_EXTERNALLY, 0);
[email protected]0dc72bbe2010-04-08 15:29:17441 real_handler_->OnResponseCompleted(info->request_id(), status, std::string());
442
[email protected]11149bd2010-06-10 16:31:04443 // Remove the non-owning pointer to the CrossSiteResourceHandler, if any,
444 // from the extra request info because the CrossSiteResourceHandler (part of
445 // the original ResourceHandler chain) will be deleted by the next statement.
446 info->set_cross_site_handler(NULL);
447
[email protected]0dc72bbe2010-04-08 15:29:17448 // This is handled entirely within the new ResourceHandler, so just reset the
449 // original ResourceHandler.
450 real_handler_ = handler;
451}
452
[email protected]7f2e792e2009-11-30 23:18:29453void BufferedResourceHandler::LoadPlugins() {
[email protected]91d9f3d2011-08-14 05:24:44454 std::vector<webkit::WebPluginInfo> plugins;
[email protected]68598072011-07-29 08:21:28455 webkit::npapi::PluginList::Singleton()->GetPlugins(&plugins);
[email protected]7f2e792e2009-11-30 23:18:29456
[email protected]9a7e1502010-10-08 04:03:50457 BrowserThread::PostTask(
458 BrowserThread::IO, FROM_HERE,
[email protected]7f2e792e2009-11-30 23:18:29459 NewRunnableMethod(this, &BufferedResourceHandler::OnPluginsLoaded));
460}
461
462void BufferedResourceHandler::OnPluginsLoaded() {
[email protected]5658a602009-11-03 23:12:52463 wait_for_plugins_ = false;
[email protected]7f2e792e2009-11-30 23:18:29464 if (!request_)
465 return;
[email protected]5658a602009-11-03 23:12:52466
[email protected]7f2e792e2009-11-30 23:18:29467 ResourceDispatcherHostRequestInfo* info =
468 ResourceDispatcherHost::InfoForRequest(request_);
469 host_->PauseRequest(info->child_id(), info->request_id(), false);
470 if (!CompleteResponseStarted(info->request_id(), false))
471 host_->CancelRequest(info->child_id(), info->request_id(), false);
[email protected]e3c404b2008-12-23 01:07:32472}