ash: In session auth dialog shows the pin lockout status message.
1. When existing PINs lock out, the delay is indefintely so we reuse the existing PIN lockout message. We tweak it a bit to make it clear that it is about PIN. 2. On the new flexible PIN lockout, the delay is converted from PinStatus and formatted into a new error message. 3. Because PinStatus is from AuthFactorStatusUpdate, which periodically emits from cryptohomed and processed by the controller. The error message will be updated every 30 seconds or immediately after a pin is locked out. BUG=b:341733466 TEST=Unit tests and VM manual tests. Change-Id: Ib95c9f02003c40b74f17cedfd6cca89c1657ed28 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5796520 Reviewed-by: Elie Maamari <emaamari@google.com> Commit-Queue: Hardik Goyal <hardikgoyal@chromium.org> Reviewed-by: Hardik Goyal <hardikgoyal@chromium.org> Cr-Commit-Position: refs/heads/main@{#1347228}
This commit is contained in:
@ -5333,7 +5333,10 @@ No devices connected.
|
||||
Incorrect PIN
|
||||
</message>
|
||||
<message name="IDS_ASH_IN_SESSION_AUTH_PIN_TOO_MANY_ATTEMPTS" desc="Text shown in the auth dialog to tell the user that PIN auth has reached maximum attempts">
|
||||
Too many attempts
|
||||
Too many PIN attempts
|
||||
</message>
|
||||
<message name="IDS_ASH_IN_SESSION_AUTH_PIN_DELAY_REQUIRED" desc="Text shown in the auth dialog to tell the user that PIN auth has reached many attempts and a rate limiting delay is in effect">
|
||||
Too many PIN attempts. Wait <ph name="TIME_LEFT">$1<ex>1 hour, 15 minutes, 10 seconds</ex></ph> and try again
|
||||
</message>
|
||||
<message name="IDS_ASH_IN_SESSION_AUTH_FINGERPRINT_AVAILABLE" desc="Text shown in the auth dialog to remind user that fingerprint auth is supported">
|
||||
Touch the fingerprint sensor
|
||||
|
@ -0,0 +1 @@
|
||||
dbf477759685f9b17ffc0f9a36c7659caeed5d0c
|
@ -1 +1 @@
|
||||
825fd9414614f6d0534cb3a1136c921a11aac1b1
|
||||
a4d4d2f8559bedff7af4c33f69ac1e5a2cba3c21
|
@ -19,6 +19,7 @@
|
||||
#include "base/check.h"
|
||||
#include "base/check_op.h"
|
||||
#include "base/functional/bind.h"
|
||||
#include "base/i18n/time_formatting.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
@ -118,6 +119,28 @@ const char* ActiveSessionAuthStateToString(
|
||||
NOTREACHED();
|
||||
}
|
||||
|
||||
std::u16string BuildPinStatusMessage(const cryptohome::PinStatus& pin_status) {
|
||||
if (!pin_status.IsLockedFactor()) {
|
||||
return u"";
|
||||
}
|
||||
if (pin_status.AvailableAt() == base::Time::Max()) {
|
||||
return l10n_util::GetStringUTF16(
|
||||
IDS_ASH_IN_SESSION_AUTH_PIN_TOO_MANY_ATTEMPTS);
|
||||
} else {
|
||||
base::TimeDelta delta = pin_status.AvailableAt() - base::Time::Now();
|
||||
std::u16string time_left_message;
|
||||
if (base::TimeDurationCompactFormatWithSeconds(
|
||||
delta, base::DurationFormatWidth::DURATION_WIDTH_WIDE,
|
||||
&time_left_message)) {
|
||||
return l10n_util::GetStringFUTF16(
|
||||
IDS_ASH_IN_SESSION_AUTH_PIN_DELAY_REQUIRED, time_left_message);
|
||||
} else {
|
||||
return l10n_util::GetStringUTF16(
|
||||
IDS_ASH_IN_SESSION_AUTH_PIN_TOO_MANY_ATTEMPTS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ActiveSessionAuthControllerImpl::TestApi::TestApi(
|
||||
@ -141,6 +164,16 @@ void ActiveSessionAuthControllerImpl::TestApi::SubmitPin(
|
||||
controller_->OnPinSubmit(base::UTF8ToUTF16(pin));
|
||||
}
|
||||
|
||||
void ActiveSessionAuthControllerImpl::TestApi::DisplayPinStatusMessage(
|
||||
const cryptohome::PinStatus pin_status) {
|
||||
controller_->DisplayPinStatusMessage(pin_status);
|
||||
}
|
||||
|
||||
const std::u16string&
|
||||
ActiveSessionAuthControllerImpl::TestApi::GetPinStatusMessage() const {
|
||||
return controller_->pin_status_message_;
|
||||
}
|
||||
|
||||
void ActiveSessionAuthControllerImpl::TestApi::Close() {
|
||||
controller_->Close();
|
||||
}
|
||||
@ -410,12 +443,20 @@ void ActiveSessionAuthControllerImpl::ProcessAuthFactorStatusUpdate(
|
||||
/*fallback_type=*/cryptohome::AuthFactorType::kPassword);
|
||||
if (auth_factor.ref().type() == cryptohome::AuthFactorType::kPin) {
|
||||
CHECK(contents_view_);
|
||||
bool pin_enabled = !auth_factor.GetPinStatus().IsLockedFactor();
|
||||
auto pin_status = auth_factor.GetPinStatus();
|
||||
bool pin_enabled = !pin_status.IsLockedFactor();
|
||||
// Only need to update the auth view because |available_factors_| is only
|
||||
// used to initialize the view.
|
||||
contents_view_->SetHasPin(pin_enabled);
|
||||
DisplayPinStatusMessage(pin_status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ActiveSessionAuthControllerImpl::DisplayPinStatusMessage(
|
||||
const cryptohome::PinStatus pin_status) {
|
||||
pin_status_message_ = BuildPinStatusMessage(pin_status);
|
||||
contents_view_->SetPinStatus(pin_status_message_);
|
||||
}
|
||||
|
||||
} // namespace ash
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "ash/public/cpp/auth/active_session_auth_controller.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "chromeos/ash/components/cryptohome/auth_factor.h"
|
||||
#include "chromeos/ash/components/dbus/userdataauth/userdataauth_client.h"
|
||||
#include "chromeos/ash/components/login/auth/auth_factor_editor.h"
|
||||
#include "chromeos/ash/components/login/auth/auth_performer.h"
|
||||
@ -59,6 +60,11 @@ class ASH_EXPORT ActiveSessionAuthControllerImpl
|
||||
// manually entered it.
|
||||
void SubmitPin(const std::string& pin);
|
||||
|
||||
// Simulate building and displaying a pin status message.
|
||||
void DisplayPinStatusMessage(const cryptohome::PinStatus pin_status);
|
||||
|
||||
const std::u16string& GetPinStatusMessage() const;
|
||||
|
||||
void Close();
|
||||
|
||||
private:
|
||||
@ -129,6 +135,10 @@ class ASH_EXPORT ActiveSessionAuthControllerImpl
|
||||
// called after auth factors configuration is updated.
|
||||
bool IsPinLocked() const;
|
||||
|
||||
// Show a PinStatus based error message, only if |pin_status| represents
|
||||
// a locked factor.
|
||||
void DisplayPinStatusMessage(const cryptohome::PinStatus pin_status);
|
||||
|
||||
std::unique_ptr<views::Widget> widget_;
|
||||
|
||||
base::ScopedObservation<views::View, ViewObserver> contents_view_observer_{
|
||||
@ -139,6 +149,7 @@ class ASH_EXPORT ActiveSessionAuthControllerImpl
|
||||
AccountId account_id_;
|
||||
std::u16string title_;
|
||||
std::u16string description_;
|
||||
std::u16string pin_status_message_;
|
||||
|
||||
std::unique_ptr<AuthFactorEditor> auth_factor_editor_;
|
||||
std::unique_ptr<AuthPerformer> auth_performer_;
|
||||
|
@ -6,7 +6,9 @@
|
||||
#include "ash/constants/ash_pref_names.h"
|
||||
#include "ash/session/session_controller_impl.h"
|
||||
#include "ash/shell.h"
|
||||
#include "ash/strings/grit/ash_strings.h"
|
||||
#include "ash/test/ash_test_base.h"
|
||||
#include "base/test/run_until.h"
|
||||
#include "base/test/test_future.h"
|
||||
#include "chromeos/ash/components/cryptohome/system_salt_getter.h"
|
||||
#include "chromeos/ash/components/dbus/userdataauth/fake_cryptohome_misc_client.h"
|
||||
@ -19,6 +21,7 @@
|
||||
#include "components/user_manager/known_user.h"
|
||||
#include "components/user_manager/user_manager.h"
|
||||
#include "third_party/cros_system_api/dbus/cryptohome/dbus-constants.h"
|
||||
#include "ui/base/l10n/l10n_util.h"
|
||||
|
||||
namespace ash {
|
||||
|
||||
@ -412,6 +415,44 @@ TEST_F(ActiveSessionAuthControllerTest, BadPinThenGoodPassword) {
|
||||
EXPECT_EQ(future.Get<bool>(), true);
|
||||
}
|
||||
|
||||
// Check the format and content of pin lockout status message.
|
||||
TEST_F(ActiveSessionAuthControllerTest, PinLockoutMessage) {
|
||||
AddGaiaPassword(account_id_, kExpectedPassword);
|
||||
AddCryptohomePin(account_id_, kExpectedPin);
|
||||
const std::string bad_pin = "bad_pin";
|
||||
|
||||
user_manager::KnownUser known_user(Shell::Get()->local_state());
|
||||
known_user.SetStringPref(account_id_, prefs::kQuickUnlockPinSalt,
|
||||
kExpectedSalt);
|
||||
|
||||
auto* controller = static_cast<ActiveSessionAuthControllerImpl*>(
|
||||
Shell::Get()->active_session_auth_controller());
|
||||
auto test_api = ActiveSessionAuthControllerImpl::TestApi(controller);
|
||||
|
||||
OnAuthComplete future;
|
||||
|
||||
Shell::Get()->active_session_auth_controller()->ShowAuthDialog(
|
||||
std::make_unique<SettingsAuthRequest>(future.GetCallback()));
|
||||
|
||||
// Await show.
|
||||
ASSERT_TRUE(base::test::RunUntil([&]() { return controller->IsShown(); }));
|
||||
|
||||
const base::TimeDelta in_a_while = base::Seconds(60);
|
||||
cryptohome::PinStatus soft_lockout{in_a_while};
|
||||
test_api.DisplayPinStatusMessage(soft_lockout);
|
||||
|
||||
EXPECT_EQ(
|
||||
test_api.GetPinStatusMessage(),
|
||||
l10n_util::GetStringFUTF16(IDS_ASH_IN_SESSION_AUTH_PIN_DELAY_REQUIRED,
|
||||
u"1 minute, 0 seconds"));
|
||||
|
||||
cryptohome::PinStatus hard_lockout{base::TimeDelta::Max()};
|
||||
test_api.DisplayPinStatusMessage(hard_lockout);
|
||||
EXPECT_EQ(
|
||||
test_api.GetPinStatusMessage(),
|
||||
l10n_util::GetStringUTF16(IDS_ASH_IN_SESSION_AUTH_PIN_TOO_MANY_ATTEMPTS));
|
||||
}
|
||||
|
||||
// Tests that the OnAuthCancel callback is called with the correct
|
||||
// parameters.
|
||||
TEST_F(ActiveSessionAuthControllerTest, OnAuthCancel) {
|
||||
|
@ -262,7 +262,7 @@ TEST_F(AuthDialogContentsViewPixelTest, PinAndFingerprintWithPinFail) {
|
||||
|
||||
// Verify the UI.
|
||||
EXPECT_TRUE(GetPixelDiffer()->CompareUiComponentsOnPrimaryScreen(
|
||||
"pin_fingerprint_pin_fail", /*revision_number=*/3, widget.get()));
|
||||
"pin_fingerprint_pin_fail", /*revision_number=*/4, widget.get()));
|
||||
}
|
||||
|
||||
TEST_F(AuthDialogContentsViewPixelTest,
|
||||
|
Reference in New Issue
Block a user