Commit a532eef9 authored by Sarah Hu's avatar Sarah Hu Committed by Commit Bot

wire up some special screens to views login screen

1. ShowPasswordChangedDialog
2. ShowWhitelistCheckFailedError
3. ShowUnrecoverableCryptohomeErrorDialog

Bug: 828058
Change-Id: I7269d927e9239319b4a24e4655d0ceaadf5c044b
Reviewed-on: https://chromium-review.googlesource.com/1087772
Commit-Queue: Xiaoyin Hu <xiaoyinh@chromium.org>
Reviewed-by: default avatarJacob Dufault <jdufault@chromium.org>
Reviewed-by: default avatarXiyuan Xia <xiyuan@chromium.org>
Cr-Commit-Position: refs/heads/master@{#565124}
parent 2a198bd3
...@@ -1151,8 +1151,6 @@ source_set("chromeos") { ...@@ -1151,8 +1151,6 @@ source_set("chromeos") {
"login/ui/captive_portal_view.h", "login/ui/captive_portal_view.h",
"login/ui/captive_portal_window_proxy.cc", "login/ui/captive_portal_window_proxy.cc",
"login/ui/captive_portal_window_proxy.h", "login/ui/captive_portal_window_proxy.h",
"login/ui/gaia_dialog_delegate.cc",
"login/ui/gaia_dialog_delegate.h",
"login/ui/input_events_blocker.cc", "login/ui/input_events_blocker.cc",
"login/ui/input_events_blocker.h", "login/ui/input_events_blocker.h",
"login/ui/login_display.cc", "login/ui/login_display.cc",
...@@ -1173,6 +1171,8 @@ source_set("chromeos") { ...@@ -1173,6 +1171,8 @@ source_set("chromeos") {
"login/ui/login_feedback.h", "login/ui/login_feedback.h",
"login/ui/login_web_dialog.cc", "login/ui/login_web_dialog.cc",
"login/ui/login_web_dialog.h", "login/ui/login_web_dialog.h",
"login/ui/oobe_ui_dialog_delegate.cc",
"login/ui/oobe_ui_dialog_delegate.h",
"login/ui/preloaded_web_view.cc", "login/ui/preloaded_web_view.cc",
"login/ui/preloaded_web_view.h", "login/ui/preloaded_web_view.h",
"login/ui/preloaded_web_view_factory.cc", "login/ui/preloaded_web_view_factory.cc",
......
...@@ -67,10 +67,6 @@ user_manager::UserManager* AppLaunchSigninScreen::GetUserManager() { ...@@ -67,10 +67,6 @@ user_manager::UserManager* AppLaunchSigninScreen::GetUserManager() {
: user_manager::UserManager::Get(); : user_manager::UserManager::Get();
} }
void AppLaunchSigninScreen::CancelPasswordChangedFlow() {
NOTREACHED();
}
void AppLaunchSigninScreen::CancelUserAdding() { void AppLaunchSigninScreen::CancelUserAdding() {
NOTREACHED(); NOTREACHED();
} }
...@@ -86,20 +82,12 @@ void AppLaunchSigninScreen::Login(const UserContext& user_context, ...@@ -86,20 +82,12 @@ void AppLaunchSigninScreen::Login(const UserContext& user_context,
user_context)); user_context));
} }
void AppLaunchSigninScreen::MigrateUserData(const std::string& old_password) {
NOTREACHED();
}
void AppLaunchSigninScreen::OnSigninScreenReady() {} void AppLaunchSigninScreen::OnSigninScreenReady() {}
void AppLaunchSigninScreen::RemoveUser(const AccountId& account_id) { void AppLaunchSigninScreen::RemoveUser(const AccountId& account_id) {
NOTREACHED(); NOTREACHED();
} }
void AppLaunchSigninScreen::ResyncUserData() {
NOTREACHED();
}
void AppLaunchSigninScreen::ShowEnterpriseEnrollmentScreen() { void AppLaunchSigninScreen::ShowEnterpriseEnrollmentScreen() {
NOTREACHED(); NOTREACHED();
} }
......
...@@ -54,14 +54,11 @@ class AppLaunchSigninScreen : public SigninScreenHandlerDelegate, ...@@ -54,14 +54,11 @@ class AppLaunchSigninScreen : public SigninScreenHandlerDelegate,
const user_manager::UserList& GetUsers() const; const user_manager::UserList& GetUsers() const;
// SigninScreenHandlerDelegate implementation: // SigninScreenHandlerDelegate implementation:
void CancelPasswordChangedFlow() override;
void CancelUserAdding() override; void CancelUserAdding() override;
void Login(const UserContext& user_context, void Login(const UserContext& user_context,
const SigninSpecifics& specifics) override; const SigninSpecifics& specifics) override;
void MigrateUserData(const std::string& old_password) override;
void OnSigninScreenReady() override; void OnSigninScreenReady() override;
void RemoveUser(const AccountId& account_id) override; void RemoveUser(const AccountId& account_id) override;
void ResyncUserData() override;
void ShowEnterpriseEnrollmentScreen() override; void ShowEnterpriseEnrollmentScreen() override;
void ShowEnableDebuggingScreen() override; void ShowEnableDebuggingScreen() override;
void ShowKioskEnableScreen() override; void ShowKioskEnableScreen() override;
......
...@@ -517,13 +517,6 @@ ExistingUserController::~ExistingUserController() { ...@@ -517,13 +517,6 @@ ExistingUserController::~ExistingUserController() {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// ExistingUserController, LoginDisplay::Delegate implementation: // ExistingUserController, LoginDisplay::Delegate implementation:
// //
void ExistingUserController::CancelPasswordChangedFlow() {
login_performer_.reset(nullptr);
ClearActiveDirectoryState();
PerformLoginFinishedActions(true /* start auto login timer */);
}
void ExistingUserController::CompleteLogin(const UserContext& user_context) { void ExistingUserController::CompleteLogin(const UserContext& user_context) {
if (!host_) { if (!host_) {
// Complete login event was generated already from UI. Ignore notification. // Complete login event was generated already from UI. Ignore notification.
...@@ -677,14 +670,6 @@ void ExistingUserController::RestartLogin(const UserContext& user_context) { ...@@ -677,14 +670,6 @@ void ExistingUserController::RestartLogin(const UserContext& user_context) {
login_display_->ShowSigninUI(user_context.GetAccountId().GetUserEmail()); login_display_->ShowSigninUI(user_context.GetAccountId().GetUserEmail());
} }
void ExistingUserController::MigrateUserData(const std::string& old_password) {
// LoginPerformer instance has state of the user so it should exist.
if (login_performer_.get()) {
VLOG(1) << "Migrate the existing cryptohome to new password.";
login_performer_->RecoverEncryptedData(old_password);
}
}
void ExistingUserController::OnSigninScreenReady() { void ExistingUserController::OnSigninScreenReady() {
auto_launch_ready_ = true; auto_launch_ready_ = true;
StartAutoLoginTimer(); StartAutoLoginTimer();
...@@ -722,14 +707,6 @@ void ExistingUserController::OnStartKioskAutolaunchScreen() { ...@@ -722,14 +707,6 @@ void ExistingUserController::OnStartKioskAutolaunchScreen() {
ShowKioskAutolaunchScreen(); ShowKioskAutolaunchScreen();
} }
void ExistingUserController::ResyncUserData() {
// LoginPerformer instance has state of the user so it should exist.
if (login_performer_.get()) {
VLOG(1) << "Create a new cryptohome and resync user data.";
login_performer_->ResyncEncryptedData();
}
}
void ExistingUserController::SetDisplayEmail(const std::string& email) { void ExistingUserController::SetDisplayEmail(const std::string& email) {
display_email_ = email; display_email_ = email;
} }
...@@ -1446,6 +1423,28 @@ void ExistingUserController::StopAutoLoginTimer() { ...@@ -1446,6 +1423,28 @@ void ExistingUserController::StopAutoLoginTimer() {
auto_login_timer_->Stop(); auto_login_timer_->Stop();
} }
void ExistingUserController::CancelPasswordChangedFlow() {
login_performer_.reset(nullptr);
ClearActiveDirectoryState();
PerformLoginFinishedActions(true /* start auto login timer */);
}
void ExistingUserController::MigrateUserData(const std::string& old_password) {
// LoginPerformer instance has state of the user so it should exist.
if (login_performer_.get()) {
VLOG(1) << "Migrate the existing cryptohome to new password.";
login_performer_->RecoverEncryptedData(old_password);
}
}
void ExistingUserController::ResyncUserData() {
// LoginPerformer instance has state of the user so it should exist.
if (login_performer_.get()) {
VLOG(1) << "Create a new cryptohome and resync user data.";
login_performer_->ResyncEncryptedData();
}
}
void ExistingUserController::StartAutoLoginTimer() { void ExistingUserController::StartAutoLoginTimer() {
if (!auto_launch_ready_ || is_login_in_progress_ || if (!auto_launch_ready_ || is_login_in_progress_ ||
(!public_session_auto_login_account_id_.is_valid() && (!public_session_auto_login_account_id_.is_valid() &&
......
...@@ -89,20 +89,28 @@ class ExistingUserController ...@@ -89,20 +89,28 @@ class ExistingUserController
// Stop the auto-login timer when a login attempt begins. // Stop the auto-login timer when a login attempt begins.
void StopAutoLoginTimer(); void StopAutoLoginTimer();
// Cancels current password changed flow.
void CancelPasswordChangedFlow();
// Decrypt cryptohome using user provided |old_password| and migrate to new
// password.
void MigrateUserData(const std::string& old_password);
// Ignore password change, remove existing cryptohome and force full sync of
// user data.
void ResyncUserData();
// LoginDisplay::Delegate: implementation // LoginDisplay::Delegate: implementation
void CancelPasswordChangedFlow() override;
base::string16 GetConnectedNetworkName() override; base::string16 GetConnectedNetworkName() override;
bool IsSigninInProgress() const override; bool IsSigninInProgress() const override;
void Login(const UserContext& user_context, void Login(const UserContext& user_context,
const SigninSpecifics& specifics) override; const SigninSpecifics& specifics) override;
void MigrateUserData(const std::string& old_password) override;
void OnSigninScreenReady() override; void OnSigninScreenReady() override;
void OnStartEnterpriseEnrollment() override; void OnStartEnterpriseEnrollment() override;
void OnStartEnableDebuggingScreen() override; void OnStartEnableDebuggingScreen() override;
void OnStartKioskEnableScreen() override; void OnStartKioskEnableScreen() override;
void OnStartKioskAutolaunchScreen() override; void OnStartKioskAutolaunchScreen() override;
void ResetAutoLoginTimer() override; void ResetAutoLoginTimer() override;
void ResyncUserData() override;
void ShowWrongHWIDScreen() override; void ShowWrongHWIDScreen() override;
void ShowUpdateRequiredScreen() override; void ShowUpdateRequiredScreen() override;
void Signout() override; void Signout() override;
......
...@@ -286,11 +286,6 @@ content::WebContents* WebUIScreenLocker::GetWebContents() { ...@@ -286,11 +286,6 @@ content::WebContents* WebUIScreenLocker::GetWebContents() {
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// WebUIScreenLocker, LoginDisplay::Delegate: // WebUIScreenLocker, LoginDisplay::Delegate:
void WebUIScreenLocker::CancelPasswordChangedFlow() {
NOTREACHED();
}
base::string16 WebUIScreenLocker::GetConnectedNetworkName() { base::string16 WebUIScreenLocker::GetConnectedNetworkName() {
return network_state_helper_->GetCurrentNetworkName(); return network_state_helper_->GetCurrentNetworkName();
} }
...@@ -307,10 +302,6 @@ void WebUIScreenLocker::Login(const UserContext& user_context, ...@@ -307,10 +302,6 @@ void WebUIScreenLocker::Login(const UserContext& user_context,
user_context, ScreenLocker::AuthenticateCallback()); user_context, ScreenLocker::AuthenticateCallback());
} }
void WebUIScreenLocker::MigrateUserData(const std::string& old_password) {
NOTREACHED();
}
void WebUIScreenLocker::OnSigninScreenReady() { void WebUIScreenLocker::OnSigninScreenReady() {
VLOG(2) << "Lock screen signin screen is ready"; VLOG(2) << "Lock screen signin screen is ready";
} }
...@@ -341,10 +332,6 @@ void WebUIScreenLocker::ShowUpdateRequiredScreen() { ...@@ -341,10 +332,6 @@ void WebUIScreenLocker::ShowUpdateRequiredScreen() {
void WebUIScreenLocker::ResetAutoLoginTimer() {} void WebUIScreenLocker::ResetAutoLoginTimer() {}
void WebUIScreenLocker::ResyncUserData() {
NOTREACHED();
}
void WebUIScreenLocker::Signout() { void WebUIScreenLocker::Signout() {
chromeos::ScreenLocker::default_screen_locker()->Signout(); chromeos::ScreenLocker::default_screen_locker()->Signout();
} }
......
...@@ -85,12 +85,10 @@ class WebUIScreenLocker : public WebUILoginView, ...@@ -85,12 +85,10 @@ class WebUIScreenLocker : public WebUILoginView,
content::WebContents* GetWebContents() override; content::WebContents* GetWebContents() override;
// LoginDisplay::Delegate: // LoginDisplay::Delegate:
void CancelPasswordChangedFlow() override;
base::string16 GetConnectedNetworkName() override; base::string16 GetConnectedNetworkName() override;
bool IsSigninInProgress() const override; bool IsSigninInProgress() const override;
void Login(const UserContext& user_context, void Login(const UserContext& user_context,
const SigninSpecifics& specifics) override; const SigninSpecifics& specifics) override;
void MigrateUserData(const std::string& old_password) override;
void OnSigninScreenReady() override; void OnSigninScreenReady() override;
void OnStartEnterpriseEnrollment() override; void OnStartEnterpriseEnrollment() override;
void OnStartEnableDebuggingScreen() override; void OnStartEnableDebuggingScreen() override;
...@@ -99,7 +97,6 @@ class WebUIScreenLocker : public WebUILoginView, ...@@ -99,7 +97,6 @@ class WebUIScreenLocker : public WebUILoginView,
void ShowWrongHWIDScreen() override; void ShowWrongHWIDScreen() override;
void ShowUpdateRequiredScreen() override; void ShowUpdateRequiredScreen() override;
void ResetAutoLoginTimer() override; void ResetAutoLoginTimer() override;
void ResyncUserData() override;
void Signout() override; void Signout() override;
// WidgetObserver: // WidgetObserver:
......
...@@ -126,4 +126,10 @@ const user_manager::UserList FakeLoginDisplayHost::GetUsers() { ...@@ -126,4 +126,10 @@ const user_manager::UserList FakeLoginDisplayHost::GetUsers() {
return user_manager::UserList(); return user_manager::UserList();
} }
void FakeLoginDisplayHost::CancelPasswordChangedFlow() {}
void FakeLoginDisplayHost::MigrateUserData(const std::string& old_password) {}
void FakeLoginDisplayHost::ResyncUserData() {}
} // namespace chromeos } // namespace chromeos
...@@ -58,6 +58,9 @@ class FakeLoginDisplayHost : public LoginDisplayHost { ...@@ -58,6 +58,9 @@ class FakeLoginDisplayHost : public LoginDisplayHost {
const base::Optional<AccountId>& account) override; const base::Optional<AccountId>& account) override;
void UpdateGaiaDialogSize(int width, int height) override; void UpdateGaiaDialogSize(int width, int height) override;
const user_manager::UserList GetUsers() override; const user_manager::UserList GetUsers() override;
void CancelPasswordChangedFlow() override;
void MigrateUserData(const std::string& old_password) override;
void ResyncUserData() override;
private: private:
class FakeBaseScreen; class FakeBaseScreen;
......
...@@ -36,17 +36,6 @@ class LoginDisplay { ...@@ -36,17 +36,6 @@ class LoginDisplay {
class Delegate { class Delegate {
public: public:
// Cancels current password changed flow.
virtual void CancelPasswordChangedFlow() = 0;
// Ignore password change, remove existing cryptohome and
// force full sync of user data.
virtual void ResyncUserData() = 0;
// Decrypt cryptohome using user provided |old_password|
// and migrate to new password.
virtual void MigrateUserData(const std::string& old_password) = 0;
// Sign in using |username| and |password| specified. // Sign in using |username| and |password| specified.
// Used for known users only. // Used for known users only.
virtual void Login(const UserContext& user_context, virtual void Login(const UserContext& user_context,
......
...@@ -167,6 +167,18 @@ class LoginDisplayHost { ...@@ -167,6 +167,18 @@ class LoginDisplayHost {
// Returns true if user is allowed to log in by domain policy. // Returns true if user is allowed to log in by domain policy.
virtual bool IsUserWhitelisted(const AccountId& account_id) = 0; virtual bool IsUserWhitelisted(const AccountId& account_id) = 0;
// ----- Password change flow methods -----
// Cancels current password changed flow.
virtual void CancelPasswordChangedFlow() = 0;
// Decrypt cryptohome using user provided |old_password| and migrate to new
// password.
virtual void MigrateUserData(const std::string& old_password) = 0;
// Ignore password change, remove existing cryptohome and force full sync of
// user data.
virtual void ResyncUserData() = 0;
protected: protected:
LoginDisplayHost(); LoginDisplayHost();
virtual ~LoginDisplayHost(); virtual ~LoginDisplayHost();
......
...@@ -229,6 +229,27 @@ bool LoginDisplayHostCommon::IsUserWhitelisted(const AccountId& account_id) { ...@@ -229,6 +229,27 @@ bool LoginDisplayHostCommon::IsUserWhitelisted(const AccountId& account_id) {
return controller->IsUserWhitelisted(account_id); return controller->IsUserWhitelisted(account_id);
} }
void LoginDisplayHostCommon::CancelPasswordChangedFlow() {
ExistingUserController* controller =
ExistingUserController::current_controller();
if (controller)
controller->CancelPasswordChangedFlow();
}
void LoginDisplayHostCommon::MigrateUserData(const std::string& old_password) {
ExistingUserController* controller =
ExistingUserController::current_controller();
if (controller)
controller->MigrateUserData(old_password);
}
void LoginDisplayHostCommon::ResyncUserData() {
ExistingUserController* controller =
ExistingUserController::current_controller();
if (controller)
controller->ResyncUserData();
}
void LoginDisplayHostCommon::Observe( void LoginDisplayHostCommon::Observe(
int type, int type,
const content::NotificationSource& source, const content::NotificationSource& source,
......
...@@ -53,6 +53,9 @@ class LoginDisplayHostCommon : public LoginDisplayHost, ...@@ -53,6 +53,9 @@ class LoginDisplayHostCommon : public LoginDisplayHost,
void LoadWallpaper(const AccountId& account_id) final; void LoadWallpaper(const AccountId& account_id) final;
void LoadSigninWallpaper() final; void LoadSigninWallpaper() final;
bool IsUserWhitelisted(const AccountId& account_id) final; bool IsUserWhitelisted(const AccountId& account_id) final;
void CancelPasswordChangedFlow() override;
void MigrateUserData(const std::string& old_password) final;
void ResyncUserData() final;
// content::NotificationObserver: // content::NotificationObserver:
void Observe(int type, void Observe(int type,
......
...@@ -11,9 +11,9 @@ ...@@ -11,9 +11,9 @@
#include "chrome/browser/chromeos/login/existing_user_controller.h" #include "chrome/browser/chromeos/login/existing_user_controller.h"
#include "chrome/browser/chromeos/login/screens/chrome_user_selection_screen.h" #include "chrome/browser/chromeos/login/screens/chrome_user_selection_screen.h"
#include "chrome/browser/chromeos/login/screens/gaia_view.h" #include "chrome/browser/chromeos/login/screens/gaia_view.h"
#include "chrome/browser/chromeos/login/ui/gaia_dialog_delegate.h"
#include "chrome/browser/chromeos/login/ui/login_display.h" #include "chrome/browser/chromeos/login/ui/login_display.h"
#include "chrome/browser/chromeos/login/ui/login_display_mojo.h" #include "chrome/browser/chromeos/login/ui/login_display_mojo.h"
#include "chrome/browser/chromeos/login/ui/oobe_ui_dialog_delegate.h"
#include "chrome/browser/chromeos/login/user_board_view_mojo.h" #include "chrome/browser/chromeos/login/user_board_view_mojo.h"
#include "chrome/browser/chromeos/login/wizard_controller.h" #include "chrome/browser/chromeos/login/wizard_controller.h"
#include "chrome/browser/ui/ash/wallpaper_controller_client.h" #include "chrome/browser/ui/ash/wallpaper_controller_client.h"
...@@ -44,7 +44,8 @@ LoginDisplayHostMojo::~LoginDisplayHostMojo() { ...@@ -44,7 +44,8 @@ LoginDisplayHostMojo::~LoginDisplayHostMojo() {
dialog_->Close(); dialog_->Close();
} }
void LoginDisplayHostMojo::OnDialogDestroyed(const GaiaDialogDelegate* dialog) { void LoginDisplayHostMojo::OnDialogDestroyed(
const OobeUIDialogDelegate* dialog) {
if (dialog == dialog_) { if (dialog == dialog_) {
dialog_ = nullptr; dialog_ = nullptr;
wizard_controller_.reset(); wizard_controller_.reset();
...@@ -57,6 +58,26 @@ void LoginDisplayHostMojo::SetUsers(const user_manager::UserList& users) { ...@@ -57,6 +58,26 @@ void LoginDisplayHostMojo::SetUsers(const user_manager::UserList& users) {
GetOobeUI()->SetLoginUserCount(users_.size()); GetOobeUI()->SetLoginUserCount(users_.size());
} }
void LoginDisplayHostMojo::ShowPasswordChangedDialog(bool show_password_error,
const std::string& email) {
DCHECK(GetOobeUI());
GetOobeUI()->signin_screen_handler()->ShowPasswordChangedDialog(
show_password_error, email);
dialog_->Show(false /*closable_by_esc*/);
}
void LoginDisplayHostMojo::ShowWhitelistCheckFailedError() {
DCHECK(GetOobeUI());
GetOobeUI()->signin_screen_handler()->ShowWhitelistCheckFailedError();
dialog_->Show(true /*closable_by_esc*/);
}
void LoginDisplayHostMojo::ShowUnrecoverableCrypthomeErrorDialog() {
DCHECK(GetOobeUI());
GetOobeUI()->signin_screen_handler()->ShowUnrecoverableCrypthomeErrorDialog();
dialog_->Show(false /*closable_by_esc*/);
}
LoginDisplay* LoginDisplayHostMojo::CreateLoginDisplay( LoginDisplay* LoginDisplayHostMojo::CreateLoginDisplay(
LoginDisplay::Delegate* delegate) { LoginDisplay::Delegate* delegate) {
user_selection_screen_->SetLoginDisplayDelegate(delegate); user_selection_screen_->SetLoginDisplayDelegate(delegate);
...@@ -64,8 +85,11 @@ LoginDisplay* LoginDisplayHostMojo::CreateLoginDisplay( ...@@ -64,8 +85,11 @@ LoginDisplay* LoginDisplayHostMojo::CreateLoginDisplay(
} }
gfx::NativeWindow LoginDisplayHostMojo::GetNativeWindow() const { gfx::NativeWindow LoginDisplayHostMojo::GetNativeWindow() const {
NOTIMPLEMENTED(); // We can't access the login widget because it's in ash, return the native
// window of the dialog widget if it exists.
if (!dialog_)
return nullptr; return nullptr;
return dialog_->GetNativeWindow();
} }
OobeUI* LoginDisplayHostMojo::GetOobeUI() const { OobeUI* LoginDisplayHostMojo::GetOobeUI() const {
...@@ -104,8 +128,7 @@ void LoginDisplayHostMojo::StartWizard(OobeScreen first_screen) { ...@@ -104,8 +128,7 @@ void LoginDisplayHostMojo::StartWizard(OobeScreen first_screen) {
} }
WizardController* LoginDisplayHostMojo::GetWizardController() { WizardController* LoginDisplayHostMojo::GetWizardController() {
NOTIMPLEMENTED(); return wizard_controller_.get();
return nullptr;
} }
void LoginDisplayHostMojo::OnStartUserAdding() { void LoginDisplayHostMojo::OnStartUserAdding() {
...@@ -206,6 +229,12 @@ const user_manager::UserList LoginDisplayHostMojo::GetUsers() { ...@@ -206,6 +229,12 @@ const user_manager::UserList LoginDisplayHostMojo::GetUsers() {
return users_; return users_;
} }
void LoginDisplayHostMojo::CancelPasswordChangedFlow() {
// Close the Oobe UI dialog.
UpdateGaiaDialogVisibility(false /*visible*/, base::nullopt /*account*/);
LoginDisplayHostCommon::CancelPasswordChangedFlow();
}
void LoginDisplayHostMojo::HandleAuthenticateUser( void LoginDisplayHostMojo::HandleAuthenticateUser(
const AccountId& account_id, const AccountId& account_id,
const std::string& password, const std::string& password,
...@@ -294,7 +323,7 @@ void LoginDisplayHostMojo::InitWidgetAndView() { ...@@ -294,7 +323,7 @@ void LoginDisplayHostMojo::InitWidgetAndView() {
if (dialog_) if (dialog_)
return; return;
dialog_ = new GaiaDialogDelegate(weak_factory_.GetWeakPtr()); dialog_ = new OobeUIDialogDelegate(weak_factory_.GetWeakPtr());
dialog_->Init(); dialog_->Init();
} }
......
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
namespace chromeos { namespace chromeos {
class ExistingUserController; class ExistingUserController;
class GaiaDialogDelegate; class OobeUIDialogDelegate;
class UserBoardViewMojo; class UserBoardViewMojo;
class UserSelectionScreen; class UserSelectionScreen;
...@@ -32,11 +32,23 @@ class LoginDisplayHostMojo : public LoginDisplayHostCommon, ...@@ -32,11 +32,23 @@ class LoginDisplayHostMojo : public LoginDisplayHostCommon,
~LoginDisplayHostMojo() override; ~LoginDisplayHostMojo() override;
// Called when the gaia dialog is destroyed. // Called when the gaia dialog is destroyed.
void OnDialogDestroyed(const GaiaDialogDelegate* dialog); void OnDialogDestroyed(const OobeUIDialogDelegate* dialog);
// Set the users in the views login screen. // Set the users in the views login screen.
void SetUsers(const user_manager::UserList& users); void SetUsers(const user_manager::UserList& users);
// Show password changed dialog. If |show_password_error| is true, user
// already tried to enter old password but it turned out to be incorrect.
void ShowPasswordChangedDialog(bool show_password_error,
const std::string& email);
// Show whitelist check failed error. Happens after user completes online
// signin but whitelist check fails.
void ShowWhitelistCheckFailedError();
// Show unrecoverable cryptohome error dialog.
void ShowUnrecoverableCrypthomeErrorDialog();
UserSelectionScreen* user_selection_screen() { UserSelectionScreen* user_selection_screen() {
return user_selection_screen_.get(); return user_selection_screen_.get();
} }
...@@ -64,6 +76,7 @@ class LoginDisplayHostMojo : public LoginDisplayHostCommon, ...@@ -64,6 +76,7 @@ class LoginDisplayHostMojo : public LoginDisplayHostCommon,
const base::Optional<AccountId>& account) override; const base::Optional<AccountId>& account) override;
void UpdateGaiaDialogSize(int width, int height) override; void UpdateGaiaDialogSize(int width, int height) override;
const user_manager::UserList GetUsers() override; const user_manager::UserList GetUsers() override;
void CancelPasswordChangedFlow() override;
// LoginScreenClient::Delegate: // LoginScreenClient::Delegate:
void HandleAuthenticateUser(const AccountId& account_id, void HandleAuthenticateUser(const AccountId& account_id,
...@@ -99,7 +112,7 @@ class LoginDisplayHostMojo : public LoginDisplayHostCommon, ...@@ -99,7 +112,7 @@ class LoginDisplayHostMojo : public LoginDisplayHostCommon,
// Called after host deletion. // Called after host deletion.
std::vector<base::OnceClosure> completion_callbacks_; std::vector<base::OnceClosure> completion_callbacks_;
GaiaDialogDelegate* dialog_ = nullptr; OobeUIDialogDelegate* dialog_ = nullptr;
std::unique_ptr<WizardController> wizard_controller_; std::unique_ptr<WizardController> wizard_controller_;
// Users that are visible in the views login screen. // Users that are visible in the views login screen.
......
...@@ -81,7 +81,7 @@ void LoginDisplayMojo::ShowErrorScreen(LoginDisplay::SigninError error_id) { ...@@ -81,7 +81,7 @@ void LoginDisplayMojo::ShowErrorScreen(LoginDisplay::SigninError error_id) {
void LoginDisplayMojo::ShowPasswordChangedDialog(bool show_password_error, void LoginDisplayMojo::ShowPasswordChangedDialog(bool show_password_error,
const std::string& email) { const std::string& email) {
NOTIMPLEMENTED(); host_->ShowPasswordChangedDialog(show_password_error, email);
} }
void LoginDisplayMojo::ShowSigninUI(const std::string& email) { void LoginDisplayMojo::ShowSigninUI(const std::string& email) {
...@@ -89,11 +89,11 @@ void LoginDisplayMojo::ShowSigninUI(const std::string& email) { ...@@ -89,11 +89,11 @@ void LoginDisplayMojo::ShowSigninUI(const std::string& email) {
} }
void LoginDisplayMojo::ShowWhitelistCheckFailedError() { void LoginDisplayMojo::ShowWhitelistCheckFailedError() {
NOTIMPLEMENTED(); host_->ShowWhitelistCheckFailedError();
} }
void LoginDisplayMojo::ShowUnrecoverableCrypthomeErrorDialog() { void LoginDisplayMojo::ShowUnrecoverableCrypthomeErrorDialog() {
NOTIMPLEMENTED(); host_->ShowUnrecoverableCrypthomeErrorDialog();
} }
void LoginDisplayMojo::OnUserImageChanged(const user_manager::User& user) { void LoginDisplayMojo::OnUserImageChanged(const user_manager::User& user) {
......
...@@ -188,12 +188,6 @@ gfx::NativeWindow LoginDisplayWebUI::GetNativeWindow() const { ...@@ -188,12 +188,6 @@ gfx::NativeWindow LoginDisplayWebUI::GetNativeWindow() const {
} }
// LoginDisplayWebUI, SigninScreenHandlerDelegate implementation: -------------- // LoginDisplayWebUI, SigninScreenHandlerDelegate implementation: --------------
void LoginDisplayWebUI::CancelPasswordChangedFlow() {
DCHECK(delegate_);
if (delegate_)
delegate_->CancelPasswordChangedFlow();
}
void LoginDisplayWebUI::CancelUserAdding() { void LoginDisplayWebUI::CancelUserAdding() {
if (!UserAddingScreen::Get()->IsRunning()) { if (!UserAddingScreen::Get()->IsRunning()) {
LOG(ERROR) << "User adding screen not running."; LOG(ERROR) << "User adding screen not running.";
...@@ -208,12 +202,6 @@ void LoginDisplayWebUI::Login(const UserContext& user_context, ...@@ -208,12 +202,6 @@ void LoginDisplayWebUI::Login(const UserContext& user_context,
delegate_->Login(user_context, specifics); delegate_->Login(user_context, specifics);
} }
void LoginDisplayWebUI::MigrateUserData(const std::string& old_password) {
DCHECK(delegate_);
if (delegate_)
delegate_->MigrateUserData(old_password);
}
void LoginDisplayWebUI::OnSigninScreenReady() { void LoginDisplayWebUI::OnSigninScreenReady() {
SignInScreenController::Get()->OnSigninScreenReady(); SignInScreenController::Get()->OnSigninScreenReady();
...@@ -225,12 +213,6 @@ void LoginDisplayWebUI::RemoveUser(const AccountId& account_id) { ...@@ -225,12 +213,6 @@ void LoginDisplayWebUI::RemoveUser(const AccountId& account_id) {
SignInScreenController::Get()->RemoveUser(account_id); SignInScreenController::Get()->RemoveUser(account_id);
} }
void LoginDisplayWebUI::ResyncUserData() {
DCHECK(delegate_);
if (delegate_)
delegate_->ResyncUserData();
}
void LoginDisplayWebUI::ShowEnterpriseEnrollmentScreen() { void LoginDisplayWebUI::ShowEnterpriseEnrollmentScreen() {
if (delegate_) if (delegate_)
delegate_->OnStartEnterpriseEnrollment(); delegate_->OnStartEnterpriseEnrollment();
......
...@@ -54,10 +54,6 @@ class LoginDisplayWebUI : public LoginDisplay, ...@@ -54,10 +54,6 @@ class LoginDisplayWebUI : public LoginDisplay,
gfx::NativeWindow GetNativeWindow() const override; gfx::NativeWindow GetNativeWindow() const override;
// SigninScreenHandlerDelegate implementation: // SigninScreenHandlerDelegate implementation:
void CancelPasswordChangedFlow() override;
void ResyncUserData() override;
void MigrateUserData(const std::string& old_password) override;
void Login(const UserContext& user_context, void Login(const UserContext& user_context,
const SigninSpecifics& specifics) override; const SigninSpecifics& specifics) override;
bool IsSigninInProgress() const override; bool IsSigninInProgress() const override;
......
...@@ -164,11 +164,13 @@ void LoginFeedback::FeedbackWindowHandler::OnAppWindowAdded( ...@@ -164,11 +164,13 @@ void LoginFeedback::FeedbackWindowHandler::OnAppWindowAdded(
// Move the feedback window to the same container as the login screen and make // Move the feedback window to the same container as the login screen and make
// it a transient child of the login screen. // it a transient child of the login screen.
if (LoginDisplayHost::default_host()->GetNativeWindow()) {
views::Widget::ReparentNativeView( views::Widget::ReparentNativeView(
app_window->GetNativeWindow(), app_window->GetNativeWindow(),
LoginDisplayHost::default_host()->GetNativeWindow()->parent()); LoginDisplayHost::default_host()->GetNativeWindow()->parent());
wm::AddTransientChild(LoginDisplayHost::default_host()->GetNativeWindow(), wm::AddTransientChild(LoginDisplayHost::default_host()->GetNativeWindow(),
app_window->GetNativeWindow()); app_window->GetNativeWindow());
}
} }
void LoginFeedback::FeedbackWindowHandler::OnAppWindowRemoved( void LoginFeedback::FeedbackWindowHandler::OnAppWindowRemoved(
......
...@@ -64,6 +64,9 @@ class MockLoginDisplayHost : public LoginDisplayHost { ...@@ -64,6 +64,9 @@ class MockLoginDisplayHost : public LoginDisplayHost {
MOCK_METHOD1(LoadWallpaper, void(const AccountId&)); MOCK_METHOD1(LoadWallpaper, void(const AccountId&));
MOCK_METHOD0(LoadSigninWallpaper, void()); MOCK_METHOD0(LoadSigninWallpaper, void());
MOCK_METHOD1(IsUserWhitelisted, bool(const AccountId&)); MOCK_METHOD1(IsUserWhitelisted, bool(const AccountId&));
MOCK_METHOD0(CancelPasswordChangedFlow, void());
MOCK_METHOD1(MigrateUserData, void(const std::string&));
MOCK_METHOD0(ResyncUserData, void());
private: private:
DISALLOW_COPY_AND_ASSIGN(MockLoginDisplayHost); DISALLOW_COPY_AND_ASSIGN(MockLoginDisplayHost);
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "chrome/browser/chromeos/login/ui/gaia_dialog_delegate.h" #include "chrome/browser/chromeos/login/ui/oobe_ui_dialog_delegate.h"
#include "ash/public/cpp/shell_window_ids.h" #include "ash/public/cpp/shell_window_ids.h"
#include "chrome/browser/chromeos/login/ui/login_display_host_mojo.h" #include "chrome/browser/chromeos/login/ui/login_display_host_mojo.h"
...@@ -28,17 +28,17 @@ constexpr int kGaiaDialogWidth = 768; ...@@ -28,17 +28,17 @@ constexpr int kGaiaDialogWidth = 768;
} // namespace } // namespace
GaiaDialogDelegate::GaiaDialogDelegate( OobeUIDialogDelegate::OobeUIDialogDelegate(
base::WeakPtr<LoginDisplayHostMojo> controller) base::WeakPtr<LoginDisplayHostMojo> controller)
: controller_(controller), : controller_(controller),
size_(gfx::Size(kGaiaDialogWidth, kGaiaDialogHeight)) {} size_(gfx::Size(kGaiaDialogWidth, kGaiaDialogHeight)) {}
GaiaDialogDelegate::~GaiaDialogDelegate() { OobeUIDialogDelegate::~OobeUIDialogDelegate() {
if (controller_) if (controller_)
controller_->OnDialogDestroyed(this); controller_->OnDialogDestroyed(this);
} }
void GaiaDialogDelegate::Init() { void OobeUIDialogDelegate::Init() {
DCHECK(!dialog_view_ && !dialog_widget_); DCHECK(!dialog_view_ && !dialog_widget_);
// Life cycle of |dialog_view_| is managed by the widget: // Life cycle of |dialog_view_| is managed by the widget:
// Widget owns a root view which has |dialog_view_| as its child view. // Widget owns a root view which has |dialog_view_| as its child view.
...@@ -59,22 +59,22 @@ void GaiaDialogDelegate::Init() { ...@@ -59,22 +59,22 @@ void GaiaDialogDelegate::Init() {
dialog_view_->web_contents()); dialog_view_->web_contents());
} }
void GaiaDialogDelegate::Show(bool closable_by_esc) { void OobeUIDialogDelegate::Show(bool closable_by_esc) {
closable_by_esc_ = closable_by_esc; closable_by_esc_ = closable_by_esc;
dialog_widget_->Show(); dialog_widget_->Show();
} }
void GaiaDialogDelegate::Hide() { void OobeUIDialogDelegate::Hide() {
if (dialog_widget_) if (dialog_widget_)
dialog_widget_->Hide(); dialog_widget_->Hide();
} }
void GaiaDialogDelegate::Close() { void OobeUIDialogDelegate::Close() {
if (dialog_widget_) if (dialog_widget_)
dialog_widget_->Close(); dialog_widget_->Close();
} }
void GaiaDialogDelegate::SetSize(int width, int height) { void OobeUIDialogDelegate::SetSize(int width, int height) {
if (size_ == gfx::Size(width, height)) if (size_ == gfx::Size(width, height))
return; return;
...@@ -94,7 +94,7 @@ void GaiaDialogDelegate::SetSize(int width, int height) { ...@@ -94,7 +94,7 @@ void GaiaDialogDelegate::SetSize(int width, int height) {
dialog_widget_->SetBounds(bounds); dialog_widget_->SetBounds(bounds);
} }
OobeUI* GaiaDialogDelegate::GetOobeUI() const { OobeUI* OobeUIDialogDelegate::GetOobeUI() const {
if (dialog_view_) { if (dialog_view_) {
content::WebUI* webui = dialog_view_->web_contents()->GetWebUI(); content::WebUI* webui = dialog_view_->web_contents()->GetWebUI();
if (webui) if (webui)
...@@ -103,57 +103,61 @@ OobeUI* GaiaDialogDelegate::GetOobeUI() const { ...@@ -103,57 +103,61 @@ OobeUI* GaiaDialogDelegate::GetOobeUI() const {
return nullptr; return nullptr;
} }
ui::ModalType GaiaDialogDelegate::GetDialogModalType() const { gfx::NativeWindow OobeUIDialogDelegate::GetNativeWindow() const {
return dialog_widget_ ? dialog_widget_->GetNativeWindow() : nullptr;
}
ui::ModalType OobeUIDialogDelegate::GetDialogModalType() const {
return ui::MODAL_TYPE_SYSTEM; return ui::MODAL_TYPE_SYSTEM;
} }
base::string16 GaiaDialogDelegate::GetDialogTitle() const { base::string16 OobeUIDialogDelegate::GetDialogTitle() const {
return base::string16(); return base::string16();
} }
GURL GaiaDialogDelegate::GetDialogContentURL() const { GURL OobeUIDialogDelegate::GetDialogContentURL() const {
return GURL(kGaiaURL); return GURL(kGaiaURL);
} }
void GaiaDialogDelegate::GetWebUIMessageHandlers( void OobeUIDialogDelegate::GetWebUIMessageHandlers(
std::vector<content::WebUIMessageHandler*>* handlers) const {} std::vector<content::WebUIMessageHandler*>* handlers) const {}
void GaiaDialogDelegate::GetDialogSize(gfx::Size* size) const { void OobeUIDialogDelegate::GetDialogSize(gfx::Size* size) const {
*size = size_; *size = size_;
} }
bool GaiaDialogDelegate::CanResizeDialog() const { bool OobeUIDialogDelegate::CanResizeDialog() const {
return false; return false;
} }
std::string GaiaDialogDelegate::GetDialogArgs() const { std::string OobeUIDialogDelegate::GetDialogArgs() const {
return std::string(); return std::string();
} }
void GaiaDialogDelegate::OnDialogClosed(const std::string& json_retval) { void OobeUIDialogDelegate::OnDialogClosed(const std::string& json_retval) {
delete this; delete this;
} }
void GaiaDialogDelegate::OnCloseContents(content::WebContents* source, void OobeUIDialogDelegate::OnCloseContents(content::WebContents* source,
bool* out_close_dialog) { bool* out_close_dialog) {
*out_close_dialog = true; *out_close_dialog = true;
} }
bool GaiaDialogDelegate::ShouldShowDialogTitle() const { bool OobeUIDialogDelegate::ShouldShowDialogTitle() const {
return false; return false;
} }
bool GaiaDialogDelegate::HandleContextMenu( bool OobeUIDialogDelegate::HandleContextMenu(
const content::ContextMenuParams& params) { const content::ContextMenuParams& params) {
return true; return true;
} }
std::vector<ui::Accelerator> GaiaDialogDelegate::GetAccelerators() { std::vector<ui::Accelerator> OobeUIDialogDelegate::GetAccelerators() {
// TODO(crbug.com/809648): Adding necessory accelerators. // TODO(crbug.com/809648): Adding necessory accelerators.
return std::vector<ui::Accelerator>(); return std::vector<ui::Accelerator>();
} }
bool GaiaDialogDelegate::AcceleratorPressed( bool OobeUIDialogDelegate::AcceleratorPressed(
const ui::Accelerator& accelerator) { const ui::Accelerator& accelerator) {
if (ui::VKEY_ESCAPE == accelerator.key_code()) { if (ui::VKEY_ESCAPE == accelerator.key_code()) {
// The widget should not be closed until the login is done. // The widget should not be closed until the login is done.
......
...@@ -2,8 +2,8 @@ ...@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#ifndef CHROME_BROWSER_CHROMEOS_LOGIN_UI_GAIA_DIALOG_DELEGATE_H_ #ifndef CHROME_BROWSER_CHROMEOS_LOGIN_UI_OOBE_UI_DIALOG_DELEGATE_H_
#define CHROME_BROWSER_CHROMEOS_LOGIN_UI_GAIA_DIALOG_DELEGATE_H_ #define CHROME_BROWSER_CHROMEOS_LOGIN_UI_OOBE_UI_DIALOG_DELEGATE_H_
#include <string> #include <string>
...@@ -26,17 +26,17 @@ namespace chromeos { ...@@ -26,17 +26,17 @@ namespace chromeos {
class LoginDisplayHostMojo; class LoginDisplayHostMojo;
class OobeUI; class OobeUI;
// This class manages the behavior of the gaia signin dialog. // This class manages the behavior of the Oobe UI dialog.
// And its lifecycle is managed by the widget created in Show(). // And its lifecycle is managed by the widget created in Show().
// WebDialogView<----delegate_----GaiaDialogDelegate // WebDialogView<----delegate_----OobeUIDialogDelegate
// | // |
// | // |
// V // V
// clientView---->Widget's view hierarchy // clientView---->Widget's view hierarchy
class GaiaDialogDelegate : public ui::WebDialogDelegate { class OobeUIDialogDelegate : public ui::WebDialogDelegate {
public: public:
explicit GaiaDialogDelegate(base::WeakPtr<LoginDisplayHostMojo> controller); explicit OobeUIDialogDelegate(base::WeakPtr<LoginDisplayHostMojo> controller);
~GaiaDialogDelegate() override; ~OobeUIDialogDelegate() override;
// Show the dialog widget. // Show the dialog widget.
// |closable_by_esc|: Whether the widget will be hidden after press escape // |closable_by_esc|: Whether the widget will be hidden after press escape
...@@ -54,6 +54,7 @@ class GaiaDialogDelegate : public ui::WebDialogDelegate { ...@@ -54,6 +54,7 @@ class GaiaDialogDelegate : public ui::WebDialogDelegate {
void SetSize(int width, int height); void SetSize(int width, int height);
OobeUI* GetOobeUI() const; OobeUI* GetOobeUI() const;
gfx::NativeWindow GetNativeWindow() const;
private: private:
// ui::WebDialogDelegate: // ui::WebDialogDelegate:
...@@ -83,9 +84,9 @@ class GaiaDialogDelegate : public ui::WebDialogDelegate { ...@@ -83,9 +84,9 @@ class GaiaDialogDelegate : public ui::WebDialogDelegate {
gfx::Size size_; gfx::Size size_;
bool closable_by_esc_ = true; bool closable_by_esc_ = true;
DISALLOW_COPY_AND_ASSIGN(GaiaDialogDelegate); DISALLOW_COPY_AND_ASSIGN(OobeUIDialogDelegate);
}; };
} // namespace chromeos } // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_LOGIN_UI_GAIA_DIALOG_DELEGATE_H_ #endif // CHROME_BROWSER_CHROMEOS_LOGIN_UI_OOBE_UI_DIALOG_DELEGATE_H_
...@@ -1457,13 +1457,13 @@ void SigninScreenHandler::HandleCancelUserAdding() { ...@@ -1457,13 +1457,13 @@ void SigninScreenHandler::HandleCancelUserAdding() {
void SigninScreenHandler::HandleMigrateUserData( void SigninScreenHandler::HandleMigrateUserData(
const std::string& old_password) { const std::string& old_password) {
if (delegate_) if (LoginDisplayHost::default_host())
delegate_->MigrateUserData(old_password); LoginDisplayHost::default_host()->MigrateUserData(old_password);
} }
void SigninScreenHandler::HandleResyncUserData() { void SigninScreenHandler::HandleResyncUserData() {
if (delegate_) if (LoginDisplayHost::default_host())
delegate_->ResyncUserData(); LoginDisplayHost::default_host()->ResyncUserData();
} }
void SigninScreenHandler::HandleLoginUIStateChanged(const std::string& source, void SigninScreenHandler::HandleLoginUIStateChanged(const std::string& source,
...@@ -1687,10 +1687,11 @@ bool SigninScreenHandler::AllWhitelistedUsersPresent() { ...@@ -1687,10 +1687,11 @@ bool SigninScreenHandler::AllWhitelistedUsersPresent() {
} }
void SigninScreenHandler::CancelPasswordChangedFlowInternal() { void SigninScreenHandler::CancelPasswordChangedFlowInternal() {
if (delegate_) { if (delegate_)
ShowImpl(); ShowImpl();
delegate_->CancelPasswordChangedFlow();
} if (LoginDisplayHost::default_host())
LoginDisplayHost::default_host()->CancelPasswordChangedFlow();
} }
bool SigninScreenHandler::IsGaiaVisible() const { bool SigninScreenHandler::IsGaiaVisible() const {
......
...@@ -132,18 +132,6 @@ class LoginDisplayWebUIHandler { ...@@ -132,18 +132,6 @@ class LoginDisplayWebUIHandler {
// An interface for SigninScreenHandler to call WebUILoginDisplay. // An interface for SigninScreenHandler to call WebUILoginDisplay.
class SigninScreenHandlerDelegate { class SigninScreenHandlerDelegate {
public: public:
// --------------- Password change flow methods.
// Cancels current password changed flow.
virtual void CancelPasswordChangedFlow() = 0;
// Decrypt cryptohome using user provided |old_password|
// and migrate to new password.
virtual void MigrateUserData(const std::string& old_password) = 0;
// Ignore password change, remove existing cryptohome and
// force full sync of user data.
virtual void ResyncUserData() = 0;
// --------------- Sign in/out methods. // --------------- Sign in/out methods.
// Sign in using username and password specified as a part of |user_context|. // Sign in using username and password specified as a part of |user_context|.
// Used for both known and new users. // Used for both known and new users.
...@@ -305,6 +293,7 @@ class SigninScreenHandler ...@@ -305,6 +293,7 @@ class SigninScreenHandler
friend class GaiaScreenHandler; friend class GaiaScreenHandler;
friend class ReportDnsCacheClearedOnUIThread; friend class ReportDnsCacheClearedOnUIThread;
friend class SupervisedUserCreationScreenHandler; friend class SupervisedUserCreationScreenHandler;
friend class LoginDisplayHostMojo;
void ShowImpl(); void ShowImpl();
......
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