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

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

Issue 98603007: Launches a privileged utility process. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Mostly test cleanup. Created 6 years, 11 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_impl.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/metrics/histogram.h" 14 #include "base/metrics/histogram.h"
15 #include "base/process/process.h" 15 #include "base/process/process.h"
(...skipping 24 matching lines...) Expand all
40 40
41 #if defined(OS_POSIX) 41 #if defined(OS_POSIX)
42 #include "base/posix/global_descriptors.h" 42 #include "base/posix/global_descriptors.h"
43 #endif 43 #endif
44 44
45 namespace content { 45 namespace content {
46 46
47 // Having the functionality of ChildProcessLauncher be in an internal 47 // Having the functionality of ChildProcessLauncher be in an internal
48 // ref counted object allows us to automatically terminate the process when the 48 // 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. 49 // parent class destructs, while still holding on to state that we need.
50 class ChildProcessLauncher::Context 50 class ChildProcessLauncherImpl::Context
51 : public base::RefCountedThreadSafe<ChildProcessLauncher::Context> { 51 : public base::RefCountedThreadSafe<ChildProcessLauncherImpl::Context> {
52 public: 52 public:
53 Context() 53 Context()
54 : client_(NULL), 54 : client_(NULL),
55 client_thread_id_(BrowserThread::UI), 55 client_thread_id_(BrowserThread::UI),
56 termination_status_(base::TERMINATION_STATUS_NORMAL_TERMINATION), 56 termination_status_(base::TERMINATION_STATUS_NORMAL_TERMINATION),
57 exit_code_(RESULT_CODE_NORMAL_EXIT), 57 exit_code_(RESULT_CODE_NORMAL_EXIT),
58 starting_(true) 58 starting_(true)
59 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 59 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
60 , zygote_(false) 60 , zygote_(false)
61 #endif 61 #endif
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 base::ProcessHandle handle) { 119 base::ProcessHandle handle) {
120 RecordHistograms(begin_launch_time); 120 RecordHistograms(begin_launch_time);
121 if (BrowserThread::CurrentlyOn(client_thread_id)) { 121 if (BrowserThread::CurrentlyOn(client_thread_id)) {
122 // This is always invoked on the UI thread which is commonly the 122 // This is always invoked on the UI thread which is commonly the
123 // |client_thread_id| so we can shortcut one PostTask. 123 // |client_thread_id| so we can shortcut one PostTask.
124 this_object->Notify(handle); 124 this_object->Notify(handle);
125 } else { 125 } else {
126 BrowserThread::PostTask( 126 BrowserThread::PostTask(
127 client_thread_id, FROM_HERE, 127 client_thread_id, FROM_HERE,
128 base::Bind( 128 base::Bind(
129 &ChildProcessLauncher::Context::Notify, 129 &ChildProcessLauncherImpl::Context::Notify,
130 this_object, 130 this_object,
131 handle)); 131 handle));
132 } 132 }
133 } 133 }
134 #endif 134 #endif
135 135
136 void ResetClient() { 136 void ResetClient() {
137 // No need for locking as this function gets called on the same thread that 137 // No need for locking as this function gets called on the same thread that
138 // client_ would be used. 138 // client_ would be used.
139 CHECK(BrowserThread::CurrentlyOn(client_thread_id_)); 139 CHECK(BrowserThread::CurrentlyOn(client_thread_id_));
140 client_ = NULL; 140 client_ = NULL;
141 } 141 }
142 142
143 void set_terminate_child_on_shutdown(bool terminate_on_shutdown) { 143 void set_terminate_child_on_shutdown(bool terminate_on_shutdown) {
144 terminate_child_on_shutdown_ = terminate_on_shutdown; 144 terminate_child_on_shutdown_ = terminate_on_shutdown;
145 } 145 }
146 146
147 private: 147 private:
148 friend class base::RefCountedThreadSafe<ChildProcessLauncher::Context>; 148 friend class base::RefCountedThreadSafe<ChildProcessLauncherImpl::Context>;
149 friend class ChildProcessLauncher; 149 friend class ChildProcessLauncherImpl;
150 150
151 ~Context() { 151 ~Context() {
152 Terminate(); 152 Terminate();
153 } 153 }
154 154
155 static void RecordHistograms(const base::TimeTicks begin_launch_time) { 155 static void RecordHistograms(const base::TimeTicks begin_launch_time) {
156 base::TimeDelta launch_time = base::TimeTicks::Now() - begin_launch_time; 156 base::TimeDelta launch_time = base::TimeTicks::Now() - begin_launch_time;
157 if (BrowserThread::CurrentlyOn(BrowserThread::PROCESS_LAUNCHER)) { 157 if (BrowserThread::CurrentlyOn(BrowserThread::PROCESS_LAUNCHER)) {
158 RecordLaunchHistograms(launch_time); 158 RecordLaunchHistograms(launch_time);
159 } else { 159 } else {
160 BrowserThread::PostTask( 160 BrowserThread::PostTask(
161 BrowserThread::PROCESS_LAUNCHER, FROM_HERE, 161 BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
162 base::Bind(&ChildProcessLauncher::Context::RecordLaunchHistograms, 162 base::Bind(&ChildProcessLauncherImpl::Context::RecordLaunchHistograms,
163 launch_time)); 163 launch_time));
164 } 164 }
165 } 165 }
166 166
167 static void RecordLaunchHistograms(const base::TimeDelta launch_time) { 167 static void RecordLaunchHistograms(const base::TimeDelta launch_time) {
168 // Log the launch time, separating out the first one (which will likely be 168 // Log the launch time, separating out the first one (which will likely be
169 // slower due to the rest of the browser initializing at the same time). 169 // slower due to the rest of the browser initializing at the same time).
170 static bool done_first_launch = false; 170 static bool done_first_launch = false;
171 if (done_first_launch) { 171 if (done_first_launch) {
172 UMA_HISTOGRAM_TIMES("MPArch.ChildProcessLaunchSubsequent", launch_time); 172 UMA_HISTOGRAM_TIMES("MPArch.ChildProcessLaunchSubsequent", launch_time);
(...skipping 14 matching lines...) Expand all
187 int ipcfd, 187 int ipcfd,
188 #elif defined(OS_POSIX) 188 #elif defined(OS_POSIX)
189 bool use_zygote, 189 bool use_zygote,
190 const base::EnvironmentMap& env, 190 const base::EnvironmentMap& env,
191 int ipcfd, 191 int ipcfd,
192 #endif 192 #endif
193 CommandLine* cmd_line) { 193 CommandLine* cmd_line) {
194 scoped_ptr<CommandLine> cmd_line_deleter(cmd_line); 194 scoped_ptr<CommandLine> cmd_line_deleter(cmd_line);
195 base::TimeTicks begin_launch_time = base::TimeTicks::Now(); 195 base::TimeTicks begin_launch_time = base::TimeTicks::Now();
196 196
197
mef 2014/01/10 18:22:55 nit: nl
Drew Haven 2014/01/16 02:52:05 Done.
197 #if defined(OS_WIN) 198 #if defined(OS_WIN)
198 scoped_ptr<SandboxedProcessLauncherDelegate> delegate_deleter(delegate); 199 scoped_ptr<SandboxedProcessLauncherDelegate> delegate_deleter(delegate);
199 base::ProcessHandle handle = StartSandboxedProcess(delegate, cmd_line); 200 base::ProcessHandle handle = StartSandboxedProcess(delegate, cmd_line);
200 #elif defined(OS_ANDROID) 201 #elif defined(OS_ANDROID)
201 // Android WebView runs in single process, ensure that we never get here 202 // Android WebView runs in single process, ensure that we never get here
202 // when running in single process mode. 203 // when running in single process mode.
203 CHECK(!cmd_line->HasSwitch(switches::kSingleProcess)); 204 CHECK(!cmd_line->HasSwitch(switches::kSingleProcess));
204 205
205 std::string process_type = 206 std::string process_type =
206 cmd_line->GetSwitchValueASCII(switches::kProcessType); 207 cmd_line->GetSwitchValueASCII(switches::kProcessType);
207 std::vector<FileDescriptorInfo> files_to_register; 208 std::vector<FileDescriptorInfo> files_to_register;
208 files_to_register.push_back( 209 files_to_register.push_back(
209 FileDescriptorInfo(kPrimaryIPCChannel, 210 FileDescriptorInfo(kPrimaryIPCChannel,
210 base::FileDescriptor(ipcfd, false))); 211 base::FileDescriptor(ipcfd, false)));
211 212
212 GetContentClient()->browser()-> 213 GetContentClient()->browser()->
213 GetAdditionalMappedFilesForChildProcess(*cmd_line, child_process_id, 214 GetAdditionalMappedFilesForChildProcess(*cmd_line, child_process_id,
214 &files_to_register); 215 &files_to_register);
215 216
216 StartChildProcess(cmd_line->argv(), files_to_register, 217 StartChildProcess(cmd_line->argv(), files_to_register,
217 base::Bind(&ChildProcessLauncher::Context::OnChildProcessStarted, 218 base::Bind(&ChildProcessLauncherImpl::Context::OnChildProcessStarted,
218 this_object, client_thread_id, begin_launch_time)); 219 this_object, client_thread_id, begin_launch_time));
219 220
220 #elif defined(OS_POSIX) 221 #elif defined(OS_POSIX)
221 base::ProcessHandle handle = base::kNullProcessHandle; 222 base::ProcessHandle handle = base::kNullProcessHandle;
222 // We need to close the client end of the IPC channel to reliably detect 223 // We need to close the client end of the IPC channel to reliably detect
223 // child termination. 224 // child termination.
224 file_util::ScopedFD ipcfd_closer(&ipcfd); 225 file_util::ScopedFD ipcfd_closer(&ipcfd);
225 226
226 std::string process_type = 227 std::string process_type =
227 cmd_line->GetSwitchValueASCII(switches::kProcessType); 228 cmd_line->GetSwitchValueASCII(switches::kProcessType);
(...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 bool terminate_child_on_shutdown_; 404 bool terminate_child_on_shutdown_;
404 #if defined(OS_ANDROID) 405 #if defined(OS_ANDROID)
405 // The fd to close after creating the process. 406 // The fd to close after creating the process.
406 int ipcfd_; 407 int ipcfd_;
407 #elif defined(OS_POSIX) && !defined(OS_MACOSX) 408 #elif defined(OS_POSIX) && !defined(OS_MACOSX)
408 bool zygote_; 409 bool zygote_;
409 #endif 410 #endif
410 }; 411 };
411 412
412 413
413 ChildProcessLauncher::ChildProcessLauncher( 414 ChildProcessLauncherImpl::ChildProcessLauncherImpl(
414 #if defined(OS_WIN) 415 #if defined(OS_WIN)
415 SandboxedProcessLauncherDelegate* delegate, 416 SandboxedProcessLauncherDelegate* delegate,
416 #elif defined(OS_POSIX) 417 #elif defined(OS_POSIX)
417 bool use_zygote, 418 bool use_zygote,
418 const base::EnvironmentMap& environ, 419 const base::EnvironmentMap& environ,
419 int ipcfd, 420 int ipcfd,
420 #endif 421 #endif
421 CommandLine* cmd_line, 422 CommandLine* cmd_line,
422 int child_process_id, 423 int child_process_id,
423 Client* client) { 424 Client* client) {
424 context_ = new Context(); 425 context_ = new Context();
425 context_->Launch( 426 context_->Launch(
426 #if defined(OS_WIN) 427 #if defined(OS_WIN)
427 delegate, 428 delegate,
428 #elif defined(OS_ANDROID) 429 #elif defined(OS_ANDROID)
429 ipcfd, 430 ipcfd,
430 #elif defined(OS_POSIX) 431 #elif defined(OS_POSIX)
431 use_zygote, 432 use_zygote,
432 environ, 433 environ,
433 ipcfd, 434 ipcfd,
434 #endif 435 #endif
435 cmd_line, 436 cmd_line,
436 child_process_id, 437 child_process_id,
437 client); 438 client);
438 } 439 }
439 440
440 ChildProcessLauncher::~ChildProcessLauncher() { 441 ChildProcessLauncherImpl::~ChildProcessLauncherImpl() {
441 context_->ResetClient(); 442 context_->ResetClient();
442 } 443 }
443 444
444 bool ChildProcessLauncher::IsStarting() { 445 bool ChildProcessLauncherImpl::IsStarting() {
445 return context_->starting_; 446 return context_->starting_;
446 } 447 }
447 448
448 base::ProcessHandle ChildProcessLauncher::GetHandle() { 449 base::ProcessHandle ChildProcessLauncherImpl::GetHandle() {
449 DCHECK(!context_->starting_); 450 DCHECK(!context_->starting_);
450 return context_->process_.handle(); 451 return context_->process_.handle();
451 } 452 }
452 453
453 base::TerminationStatus ChildProcessLauncher::GetChildTerminationStatus( 454 base::TerminationStatus ChildProcessLauncherImpl::GetChildTerminationStatus(
454 bool known_dead, 455 bool known_dead,
455 int* exit_code) { 456 int* exit_code) {
456 base::ProcessHandle handle = context_->process_.handle(); 457 base::ProcessHandle handle = context_->process_.handle();
457 if (handle == base::kNullProcessHandle) { 458 if (handle == base::kNullProcessHandle) {
458 // Process is already gone, so return the cached termination status. 459 // Process is already gone, so return the cached termination status.
459 if (exit_code) 460 if (exit_code)
460 *exit_code = context_->exit_code_; 461 *exit_code = context_->exit_code_;
461 return context_->termination_status_; 462 return context_->termination_status_;
462 } 463 }
463 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) 464 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID)
(...skipping 20 matching lines...) Expand all
484 // here. Since GetTerminationStatus called waitpid with WNOHANG, 485 // here. Since GetTerminationStatus called waitpid with WNOHANG,
485 // it'll reap the process. However, if GetTerminationStatus didn't 486 // it'll reap the process. However, if GetTerminationStatus didn't
486 // reap the child (because it was still running), we'll need to 487 // reap the child (because it was still running), we'll need to
487 // Terminate via ProcessWatcher. So we can't close the handle here. 488 // Terminate via ProcessWatcher. So we can't close the handle here.
488 if (context_->termination_status_ != base::TERMINATION_STATUS_STILL_RUNNING) 489 if (context_->termination_status_ != base::TERMINATION_STATUS_STILL_RUNNING)
489 context_->process_.Close(); 490 context_->process_.Close();
490 491
491 return context_->termination_status_; 492 return context_->termination_status_;
492 } 493 }
493 494
494 void ChildProcessLauncher::SetProcessBackgrounded(bool background) { 495 void ChildProcessLauncherImpl::SetProcessBackgrounded(bool background) {
495 BrowserThread::PostTask( 496 BrowserThread::PostTask(
496 BrowserThread::PROCESS_LAUNCHER, FROM_HERE, 497 BrowserThread::PROCESS_LAUNCHER, FROM_HERE,
497 base::Bind( 498 base::Bind(
498 &ChildProcessLauncher::Context::SetProcessBackgrounded, 499 &ChildProcessLauncherImpl::Context::SetProcessBackgrounded,
499 GetHandle(), background)); 500 GetHandle(), background));
500 } 501 }
501 502
502 void ChildProcessLauncher::SetTerminateChildOnShutdown( 503 void ChildProcessLauncherImpl::SetTerminateChildOnShutdown(
503 bool terminate_on_shutdown) { 504 bool terminate_on_shutdown) {
504 if (context_.get()) 505 if (context_.get())
505 context_->set_terminate_child_on_shutdown(terminate_on_shutdown); 506 context_->set_terminate_child_on_shutdown(terminate_on_shutdown);
506 } 507 }
507 508
508 } // namespace content 509 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698