Index: chrome/ppapi_plugin/ppapi_thread.cc |
=================================================================== |
--- chrome/ppapi_plugin/ppapi_thread.cc (revision 0) |
+++ chrome/ppapi_plugin/ppapi_thread.cc (revision 0) |
@@ -0,0 +1,136 @@ |
+// 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 |
Property changes on: chrome/ppapi_plugin/ppapi_thread.cc |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |