1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
|
// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_BROWSER_SERVICE_HOST_UTILITY_PROCESS_HOST_H_
#define CONTENT_BROWSER_SERVICE_HOST_UTILITY_PROCESS_HOST_H_
#include <memory>
#include <optional>
#include <string>
#include <variant>
#include <vector>
#include "base/environment.h"
#include "base/process/launch.h"
#include "build/build_config.h"
#include "build/chromecast_buildflags.h"
#include "content/browser/child_process_launcher.h"
#include "content/common/child_process.mojom.h"
#include "content/common/content_export.h"
#include "content/public/browser/browser_child_process_host_delegate.h"
#include "content/public/common/zygote/zygote_buildflags.h"
#include "media/media_buildflags.h"
#include "mojo/public/cpp/bindings/generic_pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "sandbox/policy/mojom/sandbox.mojom.h"
#if BUILDFLAG(USE_ZYGOTE)
#include "content/public/common/zygote/zygote_handle.h"
#endif // BUILDFLAG(USE_ZYGOTE)
namespace base {
class Thread;
} // namespace base
#if BUILDFLAG(ENABLE_GPU_CHANNEL_MEDIA_CAPTURE)
namespace viz {
class GpuClient;
} // namespace viz
#endif // BUILDFLAG(ENABLE_GPU_CHANNEL_MEDIA_CAPTURE)
namespace content {
class BrowserChildProcessHostImpl;
class InProcessChildThreadParams;
typedef base::Thread* (*UtilityMainThreadFactoryFunction)(
const InProcessChildThreadParams&);
// This class acts as the browser-side host to a utility child process hosting a
// mojo service. This class lives solely on the UI thread. If you need to bind
// a Mojo interface, specify it via `WithBoundServiceInterfaceOnChildProcess` on
// the `Options` passed in.
class CONTENT_EXPORT UtilityProcessHost
: public BrowserChildProcessHostDelegate {
public:
static void RegisterUtilityMainThreadFactory(
UtilityMainThreadFactoryFunction create);
// Interface which may be passed to a UtilityProcessHost on construction. All
// methods are called from the IO thread.
class Client {
public:
virtual ~Client() {}
virtual void OnProcessLaunched(const base::Process& process) {}
virtual void OnProcessTerminatedNormally() {}
virtual void OnProcessCrashed() {}
};
struct CONTENT_EXPORT Options {
Options();
~Options();
Options(const Options&) = delete;
Options& operator=(const Options&) = delete;
Options(Options&&);
Options& operator=(Options&&);
// Makes the process run with a specific sandbox type, or unsandboxed if
// Sandbox::kNoSandbox is specified.
Options& WithSandboxType(sandbox::mojom::Sandbox sandbox_type);
// Sets the name of the process to appear in the task manager.
Options& WithName(const std::u16string& name);
// Sets the name used for metrics reporting. This should not be a localized
// name. This is recorded to metrics, so update UtilityProcessNameHash enum
// in enums.xml if new values are passed here.
Options& WithMetricsName(const std::string& metrics_name);
Options& WithChildFlags(int flags);
// Provides extra switches to append to the process's command line.
Options& WithExtraCommandLineSwitches(std::vector<std::string> switches);
#if BUILDFLAG(IS_WIN)
// Specifies libraries to preload before the sandbox is locked down. Paths
// should be absolute.
Options& WithPreloadLibraries(const std::vector<base::FilePath>& preloads);
#endif // BUILDFLAG(IS_WIN)
// Allows the child process to bind viz.mojom.Gpu.
Options& WithGpuClientAllowed();
#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
// Adds to ChildProcessLauncherFileData::files_to_preload, which maps |key|
// -> |file| in the new process's base::FileDescriptorStore.
Options& WithFileToPreload(
std::string key,
std::variant<base::FilePath, base::ScopedFD> file);
#endif
#if BUILDFLAG(IS_POSIX)
Options& WithEnvironment(const base::EnvironmentMap& env);
#endif
#if BUILDFLAG(USE_ZYGOTE)
Options& WithZygoteForTesting(ZygoteCommunication* handle);
#endif // BUILDFLAG(USE_ZYGOTE)
// Requests that the process bind a receiving pipe targeting the interface
// named by `receiver`. Calls to this method generally end up in
// `ChildThreadImpl::OnBindReceiver()` and the option is used for testing
// only.
Options& WithBoundReceiverOnChildProcessForTesting(
mojo::GenericPendingReceiver receiver);
// Requests that the utility process bind a receiving pipe targeting the
// service interface named by `receiver`.
Options& WithBoundServiceInterfaceOnChildProcess(
mojo::GenericPendingReceiver receiver);
// Passes the contents of this Options object to a newly returned Options
// value. This can be called when moving an in-line built Options object
// directly into a call to `Start`.
Options Pass();
private:
friend class UtilityProcessHost;
sandbox::mojom::Sandbox sandbox_type_;
// Map of environment variables to values.
base::EnvironmentMap env_;
// The non-localized name used for metrics reporting.
std::string metrics_name_;
// ChildProcessHost flags to use when starting the child process.
int child_flags_;
// Extra command line switches to append.
std::vector<std::string> extra_switches_;
#if BUILDFLAG(IS_WIN)
// Libraries to load before sandbox lockdown. Only used on Windows.
std::vector<base::FilePath> preload_libraries_;
#endif // BUILDFLAG(IS_WIN)
#if BUILDFLAG(USE_ZYGOTE)
std::optional<raw_ptr<ZygoteCommunication>> zygote_for_testing_;
#endif // BUILDFLAG(USE_ZYGOTE)
#if BUILDFLAG(ENABLE_GPU_CHANNEL_MEDIA_CAPTURE)
// Whether or not to bind viz::mojom::Gpu to the utility process.
bool allowed_gpu_;
#endif // BUILDFLAG(ENABLE_GPU_CHANNEL_MEDIA_CAPTURE)
// A mojo receiver to bind once the process starts.
std::optional<mojo::GenericPendingReceiver> receiver_to_bind_;
// A mojo service interface to bind once the process starts.
std::optional<mojo::GenericPendingReceiver> service_interface_to_bind_;
// Extra files and file descriptors to preload in the new process.
std::unique_ptr<ChildProcessLauncherFileData> file_data_;
// The process name used to identify the process in task manager.
std::u16string name_;
};
// Creates and starts a new UtilityProcessHost with the specified `Options`.
// Pass a `client` if delegate callbacks are needed.
static bool Start(Options options, std::unique_ptr<Client> client = nullptr);
UtilityProcessHost(const UtilityProcessHost&) = delete;
UtilityProcessHost& operator=(const UtilityProcessHost&) = delete;
private:
UtilityProcessHost(Options options, std::unique_ptr<Client> client);
~UtilityProcessHost() override;
// Returns a control interface for the running child process.
mojom::ChildProcess* GetChildProcess();
void MaybeBindMojoInterfaces();
// Starts the child process if needed, returns true on success.
bool StartProcess();
// BrowserChildProcessHostDelegate:
void OnProcessLaunched() override;
void OnProcessLaunchFailed(int error_code) override;
void OnProcessCrashed(int exit_code) override;
std::optional<std::string> GetServiceName() override;
void BindHostReceiver(mojo::GenericPendingReceiver receiver) override;
Options options_;
// Child process host implementation.
std::unique_ptr<BrowserChildProcessHostImpl> process_;
// Used in single-process mode instead of |process_|.
std::unique_ptr<base::Thread> in_process_thread_;
// Indicates whether the process has been successfully launched yet, or if
// launch failed.
enum class LaunchState {
kLaunchInProgress,
kLaunchComplete,
kLaunchFailed,
};
LaunchState launch_state_ = LaunchState::kLaunchInProgress;
#if BUILDFLAG(ENABLE_GPU_CHANNEL_MEDIA_CAPTURE)
std::unique_ptr<viz::GpuClient, base::OnTaskRunnerDeleter> gpu_client_;
#endif // BUILDFLAG(ENABLE_GPU_CHANNEL_MEDIA_CAPTURE)
std::unique_ptr<Client> client_;
};
} // namespace content
#endif // CONTENT_BROWSER_SERVICE_HOST_UTILITY_PROCESS_HOST_H_
|