summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorbbudge@chromium.org <bbudge@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-30 19:47:38 +0000
committerbbudge@chromium.org <bbudge@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-30 19:47:38 +0000
commit8510d2832f673410e30165cbe0ab7dfbb4710e6a (patch)
treeb51713e3264faca51726185587d7edf568dda6ed /chrome
parent031afc6601b016abd3f36cc4bdb877ae74ac2e2f (diff)
downloadchromium_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.cc58
-rw-r--r--chrome/browser/nacl_host/nacl_process_host.h26
-rw-r--r--chrome/browser/renderer_host/chrome_render_message_filter.h3
-rw-r--r--chrome/nacl/nacl_ipc_adapter.cc43
-rw-r--r--chrome/nacl/nacl_listener.cc26
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;