M119 pre-stage 2

This commit is contained in:
Alexander Frick 2023-12-28 22:15:33 -06:00
parent bff70e2b5c
commit 57cffd497b
2 changed files with 132 additions and 68 deletions

View file

@ -17,6 +17,7 @@
#include "base/files/file_path.h" #include "base/files/file_path.h"
#include "base/files/file_util.h" #include "base/files/file_util.h"
#include "base/functional/bind.h" #include "base/functional/bind.h"
#include "base/functional/overloaded.h"
#include "base/i18n/rtl.h" #include "base/i18n/rtl.h"
#include "base/immediate_crash.h" #include "base/immediate_crash.h"
#include "base/lazy_instance.h" #include "base/lazy_instance.h"
@ -105,22 +106,27 @@
#include <algorithm> #include <algorithm>
#include "base/base_switches.h"
#include "base/files/important_file_writer_cleaner.h" #include "base/files/important_file_writer_cleaner.h"
#include "base/threading/platform_thread_win.h" #include "base/threading/platform_thread_win.h"
#include "base/win/atl.h" #include "base/win/atl.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/child/v8_crashpad_support_win.h"
#include "chrome/chrome_elf/chrome_elf_main.h" #include "chrome/chrome_elf/chrome_elf_main.h"
#include "chrome/common/child_process_logging.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.h"
#include "sandbox/win/src/sandbox_factory.h" #include "sandbox/win/src/sandbox_factory.h"
#include "ui/base/resource/resource_bundle_win.h" #include "ui/base/resource/resource_bundle_win.h"
#endif #endif
#if BUILDFLAG(IS_MAC) #if BUILDFLAG(IS_MAC)
#include "base/mac/foundation_util.h" #include "base/apple/foundation_util.h"
#include "base/message_loop/message_pump_apple.h"
#include "base/message_loop/message_pump_default.h" #include "base/message_loop/message_pump_default.h"
#include "base/message_loop/message_pump_kqueue.h" #include "base/message_loop/message_pump_kqueue.h"
#include "base/message_loop/message_pump_mac.h"
#include "base/synchronization/condition_variable.h" #include "base/synchronization/condition_variable.h"
#include "chrome/app/chrome_main_mac.h" #include "chrome/app/chrome_main_mac.h"
#include "chrome/browser/chrome_browser_application_mac.h" #include "chrome/browser/chrome_browser_application_mac.h"
@ -165,8 +171,8 @@
#if BUILDFLAG(IS_ANDROID) #if BUILDFLAG(IS_ANDROID)
#include "base/android/java_exception_reporter.h" #include "base/android/java_exception_reporter.h"
#include "base/android/library_loader/library_loader_hooks.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/android/metrics/uma_session_stats.h"
#include "chrome/browser/flags/android/cached_feature_flags.h"
#include "chrome/browser/flags/android/chrome_feature_list.h" #include "chrome/browser/flags/android/chrome_feature_list.h"
#include "chrome/common/chrome_descriptors.h" #include "chrome/common/chrome_descriptors.h"
#include "components/crash/android/pure_java_exception_handler.h" #include "components/crash/android/pure_java_exception_handler.h"
@ -511,6 +517,51 @@ absl::optional<int> HandlePackExtensionSwitches(
} }
#endif // !BUILDFLAG(ENABLE_EXTENSIONS) #endif // !BUILDFLAG(ENABLE_EXTENSIONS)
#if BUILDFLAG(ENABLE_PROCESS_SINGLETON)
absl::optional<int> AcquireProcessSingleton(
const base::FilePath& user_data_dir) {
// Take the Chrome process singleton lock. The process can become the
// Browser process if it succeed to take the lock. Otherwise, the
// command-line is sent to the actual Browser process and the current
// process can be exited.
ChromeProcessSingleton::CreateInstance(user_data_dir);
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: {
// Ensure there is an instance of ResourceBundle that is initialized for
// localized string resource accesses.
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 absl::nullopt;
}
#endif
struct MainFunction { struct MainFunction {
const char* name; const char* name;
int (*function)(content::MainFunctionParams); int (*function)(content::MainFunctionParams);
@ -642,6 +693,28 @@ void RecordMainStartupMetrics(base::TimeTicks application_start_time) {
startup_metric_utils::GetCommon().RecordChromeMainEntryTime(now); startup_metric_utils::GetCommon().RecordChromeMainEntryTime(now);
} }
#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)
} // namespace } // namespace
ChromeMainDelegate::ChromeMainDelegate() ChromeMainDelegate::ChromeMainDelegate()
@ -674,68 +747,39 @@ absl::optional<int> ChromeMainDelegate::PostEarlyInitialization(
const auto* invoked_in_browser = const auto* invoked_in_browser =
absl::get_if<InvokedInBrowserProcess>(&invoked_in); absl::get_if<InvokedInBrowserProcess>(&invoked_in);
if (!invoked_in_browser) { if (!invoked_in_browser) {
CommonEarlyInitialization(); CommonEarlyInitialization(invoked_in);
return absl::nullopt; return absl::nullopt;
} }
#if BUILDFLAG(ENABLE_PROCESS_SINGLETON) #if BUILDFLAG(ENABLE_PROCESS_SINGLETON)
// Configure the early process singleton experiment. // The User Data dir is guaranteed to be valid as per InitializeUserDataDir.
const base::CommandLine& command_line = base::FilePath user_data_dir =
*base::CommandLine::ForCurrentProcess(); base::PathService::CheckedGet(chrome::DIR_USER_DATA);
ChromeProcessSingleton::SetupEarlySingletonFeature(command_line);
if (ChromeProcessSingleton::IsEarlySingletonFeatureEnabled()) { // On platforms that support the process rendezvous, acquire the process
// Take the Chrome process singleton lock. The process can become the // singleton. In case of failure, it means there is already a running browser
// Browser process if it succeed to take the lock. Otherwise, the // instance that handled the command-line.
// command-line is sent to the actual Browser process and the current if (auto process_singleton_result = AcquireProcessSingleton(user_data_dir);
// process can be exited. process_singleton_result.has_value()) {
base::FilePath user_data_dir; // To ensure that the histograms emitted in this process are reported in
if (!base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) { // case of early exit, report the metrics accumulated this session with a
return chrome::RESULT_CODE_MISSING_DATA; // future session's metrics.
DeferBrowserMetrics(user_data_dir);
#if BUILDFLAG(IS_WIN)
// In the case the process is not the singleton process, the uninstall tasks
// need to be executed here. A window will be displayed asking to close all
// running instances.
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kUninstall)) {
// Ensure there is an instance of ResourceBundle that is initialized
// for localized string resource accesses.
ui::ScopedStartupResourceBundle startup_resource_bundle;
return DoUninstallTasks(browser_util::IsBrowserAlreadyRunning());
} }
#endif
ChromeProcessSingleton::CreateInstance(user_data_dir); return process_singleton_result;
ProcessSingleton::NotifyResult notify_result =
ChromeProcessSingleton::GetInstance()->NotifyOtherProcessOrCreate();
UMA_HISTOGRAM_ENUMERATION("Chrome.ProcessSingleton.NotifyResult",
notify_result,
ProcessSingleton::kNumNotifyResults);
// If |notify_result| is not PROCESS_NONE, this process will exit. To ensure
// that the histograms emitted in this process are reported, report the
// metrics accumulated this session with a future session's metrics.
if (notify_result != ProcessSingleton::PROCESS_NONE) {
DeferBrowserMetrics(user_data_dir);
}
switch (notify_result) {
case ProcessSingleton::PROCESS_NONE:
// No process already running, continue on to starting a new one.
break;
case ProcessSingleton::PROCESS_NOTIFIED: {
// Ensure there is an instance of ResourceBundle that is initialized for
// localized string resource accesses.
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;
}
} }
#endif #endif
@ -847,7 +891,7 @@ absl::optional<int> ChromeMainDelegate::PostEarlyInitialization(
} }
#endif // BUILDFLAG(IS_CHROMEOS_LACROS) #endif // BUILDFLAG(IS_CHROMEOS_LACROS)
CommonEarlyInitialization(); CommonEarlyInitialization(invoked_in);
// Initializes the resource bundle and determines the locale. // Initializes the resource bundle and determines the locale.
std::string actual_locale = LoadLocalState( std::string actual_locale = LoadLocalState(
@ -904,7 +948,7 @@ bool ChromeMainDelegate::ShouldInitializeMojo(InvokedIn invoked_in) {
return ShouldCreateFeatureList(invoked_in); return ShouldCreateFeatureList(invoked_in);
} }
void ChromeMainDelegate::CommonEarlyInitialization() { void ChromeMainDelegate::CommonEarlyInitialization(InvokedIn invoked_in) {
const base::CommandLine* const command_line = const base::CommandLine* const command_line =
base::CommandLine::ForCurrentProcess(); base::CommandLine::ForCurrentProcess();
std::string process_type = std::string process_type =
@ -954,7 +998,16 @@ void ChromeMainDelegate::CommonEarlyInitialization() {
} else { } else {
hang_watcher_process_type = base::HangWatcher::ProcessType::kUnknownProcess; hang_watcher_process_type = base::HangWatcher::ProcessType::kUnknownProcess;
} }
base::HangWatcher::InitializeOnMainThread(hang_watcher_process_type); bool is_zygote_child = absl::visit(
base::Overloaded{[](const InvokedInBrowserProcess& invoked_in_browser) {
return false;
},
[](const InvokedInChildProcess& invoked_in_child) {
return invoked_in_child.is_zygote_child;
}},
invoked_in);
base::HangWatcher::InitializeOnMainThread(
hang_watcher_process_type, /*is_zygote_child=*/is_zygote_child);
base::InitializeCpuReductionExperiment(); base::InitializeCpuReductionExperiment();
base::sequence_manager::internal::SequenceManagerImpl::InitializeFeatures(); base::sequence_manager::internal::SequenceManagerImpl::InitializeFeatures();
@ -1271,15 +1324,15 @@ void ChromeMainDelegate::InitMacCrashReporter(
// the helper should always have a --type switch. // the helper should always have a --type switch.
// //
// This check is done this late so there is already a call to // This check is done this late so there is already a call to
// base::mac::IsBackgroundOnlyProcess(), so there is no change in // base::apple::IsBackgroundOnlyProcess(), so there is no change in
// startup/initialization order. // startup/initialization order.
// The helper's Info.plist marks it as a background only app. // The helper's Info.plist marks it as a background only app.
if (base::mac::IsBackgroundOnlyProcess()) { if (base::apple::IsBackgroundOnlyProcess()) {
CHECK(command_line.HasSwitch(switches::kProcessType) && CHECK(command_line.HasSwitch(switches::kProcessType) &&
!process_type.empty()) !process_type.empty())
<< "Helper application requires --type."; << "Helper application requires --type.";
} else if (base::mac::AmIBundled()) { } else if (base::apple::AmIBundled()) {
CHECK(!command_line.HasSwitch(switches::kProcessType) && CHECK(!command_line.HasSwitch(switches::kProcessType) &&
process_type.empty()) process_type.empty())
<< "Main application forbids --type, saw " << process_type; << "Main application forbids --type, saw " << process_type;
@ -1403,9 +1456,19 @@ void ChromeMainDelegate::PreSandboxStartup() {
#else #else
chrome::DIR_INTERNAL_PLUGINS; chrome::DIR_INTERNAL_PLUGINS;
#endif #endif
int updated_components_dir =
#if BUILDFLAG(IS_CHROMEOS_LACROS)
command_line.HasSwitch(switches::kEnableLacrosSharedComponentsDir)
? static_cast<int>(chromeos::lacros_paths::LACROS_SHARED_DIR)
: static_cast<int>(chrome::DIR_USER_DATA);
#else
chrome::DIR_USER_DATA;
#endif
component_updater::RegisterPathProvider(chrome::DIR_COMPONENTS, component_updater::RegisterPathProvider(chrome::DIR_COMPONENTS,
alt_preinstalled_components_dir, alt_preinstalled_components_dir,
chrome::DIR_USER_DATA); updated_components_dir);
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_WIN) #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_WIN)
// Android does InitLogging when library is loaded. Skip here. // Android does InitLogging when library is loaded. Skip here.
@ -1656,8 +1719,7 @@ void ChromeMainDelegate::ProcessExiting(const std::string& process_type) {
} }
#if BUILDFLAG(ENABLE_PROCESS_SINGLETON) #if BUILDFLAG(ENABLE_PROCESS_SINGLETON)
if (ChromeProcessSingleton::IsEarlySingletonFeatureEnabled()) ChromeProcessSingleton::DeleteInstance();
ChromeProcessSingleton::DeleteInstance();
#endif // BUILDFLAG(ENABLE_PROCESS_SINGLETON) #endif // BUILDFLAG(ENABLE_PROCESS_SINGLETON)
if (SubprocessNeedsResourceBundle(process_type)) if (SubprocessNeedsResourceBundle(process_type))
@ -1786,6 +1848,9 @@ absl::optional<int> ChromeMainDelegate::PreBrowserMain() {
#endif #endif
#if BUILDFLAG(IS_WIN) #if BUILDFLAG(IS_WIN)
// Register callback to handle resource exhaustion.
base::win::SetOnResourceExhaustedFunction(&OnResourceExhausted);
if (IsExtensionPointDisableSet()) { if (IsExtensionPointDisableSet()) {
sandbox::SandboxFactory::GetBrokerServices()->SetStartingMitigations( sandbox::SandboxFactory::GetBrokerServices()->SetStartingMitigations(
sandbox::MITIGATION_EXTENSION_POINT_DISABLE); sandbox::MITIGATION_EXTENSION_POINT_DISABLE);

View file

@ -6,7 +6,6 @@
#include "build/branding_buildflags.h" #include "build/branding_buildflags.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "chrome/browser/chrome_for_testing/buildflags.h"
#include "chrome/common/chrome_version.h" #include "chrome/common/chrome_version.h"
#define FPL FILE_PATH_LITERAL #define FPL FILE_PATH_LITERAL