blob: 4e17292279ca859222333455f7df2e5687bf8548 [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/containers/contains.h"
#include "base/feature_list.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/browser/webauthn/authenticator_request_dialog_model.h"
#include "chrome/grit/browser_resources.h"
#include "chrome/grit/generated_resources.h"
#include "components/strings/grit/components_strings.h"
#include "device/fido/discoverable_credential_metadata.h"
#include "device/fido/features.h"
#include "device/fido/fido_constants.h"
#include "device/fido/fido_types.h"
#include "ui/base/l10n/l10n_util.h"
#if BUILDFLAG(IS_MAC)
#include "base/mac/mac_util.h"
#include "crypto/scoped_lacontext.h"
#include "device/fido/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_->observers.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_->observers.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::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_PASSKEY);
}
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()->CancelAuthenticatorRequest();
}
}
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::IsActivityIndicatorVisible()
const {
return dialog_model()->ui_disabled_;
}
std::u16string AuthenticatorMechanismSelectorSheetModel::GetStepTitle() const {
switch (dialog_model()->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()->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()->OnManageDevicesClicked();
}
}
// 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);
}
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);
}
std::u16string
AuthenticatorNoAvailableTransportsErrorModel::GetCancelButtonLabel() const {
return l10n_util::GetStringUTF16(IDS_CLOSE);
}
std::u16string AuthenticatorNoAvailableTransportsErrorModel::GetStepTitle()
const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_ERROR_MISSING_CAPABILITY_TITLE);
}
std::u16string
AuthenticatorNoAvailableTransportsErrorModel::GetStepDescription() const {
return l10n_util::GetStringFUTF16(IDS_WEBAUTHN_ERROR_MISSING_CAPABILITY_DESC,
GetRelyingPartyIdString(dialog_model()));
}
// AuthenticatorNoPasskeysErrorModel ------------------------------------------
AuthenticatorNoPasskeysErrorModel::AuthenticatorNoPasskeysErrorModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model) {
vector_illustrations_.emplace(kPasskeyErrorIcon, kPasskeyErrorDarkIcon);
}
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);
}
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);
}
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::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()->OnSheetModelChanged();
}
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()->OnSheetModelChanged();
dialog_model()->PowerOnBleAdapter();
}
#if BUILDFLAG(IS_MAC)
// AuthenticatorBlePermissionMacSheetModel
// ------------------------------------
AuthenticatorBlePermissionMacSheetModel::
AuthenticatorBlePermissionMacSheetModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model,
OtherMechanismButtonVisibility::kVisible) {
vector_illustrations_.emplace(kPasskeyErrorBluetoothIcon,
kPasskeyErrorBluetoothDarkIcon);
}
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 true;
}
std::u16string AuthenticatorBlePermissionMacSheetModel::GetAcceptButtonLabel()
const {
return l10n_util::GetStringUTF16(IDS_OPEN_SETTINGS_LINK);
}
void AuthenticatorBlePermissionMacSheetModel::OnAccept() {
dialog_model()->OpenBlePreferences();
}
// AuthenticatorTouchIdSheetModel
// ------------------------------------
AuthenticatorTouchIdSheetModel::AuthenticatorTouchIdSheetModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model,
OtherMechanismButtonVisibility::kVisible) {}
std::u16string AuthenticatorTouchIdSheetModel::GetStepTitle() const {
switch (dialog_model()->request_type) {
case device::FidoRequestType::kGetAssertion:
return u"Use your passkey to sign in to " +
base::UTF8ToUTF16(dialog_model()->relying_party_id) + u"? (UT)";
case device::FidoRequestType::kMakeCredential:
return u"Create a passkey for " +
base::UTF8ToUTF16(dialog_model()->relying_party_id) + u"? (UT)";
}
}
std::u16string AuthenticatorTouchIdSheetModel::GetStepDescription() const {
return u"You can use saved passkeys on any device. It will be saved to "
u"Google Password Manager for your Google account (UT)";
}
bool AuthenticatorTouchIdSheetModel::IsAcceptButtonVisible() const {
return !device::fido::mac::DeviceHasBiometricsAvailable();
}
bool AuthenticatorTouchIdSheetModel::IsAcceptButtonEnabled() const {
return true;
}
bool AuthenticatorTouchIdSheetModel::IsCancelButtonVisible() const {
return true;
}
std::u16string AuthenticatorTouchIdSheetModel::GetAcceptButtonLabel() const {
return u"Use password (UT)";
}
void AuthenticatorTouchIdSheetModel::OnAccept() {
if (touch_id_completed_) {
return;
}
touch_id_completed_ = true;
dialog_model()->OnTouchIDComplete(false);
}
void AuthenticatorTouchIdSheetModel::OnTouchIDSensorTapped(
std::optional<crypto::ScopedLAContext> lacontext) {
// Ignore Touch ID ceremony status after the user has completed the ceremony.
if (touch_id_completed_) {
return;
}
if (!lacontext) {
// Authentication failed. Update the button status and rebuild the sheet,
// which will restart the Touch ID request if the sensor is not softlocked
// or display a padlock icon if it is.
dialog_model()->OnSheetModelChanged();
return;
}
touch_id_completed_ = true;
dialog_model()->lacontext = std::move(lacontext);
dialog_model()->OnTouchIDComplete(true);
}
#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::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:
std::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()->OnSheetModelChanged();
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);
}
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::
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::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()->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()->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()));
}
}
bool AuthenticatorQRSheetModel::ShowSecurityKeyLabel() const {
return dialog_model()->security_key_is_possible;
}
std::u16string AuthenticatorQRSheetModel::GetSecurityKeyLabel() const {
switch (dialog_model()->request_type) {
case device::FidoRequestType::kMakeCredential:
return l10n_util::GetStringFUTF16(
IDS_WEBAUTHN_QR_CREATE_PASSKEY_ON_SECURITY_KEY_LABEL,
GetRelyingPartyIdString(dialog_model()));
case device::FidoRequestType::kGetAssertion:
return l10n_util::GetStringFUTF16(
IDS_WEBAUTHN_QR_USE_PASSKEY_ON_SECURITY_KEY_LABEL,
GetRelyingPartyIdString(dialog_model()));
}
}
std::u16string AuthenticatorQRSheetModel::GetOtherMechanismButtonLabel() const {
// If the QR code sheet was the priority mechanism, the button taking the user
// to the selection sheet should read "Use a different passkey".
if (dialog_model()->priority_mechanism_index &&
absl::holds_alternative<
AuthenticatorRequestDialogModel::Mechanism::AddPhone>(
dialog_model()
->mechanisms[*dialog_model()->priority_mechanism_index]
.type)) {
return AuthenticatorSheetModelBase::GetOtherMechanismButtonLabel();
}
// Otherwise, the user must have tapped a button on the selection sheet to get
// here. The button taking the user to the selection sheet should read "Back".
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_BACK);
}
// 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_CABLEV2_CONNECTED_DESCRIPTION);
}
std::u16string AuthenticatorConnectedSheetModel::GetStepDescription() const {
return u"";
}
// 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()->is_off_the_record
? IDS_WEBAUTHN_CREATE_PASSKEY_EXTRA_WIN_INCOGNITO
: IDS_WEBAUTHN_CREATE_PASSKEY_EXTRA_WIN);
#else
return l10n_util::GetStringUTF16(
dialog_model()->is_off_the_record
? 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()->OnCreatePasskeyAccepted();
}
// AuthenticatorGPMErrorSheetModel -------------------------------------------
AuthenticatorGPMErrorSheetModel::AuthenticatorGPMErrorSheetModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model,
OtherMechanismButtonVisibility::kHidden) {
vector_illustrations_.emplace(kPasskeyHeaderIcon, kPasskeyHeaderDarkIcon);
}
AuthenticatorGPMErrorSheetModel::~AuthenticatorGPMErrorSheetModel() = default;
std::u16string AuthenticatorGPMErrorSheetModel::GetStepTitle() const {
return u"Something went wrong (UNTRANSLATED)";
}
std::u16string AuthenticatorGPMErrorSheetModel::GetStepDescription() const {
return u"Check your internet connection and try again (UNTRANSLATED)";
}
// 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();
}
// AuthenticatorMultiSourcePickerSheetModel --------------------------------
AuthenticatorMultiSourcePickerSheetModel::
AuthenticatorMultiSourcePickerSheetModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model) {
vector_illustrations_.emplace(kPasskeyHeaderIcon, kPasskeyHeaderDarkIcon);
using CredentialMech = AuthenticatorRequestDialogModel::Mechanism::Credential;
using ICloudKeychainMech =
AuthenticatorRequestDialogModel::Mechanism::ICloudKeychain;
bool has_local_passkeys =
base::ranges::any_of(dialog_model->mechanisms, [](const auto& mech) {
return absl::holds_alternative<CredentialMech>(mech.type) &&
absl::get<CredentialMech>(mech.type).value().source !=
device::AuthenticatorType::kPhone;
});
if (has_local_passkeys) {
primary_passkeys_label_ =
l10n_util::GetStringUTF16(IDS_WEBAUTHN_THIS_DEVICE_LABEL);
for (size_t i = 0; i < dialog_model->mechanisms.size(); ++i) {
const AuthenticatorRequestDialogModel::Mechanism& mech =
dialog_model->mechanisms[i];
if ((absl::holds_alternative<CredentialMech>(mech.type) &&
absl::get<CredentialMech>(mech.type).value().source !=
device::AuthenticatorType::kPhone) ||
// iCloud Keychain appears in the primary list if present. This
// happens when Chrome does not have permission to enumerate
// credentials from iCloud Keychain. Thus this generic option is the
// only way for the user to trigger it.
absl::holds_alternative<ICloudKeychainMech>(mech.type)) {
primary_passkey_indices_.push_back(i);
} else {
secondary_passkey_indices_.push_back(i);
}
}
return;
}
const std::optional<std::string>& phone_name =
dialog_model->priority_phone_name;
if (phone_name) {
primary_passkeys_label_ = l10n_util::GetStringFUTF16(
IDS_WEBAUTHN_FROM_PHONE_LABEL, base::UTF8ToUTF16(*phone_name));
}
for (size_t i = 0; i < dialog_model->mechanisms.size(); ++i) {
const AuthenticatorRequestDialogModel::Mechanism& mech =
dialog_model->mechanisms[i];
if (absl::holds_alternative<CredentialMech>(mech.type) &&
absl::get<CredentialMech>(mech.type).value().source ==
device::AuthenticatorType::kPhone) {
// There should not be any phone passkeys if the phone name is empty.
CHECK(phone_name);
primary_passkey_indices_.push_back(i);
} else {
secondary_passkey_indices_.push_back(i);
}
}
}
AuthenticatorMultiSourcePickerSheetModel::
~AuthenticatorMultiSourcePickerSheetModel() = default;
bool AuthenticatorMultiSourcePickerSheetModel::IsManageDevicesButtonVisible()
const {
using Mechanism = AuthenticatorRequestDialogModel::Mechanism;
// If any phones or passkeys from a phone 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 Mechanism& mech) {
return absl::holds_alternative<Mechanism::Phone>(mech.type) ||
(absl::holds_alternative<Mechanism::Credential>(mech.type) &&
absl::get<Mechanism::Credential>(mech.type).value().source ==
device::AuthenticatorType::kPhone);
});
}
void AuthenticatorMultiSourcePickerSheetModel::OnManageDevices() {
if (dialog_model()) {
dialog_model()->OnManageDevicesClicked();
}
}
std::u16string AuthenticatorMultiSourcePickerSheetModel::GetStepTitle() const {
return l10n_util::GetStringFUTF16(IDS_WEBAUTHN_CHOOSE_PASSKEY_FOR_RP_TITLE,
GetRelyingPartyIdString(dialog_model()));
}
std::u16string AuthenticatorMultiSourcePickerSheetModel::GetStepDescription()
const {
return u"";
}
// AuthenticatorPriorityMechanismSheetModel --------------------------------
AuthenticatorPriorityMechanismSheetModel::
AuthenticatorPriorityMechanismSheetModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model,
OtherMechanismButtonVisibility::kVisible) {
vector_illustrations_.emplace(kPasskeyHeaderIcon, kPasskeyHeaderDarkIcon);
}
AuthenticatorPriorityMechanismSheetModel::
~AuthenticatorPriorityMechanismSheetModel() = default;
std::u16string AuthenticatorPriorityMechanismSheetModel::GetStepTitle() const {
return l10n_util::GetStringFUTF16(IDS_WEBAUTHN_USE_PASSKEY_TITLE,
GetRelyingPartyIdString(dialog_model()));
}
std::u16string AuthenticatorPriorityMechanismSheetModel::GetStepDescription()
const {
return u"";
}
bool AuthenticatorPriorityMechanismSheetModel::IsAcceptButtonVisible() const {
return true;
}
bool AuthenticatorPriorityMechanismSheetModel::IsAcceptButtonEnabled() const {
return true;
}
std::u16string AuthenticatorPriorityMechanismSheetModel::GetAcceptButtonLabel()
const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CONTINUE);
}
void AuthenticatorPriorityMechanismSheetModel::OnAccept() {
dialog_model()->OnUserConfirmedPriorityMechanism();
}
// AuthenticatorGPMPinSheetModel -------------------------------------
AuthenticatorGPMPinSheetModel::AuthenticatorGPMPinSheetModel(
AuthenticatorRequestDialogModel* dialog_model,
int pin_digits_count,
Mode mode,
AuthenticatorRequestDialogModel::GpmPinError error)
: AuthenticatorSheetModelBase(dialog_model,
OtherMechanismButtonVisibility::kHidden),
pin_digits_count_(pin_digits_count),
mode_(mode),
error_(error) {
// TODO(rgod): Add correct illustration.
vector_illustrations_.emplace(kPasskeyHeaderIcon, kPasskeyHeaderDarkIcon);
}
AuthenticatorGPMPinSheetModel::~AuthenticatorGPMPinSheetModel() = default;
int AuthenticatorGPMPinSheetModel::pin_digits_count() const {
return pin_digits_count_;
}
void AuthenticatorGPMPinSheetModel::SetPin(std::u16string pin) {
bool full_pin_typed_before = FullPinTyped();
pin_ = std::move(pin);
bool full_pin_typed = FullPinTyped();
// When entering an existing PIN, the dialog completes as soon as all the
// digits have been typed. When creating a new PIN, the user has to hit enter
// to confirm.
if (mode_ == Mode::kPinEntry && full_pin_typed) {
dialog_model()->OnGPMPinEntered(pin_);
} else if (mode_ == Mode::kPinCreate &&
full_pin_typed_before != full_pin_typed) {
dialog_model()->OnButtonsStateChanged();
}
}
bool AuthenticatorGPMPinSheetModel::FullPinTyped() const {
return static_cast<int>(pin_.length()) == pin_digits_count_;
}
std::u16string AuthenticatorGPMPinSheetModel::GetStepTitle() const {
switch (mode_) {
case Mode::kPinCreate:
return u"Create a PIN for your Google Password Manager (UNTRANSLATED)";
case Mode::kPinEntry:
return u"Enter your PIN for your Google Password Manager (UNTRANSLATED)";
}
}
std::u16string AuthenticatorGPMPinSheetModel::GetStepDescription() const {
switch (mode_) {
case Mode::kPinCreate:
return u"Your PIN protects your data. You'll need it when you want to "
u"start using your passkeys on new devices. (UNTRANSLATED)";
case Mode::kPinEntry:
return u"Sign in with your passkey to example.com as example@gmail.com "
u"(UNTRANSLATED)";
}
}
std::u16string AuthenticatorGPMPinSheetModel::GetError() const {
switch (error_) {
case AuthenticatorRequestDialogModel::GpmPinError::kNone:
return std::u16string();
case AuthenticatorRequestDialogModel::GpmPinError::kWrongPin:
return u"Wrong PIN (UNTRANSLATED)";
}
}
bool AuthenticatorGPMPinSheetModel::IsAcceptButtonVisible() const {
return mode_ == Mode::kPinCreate;
}
bool AuthenticatorGPMPinSheetModel::IsAcceptButtonEnabled() const {
return mode_ == Mode::kPinCreate && FullPinTyped();
}
bool AuthenticatorGPMPinSheetModel::IsForgotGPMPinButtonVisible() const {
return mode_ == Mode::kPinEntry;
}
bool AuthenticatorGPMPinSheetModel::IsGPMPinOptionsButtonVisible() const {
return mode_ == Mode::kPinCreate;
}
std::u16string AuthenticatorGPMPinSheetModel::GetAcceptButtonLabel() const {
return l10n_util::GetStringUTF16(IDS_CONFIRM);
}
void AuthenticatorGPMPinSheetModel::OnAccept() {
dialog_model()->OnGPMPinEntered(pin_);
}
void AuthenticatorGPMPinSheetModel::OnGPMPinOptionChosen(
bool is_arbitrary) const {
if (!is_arbitrary) {
// The sheet already facilitates entering six digit pin.
return;
}
dialog_model()->OnGPMPinOptionChanged(is_arbitrary);
}
// AuthenticatorGPMArbitraryPinSheetModel ------------------------------------
AuthenticatorGPMArbitraryPinSheetModel::AuthenticatorGPMArbitraryPinSheetModel(
AuthenticatorRequestDialogModel* dialog_model,
Mode mode,
AuthenticatorRequestDialogModel::GpmPinError error)
: AuthenticatorSheetModelBase(dialog_model,
OtherMechanismButtonVisibility::kHidden),
mode_(mode),
error_(error) {
// TODO(rgod): Add correct illustration.
vector_illustrations_.emplace(kPasskeyHeaderIcon, kPasskeyHeaderDarkIcon);
}
AuthenticatorGPMArbitraryPinSheetModel::
~AuthenticatorGPMArbitraryPinSheetModel() = default;
void AuthenticatorGPMArbitraryPinSheetModel::SetPin(std::u16string pin) {
bool accept_button_enabled = IsAcceptButtonEnabled();
pin_ = std::move(pin);
if (accept_button_enabled != IsAcceptButtonEnabled()) {
dialog_model()->OnButtonsStateChanged();
}
}
std::u16string AuthenticatorGPMArbitraryPinSheetModel::GetStepTitle() const {
switch (mode_) {
case Mode::kPinCreate:
return u"Create a PIN for your Google Password Manager (UNTRANSLATED)";
case Mode::kPinEntry:
return u"Enter your PIN for your Google Password Manager (UNTRANSLATED)";
}
}
std::u16string AuthenticatorGPMArbitraryPinSheetModel::GetStepDescription()
const {
switch (mode_) {
case Mode::kPinCreate:
return u"Your PIN protects your data. You'll need it when you want to "
u"start using your passkeys on new devices. (UNTRANSLATED)";
case Mode::kPinEntry:
return u"Sign in with your passkey to example.com as example@gmail.com "
u"(UNTRANSLATED)";
}
}
std::u16string AuthenticatorGPMArbitraryPinSheetModel::GetError() const {
switch (error_) {
case AuthenticatorRequestDialogModel::GpmPinError::kNone:
return std::u16string();
case AuthenticatorRequestDialogModel::GpmPinError::kWrongPin:
return u"Wrong PIN (UNTRANSLATED)";
}
}
bool AuthenticatorGPMArbitraryPinSheetModel::IsAcceptButtonVisible() const {
return true;
}
bool AuthenticatorGPMArbitraryPinSheetModel::IsAcceptButtonEnabled() const {
return pin_.length() > 0;
}
bool AuthenticatorGPMArbitraryPinSheetModel::IsForgotGPMPinButtonVisible()
const {
return mode_ == Mode::kPinEntry;
}
bool AuthenticatorGPMArbitraryPinSheetModel::IsGPMPinOptionsButtonVisible()
const {
return mode_ == Mode::kPinCreate;
}
std::u16string AuthenticatorGPMArbitraryPinSheetModel::GetAcceptButtonLabel()
const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CONTINUE);
}
void AuthenticatorGPMArbitraryPinSheetModel::OnAccept() {
dialog_model()->OnGPMPinEntered(pin_);
}
void AuthenticatorGPMArbitraryPinSheetModel::OnGPMPinOptionChosen(
bool is_arbitrary) const {
if (is_arbitrary) {
// The sheet already facilitates entering arbitrary pin.
return;
}
dialog_model()->OnGPMPinOptionChanged(is_arbitrary);
}
// AuthenticatorTrustThisComputerAssertionSheetModel -------------------------
AuthenticatorTrustThisComputerAssertionSheetModel::
AuthenticatorTrustThisComputerAssertionSheetModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model,
OtherMechanismButtonVisibility::kHidden) {
// TODO(derinel): Add correct illustration.
vector_illustrations_.emplace(kPasskeyHeaderIcon, kPasskeyHeaderDarkIcon);
}
AuthenticatorTrustThisComputerAssertionSheetModel::
~AuthenticatorTrustThisComputerAssertionSheetModel() = default;
std::u16string AuthenticatorTrustThisComputerAssertionSheetModel::GetStepTitle()
const {
return u"To use this passkey, verify it's you (UNTRANSLATED)";
}
std::u16string
AuthenticatorTrustThisComputerAssertionSheetModel::GetStepDescription() const {
return u"You'll only have to do this once. You can use all of your passkey "
u"saved to Google Password Manager on this device. (UNTRANSLATED)";
}
bool AuthenticatorTrustThisComputerAssertionSheetModel::IsCancelButtonVisible()
const {
return true;
}
std::u16string
AuthenticatorTrustThisComputerAssertionSheetModel::GetCancelButtonLabel()
const {
return u"Not now (UNTRANSLATED)";
}
void AuthenticatorTrustThisComputerAssertionSheetModel::OnCancel() {
dialog_model()->ContactPriorityPhone();
}
bool AuthenticatorTrustThisComputerAssertionSheetModel::IsAcceptButtonEnabled()
const {
return true;
}
bool AuthenticatorTrustThisComputerAssertionSheetModel::IsAcceptButtonVisible()
const {
return true;
}
std::u16string
AuthenticatorTrustThisComputerAssertionSheetModel::GetAcceptButtonLabel()
const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CONTINUE);
}
void AuthenticatorTrustThisComputerAssertionSheetModel::OnAccept() {
dialog_model()->OnTrustThisComputer();
}
// AuthenticatorCreateGpmPasskeySheetModel -------------------------------------
AuthenticatorCreateGpmPasskeySheetModel::
AuthenticatorCreateGpmPasskeySheetModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model,
OtherMechanismButtonVisibility::kVisible) {
// TODO(derinel): Add correct illustration.
vector_illustrations_.emplace(kPasskeyHeaderIcon, kPasskeyHeaderDarkIcon);
}
AuthenticatorCreateGpmPasskeySheetModel::
~AuthenticatorCreateGpmPasskeySheetModel() = default;
std::u16string AuthenticatorCreateGpmPasskeySheetModel::GetStepTitle() const {
return u"Create a passkey for example.com (UNTRANSLATED)";
}
std::u16string AuthenticatorCreateGpmPasskeySheetModel::GetStepDescription()
const {
return u"You can use this passkey on any device. It will be saved to Google "
u"Password Manager for username@gmail.com. (UNTRANSLATED)";
}
bool AuthenticatorCreateGpmPasskeySheetModel::IsCancelButtonVisible() const {
return true;
}
std::u16string AuthenticatorCreateGpmPasskeySheetModel::GetCancelButtonLabel()
const {
return l10n_util::GetStringUTF16(IDS_CANCEL);
}
std::u16string
AuthenticatorCreateGpmPasskeySheetModel::GetOtherMechanismButtonLabel() const {
return u"Save another way (UT)";
}
void AuthenticatorCreateGpmPasskeySheetModel::OnCancel() {
dialog_model()->CancelAuthenticatorRequest();
}
bool AuthenticatorCreateGpmPasskeySheetModel::IsAcceptButtonEnabled() const {
return true;
}
bool AuthenticatorCreateGpmPasskeySheetModel::IsAcceptButtonVisible() const {
return true;
}
std::u16string AuthenticatorCreateGpmPasskeySheetModel::GetAcceptButtonLabel()
const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CONTINUE);
}
void AuthenticatorCreateGpmPasskeySheetModel::OnAccept() {
dialog_model()->OnGPMCreatePasskey();
}
// AuthenticatorGpmOnboardingSheetModel -------------------------------------
AuthenticatorGpmOnboardingSheetModel::AuthenticatorGpmOnboardingSheetModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model,
OtherMechanismButtonVisibility::kVisible) {
// TODO(rgod): Add correct illustration.
vector_illustrations_.emplace(kPasskeyHeaderIcon, kPasskeyHeaderDarkIcon);
}
AuthenticatorGpmOnboardingSheetModel::~AuthenticatorGpmOnboardingSheetModel() =
default;
std::u16string AuthenticatorGpmOnboardingSheetModel::GetStepTitle() const {
return u"Start saving passkeys to Google Password Manager (UNTRANSLATED)";
}
std::u16string AuthenticatorGpmOnboardingSheetModel::GetStepDescription()
const {
return u"This passkey will be saved to Google Password Manager for "
u"username@gmail.com. Learn more about passkeys. (UNTRANSLATED)";
}
bool AuthenticatorGpmOnboardingSheetModel::IsCancelButtonVisible() const {
return true;
}
std::u16string AuthenticatorGpmOnboardingSheetModel::GetCancelButtonLabel()
const {
return l10n_util::GetStringUTF16(IDS_CANCEL);
}
std::u16string
AuthenticatorGpmOnboardingSheetModel::GetOtherMechanismButtonLabel() const {
return u"Save another way (UT)";
}
void AuthenticatorGpmOnboardingSheetModel::OnCancel() {
dialog_model()->CancelAuthenticatorRequest();
}
bool AuthenticatorGpmOnboardingSheetModel::IsAcceptButtonEnabled() const {
return true;
}
bool AuthenticatorGpmOnboardingSheetModel::IsAcceptButtonVisible() const {
return true;
}
std::u16string AuthenticatorGpmOnboardingSheetModel::GetAcceptButtonLabel()
const {
return u"Get started (UT)";
}
void AuthenticatorGpmOnboardingSheetModel::OnAccept() {
dialog_model()->OnGPMOnboardingAccepted();
}
// AuthenticatorTrustThisComputerCreationSheetModel ---------------------
AuthenticatorTrustThisComputerCreationSheetModel::
AuthenticatorTrustThisComputerCreationSheetModel(
AuthenticatorRequestDialogModel* dialog_model)
: AuthenticatorSheetModelBase(dialog_model,
OtherMechanismButtonVisibility::kVisible) {
// TODO(rgod): Add correct illustration.
vector_illustrations_.emplace(kPasskeyHeaderIcon, kPasskeyHeaderDarkIcon);
}
AuthenticatorTrustThisComputerCreationSheetModel::
~AuthenticatorTrustThisComputerCreationSheetModel() = default;
std::u16string AuthenticatorTrustThisComputerCreationSheetModel::GetStepTitle()
const {
return u"To save this passkey to Google Password Manager, verify it's you "
u"(UNTRANSLATED)";
}
std::u16string
AuthenticatorTrustThisComputerCreationSheetModel::GetStepDescription() const {
return u"You'll only have to do this once. Your passkey will be saved to "
u"Google Password Manager for username@gmail.com. (UNTRANSLATED)";
}
bool AuthenticatorTrustThisComputerCreationSheetModel::IsCancelButtonVisible()
const {
return true;
}
std::u16string
AuthenticatorTrustThisComputerCreationSheetModel::GetCancelButtonLabel() const {
return l10n_util::GetStringUTF16(IDS_CANCEL);
}
void AuthenticatorTrustThisComputerCreationSheetModel::OnCancel() {
dialog_model()->StartOver();
}
bool AuthenticatorTrustThisComputerCreationSheetModel::IsAcceptButtonEnabled()
const {
return true;
}
bool AuthenticatorTrustThisComputerCreationSheetModel::IsAcceptButtonVisible()
const {
return true;
}
std::u16string
AuthenticatorTrustThisComputerCreationSheetModel::GetAcceptButtonLabel() const {
return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CONTINUE);
}
std::u16string
AuthenticatorTrustThisComputerCreationSheetModel::GetOtherMechanismButtonLabel()
const {
return u"Save another way (UT)";
}
void AuthenticatorTrustThisComputerCreationSheetModel::OnAccept() {
dialog_model()->OnTrustThisComputer();
}