blob: 9121523d5a21bd50a091501325c35401d6fd3da2 [file] [log] [blame]
// Copyright 2024 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ash/auth/active_session_auth_controller_impl.h"
#include <memory>
#include <string>
#include <string_view>
#include "ash/auth/views/active_session_auth_view.h"
#include "ash/auth/views/auth_common.h"
#include "ash/auth/views/auth_view_utils.h"
#include "ash/constants/ash_pref_names.h"
#include "ash/public/cpp/auth/active_session_auth_controller.h"
#include "ash/public/cpp/login_types.h"
#include "ash/public/cpp/shell_window_ids.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
#include "ash/strings/grit/ash_strings.h"
#include "base/check.h"
#include "base/check_op.h"
#include "base/functional/bind.h"
#include "base/i18n/time_formatting.h"
#include "base/logging.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/notreached.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "chromeos/ash/components/cryptohome/auth_factor_conversions.h"
#include "chromeos/ash/components/cryptohome/constants.h"
#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
#include "chromeos/ash/components/login/auth/auth_performer.h"
#include "chromeos/ash/components/login/auth/public/auth_callbacks.h"
#include "chromeos/ash/components/login/auth/public/auth_session_intent.h"
#include "chromeos/ash/components/login/auth/public/session_auth_factors.h"
#include "chromeos/ash/components/login/auth/public/user_context.h"
#include "chromeos/ash/components/osauth/impl/auth_surface_registry.h"
#include "chromeos/ash/components/osauth/public/auth_session_storage.h"
#include "components/account_id/account_id.h"
#include "components/user_manager/known_user.h"
#include "components/user_manager/user.h"
#include "components/user_manager/user_manager.h"
#include "ui/aura/window.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/mojom/ui_base_types.mojom-shared.h"
#include "ui/base/mojom/window_show_state.mojom.h"
#include "ui/base/ui_base_types.h"
#include "ui/display/screen.h"
#include "ui/gfx/geometry/size.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
// Enable VLOG level 1.
#undef ENABLED_VLOG_LEVEL
#define ENABLED_VLOG_LEVEL 1
namespace ash {
namespace {
// Read the salt from local state.
std::string GetUserSalt(const AccountId& account_id) {
user_manager::KnownUser known_user(Shell::Get()->local_state());
if (const std::string* salt =
known_user.FindStringPath(account_id, prefs::kQuickUnlockPinSalt)) {
return *salt;
}
return {};
}
const char* ReasonToString(AuthRequest::Reason reason) {
switch (reason) {
case AuthRequest::Reason::kPasswordManager:
return "PasswordManager";
case AuthRequest::Reason::kSettings:
return "Settings";
case AuthRequest::Reason::kWebAuthN:
return "WebAuthN";
}
NOTREACHED();
}
const char* ActiveSessionAuthStateToString(
ActiveSessionAuthControllerImpl::ActiveSessionAuthState state) {
switch (state) {
case ActiveSessionAuthControllerImpl::ActiveSessionAuthState::kOnIdle:
return "OnIdle";
case ActiveSessionAuthControllerImpl::ActiveSessionAuthState::kWaitForInit:
return "WaitForInit";
case ActiveSessionAuthControllerImpl::ActiveSessionAuthState::kInitialized:
return "Initialized";
case ActiveSessionAuthControllerImpl::ActiveSessionAuthState::
kPasswordAuthStarted:
return "PasswordAuthStarted";
case ActiveSessionAuthControllerImpl::ActiveSessionAuthState::
kPasswordAuthSucceeded:
return "PasswordAuthSucceeded";
case ActiveSessionAuthControllerImpl::ActiveSessionAuthState::
kPinAuthStarted:
return "PinAuthStarted";
case ActiveSessionAuthControllerImpl::ActiveSessionAuthState::
kPinAuthSucceeded:
return "PinAuthSucceeded";
case ActiveSessionAuthControllerImpl::ActiveSessionAuthState::
kFingerprintAuthSucceeded:
return "FingerprintAuthSucceeded";
case ActiveSessionAuthControllerImpl::ActiveSessionAuthState::
kFingerprintAuthSucceededWaiting:
return "FingerprintAuthSucceededWaiting";
case ActiveSessionAuthControllerImpl::ActiveSessionAuthState::
kCloseRequested:
return "CloseRequested";
}
NOTREACHED();
}
} // namespace
// This class manages the closing process after successful fingerprint
// authentication. It listens for two signals:
// 1. The completion of the successful authentication animation.
// 2. The authentication callback from cryptohome.
// Once both signals are received, the class triggers the closing process.
class ActiveSessionAuthControllerImpl::FingerprintAuthTracker {
public:
explicit FingerprintAuthTracker(ActiveSessionAuthControllerImpl* owner)
: owner_(owner) {
CHECK(owner_);
}
void OnAuthenticationFinished(
std::unique_ptr<UserContext> user_context,
std::optional<AuthenticationError> authentication_error) {
CHECK_EQ(authentication_finished_, false);
authentication_finished_ = true;
if (authentication_error.has_value()) {
LOG(ERROR) << "Authentication error during OnFingerprintSuccess code: "
<< authentication_error->get_cryptohome_code();
}
owner_->user_context_ = std::move(user_context);
MaybeNotifyOwner();
}
void OnAnimationFinished() {
VLOG(1) << "OnAnimationFinished";
CHECK_EQ(animation_finished_, false);
animation_finished_ = true;
MaybeNotifyOwner();
}
void MaybeNotifyOwner() {
if (authentication_finished_ && animation_finished_) {
owner_->StartClose();
}
CHECK(owner_);
CHECK(owner_->fp_auth_tracker_);
}
private:
const raw_ptr<ActiveSessionAuthControllerImpl> owner_;
bool animation_finished_ = false;
bool authentication_finished_ = false;
};
ActiveSessionAuthControllerImpl::TestApi::TestApi(
ActiveSessionAuthControllerImpl* controller)
: controller_(controller) {}
ActiveSessionAuthControllerImpl::TestApi::~TestApi() = default;
AuthFactorSet ActiveSessionAuthControllerImpl::TestApi::GetAvailableFactors()
const {
return controller_->available_factors_;
}
void ActiveSessionAuthControllerImpl::TestApi::SubmitPassword(
const std::string& password) {
controller_->OnPasswordSubmit(base::UTF8ToUTF16(password));
}
void ActiveSessionAuthControllerImpl::TestApi::SubmitPin(
const std::string& pin) {
controller_->OnPinSubmit(base::UTF8ToUTF16(pin));
}
void ActiveSessionAuthControllerImpl::TestApi::Close() {
controller_->StartClose();
}
void ActiveSessionAuthControllerImpl::TestApi::SetPinStatus(
std::unique_ptr<cryptohome::PinStatus> pin_status) {
controller_->contents_view_->SetPinStatus(std::move(pin_status));
}
std::u16string_view
ActiveSessionAuthControllerImpl::TestApi::GetPinStatusMessage() const {
return controller_->contents_view_->GetPinStatusMessage();
}
ActiveSessionAuthControllerImpl::ActiveSessionAuthControllerImpl() = default;
ActiveSessionAuthControllerImpl::~ActiveSessionAuthControllerImpl() = default;
bool ActiveSessionAuthControllerImpl::IsPreInitializedState() const {
return state_ == ActiveSessionAuthState::kOnIdle ||
state_ == ActiveSessionAuthState::kWaitForInit;
}
bool ActiveSessionAuthControllerImpl::IsSucceedState() const {
return state_ == ActiveSessionAuthState::kPasswordAuthSucceeded ||
state_ == ActiveSessionAuthState::kPinAuthSucceeded ||
state_ == ActiveSessionAuthState::kFingerprintAuthSucceeded ||
state_ == ActiveSessionAuthState::kFingerprintAuthSucceededWaiting;
}
bool ActiveSessionAuthControllerImpl::ShowAuthDialog(
std::unique_ptr<AuthRequest> auth_request) {
CHECK(auth_request);
VLOG(1) << "Show is requested with reason: "
<< ReasonToString(auth_request->GetAuthReason());
if (IsShown()) {
LOG(ERROR) << "ActiveSessionAuthController widget is already exists.";
auth_request->NotifyAuthFailure();
return false;
}
if (state_ == ActiveSessionAuthState::kWaitForInit) {
VLOG(1) << "A show request is already pending; waiting for initialization.";
return false;
}
// This state transition checking the current state is kOnIdle.
SetState(ActiveSessionAuthState::kWaitForInit);
CHECK(Shell::Get());
CHECK(Shell::Get()->session_controller());
if (Shell::Get()->session_controller()->GetSessionState() !=
session_manager::SessionState::ACTIVE) {
LOG(ERROR) << "SessionState is not active.";
return false;
}
Shell::Get()->session_controller()->AddObserver(this);
CHECK(!auth_request_);
auth_request_ = std::move(auth_request);
title_ = l10n_util::GetStringUTF16(IDS_ASH_IN_SESSION_AUTH_TITLE);
description_ = auth_request_->GetDescription();
auth_factor_editor_ =
std::make_unique<AuthFactorEditor>(UserDataAuthClient::Get());
auth_performer_ = std::make_unique<AuthPerformer>(UserDataAuthClient::Get());
account_id_ = Shell::Get()->session_controller()->GetActiveAccountId();
fingerprint_animation_finished_ = false;
fingerprint_authentication_finished_ = false;
user_manager::User* active_user =
user_manager::UserManager::Get()->GetActiveUser();
auto user_context = std::make_unique<UserContext>(*active_user);
const bool ephemeral =
user_manager::UserManager::Get()->IsUserCryptohomeDataEphemeral(
account_id_);
auth_performer_->StartAuthSession(
std::move(user_context), ephemeral, auth_request_->GetAuthSessionIntent(),
base::BindOnce(&ActiveSessionAuthControllerImpl::OnAuthSessionStarted,
weak_ptr_factory_.GetWeakPtr()));
return true;
}
bool ActiveSessionAuthControllerImpl::IsShown() const {
return widget_ != nullptr;
}
void ActiveSessionAuthControllerImpl::SetFingerprintClient(
ActiveSessionFingerprintClient* fp_client) {
CHECK_NE(fp_client_ == nullptr, fp_client == nullptr);
fp_client_ = fp_client;
}
void ActiveSessionAuthControllerImpl::OnAuthSessionStarted(
bool user_exists,
std::unique_ptr<UserContext> user_context,
std::optional<AuthenticationError> authentication_error) {
user_context_ = std::move(user_context);
if (!user_exists || authentication_error.has_value()) {
LOG(ERROR) << "Failed to start auth session, code "
<< authentication_error->get_cryptohome_code();
StartClose();
return;
}
auth_session_broadcast_id_ = user_context_->GetBroadcastId();
UserDataAuthClient::Get()->AddAuthFactorStatusUpdateObserver(this);
available_factors_.Clear();
const auto& auth_factors = user_context_->GetAuthFactorsData();
if (auth_factors.FindAnyPasswordFactor()) {
available_factors_.Put(AuthInputType::kPassword);
}
auto* pin_factor = auth_factors.FindPinFactor();
if (pin_factor) {
if (!pin_factor->GetPinStatus().IsLockedFactor()) {
available_factors_.Put(AuthInputType::kPin);
}
}
if (available_factors_.empty() && pin_factor == nullptr) {
LOG(ERROR) << "No password/PIN found for user.";
StartClose();
return;
}
uma_recorder_.RecordShow(auth_request_->GetAuthReason(), available_factors_);
MaybePrepareFingerprint(
BindOnce(&ActiveSessionAuthControllerImpl::AuthFactorsAreReady,
weak_ptr_factory_.GetWeakPtr()));
}
void ActiveSessionAuthControllerImpl::MaybePrepareFingerprint(
AuthFactorsReadyCallback on_auth_factors_ready) {
// If the fingerprint factor is allowed to use by the user for the current
// reason then start it before initialize the UI.
if (fp_client_ && fp_client_->IsFingerprintAvailable(
auth_request_->GetAuthReason(), account_id_)) {
VLOG(1) << "PrepareFingerprintAuth started.";
fp_client_->PrepareFingerprintAuth(
std::move(user_context_),
/* auth_ready_callback = */
base::BindOnce(&ActiveSessionAuthControllerImpl::OnFingerprintReady,
weak_ptr_factory_.GetWeakPtr(),
std::move(on_auth_factors_ready)),
/* on_scan_callback = */
base::BindRepeating(&ActiveSessionAuthControllerImpl::OnFingerprintScan,
weak_ptr_factory_.GetWeakPtr()));
return;
}
std::move(on_auth_factors_ready).Run(std::move(user_context_));
}
void ActiveSessionAuthControllerImpl::OnFingerprintReady(
AuthFactorsReadyCallback on_auth_factors_ready,
std::unique_ptr<UserContext> user_context,
std::optional<AuthenticationError> authentication_error) {
if (authentication_error.has_value()) {
LOG(ERROR) << "Failed to start fingerprint auth session - only "
"non-fingerprint factors will be available.";
} else {
fp_auth_tracker_ = std::make_unique<FingerprintAuthTracker>(this);
available_factors_.Put(AuthInputType::kFingerprint);
}
std::move(on_auth_factors_ready).Run(std::move(user_context));
}
void ActiveSessionAuthControllerImpl::AuthFactorsAreReady(
std::unique_ptr<UserContext> user_context) {
user_context_ = std::move(user_context);
InitUi();
}
void ActiveSessionAuthControllerImpl::OnFingerprintScan(
const FingerprintAuthScanResult scan_result) {
CHECK(!ActiveSessionAuthControllerImpl::IsPreInitializedState());
// Avoid unnecessary processing if we've already initiated close.
if (IsSucceedState() || state_ == ActiveSessionAuthState::kCloseRequested) {
return;
}
switch (scan_result) {
case FingerprintAuthScanResult::kSuccess:
contents_view_->NotifyFingerprintAuthSuccess(
base::BindOnce(&FingerprintAuthTracker::OnAnimationFinished,
base::Unretained(fp_auth_tracker_.get())));
if (state_ == ActiveSessionAuthState::kPasswordAuthStarted ||
state_ == ActiveSessionAuthState::kPinAuthStarted) {
SetState(ActiveSessionAuthState::kFingerprintAuthSucceededWaiting);
// The user_context_ is not available, we have to wait for the
// OnAuthComplete callback to have UserContext.
return;
}
HandleFingerprintAuthSuccess();
return;
case FingerprintAuthScanResult::kTooManyAttempts:
uma_recorder_.RecordAuthFailed(AuthInputType::kFingerprint);
contents_view_->SetFingerprintState(
FingerprintState::DISABLED_FROM_ATTEMPTS);
return;
case FingerprintAuthScanResult::kFailed:
uma_recorder_.RecordAuthFailed(AuthInputType::kFingerprint);
contents_view_->NotifyFingerprintAuthFailure();
return;
case FingerprintAuthScanResult::kFatalError:
contents_view_->SetFingerprintState(FingerprintState::UNAVAILABLE);
return;
}
NOTREACHED();
}
void ActiveSessionAuthControllerImpl::HandleFingerprintAuthSuccess() {
CHECK(user_context_);
uma_recorder_.RecordAuthSucceeded(AuthInputType::kFingerprint);
SetState(ActiveSessionAuthState::kFingerprintAuthSucceeded);
auth_performer_->AuthenticateWithLegacyFingerprint(
std::move(user_context_),
base::BindOnce(&FingerprintAuthTracker::OnAuthenticationFinished,
base::Unretained(fp_auth_tracker_.get())));
}
void ActiveSessionAuthControllerImpl::InitUi() {
auto contents_view = std::make_unique<ActiveSessionAuthView>(
account_id_, title_, description_, available_factors_);
contents_view_ = contents_view.get();
views::Widget::InitParams params(
views::Widget::InitParams::CLIENT_OWNS_WIDGET,
views::Widget::InitParams::TYPE_WINDOW_FRAMELESS);
params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent;
params.delegate = new views::WidgetDelegate();
params.show_state = ui::mojom::WindowShowState::kNormal;
CHECK_EQ(Shell::Get()->session_controller()->GetSessionState(),
session_manager::SessionState::ACTIVE);
params.parent = Shell::GetPrimaryRootWindow()->GetChildById(
kShellWindowId_SystemModalContainer);
params.autosize = true;
params.name = "AuthDialogWidget";
params.delegate->SetInitiallyFocusedView(contents_view.get());
params.delegate->SetModalType(ui::mojom::ModalType::kSystem);
params.delegate->SetOwnedByWidget(
views::WidgetDelegate::OwnedByWidgetPassKey());
widget_ = std::make_unique<views::Widget>();
widget_->Init(std::move(params));
widget_->SetVisibilityAnimationTransition(views::Widget::ANIMATE_NONE);
widget_->SetContentsView(std::move(contents_view));
contents_view_observer_.Observe(contents_view_);
contents_view_->AddObserver(this);
SetState(ActiveSessionAuthState::kInitialized);
const auto& auth_factors = user_context_->GetAuthFactorsData();
auto* pin_factor = auth_factors.FindPinFactor();
if (pin_factor) {
contents_view_->SetPinStatus(
std::make_unique<cryptohome::PinStatus>(pin_factor->GetPinStatus()));
}
MoveToTheCenter();
widget_->Show();
ash::AuthParts::Get()
->GetAuthSurfaceRegistry()
->NotifyInSessionAuthDialogShown();
}
void ActiveSessionAuthControllerImpl::StartClose() {
VLOG(1) << "Close with : " << ActiveSessionAuthStateToString(state_)
<< " state.";
CHECK(user_context_);
CHECK(auth_request_);
CHECK(auth_performer_);
if (!IsPreInitializedState()) {
uma_recorder_.RecordClose();
}
if (Shell::Get() && Shell::Get()->session_controller()) {
Shell::Get()->session_controller()->RemoveObserver(this);
}
contents_view_observer_.Reset();
if (contents_view_) {
contents_view_->RemoveObserver(this);
contents_view_ = nullptr;
} else {
CHECK(IsPreInitializedState());
}
auth_session_broadcast_id_.clear();
UserDataAuthClient::Get()->RemoveAuthFactorStatusUpdateObserver(this);
auth_performer_->InvalidateCurrentAttempts();
if (fp_client_ && available_factors_.Has(AuthInputType::kFingerprint)) {
CHECK(fp_auth_tracker_);
fp_client_->TerminateFingerprintAuth(
std::move(user_context_),
base::BindOnce(&ActiveSessionAuthControllerImpl::CompleteClose,
weak_ptr_factory_.GetWeakPtr()));
return;
}
CHECK(!fp_auth_tracker_);
CompleteClose(std::move(user_context_), std::nullopt);
}
void ActiveSessionAuthControllerImpl::CompleteClose(
std::unique_ptr<UserContext> user_context,
std::optional<AuthenticationError> authentication_error) {
user_context_ = std::move(user_context);
CHECK(user_context_);
CHECK(auth_request_);
auth_performer_.reset();
auth_factor_editor_.reset();
if (IsSucceedState()) {
auth_request_->NotifyAuthSuccess(std::move(user_context_));
} else {
auth_request_->NotifyAuthFailure();
user_context_.reset();
}
auth_request_.reset();
available_factors_.Clear();
SetState(ActiveSessionAuthState::kOnIdle);
title_.clear();
description_.clear();
fp_auth_tracker_.reset();
widget_.reset();
}
void ActiveSessionAuthControllerImpl::OnSessionStateChanged(
session_manager::SessionState session_state) {
if (session_state == session_manager::SessionState::ACTIVE) {
return;
}
VLOG(1) << "SessionState changed, closing process started";
switch (state_) {
case ActiveSessionAuthState::kOnIdle:
case ActiveSessionAuthState::kWaitForInit:
case ActiveSessionAuthState::kInitialized:
StartClose();
return;
case ActiveSessionAuthState::kPasswordAuthStarted:
case ActiveSessionAuthState::kPinAuthStarted:
SetState(ActiveSessionAuthState::kCloseRequested);
return;
case ActiveSessionAuthState::kPasswordAuthSucceeded:
case ActiveSessionAuthState::kPinAuthSucceeded:
case ActiveSessionAuthState::kFingerprintAuthSucceeded:
case ActiveSessionAuthState::kFingerprintAuthSucceededWaiting:
case ActiveSessionAuthState::kCloseRequested:
return;
}
NOTREACHED();
}
void ActiveSessionAuthControllerImpl::OnViewPreferredSizeChanged(
views::View* observed_view) {
MoveToTheCenter();
}
void ActiveSessionAuthControllerImpl::MoveToTheCenter() {
widget_->CenterWindow(widget_->GetContentsView()->GetPreferredSize());
}
void ActiveSessionAuthControllerImpl::OnPasswordSubmit(
std::u16string_view password) {
if (IsSucceedState()) {
return;
}
SetState(ActiveSessionAuthState::kPasswordAuthStarted);
uma_recorder_.RecordAuthStarted(AuthInputType::kPassword);
CHECK(user_context_);
const auto* password_factor =
user_context_->GetAuthFactorsData().FindAnyPasswordFactor();
CHECK(password_factor);
const cryptohome::KeyLabel key_label = password_factor->ref().label();
auth_performer_->AuthenticateWithPassword(
key_label.value(), base::UTF16ToUTF8(password), std::move(user_context_),
base::BindOnce(&ActiveSessionAuthControllerImpl::OnAuthComplete,
weak_ptr_factory_.GetWeakPtr(), AuthInputType::kPassword));
}
void ActiveSessionAuthControllerImpl::OnPinSubmit(std::u16string_view pin) {
if (IsSucceedState()) {
return;
}
SetState(ActiveSessionAuthState::kPinAuthStarted);
uma_recorder_.RecordAuthStarted(AuthInputType::kPin);
CHECK(user_context_);
user_manager::KnownUser known_user(Shell::Get()->local_state());
const std::string salt = GetUserSalt(account_id_);
auth_performer_->AuthenticateWithPin(
base::UTF16ToUTF8(pin), salt, std::move(user_context_),
base::BindOnce(&ActiveSessionAuthControllerImpl::OnAuthComplete,
weak_ptr_factory_.GetWeakPtr(), AuthInputType::kPin));
}
void ActiveSessionAuthControllerImpl::OnAuthComplete(
AuthInputType input_type,
std::unique_ptr<UserContext> user_context,
std::optional<AuthenticationError> authentication_error) {
user_context_ = std::move(user_context);
// If fingerprint auth succeeded during wait for PIN/password authentication,
// handle success directly.
if (state_ == ActiveSessionAuthState::kFingerprintAuthSucceededWaiting) {
HandleFingerprintAuthSuccess();
return;
}
CHECK(!IsSucceedState());
if (state_ == ActiveSessionAuthState::kCloseRequested) {
StartClose();
return;
}
if (authentication_error.has_value()) {
uma_recorder_.RecordAuthFailed(input_type);
contents_view_->SetErrorTitle(l10n_util::GetStringUTF16(
input_type == AuthInputType::kPassword
? IDS_ASH_IN_SESSION_AUTH_PASSWORD_INCORRECT
: IDS_ASH_IN_SESSION_AUTH_PIN_INCORRECT));
SetState(ActiveSessionAuthState::kInitialized);
} else {
uma_recorder_.RecordAuthSucceeded(input_type);
SetState(input_type == AuthInputType::kPassword
? ActiveSessionAuthState::kPasswordAuthSucceeded
: ActiveSessionAuthState::kPinAuthSucceeded);
StartClose();
}
}
void ActiveSessionAuthControllerImpl::OnClose() {
switch (state_) {
case ActiveSessionAuthState::kOnIdle:
case ActiveSessionAuthState::kWaitForInit:
NOTREACHED();
case ActiveSessionAuthState::kInitialized:
StartClose();
return;
case ActiveSessionAuthState::kPasswordAuthStarted:
case ActiveSessionAuthState::kPinAuthStarted:
SetState(ActiveSessionAuthState::kCloseRequested);
return;
case ActiveSessionAuthState::kPasswordAuthSucceeded:
case ActiveSessionAuthState::kPinAuthSucceeded:
case ActiveSessionAuthState::kFingerprintAuthSucceeded:
case ActiveSessionAuthState::kFingerprintAuthSucceededWaiting:
case ActiveSessionAuthState::kCloseRequested:
return;
}
NOTREACHED();
}
void ActiveSessionAuthControllerImpl::SetState(ActiveSessionAuthState state) {
VLOG(1) << "SetState is requested from: "
<< ActiveSessionAuthStateToString(state_)
<< " state to : " << ActiveSessionAuthStateToString(state)
<< " state.";
switch (state) {
case ActiveSessionAuthState::kOnIdle:
break;
case ActiveSessionAuthState::kWaitForInit:
CHECK(state_ == ActiveSessionAuthState::kOnIdle);
break;
case ActiveSessionAuthState::kInitialized:
CHECK(state_ == ActiveSessionAuthState::kWaitForInit ||
state_ == ActiveSessionAuthState::kPasswordAuthStarted ||
state_ == ActiveSessionAuthState::kPinAuthStarted);
contents_view_->SetInputEnabled(true);
break;
case ActiveSessionAuthState::kPasswordAuthStarted:
// Disable the UI while we are waiting for the response, except the close
// button.
CHECK_EQ(state_, ActiveSessionAuthState::kInitialized);
contents_view_->SetInputEnabled(false);
break;
case ActiveSessionAuthState::kPasswordAuthSucceeded:
CHECK_EQ(state_, ActiveSessionAuthState::kPasswordAuthStarted);
break;
case ActiveSessionAuthState::kPinAuthStarted:
CHECK_EQ(state_, ActiveSessionAuthState::kInitialized);
contents_view_->SetInputEnabled(false);
break;
case ActiveSessionAuthState::kPinAuthSucceeded:
CHECK_EQ(state_, ActiveSessionAuthState::kPinAuthStarted);
break;
case ActiveSessionAuthState::kFingerprintAuthSucceeded:
CHECK(state_ == ActiveSessionAuthState::kInitialized ||
state_ == ActiveSessionAuthState::kFingerprintAuthSucceededWaiting);
contents_view_->SetInputEnabled(false);
break;
case ActiveSessionAuthState::kFingerprintAuthSucceededWaiting:
CHECK(state_ == ActiveSessionAuthState::kPasswordAuthStarted ||
state_ == ActiveSessionAuthState::kPinAuthStarted);
contents_view_->SetInputEnabled(false);
break;
case ActiveSessionAuthState::kCloseRequested:
CHECK(state_ == ActiveSessionAuthState::kPasswordAuthStarted ||
state_ == ActiveSessionAuthState::kPinAuthStarted);
contents_view_->SetInputEnabled(false);
break;
}
state_ = state;
}
void ActiveSessionAuthControllerImpl::OnAuthFactorStatusUpdate(
const user_data_auth::AuthFactorStatusUpdate& update) {
switch (state_) {
case ActiveSessionAuthState::kInitialized:
case ActiveSessionAuthState::kPinAuthStarted:
case ActiveSessionAuthState::kPasswordAuthStarted:
CHECK_NE(auth_session_broadcast_id_, "");
if (auth_session_broadcast_id_ == update.broadcast_id()) {
auto auth_factor = cryptohome::DeserializeAuthFactor(
update.auth_factor_with_status(),
/*fallback_type=*/cryptohome::AuthFactorType::kPassword);
if (auth_factor.ref().type() == cryptohome::AuthFactorType::kPin) {
auto pin_status = auth_factor.GetPinStatus();
contents_view_->SetPinStatus(
std::make_unique<cryptohome::PinStatus>(pin_status));
}
}
return;
case ActiveSessionAuthState::kOnIdle:
case ActiveSessionAuthState::kWaitForInit:
return;
case ActiveSessionAuthState::kPasswordAuthSucceeded:
case ActiveSessionAuthState::kPinAuthSucceeded:
case ActiveSessionAuthState::kFingerprintAuthSucceeded:
case ActiveSessionAuthState::kFingerprintAuthSucceededWaiting:
case ActiveSessionAuthState::kCloseRequested:
// No need to handle PIN updates as dialog closing is in progress.
return;
}
NOTREACHED();
}
} // namespace ash