blob: 2b3ebd2514bcf1c74536aa706d66d5bc34b30946 [file] [log] [blame]
[email protected]d032f492009-09-29 00:33:461// Copyright (c) 2009 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 "build/build_config.h"
6
[email protected]e15a4fa2010-02-11 23:09:297#include "chrome/browser/nacl_host/nacl_process_host.h"
[email protected]d032f492009-09-29 00:33:468
9#if defined(OS_POSIX)
10#include <fcntl.h>
11#endif
12
[email protected]103607e2010-02-01 18:57:0913#include "base/command_line.h"
14#include "chrome/browser/nacl_host/nacl_broker_service.h"
[email protected]d032f492009-09-29 00:33:4615#include "chrome/browser/renderer_host/resource_message_filter.h"
[email protected]d032f492009-09-29 00:33:4616#include "chrome/common/chrome_switches.h"
17#include "chrome/common/logging_chrome.h"
[email protected]103607e2010-02-01 18:57:0918#include "chrome/common/nacl_cmd_line.h"
[email protected]d032f492009-09-29 00:33:4619#include "chrome/common/nacl_messages.h"
[email protected]fb1277e82009-11-21 20:32:3020#include "chrome/common/render_messages.h"
[email protected]d032f492009-09-29 00:33:4621#include "ipc/ipc_switches.h"
22
[email protected]d032f492009-09-29 00:33:4623#if defined(OS_POSIX)
24#include "ipc/ipc_channel_posix.h"
25#endif
26
27NaClProcessHost::NaClProcessHost(
[email protected]f08e47d2009-10-15 21:46:1528 ResourceDispatcherHost *resource_dispatcher_host,
29 const std::wstring& url)
[email protected]103607e2010-02-01 18:57:0930 : ChildProcessHost(NACL_LOADER_PROCESS, resource_dispatcher_host),
[email protected]fb1277e82009-11-21 20:32:3031 resource_dispatcher_host_(resource_dispatcher_host),
32 reply_msg_(NULL),
[email protected]103607e2010-02-01 18:57:0933 descriptor_(0),
34 running_on_wow64_(false) {
[email protected]f08e47d2009-10-15 21:46:1535 set_name(url);
[email protected]103607e2010-02-01 18:57:0936#if defined(OS_WIN)
37 CheckIsWow64();
38#endif
[email protected]d032f492009-09-29 00:33:4639}
40
[email protected]fb1277e82009-11-21 20:32:3041NaClProcessHost::~NaClProcessHost() {
42 if (!reply_msg_)
43 return;
44
45 // OnProcessLaunched didn't get called because the process couldn't launch.
46 // Don't keep the renderer hanging.
47 reply_msg_->set_reply_error();
48 resource_message_filter_->Send(reply_msg_);
49}
50
51bool NaClProcessHost::Launch(ResourceMessageFilter* resource_message_filter,
[email protected]d032f492009-09-29 00:33:4652 const int descriptor,
[email protected]fb1277e82009-11-21 20:32:3053 IPC::Message* reply_msg) {
[email protected]d8c7cbcc2009-10-02 19:00:3154#ifdef DISABLE_NACL
55 NOTIMPLEMENTED() << "Native Client disabled at build time";
56 return false;
57#else
[email protected]f08e47d2009-10-15 21:46:1558
[email protected]d032f492009-09-29 00:33:4659 // Create a connected socket
[email protected]fb1277e82009-11-21 20:32:3060 if (nacl::SocketPair(pair_) == -1)
[email protected]d032f492009-09-29 00:33:4661 return false;
[email protected]d032f492009-09-29 00:33:4662
63 // Launch the process
[email protected]fb1277e82009-11-21 20:32:3064 descriptor_ = descriptor;
65 if (!LaunchSelLdr()) {
66 nacl::Close(pair_[0]);
[email protected]d032f492009-09-29 00:33:4667 return false;
68 }
69
[email protected]fb1277e82009-11-21 20:32:3070 resource_message_filter_ = resource_message_filter;
71 reply_msg_ = reply_msg;
[email protected]f08e47d2009-10-15 21:46:1572
[email protected]d032f492009-09-29 00:33:4673 return true;
[email protected]d8c7cbcc2009-10-02 19:00:3174#endif // DISABLE_NACL
[email protected]d032f492009-09-29 00:33:4675}
76
[email protected]fb1277e82009-11-21 20:32:3077bool NaClProcessHost::LaunchSelLdr() {
[email protected]d032f492009-09-29 00:33:4678 if (!CreateChannel())
79 return false;
80
81 // Build command line for nacl.
[email protected]7c4ea142010-01-26 05:15:4282 FilePath exe_path = GetChildPath(true);
[email protected]fb1277e82009-11-21 20:32:3083 if (exe_path.empty())
[email protected]d032f492009-09-29 00:33:4684 return false;
85
[email protected]fb1277e82009-11-21 20:32:3086 CommandLine* cmd_line = new CommandLine(exe_path);
[email protected]103607e2010-02-01 18:57:0987 nacl::CopyNaClCommandLineArguments(cmd_line);
[email protected]599e6642010-01-27 18:52:1388
89#if defined(OS_MACOSX)
[email protected]103607e2010-02-01 18:57:0990 // TODO(dspringer): NaCl is temporalrily disabled on the Mac by default, but
91 // it can be enabled with the --enable-nacl cmd-line switch. Remove this check
92 // when the security issues in the Mac PIC code are resolved.
93 if (!cmd_line->HasSwitch(switches::kEnableNaClOnMac))
[email protected]599e6642010-01-27 18:52:1394 return false;
95#endif
96
[email protected]fb1277e82009-11-21 20:32:3097 cmd_line->AppendSwitchWithValue(switches::kProcessType,
[email protected]103607e2010-02-01 18:57:0998 switches::kNaClLoaderProcess);
[email protected]d032f492009-09-29 00:33:4699
[email protected]fb1277e82009-11-21 20:32:30100 cmd_line->AppendSwitchWithValue(switches::kProcessChannelID,
101 ASCIIToWide(channel_id()));
[email protected]d032f492009-09-29 00:33:46102
[email protected]103607e2010-02-01 18:57:09103 // On Windows we might need to start the broker process to launch a new loader
[email protected]d032f492009-09-29 00:33:46104#if defined(OS_WIN)
[email protected]103607e2010-02-01 18:57:09105 if (running_on_wow64_) {
106 NaClBrokerService::GetInstance()->Init(resource_dispatcher_host_);
107 NaClBrokerService::GetInstance()->LaunchLoader(this,
108 ASCIIToWide(channel_id()));
109 } else
[email protected]08aab352010-01-30 00:10:10110#endif
[email protected]103607e2010-02-01 18:57:09111 ChildProcessHost::Launch(
112#if defined(OS_WIN)
113 FilePath(),
114#elif defined(OS_POSIX)
115 false,
116 base::environment_vector(),
117#endif
118 cmd_line);
[email protected]d032f492009-09-29 00:33:46119
[email protected]fb1277e82009-11-21 20:32:30120 return true;
[email protected]d032f492009-09-29 00:33:46121}
122
[email protected]103607e2010-02-01 18:57:09123void NaClProcessHost::OnProcessLaunchedByBroker(base::ProcessHandle handle) {
124 set_handle(handle);
125 OnProcessLaunched();
126}
127
128bool NaClProcessHost::DidChildCrash() {
129 if (running_on_wow64_) {
130 bool child_exited;
131 return base::DidProcessCrash(&child_exited, handle());
132 }
133 return ChildProcessHost::DidChildCrash();
134}
135
[email protected]fb1277e82009-11-21 20:32:30136void NaClProcessHost::OnProcessLaunched() {
137 nacl::FileDescriptor imc_handle;
138 base::ProcessHandle nacl_process_handle;
139#if NACL_WINDOWS
140 // Duplicate the IMC handle
[email protected]103607e2010-02-01 18:57:09141 // We assume the size of imc_handle has the same size as HANDLE, so the cast
142 // below is safe.
143 DCHECK(sizeof(HANDLE) == sizeof(imc_handle));
[email protected]fb1277e82009-11-21 20:32:30144 DuplicateHandle(base::GetCurrentProcessHandle(),
145 reinterpret_cast<HANDLE>(pair_[0]),
146 resource_message_filter_->handle(),
[email protected]103607e2010-02-01 18:57:09147 reinterpret_cast<HANDLE*>(&imc_handle),
[email protected]fb1277e82009-11-21 20:32:30148 GENERIC_READ | GENERIC_WRITE,
149 FALSE,
150 DUPLICATE_CLOSE_SOURCE);
151
152 // Duplicate the process handle
153 DuplicateHandle(base::GetCurrentProcessHandle(),
154 handle(),
155 resource_message_filter_->handle(),
156 &nacl_process_handle,
157 PROCESS_DUP_HANDLE,
158 FALSE,
159 0);
160
161#else
162 int flags = fcntl(pair_[0], F_GETFD);
163 if (flags != -1) {
164 flags |= FD_CLOEXEC;
165 fcntl(pair_[0], F_SETFD, flags);
166 }
167 // No need to dup the imc_handle - we don't pass it anywhere else so
168 // it cannot be closed.
169 imc_handle.fd = pair_[0];
170 imc_handle.auto_close = true;
171
172 // We use pid as process handle on Posix
173 nacl_process_handle = handle();
174
175#endif
176
177 // Get the pid of the NaCl process
178 base::ProcessId nacl_process_id = base::GetProcId(handle());
179
180 ViewHostMsg_LaunchNaCl::WriteReplyParams(
181 reply_msg_, imc_handle, nacl_process_handle, nacl_process_id);
182 resource_message_filter_->Send(reply_msg_);
183 resource_message_filter_ = NULL;
184 reply_msg_ = NULL;
185
186 SendStartMessage();
187}
188
189void NaClProcessHost::SendStartMessage() {
[email protected]d032f492009-09-29 00:33:46190 nacl::FileDescriptor channel;
191#if defined(OS_WIN)
192 if (!DuplicateHandle(GetCurrentProcess(),
[email protected]fb1277e82009-11-21 20:32:30193 reinterpret_cast<HANDLE>(pair_[1]),
194 handle(),
[email protected]d032f492009-09-29 00:33:46195 reinterpret_cast<HANDLE*>(&channel),
196 GENERIC_READ | GENERIC_WRITE,
197 FALSE, DUPLICATE_CLOSE_SOURCE)) {
[email protected]fb1277e82009-11-21 20:32:30198 return;
[email protected]d032f492009-09-29 00:33:46199 }
200#else
[email protected]fb1277e82009-11-21 20:32:30201 channel.fd = dup(pair_[1]);
[email protected]d032f492009-09-29 00:33:46202 channel.auto_close = true;
203#endif
[email protected]fb1277e82009-11-21 20:32:30204 Send(new NaClProcessMsg_Start(descriptor_, channel));
[email protected]d032f492009-09-29 00:33:46205}
206
207void NaClProcessHost::OnMessageReceived(const IPC::Message& msg) {
208 NOTREACHED() << "Invalid message with type = " << msg.type();
209}
210
211URLRequestContext* NaClProcessHost::GetRequestContext(
212 uint32 request_id,
213 const ViewHostMsg_Resource_Request& request_data) {
214 return NULL;
215}
[email protected]103607e2010-02-01 18:57:09216
217#if defined(OS_WIN)
218// TODO(gregoryd): invoke CheckIsWow64 only once, not for each NaClProcessHost
219typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
220void NaClProcessHost::CheckIsWow64() {
221 LPFN_ISWOW64PROCESS fnIsWow64Process;
222
223 fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress(
224 GetModuleHandle(TEXT("kernel32")),
225 "IsWow64Process");
226
227 if (fnIsWow64Process != NULL) {
228 BOOL bIsWow64 = FALSE;
229 if (fnIsWow64Process(GetCurrentProcess(),&bIsWow64)) {
230 if (bIsWow64) {
231 running_on_wow64_ = true;
232 }
233 }
234 }
235}
236#endif