OLD | NEW |
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 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
64 terminate_child_on_shutdown_ = !CommandLine::ForCurrentProcess()-> | 64 terminate_child_on_shutdown_ = !CommandLine::ForCurrentProcess()-> |
65 HasSwitch(switches::kChildCleanExit); | 65 HasSwitch(switches::kChildCleanExit); |
66 #else | 66 #else |
67 terminate_child_on_shutdown_ = true; | 67 terminate_child_on_shutdown_ = true; |
68 #endif | 68 #endif |
69 } | 69 } |
70 | 70 |
71 void Launch( | 71 void Launch( |
72 #if defined(OS_WIN) | 72 #if defined(OS_WIN) |
73 SandboxedProcessLauncherDelegate* delegate, | 73 SandboxedProcessLauncherDelegate* delegate, |
| 74 bool launch_elevated, |
74 #elif defined(OS_ANDROID) | 75 #elif defined(OS_ANDROID) |
75 int ipcfd, | 76 int ipcfd, |
76 #elif defined(OS_POSIX) | 77 #elif defined(OS_POSIX) |
77 bool use_zygote, | 78 bool use_zygote, |
78 const base::EnvironmentMap& environ, | 79 const base::EnvironmentMap& environ, |
79 int ipcfd, | 80 int ipcfd, |
80 #endif | 81 #endif |
81 CommandLine* cmd_line, | 82 CommandLine* cmd_line, |
82 int child_process_id, | 83 int child_process_id, |
83 Client* client) { | 84 Client* client) { |
84 client_ = client; | 85 client_ = client; |
85 | 86 |
86 CHECK(BrowserThread::GetCurrentThreadIdentifier(&client_thread_id_)); | 87 CHECK(BrowserThread::GetCurrentThreadIdentifier(&client_thread_id_)); |
87 | 88 |
88 #if defined(OS_ANDROID) | 89 #if defined(OS_ANDROID) |
89 // We need to close the client end of the IPC channel to reliably detect | 90 // 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 | 91 // child termination. We will close this fd after we create the child |
91 // process which is asynchronous on Android. | 92 // process which is asynchronous on Android. |
92 ipcfd_ = ipcfd; | 93 ipcfd_ = ipcfd; |
93 #endif | 94 #endif |
94 BrowserThread::PostTask( | 95 BrowserThread::PostTask( |
95 BrowserThread::PROCESS_LAUNCHER, FROM_HERE, | 96 BrowserThread::PROCESS_LAUNCHER, FROM_HERE, |
96 base::Bind( | 97 base::Bind( |
97 &Context::LaunchInternal, | 98 &Context::LaunchInternal, |
98 make_scoped_refptr(this), | 99 make_scoped_refptr(this), |
99 client_thread_id_, | 100 client_thread_id_, |
100 child_process_id, | 101 child_process_id, |
101 #if defined(OS_WIN) | 102 #if defined(OS_WIN) |
102 delegate, | 103 delegate, |
| 104 launch_elevated, |
103 #elif defined(OS_ANDROID) | 105 #elif defined(OS_ANDROID) |
104 ipcfd, | 106 ipcfd, |
105 #elif defined(OS_POSIX) | 107 #elif defined(OS_POSIX) |
106 use_zygote, | 108 use_zygote, |
107 environ, | 109 environ, |
108 ipcfd, | 110 ipcfd, |
109 #endif | 111 #endif |
110 cmd_line)); | 112 cmd_line)); |
111 } | 113 } |
112 | 114 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 } | 178 } |
177 } | 179 } |
178 | 180 |
179 static void LaunchInternal( | 181 static void LaunchInternal( |
180 // |this_object| is NOT thread safe. Only use it to post a task back. | 182 // |this_object| is NOT thread safe. Only use it to post a task back. |
181 scoped_refptr<Context> this_object, | 183 scoped_refptr<Context> this_object, |
182 BrowserThread::ID client_thread_id, | 184 BrowserThread::ID client_thread_id, |
183 int child_process_id, | 185 int child_process_id, |
184 #if defined(OS_WIN) | 186 #if defined(OS_WIN) |
185 SandboxedProcessLauncherDelegate* delegate, | 187 SandboxedProcessLauncherDelegate* delegate, |
| 188 bool launch_elevated, |
186 #elif defined(OS_ANDROID) | 189 #elif defined(OS_ANDROID) |
187 int ipcfd, | 190 int ipcfd, |
188 #elif defined(OS_POSIX) | 191 #elif defined(OS_POSIX) |
189 bool use_zygote, | 192 bool use_zygote, |
190 const base::EnvironmentMap& env, | 193 const base::EnvironmentMap& env, |
191 int ipcfd, | 194 int ipcfd, |
192 #endif | 195 #endif |
193 CommandLine* cmd_line) { | 196 CommandLine* cmd_line) { |
194 scoped_ptr<CommandLine> cmd_line_deleter(cmd_line); | 197 scoped_ptr<CommandLine> cmd_line_deleter(cmd_line); |
195 base::TimeTicks begin_launch_time = base::TimeTicks::Now(); | 198 base::TimeTicks begin_launch_time = base::TimeTicks::Now(); |
196 | 199 |
197 #if defined(OS_WIN) | 200 #if defined(OS_WIN) |
198 scoped_ptr<SandboxedProcessLauncherDelegate> delegate_deleter(delegate); | 201 base::ProcessHandle handle = base::kNullProcessHandle; |
199 base::ProcessHandle handle = StartSandboxedProcess(delegate, cmd_line); | 202 if (launch_elevated) { |
| 203 base::LaunchOptions options; |
| 204 options.start_hidden = true; |
| 205 base::LaunchElevatedProcess(*cmd_line, options, &handle); |
| 206 } else { |
| 207 scoped_ptr<SandboxedProcessLauncherDelegate> delegate_deleter(delegate); |
| 208 handle = StartSandboxedProcess(delegate, cmd_line); |
| 209 } |
200 #elif defined(OS_ANDROID) | 210 #elif defined(OS_ANDROID) |
201 // Android WebView runs in single process, ensure that we never get here | 211 // Android WebView runs in single process, ensure that we never get here |
202 // when running in single process mode. | 212 // when running in single process mode. |
203 CHECK(!cmd_line->HasSwitch(switches::kSingleProcess)); | 213 CHECK(!cmd_line->HasSwitch(switches::kSingleProcess)); |
204 | 214 |
205 std::string process_type = | 215 std::string process_type = |
206 cmd_line->GetSwitchValueASCII(switches::kProcessType); | 216 cmd_line->GetSwitchValueASCII(switches::kProcessType); |
207 std::vector<FileDescriptorInfo> files_to_register; | 217 std::vector<FileDescriptorInfo> files_to_register; |
208 files_to_register.push_back( | 218 files_to_register.push_back( |
209 FileDescriptorInfo(kPrimaryIPCChannel, | 219 FileDescriptorInfo(kPrimaryIPCChannel, |
210 base::FileDescriptor(ipcfd, false))); | 220 base::FileDescriptor(ipcfd, false))); |
211 | 221 |
212 GetContentClient()->browser()-> | 222 GetContentClient()->browser()-> |
213 GetAdditionalMappedFilesForChildProcess(*cmd_line, child_process_id, | 223 GetAdditionalMappedFilesForChildProcess(*cmd_line, child_process_id, |
214 &files_to_register); | 224 &files_to_register); |
215 | 225 |
216 StartChildProcess(cmd_line->argv(), files_to_register, | 226 StartChildProcess(cmd_line->argv(), files_to_register, |
217 base::Bind(&ChildProcessLauncher::Context::OnChildProcessStarted, | 227 base::Bind(&ChildProcessLauncher::Context::OnChildProcessStarted, |
218 this_object, client_thread_id, begin_launch_time)); | 228 this_object, client_thread_id, begin_launch_time)); |
219 | 229 |
220 #elif defined(OS_POSIX) | 230 #elif defined(OS_POSIX) |
221 base::ProcessHandle handle = base::kNullProcessHandle; | 231 base::ProcessHandle handle = base::kNullProcessHandle; |
222 // We need to close the client end of the IPC channel to reliably detect | 232 // We need to close the client end of the IPC channel to reliably detect |
223 // child termination. | 233 // child termination. |
224 file_util::ScopedFD ipcfd_closer(&ipcfd); | 234 file_util::ScopedFD ipcfd_closer(&ipcfd); |
225 | 235 |
226 std::string process_type = | 236 std::string process_type = |
227 cmd_line->GetSwitchValueASCII(switches::kProcessType); | 237 cmd_line->GetSwitchValueASCII(switches::kProcessType); |
228 std::vector<FileDescriptorInfo> files_to_register; | 238 std::vector<FileDescriptorInfo> files_to_register; |
229 files_to_register.push_back( | 239 files_to_register.push_back( |
230 FileDescriptorInfo(kPrimaryIPCChannel, | 240 FileDescriptorInfo(kPrimaryIPCChannel, |
231 base::FileDescriptor(ipcfd, false))); | 241 base::FileDescriptor(ipcfd, false))); |
232 | 242 |
233 #if !defined(OS_MACOSX) | 243 #if !defined(OS_MACOSX) |
234 GetContentClient()->browser()-> | 244 GetContentClient()->browser()-> |
235 GetAdditionalMappedFilesForChildProcess(*cmd_line, child_process_id, | 245 GetAdditionalMappedFilesForChildProcess(*cmd_line, child_process_id, |
236 &files_to_register); | 246 &files_to_register); |
237 if (use_zygote) { | 247 if (use_zygote) { |
238 handle = ZygoteHostImpl::GetInstance()->ForkRequest(cmd_line->argv(), | 248 handle = ZygoteHostImpl::GetInstance()->ForkRequest(cmd_line->argv(), |
239 files_to_register, | 249 files_to_register, |
240 process_type); | 250 process_type); |
241 } else | 251 } else |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
323 #endif | 333 #endif |
324 starting_ = false; | 334 starting_ = false; |
325 process_.set_handle(handle); | 335 process_.set_handle(handle); |
326 if (!handle) | 336 if (!handle) |
327 LOG(ERROR) << "Failed to launch child process"; | 337 LOG(ERROR) << "Failed to launch child process"; |
328 | 338 |
329 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) | 339 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_ANDROID) |
330 zygote_ = zygote; | 340 zygote_ = zygote; |
331 #endif | 341 #endif |
332 if (client_) { | 342 if (client_) { |
333 client_->OnProcessLaunched(); | 343 if (handle) { |
| 344 client_->OnProcessLaunched(); |
| 345 } else { |
| 346 client_->OnProcessLaunchFailed(); |
| 347 } |
334 } else { | 348 } else { |
335 Terminate(); | 349 Terminate(); |
336 } | 350 } |
337 } | 351 } |
338 | 352 |
339 void Terminate() { | 353 void Terminate() { |
340 if (!process_.handle()) | 354 if (!process_.handle()) |
341 return; | 355 return; |
342 | 356 |
343 if (!terminate_child_on_shutdown_) | 357 if (!terminate_child_on_shutdown_) |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
406 int ipcfd_; | 420 int ipcfd_; |
407 #elif defined(OS_POSIX) && !defined(OS_MACOSX) | 421 #elif defined(OS_POSIX) && !defined(OS_MACOSX) |
408 bool zygote_; | 422 bool zygote_; |
409 #endif | 423 #endif |
410 }; | 424 }; |
411 | 425 |
412 | 426 |
413 ChildProcessLauncher::ChildProcessLauncher( | 427 ChildProcessLauncher::ChildProcessLauncher( |
414 #if defined(OS_WIN) | 428 #if defined(OS_WIN) |
415 SandboxedProcessLauncherDelegate* delegate, | 429 SandboxedProcessLauncherDelegate* delegate, |
| 430 bool launch_elevated, |
416 #elif defined(OS_POSIX) | 431 #elif defined(OS_POSIX) |
417 bool use_zygote, | 432 bool use_zygote, |
418 const base::EnvironmentMap& environ, | 433 const base::EnvironmentMap& environ, |
419 int ipcfd, | 434 int ipcfd, |
420 #endif | 435 #endif |
421 CommandLine* cmd_line, | 436 CommandLine* cmd_line, |
422 int child_process_id, | 437 int child_process_id, |
423 Client* client) { | 438 Client* client) { |
424 context_ = new Context(); | 439 context_ = new Context(); |
425 context_->Launch( | 440 context_->Launch( |
426 #if defined(OS_WIN) | 441 #if defined(OS_WIN) |
427 delegate, | 442 delegate, |
| 443 launch_elevated, |
428 #elif defined(OS_ANDROID) | 444 #elif defined(OS_ANDROID) |
429 ipcfd, | 445 ipcfd, |
430 #elif defined(OS_POSIX) | 446 #elif defined(OS_POSIX) |
431 use_zygote, | 447 use_zygote, |
432 environ, | 448 environ, |
433 ipcfd, | 449 ipcfd, |
434 #endif | 450 #endif |
435 cmd_line, | 451 cmd_line, |
436 child_process_id, | 452 child_process_id, |
437 client); | 453 client); |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
499 GetHandle(), background)); | 515 GetHandle(), background)); |
500 } | 516 } |
501 | 517 |
502 void ChildProcessLauncher::SetTerminateChildOnShutdown( | 518 void ChildProcessLauncher::SetTerminateChildOnShutdown( |
503 bool terminate_on_shutdown) { | 519 bool terminate_on_shutdown) { |
504 if (context_.get()) | 520 if (context_.get()) |
505 context_->set_terminate_child_on_shutdown(terminate_on_shutdown); | 521 context_->set_terminate_child_on_shutdown(terminate_on_shutdown); |
506 } | 522 } |
507 | 523 |
508 } // namespace content | 524 } // namespace content |
OLD | NEW |