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