Commit 16536d8d authored by Martin Kreichgauer's avatar Martin Kreichgauer Committed by Commit Bot

fido: first attempt at authenticator PIN UI

This adds views for setting up a PIN and challenging a PIN during a
WebAuthn request. Nothing wired up into //device/fido yet.

TBR=oshima@chromium.org

Change-Id: I009986e65ae38d50908d5bdfb993885489d1c0d8
Reviewed-on: https://chromium-review.googlesource.com/c/1462423
Commit-Queue: Martin Kreichgauer <martinkr@google.com>
Reviewed-by: default avatarMitsuru Oshima <oshima@chromium.org>
Reviewed-by: default avatarAdam Langley <agl@chromium.org>
Reviewed-by: default avatarKim Paulhamus <kpaulhamus@chromium.org>
Cr-Commit-Position: refs/heads/master@{#632043}
parent 87b8ef8e
......@@ -9332,6 +9332,33 @@ Please help our engineers fix this problem. Tell us what happened right before y
<message name="IDS_WEBAUTHN_CABLE_ACTIVATE_DESCRIPTION" desc="Contents of the dialog shown when the user tries to sign-in using a phone as a security key.">
A notification was sent to your phone. Follow the prompts to confirm it's you.
</message>
<message name="IDS_WEBAUTHN_PIN_ENTRY_TITLE" desc="Title of the dialog shown when instructing the user to enter the PIN code to use a security key (an external physical device for user authentication) with their computer.">
PIN required
</message>
<message name="IDS_WEBAUTHN_PIN_ENTRY_DESCRIPTION" desc="Description in the dialog shown when instructing the user to enter the PIN code to use a security key (an external physical device for user authentication) with their computer.">
Enter the PIN for your security key
</message>
<message name="IDS_WEBAUTHN_PIN_ENTRY_PIN_LABEL" desc="Label text. Displayed next to a text box where the user enters the PIN code for their security key (an external physical device for user authentication).">
PIN
</message>
<message name="IDS_WEBAUTHN_PIN_ENTRY_NEXT" desc="Button text. The user clicks this button once they have entered the PIN code into a text box in order to continue.">
Next
</message>
<message name="IDS_WEBAUTHN_PIN_SETUP_DESCRIPTION" desc="Description in the dialog shown when instructing the user to set up a PIN code to use with their security key (an external physical device for user authentication) with their computer.">
Set up a new PIN for your security key
</message>
<message name="IDS_WEBAUTHN_PIN_SETUP_CONFIRMATION_LABEL" desc="Label text. Displayed next to a text box where the user re-enters the PIN code for their security key (an external physical device for user authentication).">
Confirm PIN
</message>
<message name="IDS_WEBAUTHN_PIN_ENTRY_ERROR_INVALID_CHARACTERS" desc="Error message. Displayed when the user attempts to set a PIN code for their security key (an external physical device for user authentication), and the PIN chosen by them contains invalid characters.">
PIN contains invalid characters
</message>
<message name="IDS_WEBAUTHN_PIN_ENTRY_ERROR_TOO_SHORT" desc="Error message. Displayed when the user attempts to set a PIN code for their security key (an external physical device for user authentication), and the PIN chosen by them is too short.">
PIN is too short.
</message>
<message name="IDS_WEBAUTHN_PIN_ENTRY_ERROR_MISMATCH" desc="Error message. Displayed when the user attempts to set a PIN code for their security key (an external physical device for user authentication), and the confirmation value does not match the first value they entered.">
Confirmation does not match.
</message>
</if>
<if expr="is_macosx">
<message name="IDS_WEBAUTHN_TOUCH_ID_TITLE" desc="Title of the dialog shown when the user tries to sign in with Touch ID." meaning="'Touch ID' is the fingerprint recognition feature in macOS. Try to refer Apple support documentation in the target language for the appropriate product name translation.">
......
......@@ -306,6 +306,7 @@
<structure type="chrome_scaled_image" name="IDR_WEBAUTHN_ILLUSTRATION_PHONE" file="common/webauthn/phone.png" />
<structure type="chrome_scaled_image" name="IDR_WEBAUTHN_ILLUSTRATION_USB" file="common/webauthn/usb.png" />
<structure type="chrome_scaled_image" name="IDR_WEBAUTHN_ILLUSTRATION_WELCOME" file="common/webauthn/welcome.png" />
<structure type="chrome_scaled_image" name="IDR_WEBAUTHN_ILLUSTRATION_PIN" file="common/webauthn/usb.png" />
</if>
<if expr="is_macosx">
<structure type="chrome_scaled_image" name="IDR_WEBAUTHN_ILLUSTRATION_TOUCHID" file="common/webauthn/touchid.png" />
......
......@@ -2858,6 +2858,10 @@ jumbo_split_static_library("ui") {
"views/update_recommended_message_box.h",
"views/webauthn/authenticator_ble_pin_entry_sheet_view.cc",
"views/webauthn/authenticator_ble_pin_entry_sheet_view.h",
"views/webauthn/authenticator_client_pin_entry_sheet_view.cc",
"views/webauthn/authenticator_client_pin_entry_sheet_view.h",
"views/webauthn/authenticator_client_pin_entry_view.cc",
"views/webauthn/authenticator_client_pin_entry_view.h",
"views/webauthn/authenticator_request_dialog_view.cc",
"views/webauthn/authenticator_request_dialog_view.h",
"views/webauthn/authenticator_request_sheet_view.cc",
......
// Copyright 2019 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 "chrome/browser/ui/views/webauthn/authenticator_client_pin_entry_sheet_view.h"
#include <memory>
#include <utility>
AuthenticatorClientPinEntrySheetView::AuthenticatorClientPinEntrySheetView(
std::unique_ptr<AuthenticatorClientPinEntrySheetModel> sheet_model)
: AuthenticatorRequestSheetView(std::move(sheet_model)) {
pin_entry_sheet_model()->SetDelegate(this);
}
AuthenticatorClientPinEntrySheetView::~AuthenticatorClientPinEntrySheetView() =
default;
AuthenticatorClientPinEntrySheetModel*
AuthenticatorClientPinEntrySheetView::pin_entry_sheet_model() {
return static_cast<AuthenticatorClientPinEntrySheetModel*>(model());
}
std::unique_ptr<views::View>
AuthenticatorClientPinEntrySheetView::BuildStepSpecificContent() {
DCHECK(!pin_entry_view_);
auto view = std::make_unique<AuthenticatorClientPinEntryView>(
this, pin_entry_sheet_model()->mode() ==
AuthenticatorClientPinEntrySheetModel::Mode::
kPinSetup /* show_confirmation_text_field */);
pin_entry_view_ = view.get();
return view;
}
void AuthenticatorClientPinEntrySheetView::OnPincodeChanged(
base::string16 pincode) {
pin_entry_sheet_model()->SetPinCode(std::move(pincode));
}
void AuthenticatorClientPinEntrySheetView::OnConfirmationChanged(
base::string16 pincode) {
pin_entry_sheet_model()->SetPinConfirmation(std::move(pincode));
}
void AuthenticatorClientPinEntrySheetView::ShowPinError(
const base::string16& error) {
if (!pin_entry_view_) {
DCHECK(false);
return;
}
pin_entry_view_->UpdateError(error);
}
// Copyright 2019 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.
#ifndef CHROME_BROWSER_UI_VIEWS_WEBAUTHN_AUTHENTICATOR_CLIENT_PIN_ENTRY_SHEET_VIEW_H_
#define CHROME_BROWSER_UI_VIEWS_WEBAUTHN_AUTHENTICATOR_CLIENT_PIN_ENTRY_SHEET_VIEW_H_
#include <memory>
#include "base/macros.h"
#include "chrome/browser/ui/views/webauthn/authenticator_client_pin_entry_view.h"
#include "chrome/browser/ui/views/webauthn/authenticator_request_sheet_view.h"
#include "chrome/browser/ui/webauthn/sheet_models.h"
// Web Authentication request dialog sheet view for entering an authenticator
// PIN.
class AuthenticatorClientPinEntrySheetView
: public AuthenticatorRequestSheetView,
public AuthenticatorClientPinEntrySheetModel::Delegate,
public AuthenticatorClientPinEntryView::Delegate {
public:
explicit AuthenticatorClientPinEntrySheetView(
std::unique_ptr<AuthenticatorClientPinEntrySheetModel> model);
~AuthenticatorClientPinEntrySheetView() override;
private:
AuthenticatorClientPinEntrySheetModel* pin_entry_sheet_model();
// AuthenticatorRequestSheetView:
std::unique_ptr<views::View> BuildStepSpecificContent() override;
// AuthenticatorClientPinEntrySheetModel::Delegate:
void ShowPinError(const base::string16& error) override;
// AuthenticatorClientPinEntryView::Delegate:
void OnPincodeChanged(base::string16 pincode) override;
void OnConfirmationChanged(base::string16 pincode) override;
AuthenticatorClientPinEntryView* pin_entry_view_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(AuthenticatorClientPinEntrySheetView);
};
#endif // CHROME_BROWSER_UI_VIEWS_WEBAUTHN_AUTHENTICATOR_CLIENT_PIN_ENTRY_SHEET_VIEW_H_
// Copyright 2019 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 "chrome/browser/ui/views/webauthn/authenticator_client_pin_entry_view.h"
#include <memory>
#include <utility>
#include "base/strings/string_number_conversions.h"
#include "chrome/browser/ui/views/chrome_layout_provider.h"
#include "chrome/grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/layout/layout_provider.h"
#include "ui/views/style/typography.h"
namespace {
constexpr int kExpectedPincodeCharLength = 6;
constexpr int kPreferredTextfieldCharLength = 20;
constexpr int kTextfieldBottomBorderThickness = 2;
} // namespace
AuthenticatorClientPinEntryView::AuthenticatorClientPinEntryView(
Delegate* delegate,
bool show_confirmation_text_field)
: delegate_(delegate),
show_confirmation_text_field_(show_confirmation_text_field) {
views::GridLayout* layout =
SetLayoutManager(std::make_unique<views::GridLayout>(this));
views::ColumnSet* columns = layout->AddColumnSet(0);
columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::LEADING,
views::GridLayout::kFixedSize, views::GridLayout::USE_PREF,
0, 0);
columns->AddPaddingColumn(views::GridLayout::kFixedSize, 10);
columns->AddColumn(views::GridLayout::LEADING, views::GridLayout::LEADING,
views::GridLayout::kFixedSize, views::GridLayout::USE_PREF,
0, 0);
layout->StartRow(views::GridLayout::kFixedSize, 0);
auto pin_label = std::make_unique<views::Label>(
l10n_util::GetStringUTF16(IDS_WEBAUTHN_PIN_ENTRY_PIN_LABEL),
views::style::CONTEXT_LABEL, views::style::STYLE_PRIMARY);
pin_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
pin_label->SetEnabledColor(gfx::kGoogleBlue500);
auto* pin_label_ptr = pin_label.get();
layout->AddView(pin_label.release());
views::View* confirmation_label_ptr = nullptr;
if (show_confirmation_text_field_) {
auto confirmation_label = std::make_unique<views::Label>(
l10n_util::GetStringUTF16(IDS_WEBAUTHN_PIN_SETUP_CONFIRMATION_LABEL),
views::style::CONTEXT_LABEL, views::style::STYLE_PRIMARY);
confirmation_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
confirmation_label->SetEnabledColor(gfx::kGoogleBlue500);
confirmation_label_ptr = confirmation_label.get();
layout->AddView(confirmation_label.release());
}
layout->StartRow(views::GridLayout::kFixedSize, 0);
auto pin_text_field = std::make_unique<views::Textfield>();
pin_text_field->SetTextInputType(ui::TextInputType::TEXT_INPUT_TYPE_PASSWORD);
pin_text_field->SetBackgroundColor(gfx::kGoogleGrey100);
pin_text_field->SetMinimumWidthInChars(kExpectedPincodeCharLength);
pin_text_field->SetDefaultWidthInChars(kPreferredTextfieldCharLength);
pin_text_field->SetBorder(views::CreateSolidSidedBorder(
0, 0, kTextfieldBottomBorderThickness, 0, gfx::kGoogleBlue500));
pin_text_field->set_controller(this);
pin_text_field->SetAssociatedLabel(pin_label_ptr);
pin_text_field_ = pin_text_field.get();
layout->AddView(pin_text_field.release());
if (show_confirmation_text_field_) {
DCHECK(confirmation_label_ptr);
auto confirmation_text_field = std::make_unique<views::Textfield>();
confirmation_text_field->SetTextInputType(
ui::TextInputType::TEXT_INPUT_TYPE_PASSWORD);
confirmation_text_field->SetBackgroundColor(gfx::kGoogleGrey100);
confirmation_text_field->SetMinimumWidthInChars(kExpectedPincodeCharLength);
confirmation_text_field->SetDefaultWidthInChars(
kPreferredTextfieldCharLength);
confirmation_text_field->SetBorder(views::CreateSolidSidedBorder(
0, 0, kTextfieldBottomBorderThickness, 0, gfx::kGoogleBlue500));
confirmation_text_field->set_controller(this);
confirmation_text_field->SetAssociatedLabel(confirmation_label_ptr);
confirmation_text_field_ = confirmation_text_field.get();
layout->AddView(confirmation_text_field.release());
}
layout->StartRow(views::GridLayout::kFixedSize, 0);
auto error_label = std::make_unique<views::Label>(
base::string16(), views::style::CONTEXT_LABEL,
views::style::STYLE_PRIMARY);
error_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
error_label->SetEnabledColor(gfx::kGoogleRed500);
error_label_ = error_label.get();
layout->AddView(error_label.release(), 3 /* col_span */, 1 /* row_span */);
}
AuthenticatorClientPinEntryView::~AuthenticatorClientPinEntryView() = default;
void AuthenticatorClientPinEntryView::UpdateError(const base::string16& text) {
error_label_->SetVisible(true);
error_label_->SetText(text);
error_label_->SizeToPreferredSize();
}
void AuthenticatorClientPinEntryView::RequestFocus() {
pin_text_field_->RequestFocus();
}
void AuthenticatorClientPinEntryView::ContentsChanged(
views::Textfield* sender,
const base::string16& new_contents) {
DCHECK(sender == pin_text_field_ || sender == confirmation_text_field_);
if (sender == pin_text_field_) {
delegate_->OnPincodeChanged(new_contents);
} else {
delegate_->OnConfirmationChanged(new_contents);
}
}
bool AuthenticatorClientPinEntryView::HandleKeyEvent(
views::Textfield* sender,
const ui::KeyEvent& key_event) {
// As WebAuthN UI views do not intercept any key events, the key event must
// be further processed.
return false;
}
// Copyright 2019 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.
#ifndef CHROME_BROWSER_UI_VIEWS_WEBAUTHN_AUTHENTICATOR_CLIENT_PIN_ENTRY_VIEW_H_
#define CHROME_BROWSER_UI_VIEWS_WEBAUTHN_AUTHENTICATOR_CLIENT_PIN_ENTRY_VIEW_H_
#include "base/macros.h"
#include "base/optional.h"
#include "base/strings/string16.h"
#include "ui/views/controls/textfield/textfield_controller.h"
#include "ui/views/view.h"
namespace views {
class Textfield;
class Label;
} // namespace views
// View showing a label and text field for entering an authenticator PIN.
//
// TODO(martinkr): Reuse for BLE PIN or fold into
// AuthenticatorClientPinEntrySheetModel.
class AuthenticatorClientPinEntryView : public views::View,
public views::TextfieldController {
public:
class Delegate {
public:
virtual void OnPincodeChanged(base::string16 pin_code) = 0;
virtual void OnConfirmationChanged(base::string16 pin_confirmation) = 0;
};
explicit AuthenticatorClientPinEntryView(Delegate* delegate,
bool show_confirmation_text_field);
~AuthenticatorClientPinEntryView() override;
void UpdateError(const base::string16& value);
private:
// views::View:
void RequestFocus() override;
// views::TextFieldController:
void ContentsChanged(views::Textfield* sender,
const base::string16& new_contents) override;
bool HandleKeyEvent(views::Textfield* sender,
const ui::KeyEvent& key_event) override;
Delegate* const delegate_;
views::Textfield* pin_text_field_ = nullptr;
views::Textfield* confirmation_text_field_ = nullptr;
views::Label* error_label_ = nullptr;
const bool show_confirmation_text_field_;
DISALLOW_COPY_AND_ASSIGN(AuthenticatorClientPinEntryView);
};
#endif // CHROME_BROWSER_UI_VIEWS_WEBAUTHN_AUTHENTICATOR_CLIENT_PIN_ENTRY_VIEW_H_
......@@ -6,6 +6,7 @@
#include "base/logging.h"
#include "chrome/browser/ui/views/webauthn/authenticator_ble_pin_entry_sheet_view.h"
#include "chrome/browser/ui/views/webauthn/authenticator_client_pin_entry_sheet_view.h"
#include "chrome/browser/ui/views/webauthn/authenticator_request_sheet_view.h"
#include "chrome/browser/ui/views/webauthn/authenticator_transport_selector_sheet_view.h"
#include "chrome/browser/ui/views/webauthn/ble_device_selection_sheet_view.h"
......@@ -118,6 +119,18 @@ std::unique_ptr<AuthenticatorRequestSheetView> CreateSheetViewForCurrentStepOf(
sheet_view = std::make_unique<AuthenticatorRequestSheetView>(
std::make_unique<AuthenticatorPaaskSheetModel>(dialog_model));
break;
case Step::kClientPinEntry:
sheet_view = std::make_unique<AuthenticatorClientPinEntrySheetView>(
std::make_unique<AuthenticatorClientPinEntrySheetModel>(
dialog_model,
AuthenticatorClientPinEntrySheetModel::Mode::kPinEntry));
break;
case Step::kClientPinSetup:
sheet_view = std::make_unique<AuthenticatorClientPinEntrySheetView>(
std::make_unique<AuthenticatorClientPinEntrySheetModel>(
dialog_model,
AuthenticatorClientPinEntrySheetModel::Mode::kPinSetup));
break;
case Step::kNotStarted:
case Step::kClosed:
sheet_view = std::make_unique<AuthenticatorRequestSheetView>(
......
......@@ -8,6 +8,7 @@
#include <utility>
#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "chrome/browser/ui/webauthn/other_transports_menu_model.h"
......@@ -662,3 +663,100 @@ base::string16 AuthenticatorPaaskSheetModel::GetStepDescription() const {
ui::MenuModel* AuthenticatorPaaskSheetModel::GetOtherTransportsMenuModel() {
return other_transports_menu_model_.get();
}
// AuthenticatorClientPinEntrySheetModel
// -----------------------------------------
AuthenticatorClientPinEntrySheetModel::AuthenticatorClientPinEntrySheetModel(
AuthenticatorRequestDialogModel* dialog_model,
Mode mode)
: AuthenticatorSheetModelBase(dialog_model), mode_(mode) {}
AuthenticatorClientPinEntrySheetModel::
~AuthenticatorClientPinEntrySheetModel() = default;
void AuthenticatorClientPinEntrySheetModel::SetDelegate(Delegate* delegate) {
DCHECK(!delegate_);
delegate_ = delegate;
}
void AuthenticatorClientPinEntrySheetModel::SetPinCode(
base::string16 pin_code) {
pin_code_ = std::move(pin_code);
}
void AuthenticatorClientPinEntrySheetModel::SetPinConfirmation(
base::string16 pin_confirmation) {
DCHECK(mode_ == AuthenticatorClientPinEntrySheetModel::Mode::kPinSetup);
pin_confirmation_ = std::move(pin_confirmation);
}
gfx::ImageSkia* AuthenticatorClientPinEntrySheetModel::GetStepIllustration()
const {
return GetImage(IDR_WEBAUTHN_ILLUSTRATION_PIN);
}
base::string16 AuthenticatorClientPinEntrySheetModel::GetStepTitle() const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_PIN_ENTRY_TITLE);
}
base::string16 AuthenticatorClientPinEntrySheetModel::GetStepDescription()
const {
return l10n_util::GetStringUTF16(
mode_ == AuthenticatorClientPinEntrySheetModel::Mode::kPinEntry
? IDS_WEBAUTHN_PIN_ENTRY_DESCRIPTION
: IDS_WEBAUTHN_PIN_SETUP_DESCRIPTION);
}
bool AuthenticatorClientPinEntrySheetModel::IsAcceptButtonVisible() const {
return true;
}
bool AuthenticatorClientPinEntrySheetModel::IsAcceptButtonEnabled() const {
return true;
}
base::string16 AuthenticatorClientPinEntrySheetModel::GetAcceptButtonLabel()
const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_PIN_ENTRY_NEXT);
}
static bool IsValidUTF16(const base::string16& str16) {
std::string unused_str8;
return base::UTF16ToUTF8(str16.c_str(), str16.size(), &unused_str8);
}
void AuthenticatorClientPinEntrySheetModel::OnAccept() {
// TODO(martinkr): use device::pin::kMinLength once landed.
constexpr size_t kMinPinLength = 4;
if (!delegate_) {
NOTREACHED();
return;
}
if (mode_ == AuthenticatorClientPinEntrySheetModel::Mode::kPinSetup) {
// Validate a new PIN.
base::Optional<base::string16> error;
if (!pin_code_.empty() && !IsValidUTF16(pin_code_)) {
error = l10n_util::GetStringUTF16(
IDS_WEBAUTHN_PIN_ENTRY_ERROR_INVALID_CHARACTERS);
} else if (pin_code_.size() < kMinPinLength) {
error = l10n_util::GetStringUTF16(IDS_WEBAUTHN_PIN_ENTRY_ERROR_TOO_SHORT);
} else if (pin_code_ != pin_confirmation_) {
error = l10n_util::GetStringUTF16(IDS_WEBAUTHN_PIN_ENTRY_ERROR_MISMATCH);
}
if (error) {
delegate_->ShowPinError(*error);
return;
}
} else {
// Submit PIN to authenticator for verification.
DCHECK(mode_ == AuthenticatorClientPinEntrySheetModel::Mode::kPinEntry);
if (pin_code_.size() < kMinPinLength) {
delegate_->ShowPinError(
l10n_util::GetStringUTF16(IDS_WEBAUTHN_PIN_ENTRY_ERROR_TOO_SHORT));
return;
}
}
// TODO(martinkr): Actually set the PIN/request the PIN token and continue
// the request.
}
......@@ -344,4 +344,43 @@ class AuthenticatorPaaskSheetModel : public AuthenticatorSheetModelBase {
std::unique_ptr<OtherTransportsMenuModel> other_transports_menu_model_;
};
class AuthenticatorClientPinEntrySheetModel
: public AuthenticatorSheetModelBase {
public:
class Delegate {
public:
virtual void ShowPinError(const base::string16& error) = 0;
};
// Indicates whether the view should accommodate setting up a new PIN or
// entering an existing one.
enum class Mode { kPinEntry, kPinSetup };
AuthenticatorClientPinEntrySheetModel(
AuthenticatorRequestDialogModel* dialog_model,
Mode mode);
~AuthenticatorClientPinEntrySheetModel() override;
using AuthenticatorSheetModelBase::AuthenticatorSheetModelBase;
void SetDelegate(Delegate* delegate);
void SetPinCode(base::string16 pin_code);
void SetPinConfirmation(base::string16 pin_confirmation);
Mode mode() const { return mode_; }
private:
// AuthenticatorSheetModelBase:
gfx::ImageSkia* GetStepIllustration() const override;
base::string16 GetStepTitle() const override;
base::string16 GetStepDescription() const override;
bool IsAcceptButtonVisible() const override;
bool IsAcceptButtonEnabled() const override;
base::string16 GetAcceptButtonLabel() const override;
void OnAccept() override;
base::string16 pin_code_;
base::string16 pin_confirmation_;
const Mode mode_;
Delegate* delegate_ = nullptr;
};
#endif // CHROME_BROWSER_UI_WEBAUTHN_SHEET_MODELS_H_
......@@ -79,6 +79,10 @@ class AuthenticatorRequestDialogModel {
// Phone as a security key.
kCableActivate,
// Authenticator Client PIN.
kClientPinEntry,
kClientPinSetup,
};
// Implemented by the dialog to observe this model and show the UI panels
......
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