diff options
author | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-13 17:50:20 +0000 |
---|---|---|
committer | brettw@chromium.org <brettw@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-02-13 17:50:20 +0000 |
commit | a08ebeaea39acfe007d9ee9b25b28efd04011e5a (patch) | |
tree | c878b32554af650294155ab21491dc086cff0939 /chrome/ppapi_plugin | |
parent | 9d7557f78d893c56afcf65f2e6317feabb9af796 (diff) | |
download | chromium_src-a08ebeaea39acfe007d9ee9b25b28efd04011e5a.zip chromium_src-a08ebeaea39acfe007d9ee9b25b28efd04011e5a.tar.gz chromium_src-a08ebeaea39acfe007d9ee9b25b28efd04011e5a.tar.bz2 |
Share PPAPI out-of-process plugins between renderer processes.
This provides the hook-up for plugin sharing but not shutdown or cleanup from
errors. There is still a lot of work to do cleaning up in the plugin and the
browser when a renderer dies, or cleaning up in the renderer and browser when a
plugin dies. Currently, even the normal exit case crashes in the browser. But
fixing it in this patch would be too complicated to write or review, so I'm
going to do shutdown & error handling in a followup.
Review URL: http://codereview.chromium.org/6486034
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@74766 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/ppapi_plugin')
-rw-r--r-- | chrome/ppapi_plugin/ppapi_thread.cc | 101 | ||||
-rw-r--r-- | chrome/ppapi_plugin/ppapi_thread.h | 36 |
2 files changed, 65 insertions, 72 deletions
diff --git a/chrome/ppapi_plugin/ppapi_thread.cc b/chrome/ppapi_plugin/ppapi_thread.cc index 4e8c0c9..483863c 100644 --- a/chrome/ppapi_plugin/ppapi_thread.cc +++ b/chrome/ppapi_plugin/ppapi_thread.cc @@ -4,27 +4,33 @@ #include "chrome/ppapi_plugin/ppapi_thread.h" +#include <limits> + #include "base/process_util.h" +#include "base/rand_util.h" #include "chrome/common/child_process.h" #include "ipc/ipc_channel_handle.h" #include "ipc/ipc_sync_channel.h" +#include "ppapi/c/pp_errors.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 - { + : get_plugin_interface_(NULL), + local_pp_module_( + base::RandInt(0, std::numeric_limits<PP_Module>::max())) { } PpapiThread::~PpapiThread() { + if (library_.is_valid()) { + // The ShutdownModule function is optional. + pp::proxy::Dispatcher::ShutdownModuleFunc shutdown_module = + reinterpret_cast<pp::proxy::Dispatcher::ShutdownModuleFunc>( + library_.GetFunctionPointer("PPP_ShutdownModule")); + if (shutdown_module) + shutdown_module(); + } } // The "regular" ChildThread implements this function and does some standard @@ -37,37 +43,23 @@ PpapiThread::~PpapiThread() { bool PpapiThread::OnMessageReceived(const IPC::Message& msg) { IPC_BEGIN_MESSAGE_MAP(PpapiThread, msg) IPC_MESSAGE_HANDLER(PpapiMsg_LoadPlugin, OnMsgLoadPlugin) + IPC_MESSAGE_HANDLER(PpapiMsg_CreateChannel, OnMsgCreateChannel) IPC_END_MESSAGE_MAP() return true; } -void PpapiThread::OnMsgLoadPlugin(base::ProcessHandle host_process_handle, - const FilePath& path, - int renderer_id) { - IPC::ChannelHandle channel_handle; - if (!LoadPluginLib(host_process_handle, 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(base::ProcessHandle host_process_handle, - const FilePath& path) { +void PpapiThread::OnMsgLoadPlugin(const FilePath& path) { base::ScopedNativeLibrary library(base::LoadNativeLibrary(path)); if (!library.is_valid()) - return false; + return; // Get the GetInterface function (required). - pp::proxy::Dispatcher::GetInterfaceFunc get_interface = + get_plugin_interface_ = reinterpret_cast<pp::proxy::Dispatcher::GetInterfaceFunc>( library.GetFunctionPointer("PPP_GetInterface")); - if (!get_interface) { + if (!get_plugin_interface_) { LOG(WARNING) << "No PPP_GetInterface in plugin library"; - return false; + return; } // Get the InitializeModule function (required). @@ -76,26 +68,42 @@ bool PpapiThread::LoadPluginLib(base::ProcessHandle host_process_handle, library.GetFunctionPointer("PPP_InitializeModule")); if (!init_module) { LOG(WARNING) << "No PPP_InitializeModule in plugin library"; - return false; + return; + } + int32_t init_error = init_module( + local_pp_module_, + &pp::proxy::PluginDispatcher::GetInterfaceFromDispatcher); + if (init_error != PP_OK) { + LOG(WARNING) << "InitModule failed with error " << init_error; + return; } - - // 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( - host_process_handle, get_interface, init_module, shutdown_module)); - return true; } -bool PpapiThread::SetupRendererChannel(int renderer_id, +void PpapiThread::OnMsgCreateChannel(base::ProcessHandle host_process_handle, + int renderer_id) { + IPC::ChannelHandle channel_handle; + if (!library_.is_valid() || // Plugin couldn't be loaded. + !SetupRendererChannel(host_process_handle, renderer_id, + &channel_handle)) { + Send(new PpapiHostMsg_ChannelCreated(IPC::ChannelHandle())); + return; + } + + Send(new PpapiHostMsg_ChannelCreated(channel_handle)); +} + +bool PpapiThread::SetupRendererChannel(base::ProcessHandle host_process_handle, + int renderer_id, IPC::ChannelHandle* handle) { + pp::proxy::PluginDispatcher* dispatcher = new pp::proxy::PluginDispatcher( + host_process_handle, get_plugin_interface_); + IPC::ChannelHandle plugin_handle; plugin_handle.name = StringPrintf("%d.r%d", base::GetCurrentProcId(), renderer_id); - if (!dispatcher_->InitWithChannel( + if (!dispatcher->InitWithChannel( ChildProcess::current()->io_message_loop(), plugin_handle, false, ChildProcess::current()->GetShutDownEvent())) @@ -104,18 +112,9 @@ bool PpapiThread::SetupRendererChannel(int renderer_id, handle->name = plugin_handle.name; #if defined(OS_POSIX) // On POSIX, pass the renderer-side FD. - renderer_fd_ = dispatcher_->channel()->GetClientFileDescriptor(); - handle->socket = base::FileDescriptor(renderer_fd_, false); + handle->socket = base::FileDescriptor(dispatcher->GetRendererFD(), 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 index 08e62fc..32e45f5 100644 --- a/chrome/ppapi_plugin/ppapi_thread.h +++ b/chrome/ppapi_plugin/ppapi_thread.h @@ -12,6 +12,8 @@ #include "base/scoped_ptr.h" #include "build/build_config.h" #include "chrome/common/child_thread.h" +#include "ppapi/c/pp_module.h" +#include "ppapi/proxy/dispatcher.h" class FilePath; @@ -35,35 +37,27 @@ class PpapiThread : public ChildThread { virtual bool OnMessageReceived(const IPC::Message& msg); // Message handlers. - void OnMsgLoadPlugin(base::ProcessHandle renderer_handle, - const FilePath& path, - int renderer_id); - - bool LoadPluginLib(base::ProcessHandle host_process_handle, - const FilePath& path); + void OnMsgLoadPlugin(const FilePath& path); + void OnMsgCreateChannel(base::ProcessHandle host_process_handle, + int renderer_id); // 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, + bool SetupRendererChannel(base::ProcessHandle host_process_handle, + 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_; + pp::proxy::Dispatcher::GetInterfaceFunc get_plugin_interface_; -#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 + // Local concept of the module ID. Some functions take this. It's necessary + // for the in-process PPAPI to handle this properly, but for proxied it's + // unnecessary. The proxy talking to multiple renderers means that each + // renderer has a different idea of what the module ID is for this plugin. + // To force people to "do the right thing" we generate a random module ID + // and pass it around as necessary. + PP_Module local_pp_module_; DISALLOW_COPY_AND_ASSIGN(PpapiThread); }; |