| Index: chrome/renderer/pepper/ppb_nacl_private_impl.cc
|
| ===================================================================
|
| --- chrome/renderer/pepper/ppb_nacl_private_impl.cc (revision 143509)
|
| +++ chrome/renderer/pepper/ppb_nacl_private_impl.cc (working copy)
|
| @@ -9,36 +9,75 @@
|
| #include "base/command_line.h"
|
| #include "base/lazy_instance.h"
|
| #include "base/logging.h"
|
| +#include "base/message_loop.h"
|
| #include "base/rand_util.h"
|
| +#include "chrome/common/chrome_switches.h"
|
| #include "chrome/common/render_messages.h"
|
| +#include "content/public/common/content_client.h"
|
| #include "content/public/common/content_switches.h"
|
| +#include "content/public/common/sandbox_init.h"
|
| #include "content/public/renderer/render_thread.h"
|
| +#include "content/public/renderer/render_view.h"
|
| #include "ipc/ipc_sync_message_filter.h"
|
| #include "ppapi/c/private/ppb_nacl_private.h"
|
| #include "ppapi/native_client/src/trusted/plugin/nacl_entry_points.h"
|
| +#include "ppapi/proxy/host_dispatcher.h"
|
| +#include "ppapi/proxy/proxy_channel.h"
|
| +#include "ppapi/shared_impl/ppapi_preferences.h"
|
| +#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
|
| +#include "third_party/WebKit/Source/WebKit/chromium/public/WebElement.h"
|
| +#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
|
| +#include "third_party/WebKit/Source/WebKit/chromium/public/WebPluginContainer.h"
|
| +#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
|
| +#include "webkit/plugins/ppapi/host_globals.h"
|
| +#include "webkit/plugins/ppapi/plugin_module.h"
|
| +#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"
|
|
|
| -#if defined(OS_WIN)
|
| -#include "content/public/common/sandbox_init.h"
|
| -#endif
|
| +using content::RenderThread;
|
| +using content::RenderView;
|
| +using webkit::ppapi::HostGlobals;
|
| +using webkit::ppapi::PluginInstance;
|
| +using webkit::ppapi::PluginDelegate;
|
| +using WebKit::WebView;
|
|
|
| namespace {
|
|
|
| base::LazyInstance<scoped_refptr<IPC::SyncMessageFilter> >
|
| g_background_thread_sender = LAZY_INSTANCE_INITIALIZER;
|
|
|
| +typedef std::map<PP_Instance, IPC::ChannelHandle> ChannelHandleMap;
|
| +
|
| +base::LazyInstance<ChannelHandleMap> g_channel_handle_map =
|
| + LAZY_INSTANCE_INITIALIZER;
|
| +
|
| // Launch NaCl's sel_ldr process.
|
| PP_Bool LaunchSelLdr(PP_Instance instance,
|
| - const char* alleged_url, int socket_count,
|
| + const char* alleged_url,
|
| + int socket_count,
|
| void* imc_handles) {
|
| std::vector<nacl::FileDescriptor> sockets;
|
| IPC::Sender* sender = content::RenderThread::Get();
|
| if (sender == NULL)
|
| sender = g_background_thread_sender.Pointer()->get();
|
|
|
| + IPC::ChannelHandle channel_handle;
|
| if (!sender->Send(new ChromeViewHostMsg_LaunchNaCl(
|
| - GURL(alleged_url), socket_count, &sockets)))
|
| + GURL(alleged_url), socket_count, &sockets,
|
| + &channel_handle))) {
|
| return PP_FALSE;
|
| + }
|
|
|
| + // Don't save invalid channel handles.
|
| + bool invalid_handle = channel_handle.name.empty();
|
| +
|
| +#if defined(OS_POSIX)
|
| + if (!invalid_handle)
|
| + invalid_handle = (channel_handle.socket.fd == -1);
|
| +#endif
|
| +
|
| + if (!invalid_handle)
|
| + g_channel_handle_map.Get()[instance] = channel_handle;
|
| +
|
| CHECK(static_cast<int>(sockets.size()) == socket_count);
|
| for (int i = 0; i < socket_count; i++) {
|
| static_cast<nacl::Handle*>(imc_handles)[i] =
|
| @@ -48,7 +87,142 @@
|
| return PP_TRUE;
|
| }
|
|
|
| +class ProxyChannelDelegate
|
| + : public ppapi::proxy::ProxyChannel::Delegate {
|
| + public:
|
| + ProxyChannelDelegate();
|
| + virtual ~ProxyChannelDelegate();
|
| +
|
| + // ProxyChannel::Delegate implementation.
|
| + virtual base::MessageLoopProxy* GetIPCMessageLoop() OVERRIDE;
|
| + virtual base::WaitableEvent* GetShutdownEvent() OVERRIDE;
|
| + virtual IPC::PlatformFileForTransit ShareHandleWithRemote(
|
| + base::PlatformFile handle,
|
| + const IPC::SyncChannel& channel,
|
| + bool should_close_source) OVERRIDE;
|
| + private:
|
| + // TODO(bbudge) Modify the content public API so we can get
|
| + // the renderer process's shutdown event.
|
| + base::WaitableEvent shutdown_event_;
|
| +};
|
| +
|
| +ProxyChannelDelegate::ProxyChannelDelegate()
|
| + : shutdown_event_(true, false) {
|
| +}
|
| +
|
| +ProxyChannelDelegate::~ProxyChannelDelegate() {
|
| +}
|
| +
|
| +base::MessageLoopProxy* ProxyChannelDelegate::GetIPCMessageLoop() {
|
| + return RenderThread::Get()->GetIOMessageLoopProxy().get();
|
| +}
|
| +
|
| +base::WaitableEvent* ProxyChannelDelegate::GetShutdownEvent() {
|
| + return &shutdown_event_;
|
| +}
|
| +
|
| +IPC::PlatformFileForTransit ProxyChannelDelegate::ShareHandleWithRemote(
|
| + base::PlatformFile handle,
|
| + const IPC::SyncChannel& channel,
|
| + bool should_close_source) {
|
| + return content::BrokerGetFileHandleForProcess(handle, channel.peer_pid(),
|
| + should_close_source);
|
| +}
|
| +
|
| +// Stubbed out SyncMessageStatusReceiver, required by HostDispatcher.
|
| +// TODO(bbudge) Use a content::PepperHungPluginFilter instead.
|
| +class SyncMessageStatusReceiver
|
| + : public ppapi::proxy::HostDispatcher::SyncMessageStatusReceiver {
|
| + public:
|
| + SyncMessageStatusReceiver() {}
|
| +
|
| + // SyncMessageStatusReceiver implementation.
|
| + virtual void BeginBlockOnSyncMessage() OVERRIDE {}
|
| + virtual void EndBlockOnSyncMessage() OVERRIDE {}
|
| +
|
| + private:
|
| + virtual ~SyncMessageStatusReceiver() {}
|
| +};
|
| +
|
| +class OutOfProcessProxy : public PluginDelegate::OutOfProcessProxy {
|
| + public:
|
| + OutOfProcessProxy() {}
|
| + virtual ~OutOfProcessProxy() {}
|
| +
|
| + bool Init(const IPC::ChannelHandle& channel_handle,
|
| + PP_Module pp_module,
|
| + PP_GetInterface_Func local_get_interface,
|
| + const ppapi::Preferences& preferences,
|
| + SyncMessageStatusReceiver* status_receiver) {
|
| + dispatcher_delegate_.reset(new ProxyChannelDelegate);
|
| + dispatcher_.reset(new ppapi::proxy::HostDispatcher(
|
| + pp_module, local_get_interface, status_receiver));
|
| +
|
| + if (!dispatcher_->InitHostWithChannel(dispatcher_delegate_.get(),
|
| + channel_handle,
|
| + true, // Client.
|
| + preferences)) {
|
| + dispatcher_.reset();
|
| + dispatcher_delegate_.reset();
|
| + return false;
|
| + }
|
| +
|
| + return true;
|
| + }
|
| +
|
| + // OutOfProcessProxy implementation.
|
| + virtual const void* GetProxiedInterface(const char* name) OVERRIDE {
|
| + return dispatcher_->GetProxiedInterface(name);
|
| + }
|
| + virtual void AddInstance(PP_Instance instance) OVERRIDE {
|
| + ppapi::proxy::HostDispatcher::SetForInstance(instance, dispatcher_.get());
|
| + }
|
| + virtual void RemoveInstance(PP_Instance instance) OVERRIDE {
|
| + ppapi::proxy::HostDispatcher::RemoveForInstance(instance);
|
| + }
|
| +
|
| + private:
|
| + scoped_ptr<ppapi::proxy::HostDispatcher> dispatcher_;
|
| + scoped_ptr<ppapi::proxy::ProxyChannel::Delegate> dispatcher_delegate_;
|
| +};
|
| +
|
| PP_Bool StartPpapiProxy(PP_Instance instance) {
|
| + if (CommandLine::ForCurrentProcess()->HasSwitch(
|
| + switches::kEnableNaClIPCProxy)) {
|
| + ChannelHandleMap& map = g_channel_handle_map.Get();
|
| + ChannelHandleMap::iterator it = map.find(instance);
|
| + if (it == map.end())
|
| + return PP_FALSE;
|
| + IPC::ChannelHandle channel_handle = it->second;
|
| + map.erase(it);
|
| +
|
| + webkit::ppapi::PluginInstance* plugin_instance =
|
| + content::GetHostGlobals()->GetInstance(instance);
|
| + if (!plugin_instance)
|
| + return PP_FALSE;
|
| +
|
| + WebView* web_view =
|
| + plugin_instance->container()->element().document().frame()->view();
|
| + RenderView* render_view = content::RenderView::FromWebView(web_view);
|
| +
|
| + webkit::ppapi::PluginModule* plugin_module = plugin_instance->module();
|
| +
|
| + scoped_refptr<SyncMessageStatusReceiver>
|
| + status_receiver(new SyncMessageStatusReceiver());
|
| + scoped_ptr<OutOfProcessProxy> out_of_process_proxy(new OutOfProcessProxy);
|
| + if (out_of_process_proxy->Init(
|
| + channel_handle,
|
| + plugin_module->pp_module(),
|
| + webkit::ppapi::PluginModule::GetLocalGetInterfaceFunc(),
|
| + ppapi::Preferences(render_view->GetWebkitPreferences()),
|
| + status_receiver.get())) {
|
| + plugin_module->InitAsProxiedNaCl(
|
| + out_of_process_proxy.PassAs<PluginDelegate::OutOfProcessProxy>(),
|
| + instance);
|
| + return PP_TRUE;
|
| + }
|
| + }
|
| +
|
| return PP_FALSE;
|
| }
|
|
|
|
|