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

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: and fix posix Created 4 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 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/process.h" 16 #include "base/process/process.h"
17 #include "base/rand_util.h"
17 #include "base/strings/string_number_conversions.h" 18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/stringprintf.h"
20 #include "base/strings/utf_string_conversions.h"
18 #include "base/synchronization/lock.h" 21 #include "base/synchronization/lock.h"
19 #include "base/threading/thread.h" 22 #include "base/threading/thread.h"
20 #include "build/build_config.h" 23 #include "build/build_config.h"
21 #include "content/public/browser/content_browser_client.h" 24 #include "content/public/browser/content_browser_client.h"
22 #include "content/public/common/content_descriptors.h" 25 #include "content/public/common/content_descriptors.h"
23 #include "content/public/common/content_switches.h" 26 #include "content/public/common/content_switches.h"
24 #include "content/public/common/result_codes.h" 27 #include "content/public/common/result_codes.h"
25 #include "content/public/common/sandboxed_process_launcher_delegate.h" 28 #include "content/public/common/sandboxed_process_launcher_delegate.h"
29 #include "mojo/edk/embedder/embedder.h"
30 #include "mojo/edk/embedder/platform_channel_pair.h"
31 #include "mojo/edk/embedder/scoped_platform_handle.h"
26 32
27 #if defined(OS_WIN) 33 #if defined(OS_WIN)
28 #include "base/files/file_path.h" 34 #include "base/files/file_path.h"
29 #include "content/common/sandbox_win.h" 35 #include "content/common/sandbox_win.h"
30 #include "content/public/common/sandbox_init.h" 36 #include "content/public/common/sandbox_init.h"
31 #elif defined(OS_MACOSX) 37 #elif defined(OS_MACOSX)
32 #include "content/browser/bootstrap_sandbox_manager_mac.h" 38 #include "content/browser/bootstrap_sandbox_manager_mac.h"
33 #include "content/browser/mach_broker_mac.h" 39 #include "content/browser/mach_broker_mac.h"
34 #include "sandbox/mac/bootstrap_sandbox.h" 40 #include "sandbox/mac/bootstrap_sandbox.h"
35 #include "sandbox/mac/pre_exec_delegate.h" 41 #include "sandbox/mac/pre_exec_delegate.h"
(...skipping 15 matching lines...) Expand all
51 #include "gin/v8_initializer.h" 57 #include "gin/v8_initializer.h"
52 #endif 58 #endif
53 59
54 namespace content { 60 namespace content {
55 61
56 namespace { 62 namespace {
57 63
58 typedef base::Callback<void(ZygoteHandle, 64 typedef base::Callback<void(ZygoteHandle,
59 #if defined(OS_ANDROID) 65 #if defined(OS_ANDROID)
60 base::ScopedFD, 66 base::ScopedFD,
67 base::ScopedFD,
61 #endif 68 #endif
62 base::Process)> NotifyCallback; 69 base::Process)> NotifyCallback;
63 70
64 void RecordHistogramsOnLauncherThread(base::TimeDelta launch_time) { 71 void RecordHistogramsOnLauncherThread(base::TimeDelta launch_time) {
65 DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER); 72 DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
66 // Log the launch time, separating out the first one (which will likely be 73 // Log the launch time, separating out the first one (which will likely be
67 // slower due to the rest of the browser initializing at the same time). 74 // slower due to the rest of the browser initializing at the same time).
68 static bool done_first_launch = false; 75 static bool done_first_launch = false;
69 if (done_first_launch) { 76 if (done_first_launch) {
70 UMA_HISTOGRAM_TIMES("MPArch.ChildProcessLaunchSubsequent", launch_time); 77 UMA_HISTOGRAM_TIMES("MPArch.ChildProcessLaunchSubsequent", launch_time);
71 } else { 78 } else {
72 UMA_HISTOGRAM_TIMES("MPArch.ChildProcessLaunchFirst", launch_time); 79 UMA_HISTOGRAM_TIMES("MPArch.ChildProcessLaunchFirst", launch_time);
73 done_first_launch = true; 80 done_first_launch = true;
74 } 81 }
75 } 82 }
76 83
84 #if defined(OS_WIN)
85 // This generates a pipe name and secret to use for the Mojo IPC channel on
86 // Windows.
87 mojo::edk::ScopedPlatformHandle CreateMojoNamedPipe(base::CommandLine* cmd_line,
88 std::string* secret) {
89 std::string pipe_name =
90 base::StringPrintf("\\\\.\\pipe\\chrome.%u.%u.%I64u",
91 GetCurrentProcessId(), GetCurrentThreadId(),
92 base::RandUint64());
93 std::string pipe_secret = mojo::edk::GenerateRandomToken();
94
95 const DWORD kOpenMode = PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED |
96 FILE_FLAG_FIRST_PIPE_INSTANCE;
97 const DWORD kPipeMode = PIPE_TYPE_BYTE | PIPE_READMODE_BYTE;
98 mojo::edk::ScopedPlatformHandle pipe(mojo::edk::PlatformHandle(
99 CreateNamedPipeW(base::UTF8ToWide(pipe_name).c_str(), kOpenMode,
100 kPipeMode,
101 1, // Max instances.
102 4096, // Out buffer size.
103 4096, // In buffer size.
104 5000, // Timeout in milliseconds.
105 nullptr))); // Default security descriptor.
106 PCHECK(pipe.is_valid());
107
108 cmd_line->AppendSwitchASCII(switches::kMojoChannelName, pipe_name);
109 cmd_line->AppendSwitchASCII(switches::kMojoChannelSecret, pipe_secret);
110
111 *secret = pipe_secret;
112 return pipe;
113 }
114 #endif
115
77 #if defined(OS_ANDROID) 116 #if defined(OS_ANDROID)
78 // TODO(sievers): Remove this by defining better what happens on what 117 // TODO(sievers): Remove this by defining better what happens on what
79 // thread in the corresponding Java code. 118 // thread in the corresponding Java code.
80 void OnChildProcessStartedAndroid(const NotifyCallback& callback, 119 void OnChildProcessStartedAndroid(const NotifyCallback& callback,
81 BrowserThread::ID client_thread_id, 120 BrowserThread::ID client_thread_id,
82 const base::TimeTicks begin_launch_time, 121 const base::TimeTicks begin_launch_time,
83 base::ScopedFD ipcfd, 122 base::ScopedFD ipcfd,
123 base::ScopedFD mojo_fd,
84 base::ProcessHandle handle) { 124 base::ProcessHandle handle) {
85 // This can be called on the launcher thread or UI thread. 125 // This can be called on the launcher thread or UI thread.
86 base::TimeDelta launch_time = base::TimeTicks::Now() - begin_launch_time; 126 base::TimeDelta launch_time = base::TimeTicks::Now() - begin_launch_time;
87 BrowserThread::PostTask( 127 BrowserThread::PostTask(
88 BrowserThread::PROCESS_LAUNCHER, FROM_HERE, 128 BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
89 base::Bind(&RecordHistogramsOnLauncherThread, launch_time)); 129 base::Bind(&RecordHistogramsOnLauncherThread, launch_time));
90 130
91 base::Closure callback_on_client_thread( 131 base::Closure callback_on_client_thread(
92 base::Bind(callback, nullptr, base::Passed(&ipcfd), 132 base::Bind(callback, nullptr, base::Passed(&ipcfd),
93 base::Passed(base::Process(handle)))); 133 base::Passed(&mojo_fd), base::Passed(base::Process(handle))));
94 if (BrowserThread::CurrentlyOn(client_thread_id)) { 134 if (BrowserThread::CurrentlyOn(client_thread_id)) {
95 callback_on_client_thread.Run(); 135 callback_on_client_thread.Run();
96 } else { 136 } else {
97 BrowserThread::PostTask( 137 BrowserThread::PostTask(
98 client_thread_id, FROM_HERE, callback_on_client_thread); 138 client_thread_id, FROM_HERE, callback_on_client_thread);
99 } 139 }
100 } 140 }
101 #endif 141 #endif
102 142
103 void LaunchOnLauncherThread(const NotifyCallback& callback, 143 void LaunchOnLauncherThread(const NotifyCallback& callback,
104 BrowserThread::ID client_thread_id, 144 BrowserThread::ID client_thread_id,
105 int child_process_id, 145 int child_process_id,
106 SandboxedProcessLauncherDelegate* delegate, 146 SandboxedProcessLauncherDelegate* delegate,
107 #if defined(OS_ANDROID) 147 #if defined(OS_ANDROID)
108 base::ScopedFD ipcfd, 148 base::ScopedFD ipcfd,
109 #endif 149 #endif
150 mojo::edk::ScopedPlatformHandle client_handle,
110 base::CommandLine* cmd_line) { 151 base::CommandLine* cmd_line) {
111 DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER); 152 DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
112 scoped_ptr<SandboxedProcessLauncherDelegate> delegate_deleter(delegate); 153 scoped_ptr<SandboxedProcessLauncherDelegate> delegate_deleter(delegate);
113 #if !defined(OS_ANDROID) 154 #if !defined(OS_ANDROID)
114 ZygoteHandle zygote = nullptr; 155 ZygoteHandle zygote = nullptr;
115 #endif 156 #endif
116 #if defined(OS_WIN) 157 #if defined(OS_WIN)
117 bool launch_elevated = delegate->ShouldLaunchElevated(); 158 bool launch_elevated = delegate->ShouldLaunchElevated();
118 #elif defined(OS_MACOSX) 159 #elif defined(OS_MACOSX)
119 base::EnvironmentMap env = delegate->GetEnvironment(); 160 base::EnvironmentMap env = delegate->GetEnvironment();
(...skipping 13 matching lines...) Expand all
133 process = base::LaunchElevatedProcess(*cmd_line, options); 174 process = base::LaunchElevatedProcess(*cmd_line, options);
134 } else { 175 } else {
135 process = StartSandboxedProcess(delegate, cmd_line); 176 process = StartSandboxedProcess(delegate, cmd_line);
136 } 177 }
137 #elif defined(OS_POSIX) 178 #elif defined(OS_POSIX)
138 std::string process_type = 179 std::string process_type =
139 cmd_line->GetSwitchValueASCII(switches::kProcessType); 180 cmd_line->GetSwitchValueASCII(switches::kProcessType);
140 scoped_ptr<FileDescriptorInfo> files_to_register( 181 scoped_ptr<FileDescriptorInfo> files_to_register(
141 FileDescriptorInfoImpl::Create()); 182 FileDescriptorInfoImpl::Create());
142 183
184 base::ScopedFD mojo_fd(client_handle.release().handle);
185 DCHECK(mojo_fd.is_valid());
186
143 #if defined(OS_ANDROID) 187 #if defined(OS_ANDROID)
144 files_to_register->Share(kPrimaryIPCChannel, ipcfd.get()); 188 files_to_register->Share(kPrimaryIPCChannel, ipcfd.get());
189 files_to_register->Share(kMojoIPCChannel, mojo_fd.get());
145 #else 190 #else
146 files_to_register->Transfer(kPrimaryIPCChannel, std::move(ipcfd)); 191 files_to_register->Transfer(kPrimaryIPCChannel, std::move(ipcfd));
192 files_to_register->Transfer(kMojoIPCChannel, std::move(mojo_fd));
147 #endif 193 #endif
148 #endif 194 #endif
149 195
150 #if defined(OS_POSIX) && !defined(OS_MACOSX) 196 #if defined(OS_POSIX) && !defined(OS_MACOSX)
151 std::map<int, base::MemoryMappedFile::Region> regions; 197 std::map<int, base::MemoryMappedFile::Region> regions;
152 GetContentClient()->browser()->GetAdditionalMappedFilesForChildProcess( 198 GetContentClient()->browser()->GetAdditionalMappedFilesForChildProcess(
153 *cmd_line, child_process_id, files_to_register.get() 199 *cmd_line, child_process_id, files_to_register.get()
154 #if defined(OS_ANDROID) 200 #if defined(OS_ANDROID)
155 , &regions 201 , &regions
156 #endif 202 #endif
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
214 kAndroidICUDataDescriptor, 260 kAndroidICUDataDescriptor,
215 base::i18n::GetIcuDataFileHandle(&regions[kAndroidICUDataDescriptor])); 261 base::i18n::GetIcuDataFileHandle(&regions[kAndroidICUDataDescriptor]));
216 262
217 // Android WebView runs in single process, ensure that we never get here 263 // Android WebView runs in single process, ensure that we never get here
218 // when running in single process mode. 264 // when running in single process mode.
219 CHECK(!cmd_line->HasSwitch(switches::kSingleProcess)); 265 CHECK(!cmd_line->HasSwitch(switches::kSingleProcess));
220 266
221 StartChildProcess( 267 StartChildProcess(
222 cmd_line->argv(), child_process_id, std::move(files_to_register), regions, 268 cmd_line->argv(), child_process_id, std::move(files_to_register), regions,
223 base::Bind(&OnChildProcessStartedAndroid, callback, client_thread_id, 269 base::Bind(&OnChildProcessStartedAndroid, callback, client_thread_id,
224 begin_launch_time, base::Passed(&ipcfd))); 270 begin_launch_time, base::Passed(&ipcfd),
271 base::Passed(&mojo_fd)));
225 272
226 #elif defined(OS_POSIX) 273 #elif defined(OS_POSIX)
227 // We need to close the client end of the IPC channel to reliably detect 274 // We need to close the client end of the IPC channel to reliably detect
228 // child termination. 275 // child termination.
229 276
230 #if !defined(OS_MACOSX) 277 #if !defined(OS_MACOSX)
231 ZygoteHandle* zygote_handle = delegate->GetZygote(); 278 ZygoteHandle* zygote_handle = delegate->GetZygote();
232 // If |zygote_handle| is null, a zygote should not be used. 279 // If |zygote_handle| is null, a zygote should not be used.
233 if (zygote_handle) { 280 if (zygote_handle) {
234 // This code runs on the PROCESS_LAUNCHER thread so race conditions are not 281 // 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
414 !cmd_line->HasSwitch(switches::kNoSandbox)); 461 !cmd_line->HasSwitch(switches::kNoSandbox));
415 462
416 // We need to close the client end of the IPC channel to reliably detect 463 // We need to close the client end of the IPC channel to reliably detect
417 // child termination. We will close this fd after we create the child 464 // child termination. We will close this fd after we create the child
418 // process which is asynchronous on Android. 465 // process which is asynchronous on Android.
419 base::ScopedFD ipcfd(delegate->TakeIpcFd().release()); 466 base::ScopedFD ipcfd(delegate->TakeIpcFd().release());
420 #endif 467 #endif
421 NotifyCallback reply_callback(base::Bind(&ChildProcessLauncher::DidLaunch, 468 NotifyCallback reply_callback(base::Bind(&ChildProcessLauncher::DidLaunch,
422 weak_factory_.GetWeakPtr(), 469 weak_factory_.GetWeakPtr(),
423 terminate_child_on_shutdown_)); 470 terminate_child_on_shutdown_));
471 mojo::edk::ScopedPlatformHandle client_handle;
472 #if defined(OS_WIN)
473 mojo_server_handle_ = CreateMojoNamedPipe(cmd_line, &mojo_secret_);
474 #else
475 mojo::edk::PlatformChannelPair platform_channel;
476 client_handle = platform_channel.PassClientHandle();
477 mojo_server_handle_ = platform_channel.PassServerHandle();
478 #endif
424 BrowserThread::PostTask( 479 BrowserThread::PostTask(
425 BrowserThread::PROCESS_LAUNCHER, FROM_HERE, 480 BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
426 base::Bind(&LaunchOnLauncherThread, reply_callback, client_thread_id_, 481 base::Bind(&LaunchOnLauncherThread, reply_callback, client_thread_id_,
427 child_process_id, delegate, 482 child_process_id, delegate,
428 #if defined(OS_ANDROID) 483 #if defined(OS_ANDROID)
429 base::Passed(&ipcfd), 484 base::Passed(&ipcfd),
430 #endif 485 #endif
431 cmd_line)); 486 base::Passed(&client_handle), cmd_line));
432 } 487 }
433 488
434 void ChildProcessLauncher::UpdateTerminationStatus(bool known_dead) { 489 void ChildProcessLauncher::UpdateTerminationStatus(bool known_dead) {
435 DCHECK(CalledOnValidThread()); 490 DCHECK(CalledOnValidThread());
436 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 491 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
437 if (zygote_) { 492 if (zygote_) {
438 termination_status_ = zygote_->GetTerminationStatus( 493 termination_status_ = zygote_->GetTerminationStatus(
439 process_.Handle(), known_dead, &exit_code_); 494 process_.Handle(), known_dead, &exit_code_);
440 } else if (known_dead) { 495 } else if (known_dead) {
441 termination_status_ = 496 termination_status_ =
(...skipping 23 matching lines...) Expand all
465 base::Bind(&SetProcessBackgroundedOnLauncherThread, 520 base::Bind(&SetProcessBackgroundedOnLauncherThread,
466 base::Passed(&to_pass), background)); 521 base::Passed(&to_pass), background));
467 } 522 }
468 523
469 void ChildProcessLauncher::DidLaunch( 524 void ChildProcessLauncher::DidLaunch(
470 base::WeakPtr<ChildProcessLauncher> instance, 525 base::WeakPtr<ChildProcessLauncher> instance,
471 bool terminate_on_shutdown, 526 bool terminate_on_shutdown,
472 ZygoteHandle zygote, 527 ZygoteHandle zygote,
473 #if defined(OS_ANDROID) 528 #if defined(OS_ANDROID)
474 base::ScopedFD ipcfd, 529 base::ScopedFD ipcfd,
530 base::ScopedFD mojo_fd,
475 #endif 531 #endif
476 base::Process process) { 532 base::Process process) {
477 if (!process.IsValid()) 533 if (!process.IsValid())
478 LOG(ERROR) << "Failed to launch child process"; 534 LOG(ERROR) << "Failed to launch child process";
479 535
480 if (instance.get()) { 536 if (instance.get()) {
481 instance->Notify(zygote, 537 instance->Notify(zygote,
482 #if defined(OS_ANDROID) 538 #if defined(OS_ANDROID)
483 std::move(ipcfd), 539 std::move(ipcfd),
484 #endif 540 #endif
(...skipping 11 matching lines...) Expand all
496 552
497 void ChildProcessLauncher::Notify(ZygoteHandle zygote, 553 void ChildProcessLauncher::Notify(ZygoteHandle zygote,
498 #if defined(OS_ANDROID) 554 #if defined(OS_ANDROID)
499 base::ScopedFD ipcfd, 555 base::ScopedFD ipcfd,
500 #endif 556 #endif
501 base::Process process) { 557 base::Process process) {
502 DCHECK(CalledOnValidThread()); 558 DCHECK(CalledOnValidThread());
503 starting_ = false; 559 starting_ = false;
504 process_ = std::move(process); 560 process_ = std::move(process);
505 561
562 if (process_.IsValid()) {
563 // Set up Mojo IPC to the new process.
564 #if defined(OS_WIN)
565 mojo::edk::ChildProcessLaunched(process_.Handle(),
566 std::move(mojo_server_handle_),
567 mojo_secret_);
568 #else
569 mojo::edk::ChildProcessLaunched(process_.Handle(),
570 std::move(mojo_server_handle_));
571 #endif // defined(OS_WIN)
572 }
573
506 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 574 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
507 zygote_ = zygote; 575 zygote_ = zygote;
508 #endif 576 #endif
509 if (process_.IsValid()) { 577 if (process_.IsValid()) {
510 client_->OnProcessLaunched(); 578 client_->OnProcessLaunched();
511 } else { 579 } else {
512 termination_status_ = base::TERMINATION_STATUS_LAUNCH_FAILED; 580 termination_status_ = base::TERMINATION_STATUS_LAUNCH_FAILED;
513 client_->OnProcessLaunchFailed(); 581 client_->OnProcessLaunchFailed();
514 } 582 }
515 } 583 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
554 } 622 }
555 623
556 ChildProcessLauncher::Client* ChildProcessLauncher::ReplaceClientForTest( 624 ChildProcessLauncher::Client* ChildProcessLauncher::ReplaceClientForTest(
557 Client* client) { 625 Client* client) {
558 Client* ret = client_; 626 Client* ret = client_;
559 client_ = client; 627 client_ = client;
560 return ret; 628 return ret;
561 } 629 }
562 630
563 } // namespace content 631 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698