Merge from Chromium at DEPS revision 290040
This commit was generated by merge_to_master.py.
Change-Id: I694ec52d1e0b553f163c2faf4373d63270ab1aac
diff --git a/components/nacl/loader/nonsfi/nonsfi_listener.cc b/components/nacl/loader/nonsfi/nonsfi_listener.cc
new file mode 100644
index 0000000..839772c
--- /dev/null
+++ b/components/nacl/loader/nonsfi/nonsfi_listener.cc
@@ -0,0 +1,150 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/nacl/loader/nonsfi/nonsfi_listener.h"
+
+#include "base/command_line.h"
+#include "base/file_descriptor_posix.h"
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "base/rand_util.h"
+#include "components/nacl/common/nacl_messages.h"
+#include "components/nacl/common/nacl_types.h"
+#include "components/nacl/loader/nacl_trusted_listener.h"
+#include "components/nacl/loader/nonsfi/irt_random.h"
+#include "components/nacl/loader/nonsfi/nonsfi_main.h"
+#include "ipc/ipc_channel.h"
+#include "ipc/ipc_channel_handle.h"
+#include "ipc/ipc_switches.h"
+#include "ipc/ipc_sync_channel.h"
+#include "ppapi/nacl_irt/plugin_startup.h"
+
+#if !defined(OS_LINUX)
+# error "non-SFI mode is supported only on linux."
+#endif
+
+namespace nacl {
+namespace nonsfi {
+
+NonSfiListener::NonSfiListener() : io_thread_("NaCl_IOThread"),
+ shutdown_event_(true, false) {
+ io_thread_.StartWithOptions(
+ base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
+}
+
+NonSfiListener::~NonSfiListener() {
+}
+
+void NonSfiListener::Listen() {
+ channel_ = IPC::SyncChannel::Create(
+ CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kProcessChannelID),
+ IPC::Channel::MODE_CLIENT,
+ this, // As a Listener.
+ io_thread_.message_loop_proxy().get(),
+ true, // Create pipe now.
+ &shutdown_event_);
+ base::MessageLoop::current()->Run();
+}
+
+bool NonSfiListener::Send(IPC::Message* msg) {
+ DCHECK(channel_.get() != NULL);
+ return channel_->Send(msg);
+}
+
+bool NonSfiListener::OnMessageReceived(const IPC::Message& msg) {
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(NonSfiListener, msg)
+ IPC_MESSAGE_HANDLER(NaClProcessMsg_Start, OnStart)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}
+
+void NonSfiListener::OnStart(const nacl::NaClStartParams& params) {
+ // Random number source initialization.
+ SetUrandomFd(base::GetUrandomFD());
+
+ IPC::ChannelHandle browser_handle;
+ IPC::ChannelHandle ppapi_renderer_handle;
+ IPC::ChannelHandle manifest_service_handle;
+
+ if (params.enable_ipc_proxy) {
+ browser_handle = IPC::Channel::GenerateVerifiedChannelID("nacl");
+ ppapi_renderer_handle = IPC::Channel::GenerateVerifiedChannelID("nacl");
+ manifest_service_handle =
+ IPC::Channel::GenerateVerifiedChannelID("nacl");
+
+ // In non-SFI mode, we neither intercept nor rewrite the message using
+ // NaClIPCAdapter, and the channels are connected between the plugin and
+ // the hosts directly. So, the IPC::Channel instances will be created in
+ // the plugin side, because the IPC::Listener needs to live on the
+ // plugin's main thread. However, on initialization (i.e. before loading
+ // the plugin binary), the FD needs to be passed to the hosts. So, here
+ // we create raw FD pairs, and pass the client side FDs to the hosts,
+ // and the server side FDs to the plugin.
+ int browser_server_ppapi_fd;
+ int browser_client_ppapi_fd;
+ int renderer_server_ppapi_fd;
+ int renderer_client_ppapi_fd;
+ int manifest_service_server_fd;
+ int manifest_service_client_fd;
+ if (!IPC::SocketPair(
+ &browser_server_ppapi_fd, &browser_client_ppapi_fd) ||
+ !IPC::SocketPair(
+ &renderer_server_ppapi_fd, &renderer_client_ppapi_fd) ||
+ !IPC::SocketPair(
+ &manifest_service_server_fd, &manifest_service_client_fd)) {
+ LOG(ERROR) << "Failed to create sockets for IPC.";
+ return;
+ }
+
+ // Set the plugin IPC channel FDs.
+ ppapi::SetIPCFileDescriptors(browser_server_ppapi_fd,
+ renderer_server_ppapi_fd,
+ manifest_service_server_fd);
+ ppapi::StartUpPlugin();
+
+ // Send back to the client side IPC channel FD to the host.
+ browser_handle.socket =
+ base::FileDescriptor(browser_client_ppapi_fd, true);
+ ppapi_renderer_handle.socket =
+ base::FileDescriptor(renderer_client_ppapi_fd, true);
+ manifest_service_handle.socket =
+ base::FileDescriptor(manifest_service_client_fd, true);
+ }
+
+ // TODO(teravest): Do we plan on using this renderer handle for nexe loading
+ // for non-SFI? Right now, passing an empty channel handle instead causes
+ // hangs, so we'll keep it.
+ trusted_listener_ = new NaClTrustedListener(
+ IPC::Channel::GenerateVerifiedChannelID("nacl"),
+ io_thread_.message_loop_proxy().get());
+ if (!Send(new NaClProcessHostMsg_PpapiChannelsCreated(
+ browser_handle,
+ ppapi_renderer_handle,
+ trusted_listener_->TakeClientChannelHandle(),
+ manifest_service_handle)))
+ LOG(ERROR) << "Failed to send IPC channel handle to NaClProcessHost.";
+
+ // Ensure that the validation cache key (used as an extra input to the
+ // validation cache's hashing) isn't exposed accidentally.
+ CHECK(!params.validation_cache_enabled);
+ CHECK(params.validation_cache_key.size() == 0);
+ CHECK(params.version.size() == 0);
+ // Ensure that a debug stub FD isn't passed through accidentally.
+ CHECK(!params.enable_debug_stub);
+ CHECK(params.debug_stub_server_bound_socket.fd == -1);
+
+ CHECK(!params.uses_irt);
+ CHECK(params.handles.empty());
+
+ CHECK(params.nexe_file != IPC::InvalidPlatformFileForTransit());
+ CHECK(params.nexe_token_lo == 0);
+ CHECK(params.nexe_token_hi == 0);
+ MainStart(IPC::PlatformFileForTransitToPlatformFile(params.nexe_file));
+}
+
+} // namespace nonsfi
+} // namespace nacl