#include "chrome/app/chrome_main_delegate.h"
#include <stddef.h>
#include <string>
#include <variant>
#include "base/base_paths.h"
#include "base/check.h"
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/cpu.h"
#include "base/dcheck_is_on.h"
#include "base/features.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/i18n/rtl.h"
#include "base/immediate_crash.h"
#include "base/lazy_instance.h"
#include "base/metrics/histogram_macros.h"
#include "base/notreached.h"
#include "base/path_service.h"
#include "base/process/memory.h"
#include "base/process/process.h"
#include "base/process/process_handle.h"
#include "base/profiler/thread_group_profiler.h"
#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/thread_pool/thread_pool_instance.h"
#include "base/threading/hang_watcher.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
#include "cef/libcef/features/features.h"
#include "chrome/browser/buildflags.h"
#include "chrome/browser/chrome_content_browser_client.h"
#include "chrome/browser/chrome_resource_bundle_helper.h"
#include "chrome/browser/defaults.h"
#include "chrome/browser/headless/headless_mode_util.h"
#include "chrome/browser/lifetime/browser_shutdown.h"
#include "chrome/browser/metrics/chrome_feature_list_creator.h"
#include "chrome/browser/startup_data.h"
#include "chrome/common/buildflags.h"
#include "chrome/common/channel_info.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_content_client.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_paths_internal.h"
#include "chrome/common/chrome_result_codes.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/crash_keys.h"
#include "chrome/common/logging_chrome.h"
#include "chrome/common/profiler/chrome_thread_group_profiler_client.h"
#include "chrome/common/profiler/chrome_thread_profiler_client.h"
#include "chrome/common/profiler/core_unwinders.h"
#include "chrome/common/profiler/main_thread_stack_sampling_profiler.h"
#include "chrome/common/profiler/process_type.h"
#include "chrome/common/url_constants.h"
#include "chrome/gpu/chrome_content_gpu_client.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/renderer/chrome_content_renderer_client.h"
#include "chrome/utility/chrome_content_utility_client.h"
#include "components/component_updater/component_updater_paths.h"
#include "components/content_settings/core/common/content_settings_pattern.h"
#include "components/crash/core/app/crash_reporter_client.h"
#include "components/crash/core/common/crash_key.h"
#include "components/crash/core/common/crash_keys.h"
#include "components/devtools/devtools_pipe/devtools_pipe.h"
#include "components/memory_system/initializer.h"
#include "components/memory_system/parameters.h"
#include "components/metrics/persistent_histograms.h"
#include "components/sampling_profiler/thread_profiler.h"
#include "components/startup_metric_utils/common/startup_metric_utils.h"
#include "components/version_info/channel.h"
#include "components/version_info/version_info.h"
#include "content/public/app/initialize_mojo_core.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_paths.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/main_function_params.h"
#include "content/public/common/profiling.h"
#include "content/public/common/url_constants.h"
#include "extensions/buildflags/buildflags.h"
#include "net/http/http_cache.h"
#include "net/url_request/url_request.h"
#include "pdf/buildflags.h"
#include "printing/buildflags/buildflags.h"
#include "services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h"
#include "third_party/blink/public/common/features.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/resource/scoped_startup_resource_bundle.h"
#include "ui/base/ui_base_switches.h"
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \
BUILDFLAG(IS_MAC)
#include "components/webapps/isolated_web_apps/scheme.h"
#endif
#if BUILDFLAG(IS_WIN)
#include <malloc.h>
#include <algorithm>
#include "base/base_switches.h"
#include "base/files/important_file_writer_cleaner.h"
#include "base/process/process_handle.h"
#include "base/win/atl.h"
#include "base/win/dark_mode_support.h"
#include "base/win/resource_exhaustion.h"
#include "chrome/browser/chrome_browser_main_win.h"
#include "chrome/browser/win/browser_util.h"
#include "chrome/child/v8_crashpad_support_win.h"
#include "chrome/chrome_elf/chrome_elf_main.h"
#include "chrome/common/chrome_version.h"
#include "sandbox/win/src/sandbox.h"
#include "sandbox/win/src/sandbox_factory.h"
#include "ui/base/resource/resource_bundle_win.h"
#endif
#if BUILDFLAG(IS_MAC)
#include "base/apple/foundation_util.h"
#include "chrome/app/chrome_main_mac.h"
#include "chrome/browser/chrome_browser_application_mac.h"
#include "chrome/browser/mac/code_sign_clone_manager.h"
#include "chrome/browser/mac/relauncher.h"
#include "chrome/browser/shell_integration.h"
#include "components/crash/core/common/objc_zombie.h"
#include "ui/base/l10n/l10n_util_mac.h"
#endif
#if BUILDFLAG(IS_POSIX)
#include <locale.h>
#include <signal.h>
#include "chrome/app/chrome_crash_reporter_client.h"
#include "components/webui/about/credit_utils.h"
#endif
#if BUILDFLAG(IS_CHROMEOS)
#include "ash/constants/ash_paths.h"
#include "ash/constants/ash_switches.h"
#include "base/system/sys_info.h"
#include "chrome/browser/ash/boot_times_recorder/boot_times_recorder.h"
#include "chrome/browser/ash/dbus/ash_dbus_helper.h"
#include "chrome/browser/ash/locale/startup_settings_cache.h"
#include "chrome/browser/ash/schedqos/dbus_schedqos_state_handler.h"
#include "chromeos/ash/components/memory/memory.h"
#include "chromeos/ash/components/memory/mglru.h"
#include "chromeos/ash/experiences/arc/arc_util.h"
#include "chromeos/dbus/constants/dbus_paths.h"
#include "content/public/common/content_features.h"
#endif
#if BUILDFLAG(IS_ANDROID)
#include "base/android/java_exception_reporter.h"
#include "base/android/library_loader/library_loader_hooks.h"
#include "chrome/browser/android/flags/chrome_cached_flags.h"
#include "chrome/browser/android/metrics/uma_session_stats.h"
#include "chrome/browser/flags/android/chrome_feature_list.h"
#include "chrome/common/chrome_descriptors_android.h"
#include "components/crash/android/pure_java_exception_handler.h"
#include "net/android/network_change_notifier_factory_android.h"
#else
#include "chrome/browser/diagnostics/diagnostics_controller.h"
#include "chrome/browser/diagnostics/diagnostics_writer.h"
#endif
#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_ANDROID)
#include "v8/include/v8-wasm-trap-handler-posix.h"
#include "v8/include/v8.h"
#endif
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
#include "base/environment.h"
#endif
#if BUILDFLAG(IS_LINUX)
#include "base/nix/scoped_xdg_activation_token_injector.h"
#include "ui/linux/display_server_utils.h"
#endif
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_ANDROID) || \
BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_OHOS)
#include "chrome/browser/policy/policy_path_parser.h"
#include "components/crash/core/app/crashpad.h"
#endif
#if BUILDFLAG(ENABLE_EXTENSIONS_CORE)
#include "chrome/browser/extensions/startup_helper.h"
#include "extensions/common/constants.h"
#endif
#if BUILDFLAG(ENABLE_PDF)
#include "chrome/child/pdf_child_init.h"
#endif
#if BUILDFLAG(ENABLE_PROCESS_SINGLETON)
#include "chrome/browser/chrome_process_singleton.h"
#include "chrome/browser/process_singleton.h"
#endif
#if BUILDFLAG(IS_OZONE)
#include "ui/ozone/public/ozone_platform.h"
#endif
#if BUILDFLAG(IS_ARKWEB)
#include "arkweb/chromium_ext/chrome/app/chrome_main_delegate_for_include.cc"
#endif
base::LazyInstance<ChromeContentGpuClient>::DestructorAtExit
g_chrome_content_gpu_client = LAZY_INSTANCE_INITIALIZER;
#if BUILDFLAG(IS_ARKWEB)
base::LazyInstance<ArkWebChromeContentRendererClientExt>::DestructorAtExit
#else
base::LazyInstance<ChromeContentRendererClient>::DestructorAtExit
#endif
g_chrome_content_renderer_client = LAZY_INSTANCE_INITIALIZER;
const char* const ChromeMainDelegate::kNonWildcardDomainNonPortSchemes[] = {
#if BUILDFLAG(ENABLE_EXTENSIONS_CORE)
extensions::kExtensionScheme, extensions::kArkwebExtensionScheme,
#endif
chrome::kChromeSearchScheme,
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \
BUILDFLAG(IS_MAC)
webapps::kIsolatedAppScheme,
#endif
content::kChromeDevToolsScheme, content::kChromeUIScheme,
content::kChromeUIUntrustedScheme,
};
const size_t ChromeMainDelegate::kNonWildcardDomainNonPortSchemesSize =
std::size(kNonWildcardDomainNonPortSchemes);
namespace {
#if BUILDFLAG(IS_WIN)
bool HasDeprecatedArguments(const std::wstring& command_line) {
const wchar_t kChromeHtml[] = L"chromehtml:";
std::wstring command_line_lower = base::ToLowerASCII(command_line);
return (command_line_lower.find(kChromeHtml) != std::wstring::npos);
}
void SuppressWindowsErrorDialogs() {
UINT new_flags = SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX;
UINT existing_flags = SetErrorMode(new_flags);
SetErrorMode(existing_flags | new_flags);
}
bool IsSandboxedProcess() {
typedef bool (*IsSandboxedProcessFunc)();
IsSandboxedProcessFunc is_sandboxed_process_func =
reinterpret_cast<IsSandboxedProcessFunc>(
GetProcAddress(GetModuleHandle(NULL), "IsSandboxedProcess"));
return is_sandboxed_process_func && is_sandboxed_process_func();
}
#endif
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
void AdjustLinuxOOMScore(const std::string& process_type) {
int score = -1;
if (process_type == switches::kUtilityProcess ||
process_type == switches::kGpuProcess) {
score = content::kMiscOomScore;
} else if (process_type == switches::kZygoteProcess || process_type.empty()) {
score = content::kZygoteOomScore;
} else if (process_type == switches::kRendererProcess) {
LOG(WARNING) << "process type 'renderer' "
<< "should be created through the zygote.";
score = content::kLowestRendererOomScore;
} else {
NOTREACHED() << "Unknown process type";
}
if (score > -1)
base::AdjustOOMScore(base::GetCurrentProcId(), score);
}
#endif
bool SubprocessNeedsResourceBundle(const std::string& process_type) {
return
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
process_type == switches::kZygoteProcess ||
#endif
#if BUILDFLAG(IS_MAC)
process_type == switches::kGpuProcess ||
#endif
process_type == switches::kRendererProcess ||
process_type == switches::kUtilityProcess;
}
#if BUILDFLAG(IS_POSIX)
bool HandleCreditsSwitch(const base::CommandLine& command_line) {
if (!command_line.HasSwitch(switches::kCredits))
return false;
base::FilePath resource_dir;
bool result = base::PathService::Get(base::DIR_ASSETS, &resource_dir);
DUMP_WILL_BE_CHECK(result);
ui::ScopedStartupResourceBundle ensure_startup_resource_bundle;
base::FilePath resources_pak =
resource_dir.Append(FILE_PATH_LITERAL("resources.pak"));
#if BUILDFLAG(IS_MAC) && !defined(COMPONENT_BUILD)
if (!base::PathExists(resources_pak)) {
resources_pak =
resource_dir.Append(FILE_PATH_LITERAL("Resources/resources.pak"));
}
#endif
ui::ResourceBundle::GetSharedInstance().AddDataPackFromPath(
resources_pak, ui::kScaleFactorNone);
auto credits = about_ui::GetCredits(false);
size_t resource_loading_threshold = 100;
if (credits.size() < resource_loading_threshold)
printf("%s\n", "Failed to load credits.");
else
printf("%s\n", credits.c_str());
return true;
}
bool HandleVersionSwitches(const base::CommandLine& command_line) {
#if !BUILDFLAG(IS_MAC)
if (command_line.HasSwitch(switches::kProductVersion)) {
UNSAFE_TODO(printf("%s\n", version_info::GetVersionNumber().data()));
return true;
}
#endif
if (command_line.HasSwitch(switches::kVersion)) {
UNSAFE_TODO(printf(
"%s %s %s\n", version_info::GetProductName().data(),
version_info::GetVersionNumber().data(),
chrome::GetChannelName(chrome::WithExtendedStable(true)).c_str()));
return true;
}
return false;
}
#if BUILDFLAG(IS_LINUX)
void HandleHelpSwitches(const base::CommandLine& command_line) {
if (command_line.HasSwitch(switches::kHelp) ||
command_line.HasSwitch(switches::kHelpShort)) {
base::FilePath binary(command_line.argv()[0]);
execlp("man", "man", binary.BaseName().value().c_str(), NULL);
PLOG(FATAL) << "execlp failed";
}
}
#endif
#if !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_OHOS)
void SIGTERMProfilingShutdown(int signal) {
content::Profiling::Stop();
struct sigaction sigact;
UNSAFE_TODO(memset(&sigact, 0, sizeof(sigact)));
sigact.sa_handler = SIG_DFL;
CHECK_EQ(sigaction(SIGTERM, &sigact, nullptr), 0);
raise(signal);
}
void SetUpProfilingShutdownHandler() {
struct sigaction sigact;
sigact.sa_handler = SIGTERMProfilingShutdown;
sigact.sa_flags = SA_RESETHAND;
sigemptyset(&sigact.sa_mask);
CHECK_EQ(sigaction(SIGTERM, &sigact, nullptr), 0);
}
#endif
#endif
bool WillExitBeforeBrowserFeatureListInitialization() {
#if BUILDFLAG(ENABLE_EXTENSIONS)
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
CHECK_EQ("", command_line->GetSwitchValueASCII(switches::kProcessType))
<< "This should only be invoked in the browser process.";
if (command_line->HasSwitch(switches::kPackExtension)) {
return true;
}
#endif
return false;
}
#if BUILDFLAG(ENABLE_EXTENSIONS)
std::optional<int> HandlePackExtensionSwitches(
const base::CommandLine& command_line) {
if (!command_line.HasSwitch(switches::kPackExtension))
return std::nullopt;
CHECK(WillExitBeforeBrowserFeatureListInitialization());
CHECK(base::FeatureList::GetInstance());
ui::ScopedStartupResourceBundle ensure_startup_resource_bundle;
extensions::StartupHelper extension_startup_helper;
std::string error_message;
if (!extension_startup_helper.PackExtension(command_line, &error_message)) {
if (!error_message.empty()) {
LOG(ERROR) << error_message.c_str();
}
return CHROME_RESULT_CODE_PACK_EXTENSION_ERROR;
}
return CHROME_RESULT_CODE_NORMAL_EXIT_PACK_EXTENSION_SUCCESS;
}
#endif
#if BUILDFLAG(ENABLE_PROCESS_SINGLETON)
std::optional<int> AcquireProcessSingleton(
const base::FilePath& user_data_dir) {
ChromeProcessSingleton::CreateInstance(user_data_dir);
#if BUILDFLAG(IS_LINUX)
base::nix::ScopedXdgActivationTokenInjector activation_token_injector(
*base::CommandLine::ForCurrentProcess(), *base::Environment::Create());
#endif
ProcessSingleton::NotifyResult notify_result =
ChromeProcessSingleton::GetInstance()->NotifyOtherProcessOrCreate();
UMA_HISTOGRAM_ENUMERATION("Chrome.ProcessSingleton.NotifyResult",
notify_result, ProcessSingleton::kNumNotifyResults);
switch (notify_result) {
case ProcessSingleton::PROCESS_NONE:
break;
case ProcessSingleton::PROCESS_NOTIFIED: {
ui::ScopedStartupResourceBundle startup_resource_bundle;
printf("%s\n", base::SysWideToNativeMB(
base::UTF16ToWide(l10n_util::GetStringUTF16(
IDS_USED_EXISTING_BROWSER)))
.c_str());
return CHROME_RESULT_CODE_NORMAL_EXIT_PROCESS_NOTIFIED;
}
case ProcessSingleton::PROFILE_IN_USE:
return CHROME_RESULT_CODE_PROFILE_IN_USE;
case ProcessSingleton::LOCK_ERROR:
LOG(ERROR) << "Failed to create a ProcessSingleton for your profile "
"directory. This means that running multiple instances "
"would start multiple browser processes rather than "
"opening a new window in the existing process. Aborting "
"now to avoid profile corruption.";
return CHROME_RESULT_CODE_PROFILE_IN_USE;
}
return std::nullopt;
}
#endif
struct MainFunction {
const char* name;
int (*function)(content::MainFunctionParams);
};
void InitializeUserDataDir(base::CommandLine* command_line) {
#if BUILDFLAG(IS_WIN)
wchar_t user_data_dir_buf[MAX_PATH], invalid_user_data_dir_buf[MAX_PATH];
if (GetUserDataDirectoryThunk(user_data_dir_buf, std::size(user_data_dir_buf),
invalid_user_data_dir_buf,
std::size(invalid_user_data_dir_buf))) {
base::FilePath user_data_dir(user_data_dir_buf);
if (invalid_user_data_dir_buf[0] != 0) {
chrome::SetInvalidSpecifiedUserDataDir(
base::FilePath(invalid_user_data_dir_buf));
command_line->AppendSwitchPath(switches::kUserDataDir, user_data_dir);
}
CHECK(base::PathService::OverrideAndCreateIfNeeded(
chrome::DIR_USER_DATA, user_data_dir, false, true));
}
#else
base::FilePath user_data_dir =
command_line->GetSwitchValuePath(switches::kUserDataDir);
std::string process_type =
command_line->GetSwitchValueASCII(switches::kProcessType);
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
if (user_data_dir.empty()) {
std::unique_ptr<base::Environment> environment(base::Environment::Create());
std::optional<std::string> user_data_dir_string =
environment->GetVar("CHROME_USER_DATA_DIR");
if (user_data_dir_string.has_value() &&
base::IsStringUTF8(user_data_dir_string.value())) {
user_data_dir =
base::FilePath::FromUTF8Unsafe(user_data_dir_string.value());
}
}
#endif
#if BUILDFLAG(IS_MAC)
policy::path_parser::CheckUserDataDirPolicy(&user_data_dir);
#endif
#if BUILDFLAG(IS_ARKWEB)
const bool specified_directory_was_invalid = SetUserDataDirForArkweb(user_data_dir);
#else
const bool specified_directory_was_invalid =
!user_data_dir.empty() &&
!base::PathService::OverrideAndCreateIfNeeded(chrome::DIR_USER_DATA,
user_data_dir, false, true);
#endif
if (specified_directory_was_invalid)
chrome::SetInvalidSpecifiedUserDataDir(user_data_dir);
if (!base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) {
if (!specified_directory_was_invalid) {
if (user_data_dir.empty())
chrome::GetDefaultUserDataDirectory(&user_data_dir);
chrome::SetInvalidSpecifiedUserDataDir(user_data_dir);
}
}
if (specified_directory_was_invalid)
command_line->AppendSwitchPath(switches::kUserDataDir, user_data_dir);
#if BUILDFLAG(IS_CHROMEOS)
CHECK(base::PathService::OverrideAndCreateIfNeeded(
ash::DIR_USER_DATA, user_data_dir, false, false));
#endif
#endif
}
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_OHOS)
void InitLogging(const std::string& process_type) {
logging::OldFileDeletionState file_state = logging::APPEND_TO_OLD_LOG_FILE;
if (process_type.empty()) {
file_state = logging::DELETE_OLD_LOG_FILE;
}
const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
logging::InitChromeLogging(command_line, file_state);
#if BUILDFLAG(IS_CHROMEOS)
if (process_type.empty()) {
LOG(WARNING) << "This is Chrome version " << chrome::kChromeVersion
<< " (not a warning)";
}
#endif
}
#endif
void RecordMainStartupMetrics(const StartupTimestamps& timestamps) {
const base::TimeTicks now = base::TimeTicks::Now();
#if BUILDFLAG(IS_WIN)
startup_metric_utils::GetCommon().RecordPreReadTime(
timestamps.preread_begin_ticks, timestamps.preread_end_ticks);
#endif
#if !BUILDFLAG(IS_ANDROID)
CHECK(!timestamps.exe_entry_point_ticks.is_null());
startup_metric_utils::GetCommon().RecordApplicationStartTime(
timestamps.exe_entry_point_ticks);
#endif
#if BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || \
BUILDFLAG(IS_CHROMEOS)
startup_metric_utils::GetCommon().RecordStartupProcessCreationTime(
base::Process::Current().CreationTime());
#endif
startup_metric_utils::GetCommon().RecordChromeMainEntryTime(now);
}
#if BUILDFLAG(IS_WIN)
constexpr wchar_t kOnResourceExhaustedMessage[] =
L"Your computer has run out of resources and cannot start "
PRODUCT_SHORTNAME_STRING
L". Sign out of Windows or restart your computer and try again.";
void OnResourceExhausted() {
if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kNoErrorDialogs)) {
static constexpr wchar_t kMessageBoxTitle[] = L"System resource exhausted";
::MessageBox(nullptr, kOnResourceExhaustedMessage, kMessageBoxTitle, MB_OK);
}
base::Process::TerminateCurrentProcessImmediately(
CHROME_RESULT_CODE_SYSTEM_RESOURCE_EXHAUSTED);
}
void OnResourceExhaustedForHeadless() {
LOG(ERROR) << kOnResourceExhaustedMessage;
base::Process::TerminateCurrentProcessImmediately(EXIT_FAILURE);
}
#endif
bool IsCanaryDev() {
const auto channel = chrome::GetChannel();
return channel == version_info::Channel::CANARY ||
channel == version_info::Channel::DEV;
}
}
#if BUILDFLAG(IS_ANDROID)
ChromeMainDelegate::ChromeMainDelegate()
: ChromeMainDelegate(StartupTimestamps{}) {}
#endif
ChromeMainDelegate::ChromeMainDelegate(const StartupTimestamps& timestamps) {
RecordMainStartupMetrics(timestamps);
}
#if !BUILDFLAG(IS_ANDROID)
ChromeMainDelegate::~ChromeMainDelegate() {
std::string process_type =
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kProcessType);
const bool is_browser_process = process_type.empty();
if (is_browser_process)
browser_shutdown::RecordShutdownMetrics();
}
#else
ChromeMainDelegate::~ChromeMainDelegate() = default;
#endif
void ChromeMainDelegate::CleanupOnUIThread() {
memory_system_.reset();
}
std::optional<int> ChromeMainDelegate::PostEarlyInitialization(
InvokedIn invoked_in) {
DUMP_WILL_BE_CHECK(base::ThreadPoolInstance::Get());
const auto* invoked_in_browser =
std::get_if<InvokedInBrowserProcess>(&invoked_in);
if (!invoked_in_browser) {
CommonEarlyInitialization();
return std::nullopt;
}
#if BUILDFLAG(ENABLE_PROCESS_SINGLETON)
base::FilePath user_data_dir =
base::PathService::CheckedGet(chrome::DIR_USER_DATA);
if (auto process_singleton_result = AcquireProcessSingleton(user_data_dir);
process_singleton_result.has_value()) {
DeferBrowserMetrics(user_data_dir);
#if BUILDFLAG(IS_WIN) && !BUILDFLAG(ENABLE_CEF)
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kUninstall)) {
ui::ScopedStartupResourceBundle startup_resource_bundle;
return DoUninstallTasks(browser_util::IsBrowserAlreadyRunning());
}
#endif
return process_singleton_result;
}
#endif
#if BUILDFLAG(IS_WIN)
base::ImportantFileWriterCleaner::GetInstance().Initialize();
base::win::AllowDarkModeForApp(true);
#endif
base::FilePath metrics_dir;
if (base::PathService::Get(chrome::DIR_USER_DATA, &metrics_dir)) {
PersistentHistogramsCleanup(metrics_dir);
}
net::URLRequest::SetDefaultCookiePolicyToBlock();
#if BUILDFLAG(IS_CHROMEOS)
ash::InitializeDBus();
#endif
ChromeFeatureListCreator* chrome_feature_list_creator =
chrome_content_browser_client_->startup_data()
->chrome_feature_list_creator();
chrome_feature_list_creator->CreateFeatureList();
#if BUILDFLAG(IS_OZONE)
#if BUILDFLAG(IS_LINUX)
ui::SetOzonePlatformForLinuxIfNeeded(*base::CommandLine::ForCurrentProcess());
#endif
ui::OzonePlatform::PreEarlyInitialization();
#endif
content::InitializeMojoCore();
#if BUILDFLAG(IS_CHROMEOS)
if (base::FeatureList::IsEnabled(features::kSchedQoSOnResourcedForChrome)) {
ash::DBusSchedQOSStateHandler::Create(
base::SequencedTaskRunner::GetCurrentDefault());
base::Process::Current().InitializePriority();
}
#endif
#if BUILDFLAG(IS_WIN)
ChromeProcessSingleton::GetInstance()
->ChromeProcessSingleton::InitializeFeatures();
#endif
CommonEarlyInitialization();
std::string actual_locale = LoadLocalState(
chrome_feature_list_creator, GetResourceBundleDelegate(),
invoked_in_browser->is_running_test);
chrome_feature_list_creator->SetApplicationLocale(actual_locale);
#if !BUILDFLAG(IS_OHOS)
chrome_feature_list_creator->OverrideCachedUIStrings();
#endif
#if BUILDFLAG(IS_CHROMEOS)
ash::InitializeFeatureListDependentDBus();
#endif
#if BUILDFLAG(IS_ANDROID)
chrome_content_browser_client_->startup_data()->InitProfileKey();
net::NetworkChangeNotifier::SetFactory(
new net::NetworkChangeNotifierFactoryAndroid());
#endif
#if !BUILDFLAG(ENABLE_CEF)
bool record = true;
#if BUILDFLAG(IS_ANDROID)
record =
base::FeatureList::IsEnabled(chrome::android::kUmaBackgroundSessions);
#endif
if (record) {
chrome_content_browser_client_->startup_data()->RecordCoreSystemProfile();
}
#endif
#if BUILDFLAG(IS_ANDROID)
UmaSessionStats::OnStartup();
#endif
#if BUILDFLAG(IS_MAC)
chrome::CacheChannelInfo();
#endif
RequestUnwindPrerequisitesInstallation(chrome::GetChannel());
return std::nullopt;
}
bool ChromeMainDelegate::ShouldCreateFeatureList(InvokedIn invoked_in) {
if (std::holds_alternative<InvokedInChildProcess>(invoked_in)) {
return true;
}
return WillExitBeforeBrowserFeatureListInitialization();
}
bool ChromeMainDelegate::ShouldInitializeMojo(InvokedIn invoked_in) {
return ShouldCreateFeatureList(invoked_in);
}
void ChromeMainDelegate::CreateThreadPool(std::string_view name) {
base::ThreadGroupProfiler::SetClient(
std::make_unique<ChromeThreadGroupProfilerClient>());
base::ThreadPoolInstance::Create(name);
sampling_profiler::ThreadProfiler::SetClient(
std::make_unique<ChromeThreadProfilerClient>());
#if !BUILDFLAG(IS_ANDROID)
sampling_profiler_ = std::make_unique<MainThreadStackSamplingProfiler>();
#endif
}
void ChromeMainDelegate::CommonEarlyInitialization() {
const base::CommandLine* const command_line =
base::CommandLine::ForCurrentProcess();
std::string process_type =
command_line->GetSwitchValueASCII(switches::kProcessType);
bool is_browser_process = process_type.empty();
#if BUILDFLAG(IS_WIN)
if (base::FeatureList::IsEnabled(features::kDisableBoostPriority) &&
features::kDisableBoostPriorityMode.Get() ==
features::DisableBoostPriorityMode::kAtStartup) {
SetProcessPriorityBoost(base::GetCurrentProcessHandle(),
true);
}
#endif
#if !BUILDFLAG(IS_ARKWEB)
net::HttpCache::SplitCacheFeatureEnableByDefault();
#endif
net::NetworkAnonymizationKey::PartitionByDefault();
InitializeMemorySystem();
if (is_browser_process) {
#if BUILDFLAG(IS_CHROMEOS)
ash::InitializeMGLRU();
ash::LockMainProgramText();
#endif
}
base::HangWatcher::ProcessType hang_watcher_process_type;
if (process_type.empty()) {
hang_watcher_process_type = base::HangWatcher::ProcessType::kBrowserProcess;
} else if (process_type == switches::kGpuProcess) {
hang_watcher_process_type = base::HangWatcher::ProcessType::kGPUProcess;
} else if (process_type == switches::kRendererProcess) {
hang_watcher_process_type =
base::HangWatcher::ProcessType::kRendererProcess;
} else if (process_type == switches::kUtilityProcess) {
hang_watcher_process_type = base::HangWatcher::ProcessType::kUtilityProcess;
} else {
hang_watcher_process_type = base::HangWatcher::ProcessType::kUnknownProcess;
}
const bool emit_crashes =
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_MAC) || \
BUILDFLAG(IS_WIN)
IsCanaryDev();
#else
false;
#endif
base::HangWatcher::InitializeOnMainThread(hang_watcher_process_type,
emit_crashes);
base::features::Init();
}
#if BUILDFLAG(IS_WIN)
bool ChromeMainDelegate::ShouldHandleConsoleControlEvents() {
return true;
}
#endif
void ChromeMainDelegate::SetupTracing() {
tracing_sampler_profiler_.reset();
#if BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX)
if (base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kProcessType) == switches::kZygoteProcess) {
return;
}
#endif
base::RepeatingCallback tracing_factory =
base::BindRepeating(&CreateCoreUnwindersFactory);
tracing::TracingSamplerProfiler::UnwinderType unwinder_type =
tracing::TracingSamplerProfiler::UnwinderType::kCustomAndroid;
#if BUILDFLAG(IS_ANDROID)
if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kProcessType) &&
chrome::android::IsJavaDrivenFeatureEnabled(
chrome::android::kUseLibunwindstackNativeUnwinderAndroid)) {
tracing_factory = base::BindRepeating(&CreateLibunwindstackUnwinderFactory);
unwinder_type = tracing::TracingSamplerProfiler::UnwinderType::
kLibunwindstackUnwinderAndroid;
}
#endif
tracing_sampler_profiler_ =
tracing::TracingSamplerProfiler::CreateOnMainThread(
std::move(tracing_factory), unwinder_type);
}
std::optional<int> ChromeMainDelegate::BasicStartupComplete() {
#if BUILDFLAG(IS_CHROMEOS)
ash::BootTimesRecorder::Get()->SaveChromeMainStats();
#endif
const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
if (command_line.HasSwitch(switches::kDisableWebSecurity)) {
base::FilePath default_user_data_dir;
chrome::GetDefaultUserDataDirectory(&default_user_data_dir);
const base::FilePath specified_user_data_dir =
command_line.GetSwitchValuePath(switches::kUserDataDir)
.StripTrailingSeparators();
if (specified_user_data_dir.empty() ||
specified_user_data_dir == default_user_data_dir) {
LOG(ERROR) << "Web security may only be disabled if '--user-data-dir' is "
"also specified with a non-default value.";
base::CommandLine::ForCurrentProcess()->RemoveSwitch(
switches::kDisableWebSecurity);
}
}
const bool is_browser = !command_line.HasSwitch(switches::kProcessType);
#if BUILDFLAG(IS_WIN)
const bool pipes_are_specified_explicitly =
command_line.HasSwitch(::switches::kRemoteDebuggingIoPipes);
#else
const bool pipes_are_specified_explicitly = false;
#endif
if (is_browser && command_line.HasSwitch(::switches::kRemoteDebuggingPipe) &&
!pipes_are_specified_explicitly &&
!devtools_pipe::AreFileDescriptorsOpen()) {
LOG(ERROR) << "Remote debugging pipe file descriptors are not open.";
return CHROME_RESULT_CODE_UNSUPPORTED_PARAM;
}
#if BUILDFLAG(IS_WIN)
if (is_browser && IsSandboxedProcess()) {
return CHROME_RESULT_CODE_INVALID_SANDBOX_STATE;
}
#endif
#if BUILDFLAG(IS_MAC)
ObjcEvilDoers::ZombieEnable(true, is_browser ? 10000 : 1000);
#endif
content::Profiling::ProcessStarted();
#if !BUILDFLAG(IS_OHOS)
SetupTracing();
#endif
#if BUILDFLAG(IS_WIN)
v8_crashpad_support::SetUp();
#endif
#if BUILDFLAG(IS_POSIX)
if (HandleVersionSwitches(command_line)) {
return 0;
}
if (HandleCreditsSwitch(command_line)) {
return 0;
}
#if BUILDFLAG(IS_LINUX)
HandleHelpSwitches(command_line);
#endif
#endif
#if BUILDFLAG(IS_WIN)
if (HasDeprecatedArguments(command_line.GetCommandLineString())) {
return 1;
}
#if !DCHECK_IS_ON()
base::win::DisableHandleVerifier();
#endif
#endif
chrome::RegisterPathProvider();
#if BUILDFLAG(IS_CHROMEOS)
ash::RegisterPathProvider();
chromeos::dbus_paths::RegisterPathProvider();
#endif
ContentSettingsPattern::SetNonWildcardDomainNonPortSchemes(
kNonWildcardDomainNonPortSchemes, kNonWildcardDomainNonPortSchemesSize);
#if !BUILDFLAG(IS_ANDROID)
if (command_line.HasSwitch(switches::kDiagnostics)) {
diagnostics::DiagnosticsWriter::FormatType format =
diagnostics::DiagnosticsWriter::HUMAN;
if (command_line.HasSwitch(switches::kDiagnosticsFormat)) {
std::string format_str =
command_line.GetSwitchValueASCII(switches::kDiagnosticsFormat);
if (format_str == "machine") {
format = diagnostics::DiagnosticsWriter::MACHINE;
} else if (format_str == "log") {
format = diagnostics::DiagnosticsWriter::LOG;
} else {
DUMP_WILL_BE_CHECK_EQ("human", format_str);
}
}
diagnostics::DiagnosticsWriter writer(format);
int exit_code = diagnostics::DiagnosticsController::GetInstance()->Run(
command_line, &writer);
diagnostics::DiagnosticsController::GetInstance()->ClearResults();
return exit_code;
}
#endif
#if BUILDFLAG(IS_CHROMEOS)
base::FilePath homedir;
if (command_line.HasSwitch(ash::switches::kHomedir)) {
homedir = base::FilePath(
command_line.GetSwitchValueASCII(ash::switches::kHomedir));
base::PathService::OverrideAndCreateIfNeeded(base::DIR_HOME, homedir, true,
false);
}
if ((base::SysInfo::IsRunningOnChromeOS() &&
command_line.HasSwitch(ash::switches::kLoginUser)) ||
command_line.HasSwitch(switches::kDiagnosticsRecovery)) {
base::CommandLine interim_command_line(command_line.GetProgram());
const char* const kSwitchNames[] = {
switches::kUserDataDir,
};
interim_command_line.CopySwitchesFrom(command_line, kSwitchNames);
interim_command_line.AppendSwitch(switches::kDiagnostics);
interim_command_line.AppendSwitch(switches::kDiagnosticsRecovery);
diagnostics::DiagnosticsWriter::FormatType format =
diagnostics::DiagnosticsWriter::LOG;
if (command_line.HasSwitch(switches::kDiagnosticsFormat)) {
std::string format_str =
command_line.GetSwitchValueASCII(switches::kDiagnosticsFormat);
if (format_str == "machine") {
format = diagnostics::DiagnosticsWriter::MACHINE;
} else if (format_str == "human") {
format = diagnostics::DiagnosticsWriter::HUMAN;
} else {
DUMP_WILL_BE_CHECK_EQ("log", format_str);
}
}
diagnostics::DiagnosticsWriter writer(format);
int diagnostics_exit_code =
diagnostics::DiagnosticsController::GetInstance()->Run(command_line,
&writer);
if (diagnostics_exit_code) {
return diagnostics_exit_code;
}
int recovery_exit_code =
diagnostics::DiagnosticsController::GetInstance()->RunRecovery(
command_line, &writer);
if (recovery_exit_code) {
return recovery_exit_code;
}
}
#endif
return std::nullopt;
}
#if BUILDFLAG(IS_MAC)
void ChromeMainDelegate::InitMacCrashReporter(
const base::CommandLine& command_line,
const std::string& process_type) {
const bool browser_process = process_type.empty();
const bool install_from_dmg_relauncher_process =
process_type == switches::kRelauncherProcess &&
command_line.HasSwitch(switches::kRelauncherProcessDMGDevice);
const bool initial_client =
browser_process || install_from_dmg_relauncher_process;
crash_reporter::InitializeCrashpad(initial_client, process_type);
if (!browser_process) {
std::string metrics_client_id =
command_line.GetSwitchValueASCII(switches::kMetricsClientID);
crash_keys::SetMetricsClientIdFromGUID(metrics_client_id);
}
if (base::apple::IsBackgroundOnlyProcess()) {
CHECK(command_line.HasSwitch(switches::kProcessType) &&
!process_type.empty())
<< "Helper application requires --type.";
} else if (base::apple::AmIBundled()) {
CHECK(!command_line.HasSwitch(switches::kProcessType) &&
process_type.empty())
<< "Main application forbids --type, saw " << process_type;
}
}
void ChromeMainDelegate::SetUpInstallerPreferences(
const base::CommandLine& command_line) {
const bool uma_setting = command_line.HasSwitch(switches::kEnableUserMetrics);
const bool default_browser_setting =
command_line.HasSwitch(switches::kMakeChromeDefault);
if (uma_setting)
crash_reporter::SetUploadConsent(uma_setting);
if (default_browser_setting)
shell_integration::SetAsDefaultBrowser();
}
#endif
void ChromeMainDelegate::PreSandboxStartup() {
const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
std::string process_type =
command_line.GetSwitchValueASCII(switches::kProcessType);
if (false) {
crash_reporter::InitializeCrashKeys();
#if BUILDFLAG(IS_POSIX)
ChromeCrashReporterClient::Create();
#endif
#if BUILDFLAG(IS_MAC)
InitMacCrashReporter(command_line, process_type);
SetUpInstallerPreferences(command_line);
#endif
}
if (chrome::ProcessNeedsProfileDir(process_type)) {
InitializeUserDataDir(base::CommandLine::ForCurrentProcess());
}
component_updater::RegisterPathProvider(chrome::DIR_COMPONENTS,
chrome::DIR_INTERNAL_PLUGINS,
chrome::DIR_USER_DATA);
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_WIN) && !BUILDFLAG(IS_OHOS)
InitLogging(process_type);
#endif
#if BUILDFLAG(IS_WIN)
ui::SetResourcesDataDLL(_AtlBaseModule.GetResourceInstance());
#endif
if (SubprocessNeedsResourceBundle(process_type)) {
DUMP_WILL_BE_CHECK(command_line.HasSwitch(switches::kLang) ||
process_type == switches::kZygoteProcess ||
process_type == switches::kGpuProcess);
std::string locale = command_line.GetSwitchValueASCII(switches::kLang);
#if BUILDFLAG(IS_CHROMEOS)
if (process_type == switches::kZygoteProcess) {
DUMP_WILL_BE_CHECK(locale.empty());
locale = ash::startup_settings_cache::ReadAppLocale();
}
#endif
#if BUILDFLAG(IS_ANDROID)
auto* global_descriptors = base::GlobalDescriptors::GetInstance();
int pak_fd =
global_descriptors->Get(kAndroidMainWebViewLocalePakDescriptor);
base::MemoryMappedFile::Region pak_region =
global_descriptors->GetRegion(kAndroidMainWebViewLocalePakDescriptor);
ui::ResourceBundle::InitSharedInstanceWithPakFileRegion(base::File(pak_fd),
pak_region);
int additional_locale_pak_keys[] = {
kAndroidMainNonWebViewLocalePakDescriptor,
kAndroidFallbackWebViewLocalePakDescriptor,
kAndroidFallbackNonWebViewLocalePakDescriptor,
};
for (int additional_locale_pak_key : additional_locale_pak_keys) {
pak_fd = global_descriptors->MaybeGet(additional_locale_pak_key);
if (pak_fd != -1) {
pak_region = global_descriptors->GetRegion(additional_locale_pak_key);
ui::ResourceBundle::GetSharedInstance()
.LoadAdditionalLocaleDataWithPakFileRegion(base::File(pak_fd),
pak_region);
}
}
struct {
int key;
ui::ResourceScaleFactor scale;
} pak_configs[] = {
{kAndroidChrome100PercentPakDescriptor, ui::k100Percent},
{kAndroidUIResourcesPakDescriptor, ui::k100Percent},
#if BUILDFLAG(ENABLE_HIDPI)
{kAndroidChrome200PercentPakDescriptor, ui::k200Percent},
#endif
};
for (const auto& config : pak_configs) {
pak_fd = global_descriptors->Get(config.key);
pak_region = global_descriptors->GetRegion(config.key);
ui::ResourceBundle::GetSharedInstance().AddDataPackFromFileRegion(
base::File(pak_fd), pak_region, config.scale);
}
base::i18n::SetICUDefaultLocale(locale);
const std::string loaded_locale = locale;
#else
const std::string loaded_locale =
ui::ResourceBundle::InitSharedInstanceWithLocale(
locale, GetResourceBundleDelegate(),
ui::ResourceBundle::LOAD_COMMON_RESOURCES);
base::FilePath resources_pack_path;
base::PathService::Get(chrome::FILE_RESOURCES_PACK, &resources_pack_path);
ui::ResourceBundle::GetSharedInstance().AddDataPackFromPath(
resources_pack_path, ui::kScaleFactorNone);
#endif
CHECK(!loaded_locale.empty()) << "Locale could not be found for " << locale;
}
if (false) {
#if BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_MAC)
if (process_type != switches::kZygoteProcess &&
!command_line.HasSwitch(switches::kDisableCrashpadForTesting)) {
if (command_line.HasSwitch(switches::kPreCrashpadCrashTest)) {
base::ImmediateCrash();
}
#if BUILDFLAG(IS_ANDROID)
crash_reporter::InitializeCrashpad(process_type.empty(), process_type);
if (process_type.empty()) {
base::android::InitJavaExceptionReporter();
UninstallPureJavaExceptionHandler();
} else {
base::android::InitJavaExceptionReporterForChildProcess();
}
#else
crash_reporter::InitializeCrashpad(process_type.empty(), process_type);
#if !defined(__MUSL__)
crash_reporter::SetFirstChanceExceptionHandler(
v8::TryHandleWebAssemblyTrapPosix);
#endif
#endif
}
#endif
#if BUILDFLAG(IS_ANDROID)
CHECK_EQ(base::android::GetLibraryProcessType(),
process_type.empty() ? base::android::PROCESS_BROWSER
: base::android::PROCESS_CHILD);
#endif
crash_keys::SetCrashKeysFromCommandLine(command_line);
}
#if BUILDFLAG(ENABLE_PDF)
MaybePatchGdiGetFontData();
#endif
}
void ChromeMainDelegate::SandboxInitialized(const std::string& process_type) {
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
AdjustLinuxOOMScore(process_type);
#endif
#if BUILDFLAG(IS_WIN)
InitLogging(process_type);
SuppressWindowsErrorDialogs();
#endif
if (process_type.empty() && !headless::IsHeadlessMode()) {
base::FilePath metrics_dir;
if (base::PathService::Get(chrome::DIR_USER_DATA, &metrics_dir)) {
#if !BUILDFLAG(ARKWEB_CRASHPAD)
InstantiatePersistentHistograms(
metrics_dir,
true,
kPersistentHistogramStorageMappedFile);
#endif
} else {
DUMP_WILL_BE_NOTREACHED();
}
}
}
std::variant<int, content::MainFunctionParams> ChromeMainDelegate::RunProcess(
const std::string& process_type,
content::MainFunctionParams main_function_params) {
#if BUILDFLAG(IS_ANDROID)
NOTREACHED();
#else
#if BUILDFLAG(IS_MAC)
static const MainFunction kMainFunctions[] = {
{switches::kRelauncherProcess, mac_relauncher::internal::RelauncherMain},
{switches::kCodeSignCloneCleanupProcess,
code_sign_clone_manager::internal::ChromeCodeSignCloneCleanupMain},
};
for (size_t i = 0; i < std::size(kMainFunctions); ++i) {
if (process_type == UNSAFE_TODO(kMainFunctions[i]).name) {
return UNSAFE_TODO(kMainFunctions[i])
.function(std::move(main_function_params));
}
}
#endif
return std::move(main_function_params);
#endif
}
void ChromeMainDelegate::ProcessExiting(const std::string& process_type) {
if (process_type.empty()) {
browser_shutdown::OnShutdownStarting(
browser_shutdown::ShutdownType::kOtherExit);
}
#if BUILDFLAG(ENABLE_PROCESS_SINGLETON)
ChromeProcessSingleton::DeleteInstance();
#endif
if (SubprocessNeedsResourceBundle(process_type))
ui::ResourceBundle::CleanupSharedInstance();
#if !BUILDFLAG(IS_ANDROID)
logging::CleanupChromeLogging();
#else
logging::CloseLogFile();
#endif
}
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
void ChromeMainDelegate::ZygoteStarting(
std::vector<std::unique_ptr<content::ZygoteForkDelegate>>* delegates) {
}
void ChromeMainDelegate::ZygoteForked() {
SetupTracing();
content::Profiling::ProcessStarted();
if (content::Profiling::BeingProfiled()) {
base::debug::RestartProfilingAfterFork();
SetUpProfilingShutdownHandler();
}
#if !BUILDFLAG(ENABLE_CEF)
const base::CommandLine* command_line =
base::CommandLine::ForCurrentProcess();
std::string process_type =
command_line->GetSwitchValueASCII(switches::kProcessType);
crash_reporter::InitializeCrashpad(false, process_type);
#if !defined(__MUSL__)
crash_reporter::SetFirstChanceExceptionHandler(
v8::TryHandleWebAssemblyTrapPosix);
#endif
crash_keys::SetCrashKeysFromCommandLine(*command_line);
#endif
}
#endif
content::ContentClient* ChromeMainDelegate::CreateContentClient() {
return &chrome_content_client_;
}
content::ContentBrowserClient*
ChromeMainDelegate::CreateContentBrowserClient() {
chrome_content_browser_client_ =
std::make_unique<ChromeContentBrowserClient>();
#if !BUILDFLAG(IS_ANDROID)
CHECK(sampling_profiler_);
chrome_content_browser_client_->SetSamplingProfiler(
std::move(sampling_profiler_));
#endif
return chrome_content_browser_client_.get();
}
content::ContentGpuClient* ChromeMainDelegate::CreateContentGpuClient() {
return g_chrome_content_gpu_client.Pointer();
}
content::ContentRendererClient*
ChromeMainDelegate::CreateContentRendererClient() {
return g_chrome_content_renderer_client.Pointer();
}
content::ContentUtilityClient*
ChromeMainDelegate::CreateContentUtilityClient() {
chrome_content_utility_client_ =
std::make_unique<ChromeContentUtilityClient>();
return chrome_content_utility_client_.get();
}
std::optional<int> ChromeMainDelegate::PreBrowserMain() {
std::optional<int> exit_code = content::ContentMainDelegate::PreBrowserMain();
if (exit_code.has_value())
return exit_code;
#if BUILDFLAG(ENABLE_EXTENSIONS)
const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
std::optional<int> pack_extension_exit_code =
HandlePackExtensionSwitches(command_line);
if (pack_extension_exit_code.has_value())
return pack_extension_exit_code;
#endif
#if BUILDFLAG(IS_MAC)
chrome_browser_application_mac::RegisterBrowserCrApp();
if (l10n_util::GetLocaleOverride().empty()) {
l10n_util::OverrideLocaleWithCocoaLocale();
}
#endif
#if BUILDFLAG(IS_WIN)
base::win::SetOnResourceExhaustedFunction(
headless::IsHeadlessMode() ? &OnResourceExhaustedForHeadless
: &OnResourceExhausted);
if (IsExtensionPointDisableSet()) {
sandbox::SandboxFactory::GetBrokerServices()->SetStartingMitigations(
sandbox::MITIGATION_EXTENSION_POINT_DISABLE);
}
#endif
return std::nullopt;
}
void ChromeMainDelegate::InitializeMemorySystem() {
const base::CommandLine* const command_line =
base::CommandLine::ForCurrentProcess();
const std::string process_type =
command_line->GetSwitchValueASCII(switches::kProcessType);
const bool is_browser_process = process_type.empty();
const bool gwp_asan_boost_sampling = is_browser_process || IsCanaryDev();
const memory_system::DispatcherParameters::AllocationTraceRecorderInclusion
allocation_recorder_inclusion =
is_browser_process ? memory_system::DispatcherParameters::
AllocationTraceRecorderInclusion::kDynamic
: memory_system::DispatcherParameters::
AllocationTraceRecorderInclusion::kIgnore;
memory_system_ = std::make_unique<memory_system::MemorySystem>();
memory_system::Initializer()
.SetGwpAsanParameters(gwp_asan_boost_sampling, process_type)
.SetProfilingClientParameters(chrome::GetChannel(),
GetProfilerProcessType(*command_line))
.SetDispatcherParameters(memory_system::DispatcherParameters::
PoissonAllocationSamplerInclusion::kEnforce,
allocation_recorder_inclusion, process_type)
.Initialize(*memory_system_);
}