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, &region);
217   if (fd.is_valid()) {
218     base::File file(std::move(fd));
219     gin::V8Initializer::LoadV8SnapshotFromFile(std::move(file), &region,
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