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

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

Issue 1685183004: Bootstrap Mojo IPC independent of Chrome IPC (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 9 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
« no previous file with comments | « content/browser/child_process_launcher.h ('k') | content/browser/mojo/mojo_shell_client_host.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 The Chromium Authors. All rights reserved. 1 // Copyright 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> 7 #include <utility>
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/files/file_util.h" 11 #include "base/files/file_util.h"
12 #include "base/i18n/icu_util.h" 12 #include "base/i18n/icu_util.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/memory/scoped_ptr.h" 14 #include "base/memory/scoped_ptr.h"
15 #include "base/metrics/histogram.h" 15 #include "base/metrics/histogram.h"
16 #include "base/process/launch.h" 16 #include "base/process/launch.h"
17 #include "base/process/process.h" 17 #include "base/process/process.h"
18 #include "base/strings/string_number_conversions.h" 18 #include "base/strings/string_number_conversions.h"
19 #include "base/synchronization/lock.h" 19 #include "base/synchronization/lock.h"
20 #include "base/threading/thread.h" 20 #include "base/threading/thread.h"
21 #include "build/build_config.h" 21 #include "build/build_config.h"
22 #include "content/public/browser/content_browser_client.h" 22 #include "content/public/browser/content_browser_client.h"
23 #include "content/public/common/content_descriptors.h" 23 #include "content/public/common/content_descriptors.h"
24 #include "content/public/common/content_switches.h" 24 #include "content/public/common/content_switches.h"
25 #include "content/public/common/result_codes.h" 25 #include "content/public/common/result_codes.h"
26 #include "content/public/common/sandboxed_process_launcher_delegate.h" 26 #include "content/public/common/sandboxed_process_launcher_delegate.h"
27 #include "mojo/edk/embedder/embedder.h"
28 #include "mojo/edk/embedder/scoped_platform_handle.h"
27 29
28 #if defined(OS_WIN) 30 #if defined(OS_WIN)
29 #include "base/files/file_path.h" 31 #include "base/files/file_path.h"
32 #include "base/win/scoped_handle.h"
33 #include "base/win/win_util.h"
30 #include "content/common/sandbox_win.h" 34 #include "content/common/sandbox_win.h"
31 #include "content/public/common/sandbox_init.h" 35 #include "content/public/common/sandbox_init.h"
32 #elif defined(OS_MACOSX) 36 #elif defined(OS_MACOSX)
33 #include "content/browser/bootstrap_sandbox_manager_mac.h" 37 #include "content/browser/bootstrap_sandbox_manager_mac.h"
34 #include "content/browser/mach_broker_mac.h" 38 #include "content/browser/mach_broker_mac.h"
35 #include "sandbox/mac/bootstrap_sandbox.h" 39 #include "sandbox/mac/bootstrap_sandbox.h"
36 #include "sandbox/mac/pre_exec_delegate.h" 40 #include "sandbox/mac/pre_exec_delegate.h"
37 #elif defined(OS_ANDROID) 41 #elif defined(OS_ANDROID)
38 #include "base/android/jni_android.h" 42 #include "base/android/jni_android.h"
39 #include "content/browser/android/child_process_launcher_android.h" 43 #include "content/browser/android/child_process_launcher_android.h"
(...skipping 12 matching lines...) Expand all
52 #include "gin/v8_initializer.h" 56 #include "gin/v8_initializer.h"
53 #endif 57 #endif
54 58
55 namespace content { 59 namespace content {
56 60
57 namespace { 61 namespace {
58 62
59 typedef base::Callback<void(ZygoteHandle, 63 typedef base::Callback<void(ZygoteHandle,
60 #if defined(OS_ANDROID) 64 #if defined(OS_ANDROID)
61 base::ScopedFD, 65 base::ScopedFD,
66 base::ScopedFD,
62 #endif 67 #endif
63 base::Process)> NotifyCallback; 68 base::Process)> NotifyCallback;
64 69
65 void RecordHistogramsOnLauncherThread(base::TimeDelta launch_time) { 70 void RecordHistogramsOnLauncherThread(base::TimeDelta launch_time) {
66 DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER); 71 DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
67 // Log the launch time, separating out the first one (which will likely be 72 // Log the launch time, separating out the first one (which will likely be
68 // slower due to the rest of the browser initializing at the same time). 73 // slower due to the rest of the browser initializing at the same time).
69 static bool done_first_launch = false; 74 static bool done_first_launch = false;
70 if (done_first_launch) { 75 if (done_first_launch) {
71 UMA_HISTOGRAM_TIMES("MPArch.ChildProcessLaunchSubsequent", launch_time); 76 UMA_HISTOGRAM_TIMES("MPArch.ChildProcessLaunchSubsequent", launch_time);
72 } else { 77 } else {
73 UMA_HISTOGRAM_TIMES("MPArch.ChildProcessLaunchFirst", launch_time); 78 UMA_HISTOGRAM_TIMES("MPArch.ChildProcessLaunchFirst", launch_time);
74 done_first_launch = true; 79 done_first_launch = true;
75 } 80 }
76 } 81 }
77 82
78 #if defined(OS_ANDROID) 83 #if defined(OS_ANDROID)
79 // TODO(sievers): Remove this by defining better what happens on what 84 // TODO(sievers): Remove this by defining better what happens on what
80 // thread in the corresponding Java code. 85 // thread in the corresponding Java code.
81 void OnChildProcessStartedAndroid(const NotifyCallback& callback, 86 void OnChildProcessStartedAndroid(const NotifyCallback& callback,
82 BrowserThread::ID client_thread_id, 87 BrowserThread::ID client_thread_id,
83 const base::TimeTicks begin_launch_time, 88 const base::TimeTicks begin_launch_time,
84 base::ScopedFD ipcfd, 89 base::ScopedFD ipcfd,
90 base::ScopedFD mojo_fd,
85 base::ProcessHandle handle) { 91 base::ProcessHandle handle) {
86 // This can be called on the launcher thread or UI thread. 92 // This can be called on the launcher thread or UI thread.
87 base::TimeDelta launch_time = base::TimeTicks::Now() - begin_launch_time; 93 base::TimeDelta launch_time = base::TimeTicks::Now() - begin_launch_time;
88 BrowserThread::PostTask( 94 BrowserThread::PostTask(
89 BrowserThread::PROCESS_LAUNCHER, FROM_HERE, 95 BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
90 base::Bind(&RecordHistogramsOnLauncherThread, launch_time)); 96 base::Bind(&RecordHistogramsOnLauncherThread, launch_time));
91 97
92 base::Closure callback_on_client_thread( 98 base::Closure callback_on_client_thread(
93 base::Bind(callback, nullptr, base::Passed(&ipcfd), 99 base::Bind(callback, nullptr, base::Passed(&ipcfd),
94 base::Passed(base::Process(handle)))); 100 base::Passed(&mojo_fd), base::Passed(base::Process(handle))));
95 if (BrowserThread::CurrentlyOn(client_thread_id)) { 101 if (BrowserThread::CurrentlyOn(client_thread_id)) {
96 callback_on_client_thread.Run(); 102 callback_on_client_thread.Run();
97 } else { 103 } else {
98 BrowserThread::PostTask( 104 BrowserThread::PostTask(
99 client_thread_id, FROM_HERE, callback_on_client_thread); 105 client_thread_id, FROM_HERE, callback_on_client_thread);
100 } 106 }
101 } 107 }
102 #endif 108 #endif
103 109
104 void LaunchOnLauncherThread(const NotifyCallback& callback, 110 void LaunchOnLauncherThread(const NotifyCallback& callback,
105 BrowserThread::ID client_thread_id, 111 BrowserThread::ID client_thread_id,
106 int child_process_id, 112 int child_process_id,
107 SandboxedProcessLauncherDelegate* delegate, 113 SandboxedProcessLauncherDelegate* delegate,
108 #if defined(OS_ANDROID) 114 #if defined(OS_ANDROID)
109 base::ScopedFD ipcfd, 115 base::ScopedFD ipcfd,
110 #endif 116 #endif
117 mojo::edk::ScopedPlatformHandle client_handle,
111 base::CommandLine* cmd_line) { 118 base::CommandLine* cmd_line) {
112 DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER); 119 DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
113 scoped_ptr<SandboxedProcessLauncherDelegate> delegate_deleter(delegate); 120 scoped_ptr<SandboxedProcessLauncherDelegate> delegate_deleter(delegate);
114 #if !defined(OS_ANDROID) 121 #if !defined(OS_ANDROID)
115 ZygoteHandle zygote = nullptr; 122 ZygoteHandle zygote = nullptr;
116 #endif 123 #endif
117 #if defined(OS_WIN) 124 #if defined(OS_WIN)
118 bool launch_elevated = delegate->ShouldLaunchElevated(); 125 bool launch_elevated = delegate->ShouldLaunchElevated();
119 #elif defined(OS_MACOSX) 126 #elif defined(OS_MACOSX)
120 base::EnvironmentMap env = delegate->GetEnvironment(); 127 base::EnvironmentMap env = delegate->GetEnvironment();
121 base::ScopedFD ipcfd = delegate->TakeIpcFd(); 128 base::ScopedFD ipcfd = delegate->TakeIpcFd();
122 #elif defined(OS_POSIX) && !defined(OS_ANDROID) 129 #elif defined(OS_POSIX) && !defined(OS_ANDROID)
123 base::EnvironmentMap env = delegate->GetEnvironment(); 130 base::EnvironmentMap env = delegate->GetEnvironment();
124 base::ScopedFD ipcfd = delegate->TakeIpcFd(); 131 base::ScopedFD ipcfd = delegate->TakeIpcFd();
125 #endif 132 #endif
126 scoped_ptr<base::CommandLine> cmd_line_deleter(cmd_line); 133 scoped_ptr<base::CommandLine> cmd_line_deleter(cmd_line);
127 base::TimeTicks begin_launch_time = base::TimeTicks::Now(); 134 base::TimeTicks begin_launch_time = base::TimeTicks::Now();
128 135
129 base::Process process; 136 base::Process process;
130 #if defined(OS_WIN) 137 #if defined(OS_WIN)
131 if (launch_elevated) { 138 if (launch_elevated) {
139 // TODO(rockot): We may want to support Mojo IPC to elevated processes as
140 // well, but this isn't currently feasible without sharing a pipe path on
141 // the command line as elevated process launch goes through ShellExecuteEx.
132 base::LaunchOptions options; 142 base::LaunchOptions options;
133 options.start_hidden = true; 143 options.start_hidden = true;
134 process = base::LaunchElevatedProcess(*cmd_line, options); 144 process = base::LaunchElevatedProcess(*cmd_line, options);
135 } else { 145 } else {
136 process = StartSandboxedProcess( 146 base::HandlesToInheritVector handles;
137 delegate, cmd_line, base::HandlesToInheritVector()); 147 handles.push_back(client_handle.get().handle);
148 cmd_line->AppendSwitchASCII(
149 mojo::edk::PlatformChannelPair::kMojoPlatformChannelHandleSwitch,
150 base::UintToString(base::win::HandleToUint32(handles[0])));
151 process = StartSandboxedProcess(delegate, cmd_line, handles);
138 } 152 }
139 #elif defined(OS_POSIX) 153 #elif defined(OS_POSIX)
140 std::string process_type = 154 std::string process_type =
141 cmd_line->GetSwitchValueASCII(switches::kProcessType); 155 cmd_line->GetSwitchValueASCII(switches::kProcessType);
142 scoped_ptr<FileDescriptorInfo> files_to_register( 156 scoped_ptr<FileDescriptorInfo> files_to_register(
143 FileDescriptorInfoImpl::Create()); 157 FileDescriptorInfoImpl::Create());
144 158
159 base::ScopedFD mojo_fd(client_handle.release().handle);
160 DCHECK(mojo_fd.is_valid());
161
145 #if defined(OS_ANDROID) 162 #if defined(OS_ANDROID)
146 files_to_register->Share(kPrimaryIPCChannel, ipcfd.get()); 163 files_to_register->Share(kPrimaryIPCChannel, ipcfd.get());
164 files_to_register->Share(kMojoIPCChannel, mojo_fd.get());
147 #else 165 #else
148 files_to_register->Transfer(kPrimaryIPCChannel, std::move(ipcfd)); 166 files_to_register->Transfer(kPrimaryIPCChannel, std::move(ipcfd));
167 files_to_register->Transfer(kMojoIPCChannel, std::move(mojo_fd));
149 #endif 168 #endif
150 #endif 169 #endif
151 170
152 #if defined(OS_POSIX) && !defined(OS_MACOSX) 171 #if defined(OS_POSIX) && !defined(OS_MACOSX)
153 std::map<int, base::MemoryMappedFile::Region> regions; 172 std::map<int, base::MemoryMappedFile::Region> regions;
154 GetContentClient()->browser()->GetAdditionalMappedFilesForChildProcess( 173 GetContentClient()->browser()->GetAdditionalMappedFilesForChildProcess(
155 *cmd_line, child_process_id, files_to_register.get() 174 *cmd_line, child_process_id, files_to_register.get()
156 #if defined(OS_ANDROID) 175 #if defined(OS_ANDROID)
157 , &regions 176 , &regions
158 #endif 177 #endif
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
216 kAndroidICUDataDescriptor, 235 kAndroidICUDataDescriptor,
217 base::i18n::GetIcuDataFileHandle(&regions[kAndroidICUDataDescriptor])); 236 base::i18n::GetIcuDataFileHandle(&regions[kAndroidICUDataDescriptor]));
218 237
219 // Android WebView runs in single process, ensure that we never get here 238 // Android WebView runs in single process, ensure that we never get here
220 // when running in single process mode. 239 // when running in single process mode.
221 CHECK(!cmd_line->HasSwitch(switches::kSingleProcess)); 240 CHECK(!cmd_line->HasSwitch(switches::kSingleProcess));
222 241
223 StartChildProcess( 242 StartChildProcess(
224 cmd_line->argv(), child_process_id, std::move(files_to_register), regions, 243 cmd_line->argv(), child_process_id, std::move(files_to_register), regions,
225 base::Bind(&OnChildProcessStartedAndroid, callback, client_thread_id, 244 base::Bind(&OnChildProcessStartedAndroid, callback, client_thread_id,
226 begin_launch_time, base::Passed(&ipcfd))); 245 begin_launch_time, base::Passed(&ipcfd),
246 base::Passed(&mojo_fd)));
227 247
228 #elif defined(OS_POSIX) 248 #elif defined(OS_POSIX)
229 // We need to close the client end of the IPC channel to reliably detect 249 // We need to close the client end of the IPC channel to reliably detect
230 // child termination. 250 // child termination.
231 251
232 #if !defined(OS_MACOSX) 252 #if !defined(OS_MACOSX)
233 ZygoteHandle* zygote_handle = delegate->GetZygote(); 253 ZygoteHandle* zygote_handle = delegate->GetZygote();
234 // If |zygote_handle| is null, a zygote should not be used. 254 // If |zygote_handle| is null, a zygote should not be used.
235 if (zygote_handle) { 255 if (zygote_handle) {
236 // This code runs on the PROCESS_LAUNCHER thread so race conditions are not 256 // This code runs on the PROCESS_LAUNCHER thread so race conditions are not
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
416 !cmd_line->HasSwitch(switches::kNoSandbox)); 436 !cmd_line->HasSwitch(switches::kNoSandbox));
417 437
418 // We need to close the client end of the IPC channel to reliably detect 438 // We need to close the client end of the IPC channel to reliably detect
419 // child termination. We will close this fd after we create the child 439 // child termination. We will close this fd after we create the child
420 // process which is asynchronous on Android. 440 // process which is asynchronous on Android.
421 base::ScopedFD ipcfd(delegate->TakeIpcFd().release()); 441 base::ScopedFD ipcfd(delegate->TakeIpcFd().release());
422 #endif 442 #endif
423 NotifyCallback reply_callback(base::Bind(&ChildProcessLauncher::DidLaunch, 443 NotifyCallback reply_callback(base::Bind(&ChildProcessLauncher::DidLaunch,
424 weak_factory_.GetWeakPtr(), 444 weak_factory_.GetWeakPtr(),
425 terminate_child_on_shutdown_)); 445 terminate_child_on_shutdown_));
446 mojo::edk::ScopedPlatformHandle client_handle =
447 mojo_platform_channel_.PassClientHandle();
426 BrowserThread::PostTask( 448 BrowserThread::PostTask(
427 BrowserThread::PROCESS_LAUNCHER, FROM_HERE, 449 BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
428 base::Bind(&LaunchOnLauncherThread, reply_callback, client_thread_id_, 450 base::Bind(&LaunchOnLauncherThread, reply_callback, client_thread_id_,
429 child_process_id, delegate, 451 child_process_id, delegate,
430 #if defined(OS_ANDROID) 452 #if defined(OS_ANDROID)
431 base::Passed(&ipcfd), 453 base::Passed(&ipcfd),
432 #endif 454 #endif
433 cmd_line)); 455 base::Passed(&client_handle), cmd_line));
434 } 456 }
435 457
436 void ChildProcessLauncher::UpdateTerminationStatus(bool known_dead) { 458 void ChildProcessLauncher::UpdateTerminationStatus(bool known_dead) {
437 DCHECK(CalledOnValidThread()); 459 DCHECK(CalledOnValidThread());
438 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 460 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
439 if (zygote_) { 461 if (zygote_) {
440 termination_status_ = zygote_->GetTerminationStatus( 462 termination_status_ = zygote_->GetTerminationStatus(
441 process_.Handle(), known_dead, &exit_code_); 463 process_.Handle(), known_dead, &exit_code_);
442 } else if (known_dead) { 464 } else if (known_dead) {
443 termination_status_ = 465 termination_status_ =
(...skipping 23 matching lines...) Expand all
467 base::Bind(&SetProcessBackgroundedOnLauncherThread, 489 base::Bind(&SetProcessBackgroundedOnLauncherThread,
468 base::Passed(&to_pass), background)); 490 base::Passed(&to_pass), background));
469 } 491 }
470 492
471 void ChildProcessLauncher::DidLaunch( 493 void ChildProcessLauncher::DidLaunch(
472 base::WeakPtr<ChildProcessLauncher> instance, 494 base::WeakPtr<ChildProcessLauncher> instance,
473 bool terminate_on_shutdown, 495 bool terminate_on_shutdown,
474 ZygoteHandle zygote, 496 ZygoteHandle zygote,
475 #if defined(OS_ANDROID) 497 #if defined(OS_ANDROID)
476 base::ScopedFD ipcfd, 498 base::ScopedFD ipcfd,
499 base::ScopedFD mojo_fd,
477 #endif 500 #endif
478 base::Process process) { 501 base::Process process) {
479 if (!process.IsValid()) 502 if (!process.IsValid())
480 LOG(ERROR) << "Failed to launch child process"; 503 LOG(ERROR) << "Failed to launch child process";
481 504
482 if (instance.get()) { 505 if (instance.get()) {
483 instance->Notify(zygote, 506 instance->Notify(zygote,
484 #if defined(OS_ANDROID) 507 #if defined(OS_ANDROID)
485 std::move(ipcfd), 508 std::move(ipcfd),
486 #endif 509 #endif
(...skipping 11 matching lines...) Expand all
498 521
499 void ChildProcessLauncher::Notify(ZygoteHandle zygote, 522 void ChildProcessLauncher::Notify(ZygoteHandle zygote,
500 #if defined(OS_ANDROID) 523 #if defined(OS_ANDROID)
501 base::ScopedFD ipcfd, 524 base::ScopedFD ipcfd,
502 #endif 525 #endif
503 base::Process process) { 526 base::Process process) {
504 DCHECK(CalledOnValidThread()); 527 DCHECK(CalledOnValidThread());
505 starting_ = false; 528 starting_ = false;
506 process_ = std::move(process); 529 process_ = std::move(process);
507 530
531 if (process_.IsValid()) {
532 // Set up Mojo IPC to the new process.
533 mojo::edk::ChildProcessLaunched(process_.Handle(),
534 mojo_platform_channel_.PassServerHandle());
535 }
536
508 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 537 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
509 zygote_ = zygote; 538 zygote_ = zygote;
510 #endif 539 #endif
511 if (process_.IsValid()) { 540 if (process_.IsValid()) {
512 client_->OnProcessLaunched(); 541 client_->OnProcessLaunched();
513 } else { 542 } else {
514 termination_status_ = base::TERMINATION_STATUS_LAUNCH_FAILED; 543 termination_status_ = base::TERMINATION_STATUS_LAUNCH_FAILED;
515 client_->OnProcessLaunchFailed(); 544 client_->OnProcessLaunchFailed();
516 } 545 }
517 } 546 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
556 } 585 }
557 586
558 ChildProcessLauncher::Client* ChildProcessLauncher::ReplaceClientForTest( 587 ChildProcessLauncher::Client* ChildProcessLauncher::ReplaceClientForTest(
559 Client* client) { 588 Client* client) {
560 Client* ret = client_; 589 Client* ret = client_;
561 client_ = client; 590 client_ = client;
562 return ret; 591 return ret;
563 } 592 }
564 593
565 } // namespace content 594 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/child_process_launcher.h ('k') | content/browser/mojo/mojo_shell_client_host.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698