Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(211)

Side by Side Diff: content/browser/child_process_launcher.cc

Issue 10696025: Upstream ChildProcessLauncher changes for Android. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: add additional assert and comments Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/child_process_launcher.h" 5 #include "content/browser/child_process_launcher.h"
6 6
7 #include <utility> // For std::pair. 7 #include <utility> // For std::pair.
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
11 #include "base/file_util.h" 11 #include "base/file_util.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h" 13 #include "base/memory/scoped_ptr.h"
14 #include "base/process_util.h" 14 #include "base/process_util.h"
15 #include "base/synchronization/lock.h" 15 #include "base/synchronization/lock.h"
16 #include "base/threading/thread.h" 16 #include "base/threading/thread.h"
17 #include "content/public/browser/browser_thread.h" 17 #include "content/public/browser/browser_thread.h"
18 #include "content/public/browser/content_browser_client.h" 18 #include "content/public/browser/content_browser_client.h"
19 #include "content/public/common/content_descriptors.h" 19 #include "content/public/common/content_descriptors.h"
20 #include "content/public/common/content_switches.h" 20 #include "content/public/common/content_switches.h"
21 #include "content/public/common/result_codes.h" 21 #include "content/public/common/result_codes.h"
22 22
23 #if defined(OS_WIN) 23 #if defined(OS_WIN)
24 #include "base/file_path.h" 24 #include "base/file_path.h"
25 #include "content/common/sandbox_policy.h" 25 #include "content/common/sandbox_policy.h"
26 #elif defined(OS_MACOSX) 26 #elif defined(OS_MACOSX)
27 #include "content/browser/mach_broker_mac.h" 27 #include "content/browser/mach_broker_mac.h"
28 #elif defined(OS_ANDROID)
29 #include "base/android/jni_android.h"
30 #include "content/browser/android/sandboxed_process_launcher.h"
28 #elif defined(OS_POSIX) 31 #elif defined(OS_POSIX)
29 #include "base/memory/singleton.h" 32 #include "base/memory/singleton.h"
30 #include "content/browser/renderer_host/render_sandbox_host_linux.h" 33 #include "content/browser/renderer_host/render_sandbox_host_linux.h"
31 #include "content/browser/zygote_host_impl_linux.h" 34 #include "content/browser/zygote_host_impl_linux.h"
32 #endif 35 #endif
33 36
34 #if defined(OS_POSIX) 37 #if defined(OS_POSIX)
35 #include "base/global_descriptors_posix.h" 38 #include "base/global_descriptors_posix.h"
36 #endif 39 #endif
37 40
(...skipping 19 matching lines...) Expand all
57 terminate_child_on_shutdown_ = !CommandLine::ForCurrentProcess()-> 60 terminate_child_on_shutdown_ = !CommandLine::ForCurrentProcess()->
58 HasSwitch(switches::kRendererCleanExit); 61 HasSwitch(switches::kRendererCleanExit);
59 #else 62 #else
60 terminate_child_on_shutdown_ = true; 63 terminate_child_on_shutdown_ = true;
61 #endif 64 #endif
62 } 65 }
63 66
64 void Launch( 67 void Launch(
65 #if defined(OS_WIN) 68 #if defined(OS_WIN)
66 const FilePath& exposed_dir, 69 const FilePath& exposed_dir,
70 #elif defined(OS_ANDROID)
71 int ipcfd,
67 #elif defined(OS_POSIX) 72 #elif defined(OS_POSIX)
68 bool use_zygote, 73 bool use_zygote,
69 const base::EnvironmentVector& environ, 74 const base::EnvironmentVector& environ,
70 int ipcfd, 75 int ipcfd,
71 #endif 76 #endif
72 CommandLine* cmd_line, 77 CommandLine* cmd_line,
73 Client* client) { 78 Client* client) {
74 client_ = client; 79 client_ = client;
75 80
76 CHECK(BrowserThread::GetCurrentThreadIdentifier(&client_thread_id_)); 81 CHECK(BrowserThread::GetCurrentThreadIdentifier(&client_thread_id_));
77 82
83 #if defined(OS_ANDROID)
84 // We need to close the client end of the IPC channel to reliably detect
85 // child termination. We will close this fd after we create the child
86 // process which is asynchronous on Android.
87 ipcfd_ = ipcfd;
88 #endif
78 BrowserThread::PostTask( 89 BrowserThread::PostTask(
79 BrowserThread::PROCESS_LAUNCHER, FROM_HERE, 90 BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
80 base::Bind( 91 base::Bind(
81 &Context::LaunchInternal, 92 &Context::LaunchInternal,
82 make_scoped_refptr(this), 93 make_scoped_refptr(this),
83 client_thread_id_, 94 client_thread_id_,
84 #if defined(OS_WIN) 95 #if defined(OS_WIN)
85 exposed_dir, 96 exposed_dir,
97 #elif defined(OS_ANDROID)
98 ipcfd,
86 #elif defined(OS_POSIX) 99 #elif defined(OS_POSIX)
87 use_zygote, 100 use_zygote,
88 environ, 101 environ,
89 ipcfd, 102 ipcfd,
90 #endif 103 #endif
91 cmd_line)); 104 cmd_line));
92 } 105 }
93 106
107 #if defined(OS_ANDROID)
108 static void OnSandboxedProcessStarted(
109 // |this_object| is NOT thread safe. Only use it to post a task back.
110 scoped_refptr<Context> this_object,
111 BrowserThread::ID client_thread_id,
112 base::ProcessHandle handle) {
113 if (BrowserThread::CurrentlyOn(client_thread_id)) {
114 // This is always invoked on the UI thread which is commonly the
115 // |client_thread_id| so we can shortcut one PostTask.
116 this_object->Notify(handle);
117 } else {
118 BrowserThread::PostTask(
119 client_thread_id, FROM_HERE,
120 base::Bind(
121 &ChildProcessLauncher::Context::Notify,
122 this_object,
123 handle));
124 }
125 }
126 #endif
127
94 void ResetClient() { 128 void ResetClient() {
95 // No need for locking as this function gets called on the same thread that 129 // No need for locking as this function gets called on the same thread that
96 // client_ would be used. 130 // client_ would be used.
97 CHECK(BrowserThread::CurrentlyOn(client_thread_id_)); 131 CHECK(BrowserThread::CurrentlyOn(client_thread_id_));
98 client_ = NULL; 132 client_ = NULL;
99 } 133 }
100 134
101 void set_terminate_child_on_shutdown(bool terminate_on_shutdown) { 135 void set_terminate_child_on_shutdown(bool terminate_on_shutdown) {
102 terminate_child_on_shutdown_ = terminate_on_shutdown; 136 terminate_child_on_shutdown_ = terminate_on_shutdown;
103 } 137 }
104 138
105 private: 139 private:
106 friend class base::RefCountedThreadSafe<ChildProcessLauncher::Context>; 140 friend class base::RefCountedThreadSafe<ChildProcessLauncher::Context>;
107 friend class ChildProcessLauncher; 141 friend class ChildProcessLauncher;
108 142
109 ~Context() { 143 ~Context() {
110 Terminate(); 144 Terminate();
111 } 145 }
112 146
113 static void LaunchInternal( 147 static void LaunchInternal(
114 // |this_object| is NOT thread safe. Only use it to post a task back. 148 // |this_object| is NOT thread safe. Only use it to post a task back.
115 scoped_refptr<Context> this_object, 149 scoped_refptr<Context> this_object,
116 BrowserThread::ID client_thread_id, 150 BrowserThread::ID client_thread_id,
117 #if defined(OS_WIN) 151 #if defined(OS_WIN)
118 const FilePath& exposed_dir, 152 const FilePath& exposed_dir,
153 #elif defined(OS_ANDROID)
154 int ipcfd,
119 #elif defined(OS_POSIX) 155 #elif defined(OS_POSIX)
120 bool use_zygote, 156 bool use_zygote,
121 const base::EnvironmentVector& env, 157 const base::EnvironmentVector& env,
122 int ipcfd, 158 int ipcfd,
123 #endif 159 #endif
124 CommandLine* cmd_line) { 160 CommandLine* cmd_line) {
125 scoped_ptr<CommandLine> cmd_line_deleter(cmd_line); 161 scoped_ptr<CommandLine> cmd_line_deleter(cmd_line);
126 162
163 #if defined(OS_WIN)
164 base::ProcessHandle handle = sandbox::StartProcessWithAccess(
165 cmd_line, exposed_dir);
166 #elif defined(OS_ANDROID)
167 std::string process_type =
168 cmd_line->GetSwitchValueASCII(switches::kProcessType);
169 base::GlobalDescriptors::Mapping files_to_register;
170 files_to_register.push_back(std::pair<base::GlobalDescriptors::Key, int>(
171 kPrimaryIPCChannel, ipcfd));
172 content::GetContentClient()->browser()->
173 GetAdditionalMappedFilesForChildProcess(*cmd_line, &files_to_register);
174
175 content::StartSandboxedProcess(cmd_line->argv(),
176 ipcfd, files_to_register,
177 base::Bind(&ChildProcessLauncher::Context::OnSandboxedProcessStarted,
178 this_object, client_thread_id));
179
180 #elif defined(OS_POSIX)
127 base::ProcessHandle handle = base::kNullProcessHandle; 181 base::ProcessHandle handle = base::kNullProcessHandle;
128 #if defined(OS_WIN)
129 handle = sandbox::StartProcessWithAccess(cmd_line, exposed_dir);
130 #elif defined(OS_POSIX)
131 // We need to close the client end of the IPC channel 182 // We need to close the client end of the IPC channel
132 // to reliably detect child termination. 183 // to reliably detect child termination.
133 file_util::ScopedFD ipcfd_closer(&ipcfd); 184 file_util::ScopedFD ipcfd_closer(&ipcfd);
134 185
135 std::string process_type = 186 std::string process_type =
136 cmd_line->GetSwitchValueASCII(switches::kProcessType); 187 cmd_line->GetSwitchValueASCII(switches::kProcessType);
137 base::GlobalDescriptors::Mapping files_to_register; 188 base::GlobalDescriptors::Mapping files_to_register;
138 files_to_register.push_back(std::pair<base::GlobalDescriptors::Key, int>( 189 files_to_register.push_back(std::pair<base::GlobalDescriptors::Key, int>(
139 kPrimaryIPCChannel, ipcfd)); 190 kPrimaryIPCChannel, ipcfd));
140 #if !defined(OS_MACOSX) && !defined(OS_ANDROID) 191 #if !defined(OS_MACOSX)
141 content::GetContentClient()->browser()-> 192 content::GetContentClient()->browser()->
142 GetAdditionalMappedFilesForChildProcess(*cmd_line, &files_to_register); 193 GetAdditionalMappedFilesForChildProcess(*cmd_line, &files_to_register);
143 if (use_zygote) { 194 if (use_zygote) {
144 handle = ZygoteHostImpl::GetInstance()->ForkRequest(cmd_line->argv(), 195 handle = ZygoteHostImpl::GetInstance()->ForkRequest(cmd_line->argv(),
145 files_to_register, 196 files_to_register,
146 process_type); 197 process_type);
147 } else 198 } else
148 // Fall through to the normal posix case below when we're not zygoting. 199 // Fall through to the normal posix case below when we're not zygoting.
149 #endif // defined(OS_MACOSX) && !defined(OS_ANDROID) 200 #endif // !defined(OS_MACOSX)
150 { 201 {
151 // Convert FD mapping to FileHandleMappingVector 202 // Convert FD mapping to FileHandleMappingVector
152 base::FileHandleMappingVector fds_to_map; 203 base::FileHandleMappingVector fds_to_map;
153 for (size_t i = 0; i < files_to_register.size(); ++i) { 204 for (size_t i = 0; i < files_to_register.size(); ++i) {
154 const base::GlobalDescriptors::KeyFDPair& id_file = 205 const base::GlobalDescriptors::KeyFDPair& id_file =
155 files_to_register[i]; 206 files_to_register[i];
156 fds_to_map.push_back(std::make_pair( 207 fds_to_map.push_back(std::make_pair(
157 id_file.second, 208 id_file.second,
158 id_file.first + base::GlobalDescriptors::kBaseDescriptor)); 209 id_file.first + base::GlobalDescriptors::kBaseDescriptor));
159 } 210 }
160 211
161 #if !defined(OS_MACOSX) && !defined(OS_ANDROID) 212 #if !defined(OS_MACOSX)
162 if (process_type == switches::kRendererProcess) { 213 if (process_type == switches::kRendererProcess) {
163 const int sandbox_fd = 214 const int sandbox_fd =
164 RenderSandboxHostLinux::GetInstance()->GetRendererSocket(); 215 RenderSandboxHostLinux::GetInstance()->GetRendererSocket();
165 fds_to_map.push_back(std::make_pair( 216 fds_to_map.push_back(std::make_pair(
166 sandbox_fd, 217 sandbox_fd,
167 kSandboxIPCChannel + base::GlobalDescriptors::kBaseDescriptor)); 218 kSandboxIPCChannel + base::GlobalDescriptors::kBaseDescriptor));
168 } 219 }
169 #endif // defined(OS_MACOSX) && !defined(OS_ANDROID) 220 #endif // defined(OS_MACOSX)
170 221
171 // Actually launch the app. 222 // Actually launch the app.
172 base::LaunchOptions options; 223 base::LaunchOptions options;
173 options.environ = &env; 224 options.environ = &env;
174 options.fds_to_remap = &fds_to_map; 225 options.fds_to_remap = &fds_to_map;
175 226
176 #if defined(OS_MACOSX) 227 #if defined(OS_MACOSX)
177 // Use synchronization to make sure that the MachBroker is ready to 228 // Use synchronization to make sure that the MachBroker is ready to
178 // receive a check-in from the new process before the new process 229 // receive a check-in from the new process before the new process
179 // actually tries to check in. 230 // actually tries to check in.
(...skipping 17 matching lines...) Expand all
197 248
198 // Now that the MachBroker is ready, the child may continue. 249 // Now that the MachBroker is ready, the child may continue.
199 base::LaunchSynchronize(synchronization_handle); 250 base::LaunchSynchronize(synchronization_handle);
200 } 251 }
201 #endif // defined(OS_MACOSX) 252 #endif // defined(OS_MACOSX)
202 253
203 if (!launched) 254 if (!launched)
204 handle = base::kNullProcessHandle; 255 handle = base::kNullProcessHandle;
205 } 256 }
206 #endif // else defined(OS_POSIX) 257 #endif // else defined(OS_POSIX)
207 258 #if !defined(OS_ANDROID)
208 BrowserThread::PostTask( 259 BrowserThread::PostTask(
209 client_thread_id, FROM_HERE, 260 client_thread_id, FROM_HERE,
210 base::Bind( 261 base::Bind(
211 &Context::Notify, 262 &Context::Notify,
212 this_object.get(), 263 this_object.get(),
213 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 264 #if defined(OS_POSIX) && !defined(OS_MACOSX)
214 use_zygote, 265 use_zygote,
215 #endif 266 #endif
216 handle)); 267 handle));
268 #endif // !defined(OS_ANDROID)
217 } 269 }
218 270
219 void Notify( 271 void Notify(
220 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 272 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
221 bool zygote, 273 bool zygote,
222 #endif 274 #endif
223 base::ProcessHandle handle) { 275 base::ProcessHandle handle) {
276 #if defined(OS_ANDROID)
277 // Finally close the ipcfd
278 file_util::ScopedFD ipcfd_closer(&ipcfd_);
279 #endif
224 starting_ = false; 280 starting_ = false;
225 process_.set_handle(handle); 281 process_.set_handle(handle);
226 if (!handle) 282 if (!handle)
227 LOG(ERROR) << "Failed to launch child process"; 283 LOG(ERROR) << "Failed to launch child process";
228 284
229 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 285 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
230 zygote_ = zygote; 286 zygote_ = zygote;
231 #endif 287 #endif
232 if (client_) { 288 if (client_) {
233 client_->OnProcessLaunched(); 289 client_->OnProcessLaunched();
(...skipping 26 matching lines...) Expand all
260 bool background) { 316 bool background) {
261 base::Process process(handle); 317 base::Process process(handle);
262 process.SetProcessBackgrounded(background); 318 process.SetProcessBackgrounded(background);
263 } 319 }
264 320
265 static void TerminateInternal( 321 static void TerminateInternal(
266 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 322 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
267 bool zygote, 323 bool zygote,
268 #endif 324 #endif
269 base::ProcessHandle handle) { 325 base::ProcessHandle handle) {
326 #if defined(OS_ANDROID)
327 LOG(INFO) << "ChromeProcess: Stopping process with handle " << handle;
328 content::StopSandboxedProcess(handle);
329 #else
270 base::Process process(handle); 330 base::Process process(handle);
271 // Client has gone away, so just kill the process. Using exit code 0 331 // Client has gone away, so just kill the process. Using exit code 0
272 // means that UMA won't treat this as a crash. 332 // means that UMA won't treat this as a crash.
273 process.Terminate(content::RESULT_CODE_NORMAL_EXIT); 333 process.Terminate(content::RESULT_CODE_NORMAL_EXIT);
274 // On POSIX, we must additionally reap the child. 334 // On POSIX, we must additionally reap the child.
275 #if defined(OS_POSIX) 335 #if defined(OS_POSIX)
276 #if !defined(OS_MACOSX) && !defined(OS_ANDROID) 336 #if !defined(OS_MACOSX)
277 if (zygote) { 337 if (zygote) {
278 // If the renderer was created via a zygote, we have to proxy the reaping 338 // If the renderer was created via a zygote, we have to proxy the reaping
279 // through the zygote process. 339 // through the zygote process.
280 ZygoteHostImpl::GetInstance()->EnsureProcessTerminated(handle); 340 ZygoteHostImpl::GetInstance()->EnsureProcessTerminated(handle);
281 } else 341 } else
282 #endif // !OS_MACOSX 342 #endif // !OS_MACOSX
283 { 343 {
284 base::EnsureProcessTerminated(handle); 344 base::EnsureProcessTerminated(handle);
285 } 345 }
286 #endif // OS_POSIX 346 #endif // OS_POSIX
287 process.Close(); 347 process.Close();
348 #endif // defined(OS_ANDROID)
288 } 349 }
289 350
290 Client* client_; 351 Client* client_;
291 BrowserThread::ID client_thread_id_; 352 BrowserThread::ID client_thread_id_;
292 base::Process process_; 353 base::Process process_;
293 base::TerminationStatus termination_status_; 354 base::TerminationStatus termination_status_;
294 int exit_code_; 355 int exit_code_;
295 bool starting_; 356 bool starting_;
296 // Controls whether the child process should be terminated on browser 357 // Controls whether the child process should be terminated on browser
297 // shutdown. Default behavior is to terminate the child. 358 // shutdown. Default behavior is to terminate the child.
298 bool terminate_child_on_shutdown_; 359 bool terminate_child_on_shutdown_;
299 360 #if defined(OS_ANDROID)
300 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 361 // The fd to close after creating the process.
362 int ipcfd_;
363 #elif defined(OS_POSIX) && !defined(OS_MACOSX)
301 bool zygote_; 364 bool zygote_;
302 #endif 365 #endif
303 }; 366 };
304 367
305 368
306 ChildProcessLauncher::ChildProcessLauncher( 369 ChildProcessLauncher::ChildProcessLauncher(
307 #if defined(OS_WIN) 370 #if defined(OS_WIN)
308 const FilePath& exposed_dir, 371 const FilePath& exposed_dir,
309 #elif defined(OS_POSIX) 372 #elif defined(OS_POSIX)
310 bool use_zygote, 373 bool use_zygote,
311 const base::EnvironmentVector& environ, 374 const base::EnvironmentVector& environ,
312 int ipcfd, 375 int ipcfd,
313 #endif 376 #endif
314 CommandLine* cmd_line, 377 CommandLine* cmd_line,
315 Client* client) { 378 Client* client) {
316 context_ = new Context(); 379 context_ = new Context();
317 context_->Launch( 380 context_->Launch(
318 #if defined(OS_WIN) 381 #if defined(OS_WIN)
319 exposed_dir, 382 exposed_dir,
383 #elif defined(OS_ANDROID)
384 ipcfd,
320 #elif defined(OS_POSIX) 385 #elif defined(OS_POSIX)
321 use_zygote, 386 use_zygote,
322 environ, 387 environ,
323 ipcfd, 388 ipcfd,
324 #endif 389 #endif
325 cmd_line, 390 cmd_line,
326 client); 391 client);
327 } 392 }
328 393
329 ChildProcessLauncher::~ChildProcessLauncher() { 394 ChildProcessLauncher::~ChildProcessLauncher() {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 base::Bind( 445 base::Bind(
381 &ChildProcessLauncher::Context::SetProcessBackgrounded, 446 &ChildProcessLauncher::Context::SetProcessBackgrounded,
382 GetHandle(), background)); 447 GetHandle(), background));
383 } 448 }
384 449
385 void ChildProcessLauncher::SetTerminateChildOnShutdown( 450 void ChildProcessLauncher::SetTerminateChildOnShutdown(
386 bool terminate_on_shutdown) { 451 bool terminate_on_shutdown) {
387 if (context_) 452 if (context_)
388 context_->set_terminate_child_on_shutdown(terminate_on_shutdown); 453 context_->set_terminate_child_on_shutdown(terminate_on_shutdown);
389 } 454 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698