| Index: content/browser/child_process_launcher_helper_linux.cc
|
| diff --git a/content/browser/child_process_launcher_helper_linux.cc b/content/browser/child_process_launcher_helper_linux.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..f0a9a73f8b54607e2c319f75078c81c7dec7bd01
|
| --- /dev/null
|
| +++ b/content/browser/child_process_launcher_helper_linux.cc
|
| @@ -0,0 +1,176 @@
|
| +// Copyright 2017 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "base/posix/global_descriptors.h"
|
| +#include "content/browser/child_process_launcher.h"
|
| +#include "content/browser/child_process_launcher_helper.h"
|
| +#include "content/browser/child_process_launcher_helper_posix.h"
|
| +#include "content/browser/renderer_host/render_sandbox_host_linux.h"
|
| +#include "content/browser/zygote_host/zygote_communication_linux.h"
|
| +#include "content/browser/zygote_host/zygote_host_impl_linux.h"
|
| +#include "content/common/child_process_sandbox_support_impl_linux.h"
|
| +#include "content/public/browser/content_browser_client.h"
|
| +#include "content/public/browser/zygote_handle_linux.h"
|
| +#include "content/public/common/content_client.h"
|
| +#include "content/public/common/content_switches.h"
|
| +#include "content/public/common/result_codes.h"
|
| +#include "content/public/common/sandboxed_process_launcher_delegate.h"
|
| +#include "gin/v8_initializer.h"
|
| +
|
| +namespace content {
|
| +namespace internal {
|
| +
|
| +mojo::edk::ScopedPlatformHandle
|
| +ChildProcessLauncherHelper::PrepareMojoPipeHandlesOnClientThread() {
|
| + DCHECK_CURRENTLY_ON(client_thread_id_);
|
| + return mojo::edk::ScopedPlatformHandle();
|
| +}
|
| +
|
| +void ChildProcessLauncherHelper::BeforeLaunchOnClientThread() {
|
| + DCHECK_CURRENTLY_ON(client_thread_id_);
|
| +}
|
| +
|
| +std::unique_ptr<FileMappedForLaunch>
|
| +ChildProcessLauncherHelper::GetFilesToMap() {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
|
| +
|
| + std::unique_ptr<FileDescriptorInfo> files_to_register =
|
| + CreateDefaultPosixFilesToMap(*command_line(), child_process_id(),
|
| + mojo_client_handle());
|
| +
|
| +#if defined(V8_USE_EXTERNAL_STARTUP_DATA)
|
| + bool snapshot_loaded = false;
|
| + base::MemoryMappedFile::Region unused_region;
|
| + base::PlatformFile natives_pf =
|
| + gin::V8Initializer::GetOpenNativesFileForChildProcesses(&unused_region);
|
| + DCHECK_GE(natives_pf, 0);
|
| + files_to_register->Share(kV8NativesDataDescriptor, natives_pf);
|
| +
|
| + base::MemoryMappedFile::Region snapshot_region;
|
| + base::PlatformFile snapshot_pf =
|
| + gin::V8Initializer::GetOpenSnapshotFileForChildProcesses(
|
| + &snapshot_region);
|
| + // Failure to load the V8 snapshot is not necessarily an error. V8 can start
|
| + // up (slower) without the snapshot.
|
| + if (snapshot_pf != -1) {
|
| + snapshot_loaded = true;
|
| + files_to_register->Share(kV8SnapshotDataDescriptor, snapshot_pf);
|
| + }
|
| + if (GetProcessType() != switches::kZygoteProcess) {
|
| + command_line()->AppendSwitch(::switches::kV8NativesPassedByFD);
|
| + if (snapshot_loaded) {
|
| + command_line()->AppendSwitch(::switches::kV8SnapshotPassedByFD);
|
| + }
|
| + }
|
| +#endif // defined(V8_USE_EXTERNAL_STARTUP_DATA)
|
| +
|
| + return files_to_register;
|
| +}
|
| +
|
| +void ChildProcessLauncherHelper::BeforeLaunchOnLauncherThread(
|
| + const FileDescriptorInfo& files_to_register,
|
| + base::LaunchOptions* options) {
|
| + // Convert FD mapping to FileHandleMappingVector
|
| + std::unique_ptr<base::FileHandleMappingVector> fds_to_map =
|
| + files_to_register.GetMappingWithIDAdjustment(
|
| + base::GlobalDescriptors::kBaseDescriptor);
|
| +
|
| + if (GetProcessType() == switches::kRendererProcess) {
|
| + const int sandbox_fd =
|
| + RenderSandboxHostLinux::GetInstance()->GetRendererSocket();
|
| + fds_to_map->push_back(std::make_pair(sandbox_fd, GetSandboxFD()));
|
| + }
|
| +
|
| + options->environ = delegate_->GetEnvironment();
|
| + // fds_to_remap will de deleted in AfterLaunchOnLauncherThread() below.
|
| + options->fds_to_remap = fds_to_map.release();
|
| +}
|
| +
|
| +ChildProcessLauncherHelper::Process
|
| +ChildProcessLauncherHelper::LaunchProcessOnLauncherThread(
|
| + const base::LaunchOptions& options,
|
| + std::unique_ptr<FileMappedForLaunch> files_to_register,
|
| + bool* is_synchronous_launch,
|
| + int* launch_result) {
|
| + *is_synchronous_launch = true;
|
| +
|
| + ZygoteHandle* zygote_handle =
|
| + base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoZygote) ?
|
| + nullptr : delegate_->GetZygote();
|
| + if (zygote_handle) {
|
| + // This code runs on the PROCESS_LAUNCHER thread so race conditions are not
|
| + // an issue with the lazy initialization.
|
| + if (*zygote_handle == nullptr) {
|
| + *zygote_handle = CreateZygote();
|
| + }
|
| + base::ProcessHandle handle = (*zygote_handle)->ForkRequest(
|
| + command_line()->argv(),
|
| + std::move(files_to_register),
|
| + GetProcessType());
|
| + *launch_result = LAUNCH_RESULT_SUCCESS;
|
| + Process process;
|
| + process.process = base::Process(handle);
|
| + process.zygote = *zygote_handle;
|
| + return process;
|
| + }
|
| +
|
| + Process process;
|
| + process.process = base::LaunchProcess(*command_line(), options);
|
| + *launch_result = process.process.IsValid() ? LAUNCH_RESULT_SUCCESS
|
| + : LAUNCH_RESULT_FAILURE;
|
| + return process;
|
| +}
|
| +
|
| +void ChildProcessLauncherHelper::AfterLaunchOnLauncherThread(
|
| + const ChildProcessLauncherHelper::Process& process,
|
| + const base::LaunchOptions& options) {
|
| + delete options.fds_to_remap;
|
| +}
|
| +
|
| +// static
|
| +base::TerminationStatus ChildProcessLauncherHelper::GetTerminationStatus(
|
| + const ChildProcessLauncherHelper::Process& process,
|
| + bool known_dead,
|
| + int* exit_code) {
|
| + if (process.zygote) {
|
| + return process.zygote->GetTerminationStatus(
|
| + process.process.Handle(), known_dead, exit_code);
|
| + }
|
| + if (known_dead) {
|
| + return base::GetKnownDeadTerminationStatus(
|
| + process.process.Handle(), exit_code);
|
| + }
|
| + return base::GetTerminationStatus(process.process.Handle(), exit_code);
|
| +}
|
| +
|
| +// static
|
| +bool ChildProcessLauncherHelper::TerminateProcess(
|
| + const base::Process& process, int exit_code, bool wait) {
|
| + return process.Terminate(exit_code, wait);
|
| +}
|
| +
|
| +// static
|
| +void ChildProcessLauncherHelper::ForceNormalProcessTerminationSync(
|
| + ChildProcessLauncherHelper::Process process) {
|
| + process.process.Terminate(RESULT_CODE_NORMAL_EXIT, false);
|
| + // On POSIX, we must additionally reap the child.
|
| + if (process.zygote) {
|
| + // If the renderer was created via a zygote, we have to proxy the reaping
|
| + // through the zygote process.
|
| + process.zygote->EnsureProcessTerminated(process.process.Handle());
|
| + } else {
|
| + base::EnsureProcessTerminated(std::move(process.process));
|
| + }
|
| +}
|
| +
|
| +// static
|
| +void ChildProcessLauncherHelper::SetProcessBackgroundedOnLauncherThread(
|
| + base::Process process, bool background) {
|
| + DCHECK_CURRENTLY_ON(BrowserThread::PROCESS_LAUNCHER);
|
| + if (process.CanBackgroundProcesses())
|
| + process.SetProcessBackgrounded(background);
|
| +}
|
| +
|
| +} // namespace internal
|
| +} // namespace content
|
|
|