summaryrefslogtreecommitdiffstats
path: root/content/browser
diff options
context:
space:
mode:
authorrsesek@chromium.org <rsesek@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-27 18:05:15 +0000
committerrsesek@chromium.org <rsesek@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-09-27 18:05:15 +0000
commit4912595f15ad54608207cbacaeeb085cf542e539 (patch)
tree0d32785d543ed97e3999673eda92fe81323773ef /content/browser
parent6c36f5e4b14f45fd54d60fa9abe7fc99c749eb49 (diff)
downloadchromium_src-4912595f15ad54608207cbacaeeb085cf542e539.zip
chromium_src-4912595f15ad54608207cbacaeeb085cf542e539.tar.gz
chromium_src-4912595f15ad54608207cbacaeeb085cf542e539.tar.bz2
Move plugin loading out of process on Mac and Linux.
This creates a new set of IPC messages for the utility process to load plugins to get the WebPluginInfo data in a separate process. Previously this was done in the browser process, but that involves loading arbitrary third-party code into the address space and then executing it. BUG=17863,95114 TEST=Plugins work as before. Review URL: http://codereview.chromium.org/7889025 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@102971 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'content/browser')
-rw-r--r--content/browser/plugin_service.cc95
-rw-r--r--content/browser/utility_process_host.cc15
-rw-r--r--content/browser/utility_process_host.h10
3 files changed, 111 insertions, 9 deletions
diff --git a/content/browser/plugin_service.cc b/content/browser/plugin_service.cc
index 6be232a..873e55a 100644
--- a/content/browser/plugin_service.cc
+++ b/content/browser/plugin_service.cc
@@ -23,11 +23,13 @@
#include "content/browser/renderer_host/render_process_host.h"
#include "content/browser/renderer_host/render_view_host.h"
#include "content/browser/resource_context.h"
+#include "content/browser/utility_process_host.h"
#include "content/common/content_notification_types.h"
#include "content/common/content_switches.h"
#include "content/common/notification_service.h"
#include "content/common/pepper_plugin_registry.h"
#include "content/common/plugin_messages.h"
+#include "content/common/utility_messages.h"
#include "content/common/view_messages.h"
#include "webkit/plugins/npapi/plugin_constants_win.h"
#include "webkit/plugins/npapi/plugin_group.h"
@@ -60,6 +62,76 @@ static void GetPluginsForGroupsCallback(
callback.Run(groups);
}
+// Callback set on the PluginList to assert that plugin loading happens on the
+// correct thread.
+void WillLoadPluginsCallback() {
+ // TODO(rsesek): Change these to CHECKs.
+#if defined(OS_WIN)
+ LOG_IF(ERROR, !BrowserThread::CurrentlyOn(BrowserThread::FILE));
+#else
+ LOG(ERROR) << "Plugin loading should happen out-of-process.";
+#endif
+}
+
+#if defined(OS_POSIX)
+// Utility child process client that manages the IPC for loading plugins out of
+// process.
+class PluginLoaderClient : public UtilityProcessHost::Client {
+ public:
+ // Meant to be called on the IO thread. Will invoke the callback on the target
+ // loop when the plugins have been loaded.
+ static void LoadPluginsOutOfProcess(
+ base::MessageLoopProxy* target_loop,
+ const PluginService::GetPluginsCallback& callback) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+
+ PluginLoaderClient* client = new PluginLoaderClient(target_loop, callback);
+ UtilityProcessHost* process_host =
+ new UtilityProcessHost(client, BrowserThread::IO);
+ process_host->set_no_sandbox(true);
+#if defined(OS_MACOSX)
+ process_host->set_child_flags(ChildProcessHost::CHILD_ALLOW_HEAP_EXECUTION);
+#endif
+
+ std::vector<FilePath> extra_plugin_paths;
+ std::vector<FilePath> extra_plugin_dirs;
+ std::vector<webkit::WebPluginInfo> internal_plugins;
+ webkit::npapi::PluginList::Singleton()->GetPluginPathListsToLoad(
+ &extra_plugin_paths, &extra_plugin_dirs, &internal_plugins);
+
+ process_host->Send(new UtilityMsg_LoadPlugins(
+ extra_plugin_paths, extra_plugin_dirs, internal_plugins));
+ }
+
+ virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(PluginLoaderClient, message)
+ IPC_MESSAGE_HANDLER(UtilityHostMsg_LoadedPlugins, OnGotPlugins)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+ }
+
+ virtual void OnGotPlugins(const std::vector<webkit::WebPluginInfo>& plugins) {
+ webkit::npapi::PluginList::Singleton()->SetPlugins(plugins);
+ target_loop_->PostTask(FROM_HERE,
+ base::Bind(&RunGetPluginsCallback, callback_, plugins));
+ }
+
+ private:
+ PluginLoaderClient(base::MessageLoopProxy* target_loop,
+ const PluginService::GetPluginsCallback& callback)
+ : target_loop_(target_loop),
+ callback_(callback) {
+ }
+
+ scoped_refptr<base::MessageLoopProxy> target_loop_;
+ PluginService::GetPluginsCallback callback_;
+
+ DISALLOW_COPY_AND_ASSIGN(PluginLoaderClient);
+};
+#endif // OS_POSIX
+
} // namespace
#if defined(OS_MACOSX)
@@ -97,6 +169,9 @@ PluginService::PluginService()
: ui_locale_(
content::GetContentClient()->browser()->GetApplicationLocale()),
filter_(NULL) {
+ webkit::npapi::PluginList::Singleton()->set_will_load_plugins_callback(
+ base::Bind(&WillLoadPluginsCallback));
+
RegisterPepperPlugins();
// Load any specified on the command line as well.
@@ -448,10 +523,26 @@ void PluginService::RefreshPluginList() {
}
void PluginService::GetPlugins(const GetPluginsCallback& callback) {
+ scoped_refptr<base::MessageLoopProxy> target_loop(
+ MessageLoop::current()->message_loop_proxy());
+
+#if defined(OS_WIN)
BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
base::Bind(&PluginService::GetPluginsInternal, base::Unretained(this),
- MessageLoop::current()->message_loop_proxy(),
- callback));
+ target_loop, callback));
+#else
+ std::vector<webkit::WebPluginInfo> cached_plugins;
+ if (webkit::npapi::PluginList::Singleton()->GetPluginsIfNoRefreshNeeded(
+ &cached_plugins)) {
+ // Can't assume the caller is reentrant.
+ target_loop->PostTask(FROM_HERE,
+ base::Bind(&RunGetPluginsCallback, callback, cached_plugins));
+ } else {
+ BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
+ base::Bind(&PluginLoaderClient::LoadPluginsOutOfProcess,
+ target_loop, callback));
+ }
+#endif
}
void PluginService::GetPluginGroups(const GetPluginGroupsCallback& callback) {
diff --git a/content/browser/utility_process_host.cc b/content/browser/utility_process_host.cc
index c62ec3e..d7f57f3 100644
--- a/content/browser/utility_process_host.cc
+++ b/content/browser/utility_process_host.cc
@@ -33,6 +33,12 @@ UtilityProcessHost::UtilityProcessHost(Client* client,
client_(client),
client_thread_id_(client_thread_id),
is_batch_mode_(false),
+ no_sandbox_(false),
+#if defined(OS_LINUX)
+ child_flags_(CHILD_ALLOW_SELF),
+#else
+ child_flags_(CHILD_NORMAL),
+#endif
started_(false) {
}
@@ -61,12 +67,7 @@ void UtilityProcessHost::EndBatchMode() {
}
FilePath UtilityProcessHost::GetUtilityProcessCmd() {
-#if defined(OS_LINUX)
- int flags = CHILD_ALLOW_SELF;
-#else
- int flags = CHILD_NORMAL;
-#endif
- return GetChildPath(flags);
+ return GetChildPath(child_flags_);
}
bool UtilityProcessHost::StartProcess() {
@@ -100,7 +101,7 @@ bool UtilityProcessHost::StartProcess() {
const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
if (browser_command_line.HasSwitch(switches::kChromeFrame))
cmd_line->AppendSwitch(switches::kChromeFrame);
- if (browser_command_line.HasSwitch(switches::kNoSandbox))
+ if (no_sandbox_ || browser_command_line.HasSwitch(switches::kNoSandbox))
cmd_line->AppendSwitch(switches::kNoSandbox);
#if defined(OS_POSIX)
diff --git a/content/browser/utility_process_host.h b/content/browser/utility_process_host.h
index 9018818..69389a2 100644
--- a/content/browser/utility_process_host.h
+++ b/content/browser/utility_process_host.h
@@ -63,6 +63,10 @@ class CONTENT_EXPORT UtilityProcessHost : public BrowserChildProcessHost {
void set_exposed_dir(const FilePath& dir) { exposed_dir_ = dir; }
+ void set_no_sandbox(bool flag) { no_sandbox_ = flag; }
+
+ void set_child_flags(int flags) { child_flags_ = flags; }
+
protected:
// Allow these methods to be overridden for tests.
virtual FilePath GetUtilityProcessCmd();
@@ -90,6 +94,12 @@ class CONTENT_EXPORT UtilityProcessHost : public BrowserChildProcessHost {
// the operation.
FilePath exposed_dir_;
+ // Whether to pass switches::kNoSandbox to the child.
+ bool no_sandbox_;
+
+ // Flags defined in ChildProcessHost with which to start the process.
+ int child_flags_;
+
bool started_;
DISALLOW_COPY_AND_ASSIGN(UtilityProcessHost);