diff options
author | bbudge@chromium.org <bbudge@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-21 23:07:04 +0000 |
---|---|---|
committer | bbudge@chromium.org <bbudge@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-21 23:07:04 +0000 |
commit | e46177921cafffdf8d911d92388f6d3b66483817 (patch) | |
tree | 7857dafa96f2eb9b76e1a013a875abc9d1120ac0 | |
parent | a86c93c574d51e430b89b41a18f72924614ade6e (diff) | |
download | chromium_src-e46177921cafffdf8d911d92388f6d3b66483817.zip chromium_src-e46177921cafffdf8d911d92388f6d3b66483817.tar.gz chromium_src-e46177921cafffdf8d911d92388f6d3b66483817.tar.bz2 |
Add an IPC channel between the NaCl loader process and the renderer.
BUG=116317
TEST=manual
Review URL: https://chromiumcodereview.appspot.com/10214007
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@143483 0039d316-1c4b-4281-b951-d872f2087c98
19 files changed, 339 insertions, 37 deletions
diff --git a/chrome/browser/nacl_host/nacl_process_host.cc b/chrome/browser/nacl_host/nacl_process_host.cc index 1def1fe..161361e 100644 --- a/chrome/browser/nacl_host/nacl_process_host.cc +++ b/chrome/browser/nacl_host/nacl_process_host.cc @@ -145,6 +145,9 @@ NaClProcessHost::NaClProcessHost(const GURL& manifest_url, bool off_the_record) getenv("NACL_UNTRUSTED_EXCEPTION_HANDLING") != NULL) { enable_exception_handling_ = true; } + + enable_ipc_proxy_ = CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableNaClIPCProxy); } NaClProcessHost::~NaClProcessHost() { @@ -537,6 +540,8 @@ bool NaClProcessHost::OnMessageReceived(const IPC::Message& msg) { IPC_MESSAGE_HANDLER_DELAY_REPLY(NaClProcessMsg_AttachDebugExceptionHandler, OnAttachDebugExceptionHandler) #endif + IPC_MESSAGE_HANDLER(NaClProcessHostMsg_PpapiChannelCreated, + OnPpapiChannelCreated) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; @@ -556,7 +561,8 @@ void NaClProcessHost::OnResourcesReady() { } } -bool NaClProcessHost::ReplyToRenderer() { +bool NaClProcessHost::ReplyToRenderer( + const IPC::ChannelHandle& channel_handle) { std::vector<nacl::FileDescriptor> handles_for_renderer; for (size_t i = 0; i < internal_->sockets_for_renderer.size(); i++) { #if defined(OS_WIN) @@ -600,7 +606,7 @@ bool NaClProcessHost::ReplyToRenderer() { #endif ChromeViewHostMsg_LaunchNaCl::WriteReplyParams( - reply_msg_, handles_for_renderer); + reply_msg_, handles_for_renderer, channel_handle); chrome_render_message_filter_->Send(reply_msg_); chrome_render_message_filter_ = NULL; reply_msg_ = NULL; @@ -618,6 +624,7 @@ bool NaClProcessHost::StartNaClExecution() { params.enable_exception_handling = enable_exception_handling_; params.enable_debug_stub = CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableNaClDebug); + params.enable_ipc_proxy = enable_ipc_proxy_; base::PlatformFile irt_file = nacl_browser->IrtFile(); CHECK_NE(irt_file, base::kInvalidPlatformFileValue); @@ -665,7 +672,17 @@ bool NaClProcessHost::StartNaClExecution() { } bool NaClProcessHost::SendStart() { - return ReplyToRenderer() && StartNaClExecution(); + if (!enable_ipc_proxy_) { + if (!ReplyToRenderer(IPC::ChannelHandle())) + return false; + } + return StartNaClExecution(); +} + +void NaClProcessHost::OnPpapiChannelCreated( + const IPC::ChannelHandle& channel_handle) { + DCHECK(enable_ipc_proxy_); + ReplyToRenderer(channel_handle); } bool NaClProcessHost::StartWithLaunchedProcess() { diff --git a/chrome/browser/nacl_host/nacl_process_host.h b/chrome/browser/nacl_host/nacl_process_host.h index 4ab9413a..3a2d5fb 100644 --- a/chrome/browser/nacl_host/nacl_process_host.h +++ b/chrome/browser/nacl_host/nacl_process_host.h @@ -17,6 +17,7 @@ #include "chrome/common/nacl_types.h" #include "content/public/browser/browser_child_process_host_delegate.h" #include "googleurl/src/gurl.h" +#include "ipc/ipc_channel_handle.h" class ChromeRenderMessageFilter; class CommandLine; @@ -86,7 +87,7 @@ class NaClProcessHost : public content::BrowserChildProcessHostDelegate { // Sends the reply message to the renderer who is waiting for the plugin // to load. Returns true on success. - bool ReplyToRenderer(); + bool ReplyToRenderer(const IPC::ChannelHandle& channel_handle); // Sends the message to the NaCl process to load the plugin. Returns true // on success. @@ -113,6 +114,8 @@ class NaClProcessHost : public content::BrowserChildProcessHostDelegate { IPC::Message* reply_msg); #endif + void OnPpapiChannelCreated(const IPC::ChannelHandle& channel_handle); + GURL manifest_url_; #if defined(OS_WIN) @@ -152,6 +155,8 @@ class NaClProcessHost : public content::BrowserChildProcessHostDelegate { bool off_the_record_; + bool enable_ipc_proxy_; + DISALLOW_COPY_AND_ASSIGN(NaClProcessHost); }; diff --git a/chrome/common/nacl_messages.h b/chrome/common/nacl_messages.h index 7a6f012..57d5e10 100644 --- a/chrome/common/nacl_messages.h +++ b/chrome/common/nacl_messages.h @@ -7,6 +7,7 @@ // Multiply-included message file, no traditional include guard. #include "base/process.h" #include "chrome/common/nacl_types.h" +#include "ipc/ipc_channel_handle.h" #include "ipc/ipc_message_macros.h" #define IPC_MESSAGE_START NaClMsgStart @@ -18,6 +19,7 @@ IPC_STRUCT_TRAITS_BEGIN(nacl::NaClStartParams) IPC_STRUCT_TRAITS_MEMBER(version) IPC_STRUCT_TRAITS_MEMBER(enable_exception_handling) IPC_STRUCT_TRAITS_MEMBER(enable_debug_stub) + IPC_STRUCT_TRAITS_MEMBER(enable_ipc_proxy) IPC_STRUCT_TRAITS_END() //----------------------------------------------------------------------------- @@ -72,3 +74,9 @@ IPC_SYNC_MESSAGE_CONTROL1_1(NaClProcessMsg_QueryKnownToValidate, // database in the browser. IPC_MESSAGE_CONTROL1(NaClProcessMsg_SetKnownToValidate, std::string /* A validation signature */) + +// Notify the browser process that the server side of the PPAPI channel was +// created successfully. +IPC_MESSAGE_CONTROL1(NaClProcessHostMsg_PpapiChannelCreated, + IPC::ChannelHandle /* channel_handle */) + diff --git a/chrome/common/nacl_types.h b/chrome/common/nacl_types.h index 86ed0d0..649436d 100644 --- a/chrome/common/nacl_types.h +++ b/chrome/common/nacl_types.h @@ -55,6 +55,7 @@ struct NaClStartParams { bool enable_exception_handling; bool enable_debug_stub; + bool enable_ipc_proxy; }; } // namespace nacl diff --git a/chrome/common/render_messages.h b/chrome/common/render_messages.h index ff023cf..c4191ca 100644 --- a/chrome/common/render_messages.h +++ b/chrome/common/render_messages.h @@ -26,6 +26,7 @@ #include "chrome/common/translate_errors.h" #include "content/public/common/common_param_traits.h" #include "content/public/common/webkit_param_traits.h" +#include "ipc/ipc_channel_handle.h" #include "ipc/ipc_message_macros.h" #include "ipc/ipc_platform_file.h" #include "third_party/skia/include/core/SkBitmap.h" @@ -485,12 +486,14 @@ IPC_MESSAGE_ROUTED3(ChromeViewHostMsg_ForwardMessageToExternalHost, // A renderer sends this to the browser process when it wants to start // a new instance of the Native Client process. The browser will launch -// the process and return a handle to an IMC channel. -IPC_SYNC_MESSAGE_CONTROL2_1(ChromeViewHostMsg_LaunchNaCl, +// the process and return an IPC channel handle. This handle will only +// be valid if the NaCl IPC proxy is enabled. +IPC_SYNC_MESSAGE_CONTROL2_2(ChromeViewHostMsg_LaunchNaCl, GURL /* manifest_url */, int /* socket count */, std::vector<nacl::FileDescriptor> - /* imc channel handles */) + /* imc channel handles */, + IPC::ChannelHandle /* ipc_channel_handle */) // Notification that the page has an OpenSearch description document // associated with it. diff --git a/chrome/nacl/nacl_ipc_adapter.cc b/chrome/nacl/nacl_ipc_adapter.cc index f76fa0d..f915a6a 100644 --- a/chrome/nacl/nacl_ipc_adapter.cc +++ b/chrome/nacl/nacl_ipc_adapter.cc @@ -74,6 +74,7 @@ ssize_t NaClDescCustomRecvMsg(void* handle, NaClImcTypedMsgHdr* msg, int /* flags */) { if (msg->iov_length != 1) return -1; + msg->ndesc_length = 0; // Messages with descriptors aren't supported yet. return static_cast<ssize_t>( ToAdapter(handle)->BlockingReceive(static_cast<char*>(msg->iov[0].base), msg->iov[0].length)); @@ -281,6 +282,12 @@ NaClDesc* NaClIPCAdapter::MakeNaClDesc() { return MakeNaClDescCustom(this); } +#if defined(OS_POSIX) +int NaClIPCAdapter::TakeClientFileDescriptor() { + return io_thread_data_.channel_->TakeClientFileDescriptor(); +} +#endif + bool NaClIPCAdapter::OnMessageReceived(const IPC::Message& message) { { base::AutoLock lock(lock_); diff --git a/chrome/nacl/nacl_ipc_adapter.h b/chrome/nacl/nacl_ipc_adapter.h index 12500cd..8c3c493 100644 --- a/chrome/nacl/nacl_ipc_adapter.h +++ b/chrome/nacl/nacl_ipc_adapter.h @@ -77,6 +77,10 @@ class NaClIPCAdapter : public base::RefCountedThreadSafe<NaClIPCAdapter>, // NaClDesc is reference-counted, and a reference is returned. NaClDesc* MakeNaClDesc(); +#if defined(OS_POSIX) + int TakeClientFileDescriptor(); +#endif + // Listener implementation. virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; virtual void OnChannelConnected(int32 peer_pid) OVERRIDE; diff --git a/chrome/nacl/nacl_listener.cc b/chrome/nacl/nacl_listener.cc index a5433dc..7159749 100644 --- a/chrome/nacl/nacl_listener.cc +++ b/chrome/nacl/nacl_listener.cc @@ -13,13 +13,19 @@ #include "base/message_loop.h" #include "base/rand_util.h" #include "chrome/common/nacl_messages.h" +#include "chrome/nacl/nacl_ipc_adapter.h" #include "chrome/nacl/nacl_validation_db.h" #include "chrome/nacl/nacl_validation_query.h" +#include "ipc/ipc_channel_handle.h" +#include "ipc/ipc_switches.h" #include "ipc/ipc_sync_channel.h" #include "ipc/ipc_sync_message_filter.h" -#include "ipc/ipc_switches.h" #include "native_client/src/trusted/service_runtime/sel_main_chrome.h" +#if defined(OS_POSIX) +#include "base/file_descriptor_posix.h" +#endif + #if defined(OS_LINUX) #include "content/public/common/child_process_sandbox_support_linux.h" #endif @@ -188,6 +194,25 @@ void NaClListener::OnMsgStart(const nacl::NaClStartParams& params) { return; } + if (params.enable_ipc_proxy) { + // Create the server side of the channel and notify the process host so it + // can reply to the renderer, which will connect as client. + IPC::ChannelHandle channel_handle = + IPC::Channel::GenerateVerifiedChannelID("nacl"); + + scoped_refptr<NaClIPCAdapter> ipc_adapter(new NaClIPCAdapter( + channel_handle, io_thread_.message_loop_proxy())); + args->initial_ipc_desc = ipc_adapter.get()->MakeNaClDesc(); + +#if defined(OS_POSIX) + channel_handle.socket = base::FileDescriptor( + ipc_adapter.get()->TakeClientFileDescriptor(), true); +#endif + + if (!Send(new NaClProcessHostMsg_PpapiChannelCreated(channel_handle))) + LOG(ERROR) << "Failed to send IPC channel handle to renderer."; + } + std::vector<nacl::FileDescriptor> handles = params.handles; #if defined(OS_LINUX) || defined(OS_MACOSX) diff --git a/chrome/renderer/pepper/ppb_nacl_private_impl.cc b/chrome/renderer/pepper/ppb_nacl_private_impl.cc index b646065..6589d56 100644 --- a/chrome/renderer/pepper/ppb_nacl_private_impl.cc +++ b/chrome/renderer/pepper/ppb_nacl_private_impl.cc @@ -9,17 +9,36 @@ #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 { @@ -28,16 +47,24 @@ base::LazyInstance<scoped_refptr<IPC::SyncMessageFilter> > // Launch NaCl's sel_ldr process. PP_Bool LaunchSelLdr(PP_Instance instance, - const char* alleged_url, int socket_count, - void* imc_handles) { + const char* alleged_url, + int socket_count, + void* imc_handles, + void** ipc_channel_handle) { std::vector<nacl::FileDescriptor> sockets; IPC::Sender* sender = content::RenderThread::Get(); if (sender == NULL) sender = g_background_thread_sender.Pointer()->get(); + scoped_ptr<IPC::ChannelHandle> channel_handle(new IPC::ChannelHandle); if (!sender->Send(new ChromeViewHostMsg_LaunchNaCl( - GURL(alleged_url), socket_count, &sockets))) + GURL(alleged_url), socket_count, &sockets, + channel_handle.get()))) { + *ipc_channel_handle = NULL; return PP_FALSE; + } + + *ipc_channel_handle = channel_handle.release(); CHECK(static_cast<int>(sockets.size()) == socket_count); for (int i = 0; i < socket_count; i++) { @@ -48,7 +75,150 @@ PP_Bool LaunchSelLdr(PP_Instance instance, return PP_TRUE; } -PP_Bool StartPpapiProxy(PP_Instance instance) { +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) { + if (channel_handle.name.empty()) + return false; + +#if defined(OS_POSIX) + DCHECK_NE(-1, channel_handle.socket.fd); + if (channel_handle.socket.fd == -1) + return false; +#endif + + 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, + void* ipc_channel_handle) { + if (CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableNaClIPCProxy)) { + scoped_ptr<IPC::ChannelHandle> channel_handle( + static_cast<IPC::ChannelHandle*>(ipc_channel_handle)); + if (channel_handle->name.empty()) + return PP_FALSE; + + 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; } diff --git a/ppapi/c/private/ppb_nacl_private.h b/ppapi/c/private/ppb_nacl_private.h index dc7e7a2..06b900e 100644 --- a/ppapi/c/private/ppb_nacl_private.h +++ b/ppapi/c/private/ppb_nacl_private.h @@ -15,17 +15,21 @@ struct PPB_NaCl_Private { // This function launches NaCl's sel_ldr process. On success, the function // returns true, otherwise it returns false. When it returns true, it will - // write |socket_count| nacl::Handles to imc_handles. Unless + // write |socket_count| nacl::Handles to imc_handles. |ipc_channel_handle| + // will point to information needed to start the IPC proxy. Unless // EnableBackgroundSelLdrLaunch is called, this method must be invoked from // the main thread. PP_Bool (*LaunchSelLdr)(PP_Instance instance, const char* alleged_url, int socket_count, - void* imc_handles); + void* imc_handles, + void** ipc_channel_handle); // This function starts the PPAPI proxy so the nexe can communicate with the - // browser's renderer process. - PP_Bool (*StartPpapiProxy)(PP_Instance instance); + // browser's renderer process. |ipc_channel_handle| is the pointer returned + // by the call to LaunchSelLdr. + PP_Bool (*StartPpapiProxy)(PP_Instance instance, + void* ipc_channel_handle); // On POSIX systems, this function returns the file descriptor of // /dev/urandom. On non-POSIX systems, this function returns 0. diff --git a/ppapi/native_client/src/trusted/plugin/nacl_entry_points.h b/ppapi/native_client/src/trusted/plugin/nacl_entry_points.h index 3723394..eb66b8f 100644 --- a/ppapi/native_client/src/trusted/plugin/nacl_entry_points.h +++ b/ppapi/native_client/src/trusted/plugin/nacl_entry_points.h @@ -19,12 +19,10 @@ typedef bool (*LaunchNaClProcessFunc)(PP_Instance instance, const char* url, int socket_count, - nacl::Handle* result_sockets); - -typedef bool (*StartPpapiProxyFunc)(PP_Instance instance); + nacl::Handle* result_sockets, + void** ipc_channel_handle); extern LaunchNaClProcessFunc launch_nacl_process; -extern StartPpapiProxyFunc start_ppapi_proxy; #endif // NATIVE_CLIENT_SRC_TRUSTED_PLUGIN_NACL_ENTRY_POINTS_H_ diff --git a/ppapi/native_client/src/trusted/plugin/plugin.cc b/ppapi/native_client/src/trusted/plugin/plugin.cc index 891df69..2bfc50e 100644 --- a/ppapi/native_client/src/trusted/plugin/plugin.cc +++ b/ppapi/native_client/src/trusted/plugin/plugin.cc @@ -34,6 +34,7 @@ #include "native_client/src/trusted/desc/nacl_desc_wrapper.h" #include "native_client/src/trusted/nonnacl_util/sel_ldr_launcher.h" #include "native_client/src/trusted/plugin/json_manifest.h" +#include "native_client/src/trusted/plugin/nacl_entry_points.h" #include "native_client/src/trusted/plugin/nacl_subprocess.h" #include "native_client/src/trusted/plugin/nexe_arch.h" #include "native_client/src/trusted/plugin/plugin_error.h" @@ -54,6 +55,7 @@ #include "ppapi/c/ppp_input_event.h" #include "ppapi/c/ppp_instance.h" #include "ppapi/c/ppp_mouse_lock.h" +#include "ppapi/c/private/ppb_nacl_private.h" #include "ppapi/c/private/ppb_uma_private.h" #include "ppapi/cpp/dev/find_dev.h" #include "ppapi/cpp/dev/printing_dev.h" @@ -120,6 +122,13 @@ const int64_t kSizeKBMin = 1; const int64_t kSizeKBMax = 512*1024; // very large .nexe const uint32_t kSizeKBBuckets = 100; +const PPB_NaCl_Private* GetNaclInterface() { + pp::Module *module = pp::Module::Get(); + CHECK(module); + return static_cast<const PPB_NaCl_Private*>( + module->GetBrowserInterface(PPB_NACL_PRIVATE_INTERFACE)); +} + const PPB_UMA_Private* GetUMAInterface() { pp::Module *module = pp::Module::Get(); CHECK(module); @@ -602,13 +611,32 @@ bool Plugin::LoadNaClModuleCommon(nacl::DescWrapper* wrapper, return false; } + void* ipc_channel_handle = NULL; bool service_runtime_started = - new_service_runtime->Start(wrapper, error_info, manifest_base_url()); + new_service_runtime->Start(wrapper, + error_info, + manifest_base_url(), + &ipc_channel_handle); + nacl::scoped_ptr<char> ipc_channel_handle_ptr( + reinterpret_cast<char*>(ipc_channel_handle)); PLUGIN_PRINTF(("Plugin::LoadNaClModuleCommon (service_runtime_started=%d)\n", service_runtime_started)); if (!service_runtime_started) { return false; } + + // Try to start the Chrome IPC-based proxy. + const PPB_NaCl_Private* ppb_nacl = GetNaclInterface(); + if (ppb_nacl->StartPpapiProxy( + pp_instance(), + reinterpret_cast<void*>(ipc_channel_handle_ptr.release()))) { + using_ipc_proxy_ = true; + // We need to explicitly schedule this here. It is normally called in + // response to starting the SRPC proxy. + CHECK(init_done_cb.pp_completion_callback().func != NULL); + PLUGIN_PRINTF(("Plugin::LoadNaClModuleCommon, started ipc proxy.\n")); + pp::Module::Get()->core()->CallOnMainThread(0, init_done_cb, PP_OK); + } return true; } @@ -631,6 +659,11 @@ bool Plugin::LoadNaClModule(nacl::DescWrapper* wrapper, } bool Plugin::LoadNaClModuleContinuationIntern(ErrorInfo* error_info) { + // If we are using the IPC proxy, StartSrpcServices and StartJSObjectProxy + // don't makes sense. Return 'true' so that the plugin continues loading. + if (using_ipc_proxy_) + return true; + if (!main_subprocess_.StartSrpcServices()) { error_info->SetReport(ERROR_SRPC_CONNECTION_FAIL, "SRPC connection failure for " + @@ -862,7 +895,8 @@ Plugin::Plugin(PP_Instance pp_instance) init_time_(0), ready_time_(0), nexe_size_(0), - time_of_last_progress_event_(0) { + time_of_last_progress_event_(0), + using_ipc_proxy_(false) { PLUGIN_PRINTF(("Plugin::Plugin (this=%p, pp_instance=%" NACL_PRId32")\n", static_cast<void*>(this), pp_instance)); callback_factory_.Initialize(this); diff --git a/ppapi/native_client/src/trusted/plugin/plugin.h b/ppapi/native_client/src/trusted/plugin/plugin.h index cd79517..1a709d8 100644 --- a/ppapi/native_client/src/trusted/plugin/plugin.h +++ b/ppapi/native_client/src/trusted/plugin/plugin.h @@ -517,6 +517,9 @@ class Plugin : public pp::InstancePrivate { const FileDownloader* FindFileDownloader(PP_Resource url_loader) const; int64_t time_of_last_progress_event_; + + // Whether we are using IPC-based PPAPI proxy. + bool using_ipc_proxy_; }; } // namespace plugin diff --git a/ppapi/native_client/src/trusted/plugin/sel_ldr_launcher_chrome.cc b/ppapi/native_client/src/trusted/plugin/sel_ldr_launcher_chrome.cc index d301612..140e0d8 100644 --- a/ppapi/native_client/src/trusted/plugin/sel_ldr_launcher_chrome.cc +++ b/ppapi/native_client/src/trusted/plugin/sel_ldr_launcher_chrome.cc @@ -11,10 +11,12 @@ LaunchNaClProcessFunc launch_nacl_process = NULL; namespace plugin { bool SelLdrLauncherChrome::Start(const char* url) { - return Start(0, url); + return Start(0, url, NULL); } -bool SelLdrLauncherChrome::Start(PP_Instance instance, const char* url) { +bool SelLdrLauncherChrome::Start(PP_Instance instance, + const char* url, + void** ipc_channel_handle) { // send a synchronous message to the browser process // TODO(sehr): This is asserted to be one. Remove this parameter. static const int kNumberOfChannelsToBeCreated = 1; @@ -22,7 +24,8 @@ bool SelLdrLauncherChrome::Start(PP_Instance instance, const char* url) { !launch_nacl_process(instance, url, kNumberOfChannelsToBeCreated, - &channel_)) { + &channel_, + ipc_channel_handle)) { return false; } return true; diff --git a/ppapi/native_client/src/trusted/plugin/sel_ldr_launcher_chrome.h b/ppapi/native_client/src/trusted/plugin/sel_ldr_launcher_chrome.h index e479499..15ce771 100644 --- a/ppapi/native_client/src/trusted/plugin/sel_ldr_launcher_chrome.h +++ b/ppapi/native_client/src/trusted/plugin/sel_ldr_launcher_chrome.h @@ -13,7 +13,9 @@ namespace plugin { class SelLdrLauncherChrome : public nacl::SelLdrLauncherBase { public: virtual bool Start(const char* url); - virtual bool Start(PP_Instance instance, const char* url); + bool Start(PP_Instance instance, + const char* url, + void** ipc_channel_handle); }; } // namespace plugin diff --git a/ppapi/native_client/src/trusted/plugin/service_runtime.cc b/ppapi/native_client/src/trusted/plugin/service_runtime.cc index 5c3b4fd..4177cf1 100644 --- a/ppapi/native_client/src/trusted/plugin/service_runtime.cc +++ b/ppapi/native_client/src/trusted/plugin/service_runtime.cc @@ -623,7 +623,9 @@ bool ServiceRuntime::InitCommunication(nacl::DescWrapper* nacl_desc, } bool ServiceRuntime::Start(nacl::DescWrapper* nacl_desc, - ErrorInfo* error_info, const nacl::string& url) { + ErrorInfo* error_info, + const nacl::string& url, + void** ipc_channel_handle) { PLUGIN_PRINTF(("ServiceRuntime::Start (nacl_desc=%p)\n", reinterpret_cast<void*>(nacl_desc))); @@ -643,7 +645,9 @@ bool ServiceRuntime::Start(nacl::DescWrapper* nacl_desc, #ifdef NACL_STANDALONE bool started = tmp_subprocess->Start(url.c_str()); #else - bool started = tmp_subprocess->Start(plugin_->pp_instance(), url.c_str()); + bool started = tmp_subprocess->Start(plugin_->pp_instance(), + url.c_str(), + ipc_channel_handle); #endif if (!started) { PLUGIN_PRINTF(("ServiceRuntime::Start (start failed)\n")); diff --git a/ppapi/native_client/src/trusted/plugin/service_runtime.h b/ppapi/native_client/src/trusted/plugin/service_runtime.h index 554942a..8c9b55c 100644 --- a/ppapi/native_client/src/trusted/plugin/service_runtime.h +++ b/ppapi/native_client/src/trusted/plugin/service_runtime.h @@ -216,10 +216,12 @@ class ServiceRuntime { // Spawn a sel_ldr instance and establish an SrpcClient to it. The nexe // to be started is passed through |nacl_file_desc|. On success, returns // true. On failure, returns false and |error_string| is set to something - // describing the error. + // describing the error. |ipc_channel_handle| returns information for + // connecting the Chrome IPC-based proxy. bool Start(nacl::DescWrapper* nacl_file_desc, ErrorInfo* error_info, - const nacl::string& url); + const nacl::string& url, + void** ipc_channel_handle); // Starts the application channel to the nexe. SrpcClient* SetupAppChannel(); diff --git a/webkit/plugins/ppapi/plugin_module.cc b/webkit/plugins/ppapi/plugin_module.cc index a16f79a..423209f 100644 --- a/webkit/plugins/ppapi/plugin_module.cc +++ b/webkit/plugins/ppapi/plugin_module.cc @@ -419,7 +419,8 @@ PluginModule::PluginModule(const std::string& name, library_(NULL), name_(name), path_(path), - reserve_instance_id_(NULL) { + reserve_instance_id_(NULL), + nacl_ipc_proxy_(false) { // Ensure the globals object is created. if (!host_globals) host_globals = new HostGlobals; @@ -496,9 +497,13 @@ void PluginModule::InitAsProxied( } void PluginModule::InitAsProxiedNaCl( - PluginDelegate::OutOfProcessProxy* out_of_process_proxy, + scoped_ptr<PluginDelegate::OutOfProcessProxy> out_of_process_proxy, PP_Instance instance) { - InitAsProxied(out_of_process_proxy); + // TODO(bbudge) We need to switch the mode of the PluginModule on a + // per-instance basis. Fix this so out_of_process_proxy and other + // state is stored in a map, indexed by instance. + nacl_ipc_proxy_ = true; + InitAsProxied(out_of_process_proxy.release()); // InitAsProxied (for the trusted/out-of-process case) initializes only the // module, and one or more instances are added later. In this case, the // PluginInstance was already created as in-process, so we missed the proxy @@ -560,6 +565,11 @@ void PluginModule::InstanceDeleted(PluginInstance* instance) { if (out_of_process_proxy_.get()) out_of_process_proxy_->RemoveInstance(instance->pp_instance()); instances_.erase(instance); + + if (nacl_ipc_proxy_) { + out_of_process_proxy_.reset(); + reserve_instance_id_ = NULL; + } } scoped_refptr< ::ppapi::CallbackTracker> PluginModule::GetCallbackTracker() { diff --git a/webkit/plugins/ppapi/plugin_module.h b/webkit/plugins/ppapi/plugin_module.h index d9b0162..d9d78ba 100644 --- a/webkit/plugins/ppapi/plugin_module.h +++ b/webkit/plugins/ppapi/plugin_module.h @@ -90,7 +90,7 @@ class WEBKIT_PLUGINS_EXPORT PluginModule : // Initializes this module for the given NaCl proxy. This takes // ownership of the given pointer, even in the failure case. void InitAsProxiedNaCl( - PluginDelegate::OutOfProcessProxy* out_of_process_proxy, + scoped_ptr<PluginDelegate::OutOfProcessProxy> out_of_process_proxy, PP_Instance instance); static const PPB_Core* GetCore(); @@ -203,6 +203,8 @@ class WEBKIT_PLUGINS_EXPORT PluginModule : PP_Bool (*reserve_instance_id_)(PP_Module, PP_Instance); + bool nacl_ipc_proxy_; + DISALLOW_COPY_AND_ASSIGN(PluginModule); }; |