Commit 7b991c5c authored by Steven Bennetts's avatar Steven Bennetts Committed by Commit Bot

Chrome OS: Fix shutdown when PreMainMessageLoopRun is not called

ChromeBrowserMainParts::PreMainMessageLoopRunImpl() may return
early with chrome::RESULT_CODE_NORMAL_EXIT_PROCESS_NOTIFIED in
browser tests. This prevents PreProfileInit() and other stages
from getting called, but PostMainMessageLoopRun() is still
called, so the code needs to be careful about shutting down
singletons initialized in PostMainMessageLoopRun() stages.

Bug: 702403
Change-Id: Icfc7dd93da6f78a3ccaf4e207c720fe2073fc1db
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1893376
Commit-Queue: Steven Bennetts <stevenjb@chromium.org>
Reviewed-by: default avatarJames Cook <jamescook@chromium.org>
Reviewed-by: default avatarMitsuru Oshima <oshima@chromium.org>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#714566}
parent 04afc39a
...@@ -577,6 +577,11 @@ void ChromeBrowserMainPartsChromeos::PreProfileInit() { ...@@ -577,6 +577,11 @@ void ChromeBrowserMainPartsChromeos::PreProfileInit() {
// -- This used to be in ChromeBrowserMainParts::PreMainMessageLoopRun() // -- This used to be in ChromeBrowserMainParts::PreMainMessageLoopRun()
// -- immediately before Profile creation(). // -- immediately before Profile creation().
// PreProfileInit() is not always called if no browser process is started
// (e.g. during some browser tests). Set a boolean so that we do not try to
// destroy singletons that are initialized here.
pre_profile_init_called_ = true;
// Now that the file thread exists we can record our stats. // Now that the file thread exists we can record our stats.
BootTimesRecorder::Get()->RecordChromeMainStats(); BootTimesRecorder::Get()->RecordChromeMainStats();
LoginEventRecorder::Get()->SetDelegate(BootTimesRecorder::Get()); LoginEventRecorder::Get()->SetDelegate(BootTimesRecorder::Get());
...@@ -954,6 +959,10 @@ void ChromeBrowserMainPartsChromeos::PostBrowserStart() { ...@@ -954,6 +959,10 @@ void ChromeBrowserMainPartsChromeos::PostBrowserStart() {
} }
// Shut down services before the browser process, etc are destroyed. // Shut down services before the browser process, etc are destroyed.
// NOTE: This may get called without PreProfileInit() (or other
// PreMainMessageLoopRun sub-stages) getting called, so be careful with
// shutdown calls and test |pre_profile_init_called_| if necessary. See
// crbug.com/702403 for details.
void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() { void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() {
crostini_unsupported_action_notifier_.reset(); crostini_unsupported_action_notifier_.reset();
...@@ -965,6 +974,7 @@ void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() { ...@@ -965,6 +974,7 @@ void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() {
lock_screen_apps_state_controller_->Shutdown(); lock_screen_apps_state_controller_->Shutdown();
// This must be shut down before |arc_service_launcher_|. // This must be shut down before |arc_service_launcher_|.
if (pre_profile_init_called_)
NoteTakingHelper::Shutdown(); NoteTakingHelper::Shutdown();
arc_service_launcher_->Shutdown(); arc_service_launcher_->Shutdown();
...@@ -979,6 +989,7 @@ void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() { ...@@ -979,6 +989,7 @@ void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() {
shutdown_policy_forwarder_.reset(); shutdown_policy_forwarder_.reset();
// Destroy the application name notifier for Kiosk mode. // Destroy the application name notifier for Kiosk mode.
if (pre_profile_init_called_)
KioskModeIdleAppNameNotification::Shutdown(); KioskModeIdleAppNameNotification::Shutdown();
// Shutdown the upgrade detector for Chrome OS. The upgrade detector // Shutdown the upgrade detector for Chrome OS. The upgrade detector
...@@ -1003,6 +1014,7 @@ void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() { ...@@ -1003,6 +1014,7 @@ void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() {
wake_on_wifi_manager_.reset(); wake_on_wifi_manager_.reset();
fast_transition_observer_.reset(); fast_transition_observer_.reset();
network_throttling_observer_.reset(); network_throttling_observer_.reset();
if (pre_profile_init_called_)
ScreenLocker::ShutDownClass(); ScreenLocker::ShutDownClass();
low_disk_notification_.reset(); low_disk_notification_.reset();
demo_mode_resources_remover_.reset(); demo_mode_resources_remover_.reset();
...@@ -1021,10 +1033,10 @@ void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() { ...@@ -1021,10 +1033,10 @@ void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() {
if (LoginScreenExtensionUiHandler::Get(false /*can_create*/)) if (LoginScreenExtensionUiHandler::Get(false /*can_create*/))
LoginScreenExtensionUiHandler::Shutdown(); LoginScreenExtensionUiHandler::Shutdown();
if (pre_profile_init_called_) {
MagnificationManager::Shutdown(); MagnificationManager::Shutdown();
audio::SoundsManager::Shutdown(); audio::SoundsManager::Shutdown();
}
system::StatisticsProvider::GetInstance()->Shutdown(); system::StatisticsProvider::GetInstance()->Shutdown();
DemoSession::ShutDownIfInitialized(); DemoSession::ShutDownIfInitialized();
...@@ -1035,9 +1047,13 @@ void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() { ...@@ -1035,9 +1047,13 @@ void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() {
if (NetworkCertLoader::IsInitialized()) if (NetworkCertLoader::IsInitialized())
NetworkCertLoader::Get()->set_is_shutting_down(); NetworkCertLoader::Get()->set_is_shutting_down();
CHECK(g_browser_process);
CHECK(g_browser_process->platform_part());
// Let the UserManager unregister itself as an observer of the CrosSettings // Let the UserManager unregister itself as an observer of the CrosSettings
// singleton before it is destroyed. This also ensures that the UserManager // singleton before it is destroyed. This also ensures that the UserManager
// has no URLRequest pending (see http://crbug.com/276659). // has no URLRequest pending (see http://crbug.com/276659).
if (g_browser_process->platform_part()->user_manager())
g_browser_process->platform_part()->user_manager()->Shutdown(); g_browser_process->platform_part()->user_manager()->Shutdown();
// Let the DeviceDisablingManager unregister itself as an observer of the // Let the DeviceDisablingManager unregister itself as an observer of the
...@@ -1052,6 +1068,7 @@ void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() { ...@@ -1052,6 +1068,7 @@ void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() {
KioskAppManager::Shutdown(); KioskAppManager::Shutdown();
// Make sure that there is no pending URLRequests. // Make sure that there is no pending URLRequests.
if (pre_profile_init_called_)
UserSessionManager::GetInstance()->Shutdown(); UserSessionManager::GetInstance()->Shutdown();
// Give BrowserPolicyConnectorChromeOS a chance to unregister any observers // Give BrowserPolicyConnectorChromeOS a chance to unregister any observers
...@@ -1063,16 +1080,20 @@ void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() { ...@@ -1063,16 +1080,20 @@ void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() {
// Shutdown the virtual keyboard UI before destroying ash::Shell or the // Shutdown the virtual keyboard UI before destroying ash::Shell or the
// primary profile. // primary profile.
if (chrome_keyboard_controller_client_)
chrome_keyboard_controller_client_->Shutdown(); chrome_keyboard_controller_client_->Shutdown();
// Must occur before BrowserProcessImpl::StartTearDown() destroys the // Must occur before BrowserProcessImpl::StartTearDown() destroys the
// ProfileManager. // ProfileManager.
if (pre_profile_init_called_) {
Profile* primary_user = ProfileManager::GetPrimaryUserProfile(); Profile* primary_user = ProfileManager::GetPrimaryUserProfile();
if (primary_user) { if (primary_user) {
// See startup_settings_cache::ReadAppLocale() comment for why we do this. // See startup_settings_cache::ReadAppLocale() comment for why we do this.
startup_settings_cache::WriteAppLocale(primary_user->GetPrefs()->GetString( startup_settings_cache::WriteAppLocale(
primary_user->GetPrefs()->GetString(
language::prefs::kApplicationLocale)); language::prefs::kApplicationLocale));
} }
}
// Cleans up dbus services depending on ash. // Cleans up dbus services depending on ash.
dbus_services_->PreAshShutdown(); dbus_services_->PreAshShutdown();
...@@ -1092,9 +1113,10 @@ void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() { ...@@ -1092,9 +1113,10 @@ void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() {
// |arc_service_launcher_| uses |scheduler_configuration_manager_|. // |arc_service_launcher_| uses |scheduler_configuration_manager_|.
scheduler_configuration_manager_.reset(); scheduler_configuration_manager_.reset();
if (pre_profile_init_called_) {
AccessibilityManager::Shutdown(); AccessibilityManager::Shutdown();
input_method::Shutdown(); input_method::Shutdown();
}
// Stops all in-flight OAuth2 token fetchers before the IO thread stops. // Stops all in-flight OAuth2 token fetchers before the IO thread stops.
DeviceOAuth2TokenServiceFactory::Shutdown(); DeviceOAuth2TokenServiceFactory::Shutdown();
...@@ -1106,10 +1128,10 @@ void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() { ...@@ -1106,10 +1128,10 @@ void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() {
quirks::QuirksManager::Shutdown(); quirks::QuirksManager::Shutdown();
// Called after // Called after ChromeBrowserMainPartsLinux::PostMainMessageLoopRun() (which
// ChromeBrowserMainPartsLinux::PostMainMessageLoopRun() to be // calls chrome::CloseAsh()) because some parts of WebUI depend on
// executed after execution of chrome::CloseAsh(), because some // NetworkPortalDetector.
// parts of WebUI depends on NetworkPortalDetector. if (pre_profile_init_called_)
network_portal_detector::Shutdown(); network_portal_detector::Shutdown();
g_browser_process->platform_part()->ShutdownSessionManager(); g_browser_process->platform_part()->ShutdownSessionManager();
......
...@@ -174,6 +174,12 @@ class ChromeBrowserMainPartsChromeos : public ChromeBrowserMainPartsLinux { ...@@ -174,6 +174,12 @@ class ChromeBrowserMainPartsChromeos : public ChromeBrowserMainPartsLinux {
dark_resume_controller_; dark_resume_controller_;
std::unique_ptr<SessionTerminationManager> session_termination_manager_; std::unique_ptr<SessionTerminationManager> session_termination_manager_;
// Set when PreProfileInit() is called. If PreMainMessageLoopRun() exits
// early, this will be false during PostMainMessageLoopRun(), etc.
// Used to prevent shutting down classes that were not initialized.
bool pre_profile_init_called_ = false;
std::unique_ptr<policy::LockToSingleUserManager> lock_to_single_user_manager_; std::unique_ptr<policy::LockToSingleUserManager> lock_to_single_user_manager_;
std::unique_ptr<WilcoDtcSupportdManager> wilco_dtc_supportd_manager_; std::unique_ptr<WilcoDtcSupportdManager> wilco_dtc_supportd_manager_;
std::unique_ptr<LoginScreenExtensionsLifetimeManager> std::unique_ptr<LoginScreenExtensionsLifetimeManager>
......
...@@ -228,13 +228,13 @@ void ChromeBrowserMainExtraPartsAsh::PostMainMessageLoopRun() { ...@@ -228,13 +228,13 @@ void ChromeBrowserMainExtraPartsAsh::PostMainMessageLoopRun() {
wallpaper_controller_client_.reset(); wallpaper_controller_client_.reset();
vpn_list_forwarder_.reset(); vpn_list_forwarder_.reset();
// Initialized in PostProfileInit: // Initialized in PostProfileInit (which may not get called in some tests).
network_portal_notification_controller_.reset(); network_portal_notification_controller_.reset();
display_settings_handler_.reset(); display_settings_handler_.reset();
media_client_.reset(); media_client_.reset();
login_screen_client_.reset(); login_screen_client_.reset();
// Initialized in PreProfileInit: // Initialized in PreProfileInit (which may not get called in some tests).
system_tray_client_.reset(); system_tray_client_.reset();
session_controller_client_.reset(); session_controller_client_.reset();
ime_controller_client_.reset(); ime_controller_client_.reset();
...@@ -245,7 +245,7 @@ void ChromeBrowserMainExtraPartsAsh::PostMainMessageLoopRun() { ...@@ -245,7 +245,7 @@ void ChromeBrowserMainExtraPartsAsh::PostMainMessageLoopRun() {
app_list_client_.reset(); app_list_client_.reset();
ash_shell_init_.reset(); ash_shell_init_.reset();
cast_config_controller_media_router_.reset(); cast_config_controller_media_router_.reset();
if (chromeos::NetworkConnect::IsInitialized())
chromeos::NetworkConnect::Shutdown(); chromeos::NetworkConnect::Shutdown();
network_connect_delegate_.reset(); network_connect_delegate_.reset();
} }
......
...@@ -491,7 +491,12 @@ void NetworkConnect::Initialize(Delegate* delegate) { ...@@ -491,7 +491,12 @@ void NetworkConnect::Initialize(Delegate* delegate) {
void NetworkConnect::Shutdown() { void NetworkConnect::Shutdown() {
CHECK(g_network_connect); CHECK(g_network_connect);
delete g_network_connect; delete g_network_connect;
g_network_connect = NULL; g_network_connect = nullptr;
}
// static
bool NetworkConnect::IsInitialized() {
return g_network_connect;
} }
// static // static
......
...@@ -60,7 +60,10 @@ class COMPONENT_EXPORT(CHROMEOS_NETWORK) NetworkConnect { ...@@ -60,7 +60,10 @@ class COMPONENT_EXPORT(CHROMEOS_NETWORK) NetworkConnect {
// Destroys the global NetworkConnect object. // Destroys the global NetworkConnect object.
static void Shutdown(); static void Shutdown();
// Returns the global NetworkConnect object if initialized or NULL. // Returns true if the global NetworkConnect object is initialized.
static bool IsInitialized();
// Returns the global NetworkConnect object if initialized or null.
static NetworkConnect* Get(); static NetworkConnect* Get();
virtual ~NetworkConnect(); virtual ~NetworkConnect();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment