diff options
Diffstat (limited to 'chrome/browser/renderer_host/buffered_resource_handler.cc')
-rw-r--r-- | chrome/browser/renderer_host/buffered_resource_handler.cc | 135 |
1 files changed, 121 insertions, 14 deletions
diff --git a/chrome/browser/renderer_host/buffered_resource_handler.cc b/chrome/browser/renderer_host/buffered_resource_handler.cc index b1007fe..60212e0 100644 --- a/chrome/browser/renderer_host/buffered_resource_handler.cc +++ b/chrome/browser/renderer_host/buffered_resource_handler.cc @@ -9,10 +9,13 @@ #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/plugin_service.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" @@ -49,6 +52,7 @@ BufferedResourceHandler::BufferedResourceHandler(ResourceHandler* handler, bytes_read_(0), sniff_content_(false), should_buffer_(false), + wait_for_plugins_(false), buffering_(false), finished_(false) { } @@ -118,12 +122,13 @@ bool BufferedResourceHandler::OnReadCompleted(int request_id, int* bytes_read) { 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 +176,12 @@ bool BufferedResourceHandler::DelayResponse() { LOG(INFO) << "To buffer: " << request_->url().spec(); return true; } + + if (ShouldWaitForPlugins()) { + wait_for_plugins_ = true; + return true; + } + return false; } @@ -189,6 +200,12 @@ bool BufferedResourceHandler::ShouldBuffer(const GURL& url, 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 +236,34 @@ bool BufferedResourceHandler::KeepBuffering(int bytes_read) { 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_) { + // 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); + return true; + } + return false; } @@ -238,16 +272,10 @@ bool BufferedResourceHandler::CompleteResponseStarted(int request_id, // 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 +321,87 @@ bool BufferedResourceHandler::CompleteResponseStarted(int request_id, 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; + // 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 (!PluginService::GetInstance()->PluginsLoaded()) { + *need_plugin_list = true; + return true; + } + } else { + DCHECK(PluginService::GetInstance()->PluginsLoaded()); + } + + // Finally, check the plugin service. + bool allow_wildcard = false; + return !PluginService::GetInstance()->HavePluginFor(type, allow_wildcard); +} + +void BufferedResourceHandler::LoadPlugins() { + std::vector<WebPluginInfo> plugins; + PluginService::GetInstance()->GetPlugins(false, &plugins); + ChromeThread::GetMessageLoop(ChromeThread::IO)->PostTask(FROM_HERE, + NewRunnableMethod(this, &BufferedResourceHandler::OnPluginsLoaded)); +} + +void BufferedResourceHandler::OnPluginsLoaded() { + wait_for_plugins_ = false; + 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); } |