123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690 |
- // Copyright 2020 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "ash/in_session_auth/auth_dialog_contents_view.h"
- #include <memory>
- #include <utility>
- #include "ash/login/resources/grit/login_resources.h"
- #include "ash/login/ui/horizontal_image_sequence_animation_decoder.h"
- #include "ash/login/ui/login_password_view.h"
- #include "ash/login/ui/login_pin_input_view.h"
- #include "ash/login/ui/login_pin_view.h"
- #include "ash/login/ui/non_accessible_view.h"
- #include "ash/login/ui/views_utils.h"
- #include "ash/public/cpp/webauthn_dialog_controller.h"
- #include "ash/resources/vector_icons/vector_icons.h"
- #include "ash/strings/grit/ash_strings.h"
- #include "base/bind.h"
- #include "base/callback_helpers.h"
- #include "base/strings/utf_string_conversions.h"
- #include "base/timer/timer.h"
- #include "ui/accessibility/ax_enums.mojom.h"
- #include "ui/accessibility/ax_node_data.h"
- #include "ui/base/l10n/l10n_util.h"
- #include "ui/base/resource/resource_bundle.h"
- #include "ui/compositor/layer.h"
- #include "ui/gfx/paint_vector_icon.h"
- #include "ui/views/background.h"
- #include "ui/views/border.h"
- #include "ui/views/bubble/bubble_border.h"
- #include "ui/views/controls/button/md_text_button.h"
- #include "ui/views/controls/label.h"
- #include "ui/views/layout/box_layout.h"
- #include "ui/views/layout/fill_layout.h"
- namespace ash {
- namespace {
- constexpr int kContainerPreferredWidth = 340;
- constexpr int kBorderTopDp = 36;
- constexpr int kBorderLeftDp = 24;
- constexpr int kBorderBottomDp = 20;
- constexpr int kBorderRightDp = 24;
- constexpr int kCornerRadius = 12;
- constexpr int kTitleFontSizeDeltaDp = 4;
- constexpr int kOriginNameLineHeight = 18;
- constexpr int kSpacingAfterAvatar = 18;
- constexpr int kSpacingAfterTitle = 8;
- constexpr int kSpacingAfterOriginName = 32;
- constexpr int kSpacingAfterInputField = 16;
- constexpr int kAvatarSizeDp = 36;
- constexpr int kFingerprintIconSizeDp = 28;
- constexpr int kSpacingBetweenPinPadAndFingerprintIcon = 24;
- constexpr int kSpacingBetweenPasswordAndFingerprintIcon = 24;
- constexpr int kSpacingBetweenFingerprintIconAndLabelDp = 15;
- constexpr int kFingerprintViewWidthDp = 204;
- constexpr int kFingerprintFailedAnimationNumFrames = 45;
- constexpr base::TimeDelta kResetToDefaultIconDelay = base::Milliseconds(1300);
- constexpr base::TimeDelta kResetToDefaultMessageDelay =
- base::Milliseconds(3000);
- constexpr base::TimeDelta kFingerprintFailedAnimationDuration =
- base::Milliseconds(700);
- // 38% opacity.
- constexpr SkColor kDisabledFingerprintIconColor =
- SkColorSetA(gfx::kGoogleGrey900, 97);
- constexpr SkColor kBackgroundColor = SK_ColorWHITE;
- constexpr SkColor kTextColorSecondary = gfx::kGoogleGrey700;
- constexpr SkColor kTextColorPrimary = gfx::kGoogleGrey900;
- constexpr SkColor kErrorColor = gfx::kGoogleRed600;
- constexpr int kSpacingBeforeButtons = 32;
- } // namespace
- // Consists of fingerprint icon view and a label.
- class AuthDialogContentsView::FingerprintView : public views::View {
- public:
- // Use a subclass that inherit views::Label so that GetAccessibleNodeData
- // override is respected.
- class FingerprintLabel : public views::Label {
- public:
- // views::View
- void GetAccessibleNodeData(ui::AXNodeData* node_data) override {
- node_data->role = ax::mojom::Role::kStaticText;
- node_data->SetName(accessible_name_);
- }
- void SetAccessibleName(const std::u16string& name) {
- accessible_name_ = name;
- NotifyAccessibilityEvent(ax::mojom::Event::kTextChanged,
- true /*send_native_event*/);
- }
- private:
- std::u16string accessible_name_;
- };
- FingerprintView() {
- auto* layout = SetLayoutManager(std::make_unique<views::BoxLayout>(
- views::BoxLayout::Orientation::kVertical, gfx::Insets(),
- kSpacingBetweenFingerprintIconAndLabelDp));
- layout->set_main_axis_alignment(
- views::BoxLayout::MainAxisAlignment::kCenter);
- icon_ = AddChildView(std::make_unique<AnimatedRoundedImageView>(
- gfx::Size(kFingerprintIconSizeDp, kFingerprintIconSizeDp),
- 0 /*corner_radius*/));
- label_ = AddChildView(std::make_unique<FingerprintLabel>());
- label_->SetSubpixelRenderingEnabled(false);
- label_->SetAutoColorReadabilityEnabled(false);
- label_->SetEnabledColor(kTextColorPrimary);
- label_->SetMultiLine(true);
- label_->SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY);
- DisplayCurrentState();
- }
- FingerprintView(const FingerprintView&) = delete;
- FingerprintView& operator=(const FingerprintView&) = delete;
- ~FingerprintView() override = default;
- void SetState(FingerprintState state) {
- if (state_ == state)
- return;
- state_ = state;
- DisplayCurrentState();
- }
- void SetCanUsePin(bool can_use_pin) {
- if (can_use_pin_ == can_use_pin)
- return;
- can_use_pin_ = can_use_pin;
- DisplayCurrentState();
- }
- // Notify the user of the fingerprint auth result. Should be called after
- // SetState. If fingerprint auth failed and retry is allowed, reset to
- // default state after animation.
- void NotifyFingerprintAuthResult(bool success) {
- reset_state_.Stop();
- if (state_ == FingerprintState::DISABLED_FROM_ATTEMPTS) {
- label_->SetText(l10n_util::GetStringUTF16(
- IDS_ASH_IN_SESSION_AUTH_FINGERPRINT_DISABLED_FROM_ATTEMPTS));
- label_->SetAccessibleName(l10n_util::GetStringUTF16(
- IDS_ASH_IN_SESSION_AUTH_FINGERPRINT_ACCESSIBLE_DISABLED_FROM_ATTEMPTS));
- } else if (success) {
- label_->SetText(l10n_util::GetStringUTF16(
- IDS_ASH_IN_SESSION_AUTH_FINGERPRINT_SUCCESS));
- label_->SetAccessibleName(l10n_util::GetStringUTF16(
- IDS_ASH_IN_SESSION_AUTH_FINGERPRINT_ACCESSIBLE_SUCCESS));
- } else {
- label_->SetText(l10n_util::GetStringUTF16(
- IDS_ASH_IN_SESSION_AUTH_FINGERPRINT_FAILED));
- label_->SetAccessibleName(l10n_util::GetStringUTF16(
- IDS_ASH_IN_SESSION_AUTH_FINGERPRINT_ACCESSIBLE_FAILED));
- }
- if (!success) {
- // This is just to display the "fingerprint auth failure" animation. It
- // does not necessarily mean |state_| is DISABLED_FROM_ATTEMPTS.
- SetIcon(FingerprintState::DISABLED_FROM_ATTEMPTS);
- // base::Unretained is safe because reset_state_ is owned by |this|.
- reset_state_.Start(FROM_HERE, kResetToDefaultIconDelay,
- base::BindOnce(&FingerprintView::DisplayCurrentState,
- base::Unretained(this)));
- label_->NotifyAccessibilityEvent(ax::mojom::Event::kAlert,
- true /*send_native_event*/);
- }
- }
- // views::View:
- gfx::Size CalculatePreferredSize() const override {
- gfx::Size size = views::View::CalculatePreferredSize();
- size.set_width(kFingerprintViewWidthDp);
- return size;
- }
- // views::View:
- void OnGestureEvent(ui::GestureEvent* event) override {
- if (event->type() != ui::ET_GESTURE_TAP)
- return;
- if (state_ == FingerprintState::AVAILABLE_DEFAULT ||
- state_ == FingerprintState::AVAILABLE_WITH_TOUCH_SENSOR_WARNING) {
- SetState(FingerprintState::AVAILABLE_WITH_TOUCH_SENSOR_WARNING);
- reset_state_.Start(
- FROM_HERE, kResetToDefaultMessageDelay,
- base::BindOnce(&FingerprintView::SetState, base::Unretained(this),
- FingerprintState::AVAILABLE_DEFAULT));
- }
- }
- private:
- void DisplayCurrentState() {
- SetVisible(state_ != FingerprintState::UNAVAILABLE);
- SetIcon(state_);
- if (state_ != FingerprintState::UNAVAILABLE) {
- std::u16string fingerprint_text =
- l10n_util::GetStringUTF16(GetTextIdFromState());
- label_->SetText(fingerprint_text);
- label_->SetAccessibleName(
- state_ == FingerprintState::DISABLED_FROM_ATTEMPTS
- ? l10n_util::GetStringUTF16(
- IDS_ASH_IN_SESSION_AUTH_FINGERPRINT_ACCESSIBLE_DISABLED_FROM_ATTEMPTS)
- : fingerprint_text);
- }
- }
- void SetIcon(FingerprintState state) {
- const SkColor color =
- (state == FingerprintState::AVAILABLE_DEFAULT ||
- state == FingerprintState::AVAILABLE_WITH_TOUCH_SENSOR_WARNING
- ? kTextColorPrimary
- : kDisabledFingerprintIconColor);
- switch (state) {
- case FingerprintState::UNAVAILABLE:
- case FingerprintState::AVAILABLE_DEFAULT:
- case FingerprintState::AVAILABLE_WITH_TOUCH_SENSOR_WARNING:
- case FingerprintState::DISABLED_FROM_TIMEOUT:
- icon_->SetImage(gfx::CreateVectorIcon(kLockScreenFingerprintIcon,
- kFingerprintIconSizeDp, color));
- break;
- case FingerprintState::DISABLED_FROM_ATTEMPTS:
- icon_->SetAnimationDecoder(
- std::make_unique<HorizontalImageSequenceAnimationDecoder>(
- *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
- IDR_LOGIN_FINGERPRINT_UNLOCK_SPINNER),
- kFingerprintFailedAnimationDuration,
- kFingerprintFailedAnimationNumFrames),
- AnimatedRoundedImageView::Playback::kSingle);
- break;
- }
- }
- int GetTextIdFromState() const {
- switch (state_) {
- case FingerprintState::AVAILABLE_DEFAULT:
- return IDS_ASH_IN_SESSION_AUTH_FINGERPRINT_AVAILABLE;
- case FingerprintState::AVAILABLE_WITH_TOUCH_SENSOR_WARNING:
- return IDS_ASH_IN_SESSION_AUTH_FINGERPRINT_TOUCH_SENSOR;
- case FingerprintState::DISABLED_FROM_ATTEMPTS:
- return IDS_ASH_IN_SESSION_AUTH_FINGERPRINT_DISABLED_FROM_ATTEMPTS;
- case FingerprintState::DISABLED_FROM_TIMEOUT:
- if (can_use_pin_)
- return IDS_ASH_IN_SESSION_AUTH_FINGERPRINT_PIN_OR_PASSWORD_REQUIRED;
- return IDS_ASH_IN_SESSION_AUTH_FINGERPRINT_PASSWORD_REQUIRED;
- case FingerprintState::UNAVAILABLE:
- NOTREACHED();
- return 0;
- }
- }
- FingerprintLabel* label_ = nullptr;
- AnimatedRoundedImageView* icon_ = nullptr;
- FingerprintState state_ = FingerprintState::AVAILABLE_DEFAULT;
- bool can_use_pin_ = false;
- base::OneShotTimer reset_state_;
- };
- class AuthDialogContentsView::TitleLabel : public views::Label {
- public:
- TitleLabel() {
- SetSubpixelRenderingEnabled(false);
- SetAutoColorReadabilityEnabled(false);
- SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY);
- const gfx::FontList& base_font_list = views::Label::GetDefaultFontList();
- SetFontList(base_font_list.Derive(kTitleFontSizeDeltaDp,
- gfx::Font::FontStyle::NORMAL,
- gfx::Font::Weight::MEDIUM));
- SetMaximumWidthSingleLine(kContainerPreferredWidth);
- SetElideBehavior(gfx::ElideBehavior::ELIDE_TAIL);
- SetPreferredSize(gfx::Size(kContainerPreferredWidth,
- GetHeightForWidth(kContainerPreferredWidth)));
- SetHorizontalAlignment(gfx::ALIGN_CENTER);
- }
- bool IsShowingError() const { return is_showing_error_; }
- void ShowTitle() {
- std::u16string title =
- l10n_util::GetStringUTF16(IDS_ASH_IN_SESSION_AUTH_TITLE);
- SetText(title);
- SetEnabledColor(kTextColorPrimary);
- is_showing_error_ = false;
- SetAccessibleName(title);
- }
- void ShowError(const std::u16string& error_text) {
- SetText(error_text);
- SetEnabledColor(kErrorColor);
- is_showing_error_ = true;
- SetAccessibleName(error_text);
- NotifyAccessibilityEvent(ax::mojom::Event::kAlert,
- true /*send_native_event*/);
- }
- // views::View
- void GetAccessibleNodeData(ui::AXNodeData* node_data) override {
- node_data->role = ax::mojom::Role::kStaticText;
- node_data->SetName(accessible_name_);
- }
- private:
- void SetAccessibleName(const std::u16string& name) {
- accessible_name_ = name;
- NotifyAccessibilityEvent(ax::mojom::Event::kTextChanged,
- true /*send_native_event*/);
- }
- bool is_showing_error_ = false;
- std::u16string accessible_name_;
- };
- AuthDialogContentsView::AuthDialogContentsView(
- uint32_t auth_methods,
- const std::string& origin_name,
- const AuthMethodsMetadata& auth_metadata,
- const UserAvatar& avatar)
- : auth_methods_(auth_methods),
- origin_name_(origin_name),
- auth_metadata_(auth_metadata) {
- SetLayoutManager(std::make_unique<views::FillLayout>());
- auto border = std::make_unique<views::BubbleBorder>(
- views::BubbleBorder::FLOAT, views::BubbleBorder::STANDARD_SHADOW);
- border->SetColor(kBackgroundColor);
- border->SetCornerRadius(kCornerRadius);
- SetBackground(std::make_unique<views::BubbleBackground>(border.get()));
- SetBorder(std::move(border));
- container_ = AddChildView(std::make_unique<NonAccessibleView>());
- container_->SetBorder(views::CreateEmptyBorder(gfx::Insets::TLBR(
- kBorderTopDp, kBorderLeftDp, kBorderBottomDp, kBorderRightDp)));
- main_layout_ =
- container_->SetLayoutManager(std::make_unique<views::BoxLayout>(
- views::BoxLayout::Orientation::kVertical));
- main_layout_->set_main_axis_alignment(
- views::BoxLayout::MainAxisAlignment::kStart);
- main_layout_->set_cross_axis_alignment(
- views::BoxLayout::CrossAxisAlignment::kCenter);
- AddAvatarView(avatar);
- AddVerticalSpacing(kSpacingAfterAvatar);
- AddTitleView();
- AddVerticalSpacing(kSpacingAfterTitle);
- AddOriginNameView();
- AddVerticalSpacing(kSpacingAfterOriginName);
- if (auth_methods_ & kAuthPin) {
- if (LoginPinInputView::IsAutosubmitSupported(
- auth_metadata_.autosubmit_pin_length)) {
- pin_autosubmit_on_ = true;
- AddPinDigitInputView();
- } else {
- pin_autosubmit_on_ = false;
- AddPinTextInputView();
- }
- AddVerticalSpacing(kSpacingAfterInputField);
- // PIN pad is always visible regardless of PIN autosubmit status.
- AddPinPadView();
- } else if (auth_methods & kAuthPassword) {
- AddPasswordView();
- }
- if (auth_methods_ & kAuthFingerprint) {
- if (pin_pad_view_) {
- AddVerticalSpacing(kSpacingBetweenPinPadAndFingerprintIcon);
- } else if (password_view_) {
- AddVerticalSpacing(kSpacingBetweenPasswordAndFingerprintIcon);
- }
- fingerprint_view_ =
- container_->AddChildView(std::make_unique<FingerprintView>());
- fingerprint_view_->SetCanUsePin(auth_methods_ & kAuthPin);
- }
- AddVerticalSpacing(kSpacingBeforeButtons);
- AddActionButtonsView();
- }
- AuthDialogContentsView::~AuthDialogContentsView() = default;
- void AuthDialogContentsView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
- views::View::GetAccessibleNodeData(node_data);
- node_data->role = ax::mojom::Role::kDialog;
- node_data->SetName(
- l10n_util::GetStringFUTF16(IDS_ASH_IN_SESSION_AUTH_ACCESSIBLE_TITLE,
- base::UTF8ToUTF16(origin_name_)));
- }
- void AuthDialogContentsView::RequestFocus() {
- if (auth_methods_ == kAuthFingerprint) {
- // There's no PIN input field, so let the focus be on the cancel button
- // (instead of the help button) because it is more often used.
- cancel_button_->RequestFocus();
- return;
- }
- // For other cases, the base method correctly sets focus to the input field.
- views::View::RequestFocus();
- }
- void AuthDialogContentsView::AddedToWidget() {
- if (auth_methods_ & kAuthFingerprint) {
- // Inject a callback from the contents view so that we can show retry
- // prompt.
- WebAuthNDialogController::Get()->AuthenticateUserWithFingerprint(
- base::BindOnce(&AuthDialogContentsView::OnFingerprintAuthComplete,
- weak_factory_.GetWeakPtr()));
- }
- }
- void AuthDialogContentsView::AddAvatarView(const UserAvatar& avatar) {
- avatar_view_ =
- container_->AddChildView(std::make_unique<AnimatedRoundedImageView>(
- gfx::Size(kAvatarSizeDp, kAvatarSizeDp),
- kAvatarSizeDp / 2 /*corner_radius*/));
- avatar_view_->SetImage(avatar.image);
- }
- void AuthDialogContentsView::AddTitleView() {
- title_ = container_->AddChildView(std::make_unique<TitleLabel>());
- title_->ShowTitle();
- }
- void AuthDialogContentsView::AddOriginNameView() {
- origin_name_view_ =
- container_->AddChildView(std::make_unique<views::Label>());
- origin_name_view_->SetEnabledColor(kTextColorSecondary);
- origin_name_view_->SetSubpixelRenderingEnabled(false);
- origin_name_view_->SetAutoColorReadabilityEnabled(false);
- origin_name_view_->SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY);
- origin_name_view_->SetText(
- l10n_util::GetStringFUTF16(IDS_ASH_IN_SESSION_AUTH_ORIGIN_NAME_PROMPT,
- base::UTF8ToUTF16(origin_name_)));
- origin_name_view_->SetMultiLine(true);
- origin_name_view_->SetMaximumWidth(kContainerPreferredWidth);
- origin_name_view_->SetLineHeight(kOriginNameLineHeight);
- origin_name_view_->SetPreferredSize(gfx::Size(
- kContainerPreferredWidth,
- origin_name_view_->GetHeightForWidth(kContainerPreferredWidth)));
- origin_name_view_->SetHorizontalAlignment(gfx::ALIGN_CENTER);
- }
- void AuthDialogContentsView::AddPinTextInputView() {
- pin_text_input_view_ =
- container_->AddChildView(std::make_unique<LoginPasswordView>(palette_));
- pin_text_input_view_->SetPaintToLayer();
- pin_text_input_view_->layer()->SetFillsBoundsOpaquely(false);
- pin_text_input_view_->SetDisplayPasswordButtonVisible(true);
- pin_text_input_view_->SetEnabledOnEmptyPassword(false);
- pin_text_input_view_->SetFocusEnabledForTextfield(true);
- pin_text_input_view_->SetPlaceholderText(
- l10n_util::GetStringUTF16(IDS_ASH_IN_SESSION_AUTH_PIN_PLACEHOLDER));
- }
- void AuthDialogContentsView::AddPasswordView() {
- password_view_ =
- container_->AddChildView(std::make_unique<LoginPasswordView>(palette_));
- password_view_->SetPaintToLayer();
- password_view_->layer()->SetFillsBoundsOpaquely(false);
- password_view_->SetDisplayPasswordButtonVisible(true);
- password_view_->SetEnabledOnEmptyPassword(false);
- password_view_->SetFocusEnabledForTextfield(true);
- password_view_->SetPlaceholderText(
- l10n_util::GetStringUTF16(IDS_ASH_IN_SESSION_AUTH_PASSWORD_PLACEHOLDER));
- password_view_->Init(
- base::BindRepeating(&AuthDialogContentsView::OnAuthSubmit,
- base::Unretained(this),
- /*authenticated_by_pin=*/false),
- base::BindRepeating(&AuthDialogContentsView::OnInputTextChanged,
- base::Unretained(this)),
- base::DoNothing(), views::Button::PressedCallback());
- }
- void AuthDialogContentsView::AddPinPadView() {
- DCHECK(auth_methods_ & kAuthPin);
- if (pin_autosubmit_on_) {
- pin_pad_view_ = container_->AddChildView(std::make_unique<LoginPinView>(
- LoginPinView::Style::kAlphanumeric, palette_,
- base::BindRepeating(&AuthDialogContentsView::OnInsertDigitFromPinPad,
- base::Unretained(this)),
- base::BindRepeating(&AuthDialogContentsView::OnBackspaceFromPinPad,
- base::Unretained(this))));
- pin_digit_input_view_->Init(
- base::BindRepeating(&AuthDialogContentsView::OnAuthSubmit,
- base::Unretained(this),
- /*authenticated_by_pin=*/true),
- base::BindRepeating(&AuthDialogContentsView::OnInputTextChanged,
- base::Unretained(this)));
- } else {
- pin_pad_view_ = container_->AddChildView(std::make_unique<LoginPinView>(
- LoginPinView::Style::kAlphanumeric, palette_,
- base::BindRepeating(&AuthDialogContentsView::OnInsertDigitFromPinPad,
- base::Unretained(this)),
- base::BindRepeating(&AuthDialogContentsView::OnBackspaceFromPinPad,
- base::Unretained(this)),
- base::BindRepeating(&LoginPasswordView::SubmitPassword,
- base::Unretained(pin_text_input_view_))));
- pin_text_input_view_->Init(
- base::BindRepeating(&AuthDialogContentsView::OnAuthSubmit,
- base::Unretained(this),
- /*authenticated_by_pin=*/true),
- base::BindRepeating(&AuthDialogContentsView::OnInputTextChanged,
- base::Unretained(this)),
- base::DoNothing(), views::Button::PressedCallback());
- }
- pin_pad_view_->SetVisible(true);
- }
- void AuthDialogContentsView::AddPinDigitInputView() {
- pin_digit_input_view_ =
- container_->AddChildView(std::make_unique<LoginPinInputView>(palette_));
- pin_digit_input_view_->UpdateLength(auth_metadata_.autosubmit_pin_length);
- pin_digit_input_view_->SetVisible(true);
- }
- void AuthDialogContentsView::AddVerticalSpacing(int height) {
- auto* spacing =
- container_->AddChildView(std::make_unique<NonAccessibleView>());
- spacing->SetPreferredSize(gfx::Size(kContainerPreferredWidth, height));
- }
- void AuthDialogContentsView::AddActionButtonsView() {
- action_view_container_ =
- container_->AddChildView(std::make_unique<NonAccessibleView>());
- auto* buttons_layout = action_view_container_->SetLayoutManager(
- std::make_unique<views::BoxLayout>(
- views::BoxLayout::Orientation::kHorizontal));
- buttons_layout->set_main_axis_alignment(
- views::BoxLayout::MainAxisAlignment::kStart);
- help_button_ =
- action_view_container_->AddChildView(std::make_unique<views::LabelButton>(
- base::BindRepeating(&AuthDialogContentsView::OnNeedHelpButtonPressed,
- base::Unretained(this)),
- l10n_util::GetStringUTF16(IDS_ASH_IN_SESSION_AUTH_HELP),
- views::style::CONTEXT_BUTTON));
- help_button_->SetEnabledTextColors(kTextColorPrimary);
- auto* spacing = action_view_container_->AddChildView(
- std::make_unique<NonAccessibleView>());
- buttons_layout->SetFlexForView(spacing, 1);
- cancel_button_ = action_view_container_->AddChildView(
- std::make_unique<views::MdTextButton>(
- base::BindRepeating(&AuthDialogContentsView::OnCancelButtonPressed,
- base::Unretained(this)),
- l10n_util::GetStringUTF16(IDS_ASH_IN_SESSION_AUTH_CANCEL)));
- action_view_container_->SetPreferredSize(
- gfx::Size(kContainerPreferredWidth, cancel_button_->height()));
- }
- void AuthDialogContentsView::OnInsertDigitFromPinPad(int digit) {
- // Ignore anything if reached max attempts.
- if (pin_locked_out_)
- return;
- if (title_->IsShowingError())
- title_->ShowTitle();
- if (pin_autosubmit_on_) {
- pin_digit_input_view_->InsertDigit(digit);
- } else {
- pin_text_input_view_->InsertNumber(digit);
- }
- }
- void AuthDialogContentsView::OnBackspaceFromPinPad() {
- // Ignore anything if reached max attempts.
- if (pin_locked_out_)
- return;
- if (title_->IsShowingError())
- title_->ShowTitle();
- if (pin_autosubmit_on_) {
- pin_digit_input_view_->Backspace();
- } else {
- pin_text_input_view_->Backspace();
- }
- }
- void AuthDialogContentsView::OnInputTextChanged(bool is_empty) {
- // If the user is interacting with the input field, restore the title (clear
- // error message).
- //
- // If |is_empty| is true, this call may come from resetting
- // |pin_text_input_view_| or |pin_digit_input_view_|, when the error message
- // hasn't been shown and read yet. In this case we don't restore the title.
- if (title_->IsShowingError() && !is_empty)
- title_->ShowTitle();
- if (pin_pad_view_) {
- pin_pad_view_->OnPasswordTextChanged(is_empty);
- }
- }
- void AuthDialogContentsView::OnAuthSubmit(bool authenticated_by_pin,
- const std::u16string& password) {
- if (authenticated_by_pin) {
- if (pin_autosubmit_on_) {
- pin_digit_input_view_->SetReadOnly(true);
- } else {
- pin_text_input_view_->SetReadOnly(true);
- }
- } else {
- password_view_->SetReadOnly(true);
- }
- WebAuthNDialogController::Get()->AuthenticateUserWithPasswordOrPin(
- base::UTF16ToUTF8(password), authenticated_by_pin,
- base::BindOnce(&AuthDialogContentsView::OnPasswordOrPinAuthComplete,
- weak_factory_.GetWeakPtr(), authenticated_by_pin));
- }
- void AuthDialogContentsView::OnPasswordOrPinAuthComplete(
- bool authenticated_by_pin,
- bool success,
- bool can_use_pin) {
- // On success, do nothing, and the dialog will dismiss.
- if (success)
- return;
- std::u16string error_text;
- if (authenticated_by_pin) {
- pin_locked_out_ = !can_use_pin;
- error_text =
- pin_locked_out_
- ? l10n_util::GetStringUTF16(
- IDS_ASH_IN_SESSION_AUTH_PIN_TOO_MANY_ATTEMPTS)
- : l10n_util::GetStringUTF16(IDS_ASH_IN_SESSION_AUTH_PIN_INCORRECT);
- } else {
- error_text =
- l10n_util::GetStringUTF16(IDS_ASH_IN_SESSION_AUTH_PASSWORD_INCORRECT);
- }
- title_->ShowError(error_text);
- if (!authenticated_by_pin) {
- password_view_->Reset();
- password_view_->SetReadOnly(false);
- } else if (can_use_pin) {
- if (pin_autosubmit_on_) {
- pin_digit_input_view_->Reset();
- pin_digit_input_view_->SetReadOnly(false);
- } else {
- pin_text_input_view_->Reset();
- pin_text_input_view_->SetReadOnly(false);
- }
- }
- }
- void AuthDialogContentsView::OnFingerprintAuthComplete(
- bool success,
- FingerprintState fingerprint_state) {
- fingerprint_view_->SetState(fingerprint_state);
- // Prepare for the next fingerprint scan.
- if (!success && fingerprint_state == FingerprintState::AVAILABLE_DEFAULT) {
- WebAuthNDialogController::Get()->AuthenticateUserWithFingerprint(
- base::BindOnce(&AuthDialogContentsView::OnFingerprintAuthComplete,
- weak_factory_.GetWeakPtr()));
- }
- fingerprint_view_->NotifyFingerprintAuthResult(success);
- }
- void AuthDialogContentsView::OnCancelButtonPressed(const ui::Event& event) {
- WebAuthNDialogController::Get()->Cancel();
- }
- void AuthDialogContentsView::OnNeedHelpButtonPressed(const ui::Event& event) {
- WebAuthNDialogController::Get()->OpenInSessionAuthHelpPage();
- }
- } // namespace ash
|