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_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"
@ -105,22 +106,27 @@
#include <algorithm>
#include "base/base_switches.h"
#include "base/files/important_file_writer_cleaner.h"
#include "base/threading/platform_thread_win.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/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/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_kqueue.h"
#include "base/message_loop/message_pump_mac.h"
#include "base/synchronization/condition_variable.h"
#include "chrome/app/chrome_main_mac.h"
#include "chrome/browser/chrome_browser_application_mac.h"
@ -165,8 +171,8 @@
#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/cached_feature_flags.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"
@ -511,6 +517,51 @@ absl::optional<int> HandlePackExtensionSwitches(
}
#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 {
const char* name;
int (*function)(content::MainFunctionParams);
@ -642,6 +693,28 @@ void RecordMainStartupMetrics(base::TimeTicks application_start_time) {
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
ChromeMainDelegate::ChromeMainDelegate()
@ -674,68 +747,39 @@ absl::optional<int> ChromeMainDelegate::PostEarlyInitialization(
const auto* invoked_in_browser =
absl::get_if<InvokedInBrowserProcess>(&invoked_in);
if (!invoked_in_browser) {
CommonEarlyInitialization();
CommonEarlyInitialization(invoked_in);
return absl::nullopt;
}
#if BUILDFLAG(ENABLE_PROCESS_SINGLETON)
// Configure the early process singleton experiment.
const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
ChromeProcessSingleton::SetupEarlySingletonFeature(command_line);
// The User Data dir is guaranteed to be valid as per InitializeUserDataDir.
base::FilePath user_data_dir =
base::PathService::CheckedGet(chrome::DIR_USER_DATA);
if (ChromeProcessSingleton::IsEarlySingletonFeatureEnabled()) {
// 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.
base::FilePath user_data_dir;
if (!base::PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) {
return chrome::RESULT_CODE_MISSING_DATA;
}
ChromeProcessSingleton::CreateInstance(user_data_dir);
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) {
// On platforms that support the process rendezvous, acquire the process
// singleton. In case of failure, it means there is already a running browser
// instance that handled the command-line.
if (auto process_singleton_result = AcquireProcessSingleton(user_data_dir);
process_singleton_result.has_value()) {
// To ensure that the histograms emitted in this process are reported in
// case of early exit, report the metrics accumulated this session with a
// future session's metrics.
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.
#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;
printf("%s\n", base::SysWideToNativeMB(
base::UTF16ToWide(l10n_util::GetStringUTF16(
IDS_USED_EXISTING_BROWSER)))
.c_str());
return chrome::RESULT_CODE_NORMAL_EXIT_PROCESS_NOTIFIED;
return DoUninstallTasks(browser_util::IsBrowserAlreadyRunning());
}
#endif
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 process_singleton_result;
}
#endif
@ -847,7 +891,7 @@ absl::optional<int> ChromeMainDelegate::PostEarlyInitialization(
}
#endif // BUILDFLAG(IS_CHROMEOS_LACROS)
CommonEarlyInitialization();
CommonEarlyInitialization(invoked_in);
// Initializes the resource bundle and determines the locale.
std::string actual_locale = LoadLocalState(
@ -904,7 +948,7 @@ bool ChromeMainDelegate::ShouldInitializeMojo(InvokedIn invoked_in) {
return ShouldCreateFeatureList(invoked_in);
}
void ChromeMainDelegate::CommonEarlyInitialization() {
void ChromeMainDelegate::CommonEarlyInitialization(InvokedIn invoked_in) {
const base::CommandLine* const command_line =
base::CommandLine::ForCurrentProcess();
std::string process_type =
@ -954,7 +998,16 @@ void ChromeMainDelegate::CommonEarlyInitialization() {
} else {
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::sequence_manager::internal::SequenceManagerImpl::InitializeFeatures();
@ -1271,15 +1324,15 @@ void ChromeMainDelegate::InitMacCrashReporter(
// the helper should always have a --type switch.
//
// 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.
// 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) &&
!process_type.empty())
<< "Helper application requires --type.";
} else if (base::mac::AmIBundled()) {
} else if (base::apple::AmIBundled()) {
CHECK(!command_line.HasSwitch(switches::kProcessType) &&
process_type.empty())
<< "Main application forbids --type, saw " << process_type;
@ -1403,9 +1456,19 @@ void ChromeMainDelegate::PreSandboxStartup() {
#else
chrome::DIR_INTERNAL_PLUGINS;
#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,
alt_preinstalled_components_dir,
chrome::DIR_USER_DATA);
updated_components_dir);
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_WIN)
// Android does InitLogging when library is loaded. Skip here.
@ -1656,7 +1719,6 @@ void ChromeMainDelegate::ProcessExiting(const std::string& process_type) {
}
#if BUILDFLAG(ENABLE_PROCESS_SINGLETON)
if (ChromeProcessSingleton::IsEarlySingletonFeatureEnabled())
ChromeProcessSingleton::DeleteInstance();
#endif // BUILDFLAG(ENABLE_PROCESS_SINGLETON)
@ -1786,6 +1848,9 @@ absl::optional<int> ChromeMainDelegate::PreBrowserMain() {
#endif
#if BUILDFLAG(IS_WIN)
// Register callback to handle resource exhaustion.
base::win::SetOnResourceExhaustedFunction(&OnResourceExhausted);
if (IsExtensionPointDisableSet()) {
sandbox::SandboxFactory::GetBrokerServices()->SetStartingMitigations(
sandbox::MITIGATION_EXTENSION_POINT_DISABLE);

View file

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