chrome_main_delegate.cc 60 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544
  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. #include "chrome/app/chrome_main_delegate.h"
  5. #include <stddef.h>
  6. #include <string>
  7. #include "base/base_paths.h"
  8. #include "base/bind.h"
  9. #include "base/check.h"
  10. #include "base/command_line.h"
  11. #include "base/cpu.h"
  12. #include "base/cpu_reduction_experiment.h"
  13. #include "base/dcheck_is_on.h"
  14. #include "base/files/file_path.h"
  15. #include "base/files/file_util.h"
  16. #include "base/i18n/rtl.h"
  17. #include "base/immediate_crash.h"
  18. #include "base/lazy_instance.h"
  19. #include "base/notreached.h"
  20. #include "base/path_service.h"
  21. #include "base/process/memory.h"
  22. #include "base/process/process.h"
  23. #include "base/process/process_handle.h"
  24. #include "base/strings/string_util.h"
  25. #include "base/strings/utf_string_conversions.h"
  26. #include "base/task/sequence_manager/sequence_manager_impl.h"
  27. #include "base/task/sequence_manager/thread_controller_power_monitor.h"
  28. #include "base/task/thread_pool/thread_pool_instance.h"
  29. #include "base/threading/hang_watcher.h"
  30. #include "base/threading/platform_thread.h"
  31. #include "base/threading/thread_task_runner_handle.h"
  32. #include "base/time/time.h"
  33. #include "base/timer/timer.h"
  34. #include "base/trace_event/trace_event_impl.h"
  35. #include "build/build_config.h"
  36. #include "build/chromeos_buildflags.h"
  37. #include "chrome/browser/chrome_content_browser_client.h"
  38. #include "chrome/browser/chrome_resource_bundle_helper.h"
  39. #include "chrome/browser/defaults.h"
  40. #include "chrome/browser/metrics/chrome_feature_list_creator.h"
  41. #include "chrome/browser/startup_data.h"
  42. #include "chrome/common/buildflags.h"
  43. #include "chrome/common/channel_info.h"
  44. #include "chrome/common/chrome_content_client.h"
  45. #include "chrome/common/chrome_features.h"
  46. #include "chrome/common/chrome_paths.h"
  47. #include "chrome/common/chrome_paths_internal.h"
  48. #include "chrome/common/chrome_result_codes.h"
  49. #include "chrome/common/chrome_switches.h"
  50. #include "chrome/common/crash_keys.h"
  51. #include "chrome/common/logging_chrome.h"
  52. #include "chrome/common/profiler/process_type.h"
  53. #include "chrome/common/profiler/unwind_util.h"
  54. #include "chrome/common/url_constants.h"
  55. #include "chrome/gpu/chrome_content_gpu_client.h"
  56. #include "chrome/renderer/chrome_content_renderer_client.h"
  57. #include "chrome/utility/chrome_content_utility_client.h"
  58. #include "components/component_updater/component_updater_paths.h"
  59. #include "components/content_settings/core/common/content_settings_pattern.h"
  60. #include "components/crash/core/app/crash_reporter_client.h"
  61. #include "components/crash/core/common/crash_key.h"
  62. #include "components/crash/core/common/crash_keys.h"
  63. #include "components/gwp_asan/buildflags/buildflags.h"
  64. #include "components/heap_profiling/in_process/heap_profiler_controller.h"
  65. #include "components/nacl/common/buildflags.h"
  66. #include "components/services/heap_profiling/public/cpp/profiling_client.h"
  67. #include "components/startup_metric_utils/browser/startup_metric_utils.h"
  68. #include "components/version_info/version_info.h"
  69. #include "content/public/common/content_client.h"
  70. #include "content/public/common/content_constants.h"
  71. #include "content/public/common/content_paths.h"
  72. #include "content/public/common/content_switches.h"
  73. #include "content/public/common/main_function_params.h"
  74. #include "content/public/common/profiling.h"
  75. #include "content/public/common/url_constants.h"
  76. #include "extensions/buildflags/buildflags.h"
  77. #include "net/http/http_cache.h"
  78. #include "net/url_request/url_request.h"
  79. #include "pdf/buildflags.h"
  80. #include "ppapi/buildflags/buildflags.h"
  81. #include "printing/buildflags/buildflags.h"
  82. #include "services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h"
  83. #include "third_party/abseil-cpp/absl/types/variant.h"
  84. #include "third_party/blink/public/common/features.h"
  85. #include "ui/base/resource/resource_bundle.h"
  86. #include "ui/base/ui_base_switches.h"
  87. #if BUILDFLAG(IS_WIN)
  88. #include <malloc.h>
  89. #include <algorithm>
  90. #include "base/files/important_file_writer_cleaner.h"
  91. #include "base/threading/platform_thread_win.h"
  92. #include "base/win/atl.h"
  93. #include "chrome/child/v8_crashpad_support_win.h"
  94. #include "chrome/chrome_elf/chrome_elf_main.h"
  95. #include "chrome/common/child_process_logging.h"
  96. #include "chrome/common/win/delay_load_failure_hook.h"
  97. #include "chrome/install_static/install_util.h"
  98. #include "components/browser_watcher/extended_crash_reporting.h"
  99. #include "sandbox/win/src/sandbox.h"
  100. #include "ui/base/resource/resource_bundle_win.h"
  101. #endif
  102. #if BUILDFLAG(IS_MAC)
  103. #include "base/mac/foundation_util.h"
  104. #include "base/message_loop/message_pump_mac.h"
  105. #include "chrome/app/chrome_main_mac.h"
  106. #include "chrome/browser/chrome_browser_application_mac.h"
  107. #include "chrome/browser/mac/relauncher.h"
  108. #include "chrome/browser/shell_integration.h"
  109. #include "components/crash/core/common/objc_zombie.h"
  110. #include "ui/base/l10n/l10n_util_mac.h"
  111. #endif
  112. #if BUILDFLAG(IS_POSIX)
  113. #include <locale.h>
  114. #include <signal.h>
  115. #include "chrome/app/chrome_crash_reporter_client.h"
  116. #include "components/about_ui/credit_utils.h"
  117. #endif
  118. #if BUILDFLAG(ENABLE_NACL) && (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS))
  119. #include "components/nacl/common/nacl_paths.h"
  120. #include "components/nacl/zygote/nacl_fork_delegate_linux.h"
  121. #endif
  122. #if BUILDFLAG(IS_CHROMEOS)
  123. #include "chromeos/dbus/constants/dbus_paths.h"
  124. #endif
  125. #if BUILDFLAG(IS_CHROMEOS_ASH)
  126. #include "ash/constants/ash_paths.h"
  127. #include "ash/constants/ash_switches.h"
  128. #include "base/system/sys_info.h"
  129. #include "chrome/browser/ash/boot_times_recorder.h"
  130. #include "chrome/browser/ash/dbus/ash_dbus_helper.h"
  131. #include "chrome/browser/ash/startup_settings_cache.h"
  132. #include "chromeos/ash/components/memory/kstaled.h"
  133. #include "chromeos/ash/components/memory/memory.h"
  134. #include "chromeos/ash/components/memory/swap_configuration.h"
  135. #include "chromeos/hugepage_text/hugepage_text.h"
  136. #include "ui/lottie/resource.h" // nogncheck
  137. #endif
  138. #if BUILDFLAG(IS_ANDROID)
  139. #include "base/android/java_exception_reporter.h"
  140. #include "base/android/library_loader/library_loader_hooks.h"
  141. #include "chrome/browser/android/metrics/uma_session_stats.h"
  142. #include "chrome/browser/flags/android/chrome_feature_list.h"
  143. #include "chrome/common/chrome_descriptors.h"
  144. #include "components/crash/android/pure_java_exception_handler.h"
  145. #include "net/android/network_change_notifier_factory_android.h"
  146. #else // BUILDFLAG(IS_ANDROID)
  147. // Diagnostics is only available on non-android platforms.
  148. #include "chrome/browser/diagnostics/diagnostics_controller.h"
  149. #include "chrome/browser/diagnostics/diagnostics_writer.h"
  150. #endif
  151. #if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_ANDROID)
  152. #include "components/crash/core/app/breakpad_linux.h"
  153. #include "v8/include/v8-wasm-trap-handler-posix.h"
  154. #include "v8/include/v8.h"
  155. #endif
  156. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  157. #include "base/environment.h"
  158. #endif
  159. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
  160. #include "base/message_loop/message_pump_libevent.h"
  161. #endif
  162. #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID) || \
  163. BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  164. #include "chrome/browser/policy/policy_path_parser.h"
  165. #include "components/crash/core/app/crashpad.h"
  166. #endif
  167. #if BUILDFLAG(ENABLE_EXTENSIONS)
  168. #include "chrome/browser/extensions/startup_helper.h"
  169. #include "extensions/common/constants.h"
  170. #endif
  171. #if BUILDFLAG(ENABLE_NACL)
  172. #include "components/nacl/common/nacl_switches.h"
  173. #include "components/nacl/renderer/plugin/ppapi_entrypoints.h"
  174. #endif
  175. #if BUILDFLAG(ENABLE_PDF)
  176. #include "chrome/child/pdf_child_init.h"
  177. #endif
  178. #if BUILDFLAG(ENABLE_GWP_ASAN)
  179. #include "components/gwp_asan/client/gwp_asan.h" // nogncheck
  180. #endif
  181. #if BUILDFLAG(IS_CHROMEOS_LACROS)
  182. #include "chrome/common/chrome_paths_lacros.h"
  183. #include "chromeos/crosapi/cpp/crosapi_constants.h" // nogncheck
  184. #include "chromeos/crosapi/mojom/crosapi.mojom.h" // nogncheck
  185. #include "chromeos/lacros/dbus/lacros_dbus_helper.h"
  186. #include "chromeos/lacros/lacros_paths.h"
  187. #include "chromeos/lacros/lacros_service.h"
  188. #include "chromeos/startup/browser_params_proxy.h" // nogncheck
  189. #include "media/base/media_switches.h"
  190. #include "ui/base/resource/data_pack_with_resource_sharing_lacros.h"
  191. #endif
  192. base::LazyInstance<ChromeContentGpuClient>::DestructorAtExit
  193. g_chrome_content_gpu_client = LAZY_INSTANCE_INITIALIZER;
  194. base::LazyInstance<ChromeContentRendererClient>::DestructorAtExit
  195. g_chrome_content_renderer_client = LAZY_INSTANCE_INITIALIZER;
  196. extern int NaClMain(content::MainFunctionParams);
  197. const char* const ChromeMainDelegate::kNonWildcardDomainNonPortSchemes[] = {
  198. #if BUILDFLAG(ENABLE_EXTENSIONS)
  199. extensions::kExtensionScheme,
  200. #endif
  201. chrome::kChromeSearchScheme, content::kChromeDevToolsScheme,
  202. content::kChromeUIScheme, content::kChromeUIUntrustedScheme};
  203. const size_t ChromeMainDelegate::kNonWildcardDomainNonPortSchemesSize =
  204. std::size(kNonWildcardDomainNonPortSchemes);
  205. namespace {
  206. #if BUILDFLAG(IS_CHROMEOS_LACROS)
  207. const base::FilePath::CharType kUserHomeDirPrefix[] =
  208. FILE_PATH_LITERAL("/home/user");
  209. #endif // BUILDFLAG(IS_CHROMEOS_LACROS)
  210. #if BUILDFLAG(IS_WIN)
  211. // Early versions of Chrome incorrectly registered a chromehtml: URL handler,
  212. // which gives us nothing but trouble. Avoid launching chrome this way since
  213. // some apps fail to properly escape arguments.
  214. bool HasDeprecatedArguments(const std::wstring& command_line) {
  215. const wchar_t kChromeHtml[] = L"chromehtml:";
  216. std::wstring command_line_lower = base::ToLowerASCII(command_line);
  217. // We are only searching for ASCII characters so this is OK.
  218. return (command_line_lower.find(kChromeHtml) != std::wstring::npos);
  219. }
  220. // If we try to access a path that is not currently available, we want the call
  221. // to fail rather than show an error dialog.
  222. void SuppressWindowsErrorDialogs() {
  223. UINT new_flags = SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX;
  224. // Preserve existing error mode.
  225. UINT existing_flags = SetErrorMode(new_flags);
  226. SetErrorMode(existing_flags | new_flags);
  227. }
  228. bool IsSandboxedProcess() {
  229. typedef bool (*IsSandboxedProcessFunc)();
  230. IsSandboxedProcessFunc is_sandboxed_process_func =
  231. reinterpret_cast<IsSandboxedProcessFunc>(
  232. GetProcAddress(GetModuleHandle(NULL), "IsSandboxedProcess"));
  233. return is_sandboxed_process_func && is_sandboxed_process_func();
  234. }
  235. void SetUpExtendedCrashReporting(bool is_browser_process) {
  236. browser_watcher::ExtendedCrashReporting* extended_crash_reporting =
  237. browser_watcher::ExtendedCrashReporting::SetUpIfEnabled(
  238. is_browser_process
  239. ? browser_watcher::ExtendedCrashReporting::kBrowserProcess
  240. : browser_watcher::ExtendedCrashReporting::kOther);
  241. if (!extended_crash_reporting)
  242. return;
  243. // Record product, version, channel and special build strings.
  244. wchar_t exe_file[MAX_PATH] = {};
  245. CHECK(::GetModuleFileName(nullptr, exe_file, std::size(exe_file)));
  246. std::wstring product_name, version_number, channel_name, special_build;
  247. install_static::GetExecutableVersionDetails(
  248. exe_file, &product_name, &version_number, &special_build, &channel_name);
  249. extended_crash_reporting->SetProductStrings(
  250. base::WideToUTF16(product_name), base::WideToUTF16(version_number),
  251. base::WideToUTF16(channel_name), base::WideToUTF16(special_build));
  252. }
  253. #endif // BUILDFLAG(IS_WIN)
  254. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  255. void AdjustLinuxOOMScore(const std::string& process_type) {
  256. int score = -1;
  257. if (process_type == switches::kPpapiPluginProcess) {
  258. score = content::kPluginOomScore;
  259. } else if (process_type == switches::kUtilityProcess ||
  260. process_type == switches::kGpuProcess) {
  261. score = content::kMiscOomScore;
  262. #if BUILDFLAG(ENABLE_NACL)
  263. } else if (process_type == switches::kNaClLoaderProcess) {
  264. score = content::kPluginOomScore;
  265. #endif
  266. } else if (process_type == switches::kZygoteProcess || process_type.empty()) {
  267. // For zygotes and unlabeled process types, we want to still make
  268. // them killable by the OOM killer.
  269. score = content::kZygoteOomScore;
  270. } else if (process_type == switches::kRendererProcess) {
  271. LOG(WARNING) << "process type 'renderer' "
  272. << "should be created through the zygote.";
  273. // When debugging, this process type can end up being run directly, but
  274. // this isn't the typical path for assigning the OOM score for it. Still,
  275. // we want to assign a score that is somewhat representative for debugging.
  276. score = content::kLowestRendererOomScore;
  277. } else {
  278. NOTREACHED() << "Unknown process type";
  279. }
  280. // In the case of a 0 score, still try to adjust it. Most likely the score is
  281. // 0 already, but it may not be if this process inherited a higher score from
  282. // its parent process.
  283. if (score > -1)
  284. base::AdjustOOMScore(base::GetCurrentProcId(), score);
  285. }
  286. #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  287. // Returns true if this subprocess type needs the ResourceBundle initialized
  288. // and resources loaded.
  289. bool SubprocessNeedsResourceBundle(const std::string& process_type) {
  290. return
  291. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  292. // The zygote process opens the resources for the renderers.
  293. process_type == switches::kZygoteProcess ||
  294. #endif
  295. #if BUILDFLAG(IS_MAC)
  296. // Mac needs them too for scrollbar related images and for sandbox
  297. // profiles.
  298. #if BUILDFLAG(ENABLE_NACL)
  299. process_type == switches::kNaClLoaderProcess ||
  300. #endif
  301. process_type == switches::kGpuProcess ||
  302. #endif
  303. process_type == switches::kPpapiPluginProcess ||
  304. process_type == switches::kRendererProcess ||
  305. process_type == switches::kUtilityProcess;
  306. }
  307. #if BUILDFLAG(IS_POSIX)
  308. bool HandleCreditsSwitch(const base::CommandLine& command_line) {
  309. if (!command_line.HasSwitch(switches::kCredits))
  310. return false;
  311. // Load resources: about_credits.html is in component_resources.pak that is
  312. // re-packed into resources.pak.
  313. base::FilePath resource_dir;
  314. bool result = base::PathService::Get(base::DIR_ASSETS, &resource_dir);
  315. DCHECK(result);
  316. const std::string locale =
  317. command_line.GetSwitchValueASCII(::switches::kLang);
  318. ui::ResourceBundle::InitSharedInstanceWithLocale(
  319. locale, /**parameter_name=*/nullptr,
  320. ui::ResourceBundle::DO_NOT_LOAD_COMMON_RESOURCES);
  321. base::FilePath resources_pak =
  322. resource_dir.Append(FILE_PATH_LITERAL("resources.pak"));
  323. #if BUILDFLAG(IS_MAC) && !defined(COMPONENT_BUILD)
  324. // In non-component builds, check if a fallback in Resources/ folder is
  325. // available.
  326. if (!base::PathExists(resources_pak)) {
  327. resources_pak =
  328. resource_dir.Append(FILE_PATH_LITERAL("Resources/resources.pak"));
  329. }
  330. #endif
  331. ui::ResourceBundle::GetSharedInstance().AddDataPackFromPath(
  332. resources_pak, ui::kScaleFactorNone);
  333. auto credits = about_ui::GetCredits(/**include_scripts=*/false);
  334. // If resources failed to load, about_ui::GetCredits returns
  335. // a malformed HTML doc containing `</body>\n</html>`.
  336. // When the resources loaded successfully, we get a huge document
  337. // (~8 MiB) instead.
  338. // We use a threshold of 100 characters to see if the resources
  339. // were loaded successfully.
  340. size_t resource_loading_threshold = 100;
  341. if (credits.size() < resource_loading_threshold)
  342. printf("%s\n", "Failed to load credits.");
  343. else
  344. printf("%s\n", credits.c_str());
  345. return true;
  346. }
  347. // Check for --version and --product-version; return true if we encountered
  348. // one of these switches and should exit now.
  349. bool HandleVersionSwitches(const base::CommandLine& command_line) {
  350. #if !BUILDFLAG(IS_MAC)
  351. if (command_line.HasSwitch(switches::kProductVersion)) {
  352. printf("%s\n", version_info::GetVersionNumber().c_str());
  353. return true;
  354. }
  355. #endif
  356. if (command_line.HasSwitch(switches::kVersion)) {
  357. printf("%s %s %s\n", version_info::GetProductName().c_str(),
  358. version_info::GetVersionNumber().c_str(),
  359. chrome::GetChannelName(chrome::WithExtendedStable(true)).c_str());
  360. return true;
  361. }
  362. return false;
  363. }
  364. // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch
  365. // of lacros-chrome is complete.
  366. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
  367. // Show the man page if --help or -h is on the command line.
  368. void HandleHelpSwitches(const base::CommandLine& command_line) {
  369. if (command_line.HasSwitch(switches::kHelp) ||
  370. command_line.HasSwitch(switches::kHelpShort)) {
  371. base::FilePath binary(command_line.argv()[0]);
  372. execlp("man", "man", binary.BaseName().value().c_str(), NULL);
  373. PLOG(FATAL) << "execlp failed";
  374. }
  375. }
  376. #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
  377. #if !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_ANDROID)
  378. void SIGTERMProfilingShutdown(int signal) {
  379. content::Profiling::Stop();
  380. struct sigaction sigact;
  381. memset(&sigact, 0, sizeof(sigact));
  382. sigact.sa_handler = SIG_DFL;
  383. CHECK_EQ(sigaction(SIGTERM, &sigact, NULL), 0);
  384. raise(signal);
  385. }
  386. void SetUpProfilingShutdownHandler() {
  387. struct sigaction sigact;
  388. sigact.sa_handler = SIGTERMProfilingShutdown;
  389. sigact.sa_flags = SA_RESETHAND;
  390. sigemptyset(&sigact.sa_mask);
  391. CHECK_EQ(sigaction(SIGTERM, &sigact, NULL), 0);
  392. }
  393. #endif // !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_ANDROID)
  394. #endif // BUILDFLAG(IS_POSIX)
  395. #if BUILDFLAG(ENABLE_EXTENSIONS)
  396. absl::optional<int> HandlePackExtensionSwitches(
  397. const base::CommandLine& command_line) {
  398. // If the command line specifies --pack-extension, attempt the pack extension
  399. // startup action and exit.
  400. if (!command_line.HasSwitch(switches::kPackExtension))
  401. return absl::nullopt;
  402. const std::string locale =
  403. command_line.GetSwitchValueASCII(::switches::kLang);
  404. ui::ResourceBundle::InitSharedInstanceWithLocale(
  405. locale, /*delegate=*/nullptr,
  406. ui::ResourceBundle::DO_NOT_LOAD_COMMON_RESOURCES);
  407. extensions::StartupHelper extension_startup_helper;
  408. std::string error_message;
  409. if (!extension_startup_helper.PackExtension(command_line, &error_message)) {
  410. if (!error_message.empty()) {
  411. LOG(ERROR) << error_message.c_str();
  412. }
  413. return chrome::RESULT_CODE_PACK_EXTENSION_ERROR;
  414. }
  415. return chrome::RESULT_CODE_NORMAL_EXIT_PACK_EXTENSION_SUCCESS;
  416. }
  417. #endif // !BUILDFLAG(ENABLE_EXTENSIONS)
  418. struct MainFunction {
  419. const char* name;
  420. int (*function)(content::MainFunctionParams);
  421. };
  422. // Initializes the user data dir. Must be called before InitializeLocalState().
  423. void InitializeUserDataDir(base::CommandLine* command_line) {
  424. #if BUILDFLAG(IS_WIN)
  425. // Reach out to chrome_elf for the truth on the user data directory.
  426. // Note that in tests, this links to chrome_elf_test_stubs.
  427. wchar_t user_data_dir_buf[MAX_PATH], invalid_user_data_dir_buf[MAX_PATH];
  428. // In tests this may return false, implying the user data dir should be unset.
  429. if (GetUserDataDirectoryThunk(user_data_dir_buf, std::size(user_data_dir_buf),
  430. invalid_user_data_dir_buf,
  431. std::size(invalid_user_data_dir_buf))) {
  432. base::FilePath user_data_dir(user_data_dir_buf);
  433. if (invalid_user_data_dir_buf[0] != 0) {
  434. chrome::SetInvalidSpecifiedUserDataDir(
  435. base::FilePath(invalid_user_data_dir_buf));
  436. command_line->AppendSwitchPath(switches::kUserDataDir, user_data_dir);
  437. }
  438. CHECK(base::PathService::OverrideAndCreateIfNeeded(
  439. chrome::DIR_USER_DATA, user_data_dir, false, true));
  440. }
  441. #else // BUILDFLAG(IS_WIN)
  442. base::FilePath user_data_dir =
  443. command_line->GetSwitchValuePath(switches::kUserDataDir);
  444. std::string process_type =
  445. command_line->GetSwitchValueASCII(switches::kProcessType);
  446. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  447. // On Linux, Chrome does not support running multiple copies under different
  448. // DISPLAYs, so the profile directory can be specified in the environment to
  449. // support the virtual desktop use-case.
  450. if (user_data_dir.empty()) {
  451. std::string user_data_dir_string;
  452. std::unique_ptr<base::Environment> environment(base::Environment::Create());
  453. if (environment->GetVar("CHROME_USER_DATA_DIR", &user_data_dir_string) &&
  454. base::IsStringUTF8(user_data_dir_string)) {
  455. user_data_dir = base::FilePath::FromUTF8Unsafe(user_data_dir_string);
  456. }
  457. }
  458. #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  459. #if BUILDFLAG(IS_MAC)
  460. policy::path_parser::CheckUserDataDirPolicy(&user_data_dir);
  461. #endif // BUILDFLAG(IS_MAC)
  462. const bool specified_directory_was_invalid =
  463. !user_data_dir.empty() &&
  464. !base::PathService::OverrideAndCreateIfNeeded(chrome::DIR_USER_DATA,
  465. user_data_dir, false, true);
  466. // Save inaccessible or invalid paths so the user may be prompted later.
  467. if (specified_directory_was_invalid)
  468. chrome::SetInvalidSpecifiedUserDataDir(user_data_dir);
  469. // Warn and fail early if the process fails to get a user data directory.
  470. if (!base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) {
  471. // If an invalid command-line or policy override was specified, the user
  472. // will be given an error with that value. Otherwise, use the directory
  473. // returned by PathService (or the fallback default directory) in the error.
  474. if (!specified_directory_was_invalid) {
  475. // base::PathService::Get() returns false and yields an empty path if it
  476. // fails to create DIR_USER_DATA. Retrieve the default value manually to
  477. // display a more meaningful error to the user in that case.
  478. if (user_data_dir.empty())
  479. chrome::GetDefaultUserDataDirectory(&user_data_dir);
  480. chrome::SetInvalidSpecifiedUserDataDir(user_data_dir);
  481. }
  482. // The browser process (which is identified by an empty |process_type|) will
  483. // handle the error later; other processes that need the dir crash here.
  484. CHECK(process_type.empty()) << "Unable to get the user data directory "
  485. << "for process type: " << process_type;
  486. }
  487. // Append the fallback user data directory to the commandline. Otherwise,
  488. // child or service processes will attempt to use the invalid directory.
  489. if (specified_directory_was_invalid)
  490. command_line->AppendSwitchPath(switches::kUserDataDir, user_data_dir);
  491. #endif // BUILDFLAG(IS_WIN)
  492. }
  493. #if !BUILDFLAG(IS_ANDROID)
  494. void InitLogging(const std::string& process_type) {
  495. logging::OldFileDeletionState file_state = logging::APPEND_TO_OLD_LOG_FILE;
  496. if (process_type.empty()) {
  497. file_state = logging::DELETE_OLD_LOG_FILE;
  498. }
  499. const base::CommandLine& command_line =
  500. *base::CommandLine::ForCurrentProcess();
  501. logging::InitChromeLogging(command_line, file_state);
  502. }
  503. #endif
  504. void RecordMainStartupMetrics(base::TimeTicks application_start_time) {
  505. const base::TimeTicks now = base::TimeTicks::Now();
  506. #if BUILDFLAG(IS_WIN)
  507. DCHECK(!application_start_time.is_null());
  508. startup_metric_utils::RecordApplicationStartTime(application_start_time);
  509. #elif BUILDFLAG(IS_ANDROID)
  510. // On Android the main entry point time is the time when the Java code starts.
  511. // This happens before the shared library containing this code is even loaded.
  512. // The Java startup code has recorded that time, but the C++ code can't fetch
  513. // it from the Java side until it has initialized the JNI. See
  514. // ChromeMainDelegateAndroid.
  515. #else
  516. // On other platforms, |application_start_time| == |now| since the application
  517. // starts with ChromeMain().
  518. startup_metric_utils::RecordApplicationStartTime(now);
  519. #endif
  520. #if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || \
  521. BUILDFLAG(IS_CHROMEOS)
  522. // Record the startup process creation time on supported platforms. On Android
  523. // this is recorded in ChromeMainDelegateAndroid.
  524. startup_metric_utils::RecordStartupProcessCreationTime(
  525. base::Process::Current().CreationTime());
  526. #endif
  527. startup_metric_utils::RecordChromeMainEntryTime(now);
  528. }
  529. } // namespace
  530. ChromeMainDelegate::ChromeMainDelegate()
  531. : ChromeMainDelegate(base::TimeTicks()) {}
  532. ChromeMainDelegate::ChromeMainDelegate(base::TimeTicks exe_entry_point_ticks) {
  533. // Record startup metrics in the browser process. For component builds, there
  534. // is no way to know the type of process (process command line is not yet
  535. // initialized), so the function below will also be called in renderers.
  536. // This doesn't matter as it simply sets global variables.
  537. RecordMainStartupMetrics(exe_entry_point_ticks);
  538. }
  539. ChromeMainDelegate::~ChromeMainDelegate() = default;
  540. absl::optional<int> ChromeMainDelegate::PostEarlyInitialization(
  541. InvokedIn invoked_in) {
  542. DCHECK(base::ThreadPoolInstance::Get());
  543. const auto* invoked_in_browser =
  544. absl::get_if<InvokedInBrowserProcess>(&invoked_in);
  545. if (!invoked_in_browser) {
  546. CommonEarlyInitialization();
  547. return absl::nullopt;
  548. }
  549. #if BUILDFLAG(IS_WIN)
  550. // Initialize the cleaner of left-behind tmp files now that the main thread
  551. // has its SequencedTaskRunner; see https://crbug.com/1075917.
  552. base::ImportantFileWriterCleaner::GetInstance().Initialize();
  553. // For now, do not enable delay load failure hooks for browser process except
  554. // in tests, where failures really shouldn't happen.
  555. if (invoked_in_browser->is_running_test)
  556. chrome::DisableDelayLoadFailureHooksForCurrentModule();
  557. #endif
  558. // Chrome disallows cookies by default. All code paths that want to use
  559. // cookies need to go through one of Chrome's URLRequestContexts which have
  560. // a ChromeNetworkDelegate attached that selectively allows cookies again.
  561. net::URLRequest::SetDefaultCookiePolicyToBlock();
  562. // On Chrome OS, IPC (D-Bus, Crosapi) is required to create the FeatureList,
  563. // which depends on policy from an OS service. So, initialize it at this
  564. // timing.
  565. #if BUILDFLAG(IS_CHROMEOS_ASH)
  566. // The feature list depends on BrowserPolicyConnectorAsh which depends
  567. // on DBus, so initialize it here. Some D-Bus clients may depend on feature
  568. // list, so initialize them separately later at the end of this function.
  569. ash::InitializeDBus();
  570. #elif BUILDFLAG(IS_CHROMEOS_LACROS)
  571. // Initialize D-Bus for Lacros.
  572. chromeos::LacrosInitializeDBus();
  573. // LacrosService instance needs the sequence of the main thread,
  574. // and needs to be created earlier than incoming Mojo invitation handling.
  575. // This also needs ThreadPool sequences to post some tasks internally.
  576. // However, the tasks can be suspended until actual start of the ThreadPool
  577. // sequences later.
  578. lacros_service_ = std::make_unique<chromeos::LacrosService>();
  579. {
  580. const chromeos::BrowserParamsProxy* init_params =
  581. chromeos::BrowserParamsProxy::Get();
  582. // This lives here rather than in ChromeBrowserMainExtraPartsLacros due to
  583. // timing constraints. If we relocate it, then the flags aren't propagated
  584. // to the GPU process.
  585. if (init_params->BuildFlags().has_value()) {
  586. for (auto flag : init_params->BuildFlags().value()) {
  587. switch (flag) {
  588. case crosapi::mojom::BuildFlag::kUnknown:
  589. break;
  590. case crosapi::mojom::BuildFlag::kEnablePlatformEncryptedHevc:
  591. // This was deprecated.
  592. break;
  593. case crosapi::mojom::BuildFlag::kEnablePlatformHevc:
  594. base::CommandLine::ForCurrentProcess()->AppendSwitch(
  595. switches::kLacrosEnablePlatformHevc);
  596. break;
  597. case crosapi::mojom::BuildFlag::kUseChromeosProtectedMedia:
  598. base::CommandLine::ForCurrentProcess()->AppendSwitch(
  599. switches::kLacrosUseChromeosProtectedMedia);
  600. break;
  601. case crosapi::mojom::BuildFlag::kUseChromeosProtectedAv1:
  602. base::CommandLine::ForCurrentProcess()->AppendSwitch(
  603. switches::kLacrosUseChromeosProtectedAv1);
  604. break;
  605. }
  606. }
  607. }
  608. }
  609. #endif
  610. ChromeFeatureListCreator* chrome_feature_list_creator =
  611. chrome_content_browser_client_->startup_data()
  612. ->chrome_feature_list_creator();
  613. chrome_feature_list_creator->CreateFeatureList();
  614. CommonEarlyInitialization();
  615. // Initializes the resource bundle and determines the locale.
  616. std::string actual_locale = LoadLocalState(
  617. chrome_feature_list_creator, invoked_in_browser->is_running_test);
  618. chrome_feature_list_creator->SetApplicationLocale(actual_locale);
  619. chrome_feature_list_creator->OverrideCachedUIStrings();
  620. // On Chrome OS, initialize D-Bus clients that depend on feature list.
  621. #if BUILDFLAG(IS_CHROMEOS_ASH)
  622. ash::InitializeFeatureListDependentDBus();
  623. #elif BUILDFLAG(IS_CHROMEOS_LACROS)
  624. chromeos::LacrosInitializeFeatureListDependentDBus();
  625. #endif
  626. #if BUILDFLAG(IS_ANDROID)
  627. chrome_content_browser_client_->startup_data()->CreateProfilePrefService();
  628. net::NetworkChangeNotifier::SetFactory(
  629. new net::NetworkChangeNotifierFactoryAndroid());
  630. #endif
  631. if (base::FeatureList::IsEnabled(
  632. features::kWriteBasicSystemProfileToPersistentHistogramsFile)) {
  633. bool record = true;
  634. #if BUILDFLAG(IS_ANDROID)
  635. record =
  636. base::FeatureList::IsEnabled(chrome::android::kUmaBackgroundSessions);
  637. #endif
  638. if (record)
  639. chrome_content_browser_client_->startup_data()->RecordCoreSystemProfile();
  640. }
  641. #if BUILDFLAG(IS_ANDROID)
  642. UmaSessionStats::OnStartup();
  643. #endif
  644. #if BUILDFLAG(IS_MAC)
  645. chrome::CacheChannelInfo();
  646. #endif
  647. return absl::nullopt;
  648. }
  649. bool ChromeMainDelegate::ShouldCreateFeatureList(InvokedIn invoked_in) {
  650. // In the browser process Chrome creates the FeatureList, so content should
  651. // not.
  652. return absl::holds_alternative<InvokedInChildProcess>(invoked_in);
  653. }
  654. void ChromeMainDelegate::CommonEarlyInitialization() {
  655. std::string process_type =
  656. base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
  657. switches::kProcessType);
  658. bool is_browser_process = process_type.empty();
  659. // Enable Split cache by default here and not in content/ so as to not
  660. // impact non-Chrome embedders like WebView, Cronet etc. This only enables
  661. // it if not already overridden by command line, field trial etc.
  662. net::HttpCache::SplitCacheFeatureEnableByDefault();
  663. #if BUILDFLAG(IS_CHROMEOS)
  664. // Threading features.
  665. base::PlatformThread::InitThreadPostFieldTrial();
  666. #endif
  667. version_info::Channel channel = chrome::GetChannel();
  668. [[maybe_unused]] bool is_canary_dev =
  669. (channel == version_info::Channel::CANARY ||
  670. channel == version_info::Channel::DEV);
  671. // GWP-ASAN requires crashpad to gather alloc/dealloc stack traces, which is
  672. // not always enabled on Linux/ChromeOS.
  673. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  674. bool enable_gwp_asan = crash_reporter::IsCrashpadEnabled();
  675. #else
  676. bool enable_gwp_asan = true;
  677. #endif
  678. if (enable_gwp_asan) {
  679. #if BUILDFLAG(ENABLE_GWP_ASAN_MALLOC)
  680. gwp_asan::EnableForMalloc(is_canary_dev || is_browser_process,
  681. process_type.c_str());
  682. #endif
  683. #if BUILDFLAG(ENABLE_GWP_ASAN_PARTITIONALLOC)
  684. gwp_asan::EnableForPartitionAlloc(is_canary_dev || is_browser_process,
  685. process_type.c_str());
  686. #endif
  687. }
  688. // Start heap profiling as early as possible so it can start recording
  689. // memory allocations.
  690. heap_profiler_controller_ = std::make_unique<HeapProfilerController>(
  691. channel,
  692. GetProfileParamsProcess(*base::CommandLine::ForCurrentProcess()));
  693. heap_profiler_controller_->StartIfEnabled();
  694. if (is_browser_process) {
  695. #if BUILDFLAG(IS_CHROMEOS_ASH)
  696. ash::ConfigureSwap();
  697. ash::InitializeKstaled();
  698. // If we're in an experimental group that locks the browser text we will do
  699. // that now.
  700. ash::LockMainProgramText();
  701. #endif
  702. }
  703. #if BUILDFLAG(IS_WIN)
  704. SetUpExtendedCrashReporting(is_browser_process);
  705. base::sequence_manager::internal::ThreadControllerPowerMonitor::
  706. InitializeOnMainThread();
  707. base::InitializePlatformThreadFeatures();
  708. #endif
  709. // Initialize the HangWatcher.
  710. base::HangWatcher::ProcessType hang_watcher_process_type;
  711. if (process_type.empty()) {
  712. hang_watcher_process_type = base::HangWatcher::ProcessType::kBrowserProcess;
  713. } else if (process_type == switches::kGpuProcess) {
  714. hang_watcher_process_type = base::HangWatcher::ProcessType::kGPUProcess;
  715. } else if (process_type == switches::kRendererProcess) {
  716. hang_watcher_process_type =
  717. base::HangWatcher::ProcessType::kRendererProcess;
  718. } else if (process_type == switches::kUtilityProcess) {
  719. hang_watcher_process_type = base::HangWatcher::ProcessType::kUtilityProcess;
  720. } else {
  721. hang_watcher_process_type = base::HangWatcher::ProcessType::kUnknownProcess;
  722. }
  723. base::HangWatcher::InitializeOnMainThread(hang_watcher_process_type);
  724. base::internal::TimerBase::InitializeFeatures();
  725. base::InitializeCpuReductionExperiment();
  726. base::sequence_manager::internal::SequenceManagerImpl::InitializeFeatures();
  727. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID)
  728. base::MessagePumpLibevent::InitializeFeatures();
  729. #elif BUILDFLAG(IS_MAC)
  730. base::PlatformThread::InitializeOptimizedRealtimeThreadingFeature();
  731. base::MessagePumpCFRunLoopBase::InitializeFeatures();
  732. #endif
  733. }
  734. #if BUILDFLAG(IS_WIN)
  735. bool ChromeMainDelegate::ShouldHandleConsoleControlEvents() {
  736. // Handle console control events so that orderly shutdown can be performed by
  737. // ChromeContentBrowserClient's override of SessionEnding.
  738. return true;
  739. }
  740. #endif
  741. absl::optional<int> ChromeMainDelegate::BasicStartupComplete() {
  742. #if BUILDFLAG(IS_CHROMEOS_ASH)
  743. ash::BootTimesRecorder::Get()->SaveChromeMainStats();
  744. #endif
  745. const base::CommandLine& command_line =
  746. *base::CommandLine::ForCurrentProcess();
  747. // Only allow disabling web security via the command-line flag if the user has
  748. // specified a distinct profile directory. This still enables tests to disable
  749. // web security by setting the kWebKitWebSecurityEnabled pref directly.
  750. //
  751. // Note that this is done in ChromeMainDelegate::BasicStartupComplete()
  752. // because this is the earliest callback. Many places in Chromium gate
  753. // security features around kDisableWebSecurity, and it is unreasonable to
  754. // expect them all to properly also check for kUserDataDir.
  755. if (command_line.HasSwitch(switches::kDisableWebSecurity)) {
  756. base::FilePath default_user_data_dir;
  757. chrome::GetDefaultUserDataDirectory(&default_user_data_dir);
  758. const base::FilePath specified_user_data_dir =
  759. command_line.GetSwitchValuePath(switches::kUserDataDir)
  760. .StripTrailingSeparators();
  761. if (specified_user_data_dir.empty() ||
  762. specified_user_data_dir == default_user_data_dir) {
  763. LOG(ERROR) << "Web security may only be disabled if '--user-data-dir' is "
  764. "also specified with a non-default value.";
  765. base::CommandLine::ForCurrentProcess()->RemoveSwitch(
  766. switches::kDisableWebSecurity);
  767. }
  768. }
  769. #if BUILDFLAG(IS_WIN)
  770. // Browser should not be sandboxed.
  771. const bool is_browser = !command_line.HasSwitch(switches::kProcessType);
  772. if (is_browser && IsSandboxedProcess())
  773. return chrome::RESULT_CODE_INVALID_SANDBOX_STATE;
  774. #endif
  775. #if BUILDFLAG(IS_MAC)
  776. // Give the browser process a longer treadmill, since crashes
  777. // there have more impact.
  778. const bool is_browser = !command_line.HasSwitch(switches::kProcessType);
  779. ObjcEvilDoers::ZombieEnable(true, is_browser ? 10000 : 1000);
  780. #endif
  781. content::Profiling::ProcessStarted();
  782. // Setup tracing sampler profiler as early as possible at startup if needed.
  783. // We pass in CreateCoreUnwindersFactory here since it lives in the chrome/
  784. // layer while TracingSamplerProfiler is outside of chrome/.
  785. tracing_sampler_profiler_ =
  786. tracing::TracingSamplerProfiler::CreateOnMainThread(
  787. base::BindRepeating(&CreateCoreUnwindersFactory));
  788. #if BUILDFLAG(IS_WIN)
  789. v8_crashpad_support::SetUp();
  790. #endif
  791. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  792. if (!crash_reporter::IsCrashpadEnabled()) {
  793. breakpad::SetFirstChanceExceptionHandler(v8::TryHandleWebAssemblyTrapPosix);
  794. }
  795. #endif
  796. #if BUILDFLAG(IS_POSIX)
  797. if (HandleVersionSwitches(command_line)) {
  798. return 0; // Got a --version switch; exit with a success error code.
  799. }
  800. if (HandleCreditsSwitch(command_line)) {
  801. return 0; // Got a --credits switch; exit with a success error code.
  802. }
  803. // TODO(crbug.com/1052397): Revisit the macro expression once build flag
  804. // switch of lacros-chrome is complete.
  805. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
  806. // This will directly exit if the user asked for help.
  807. HandleHelpSwitches(command_line);
  808. #endif
  809. #endif // BUILDFLAG(IS_POSIX)
  810. #if BUILDFLAG(IS_WIN)
  811. // Must do this before any other usage of command line!
  812. if (HasDeprecatedArguments(command_line.GetCommandLineString())) {
  813. return 1;
  814. }
  815. // HandleVerifier detects and reports incorrect handle manipulations. It
  816. // tracks handle operations on builds that support DCHECK only.
  817. #if !DCHECK_IS_ON()
  818. base::win::DisableHandleVerifier();
  819. #endif
  820. #endif // BUILDFLAG(IS_WIN)
  821. chrome::RegisterPathProvider();
  822. #if BUILDFLAG(IS_CHROMEOS_ASH)
  823. ash::RegisterPathProvider();
  824. #endif
  825. #if BUILDFLAG(IS_CHROMEOS_LACROS)
  826. chromeos::lacros_paths::RegisterPathProvider();
  827. #endif
  828. #if BUILDFLAG(IS_CHROMEOS)
  829. chromeos::dbus_paths::RegisterPathProvider();
  830. #endif
  831. #if BUILDFLAG(ENABLE_NACL) && (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS))
  832. nacl::RegisterPathProvider();
  833. #endif
  834. ContentSettingsPattern::SetNonWildcardDomainNonPortSchemes(
  835. kNonWildcardDomainNonPortSchemes, kNonWildcardDomainNonPortSchemesSize);
  836. // No support for ANDROID yet as DiagnosticsController needs wchar support.
  837. // TODO(gspencer): That's not true anymore, or at least there are no w-string
  838. // references anymore. Not sure if that means this can be enabled on Android or
  839. // not though. As there is no easily accessible command line on Android, I'm
  840. // not sure this is a big deal.
  841. #if !BUILDFLAG(IS_ANDROID)
  842. // If we are in diagnostics mode this is the end of the line: after the
  843. // diagnostics are run the process will invariably exit.
  844. if (command_line.HasSwitch(switches::kDiagnostics)) {
  845. diagnostics::DiagnosticsWriter::FormatType format =
  846. diagnostics::DiagnosticsWriter::HUMAN;
  847. if (command_line.HasSwitch(switches::kDiagnosticsFormat)) {
  848. std::string format_str =
  849. command_line.GetSwitchValueASCII(switches::kDiagnosticsFormat);
  850. if (format_str == "machine") {
  851. format = diagnostics::DiagnosticsWriter::MACHINE;
  852. } else if (format_str == "log") {
  853. format = diagnostics::DiagnosticsWriter::LOG;
  854. } else {
  855. DCHECK_EQ("human", format_str);
  856. }
  857. }
  858. diagnostics::DiagnosticsWriter writer(format);
  859. int exit_code = diagnostics::DiagnosticsController::GetInstance()->Run(
  860. command_line, &writer);
  861. diagnostics::DiagnosticsController::GetInstance()->ClearResults();
  862. return exit_code;
  863. }
  864. #endif
  865. #if BUILDFLAG(IS_CHROMEOS_ASH)
  866. // Initialize primary user homedir (in multi-profile session) as it may be
  867. // passed as a command line switch.
  868. base::FilePath homedir;
  869. if (command_line.HasSwitch(ash::switches::kHomedir)) {
  870. homedir = base::FilePath(
  871. command_line.GetSwitchValueASCII(ash::switches::kHomedir));
  872. base::PathService::OverrideAndCreateIfNeeded(base::DIR_HOME, homedir, true,
  873. false);
  874. }
  875. // If we are recovering from a crash on a ChromeOS device, then we will do
  876. // some recovery using the diagnostics module, and then continue on. We fake
  877. // up a command line to tell it that we want it to recover, and to preserve
  878. // the original command line. Note: logging at this point is to /var/log/ui.
  879. if ((base::SysInfo::IsRunningOnChromeOS() &&
  880. command_line.HasSwitch(ash::switches::kLoginUser)) ||
  881. command_line.HasSwitch(switches::kDiagnosticsRecovery)) {
  882. base::CommandLine interim_command_line(command_line.GetProgram());
  883. const char* const kSwitchNames[] = {
  884. switches::kUserDataDir,
  885. };
  886. interim_command_line.CopySwitchesFrom(command_line, kSwitchNames,
  887. std::size(kSwitchNames));
  888. interim_command_line.AppendSwitch(switches::kDiagnostics);
  889. interim_command_line.AppendSwitch(switches::kDiagnosticsRecovery);
  890. diagnostics::DiagnosticsWriter::FormatType format =
  891. diagnostics::DiagnosticsWriter::LOG;
  892. if (command_line.HasSwitch(switches::kDiagnosticsFormat)) {
  893. std::string format_str =
  894. command_line.GetSwitchValueASCII(switches::kDiagnosticsFormat);
  895. if (format_str == "machine") {
  896. format = diagnostics::DiagnosticsWriter::MACHINE;
  897. } else if (format_str == "human") {
  898. format = diagnostics::DiagnosticsWriter::HUMAN;
  899. } else {
  900. DCHECK_EQ("log", format_str);
  901. }
  902. }
  903. diagnostics::DiagnosticsWriter writer(format);
  904. int diagnostics_exit_code =
  905. diagnostics::DiagnosticsController::GetInstance()->Run(command_line,
  906. &writer);
  907. if (diagnostics_exit_code) {
  908. // Diagnostics has failed somehow, so we exit.
  909. return diagnostics_exit_code;
  910. }
  911. // Now we run the actual recovery tasks.
  912. int recovery_exit_code =
  913. diagnostics::DiagnosticsController::GetInstance()->RunRecovery(
  914. command_line, &writer);
  915. if (recovery_exit_code) {
  916. // Recovery has failed somehow, so we exit.
  917. return recovery_exit_code;
  918. }
  919. } else { // Not running diagnostics or recovery.
  920. diagnostics::DiagnosticsController::GetInstance()->RecordRegularStartup();
  921. }
  922. #endif
  923. // The TLS slot used by the memlog allocator shim needs to be initialized
  924. // early to ensure that it gets assigned a low slot number. If it gets
  925. // initialized too late, the glibc TLS system will require a malloc call in
  926. // order to allocate storage for a higher slot number. Since malloc is hooked,
  927. // this causes re-entrancy into the allocator shim, while the TLS object is
  928. // partially-initialized, which the TLS object is supposed to protect again.
  929. heap_profiling::InitTLSSlot();
  930. return absl::nullopt;
  931. }
  932. #if BUILDFLAG(IS_MAC)
  933. void ChromeMainDelegate::InitMacCrashReporter(
  934. const base::CommandLine& command_line,
  935. const std::string& process_type) {
  936. // TODO(mark): Right now, InitializeCrashpad() needs to be called after
  937. // CommandLine::Init() and chrome::RegisterPathProvider(). Ideally, Crashpad
  938. // initialization could occur sooner, preferably even before the framework
  939. // dylib is even loaded, to catch potential early crashes.
  940. const bool browser_process = process_type.empty();
  941. const bool install_from_dmg_relauncher_process =
  942. process_type == switches::kRelauncherProcess &&
  943. command_line.HasSwitch(switches::kRelauncherProcessDMGDevice);
  944. const bool initial_client =
  945. browser_process || install_from_dmg_relauncher_process;
  946. crash_reporter::InitializeCrashpad(initial_client, process_type);
  947. if (!browser_process) {
  948. std::string metrics_client_id =
  949. command_line.GetSwitchValueASCII(switches::kMetricsClientID);
  950. crash_keys::SetMetricsClientIdFromGUID(metrics_client_id);
  951. }
  952. // Mac Chrome is packaged with a main app bundle and a helper app bundle.
  953. // The main app bundle should only be used for the browser process, so it
  954. // should never see a --type switch (switches::kProcessType). Likewise,
  955. // the helper should always have a --type switch.
  956. //
  957. // This check is done this late so there is already a call to
  958. // base::mac::IsBackgroundOnlyProcess(), so there is no change in
  959. // startup/initialization order.
  960. // The helper's Info.plist marks it as a background only app.
  961. if (base::mac::IsBackgroundOnlyProcess()) {
  962. CHECK(command_line.HasSwitch(switches::kProcessType) &&
  963. !process_type.empty())
  964. << "Helper application requires --type.";
  965. } else if (base::mac::AmIBundled()) {
  966. CHECK(!command_line.HasSwitch(switches::kProcessType) &&
  967. process_type.empty())
  968. << "Main application forbids --type, saw " << process_type;
  969. }
  970. }
  971. void ChromeMainDelegate::SetUpInstallerPreferences(
  972. const base::CommandLine& command_line) {
  973. const bool uma_setting = command_line.HasSwitch(switches::kEnableUserMetrics);
  974. const bool default_browser_setting =
  975. command_line.HasSwitch(switches::kMakeChromeDefault);
  976. if (uma_setting)
  977. crash_reporter::SetUploadConsent(uma_setting);
  978. if (default_browser_setting)
  979. shell_integration::SetAsDefaultBrowser();
  980. }
  981. #endif // BUILDFLAG(IS_MAC)
  982. void ChromeMainDelegate::PreSandboxStartup() {
  983. const base::CommandLine& command_line =
  984. *base::CommandLine::ForCurrentProcess();
  985. std::string process_type =
  986. command_line.GetSwitchValueASCII(switches::kProcessType);
  987. crash_reporter::InitializeCrashKeys();
  988. #if BUILDFLAG(IS_POSIX)
  989. ChromeCrashReporterClient::Create();
  990. #endif
  991. #if BUILDFLAG(IS_MAC)
  992. InitMacCrashReporter(command_line, process_type);
  993. SetUpInstallerPreferences(command_line);
  994. #endif
  995. #if BUILDFLAG(IS_WIN)
  996. child_process_logging::Init();
  997. #endif
  998. #if defined(ARCH_CPU_ARM_FAMILY) && \
  999. (BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS))
  1000. // Create an instance of the CPU class to parse /proc/cpuinfo and cache
  1001. // cpu_brand info.
  1002. base::CPU cpu_info;
  1003. #endif
  1004. // Initialize the user data dir for any process type that needs it.
  1005. if (chrome::ProcessNeedsProfileDir(process_type))
  1006. InitializeUserDataDir(base::CommandLine::ForCurrentProcess());
  1007. #if BUILDFLAG(IS_CHROMEOS_LACROS)
  1008. if (process_type.empty() || process_type == switches::kZygoteProcess ||
  1009. process_type == switches::kUtilityProcess) {
  1010. // Initialize BrowserInitParams before generating and loading shared
  1011. // resource file since the path required for the feature is set by
  1012. // BrowserInitParams initialization.
  1013. const chromeos::BrowserParamsProxy* init_params =
  1014. chromeos::BrowserParamsProxy::Get();
  1015. chrome::SetLacrosDefaultPathsFromInitParams(
  1016. init_params->DefaultPaths().get());
  1017. // Override the login user DIR_HOME path for the Lacros browser process. The
  1018. // primary user id hash is expected to be already set, because Lacros should
  1019. // only run inside the user session.
  1020. if (init_params->CrosUserIdHash().has_value()) {
  1021. base::FilePath homedir(kUserHomeDirPrefix);
  1022. homedir = homedir.Append(init_params->CrosUserIdHash().value());
  1023. base::PathService::OverrideAndCreateIfNeeded(
  1024. base::DIR_HOME, homedir, /*is_absolute=*/true, /*create=*/false);
  1025. }
  1026. }
  1027. // Generate shared resource file only on browser process. This is to avoid
  1028. // generating a file in different processes again.
  1029. // Also generate only when resource file sharing feature is enabled.
  1030. if (command_line.HasSwitch(switches::kEnableResourcesFileSharing) &&
  1031. process_type.empty()) {
  1032. base::FilePath ash_resources_dir;
  1033. base::FilePath lacros_resources_dir;
  1034. base::FilePath user_data_dir;
  1035. if (base::PathService::Get(chromeos::lacros_paths::ASH_RESOURCES_DIR,
  1036. &ash_resources_dir) &&
  1037. base::PathService::Get(base::DIR_ASSETS, &lacros_resources_dir) &&
  1038. base::PathService::Get(chromeos::lacros_paths::USER_DATA_DIR,
  1039. &user_data_dir)) {
  1040. ui::DataPackWithResourceSharing::MaybeGenerateFallbackAndMapping(
  1041. ash_resources_dir.Append(FILE_PATH_LITERAL("resources.pak")),
  1042. lacros_resources_dir.Append(FILE_PATH_LITERAL("resources.pak")),
  1043. user_data_dir.Append(crosapi::kSharedResourcesPackName),
  1044. ui::kScaleFactorNone);
  1045. ui::DataPackWithResourceSharing::MaybeGenerateFallbackAndMapping(
  1046. ash_resources_dir.Append(FILE_PATH_LITERAL("chrome_100_percent.pak")),
  1047. lacros_resources_dir.Append(
  1048. FILE_PATH_LITERAL("chrome_100_percent.pak")),
  1049. user_data_dir.Append(crosapi::kSharedChrome100PercentPackName),
  1050. ui::k100Percent);
  1051. ui::DataPackWithResourceSharing::MaybeGenerateFallbackAndMapping(
  1052. ash_resources_dir.Append(FILE_PATH_LITERAL("chrome_200_percent.pak")),
  1053. lacros_resources_dir.Append(
  1054. FILE_PATH_LITERAL("chrome_200_percent.pak")),
  1055. user_data_dir.Append(crosapi::kSharedChrome200PercentPackName),
  1056. ui::k200Percent);
  1057. }
  1058. }
  1059. #endif // BUILDFLAG(IS_CHROMEOS_LACROS)
  1060. // Register component_updater PathProvider after DIR_USER_DATA overridden by
  1061. // command line flags. Maybe move the chrome PathProvider down here also?
  1062. int alt_preinstalled_components_dir =
  1063. #if BUILDFLAG(IS_CHROMEOS_ASH)
  1064. ash::DIR_PREINSTALLED_COMPONENTS;
  1065. #else
  1066. chrome::DIR_INTERNAL_PLUGINS;
  1067. #endif
  1068. component_updater::RegisterPathProvider(chrome::DIR_COMPONENTS,
  1069. alt_preinstalled_components_dir,
  1070. chrome::DIR_USER_DATA);
  1071. #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_WIN)
  1072. // Android does InitLogging when library is loaded. Skip here.
  1073. // For windows we call InitLogging when the sandbox is initialized.
  1074. InitLogging(process_type);
  1075. #endif
  1076. #if BUILDFLAG(IS_WIN)
  1077. // TODO(zturner): Throbber icons and cursors are still stored in chrome.dll,
  1078. // this can be killed once those are merged into resources.pak. See
  1079. // GlassBrowserFrameView::InitThrobberIcons(), https://crbug.com/368327 and
  1080. // https://crbug.com/1178117.
  1081. ui::SetResourcesDataDLL(_AtlBaseModule.GetResourceInstance());
  1082. #endif
  1083. if (SubprocessNeedsResourceBundle(process_type)) {
  1084. // Initialize ResourceBundle which handles files loaded from external
  1085. // sources. The language should have been passed in to us from the
  1086. // browser process as a command line flag.
  1087. #if !BUILDFLAG(ENABLE_NACL)
  1088. DCHECK(command_line.HasSwitch(switches::kLang) ||
  1089. process_type == switches::kZygoteProcess ||
  1090. process_type == switches::kGpuProcess ||
  1091. process_type == switches::kPpapiPluginProcess);
  1092. #else
  1093. DCHECK(command_line.HasSwitch(switches::kLang) ||
  1094. process_type == switches::kZygoteProcess ||
  1095. process_type == switches::kGpuProcess ||
  1096. process_type == switches::kNaClLoaderProcess ||
  1097. process_type == switches::kPpapiPluginProcess);
  1098. #endif
  1099. // TODO(markusheintz): The command line flag --lang is actually processed
  1100. // by the CommandLinePrefStore, and made available through the PrefService
  1101. // via the preference prefs::kApplicationLocale. The browser process uses
  1102. // the --lang flag to pass the value of the PrefService in here. Maybe
  1103. // this value could be passed in a different way.
  1104. std::string locale = command_line.GetSwitchValueASCII(switches::kLang);
  1105. #if BUILDFLAG(IS_CHROMEOS_ASH)
  1106. if (process_type == switches::kZygoteProcess) {
  1107. DCHECK(locale.empty());
  1108. // See comment at ReadAppLocale() for why we do this.
  1109. locale = ash::startup_settings_cache::ReadAppLocale();
  1110. }
  1111. ui::ResourceBundle::SetLottieParsingFunctions(
  1112. &lottie::ParseLottieAsStillImage,
  1113. &lottie::ParseLottieAsThemedStillImage);
  1114. #endif
  1115. #if BUILDFLAG(IS_ANDROID)
  1116. // The renderer sandbox prevents us from accessing our .pak files directly.
  1117. // Therefore file descriptors to the .pak files that we need are passed in
  1118. // at process creation time.
  1119. auto* global_descriptors = base::GlobalDescriptors::GetInstance();
  1120. int pak_fd = global_descriptors->Get(kAndroidLocalePakDescriptor);
  1121. base::MemoryMappedFile::Region pak_region =
  1122. global_descriptors->GetRegion(kAndroidLocalePakDescriptor);
  1123. ui::ResourceBundle::InitSharedInstanceWithPakFileRegion(base::File(pak_fd),
  1124. pak_region);
  1125. // Load secondary locale .pak file if it exists.
  1126. pak_fd = global_descriptors->MaybeGet(kAndroidSecondaryLocalePakDescriptor);
  1127. if (pak_fd != -1) {
  1128. pak_region =
  1129. global_descriptors->GetRegion(kAndroidSecondaryLocalePakDescriptor);
  1130. ui::ResourceBundle::GetSharedInstance()
  1131. .LoadSecondaryLocaleDataWithPakFileRegion(base::File(pak_fd),
  1132. pak_region);
  1133. }
  1134. int extra_pak_keys[] = {
  1135. kAndroidChrome100PercentPakDescriptor,
  1136. kAndroidUIResourcesPakDescriptor,
  1137. };
  1138. for (int extra_pak_key : extra_pak_keys) {
  1139. pak_fd = global_descriptors->Get(extra_pak_key);
  1140. pak_region = global_descriptors->GetRegion(extra_pak_key);
  1141. ui::ResourceBundle::GetSharedInstance().AddDataPackFromFileRegion(
  1142. base::File(pak_fd), pak_region, ui::k100Percent);
  1143. }
  1144. // For Android: Native resources for DFMs should only be used by the browser
  1145. // process. Their file descriptors and memory mapped file region are not
  1146. // passed to child processes, and are therefore not loaded here.
  1147. base::i18n::SetICUDefaultLocale(locale);
  1148. const std::string loaded_locale = locale;
  1149. #else
  1150. const std::string loaded_locale =
  1151. ui::ResourceBundle::InitSharedInstanceWithLocale(
  1152. locale, NULL, ui::ResourceBundle::LOAD_COMMON_RESOURCES);
  1153. base::FilePath resources_pack_path;
  1154. base::PathService::Get(chrome::FILE_RESOURCES_PACK, &resources_pack_path);
  1155. #if BUILDFLAG(IS_CHROMEOS_LACROS)
  1156. if (command_line.HasSwitch(switches::kEnableResourcesFileSharing)) {
  1157. // If LacrosResourcesFileSharing feature is enabled, Lacros refers to ash
  1158. // resources pak file.
  1159. base::FilePath ash_resources_pack_path;
  1160. base::PathService::Get(chrome::FILE_ASH_RESOURCES_PACK,
  1161. &ash_resources_pack_path);
  1162. base::FilePath shared_resources_pack_path;
  1163. base::PathService::Get(chrome::FILE_RESOURCES_FOR_SHARING_PACK,
  1164. &shared_resources_pack_path);
  1165. ui::ResourceBundle::GetSharedInstance()
  1166. .AddDataPackFromPathWithAshResources(
  1167. shared_resources_pack_path, ash_resources_pack_path,
  1168. resources_pack_path, ui::kScaleFactorNone);
  1169. } else {
  1170. ui::ResourceBundle::GetSharedInstance().AddDataPackFromPath(
  1171. resources_pack_path, ui::kScaleFactorNone);
  1172. }
  1173. #else
  1174. ui::ResourceBundle::GetSharedInstance().AddDataPackFromPath(
  1175. resources_pack_path, ui::kScaleFactorNone);
  1176. #endif // BUILDFLAG(IS_CHROMEOS_LACROS)
  1177. #endif // BUILDFLAG(IS_ANDROID)
  1178. CHECK(!loaded_locale.empty()) << "Locale could not be found for " << locale;
  1179. }
  1180. #if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
  1181. // Zygote needs to call InitCrashReporter() in RunZygote().
  1182. if (process_type != switches::kZygoteProcess) {
  1183. if (command_line.HasSwitch(switches::kPreCrashpadCrashTest)) {
  1184. // Crash for the purposes of testing the handling of crashes that happen
  1185. // before crashpad is initialized. Please leave this check immediately
  1186. // before the crashpad initialization; the amount of memory used at this
  1187. // point is important to the test.
  1188. IMMEDIATE_CRASH();
  1189. }
  1190. #if BUILDFLAG(IS_ANDROID)
  1191. crash_reporter::InitializeCrashpad(process_type.empty(), process_type);
  1192. if (process_type.empty()) {
  1193. base::android::InitJavaExceptionReporter();
  1194. UninstallPureJavaExceptionHandler();
  1195. } else {
  1196. base::android::InitJavaExceptionReporterForChildProcess();
  1197. }
  1198. #else // !BUILDFLAG(IS_ANDROID)
  1199. if (crash_reporter::IsCrashpadEnabled()) {
  1200. crash_reporter::InitializeCrashpad(process_type.empty(), process_type);
  1201. crash_reporter::SetFirstChanceExceptionHandler(
  1202. v8::TryHandleWebAssemblyTrapPosix);
  1203. } else {
  1204. breakpad::InitCrashReporter(process_type);
  1205. }
  1206. #endif // BUILDFLAG(IS_ANDROID)
  1207. }
  1208. #endif // BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
  1209. #if BUILDFLAG(IS_ANDROID)
  1210. CHECK_EQ(base::android::GetLibraryProcessType(),
  1211. process_type.empty() ? base::android::PROCESS_BROWSER
  1212. : base::android::PROCESS_CHILD);
  1213. #endif // BUILDFLAG(IS_ANDROID)
  1214. // After all the platform Breakpads have been initialized, store the command
  1215. // line for crash reporting.
  1216. crash_keys::SetCrashKeysFromCommandLine(command_line);
  1217. #if BUILDFLAG(ENABLE_PDF)
  1218. MaybePatchGdiGetFontData();
  1219. #endif
  1220. }
  1221. void ChromeMainDelegate::SandboxInitialized(const std::string& process_type) {
  1222. // Note: If you are adding a new process type below, be sure to adjust the
  1223. // AdjustLinuxOOMScore function too.
  1224. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  1225. AdjustLinuxOOMScore(process_type);
  1226. #endif
  1227. #if BUILDFLAG(IS_WIN)
  1228. InitLogging(process_type);
  1229. SuppressWindowsErrorDialogs();
  1230. #endif
  1231. #if BUILDFLAG(ENABLE_NACL)
  1232. ChromeContentClient::SetNaClEntryFunctions(nacl_plugin::PPP_GetInterface,
  1233. nacl_plugin::PPP_InitializeModule,
  1234. nacl_plugin::PPP_ShutdownModule);
  1235. #endif
  1236. }
  1237. absl::variant<int, content::MainFunctionParams> ChromeMainDelegate::RunProcess(
  1238. const std::string& process_type,
  1239. content::MainFunctionParams main_function_params) {
  1240. #if BUILDFLAG(IS_ANDROID)
  1241. NOTREACHED(); // Android provides a subclass and shares no code here.
  1242. #else
  1243. static const MainFunction kMainFunctions[] = {
  1244. #if BUILDFLAG(IS_MAC)
  1245. {switches::kRelauncherProcess, mac_relauncher::internal::RelauncherMain},
  1246. #endif
  1247. // This entry is not needed on Linux, where the NaCl loader
  1248. // process is launched via nacl_helper instead.
  1249. #if BUILDFLAG(ENABLE_NACL) && !BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS)
  1250. {switches::kNaClLoaderProcess, NaClMain},
  1251. #else
  1252. {"<invalid>", nullptr}, // To avoid constant array of size 0
  1253. // when NaCl disabled
  1254. #endif
  1255. };
  1256. for (size_t i = 0; i < std::size(kMainFunctions); ++i) {
  1257. if (process_type == kMainFunctions[i].name)
  1258. return kMainFunctions[i].function(std::move(main_function_params));
  1259. }
  1260. #endif // !BUILDFLAG(IS_ANDROID)
  1261. return std::move(main_function_params);
  1262. }
  1263. void ChromeMainDelegate::ProcessExiting(const std::string& process_type) {
  1264. if (SubprocessNeedsResourceBundle(process_type))
  1265. ui::ResourceBundle::CleanupSharedInstance();
  1266. #if !BUILDFLAG(IS_ANDROID)
  1267. logging::CleanupChromeLogging();
  1268. #else
  1269. // Android doesn't use InitChromeLogging, so we close the log file manually.
  1270. logging::CloseLogFile();
  1271. #endif // !BUILDFLAG(IS_ANDROID)
  1272. }
  1273. #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  1274. void ChromeMainDelegate::ZygoteStarting(
  1275. std::vector<std::unique_ptr<content::ZygoteForkDelegate>>* delegates) {
  1276. #if BUILDFLAG(IS_CHROMEOS_ASH)
  1277. chromeos::InitHugepagesAndMlockSelf();
  1278. #endif
  1279. #if BUILDFLAG(ENABLE_NACL)
  1280. nacl::AddNaClZygoteForkDelegates(delegates);
  1281. #endif
  1282. }
  1283. void ChromeMainDelegate::ZygoteForked() {
  1284. content::Profiling::ProcessStarted();
  1285. if (content::Profiling::BeingProfiled()) {
  1286. base::debug::RestartProfilingAfterFork();
  1287. SetUpProfilingShutdownHandler();
  1288. }
  1289. // Needs to be called after we have chrome::DIR_USER_DATA. BrowserMain sets
  1290. // this up for the browser process in a different manner.
  1291. const base::CommandLine* command_line =
  1292. base::CommandLine::ForCurrentProcess();
  1293. std::string process_type =
  1294. command_line->GetSwitchValueASCII(switches::kProcessType);
  1295. if (crash_reporter::IsCrashpadEnabled()) {
  1296. crash_reporter::InitializeCrashpad(false, process_type);
  1297. crash_reporter::SetFirstChanceExceptionHandler(
  1298. v8::TryHandleWebAssemblyTrapPosix);
  1299. } else {
  1300. breakpad::InitCrashReporter(process_type);
  1301. }
  1302. // Reset the command line for the newly spawned process.
  1303. crash_keys::SetCrashKeysFromCommandLine(*command_line);
  1304. }
  1305. #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
  1306. content::ContentClient* ChromeMainDelegate::CreateContentClient() {
  1307. return &chrome_content_client_;
  1308. }
  1309. content::ContentBrowserClient*
  1310. ChromeMainDelegate::CreateContentBrowserClient() {
  1311. chrome_content_browser_client_ =
  1312. std::make_unique<ChromeContentBrowserClient>();
  1313. return chrome_content_browser_client_.get();
  1314. }
  1315. content::ContentGpuClient* ChromeMainDelegate::CreateContentGpuClient() {
  1316. return g_chrome_content_gpu_client.Pointer();
  1317. }
  1318. content::ContentRendererClient*
  1319. ChromeMainDelegate::CreateContentRendererClient() {
  1320. return g_chrome_content_renderer_client.Pointer();
  1321. }
  1322. content::ContentUtilityClient*
  1323. ChromeMainDelegate::CreateContentUtilityClient() {
  1324. chrome_content_utility_client_ =
  1325. std::make_unique<ChromeContentUtilityClient>();
  1326. return chrome_content_utility_client_.get();
  1327. }
  1328. absl::optional<int> ChromeMainDelegate::PreBrowserMain() {
  1329. #if BUILDFLAG(ENABLE_EXTENSIONS)
  1330. const base::CommandLine& command_line =
  1331. *base::CommandLine::ForCurrentProcess();
  1332. absl::optional<int> pack_extension_exit_code =
  1333. HandlePackExtensionSwitches(command_line);
  1334. if (pack_extension_exit_code.has_value())
  1335. return pack_extension_exit_code; // Got a --pack-extension switch; exit.
  1336. #endif
  1337. #if BUILDFLAG(IS_MAC)
  1338. // Tell Cocoa to finish its initialization, which we want to do manually
  1339. // instead of calling NSApplicationMain(). The primary reason is that NSAM()
  1340. // never returns, which would leave all the objects currently on the stack
  1341. // in scoped_ptrs hanging and never cleaned up. We then load the main nib
  1342. // directly. The main event loop is run from common code using the
  1343. // MessageLoop API, which works out ok for us because it's a wrapper around
  1344. // CFRunLoop.
  1345. // Initialize NSApplication using the custom subclass.
  1346. chrome_browser_application_mac::RegisterBrowserCrApp();
  1347. if (l10n_util::GetLocaleOverride().empty()) {
  1348. // The browser process only wants to support the language Cocoa will use,
  1349. // so force the app locale to be overridden with that value. This must
  1350. // happen before the ResourceBundle is loaded, which happens in
  1351. // ChromeBrowserMainParts::PreEarlyInitialization().
  1352. // Don't do this if the locale is already set, which is done by integration
  1353. // tests to ensure tests always run with the same locale.
  1354. l10n_util::OverrideLocaleWithCocoaLocale();
  1355. }
  1356. #endif
  1357. // Do not interrupt startup.
  1358. return absl::nullopt;
  1359. }