blob: 1e3bcffa83366cc39e4d29c733daa9763a687b17 [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
[email protected]fb1277e82009-11-21 20:32:3089 cmd_line->AppendSwitchWithValue(switches::kProcessType,
[email protected]103607e2010-02-01 18:57:0990 switches::kNaClLoaderProcess);
[email protected]d032f492009-09-29 00:33:4691
[email protected]fb1277e82009-11-21 20:32:3092 cmd_line->AppendSwitchWithValue(switches::kProcessChannelID,
93 ASCIIToWide(channel_id()));
[email protected]d032f492009-09-29 00:33:4694
[email protected]103607e2010-02-01 18:57:0995 // On Windows we might need to start the broker process to launch a new loader
[email protected]d032f492009-09-29 00:33:4696#if defined(OS_WIN)
[email protected]103607e2010-02-01 18:57:0997 if (running_on_wow64_) {
98 NaClBrokerService::GetInstance()->Init(resource_dispatcher_host_);
[email protected]2a4d7542010-03-17 02:06:3399 return NaClBrokerService::GetInstance()->LaunchLoader(this,
100 ASCIIToWide(channel_id()));
[email protected]84638c72010-03-02 20:13:08101 } else // NO_LINT
[email protected]08aab352010-01-30 00:10:10102#endif
[email protected]103607e2010-02-01 18:57:09103 ChildProcessHost::Launch(
104#if defined(OS_WIN)
105 FilePath(),
106#elif defined(OS_POSIX)
[email protected]9aaa3222010-03-09 18:58:00107 true, // use_zygote
[email protected]103607e2010-02-01 18:57:09108 base::environment_vector(),
109#endif
110 cmd_line);
[email protected]d032f492009-09-29 00:33:46111
[email protected]fb1277e82009-11-21 20:32:30112 return true;
[email protected]d032f492009-09-29 00:33:46113}
114
[email protected]103607e2010-02-01 18:57:09115void NaClProcessHost::OnProcessLaunchedByBroker(base::ProcessHandle handle) {
116 set_handle(handle);
117 OnProcessLaunched();
118}
119
120bool NaClProcessHost::DidChildCrash() {
121 if (running_on_wow64_) {
122 bool child_exited;
123 return base::DidProcessCrash(&child_exited, handle());
124 }
125 return ChildProcessHost::DidChildCrash();
126}
127
[email protected]16e70ae2010-03-08 21:41:28128void NaClProcessHost::OnChildDied() {
129#if defined(OS_WIN)
130 NaClBrokerService::GetInstance()->OnLoaderDied();
131#endif
132 ChildProcessHost::OnChildDied();
133}
134
[email protected]fb1277e82009-11-21 20:32:30135void NaClProcessHost::OnProcessLaunched() {
136 nacl::FileDescriptor imc_handle;
137 base::ProcessHandle nacl_process_handle;
[email protected]16e70ae2010-03-08 21:41:28138#if defined(OS_WIN)
[email protected]fb1277e82009-11-21 20:32:30139 // Duplicate the IMC handle
[email protected]103607e2010-02-01 18:57:09140 // We assume the size of imc_handle has the same size as HANDLE, so the cast
141 // below is safe.
142 DCHECK(sizeof(HANDLE) == sizeof(imc_handle));
[email protected]fb1277e82009-11-21 20:32:30143 DuplicateHandle(base::GetCurrentProcessHandle(),
144 reinterpret_cast<HANDLE>(pair_[0]),
145 resource_message_filter_->handle(),
[email protected]103607e2010-02-01 18:57:09146 reinterpret_cast<HANDLE*>(&imc_handle),
[email protected]fb1277e82009-11-21 20:32:30147 GENERIC_READ | GENERIC_WRITE,
148 FALSE,
149 DUPLICATE_CLOSE_SOURCE);
150
151 // Duplicate the process handle
152 DuplicateHandle(base::GetCurrentProcessHandle(),
153 handle(),
154 resource_message_filter_->handle(),
155 &nacl_process_handle,
156 PROCESS_DUP_HANDLE,
157 FALSE,
158 0);
159
160#else
161 int flags = fcntl(pair_[0], F_GETFD);
162 if (flags != -1) {
163 flags |= FD_CLOEXEC;
164 fcntl(pair_[0], F_SETFD, flags);
165 }
166 // No need to dup the imc_handle - we don't pass it anywhere else so
167 // it cannot be closed.
168 imc_handle.fd = pair_[0];
169 imc_handle.auto_close = true;
170
171 // We use pid as process handle on Posix
172 nacl_process_handle = handle();
173
174#endif
175
176 // Get the pid of the NaCl process
177 base::ProcessId nacl_process_id = base::GetProcId(handle());
178
179 ViewHostMsg_LaunchNaCl::WriteReplyParams(
180 reply_msg_, imc_handle, nacl_process_handle, nacl_process_id);
181 resource_message_filter_->Send(reply_msg_);
182 resource_message_filter_ = NULL;
183 reply_msg_ = NULL;
184
185 SendStartMessage();
186}
187
188void NaClProcessHost::SendStartMessage() {
[email protected]d032f492009-09-29 00:33:46189 nacl::FileDescriptor channel;
190#if defined(OS_WIN)
191 if (!DuplicateHandle(GetCurrentProcess(),
[email protected]fb1277e82009-11-21 20:32:30192 reinterpret_cast<HANDLE>(pair_[1]),
193 handle(),
[email protected]d032f492009-09-29 00:33:46194 reinterpret_cast<HANDLE*>(&channel),
195 GENERIC_READ | GENERIC_WRITE,
196 FALSE, DUPLICATE_CLOSE_SOURCE)) {
[email protected]fb1277e82009-11-21 20:32:30197 return;
[email protected]d032f492009-09-29 00:33:46198 }
199#else
[email protected]fb1277e82009-11-21 20:32:30200 channel.fd = dup(pair_[1]);
[email protected]d032f492009-09-29 00:33:46201 channel.auto_close = true;
202#endif
[email protected]fb1277e82009-11-21 20:32:30203 Send(new NaClProcessMsg_Start(descriptor_, channel));
[email protected]d032f492009-09-29 00:33:46204}
205
206void NaClProcessHost::OnMessageReceived(const IPC::Message& msg) {
207 NOTREACHED() << "Invalid message with type = " << msg.type();
208}
209
210URLRequestContext* NaClProcessHost::GetRequestContext(
211 uint32 request_id,
212 const ViewHostMsg_Resource_Request& request_data) {
213 return NULL;
214}
[email protected]103607e2010-02-01 18:57:09215
216#if defined(OS_WIN)
217// TODO(gregoryd): invoke CheckIsWow64 only once, not for each NaClProcessHost
218typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);
219void NaClProcessHost::CheckIsWow64() {
220 LPFN_ISWOW64PROCESS fnIsWow64Process;
221
222 fnIsWow64Process = (LPFN_ISWOW64PROCESS) GetProcAddress(
223 GetModuleHandle(TEXT("kernel32")),
224 "IsWow64Process");
225
226 if (fnIsWow64Process != NULL) {
227 BOOL bIsWow64 = FALSE;
228 if (fnIsWow64Process(GetCurrentProcess(),&bIsWow64)) {
229 if (bIsWow64) {
230 running_on_wow64_ = true;
231 }
232 }
233 }
234}
235#endif