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
3 // found in the LICENSE file.
4
5 #include "content/app/content_main_runner_impl.h"
6
7 #include <stddef.h>
8 #include <stdlib.h>
9 #include <string.h>
10
11 #include <memory>
12 #include <string>
13 #include <utility>
14 #include <vector>
15
16 #include "base/allocator/allocator_check.h"
17 #include "base/allocator/allocator_extension.h"
18 #include "base/allocator/buildflags.h"
19 #include "base/at_exit.h"
20 #include "base/base_switches.h"
21 #include "base/bind.h"
22 #include "base/command_line.h"
23 #include "base/debug/debugger.h"
24 #include "base/debug/leak_annotations.h"
25 #include "base/debug/stack_trace.h"
26 #include "base/feature_list.h"
27 #include "base/files/file_path.h"
28 #include "base/i18n/icu_util.h"
29 #include "base/lazy_instance.h"
30 #include "base/logging.h"
31 #include "base/macros.h"
32 #include "base/metrics/field_trial.h"
33 #include "base/metrics/histogram_base.h"
34 #include "base/path_service.h"
35 #include "base/power_monitor/power_monitor.h"
36 #include "base/power_monitor/power_monitor_device_source.h"
37 #include "base/process/launch.h"
38 #include "base/process/memory.h"
39 #include "base/process/process.h"
40 #include "base/process/process_handle.h"
41 #include "base/single_thread_task_runner.h"
42 #include "base/strings/string_number_conversions.h"
43 #include "base/strings/string_util.h"
44 #include "base/strings/stringprintf.h"
45 #include "base/task/post_task.h"
46 #include "base/task/thread_pool/thread_pool_instance.h"
47 #include "base/trace_event/trace_event.h"
48 #include "components/discardable_memory/service/discardable_shared_memory_manager.h"
49 #include "components/download/public/common/download_task_runner.h"
50 #include "content/app/mojo/mojo_init.h"
51 #include "content/app/service_manager_environment.h"
52 #include "content/browser/browser_process_sub_thread.h"
53 #include "content/browser/browser_thread_impl.h"
54 #include "content/browser/scheduler/browser_task_executor.h"
55 #include "content/browser/startup_data_impl.h"
56 #include "content/browser/startup_helper.h"
57 #include "content/browser/tracing/memory_instrumentation_util.h"
58 #include "content/common/content_constants_internal.h"
59 #include "content/common/url_schemes.h"
60 #include "content/public/app/content_main_delegate.h"
61 #include "content/public/browser/system_connector.h"
62 #include "content/public/common/content_constants.h"
63 #include "content/public/common/content_descriptor_keys.h"
64 #include "content/public/common/content_features.h"
65 #include "content/public/common/content_paths.h"
66 #include "content/public/common/content_switches.h"
67 #include "content/public/common/main_function_params.h"
68 #include "content/public/common/network_service_util.h"
69 #include "content/public/common/sandbox_init.h"
70 #include "gin/v8_initializer.h"
71 #include "media/base/media.h"
72 #include "media/media_buildflags.h"
73 #include "ppapi/buildflags/buildflags.h"
74 #include "services/network/public/cpp/features.h"
75 #include "services/service_manager/embedder/switches.h"
76 #include "services/service_manager/sandbox/sandbox_type.h"
77 #include "services/service_manager/sandbox/switches.h"
78 #include "services/service_manager/zygote/common/zygote_buildflags.h"
79 #include "services/tracing/public/cpp/trace_startup.h"
80 #include "third_party/blink/public/common/origin_trials/trial_token_validator.h"
81 #include "ui/base/ui_base_paths.h"
82 #include "ui/base/ui_base_switches.h"
83 #include "ui/display/display_switches.h"
84 #include "ui/gfx/switches.h"
85
86 #if defined(OS_WIN)
87 #include <malloc.h>
88 #include <cstring>
89
90 #include "base/trace_event/trace_event_etw_export_win.h"
91 #include "ui/base/l10n/l10n_util_win.h"
92 #include "ui/display/win/dpi.h"
93 #elif defined(OS_MACOSX)
94 #include "sandbox/mac/seatbelt.h"
95 #include "sandbox/mac/seatbelt_exec.h"
96 #endif // OS_WIN
97
98 #if defined(OS_POSIX) || defined(OS_FUCHSIA)
99 #include <signal.h>
100
101 #include "base/file_descriptor_store.h"
102 #include "base/posix/global_descriptors.h"
103 #include "content/public/common/content_descriptors.h"
104
105 #if !defined(OS_MACOSX) && !defined(OS_BSD)
106 #include "services/service_manager/zygote/common/zygote_fork_delegate_linux.h"
107 #endif
108 #if !defined(OS_MACOSX) && !defined(OS_ANDROID) && !defined(OS_BSD)
109 #include "sandbox/linux/services/libc_interceptor.h"
110 #include "services/service_manager/zygote/zygote_main.h"
111 #endif
112
113 #endif // OS_POSIX || OS_FUCHSIA
114
115 #if defined(OS_LINUX) || defined(OS_BSD)
116 #include "base/native_library.h"
117 #include "base/rand_util.h"
118 #include "services/service_manager/zygote/common/common_sandbox_support_linux.h"
119 #include "third_party/blink/public/platform/web_font_render_style.h"
120 #include "third_party/boringssl/src/include/openssl/crypto.h"
121 #include "third_party/boringssl/src/include/openssl/rand.h"
122 #include "third_party/skia/include/core/SkFontMgr.h"
123 #include "third_party/skia/include/ports/SkFontMgr_android.h"
124
125 #if BUILDFLAG(ENABLE_PLUGINS)
126 #include "content/common/pepper_plugin_list.h"
127 #include "content/public/common/pepper_plugin_info.h"
128 #endif
129
130 #if BUILDFLAG(ENABLE_LIBRARY_CDMS)
131 #include "content/public/common/cdm_info.h"
132 #include "content/public/common/content_client.h"
133 #endif
134
135 #if BUILDFLAG(ENABLE_WEBRTC)
136 #include "third_party/webrtc_overrides/init_webrtc.h" // nogncheck
137 #endif
138 #endif // OS_LINUX || defined(OS_BSD)
139
140 #if !defined(CHROME_MULTIPLE_DLL_BROWSER)
141 #include "content/child/field_trial.h"
142 #include "content/public/gpu/content_gpu_client.h"
143 #include "content/public/renderer/content_renderer_client.h"
144 #include "content/public/utility/content_utility_client.h"
145 #endif
146
147 #if !defined(CHROME_MULTIPLE_DLL_CHILD)
148 #include "content/browser/browser_main.h"
149 #include "content/public/browser/content_browser_client.h"
150 #endif
151
152 #if !defined(CHROME_MULTIPLE_DLL_BROWSER) && !defined(CHROME_MULTIPLE_DLL_CHILD)
153 #include "content/browser/gpu/gpu_main_thread_factory.h"
154 #include "content/browser/renderer_host/render_process_host_impl.h"
155 #include "content/browser/utility_process_host.h"
156 #include "content/gpu/in_process_gpu_thread.h"
157 #include "content/renderer/in_process_renderer_thread.h"
158 #include "content/utility/in_process_utility_thread.h"
159 #endif
160
161 #if BUILDFLAG(USE_ZYGOTE_HANDLE)
162 #include "content/browser/sandbox_host_linux.h"
163 #include "media/base/media_switches.h"
164 #include "services/service_manager/zygote/common/common_sandbox_support_linux.h"
165 #include "services/service_manager/zygote/common/zygote_handle.h"
166 #include "services/service_manager/zygote/host/zygote_communication_linux.h"
167 #include "services/service_manager/zygote/host/zygote_host_impl_linux.h"
168 #endif
169
170 #if defined(OS_ANDROID)
171 #include "content/browser/android/browser_startup_controller.h"
172 #endif
173
174 namespace content {
175 extern int GpuMain(const content::MainFunctionParams&);
176 #if BUILDFLAG(ENABLE_PLUGINS)
177 extern int PpapiPluginMain(const MainFunctionParams&);
178 extern int PpapiBrokerMain(const MainFunctionParams&);
179 #endif
180 extern int RendererMain(const content::MainFunctionParams&);
181 extern int UtilityMain(const MainFunctionParams&);
182 } // namespace content
183
184 namespace content {
185
186 namespace {
187
188 #if defined(V8_USE_EXTERNAL_STARTUP_DATA) && defined(OS_ANDROID)
189 #if defined __LP64__
190 #define kV8SnapshotDataDescriptor kV8Snapshot64DataDescriptor
191 #else
192 #define kV8SnapshotDataDescriptor kV8Snapshot32DataDescriptor
193 #endif
194 #endif
195
196 #if defined(V8_USE_EXTERNAL_STARTUP_DATA)
LoadV8SnapshotFile()197 void LoadV8SnapshotFile() {
198 #if defined(USE_V8_CONTEXT_SNAPSHOT)
199 static constexpr gin::V8Initializer::V8SnapshotFileType kSnapshotType =
200 gin::V8Initializer::V8SnapshotFileType::kWithAdditionalContext;
201 static const char* snapshot_data_descriptor =
202 kV8ContextSnapshotDataDescriptor;
203 #else
204 static constexpr gin::V8Initializer::V8SnapshotFileType kSnapshotType =
205 gin::V8Initializer::V8SnapshotFileType::kDefault;
206 static const char* snapshot_data_descriptor = kV8SnapshotDataDescriptor;
207 #endif // USE_V8_CONTEXT_SNAPSHOT
208 ALLOW_UNUSED_LOCAL(kSnapshotType);
209 ALLOW_UNUSED_LOCAL(snapshot_data_descriptor);
210
211 #if defined(OS_POSIX) && !defined(OS_MACOSX)
212 base::FileDescriptorStore& file_descriptor_store =
213 base::FileDescriptorStore::GetInstance();
214 base::MemoryMappedFile::Region region;
215 base::ScopedFD fd =
216 file_descriptor_store.MaybeTakeFD(snapshot_data_descriptor, ®ion);
217 if (fd.is_valid()) {
218 base::File file(std::move(fd));
219 gin::V8Initializer::LoadV8SnapshotFromFile(std::move(file), ®ion,
220 kSnapshotType);
221 return;
222 }
223 #endif // OS_POSIX && !OS_MACOSX
224
225 #if !defined(CHROME_MULTIPLE_DLL_BROWSER)
226 gin::V8Initializer::LoadV8Snapshot(kSnapshotType);
227 #endif // !CHROME_MULTIPLE_DLL_BROWSER
228 }
229 #endif // V8_USE_EXTERNAL_STARTUP_DATA
230
InitializeV8IfNeeded(const base::CommandLine & command_line,const std::string & process_type)231 void InitializeV8IfNeeded(const base::CommandLine& command_line,
232 const std::string& process_type) {
233 if (process_type == switches::kGpuProcess)
234 return;
235
236 #if defined(V8_USE_EXTERNAL_STARTUP_DATA)
237 LoadV8SnapshotFile();
238 #endif // V8_USE_EXTERNAL_STARTUP_DATA
239 }
240
241 #if BUILDFLAG(USE_ZYGOTE_HANDLE)
LaunchZygoteHelper(base::CommandLine * cmd_line,base::ScopedFD * control_fd)242 pid_t LaunchZygoteHelper(base::CommandLine* cmd_line,
243 base::ScopedFD* control_fd) {
244 // Append any switches from the browser process that need to be forwarded on
245 // to the zygote/renderers.
246 static const char* const kForwardSwitches[] = {
247 switches::kAndroidFontsPath, switches::kClearKeyCdmPathForTesting,
248 switches::kEnableLogging, // Support, e.g., --enable-logging=stderr.
249 // Need to tell the zygote that it is headless so that we don't try to use
250 // the wrong type of main delegate.
251 switches::kHeadless,
252 // Zygote process needs to know what resources to have loaded when it
253 // becomes a renderer process.
254 switches::kForceDeviceScaleFactor, switches::kLoggingLevel,
255 switches::kPpapiInProcess, switches::kRegisterPepperPlugins, switches::kV,
256 switches::kVModule,
257 };
258 cmd_line->CopySwitchesFrom(*base::CommandLine::ForCurrentProcess(),
259 kForwardSwitches, base::size(kForwardSwitches));
260
261 GetContentClient()->browser()->AppendExtraCommandLineSwitches(cmd_line, -1);
262
263 // Start up the sandbox host process and get the file descriptor for the
264 // sandboxed processes to talk to it.
265 base::FileHandleMappingVector additional_remapped_fds;
266 additional_remapped_fds.emplace_back(
267 SandboxHostLinux::GetInstance()->GetChildSocket(),
268 service_manager::GetSandboxFD());
269
270 return service_manager::ZygoteHostImpl::GetInstance()->LaunchZygote(
271 cmd_line, control_fd, std::move(additional_remapped_fds));
272 }
273
274 // Initializes the Zygote sandbox host. No thread should be created before this
275 // call, as InitializeZygoteSandboxForBrowserProcess() will end-up using fork().
InitializeZygoteSandboxForBrowserProcess(const base::CommandLine & parsed_command_line)276 void InitializeZygoteSandboxForBrowserProcess(
277 const base::CommandLine& parsed_command_line) {
278 TRACE_EVENT0("startup", "SetupSandbox");
279 // SandboxHostLinux needs to be initialized even if the sandbox and
280 // zygote are both disabled. It initializes the sandboxed process socket.
281 SandboxHostLinux::GetInstance()->Init();
282
283 if (parsed_command_line.HasSwitch(switches::kSingleProcess))
284 return;
285
286 if (parsed_command_line.HasSwitch(switches::kNoZygote)) {
287 if (!parsed_command_line.HasSwitch(service_manager::switches::kNoSandbox)) {
288 LOG(ERROR) << "--no-sandbox should be used together with --no--zygote";
289 exit(EXIT_FAILURE);
290 }
291 return;
292 }
293
294 // Tickle the zygote host so it forks now.
295 service_manager::ZygoteHostImpl::GetInstance()->Init(parsed_command_line);
296 service_manager::CreateUnsandboxedZygote(base::BindOnce(LaunchZygoteHelper));
297 service_manager::ZygoteHandle generic_zygote =
298 service_manager::CreateGenericZygote(base::BindOnce(LaunchZygoteHelper));
299
300 // TODO(kerrnel): Investigate doing this without the ZygoteHostImpl as a
301 // proxy. It is currently done this way due to concerns about race
302 // conditions.
303 service_manager::ZygoteHostImpl::GetInstance()->SetRendererSandboxStatus(
304 generic_zygote->GetSandboxStatus());
305 }
306 #endif // BUILDFLAG(USE_ZYGOTE_HANDLE)
307
308 #if defined(OS_LINUX) || defined(OS_BSD)
309
310 #if BUILDFLAG(ENABLE_PLUGINS)
311 // Loads the (native) libraries but does not initialize them (i.e., does not
312 // call PPP_InitializeModule). This is needed by the zygote on Linux to get
313 // access to the plugins before entering the sandbox.
PreloadPepperPlugins()314 void PreloadPepperPlugins() {
315 std::vector<PepperPluginInfo> plugins;
316 ComputePepperPluginList(&plugins);
317 for (const auto& plugin : plugins) {
318 if (!plugin.is_internal) {
319 base::NativeLibraryLoadError error;
320 base::NativeLibrary library =
321 base::LoadNativeLibrary(plugin.path, &error);
322 VLOG_IF(1, !library) << "Unable to load plugin " << plugin.path.value()
323 << " " << error.ToString();
324
325 ignore_result(library); // Prevent release-mode warning.
326 }
327 }
328 }
329 #endif
330
331 #if BUILDFLAG(ENABLE_LIBRARY_CDMS)
332 // Loads registered library CDMs but does not initialize them. This is needed by
333 // the zygote on Linux to get access to the CDMs before entering the sandbox.
PreloadLibraryCdms()334 void PreloadLibraryCdms() {
335 std::vector<CdmInfo> cdms;
336 GetContentClient()->AddContentDecryptionModules(&cdms, nullptr);
337 for (const auto& cdm : cdms) {
338 base::NativeLibraryLoadError error;
339 base::NativeLibrary library = base::LoadNativeLibrary(cdm.path, &error);
340 VLOG_IF(1, !library) << "Unable to load CDM " << cdm.path.value()
341 << " (error: " << error.ToString() << ")";
342 ignore_result(library); // Prevent release-mode warning.
343 }
344 }
345 #endif // BUILDFLAG(ENABLE_LIBRARY_CDMS)
346
347 #if BUILDFLAG(USE_ZYGOTE_HANDLE)
PreSandboxInit()348 void PreSandboxInit() {
349 #if defined(ARCH_CPU_ARM_FAMILY)
350 // On ARM, BoringSSL requires access to /proc/cpuinfo to determine processor
351 // features. Query this before entering the sandbox.
352 CRYPTO_library_init();
353 #endif
354
355 // Pass BoringSSL a copy of the /dev/urandom file descriptor so RAND_bytes
356 // will work inside the sandbox.
357 RAND_set_urandom_fd(base::GetUrandomFD());
358
359 #if BUILDFLAG(ENABLE_PLUGINS)
360 // Ensure access to the Pepper plugins before the sandbox is turned on.
361 PreloadPepperPlugins();
362 #endif
363 #if BUILDFLAG(ENABLE_LIBRARY_CDMS)
364 // Ensure access to the library CDMs before the sandbox is turned on.
365 PreloadLibraryCdms();
366 #endif
367 #if BUILDFLAG(ENABLE_WEBRTC)
368 InitializeWebRtcModule();
369 #endif
370
371 // Set the android SkFontMgr for blink. We need to ensure this is done
372 // before the sandbox is initialized to allow the font manager to access
373 // font configuration files on disk.
374 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
375 switches::kAndroidFontsPath)) {
376 std::string android_fonts_dir =
377 base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
378 switches::kAndroidFontsPath);
379
380 if (android_fonts_dir.size() > 0 && android_fonts_dir.back() != '/')
381 android_fonts_dir += '/';
382
383 SkFontMgr_Android_CustomFonts custom;
384 custom.fSystemFontUse =
385 SkFontMgr_Android_CustomFonts::SystemFontUse::kOnlyCustom;
386 custom.fBasePath = android_fonts_dir.c_str();
387
388 std::string font_config;
389 std::string fallback_font_config;
390 if (android_fonts_dir.find("kitkat") != std::string::npos) {
391 font_config = android_fonts_dir + "system_fonts.xml";
392 fallback_font_config = android_fonts_dir + "fallback_fonts.xml";
393 custom.fFallbackFontsXml = fallback_font_config.c_str();
394 } else {
395 font_config = android_fonts_dir + "fonts.xml";
396 custom.fFallbackFontsXml = nullptr;
397 }
398 custom.fFontsXml = font_config.c_str();
399 custom.fIsolated = true;
400
401 blink::WebFontRenderStyle::SetSkiaFontManager(
402 SkFontMgr_New_Android(&custom));
403 }
404 }
405 #endif // BUILDFLAG(USE_ZYGOTE_HANDLE)
406
407 #endif // OS_LINUX || defined(OS_BSD)
408
409 } // namespace
410
411 class ContentClientCreator {
412 public:
Create(ContentMainDelegate * delegate)413 static void Create(ContentMainDelegate* delegate) {
414 ContentClient* client = delegate->CreateContentClient();
415 DCHECK(client);
416 SetContentClient(client);
417 }
418 };
419
420 class ContentClientInitializer {
421 public:
Set(const std::string & process_type,ContentMainDelegate * delegate)422 static void Set(const std::string& process_type,
423 ContentMainDelegate* delegate) {
424 ContentClient* content_client = GetContentClient();
425 #if !defined(CHROME_MULTIPLE_DLL_CHILD)
426 if (process_type.empty())
427 content_client->browser_ = delegate->CreateContentBrowserClient();
428 #endif // !CHROME_MULTIPLE_DLL_CHILD
429
430 #if !defined(CHROME_MULTIPLE_DLL_BROWSER)
431 base::CommandLine* cmd = base::CommandLine::ForCurrentProcess();
432 if (process_type == switches::kGpuProcess ||
433 cmd->HasSwitch(switches::kSingleProcess) ||
434 (process_type.empty() && cmd->HasSwitch(switches::kInProcessGPU)))
435 content_client->gpu_ = delegate->CreateContentGpuClient();
436
437 if (process_type == switches::kRendererProcess ||
438 cmd->HasSwitch(switches::kSingleProcess))
439 content_client->renderer_ = delegate->CreateContentRendererClient();
440
441 if (process_type == switches::kUtilityProcess ||
442 cmd->HasSwitch(switches::kSingleProcess))
443 content_client->utility_ = delegate->CreateContentUtilityClient();
444 #endif // !CHROME_MULTIPLE_DLL_BROWSER
445 }
446 };
447
448 // We dispatch to a process-type-specific FooMain() based on a command-line
449 // flag. This struct is used to build a table of (flag, main function) pairs.
450 struct MainFunction {
451 const char* name;
452 int (*function)(const MainFunctionParams&);
453 };
454
455 #if BUILDFLAG(USE_ZYGOTE_HANDLE)
456 // On platforms that use the zygote, we have a special subset of
457 // subprocesses that are launched via the zygote. This function
458 // fills in some process-launching bits around ZygoteMain().
459 // Returns the exit code of the subprocess.
RunZygote(ContentMainDelegate * delegate)460 int RunZygote(ContentMainDelegate* delegate) {
461 static const MainFunction kMainFunctions[] = {
462 {switches::kGpuProcess, GpuMain},
463 {switches::kRendererProcess, RendererMain},
464 {switches::kUtilityProcess, UtilityMain},
465 #if BUILDFLAG(ENABLE_PLUGINS)
466 {switches::kPpapiPluginProcess, PpapiPluginMain},
467 #endif
468 };
469
470 std::vector<std::unique_ptr<service_manager::ZygoteForkDelegate>>
471 zygote_fork_delegates;
472 delegate->ZygoteStarting(&zygote_fork_delegates);
473 media::InitializeMediaLibrary();
474
475 #if defined(OS_LINUX) || defined(OS_BSD)
476 PreSandboxInit();
477 #endif
478
479 // This function call can return multiple times, once per fork().
480 if (!service_manager::ZygoteMain(std::move(zygote_fork_delegates))) {
481 return 1;
482 }
483
484 delegate->ZygoteForked();
485
486 // Zygote::HandleForkRequest may have reallocated the command
487 // line so update it here with the new version.
488 const base::CommandLine& command_line =
489 *base::CommandLine::ForCurrentProcess();
490 std::string process_type =
491 command_line.GetSwitchValueASCII(switches::kProcessType);
492 ContentClientInitializer::Set(process_type, delegate);
493
494 MainFunctionParams main_params(command_line);
495 main_params.zygote_child = true;
496
497 InitializeFieldTrialAndFeatureList();
498 delegate->PostFieldTrialInitialization();
499
500 for (size_t i = 0; i < base::size(kMainFunctions); ++i) {
501 if (process_type == kMainFunctions[i].name)
502 return kMainFunctions[i].function(main_params);
503 }
504
505 return delegate->RunProcess(process_type, main_params);
506 }
507 #endif // BUILDFLAG(USE_ZYGOTE_HANDLE)
508
RegisterMainThreadFactories()509 static void RegisterMainThreadFactories() {
510 #if !defined(CHROME_MULTIPLE_DLL_BROWSER) && !defined(CHROME_MULTIPLE_DLL_CHILD)
511 UtilityProcessHost::RegisterUtilityMainThreadFactory(
512 CreateInProcessUtilityThread);
513 RenderProcessHostImpl::RegisterRendererMainThreadFactory(
514 CreateInProcessRendererThread);
515 content::RegisterGpuMainThreadFactory(CreateInProcessGpuThread);
516 #else
517 base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess();
518 if (command_line.HasSwitch(switches::kSingleProcess)) {
519 LOG(FATAL)
520 << "--single-process is not supported in chrome multiple dll browser.";
521 }
522 if (command_line.HasSwitch(switches::kInProcessGPU)) {
523 LOG(FATAL)
524 << "--in-process-gpu is not supported in chrome multiple dll browser.";
525 }
526 #endif // !CHROME_MULTIPLE_DLL_BROWSER && !CHROME_MULTIPLE_DLL_CHILD
527 }
528
529 #if !defined(CHROME_MULTIPLE_DLL_CHILD)
530 // Run the main function for browser process.
531 // Returns the exit code for this process.
RunBrowserProcessMain(const MainFunctionParams & main_function_params,ContentMainDelegate * delegate)532 int RunBrowserProcessMain(const MainFunctionParams& main_function_params,
533 ContentMainDelegate* delegate) {
534 int exit_code = delegate->RunProcess("", main_function_params);
535 if (exit_code >= 0)
536 return exit_code;
537 return BrowserMain(main_function_params);
538 }
539 #endif // !defined(CHROME_MULTIPLE_DLL_CHILD)
540
541 // Run the FooMain() for a given process type.
542 // Returns the exit code for this process.
RunOtherNamedProcessTypeMain(const std::string & process_type,const MainFunctionParams & main_function_params,ContentMainDelegate * delegate)543 int RunOtherNamedProcessTypeMain(const std::string& process_type,
544 const MainFunctionParams& main_function_params,
545 ContentMainDelegate* delegate) {
546 #if !defined(CHROME_MULTIPLE_DLL_BROWSER)
547 static const MainFunction kMainFunctions[] = {
548 #if BUILDFLAG(ENABLE_PLUGINS)
549 {switches::kPpapiPluginProcess, PpapiPluginMain},
550 {switches::kPpapiBrokerProcess, PpapiBrokerMain},
551 #endif // ENABLE_PLUGINS
552 {switches::kUtilityProcess, UtilityMain},
553 {switches::kRendererProcess, RendererMain},
554 {switches::kGpuProcess, GpuMain},
555 };
556
557 for (size_t i = 0; i < base::size(kMainFunctions); ++i) {
558 if (process_type == kMainFunctions[i].name) {
559 int exit_code = delegate->RunProcess(process_type, main_function_params);
560 if (exit_code >= 0)
561 return exit_code;
562 return kMainFunctions[i].function(main_function_params);
563 }
564 }
565 #endif // !CHROME_MULTIPLE_DLL_BROWSER
566
567 #if BUILDFLAG(USE_ZYGOTE_HANDLE)
568 // Zygote startup is special -- see RunZygote comments above
569 // for why we don't use ZygoteMain directly.
570 if (process_type == service_manager::switches::kZygoteProcess)
571 return RunZygote(delegate);
572 #endif // BUILDFLAG(USE_ZYGOTE_HANDLE)
573
574 // If it's a process we don't know about, the embedder should know.
575 return delegate->RunProcess(process_type, main_function_params);
576 }
577
578 // static
Create()579 ContentMainRunnerImpl* ContentMainRunnerImpl::Create() {
580 return new ContentMainRunnerImpl();
581 }
582
ContentMainRunnerImpl()583 ContentMainRunnerImpl::ContentMainRunnerImpl() {
584 #if defined(OS_WIN)
585 memset(&sandbox_info_, 0, sizeof(sandbox_info_));
586 #endif
587 }
588
~ContentMainRunnerImpl()589 ContentMainRunnerImpl::~ContentMainRunnerImpl() {
590 if (is_initialized_ && !is_shutdown_)
591 Shutdown();
592 }
593
TerminateForFatalInitializationError()594 int ContentMainRunnerImpl::TerminateForFatalInitializationError() {
595 return delegate_->TerminateForFatalInitializationError();
596 }
597
Initialize(const ContentMainParams & params)598 int ContentMainRunnerImpl::Initialize(const ContentMainParams& params) {
599 ui_task_ = params.ui_task;
600 created_main_parts_closure_ = params.created_main_parts_closure;
601
602 #if defined(OS_WIN)
603 sandbox_info_ = *params.sandbox_info;
604 #else // !OS_WIN
605
606 #if defined(OS_MACOSX)
607 autorelease_pool_ = params.autorelease_pool;
608 #endif // defined(OS_MACOSX)
609
610 #if defined(OS_ANDROID)
611 // Now that mojo's core is initialized (by service manager's Main()), we can
612 // enable tracing. Note that only Android builds have the ctor/dtor handlers
613 // set up to use trace events at this point (because AtExitManager is already
614 // set up when the library is loaded). Other platforms enable tracing below,
615 // after the initialization of AtExitManager.
616 tracing::EnableStartupTracingIfNeeded();
617
618 TRACE_EVENT0("startup,benchmark,rail", "ContentMainRunnerImpl::Initialize");
619 #endif // OS_ANDROID
620
621 base::GlobalDescriptors* g_fds = base::GlobalDescriptors::GetInstance();
622 ALLOW_UNUSED_LOCAL(g_fds);
623
624 // On Android, the ipc_fd is passed through the Java service.
625 #if !defined(OS_ANDROID)
626 g_fds->Set(service_manager::kMojoIPCChannel,
627 service_manager::kMojoIPCChannel +
628 base::GlobalDescriptors::kBaseDescriptor);
629
630 g_fds->Set(service_manager::kFieldTrialDescriptor,
631 service_manager::kFieldTrialDescriptor +
632 base::GlobalDescriptors::kBaseDescriptor);
633 #endif // !OS_ANDROID
634
635 #if defined(OS_LINUX)
636 g_fds->Set(service_manager::kCrashDumpSignal,
637 service_manager::kCrashDumpSignal +
638 base::GlobalDescriptors::kBaseDescriptor);
639 #endif // OS_LINUX
640
641 #endif // !OS_WIN
642
643 is_initialized_ = true;
644 delegate_ = params.delegate;
645
646 // The exit manager is in charge of calling the dtors of singleton objects.
647 // On Android, AtExitManager is set up when library is loaded.
648 // A consequence of this is that you can't use the ctor/dtor-based
649 // TRACE_EVENT methods on Linux or iOS builds till after we set this up.
650 #if !defined(OS_ANDROID)
651 if (!ui_task_) {
652 // When running browser tests, don't create a second AtExitManager as that
653 // interfers with shutdown when objects created before ContentMain is
654 // called are destructed when it returns.
655 exit_manager_.reset(new base::AtExitManager);
656 }
657 #endif // !OS_ANDROID
658
659 int exit_code = 0;
660 if (!GetContentClient())
661 ContentClientCreator::Create(delegate_);
662 if (delegate_->BasicStartupComplete(&exit_code))
663 return exit_code;
664 completed_basic_startup_ = true;
665
666 const base::CommandLine& command_line =
667 *base::CommandLine::ForCurrentProcess();
668 std::string process_type =
669 command_line.GetSwitchValueASCII(switches::kProcessType);
670
671 #if defined(OS_WIN)
672 if (command_line.HasSwitch(switches::kDeviceScaleFactor)) {
673 std::string scale_factor_string =
674 command_line.GetSwitchValueASCII(switches::kDeviceScaleFactor);
675 double scale_factor = 0;
676 if (base::StringToDouble(scale_factor_string, &scale_factor))
677 display::win::SetDefaultDeviceScaleFactor(scale_factor);
678 }
679 #endif
680
681 RegisterContentSchemes();
682 ContentClientInitializer::Set(process_type, delegate_);
683
684 #if !defined(OS_ANDROID)
685 // Enable startup tracing asap to avoid early TRACE_EVENT calls being
686 // ignored. For Android, startup tracing is enabled in an even earlier place
687 // above.
688 //
689 // Startup tracing flags are not (and should not be) passed to Zygote
690 // processes. We will enable tracing when forked, if needed.
691 bool enable_startup_tracing =
692 process_type != service_manager::switches::kZygoteProcess;
693 #if BUILDFLAG(USE_ZYGOTE_HANDLE)
694 // In the browser process, we have to enable startup tracing after
695 // InitializeZygoteSandboxForBrowserProcess() is run below, because that
696 // function forks and may call trace macros in the forked process.
697 if (process_type.empty())
698 enable_startup_tracing = false;
699 #endif // BUILDFLAG(USE_ZYGOTE_HANDLE)
700 if (enable_startup_tracing)
701 tracing::EnableStartupTracingIfNeeded();
702
703 #if defined(OS_WIN)
704 base::trace_event::TraceEventETWExport::EnableETWExport();
705 #endif // OS_WIN
706
707 // Android tracing started at the beginning of the method.
708 // Other OSes have to wait till we get here in order for all the memory
709 // management setup to be completed.
710 TRACE_EVENT0("startup,benchmark,rail", "ContentMainRunnerImpl::Initialize");
711 #endif // !OS_ANDROID
712
713 #if !defined(TOOLKIT_QT)
714 // If we are on a platform where the default allocator is overridden (shim
715 // layer on windows, tcmalloc on Linux Desktop) smoke-tests that the
716 // overriding logic is working correctly. If not causes a hard crash, as its
717 // unexpected absence has security implications.
718 CHECK(base::allocator::IsAllocatorInitialized());
719 #endif
720
721 #if defined(OS_POSIX) || defined(OS_FUCHSIA)
722 if (!process_type.empty()) {
723 // When you hit Ctrl-C in a terminal running the browser
724 // process, a SIGINT is delivered to the entire process group.
725 // When debugging the browser process via gdb, gdb catches the
726 // SIGINT for the browser process (and dumps you back to the gdb
727 // console) but doesn't for the child processes, killing them.
728 // The fix is to have child processes ignore SIGINT; they'll die
729 // on their own when the browser process goes away.
730 //
731 // Note that we *can't* rely on BeingDebugged to catch this case because
732 // we are the child process, which is not being debugged.
733 // TODO(evanm): move this to some shared subprocess-init function.
734 if (!base::debug::BeingDebugged())
735 signal(SIGINT, SIG_IGN);
736 }
737 #endif
738
739 RegisterPathProvider();
740
741 #if defined(OS_ANDROID) && (ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE)
742 // On Android, we have two ICU data files. A main one with most languages
743 // that is expected to always be available and an extra one that is
744 // installed separately via a dynamic feature module. If the extra ICU data
745 // file is available we have to apply it _before_ the main ICU data file.
746 // Otherwise, the languages of the extra ICU file will be overridden.
747 if (process_type.empty()) {
748 TRACE_EVENT0("startup", "InitializeICU");
749 // In browser process load ICU data files from disk.
750 if (GetContentClient()->browser()->ShouldLoadExtraIcuDataFile()) {
751 if (!base::i18n::InitializeExtraICU()) {
752 return TerminateForFatalInitializationError();
753 }
754 }
755 if (!base::i18n::InitializeICU()) {
756 return TerminateForFatalInitializationError();
757 }
758 } else {
759 // In child process map ICU data files loaded by browser process.
760 int icu_extra_data_fd = g_fds->MaybeGet(kAndroidICUExtraDataDescriptor);
761 if (icu_extra_data_fd != -1) {
762 auto icu_extra_data_region =
763 g_fds->GetRegion(kAndroidICUExtraDataDescriptor);
764 if (!base::i18n::InitializeExtraICUWithFileDescriptor(
765 icu_extra_data_fd, icu_extra_data_region)) {
766 return TerminateForFatalInitializationError();
767 }
768 }
769 int icu_data_fd = g_fds->MaybeGet(kAndroidICUDataDescriptor);
770 if (icu_data_fd == -1) {
771 return TerminateForFatalInitializationError();
772 }
773 auto icu_data_region = g_fds->GetRegion(kAndroidICUDataDescriptor);
774 if (!base::i18n::InitializeICUWithFileDescriptor(icu_data_fd,
775 icu_data_region)) {
776 return TerminateForFatalInitializationError();
777 }
778 }
779 #else
780 if (!base::i18n::InitializeICU())
781 return TerminateForFatalInitializationError();
782 #endif // OS_ANDROID && (ICU_UTIL_DATA_IMPL == ICU_UTIL_DATA_FILE)
783
784 InitializeV8IfNeeded(command_line, process_type);
785
786 blink::TrialTokenValidator::SetOriginTrialPolicyGetter(
787 base::BindRepeating([]() -> blink::OriginTrialPolicy* {
788 if (auto* client = GetContentClient())
789 return client->GetOriginTrialPolicy();
790 return nullptr;
791 }));
792
793 #if !defined(OFFICIAL_BUILD)
794 #if defined(OS_WIN)
795 bool should_enable_stack_dump = !process_type.empty();
796 #else
797 bool should_enable_stack_dump = true;
798 #endif
799 // Print stack traces to stderr when crashes occur. This opens up security
800 // holes so it should never be enabled for official builds. This needs to
801 // happen before crash reporting is initialized (which for chrome happens in
802 // the call to PreSandboxStartup() on the delegate below), because otherwise
803 // this would interfere with signal handlers used by crash reporting.
804 if (should_enable_stack_dump &&
805 !command_line.HasSwitch(
806 service_manager::switches::kDisableInProcessStackTraces)) {
807 base::debug::EnableInProcessStackDumping();
808 }
809
810 base::debug::VerifyDebugger();
811 #endif // !defined(OFFICIAL_BUILD)
812
813 delegate_->PreSandboxStartup();
814
815 #if defined(OS_WIN)
816 if (!InitializeSandbox(
817 service_manager::SandboxTypeFromCommandLine(command_line),
818 params.sandbox_info))
819 return TerminateForFatalInitializationError();
820 #elif defined(OS_MACOSX)
821 // Only the GPU process still runs the V1 sandbox.
822 bool v2_enabled = base::CommandLine::ForCurrentProcess()->HasSwitch(
823 sandbox::switches::kSeatbeltClientName);
824
825 if (!v2_enabled && process_type == switches::kGpuProcess) {
826 if (!InitializeSandbox()) {
827 return TerminateForFatalInitializationError();
828 }
829 } else if (v2_enabled) {
830 CHECK(sandbox::Seatbelt::IsSandboxed());
831 }
832 #endif
833
834 delegate_->SandboxInitialized(process_type);
835
836 #if BUILDFLAG(USE_ZYGOTE_HANDLE)
837 if (process_type.empty()) {
838 // The sandbox host needs to be initialized before forking a thread to
839 // start the ServiceManager, and after setting up the sandbox and invoking
840 // SandboxInitialized().
841 InitializeZygoteSandboxForBrowserProcess(
842 *base::CommandLine::ForCurrentProcess());
843
844 // We can only enable startup tracing after
845 // InitializeZygoteSandboxForBrowserProcess(), because the latter may fork
846 // and run code that calls trace event macros in the forked process (which
847 // could cause all sorts of issues, like writing to the same tracing SMB
848 // from two processes).
849 tracing::EnableStartupTracingIfNeeded();
850 }
851 #endif // BUILDFLAG(USE_ZYGOTE_HANDLE)
852
853 // Return -1 to indicate no early termination.
854 return -1;
855 }
856
Run(bool start_service_manager_only)857 int ContentMainRunnerImpl::Run(bool start_service_manager_only) {
858 DCHECK(is_initialized_);
859 DCHECK(!is_shutdown_);
860 const base::CommandLine& command_line =
861 *base::CommandLine::ForCurrentProcess();
862 std::string process_type =
863 command_line.GetSwitchValueASCII(switches::kProcessType);
864
865 #if !defined(CHROME_MULTIPLE_DLL_BROWSER)
866 // Run this logic on all child processes. Zygotes will run this at a later
867 // point in time when the command line has been updated.
868 if (!process_type.empty() &&
869 process_type != service_manager::switches::kZygoteProcess) {
870 InitializeFieldTrialAndFeatureList();
871 delegate_->PostFieldTrialInitialization();
872 }
873 #endif
874
875 MainFunctionParams main_params(command_line);
876 main_params.ui_task = ui_task_;
877 main_params.created_main_parts_closure = created_main_parts_closure_;
878 #if defined(OS_WIN)
879 main_params.sandbox_info = &sandbox_info_;
880 #elif defined(OS_MACOSX)
881 main_params.autorelease_pool = autorelease_pool_;
882 #endif
883
884 RegisterMainThreadFactories();
885
886 #if !defined(CHROME_MULTIPLE_DLL_CHILD)
887 if (process_type.empty())
888 return RunServiceManager(main_params, start_service_manager_only);
889 #endif // !defined(CHROME_MULTIPLE_DLL_CHILD)
890
891 return RunOtherNamedProcessTypeMain(process_type, main_params, delegate_);
892 }
893
894 #if !defined(CHROME_MULTIPLE_DLL_CHILD)
RunServiceManager(MainFunctionParams & main_params,bool start_service_manager_only)895 int ContentMainRunnerImpl::RunServiceManager(MainFunctionParams& main_params,
896 bool start_service_manager_only) {
897 TRACE_EVENT0("startup", "ContentMainRunnerImpl::RunServiceManager");
898 if (is_browser_main_loop_started_)
899 return -1;
900
901 bool should_start_service_manager_only = start_service_manager_only;
902 if (!service_manager_environment_) {
903 if (delegate_->ShouldCreateFeatureList()) {
904 // This is intentionally leaked since it needs to live for the duration
905 // of the process and there's no benefit in cleaning it up at exit.
906 base::FieldTrialList* leaked_field_trial_list =
907 SetUpFieldTrialsAndFeatureList().release();
908 ANNOTATE_LEAKING_OBJECT_PTR(leaked_field_trial_list);
909 ignore_result(leaked_field_trial_list);
910 delegate_->PostFieldTrialInitialization();
911 }
912
913 if (GetContentClient()->browser()->ShouldCreateThreadPool()) {
914 // Create and start the ThreadPool early to allow upcoming code to use
915 // the post_task.h API.
916 base::ThreadPoolInstance::Create("Browser");
917 }
918
919 delegate_->PreCreateMainMessageLoop();
920 #if defined(OS_WIN)
921 if (l10n_util::GetLocaleOverrides().empty()) {
922 // Override the configured locale with the user's preferred UI language.
923 // Don't do this if the locale is already set, which is done by
924 // integration tests to ensure tests always run with the same locale.
925 l10n_util::OverrideLocaleWithUILanguageList();
926 }
927 #endif
928
929 // Register the TaskExecutor for posting task to the BrowserThreads. It is
930 // incorrect to post to a BrowserThread before this point. This instantiates
931 // and binds the MessageLoopForUI on the main thread (but it's only labeled
932 // as BrowserThread::UI in BrowserMainLoop::MainMessageLoopStart).
933 BrowserTaskExecutor::Create();
934
935 delegate_->PostEarlyInitialization(main_params.ui_task != nullptr);
936
937 // The hang watcher needs to be started once the feature list is available
938 // but before the IO thread is started.
939 if (base::FeatureList::IsEnabled(base::HangWatcher::kEnableHangWatcher)) {
940 hang_watcher_ = new base::HangWatcher(
941 base::BindRepeating((&base::HangWatcher::RecordHang)));
942 ANNOTATE_LEAKING_OBJECT_PTR(hang_watcher_);
943 }
944
945 if (GetContentClient()->browser()->ShouldCreateThreadPool()) {
946 // The FeatureList needs to create before starting the ThreadPool.
947 StartBrowserThreadPool();
948 }
949
950 BrowserTaskExecutor::PostFeatureListSetup();
951
952 tracing::InitTracingPostThreadPoolStartAndFeatureList();
953
954 if (should_start_service_manager_only)
955 ForceInProcessNetworkService(true);
956
957 discardable_shared_memory_manager_ =
958 std::make_unique<discardable_memory::DiscardableSharedMemoryManager>();
959
960 // PowerMonitor is needed in reduced mode. BrowserMainLoop will safely skip
961 // initializing it again if it has already been initialized.
962 base::PowerMonitor::Initialize(
963 std::make_unique<base::PowerMonitorDeviceSource>());
964
965 service_manager_environment_ = std::make_unique<ServiceManagerEnvironment>(
966 BrowserTaskExecutor::CreateIOThread());
967 download::SetIOTaskRunner(
968 service_manager_environment_->ipc_thread()->task_runner());
969
970 InitializeBrowserMemoryInstrumentationClient();
971
972 #if defined(OS_ANDROID)
973 if (start_service_manager_only) {
974 base::ThreadTaskRunnerHandle::Get()->PostTask(
975 FROM_HERE, base::BindOnce(&ServiceManagerStartupComplete));
976 }
977 #endif
978 }
979
980 if (should_start_service_manager_only) {
981 DVLOG(0) << "Chrome is running in ServiceManager only mode.";
982 return -1;
983 }
984
985 DVLOG(0) << "Chrome is running in full browser mode.";
986 is_browser_main_loop_started_ = true;
987 startup_data_ = service_manager_environment_->CreateBrowserStartupData();
988 main_params.startup_data = startup_data_.get();
989 return RunBrowserProcessMain(main_params, delegate_);
990 }
991 #endif // !defined(CHROME_MULTIPLE_DLL_CHILD)
992
Shutdown()993 void ContentMainRunnerImpl::Shutdown() {
994 DCHECK(is_initialized_);
995 DCHECK(!is_shutdown_);
996
997 #if !defined(CHROME_MULTIPLE_DLL_CHILD)
998 service_manager_environment_.reset();
999 #endif
1000
1001 if (completed_basic_startup_) {
1002 const base::CommandLine& command_line =
1003 *base::CommandLine::ForCurrentProcess();
1004 std::string process_type =
1005 command_line.GetSwitchValueASCII(switches::kProcessType);
1006
1007 delegate_->ProcessExiting(process_type);
1008 }
1009
1010 #if !defined(CHROME_MULTIPLE_DLL_CHILD)
1011 service_manager_environment_.reset();
1012 // The BrowserTaskExecutor needs to be destroyed before |exit_manager_|.
1013 BrowserTaskExecutor::Shutdown();
1014 #endif // !defined(CHROME_MULTIPLE_DLL_CHILD)
1015
1016 #if defined(OS_WIN)
1017 #ifdef _CRTDBG_MAP_ALLOC
1018 _CrtDumpMemoryLeaks();
1019 #endif // _CRTDBG_MAP_ALLOC
1020 #endif // OS_WIN
1021
1022 exit_manager_.reset(nullptr);
1023
1024 delegate_ = nullptr;
1025 is_shutdown_ = true;
1026 }
1027
1028 // static
Create()1029 ContentMainRunner* ContentMainRunner::Create() {
1030 return ContentMainRunnerImpl::Create();
1031 }
1032
1033 } // namespace content
1034