chromium/chrome/app/chrome_main_delegate.cc

// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifdef UNSAFE_BUFFERS_BUILD
// TODO(crbug.com/40285824): Remove this and convert code to safer constructs.
#pragma allow_unsafe_buffers
#endif

#include "chrome/app/chrome_main_delegate.h"

#include <stddef.h>

#include <string>

#include "base/base_paths.h"
#include "base/check.h"
#include "base/command_line.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/functional/overloaded.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/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 "base/trace_event/trace_event_impl.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.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/lifetime/browser_shutdown.h"
#include "chrome/browser/mac/code_sign_clone_manager.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/main_thread_stack_sampling_profiler.h"
#include "chrome/common/profiler/process_type.h"
#include "chrome/common/profiler/unwind_util.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/nacl/common/buildflags.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 "ppapi/buildflags/buildflags.h"
#include "printing/buildflags/buildflags.h"
#include "services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h"
#include "third_party/abseil-cpp/absl/types/variant.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)
#include <malloc.h>

#include <algorithm>

#include "base/base_switches.h"
#include "base/files/important_file_writer_cleaner.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/child_process_logging.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/headless/headless_mode_util.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/about_ui/credit_utils.h"
#endif

#if BUILDFLAG(ENABLE_NACL) && (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS))
#include "components/nacl/common/nacl_paths.h"
#include "components/nacl/zygote/nacl_fork_delegate_linux.h"
#endif

#if BUILDFLAG(IS_CHROMEOS)
#include "chromeos/dbus/constants/dbus_paths.h"
#endif

#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "ash/components/arc/arc_util.h"
#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 "content/public/common/content_features.h"
#include "ui/lottie/resource.h"  // nogncheck
#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.h"
#include "components/crash/android/pure_java_exception_handler.h"
#include "net/android/network_change_notifier_factory_android.h"
#else  // BUILDFLAG(IS_ANDROID)
// Diagnostics is only available on non-android platforms.
#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)
#include "chrome/browser/policy/policy_path_parser.h"
#include "components/crash/core/app/crashpad.h"
#endif

#if BUILDFLAG(ENABLE_EXTENSIONS)
#include "chrome/browser/extensions/startup_helper.h"
#include "extensions/common/constants.h"
#endif

#if BUILDFLAG(ENABLE_NACL)
#include "components/nacl/common/nacl_switches.h"
#include "components/nacl/renderer/plugin/ppapi_entrypoints.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  // BUILDFLAG(ENABLE_PROCESS_SINGLETON)

#if BUILDFLAG(IS_CHROMEOS_LACROS)
#include "base/scoped_add_feature_flags.h"
#include "chrome/common/chrome_paths_lacros.h"
#include "chromeos/crosapi/cpp/crosapi_constants.h"  // nogncheck
#include "chromeos/crosapi/mojom/crosapi.mojom.h"    // nogncheck
#include "chromeos/lacros/dbus/lacros_dbus_helper.h"
#include "chromeos/lacros/lacros_paths.h"
#include "chromeos/lacros/lacros_service.h"
#include "chromeos/startup/browser_params_proxy.h"      // nogncheck
#include "chromeos/startup/browser_postlogin_params.h"  // nogncheck
#include "chromeos/startup/startup.h"                   // nogncheck
#include "chromeos/startup/startup_switches.h"          // nogncheck
#include "components/crash/core/app/client_upload_info.h"
#include "content/public/browser/zygote_host/zygote_host_linux.h"
#include "media/base/media_switches.h"
#include "ui/accessibility/accessibility_features.h"
#include "ui/base/resource/data_pack_with_resource_sharing_lacros.h"
#include "ui/base/ui_base_features.h"
#include "ui/gfx/switches.h"
#endif

#if BUILDFLAG(IS_OZONE)
#include "ui/ozone/public/ozone_platform.h"
#endif  // BUILDFLAG(IS_OZONE)

base::LazyInstance<ChromeContentGpuClient>::DestructorAtExit
    g_chrome_content_gpu_client =;
base::LazyInstance<ChromeContentRendererClient>::DestructorAtExit
    g_chrome_content_renderer_client =;

extern int NaClMain(content::MainFunctionParams);

const char* const ChromeMainDelegate::kNonWildcardDomainNonPortSchemes[] =;
const size_t ChromeMainDelegate::kNonWildcardDomainNonPortSchemesSize =;

namespace {

#if BUILDFLAG(IS_CHROMEOS_LACROS)
const base::FilePath::CharType kUserHomeDirPrefix[] =
    FILE_PATH_LITERAL("/home/user");
#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)

#if BUILDFLAG(IS_WIN)
// Early versions of Chrome incorrectly registered a chromehtml: URL handler,
// which gives us nothing but trouble. Avoid launching chrome this way since
// some apps fail to properly escape arguments.
bool HasDeprecatedArguments(const std::wstring& command_line) {
  const wchar_t kChromeHtml[] = L"chromehtml:";
  std::wstring command_line_lower = base::ToLowerASCII(command_line);
  // We are only searching for ASCII characters so this is OK.
  return (command_line_lower.find(kChromeHtml) != std::wstring::npos);
}

// If we try to access a path that is not currently available, we want the call
// to fail rather than show an error dialog.
void SuppressWindowsErrorDialogs() {
  UINT new_flags = SEM_FAILCRITICALERRORS | SEM_NOOPENFILEERRORBOX;

  // Preserve existing error mode.
  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  // BUILDFLAG(IS_WIN)

#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
void AdjustLinuxOOMScore(const std::string& process_type) {}
#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)

// Returns true if this subprocess type needs the ResourceBundle initialized
// and resources loaded.
bool SubprocessNeedsResourceBundle(const std::string& process_type) {}

#if BUILDFLAG(IS_POSIX)
bool HandleCreditsSwitch(const base::CommandLine& command_line) {}

// Check for --version and --product-version; return true if we encountered
// one of these switches and should exit now.
bool HandleVersionSwitches(const base::CommandLine& command_line) {}

// TODO(crbug.com/40118868): Revisit the macro expression once build flag switch
// of lacros-chrome is complete.
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)
// Show the man page if --help or -h is on the command line.
void HandleHelpSwitches(const base::CommandLine& command_line) {}
#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS_LACROS)

#if BUILDFLAG(IS_CHROMEOS_LACROS)
// BrowserManager launches Lacros redirecting its stderr to a log file.
// This function redirects stderr a second time, to another log file, after
// user login has happened (e.g. to the cryptohome).
// Only useful when pre-launching Lacros at login screen.
void RedirectLacrosLogging() {
  const base::CommandLine& cmdline = *base::CommandLine::ForCurrentProcess();
  uint32_t logging_dest = logging::DetermineLoggingDestination(cmdline);
  base::FilePath log_file =
      cmdline.GetSwitchValuePath(chromeos::switches::kCrosPostLoginLogFile);

  if (!log_file.empty() && (logging_dest & logging::LOG_TO_STDERR)) {
    log_file = logging::SetUpLogFile(log_file, /*new_log=*/true);
    FILE* result = freopen(log_file.value().c_str(), "a", stderr);
    DPCHECK(result != nullptr);

    // Redirect Zygote and future children's logs.
    if (result) {
      content::ZygoteHost::GetInstance()->ReinitializeLogging(logging_dest,
                                                              STDERR_FILENO);
    }
  }
}

// When prelaunching Lacros at login screen, the initialization of Crashpad
// relies on the consent preferences of Ash. After login, we can rely on
// the user-specific preferences. This function updates the user consent
// preferences from the default location (the user's cryptohome).
void SetCrashpadUploadConsentPostLogin() {
  crash_reporter::SetUploadConsent(
      crash_reporter::GetClientCollectStatsConsent());
}
#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)

#if !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_ANDROID)
void SIGTERMProfilingShutdown(int signal) {}

void SetUpProfilingShutdownHandler() {}
#endif  // !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_ANDROID)

#endif  // BUILDFLAG(IS_POSIX)

// Returns true if the browser will exit before feature list initialization
// happens in the browser process.
bool WillExitBeforeBrowserFeatureListInitialization() {}

#if BUILDFLAG(ENABLE_EXTENSIONS)
std::optional<int> HandlePackExtensionSwitches(
    const base::CommandLine& command_line) {}
#endif  // !BUILDFLAG(ENABLE_EXTENSIONS)

#if BUILDFLAG(ENABLE_PROCESS_SINGLETON)
std::optional<int> AcquireProcessSingleton(
    const base::FilePath& user_data_dir) {}
#endif

struct MainFunction {};

// Initializes the user data dir. Must be called before InitializeLocalState().
void InitializeUserDataDir(base::CommandLine* command_line) {}

#if BUILDFLAG(IS_CHROMEOS_LACROS)
// If Lacros was prelaunched at login screen, this method blocks waiting
// for the user to login. It can be called before or after the Zygotes
// have been forked.
void MaybeBlockAtLoginScreen(bool after_zygotes_fork) {
  auto* command_line = base::CommandLine::ForCurrentProcess();
  std::string process_type =
      command_line->GetSwitchValueASCII(switches::kProcessType);

  if (process_type.empty() && chromeos::IsLaunchedWithPostLoginParams()) {
    // NOTE: When prelaunching Lacros, this is as far as Lacros's initialization
    // will go at the login screen. The browser process will block here.
    //
    // IMPORTANT NOTE: If your code requires access to post-login parameters
    // (which are only known after login), please place them *after* this call.
    chromeos::BrowserParamsProxy::WaitForLogin();

    // NOTE: When launching Lacros at login screen, after this point,
    // the user should have logged in. The cryptohome is now accessible.
    if (chrome::ProcessNeedsProfileDir(process_type)) {
      InitializeUserDataDir(base::CommandLine::ForCurrentProcess());
    }

    // Redirect logs from system directory to cryptohome.
    RedirectLacrosLogging();

    // If Lacros blocked after forking the zygotes, Crashpad has
    // already been initialized, but we need to update the upload
    // consent based on the user's preferences.
    if (after_zygotes_fork) {
      // Update upload consent to reflect the user's preference.
      SetCrashpadUploadConsentPostLogin();
    }
  }
}
#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)

#if !BUILDFLAG(IS_ANDROID)
void InitLogging(const std::string& process_type) {}
#endif  // !BUILDFLAG(IS_ANDROID)

void RecordMainStartupMetrics(const StartupTimestamps& timestamps) {}

#if BUILDFLAG(IS_WIN)
void OnResourceExhausted() {
  // RegisterClassEx will fail if the session's pool of ATOMs is exhausted. This
  // appears to happen most often when the browser is being driven by automation
  // tools, though the underlying reason for this remains a mystery
  // (https://crbug.com/1470483). There is nothing that Chrome can do to
  // meaningfully run until the user restarts their session by signing out of
  // Windows or restarting their computer.
  if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kNoErrorDialogs)) {
    static constexpr wchar_t kMessageBoxTitle[] = L"System resource exhausted";
    static constexpr wchar_t kMessage[] =
        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.";
    ::MessageBox(nullptr, kMessage, kMessageBoxTitle, MB_OK);
  }
  base::Process::TerminateCurrentProcessImmediately(
      chrome::RESULT_CODE_SYSTEM_RESOURCE_EXHAUSTED);
}
#endif  // !BUILDFLAG(IS_WIN)

#if BUILDFLAG(IS_CHROMEOS_LACROS)
void AddFeatureFlagsToCommandLine() {
  CHECK(!base::FeatureList::GetInstance());
  base::ScopedAddFeatureFlags flags(base::CommandLine::ForCurrentProcess());

  const auto& init_params = *chromeos::BrowserParamsProxy::Get();
  if (init_params.IsVariableRefreshRateAlwaysOn()) {
    flags.EnableIfNotSet(features::kEnableVariableRefreshRateAlwaysOn);
  }

  if (init_params.IsPdfOcrEnabled()) {
    flags.EnableIfNotSet(features::kPdfOcr);
  }
}
#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)

bool IsCanaryDev() {}

}  // namespace

#if BUILDFLAG(IS_ANDROID)
ChromeMainDelegate::ChromeMainDelegate()
    : ChromeMainDelegate(StartupTimestamps{}) {}
#endif

ChromeMainDelegate::ChromeMainDelegate(const StartupTimestamps& timestamps) {}

#if !BUILDFLAG(IS_ANDROID)
ChromeMainDelegate::~ChromeMainDelegate() {}
#else
ChromeMainDelegate::~ChromeMainDelegate() = default;
#endif  // !BUILDFLAG(IS_ANDROID)

std::optional<int> ChromeMainDelegate::PostEarlyInitialization(
    InvokedIn invoked_in) {}

bool ChromeMainDelegate::ShouldCreateFeatureList(InvokedIn invoked_in) {}

bool ChromeMainDelegate::ShouldInitializeMojo(InvokedIn invoked_in) {}

void ChromeMainDelegate::CreateThreadPool(std::string_view name) {}

void ChromeMainDelegate::CommonEarlyInitialization(InvokedIn invoked_in) {}

#if BUILDFLAG(IS_WIN)
bool ChromeMainDelegate::ShouldHandleConsoleControlEvents() {
  // Handle console control events so that orderly shutdown can be performed by
  // ChromeContentBrowserClient's override of SessionEnding.
  return true;
}
#endif

void ChromeMainDelegate::SetupTracing() {}

std::optional<int> ChromeMainDelegate::BasicStartupComplete() {}

#if BUILDFLAG(IS_MAC)
void ChromeMainDelegate::InitMacCrashReporter(
    const base::CommandLine& command_line,
    const std::string& process_type) {
  // TODO(mark): Right now, InitializeCrashpad() needs to be called after
  // CommandLine::Init() and chrome::RegisterPathProvider().  Ideally, Crashpad
  // initialization could occur sooner, preferably even before the framework
  // dylib is even loaded, to catch potential early crashes.

  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);
  }

  // Mac Chrome is packaged with a main app bundle and a helper app bundle.
  // The main app bundle should only be used for the browser process, so it
  // should never see a --type switch (switches::kProcessType).  Likewise,
  // the helper should always have a --type switch.
  //
  // This check is done this late so there is already a call to
  // base::apple::IsBackgroundOnlyProcess(), so there is no change in
  // startup/initialization order.

  // The helper's Info.plist marks it as a background only app.
  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  // BUILDFLAG(IS_MAC)

void ChromeMainDelegate::PreSandboxStartup() {}

void ChromeMainDelegate::SandboxInitialized(const std::string& process_type) {}

absl::variant<int, content::MainFunctionParams> ChromeMainDelegate::RunProcess(
    const std::string& process_type,
    content::MainFunctionParams main_function_params) {}

void ChromeMainDelegate::ProcessExiting(const std::string& process_type) {}

#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
void ChromeMainDelegate::ZygoteStarting(
    std::vector<std::unique_ptr<content::ZygoteForkDelegate>>* delegates) {}

void ChromeMainDelegate::ZygoteForked() {}

#endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)

content::ContentClient* ChromeMainDelegate::CreateContentClient() {}

content::ContentBrowserClient*
ChromeMainDelegate::CreateContentBrowserClient() {}

content::ContentGpuClient* ChromeMainDelegate::CreateContentGpuClient() {}

content::ContentRendererClient*
ChromeMainDelegate::CreateContentRendererClient() {}

content::ContentUtilityClient*
ChromeMainDelegate::CreateContentUtilityClient() {}

std::optional<int> ChromeMainDelegate::PreBrowserMain() {}

void ChromeMainDelegate::InitializeMemorySystem() {}