| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 
|  | 2 // Use of this source code is governed by a BSD-style license that can be | 
|  | 3 // found in the LICENSE file. | 
|  | 4 | 
|  | 5 #include "chrome/ppapi_plugin/ppapi_thread.h" | 
|  | 6 | 
|  | 7 #include "base/process_util.h" | 
|  | 8 #include "chrome/common/child_process.h" | 
|  | 9 #include "ipc/ipc_channel_handle.h" | 
|  | 10 #include "ipc/ipc_sync_channel.h" | 
|  | 11 #include "ppapi/c/ppp.h" | 
|  | 12 #include "ppapi/proxy/plugin_dispatcher.h" | 
|  | 13 #include "ppapi/proxy/ppapi_messages.h" | 
|  | 14 | 
|  | 15 #if defined(OS_POSIX) | 
|  | 16 #include "base/eintr_wrapper.h" | 
|  | 17 #include "ipc/ipc_channel_posix.h" | 
|  | 18 #endif | 
|  | 19 | 
|  | 20 PpapiThread::PpapiThread() | 
|  | 21     : | 
|  | 22 #if defined(OS_POSIX) | 
|  | 23     renderer_fd_(-1) | 
|  | 24 #endif | 
|  | 25     { | 
|  | 26 } | 
|  | 27 | 
|  | 28 PpapiThread::~PpapiThread() { | 
|  | 29   pp::proxy::PluginDispatcher::SetGlobal(NULL); | 
|  | 30 } | 
|  | 31 | 
|  | 32 // The "regular" ChildThread implements this function and does some standard | 
|  | 33 // dispatching, then uses the message router. We don't actually need any of | 
|  | 34 // this so this function just overrides that one. | 
|  | 35 // | 
|  | 36 // Note that this function is called only for messages from the channel to the | 
|  | 37 // browser process. Messages from the renderer process are sent via a different | 
|  | 38 // channel that ends up at Dispatcher::OnMessageReceived. | 
|  | 39 void PpapiThread::OnMessageReceived(const IPC::Message& msg) { | 
|  | 40   IPC_BEGIN_MESSAGE_MAP(PpapiThread, msg) | 
|  | 41     IPC_MESSAGE_HANDLER(PpapiMsg_LoadPlugin, OnLoadPlugin) | 
|  | 42 | 
|  | 43     // The rest of the messages go to the dispatcher. | 
|  | 44     /*IPC_MESSAGE_UNHANDLED( | 
|  | 45       if (dispatcher_.get()) | 
|  | 46         dispatcher_->OnMessageReceived(msg) | 
|  | 47     )*/ | 
|  | 48   IPC_END_MESSAGE_MAP() | 
|  | 49 } | 
|  | 50 | 
|  | 51 void PpapiThread::OnLoadPlugin(const FilePath& path, int renderer_id) { | 
|  | 52   IPC::ChannelHandle channel_handle; | 
|  | 53   if (!LoadPluginLib(path) || | 
|  | 54       !SetupRendererChannel(renderer_id, &channel_handle)) { | 
|  | 55     // An empty channel handle indicates error. | 
|  | 56     Send(new PpapiHostMsg_PluginLoaded(IPC::ChannelHandle())); | 
|  | 57     return; | 
|  | 58   } | 
|  | 59 | 
|  | 60   Send(new PpapiHostMsg_PluginLoaded(channel_handle)); | 
|  | 61 } | 
|  | 62 | 
|  | 63 bool PpapiThread::LoadPluginLib(const FilePath& path) { | 
|  | 64   base::ScopedNativeLibrary library(base::LoadNativeLibrary(path)); | 
|  | 65   if (!library.is_valid()) | 
|  | 66     return false; | 
|  | 67 | 
|  | 68   // Get the GetInterface function (required). | 
|  | 69   pp::proxy::Dispatcher::GetInterfaceFunc get_interface = | 
|  | 70       reinterpret_cast<pp::proxy::Dispatcher::GetInterfaceFunc>( | 
|  | 71           library.GetFunctionPointer("PPP_GetInterface")); | 
|  | 72   if (!get_interface) { | 
|  | 73     LOG(WARNING) << "No PPP_GetInterface in plugin library"; | 
|  | 74     return false; | 
|  | 75   } | 
|  | 76 | 
|  | 77   // Get the InitializeModule function (required). | 
|  | 78   pp::proxy::Dispatcher::InitModuleFunc init_module = | 
|  | 79       reinterpret_cast<pp::proxy::Dispatcher::InitModuleFunc>( | 
|  | 80           library.GetFunctionPointer("PPP_InitializeModule")); | 
|  | 81   if (!init_module) { | 
|  | 82     LOG(WARNING) << "No PPP_InitializeModule in plugin library"; | 
|  | 83     return false; | 
|  | 84   } | 
|  | 85 | 
|  | 86   // Get the ShutdownModule function (optional). | 
|  | 87   pp::proxy::Dispatcher::ShutdownModuleFunc shutdown_module = | 
|  | 88       reinterpret_cast<pp::proxy::Dispatcher::ShutdownModuleFunc>( | 
|  | 89           library.GetFunctionPointer("PPP_ShutdownModule")); | 
|  | 90 | 
|  | 91   library_.Reset(library.Release()); | 
|  | 92   dispatcher_.reset(new pp::proxy::PluginDispatcher(get_interface, init_module, | 
|  | 93                                                     shutdown_module)); | 
|  | 94   pp::proxy::PluginDispatcher::SetGlobal(dispatcher_.get()); | 
|  | 95   return true; | 
|  | 96 } | 
|  | 97 | 
|  | 98 bool PpapiThread::SetupRendererChannel(int renderer_id, | 
|  | 99                                        IPC::ChannelHandle* handle) { | 
|  | 100   std::string channel_key = StringPrintf( | 
|  | 101       "%d.r%d", base::GetCurrentProcId(), renderer_id); | 
|  | 102 | 
|  | 103 #if defined(OS_POSIX) | 
|  | 104   // This gets called when the PluginChannel is initially created. At this | 
|  | 105   // point, create the socketpair and assign the plugin side FD to the channel | 
|  | 106   // name. Keep the renderer side FD as a member variable in the PluginChannel | 
|  | 107   // to be able to transmit it through IPC. | 
|  | 108   int plugin_fd; | 
|  | 109   if (!IPC::SocketPair(&plugin_fd, &renderer_fd_)) | 
|  | 110     return false; | 
|  | 111   IPC::AddChannelSocket(channel_key, plugin_fd); | 
|  | 112 #endif | 
|  | 113 | 
|  | 114   if (!dispatcher_->InitWithChannel( | 
|  | 115           ChildProcess::current()->io_message_loop(), | 
|  | 116           channel_key, false, | 
|  | 117           ChildProcess::current()->GetShutDownEvent())) | 
|  | 118     return false; | 
|  | 119 | 
|  | 120   handle->name = channel_key; | 
|  | 121 #if defined(OS_POSIX) | 
|  | 122   // On POSIX, pass the renderer-side FD. | 
|  | 123   handle->socket = base::FileDescriptor(renderer_fd_, false); | 
|  | 124 #endif | 
|  | 125   return true; | 
|  | 126 } | 
|  | 127 | 
|  | 128 #if defined(OS_POSIX) | 
|  | 129 void PpapiThread::CloseRendererFD() { | 
|  | 130   if (renderer_fd_ != -1) { | 
|  | 131     if (HANDLE_EINTR(close(renderer_fd_)) < 0) | 
|  | 132       PLOG(ERROR) << "close"; | 
|  | 133     renderer_fd_ = -1; | 
|  | 134   } | 
|  | 135 } | 
|  | 136 #endif | 
| OLD | NEW | 
|---|