summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-10 01:16:11 +0000
committerbrettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-11-10 01:16:11 +0000
commit709a847ee12e1380df59db8cd3c972ec4f9c674e (patch)
tree48217fd87c7e1fe15afdd90db26a925f7db28a1b
parentf30e74751217091c0b6050080f46cd6eb4914226 (diff)
downloadchromium_src-709a847ee12e1380df59db8cd3c972ec4f9c674e.zip
chromium_src-709a847ee12e1380df59db8cd3c972ec4f9c674e.tar.gz
chromium_src-709a847ee12e1380df59db8cd3c972ec4f9c674e.tar.bz2
Implement a new process type for running PPAPI plugins. The process itself is
quite simple and just sets up the PPAPI dispatcher and loads the library. There is a new command line switch --ppapi-out-of-process which runs PPAPI plugins out of process using the new code path. There is some logic in RenderView and PepperPluginModule for setting up this connection, but it should be straightforward. TEST=none BUG=none Review URL: http://codereview.chromium.org/3915002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@65614 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--base/base.gypi2
-rw-r--r--base/scoped_native_library.cc44
-rw-r--r--base/scoped_native_library.h36
-rw-r--r--chrome/app/chrome_dll_main.cc6
-rw-r--r--chrome/app/dummy_main_functions.cc4
-rw-r--r--chrome/browser/DEPS1
-rw-r--r--chrome/browser/ppapi_plugin_process_host.cc101
-rw-r--r--chrome/browser/ppapi_plugin_process_host.h57
-rw-r--r--chrome/browser/renderer_host/browser_render_process_host.cc3
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.cc15
-rw-r--r--chrome/browser/renderer_host/resource_message_filter.h7
-rw-r--r--chrome/chrome.gyp19
-rw-r--r--chrome/chrome_browser.gypi2
-rw-r--r--chrome/common/child_process_info.cc3
-rw-r--r--chrome/common/child_process_info.h3
-rw-r--r--chrome/common/chrome_switches.cc12
-rw-r--r--chrome/common/chrome_switches.h4
-rw-r--r--chrome/common/pepper_plugin_registry.cc27
-rw-r--r--chrome/common/pepper_plugin_registry.h17
-rw-r--r--chrome/common/render_messages_internal.h8
-rw-r--r--chrome/common/sandbox_policy.cc2
-rw-r--r--chrome/ppapi_plugin/ppapi_plugin_main.cc34
-rw-r--r--chrome/ppapi_plugin/ppapi_process.cc11
-rw-r--r--chrome/ppapi_plugin/ppapi_process.h20
-rw-r--r--chrome/ppapi_plugin/ppapi_thread.cc135
-rw-r--r--chrome/ppapi_plugin/ppapi_thread.h67
-rw-r--r--chrome/renderer/pepper_plugin_delegate_impl.cc19
-rw-r--r--chrome/renderer/pepper_plugin_delegate_impl.h5
-rw-r--r--chrome/renderer/render_view.cc11
-rw-r--r--ipc/ipc_message_utils.h2
-rw-r--r--ppapi/ppapi.gyp83
-rw-r--r--ppapi/proxy/dispatcher.cc3
-rw-r--r--ppapi/proxy/plugin_dispatcher.cc7
-rw-r--r--ppapi/proxy/ppapi_param_traits.h2
-rw-r--r--ppapi/proxy/ppb_image_data_proxy.cc8
-rw-r--r--ppapi/proxy/ppb_url_request_info_proxy.h2
-rw-r--r--ppapi/proxy/ppp_instance_proxy.cc2
-rw-r--r--ppapi/proxy/serialized_var.cc2
-rw-r--r--webkit/glue/plugins/pepper_graphics_2d.cc3
-rw-r--r--webkit/glue/plugins/pepper_plugin_module.cc64
-rw-r--r--webkit/glue/plugins/pepper_plugin_module.h28
-rw-r--r--webkit/glue/webkit_glue.gypi1
42 files changed, 843 insertions, 39 deletions
diff --git a/base/base.gypi b/base/base.gypi
index 78c97aa..ee1f5c9 100644
--- a/base/base.gypi
+++ b/base/base.gypi
@@ -198,6 +198,8 @@
'scoped_callback_factory.h',
'mac/scoped_cftyperef.h',
'scoped_handle.h',
+ 'scoped_native_library.cc',
+ 'scoped_native_library.h',
'scoped_nsobject.h',
'scoped_open_process.h',
'scoped_ptr.h',
diff --git a/base/scoped_native_library.cc b/base/scoped_native_library.cc
new file mode 100644
index 0000000..9d34449
--- /dev/null
+++ b/base/scoped_native_library.cc
@@ -0,0 +1,44 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/scoped_native_library.h"
+
+namespace base {
+
+ScopedNativeLibrary::ScopedNativeLibrary() : library_(NULL) {
+}
+
+ScopedNativeLibrary::ScopedNativeLibrary(NativeLibrary library)
+ : library_(library) {
+}
+
+ScopedNativeLibrary::ScopedNativeLibrary(const FilePath& library_path) {
+ library_ = base::LoadNativeLibrary(library_path);
+}
+
+ScopedNativeLibrary::~ScopedNativeLibrary() {
+ if (library_)
+ base::UnloadNativeLibrary(library_);
+}
+
+void* ScopedNativeLibrary::GetFunctionPointer(
+ const char* function_name) const {
+ if (!library_)
+ return NULL;
+ return base::GetFunctionPointerFromNativeLibrary(library_, function_name);
+}
+
+void ScopedNativeLibrary::Reset(NativeLibrary library) {
+ if (library_)
+ base::UnloadNativeLibrary(library_);
+ library_ = library;
+}
+
+NativeLibrary ScopedNativeLibrary::Release() {
+ NativeLibrary result = library_;
+ library_ = NULL;
+ return result;
+}
+
+} // namespace base
diff --git a/base/scoped_native_library.h b/base/scoped_native_library.h
index bed5c39..28b29b3 100644
--- a/base/scoped_native_library.h
+++ b/base/scoped_native_library.h
@@ -17,23 +17,33 @@ namespace base {
// This class automatically unloads the loaded library in its destructor.
class ScopedNativeLibrary {
public:
- explicit ScopedNativeLibrary(const FilePath& library_path) {
- library_ = base::LoadNativeLibrary(library_path);
- }
+ // Initializes with a NULL library.
+ ScopedNativeLibrary();
- ~ScopedNativeLibrary() {
- if (library_)
- base::UnloadNativeLibrary(library_);
- }
+ // Takes ownership of the given library handle.
+ explicit ScopedNativeLibrary(NativeLibrary library);
- void* GetFunctionPointer(const char* function_name) {
- if (!library_)
- return NULL;
- return base::GetFunctionPointerFromNativeLibrary(library_, function_name);
- }
+ // Opens the given library and manages its lifetime.
+ explicit ScopedNativeLibrary(const FilePath& library_path);
+
+ ~ScopedNativeLibrary();
+
+ // Returns true if there's a valid library loaded.
+ bool is_valid() const { return !!library_; }
+
+ void* GetFunctionPointer(const char* function_name) const;
+
+ // Takes ownership of the given library handle. Any existing handle will
+ // be freed.
+ void Reset(NativeLibrary library);
+
+ // Returns the native library handle and removes it from this object. The
+ // caller must manage the lifetime of the handle.
+ NativeLibrary Release();
private:
- base::NativeLibrary library_;
+ NativeLibrary library_;
+
DISALLOW_COPY_AND_ASSIGN(ScopedNativeLibrary);
};
diff --git a/chrome/app/chrome_dll_main.cc b/chrome/app/chrome_dll_main.cc
index 9af130e..04fe4b9 100644
--- a/chrome/app/chrome_dll_main.cc
+++ b/chrome/app/chrome_dll_main.cc
@@ -110,6 +110,7 @@ extern int BrowserMain(const MainFunctionParams&);
extern int RendererMain(const MainFunctionParams&);
extern int GpuMain(const MainFunctionParams&);
extern int PluginMain(const MainFunctionParams&);
+extern int PpapiPluginMain(const MainFunctionParams&);
extern int WorkerMain(const MainFunctionParams&);
extern int NaClMain(const MainFunctionParams&);
extern int UtilityMain(const MainFunctionParams&);
@@ -277,7 +278,8 @@ static void AdjustLinuxOOMScore(const std::string& process_type) {
const int kPluginScore = 10;
int score = -1;
- if (process_type == switches::kPluginProcess) {
+ if (process_type == switches::kPluginProcess ||
+ process_type == switches::kPpapiPluginProcess) {
score = kPluginScore;
} else if (process_type == switches::kUtilityProcess ||
process_type == switches::kWorkerProcess ||
@@ -843,6 +845,8 @@ int ChromeMain(int argc, char** argv) {
rv = RendererMain(main_params);
} else if (process_type == switches::kPluginProcess) {
rv = PluginMain(main_params);
+ } else if (process_type == switches::kPpapiPluginProcess) {
+ rv = PpapiPluginMain(main_params);
} else if (process_type == switches::kUtilityProcess) {
rv = UtilityMain(main_params);
} else if (process_type == switches::kGpuProcess) {
diff --git a/chrome/app/dummy_main_functions.cc b/chrome/app/dummy_main_functions.cc
index a6e325e..77867de 100644
--- a/chrome/app/dummy_main_functions.cc
+++ b/chrome/app/dummy_main_functions.cc
@@ -19,6 +19,10 @@ int PluginMain(const MainFunctionParams& parameters) {
return ResultCodes::BAD_PROCESS_TYPE;
}
+int PpapiPluginMain(const MainFunctionParams& parameters) {
+ return ResultCodes::BAD_PROCESS_TYPE;
+}
+
int WorkerMain(const MainFunctionParams& parameters) {
return ResultCodes::BAD_PROCESS_TYPE;
}
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS
index 3135229..b92e996 100644
--- a/chrome/browser/DEPS
+++ b/chrome/browser/DEPS
@@ -9,6 +9,7 @@ include_rules = [
"+chrome/views",
"+cros",
"+grit", # For generated headers
+ "+ppapi/proxy",
"+rlz",
"+sandbox/linux",
"+sandbox/src", # The path doesn't say it, but this is the Windows sandbox.
diff --git a/chrome/browser/ppapi_plugin_process_host.cc b/chrome/browser/ppapi_plugin_process_host.cc
new file mode 100644
index 0000000..8adbd30
--- /dev/null
+++ b/chrome/browser/ppapi_plugin_process_host.cc
@@ -0,0 +1,101 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ppapi_plugin_process_host.h"
+
+#include "base/command_line.h"
+#include "base/file_path.h"
+#include "base/process_util.h"
+#include "chrome/browser/renderer_host/resource_message_filter.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/render_messages.h"
+#include "ipc/ipc_channel_handle.h"
+#include "ipc/ipc_switches.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+PpapiPluginProcessHost::PpapiPluginProcessHost(ResourceMessageFilter* filter)
+ : BrowserChildProcessHost(ChildProcessInfo::PPAPI_PLUGIN_PROCESS,
+ filter->resource_dispatcher_host()),
+ filter_(filter) {
+}
+
+PpapiPluginProcessHost::~PpapiPluginProcessHost() {
+}
+
+void PpapiPluginProcessHost::Init(const FilePath& path,
+ IPC::Message* reply_msg) {
+ plugin_path_ = path;
+ reply_msg_.reset(reply_msg);
+
+ if (!CreateChannel()) {
+ ReplyToRenderer(IPC::ChannelHandle());
+ return;
+ }
+
+ const CommandLine& browser_command_line = *CommandLine::ForCurrentProcess();
+ CommandLine::StringType plugin_launcher =
+ browser_command_line.GetSwitchValueNative(switches::kPpapiPluginLauncher);
+
+ FilePath exe_path = ChildProcessHost::GetChildPath(plugin_launcher.empty());
+ if (exe_path.empty()) {
+ ReplyToRenderer(IPC::ChannelHandle());
+ return;
+ }
+
+ CommandLine* cmd_line = new CommandLine(exe_path);
+ cmd_line->AppendSwitchASCII(switches::kProcessType,
+ switches::kPpapiPluginProcess);
+ cmd_line->AppendSwitchASCII(switches::kProcessChannelID, channel_id());
+
+ if (!plugin_launcher.empty())
+ cmd_line->PrependWrapper(plugin_launcher);
+
+ Launch(
+#if defined(OS_WIN)
+ FilePath(),
+#elif defined(OS_POSIX)
+ true, base::environment_vector(),
+#endif
+ cmd_line);
+}
+
+void PpapiPluginProcessHost::OnProcessLaunched() {
+}
+
+URLRequestContext* PpapiPluginProcessHost::GetRequestContext(
+ uint32 request_id,
+ const ViewHostMsg_Resource_Request& request_data) {
+ return NULL;
+}
+
+void PpapiPluginProcessHost::OnMessageReceived(const IPC::Message& msg) {
+ IPC_BEGIN_MESSAGE_MAP(PpapiPluginProcessHost, msg)
+ IPC_MESSAGE_HANDLER(PpapiHostMsg_PluginLoaded, OnPluginLoaded)
+ IPC_MESSAGE_UNHANDLED_ERROR();
+ IPC_END_MESSAGE_MAP()
+}
+
+void PpapiPluginProcessHost::OnChannelConnected(int32 peer_pid) {
+ PpapiMsg_LoadPlugin* msg = new PpapiMsg_LoadPlugin(plugin_path_,
+ filter_->id());
+ if (!Send(msg)) // Just send an empty handle on failure.
+ ReplyToRenderer(IPC::ChannelHandle());
+ // This function will result in OnChannelCreated getting called to finish.
+}
+
+void PpapiPluginProcessHost::OnChannelError() {
+ if (reply_msg_.get())
+ ReplyToRenderer(IPC::ChannelHandle());
+}
+
+void PpapiPluginProcessHost::OnPluginLoaded(const IPC::ChannelHandle& handle) {
+ ReplyToRenderer(handle);
+}
+
+void PpapiPluginProcessHost::ReplyToRenderer(const IPC::ChannelHandle& handle) {
+ DCHECK(reply_msg_.get());
+ ViewHostMsg_OpenChannelToPepperPlugin::WriteReplyParams(reply_msg_.get(),
+ handle);
+ filter_->Send(reply_msg_.release());
+}
diff --git a/chrome/browser/ppapi_plugin_process_host.h b/chrome/browser/ppapi_plugin_process_host.h
new file mode 100644
index 0000000..956148c
--- /dev/null
+++ b/chrome/browser/ppapi_plugin_process_host.h
@@ -0,0 +1,57 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_PPAPI_PLUGIN_PROCESS_HOST_H_
+#define CHROME_BROWSER_PPAPI_PLUGIN_PROCESS_HOST_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/file_path.h"
+#include "chrome/browser/browser_child_process_host.h"
+
+class ResourceMessageFilter;
+
+namespace IPC {
+struct ChannelHandle;
+class Message;
+}
+
+class PpapiPluginProcessHost : public BrowserChildProcessHost {
+ public:
+ explicit PpapiPluginProcessHost(ResourceMessageFilter* filter);
+ virtual ~PpapiPluginProcessHost();
+
+ void Init(const FilePath& path, IPC::Message* reply_msg);
+
+ private:
+ virtual bool CanShutdown() { return true; }
+ virtual void OnProcessLaunched();
+ virtual URLRequestContext* GetRequestContext(
+ uint32 request_id,
+ const ViewHostMsg_Resource_Request& request_data);
+
+ virtual void OnMessageReceived(const IPC::Message& msg);
+ virtual void OnChannelConnected(int32 peer_pid);
+ virtual void OnChannelError();
+
+ // IPC message handlers.
+ void OnPluginLoaded(const IPC::ChannelHandle& handle);
+
+ // Sends the reply_msg_ to the renderer with the given channel info.
+ void ReplyToRenderer(const IPC::ChannelHandle& handle);
+
+ ResourceMessageFilter* filter_;
+
+ // Path to the plugin library.
+ FilePath plugin_path_;
+
+ // When we're waiting for initialization of the plugin, this contains the
+ // reply message for the renderer to tell it that it can continue.
+ scoped_ptr<IPC::Message> reply_msg_;
+
+ DISALLOW_COPY_AND_ASSIGN(PpapiPluginProcessHost);
+};
+
+#endif // CHROME_BROWSER_PPAPI_PLUGIN_PROCESS_HOST_H_
+
diff --git a/chrome/browser/renderer_host/browser_render_process_host.cc b/chrome/browser/renderer_host/browser_render_process_host.cc
index af37c6b..e8d3977 100644
--- a/chrome/browser/renderer_host/browser_render_process_host.cc
+++ b/chrome/browser/renderer_host/browser_render_process_host.cc
@@ -623,7 +623,8 @@ void BrowserRenderProcessHost::PropagateBrowserCommandLineToRenderer(
switches::kEnableResourceContentSettings,
switches::kPrelaunchGpuProcess,
switches::kEnableAcceleratedDecoding,
- switches::kDisableFileSystem
+ switches::kDisableFileSystem,
+ switches::kPpapiOutOfProcess
};
renderer_cmd->CopySwitchesFrom(browser_cmd, kSwitchNames,
arraysize(kSwitchNames));
diff --git a/chrome/browser/renderer_host/resource_message_filter.cc b/chrome/browser/renderer_host/resource_message_filter.cc
index 13a9246..35ae872 100644
--- a/chrome/browser/renderer_host/resource_message_filter.cc
+++ b/chrome/browser/renderer_host/resource_message_filter.cc
@@ -37,10 +37,11 @@
#include "chrome/browser/notifications/desktop_notification_service.h"
#include "chrome/browser/notifications/notifications_prefs_cache.h"
#include "chrome/browser/platform_util.h"
-#include "chrome/browser/plugin_service.h"
#include "chrome/browser/plugin_process_host.h"
-#include "chrome/browser/printing/printer_query.h"
+#include "chrome/browser/plugin_service.h"
+#include "chrome/browser/ppapi_plugin_process_host.h"
#include "chrome/browser/printing/print_job_manager.h"
+#include "chrome/browser/printing/printer_query.h"
#include "chrome/browser/profile.h"
#include "chrome/browser/renderer_host/audio_renderer_host.h"
#include "chrome/browser/renderer_host/blob_dispatcher_host.h"
@@ -449,6 +450,8 @@ bool ResourceMessageFilter::OnMessageReceived(const IPC::Message& msg) {
OnReceiveContextMenuMsg(msg))
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_OpenChannelToPlugin,
OnOpenChannelToPlugin)
+ IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_OpenChannelToPepperPlugin,
+ OnOpenChannelToPepperPlugin)
IPC_MESSAGE_HANDLER_DELAY_REPLY(ViewHostMsg_LaunchNaCl, OnLaunchNaCl)
IPC_MESSAGE_HANDLER(ViewHostMsg_CreateWorker, OnCreateWorker)
IPC_MESSAGE_HANDLER(ViewHostMsg_LookupSharedWorker, OnLookupSharedWorker)
@@ -876,6 +879,14 @@ void ResourceMessageFilter::OnOpenChannelToPlugin(const GURL& url,
new OpenChannelToPluginCallback(this, reply_msg));
}
+void ResourceMessageFilter::OnOpenChannelToPepperPlugin(
+ const FilePath& path,
+ IPC::Message* reply_msg) {
+ PpapiPluginProcessHost* host = new PpapiPluginProcessHost(this);
+ host->Init(path, reply_msg);
+ ppapi_plugin_hosts_.push_back(linked_ptr<PpapiPluginProcessHost>(host));
+}
+
void ResourceMessageFilter::OnLaunchNaCl(
const std::wstring& url, int channel_descriptor, IPC::Message* reply_msg) {
NaClProcessHost* host = new NaClProcessHost(resource_dispatcher_host_, url);
diff --git a/chrome/browser/renderer_host/resource_message_filter.h b/chrome/browser/renderer_host/resource_message_filter.h
index 850306e..b64c7c5 100644
--- a/chrome/browser/renderer_host/resource_message_filter.h
+++ b/chrome/browser/renderer_host/resource_message_filter.h
@@ -17,6 +17,7 @@
#include "app/surface/transport_dib.h"
#include "base/callback.h"
#include "base/file_path.h"
+#include "base/linked_ptr.h"
#include "base/process.h"
#include "base/ref_counted.h"
#include "base/string16.h"
@@ -43,6 +44,7 @@ class GeolocationDispatcherHostOld;
class HostZoomMap;
class IndexedDBDispatcherHost;
class NotificationsPrefsCache;
+class PpapiPluginProcessHost;
class Profile;
class RenderWidgetHelper;
class SearchProviderInstallStateDispatcherHost;
@@ -195,6 +197,8 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
void OnOpenChannelToPlugin(const GURL& url,
const std::string& mime_type,
IPC::Message* reply_msg);
+ void OnOpenChannelToPepperPlugin(const FilePath& path,
+ IPC::Message* reply_msg);
void OnLaunchNaCl(const std::wstring& url,
int channel_descriptor,
IPC::Message* reply_msg);
@@ -474,6 +478,9 @@ class ResourceMessageFilter : public IPC::ChannelProxy::MessageFilter,
base::TimeTicks last_plugin_refresh_time_; // Initialized to 0.
+ // A list of all Ppapi plugin processes for this renderer.
+ std::vector<linked_ptr<PpapiPluginProcessHost> > ppapi_plugin_hosts_;
+
// A callback to create a routing id for the associated renderer process.
scoped_ptr<CallbackWithReturnValue<int>::Type> next_route_id_callback_;
diff --git a/chrome/chrome.gyp b/chrome/chrome.gyp
index 135dde4..5212da2 100644
--- a/chrome/chrome.gyp
+++ b/chrome/chrome.gyp
@@ -24,6 +24,7 @@
'common',
'browser',
'chrome_gpu',
+ 'ppapi_plugin',
'profile_import',
'renderer',
'syncapi',
@@ -807,6 +808,24 @@
],
},
{
+ 'target_name': 'ppapi_plugin',
+ 'type': '<(library)',
+ 'dependencies': [
+ '../base/base.gyp:base',
+ '../ppapi/ppapi.gyp:ppapi_proxy',
+ ],
+ 'sources': [
+ 'ppapi_plugin/ppapi_plugin_main.cc',
+ 'ppapi_plugin/ppapi_process.cc',
+ 'ppapi_plugin/ppapi_process.h',
+ 'ppapi_plugin/ppapi_thread.cc',
+ 'ppapi_plugin/ppapi_thread.h',
+ ],
+ 'include_dirs': [
+ '..',
+ ],
+ },
+ {
'target_name': 'worker',
'type': '<(library)',
'msvs_guid': 'C78D02D0-A366-4EC6-A248-AA8E64C4BA18',
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index 7672b8c..01e9290 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -2423,6 +2423,8 @@
'browser/power_save_blocker_common.cc',
'browser/power_save_blocker_stub.cc',
'browser/power_save_blocker_win.cc',
+ 'browser/ppapi_plugin_process_host.cc',
+ 'browser/ppapi_plugin_process_host.h',
'browser/preferences_mac.cc',
'browser/preferences_mac.h',
'browser/prefs/browser_prefs.cc',
diff --git a/chrome/common/child_process_info.cc b/chrome/common/child_process_info.cc
index bd94ff26..1af0cdb 100644
--- a/chrome/common/child_process_info.cc
+++ b/chrome/common/child_process_info.cc
@@ -64,6 +64,8 @@ std::string ChildProcessInfo::GetTypeNameInEnglish(
return "Native Client broker";
case GPU_PROCESS:
return "GPU";
+ case PPAPI_PLUGIN_PROCESS:
+ return "Pepper Plugin";
case UNKNOWN_PROCESS:
default:
DCHECK(false) << "Unknown child process type!";
@@ -96,6 +98,7 @@ string16 ChildProcessInfo::GetLocalizedTitle() const {
return l10n_util::GetStringUTF16(IDS_TASK_MANAGER_NACL_BROKER_PREFIX);
case ChildProcessInfo::PLUGIN_PROCESS:
+ case ChildProcessInfo::PPAPI_PLUGIN_PROCESS:
return l10n_util::GetStringFUTF16(IDS_TASK_MANAGER_PLUGIN_PREFIX,
title,
WideToUTF16Hack(version_));
diff --git a/chrome/common/child_process_info.h b/chrome/common/child_process_info.h
index 78b0a2a..651978f 100644
--- a/chrome/common/child_process_info.h
+++ b/chrome/common/child_process_info.h
@@ -28,7 +28,8 @@ class ChildProcessInfo {
ZYGOTE_PROCESS,
SANDBOX_HELPER_PROCESS,
NACL_BROKER_PROCESS,
- GPU_PROCESS
+ GPU_PROCESS,
+ PPAPI_PLUGIN_PROCESS
};
ChildProcessInfo(const ChildProcessInfo& original);
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index 2678d36..386395b 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -846,6 +846,18 @@ const char kPluginProcess[] = "plugin";
// Causes the plugin process to display a dialog on launch.
const char kPluginStartupDialog[] = "plugin-startup-dialog";
+// Runs PPAPI (Pepper) plugins out-of-process.
+const char kPpapiOutOfProcess[] = "ppapi-out-of-process";
+
+// Like kPluginLauncher for PPAPI plugins.
+const char kPpapiPluginLauncher[] = "ppapi-plugin-launcher";
+
+// Argument to the process type that indicates a PPAPI plugin process type.
+const char kPpapiPluginProcess[] = "ppapi";
+
+// Causes the PPAPI sub process to display a dialog on launch.
+const char kPpapiStartupDialog[] = "ppapi-startup-dialog";
+
// Establishes a channel to the GPU process asynchronously and (re)launches it
// if necessary when a renderer process starts.
const char kPrelaunchGpuProcess[] = "prelaunch-gpu-process";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index 8d7db8e..15ec7e5 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -243,6 +243,10 @@ extern const char kPluginLauncher[];
extern const char kPluginPath[];
extern const char kPluginProcess[];
extern const char kPluginStartupDialog[];
+extern const char kPpapiOutOfProcess[];
+extern const char kPpapiPluginLauncher[];
+extern const char kPpapiPluginProcess[];
+extern const char kPpapiStartupDialog[];
extern const char kPrelaunchGpuProcess[];
extern const char kPrint[];
extern const char kProcessPerSite[];
diff --git a/chrome/common/pepper_plugin_registry.cc b/chrome/common/pepper_plugin_registry.cc
index 92fae2e..50f50e7 100644
--- a/chrome/common/pepper_plugin_registry.cc
+++ b/chrome/common/pepper_plugin_registry.cc
@@ -21,7 +21,9 @@ const char* PepperPluginRegistry::kPDFPluginExtension = "pdf";
const char* PepperPluginRegistry::kPDFPluginDescription =
"Portable Document Format";
-PepperPluginInfo::PepperPluginInfo() : is_internal(false) {
+PepperPluginInfo::PepperPluginInfo()
+ : is_internal(false),
+ is_out_of_process(false) {
}
PepperPluginInfo::~PepperPluginInfo() {}
@@ -52,7 +54,7 @@ void PepperPluginRegistry::PreloadModules() {
std::vector<PepperPluginInfo> plugins;
GetList(&plugins);
for (size_t i = 0; i < plugins.size(); ++i) {
- if (!plugins[i].is_internal) {
+ if (!plugins[i].is_internal && !plugins[i].is_out_of_process) {
base::NativeLibrary library = base::LoadNativeLibrary(plugins[i].path);
LOG_IF(WARNING, !library) << "Unable to load plugin "
<< plugins[i].path.value();
@@ -69,6 +71,9 @@ void PepperPluginRegistry::GetPluginInfoFromSwitch(
if (value.empty())
return;
+ bool out_of_process =
+ CommandLine::ForCurrentProcess()->HasSwitch(switches::kPpapiOutOfProcess);
+
// FORMAT:
// command-line = <plugin-entry> + *( LWS + "," + LWS + <plugin-entry> )
// plugin-entry = <file-path> + ["#" + <name> + ["#" + <description>]] +
@@ -88,6 +93,7 @@ void PepperPluginRegistry::GetPluginInfoFromSwitch(
base::SplitString(parts[0], '#', &name_parts);
PepperPluginInfo plugin;
+ plugin.is_out_of_process = out_of_process;
#if defined(OS_WIN)
// This means we can't provide plugins from non-ASCII paths, but
// since this switch is only for development I don't think that's
@@ -168,6 +174,19 @@ void PepperPluginRegistry::GetInternalPluginInfo(
#endif
}
+bool PepperPluginRegistry::RunOutOfProcessForPlugin(
+ const FilePath& path) const {
+ // TODO(brettw) don't recompute this every time. But since this Pepper
+ // switch is only for development, it's OK for now.
+ std::vector<PepperPluginInfo> plugins;
+ GetList(&plugins);
+ for (size_t i = 0; i < plugins.size(); ++i) {
+ if (path == plugins[i].path)
+ return plugins[i].is_out_of_process;
+ }
+ return false;
+}
+
pepper::PluginModule* PepperPluginRegistry::GetModule(
const FilePath& path) const {
ModuleMap::const_iterator it = modules_.find(path);
@@ -181,6 +200,7 @@ PepperPluginRegistry::~PepperPluginRegistry() {}
PepperPluginRegistry::PepperPluginRegistry() {
InternalPluginInfoList internal_plugin_info;
GetInternalPluginInfo(&internal_plugin_info);
+
// Register modules for these suckers.
for (InternalPluginInfoList::const_iterator it =
internal_plugin_info.begin();
@@ -203,6 +223,9 @@ PepperPluginRegistry::PepperPluginRegistry() {
GetPluginInfoFromSwitch(&plugins);
GetExtraPlugins(&plugins);
for (size_t i = 0; i < plugins.size(); ++i) {
+ if (plugins[i].is_out_of_process)
+ continue; // Only preload in-process plugins.
+
const FilePath& path = plugins[i].path;
ModuleHandle module = pepper::PluginModule::CreateModule(path);
if (!module) {
diff --git a/chrome/common/pepper_plugin_registry.h b/chrome/common/pepper_plugin_registry.h
index ebabc2e..60762c5b 100644
--- a/chrome/common/pepper_plugin_registry.h
+++ b/chrome/common/pepper_plugin_registry.h
@@ -14,10 +14,16 @@
#include "webkit/glue/plugins/pepper_plugin_module.h"
struct PepperPluginInfo {
- PepperPluginInfo(); // Needed to initialize |is_internal|.
+ PepperPluginInfo();
~PepperPluginInfo();
- bool is_internal; // Defaults to false (see constructor).
+ // Indicates internal plugins for which there's not actually a library.
+ // Defaults to false.
+ bool is_internal;
+
+ // True when this plugin should be run out of process. Defaults to false.
+ bool is_out_of_process;
+
FilePath path; // Internal plugins have "internal-[name]" as path.
std::vector<std::string> mime_types;
std::string name;
@@ -46,6 +52,13 @@ class PepperPluginRegistry {
// access to the plugins before entering the sandbox.
static void PreloadModules();
+ // Returns true if the given plugin is a pepper plugin that should be run
+ // out of process.
+ bool RunOutOfProcessForPlugin(const FilePath& path) const;
+
+ // Returns a preloaded module for the given path. This only works for
+ // non-out-of-process plugins since we preload them so they will run in the
+ // sandbox. Returns NULL if the plugin hasn't been preloaded.
pepper::PluginModule* GetModule(const FilePath& path) const;
~PepperPluginRegistry();
diff --git a/chrome/common/render_messages_internal.h b/chrome/common/render_messages_internal.h
index f00c806..a4ac77f 100644
--- a/chrome/common/render_messages_internal.h
+++ b/chrome/common/render_messages_internal.h
@@ -1578,6 +1578,14 @@ IPC_BEGIN_MESSAGES(ViewHost)
WebPluginInfo /* info */)
// A renderer sends this to the browser process when it wants to
+ // create a pepper plugin. The browser will create the plugin process if
+ // necessary, and will return a handle to the channel on success.
+ // On error an empty string is returned.
+ IPC_SYNC_MESSAGE_CONTROL1_1(ViewHostMsg_OpenChannelToPepperPlugin,
+ FilePath /* path */,
+ IPC::ChannelHandle /* handle to channel */)
+
+ // A renderer sends this to the browser process when it wants to
// create connect to the GPU. The browser will create the GPU process if
// necessary, and will return a handle to the channel via
// a GpuChannelEstablished message.
diff --git a/chrome/common/sandbox_policy.cc b/chrome/common/sandbox_policy.cc
index 0ab7563..4a6653f 100644
--- a/chrome/common/sandbox_policy.cc
+++ b/chrome/common/sandbox_policy.cc
@@ -475,6 +475,8 @@ base::ProcessHandle StartProcessWithAccess(CommandLine* cmd_line,
type = ChildProcessInfo::NACL_BROKER_PROCESS;
} else if (type_str == switches::kGpuProcess) {
type = ChildProcessInfo::GPU_PROCESS;
+ } else if (type_str == switches::kPpapiPluginProcess) {
+ type = ChildProcessInfo::PPAPI_PLUGIN_PROCESS;
} else {
NOTREACHED();
return 0;
diff --git a/chrome/ppapi_plugin/ppapi_plugin_main.cc b/chrome/ppapi_plugin/ppapi_plugin_main.cc
new file mode 100644
index 0000000..6738860
--- /dev/null
+++ b/chrome/ppapi_plugin/ppapi_plugin_main.cc
@@ -0,0 +1,34 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/message_loop.h"
+#include "build/build_config.h"
+#include "chrome/common/child_process.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/main_function_params.h"
+#include "chrome/ppapi_plugin/ppapi_thread.h"
+
+// Main function for starting the PPAPI plugin process.
+int PpapiPluginMain(const MainFunctionParams& parameters) {
+#if defined(OS_LINUX)
+ // On Linux we exec ourselves from /proc/self/exe, but that makes the
+ // process name that shows up in "ps" etc. for this process show as
+ // "exe" instead of "chrome" or something reasonable. Try to fix it.
+ CommandLine::SetProcTitle();
+#endif
+
+ const CommandLine& command_line = parameters.command_line_;
+ if (command_line.HasSwitch(switches::kPpapiStartupDialog)) {
+ ChildProcess::WaitForDebugger(L"Ppapi");
+ }
+
+ MessageLoop main_message_loop(MessageLoop::TYPE_UI);
+ PlatformThread::SetName("CrPPAPIMain");
+
+ ChildProcess ppapi_process;
+ ppapi_process.set_main_thread(new PpapiThread());
+
+ main_message_loop.Run();
+ return 0;
+}
diff --git a/chrome/ppapi_plugin/ppapi_process.cc b/chrome/ppapi_plugin/ppapi_process.cc
new file mode 100644
index 0000000..8cb9c7d
--- /dev/null
+++ b/chrome/ppapi_plugin/ppapi_process.cc
@@ -0,0 +1,11 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/ppapi_plugin/ppapi_process.h"
+
+PpapiProcess::PpapiProcess() {
+}
+
+PpapiProcess::~PpapiProcess() {
+}
diff --git a/chrome/ppapi_plugin/ppapi_process.h b/chrome/ppapi_plugin/ppapi_process.h
new file mode 100644
index 0000000..590f995
--- /dev/null
+++ b/chrome/ppapi_plugin/ppapi_process.h
@@ -0,0 +1,20 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_PPAPI_PLUGIN_PPAPI_PROCESS_H_
+#define CHROME_PPAPI_PLUGIN_PPAPI_PROCESS_H_
+#pragma once
+
+#include "chrome/common/child_process.h"
+
+class PpapiProcess : public ChildProcess {
+ public:
+ PpapiProcess();
+ ~PpapiProcess();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PpapiProcess);
+};
+
+#endif // CHROME_PPAPI_PLUGIN_PPAPI_PROCESS_H_
diff --git a/chrome/ppapi_plugin/ppapi_thread.cc b/chrome/ppapi_plugin/ppapi_thread.cc
new file mode 100644
index 0000000..36ea9f6
--- /dev/null
+++ b/chrome/ppapi_plugin/ppapi_thread.cc
@@ -0,0 +1,135 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/ppapi_plugin/ppapi_thread.h"
+
+#include "base/process_util.h"
+#include "chrome/common/child_process.h"
+#include "ipc/ipc_channel_handle.h"
+#include "ipc/ipc_sync_channel.h"
+#include "ppapi/c/ppp.h"
+#include "ppapi/proxy/plugin_dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
+
+#if defined(OS_POSIX)
+#include "base/eintr_wrapper.h"
+#include "ipc/ipc_channel_posix.h"
+#endif
+
+PpapiThread::PpapiThread()
+#if defined(OS_POSIX)
+ : renderer_fd_(-1)
+#endif
+ {
+}
+
+PpapiThread::~PpapiThread() {
+ pp::proxy::PluginDispatcher::SetGlobal(NULL);
+}
+
+// The "regular" ChildThread implements this function and does some standard
+// dispatching, then uses the message router. We don't actually need any of
+// this so this function just overrides that one.
+//
+// Note that this function is called only for messages from the channel to the
+// browser process. Messages from the renderer process are sent via a different
+// channel that ends up at Dispatcher::OnMessageReceived.
+void PpapiThread::OnMessageReceived(const IPC::Message& msg) {
+ IPC_BEGIN_MESSAGE_MAP(PpapiThread, msg)
+ IPC_MESSAGE_HANDLER(PpapiMsg_LoadPlugin, OnLoadPlugin)
+
+ // The rest of the messages go to the dispatcher.
+ /*IPC_MESSAGE_UNHANDLED(
+ if (dispatcher_.get())
+ dispatcher_->OnMessageReceived(msg)
+ )*/
+ IPC_END_MESSAGE_MAP()
+}
+
+void PpapiThread::OnLoadPlugin(const FilePath& path, int renderer_id) {
+ IPC::ChannelHandle channel_handle;
+ if (!LoadPluginLib(path) ||
+ !SetupRendererChannel(renderer_id, &channel_handle)) {
+ // An empty channel handle indicates error.
+ Send(new PpapiHostMsg_PluginLoaded(IPC::ChannelHandle()));
+ return;
+ }
+
+ Send(new PpapiHostMsg_PluginLoaded(channel_handle));
+}
+
+bool PpapiThread::LoadPluginLib(const FilePath& path) {
+ base::ScopedNativeLibrary library(base::LoadNativeLibrary(path));
+ if (!library.is_valid())
+ return false;
+
+ // Get the GetInterface function (required).
+ pp::proxy::Dispatcher::GetInterfaceFunc get_interface =
+ reinterpret_cast<pp::proxy::Dispatcher::GetInterfaceFunc>(
+ library.GetFunctionPointer("PPP_GetInterface"));
+ if (!get_interface) {
+ LOG(WARNING) << "No PPP_GetInterface in plugin library";
+ return false;
+ }
+
+ // Get the InitializeModule function (required).
+ pp::proxy::Dispatcher::InitModuleFunc init_module =
+ reinterpret_cast<pp::proxy::Dispatcher::InitModuleFunc>(
+ library.GetFunctionPointer("PPP_InitializeModule"));
+ if (!init_module) {
+ LOG(WARNING) << "No PPP_InitializeModule in plugin library";
+ return false;
+ }
+
+ // Get the ShutdownModule function (optional).
+ pp::proxy::Dispatcher::ShutdownModuleFunc shutdown_module =
+ reinterpret_cast<pp::proxy::Dispatcher::ShutdownModuleFunc>(
+ library.GetFunctionPointer("PPP_ShutdownModule"));
+
+ library_.Reset(library.Release());
+ dispatcher_.reset(new pp::proxy::PluginDispatcher(get_interface, init_module,
+ shutdown_module));
+ pp::proxy::PluginDispatcher::SetGlobal(dispatcher_.get());
+ return true;
+}
+
+bool PpapiThread::SetupRendererChannel(int renderer_id,
+ IPC::ChannelHandle* handle) {
+ std::string channel_key = StringPrintf(
+ "%d.r%d", base::GetCurrentProcId(), renderer_id);
+
+#if defined(OS_POSIX)
+ // This gets called when the PluginChannel is initially created. At this
+ // point, create the socketpair and assign the plugin side FD to the channel
+ // name. Keep the renderer side FD as a member variable in the PluginChannel
+ // to be able to transmit it through IPC.
+ int plugin_fd;
+ if (!IPC::SocketPair(&plugin_fd, &renderer_fd_))
+ return false;
+ IPC::AddChannelSocket(channel_key, plugin_fd);
+#endif
+
+ if (!dispatcher_->InitWithChannel(
+ ChildProcess::current()->io_message_loop(),
+ channel_key, false,
+ ChildProcess::current()->GetShutDownEvent()))
+ return false;
+
+ handle->name = channel_key;
+#if defined(OS_POSIX)
+ // On POSIX, pass the renderer-side FD.
+ handle->socket = base::FileDescriptor(renderer_fd_, false);
+#endif
+ return true;
+}
+
+#if defined(OS_POSIX)
+void PpapiThread::CloseRendererFD() {
+ if (renderer_fd_ != -1) {
+ if (HANDLE_EINTR(close(renderer_fd_)) < 0)
+ PLOG(ERROR) << "close";
+ renderer_fd_ = -1;
+ }
+}
+#endif
diff --git a/chrome/ppapi_plugin/ppapi_thread.h b/chrome/ppapi_plugin/ppapi_thread.h
new file mode 100644
index 0000000..ed7b024
--- /dev/null
+++ b/chrome/ppapi_plugin/ppapi_thread.h
@@ -0,0 +1,67 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_PPAPI_PLUGIN_PPAPI_THREAD_H_
+#define CHROME_PPAPI_PLUGIN_PPAPI_THREAD_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/scoped_native_library.h"
+#include "base/scoped_ptr.h"
+#include "build/build_config.h"
+#include "chrome/common/child_thread.h"
+
+class FilePath;
+
+namespace IPC {
+struct ChannelHandle;
+}
+
+namespace pp {
+namespace proxy {
+class PluginDispatcher;
+}
+}
+
+class PpapiThread : public ChildThread {
+ public:
+ PpapiThread();
+ ~PpapiThread();
+
+ private:
+ // ChildThread overrides.
+ virtual void OnMessageReceived(const IPC::Message& msg);
+
+ // Message handlers.
+ void OnLoadPlugin(const FilePath& path, int renderer_id);
+
+ bool LoadPluginLib(const FilePath& path);
+
+ // Sets up the channel to the given renderer. On success, returns true and
+ // fills the given ChannelHandle with the information from the new channel.
+ bool SetupRendererChannel(int renderer_id,
+ IPC::ChannelHandle* handle);
+
+#if defined(OS_POSIX)
+ // Close the plugin process' copy of the renderer's side of the plugin
+ // channel. This can be called after the renderer is known to have its own
+ // copy of renderer_fd_.
+ void CloseRendererFD();
+#endif
+
+ base::ScopedNativeLibrary library_;
+
+ scoped_ptr<pp::proxy::PluginDispatcher> dispatcher_;
+
+#if defined(OS_POSIX)
+ // FD for the renderer end of the socket. It is closed when the IPC layer
+ // indicates that the channel is connected, proving that the renderer has
+ // access to its side of the socket.
+ int renderer_fd_;
+#endif
+
+ DISALLOW_COPY_AND_ASSIGN(PpapiThread);
+};
+
+#endif // CHROME_PPAPI_PLUGIN_PPAPI_THREAD_H_
diff --git a/chrome/renderer/pepper_plugin_delegate_impl.cc b/chrome/renderer/pepper_plugin_delegate_impl.cc
index f897435..f338343 100644
--- a/chrome/renderer/pepper_plugin_delegate_impl.cc
+++ b/chrome/renderer/pepper_plugin_delegate_impl.cc
@@ -30,6 +30,7 @@
#include "chrome/renderer/webplugin_delegate_proxy.h"
#include "gfx/size.h"
#include "grit/locale_settings.h"
+#include "ipc/ipc_channel_handle.h"
#include "ppapi/c/dev/pp_video_dev.h"
#include "third_party/WebKit/WebKit/chromium/public/WebFileChooserCompletion.h"
#include "third_party/WebKit/WebKit/chromium/public/WebFileChooserParams.h"
@@ -38,6 +39,7 @@
#include "webkit/fileapi/file_system_callback_dispatcher.h"
#include "webkit/glue/plugins/pepper_file_io.h"
#include "webkit/glue/plugins/pepper_plugin_instance.h"
+#include "webkit/glue/plugins/pepper_plugin_module.h"
#include "webkit/glue/plugins/webplugin.h"
#if defined(OS_MACOSX)
@@ -404,7 +406,22 @@ PepperPluginDelegateImpl::PepperPluginDelegateImpl(RenderView* render_view)
id_generator_(0) {
}
-PepperPluginDelegateImpl::~PepperPluginDelegateImpl() {}
+PepperPluginDelegateImpl::~PepperPluginDelegateImpl() {
+}
+
+scoped_refptr<pepper::PluginModule>
+PepperPluginDelegateImpl::CreateOutOfProcessPepperPlugin(
+ const FilePath& path) {
+ IPC::ChannelHandle channel_handle;
+ render_view_->Send(new ViewHostMsg_OpenChannelToPepperPlugin(
+ path, &channel_handle));
+ if (channel_handle.name.empty())
+ return scoped_refptr<pepper::PluginModule>(); // Couldn't be initialized.
+ return pepper::PluginModule::CreateOutOfProcessModule(
+ ChildProcess::current()->io_message_loop(),
+ channel_handle,
+ ChildProcess::current()->GetShutDownEvent());
+}
void PepperPluginDelegateImpl::ViewInitiatedPaint() {
// Notify all of our instances that we started painting. This is used for
diff --git a/chrome/renderer/pepper_plugin_delegate_impl.h b/chrome/renderer/pepper_plugin_delegate_impl.h
index f817862..9402ae2 100644
--- a/chrome/renderer/pepper_plugin_delegate_impl.h
+++ b/chrome/renderer/pepper_plugin_delegate_impl.h
@@ -11,6 +11,7 @@
#include "base/basictypes.h"
#include "base/id_map.h"
+#include "base/ref_counted.h"
#include "base/weak_ptr.h"
#include "ppapi/c/pp_errors.h"
#include "webkit/glue/plugins/pepper_plugin_delegate.h"
@@ -26,6 +27,7 @@ class Rect;
namespace pepper {
class FileIO;
class PluginInstance;
+class PluginModule;
}
namespace WebKit {
@@ -42,6 +44,9 @@ class PepperPluginDelegateImpl
explicit PepperPluginDelegateImpl(RenderView* render_view);
virtual ~PepperPluginDelegateImpl();
+ scoped_refptr<pepper::PluginModule> CreateOutOfProcessPepperPlugin(
+ const FilePath& path);
+
// Called by RenderView to tell us about painting events, these two functions
// just correspond to the DidInitiatePaint and DidFlushPaint in R.V..
void ViewInitiatedPaint();
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 2378d9e..9b0a283 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -2542,8 +2542,15 @@ WebPlugin* RenderView::createPlugin(WebFrame* frame,
if (info.path.value() == kDefaultPluginLibraryName ||
plugin_setting == CONTENT_SETTING_ALLOW ||
host_setting == CONTENT_SETTING_ALLOW) {
- scoped_refptr<pepper::PluginModule> pepper_module(
- PepperPluginRegistry::GetInstance()->GetModule(info.path));
+ scoped_refptr<pepper::PluginModule> pepper_module;
+ if (PepperPluginRegistry::GetInstance()->RunOutOfProcessForPlugin(
+ info.path)) {
+ pepper_module =
+ pepper_delegate_.CreateOutOfProcessPepperPlugin(info.path);
+ } else {
+ pepper_module =
+ PepperPluginRegistry::GetInstance()->GetModule(info.path);
+ }
if (pepper_module) {
return CreatePepperPlugin(frame,
params,
diff --git a/ipc/ipc_message_utils.h b/ipc/ipc_message_utils.h
index 9629fac..7c6018f 100644
--- a/ipc/ipc_message_utils.h
+++ b/ipc/ipc_message_utils.h
@@ -76,6 +76,8 @@ enum IPCMessageStart {
GpuVideoDecoderMsgStart,
ServiceMsgStart,
ServiceHostMsgStart,
+ PpapiMsgStart,
+ PpapiHostMsgStart,
// NOTE: When you add a new message class, also update
// IPCStatusView::IPCStatusView to ensure logging works.
LastMsgIndex
diff --git a/ppapi/ppapi.gyp b/ppapi/ppapi.gyp
index d968ddf..04c3048 100644
--- a/ppapi/ppapi.gyp
+++ b/ppapi/ppapi.gyp
@@ -473,5 +473,88 @@
}],
],
},
+ {
+ 'target_name': 'ppapi_proxy',
+ 'type': 'static_library',
+ 'dependencies': [
+ '../ipc/ipc.gyp:ipc',
+ 'ppapi_c',
+ ],
+ 'all_dependent_settings': {
+ 'include_dirs': [
+ '..',
+ ],
+ },
+ 'include_dirs': [
+ '..',
+ '../..', # For nacl includes to work.
+ ],
+ 'sources': [
+ 'proxy/callback_tracker.cc',
+ 'proxy/callback_tracker.h',
+ 'proxy/dispatcher.cc',
+ 'proxy/dispatcher.h',
+ 'proxy/host_dispatcher.cc',
+ 'proxy/host_dispatcher.h',
+ 'proxy/host_var_serialization_rules.cc',
+ 'proxy/host_var_serialization_rules.h',
+ 'proxy/interface_proxy.cc',
+ 'proxy/interface_proxy.h',
+ 'proxy/plugin_dispatcher.cc',
+ 'proxy/plugin_dispatcher.h',
+ 'proxy/plugin_resource.cc',
+ 'proxy/plugin_resource.h',
+ 'proxy/plugin_resource_tracker.cc',
+ 'proxy/plugin_resource_tracker.h',
+ 'proxy/plugin_var_serialization_rules.cc',
+ 'proxy/plugin_var_serialization_rules.h',
+ 'proxy/plugin_var_tracker.cc',
+ 'proxy/plugin_var_tracker.h',
+ 'proxy/ppapi_messages.cc',
+ 'proxy/ppapi_messages.h',
+ 'proxy/ppapi_messages_internal.h',
+ 'proxy/ppapi_param_traits.cc',
+ 'proxy/ppapi_param_traits.h',
+ #'proxy/ppb_char_set_proxy.cc',
+ #'proxy/ppb_char_set_proxy.h',
+ 'proxy/ppb_core_proxy.cc',
+ 'proxy/ppb_core_proxy.h',
+ #'proxy/ppb_font_proxy.cc',
+ #'proxy/ppb_font_proxy.h',
+ 'proxy/ppb_graphics_2d_proxy.cc',
+ 'proxy/ppb_graphics_2d_proxy.h',
+ 'proxy/ppb_image_data_proxy.cc',
+ 'proxy/ppb_image_data_proxy.h',
+ 'proxy/ppb_instance_proxy.cc',
+ 'proxy/ppb_instance_proxy.h',
+ 'proxy/ppb_testing_proxy.cc',
+ 'proxy/ppb_testing_proxy.h',
+ 'proxy/ppb_url_loader_proxy.cc',
+ 'proxy/ppb_url_loader_proxy.h',
+ 'proxy/ppb_url_request_info_proxy.cc',
+ 'proxy/ppb_url_request_info_proxy.h',
+ 'proxy/ppb_url_response_info_proxy.cc',
+ 'proxy/ppb_url_response_info_proxy.h',
+ 'proxy/ppb_var_deprecated_proxy.cc',
+ 'proxy/ppb_var_deprecated_proxy.h',
+ 'proxy/ppp_class_proxy.cc',
+ 'proxy/ppp_class_proxy.h',
+ 'proxy/ppp_instance_proxy.cc',
+ 'proxy/ppp_instance_proxy.h',
+ 'proxy/serialized_var.cc',
+ 'proxy/serialized_var.h',
+ 'proxy/var_serialization_rules.h',
+ ],
+ 'defines': [
+ ],
+ 'conditions': [
+ ['OS=="win"', {
+ }],
+ ['OS=="linux"', {
+ }],
+ ['OS=="mac"', {
+ }]
+ ],
+ },
],
}
diff --git a/ppapi/proxy/dispatcher.cc b/ppapi/proxy/dispatcher.cc
index 3a0f5a4..476f403 100644
--- a/ppapi/proxy/dispatcher.cc
+++ b/ppapi/proxy/dispatcher.cc
@@ -8,6 +8,7 @@
#include <map>
+#include "base/compiler_specific.h"
#include "base/logging.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_sync_channel.h"
@@ -45,7 +46,7 @@ Dispatcher::Dispatcher(GetInterfaceFunc local_get_interface)
disallow_trusted_interfaces_(true),
local_get_interface_(local_get_interface),
declared_supported_remote_interfaces_(false),
- callback_tracker_(this) {
+ callback_tracker_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
memset(id_to_proxy_, 0,
static_cast<int>(INTERFACE_ID_COUNT) * sizeof(InterfaceProxy*));
}
diff --git a/ppapi/proxy/plugin_dispatcher.cc b/ppapi/proxy/plugin_dispatcher.cc
index 1997dc4..085c15c 100644
--- a/ppapi/proxy/plugin_dispatcher.cc
+++ b/ppapi/proxy/plugin_dispatcher.cc
@@ -6,6 +6,7 @@
#include <map>
+#include "base/compiler_specific.h"
#include "base/logging.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_sync_channel.h"
@@ -35,8 +36,10 @@ PluginDispatcher::PluginDispatcher(GetInterfaceFunc get_interface,
: Dispatcher(get_interface),
init_module_(init_module),
shutdown_module_(shutdown_module),
- plugin_resource_tracker_(new PluginResourceTracker(this)),
- plugin_var_tracker_(new PluginVarTracker(this)) {
+ plugin_resource_tracker_(new PluginResourceTracker(
+ ALLOW_THIS_IN_INITIALIZER_LIST(this))),
+ plugin_var_tracker_(new PluginVarTracker(
+ ALLOW_THIS_IN_INITIALIZER_LIST(this))) {
SetSerializationRules(
new PluginVarSerializationRules(plugin_var_tracker_.get()));
diff --git a/ppapi/proxy/ppapi_param_traits.h b/ppapi/proxy/ppapi_param_traits.h
index 0c13ff5..2bb2a7a 100644
--- a/ppapi/proxy/ppapi_param_traits.h
+++ b/ppapi/proxy/ppapi_param_traits.h
@@ -17,7 +17,7 @@ struct PP_ObjectProperty;
namespace pp {
namespace proxy {
struct PPBFont_DrawTextAt_Params;
-class SerializedFontDescription;
+struct SerializedFontDescription;
class SerializedVar;
}
}
diff --git a/ppapi/proxy/ppb_image_data_proxy.cc b/ppapi/proxy/ppb_image_data_proxy.cc
index 27d78726..54032ee 100644
--- a/ppapi/proxy/ppb_image_data_proxy.cc
+++ b/ppapi/proxy/ppb_image_data_proxy.cc
@@ -70,7 +70,8 @@ void* ImageData::Map() {
mapped_data_ = address;
return address;
#else
- #error write this
+ NOTIMPLEMENTED();
+ return NULL;
#endif
}
@@ -79,7 +80,7 @@ void ImageData::Unmap() {
if (mapped_data_)
shmdt(mapped_data_);
#else
- #error write this
+ NOTIMPLEMENTED();
#endif
mapped_data_ = NULL;
}
@@ -225,8 +226,9 @@ void PPB_ImageData_Proxy::OnMsgCreate(PP_Module module,
const PPB_ImageDataTrusted* trusted =
reinterpret_cast<const PPB_ImageDataTrusted*>(
dispatcher()->GetLocalInterface(PPB_IMAGEDATA_TRUSTED_INTERFACE));
+ uint32_t byte_count = 0;
if (trusted)
- *result_shm_handle = trusted->GetNativeMemoryHandle(*result);
+ *result_shm_handle = trusted->GetNativeMemoryHandle(*result, &byte_count);
}
}
diff --git a/ppapi/proxy/ppb_url_request_info_proxy.h b/ppapi/proxy/ppb_url_request_info_proxy.h
index c0f98e9..6acfd75 100644
--- a/ppapi/proxy/ppb_url_request_info_proxy.h
+++ b/ppapi/proxy/ppb_url_request_info_proxy.h
@@ -39,7 +39,7 @@ class PPB_URLRequestInfo_Proxy : public InterfaceProxy {
int32_t property,
SerializedVarReceiveInput value);
void OnMsgAppendDataToBody(PP_Resource request,
- const std::string& request);
+ const std::string& data);
void OnMsgAppendFileToBody(PP_Resource request,
PP_Resource file_ref,
int64_t start_offset,
diff --git a/ppapi/proxy/ppp_instance_proxy.cc b/ppapi/proxy/ppp_instance_proxy.cc
index ccc6803..8551d2b 100644
--- a/ppapi/proxy/ppp_instance_proxy.cc
+++ b/ppapi/proxy/ppp_instance_proxy.cc
@@ -77,7 +77,7 @@ PP_Var GetInstanceObject(PP_Instance instance) {
Dispatcher* dispatcher = HostDispatcher::GetForInstance(instance);
ReceiveSerializedVarReturnValue result;
dispatcher->Send(new PpapiMsg_PPPInstance_GetInstanceObject(
- instance, INTERFACE_ID_PPP_INSTANCE, &result));
+ INTERFACE_ID_PPP_INSTANCE, instance, &result));
return result.Return(dispatcher);
}
diff --git a/ppapi/proxy/serialized_var.cc b/ppapi/proxy/serialized_var.cc
index ef968ea..a5356c5 100644
--- a/ppapi/proxy/serialized_var.cc
+++ b/ppapi/proxy/serialized_var.cc
@@ -123,7 +123,7 @@ void SerializedVar::Inner::WriteToMessage(IPC::Message* m) const {
// just serialized.
break;
case PP_VARTYPE_BOOL:
- m->WriteBool(var_.value.as_bool);
+ m->WriteBool(PPBoolToBool(var_.value.as_bool));
break;
case PP_VARTYPE_INT32:
m->WriteInt(var_.value.as_int);
diff --git a/webkit/glue/plugins/pepper_graphics_2d.cc b/webkit/glue/plugins/pepper_graphics_2d.cc
index a8d5091..a4f9134 100644
--- a/webkit/glue/plugins/pepper_graphics_2d.cc
+++ b/webkit/glue/plugins/pepper_graphics_2d.cc
@@ -420,6 +420,7 @@ bool Graphics2D::ReadImageData(PP_Resource image,
SkIntToScalar(image_resource->width()),
SkIntToScalar(image_resource->height()) };
+ ImageDataAutoMapper auto_mapper2(image_data_);
if (image_resource->format() != image_data_->format()) {
// Convert the image data if the format does not match.
ConvertImageData(image_data_, src_irect, image_resource.get(), dest_rect);
@@ -472,7 +473,7 @@ bool Graphics2D::BindToInstance(PluginInstance* new_instance) {
void Graphics2D::Paint(WebKit::WebCanvas* canvas,
const gfx::Rect& plugin_rect,
const gfx::Rect& paint_rect) {
- // We're guaranteed to have a mapped canvas since we mapped it in Init().
+ ImageDataAutoMapper auto_mapper(image_data_);
const SkBitmap& backing_bitmap = *image_data_->GetMappedBitmap();
#if defined(OS_MACOSX)
diff --git a/webkit/glue/plugins/pepper_plugin_module.cc b/webkit/glue/plugins/pepper_plugin_module.cc
index 662055a..cf17813 100644
--- a/webkit/glue/plugins/pepper_plugin_module.cc
+++ b/webkit/glue/plugins/pepper_plugin_module.cc
@@ -48,6 +48,8 @@
#include "ppapi/c/ppb_var.h"
#include "ppapi/c/ppp.h"
#include "ppapi/c/ppp_instance.h"
+#include "ppapi/proxy/host_dispatcher.h"
+#include "ppapi/proxy/ppapi_messages.h"
#include "webkit/glue/plugins/pepper_audio.h"
#include "webkit/glue/plugins/pepper_buffer.h"
#include "webkit/glue/plugins/pepper_common.h"
@@ -83,6 +85,10 @@
#include "webkit/glue/plugins/pepper_graphics_3d.h"
#endif // ENABLE_GPU
+#if defined(OS_POSIX)
+#include "ipc/ipc_channel_posix.h"
+#endif
+
namespace pepper {
namespace {
@@ -335,6 +341,7 @@ scoped_refptr<PluginModule> PluginModule::CreateModule(
return lib;
}
+// static
scoped_refptr<PluginModule> PluginModule::CreateInternalModule(
EntryPoints entry_points) {
scoped_refptr<PluginModule> lib(new PluginModule());
@@ -345,6 +352,17 @@ scoped_refptr<PluginModule> PluginModule::CreateInternalModule(
}
// static
+scoped_refptr<PluginModule> PluginModule::CreateOutOfProcessModule(
+ MessageLoop* ipc_message_loop,
+ const IPC::ChannelHandle& handle,
+ base::WaitableEvent* shutdown_event) {
+ scoped_refptr<PluginModule> lib(new PluginModule);
+ if (!lib->InitForOutOfProcess(ipc_message_loop, handle, shutdown_event))
+ return NULL;
+ return lib;
+}
+
+// static
const PPB_Core* PluginModule::GetCore() {
return &core_interface;
}
@@ -386,10 +404,41 @@ bool PluginModule::InitFromFile(const FilePath& path) {
return true;
}
+bool PluginModule::InitForOutOfProcess(MessageLoop* ipc_message_loop,
+ const IPC::ChannelHandle& handle,
+ base::WaitableEvent* shutdown_event) {
+ const PPB_Var_Deprecated* var_interface =
+ reinterpret_cast<const PPB_Var_Deprecated*>(
+ GetInterface(PPB_VAR_DEPRECATED_INTERFACE));
+ dispatcher_.reset(new pp::proxy::HostDispatcher(var_interface,
+ pp_module(), &GetInterface));
+
+#if defined(OS_POSIX)
+ // If we received a ChannelHandle, register it now.
+ if (handle.socket.fd >= 0)
+ IPC::AddChannelSocket(handle.name, handle.socket.fd);
+#endif
+
+ if (!dispatcher_->InitWithChannel(ipc_message_loop, handle.name, true,
+ shutdown_event)) {
+ dispatcher_.reset();
+ return false;
+ }
+
+ bool init_result = false;
+ dispatcher_->Send(new PpapiMsg_InitializeModule(pp_module(), &init_result));
+
+ if (!init_result) {
+ // TODO(brettw) does the module get unloaded in this case?
+ dispatcher_.reset();
+ return false;
+ }
+ return true;
+}
+
// static
bool PluginModule::LoadEntryPoints(const base::NativeLibrary& library,
EntryPoints* entry_points) {
-
entry_points->get_interface =
reinterpret_cast<PPP_GetInterfaceFunc>(
base::GetFunctionPointerFromNativeLibrary(library,
@@ -426,7 +475,13 @@ PluginInstance* PluginModule::CreateInstance(PluginDelegate* delegate) {
LOG(WARNING) << "Plugin doesn't support instance interface, failing.";
return NULL;
}
- return new PluginInstance(delegate, this, plugin_instance_interface);
+ PluginInstance* instance = new PluginInstance(delegate, this,
+ plugin_instance_interface);
+ if (dispatcher_.get()) {
+ pp::proxy::HostDispatcher::SetForInstance(instance->pp_instance(),
+ dispatcher_.get());
+ }
+ return instance;
}
PluginInstance* PluginModule::GetSomeInstance() const {
@@ -437,6 +492,10 @@ PluginInstance* PluginModule::GetSomeInstance() const {
}
const void* PluginModule::GetPluginInterface(const char* name) const {
+ if (dispatcher_.get())
+ return dispatcher_->GetProxiedInterface(name);
+
+ // In-process plugins.
if (!entry_points_.get_interface)
return NULL;
return entry_points_.get_interface(name);
@@ -447,6 +506,7 @@ void PluginModule::InstanceCreated(PluginInstance* instance) {
}
void PluginModule::InstanceDeleted(PluginInstance* instance) {
+ pp::proxy::HostDispatcher::RemoveForInstance(instance->pp_instance());
instances_.erase(instance);
}
diff --git a/webkit/glue/plugins/pepper_plugin_module.h b/webkit/glue/plugins/pepper_plugin_module.h
index cf7defb..6ba3146 100644
--- a/webkit/glue/plugins/pepper_plugin_module.h
+++ b/webkit/glue/plugins/pepper_plugin_module.h
@@ -16,10 +16,25 @@
#include "ppapi/c/ppb.h"
class FilePath;
+class MessageLoop;
typedef struct NPObject NPObject;
struct PPB_Core;
typedef void* NPIdentifier;
+namespace base {
+class WaitableEvent;
+}
+
+namespace pp {
+namespace proxy {
+class HostDispatcher;
+} // proxy
+} // pp
+
+namespace IPC {
+struct ChannelHandle;
+}
+
namespace pepper {
class ObjectVar;
@@ -56,6 +71,10 @@ class PluginModule : public base::RefCounted<PluginModule>,
static scoped_refptr<PluginModule> CreateModule(const FilePath& path);
static scoped_refptr<PluginModule> CreateInternalModule(
EntryPoints entry_points);
+ static scoped_refptr<PluginModule> CreateOutOfProcessModule(
+ MessageLoop* ipc_message_loop,
+ const IPC::ChannelHandle& handle,
+ base::WaitableEvent* shutdown_event);
static const PPB_Core* GetCore();
@@ -101,9 +120,16 @@ class PluginModule : public base::RefCounted<PluginModule>,
bool InitFromEntryPoints(const EntryPoints& entry_points);
bool InitFromFile(const FilePath& path);
+ bool InitForOutOfProcess(MessageLoop* ipc_message_loop,
+ const IPC::ChannelHandle& handle,
+ base::WaitableEvent* shutdown_event);
static bool LoadEntryPoints(const base::NativeLibrary& library,
EntryPoints* entry_points);
+ // Dispatcher for out-of-process plugins. This will be null when the plugin
+ // is being run in-process.
+ scoped_ptr<pp::proxy::HostDispatcher> dispatcher_;
+
PP_Module pp_module_;
bool initialized_;
@@ -115,7 +141,7 @@ class PluginModule : public base::RefCounted<PluginModule>,
base::NativeLibrary library_;
// Contains pointers to the entry points of the actual plugin
- // implementation.
+ // implementation. These will be NULL for out-of-process plugins.
EntryPoints entry_points_;
// The name of the module.
diff --git a/webkit/glue/webkit_glue.gypi b/webkit/glue/webkit_glue.gypi
index 99fb8b8..8ed3e8b 100644
--- a/webkit/glue/webkit_glue.gypi
+++ b/webkit/glue/webkit_glue.gypi
@@ -147,6 +147,7 @@
'<(DEPTH)/base/base.gyp:base_i18n',
'<(DEPTH)/gpu/gpu.gyp:gles2_implementation',
'<(DEPTH)/net/net.gyp:net',
+ '<(DEPTH)/ppapi/ppapi.gyp:ppapi_proxy',
'<(DEPTH)/printing/printing.gyp:printing',
'<(DEPTH)/skia/skia.gyp:skia',
'<(DEPTH)/third_party/icu/icu.gyp:icui18n',