Commit 10c40a35 authored by Toni Barzic's avatar Toni Barzic Committed by Commit Bot

Do not assume OobeUI is around when deleting AppLaunchController

Currently, AppLaunchController assumes that AppLaunchSplashScreenView,
owned by OobeUI, is around during AppLaunchController destruction. Both
AppLaunchController and OobeUI lifetime is controlled by
LoginDisplayHost, but OobeUI is technically owned by login window
(which gets created by LoginDisplayHost, and closed on LoginDisplayHost
destruction).

Whether AppLaunchController get deleted before or after
AppLaunchSplashScreenView largely depends on how the login window is
closed/destroyed - generally the window is destroyed asynchronously
when LoginDisplayHost goes out of scope, in which case AppLaunchController
is deleted before the splash screen view, but this does not seem to be
guaranteed.

For example, in AutoLaunchedNonKioskEnabledAppTest.NotLaunched test with
mash enabled, oobe_ui gets deleted synchronously when ScopedKeepAlive
owned by LoginDisplayHostCommon gets deleted (which happens before the
AppLaunchController is deleted) - ScopedKeepAlive going out of scope
causes MusClient to start closing all widgets.

To work around this have AppLaunchSplashScreenView notify its delegate
(i.e. AppLaunchController) when it gets deleted, so the delegate can stop
referencing it when that happens.

Technically, the linked bug could be fixed by ensuring that app launch
controller is deleted before ScopedKeepAlive, but that seems more
fragile, and it doesn't necessarily address all concerns (e.g. the case
where login window is removed for a reason other than login display host
destruction).

NOTE: The same applies to the ArcKioskController and
ArcKioskSplashScreenView.

Bug: 838992

Change-Id: I9b31293e791c1f8980e780e69f6061f87a968095
Reviewed-on: https://chromium-review.googlesource.com/1041485Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Commit-Queue: Toni Barzic <tbarzic@chromium.org>
Cr-Commit-Position: refs/heads/master@{#556181}
parent cd3021a5
...@@ -157,6 +157,7 @@ AppLaunchController::AppLaunchController(const std::string& app_id, ...@@ -157,6 +157,7 @@ AppLaunchController::AppLaunchController(const std::string& app_id,
} }
AppLaunchController::~AppLaunchController() { AppLaunchController::~AppLaunchController() {
if (app_launch_splash_screen_view_)
app_launch_splash_screen_view_->SetDelegate(nullptr); app_launch_splash_screen_view_->SetDelegate(nullptr);
} }
...@@ -303,6 +304,10 @@ void AppLaunchController::OnNetworkStateChanged(bool online) { ...@@ -303,6 +304,10 @@ void AppLaunchController::OnNetworkStateChanged(bool online) {
MaybeShowNetworkConfigureUI(); MaybeShowNetworkConfigureUI();
} }
void AppLaunchController::OnDeletingSplashScreenView() {
app_launch_splash_screen_view_ = nullptr;
}
void AppLaunchController::OnProfileLoaded(Profile* profile) { void AppLaunchController::OnProfileLoaded(Profile* profile) {
SYSLOG(INFO) << "Profile loaded... Starting app launch."; SYSLOG(INFO) << "Profile loaded... Starting app launch.";
profile_ = profile; profile_ = profile;
...@@ -344,7 +349,6 @@ void AppLaunchController::CleanUp() { ...@@ -344,7 +349,6 @@ void AppLaunchController::CleanUp() {
startup_app_launcher_.reset(); startup_app_launcher_.reset();
splash_wait_timer_.Stop(); splash_wait_timer_.Stop();
if (host_)
host_->Finalize(base::OnceClosure()); host_->Finalize(base::OnceClosure());
} }
...@@ -392,6 +396,9 @@ bool AppLaunchController::NeedOwnerAuthToConfigureNetwork() { ...@@ -392,6 +396,9 @@ bool AppLaunchController::NeedOwnerAuthToConfigureNetwork() {
} }
void AppLaunchController::MaybeShowNetworkConfigureUI() { void AppLaunchController::MaybeShowNetworkConfigureUI() {
if (!app_launch_splash_screen_view_)
return;
if (CanConfigureNetwork()) { if (CanConfigureNetwork()) {
if (NeedOwnerAuthToConfigureNetwork()) { if (NeedOwnerAuthToConfigureNetwork()) {
if (network_config_requested_) if (network_config_requested_)
...@@ -408,6 +415,9 @@ void AppLaunchController::MaybeShowNetworkConfigureUI() { ...@@ -408,6 +415,9 @@ void AppLaunchController::MaybeShowNetworkConfigureUI() {
} }
void AppLaunchController::ShowNetworkConfigureUIWhenReady() { void AppLaunchController::ShowNetworkConfigureUIWhenReady() {
if (!app_launch_splash_screen_view_)
return;
if (!profile_) { if (!profile_) {
show_network_config_ui_after_profile_load_ = true; show_network_config_ui_after_profile_load_ = true;
app_launch_splash_screen_view_->UpdateAppLaunchState( app_launch_splash_screen_view_->UpdateAppLaunchState(
...@@ -422,6 +432,9 @@ void AppLaunchController::ShowNetworkConfigureUIWhenReady() { ...@@ -422,6 +432,9 @@ void AppLaunchController::ShowNetworkConfigureUIWhenReady() {
} }
void AppLaunchController::InitializeNetwork() { void AppLaunchController::InitializeNetwork() {
if (!app_launch_splash_screen_view_)
return;
// Show the network configuration dialog if network is not initialized // Show the network configuration dialog if network is not initialized
// after a brief wait time. // after a brief wait time.
waiting_for_network_ = true; waiting_for_network_ = true;
...@@ -434,7 +447,8 @@ void AppLaunchController::InitializeNetwork() { ...@@ -434,7 +447,8 @@ void AppLaunchController::InitializeNetwork() {
} }
bool AppLaunchController::IsNetworkReady() { bool AppLaunchController::IsNetworkReady() {
return app_launch_splash_screen_view_->IsNetworkReady(); return app_launch_splash_screen_view_ &&
app_launch_splash_screen_view_->IsNetworkReady();
} }
bool AppLaunchController::ShouldSkipAppInstallation() { bool AppLaunchController::ShouldSkipAppInstallation() {
...@@ -442,6 +456,9 @@ bool AppLaunchController::ShouldSkipAppInstallation() { ...@@ -442,6 +456,9 @@ bool AppLaunchController::ShouldSkipAppInstallation() {
} }
void AppLaunchController::OnInstallingApp() { void AppLaunchController::OnInstallingApp() {
if (!app_launch_splash_screen_view_)
return;
app_launch_splash_screen_view_->UpdateAppLaunchState( app_launch_splash_screen_view_->UpdateAppLaunchState(
AppLaunchSplashScreenView::APP_LAUNCH_STATE_INSTALLING_APPLICATION); AppLaunchSplashScreenView::APP_LAUNCH_STATE_INSTALLING_APPLICATION);
...@@ -495,8 +512,10 @@ void AppLaunchController::OnReadyToLaunch() { ...@@ -495,8 +512,10 @@ void AppLaunchController::OnReadyToLaunch() {
void AppLaunchController::OnLaunchSucceeded() { void AppLaunchController::OnLaunchSucceeded() {
SYSLOG(INFO) << "Kiosk launch succeeded, wait for app window."; SYSLOG(INFO) << "Kiosk launch succeeded, wait for app window.";
if (app_launch_splash_screen_view_) {
app_launch_splash_screen_view_->UpdateAppLaunchState( app_launch_splash_screen_view_->UpdateAppLaunchState(
AppLaunchSplashScreenView::APP_LAUNCH_STATE_WAITING_APP_WINDOW); AppLaunchSplashScreenView::APP_LAUNCH_STATE_WAITING_APP_WINDOW);
}
DCHECK(!app_window_watcher_); DCHECK(!app_window_watcher_);
app_window_watcher_.reset(new AppWindowWatcher(this, app_id_)); app_window_watcher_.reset(new AppWindowWatcher(this, app_id_));
...@@ -517,8 +536,8 @@ void AppLaunchController::OnLaunchFailed(KioskAppLaunchError::Error error) { ...@@ -517,8 +536,8 @@ void AppLaunchController::OnLaunchFailed(KioskAppLaunchError::Error error) {
// Saves the error and ends the session to go back to login screen. // Saves the error and ends the session to go back to login screen.
KioskAppLaunchError::Save(error); KioskAppLaunchError::Save(error);
chrome::AttemptUserExit();
CleanUp(); CleanUp();
chrome::AttemptUserExit();
} }
bool AppLaunchController::IsShowingNetworkConfigScreen() { bool AppLaunchController::IsShowingNetworkConfigScreen() {
......
...@@ -97,6 +97,7 @@ class AppLaunchController : public AppLaunchSplashScreenView::Delegate, ...@@ -97,6 +97,7 @@ class AppLaunchController : public AppLaunchSplashScreenView::Delegate,
void OnCancelAppLaunch() override; void OnCancelAppLaunch() override;
void OnNetworkConfigRequested(bool requested) override; void OnNetworkConfigRequested(bool requested) override;
void OnNetworkStateChanged(bool online) override; void OnNetworkStateChanged(bool online) override;
void OnDeletingSplashScreenView() override;
// StartupAppLauncher::Delegate overrides: // StartupAppLauncher::Delegate overrides:
void InitializeNetwork() override; void InitializeNetwork() override;
......
...@@ -34,6 +34,7 @@ ArcKioskController::ArcKioskController(LoginDisplayHost* host, OobeUI* oobe_ui) ...@@ -34,6 +34,7 @@ ArcKioskController::ArcKioskController(LoginDisplayHost* host, OobeUI* oobe_ui)
weak_ptr_factory_(this) {} weak_ptr_factory_(this) {}
ArcKioskController::~ArcKioskController() { ArcKioskController::~ArcKioskController() {
if (arc_kiosk_splash_screen_view_)
arc_kiosk_splash_screen_view_->SetDelegate(nullptr); arc_kiosk_splash_screen_view_->SetDelegate(nullptr);
} }
...@@ -57,7 +58,7 @@ void ArcKioskController::CleanUp() { ...@@ -57,7 +58,7 @@ void ArcKioskController::CleanUp() {
// Delegate is registered only when |profile_| is set. // Delegate is registered only when |profile_| is set.
if (profile_) if (profile_)
ArcKioskAppService::Get(profile_)->SetDelegate(nullptr); ArcKioskAppService::Get(profile_)->SetDelegate(nullptr);
if (host_)
host_->Finalize(base::OnceClosure()); host_->Finalize(base::OnceClosure());
} }
...@@ -72,8 +73,8 @@ void ArcKioskController::OnAuthFailure(const AuthFailure& error) { ...@@ -72,8 +73,8 @@ void ArcKioskController::OnAuthFailure(const AuthFailure& error) {
LOG(ERROR) << "ARC Kiosk launch failed. Will now shut down, error=" LOG(ERROR) << "ARC Kiosk launch failed. Will now shut down, error="
<< error.GetErrorString(); << error.GetErrorString();
KioskAppLaunchError::Save(KioskAppLaunchError::ARC_AUTH_FAILED); KioskAppLaunchError::Save(KioskAppLaunchError::ARC_AUTH_FAILED);
chrome::AttemptUserExit();
CleanUp(); CleanUp();
chrome::AttemptUserExit();
} }
void ArcKioskController::OnAuthSuccess(const UserContext& user_context) { void ArcKioskController::OnAuthSuccess(const UserContext& user_context) {
...@@ -124,14 +125,19 @@ void ArcKioskController::OnProfilePrepared(Profile* profile, ...@@ -124,14 +125,19 @@ void ArcKioskController::OnProfilePrepared(Profile* profile,
// a profile load, so invalidate the delegate now. // a profile load, so invalidate the delegate now.
UserSessionManager::GetInstance()->DelegateDeleted(this); UserSessionManager::GetInstance()->DelegateDeleted(this);
ArcKioskAppService::Get(profile_)->SetDelegate(this); ArcKioskAppService::Get(profile_)->SetDelegate(this);
if (arc_kiosk_splash_screen_view_) {
arc_kiosk_splash_screen_view_->UpdateArcKioskState( arc_kiosk_splash_screen_view_->UpdateArcKioskState(
ArcKioskSplashScreenView::ArcKioskState::WAITING_APP_LAUNCH); ArcKioskSplashScreenView::ArcKioskState::WAITING_APP_LAUNCH);
}
} }
void ArcKioskController::OnAppStarted() { void ArcKioskController::OnAppStarted() {
DVLOG(1) << "ARC Kiosk launch succeeded, wait for app window."; DVLOG(1) << "ARC Kiosk launch succeeded, wait for app window.";
if (arc_kiosk_splash_screen_view_) {
arc_kiosk_splash_screen_view_->UpdateArcKioskState( arc_kiosk_splash_screen_view_->UpdateArcKioskState(
ArcKioskSplashScreenView::ArcKioskState::WAITING_APP_WINDOW); ArcKioskSplashScreenView::ArcKioskState::WAITING_APP_WINDOW);
}
} }
void ArcKioskController::OnAppWindowLaunched() { void ArcKioskController::OnAppWindowLaunched() {
...@@ -150,4 +156,8 @@ void ArcKioskController::OnCancelArcKioskLaunch() { ...@@ -150,4 +156,8 @@ void ArcKioskController::OnCancelArcKioskLaunch() {
chrome::AttemptUserExit(); chrome::AttemptUserExit();
} }
void ArcKioskController::OnDeletingSplashScreenView() {
arc_kiosk_splash_screen_view_ = nullptr;
}
} // namespace chromeos } // namespace chromeos
...@@ -62,11 +62,12 @@ class ArcKioskController : public LoginPerformer::Delegate, ...@@ -62,11 +62,12 @@ class ArcKioskController : public LoginPerformer::Delegate,
// ArcKioskSplashScreenView::Delegate implementation: // ArcKioskSplashScreenView::Delegate implementation:
void OnCancelArcKioskLaunch() override; void OnCancelArcKioskLaunch() override;
void OnDeletingSplashScreenView() override;
// LoginDisplayHost owns itself. // LoginDisplayHost owns itself.
LoginDisplayHost* const host_; LoginDisplayHost* const host_;
// Owned by OobeUI. // Owned by OobeUI.
ArcKioskSplashScreenView* const arc_kiosk_splash_screen_view_; ArcKioskSplashScreenView* arc_kiosk_splash_screen_view_;
// Not owning here. // Not owning here.
Profile* profile_ = nullptr; Profile* profile_ = nullptr;
......
...@@ -542,9 +542,7 @@ class AutoLaunchedNonKioskEnabledAppTest : public AutoLaunchedKioskTest { ...@@ -542,9 +542,7 @@ class AutoLaunchedNonKioskEnabledAppTest : public AutoLaunchedKioskTest {
DISALLOW_COPY_AND_ASSIGN(AutoLaunchedNonKioskEnabledAppTest); DISALLOW_COPY_AND_ASSIGN(AutoLaunchedNonKioskEnabledAppTest);
}; };
// Disabled due to flaky failures: https://crbug.com/838992 IN_PROC_BROWSER_TEST_F(AutoLaunchedNonKioskEnabledAppTest, NotLaunched) {
IN_PROC_BROWSER_TEST_F(AutoLaunchedNonKioskEnabledAppTest,
DISABLED_NotLaunched) {
// Verify that Chrome hasn't already exited, e.g. in order to apply user // Verify that Chrome hasn't already exited, e.g. in order to apply user
// session flags. // session flags.
ASSERT_FALSE(termination_observer_->terminated()); ASSERT_FALSE(termination_observer_->terminated());
......
...@@ -36,6 +36,9 @@ class AppLaunchSplashScreenView { ...@@ -36,6 +36,9 @@ class AppLaunchSplashScreenView {
// is connected to the Internet. // is connected to the Internet.
virtual void OnNetworkStateChanged(bool online) = 0; virtual void OnNetworkStateChanged(bool online) = 0;
// Invoked when the splash screen view is being deleted.
virtual void OnDeletingSplashScreenView() = 0;
protected: protected:
virtual ~Delegate() {} virtual ~Delegate() {}
}; };
......
...@@ -24,6 +24,9 @@ class ArcKioskSplashScreenView { ...@@ -24,6 +24,9 @@ class ArcKioskSplashScreenView {
// Invoked when the launch bailout shortcut key is pressed. // Invoked when the launch bailout shortcut key is pressed.
virtual void OnCancelArcKioskLaunch() = 0; virtual void OnCancelArcKioskLaunch() = 0;
// Invoked when the splash screen view gets being deleted.
virtual void OnDeletingSplashScreenView() = 0;
protected: protected:
virtual ~Delegate() = default; virtual ~Delegate() = default;
......
...@@ -52,6 +52,8 @@ AppLaunchSplashScreenHandler::AppLaunchSplashScreenHandler( ...@@ -52,6 +52,8 @@ AppLaunchSplashScreenHandler::AppLaunchSplashScreenHandler(
AppLaunchSplashScreenHandler::~AppLaunchSplashScreenHandler() { AppLaunchSplashScreenHandler::~AppLaunchSplashScreenHandler() {
network_state_informer_->RemoveObserver(this); network_state_informer_->RemoveObserver(this);
if (delegate_)
delegate_->OnDeletingSplashScreenView();
} }
void AppLaunchSplashScreenHandler::DeclareLocalizedValues( void AppLaunchSplashScreenHandler::DeclareLocalizedValues(
......
...@@ -28,7 +28,10 @@ ArcKioskSplashScreenHandler::ArcKioskSplashScreenHandler() ...@@ -28,7 +28,10 @@ ArcKioskSplashScreenHandler::ArcKioskSplashScreenHandler()
set_call_js_prefix(kJsScreenPath); set_call_js_prefix(kJsScreenPath);
} }
ArcKioskSplashScreenHandler::~ArcKioskSplashScreenHandler() = default; ArcKioskSplashScreenHandler::~ArcKioskSplashScreenHandler() {
if (delegate_)
delegate_->OnDeletingSplashScreenView();
}
void ArcKioskSplashScreenHandler::DeclareLocalizedValues( void ArcKioskSplashScreenHandler::DeclareLocalizedValues(
::login::LocalizedValuesBuilder* builder) { ::login::LocalizedValuesBuilder* builder) {
......
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