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

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

Issue 98603007: Launches a privileged utility process. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Cleans up ChildProcessLauncher implementations. Created 6 years, 10 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
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"
(...skipping 14 matching lines...) Expand all
25 #include "base/files/file_path.h" 25 #include "base/files/file_path.h"
26 #include "content/common/sandbox_win.h" 26 #include "content/common/sandbox_win.h"
27 #include "content/public/common/sandbox_init.h" 27 #include "content/public/common/sandbox_init.h"
28 #include "content/public/common/sandboxed_process_launcher_delegate.h" 28 #include "content/public/common/sandboxed_process_launcher_delegate.h"
29 #elif defined(OS_MACOSX) 29 #elif defined(OS_MACOSX)
30 #include "content/browser/mach_broker_mac.h" 30 #include "content/browser/mach_broker_mac.h"
31 #elif defined(OS_ANDROID) 31 #elif defined(OS_ANDROID)
32 #include "base/android/jni_android.h" 32 #include "base/android/jni_android.h"
33 #include "content/browser/android/child_process_launcher_android.h" 33 #include "content/browser/android/child_process_launcher_android.h"
34 #elif defined(OS_POSIX) 34 #elif defined(OS_POSIX)
35 #include "base/memory/shared_memory.h"
35 #include "base/memory/singleton.h" 36 #include "base/memory/singleton.h"
36 #include "content/browser/renderer_host/render_sandbox_host_linux.h" 37 #include "content/browser/renderer_host/render_sandbox_host_linux.h"
37 #include "content/browser/zygote_host/zygote_host_impl_linux.h" 38 #include "content/browser/zygote_host/zygote_host_impl_linux.h"
38 #include "content/common/child_process_sandbox_support_impl_linux.h" 39 #include "content/common/child_process_sandbox_support_impl_linux.h"
39 #endif 40 #endif
40 41
41 #if defined(OS_POSIX) 42 #if defined(OS_POSIX)
43 #include "base/metrics/stats_table.h"
42 #include "base/posix/global_descriptors.h" 44 #include "base/posix/global_descriptors.h"
43 #endif 45 #endif
44 46
45 namespace content { 47 namespace content {
46 48
47 // Having the functionality of ChildProcessLauncher be in an internal 49 // Having the functionality of ChildProcessLauncher be in an internal
48 // ref counted object allows us to automatically terminate the process when the 50 // ref counted object allows us to automatically terminate the process when the
49 // parent class destructs, while still holding on to state that we need. 51 // parent class destructs, while still holding on to state that we need.
50 class ChildProcessLauncher::Context 52 class ChildProcessLauncher::Context
51 : public base::RefCountedThreadSafe<ChildProcessLauncher::Context> { 53 : public base::RefCountedThreadSafe<ChildProcessLauncher::Context> {
(...skipping 12 matching lines...) Expand all
64 terminate_child_on_shutdown_ = !CommandLine::ForCurrentProcess()-> 66 terminate_child_on_shutdown_ = !CommandLine::ForCurrentProcess()->
65 HasSwitch(switches::kChildCleanExit); 67 HasSwitch(switches::kChildCleanExit);
66 #else 68 #else
67 terminate_child_on_shutdown_ = true; 69 terminate_child_on_shutdown_ = true;
68 #endif 70 #endif
69 } 71 }
70 72
71 void Launch( 73 void Launch(
72 #if defined(OS_WIN) 74 #if defined(OS_WIN)
73 SandboxedProcessLauncherDelegate* delegate, 75 SandboxedProcessLauncherDelegate* delegate,
76 bool launch_elevated,
74 #elif defined(OS_ANDROID) 77 #elif defined(OS_ANDROID)
75 int ipcfd, 78 int ipcfd,
76 #elif defined(OS_POSIX) 79 #elif defined(OS_POSIX)
77 bool use_zygote, 80 bool use_zygote,
78 const base::EnvironmentMap& environ, 81 const base::EnvironmentMap& environ,
79 int ipcfd, 82 int ipcfd,
80 #endif 83 #endif
81 CommandLine* cmd_line, 84 CommandLine* cmd_line,
82 int child_process_id, 85 int child_process_id,
83 Client* client) { 86 Client* client) {
84 client_ = client; 87 client_ = client;
85 88
86 CHECK(BrowserThread::GetCurrentThreadIdentifier(&client_thread_id_)); 89 CHECK(BrowserThread::GetCurrentThreadIdentifier(&client_thread_id_));
87 90
88 #if defined(OS_ANDROID) 91 #if defined(OS_ANDROID)
89 // We need to close the client end of the IPC channel to reliably detect 92 // We need to close the client end of the IPC channel to reliably detect
90 // child termination. We will close this fd after we create the child 93 // child termination. We will close this fd after we create the child
91 // process which is asynchronous on Android. 94 // process which is asynchronous on Android.
92 ipcfd_ = ipcfd; 95 ipcfd_ = ipcfd;
93 #endif 96 #endif
94 BrowserThread::PostTask( 97 BrowserThread::PostTask(
95 BrowserThread::PROCESS_LAUNCHER, FROM_HERE, 98 BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
96 base::Bind( 99 base::Bind(
97 &Context::LaunchInternal, 100 &Context::LaunchInternal,
98 make_scoped_refptr(this), 101 make_scoped_refptr(this),
99 client_thread_id_, 102 client_thread_id_,
100 child_process_id, 103 child_process_id,
101 #if defined(OS_WIN) 104 #if defined(OS_WIN)
102 delegate, 105 delegate,
106 launch_elevated,
103 #elif defined(OS_ANDROID) 107 #elif defined(OS_ANDROID)
104 ipcfd, 108 ipcfd,
105 #elif defined(OS_POSIX) 109 #elif defined(OS_POSIX)
106 use_zygote, 110 use_zygote,
107 environ, 111 environ,
108 ipcfd, 112 ipcfd,
109 #endif 113 #endif
114
jam 2014/01/30 21:41:03 nit: drop the empty line
Drew Haven 2014/01/31 20:00:12 Done.
110 cmd_line)); 115 cmd_line));
111 } 116 }
112 117
113 #if defined(OS_ANDROID) 118 #if defined(OS_ANDROID)
114 static void OnChildProcessStarted( 119 static void OnChildProcessStarted(
115 // |this_object| is NOT thread safe. Only use it to post a task back. 120 // |this_object| is NOT thread safe. Only use it to post a task back.
116 scoped_refptr<Context> this_object, 121 scoped_refptr<Context> this_object,
117 BrowserThread::ID client_thread_id, 122 BrowserThread::ID client_thread_id,
118 const base::TimeTicks begin_launch_time, 123 const base::TimeTicks begin_launch_time,
119 base::ProcessHandle handle) { 124 base::ProcessHandle handle) {
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
176 } 181 }
177 } 182 }
178 183
179 static void LaunchInternal( 184 static void LaunchInternal(
180 // |this_object| is NOT thread safe. Only use it to post a task back. 185 // |this_object| is NOT thread safe. Only use it to post a task back.
181 scoped_refptr<Context> this_object, 186 scoped_refptr<Context> this_object,
182 BrowserThread::ID client_thread_id, 187 BrowserThread::ID client_thread_id,
183 int child_process_id, 188 int child_process_id,
184 #if defined(OS_WIN) 189 #if defined(OS_WIN)
185 SandboxedProcessLauncherDelegate* delegate, 190 SandboxedProcessLauncherDelegate* delegate,
191 bool launch_elevated,
186 #elif defined(OS_ANDROID) 192 #elif defined(OS_ANDROID)
187 int ipcfd, 193 int ipcfd,
188 #elif defined(OS_POSIX) 194 #elif defined(OS_POSIX)
189 bool use_zygote, 195 bool use_zygote,
190 const base::EnvironmentMap& env, 196 const base::EnvironmentMap& env,
191 int ipcfd, 197 int ipcfd,
192 #endif 198 #endif
193 CommandLine* cmd_line) { 199 CommandLine* cmd_line) {
194 scoped_ptr<CommandLine> cmd_line_deleter(cmd_line); 200 scoped_ptr<CommandLine> cmd_line_deleter(cmd_line);
195 base::TimeTicks begin_launch_time = base::TimeTicks::Now(); 201 base::TimeTicks begin_launch_time = base::TimeTicks::Now();
196 202
197 #if defined(OS_WIN) 203 #if defined(OS_WIN)
198 scoped_ptr<SandboxedProcessLauncherDelegate> delegate_deleter(delegate); 204 base::ProcessHandle handle = base::kNullProcessHandle;
199 base::ProcessHandle handle = StartSandboxedProcess(delegate, cmd_line); 205 if (launch_elevated) {
200 #elif defined(OS_ANDROID) 206 base::LaunchOptions options;
201 // Android WebView runs in single process, ensure that we never get here 207 options.start_hidden = true;
202 // when running in single process mode. 208 base::LaunchElevatedProcess(*cmd_line, options, &handle);
203 CHECK(!cmd_line->HasSwitch(switches::kSingleProcess)); 209 } else {
204 210 scoped_ptr<SandboxedProcessLauncherDelegate> delegate_deleter(delegate);
211 handle = StartSandboxedProcess(delegate, cmd_line);
212 }
213 #elif defined(OS_POSIX)
205 std::string process_type = 214 std::string process_type =
206 cmd_line->GetSwitchValueASCII(switches::kProcessType); 215 cmd_line->GetSwitchValueASCII(switches::kProcessType);
207 std::vector<FileDescriptorInfo> files_to_register; 216 std::vector<FileDescriptorInfo> files_to_register;
208 files_to_register.push_back( 217 files_to_register.push_back(
209 FileDescriptorInfo(kPrimaryIPCChannel, 218 FileDescriptorInfo(kPrimaryIPCChannel,
210 base::FileDescriptor(ipcfd, false))); 219 base::FileDescriptor(ipcfd, false)));
220 base::StatsTable* stats_table = base::StatsTable::current();
jam 2014/01/30 21:41:03 this, and some of the other changes in this file a
Drew Haven 2014/01/31 20:00:12 Done.
221 if (stats_table &&
222 base::SharedMemory::IsHandleValid(
223 stats_table->GetSharedMemoryHandle())) {
224 files_to_register.push_back(
225 FileDescriptorInfo(kStatsTableSharedMemFd,
226 stats_table->GetSharedMemoryHandle()));
227 }
228 #endif
229
230 #if defined(OS_ANDROID)
231 // Android WebView runs in single process, ensure that we never get here
232 // when running in single process mode.
233 CHECK(!cmd_line->HasSwitch(switches::kSingleProcess));
211 234
212 GetContentClient()->browser()-> 235 GetContentClient()->browser()->
213 GetAdditionalMappedFilesForChildProcess(*cmd_line, child_process_id, 236 GetAdditionalMappedFilesForChildProcess(*cmd_line, child_process_id,
214 &files_to_register); 237 &files_to_register);
215 238
216 StartChildProcess(cmd_line->argv(), files_to_register, 239 StartChildProcess(cmd_line->argv(), files_to_register,
217 base::Bind(&ChildProcessLauncher::Context::OnChildProcessStarted, 240 base::Bind(&ChildProcessLauncher::Context::OnChildProcessStarted,
218 this_object, client_thread_id, begin_launch_time)); 241 this_object, client_thread_id, begin_launch_time));
219 242
220 #elif defined(OS_POSIX) 243 #elif defined(OS_POSIX)
221 base::ProcessHandle handle = base::kNullProcessHandle; 244 base::ProcessHandle handle = base::kNullProcessHandle;
222 // We need to close the client end of the IPC channel to reliably detect 245 // We need to close the client end of the IPC channel to reliably detect
223 // child termination. 246 // child termination.
224 file_util::ScopedFD ipcfd_closer(&ipcfd); 247 file_util::ScopedFD ipcfd_closer(&ipcfd);
225 248
226 std::string process_type =
227 cmd_line->GetSwitchValueASCII(switches::kProcessType);
228 std::vector<FileDescriptorInfo> files_to_register;
229 files_to_register.push_back(
230 FileDescriptorInfo(kPrimaryIPCChannel,
231 base::FileDescriptor(ipcfd, false)));
232
233 #if !defined(OS_MACOSX) 249 #if !defined(OS_MACOSX)
234 GetContentClient()->browser()-> 250 GetContentClient()->browser()->
235 GetAdditionalMappedFilesForChildProcess(*cmd_line, child_process_id, 251 GetAdditionalMappedFilesForChildProcess(*cmd_line, child_process_id,
236 &files_to_register); 252 &files_to_register);
237 if (use_zygote) { 253 if (use_zygote) {
238 handle = ZygoteHostImpl::GetInstance()->ForkRequest(cmd_line->argv(), 254 handle = ZygoteHostImpl::GetInstance()->ForkRequest(cmd_line->argv(),
239 files_to_register, 255 files_to_register,
240 process_type); 256 process_type);
241 } else 257 } else
242 // Fall through to the normal posix case below when we're not zygoting. 258 // Fall through to the normal posix case below when we're not zygoting.
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 #endif 339 #endif
324 starting_ = false; 340 starting_ = false;
325 process_.set_handle(handle); 341 process_.set_handle(handle);
326 if (!handle) 342 if (!handle)
327 LOG(ERROR) << "Failed to launch child process"; 343 LOG(ERROR) << "Failed to launch child process";
328 344
329 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 345 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
330 zygote_ = zygote; 346 zygote_ = zygote;
331 #endif 347 #endif
332 if (client_) { 348 if (client_) {
333 client_->OnProcessLaunched(); 349 if (handle) {
350 client_->OnProcessLaunched();
351 } else {
352 client_->OnProcessLaunchFailed();
353 }
334 } else { 354 } else {
335 Terminate(); 355 Terminate();
336 } 356 }
337 } 357 }
338 358
339 void Terminate() { 359 void Terminate() {
340 if (!process_.handle()) 360 if (!process_.handle())
341 return; 361 return;
342 362
343 if (!terminate_child_on_shutdown_) 363 if (!terminate_child_on_shutdown_)
(...skipping 17 matching lines...) Expand all
361 base::Process process(handle); 381 base::Process process(handle);
362 process.SetProcessBackgrounded(background); 382 process.SetProcessBackgrounded(background);
363 } 383 }
364 384
365 static void TerminateInternal( 385 static void TerminateInternal(
366 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 386 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
367 bool zygote, 387 bool zygote,
368 #endif 388 #endif
369 base::ProcessHandle handle) { 389 base::ProcessHandle handle) {
370 #if defined(OS_ANDROID) 390 #if defined(OS_ANDROID)
371 LOG(INFO) << "ChromeProcess: Stopping process with handle " << handle; 391 VLOG(0) << "ChromeProcess: Stopping process with handle " << handle;
372 StopChildProcess(handle); 392 StopChildProcess(handle);
373 #else 393 #else
374 base::Process process(handle); 394 base::Process process(handle);
375 // Client has gone away, so just kill the process. Using exit code 0 395 // Client has gone away, so just kill the process. Using exit code 0
376 // means that UMA won't treat this as a crash. 396 // means that UMA won't treat this as a crash.
377 process.Terminate(RESULT_CODE_NORMAL_EXIT); 397 process.Terminate(RESULT_CODE_NORMAL_EXIT);
378 // On POSIX, we must additionally reap the child. 398 // On POSIX, we must additionally reap the child.
379 #if defined(OS_POSIX) 399 #if defined(OS_POSIX)
380 #if !defined(OS_MACOSX) 400 #if !defined(OS_MACOSX)
381 if (zygote) { 401 if (zygote) {
(...skipping 24 matching lines...) Expand all
406 int ipcfd_; 426 int ipcfd_;
407 #elif defined(OS_POSIX) && !defined(OS_MACOSX) 427 #elif defined(OS_POSIX) && !defined(OS_MACOSX)
408 bool zygote_; 428 bool zygote_;
409 #endif 429 #endif
410 }; 430 };
411 431
412 432
413 ChildProcessLauncher::ChildProcessLauncher( 433 ChildProcessLauncher::ChildProcessLauncher(
414 #if defined(OS_WIN) 434 #if defined(OS_WIN)
415 SandboxedProcessLauncherDelegate* delegate, 435 SandboxedProcessLauncherDelegate* delegate,
436 bool launch_elevated,
416 #elif defined(OS_POSIX) 437 #elif defined(OS_POSIX)
417 bool use_zygote, 438 bool use_zygote,
418 const base::EnvironmentMap& environ, 439 const base::EnvironmentMap& environ,
419 int ipcfd, 440 int ipcfd,
420 #endif 441 #endif
421 CommandLine* cmd_line, 442 CommandLine* cmd_line,
422 int child_process_id, 443 int child_process_id,
423 Client* client) { 444 Client* client) {
424 context_ = new Context(); 445 context_ = new Context();
425 context_->Launch( 446 context_->Launch(
426 #if defined(OS_WIN) 447 #if defined(OS_WIN)
427 delegate, 448 delegate,
449 launch_elevated,
428 #elif defined(OS_ANDROID) 450 #elif defined(OS_ANDROID)
429 ipcfd, 451 ipcfd,
430 #elif defined(OS_POSIX) 452 #elif defined(OS_POSIX)
431 use_zygote, 453 use_zygote,
432 environ, 454 environ,
433 ipcfd, 455 ipcfd,
434 #endif 456 #endif
435 cmd_line, 457 cmd_line,
436 child_process_id, 458 child_process_id,
437 client); 459 client);
(...skipping 19 matching lines...) Expand all
457 if (handle == base::kNullProcessHandle) { 479 if (handle == base::kNullProcessHandle) {
458 // Process is already gone, so return the cached termination status. 480 // Process is already gone, so return the cached termination status.
459 if (exit_code) 481 if (exit_code)
460 *exit_code = context_->exit_code_; 482 *exit_code = context_->exit_code_;
461 return context_->termination_status_; 483 return context_->termination_status_;
462 } 484 }
463 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 485 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
464 if (context_->zygote_) { 486 if (context_->zygote_) {
465 context_->termination_status_ = ZygoteHostImpl::GetInstance()-> 487 context_->termination_status_ = ZygoteHostImpl::GetInstance()->
466 GetTerminationStatus(handle, known_dead, &context_->exit_code_); 488 GetTerminationStatus(handle, known_dead, &context_->exit_code_);
467 } else 489 } else if (known_dead) {
490 context_->termination_status_ =
491 base::GetKnownDeadTerminationStatus(handle, &context_->exit_code_);
492 } else {
468 #elif defined(OS_MACOSX) 493 #elif defined(OS_MACOSX)
469 if (known_dead) { 494 if (known_dead) {
470 context_->termination_status_ = 495 context_->termination_status_ =
471 base::GetKnownDeadTerminationStatus(handle, &context_->exit_code_); 496 base::GetKnownDeadTerminationStatus(handle, &context_->exit_code_);
472 } else 497 } else {
498 #elif defined(OS_ANDROID)
499 if (IsChildProcessOomProtected(handle)) {
500 context_->termination_status_ = base::TERMINATION_STATUS_OOM_PROTECTED;
501 } else {
502 #else
503 {
473 #endif 504 #endif
474 {
475 context_->termination_status_ = 505 context_->termination_status_ =
476 base::GetTerminationStatus(handle, &context_->exit_code_); 506 base::GetTerminationStatus(handle, &context_->exit_code_);
477 } 507 }
478 508
479 if (exit_code) 509 if (exit_code)
480 *exit_code = context_->exit_code_; 510 *exit_code = context_->exit_code_;
481 511
482 // POSIX: If the process crashed, then the kernel closed the socket 512 // POSIX: If the process crashed, then the kernel closed the socket
483 // for it and so the child has already died by the time we get 513 // for it and so the child has already died by the time we get
484 // here. Since GetTerminationStatus called waitpid with WNOHANG, 514 // here. Since GetTerminationStatus called waitpid with WNOHANG,
(...skipping 14 matching lines...) Expand all
499 GetHandle(), background)); 529 GetHandle(), background));
500 } 530 }
501 531
502 void ChildProcessLauncher::SetTerminateChildOnShutdown( 532 void ChildProcessLauncher::SetTerminateChildOnShutdown(
503 bool terminate_on_shutdown) { 533 bool terminate_on_shutdown) {
504 if (context_.get()) 534 if (context_.get())
505 context_->set_terminate_child_on_shutdown(terminate_on_shutdown); 535 context_->set_terminate_child_on_shutdown(terminate_on_shutdown);
506 } 536 }
507 537
508 } // namespace content 538 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698