Commit 947f2470 authored by Jacob Dufault's avatar Jacob Dufault Committed by Commit Bot

cros: Simplify fingerprint mojom between ash and chrome

- Renamed FingerprintUnlockState to FingerprintState
- FingerprintState no longer has AUTH_FAILED and AUTH_SUCCESS. FingerprintState
  instead determines if fingerprint is enabled. A seperate mojom method is used
  to notify the ash that an authentication attempt has taken place.
- Reordered fingerprint mojom method so it is next to PIN
- Eliminated ScreenLocker::FingerprintState, which duplicated the mojom type
- Fixed a bug in screen_locker.cc where timing out PIN depended on fingerprint
  being enabled.
- Backlights being forced off is now reset only after an authentication attempt.
  This means that fingerprint timing out will not turn the display on.
- Lock screen is now initialized with full fingerprint state instead of a bool.
- Renamed some methods to increase clarity

Bug: 897226
Change-Id: I841c7bbdd32730532148ddae96e1b490bee4eb0a
Reviewed-on: https://chromium-review.googlesource.com/c/1291998Reviewed-by: default avatarGreg Kerr <kerrnel@chromium.org>
Reviewed-by: default avatarWenzhao (Colin) Zang <wzang@chromium.org>
Commit-Queue: Jacob Dufault <jdufault@chromium.org>
Cr-Commit-Position: refs/heads/master@{#602450}
parent 3316e466
...@@ -382,6 +382,19 @@ void LoginScreenController::SetPinEnabledForUser(const AccountId& account_id, ...@@ -382,6 +382,19 @@ void LoginScreenController::SetPinEnabledForUser(const AccountId& account_id,
DataDispatcher()->SetPinEnabledForUser(account_id, is_enabled); DataDispatcher()->SetPinEnabledForUser(account_id, is_enabled);
} }
void LoginScreenController::SetFingerprintState(const AccountId& account_id,
mojom::FingerprintState state) {
if (DataDispatcher())
DataDispatcher()->SetFingerprintState(account_id, state);
}
void LoginScreenController::NotifyFingerprintAuthResult(
const AccountId& account_id,
bool successful) {
if (DataDispatcher())
DataDispatcher()->NotifyFingerprintAuthResult(account_id, successful);
}
void LoginScreenController::SetAvatarForUser(const AccountId& account_id, void LoginScreenController::SetAvatarForUser(const AccountId& account_id,
mojom::UserAvatarPtr avatar) { mojom::UserAvatarPtr avatar) {
for (auto& observer : observers_) for (auto& observer : observers_)
...@@ -447,13 +460,6 @@ void LoginScreenController::SetPublicSessionKeyboardLayouts( ...@@ -447,13 +460,6 @@ void LoginScreenController::SetPublicSessionKeyboardLayouts(
} }
} }
void LoginScreenController::SetFingerprintUnlockState(
const AccountId& account_id,
mojom::FingerprintUnlockState state) {
if (DataDispatcher())
DataDispatcher()->SetFingerprintUnlockState(account_id, state);
}
void LoginScreenController::SetKioskApps( void LoginScreenController::SetKioskApps(
std::vector<mojom::KioskAppInfoPtr> kiosk_apps) { std::vector<mojom::KioskAppInfoPtr> kiosk_apps) {
Shelf::ForWindow(Shell::Get()->GetPrimaryRootWindow()) Shelf::ForWindow(Shell::Get()->GetPrimaryRootWindow())
......
...@@ -121,6 +121,10 @@ class ASH_EXPORT LoginScreenController : public mojom::LoginScreen { ...@@ -121,6 +121,10 @@ class ASH_EXPORT LoginScreenController : public mojom::LoginScreen {
void SetUserList(std::vector<mojom::LoginUserInfoPtr> users) override; void SetUserList(std::vector<mojom::LoginUserInfoPtr> users) override;
void SetPinEnabledForUser(const AccountId& account_id, void SetPinEnabledForUser(const AccountId& account_id,
bool is_enabled) override; bool is_enabled) override;
void SetFingerprintState(const AccountId& account_id,
mojom::FingerprintState state) override;
void NotifyFingerprintAuthResult(const AccountId& account_id,
bool successful) override;
void SetAvatarForUser(const AccountId& account_id, void SetAvatarForUser(const AccountId& account_id,
mojom::UserAvatarPtr avatar) override; mojom::UserAvatarPtr avatar) override;
void SetAuthEnabledForUser( void SetAuthEnabledForUser(
...@@ -143,8 +147,6 @@ class ASH_EXPORT LoginScreenController : public mojom::LoginScreen { ...@@ -143,8 +147,6 @@ class ASH_EXPORT LoginScreenController : public mojom::LoginScreen {
const AccountId& account_id, const AccountId& account_id,
const std::string& locale, const std::string& locale,
std::vector<mojom::InputMethodItemPtr> keyboard_layouts) override; std::vector<mojom::InputMethodItemPtr> keyboard_layouts) override;
void SetFingerprintUnlockState(const AccountId& account_id,
mojom::FingerprintUnlockState state) override;
void SetKioskApps(std::vector<mojom::KioskAppInfoPtr> kiosk_apps) override; void SetKioskApps(std::vector<mojom::KioskAppInfoPtr> kiosk_apps) override;
void ShowKioskAppError(const std::string& message) override; void ShowKioskAppError(const std::string& message) override;
void NotifyOobeDialogState(mojom::OobeDialogState state) override; void NotifyOobeDialogState(mojom::OobeDialogState state) override;
......
...@@ -324,9 +324,7 @@ views::View* LockContentsView::TestApi::main_view() const { ...@@ -324,9 +324,7 @@ views::View* LockContentsView::TestApi::main_view() const {
LockContentsView::UserState::UserState(const mojom::LoginUserInfoPtr& user_info) LockContentsView::UserState::UserState(const mojom::LoginUserInfoPtr& user_info)
: account_id(user_info->basic_user_info->account_id) { : account_id(user_info->basic_user_info->account_id) {
fingerprint_state = user_info->allow_fingerprint_unlock fingerprint_state = user_info->fingerprint_state;
? mojom::FingerprintUnlockState::AVAILABLE
: mojom::FingerprintUnlockState::UNAVAILABLE;
if (user_info->auth_type == proximity_auth::mojom::AuthType::ONLINE_SIGN_IN) if (user_info->auth_type == proximity_auth::mojom::AuthType::ONLINE_SIGN_IN)
force_online_sign_in = true; force_online_sign_in = true;
} }
...@@ -632,6 +630,82 @@ void LockContentsView::OnPinEnabledForUserChanged(const AccountId& user, ...@@ -632,6 +630,82 @@ void LockContentsView::OnPinEnabledForUserChanged(const AccountId& user,
LayoutAuth(big_user, nullptr /*opt_to_hide*/, true /*animate*/); LayoutAuth(big_user, nullptr /*opt_to_hide*/, true /*animate*/);
} }
void LockContentsView::OnFingerprintStateChanged(
const AccountId& account_id,
mojom::FingerprintState state) {
UserState* user_state = FindStateForUser(account_id);
if (!user_state)
return;
user_state->fingerprint_state = state;
LoginBigUserView* big_view =
TryToFindBigUser(account_id, true /*require_auth_active*/);
if (!big_view || !big_view->auth_user())
return;
// TODO(crbug.com/893298): Re-enable animation once the error bubble supports
// being displayed on the left. This also requires that we dynamically
// track/update the position of the bubble, or alternatively we set the bubble
// location to the target animation position and not the current position.
bool animate = true;
if (user_state->fingerprint_state ==
mojom::FingerprintState::DISABLED_FROM_TIMEOUT) {
animate = false;
}
big_view->auth_user()->SetFingerprintState(user_state->fingerprint_state);
LayoutAuth(big_view, nullptr /*opt_to_hide*/, animate);
if (user_state->fingerprint_state ==
mojom::FingerprintState::DISABLED_FROM_TIMEOUT) {
base::string16 error_text = l10n_util::GetStringUTF16(
IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_DISABLED_FROM_TIMEOUT);
auto* label = new views::Label(error_text);
label->SetAutoColorReadabilityEnabled(false);
label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
label->SetEnabledColor(SK_ColorWHITE);
label->SetSubpixelRenderingEnabled(false);
const gfx::FontList& base_font_list = views::Label::GetDefaultFontList();
label->SetFontList(base_font_list.Derive(0, gfx::Font::FontStyle::NORMAL,
gfx::Font::Weight::NORMAL));
label->SetMultiLine(true);
label->SetAllowCharacterBreak(true);
// Make sure to set a maximum label width, otherwise text wrapping will
// significantly increase width and layout may not work correctly if
// the input string is very long.
label->SetMaximumWidth(
big_view->auth_user()->password_view()->GetPreferredSize().width());
auto* container = new NonAccessibleView();
container->SetLayoutManager(
std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical));
container->AddChildView(label);
auth_error_bubble_->ShowErrorBubble(
container, big_view->auth_user()->password_view() /*anchor_view*/,
LoginBubble::kFlagPersistent);
}
}
void LockContentsView::OnFingerprintAuthResult(const AccountId& account_id,
bool success) {
// Make sure the display backlight is not forced off if there is a fingerprint
// authentication attempt. If the display backlight is off, then the device
// will authenticate and dismiss the lock screen but it will not be visible to
// the user.
Shell::Get()->power_button_controller()->StopForcingBacklightsOff();
// |account_id| comes from IPC, make sure it refers to a valid user. The
// fingerprint scan could have also happened while switching users, so the
// associated account is no longer a big user.
LoginBigUserView* big_view =
TryToFindBigUser(account_id, true /*require_auth_active*/);
if (!big_view || !big_view->auth_user())
return;
big_view->auth_user()->NotifyFingerprintAuthResult(success);
}
void LockContentsView::OnAuthEnabledForUserChanged( void LockContentsView::OnAuthEnabledForUserChanged(
const AccountId& user, const AccountId& user,
bool enabled, bool enabled,
...@@ -895,69 +969,6 @@ void LockContentsView::OnDetachableBasePairingStatusChanged( ...@@ -895,69 +969,6 @@ void LockContentsView::OnDetachableBasePairingStatusChanged(
GetWidget()->GetFocusManager()->ClearFocus(); GetWidget()->GetFocusManager()->ClearFocus();
} }
void LockContentsView::OnFingerprintUnlockStateChanged(
const AccountId& account_id,
mojom::FingerprintUnlockState state) {
// Make sure the display backlight is not forced off if there is a fingerprint
// authentication attempt. If the display backlight is off, then the device
// will authenticate and dismiss the lock screen but it will not be visible to
// the user.
Shell::Get()->power_button_controller()->StopForcingBacklightsOff();
UserState* user_state = FindStateForUser(account_id);
if (!user_state)
return;
user_state->fingerprint_state = state;
LoginBigUserView* big_view =
TryToFindBigUser(account_id, true /*require_auth_active*/);
if (!big_view || !big_view->auth_user())
return;
// TODO(crbug.com/893298): Re-enable animation once the error bubble supports
// being displayed on the left. This also requires that we dynamically
// track/update the position of the bubble, or alternatively we set the bubble
// location to the target animation position and not the current position.
bool animate = true;
if (user_state->fingerprint_state ==
mojom::FingerprintUnlockState::AUTH_DISABLED_FROM_TIMEOUT) {
animate = false;
}
big_view->auth_user()->SetFingerprintState(user_state->fingerprint_state);
LayoutAuth(big_view, nullptr /*opt_to_hide*/, animate);
if (user_state->fingerprint_state ==
mojom::FingerprintUnlockState::AUTH_DISABLED_FROM_TIMEOUT) {
base::string16 error_text = l10n_util::GetStringUTF16(
IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_DISABLED_FROM_TIMEOUT);
auto* label = new views::Label(error_text);
label->SetAutoColorReadabilityEnabled(false);
label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
label->SetEnabledColor(SK_ColorWHITE);
label->SetSubpixelRenderingEnabled(false);
const gfx::FontList& base_font_list = views::Label::GetDefaultFontList();
label->SetFontList(base_font_list.Derive(0, gfx::Font::FontStyle::NORMAL,
gfx::Font::Weight::NORMAL));
label->SetMultiLine(true);
label->SetAllowCharacterBreak(true);
// Make sure to set a maximum label width, otherwise text wrapping will
// significantly increase width and layout may not work correctly if
// the input string is very long.
label->SetMaximumWidth(
big_view->auth_user()->password_view()->GetPreferredSize().width());
auto* container = new NonAccessibleView();
container->SetLayoutManager(
std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical));
container->AddChildView(label);
auth_error_bubble_->ShowErrorBubble(
container, big_view->auth_user()->password_view() /*anchor_view*/,
LoginBubble::kFlagPersistent);
}
}
void LockContentsView::SetAvatarForUser(const AccountId& account_id, void LockContentsView::SetAvatarForUser(const AccountId& account_id,
const mojom::UserAvatarPtr& avatar) { const mojom::UserAvatarPtr& avatar) {
auto replace = [&](const mojom::LoginUserInfoPtr& user) { auto replace = [&](const mojom::LoginUserInfoPtr& user) {
...@@ -1343,10 +1354,9 @@ void LockContentsView::LayoutAuth(LoginBigUserView* to_update, ...@@ -1343,10 +1354,9 @@ void LockContentsView::LayoutAuth(LoginBigUserView* to_update,
to_update_auth |= LoginAuthUserView::AUTH_PIN; to_update_auth |= LoginAuthUserView::AUTH_PIN;
if (state->enable_tap_auth) if (state->enable_tap_auth)
to_update_auth |= LoginAuthUserView::AUTH_TAP; to_update_auth |= LoginAuthUserView::AUTH_TAP;
if (state->fingerprint_state != if (state->fingerprint_state != mojom::FingerprintState::UNAVAILABLE &&
mojom::FingerprintUnlockState::UNAVAILABLE &&
state->fingerprint_state != state->fingerprint_state !=
mojom::FingerprintUnlockState::AUTH_DISABLED_FROM_TIMEOUT) { mojom::FingerprintState::DISABLED_FROM_TIMEOUT) {
to_update_auth |= LoginAuthUserView::AUTH_FINGERPRINT; to_update_auth |= LoginAuthUserView::AUTH_FINGERPRINT;
} }
......
...@@ -142,6 +142,10 @@ class ASH_EXPORT LockContentsView ...@@ -142,6 +142,10 @@ class ASH_EXPORT LockContentsView
void OnUsersChanged( void OnUsersChanged(
const std::vector<mojom::LoginUserInfoPtr>& users) override; const std::vector<mojom::LoginUserInfoPtr>& users) override;
void OnPinEnabledForUserChanged(const AccountId& user, bool enabled) override; void OnPinEnabledForUserChanged(const AccountId& user, bool enabled) override;
void OnFingerprintStateChanged(const AccountId& account_id,
mojom::FingerprintState state) override;
void OnFingerprintAuthResult(const AccountId& account_id,
bool success) override;
void OnAuthEnabledForUserChanged( void OnAuthEnabledForUserChanged(
const AccountId& user, const AccountId& user,
bool enabled, bool enabled,
...@@ -173,9 +177,6 @@ class ASH_EXPORT LockContentsView ...@@ -173,9 +177,6 @@ class ASH_EXPORT LockContentsView
const std::vector<mojom::InputMethodItemPtr>& keyboard_layouts) override; const std::vector<mojom::InputMethodItemPtr>& keyboard_layouts) override;
void OnDetachableBasePairingStatusChanged( void OnDetachableBasePairingStatusChanged(
DetachableBasePairingStatus pairing_status) override; DetachableBasePairingStatus pairing_status) override;
void OnFingerprintUnlockStateChanged(
const AccountId& account_id,
mojom::FingerprintUnlockState state) override;
// SystemTrayFocusObserver: // SystemTrayFocusObserver:
void OnFocusLeavingSystemTray(bool reverse) override; void OnFocusLeavingSystemTray(bool reverse) override;
...@@ -212,7 +213,7 @@ class ASH_EXPORT LockContentsView ...@@ -212,7 +213,7 @@ class ASH_EXPORT LockContentsView
bool force_online_sign_in = false; bool force_online_sign_in = false;
bool disable_auth = false; bool disable_auth = false;
mojom::EasyUnlockIconOptionsPtr easy_unlock_state; mojom::EasyUnlockIconOptionsPtr easy_unlock_state;
mojom::FingerprintUnlockState fingerprint_state; mojom::FingerprintState fingerprint_state;
private: private:
DISALLOW_COPY_AND_ASSIGN(UserState); DISALLOW_COPY_AND_ASSIGN(UserState);
......
...@@ -50,6 +50,27 @@ using ::testing::Mock; ...@@ -50,6 +50,27 @@ using ::testing::Mock;
namespace ash { namespace ash {
namespace {
void PressAndReleasePowerButton() {
base::SimpleTestTickClock tick_clock;
auto dispatch_power_button_event_after_delay =
[&](const base::TimeDelta& delta, bool down) {
tick_clock.Advance(delta + base::TimeDelta::FromMilliseconds(1));
Shell::Get()->power_button_controller()->OnPowerButtonEvent(
down, tick_clock.NowTicks());
base::RunLoop().RunUntilIdle();
};
// Press and release the power button to force backlights off.
dispatch_power_button_event_after_delay(
PowerButtonController::kIgnorePowerButtonAfterResumeDelay, true /*down*/);
dispatch_power_button_event_after_delay(
PowerButtonController::kIgnoreRepeatedButtonUpDelay, false /*down*/);
}
} // namespace
using LockContentsViewUnitTest = LoginTestBase; using LockContentsViewUnitTest = LoginTestBase;
using LockContentsViewKeyboardUnitTest = LoginKeyboardTestBase; using LockContentsViewKeyboardUnitTest = LoginKeyboardTestBase;
...@@ -2054,9 +2075,11 @@ TEST_F(LockContentsViewUnitTest, RemoveUserFocusMovesBackToPrimaryUser) { ...@@ -2054,9 +2075,11 @@ TEST_F(LockContentsViewUnitTest, RemoveUserFocusMovesBackToPrimaryUser) {
EXPECT_TRUE(HasFocusInAnyChildView(test_api.primary_big_view())); EXPECT_TRUE(HasFocusInAnyChildView(test_api.primary_big_view()));
} }
// Verifies that setting fingerprint state makes sure the backlights are not // Verifies that setting fingerprint state keeps the backlights forced off. A
// forced off. // fingerprint state change is not a user action, excluding too many
TEST_F(LockContentsViewUnitTest, BacklightIsNotForcedOffAfterFingerprint) { // authentication attempts, which will trigger the auth attempt flow.
TEST_F(LockContentsViewUnitTest,
BacklightRemainsForcedOffAfterFingerprintStateChange) {
// Enter tablet mode so the power button events force the backlight off. // Enter tablet mode so the power button events force the backlight off.
Shell::Get()->power_button_controller()->OnTabletModeStarted(); Shell::Get()->power_button_controller()->OnTabletModeStarted();
...@@ -2068,26 +2091,46 @@ TEST_F(LockContentsViewUnitTest, BacklightIsNotForcedOffAfterFingerprint) { ...@@ -2068,26 +2091,46 @@ TEST_F(LockContentsViewUnitTest, BacklightIsNotForcedOffAfterFingerprint) {
AddUsers(1); AddUsers(1);
SetWidget(CreateWidgetWithContent(lock)); SetWidget(CreateWidgetWithContent(lock));
// Press and release the power button to force backlights off. // Force the backlights off.
base::SimpleTestTickClock tick_clock; PressAndReleasePowerButton();
auto dispatch_power_button_event_after_delay =
[&](const base::TimeDelta& delta, bool down) {
tick_clock.Advance(delta + base::TimeDelta::FromMilliseconds(1));
Shell::Get()->power_button_controller()->OnPowerButtonEvent(
down, tick_clock.NowTicks());
base::RunLoop().RunUntilIdle();
};
dispatch_power_button_event_after_delay(
PowerButtonController::kIgnorePowerButtonAfterResumeDelay, true /*down*/);
dispatch_power_button_event_after_delay(
PowerButtonController::kIgnoreRepeatedButtonUpDelay, false /*down*/);
EXPECT_TRUE( EXPECT_TRUE(
Shell::Get()->backlights_forced_off_setter()->backlights_forced_off()); Shell::Get()->backlights_forced_off_setter()->backlights_forced_off());
// Change fingerprint state, backlight should not be forced off. // Change fingerprint state; backlights remain forced off.
data_dispatcher()->SetFingerprintUnlockState( data_dispatcher()->SetFingerprintState(
users()[0]->basic_user_info->account_id, users()[0]->basic_user_info->account_id,
mojom::FingerprintUnlockState::AUTH_FAILED); mojom::FingerprintState::DISABLED_FROM_ATTEMPTS);
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(
Shell::Get()->backlights_forced_off_setter()->backlights_forced_off());
Shell::Get()->power_button_controller()->OnTabletModeEnded();
}
// Verifies that a fingerprint authentication attempt makes sure the backlights
// are not forced off.
TEST_F(LockContentsViewUnitTest,
BacklightIsNotForcedOffAfterFingerprintAuthenticationAttempt) {
// Enter tablet mode so the power button events force the backlight off.
Shell::Get()->power_button_controller()->OnTabletModeStarted();
// Show lock screen with one normal user.
auto* lock = new LockContentsView(
mojom::TrayActionState::kNotAvailable, LockScreen::ScreenType::kLock,
data_dispatcher(),
std::make_unique<FakeLoginDetachableBaseModel>(data_dispatcher()));
AddUsers(1);
SetWidget(CreateWidgetWithContent(lock));
// Force the backlights off.
PressAndReleasePowerButton();
EXPECT_TRUE(
Shell::Get()->backlights_forced_off_setter()->backlights_forced_off());
// Validate a fingerprint authentication attempt resets backlights being
// forced off.
data_dispatcher()->NotifyFingerprintAuthResult(
users()[0]->basic_user_info->account_id, false /*successful*/);
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
EXPECT_FALSE( EXPECT_FALSE(
Shell::Get()->backlights_forced_off_setter()->backlights_forced_off()); Shell::Get()->backlights_forced_off_setter()->backlights_forced_off());
......
...@@ -58,6 +58,8 @@ enum { ...@@ -58,6 +58,8 @@ enum {
kPerUserToggleTap, kPerUserToggleTap,
kPerUserCycleEasyUnlockState, kPerUserCycleEasyUnlockState,
kPerUserCycleFingerprintState, kPerUserCycleFingerprintState,
kPerUserAuthFingerprintSuccessState,
kPerUserAuthFingerprintFailState,
kPerUserForceOnlineSignIn, kPerUserForceOnlineSignIn,
kPerUserToggleAuthEnabled, kPerUserToggleAuthEnabled,
kPerUserUseDetachableBase, kPerUserUseDetachableBase,
...@@ -103,8 +105,8 @@ struct UserMetadata { ...@@ -103,8 +105,8 @@ struct UserMetadata {
bool enable_auth = true; bool enable_auth = true;
user_manager::UserType type = user_manager::USER_TYPE_REGULAR; user_manager::UserType type = user_manager::USER_TYPE_REGULAR;
mojom::EasyUnlockIconId easy_unlock_id = mojom::EasyUnlockIconId::NONE; mojom::EasyUnlockIconId easy_unlock_id = mojom::EasyUnlockIconId::NONE;
mojom::FingerprintUnlockState fingerprint_state = mojom::FingerprintState fingerprint_state =
mojom::FingerprintUnlockState::UNAVAILABLE; mojom::FingerprintState::UNAVAILABLE;
}; };
std::string DetachableBasePairingStatusToString( std::string DetachableBasePairingStatusToString(
...@@ -319,15 +321,21 @@ class LockDebugView::DebugDataDispatcherTransformer ...@@ -319,15 +321,21 @@ class LockDebugView::DebugDataDispatcherTransformer
} }
// Enables fingerprint auth for the user at |user_index|. // Enables fingerprint auth for the user at |user_index|.
void CycleFingerprintUnlockForUserIndex(size_t user_index) { void CycleFingerprintStateForUserIndex(size_t user_index) {
DCHECK(user_index >= 0 && user_index < debug_users_.size()); DCHECK(user_index >= 0 && user_index < debug_users_.size());
UserMetadata* debug_user = &debug_users_[user_index]; UserMetadata* debug_user = &debug_users_[user_index];
debug_user->fingerprint_state = static_cast<mojom::FingerprintUnlockState>( debug_user->fingerprint_state = static_cast<mojom::FingerprintState>(
(static_cast<int>(debug_user->fingerprint_state) + 1) % (static_cast<int>(debug_user->fingerprint_state) + 1) %
(static_cast<int>(mojom::FingerprintUnlockState::kMaxValue) + 1)); (static_cast<int>(mojom::FingerprintState::kMaxValue) + 1));
debug_dispatcher_.SetFingerprintUnlockState(debug_user->account_id, debug_dispatcher_.SetFingerprintState(debug_user->account_id,
debug_user->fingerprint_state); debug_user->fingerprint_state);
}
void AuthenticateFingerprintForUserIndex(size_t user_index, bool success) {
DCHECK(user_index >= 0 && user_index < debug_users_.size());
UserMetadata* debug_user = &debug_users_[user_index];
debug_dispatcher_.NotifyFingerprintAuthResult(debug_user->account_id,
success);
} }
// Force online sign-in for the user at |user_index|. // Force online sign-in for the user at |user_index|.
...@@ -939,7 +947,15 @@ void LockDebugView::ButtonPressed(views::Button* sender, ...@@ -939,7 +947,15 @@ void LockDebugView::ButtonPressed(views::Button* sender,
// Cycle fingerprint unlock state. // Cycle fingerprint unlock state.
if (sender->id() == ButtonId::kPerUserCycleFingerprintState) if (sender->id() == ButtonId::kPerUserCycleFingerprintState)
debug_data_dispatcher_->CycleFingerprintUnlockForUserIndex(sender->tag()); debug_data_dispatcher_->CycleFingerprintStateForUserIndex(sender->tag());
if (sender->id() == ButtonId::kPerUserAuthFingerprintSuccessState) {
debug_data_dispatcher_->AuthenticateFingerprintForUserIndex(sender->tag(),
true);
}
if (sender->id() == ButtonId::kPerUserAuthFingerprintFailState) {
debug_data_dispatcher_->AuthenticateFingerprintForUserIndex(sender->tag(),
false);
}
// Force online sign-in. // Force online sign-in.
if (sender->id() == ButtonId::kPerUserForceOnlineSignIn) if (sender->id() == ButtonId::kPerUserForceOnlineSignIn)
...@@ -985,9 +1001,15 @@ void LockDebugView::UpdatePerUserActionContainer() { ...@@ -985,9 +1001,15 @@ void LockDebugView::UpdatePerUserActionContainer() {
AddButton("Toggle Tap", ButtonId::kPerUserToggleTap, row)->set_tag(i); AddButton("Toggle Tap", ButtonId::kPerUserToggleTap, row)->set_tag(i);
AddButton("Cycle easy unlock", ButtonId::kPerUserCycleEasyUnlockState, row) AddButton("Cycle easy unlock", ButtonId::kPerUserCycleEasyUnlockState, row)
->set_tag(i); ->set_tag(i);
AddButton("Cycle fingerprint unlock", AddButton("Cycle fingerprint state",
ButtonId::kPerUserCycleFingerprintState, row) ButtonId::kPerUserCycleFingerprintState, row)
->set_tag(i); ->set_tag(i);
AddButton("Send fingerprint auth success",
ButtonId::kPerUserAuthFingerprintSuccessState, row)
->set_tag(i);
AddButton("Send fingerprint auth fail",
ButtonId::kPerUserAuthFingerprintFailState, row)
->set_tag(i);
AddButton("Force online sign-in", ButtonId::kPerUserForceOnlineSignIn, row) AddButton("Force online sign-in", ButtonId::kPerUserForceOnlineSignIn, row)
->set_tag(i); ->set_tag(i);
AddButton("Toggle auth enabled", ButtonId::kPerUserToggleAuthEnabled, row) AddButton("Toggle auth enabled", ButtonId::kPerUserToggleAuthEnabled, row)
......
...@@ -156,63 +156,61 @@ void DecorateOnlineSignInMessage(views::LabelButton* label_button) { ...@@ -156,63 +156,61 @@ void DecorateOnlineSignInMessage(views::LabelButton* label_button) {
// The label shown below the fingerprint icon. // The label shown below the fingerprint icon.
class FingerprintLabel : public views::Label { class FingerprintLabel : public views::Label {
public: public:
explicit FingerprintLabel(mojom::FingerprintUnlockState state) { FingerprintLabel() {
SetSubpixelRenderingEnabled(false); SetSubpixelRenderingEnabled(false);
SetAutoColorReadabilityEnabled(false); SetAutoColorReadabilityEnabled(false);
SetEnabledColor(login_constants::kAuthMethodsTextColor); SetEnabledColor(login_constants::kAuthMethodsTextColor);
SetState(state); SetTextBasedOnState(mojom::FingerprintState::AVAILABLE);
} }
void SetState(mojom::FingerprintUnlockState state) { void SetTextBasedOnAuthAttempt(bool success) {
auto get_label_id = [&]() { SetText(l10n_util::GetStringUTF16(
success ? IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_AUTH_SUCCESS
: IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_AUTH_FAILED));
SetAccessibleName(l10n_util::GetStringUTF16(
success ? IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_ACCESSIBLE_AUTH_SUCCESS
: IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_ACCESSIBLE_AUTH_FAILED));
}
void SetTextBasedOnState(mojom::FingerprintState state) {
auto get_displayed_id = [&]() {
switch (state) { switch (state) {
case mojom::FingerprintUnlockState::UNAVAILABLE: case mojom::FingerprintState::UNAVAILABLE:
case mojom::FingerprintUnlockState::AVAILABLE: case mojom::FingerprintState::AVAILABLE:
return IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_AVAILABLE; return IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_AVAILABLE;
case mojom::FingerprintUnlockState::AUTH_SUCCESS: case mojom::FingerprintState::DISABLED_FROM_ATTEMPTS:
return IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_AUTH_SUCCESS;
case mojom::FingerprintUnlockState::AUTH_FAILED:
return IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_AUTH_FAILED;
case mojom::FingerprintUnlockState::AUTH_DISABLED:
return IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_DISABLED_FROM_ATTEMPTS; return IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_DISABLED_FROM_ATTEMPTS;
case mojom::FingerprintUnlockState::AUTH_DISABLED_FROM_TIMEOUT: case mojom::FingerprintState::DISABLED_FROM_TIMEOUT:
return IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_DISABLED_FROM_TIMEOUT; return IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_DISABLED_FROM_TIMEOUT;
} }
NOTREACHED(); NOTREACHED();
}; };
state_ = state; auto get_accessible_id = [&]() {
SetText(l10n_util::GetStringUTF16(get_label_id())); if (state == mojom::FingerprintState::DISABLED_FROM_ATTEMPTS)
NotifyAccessibilityEvent(ax::mojom::Event::kTextChanged, return IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_ACCESSIBLE_AUTH_DISABLED_FROM_ATTEMPTS;
true /*send_native_event*/); return get_displayed_id();
};
SetText(l10n_util::GetStringUTF16(get_displayed_id()));
SetAccessibleName(l10n_util::GetStringUTF16(get_accessible_id()));
} }
// views::View: // views::View:
void GetAccessibleNodeData(ui::AXNodeData* node_data) override { void GetAccessibleNodeData(ui::AXNodeData* node_data) override {
auto get_string_id = [&]() {
switch (state_) {
case mojom::FingerprintUnlockState::UNAVAILABLE:
return IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_DISABLED_FROM_TIMEOUT;
case mojom::FingerprintUnlockState::AVAILABLE:
return IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_AVAILABLE;
case mojom::FingerprintUnlockState::AUTH_SUCCESS:
return IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_ACCESSIBLE_AUTH_SUCCESS;
case mojom::FingerprintUnlockState::AUTH_FAILED:
return IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_ACCESSIBLE_AUTH_FAILED;
case mojom::FingerprintUnlockState::AUTH_DISABLED:
return IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_ACCESSIBLE_AUTH_DISABLED_FROM_ATTEMPTS;
case mojom::FingerprintUnlockState::AUTH_DISABLED_FROM_TIMEOUT:
return IDS_ASH_LOGIN_FINGERPRINT_UNLOCK_DISABLED_FROM_TIMEOUT;
}
};
node_data->role = ax::mojom::Role::kStaticText; node_data->role = ax::mojom::Role::kStaticText;
node_data->SetName(l10n_util::GetStringUTF16(get_string_id())); node_data->SetName(accessible_name_);
} }
private: private:
mojom::FingerprintUnlockState state_; void SetAccessibleName(const base::string16& name) {
accessible_name_ = name;
NotifyAccessibilityEvent(ax::mojom::Event::kTextChanged,
true /*send_native_event*/);
}
base::string16 accessible_name_;
DISALLOW_COPY_AND_ASSIGN(FingerprintLabel); DISALLOW_COPY_AND_ASSIGN(FingerprintLabel);
}; };
...@@ -240,38 +238,45 @@ class LoginAuthUserView::FingerprintView : public views::View { ...@@ -240,38 +238,45 @@ class LoginAuthUserView::FingerprintView : public views::View {
kLockScreenFingerprintIcon, kFingerprintIconSizeDp, SK_ColorWHITE)); kLockScreenFingerprintIcon, kFingerprintIconSizeDp, SK_ColorWHITE));
AddChildView(icon_); AddChildView(icon_);
label_ = new FingerprintLabel(mojom::FingerprintUnlockState::AVAILABLE); label_ = new FingerprintLabel();
AddChildView(label_); AddChildView(label_);
DisplayCurrentState();
} }
~FingerprintView() override = default; ~FingerprintView() override = default;
void SetState(mojom::FingerprintUnlockState state) { void SetState(mojom::FingerprintState state) {
if (state_ == state) if (state_ == state)
return; return;
reset_state_.Stop();
state_ = state; state_ = state;
SetVisible(state != mojom::FingerprintUnlockState::UNAVAILABLE &&
state !=
mojom::FingerprintUnlockState::AUTH_DISABLED_FROM_TIMEOUT);
SetIcon(state);
label_->SetState(state);
if (ShouldFireChromeVoxAlert(state)) {
label_->NotifyAccessibilityEvent(ax::mojom::Event::kAlert,
true /*send_native_event*/);
}
// Fingerprint icon reset to default sometime after AUTH_FAILED. DisplayCurrentState();
if (ShouldFireChromeVoxAlert(state))
FireAlert();
}
void NotifyFingerprintAuthResult(bool success) {
reset_state_.Stop(); reset_state_.Stop();
if (state == mojom::FingerprintUnlockState::AUTH_FAILED) { label_->SetTextBasedOnAuthAttempt(success);
if (success) {
icon_->SetImage(gfx::CreateVectorIcon(kLockScreenFingerprintSuccessIcon,
kFingerprintIconSizeDp,
gfx::kGoogleGreenDark500));
} else {
SetIcon(mojom::FingerprintState::DISABLED_FROM_ATTEMPTS);
// base::Unretained is safe because reset_state_ is owned by |this|. // base::Unretained is safe because reset_state_ is owned by |this|.
reset_state_.Start( reset_state_.Start(
FROM_HERE, FROM_HERE,
base::TimeDelta::FromMilliseconds(kResetToDefaultIconDelayMs), base::TimeDelta::FromMilliseconds(kResetToDefaultIconDelayMs),
base::BindRepeating(&FingerprintView::SetState, base::BindRepeating(&FingerprintView::DisplayCurrentState,
base::Unretained(this), base::Unretained(this)));
mojom::FingerprintUnlockState::AVAILABLE));
FireAlert();
} }
} }
...@@ -283,21 +288,27 @@ class LoginAuthUserView::FingerprintView : public views::View { ...@@ -283,21 +288,27 @@ class LoginAuthUserView::FingerprintView : public views::View {
} }
private: private:
void SetIcon(mojom::FingerprintUnlockState state) { void DisplayCurrentState() {
SetVisible(state_ != mojom::FingerprintState::UNAVAILABLE &&
state_ != mojom::FingerprintState::DISABLED_FROM_TIMEOUT);
SetIcon(state_);
label_->SetTextBasedOnState(state_);
}
void FireAlert() {
label_->NotifyAccessibilityEvent(ax::mojom::Event::kAlert,
true /*send_native_event*/);
}
void SetIcon(mojom::FingerprintState state) {
switch (state) { switch (state) {
case mojom::FingerprintUnlockState::UNAVAILABLE: case mojom::FingerprintState::UNAVAILABLE:
case mojom::FingerprintUnlockState::AVAILABLE: case mojom::FingerprintState::AVAILABLE:
case mojom::FingerprintUnlockState::AUTH_DISABLED_FROM_TIMEOUT: case mojom::FingerprintState::DISABLED_FROM_TIMEOUT:
icon_->SetImage(gfx::CreateVectorIcon( icon_->SetImage(gfx::CreateVectorIcon(
kLockScreenFingerprintIcon, kFingerprintIconSizeDp, SK_ColorWHITE)); kLockScreenFingerprintIcon, kFingerprintIconSizeDp, SK_ColorWHITE));
break; break;
case mojom::FingerprintUnlockState::AUTH_SUCCESS: case mojom::FingerprintState::DISABLED_FROM_ATTEMPTS:
icon_->SetImage(gfx::CreateVectorIcon(kLockScreenFingerprintSuccessIcon,
kFingerprintIconSizeDp,
gfx::kGoogleGreenDark500));
break;
case mojom::FingerprintUnlockState::AUTH_FAILED:
case mojom::FingerprintUnlockState::AUTH_DISABLED:
icon_->SetAnimationDecoder( icon_->SetAnimationDecoder(
std::make_unique<HorizontalImageSequenceAnimationDecoder>( std::make_unique<HorizontalImageSequenceAnimationDecoder>(
*ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed( *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
...@@ -310,17 +321,15 @@ class LoginAuthUserView::FingerprintView : public views::View { ...@@ -310,17 +321,15 @@ class LoginAuthUserView::FingerprintView : public views::View {
} }
} }
bool ShouldFireChromeVoxAlert(mojom::FingerprintUnlockState state) { bool ShouldFireChromeVoxAlert(mojom::FingerprintState state) {
return state == mojom::FingerprintUnlockState::AUTH_FAILED || return state == mojom::FingerprintState::DISABLED_FROM_ATTEMPTS ||
state == mojom::FingerprintUnlockState::AUTH_DISABLED || state == mojom::FingerprintState::DISABLED_FROM_TIMEOUT;
state == mojom::FingerprintUnlockState::AUTH_DISABLED_FROM_TIMEOUT;
} }
FingerprintLabel* label_ = nullptr; FingerprintLabel* label_ = nullptr;
AnimatedRoundedImageView* icon_ = nullptr; AnimatedRoundedImageView* icon_ = nullptr;
base::OneShotTimer reset_state_; base::OneShotTimer reset_state_;
mojom::FingerprintUnlockState state_ = mojom::FingerprintState state_ = mojom::FingerprintState::AVAILABLE;
mojom::FingerprintUnlockState::UNAVAILABLE;
DISALLOW_COPY_AND_ASSIGN(FingerprintView); DISALLOW_COPY_AND_ASSIGN(FingerprintView);
}; };
...@@ -808,11 +817,14 @@ void LoginAuthUserView::UpdateForUser(const mojom::LoginUserInfoPtr& user) { ...@@ -808,11 +817,14 @@ void LoginAuthUserView::UpdateForUser(const mojom::LoginUserInfoPtr& user) {
base::UTF8ToUTF16(user->basic_user_info->display_name)); base::UTF8ToUTF16(user->basic_user_info->display_name));
} }
void LoginAuthUserView::SetFingerprintState( void LoginAuthUserView::SetFingerprintState(mojom::FingerprintState state) {
mojom::FingerprintUnlockState state) {
fingerprint_view_->SetState(state); fingerprint_view_->SetState(state);
} }
void LoginAuthUserView::NotifyFingerprintAuthResult(bool success) {
fingerprint_view_->NotifyFingerprintAuthResult(success);
}
void LoginAuthUserView::SetAuthReenabledTime( void LoginAuthUserView::SetAuthReenabledTime(
const base::Time& auth_reenabled_time) { const base::Time& auth_reenabled_time) {
disabled_auth_message_->SetAuthReenabledTime(auth_reenabled_time); disabled_auth_message_->SetAuthReenabledTime(auth_reenabled_time);
......
...@@ -115,7 +115,11 @@ class ASH_EXPORT LoginAuthUserView : public NonAccessibleView, ...@@ -115,7 +115,11 @@ class ASH_EXPORT LoginAuthUserView : public NonAccessibleView,
// Update the displayed name, icon, etc to that of |user|. // Update the displayed name, icon, etc to that of |user|.
void UpdateForUser(const mojom::LoginUserInfoPtr& user); void UpdateForUser(const mojom::LoginUserInfoPtr& user);
void SetFingerprintState(mojom::FingerprintUnlockState state); // Update the current fingerprint state.
void SetFingerprintState(mojom::FingerprintState state);
// Called to show a fingerprint authentication attempt result.
void NotifyFingerprintAuthResult(bool success);
// Set the time when auth will be reenabled. It will be included in the // Set the time when auth will be reenabled. It will be included in the
// message shown to user when auth method is |AUTH_DISABLED|. // message shown to user when auth method is |AUTH_DISABLED|.
......
...@@ -15,6 +15,14 @@ void LoginDataDispatcher::Observer::OnPinEnabledForUserChanged( ...@@ -15,6 +15,14 @@ void LoginDataDispatcher::Observer::OnPinEnabledForUserChanged(
const AccountId& user, const AccountId& user,
bool enabled) {} bool enabled) {}
void LoginDataDispatcher::Observer::OnFingerprintStateChanged(
const AccountId& account_id,
mojom::FingerprintState state) {}
void LoginDataDispatcher::Observer::OnFingerprintAuthResult(
const AccountId& account_id,
bool successful) {}
void LoginDataDispatcher::Observer::OnAuthEnabledForUserChanged( void LoginDataDispatcher::Observer::OnAuthEnabledForUserChanged(
const AccountId& user, const AccountId& user,
bool enabled, bool enabled,
...@@ -63,10 +71,6 @@ void LoginDataDispatcher::Observer::OnPublicSessionKeyboardLayoutsChanged( ...@@ -63,10 +71,6 @@ void LoginDataDispatcher::Observer::OnPublicSessionKeyboardLayoutsChanged(
void LoginDataDispatcher::Observer::OnDetachableBasePairingStatusChanged( void LoginDataDispatcher::Observer::OnDetachableBasePairingStatusChanged(
DetachableBasePairingStatus pairing_status) {} DetachableBasePairingStatus pairing_status) {}
void LoginDataDispatcher::Observer::OnFingerprintUnlockStateChanged(
const AccountId& account_id,
mojom::FingerprintUnlockState state) {}
LoginDataDispatcher::LoginDataDispatcher() = default; LoginDataDispatcher::LoginDataDispatcher() = default;
LoginDataDispatcher::~LoginDataDispatcher() = default; LoginDataDispatcher::~LoginDataDispatcher() = default;
...@@ -91,6 +95,19 @@ void LoginDataDispatcher::SetPinEnabledForUser(const AccountId& user, ...@@ -91,6 +95,19 @@ void LoginDataDispatcher::SetPinEnabledForUser(const AccountId& user,
observer.OnPinEnabledForUserChanged(user, enabled); observer.OnPinEnabledForUserChanged(user, enabled);
} }
void LoginDataDispatcher::SetFingerprintState(const AccountId& account_id,
mojom::FingerprintState state) {
for (auto& observer : observers_)
observer.OnFingerprintStateChanged(account_id, state);
}
void LoginDataDispatcher::NotifyFingerprintAuthResult(
const AccountId& account_id,
bool successful) {
for (auto& observer : observers_)
observer.OnFingerprintAuthResult(account_id, successful);
}
void LoginDataDispatcher::SetAuthEnabledForUser( void LoginDataDispatcher::SetAuthEnabledForUser(
const AccountId& account_id, const AccountId& account_id,
bool is_enabled, bool is_enabled,
...@@ -179,11 +196,4 @@ void LoginDataDispatcher::SetDetachableBasePairingStatus( ...@@ -179,11 +196,4 @@ void LoginDataDispatcher::SetDetachableBasePairingStatus(
observer.OnDetachableBasePairingStatusChanged(pairing_status); observer.OnDetachableBasePairingStatusChanged(pairing_status);
} }
void LoginDataDispatcher::SetFingerprintUnlockState(
const AccountId& account_id,
mojom::FingerprintUnlockState state) {
for (auto& observer : observers_)
observer.OnFingerprintUnlockStateChanged(account_id, state);
}
} // namespace ash } // namespace ash
...@@ -49,6 +49,14 @@ class ASH_EXPORT LoginDataDispatcher { ...@@ -49,6 +49,14 @@ class ASH_EXPORT LoginDataDispatcher {
virtual void OnPinEnabledForUserChanged(const AccountId& user, virtual void OnPinEnabledForUserChanged(const AccountId& user,
bool enabled); bool enabled);
// Called when fingerprint unlock state changes for user with |account_id|.
virtual void OnFingerprintStateChanged(const AccountId& account_id,
mojom::FingerprintState state);
// Called after a fingerprint authentication attempt.
virtual void OnFingerprintAuthResult(const AccountId& account_id,
bool successful);
// Called when auth should be enabled or disabled for |user|. By default, // Called when auth should be enabled or disabled for |user|. By default,
// auth should be enabled. // auth should be enabled.
virtual void OnAuthEnabledForUserChanged( virtual void OnAuthEnabledForUserChanged(
...@@ -109,11 +117,6 @@ class ASH_EXPORT LoginDataDispatcher { ...@@ -109,11 +117,6 @@ class ASH_EXPORT LoginDataDispatcher {
// base is attached or detached. // base is attached or detached.
virtual void OnDetachableBasePairingStatusChanged( virtual void OnDetachableBasePairingStatusChanged(
DetachableBasePairingStatus pairing_status); DetachableBasePairingStatus pairing_status);
// Called when fingerprint unlock state changes for user with |account_id|.
virtual void OnFingerprintUnlockStateChanged(
const AccountId& account_id,
mojom::FingerprintUnlockState state);
}; };
LoginDataDispatcher(); LoginDataDispatcher();
...@@ -124,6 +127,10 @@ class ASH_EXPORT LoginDataDispatcher { ...@@ -124,6 +127,10 @@ class ASH_EXPORT LoginDataDispatcher {
void NotifyUsers(const std::vector<mojom::LoginUserInfoPtr>& users); void NotifyUsers(const std::vector<mojom::LoginUserInfoPtr>& users);
void SetPinEnabledForUser(const AccountId& user, bool enabled); void SetPinEnabledForUser(const AccountId& user, bool enabled);
void SetFingerprintState(const AccountId& account_id,
mojom::FingerprintState state);
void NotifyFingerprintAuthResult(const AccountId& account_id,
bool successful);
void SetAuthEnabledForUser(const AccountId& account_id, void SetAuthEnabledForUser(const AccountId& account_id,
bool is_enabled, bool is_enabled,
base::Optional<base::Time> auth_reenabled_time); base::Optional<base::Time> auth_reenabled_time);
...@@ -150,8 +157,6 @@ class ASH_EXPORT LoginDataDispatcher { ...@@ -150,8 +157,6 @@ class ASH_EXPORT LoginDataDispatcher {
const std::vector<mojom::InputMethodItemPtr>& keyboard_layouts); const std::vector<mojom::InputMethodItemPtr>& keyboard_layouts);
void SetDetachableBasePairingStatus( void SetDetachableBasePairingStatus(
DetachableBasePairingStatus pairing_status); DetachableBasePairingStatus pairing_status);
void SetFingerprintUnlockState(const AccountId& account_id,
mojom::FingerprintUnlockState state);
private: private:
base::ObserverList<Observer>::Unchecked observers_; base::ObserverList<Observer>::Unchecked observers_;
......
...@@ -114,6 +114,17 @@ interface LoginScreen { ...@@ -114,6 +114,17 @@ interface LoginScreen {
// |is_enabled|: True if pin unlock is enabled. // |is_enabled|: True if pin unlock is enabled.
SetPinEnabledForUser(signin.mojom.AccountId account_id, bool is_enabled); SetPinEnabledForUser(signin.mojom.AccountId account_id, bool is_enabled);
// Update the status of fingerprint for |account_id|.
SetFingerprintState(signin.mojom.AccountId account_id,
FingerprintState state);
// Called after a fingerprint authentication attempt has been made. If
// |successful| is true, then the fingerprint authentication attempt was
// successful and the device should be unlocked. If false, an error message
// should be shown to the user.
NotifyFingerprintAuthResult(signin.mojom.AccountId account_id,
bool successful);
// Change the user's avatar. Some avatars may take a long time to load and the // Change the user's avatar. Some avatars may take a long time to load and the
// login screen may already be visible. // login screen may already be visible.
SetAvatarForUser(signin.mojom.AccountId account_id, UserAvatar avatar); SetAvatarForUser(signin.mojom.AccountId account_id, UserAvatar avatar);
...@@ -173,10 +184,6 @@ interface LoginScreen { ...@@ -173,10 +184,6 @@ interface LoginScreen {
string locale, string locale,
array<InputMethodItem> keyboard_layouts); array<InputMethodItem> keyboard_layouts);
// Set the fingerprint unlock state for user with |account_id|.
SetFingerprintUnlockState(signin.mojom.AccountId account_id,
FingerprintUnlockState state);
// Update the kiosk app data for the login screen. // Update the kiosk app data for the login screen.
SetKioskApps(array<KioskAppInfo> kiosk_apps); SetKioskApps(array<KioskAppInfo> kiosk_apps);
......
...@@ -38,26 +38,19 @@ enum EasyUnlockIconId { ...@@ -38,26 +38,19 @@ enum EasyUnlockIconId {
SPINNER, SPINNER,
}; };
// Fingerprint unlock state in the views lock screen. // The status of fingerprint availability.
enum FingerprintUnlockState { enum FingerprintState {
// Fingerprint unlock is not available. // The user cannot use fingerprint. This may be because:
// - they are not the primary user
// - they never registered fingerprint
// - the device does not have a fingerprint sensor
UNAVAILABLE, UNAVAILABLE,
// Fingerprint unlock is available. // Fingerprint can be used to unlock the device.
AVAILABLE, AVAILABLE,
// The unlock attempt is successful, the fingerprint is matched. // There have been too many attempts, so now fingerprint is disabled.
AUTH_SUCCESS, DISABLED_FROM_ATTEMPTS,
// The unlock attempt is unsuccessful; the fingerprint is not // It has been too long since the device was last used.
// recognized; however, the user can make another fingerprint auth DISABLED_FROM_TIMEOUT,
// attempt.
AUTH_FAILED,
// The unlock attempt is unsuccessful; the fingerprint is not
// recognized. There have been too many unlock attempts and fingerprint
// is now disabled.
AUTH_DISABLED,
// Fingerprint unlock is disabled because user is forced to use an
// authentication method that authenticates via cryptohome.
// I.e., password, cryptohome-based PIN, easy unlock.
AUTH_DISABLED_FROM_TIMEOUT,
}; };
// Information about the custom icon in the user pod. // Information about the custom icon in the user pod.
...@@ -154,8 +147,9 @@ struct LoginUserInfo { ...@@ -154,8 +147,9 @@ struct LoginUserInfo {
// True if this user is the device owner. // True if this user is the device owner.
bool is_device_owner; bool is_device_owner;
// True if fingerprint unlock is allowed for this user. // The initial fingerprint state. There are other mojom methods (ie,
bool allow_fingerprint_unlock; // login_screen.mojom::SetFingerprintState) which update the current state.
FingerprintState fingerprint_state;
// True if multi-profiles sign in is allowed for this user. // True if multi-profiles sign in is allowed for this user.
bool is_multiprofile_allowed; bool is_multiprofile_allowed;
......
...@@ -90,19 +90,12 @@ namespace { ...@@ -90,19 +90,12 @@ namespace {
// unlock happens even if animations are broken. // unlock happens even if animations are broken.
const int kUnlockGuardTimeoutMs = 400; const int kUnlockGuardTimeoutMs = 400;
// Returns true if fingerprint authentication is available for one of the // Returns true if fingerprint authentication is available for |user|.
// |users|. bool IsFingerprintAvailableForUser(const user_manager::User* user) {
bool IsFingerprintAuthenticationAvailableForUsers( quick_unlock::QuickUnlockStorage* quick_unlock_storage =
const user_manager::UserList& users) { quick_unlock::QuickUnlockFactory::GetForUser(user);
for (auto* user : users) { return quick_unlock_storage &&
quick_unlock::QuickUnlockStorage* quick_unlock_storage = quick_unlock_storage->IsFingerprintAuthenticationAvailable();
quick_unlock::QuickUnlockFactory::GetForUser(user);
if (quick_unlock_storage &&
quick_unlock_storage->IsFingerprintAuthenticationAvailable()) {
return true;
}
}
return false;
} }
// Observer to start ScreenLocker when locking the screen is requested. // Observer to start ScreenLocker when locking the screen is requested.
...@@ -674,7 +667,10 @@ void ScreenLocker::ScreenLockReady() { ...@@ -674,7 +667,10 @@ void ScreenLocker::ScreenLockReady() {
->GetActiveIMEState() ->GetActiveIMEState()
->EnableLockScreenLayouts(); ->EnableLockScreenLayouts();
if (IsFingerprintAuthenticationAvailableForUsers(users_)) { // Start a fingerprint authentication session if fingerprint is available for
// the primary user. Only the primary user can use fingerprint.
if (IsFingerprintAvailableForUser(
user_manager::UserManager::Get()->GetPrimaryUser())) {
VLOG(1) << "Fingerprint is available on lock screen, start fingerprint " VLOG(1) << "Fingerprint is available on lock screen, start fingerprint "
<< "auth session now."; << "auth session now.";
fp_service_->StartAuthSession(); fp_service_->StartAuthSession();
...@@ -682,7 +678,7 @@ void ScreenLocker::ScreenLockReady() { ...@@ -682,7 +678,7 @@ void ScreenLocker::ScreenLockReady() {
VLOG(1) << "Fingerprint is not available on lock screen"; VLOG(1) << "Fingerprint is not available on lock screen";
} }
UpdateFingerprintState( MaybeDisablePinAndFingerprintFromTimeout(
"ScreenLockReady", "ScreenLockReady",
user_manager::UserManager::Get()->GetPrimaryUser()->GetAccountId()); user_manager::UserManager::Get()->GetPrimaryUser()->GetAccountId());
} }
...@@ -727,8 +723,8 @@ void ScreenLocker::OnAuthScanDone( ...@@ -727,8 +723,8 @@ void ScreenLocker::OnAuthScanDone(
OnFingerprintAuthFailure(*active_user); OnFingerprintAuthFailure(*active_user);
return; return;
} }
delegate_->SetFingerprintState(active_user->GetAccountId(), delegate_->NotifyFingerprintAuthResult(active_user->GetAccountId(),
FingerprintState::kSignin); true /*success*/);
VLOG(1) << "Fingerprint unlock is successful."; VLOG(1) << "Fingerprint unlock is successful.";
LoginScreenClient::Get()->auth_recorder()->RecordFingerprintAuthSuccess( LoginScreenClient::Get()->auth_recorder()->RecordFingerprintAuthSuccess(
true /*success*/, true /*success*/,
...@@ -745,8 +741,8 @@ void ScreenLocker::OnFingerprintAuthFailure(const user_manager::User& user) { ...@@ -745,8 +741,8 @@ void ScreenLocker::OnFingerprintAuthFailure(const user_manager::User& user) {
unlock_attempt_type_, UnlockType::AUTH_COUNT); unlock_attempt_type_, UnlockType::AUTH_COUNT);
LoginScreenClient::Get()->auth_recorder()->RecordFingerprintAuthSuccess( LoginScreenClient::Get()->auth_recorder()->RecordFingerprintAuthSuccess(
false /*success*/, base::nullopt /*num_attempts*/); false /*success*/, base::nullopt /*num_attempts*/);
delegate_->SetFingerprintState(user.GetAccountId(), delegate_->NotifyFingerprintAuthResult(user.GetAccountId(),
FingerprintState::kFailed); false /*success*/);
quick_unlock::QuickUnlockStorage* quick_unlock_storage = quick_unlock::QuickUnlockStorage* quick_unlock_storage =
quick_unlock::QuickUnlockFactory::GetForUser(&user); quick_unlock::QuickUnlockFactory::GetForUser(&user);
...@@ -756,8 +752,9 @@ void ScreenLocker::OnFingerprintAuthFailure(const user_manager::User& user) { ...@@ -756,8 +752,9 @@ void ScreenLocker::OnFingerprintAuthFailure(const user_manager::User& user) {
if (quick_unlock_storage->fingerprint_storage()->ExceededUnlockAttempts()) { if (quick_unlock_storage->fingerprint_storage()->ExceededUnlockAttempts()) {
VLOG(1) << "Fingerprint unlock is disabled because it reached maximum" VLOG(1) << "Fingerprint unlock is disabled because it reached maximum"
<< " unlock attempt."; << " unlock attempt.";
delegate_->SetFingerprintState(user.GetAccountId(), delegate_->SetFingerprintState(
FingerprintState::kRemoved); user.GetAccountId(),
ash::mojom::FingerprintState::DISABLED_FROM_ATTEMPTS);
delegate_->ShowErrorMessage(IDS_LOGIN_ERROR_FINGERPRINT_MAX_ATTEMPT, delegate_->ShowErrorMessage(IDS_LOGIN_ERROR_FINGERPRINT_MAX_ATTEMPT,
HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT); HelpAppLauncher::HELP_CANT_ACCESS_ACCOUNT);
} }
...@@ -769,39 +766,44 @@ void ScreenLocker::OnFingerprintAuthFailure(const user_manager::User& user) { ...@@ -769,39 +766,44 @@ void ScreenLocker::OnFingerprintAuthFailure(const user_manager::User& user) {
} }
} }
void ScreenLocker::UpdateFingerprintState(const std::string& source, void ScreenLocker::MaybeDisablePinAndFingerprintFromTimeout(
const AccountId& account_id) { const std::string& source,
VLOG(1) << "Updating fingerprint state (source=" << source << ")"; const AccountId& account_id) {
update_fingerprint_state_timer_.Stop(); VLOG(1) << "MaybeDisablePinAndFingerprintFromTimeout source=" << source;
quick_unlock::QuickUnlockStorage* quick_unlock_storage =
quick_unlock::QuickUnlockFactory::GetForAccountId(account_id);
// If strong auth is required, disable fingerprint. update_fingerprint_state_timer_.Stop();
if (quick_unlock_storage && !quick_unlock_storage->HasStrongAuth() &&
quick_unlock_storage->fingerprint_storage()->IsFingerprintAvailable()) {
VLOG(1) << "Require strong auth to make fingerprint unlock available.";
delegate_->SetFingerprintState(account_id, FingerprintState::kTimeout);
// Prefs based pin will be unavailable when strong auth is required. // Update PIN state.
quick_unlock::PinBackend::GetInstance()->CanAuthenticate( quick_unlock::PinBackend::GetInstance()->CanAuthenticate(
account_id, base::BindOnce(&ScreenLocker::OnPinCanAuthenticate, account_id, base::BindOnce(&ScreenLocker::OnPinCanAuthenticate,
weak_factory_.GetWeakPtr(), account_id)); weak_factory_.GetWeakPtr(), account_id));
return;
}
// If fingerprint is available, call this function again when strong auth quick_unlock::QuickUnlockStorage* quick_unlock_storage =
// will expire. quick_unlock::QuickUnlockFactory::GetForAccountId(account_id);
if (quick_unlock_storage && if (quick_unlock_storage) {
quick_unlock_storage->IsFingerprintAuthenticationAvailable()) { if (quick_unlock_storage->HasStrongAuth()) {
const base::TimeDelta next_strong_auth = // Call this function again when strong authentication expires. PIN may
quick_unlock_storage->TimeUntilNextStrongAuth(); // also depend on strong authentication if it is prefs-based. Fingerprint
VLOG(1) << "Scheduling next fingerprint state update in " // always requires strong authentication.
<< next_strong_auth; const base::TimeDelta next_strong_auth =
update_fingerprint_state_timer_.Start( quick_unlock_storage->TimeUntilNextStrongAuth();
FROM_HERE, next_strong_auth, VLOG(1) << "Scheduling next pin and fingerprint timeout check in "
base::BindOnce(&ScreenLocker::UpdateFingerprintState, << next_strong_auth;
base::Unretained(this), update_fingerprint_state_timer_.Start(
"update_fingerprint_state_timer_", account_id)); FROM_HERE, next_strong_auth,
base::BindOnce(
&ScreenLocker::MaybeDisablePinAndFingerprintFromTimeout,
base::Unretained(this), "update_fingerprint_state_timer_",
account_id));
} else {
// Strong auth is unavailable; disable fingerprint if it was enabled.
if (quick_unlock_storage->fingerprint_storage()
->IsFingerprintAvailable()) {
VLOG(1) << "Require strong auth to make fingerprint unlock available.";
delegate_->SetFingerprintState(
account_id, ash::mojom::FingerprintState::DISABLED_FROM_TIMEOUT);
}
}
} }
} }
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include "ash/public/interfaces/login_user_info.mojom.h"
#include "base/callback_forward.h" #include "base/callback_forward.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/ref_counted.h" #include "base/memory/ref_counted.h"
...@@ -49,15 +50,6 @@ class WebUIScreenLockerTester; ...@@ -49,15 +50,6 @@ class WebUIScreenLockerTester;
class ScreenLocker : public AuthStatusConsumer, class ScreenLocker : public AuthStatusConsumer,
public device::mojom::FingerprintObserver { public device::mojom::FingerprintObserver {
public: public:
enum class FingerprintState {
kHidden,
kDefault,
kSignin,
kFailed,
kRemoved,
kTimeout,
};
// Delegate used to send internal state changes back to the UI. // Delegate used to send internal state changes back to the UI.
class Delegate { class Delegate {
public: public:
...@@ -93,7 +85,11 @@ class ScreenLocker : public AuthStatusConsumer, ...@@ -93,7 +85,11 @@ class ScreenLocker : public AuthStatusConsumer,
// Called when fingerprint state has changed. // Called when fingerprint state has changed.
virtual void SetFingerprintState(const AccountId& account_id, virtual void SetFingerprintState(const AccountId& account_id,
FingerprintState state) = 0; ash::mojom::FingerprintState state) = 0;
// Called after a fingerprint authentication attempt.
virtual void NotifyFingerprintAuthResult(const AccountId& account_id,
bool success) = 0;
// Returns the web contents used to back the lock screen. // Returns the web contents used to back the lock screen.
// TODO(jdufault): Remove this function when we remove WebUIScreenLocker. // TODO(jdufault): Remove this function when we remove WebUIScreenLocker.
...@@ -243,8 +239,11 @@ class ScreenLocker : public AuthStatusConsumer, ...@@ -243,8 +239,11 @@ class ScreenLocker : public AuthStatusConsumer,
// check has completed. // check has completed.
void ContinueAuthenticate(const UserContext& user_context); void ContinueAuthenticate(const UserContext& user_context);
void UpdateFingerprintState(const std::string& source, // Periodically called to see if PIN and fingerprint are still available for
const AccountId& account_id); // use. PIN and fingerprint are disabled after a certain period of time (e.g.
// 24 hours).
void MaybeDisablePinAndFingerprintFromTimeout(const std::string& source,
const AccountId& account_id);
void OnPinCanAuthenticate(const AccountId& account_id, bool can_authenticate); void OnPinCanAuthenticate(const AccountId& account_id, bool can_authenticate);
......
...@@ -9,7 +9,6 @@ ...@@ -9,7 +9,6 @@
#include <utility> #include <utility>
#include "ash/public/cpp/ash_features.h" #include "ash/public/cpp/ash_features.h"
#include "ash/public/interfaces/login_user_info.mojom.h"
#include "base/bind.h" #include "base/bind.h"
#include "base/bind_helpers.h" #include "base/bind_helpers.h"
#include "base/i18n/time_formatting.h" #include "base/i18n/time_formatting.h"
...@@ -49,24 +48,6 @@ constexpr char kWebCameraDeviceContext[] = "WebCamera: WebCamera"; ...@@ -49,24 +48,6 @@ constexpr char kWebCameraDeviceContext[] = "WebCamera: WebCamera";
constexpr base::TimeDelta kExternalBinaryAuthTimeout = constexpr base::TimeDelta kExternalBinaryAuthTimeout =
base::TimeDelta::FromSeconds(2); base::TimeDelta::FromSeconds(2);
ash::mojom::FingerprintUnlockState ConvertFromFingerprintState(
ScreenLocker::FingerprintState state) {
switch (state) {
case ScreenLocker::FingerprintState::kHidden:
return ash::mojom::FingerprintUnlockState::UNAVAILABLE;
case ScreenLocker::FingerprintState::kDefault:
return ash::mojom::FingerprintUnlockState::AVAILABLE;
case ScreenLocker::FingerprintState::kSignin:
return ash::mojom::FingerprintUnlockState::AUTH_SUCCESS;
case ScreenLocker::FingerprintState::kFailed:
return ash::mojom::FingerprintUnlockState::AUTH_FAILED;
case ScreenLocker::FingerprintState::kRemoved:
return ash::mojom::FingerprintUnlockState::AUTH_DISABLED;
case ScreenLocker::FingerprintState::kTimeout:
return ash::mojom::FingerprintUnlockState::AUTH_DISABLED_FROM_TIMEOUT;
}
}
// Starts the graph specified by |configuration| if the current graph // Starts the graph specified by |configuration| if the current graph
// is SUSPENDED or if the current configuration is different. // is SUSPENDED or if the current configuration is different.
void StartGraphIfNeeded(chromeos::MediaAnalyticsClient* client, void StartGraphIfNeeded(chromeos::MediaAnalyticsClient* client,
...@@ -196,9 +177,15 @@ void ViewsScreenLocker::OnAshLockAnimationFinished() { ...@@ -196,9 +177,15 @@ void ViewsScreenLocker::OnAshLockAnimationFinished() {
void ViewsScreenLocker::SetFingerprintState( void ViewsScreenLocker::SetFingerprintState(
const AccountId& account_id, const AccountId& account_id,
ScreenLocker::FingerprintState state) { ash::mojom::FingerprintState state) {
LoginScreenClient::Get()->login_screen()->SetFingerprintUnlockState( LoginScreenClient::Get()->login_screen()->SetFingerprintState(account_id,
account_id, ConvertFromFingerprintState(state)); state);
}
void ViewsScreenLocker::NotifyFingerprintAuthResult(const AccountId& account_id,
bool success) {
LoginScreenClient::Get()->login_screen()->NotifyFingerprintAuthResult(
account_id, success);
} }
content::WebContents* ViewsScreenLocker::GetWebContents() { content::WebContents* ViewsScreenLocker::GetWebContents() {
......
...@@ -49,7 +49,9 @@ class ViewsScreenLocker : public LoginScreenClient::Delegate, ...@@ -49,7 +49,9 @@ class ViewsScreenLocker : public LoginScreenClient::Delegate,
void OnHeaderBarVisible() override; void OnHeaderBarVisible() override;
void OnAshLockAnimationFinished() override; void OnAshLockAnimationFinished() override;
void SetFingerprintState(const AccountId& account_id, void SetFingerprintState(const AccountId& account_id,
ScreenLocker::FingerprintState state) override; ash::mojom::FingerprintState state) override;
void NotifyFingerprintAuthResult(const AccountId& account_id,
bool success) override;
content::WebContents* GetWebContents() override; content::WebContents* GetWebContents() override;
// LoginScreenClient::Delegate // LoginScreenClient::Delegate
......
...@@ -258,26 +258,13 @@ void WebUIScreenLocker::OnAshLockAnimationFinished() { ...@@ -258,26 +258,13 @@ void WebUIScreenLocker::OnAshLockAnimationFinished() {
void WebUIScreenLocker::SetFingerprintState( void WebUIScreenLocker::SetFingerprintState(
const AccountId& account_id, const AccountId& account_id,
ScreenLocker::FingerprintState state) { ash::mojom::FingerprintState state) {
// TODO(xiaoyinh@): Modify JS side to consolidate removeUserPodFingerprintIcon NOTREACHED();
// and setUserPodFingerprintIcon into single JS function. }
if (state == ScreenLocker::FingerprintState::kRemoved) {
GetWebUI()->CallJavascriptFunctionUnsafe(
"login.AccountPickerScreen.removeUserPodFingerprintIcon",
::login::MakeValue(account_id));
return;
}
chromeos::quick_unlock::QuickUnlockStorage* quick_unlock_storage = void WebUIScreenLocker::NotifyFingerprintAuthResult(const AccountId& account_id,
chromeos::quick_unlock::QuickUnlockFactory::GetForAccountId(account_id); bool success) {
if (!quick_unlock_storage || NOTREACHED();
!quick_unlock_storage->IsFingerprintAuthenticationAvailable()) {
state = ScreenLocker::FingerprintState::kHidden;
}
GetWebUI()->CallJavascriptFunctionUnsafe(
"login.AccountPickerScreen.setUserPodFingerprintIcon",
::login::MakeValue(account_id),
::login::MakeValue(static_cast<int>(state)));
} }
content::WebContents* WebUIScreenLocker::GetWebContents() { content::WebContents* WebUIScreenLocker::GetWebContents() {
......
...@@ -81,7 +81,9 @@ class WebUIScreenLocker : public WebUILoginView, ...@@ -81,7 +81,9 @@ class WebUIScreenLocker : public WebUILoginView,
void OnHeaderBarVisible() override; void OnHeaderBarVisible() override;
void OnAshLockAnimationFinished() override; void OnAshLockAnimationFinished() override;
void SetFingerprintState(const AccountId& account_id, void SetFingerprintState(const AccountId& account_id,
ScreenLocker::FingerprintState state) override; ash::mojom::FingerprintState state) override;
void NotifyFingerprintAuthResult(const AccountId& account_id,
bool success) override;
content::WebContents* GetWebContents() override; content::WebContents* GetWebContents() override;
// LoginDisplay::Delegate: // LoginDisplay::Delegate:
......
...@@ -156,18 +156,38 @@ void AddPublicSessionDetailsToUserDictionaryEntry( ...@@ -156,18 +156,38 @@ void AddPublicSessionDetailsToUserDictionaryEntry(
has_multiple_locales); has_multiple_locales);
} }
// Returns true if the fingerprint icon should be displayed for the given // Determines the initial fingerprint state for the given user.
// |user|. ash::mojom::FingerprintState GetInitialFingerprintState(
bool AllowFingerprintForUser(const user_manager::User* user) { const user_manager::User* user) {
// User must be logged in.
if (!user->is_logged_in()) if (!user->is_logged_in())
return false; return ash::mojom::FingerprintState::UNAVAILABLE;
// Quick unlock storage must be available.
quick_unlock::QuickUnlockStorage* quick_unlock_storage = quick_unlock::QuickUnlockStorage* quick_unlock_storage =
quick_unlock::QuickUnlockFactory::GetForUser(user); quick_unlock::QuickUnlockFactory::GetForUser(user);
if (!quick_unlock_storage) if (!quick_unlock_storage)
return false; return ash::mojom::FingerprintState::UNAVAILABLE;
// Fingerprint is not registered for this account.
if (!quick_unlock_storage->fingerprint_storage()->HasRecord())
return ash::mojom::FingerprintState::UNAVAILABLE;
// Fingerprint unlock attempts should not be exceeded, as the lock screen has
// not been displayed yet.
DCHECK(
!quick_unlock_storage->fingerprint_storage()->ExceededUnlockAttempts());
// It has been too long since the last authentication.
if (!quick_unlock_storage->HasStrongAuth())
return ash::mojom::FingerprintState::DISABLED_FROM_TIMEOUT;
// Auth is available.
if (quick_unlock_storage->IsFingerprintAuthenticationAvailable())
return ash::mojom::FingerprintState::AVAILABLE;
return quick_unlock_storage->IsFingerprintAuthenticationAvailable(); // Default to unavailabe.
return ash::mojom::FingerprintState::UNAVAILABLE;
} }
// Returns true if dircrypto migration check should be performed. // Returns true if dircrypto migration check should be performed.
...@@ -385,7 +405,9 @@ void UserSelectionScreen::FillUserDictionary( ...@@ -385,7 +405,9 @@ void UserSelectionScreen::FillUserDictionary(
user_dict->SetBoolean(kKeySignedIn, user->is_logged_in()); user_dict->SetBoolean(kKeySignedIn, user->is_logged_in());
user_dict->SetBoolean(kKeyIsOwner, is_owner); user_dict->SetBoolean(kKeyIsOwner, is_owner);
user_dict->SetBoolean(kKeyIsActiveDirectory, user->IsActiveDirectoryUser()); user_dict->SetBoolean(kKeyIsActiveDirectory, user->IsActiveDirectoryUser());
user_dict->SetBoolean(kKeyAllowFingerprint, AllowFingerprintForUser(user)); user_dict->SetBoolean(kKeyAllowFingerprint,
GetInitialFingerprintState(user) ==
ash::mojom::FingerprintState::AVAILABLE);
FillMultiProfileUserPrefs(user, user_dict, is_signin_to_add); FillMultiProfileUserPrefs(user, user_dict, is_signin_to_add);
...@@ -814,7 +836,7 @@ UserSelectionScreen::UpdateAndReturnUserListForMojo() { ...@@ -814,7 +836,7 @@ UserSelectionScreen::UpdateAndReturnUserListForMojo() {
user_info->is_signed_in = user->is_logged_in(); user_info->is_signed_in = user->is_logged_in();
user_info->is_device_owner = is_owner; user_info->is_device_owner = is_owner;
user_info->can_remove = CanRemoveUser(user); user_info->can_remove = CanRemoveUser(user);
user_info->allow_fingerprint_unlock = AllowFingerprintForUser(user); user_info->fingerprint_state = GetInitialFingerprintState(user);
// Fill multi-profile data. // Fill multi-profile data.
if (!is_signin_to_add) { if (!is_signin_to_add) {
......
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