Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / components / nacl / loader / nonsfi / nonsfi_listener.cc
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/nacl/loader/nonsfi/nonsfi_listener.h"
6
7 #include "base/command_line.h"
8 #include "base/file_descriptor_posix.h"
9 #include "base/logging.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/rand_util.h"
12 #include "components/nacl/common/nacl_messages.h"
13 #include "components/nacl/common/nacl_types.h"
14 #include "components/nacl/loader/nacl_trusted_listener.h"
15 #include "components/nacl/loader/nonsfi/irt_random.h"
16 #include "components/nacl/loader/nonsfi/nonsfi_main.h"
17 #include "ipc/ipc_channel.h"
18 #include "ipc/ipc_channel_handle.h"
19 #include "ipc/ipc_switches.h"
20 #include "ipc/ipc_sync_channel.h"
21 #include "ppapi/nacl_irt/plugin_startup.h"
22
23 #if !defined(OS_LINUX)
24 # error "non-SFI mode is supported only on linux."
25 #endif
26
27 namespace nacl {
28 namespace nonsfi {
29
30 NonSfiListener::NonSfiListener() : io_thread_("NaCl_IOThread"),
31                                    shutdown_event_(true, false) {
32   io_thread_.StartWithOptions(
33       base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
34 }
35
36 NonSfiListener::~NonSfiListener() {
37 }
38
39 void NonSfiListener::Listen() {
40   channel_ = IPC::SyncChannel::Create(
41       CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
42           switches::kProcessChannelID),
43       IPC::Channel::MODE_CLIENT,
44       this,  // As a Listener.
45       io_thread_.message_loop_proxy().get(),
46       true,  // Create pipe now.
47       &shutdown_event_);
48   base::MessageLoop::current()->Run();
49 }
50
51 bool NonSfiListener::Send(IPC::Message* msg) {
52   DCHECK(channel_.get() != NULL);
53   return channel_->Send(msg);
54 }
55
56 bool NonSfiListener::OnMessageReceived(const IPC::Message& msg) {
57   bool handled = true;
58   IPC_BEGIN_MESSAGE_MAP(NonSfiListener, msg)
59       IPC_MESSAGE_HANDLER(NaClProcessMsg_Start, OnStart)
60       IPC_MESSAGE_UNHANDLED(handled = false)
61   IPC_END_MESSAGE_MAP()
62   return handled;
63 }
64
65 void NonSfiListener::OnStart(const nacl::NaClStartParams& params) {
66   // Random number source initialization.
67   SetUrandomFd(base::GetUrandomFD());
68
69   IPC::ChannelHandle browser_handle;
70   IPC::ChannelHandle ppapi_renderer_handle;
71   IPC::ChannelHandle manifest_service_handle;
72
73   if (params.enable_ipc_proxy) {
74     browser_handle = IPC::Channel::GenerateVerifiedChannelID("nacl");
75     ppapi_renderer_handle = IPC::Channel::GenerateVerifiedChannelID("nacl");
76     manifest_service_handle =
77         IPC::Channel::GenerateVerifiedChannelID("nacl");
78
79     // In non-SFI mode, we neither intercept nor rewrite the message using
80     // NaClIPCAdapter, and the channels are connected between the plugin and
81     // the hosts directly. So, the IPC::Channel instances will be created in
82     // the plugin side, because the IPC::Listener needs to live on the
83     // plugin's main thread. However, on initialization (i.e. before loading
84     // the plugin binary), the FD needs to be passed to the hosts. So, here
85     // we create raw FD pairs, and pass the client side FDs to the hosts,
86     // and the server side FDs to the plugin.
87     int browser_server_ppapi_fd;
88     int browser_client_ppapi_fd;
89     int renderer_server_ppapi_fd;
90     int renderer_client_ppapi_fd;
91     int manifest_service_server_fd;
92     int manifest_service_client_fd;
93     if (!IPC::SocketPair(
94             &browser_server_ppapi_fd, &browser_client_ppapi_fd) ||
95         !IPC::SocketPair(
96             &renderer_server_ppapi_fd, &renderer_client_ppapi_fd) ||
97         !IPC::SocketPair(
98             &manifest_service_server_fd, &manifest_service_client_fd)) {
99       LOG(ERROR) << "Failed to create sockets for IPC.";
100       return;
101     }
102
103     // Set the plugin IPC channel FDs.
104     ppapi::SetIPCFileDescriptors(browser_server_ppapi_fd,
105                                  renderer_server_ppapi_fd,
106                                  manifest_service_server_fd);
107     ppapi::StartUpPlugin();
108
109     // Send back to the client side IPC channel FD to the host.
110     browser_handle.socket =
111         base::FileDescriptor(browser_client_ppapi_fd, true);
112     ppapi_renderer_handle.socket =
113         base::FileDescriptor(renderer_client_ppapi_fd, true);
114     manifest_service_handle.socket =
115         base::FileDescriptor(manifest_service_client_fd, true);
116   }
117
118   // TODO(teravest): Do we plan on using this renderer handle for nexe loading
119   // for non-SFI? Right now, passing an empty channel handle instead causes
120   // hangs, so we'll keep it.
121   trusted_listener_ = new NaClTrustedListener(
122       IPC::Channel::GenerateVerifiedChannelID("nacl"),
123       io_thread_.message_loop_proxy().get());
124   if (!Send(new NaClProcessHostMsg_PpapiChannelsCreated(
125           browser_handle,
126           ppapi_renderer_handle,
127           trusted_listener_->TakeClientChannelHandle(),
128           manifest_service_handle)))
129     LOG(ERROR) << "Failed to send IPC channel handle to NaClProcessHost.";
130
131   // Ensure that the validation cache key (used as an extra input to the
132   // validation cache's hashing) isn't exposed accidentally.
133   CHECK(!params.validation_cache_enabled);
134   CHECK(params.validation_cache_key.size() == 0);
135   CHECK(params.version.size() == 0);
136   // Ensure that a debug stub FD isn't passed through accidentally.
137   CHECK(!params.enable_debug_stub);
138   CHECK(params.debug_stub_server_bound_socket.fd == -1);
139
140   CHECK(!params.uses_irt);
141   CHECK(params.handles.empty());
142
143   CHECK(params.nexe_file != IPC::InvalidPlatformFileForTransit());
144   CHECK(params.nexe_token_lo == 0);
145   CHECK(params.nexe_token_hi == 0);
146   MainStart(IPC::PlatformFileForTransitToPlatformFile(params.nexe_file));
147 }
148
149 }  // namespace nonsfi
150 }  // namespace nacl