summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-15 00:04:01 +0000
committerjam@chromium.org <jam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-08-15 00:04:01 +0000
commit35fa6a20ef621d22e6ba79e7306abad870cab4e4 (patch)
treed976dc15d9ac13976cb444cce875d5cbb790e102
parentb7a20d363af744159a2bb85bfe3db027d2d4819e (diff)
downloadchromium_src-35fa6a20ef621d22e6ba79e7306abad870cab4e4.zip
chromium_src-35fa6a20ef621d22e6ba79e7306abad870cab4e4.tar.gz
chromium_src-35fa6a20ef621d22e6ba79e7306abad870cab4e4.tar.bz2
Ensure we don't load plugins on the IO thread.
I had to move the locks from PluginService to PluginList, so that a lock (which can block other threads) isn't held while loading the plugins. BUG=17938 TEST=added asserts which crash if plugins loaded on IO thread, current UI tests exercise them Review URL: http://codereview.chromium.org/164305 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@23501 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/metrics/metrics_service.cc23
-rw-r--r--chrome/browser/metrics/metrics_service.h7
-rw-r--r--chrome/browser/plugin_service.cc43
-rw-r--r--chrome/browser/plugin_service.h17
-rw-r--r--chrome/browser/renderer_host/buffered_resource_handler.cc146
-rw-r--r--chrome/browser/renderer_host/buffered_resource_handler.h18
-rw-r--r--chrome/browser/renderer_host/resource_dispatcher_host.cc54
-rw-r--r--chrome/browser/renderer_host/resource_dispatcher_host.h8
-rw-r--r--chrome/browser/renderer_host/resource_handler.h6
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.cc24
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.h4
-rw-r--r--chrome/common/chrome_plugin_lib.cc17
-rw-r--r--chrome/common/render_messages_internal.h4
-rw-r--r--chrome/renderer/renderer_glue.cc5
-rw-r--r--webkit/glue/plugins/plugin_lib.cc2
-rw-r--r--webkit/glue/plugins/plugin_list.cc105
-rw-r--r--webkit/glue/plugins/plugin_list.h50
-rw-r--r--webkit/glue/plugins/plugin_list_linux.cc10
-rw-r--r--webkit/glue/plugins/plugin_list_mac.mm14
-rw-r--r--webkit/glue/plugins/plugin_list_win.cc59
-rw-r--r--webkit/glue/webkit_glue.h2
-rw-r--r--webkit/glue/webkitclient_impl.cc3
-rw-r--r--webkit/tools/test_shell/test_shell_gtk.cc4
-rw-r--r--webkit/tools/test_shell/test_shell_mac.mm4
-rw-r--r--webkit/tools/test_shell/test_shell_win.cc4
-rw-r--r--webkit/tools/test_shell/test_worker/test_worker_main.cc3
26 files changed, 339 insertions, 297 deletions
diff --git a/chrome/browser/metrics/metrics_service.cc b/chrome/browser/metrics/metrics_service.cc
index ae4330d..71b162c 100644
--- a/chrome/browser/metrics/metrics_service.cc
+++ b/chrome/browser/metrics/metrics_service.cc
@@ -181,7 +181,6 @@
#include "chrome/browser/browser_process.h"
#include "chrome/browser/load_notification_details.h"
#include "chrome/browser/memory_details.h"
-#include "chrome/browser/plugin_service.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/renderer_host/render_process_host.h"
#include "chrome/browser/search_engines/template_url.h"
@@ -197,6 +196,7 @@
#include "chrome/common/render_messages.h"
#include "googleurl/src/gurl.h"
#include "net/base/load_flags.h"
+#include "webkit/glue/plugins/plugin_list.h"
#if defined(OS_POSIX)
// TODO(port): Move these headers above as they are ported.
@@ -288,9 +288,15 @@ class MetricsMemoryDetails : public MemoryDetails {
};
class MetricsService::GetPluginListTaskComplete : public Task {
+ public:
+ explicit GetPluginListTaskComplete(
+ const std::vector<WebPluginInfo>& plugins) : plugins_(plugins) { }
virtual void Run() {
- g_browser_process->metrics_service()->OnGetPluginListTaskComplete();
+ g_browser_process->metrics_service()->OnGetPluginListTaskComplete(plugins_);
}
+
+ private:
+ std::vector<WebPluginInfo> plugins_;
};
class MetricsService::GetPluginListTask : public Task {
@@ -300,9 +306,10 @@ class MetricsService::GetPluginListTask : public Task {
virtual void Run() {
std::vector<WebPluginInfo> plugins;
- PluginService::GetInstance()->GetPlugins(false, &plugins);
+ NPAPI::PluginList::Singleton()->GetPlugins(false, &plugins);
- callback_loop_->PostTask(FROM_HERE, new GetPluginListTaskComplete());
+ callback_loop_->PostTask(
+ FROM_HERE, new GetPluginListTaskComplete(plugins));
}
private:
@@ -751,8 +758,10 @@ void MetricsService::InitializeMetricsState() {
ScheduleNextStateSave();
}
-void MetricsService::OnGetPluginListTaskComplete() {
+void MetricsService::OnGetPluginListTaskComplete(
+ const std::vector<WebPluginInfo>& plugins) {
DCHECK(state_ == PLUGIN_LIST_REQUESTED);
+ plugins_ = plugins;
if (state_ == PLUGIN_LIST_REQUESTED)
state_ = PLUGIN_LIST_ARRIVED;
}
@@ -1122,11 +1131,9 @@ bool MetricsService::TransmissionPermitted() const {
void MetricsService::PrepareInitialLog() {
DCHECK(state_ == PLUGIN_LIST_ARRIVED);
- std::vector<WebPluginInfo> plugins;
- PluginService::GetInstance()->GetPlugins(false, &plugins);
MetricsLog* log = new MetricsLog(client_id_, session_id_);
- log->RecordEnvironment(plugins, profile_dictionary_.get());
+ log->RecordEnvironment(plugins_, profile_dictionary_.get());
// Histograms only get written to current_log_, so setup for the write.
MetricsLog* save_log = current_log_;
diff --git a/chrome/browser/metrics/metrics_service.h b/chrome/browser/metrics/metrics_service.h
index e173915..76fc303 100644
--- a/chrome/browser/metrics/metrics_service.h
+++ b/chrome/browser/metrics/metrics_service.h
@@ -21,7 +21,7 @@
#include "chrome/browser/metrics/metrics_log.h"
#include "chrome/browser/net/url_fetcher.h"
#include "chrome/common/notification_registrar.h"
-#include "webkit/glue/webplugin.h"
+#include "webkit/glue/webplugininfo.h"
#include "testing/gtest/include/gtest/gtest_prod.h"
class BookmarkModel;
@@ -99,7 +99,7 @@ class MetricsService : public NotificationObserver,
void RecordBreakpadHasDebugger(bool has_debugger);
// Callback to let us knew that the plugin list is warmed up.
- void OnGetPluginListTaskComplete();
+ void OnGetPluginListTaskComplete(const std::vector<WebPluginInfo>& plugins);
// Save any unsent logs into a persistent store in a pref. We always do this
// at shutdown, but we can do it as we reduce the list as well.
@@ -402,6 +402,9 @@ class MetricsService : public NotificationObserver,
// state.
State state_;
+ // The list of plugins which was retrieved on the file thread.
+ std::vector<WebPluginInfo> plugins_;
+
// A log that we are currently transmiting, or about to try to transmit.
MetricsLog* pending_log_;
diff --git a/chrome/browser/plugin_service.cc b/chrome/browser/plugin_service.cc
index d9d3e65..fe6dfa6 100644
--- a/chrome/browser/plugin_service.cc
+++ b/chrome/browser/plugin_service.cc
@@ -40,8 +40,10 @@ PluginService::PluginService()
// Load the one specified on the command line as well.
const CommandLine* command_line = CommandLine::ForCurrentProcess();
std::wstring path = command_line->GetSwitchValue(switches::kLoadPlugin);
- if (!path.empty())
- NPAPI::PluginList::AddExtraPluginPath(FilePath::FromWStringHack(path));
+ if (!path.empty()) {
+ NPAPI::PluginList::Singleton()->AddExtraPluginPath(
+ FilePath::FromWStringHack(path));
+ }
#if defined(OS_WIN)
hkcu_key_.Create(
@@ -75,12 +77,6 @@ PluginService::~PluginService() {
#endif
}
-void PluginService::GetPlugins(bool refresh,
- std::vector<WebPluginInfo>* plugins) {
- AutoLock lock(lock_);
- NPAPI::PluginList::Singleton()->GetPlugins(refresh, plugins);
-}
-
void PluginService::LoadChromePlugins(
ResourceDispatcherHost* resource_dispatcher_host) {
resource_dispatcher_host_ = resource_dispatcher_host;
@@ -88,12 +84,10 @@ void PluginService::LoadChromePlugins(
}
void PluginService::SetChromePluginDataDir(const FilePath& data_dir) {
- AutoLock lock(lock_);
chrome_plugin_data_dir_ = data_dir;
}
const FilePath& PluginService::GetChromePluginDataDir() {
- AutoLock lock(lock_);
return chrome_plugin_data_dir_;
}
@@ -132,7 +126,8 @@ PluginProcessHost* PluginService::FindOrStartPluginProcess(
return plugin_host;
WebPluginInfo info;
- if (!GetPluginInfoByPath(plugin_path, &info)) {
+ if (!NPAPI::PluginList::Singleton()->GetPluginInfoByPath(
+ plugin_path, &info)) {
DCHECK(false);
return NULL;
}
@@ -179,7 +174,6 @@ FilePath PluginService::GetPluginPath(const GURL& url,
const std::string& mime_type,
const std::string& clsid,
std::string* actual_mime_type) {
- AutoLock lock(lock_);
bool allow_wildcard = true;
WebPluginInfo info;
if (NPAPI::PluginList::Singleton()->GetPluginInfo(url, mime_type, clsid,
@@ -192,23 +186,6 @@ FilePath PluginService::GetPluginPath(const GURL& url,
return FilePath();
}
-bool PluginService::GetPluginInfoByPath(const FilePath& plugin_path,
- WebPluginInfo* info) {
- AutoLock lock(lock_);
- return NPAPI::PluginList::Singleton()->GetPluginInfoByPath(plugin_path, info);
-}
-
-bool PluginService::HavePluginFor(const std::string& mime_type,
- bool allow_wildcard) {
- AutoLock lock(lock_);
-
- GURL url;
- WebPluginInfo info;
- return NPAPI::PluginList::Singleton()->GetPluginInfo(url, mime_type, "",
- allow_wildcard, &info,
- NULL);
-}
-
void PluginService::OnWaitableEventSignaled(base::WaitableEvent* waitable_event) {
#if defined(OS_WIN)
if (waitable_event == hkcu_event_.get()) {
@@ -217,8 +194,7 @@ void PluginService::OnWaitableEventSignaled(base::WaitableEvent* waitable_event)
hklm_key_.StartWatching();
}
- AutoLock lock(lock_);
- NPAPI::PluginList::ResetPluginsLoaded();
+ NPAPI::PluginList::Singleton()->ResetPluginsLoaded();
for (RenderProcessHost::iterator it = RenderProcessHost::begin();
it != RenderProcessHost::end(); ++it) {
@@ -242,9 +218,8 @@ void PluginService::Observe(NotificationType type,
extension != extensions->end(); ++extension) {
for (size_t i = 0; i < (*extension)->plugins().size(); ++i ) {
const Extension::PluginInfo& plugin = (*extension)->plugins()[i];
- AutoLock lock(lock_);
- NPAPI::PluginList::ResetPluginsLoaded();
- NPAPI::PluginList::AddExtraPluginPath(plugin.path);
+ NPAPI::PluginList::Singleton()->ResetPluginsLoaded();
+ NPAPI::PluginList::Singleton()->AddExtraPluginPath(plugin.path);
if (!plugin.is_public)
private_plugins_[plugin.path] = (*extension)->url();
}
diff --git a/chrome/browser/plugin_service.h b/chrome/browser/plugin_service.h
index 8bcbf7c..6933895 100644
--- a/chrome/browser/plugin_service.h
+++ b/chrome/browser/plugin_service.h
@@ -12,7 +12,6 @@
#include "base/basictypes.h"
#include "base/hash_tables.h"
-#include "base/lock.h"
#include "base/ref_counted.h"
#include "base/singleton.h"
#include "base/waitable_event_watcher.h"
@@ -36,8 +35,8 @@ class URLRequestContext;
class ResourceDispatcherHost;
class ResourceMessageFilter;
-// This can be called on the main thread and IO thread. However it must
-// be created on the main thread.
+// This must be created on the main thread but it's only called on the IO/file
+// thread.
class PluginService
: public base::WaitableEventWatcher::Delegate,
public NotificationObserver {
@@ -45,9 +44,6 @@ class PluginService
// Returns the PluginService singleton.
static PluginService* GetInstance();
- // Gets the list of available plugins.
- void GetPlugins(bool refresh, std::vector<WebPluginInfo>* plugins);
-
// Load all the plugins that should be loaded for the lifetime of the browser
// (ie, with the LoadOnStartup flag set).
void LoadChromePlugins(ResourceDispatcherHost* resource_dispatcher_host);
@@ -82,8 +78,6 @@ class PluginService
const std::wstring& locale,
IPC::Message* reply_msg);
- bool HavePluginFor(const std::string& mime_type, bool allow_wildcard);
-
// Get the path to the plugin specified. policy_url is the URL of the page
// requesting the plugin, so we can verify whether the plugin is allowed
// on that page.
@@ -115,9 +109,6 @@ class PluginService
virtual void Observe(NotificationType type, const NotificationSource& source,
const NotificationDetails& details);
- // Get plugin info by matching full path.
- bool GetPluginInfoByPath(const FilePath& plugin_path, WebPluginInfo* info);
-
// Returns true if the given plugin is allowed to be used by a page with
// the given URL.
bool PluginAllowedForURL(const FilePath& plugin_path, const GURL& url);
@@ -143,10 +134,6 @@ class PluginService
typedef base::hash_map<FilePath, GURL> PrivatePluginMap;
PrivatePluginMap private_plugins_;
- // Need synchronization whenever we access the plugin_list singelton through
- // webkit_glue since this class is called on the main and IO thread.
- Lock lock_;
-
NotificationRegistrar registrar_;
#if defined(OS_WIN)
diff --git a/chrome/browser/renderer_host/buffered_resource_handler.cc b/chrome/browser/renderer_host/buffered_resource_handler.cc
index b1007fe..35b8b85 100644
--- a/chrome/browser/renderer_host/buffered_resource_handler.cc
+++ b/chrome/browser/renderer_host/buffered_resource_handler.cc
@@ -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 @@ BufferedResourceHandler::BufferedResourceHandler(ResourceHandler* handler,
bytes_read_(0),
sniff_content_(false),
should_buffer_(false),
+ wait_for_plugins_(false),
buffering_(false),
finished_(false) {
}
@@ -75,7 +79,6 @@ bool BufferedResourceHandler::OnResponseStarted(int request_id,
return true;
}
-
bool BufferedResourceHandler::OnResponseCompleted(
int request_id,
const URLRequestStatus& status,
@@ -83,6 +86,11 @@ bool BufferedResourceHandler::OnResponseCompleted(
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 @@ 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 +180,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 +204,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 +240,29 @@ 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_)
+ return true;
+
return false;
}
@@ -238,16 +271,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 +320,97 @@ 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;
+ // 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);
}
diff --git a/chrome/browser/renderer_host/buffered_resource_handler.h b/chrome/browser/renderer_host/buffered_resource_handler.h
index 3799b99..1a0af52 100644
--- a/chrome/browser/renderer_host/buffered_resource_handler.h
+++ b/chrome/browser/renderer_host/buffered_resource_handler.h
@@ -30,6 +30,7 @@ class BufferedResourceHandler : public ResourceHandler {
bool OnResponseCompleted(int request_id,
const URLRequestStatus& status,
const std::string& security_info);
+ void OnRequestClosed();
private:
// Returns true if we should delay OnResponseStarted forwarding.
@@ -49,6 +50,22 @@ class BufferedResourceHandler : public ResourceHandler {
// this is invoked from |OnResponseCompleted|.
bool CompleteResponseStarted(int request_id, bool in_complete);
+ // Returns true if we have to wait until the plugin list is generated.
+ bool ShouldWaitForPlugins();
+
+ // A test to determining whether the request should be forwarded to the
+ // download thread. If need_plugin_list was passed in and was set to true,
+ // that means that the check couldn't be fully done because the plugins aren't
+ // loaded. The function should be called again after the plugin list is
+ // loaded.
+ bool ShouldDownload(bool* need_plugin_list);
+
+ // Called on the file thread to load the list of plugins.
+ void LoadPlugins();
+
+ // Called on the IO thread once the list of plugins has been loaded.
+ void OnPluginsLoaded();
+
scoped_refptr<ResourceHandler> real_handler_;
scoped_refptr<ResourceResponse> response_;
ResourceDispatcherHost* host_;
@@ -59,6 +76,7 @@ class BufferedResourceHandler : public ResourceHandler {
int bytes_read_;
bool sniff_content_;
bool should_buffer_;
+ bool wait_for_plugins_;
bool buffering_;
bool finished_;
diff --git a/chrome/browser/renderer_host/resource_dispatcher_host.cc b/chrome/browser/renderer_host/resource_dispatcher_host.cc
index b71f64f..9b32684 100644
--- a/chrome/browser/renderer_host/resource_dispatcher_host.cc
+++ b/chrome/browser/renderer_host/resource_dispatcher_host.cc
@@ -254,7 +254,6 @@ ResourceDispatcherHost::ResourceDispatcherHost(MessageLoop* io_loop)
safe_browsing_(new SafeBrowsingService),
webkit_thread_(new WebKitThread),
request_id_(-1),
- plugin_service_(PluginService::GetInstance()),
ALLOW_THIS_IN_INITIALIZER_LIST(method_runner_(this)),
is_shutdown_(false),
max_outstanding_requests_cost_per_process_(
@@ -466,7 +465,7 @@ void ResourceDispatcherHost::BeginRequest(
// requests. Does nothing if they are already loaded.
// TODO(mpcomplete): This takes 200 ms! Investigate parallelizing this by
// starting the load earlier in a BG thread.
- plugin_service_->LoadChromePlugins(this);
+ PluginService::GetInstance()->LoadChromePlugins(this);
// Construct the event handler.
scoped_refptr<ResourceHandler> handler;
@@ -666,7 +665,7 @@ void ResourceDispatcherHost::BeginDownload(const GURL& url,
// Ensure the Chrome plugins are loaded, as they may intercept network
// requests. Does nothing if they are already loaded.
- plugin_service_->LoadChromePlugins(this);
+ PluginService::GetInstance()->LoadChromePlugins(this);
URLRequest* request = new URLRequest(url, this);
request_id_--;
@@ -732,7 +731,7 @@ void ResourceDispatcherHost::BeginSaveFile(const GURL& url,
// Ensure the Chrome plugins are loaded, as they may intercept network
// requests. Does nothing if they are already loaded.
- plugin_service_->LoadChromePlugins(this);
+ PluginService::GetInstance()->LoadChromePlugins(this);
scoped_refptr<ResourceHandler> handler =
new SaveFileResourceHandler(process_id,
@@ -1258,53 +1257,6 @@ void ResourceDispatcherHost::BeginRequestInternal(URLRequest* request) {
}
}
-// This test mirrors the decision that WebKit makes in
-// WebFrameLoaderClient::dispatchDecidePolicyForMIMEType.
-// static.
-bool ResourceDispatcherHost::ShouldDownload(
- const std::string& mime_type, const std::string& content_disposition) {
- std::string type = StringToLowerASCII(mime_type);
- std::string disposition = StringToLowerASCII(content_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;
-
- // Finally, check the plugin service.
- bool allow_wildcard = false;
- return !plugin_service_->HavePluginFor(type, allow_wildcard);
-}
-
bool ResourceDispatcherHost::PauseRequestIfNeeded(ExtraRequestInfo* info) {
if (info->pause_count > 0)
info->is_paused = true;
diff --git a/chrome/browser/renderer_host/resource_dispatcher_host.h b/chrome/browser/renderer_host/resource_dispatcher_host.h
index 5353562..e36e97f 100644
--- a/chrome/browser/renderer_host/resource_dispatcher_host.h
+++ b/chrome/browser/renderer_host/resource_dispatcher_host.h
@@ -108,6 +108,7 @@ class ResourceDispatcherHost : public URLRequest::Delegate {
has_started_reading(false),
paused_read_bytes(0) {
}
+ virtual ~ExtraRequestInfo() { resource_handler->OnRequestClosed(); }
// Top-level ResourceHandler servicing this request.
scoped_refptr<ResourceHandler> resource_handler;
@@ -352,11 +353,6 @@ class ResourceDispatcherHost : public URLRequest::Delegate {
// Retrieves a URLRequest. Must be called from the IO thread.
URLRequest* GetURLRequest(GlobalRequestID request_id) const;
- // A test to determining whether a given request should be forwarded to the
- // download thread.
- bool ShouldDownload(const std::string& mime_type,
- const std::string& content_disposition);
-
// Notifies our observers that a request has been cancelled.
void NotifyResponseCompleted(URLRequest* request, int process_id);
@@ -551,8 +547,6 @@ class ResourceDispatcherHost : public URLRequest::Delegate {
// List of objects observing resource dispatching.
ObserverList<Observer> observer_list_;
- PluginService* plugin_service_;
-
// For running tasks.
ScopedRunnableMethodFactory<ResourceDispatcherHost> method_runner_;
diff --git a/chrome/browser/renderer_host/resource_handler.h b/chrome/browser/renderer_host/resource_handler.h
index 76851b6..39a85fa 100644
--- a/chrome/browser/renderer_host/resource_handler.h
+++ b/chrome/browser/renderer_host/resource_handler.h
@@ -52,7 +52,7 @@ struct ResourceResponse : public base::RefCounted<ResourceResponse> {
// The resource dispatcher host uses this interface to push load events to the
// renderer, allowing for differences in the types of IPC messages generated.
// See the implementations of this interface defined below.
-class ResourceHandler : public base::RefCounted<ResourceHandler> {
+class ResourceHandler : public base::RefCountedThreadSafe<ResourceHandler> {
public:
virtual ~ResourceHandler() {}
@@ -93,6 +93,10 @@ class ResourceHandler : public base::RefCounted<ResourceHandler> {
virtual bool OnResponseCompleted(int request_id,
const URLRequestStatus& status,
const std::string& security_info) = 0;
+
+ // Signals that the request is closed (i.e. finished successfully, cancelled).
+ // This is a signal that the associated URLRequest isn't valid anymore.
+ virtual void OnRequestClosed() { }
};
#endif // CHROME_BROWSER_RENDERER_HOST_RESOURCE_HANDLER_H_
diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc
index d817aa7..f47db7d 100644
--- a/chrome/browser/renderer_host/resource_message_filter.cc
+++ b/chrome/browser/renderer_host/resource_message_filter.cc
@@ -44,6 +44,7 @@
#include "net/http/http_cache.h"
#include "net/http/http_transaction_factory.h"
#include "net/url_request/url_request_context.h"
+#include "webkit/glue/plugins/plugin_list.h"
#include "webkit/glue/webkit_glue.h"
#include "webkit/glue/webplugin.h"
@@ -282,13 +283,12 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& msg) {
IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWidget, OnMsgCreateWidget)
IPC_MESSAGE_HANDLER(ViewHostMsg_SetCookie, OnSetCookie)
IPC_MESSAGE_HANDLER(ViewHostMsg_GetCookies, OnGetCookies)
- IPC_MESSAGE_HANDLER(ViewHostMsg_GetDataDir, OnGetDataDir)
IPC_MESSAGE_HANDLER(ViewHostMsg_PluginMessage, OnPluginMessage)
IPC_MESSAGE_HANDLER(ViewHostMsg_PluginSyncMessage, OnPluginSyncMessage)
#if defined(OS_WIN) // This hack is Windows-specific.
IPC_MESSAGE_HANDLER(ViewHostMsg_LoadFont, OnLoadFont)
#endif
- IPC_MESSAGE_HANDLER(ViewHostMsg_GetPlugins, OnGetPlugins)
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_GetPlugins, OnGetPlugins)
IPC_MESSAGE_HANDLER(ViewHostMsg_GetPluginPath, OnGetPluginPath)
IPC_MESSAGE_HANDLER(ViewHostMsg_DownloadUrl, OnDownloadUrl)
IPC_MESSAGE_HANDLER_GENERIC(ViewHostMsg_ContextMenu,
@@ -463,10 +463,6 @@ void ResourceMessageFilter::OnGetCookies(const GURL& url,
*cookies = context->cookie_store()->GetCookies(url);
}
-void ResourceMessageFilter::OnGetDataDir(std::wstring* data_dir) {
- *data_dir = plugin_service_->GetChromePluginDataDir().ToWStringHack();
-}
-
void ResourceMessageFilter::OnPluginMessage(const FilePath& plugin_path,
const std::vector<uint8>& data) {
DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
@@ -545,8 +541,20 @@ void ResourceMessageFilter::OnLoadFont(LOGFONT font) {
#endif
void ResourceMessageFilter::OnGetPlugins(bool refresh,
- std::vector<WebPluginInfo>* plugins) {
- plugin_service_->GetPlugins(refresh, plugins);
+ IPC::Message* reply_msg) {
+ ChromeThread::GetMessageLoop(ChromeThread::FILE)->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &ResourceMessageFilter::OnGetPluginsOnFileThread,
+ refresh, reply_msg));
+}
+
+void ResourceMessageFilter::OnGetPluginsOnFileThread(bool refresh,
+ IPC::Message* reply_msg) {
+ std::vector<WebPluginInfo> plugins;
+ NPAPI::PluginList::Singleton()->GetPlugins(refresh, &plugins);
+
+ ViewHostMsg_GetPlugins::WriteReplyParams(reply_msg, plugins);
+ ChromeThread::GetMessageLoop(ChromeThread::IO)->PostTask(FROM_HERE,
+ NewRunnableMethod(this, &ResourceMessageFilter::Send, reply_msg));
}
void ResourceMessageFilter::OnGetPluginPath(const GURL& url,
diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h
index e435bac..40209a9 100644
--- a/chrome/browser/renderer_host/resource_message_filter.h
+++ b/chrome/browser/renderer_host/resource_message_filter.h
@@ -119,7 +119,6 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
void OnGetCookies(const GURL& url,
const GURL& first_party_for_cookies,
std::string* cookies);
- void OnGetDataDir(std::wstring* data_dir);
void OnPluginMessage(const FilePath& plugin_path,
const std::vector<uint8>& message);
void OnPluginSyncMessage(const FilePath& plugin_path,
@@ -141,7 +140,8 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
// Not handled in the IO thread on Mac.
void OnGetScreenInfo(gfx::NativeViewId window, IPC::Message* reply);
#endif
- void OnGetPlugins(bool refresh, std::vector<WebPluginInfo>* plugins);
+ void OnGetPlugins(bool refresh, IPC::Message* reply_msg);
+ void OnGetPluginsOnFileThread(bool refresh, IPC::Message* reply_msg);
void OnGetPluginPath(const GURL& url,
const GURL& policy_url,
const std::string& mime_type,
diff --git a/chrome/common/chrome_plugin_lib.cc b/chrome/common/chrome_plugin_lib.cc
index 947527f..86789a4 100644
--- a/chrome/common/chrome_plugin_lib.cc
+++ b/chrome/common/chrome_plugin_lib.cc
@@ -42,12 +42,6 @@ static PluginMap* g_loaded_libs;
static PlatformThreadId g_plugin_thread_id = 0;
static MessageLoop* g_plugin_thread_loop = NULL;
-#ifdef GEARS_STATIC_LIB
-// defined in gears/base/chrome/module_cr.cc
-CPError STDCALL Gears_CP_Initialize(CPID id, const CPBrowserFuncs *bfuncs,
- CPPluginFuncs *pfuncs);
-#endif
-
static bool IsSingleProcessMode() {
// We don't support ChromePlugins in single-process mode.
return CommandLine::ForCurrentProcess()->HasSwitch(switches::kSingleProcess);
@@ -120,9 +114,7 @@ void ChromePluginLib::RegisterPluginsWithNPAPI() {
FilePath path;
if (!PathService::Get(chrome::FILE_GEARS_PLUGIN, &path))
return;
- // Note: we can only access the NPAPI list because the PluginService has done
- // the locking for us. We should not touch it anywhere else.
- NPAPI::PluginList::AddExtraPluginPath(path);
+ NPAPI::PluginList::Singleton()->AddExtraPluginPath(path);
}
static void LogPluginLoadTime(const TimeDelta &time) {
@@ -253,13 +245,6 @@ bool ChromePluginLib::Load() {
return false;
#else
DCHECK(module_ == 0);
-#ifdef GEARS_STATIC_LIB
- FilePath path;
- if (filename_.BaseName().value().find(FILE_PATH_LITERAL("gears")) == 0) {
- CP_Initialize_ = &Gears_CP_Initialize;
- return true;
- }
-#endif
module_ = LoadLibrary(filename_.value().c_str());
if (module_ == 0)
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index 2ab7397..80e5510 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -905,10 +905,6 @@ IPC_BEGIN_MESSAGES(ViewHost)
FilePath /* filename */,
std::string /* actual mime type for url */)
- // Retrieve the data directory associated with the renderer's profile.
- IPC_SYNC_MESSAGE_CONTROL0_1(ViewHostMsg_GetDataDir,
- std::wstring /* data_dir_retval */)
-
// Allows a chrome plugin loaded in a renderer process to send arbitrary
// data to an instance of the same plugin loaded in the browser process.
IPC_MESSAGE_CONTROL2(ViewHostMsg_PluginMessage,
diff --git a/chrome/renderer/renderer_glue.cc b/chrome/renderer/renderer_glue.cc
index 12ec6fa..affb348 100644
--- a/chrome/renderer/renderer_glue.cc
+++ b/chrome/renderer/renderer_glue.cc
@@ -202,11 +202,10 @@ std::string GetUIResourceProtocol() {
return "chrome";
}
-bool GetPlugins(bool refresh, std::vector<WebPluginInfo>* plugins) {
+void GetPlugins(bool refresh, std::vector<WebPluginInfo>* plugins) {
if (!RenderThread::current()->plugin_refresh_allowed())
refresh = false;
- return RenderThread::current()->Send(new ViewHostMsg_GetPlugins(
- refresh, plugins));
+ RenderThread::current()->Send(new ViewHostMsg_GetPlugins(refresh, plugins));
}
// static factory function
diff --git a/webkit/glue/plugins/plugin_lib.cc b/webkit/glue/plugins/plugin_lib.cc
index 9e8a681..11f8675 100644
--- a/webkit/glue/plugins/plugin_lib.cc
+++ b/webkit/glue/plugins/plugin_lib.cc
@@ -36,7 +36,7 @@ PluginLib* PluginLib::CreatePluginLib(const FilePath& filename) {
WebPluginInfo info;
const PluginEntryPoints* entry_points = NULL;
- if (!PluginList::ReadPluginInfo(filename, &info, &entry_points))
+ if (!PluginList::Singleton()->ReadPluginInfo(filename, &info, &entry_points))
return NULL;
return new PluginLib(info, entry_points);
diff --git a/webkit/glue/plugins/plugin_list.cc b/webkit/glue/plugins/plugin_list.cc
index f443364..44f7428 100644
--- a/webkit/glue/plugins/plugin_list.cc
+++ b/webkit/glue/plugins/plugin_list.cc
@@ -25,49 +25,44 @@ base::LazyInstance<PluginList> g_singleton(base::LINKER_INITIALIZED);
// static
PluginList* PluginList::Singleton() {
- PluginList* singleton = g_singleton.Pointer();
- if (!singleton->plugins_loaded_) {
- singleton->LoadPlugins(false);
- DCHECK(singleton->plugins_loaded_);
- }
- return singleton;
+ return g_singleton.Pointer();
+}
+
+bool PluginList::PluginsLoaded() {
+ AutoLock lock(lock_);
+ return plugins_loaded_;
}
-// static
void PluginList::ResetPluginsLoaded() {
- // We access the singleton directly, and not through Singleton(), since
- // we don't want LoadPlugins() to be called.
- g_singleton.Pointer()->plugins_loaded_ = false;
+ AutoLock lock(lock_);
+ plugins_loaded_ = false;
}
-// static
void PluginList::AddExtraPluginPath(const FilePath& plugin_path) {
- DCHECK(!g_singleton.Pointer()->plugins_loaded_);
- g_singleton.Pointer()->extra_plugin_paths_.push_back(plugin_path);
+ AutoLock lock(lock_);
+ extra_plugin_paths_.push_back(plugin_path);
}
-// static
void PluginList::AddExtraPluginDir(const FilePath& plugin_dir) {
- DCHECK(!g_singleton.Pointer()->plugins_loaded_);
- g_singleton.Pointer()->extra_plugin_dirs_.push_back(plugin_dir);
+ AutoLock lock(lock_);
+ extra_plugin_dirs_.push_back(plugin_dir);
}
void PluginList::RegisterInternalPlugin(const PluginVersionInfo& info) {
- DCHECK(!g_singleton.Pointer()->plugins_loaded_);
- g_singleton.Pointer()->internal_plugins_.push_back(info);
+ AutoLock lock(lock_);
+ internal_plugins_.push_back(info);
}
bool PluginList::ReadPluginInfo(const FilePath &filename,
WebPluginInfo* info,
const PluginEntryPoints** entry_points) {
- // We access the singleton directly, and not through Singleton(), since
- // we might be in a LoadPlugins call and don't want to call it recursively!
- const std::vector<PluginVersionInfo>& internal_plugins =
- g_singleton.Pointer()->internal_plugins_;
- for (size_t i = 0; i < internal_plugins.size(); ++i) {
- if (filename == internal_plugins[i].path) {
- *entry_points = &internal_plugins[i].entry_points;
- return CreateWebPluginInfo(internal_plugins[i], info);
+ {
+ AutoLock lock(lock_);
+ for (size_t i = 0; i < internal_plugins_.size(); ++i) {
+ if (filename == internal_plugins_[i].path) {
+ *entry_points = &internal_plugins_[i].entry_points;
+ return CreateWebPluginInfo(internal_plugins_[i], info);
+ }
}
}
@@ -146,46 +141,60 @@ PluginList::PluginList() : plugins_loaded_(false) {
}
void PluginList::LoadPlugins(bool refresh) {
- if (plugins_loaded_ && !refresh)
- return;
-
- plugins_.clear();
- plugins_loaded_ = true;
+ // Don't want to hold the lock while loading new plugins, so we don't block
+ // other methods if they're called on other threads.
+ std::vector<FilePath> extra_plugin_paths;
+ std::vector<FilePath> extra_plugin_dirs;
+ {
+ AutoLock lock(lock_);
+ if (plugins_loaded_ && !refresh)
+ return;
+
+ extra_plugin_paths = extra_plugin_paths_;
+ extra_plugin_dirs = extra_plugin_dirs_;
+ }
base::TimeTicks start_time = base::TimeTicks::Now();
+ std::vector<WebPluginInfo> new_plugins;
+
std::vector<FilePath> directories_to_scan;
GetPluginDirectories(&directories_to_scan);
- for (size_t i = 0; i < extra_plugin_paths_.size(); ++i)
- LoadPlugin(extra_plugin_paths_[i]);
+ for (size_t i = 0; i < extra_plugin_paths.size(); ++i)
+ LoadPlugin(extra_plugin_paths[i], &new_plugins);
- for (size_t i = 0; i < extra_plugin_dirs_.size(); ++i) {
- LoadPluginsFromDir(extra_plugin_dirs_[i]);
+ for (size_t i = 0; i < extra_plugin_dirs.size(); ++i) {
+ LoadPluginsFromDir(extra_plugin_dirs[i], &new_plugins);
}
for (size_t i = 0; i < directories_to_scan.size(); ++i) {
- LoadPluginsFromDir(directories_to_scan[i]);
+ LoadPluginsFromDir(directories_to_scan[i], &new_plugins);
}
- LoadInternalPlugins();
+ LoadInternalPlugins(&new_plugins);
if (webkit_glue::IsDefaultPluginEnabled())
- LoadPlugin(FilePath(kDefaultPluginLibraryName));
+ LoadPlugin(FilePath(kDefaultPluginLibraryName), &new_plugins);
base::TimeTicks end_time = base::TimeTicks::Now();
base::TimeDelta elapsed = end_time - start_time;
DLOG(INFO) << "Loaded plugin list in " << elapsed.InMilliseconds() << " ms.";
+
+ AutoLock lock(lock_);
+ plugins_ = new_plugins;
+ plugins_loaded_ = true;
}
-void PluginList::LoadPlugin(const FilePath &path) {
+void PluginList::LoadPlugin(const FilePath &path,
+ std::vector<WebPluginInfo>* plugins) {
WebPluginInfo plugin_info;
const PluginEntryPoints* entry_points;
if (!ReadPluginInfo(path, &plugin_info, &entry_points))
return;
- if (!ShouldLoadPlugin(plugin_info))
+ if (!ShouldLoadPlugin(plugin_info, plugins))
return;
if (path.value() != kDefaultPluginLibraryName
@@ -203,7 +212,7 @@ void PluginList::LoadPlugin(const FilePath &path) {
}
}
- plugins_.push_back(plugin_info);
+ plugins->push_back(plugin_info);
}
bool PluginList::FindPlugin(const std::string& mime_type,
@@ -212,6 +221,8 @@ bool PluginList::FindPlugin(const std::string& mime_type,
WebPluginInfo* info) {
DCHECK(mime_type == StringToLowerASCII(mime_type));
+ LoadPlugins(false);
+ AutoLock lock(lock_);
for (size_t i = 0; i < plugins_.size(); ++i) {
if (SupportsType(plugins_[i], mime_type, allow_wildcard)) {
#if defined(OS_WIN)
@@ -232,6 +243,8 @@ bool PluginList::FindPlugin(const std::string& mime_type,
bool PluginList::FindPlugin(const GURL &url, std::string* actual_mime_type,
WebPluginInfo* info) {
+ LoadPlugins(false);
+ AutoLock lock(lock_);
std::string path = url.path();
std::string::size_type last_dot = path.rfind('.');
if (last_dot == std::string::npos)
@@ -286,13 +299,11 @@ bool PluginList::SupportsExtension(const WebPluginInfo& info,
}
-bool PluginList::GetPlugins(bool refresh, std::vector<WebPluginInfo>* plugins) {
- if (refresh)
- LoadPlugins(true);
+void PluginList::GetPlugins(bool refresh, std::vector<WebPluginInfo>* plugins) {
+ LoadPlugins(refresh);
+ AutoLock lock(lock_);
*plugins = plugins_;
-
- return true;
}
bool PluginList::GetPluginInfo(const GURL& url,
@@ -322,6 +333,8 @@ bool PluginList::GetPluginInfo(const GURL& url,
bool PluginList::GetPluginInfoByPath(const FilePath& plugin_path,
WebPluginInfo* info) {
+ LoadPlugins(false);
+ AutoLock lock(lock_);
for (size_t i = 0; i < plugins_.size(); ++i) {
if (plugins_[i].path == plugin_path) {
*info = plugins_[i];
diff --git a/webkit/glue/plugins/plugin_list.h b/webkit/glue/plugins/plugin_list.h
index 9faf899..4c103c0 100644
--- a/webkit/glue/plugins/plugin_list.h
+++ b/webkit/glue/plugins/plugin_list.h
@@ -11,6 +11,7 @@
#include "base/basictypes.h"
#include "base/file_path.h"
+#include "base/lock.h"
#include "webkit/glue/webplugininfo.h"
#include "webkit/glue/plugins/nphostapi.h"
@@ -66,39 +67,39 @@ struct PluginVersionInfo {
// the machine-wide and user plugin directories and loads anything that has
// the correct types. On Linux, it walks the plugin directories as well
// (e.g. /usr/lib/browser-plugins/).
+// This object is thread safe.
class PluginList {
public:
- // Gets the one instance of the PluginList. Accessing the singleton causes
- // the PluginList to look on disk for existing plugins. It does not actually
- // load libraries, that will only happen when you initialize the plugin for
- // the first time.
+ // Gets the one instance of the PluginList.
static PluginList* Singleton();
+ // Returns true iff the plugin list has been loaded already.
+ bool PluginsLoaded();
+
// Clear the plugins_loaded_ bit to force a refresh next time we retrieve
// plugins.
- static void ResetPluginsLoaded();
+ void ResetPluginsLoaded();
- // Add an extra plugin to load when we actually do the loading. This is
- // static because we want to be able to add to it without searching the disk
- // for plugins. Must be called before the plugins have been loaded.
- static void AddExtraPluginPath(const FilePath& plugin_path);
+ // Add an extra plugin to load when we actually do the loading. Must be
+ // called before the plugins have been loaded.
+ void AddExtraPluginPath(const FilePath& plugin_path);
// Same as above, but specifies a directory in which to search for plugins.
- static void AddExtraPluginDir(const FilePath& plugin_dir);
+ void AddExtraPluginDir(const FilePath& plugin_dir);
// Register an internal plugin with the specified plugin information and
// function pointers. An internal plugin must be registered before it can
// be loaded using PluginList::LoadPlugin().
- static void RegisterInternalPlugin(const PluginVersionInfo& info);
+ void RegisterInternalPlugin(const PluginVersionInfo& info);
// Creates a WebPluginInfo structure given a plugin's path. On success
// returns true, with the information being put into "info". If it's an
// internal plugin, "entry_points" is filled in as well with a
// internally-owned PluginEntryPoints pointer.
// Returns false if the library couldn't be found, or if it's not a plugin.
- static bool ReadPluginInfo(const FilePath& filename,
- WebPluginInfo* info,
- const PluginEntryPoints** entry_points);
+ bool ReadPluginInfo(const FilePath& filename,
+ WebPluginInfo* info,
+ const PluginEntryPoints** entry_points);
// Populate a WebPluginInfo from a PluginVersionInfo.
static bool CreateWebPluginInfo(const PluginVersionInfo& pvi,
@@ -108,7 +109,7 @@ class PluginList {
void Shutdown();
// Get all the plugins
- bool GetPlugins(bool refresh, std::vector<WebPluginInfo>* plugins);
+ void GetPlugins(bool refresh, std::vector<WebPluginInfo>* plugins);
// Returns true if a plugin is found for the given url and mime type.
// The mime type which corresponds to the URL is optionally returned
@@ -128,7 +129,8 @@ class PluginList {
WebPluginInfo* info);
// Load a specific plugin with full path.
- void LoadPlugin(const FilePath& filename);
+ void LoadPlugin(const FilePath& filename,
+ std::vector<WebPluginInfo>* plugins);
private:
// Constructors are private for singletons
@@ -138,13 +140,17 @@ class PluginList {
void LoadPlugins(bool refresh);
// Load all plugins from a specific directory
- void LoadPluginsFromDir(const FilePath& path);
+ void LoadPluginsFromDir(const FilePath& path,
+ std::vector<WebPluginInfo>* plugins);
// Returns true if we should load the given plugin, or false otherwise.
- bool ShouldLoadPlugin(const WebPluginInfo& info);
+ // plugins is the list of plugins we have crawled in the current plugin
+ // loading run.
+ bool ShouldLoadPlugin(const WebPluginInfo& info,
+ std::vector<WebPluginInfo>* plugins);
// Load internal plugins.
- void LoadInternalPlugins();
+ void LoadInternalPlugins(std::vector<WebPluginInfo>* plugins);
// Find a plugin by mime type, and clsid.
// If clsid is empty, we will just find the plugin that supports mime type.
@@ -216,9 +222,13 @@ class PluginList {
// Holds information about internal plugins.
std::vector<PluginVersionInfo> internal_plugins_;
+ // Need synchronization for the above members since this object can be
+ // accessed on multiple threads.
+ Lock lock_;
+
friend struct base::DefaultLazyInstanceTraits<PluginList>;
- DISALLOW_EVIL_CONSTRUCTORS(PluginList);
+ DISALLOW_COPY_AND_ASSIGN(PluginList);
};
} // namespace NPAPI
diff --git a/webkit/glue/plugins/plugin_list_linux.cc b/webkit/glue/plugins/plugin_list_linux.cc
index 0d9b577..2a92bbd 100644
--- a/webkit/glue/plugins/plugin_list_linux.cc
+++ b/webkit/glue/plugins/plugin_list_linux.cc
@@ -44,7 +44,8 @@ void PluginList::GetPluginDirectories(std::vector<FilePath>* plugin_dirs) {
plugin_dirs->push_back(FilePath("/usr/lib/mozilla/plugins"));
}
-void PluginList::LoadPluginsFromDir(const FilePath& path) {
+void PluginList::LoadPluginsFromDir(const FilePath& path,
+ std::vector<WebPluginInfo>* plugins) {
file_util::FileEnumerator enumerator(path,
false, // not recursive
file_util::FileEnumerator::FILES);
@@ -52,11 +53,12 @@ void PluginList::LoadPluginsFromDir(const FilePath& path) {
path = enumerator.Next()) {
// Skip over Mozilla .xpt files.
if (!path.MatchesExtension(FILE_PATH_LITERAL(".xpt")))
- LoadPlugin(path);
+ LoadPlugin(path, plugins);
}
}
-bool PluginList::ShouldLoadPlugin(const WebPluginInfo& info) {
+bool PluginList::ShouldLoadPlugin(const WebPluginInfo& info,
+ std::vector<WebPluginInfo>* plugins) {
// The equivalent Windows code verifies we haven't loaded a newer version
// of the same plugin, and then blacklists some known bad plugins.
// The equivalent Mac code verifies that plugins encountered first in the
@@ -66,7 +68,7 @@ bool PluginList::ShouldLoadPlugin(const WebPluginInfo& info) {
return true;
}
-void PluginList::LoadInternalPlugins() {
+void PluginList::LoadInternalPlugins(std::vector<WebPluginInfo>* plugins) {
// none for now
}
diff --git a/webkit/glue/plugins/plugin_list_mac.mm b/webkit/glue/plugins/plugin_list_mac.mm
index 5e8d250..c3d216f 100644
--- a/webkit/glue/plugins/plugin_list_mac.mm
+++ b/webkit/glue/plugins/plugin_list_mac.mm
@@ -56,17 +56,19 @@ void PluginList::GetPluginDirectories(std::vector<FilePath>* plugin_dirs) {
GetPluginPrivateDirectory(plugin_dirs);
}
-void PluginList::LoadPluginsFromDir(const FilePath &path) {
+void PluginList::LoadPluginsFromDir(const FilePath &path,
+ std::vector<WebPluginInfo>* plugins) {
file_util::FileEnumerator enumerator(path,
false, // not recursive
file_util::FileEnumerator::DIRECTORIES);
for (FilePath path = enumerator.Next(); !path.value().empty();
path = enumerator.Next()) {
- LoadPlugin(path);
+ LoadPlugin(path, plugins);
}
}
-bool PluginList::ShouldLoadPlugin(const WebPluginInfo& info) {
+bool PluginList::ShouldLoadPlugin(const WebPluginInfo& info,
+ std::vector<WebPluginInfo>* plugins) {
// The Gears plugin is Safari-specific, and causes crashes, so don't load it.
for (std::vector<WebPluginMimeType>::const_iterator i =
info.mime_types.begin(); i != info.mime_types.end(); ++i) {
@@ -87,8 +89,8 @@ bool PluginList::ShouldLoadPlugin(const WebPluginInfo& info) {
// Hierarchy check
// (we're loading plugins hierarchically from Library folders, so plugins we
// encounter earlier must override plugins we encounter later)
- for (size_t i = 0; i < plugins_.size(); ++i) {
- if (plugins_[i].path.BaseName() == info.path.BaseName()) {
+ for (size_t i = 0; i < plugins->size(); ++i) {
+ if ((*plugins)[i].path.BaseName() == info.path.BaseName()) {
return false; // We already have a loaded plugin higher in the hierarchy.
}
}
@@ -96,7 +98,7 @@ bool PluginList::ShouldLoadPlugin(const WebPluginInfo& info) {
return true;
}
-void PluginList::LoadInternalPlugins() {
+void PluginList::LoadInternalPlugins(std::vector<WebPluginInfo>* plugins) {
// none for now
}
diff --git a/webkit/glue/plugins/plugin_list_win.cc b/webkit/glue/plugins/plugin_list_win.cc
index 94104c8..b92e2f2 100644
--- a/webkit/glue/plugins/plugin_list_win.cc
+++ b/webkit/glue/plugins/plugin_list_win.cc
@@ -39,13 +39,6 @@ const TCHAR kRegistryBrowserJavaVersion[] = _T("BrowserJavaVersion");
const TCHAR kRegistryCurrentJavaVersion[] = _T("CurrentVersion");
const TCHAR kRegistryJavaHome[] = _T("JavaHome");
-#ifdef GEARS_STATIC_LIB
-// defined in gears/base/common/module.cc
-NPError API_CALL Gears_NP_GetEntryPoints(NPPluginFuncs* funcs);
-NPError API_CALL Gears_NP_Initialize(NPNetscapeFuncs* funcs);
-NPError API_CALL Gears_NP_Shutdown(void);
-#endif
-
// The application path where we expect to find plugins.
void GetAppDirectory(std::set<FilePath>* plugin_dirs) {
std::wstring app_path;
@@ -226,22 +219,6 @@ void PluginList::PlatformInit() {
activex_shim::ActiveX_Shim_NP_Shutdown
}
},
-#ifdef GEARS_STATIC_LIB
- {
- FilePath(kGearsPluginLibraryName),
- L"Gears",
- L"Statically linked Gears",
- L"1, 0, 0, 1",
- L"application/x-googlegears",
- L"",
- L"",
- {
- Gears_NP_GetEntryPoints,
- Gears_NP_Initialize,
- Gears_NP_Shutdown
- }
- },
-#endif
};
for (int i = 0; i < arraysize(builtin_plugins); ++i)
@@ -275,7 +252,8 @@ void PluginList::GetPluginDirectories(std::vector<FilePath>* plugin_dirs) {
plugin_dirs->push_back(*i);
}
-void PluginList::LoadPluginsFromDir(const FilePath &path) {
+void PluginList::LoadPluginsFromDir(const FilePath &path,
+ std::vector<WebPluginInfo>* plugins) {
WIN32_FIND_DATA find_file_data;
HANDLE find_handle;
@@ -290,7 +268,7 @@ void PluginList::LoadPluginsFromDir(const FilePath &path) {
do {
if (!(find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
FilePath filename = path.Append(find_file_data.cFileName);
- LoadPlugin(filename);
+ LoadPlugin(filename, plugins);
}
} while (FindNextFile(find_handle, &find_file_data) != 0);
@@ -317,13 +295,13 @@ bool IsNewerVersion(const std::wstring& a, const std::wstring& b) {
return false;
}
-bool PluginList::ShouldLoadPlugin(const WebPluginInfo& info) {
-
+bool PluginList::ShouldLoadPlugin(const WebPluginInfo& info,
+ std::vector<WebPluginInfo>* plugins) {
// Version check
- for (size_t i = 0; i < plugins_.size(); ++i) {
- if (plugins_[i].path.BaseName() == info.path.BaseName() &&
- !IsNewerVersion(plugins_[i].version, info.version)) {
+ for (size_t i = 0; i < plugins->size(); ++i) {
+ if ((*plugins)[i].path.BaseName() == info.path.BaseName() &&
+ !IsNewerVersion((*plugins)[i].version, info.version)) {
return false; // We already have a loaded plugin whose version is newer.
}
}
@@ -360,15 +338,15 @@ bool PluginList::ShouldLoadPlugin(const WebPluginInfo& info) {
if (dont_load_new_wmp_)
return false;
- for (size_t i = 0; i < plugins_.size(); ++i) {
- if (plugins_[i].path.BaseName().value() == kOldWMPPlugin) {
- plugins_.erase(plugins_.begin() + i);
+ for (size_t i = 0; i < plugins->size(); ++i) {
+ if ((*plugins)[i].path.BaseName().value() == kOldWMPPlugin) {
+ plugins->erase(plugins->begin() + i);
break;
}
}
} else if (filename == kOldWMPPlugin) {
- for (size_t i = 0; i < plugins_.size(); ++i) {
- if (plugins_[i].path.BaseName().value() == kNewWMPPlugin)
+ for (size_t i = 0; i < plugins->size(); ++i) {
+ if ((*plugins)[i].path.BaseName().value() == kNewWMPPlugin)
return false;
}
}
@@ -377,16 +355,11 @@ bool PluginList::ShouldLoadPlugin(const WebPluginInfo& info) {
return true;
}
-void PluginList::LoadInternalPlugins() {
-#ifdef GEARS_STATIC_LIB
- LoadPlugin(FilePath(kGearsPluginLibraryName));
-#endif
-
+void PluginList::LoadInternalPlugins(std::vector<WebPluginInfo>* plugins) {
if (!use_internal_activex_shim_)
- return;
- LoadPlugin(FilePath(kActiveXShimFileName));
- LoadPlugin(FilePath(kActiveXShimFileNameForMediaPlayer));
+ LoadPlugin(FilePath(kActiveXShimFileName), plugins);
+ LoadPlugin(FilePath(kActiveXShimFileNameForMediaPlayer), plugins);
}
} // namespace NPAPI
diff --git a/webkit/glue/webkit_glue.h b/webkit/glue/webkit_glue.h
index 998fbce..686e676 100644
--- a/webkit/glue/webkit_glue.h
+++ b/webkit/glue/webkit_glue.h
@@ -174,7 +174,7 @@ std::string GetUIResourceProtocol();
bool GetExeDirectory(std::wstring* path);
// Embedders implement this function to return the list of plugins to Webkit.
-bool GetPlugins(bool refresh, std::vector<WebPluginInfo>* plugins);
+void GetPlugins(bool refresh, std::vector<WebPluginInfo>* plugins);
// Returns true if the plugins run in the same process as the renderer, and
// false otherwise.
diff --git a/webkit/glue/webkitclient_impl.cc b/webkit/glue/webkitclient_impl.cc
index afc4f80..d257d53 100644
--- a/webkit/glue/webkitclient_impl.cc
+++ b/webkit/glue/webkitclient_impl.cc
@@ -108,8 +108,7 @@ WebURLLoader* WebKitClientImpl::createURLLoader() {
void WebKitClientImpl::getPluginList(bool refresh,
WebPluginListBuilder* builder) {
std::vector<WebPluginInfo> plugins;
- if (!GetPlugins(refresh, &plugins))
- return;
+ GetPlugins(refresh, &plugins);
for (size_t i = 0; i < plugins.size(); ++i) {
const WebPluginInfo& plugin = plugins[i];
diff --git a/webkit/tools/test_shell/test_shell_gtk.cc b/webkit/tools/test_shell/test_shell_gtk.cc
index 2659f7b..cf35788 100644
--- a/webkit/tools/test_shell/test_shell_gtk.cc
+++ b/webkit/tools/test_shell/test_shell_gtk.cc
@@ -692,8 +692,8 @@ StringPiece GetDataResource(int resource_id) {
return TestShell::NetResourceProvider(resource_id);
}
-bool GetPlugins(bool refresh, std::vector<WebPluginInfo>* plugins) {
- return NPAPI::PluginList::Singleton()->GetPlugins(refresh, plugins);
+void GetPlugins(bool refresh, std::vector<WebPluginInfo>* plugins) {
+ NPAPI::PluginList::Singleton()->GetPlugins(refresh, plugins);
}
} // namespace webkit_glue
diff --git a/webkit/tools/test_shell/test_shell_mac.mm b/webkit/tools/test_shell/test_shell_mac.mm
index dff44c9..e2a9139 100644
--- a/webkit/tools/test_shell/test_shell_mac.mm
+++ b/webkit/tools/test_shell/test_shell_mac.mm
@@ -700,8 +700,8 @@ StringPiece GetDataResource(int resource_id) {
return StringPiece();
}
-bool GetPlugins(bool refresh, std::vector<WebPluginInfo>* plugins) {
- return NPAPI::PluginList::Singleton()->GetPlugins(refresh, plugins);
+void GetPlugins(bool refresh, std::vector<WebPluginInfo>* plugins) {
+ NPAPI::PluginList::Singleton()->GetPlugins(refresh, plugins);
}
bool DownloadUrl(const std::string& url, NSWindow* caller_window) {
diff --git a/webkit/tools/test_shell/test_shell_win.cc b/webkit/tools/test_shell/test_shell_win.cc
index 7c682b2..0a9e141 100644
--- a/webkit/tools/test_shell/test_shell_win.cc
+++ b/webkit/tools/test_shell/test_shell_win.cc
@@ -758,8 +758,8 @@ HCURSOR LoadCursor(int cursor_id) {
return NULL;
}
-bool GetPlugins(bool refresh, std::vector<WebPluginInfo>* plugins) {
- return NPAPI::PluginList::Singleton()->GetPlugins(refresh, plugins);
+void GetPlugins(bool refresh, std::vector<WebPluginInfo>* plugins) {
+ NPAPI::PluginList::Singleton()->GetPlugins(refresh, plugins);
}
bool EnsureFontLoaded(HFONT font) {
diff --git a/webkit/tools/test_shell/test_worker/test_worker_main.cc b/webkit/tools/test_shell/test_worker/test_worker_main.cc
index e20f772..aefbccb 100644
--- a/webkit/tools/test_shell/test_worker/test_worker_main.cc
+++ b/webkit/tools/test_shell/test_worker/test_worker_main.cc
@@ -208,8 +208,7 @@ bool SpellCheckWord(const wchar_t* word, int word_len,
return true;
}
-bool GetPlugins(bool refresh, std::vector<WebPluginInfo>* plugins) {
- return false;
+void GetPlugins(bool refresh, std::vector<WebPluginInfo>* plugins) {
}
bool IsPluginRunningInRendererProcess() {