diff options
author | bbudge@chromium.org <bbudge@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-30 19:47:38 +0000 |
---|---|---|
committer | bbudge@chromium.org <bbudge@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-30 19:47:38 +0000 |
commit | 8510d2832f673410e30165cbe0ab7dfbb4710e6a (patch) | |
tree | b51713e3264faca51726185587d7edf568dda6ed /chrome | |
parent | 031afc6601b016abd3f36cc4bdb877ae74ac2e2f (diff) | |
download | chromium_src-8510d2832f673410e30165cbe0ab7dfbb4710e6a.zip chromium_src-8510d2832f673410e30165cbe0ab7dfbb4710e6a.tar.gz chromium_src-8510d2832f673410e30165cbe0ab7dfbb4710e6a.tar.bz2 |
Change NaCl IPC PPAPI proxy startup to support a NaCl-Browser process
channel.
NaClProcessHost now creates an initial NaCl-Browser channel, then uses
it to send a message to create the NaCl-Renderer channel. The main() for
the IPC-IRT creates a PpapiDispatcher object to manage this channel and
manage the PluginDispatchers for each renderer.
BUG=116317
TEST=manual
TBR=bbudge@chromium.org
Review URL: https://chromiumcodereview.appspot.com/10912011
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@154231 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r-- | chrome/browser/nacl_host/nacl_process_host.cc | 58 | ||||
-rw-r--r-- | chrome/browser/nacl_host/nacl_process_host.h | 26 | ||||
-rw-r--r-- | chrome/browser/renderer_host/chrome_render_message_filter.h | 3 | ||||
-rw-r--r-- | chrome/nacl/nacl_ipc_adapter.cc | 43 | ||||
-rw-r--r-- | chrome/nacl/nacl_listener.cc | 26 |
5 files changed, 136 insertions, 20 deletions
diff --git a/chrome/browser/nacl_host/nacl_process_host.cc b/chrome/browser/nacl_host/nacl_process_host.cc index f6edd8f..a21d163 100644 --- a/chrome/browser/nacl_host/nacl_process_host.cc +++ b/chrome/browser/nacl_host/nacl_process_host.cc @@ -18,7 +18,9 @@ #include "base/utf_string_conversions.h" #include "base/win/windows_version.h" #include "build/build_config.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/extensions/extension_info_map.h" +#include "chrome/browser/io_thread.h" #include "chrome/browser/nacl_host/nacl_browser.h" #include "chrome/browser/renderer_host/chrome_render_message_filter.h" #include "chrome/common/chrome_constants.h" @@ -33,9 +35,11 @@ #include "content/public/browser/browser_child_process_host.h" #include "content/public/browser/child_process_data.h" #include "content/public/common/child_process_host.h" +#include "ipc/ipc_channel.h" #include "ipc/ipc_switches.h" #include "native_client/src/shared/imc/nacl_imc.h" #include "net/base/net_util.h" +#include "ppapi/proxy/ppapi_messages.h" #if defined(OS_POSIX) #include <fcntl.h> @@ -55,6 +59,7 @@ using content::BrowserThread; using content::ChildProcessData; using content::ChildProcessHost; +using ppapi::proxy::SerializedHandle; namespace { @@ -114,6 +119,15 @@ struct NaClProcessHost::NaClInternal { // ----------------------------------------------------------------------------- +NaClProcessHost::PluginListener::PluginListener(NaClProcessHost* host) + : host_(host) { +} + +bool NaClProcessHost::PluginListener::OnMessageReceived( + const IPC::Message& msg) { + return host_->OnUntrustedMessageForwarded(msg); +} + NaClProcessHost::NaClProcessHost(const GURL& manifest_url, bool off_the_record) : manifest_url_(manifest_url), #if defined(OS_WIN) @@ -129,7 +143,9 @@ NaClProcessHost::NaClProcessHost(const GURL& manifest_url, bool off_the_record) ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), enable_exception_handling_(false), enable_debug_stub_(false), - off_the_record_(off_the_record) { + off_the_record_(off_the_record), + enable_ipc_proxy_(false), + ALLOW_THIS_IN_INITIALIZER_LIST(ipc_plugin_listener_(this)) { process_.reset(content::BrowserChildProcessHost::Create( content::PROCESS_TYPE_NACL_LOADER, this)); @@ -681,10 +697,48 @@ bool NaClProcessHost::SendStart() { return StartNaClExecution(); } +// This method is called when NaClProcessHostMsg_PpapiChannelCreated is +// received or PpapiHostMsg_ChannelCreated is forwarded by our plugin +// listener. void NaClProcessHost::OnPpapiChannelCreated( const IPC::ChannelHandle& channel_handle) { DCHECK(enable_ipc_proxy_); - ReplyToRenderer(channel_handle); + // If the proxy channel is null, this must be the initial NaCl-Browser IPC + // channel. + if (!ipc_proxy_channel_.get()) { + ipc_proxy_channel_.reset( + new IPC::ChannelProxy(channel_handle, + IPC::Channel::MODE_CLIENT, + &ipc_plugin_listener_, + base::MessageLoopProxy::current())); + // Send a message to create the NaCl-Renderer channel. The handle is just + // a place holder. + ipc_proxy_channel_->Send( + new PpapiMsg_CreateNaClChannel( + chrome_render_message_filter_->render_process_id(), + chrome_render_message_filter_->off_the_record(), + SerializedHandle(SerializedHandle::CHANNEL_HANDLE, + IPC::InvalidPlatformFileForTransit()))); + } else if (reply_msg_) { + // Otherwise, this must be a renderer channel. + ReplyToRenderer(channel_handle); + } else { + // Attempt to open more than 1 renderer channel is not supported. + // Shut down the NaCl process. + process_->GetHost()->ForceShutdown(); + } +} + +bool NaClProcessHost::OnUntrustedMessageForwarded(const IPC::Message& msg) { + // Handle messages that have been forwarded from our PluginListener. + // These messages come from untrusted code so should be handled with care. + bool handled = true; + IPC_BEGIN_MESSAGE_MAP(NaClProcessHost, msg) + IPC_MESSAGE_HANDLER(PpapiHostMsg_ChannelCreated, + OnPpapiChannelCreated) + IPC_MESSAGE_UNHANDLED(handled = false) + IPC_END_MESSAGE_MAP() + return handled; } bool NaClProcessHost::StartWithLaunchedProcess() { diff --git a/chrome/browser/nacl_host/nacl_process_host.h b/chrome/browser/nacl_host/nacl_process_host.h index ac0692e..b2d0c53 100644 --- a/chrome/browser/nacl_host/nacl_process_host.h +++ b/chrome/browser/nacl_host/nacl_process_host.h @@ -26,6 +26,10 @@ namespace content { class BrowserChildProcessHost; } +namespace IPC { +class ChannelProxy; +} + // Represents the browser side of the browser <--> NaCl communication // channel. There will be one NaClProcessHost per NaCl process // The browser is responsible for starting the NaCl process @@ -60,12 +64,25 @@ class NaClProcessHost : public content::BrowserChildProcessHostDelegate { bool Send(IPC::Message* msg); private: + friend class PluginListener; + // Internal class that holds the nacl::Handle objecs so that // nacl_process_host.h doesn't include NaCl headers. Needed since it's // included by src\content, which can't depend on the NaCl gyp file because it // depends on chrome.gyp (circular dependency). struct NaClInternal; + // PluginListener that forwards any messages from untrusted code that aren't + // handled by the PepperMessageFilter to us. + class PluginListener : public IPC::Listener { + public: + explicit PluginListener(NaClProcessHost* host); + virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE; + private: + // Non-owning pointer so we can forward messages to the host. + NaClProcessHost* host_; + }; + #if defined(OS_WIN) // Create command line for launching loader under nacl-gdb. scoped_ptr<CommandLine> GetCommandForLaunchWithGdb(const FilePath& nacl_gdb, @@ -113,7 +130,11 @@ class NaClProcessHost : public content::BrowserChildProcessHostDelegate { IPC::Message* reply_msg); #endif + // Called when a PPAPI IPC channel has been created. void OnPpapiChannelCreated(const IPC::ChannelHandle& channel_handle); + // Called by PluginListener, so messages from the untrusted side of + // the IPC proxy can be handled. + bool OnUntrustedMessageForwarded(const IPC::Message& msg); GURL manifest_url_; @@ -159,6 +180,11 @@ class NaClProcessHost : public content::BrowserChildProcessHostDelegate { bool enable_ipc_proxy_; + // Channel proxy to terminate the NaCl-Browser PPAPI channel. + scoped_ptr<IPC::ChannelProxy> ipc_proxy_channel_; + // Plugin listener, to forward browser channel messages to us. + PluginListener ipc_plugin_listener_; + DISALLOW_COPY_AND_ASSIGN(NaClProcessHost); }; diff --git a/chrome/browser/renderer_host/chrome_render_message_filter.h b/chrome/browser/renderer_host/chrome_render_message_filter.h index 327ff70..3a34378 100644 --- a/chrome/browser/renderer_host/chrome_render_message_filter.h +++ b/chrome/browser/renderer_host/chrome_render_message_filter.h @@ -66,6 +66,9 @@ class ChromeRenderMessageFilter : public content::BrowserMessageFilter { const IPC::Message& message, content::BrowserThread::ID* thread) OVERRIDE; + int render_process_id() { return render_process_id_; } + bool off_the_record() { return off_the_record_; } + private: friend class content::BrowserThread; friend class base::DeleteHelper<ChromeRenderMessageFilter>; diff --git a/chrome/nacl/nacl_ipc_adapter.cc b/chrome/nacl/nacl_ipc_adapter.cc index 4f4f328..71b5cc56 100644 --- a/chrome/nacl/nacl_ipc_adapter.cc +++ b/chrome/nacl/nacl_ipc_adapter.cc @@ -89,9 +89,9 @@ void DeleteChannel(IPC::Channel* channel) { delete channel; } -void WriteFileDescriptor(int handle_index, - const ppapi::proxy::SerializedHandle& handle, - IPC::Message* message) { +void WriteHandle(int handle_index, + const ppapi::proxy::SerializedHandle& handle, + IPC::Message* message) { ppapi::proxy::SerializedHandle::WriteHeader(handle.header(), message); // Now write the handle itself in POSIX style. @@ -108,7 +108,7 @@ void ConvertHandle(const ppapi::proxy::SerializedHandle& handle, Handles* handles, IPC::Message* msg, int* handle_index) { handles->push_back(handle); if (msg) - WriteFileDescriptor((*handle_index)++, handle, msg); + WriteHandle((*handle_index)++, handle, msg); } // This overload is to catch all types other than SerializedHandle. On Windows, @@ -434,6 +434,7 @@ int NaClIPCAdapter::TakeClientFileDescriptor() { return false; \ break; \ } + bool NaClIPCAdapter::OnMessageReceived(const IPC::Message& msg) { { base::AutoLock lock(lock_); @@ -443,12 +444,21 @@ bool NaClIPCAdapter::OnMessageReceived(const IPC::Message& msg) { // Pointer to the "new" message we will rewrite on Windows. On posix, this // isn't necessary, so it will stay NULL. IPC::Message* new_msg_ptr = NULL; -#if defined(OS_WIN) IPC::Message new_msg(msg.routing_id(), msg.type(), msg.priority()); +#if defined(OS_WIN) new_msg_ptr = &new_msg; +#else + // Even on POSIX, we have to rewrite messages to create channels, because + // these contain a handle with an invalid (place holder) descriptor. The + // message sending code sees this and doesn't pass the descriptor over + // correctly. + if (msg.type() == PpapiMsg_CreateNaClChannel::ID) + new_msg_ptr = &new_msg; #endif + Handles handles; switch (msg.type()) { + CASE_FOR_MESSAGE(PpapiMsg_CreateNaClChannel) CASE_FOR_MESSAGE(PpapiMsg_PPBAudio_NotifyAudioStreamCreated) CASE_FOR_MESSAGE(PpapiMsg_PPBAudioInput_OpenACK) case IPC_REPLY_ID: { @@ -502,10 +512,33 @@ bool NaClIPCAdapter::OnMessageReceived(const IPC::Message& msg) { iter->descriptor().fd #endif )); + break; + } + case ppapi::proxy::SerializedHandle::CHANNEL_HANDLE: { + // Check that this came from a PpapiMsg_CreateNaClChannel message. + // This code here is only appropriate for that message. + DCHECK(msg.type() == PpapiMsg_CreateNaClChannel::ID); + IPC::ChannelHandle channel_handle = + IPC::Channel::GenerateVerifiedChannelID("nacl"); + scoped_refptr<NaClIPCAdapter> ipc_adapter( + new NaClIPCAdapter(channel_handle, task_runner_)); +#if defined(OS_POSIX) + channel_handle.socket = base::FileDescriptor( + ipc_adapter->TakeClientFileDescriptor(), true); +#endif + nacl_desc.reset(factory.MakeGeneric(ipc_adapter->MakeNaClDesc())); + // Send back a message that the channel was created. + scoped_ptr<IPC::Message> response( + new PpapiHostMsg_ChannelCreated(channel_handle)); + task_runner_->PostTask(FROM_HERE, + base::Bind(&NaClIPCAdapter::SendMessageOnIOThread, this, + base::Passed(&response))); + break; } case ppapi::proxy::SerializedHandle::INVALID: { // Nothing to do. TODO(dmichael): Should we log this? Or is it // sometimes okay to pass an INVALID handle? + break; } // No default, so the compiler will warn us if new types get added. } diff --git a/chrome/nacl/nacl_listener.cc b/chrome/nacl/nacl_listener.cc index 34991ec..7d1fde6 100644 --- a/chrome/nacl/nacl_listener.cc +++ b/chrome/nacl/nacl_listener.cc @@ -198,22 +198,22 @@ void NaClListener::OnMsgStart(const nacl::NaClStartParams& params) { } 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 = + // Create the initial PPAPI IPC channel between the NaCl IRT and the + // browser process. The IRT uses this channel to communicate with the + // browser and to create additional IPC channels to renderer processes. + IPC::ChannelHandle 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(); - + scoped_refptr<NaClIPCAdapter> ipc_adapter( + new NaClIPCAdapter(handle, io_thread_.message_loop_proxy())); + // Pass a NaClDesc to the untrusted side. This will hold a ref to the + // NaClIPCAdapter. + args->initial_ipc_desc = ipc_adapter->MakeNaClDesc(); #if defined(OS_POSIX) - channel_handle.socket = base::FileDescriptor( - ipc_adapter.get()->TakeClientFileDescriptor(), true); + handle.socket = base::FileDescriptor( + ipc_adapter->TakeClientFileDescriptor(), true); #endif - - if (!Send(new NaClProcessHostMsg_PpapiChannelCreated(channel_handle))) - LOG(ERROR) << "Failed to send IPC channel handle to renderer."; + if (!Send(new NaClProcessHostMsg_PpapiChannelCreated(handle))) + LOG(ERROR) << "Failed to send IPC channel handle to NaClProcessHost."; } std::vector<nacl::FileDescriptor> handles = params.handles; |