blob: 867b29ca2b44189f10982784d171351842e89b22 [file] [log] [blame]
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/ui/webauthn/sheet_models.h"
#include <memory>
#include <string>
#include <utility>
#include "base/check_op.h"
#include "base/i18n/number_formatting.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/notreached.h"
#include "base/ranges/algorithm.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "chrome/app/vector_icons/vector_icons.h"
#include "chrome/browser/ui/webauthn/webauthn_ui_helpers.h"
#include "chrome/grit/browser_resources.h"
#include "chrome/grit/generated_resources.h"
#include "components/strings/grit/components_strings.h"
#include "components/url_formatter/elide_url.h"
#include "device/fido/authenticator_get_assertion_response.h"
#include "device/fido/discoverable_credential_metadata.h"
#include "device/fido/fido_types.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/font_list.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/gfx/text_utils.h"
#include "url/gurl.h"
#if BUILDFLAG(IS_MAC)
#include "base/mac/mac_util.h"
#endif
namespace {
// Possibly returns a resident key warning if the model indicates that it's
// needed.
std::u16string PossibleResidentKeyWarning(
AuthenticatorRequestDialogModel* dialog_model) {
switch (dialog_model->resident_key_requirement()) {
case device::ResidentKeyRequirement::kDiscouraged:
return std::u16string();
case device::ResidentKeyRequirement::kPreferred:
return l10n_util::GetStringUTF16(
IDS_WEBAUTHN_RESIDENT_KEY_PREFERRED_PRIVACY);
case device::ResidentKeyRequirement::kRequired:
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_RESIDENT_KEY_PRIVACY);
}
NOTREACHED();
return std::u16string();
}
} // namespace
// AuthenticatorSheetModelBase ------------------------------------------------
AuthenticatorSheetModelBase::AuthenticatorSheetModelBase(
AuthenticatorRequestDialogModel* dialog_model)
: dialog_model_(dialog_model) {
DCHECK(dialog_model);
dialog_model_->AddObserver(this);
}
AuthenticatorSheetModelBase::AuthenticatorSheetModelBase(
AuthenticatorRequestDialogModel* dialog_model,
OtherMechanismButtonVisibility other_mechanism_button_visibility)
: AuthenticatorSheetModelBase(dialog_model) {
other_mechanism_button_visibility_ = other_mechanism_button_visibility;
}
AuthenticatorSheetModelBase::~AuthenticatorSheetModelBase() {
if (dialog_model_) {
dialog_model_->RemoveObserver(this);
dialog_model_ = nullptr;
}
}
// static
std::u16string AuthenticatorSheetModelBase::GetRelyingPartyIdString(
const AuthenticatorRequestDialogModel* dialog_model) {
// The preferred width of medium snap point modal dialog view is 448 dp, but
// we leave some room for padding between the text and the modal views.
static constexpr int kDialogWidth = 300;
return webauthn_ui_helpers::RpIdToElidedHost(dialog_model->relying_party_id(),
kDialogWidth);
}
bool AuthenticatorSheetModelBase::IsActivityIndicatorVisible() const {
return false;
}
bool AuthenticatorSheetModelBase::IsBackButtonVisible() const {
return true;
}
bool AuthenticatorSheetModelBase::IsCancelButtonVisible() const {
return true;
}
bool AuthenticatorSheetModelBase::IsOtherMechanismButtonVisible() const {
return other_mechanism_button_visibility_ ==
OtherMechanismButtonVisibility::kVisible &&
dialog_model_ && dialog_model_->mechanisms().size() > 1;
}
std::u16string AuthenticatorSheetModelBase::GetOtherMechanismButtonLabel()
const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_USE_A_DIFFERENT_DEVICE);
}
std::u16string AuthenticatorSheetModelBase::GetCancelButtonLabel() const {
return l10n_util::GetStringUTF16(IDS_CANCEL);
}
bool AuthenticatorSheetModelBase::IsAcceptButtonVisible() const {
return false;
}
bool AuthenticatorSheetModelBase::IsAcceptButtonEnabled() const {
return false;
}
std::u16string AuthenticatorSheetModelBase::GetAcceptButtonLabel() const {
return std::u16string();
}
void AuthenticatorSheetModelBase::OnBack() {
if (dialog_model()) {
dialog_model()->StartOver();
}
}
void AuthenticatorSheetModelBase::OnAccept() {
NOTREACHED();
}
void AuthenticatorSheetModelBase::OnCancel() {
if (dialog_model()) {
dialog_model()->Cancel();
}
}
void AuthenticatorSheetModelBase::OnModelDestroyed(
AuthenticatorRequestDialogModel* model) {
DCHECK(model == dialog_model_);
dialog_model_ = nullptr;
}
// AuthenticatorMechanismSelectorSheetModel -----------------------------------
AuthenticatorMechanismSelectorSheetModel::
AuthenticatorMechanismSelectorSheetModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model) {
vector_illustrations_.emplace(kPasskeyHeaderIcon, kPasskeyHeaderDarkIcon);
}
bool AuthenticatorMechanismSelectorSheetModel::IsBackButtonVisible() const {
return false;
}
std::u16string AuthenticatorMechanismSelectorSheetModel::GetStepTitle() const {
switch (dialog_model()->transport_availability()->request_type) {
case device::FidoRequestType::kMakeCredential:
return l10n_util::GetStringUTF16(
IDS_WEBAUTHN_CREATE_PASSKEY_CHOOSE_DEVICE_TITLE);
case device::FidoRequestType::kGetAssertion:
return l10n_util::GetStringUTF16(
IDS_WEBAUTHN_USE_PASSKEY_CHOOSE_DEVICE_TITLE);
}
}
std::u16string AuthenticatorMechanismSelectorSheetModel::GetStepDescription()
const {
switch (dialog_model()->transport_availability()->request_type) {
case device::FidoRequestType::kMakeCredential:
return l10n_util::GetStringFUTF16(
IDS_WEBAUTHN_CREATE_PASSKEY_CHOOSE_DEVICE_BODY,
GetRelyingPartyIdString(dialog_model()));
case device::FidoRequestType::kGetAssertion:
return l10n_util::GetStringFUTF16(
IDS_WEBAUTHN_USE_PASSKEY_CHOOSE_DEVICE_BODY,
GetRelyingPartyIdString(dialog_model()));
}
}
bool AuthenticatorMechanismSelectorSheetModel::IsManageDevicesButtonVisible()
const {
// If any phones are shown then also show a button that goes to the settings
// page to manage them.
return base::ranges::any_of(
dialog_model()->mechanisms(),
[](const AuthenticatorRequestDialogModel::Mechanism& mechanism) {
return absl::holds_alternative<
AuthenticatorRequestDialogModel::Mechanism::Phone>(mechanism.type);
});
}
void AuthenticatorMechanismSelectorSheetModel::OnManageDevices() {
if (dialog_model()) {
dialog_model()->ManageDevices();
}
}
// AuthenticatorInsertAndActivateUsbSheetModel ----------------------
AuthenticatorInsertAndActivateUsbSheetModel::
AuthenticatorInsertAndActivateUsbSheetModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model,
OtherMechanismButtonVisibility::kVisible) {
vector_illustrations_.emplace(kPasskeyUsbIcon, kPasskeyUsbDarkIcon);
}
bool AuthenticatorInsertAndActivateUsbSheetModel::IsActivityIndicatorVisible()
const {
return true;
}
std::u16string AuthenticatorInsertAndActivateUsbSheetModel::GetStepTitle()
const {
return l10n_util::GetStringFUTF16(IDS_WEBAUTHN_GENERIC_TITLE,
GetRelyingPartyIdString(dialog_model()));
}
std::u16string AuthenticatorInsertAndActivateUsbSheetModel::GetStepDescription()
const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_USB_ACTIVATE_DESCRIPTION);
}
std::u16string
AuthenticatorInsertAndActivateUsbSheetModel::GetAdditionalDescription() const {
return PossibleResidentKeyWarning(dialog_model());
}
// AuthenticatorTimeoutErrorModel ---------------------------------------------
AuthenticatorTimeoutErrorModel::AuthenticatorTimeoutErrorModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model) {
vector_illustrations_.emplace(kPasskeyErrorIcon, kPasskeyErrorDarkIcon);
}
bool AuthenticatorTimeoutErrorModel::IsBackButtonVisible() const {
return false;
}
std::u16string AuthenticatorTimeoutErrorModel::GetCancelButtonLabel() const {
return l10n_util::GetStringUTF16(IDS_CLOSE);
}
std::u16string AuthenticatorTimeoutErrorModel::GetStepTitle() const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_ERROR_GENERIC_TITLE);
}
std::u16string AuthenticatorTimeoutErrorModel::GetStepDescription() const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_ERROR_TIMEOUT_DESCRIPTION);
}
// AuthenticatorNoAvailableTransportsErrorModel -------------------------------
AuthenticatorNoAvailableTransportsErrorModel::
AuthenticatorNoAvailableTransportsErrorModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model) {
vector_illustrations_.emplace(kPasskeyErrorIcon, kPasskeyErrorDarkIcon);
}
bool AuthenticatorNoAvailableTransportsErrorModel::IsBackButtonVisible() const {
return false;
}
std::u16string
AuthenticatorNoAvailableTransportsErrorModel::GetCancelButtonLabel() const {
return l10n_util::GetStringUTF16(IDS_CLOSE);
}
std::u16string AuthenticatorNoAvailableTransportsErrorModel::GetStepTitle()
const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_ERROR_NO_TRANSPORTS_TITLE);
}
std::u16string
AuthenticatorNoAvailableTransportsErrorModel::GetStepDescription() const {
return l10n_util::GetStringUTF16(
IDS_WEBAUTHN_ERROR_NO_TRANSPORTS_DESCRIPTION);
}
// AuthenticatorNoPasskeysErrorModel ------------------------------------------
AuthenticatorNoPasskeysErrorModel::AuthenticatorNoPasskeysErrorModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model) {
vector_illustrations_.emplace(kPasskeyErrorIcon, kPasskeyErrorDarkIcon);
}
bool AuthenticatorNoPasskeysErrorModel::IsBackButtonVisible() const {
return false;
}
std::u16string AuthenticatorNoPasskeysErrorModel::GetCancelButtonLabel() const {
return l10n_util::GetStringUTF16(IDS_CLOSE);
}
std::u16string AuthenticatorNoPasskeysErrorModel::GetStepTitle() const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_ERROR_NO_PASSKEYS_TITLE);
}
std::u16string AuthenticatorNoPasskeysErrorModel::GetStepDescription() const {
return l10n_util::GetStringFUTF16(IDS_WEBAUTHN_ERROR_NO_PASSKEYS_DESCRIPTION,
GetRelyingPartyIdString(dialog_model()));
}
// AuthenticatorNotRegisteredErrorModel ---------------------------------------
AuthenticatorNotRegisteredErrorModel::AuthenticatorNotRegisteredErrorModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model) {
vector_illustrations_.emplace(kPasskeyErrorIcon, kPasskeyErrorDarkIcon);
}
bool AuthenticatorNotRegisteredErrorModel::IsBackButtonVisible() const {
return false;
}
std::u16string AuthenticatorNotRegisteredErrorModel::GetCancelButtonLabel()
const {
return l10n_util::GetStringUTF16(IDS_CLOSE);
}
bool AuthenticatorNotRegisteredErrorModel::IsAcceptButtonVisible() const {
return dialog_model()->offer_try_again_in_ui();
}
bool AuthenticatorNotRegisteredErrorModel::IsAcceptButtonEnabled() const {
return true;
}
std::u16string AuthenticatorNotRegisteredErrorModel::GetAcceptButtonLabel()
const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_RETRY);
}
std::u16string AuthenticatorNotRegisteredErrorModel::GetStepTitle() const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_ERROR_WRONG_KEY_TITLE);
}
std::u16string AuthenticatorNotRegisteredErrorModel::GetStepDescription()
const {
return l10n_util::GetStringUTF16(
IDS_WEBAUTHN_ERROR_WRONG_KEY_SIGN_DESCRIPTION);
}
void AuthenticatorNotRegisteredErrorModel::OnAccept() {
dialog_model()->StartOver();
}
// AuthenticatorAlreadyRegisteredErrorModel -----------------------------------
AuthenticatorAlreadyRegisteredErrorModel::
AuthenticatorAlreadyRegisteredErrorModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model) {
vector_illustrations_.emplace(kPasskeyErrorIcon, kPasskeyErrorDarkIcon);
}
bool AuthenticatorAlreadyRegisteredErrorModel::IsBackButtonVisible() const {
return false;
}
std::u16string AuthenticatorAlreadyRegisteredErrorModel::GetCancelButtonLabel()
const {
return l10n_util::GetStringUTF16(IDS_CLOSE);
}
bool AuthenticatorAlreadyRegisteredErrorModel::IsAcceptButtonVisible() const {
return dialog_model()->offer_try_again_in_ui();
}
bool AuthenticatorAlreadyRegisteredErrorModel::IsAcceptButtonEnabled() const {
return true;
}
std::u16string AuthenticatorAlreadyRegisteredErrorModel::GetAcceptButtonLabel()
const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_RETRY);
}
std::u16string AuthenticatorAlreadyRegisteredErrorModel::GetStepTitle() const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_ERROR_WRONG_DEVICE_TITLE);
}
std::u16string AuthenticatorAlreadyRegisteredErrorModel::GetStepDescription()
const {
return l10n_util::GetStringUTF16(
IDS_WEBAUTHN_ERROR_WRONG_DEVICE_REGISTER_DESCRIPTION);
}
void AuthenticatorAlreadyRegisteredErrorModel::OnAccept() {
dialog_model()->StartOver();
}
// AuthenticatorInternalUnrecognizedErrorSheetModel ---------------------------
AuthenticatorInternalUnrecognizedErrorSheetModel::
AuthenticatorInternalUnrecognizedErrorSheetModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model) {
vector_illustrations_.emplace(kPasskeyErrorIcon, kPasskeyErrorDarkIcon);
}
bool AuthenticatorInternalUnrecognizedErrorSheetModel::IsBackButtonVisible()
const {
return dialog_model()->offer_try_again_in_ui();
}
bool AuthenticatorInternalUnrecognizedErrorSheetModel::IsAcceptButtonVisible()
const {
return dialog_model()->offer_try_again_in_ui();
}
bool AuthenticatorInternalUnrecognizedErrorSheetModel::IsAcceptButtonEnabled()
const {
return true;
}
std::u16string
AuthenticatorInternalUnrecognizedErrorSheetModel::GetAcceptButtonLabel() const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_RETRY);
}
std::u16string AuthenticatorInternalUnrecognizedErrorSheetModel::GetStepTitle()
const {
return l10n_util::GetStringUTF16(
IDS_WEBAUTHN_ERROR_INTERNAL_UNRECOGNIZED_TITLE);
}
std::u16string
AuthenticatorInternalUnrecognizedErrorSheetModel::GetStepDescription() const {
return l10n_util::GetStringUTF16(
IDS_WEBAUTHN_ERROR_INTERNAL_UNRECOGNIZED_DESCRIPTION);
}
void AuthenticatorInternalUnrecognizedErrorSheetModel::OnAccept() {
dialog_model()->StartOver();
}
// AuthenticatorBlePowerOnManualSheetModel ------------------------------------
AuthenticatorBlePowerOnManualSheetModel::
AuthenticatorBlePowerOnManualSheetModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model,
OtherMechanismButtonVisibility::kVisible) {
vector_illustrations_.emplace(kPasskeyErrorBluetoothIcon,
kPasskeyErrorBluetoothDarkIcon);
}
std::u16string AuthenticatorBlePowerOnManualSheetModel::GetStepTitle() const {
return l10n_util::GetStringUTF16(
IDS_WEBAUTHN_BLUETOOTH_POWER_ON_MANUAL_TITLE);
}
std::u16string AuthenticatorBlePowerOnManualSheetModel::GetStepDescription()
const {
return l10n_util::GetStringUTF16(
IDS_WEBAUTHN_BLUETOOTH_POWER_ON_MANUAL_DESCRIPTION);
}
bool AuthenticatorBlePowerOnManualSheetModel::IsAcceptButtonVisible() const {
return true;
}
bool AuthenticatorBlePowerOnManualSheetModel::IsAcceptButtonEnabled() const {
return dialog_model()->ble_adapter_is_powered();
}
std::u16string AuthenticatorBlePowerOnManualSheetModel::GetAcceptButtonLabel()
const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_BLUETOOTH_POWER_ON_MANUAL_NEXT);
}
void AuthenticatorBlePowerOnManualSheetModel::OnBluetoothPoweredStateChanged() {
dialog_model()->OnSheetModelDidChange();
}
void AuthenticatorBlePowerOnManualSheetModel::OnAccept() {
dialog_model()->ContinueWithFlowAfterBleAdapterPowered();
}
// AuthenticatorBlePowerOnAutomaticSheetModel
// ------------------------------------
AuthenticatorBlePowerOnAutomaticSheetModel::
AuthenticatorBlePowerOnAutomaticSheetModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model,
OtherMechanismButtonVisibility::kVisible) {
vector_illustrations_.emplace(kPasskeyErrorBluetoothIcon,
kPasskeyErrorBluetoothDarkIcon);
}
bool AuthenticatorBlePowerOnAutomaticSheetModel::IsActivityIndicatorVisible()
const {
return busy_powering_on_ble_;
}
std::u16string AuthenticatorBlePowerOnAutomaticSheetModel::GetStepTitle()
const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_BLUETOOTH_POWER_ON_AUTO_TITLE);
}
std::u16string AuthenticatorBlePowerOnAutomaticSheetModel::GetStepDescription()
const {
return l10n_util::GetStringUTF16(
IDS_WEBAUTHN_BLUETOOTH_POWER_ON_AUTO_DESCRIPTION);
}
bool AuthenticatorBlePowerOnAutomaticSheetModel::IsAcceptButtonVisible() const {
return true;
}
bool AuthenticatorBlePowerOnAutomaticSheetModel::IsAcceptButtonEnabled() const {
return !busy_powering_on_ble_;
}
std::u16string
AuthenticatorBlePowerOnAutomaticSheetModel::GetAcceptButtonLabel() const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_BLUETOOTH_POWER_ON_AUTO_NEXT);
}
void AuthenticatorBlePowerOnAutomaticSheetModel::OnAccept() {
busy_powering_on_ble_ = true;
dialog_model()->OnSheetModelDidChange();
dialog_model()->PowerOnBleAdapter();
}
#if BUILDFLAG(IS_MAC)
// AuthenticatorBlePermissionMacSheetModel
// ------------------------------------
AuthenticatorBlePermissionMacSheetModel::
AuthenticatorBlePermissionMacSheetModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model,
OtherMechanismButtonVisibility::kVisible) {
vector_illustrations_.emplace(kPasskeyErrorBluetoothIcon,
kPasskeyErrorBluetoothDarkIcon);
}
bool AuthenticatorBlePermissionMacSheetModel::ShouldFocusBackArrow() const {
return true;
}
std::u16string AuthenticatorBlePermissionMacSheetModel::GetStepTitle() const {
// An empty title causes the title View to be omitted.
return u"";
}
std::u16string AuthenticatorBlePermissionMacSheetModel::GetStepDescription()
const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_BLUETOOTH_PERMISSION);
}
bool AuthenticatorBlePermissionMacSheetModel::IsAcceptButtonVisible() const {
return true;
}
bool AuthenticatorBlePermissionMacSheetModel::IsAcceptButtonEnabled() const {
return true;
}
bool AuthenticatorBlePermissionMacSheetModel::IsCancelButtonVisible() const {
return false;
}
std::u16string AuthenticatorBlePermissionMacSheetModel::GetAcceptButtonLabel()
const {
return l10n_util::GetStringUTF16(IDS_OPEN_SETTINGS_LINK);
}
void AuthenticatorBlePermissionMacSheetModel::OnAccept() {
dialog_model()->OpenBlePreferences();
}
#endif // IS_MAC
// AuthenticatorOffTheRecordInterstitialSheetModel
// -----------------------------------------
AuthenticatorOffTheRecordInterstitialSheetModel::
AuthenticatorOffTheRecordInterstitialSheetModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model) {
// TODO(1358719): Add more specific illustration once available. The
// "error" graphic is a large question mark, so it looks visually very
// similar.
vector_illustrations_.emplace(kPasskeyErrorIcon, kPasskeyErrorDarkIcon);
}
std::u16string AuthenticatorOffTheRecordInterstitialSheetModel::GetStepTitle()
const {
return l10n_util::GetStringFUTF16(
IDS_WEBAUTHN_PLATFORM_AUTHENTICATOR_OFF_THE_RECORD_INTERSTITIAL_TITLE,
GetRelyingPartyIdString(dialog_model()));
}
std::u16string
AuthenticatorOffTheRecordInterstitialSheetModel::GetStepDescription() const {
return l10n_util::GetStringUTF16(
IDS_WEBAUTHN_PLATFORM_AUTHENTICATOR_OFF_THE_RECORD_INTERSTITIAL_DESCRIPTION);
}
bool AuthenticatorOffTheRecordInterstitialSheetModel::IsAcceptButtonVisible()
const {
return true;
}
bool AuthenticatorOffTheRecordInterstitialSheetModel::IsAcceptButtonEnabled()
const {
return true;
}
std::u16string
AuthenticatorOffTheRecordInterstitialSheetModel::GetAcceptButtonLabel() const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CONTINUE);
}
void AuthenticatorOffTheRecordInterstitialSheetModel::OnAccept() {
dialog_model()->OnOffTheRecordInterstitialAccepted();
}
std::u16string
AuthenticatorOffTheRecordInterstitialSheetModel::GetCancelButtonLabel() const {
return l10n_util::GetStringUTF16(
IDS_WEBAUTHN_PLATFORM_AUTHENTICATOR_OFF_THE_RECORD_INTERSTITIAL_DENY);
}
// AuthenticatorPaaskSheetModel -----------------------------------------
AuthenticatorPaaskSheetModel::AuthenticatorPaaskSheetModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model,
OtherMechanismButtonVisibility::kVisible) {
vector_illustrations_.emplace(kPasskeyPhoneIcon, kPasskeyPhoneDarkIcon);
}
AuthenticatorPaaskSheetModel::~AuthenticatorPaaskSheetModel() = default;
bool AuthenticatorPaaskSheetModel::IsActivityIndicatorVisible() const {
return true;
}
std::u16string AuthenticatorPaaskSheetModel::GetStepTitle() const {
switch (dialog_model()->cable_ui_type()) {
case AuthenticatorRequestDialogModel::CableUIType::CABLE_V1:
case AuthenticatorRequestDialogModel::CableUIType::CABLE_V2_SERVER_LINK:
// caBLEv1 and v2 server-link don't include device names.
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CABLE_ACTIVATE_TITLE);
case AuthenticatorRequestDialogModel::CableUIType::CABLE_V2_2ND_FACTOR:
return l10n_util::GetStringUTF16(
IDS_WEBAUTHN_CABLE_ACTIVATE_TITLE_DEVICE);
}
}
std::u16string AuthenticatorPaaskSheetModel::GetStepDescription() const {
switch (dialog_model()->cable_ui_type()) {
case AuthenticatorRequestDialogModel::CableUIType::CABLE_V1:
case AuthenticatorRequestDialogModel::CableUIType::CABLE_V2_SERVER_LINK:
// caBLEv1 and v2 server-link don't include device names.
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CABLE_ACTIVATE_DESCRIPTION);
case AuthenticatorRequestDialogModel::CableUIType::CABLE_V2_2ND_FACTOR: {
DCHECK(dialog_model()->selected_phone_name());
return l10n_util::GetStringFUTF16(
IDS_WEBAUTHN_CABLE_ACTIVATE_DEVICE_NAME_DESCRIPTION,
base::UTF8ToUTF16(
dialog_model()->selected_phone_name().value_or("")));
}
}
}
// AuthenticatorAndroidAccessorySheetModel ------------------------------------
AuthenticatorAndroidAccessorySheetModel::
AuthenticatorAndroidAccessorySheetModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model,
OtherMechanismButtonVisibility::kVisible) {
vector_illustrations_.emplace(kPasskeyAoaIcon, kPasskeyAoaDarkIcon);
}
AuthenticatorAndroidAccessorySheetModel::
~AuthenticatorAndroidAccessorySheetModel() = default;
bool AuthenticatorAndroidAccessorySheetModel::IsBackButtonVisible() const {
return true;
}
bool AuthenticatorAndroidAccessorySheetModel::IsActivityIndicatorVisible()
const {
return true;
}
std::u16string AuthenticatorAndroidAccessorySheetModel::GetStepTitle() const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CABLEV2_AOA_TITLE);
}
std::u16string AuthenticatorAndroidAccessorySheetModel::GetStepDescription()
const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CABLEV2_AOA_DESCRIPTION);
}
// AuthenticatorClientPinEntrySheetModel
// -----------------------------------------
AuthenticatorClientPinEntrySheetModel::AuthenticatorClientPinEntrySheetModel(
AuthenticatorRequestDialogModel* dialog_model,
Mode mode,
device::pin::PINEntryError error)
: AuthenticatorSheetModelBase(dialog_model,
OtherMechanismButtonVisibility::kVisible),
mode_(mode) {
vector_illustrations_.emplace(kPasskeyUsbIcon, kPasskeyUsbDarkIcon);
switch (error) {
case device::pin::PINEntryError::kNoError:
break;
case device::pin::PINEntryError::kInternalUvLocked:
error_ = l10n_util::GetStringUTF16(IDS_WEBAUTHN_UV_ERROR_LOCKED);
break;
case device::pin::PINEntryError::kInvalidCharacters:
error_ = l10n_util::GetStringUTF16(
IDS_WEBAUTHN_PIN_ENTRY_ERROR_INVALID_CHARACTERS);
break;
case device::pin::PINEntryError::kSameAsCurrentPIN:
error_ = l10n_util::GetStringUTF16(
IDS_WEBAUTHN_PIN_ENTRY_ERROR_SAME_AS_CURRENT);
break;
case device::pin::PINEntryError::kTooShort:
error_ = l10n_util::GetPluralStringFUTF16(
IDS_WEBAUTHN_PIN_ENTRY_ERROR_TOO_SHORT,
dialog_model->min_pin_length());
break;
case device::pin::PINEntryError::kWrongPIN:
absl::optional<int> attempts = dialog_model->pin_attempts();
error_ =
attempts && *attempts <= 3
? l10n_util::GetPluralStringFUTF16(
IDS_WEBAUTHN_PIN_ENTRY_ERROR_FAILED_RETRIES, *attempts)
: l10n_util::GetStringUTF16(IDS_WEBAUTHN_PIN_ENTRY_ERROR_FAILED);
break;
}
}
AuthenticatorClientPinEntrySheetModel::
~AuthenticatorClientPinEntrySheetModel() = default;
void AuthenticatorClientPinEntrySheetModel::SetPinCode(
std::u16string pin_code) {
pin_code_ = std::move(pin_code);
}
void AuthenticatorClientPinEntrySheetModel::SetPinConfirmation(
std::u16string pin_confirmation) {
DCHECK(mode_ == Mode::kPinSetup || mode_ == Mode::kPinChange);
pin_confirmation_ = std::move(pin_confirmation);
}
std::u16string AuthenticatorClientPinEntrySheetModel::GetStepTitle() const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_PIN_ENTRY_TITLE);
}
std::u16string AuthenticatorClientPinEntrySheetModel::GetStepDescription()
const {
switch (mode_) {
case Mode::kPinChange:
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_FORCE_PIN_CHANGE);
case Mode::kPinEntry:
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_PIN_ENTRY_DESCRIPTION);
case Mode::kPinSetup:
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_PIN_SETUP_DESCRIPTION);
}
}
std::u16string AuthenticatorClientPinEntrySheetModel::GetError() const {
return error_;
}
bool AuthenticatorClientPinEntrySheetModel::IsAcceptButtonVisible() const {
return true;
}
bool AuthenticatorClientPinEntrySheetModel::IsAcceptButtonEnabled() const {
return true;
}
std::u16string AuthenticatorClientPinEntrySheetModel::GetAcceptButtonLabel()
const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_PIN_ENTRY_NEXT);
}
void AuthenticatorClientPinEntrySheetModel::OnAccept() {
if ((mode_ == Mode::kPinChange || mode_ == Mode::kPinSetup) &&
pin_code_ != pin_confirmation_) {
error_ = l10n_util::GetStringUTF16(IDS_WEBAUTHN_PIN_ENTRY_ERROR_MISMATCH);
dialog_model()->OnSheetModelDidChange();
return;
}
if (dialog_model()) {
dialog_model()->OnHavePIN(pin_code_);
}
}
// AuthenticatorClientPinTapAgainSheetModel ----------------------
AuthenticatorClientPinTapAgainSheetModel::
AuthenticatorClientPinTapAgainSheetModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model) {
vector_illustrations_.emplace(kPasskeyUsbIcon, kPasskeyUsbDarkIcon);
}
AuthenticatorClientPinTapAgainSheetModel::
~AuthenticatorClientPinTapAgainSheetModel() = default;
bool AuthenticatorClientPinTapAgainSheetModel::IsActivityIndicatorVisible()
const {
return true;
}
std::u16string AuthenticatorClientPinTapAgainSheetModel::GetStepTitle() const {
return l10n_util::GetStringFUTF16(IDS_WEBAUTHN_GENERIC_TITLE,
GetRelyingPartyIdString(dialog_model()));
}
std::u16string AuthenticatorClientPinTapAgainSheetModel::GetStepDescription()
const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_PIN_TAP_AGAIN_DESCRIPTION);
}
std::u16string
AuthenticatorClientPinTapAgainSheetModel::GetAdditionalDescription() const {
return PossibleResidentKeyWarning(dialog_model());
}
// AuthenticatorBioEnrollmentSheetModel ----------------------------------
// No illustration since the content already has a large animated
// fingerprint icon.
AuthenticatorBioEnrollmentSheetModel::AuthenticatorBioEnrollmentSheetModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model) {}
AuthenticatorBioEnrollmentSheetModel::~AuthenticatorBioEnrollmentSheetModel() =
default;
bool AuthenticatorBioEnrollmentSheetModel::IsActivityIndicatorVisible() const {
return !IsAcceptButtonVisible();
}
std::u16string AuthenticatorBioEnrollmentSheetModel::GetStepTitle() const {
return l10n_util::GetStringUTF16(
IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_ADD_TITLE);
}
std::u16string AuthenticatorBioEnrollmentSheetModel::GetStepDescription()
const {
return IsAcceptButtonVisible()
? l10n_util::GetStringUTF16(
IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_ENROLLING_COMPLETE_LABEL)
: l10n_util::GetStringUTF16(
IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_ENROLLING_LABEL);
}
bool AuthenticatorBioEnrollmentSheetModel::IsAcceptButtonEnabled() const {
return true;
}
bool AuthenticatorBioEnrollmentSheetModel::IsAcceptButtonVisible() const {
return dialog_model()->bio_samples_remaining() &&
dialog_model()->bio_samples_remaining() <= 0;
}
std::u16string AuthenticatorBioEnrollmentSheetModel::GetAcceptButtonLabel()
const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_PIN_ENTRY_NEXT);
}
bool AuthenticatorBioEnrollmentSheetModel::IsCancelButtonVisible() const {
return !IsAcceptButtonVisible();
}
std::u16string AuthenticatorBioEnrollmentSheetModel::GetCancelButtonLabel()
const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_INLINE_ENROLLMENT_CANCEL_LABEL);
}
void AuthenticatorBioEnrollmentSheetModel::OnAccept() {
dialog_model()->OnBioEnrollmentDone();
}
void AuthenticatorBioEnrollmentSheetModel::OnCancel() {
OnAccept();
}
// AuthenticatorRetryUvSheetModel -------------------------------------
AuthenticatorRetryUvSheetModel::AuthenticatorRetryUvSheetModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model,
OtherMechanismButtonVisibility::kVisible) {
vector_illustrations_.emplace(kPasskeyFingerprintIcon,
kPasskeyFingerprintDarkIcon);
}
AuthenticatorRetryUvSheetModel::~AuthenticatorRetryUvSheetModel() = default;
bool AuthenticatorRetryUvSheetModel::IsActivityIndicatorVisible() const {
return true;
}
std::u16string AuthenticatorRetryUvSheetModel::GetStepTitle() const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_UV_RETRY_TITLE);
}
std::u16string AuthenticatorRetryUvSheetModel::GetStepDescription() const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_UV_RETRY_DESCRIPTION);
}
std::u16string AuthenticatorRetryUvSheetModel::GetError() const {
int attempts = *dialog_model()->uv_attempts();
if (attempts > 3) {
return std::u16string();
}
return l10n_util::GetPluralStringFUTF16(
IDS_WEBAUTHN_UV_RETRY_ERROR_FAILED_RETRIES, attempts);
}
// AuthenticatorGenericErrorSheetModel -----------------------------------
// static
std::unique_ptr<AuthenticatorGenericErrorSheetModel>
AuthenticatorGenericErrorSheetModel::ForClientPinErrorSoftBlock(
AuthenticatorRequestDialogModel* dialog_model) {
return base::WrapUnique(new AuthenticatorGenericErrorSheetModel(
dialog_model, l10n_util::GetStringUTF16(IDS_WEBAUTHN_ERROR_GENERIC_TITLE),
l10n_util::GetStringUTF16(
IDS_WEBAUTHN_CLIENT_PIN_SOFT_BLOCK_DESCRIPTION)));
}
// static
std::unique_ptr<AuthenticatorGenericErrorSheetModel>
AuthenticatorGenericErrorSheetModel::ForClientPinErrorHardBlock(
AuthenticatorRequestDialogModel* dialog_model) {
return base::WrapUnique(new AuthenticatorGenericErrorSheetModel(
dialog_model, l10n_util::GetStringUTF16(IDS_WEBAUTHN_ERROR_GENERIC_TITLE),
l10n_util::GetStringUTF16(
IDS_WEBAUTHN_CLIENT_PIN_HARD_BLOCK_DESCRIPTION)));
}
// static
std::unique_ptr<AuthenticatorGenericErrorSheetModel>
AuthenticatorGenericErrorSheetModel::ForClientPinErrorAuthenticatorRemoved(
AuthenticatorRequestDialogModel* dialog_model) {
return base::WrapUnique(new AuthenticatorGenericErrorSheetModel(
dialog_model, l10n_util::GetStringUTF16(IDS_WEBAUTHN_ERROR_GENERIC_TITLE),
l10n_util::GetStringUTF16(
IDS_WEBAUTHN_CLIENT_PIN_AUTHENTICATOR_REMOVED_DESCRIPTION)));
}
// static
std::unique_ptr<AuthenticatorGenericErrorSheetModel>
AuthenticatorGenericErrorSheetModel::ForMissingCapability(
AuthenticatorRequestDialogModel* dialog_model) {
return base::WrapUnique(new AuthenticatorGenericErrorSheetModel(
dialog_model,
l10n_util::GetStringUTF16(IDS_WEBAUTHN_ERROR_MISSING_CAPABILITY_TITLE),
l10n_util::GetStringFUTF16(IDS_WEBAUTHN_ERROR_MISSING_CAPABILITY_DESC,
GetRelyingPartyIdString(dialog_model))));
}
// static
std::unique_ptr<AuthenticatorGenericErrorSheetModel>
AuthenticatorGenericErrorSheetModel::ForStorageFull(
AuthenticatorRequestDialogModel* dialog_model) {
return base::WrapUnique(new AuthenticatorGenericErrorSheetModel(
dialog_model,
l10n_util::GetStringUTF16(IDS_WEBAUTHN_ERROR_MISSING_CAPABILITY_TITLE),
l10n_util::GetStringUTF16(IDS_WEBAUTHN_STORAGE_FULL_DESC)));
}
std::unique_ptr<AuthenticatorGenericErrorSheetModel>
AuthenticatorGenericErrorSheetModel::ForWindowsHelloNotEnabled(
AuthenticatorRequestDialogModel* dialog_model) {
return base::WrapUnique(new AuthenticatorGenericErrorSheetModel(
dialog_model,
l10n_util::GetStringUTF16(IDS_WEBAUTHN_WINDOWS_HELLO_NOT_ENABLED_TITLE),
l10n_util::GetStringUTF16(
IDS_WEBAUTHN_WINDOWS_HELLO_NOT_ENABLED_DESCRIPTION)));
}
AuthenticatorGenericErrorSheetModel::AuthenticatorGenericErrorSheetModel(
AuthenticatorRequestDialogModel* dialog_model,
std::u16string title,
std::u16string description)
: AuthenticatorSheetModelBase(dialog_model),
title_(std::move(title)),
description_(std::move(description)) {
vector_illustrations_.emplace(kPasskeyErrorIcon, kPasskeyErrorDarkIcon);
}
bool AuthenticatorGenericErrorSheetModel::IsBackButtonVisible() const {
return false;
}
std::u16string AuthenticatorGenericErrorSheetModel::GetCancelButtonLabel()
const {
return l10n_util::GetStringUTF16(IDS_CLOSE);
}
bool AuthenticatorGenericErrorSheetModel::IsAcceptButtonVisible() const {
return dialog_model()->offer_try_again_in_ui();
}
bool AuthenticatorGenericErrorSheetModel::IsAcceptButtonEnabled() const {
return true;
}
std::u16string AuthenticatorGenericErrorSheetModel::GetAcceptButtonLabel()
const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_RETRY);
}
std::u16string AuthenticatorGenericErrorSheetModel::GetStepTitle() const {
return title_;
}
std::u16string AuthenticatorGenericErrorSheetModel::GetStepDescription() const {
return description_;
}
void AuthenticatorGenericErrorSheetModel::OnAccept() {
dialog_model()->StartOver();
}
// AuthenticatorResidentCredentialConfirmationSheetView -----------------------
// TODO(1358719): Add more specific illustration once available. The "error"
// graphic is a large question mark, so it looks visually very similar.
AuthenticatorResidentCredentialConfirmationSheetView::
AuthenticatorResidentCredentialConfirmationSheetView(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model) {
vector_illustrations_.emplace(kPasskeyErrorIcon, kPasskeyErrorDarkIcon);
}
AuthenticatorResidentCredentialConfirmationSheetView::
~AuthenticatorResidentCredentialConfirmationSheetView() = default;
bool AuthenticatorResidentCredentialConfirmationSheetView::IsBackButtonVisible()
const {
return false;
}
bool AuthenticatorResidentCredentialConfirmationSheetView::
IsAcceptButtonVisible() const {
return true;
}
bool AuthenticatorResidentCredentialConfirmationSheetView::
IsAcceptButtonEnabled() const {
return true;
}
std::u16string
AuthenticatorResidentCredentialConfirmationSheetView::GetAcceptButtonLabel()
const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CONTINUE);
}
std::u16string
AuthenticatorResidentCredentialConfirmationSheetView::GetStepTitle() const {
return l10n_util::GetStringFUTF16(IDS_WEBAUTHN_GENERIC_TITLE,
GetRelyingPartyIdString(dialog_model()));
}
std::u16string
AuthenticatorResidentCredentialConfirmationSheetView::GetStepDescription()
const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_RESIDENT_KEY_PRIVACY);
}
void AuthenticatorResidentCredentialConfirmationSheetView::OnAccept() {
dialog_model()->OnResidentCredentialConfirmed();
}
// AuthenticatorSelectAccountSheetModel ---------------------------------------
AuthenticatorSelectAccountSheetModel::AuthenticatorSelectAccountSheetModel(
AuthenticatorRequestDialogModel* dialog_model,
UserVerificationMode mode,
SelectionType type)
: AuthenticatorSheetModelBase(
dialog_model,
mode == kPreUserVerification
? OtherMechanismButtonVisibility::kVisible
: OtherMechanismButtonVisibility::kHidden),
user_verification_mode_(mode),
selection_type_(type) {
vector_illustrations_.emplace(kPasskeyHeaderIcon, kPasskeyHeaderDarkIcon);
}
AuthenticatorSelectAccountSheetModel::~AuthenticatorSelectAccountSheetModel() =
default;
AuthenticatorSelectAccountSheetModel::SelectionType
AuthenticatorSelectAccountSheetModel::selection_type() const {
return selection_type_;
}
const device::DiscoverableCredentialMetadata&
AuthenticatorSelectAccountSheetModel::SingleCredential() const {
DCHECK_EQ(selection_type_, kSingleAccount);
DCHECK_EQ(dialog_model()->creds().size(), 1u);
return dialog_model()->creds().at(0);
}
void AuthenticatorSelectAccountSheetModel::SetCurrentSelection(int selected) {
DCHECK_EQ(selection_type_, kMultipleAccounts);
DCHECK_LE(0, selected);
DCHECK_LT(static_cast<size_t>(selected), dialog_model()->creds().size());
selected_ = selected;
}
void AuthenticatorSelectAccountSheetModel::OnAccept() {
const size_t index = selection_type_ == kMultipleAccounts ? selected_ : 0;
switch (user_verification_mode_) {
case kPreUserVerification:
dialog_model()->OnAccountPreselectedIndex(index);
break;
case kPostUserVerification:
dialog_model()->OnAccountSelected(index);
break;
}
}
std::u16string AuthenticatorSelectAccountSheetModel::GetStepTitle() const {
switch (selection_type_) {
case kSingleAccount:
return l10n_util::GetStringFUTF16(
IDS_WEBAUTHN_USE_PASSKEY_TITLE,
GetRelyingPartyIdString(dialog_model()));
case kMultipleAccounts:
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CHOOSE_PASSKEY_TITLE);
}
}
std::u16string AuthenticatorSelectAccountSheetModel::GetStepDescription()
const {
switch (selection_type_) {
case kSingleAccount:
return u"";
case kMultipleAccounts:
return l10n_util::GetStringFUTF16(
IDS_WEBAUTHN_CHOOSE_PASSKEY_BODY,
GetRelyingPartyIdString(dialog_model()));
}
}
bool AuthenticatorSelectAccountSheetModel::IsAcceptButtonVisible() const {
return selection_type_ == kSingleAccount;
}
bool AuthenticatorSelectAccountSheetModel::IsAcceptButtonEnabled() const {
return selection_type_ == kSingleAccount;
}
std::u16string AuthenticatorSelectAccountSheetModel::GetAcceptButtonLabel()
const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CONTINUE);
}
// AttestationPermissionRequestSheetModel -------------------------------------
// TODO(1358719): Add more specific illustration once available.
AttestationPermissionRequestSheetModel::AttestationPermissionRequestSheetModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model) {
vector_illustrations_.emplace(kPasskeyUsbIcon, kPasskeyUsbDarkIcon);
}
AttestationPermissionRequestSheetModel::
~AttestationPermissionRequestSheetModel() = default;
void AttestationPermissionRequestSheetModel::OnAccept() {
dialog_model()->OnAttestationPermissionResponse(true);
}
void AttestationPermissionRequestSheetModel::OnCancel() {
dialog_model()->OnAttestationPermissionResponse(false);
}
std::u16string AttestationPermissionRequestSheetModel::GetStepTitle() const {
return l10n_util::GetStringUTF16(
IDS_WEBAUTHN_REQUEST_ATTESTATION_PERMISSION_TITLE);
}
std::u16string AttestationPermissionRequestSheetModel::GetStepDescription()
const {
return l10n_util::GetStringFUTF16(
IDS_WEBAUTHN_REQUEST_ATTESTATION_PERMISSION_DESC,
GetRelyingPartyIdString(dialog_model()));
}
bool AttestationPermissionRequestSheetModel::IsBackButtonVisible() const {
return false;
}
bool AttestationPermissionRequestSheetModel::IsAcceptButtonVisible() const {
return true;
}
bool AttestationPermissionRequestSheetModel::IsAcceptButtonEnabled() const {
return true;
}
std::u16string AttestationPermissionRequestSheetModel::GetAcceptButtonLabel()
const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_ALLOW_ATTESTATION);
}
bool AttestationPermissionRequestSheetModel::IsCancelButtonVisible() const {
return true;
}
std::u16string AttestationPermissionRequestSheetModel::GetCancelButtonLabel()
const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_DENY_ATTESTATION);
}
// EnterpriseAttestationPermissionRequestSheetModel ---------------------------
EnterpriseAttestationPermissionRequestSheetModel::
EnterpriseAttestationPermissionRequestSheetModel(
AuthenticatorRequestDialogModel* dialog_model)
: AttestationPermissionRequestSheetModel(dialog_model) {}
std::u16string EnterpriseAttestationPermissionRequestSheetModel::GetStepTitle()
const {
return l10n_util::GetStringUTF16(
IDS_WEBAUTHN_REQUEST_ENTERPRISE_ATTESTATION_PERMISSION_TITLE);
}
std::u16string
EnterpriseAttestationPermissionRequestSheetModel::GetStepDescription() const {
return l10n_util::GetStringFUTF16(
IDS_WEBAUTHN_REQUEST_ENTERPRISE_ATTESTATION_PERMISSION_DESC,
GetRelyingPartyIdString(dialog_model()));
}
// AuthenticatorQRSheetModel --------------------------------------------------
// No illustration since there already is the QR code.
AuthenticatorQRSheetModel::AuthenticatorQRSheetModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model,
OtherMechanismButtonVisibility::kVisible) {}
AuthenticatorQRSheetModel::~AuthenticatorQRSheetModel() = default;
std::u16string AuthenticatorQRSheetModel::GetStepTitle() const {
switch (dialog_model()->transport_availability()->request_type) {
case device::FidoRequestType::kMakeCredential:
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CREATE_PASSKEY_QR_TITLE);
case device::FidoRequestType::kGetAssertion:
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_USE_PASSKEY_QR_TITLE);
}
}
std::u16string AuthenticatorQRSheetModel::GetStepDescription() const {
switch (dialog_model()->transport_availability()->request_type) {
case device::FidoRequestType::kMakeCredential:
return l10n_util::GetStringFUTF16(
IDS_WEBAUTHN_CREATE_PASSKEY_QR_BODY,
GetRelyingPartyIdString(dialog_model()));
case device::FidoRequestType::kGetAssertion:
return l10n_util::GetStringFUTF16(
IDS_WEBAUTHN_USE_PASSKEY_QR_BODY,
GetRelyingPartyIdString(dialog_model()));
}
}
// AuthenticatorConnectingSheetModel ------------------------------------------
AuthenticatorConnectingSheetModel::AuthenticatorConnectingSheetModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model,
OtherMechanismButtonVisibility::kHidden) {
lottie_illustrations_.emplace(IDR_WEBAUTHN_HYBRID_CONNECTING_LIGHT,
IDR_WEBAUTHN_HYBRID_CONNECTING_DARK);
}
AuthenticatorConnectingSheetModel::~AuthenticatorConnectingSheetModel() =
default;
std::u16string AuthenticatorConnectingSheetModel::GetStepTitle() const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CABLEV2_CONNECTING_TITLE);
}
std::u16string AuthenticatorConnectingSheetModel::GetStepDescription() const {
return u"";
}
// AuthenticatorConnectedSheetModel ------------------------------------------
AuthenticatorConnectedSheetModel::AuthenticatorConnectedSheetModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model,
OtherMechanismButtonVisibility::kHidden) {
vector_illustrations_.emplace(kPasskeyPhoneIcon, kPasskeyPhoneDarkIcon);
}
AuthenticatorConnectedSheetModel::~AuthenticatorConnectedSheetModel() = default;
bool AuthenticatorConnectedSheetModel::IsActivityIndicatorVisible() const {
return false;
}
std::u16string AuthenticatorConnectedSheetModel::GetStepTitle() const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CABLE_ACTIVATE_TITLE_DEVICE);
}
std::u16string AuthenticatorConnectedSheetModel::GetStepDescription() const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CABLEV2_CONNECTED_DESCRIPTION);
}
// AuthenticatorCableErrorSheetModel ------------------------------------------
AuthenticatorCableErrorSheetModel::AuthenticatorCableErrorSheetModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model,
OtherMechanismButtonVisibility::kHidden) {
vector_illustrations_.emplace(kPasskeyErrorIcon, kPasskeyErrorDarkIcon);
}
AuthenticatorCableErrorSheetModel::~AuthenticatorCableErrorSheetModel() =
default;
bool AuthenticatorCableErrorSheetModel::IsOtherMechanismButtonVisible() const {
return false;
}
std::u16string AuthenticatorCableErrorSheetModel::GetStepTitle() const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_ERROR_GENERIC_TITLE);
}
std::u16string AuthenticatorCableErrorSheetModel::GetStepDescription() const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CABLEV2_ERROR_DESCRIPTION);
}
std::u16string AuthenticatorCableErrorSheetModel::GetCancelButtonLabel() const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CABLEV2_ERROR_CLOSE);
}
// AuthenticatorCreatePasskeySheetModel
// --------------------------------------------------
AuthenticatorCreatePasskeySheetModel::AuthenticatorCreatePasskeySheetModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model,
OtherMechanismButtonVisibility::kVisible) {
vector_illustrations_.emplace(kPasskeyHeaderIcon, kPasskeyHeaderDarkIcon);
}
AuthenticatorCreatePasskeySheetModel::~AuthenticatorCreatePasskeySheetModel() =
default;
std::u16string AuthenticatorCreatePasskeySheetModel::GetStepTitle() const {
return l10n_util::GetStringFUTF16(IDS_WEBAUTHN_CREATE_PASSKEY_TITLE,
GetRelyingPartyIdString(dialog_model()));
}
std::u16string AuthenticatorCreatePasskeySheetModel::GetStepDescription()
const {
return u"";
}
std::u16string
AuthenticatorCreatePasskeySheetModel::passkey_storage_description() const {
#if BUILDFLAG(IS_WIN)
return l10n_util::GetStringUTF16(
dialog_model()->transport_availability()->is_off_the_record_context
? IDS_WEBAUTHN_CREATE_PASSKEY_EXTRA_WIN_INCOGNITO
: IDS_WEBAUTHN_CREATE_PASSKEY_EXTRA_WIN);
#else
return l10n_util::GetStringUTF16(
dialog_model()->transport_availability()->is_off_the_record_context
? IDS_WEBAUTHN_CREATE_PASSKEY_EXTRA_INCOGNITO
: IDS_WEBAUTHN_CREATE_PASSKEY_EXTRA);
#endif
}
bool AuthenticatorCreatePasskeySheetModel::IsAcceptButtonVisible() const {
return true;
}
bool AuthenticatorCreatePasskeySheetModel::IsAcceptButtonEnabled() const {
return true;
}
std::u16string AuthenticatorCreatePasskeySheetModel::GetAcceptButtonLabel()
const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CONTINUE);
}
void AuthenticatorCreatePasskeySheetModel::OnAccept() {
dialog_model()->HideDialogAndDispatchToPlatformAuthenticator();
}
// AuthenticatorPhoneConfirmationSheet --------------------------------
AuthenticatorPhoneConfirmationSheet::AuthenticatorPhoneConfirmationSheet(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model,
OtherMechanismButtonVisibility::kVisible) {
vector_illustrations_.emplace(kPasskeyPhoneIcon, kPasskeyPhoneDarkIcon);
}
AuthenticatorPhoneConfirmationSheet::~AuthenticatorPhoneConfirmationSheet() =
default;
std::u16string AuthenticatorPhoneConfirmationSheet::GetStepTitle() const {
return l10n_util::GetStringFUTF16(
IDS_WEBAUTHN_PHONE_CONFIRMATION_TITLE,
base::UTF8ToUTF16(dialog_model()->paired_phone_names().at(0)),
GetRelyingPartyIdString(dialog_model()));
}
std::u16string AuthenticatorPhoneConfirmationSheet::GetStepDescription() const {
return u"";
}
bool AuthenticatorPhoneConfirmationSheet::IsAcceptButtonVisible() const {
return true;
}
bool AuthenticatorPhoneConfirmationSheet::IsAcceptButtonEnabled() const {
return true;
}
std::u16string AuthenticatorPhoneConfirmationSheet::GetAcceptButtonLabel()
const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CONTINUE);
}
void AuthenticatorPhoneConfirmationSheet::OnAccept() {
dialog_model()->ContactPriorityPhone();
}