Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5490)

Unified Diff: chrome/browser/renderer_host/buffered_resource_handler.cc

Issue 164305: Ensure we don't load plugins on the IO thread (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/renderer_host/buffered_resource_handler.cc
===================================================================
--- chrome/browser/renderer_host/buffered_resource_handler.cc (revision 23449)
+++ chrome/browser/renderer_host/buffered_resource_handler.cc (working copy)
@@ -9,12 +9,15 @@
#include "base/string_util.h"
#include "net/base/mime_sniffer.h"
#include "net/base/net_errors.h"
+#include "chrome/browser/chrome_thread.h"
#include "chrome/browser/renderer_host/download_throttling_resource_handler.h"
#include "chrome/browser/renderer_host/resource_dispatcher_host.h"
#include "chrome/common/url_constants.h"
#include "net/base/mime_sniffer.h"
+#include "net/base/mime_util.h"
#include "net/base/io_buffer.h"
#include "net/http/http_response_headers.h"
+#include "webkit/glue/plugins/plugin_list.h"
namespace {
@@ -49,6 +52,7 @@
bytes_read_(0),
sniff_content_(false),
should_buffer_(false),
+ wait_for_plugins_(false),
buffering_(false),
finished_(false) {
}
@@ -75,7 +79,6 @@
return true;
}
-
bool BufferedResourceHandler::OnResponseCompleted(
int request_id,
const URLRequestStatus& status,
@@ -83,6 +86,11 @@
return real_handler_->OnResponseCompleted(request_id, status, security_info);
}
+void BufferedResourceHandler::OnRequestClosed() {
+ request_ = NULL;
+ real_handler_->OnRequestClosed();
+}
+
// We'll let the original event handler provide a buffer, and reuse it for
// subsequent reads until we're done buffering.
bool BufferedResourceHandler::OnWillRead(int request_id, net::IOBuffer** buf,
@@ -118,12 +126,13 @@
return true;
LOG(INFO) << "Finished buffering " << request_->url().spec();
- sniff_content_ = should_buffer_ = false;
*bytes_read = bytes_read_;
// Done buffering, send the pending ResponseStarted event.
if (!CompleteResponseStarted(request_id, true))
return false;
+ } else if (wait_for_plugins_) {
+ return true;
}
// Release the reference that we acquired at OnWillRead.
@@ -171,6 +180,12 @@
LOG(INFO) << "To buffer: " << request_->url().spec();
return true;
}
+
+ if (ShouldWaitForPlugins()) {
+ wait_for_plugins_ = true;
+ return true;
+ }
+
return false;
}
@@ -189,6 +204,12 @@
return mime_type == "text/html";
}
+bool BufferedResourceHandler::DidBufferEnough(int bytes_read) {
+ const int kRequiredLength = 256;
+
+ return bytes_read >= kRequiredLength;
+}
+
bool BufferedResourceHandler::KeepBuffering(int bytes_read) {
DCHECK(read_buffer_);
if (my_buffer_) {
@@ -219,17 +240,29 @@
response_->response_head.mime_type.assign(new_type);
// We just sniffed the mime type, maybe there is a doctype to process.
- if (ShouldBuffer(request_->url(), new_type))
+ if (ShouldBuffer(request_->url(), new_type)) {
should_buffer_ = true;
+ } else if (ShouldWaitForPlugins()) {
+ wait_for_plugins_ = true;
+ }
}
- if (!finished_ && should_buffer_) {
- if (!DidBufferEnough(bytes_read_)) {
+ if (should_buffer_) {
+ if (!finished_ && !DidBufferEnough(bytes_read_)) {
buffering_ = true;
return true;
}
+
+ should_buffer_ = false;
+ if (ShouldWaitForPlugins())
+ wait_for_plugins_ = true;
}
+
buffering_ = false;
+
+ if (wait_for_plugins_)
+ return true;
+
return false;
}
@@ -238,16 +271,10 @@
// Check to see if we should forward the data from this request to the
// download thread.
// TODO(paulg): Only download if the context from the renderer allows it.
- std::string content_disposition;
- request_->GetResponseHeaderByName("content-disposition",
- &content_disposition);
-
ResourceDispatcherHost::ExtraRequestInfo* info =
ResourceDispatcherHost::ExtraInfoForRequest(request_);
- if (info->allow_download &&
- host_->ShouldDownload(response_->response_head.mime_type,
- content_disposition)) {
+ if (info->allow_download && ShouldDownload(NULL)) {
if (response_->response_head.headers && // Can be NULL if FTP.
response_->response_head.headers->response_code() / 100 != 2) {
// The response code indicates that this is an error page, but we don't
@@ -293,8 +320,97 @@
return real_handler_->OnResponseStarted(request_id, response_);
}
-bool BufferedResourceHandler::DidBufferEnough(int bytes_read) {
- const int kRequiredLength = 256;
+bool BufferedResourceHandler::ShouldWaitForPlugins() {
+ bool need_plugin_list;
+ if (!ShouldDownload(&need_plugin_list) || !need_plugin_list)
+ return false;
- return bytes_read >= kRequiredLength;
+ // We don't want to keep buffering as our buffer will fill up.
+ ResourceDispatcherHost::ExtraRequestInfo* info =
+ ResourceDispatcherHost::ExtraInfoForRequest(request_);
+ host_->PauseRequest(info->process_id, info->request_id, true);
+
+ // Schedule plugin loading on the file thread.
+ ChromeThread::GetMessageLoop(ChromeThread::FILE)->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &BufferedResourceHandler::LoadPlugins));
+ return true;
}
+
+// This test mirrors the decision that WebKit makes in
+// WebFrameLoaderClient::dispatchDecidePolicyForMIMEType.
+bool BufferedResourceHandler::ShouldDownload(bool* need_plugin_list) {
+ if (need_plugin_list)
+ *need_plugin_list = false;
+ std::string type = StringToLowerASCII(response_->response_head.mime_type);
+ std::string disposition;
+ request_->GetResponseHeaderByName("content-disposition", &disposition);
+ disposition = StringToLowerASCII(disposition);
+
+ // First, examine content-disposition.
+ if (!disposition.empty()) {
+ bool should_download = true;
+
+ // Some broken sites just send ...
+ // Content-Disposition: ; filename="file"
+ // ... screen those out here.
+ if (disposition[0] == ';')
+ should_download = false;
+
+ if (disposition.compare(0, 6, "inline") == 0)
+ should_download = false;
+
+ // Some broken sites just send ...
+ // Content-Disposition: filename="file"
+ // ... without a disposition token... Screen those out.
+ if (disposition.compare(0, 8, "filename") == 0)
+ should_download = false;
+
+ // Also in use is Content-Disposition: name="file"
+ if (disposition.compare(0, 4, "name") == 0)
+ should_download = false;
+
+ // We have a content-disposition of "attachment" or unknown.
+ // RFC 2183, section 2.8 says that an unknown disposition
+ // value should be treated as "attachment".
+ if (should_download)
+ return true;
+ }
+
+ // MIME type checking.
+ if (net::IsSupportedMimeType(type))
+ return false;
+
+ if (need_plugin_list) {
+ if (!NPAPI::PluginList::Singleton()->PluginsLoaded()) {
+ *need_plugin_list = true;
+ return true;
+ }
+ } else {
+ DCHECK(NPAPI::PluginList::Singleton()->PluginsLoaded());
+ }
+
+ // Finally, check the plugin list.
+ WebPluginInfo info;
+ bool allow_wildcard = false;
+ return !NPAPI::PluginList::Singleton()->GetPluginInfo(
+ GURL(), type, "", allow_wildcard, &info, NULL);
+}
+
+void BufferedResourceHandler::LoadPlugins() {
+ std::vector<WebPluginInfo> plugins;
+ NPAPI::PluginList::Singleton()->GetPlugins(false, &plugins);
+ ChromeThread::GetMessageLoop(ChromeThread::IO)->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &BufferedResourceHandler::OnPluginsLoaded));
+}
+
+void BufferedResourceHandler::OnPluginsLoaded() {
+ wait_for_plugins_ = false;
+ if (!request_)
+ return;
+
+ ResourceDispatcherHost::ExtraRequestInfo* info =
+ ResourceDispatcherHost::ExtraInfoForRequest(request_);
+ host_->PauseRequest(info->process_id, info->request_id, false);
+ if (!CompleteResponseStarted(info->request_id, false))
+ host_->CancelRequest(info->process_id, info->request_id, false);
+}
« no previous file with comments | « chrome/browser/renderer_host/buffered_resource_handler.h ('k') | chrome/browser/renderer_host/resource_dispatcher_host.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698