1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "chrome/browser/ui/webauthn/sheet_models.h"
6 
7 #include <memory>
8 #include <string>
9 #include <utility>
10 
11 #include "base/check_op.h"
12 #include "base/memory/ptr_util.h"
13 #include "base/notreached.h"
14 #include "base/strings/string_number_conversions.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "build/build_config.h"
17 #include "chrome/app/vector_icons/vector_icons.h"
18 #include "chrome/browser/ui/webauthn/other_transports_menu_model.h"
19 #include "chrome/grit/generated_resources.h"
20 #include "components/strings/grit/components_strings.h"
21 #include "components/url_formatter/elide_url.h"
22 #include "device/fido/authenticator_get_assertion_response.h"
23 #include "device/fido/features.h"
24 #include "ui/base/l10n/l10n_util.h"
25 #include "ui/gfx/font_list.h"
26 #include "ui/gfx/text_utils.h"
27 #include "url/gurl.h"
28 
29 namespace {
30 
GetRelyingPartyIdString(AuthenticatorRequestDialogModel * dialog_model)31 base::string16 GetRelyingPartyIdString(
32     AuthenticatorRequestDialogModel* dialog_model) {
33   static constexpr char kRpIdUrlPrefix[] = "https://";
34   // The preferred width of medium snap point modal dialog view is 448 dp, but
35   // we leave some room for padding between the text and the modal views.
36   static constexpr int kDialogWidth = 300;
37   const auto& rp_id = dialog_model->relying_party_id();
38   DCHECK(!rp_id.empty());
39   GURL rp_id_url(kRpIdUrlPrefix + rp_id);
40   return url_formatter::ElideHost(rp_id_url, gfx::FontList(), kDialogWidth);
41 }
42 
43 // Possibly returns a resident key warning if the model indicates that it's
44 // needed.
PossibleResidentKeyWarning(AuthenticatorRequestDialogModel * dialog_model)45 base::string16 PossibleResidentKeyWarning(
46     AuthenticatorRequestDialogModel* dialog_model) {
47   if (dialog_model->might_create_resident_credential()) {
48     return l10n_util::GetStringUTF16(IDS_WEBAUTHN_RESIDENT_KEY_PRIVACY);
49   }
50   return base::string16();
51 }
52 
53 }  // namespace
54 
55 // AuthenticatorSheetModelBase ------------------------------------------------
56 
AuthenticatorSheetModelBase(AuthenticatorRequestDialogModel * dialog_model)57 AuthenticatorSheetModelBase::AuthenticatorSheetModelBase(
58     AuthenticatorRequestDialogModel* dialog_model)
59     : dialog_model_(dialog_model) {
60   DCHECK(dialog_model);
61   dialog_model_->AddObserver(this);
62 }
63 
~AuthenticatorSheetModelBase()64 AuthenticatorSheetModelBase::~AuthenticatorSheetModelBase() {
65   if (dialog_model_) {
66     dialog_model_->RemoveObserver(this);
67     dialog_model_ = nullptr;
68   }
69 }
70 
IsActivityIndicatorVisible() const71 bool AuthenticatorSheetModelBase::IsActivityIndicatorVisible() const {
72   return false;
73 }
74 
IsBackButtonVisible() const75 bool AuthenticatorSheetModelBase::IsBackButtonVisible() const {
76   return true;
77 }
78 
IsCancelButtonVisible() const79 bool AuthenticatorSheetModelBase::IsCancelButtonVisible() const {
80   return true;
81 }
82 
GetCancelButtonLabel() const83 base::string16 AuthenticatorSheetModelBase::GetCancelButtonLabel() const {
84   return l10n_util::GetStringUTF16(IDS_CANCEL);
85 }
86 
IsAcceptButtonVisible() const87 bool AuthenticatorSheetModelBase::IsAcceptButtonVisible() const {
88   return false;
89 }
90 
IsAcceptButtonEnabled() const91 bool AuthenticatorSheetModelBase::IsAcceptButtonEnabled() const {
92   return false;
93 }
94 
GetAcceptButtonLabel() const95 base::string16 AuthenticatorSheetModelBase::GetAcceptButtonLabel() const {
96   return base::string16();
97 }
98 
OnBack()99 void AuthenticatorSheetModelBase::OnBack() {
100   if (dialog_model())
101     dialog_model()->StartOver();
102 }
103 
OnAccept()104 void AuthenticatorSheetModelBase::OnAccept() {
105   NOTREACHED();
106 }
107 
OnCancel()108 void AuthenticatorSheetModelBase::OnCancel() {
109   if (dialog_model())
110     dialog_model()->Cancel();
111 }
112 
OnModelDestroyed()113 void AuthenticatorSheetModelBase::OnModelDestroyed() {
114   dialog_model_ = nullptr;
115 }
116 
117 // AuthenticatorTransportSelectorSheetModel -----------------------------------
118 
IsBackButtonVisible() const119 bool AuthenticatorTransportSelectorSheetModel::IsBackButtonVisible() const {
120   return false;
121 }
122 
123 const gfx::VectorIcon&
GetStepIllustration(ImageColorScheme color_scheme) const124 AuthenticatorTransportSelectorSheetModel::GetStepIllustration(
125     ImageColorScheme color_scheme) const {
126   return color_scheme == ImageColorScheme::kDark ? kWebauthnWelcomeDarkIcon
127                                                  : kWebauthnWelcomeIcon;
128 }
129 
GetStepTitle() const130 base::string16 AuthenticatorTransportSelectorSheetModel::GetStepTitle() const {
131   return l10n_util::GetStringFUTF16(IDS_WEBAUTHN_TRANSPORT_SELECTION_TITLE,
132                                     GetRelyingPartyIdString(dialog_model()));
133 }
134 
GetStepDescription() const135 base::string16 AuthenticatorTransportSelectorSheetModel::GetStepDescription()
136     const {
137   return l10n_util::GetStringUTF16(
138       IDS_WEBAUTHN_TRANSPORT_SELECTION_DESCRIPTION);
139 }
140 
OnTransportSelected(AuthenticatorTransport transport)141 void AuthenticatorTransportSelectorSheetModel::OnTransportSelected(
142     AuthenticatorTransport transport) {
143   dialog_model()->StartGuidedFlowForTransport(transport);
144 }
145 
StartWinNativeApi()146 void AuthenticatorTransportSelectorSheetModel::StartWinNativeApi() {
147   dialog_model()->StartWinNativeApi();
148 }
149 
150 // AuthenticatorInsertAndActivateUsbSheetModel ----------------------
151 
152 AuthenticatorInsertAndActivateUsbSheetModel::
AuthenticatorInsertAndActivateUsbSheetModel(AuthenticatorRequestDialogModel * dialog_model)153     AuthenticatorInsertAndActivateUsbSheetModel(
154         AuthenticatorRequestDialogModel* dialog_model)
155     : AuthenticatorSheetModelBase(dialog_model),
156       other_transports_menu_model_(std::make_unique<OtherTransportsMenuModel>(
157           dialog_model,
158           AuthenticatorTransport::kUsbHumanInterfaceDevice)) {}
159 
160 AuthenticatorInsertAndActivateUsbSheetModel::
161     ~AuthenticatorInsertAndActivateUsbSheetModel() = default;
162 
IsActivityIndicatorVisible() const163 bool AuthenticatorInsertAndActivateUsbSheetModel::IsActivityIndicatorVisible()
164     const {
165   return true;
166 }
167 
168 const gfx::VectorIcon&
GetStepIllustration(ImageColorScheme color_scheme) const169 AuthenticatorInsertAndActivateUsbSheetModel::GetStepIllustration(
170     ImageColorScheme color_scheme) const {
171   return color_scheme == ImageColorScheme::kDark ? kWebauthnUsbDarkIcon
172                                                  : kWebauthnUsbIcon;
173 }
174 
GetStepTitle() const175 base::string16 AuthenticatorInsertAndActivateUsbSheetModel::GetStepTitle()
176     const {
177   return l10n_util::GetStringFUTF16(IDS_WEBAUTHN_GENERIC_TITLE,
178                                     GetRelyingPartyIdString(dialog_model()));
179 }
180 
GetStepDescription() const181 base::string16 AuthenticatorInsertAndActivateUsbSheetModel::GetStepDescription()
182     const {
183   return l10n_util::GetStringUTF16(IDS_WEBAUTHN_USB_ACTIVATE_DESCRIPTION);
184 }
185 
186 base::string16
GetAdditionalDescription() const187 AuthenticatorInsertAndActivateUsbSheetModel::GetAdditionalDescription() const {
188   return PossibleResidentKeyWarning(dialog_model());
189 }
190 
191 ui::MenuModel*
GetOtherTransportsMenuModel()192 AuthenticatorInsertAndActivateUsbSheetModel::GetOtherTransportsMenuModel() {
193   return other_transports_menu_model_.get();
194 }
195 
196 // AuthenticatorTimeoutErrorModel ---------------------------------------------
197 
IsBackButtonVisible() const198 bool AuthenticatorTimeoutErrorModel::IsBackButtonVisible() const {
199   return false;
200 }
201 
GetCancelButtonLabel() const202 base::string16 AuthenticatorTimeoutErrorModel::GetCancelButtonLabel() const {
203   return l10n_util::GetStringUTF16(IDS_CLOSE);
204 }
205 
GetStepIllustration(ImageColorScheme color_scheme) const206 const gfx::VectorIcon& AuthenticatorTimeoutErrorModel::GetStepIllustration(
207     ImageColorScheme color_scheme) const {
208   return color_scheme == ImageColorScheme::kDark ? kWebauthnErrorDarkIcon
209                                                  : kWebauthnErrorIcon;
210 }
211 
GetStepTitle() const212 base::string16 AuthenticatorTimeoutErrorModel::GetStepTitle() const {
213   return l10n_util::GetStringUTF16(IDS_WEBAUTHN_ERROR_GENERIC_TITLE);
214 }
215 
GetStepDescription() const216 base::string16 AuthenticatorTimeoutErrorModel::GetStepDescription() const {
217   return l10n_util::GetStringUTF16(IDS_WEBAUTHN_ERROR_TIMEOUT_DESCRIPTION);
218 }
219 
220 // AuthenticatorNoAvailableTransportsErrorModel -------------------------------
221 
IsBackButtonVisible() const222 bool AuthenticatorNoAvailableTransportsErrorModel::IsBackButtonVisible() const {
223   return false;
224 }
225 
226 base::string16
GetCancelButtonLabel() const227 AuthenticatorNoAvailableTransportsErrorModel::GetCancelButtonLabel() const {
228   return l10n_util::GetStringUTF16(IDS_CLOSE);
229 }
230 
231 const gfx::VectorIcon&
GetStepIllustration(ImageColorScheme color_scheme) const232 AuthenticatorNoAvailableTransportsErrorModel::GetStepIllustration(
233     ImageColorScheme color_scheme) const {
234   return color_scheme == ImageColorScheme::kDark ? kWebauthnErrorDarkIcon
235                                                  : kWebauthnErrorIcon;
236 }
237 
GetStepTitle() const238 base::string16 AuthenticatorNoAvailableTransportsErrorModel::GetStepTitle()
239     const {
240   return l10n_util::GetStringUTF16(IDS_WEBAUTHN_ERROR_NO_TRANSPORTS_TITLE);
241 }
242 
243 base::string16
GetStepDescription() const244 AuthenticatorNoAvailableTransportsErrorModel::GetStepDescription() const {
245   return l10n_util::GetStringUTF16(
246       IDS_WEBAUTHN_ERROR_NO_TRANSPORTS_DESCRIPTION);
247 }
248 
249 // AuthenticatorNotRegisteredErrorModel ---------------------------------------
250 
IsBackButtonVisible() const251 bool AuthenticatorNotRegisteredErrorModel::IsBackButtonVisible() const {
252   return false;
253 }
254 
GetCancelButtonLabel() const255 base::string16 AuthenticatorNotRegisteredErrorModel::GetCancelButtonLabel()
256     const {
257   return l10n_util::GetStringUTF16(IDS_CLOSE);
258 }
259 
IsAcceptButtonVisible() const260 bool AuthenticatorNotRegisteredErrorModel::IsAcceptButtonVisible() const {
261   return dialog_model()->offer_try_again_in_ui();
262 }
263 
IsAcceptButtonEnabled() const264 bool AuthenticatorNotRegisteredErrorModel::IsAcceptButtonEnabled() const {
265   return true;
266 }
267 
GetAcceptButtonLabel() const268 base::string16 AuthenticatorNotRegisteredErrorModel::GetAcceptButtonLabel()
269     const {
270   return l10n_util::GetStringUTF16(IDS_WEBAUTHN_RETRY);
271 }
272 
273 const gfx::VectorIcon&
GetStepIllustration(ImageColorScheme color_scheme) const274 AuthenticatorNotRegisteredErrorModel::GetStepIllustration(
275     ImageColorScheme color_scheme) const {
276   return color_scheme == ImageColorScheme::kDark ? kWebauthnErrorDarkIcon
277                                                  : kWebauthnErrorIcon;
278 }
279 
GetStepTitle() const280 base::string16 AuthenticatorNotRegisteredErrorModel::GetStepTitle() const {
281   return l10n_util::GetStringUTF16(IDS_WEBAUTHN_ERROR_WRONG_KEY_TITLE);
282 }
283 
GetStepDescription() const284 base::string16 AuthenticatorNotRegisteredErrorModel::GetStepDescription()
285     const {
286   return l10n_util::GetStringUTF16(
287       IDS_WEBAUTHN_ERROR_WRONG_KEY_SIGN_DESCRIPTION);
288 }
289 
OnAccept()290 void AuthenticatorNotRegisteredErrorModel::OnAccept() {
291   dialog_model()->StartOver();
292 }
293 
294 // AuthenticatorAlreadyRegisteredErrorModel -----------------------------------
295 
IsBackButtonVisible() const296 bool AuthenticatorAlreadyRegisteredErrorModel::IsBackButtonVisible() const {
297   return false;
298 }
299 
GetCancelButtonLabel() const300 base::string16 AuthenticatorAlreadyRegisteredErrorModel::GetCancelButtonLabel()
301     const {
302   return l10n_util::GetStringUTF16(IDS_CLOSE);
303 }
304 
IsAcceptButtonVisible() const305 bool AuthenticatorAlreadyRegisteredErrorModel::IsAcceptButtonVisible() const {
306   return dialog_model()->offer_try_again_in_ui();
307 }
308 
IsAcceptButtonEnabled() const309 bool AuthenticatorAlreadyRegisteredErrorModel::IsAcceptButtonEnabled() const {
310   return true;
311 }
312 
GetAcceptButtonLabel() const313 base::string16 AuthenticatorAlreadyRegisteredErrorModel::GetAcceptButtonLabel()
314     const {
315   return l10n_util::GetStringUTF16(IDS_WEBAUTHN_RETRY);
316 }
317 
318 const gfx::VectorIcon&
GetStepIllustration(ImageColorScheme color_scheme) const319 AuthenticatorAlreadyRegisteredErrorModel::GetStepIllustration(
320     ImageColorScheme color_scheme) const {
321   return color_scheme == ImageColorScheme::kDark ? kWebauthnErrorDarkIcon
322                                                  : kWebauthnErrorIcon;
323 }
324 
GetStepTitle() const325 base::string16 AuthenticatorAlreadyRegisteredErrorModel::GetStepTitle() const {
326   return l10n_util::GetStringUTF16(IDS_WEBAUTHN_ERROR_WRONG_KEY_TITLE);
327 }
328 
GetStepDescription() const329 base::string16 AuthenticatorAlreadyRegisteredErrorModel::GetStepDescription()
330     const {
331   return l10n_util::GetStringUTF16(
332       IDS_WEBAUTHN_ERROR_WRONG_KEY_REGISTER_DESCRIPTION);
333 }
334 
OnAccept()335 void AuthenticatorAlreadyRegisteredErrorModel::OnAccept() {
336   dialog_model()->StartOver();
337 }
338 
339 // AuthenticatorInternalUnrecognizedErrorSheetModel
340 // -----------------------------------
IsBackButtonVisible() const341 bool AuthenticatorInternalUnrecognizedErrorSheetModel::IsBackButtonVisible()
342     const {
343   return dialog_model()->offer_try_again_in_ui();
344 }
345 
IsAcceptButtonVisible() const346 bool AuthenticatorInternalUnrecognizedErrorSheetModel::IsAcceptButtonVisible()
347     const {
348   return dialog_model()->offer_try_again_in_ui();
349 }
350 
IsAcceptButtonEnabled() const351 bool AuthenticatorInternalUnrecognizedErrorSheetModel::IsAcceptButtonEnabled()
352     const {
353   return true;
354 }
355 
356 base::string16
GetAcceptButtonLabel() const357 AuthenticatorInternalUnrecognizedErrorSheetModel::GetAcceptButtonLabel() const {
358   return l10n_util::GetStringUTF16(IDS_WEBAUTHN_RETRY);
359 }
360 
361 const gfx::VectorIcon&
GetStepIllustration(ImageColorScheme color_scheme) const362 AuthenticatorInternalUnrecognizedErrorSheetModel::GetStepIllustration(
363     ImageColorScheme color_scheme) const {
364   return color_scheme == ImageColorScheme::kDark ? kWebauthnErrorDarkIcon
365                                                  : kWebauthnErrorIcon;
366 }
367 
GetStepTitle() const368 base::string16 AuthenticatorInternalUnrecognizedErrorSheetModel::GetStepTitle()
369     const {
370   return l10n_util::GetStringUTF16(
371       IDS_WEBAUTHN_ERROR_INTERNAL_UNRECOGNIZED_TITLE);
372 }
373 
374 base::string16
GetStepDescription() const375 AuthenticatorInternalUnrecognizedErrorSheetModel::GetStepDescription() const {
376   return l10n_util::GetStringUTF16(
377       IDS_WEBAUTHN_ERROR_INTERNAL_UNRECOGNIZED_DESCRIPTION);
378 }
379 
OnAccept()380 void AuthenticatorInternalUnrecognizedErrorSheetModel::OnAccept() {
381   dialog_model()->StartOver();
382 }
383 
384 // AuthenticatorBlePowerOnManualSheetModel ------------------------------------
385 
386 const gfx::VectorIcon&
GetStepIllustration(ImageColorScheme color_scheme) const387 AuthenticatorBlePowerOnManualSheetModel::GetStepIllustration(
388     ImageColorScheme color_scheme) const {
389   return color_scheme == ImageColorScheme::kDark
390              ? kWebauthnErrorBluetoothDarkIcon
391              : kWebauthnErrorBluetoothIcon;
392 }
393 
GetStepTitle() const394 base::string16 AuthenticatorBlePowerOnManualSheetModel::GetStepTitle() const {
395   return l10n_util::GetStringUTF16(
396       IDS_WEBAUTHN_BLUETOOTH_POWER_ON_MANUAL_TITLE);
397 }
398 
GetStepDescription() const399 base::string16 AuthenticatorBlePowerOnManualSheetModel::GetStepDescription()
400     const {
401   return l10n_util::GetStringUTF16(
402       IDS_WEBAUTHN_BLUETOOTH_POWER_ON_MANUAL_DESCRIPTION);
403 }
404 
IsAcceptButtonVisible() const405 bool AuthenticatorBlePowerOnManualSheetModel::IsAcceptButtonVisible() const {
406   return true;
407 }
408 
IsAcceptButtonEnabled() const409 bool AuthenticatorBlePowerOnManualSheetModel::IsAcceptButtonEnabled() const {
410   return dialog_model()->ble_adapter_is_powered();
411 }
412 
GetAcceptButtonLabel() const413 base::string16 AuthenticatorBlePowerOnManualSheetModel::GetAcceptButtonLabel()
414     const {
415   return l10n_util::GetStringUTF16(IDS_WEBAUTHN_BLUETOOTH_POWER_ON_MANUAL_NEXT);
416 }
417 
OnBluetoothPoweredStateChanged()418 void AuthenticatorBlePowerOnManualSheetModel::OnBluetoothPoweredStateChanged() {
419   dialog_model()->OnSheetModelDidChange();
420 }
421 
OnAccept()422 void AuthenticatorBlePowerOnManualSheetModel::OnAccept() {
423   dialog_model()->ContinueWithFlowAfterBleAdapterPowered();
424 }
425 
426 // AuthenticatorBlePowerOnAutomaticSheetModel
427 // ------------------------------------
428 
IsActivityIndicatorVisible() const429 bool AuthenticatorBlePowerOnAutomaticSheetModel::IsActivityIndicatorVisible()
430     const {
431   return busy_powering_on_ble_;
432 }
433 
434 const gfx::VectorIcon&
GetStepIllustration(ImageColorScheme color_scheme) const435 AuthenticatorBlePowerOnAutomaticSheetModel::GetStepIllustration(
436     ImageColorScheme color_scheme) const {
437   return color_scheme == ImageColorScheme::kDark
438              ? kWebauthnErrorBluetoothDarkIcon
439              : kWebauthnErrorBluetoothIcon;
440 }
441 
GetStepTitle() const442 base::string16 AuthenticatorBlePowerOnAutomaticSheetModel::GetStepTitle()
443     const {
444   return l10n_util::GetStringUTF16(IDS_WEBAUTHN_BLUETOOTH_POWER_ON_AUTO_TITLE);
445 }
446 
GetStepDescription() const447 base::string16 AuthenticatorBlePowerOnAutomaticSheetModel::GetStepDescription()
448     const {
449   return l10n_util::GetStringUTF16(
450       IDS_WEBAUTHN_BLUETOOTH_POWER_ON_AUTO_DESCRIPTION);
451 }
452 
IsAcceptButtonVisible() const453 bool AuthenticatorBlePowerOnAutomaticSheetModel::IsAcceptButtonVisible() const {
454   return true;
455 }
456 
IsAcceptButtonEnabled() const457 bool AuthenticatorBlePowerOnAutomaticSheetModel::IsAcceptButtonEnabled() const {
458   return !busy_powering_on_ble_;
459 }
460 
461 base::string16
GetAcceptButtonLabel() const462 AuthenticatorBlePowerOnAutomaticSheetModel::GetAcceptButtonLabel() const {
463   return l10n_util::GetStringUTF16(IDS_WEBAUTHN_BLUETOOTH_POWER_ON_AUTO_NEXT);
464 }
465 
OnAccept()466 void AuthenticatorBlePowerOnAutomaticSheetModel::OnAccept() {
467   busy_powering_on_ble_ = true;
468   dialog_model()->OnSheetModelDidChange();
469   dialog_model()->PowerOnBleAdapter();
470 }
471 
472 // AuthenticatorTouchIdIncognitoBumpSheetModel
473 // -----------------------------------------
474 
475 AuthenticatorTouchIdIncognitoBumpSheetModel::
AuthenticatorTouchIdIncognitoBumpSheetModel(AuthenticatorRequestDialogModel * dialog_model)476     AuthenticatorTouchIdIncognitoBumpSheetModel(
477         AuthenticatorRequestDialogModel* dialog_model)
478     : AuthenticatorSheetModelBase(dialog_model),
479       other_transports_menu_model_(std::make_unique<OtherTransportsMenuModel>(
480           dialog_model,
481           AuthenticatorTransport::kInternal)) {}
482 
483 AuthenticatorTouchIdIncognitoBumpSheetModel::
484     ~AuthenticatorTouchIdIncognitoBumpSheetModel() = default;
485 
486 const gfx::VectorIcon&
GetStepIllustration(ImageColorScheme color_scheme) const487 AuthenticatorTouchIdIncognitoBumpSheetModel::GetStepIllustration(
488     ImageColorScheme color_scheme) const {
489   return color_scheme == ImageColorScheme::kDark ? kWebauthnPermissionDarkIcon
490                                                  : kWebauthnPermissionIcon;
491 }
492 
GetStepTitle() const493 base::string16 AuthenticatorTouchIdIncognitoBumpSheetModel::GetStepTitle()
494     const {
495 #if defined(OS_MAC)
496   return l10n_util::GetStringFUTF16(IDS_WEBAUTHN_TOUCH_ID_INCOGNITO_BUMP_TITLE,
497                                     GetRelyingPartyIdString(dialog_model()));
498 #else
499   return base::string16();
500 #endif  // defined(OS_MAC)
501 }
502 
GetStepDescription() const503 base::string16 AuthenticatorTouchIdIncognitoBumpSheetModel::GetStepDescription()
504     const {
505 #if defined(OS_MAC)
506   return l10n_util::GetStringUTF16(
507       IDS_WEBAUTHN_TOUCH_ID_INCOGNITO_BUMP_DESCRIPTION);
508 #else
509   return base::string16();
510 #endif  // defined(OS_MAC)
511 }
512 
513 ui::MenuModel*
GetOtherTransportsMenuModel()514 AuthenticatorTouchIdIncognitoBumpSheetModel::GetOtherTransportsMenuModel() {
515   return other_transports_menu_model_.get();
516 }
517 
IsAcceptButtonVisible() const518 bool AuthenticatorTouchIdIncognitoBumpSheetModel::IsAcceptButtonVisible()
519     const {
520   return true;
521 }
522 
IsAcceptButtonEnabled() const523 bool AuthenticatorTouchIdIncognitoBumpSheetModel::IsAcceptButtonEnabled()
524     const {
525   return true;
526 }
527 
528 base::string16
GetAcceptButtonLabel() const529 AuthenticatorTouchIdIncognitoBumpSheetModel::GetAcceptButtonLabel() const {
530 #if defined(OS_MAC)
531   return l10n_util::GetStringUTF16(
532       IDS_WEBAUTHN_TOUCH_ID_INCOGNITO_BUMP_CONTINUE);
533 #else
534   return base::string16();
535 #endif  // defined(OS_MAC)
536 }
537 
OnAccept()538 void AuthenticatorTouchIdIncognitoBumpSheetModel::OnAccept() {
539   dialog_model()->HideDialogAndTryTouchId();
540 }
541 
542 // AuthenticatorPaaskSheetModel -----------------------------------------
543 
AuthenticatorPaaskSheetModel(AuthenticatorRequestDialogModel * dialog_model)544 AuthenticatorPaaskSheetModel::AuthenticatorPaaskSheetModel(
545     AuthenticatorRequestDialogModel* dialog_model)
546     : AuthenticatorSheetModelBase(dialog_model),
547       other_transports_menu_model_(std::make_unique<OtherTransportsMenuModel>(
548           dialog_model,
549           AuthenticatorTransport::kCloudAssistedBluetoothLowEnergy)) {}
550 
551 AuthenticatorPaaskSheetModel::~AuthenticatorPaaskSheetModel() = default;
552 
IsBackButtonVisible() const553 bool AuthenticatorPaaskSheetModel::IsBackButtonVisible() const {
554 #if defined(OS_WIN)
555   return !base::FeatureList::IsEnabled(device::kWebAuthUseNativeWinApi);
556 #else
557   return true;
558 #endif
559 }
560 
IsActivityIndicatorVisible() const561 bool AuthenticatorPaaskSheetModel::IsActivityIndicatorVisible() const {
562   return true;
563 }
564 
GetStepIllustration(ImageColorScheme color_scheme) const565 const gfx::VectorIcon& AuthenticatorPaaskSheetModel::GetStepIllustration(
566     ImageColorScheme color_scheme) const {
567   return color_scheme == ImageColorScheme::kDark ? kWebauthnPhoneDarkIcon
568                                                  : kWebauthnPhoneIcon;
569 }
570 
GetStepTitle() const571 base::string16 AuthenticatorPaaskSheetModel::GetStepTitle() const {
572   return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CABLE_ACTIVATE_TITLE);
573 }
574 
GetStepDescription() const575 base::string16 AuthenticatorPaaskSheetModel::GetStepDescription() const {
576   return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CABLE_ACTIVATE_DESCRIPTION);
577 }
578 
GetOtherTransportsMenuModel()579 ui::MenuModel* AuthenticatorPaaskSheetModel::GetOtherTransportsMenuModel() {
580   return other_transports_menu_model_.get();
581 }
582 
583 // AuthenticatorPaaskV2SheetModel  -----------------------------------------
584 
AuthenticatorPaaskV2SheetModel(AuthenticatorRequestDialogModel * dialog_model)585 AuthenticatorPaaskV2SheetModel::AuthenticatorPaaskV2SheetModel(
586     AuthenticatorRequestDialogModel* dialog_model)
587     : AuthenticatorSheetModelBase(dialog_model),
588       other_transports_menu_model_(std::make_unique<OtherTransportsMenuModel>(
589           dialog_model,
590           AuthenticatorTransport::kCloudAssistedBluetoothLowEnergy)) {}
591 
592 AuthenticatorPaaskV2SheetModel::~AuthenticatorPaaskV2SheetModel() = default;
593 
IsBackButtonVisible() const594 bool AuthenticatorPaaskV2SheetModel::IsBackButtonVisible() const {
595 #if defined(OS_WIN)
596   return !base::FeatureList::IsEnabled(device::kWebAuthUseNativeWinApi);
597 #else
598   return true;
599 #endif
600 }
601 
IsActivityIndicatorVisible() const602 bool AuthenticatorPaaskV2SheetModel::IsActivityIndicatorVisible() const {
603   return true;
604 }
605 
GetStepIllustration(ImageColorScheme color_scheme) const606 const gfx::VectorIcon& AuthenticatorPaaskV2SheetModel::GetStepIllustration(
607     ImageColorScheme color_scheme) const {
608   return color_scheme == ImageColorScheme::kDark ? kWebauthnPhoneDarkIcon
609                                                  : kWebauthnPhoneIcon;
610 }
611 
IsAcceptButtonVisible() const612 bool AuthenticatorPaaskV2SheetModel::IsAcceptButtonVisible() const {
613   return true;
614 }
615 
IsAcceptButtonEnabled() const616 bool AuthenticatorPaaskV2SheetModel::IsAcceptButtonEnabled() const {
617   return true;
618 }
619 
GetAcceptButtonLabel() const620 base::string16 AuthenticatorPaaskV2SheetModel::GetAcceptButtonLabel() const {
621   return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CABLE_QR_TITLE);
622 }
623 
OnAccept()624 void AuthenticatorPaaskV2SheetModel::OnAccept() {
625   return dialog_model()->StartPhonePairing();
626 }
627 
GetStepTitle() const628 base::string16 AuthenticatorPaaskV2SheetModel::GetStepTitle() const {
629   return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CABLE_V2_ACTIVATE_TITLE);
630 }
631 
GetStepDescription() const632 base::string16 AuthenticatorPaaskV2SheetModel::GetStepDescription() const {
633   return l10n_util::GetStringUTF16(
634       IDS_WEBAUTHN_CABLE_V2_ACTIVATE_DESCRIPTION_SHORT);
635 }
636 
GetOtherTransportsMenuModel()637 ui::MenuModel* AuthenticatorPaaskV2SheetModel::GetOtherTransportsMenuModel() {
638   return other_transports_menu_model_.get();
639 }
640 
641 // AuthenticatorClientPinEntrySheetModel
642 // -----------------------------------------
643 
AuthenticatorClientPinEntrySheetModel(AuthenticatorRequestDialogModel * dialog_model,Mode mode)644 AuthenticatorClientPinEntrySheetModel::AuthenticatorClientPinEntrySheetModel(
645     AuthenticatorRequestDialogModel* dialog_model,
646     Mode mode)
647     : AuthenticatorSheetModelBase(dialog_model), mode_(mode) {
648   if (!dialog_model->has_attempted_pin_entry()) {
649     if (dialog_model->uv_attempts() == 0) {
650       error_ = l10n_util::GetStringUTF16(IDS_WEBAUTHN_UV_ERROR_LOCKED);
651     }
652     return;
653   }
654 
655   if (mode_ == AuthenticatorClientPinEntrySheetModel::Mode::kPinEntry) {
656     base::Optional<int> attempts = dialog_model->pin_attempts();
657     error_ =
658         attempts && *attempts <= 3
659             ? l10n_util::GetPluralStringFUTF16(
660                   IDS_WEBAUTHN_PIN_ENTRY_ERROR_FAILED_RETRIES, *attempts)
661             : l10n_util::GetStringUTF16(IDS_WEBAUTHN_PIN_ENTRY_ERROR_FAILED);
662     return;
663   }
664 
665   DCHECK(mode_ == AuthenticatorClientPinEntrySheetModel::Mode::kPinSetup);
666   error_ = l10n_util::GetStringUTF16(IDS_WEBAUTHN_PIN_SETUP_ERROR_FAILED);
667 }
668 
669 AuthenticatorClientPinEntrySheetModel::
670     ~AuthenticatorClientPinEntrySheetModel() = default;
671 
SetPinCode(base::string16 pin_code)672 void AuthenticatorClientPinEntrySheetModel::SetPinCode(
673     base::string16 pin_code) {
674   pin_code_ = std::move(pin_code);
675 }
676 
SetPinConfirmation(base::string16 pin_confirmation)677 void AuthenticatorClientPinEntrySheetModel::SetPinConfirmation(
678     base::string16 pin_confirmation) {
679   DCHECK(mode_ == AuthenticatorClientPinEntrySheetModel::Mode::kPinSetup);
680   pin_confirmation_ = std::move(pin_confirmation);
681 }
682 
683 const gfx::VectorIcon&
GetStepIllustration(ImageColorScheme color_scheme) const684 AuthenticatorClientPinEntrySheetModel::GetStepIllustration(
685     ImageColorScheme color_scheme) const {
686   return color_scheme == ImageColorScheme::kDark ? kWebauthnUsbDarkIcon
687                                                  : kWebauthnUsbIcon;
688 }
689 
GetStepTitle() const690 base::string16 AuthenticatorClientPinEntrySheetModel::GetStepTitle() const {
691   return l10n_util::GetStringUTF16(IDS_WEBAUTHN_PIN_ENTRY_TITLE);
692 }
693 
GetStepDescription() const694 base::string16 AuthenticatorClientPinEntrySheetModel::GetStepDescription()
695     const {
696   return l10n_util::GetStringUTF16(
697       mode_ == AuthenticatorClientPinEntrySheetModel::Mode::kPinEntry
698           ? IDS_WEBAUTHN_PIN_ENTRY_DESCRIPTION
699           : IDS_WEBAUTHN_PIN_SETUP_DESCRIPTION);
700 }
701 
GetError() const702 base::string16 AuthenticatorClientPinEntrySheetModel::GetError() const {
703   return error_;
704 }
705 
IsAcceptButtonVisible() const706 bool AuthenticatorClientPinEntrySheetModel::IsAcceptButtonVisible() const {
707   return true;
708 }
709 
IsAcceptButtonEnabled() const710 bool AuthenticatorClientPinEntrySheetModel::IsAcceptButtonEnabled() const {
711   return true;
712 }
713 
GetAcceptButtonLabel() const714 base::string16 AuthenticatorClientPinEntrySheetModel::GetAcceptButtonLabel()
715     const {
716   return l10n_util::GetStringUTF16(IDS_WEBAUTHN_PIN_ENTRY_NEXT);
717 }
718 
IsValidUTF16(const base::string16 & str16)719 static bool IsValidUTF16(const base::string16& str16) {
720   std::string unused_str8;
721   return base::UTF16ToUTF8(str16.c_str(), str16.size(), &unused_str8);
722 }
723 
OnAccept()724 void AuthenticatorClientPinEntrySheetModel::OnAccept() {
725   // TODO(martinkr): use device::pin::kMinLength once landed.
726   constexpr size_t kMinPinLength = 4;
727   if (mode_ == AuthenticatorClientPinEntrySheetModel::Mode::kPinSetup) {
728     // Validate a new PIN.
729     base::Optional<base::string16> error;
730     if (!pin_code_.empty() && !IsValidUTF16(pin_code_)) {
731       error = l10n_util::GetStringUTF16(
732           IDS_WEBAUTHN_PIN_ENTRY_ERROR_INVALID_CHARACTERS);
733     } else if (pin_code_.size() < kMinPinLength) {
734       error = l10n_util::GetStringUTF16(IDS_WEBAUTHN_PIN_ENTRY_ERROR_TOO_SHORT);
735     } else if (pin_code_ != pin_confirmation_) {
736       error = l10n_util::GetStringUTF16(IDS_WEBAUTHN_PIN_ENTRY_ERROR_MISMATCH);
737     }
738     if (error) {
739       error_ = *error;
740       dialog_model()->OnSheetModelDidChange();
741       return;
742     }
743   } else {
744     // Submit PIN to authenticator for verification.
745     DCHECK(mode_ == AuthenticatorClientPinEntrySheetModel::Mode::kPinEntry);
746     // TODO: use device::pin::IsValid instead.
747     if (pin_code_.size() < kMinPinLength) {
748       error_ =
749           l10n_util::GetStringUTF16(IDS_WEBAUTHN_PIN_ENTRY_ERROR_TOO_SHORT);
750       dialog_model()->OnSheetModelDidChange();
751       return;
752     }
753   }
754 
755   if (dialog_model()) {
756     dialog_model()->OnHavePIN(base::UTF16ToUTF8(pin_code_));
757   }
758 }
759 
760 // AuthenticatorClientPinTapAgainSheetModel ----------------------
761 
762 AuthenticatorClientPinTapAgainSheetModel::
AuthenticatorClientPinTapAgainSheetModel(AuthenticatorRequestDialogModel * dialog_model)763     AuthenticatorClientPinTapAgainSheetModel(
764         AuthenticatorRequestDialogModel* dialog_model)
765     : AuthenticatorSheetModelBase(dialog_model) {}
766 
767 AuthenticatorClientPinTapAgainSheetModel::
768     ~AuthenticatorClientPinTapAgainSheetModel() = default;
769 
IsActivityIndicatorVisible() const770 bool AuthenticatorClientPinTapAgainSheetModel::IsActivityIndicatorVisible()
771     const {
772   return true;
773 }
774 
775 const gfx::VectorIcon&
GetStepIllustration(ImageColorScheme color_scheme) const776 AuthenticatorClientPinTapAgainSheetModel::GetStepIllustration(
777     ImageColorScheme color_scheme) const {
778   return color_scheme == ImageColorScheme::kDark ? kWebauthnUsbDarkIcon
779                                                  : kWebauthnUsbIcon;
780 }
781 
GetStepTitle() const782 base::string16 AuthenticatorClientPinTapAgainSheetModel::GetStepTitle() const {
783   return l10n_util::GetStringFUTF16(IDS_WEBAUTHN_GENERIC_TITLE,
784                                     GetRelyingPartyIdString(dialog_model()));
785 }
786 
GetStepDescription() const787 base::string16 AuthenticatorClientPinTapAgainSheetModel::GetStepDescription()
788     const {
789   return l10n_util::GetStringUTF16(IDS_WEBAUTHN_PIN_TAP_AGAIN_DESCRIPTION);
790 }
791 
792 base::string16
GetAdditionalDescription() const793 AuthenticatorClientPinTapAgainSheetModel::GetAdditionalDescription() const {
794   return PossibleResidentKeyWarning(dialog_model());
795 }
796 
797 // AuthenticatorBioEnrollmentSheetModel ----------------------------------
798 
AuthenticatorBioEnrollmentSheetModel(AuthenticatorRequestDialogModel * dialog_model)799 AuthenticatorBioEnrollmentSheetModel::AuthenticatorBioEnrollmentSheetModel(
800     AuthenticatorRequestDialogModel* dialog_model)
801     : AuthenticatorSheetModelBase(dialog_model) {}
802 
803 AuthenticatorBioEnrollmentSheetModel::~AuthenticatorBioEnrollmentSheetModel() =
804     default;
805 
IsActivityIndicatorVisible() const806 bool AuthenticatorBioEnrollmentSheetModel::IsActivityIndicatorVisible() const {
807   return !IsAcceptButtonVisible();
808 }
809 
810 const gfx::VectorIcon&
GetStepIllustration(ImageColorScheme color_scheme) const811 AuthenticatorBioEnrollmentSheetModel::GetStepIllustration(
812     ImageColorScheme color_scheme) const {
813   return color_scheme == ImageColorScheme::kDark ? kWebauthnFingerprintDarkIcon
814                                                  : kWebauthnFingerprintIcon;
815 }
816 
GetStepTitle() const817 base::string16 AuthenticatorBioEnrollmentSheetModel::GetStepTitle() const {
818   return l10n_util::GetStringUTF16(
819       IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_ADD_TITLE);
820 }
821 
GetStepDescription() const822 base::string16 AuthenticatorBioEnrollmentSheetModel::GetStepDescription()
823     const {
824   return IsAcceptButtonVisible()
825              ? l10n_util::GetStringUTF16(
826                    IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_ENROLLING_COMPLETE_LABEL)
827              : l10n_util::GetStringUTF16(
828                    IDS_SETTINGS_SECURITY_KEYS_BIO_ENROLLMENT_ENROLLING_LABEL);
829 }
830 
IsAcceptButtonEnabled() const831 bool AuthenticatorBioEnrollmentSheetModel::IsAcceptButtonEnabled() const {
832   return true;
833 }
834 
IsAcceptButtonVisible() const835 bool AuthenticatorBioEnrollmentSheetModel::IsAcceptButtonVisible() const {
836   return dialog_model()->bio_samples_remaining() &&
837          dialog_model()->bio_samples_remaining() <= 0;
838 }
839 
GetAcceptButtonLabel() const840 base::string16 AuthenticatorBioEnrollmentSheetModel::GetAcceptButtonLabel()
841     const {
842   return l10n_util::GetStringUTF16(IDS_WEBAUTHN_PIN_ENTRY_NEXT);
843 }
844 
IsCancelButtonVisible() const845 bool AuthenticatorBioEnrollmentSheetModel::IsCancelButtonVisible() const {
846   return !IsAcceptButtonVisible();
847 }
848 
GetCancelButtonLabel() const849 base::string16 AuthenticatorBioEnrollmentSheetModel::GetCancelButtonLabel()
850     const {
851   return l10n_util::GetStringUTF16(IDS_WEBAUTHN_INLINE_ENROLLMENT_CANCEL_LABEL);
852 }
853 
OnAccept()854 void AuthenticatorBioEnrollmentSheetModel::OnAccept() {
855   dialog_model()->OnBioEnrollmentDone();
856 }
857 
OnCancel()858 void AuthenticatorBioEnrollmentSheetModel::OnCancel() {
859   OnAccept();
860 }
861 
862 // AuthenticatorRetryUvSheetModel -------------------------------------
863 
AuthenticatorRetryUvSheetModel(AuthenticatorRequestDialogModel * dialog_model)864 AuthenticatorRetryUvSheetModel::AuthenticatorRetryUvSheetModel(
865     AuthenticatorRequestDialogModel* dialog_model)
866     : AuthenticatorSheetModelBase(dialog_model) {}
867 
868 AuthenticatorRetryUvSheetModel::~AuthenticatorRetryUvSheetModel() = default;
869 
IsActivityIndicatorVisible() const870 bool AuthenticatorRetryUvSheetModel::IsActivityIndicatorVisible() const {
871   return true;
872 }
873 
GetStepIllustration(ImageColorScheme color_scheme) const874 const gfx::VectorIcon& AuthenticatorRetryUvSheetModel::GetStepIllustration(
875     ImageColorScheme color_scheme) const {
876   return color_scheme == ImageColorScheme::kDark ? kWebauthnFingerprintDarkIcon
877                                                  : kWebauthnFingerprintIcon;
878 }
879 
GetStepTitle() const880 base::string16 AuthenticatorRetryUvSheetModel::GetStepTitle() const {
881   return l10n_util::GetStringUTF16(IDS_WEBAUTHN_UV_RETRY_TITLE);
882 }
883 
GetStepDescription() const884 base::string16 AuthenticatorRetryUvSheetModel::GetStepDescription() const {
885   return l10n_util::GetStringUTF16(IDS_WEBAUTHN_UV_RETRY_DESCRIPTION);
886 }
887 
GetError() const888 base::string16 AuthenticatorRetryUvSheetModel::GetError() const {
889   int attempts = *dialog_model()->uv_attempts();
890   if (attempts > 3) {
891     return base::string16();
892   }
893   return l10n_util::GetPluralStringFUTF16(
894       IDS_WEBAUTHN_UV_RETRY_ERROR_FAILED_RETRIES, attempts);
895 }
896 
897 // AuthenticatorGenericErrorSheetModel -----------------------------------
898 
899 // static
900 std::unique_ptr<AuthenticatorGenericErrorSheetModel>
ForClientPinErrorSoftBlock(AuthenticatorRequestDialogModel * dialog_model)901 AuthenticatorGenericErrorSheetModel::ForClientPinErrorSoftBlock(
902     AuthenticatorRequestDialogModel* dialog_model) {
903   return base::WrapUnique(new AuthenticatorGenericErrorSheetModel(
904       dialog_model, l10n_util::GetStringUTF16(IDS_WEBAUTHN_ERROR_GENERIC_TITLE),
905       l10n_util::GetStringUTF16(
906           IDS_WEBAUTHN_CLIENT_PIN_SOFT_BLOCK_DESCRIPTION)));
907 }
908 
909 // static
910 std::unique_ptr<AuthenticatorGenericErrorSheetModel>
ForClientPinErrorHardBlock(AuthenticatorRequestDialogModel * dialog_model)911 AuthenticatorGenericErrorSheetModel::ForClientPinErrorHardBlock(
912     AuthenticatorRequestDialogModel* dialog_model) {
913   return base::WrapUnique(new AuthenticatorGenericErrorSheetModel(
914       dialog_model, l10n_util::GetStringUTF16(IDS_WEBAUTHN_ERROR_GENERIC_TITLE),
915       l10n_util::GetStringUTF16(
916           IDS_WEBAUTHN_CLIENT_PIN_HARD_BLOCK_DESCRIPTION)));
917 }
918 
919 // static
920 std::unique_ptr<AuthenticatorGenericErrorSheetModel>
ForClientPinErrorAuthenticatorRemoved(AuthenticatorRequestDialogModel * dialog_model)921 AuthenticatorGenericErrorSheetModel::ForClientPinErrorAuthenticatorRemoved(
922     AuthenticatorRequestDialogModel* dialog_model) {
923   return base::WrapUnique(new AuthenticatorGenericErrorSheetModel(
924       dialog_model, l10n_util::GetStringUTF16(IDS_WEBAUTHN_ERROR_GENERIC_TITLE),
925       l10n_util::GetStringUTF16(
926           IDS_WEBAUTHN_CLIENT_PIN_AUTHENTICATOR_REMOVED_DESCRIPTION)));
927 }
928 
929 // static
930 std::unique_ptr<AuthenticatorGenericErrorSheetModel>
ForMissingCapability(AuthenticatorRequestDialogModel * dialog_model)931 AuthenticatorGenericErrorSheetModel::ForMissingCapability(
932     AuthenticatorRequestDialogModel* dialog_model) {
933   return base::WrapUnique(new AuthenticatorGenericErrorSheetModel(
934       dialog_model,
935       l10n_util::GetStringUTF16(IDS_WEBAUTHN_ERROR_MISSING_CAPABILITY_TITLE),
936       l10n_util::GetStringFUTF16(IDS_WEBAUTHN_ERROR_MISSING_CAPABILITY_DESC,
937                                  GetRelyingPartyIdString(dialog_model))));
938 }
939 
940 // static
941 std::unique_ptr<AuthenticatorGenericErrorSheetModel>
ForStorageFull(AuthenticatorRequestDialogModel * dialog_model)942 AuthenticatorGenericErrorSheetModel::ForStorageFull(
943     AuthenticatorRequestDialogModel* dialog_model) {
944   return base::WrapUnique(new AuthenticatorGenericErrorSheetModel(
945       dialog_model,
946       l10n_util::GetStringUTF16(IDS_WEBAUTHN_ERROR_MISSING_CAPABILITY_TITLE),
947       l10n_util::GetStringUTF16(IDS_WEBAUTHN_STORAGE_FULL_DESC)));
948 }
949 
AuthenticatorGenericErrorSheetModel(AuthenticatorRequestDialogModel * dialog_model,base::string16 title,base::string16 description)950 AuthenticatorGenericErrorSheetModel::AuthenticatorGenericErrorSheetModel(
951     AuthenticatorRequestDialogModel* dialog_model,
952     base::string16 title,
953     base::string16 description)
954     : AuthenticatorSheetModelBase(dialog_model),
955       title_(std::move(title)),
956       description_(std::move(description)) {}
957 
IsBackButtonVisible() const958 bool AuthenticatorGenericErrorSheetModel::IsBackButtonVisible() const {
959   return false;
960 }
961 
GetCancelButtonLabel() const962 base::string16 AuthenticatorGenericErrorSheetModel::GetCancelButtonLabel()
963     const {
964   return l10n_util::GetStringUTF16(IDS_CLOSE);
965 }
966 
GetStepIllustration(ImageColorScheme color_scheme) const967 const gfx::VectorIcon& AuthenticatorGenericErrorSheetModel::GetStepIllustration(
968     ImageColorScheme color_scheme) const {
969   return color_scheme == ImageColorScheme::kDark ? kWebauthnErrorDarkIcon
970                                                  : kWebauthnErrorIcon;
971 }
972 
GetStepTitle() const973 base::string16 AuthenticatorGenericErrorSheetModel::GetStepTitle() const {
974   return title_;
975 }
976 
GetStepDescription() const977 base::string16 AuthenticatorGenericErrorSheetModel::GetStepDescription() const {
978   return description_;
979 }
980 
981 // AuthenticatorResidentCredentialConfirmationSheetView -----------------------
982 
983 AuthenticatorResidentCredentialConfirmationSheetView::
AuthenticatorResidentCredentialConfirmationSheetView(AuthenticatorRequestDialogModel * dialog_model)984     AuthenticatorResidentCredentialConfirmationSheetView(
985         AuthenticatorRequestDialogModel* dialog_model)
986     : AuthenticatorSheetModelBase(dialog_model) {}
987 
988 AuthenticatorResidentCredentialConfirmationSheetView::
989     ~AuthenticatorResidentCredentialConfirmationSheetView() = default;
990 
991 const gfx::VectorIcon&
GetStepIllustration(ImageColorScheme color_scheme) const992 AuthenticatorResidentCredentialConfirmationSheetView::GetStepIllustration(
993     ImageColorScheme color_scheme) const {
994   return color_scheme == ImageColorScheme::kDark ? kWebauthnPermissionDarkIcon
995                                                  : kWebauthnPermissionIcon;
996 }
997 
IsBackButtonVisible() const998 bool AuthenticatorResidentCredentialConfirmationSheetView::IsBackButtonVisible()
999     const {
1000   return false;
1001 }
1002 
1003 bool AuthenticatorResidentCredentialConfirmationSheetView::
IsAcceptButtonVisible() const1004     IsAcceptButtonVisible() const {
1005   return true;
1006 }
1007 
1008 bool AuthenticatorResidentCredentialConfirmationSheetView::
IsAcceptButtonEnabled() const1009     IsAcceptButtonEnabled() const {
1010   return true;
1011 }
1012 
1013 base::string16
GetAcceptButtonLabel() const1014 AuthenticatorResidentCredentialConfirmationSheetView::GetAcceptButtonLabel()
1015     const {
1016   return l10n_util::GetStringUTF16(IDS_WEBAUTHN_WELCOME_SCREEN_NEXT);
1017 }
1018 
1019 base::string16
GetStepTitle() const1020 AuthenticatorResidentCredentialConfirmationSheetView::GetStepTitle() const {
1021   return l10n_util::GetStringFUTF16(IDS_WEBAUTHN_GENERIC_TITLE,
1022                                     GetRelyingPartyIdString(dialog_model()));
1023 }
1024 
1025 base::string16
GetStepDescription() const1026 AuthenticatorResidentCredentialConfirmationSheetView::GetStepDescription()
1027     const {
1028   return l10n_util::GetStringUTF16(IDS_WEBAUTHN_RESIDENT_KEY_PRIVACY);
1029 }
1030 
OnAccept()1031 void AuthenticatorResidentCredentialConfirmationSheetView::OnAccept() {
1032   dialog_model()->OnResidentCredentialConfirmed();
1033 }
1034 
1035 // AuthenticatorSelectAccountSheetModel ---------------------------------------
1036 
AuthenticatorSelectAccountSheetModel(AuthenticatorRequestDialogModel * dialog_model)1037 AuthenticatorSelectAccountSheetModel::AuthenticatorSelectAccountSheetModel(
1038     AuthenticatorRequestDialogModel* dialog_model)
1039     : AuthenticatorSheetModelBase(dialog_model) {}
1040 
1041 AuthenticatorSelectAccountSheetModel::~AuthenticatorSelectAccountSheetModel() =
1042     default;
1043 
SetCurrentSelection(int selected)1044 void AuthenticatorSelectAccountSheetModel::SetCurrentSelection(int selected) {
1045   DCHECK_LE(0, selected);
1046   DCHECK_LT(static_cast<size_t>(selected), dialog_model()->responses().size());
1047   selected_ = selected;
1048 }
1049 
OnAccept()1050 void AuthenticatorSelectAccountSheetModel::OnAccept() {
1051   dialog_model()->OnAccountSelected(selected_);
1052 }
1053 
1054 const gfx::VectorIcon&
GetStepIllustration(ImageColorScheme color_scheme) const1055 AuthenticatorSelectAccountSheetModel::GetStepIllustration(
1056     ImageColorScheme color_scheme) const {
1057   // TODO: this is likely the wrong image.
1058   return color_scheme == ImageColorScheme::kDark ? kWebauthnWelcomeDarkIcon
1059                                                  : kWebauthnWelcomeIcon;
1060 }
1061 
GetStepTitle() const1062 base::string16 AuthenticatorSelectAccountSheetModel::GetStepTitle() const {
1063   return l10n_util::GetStringUTF16(IDS_WEBAUTHN_SELECT_ACCOUNT);
1064 }
1065 
GetStepDescription() const1066 base::string16 AuthenticatorSelectAccountSheetModel::GetStepDescription()
1067     const {
1068   return base::string16();
1069 }
1070 
IsAcceptButtonVisible() const1071 bool AuthenticatorSelectAccountSheetModel::IsAcceptButtonVisible() const {
1072   return false;
1073 }
1074 
IsAcceptButtonEnabled() const1075 bool AuthenticatorSelectAccountSheetModel::IsAcceptButtonEnabled() const {
1076   return false;
1077 }
1078 
GetAcceptButtonLabel() const1079 base::string16 AuthenticatorSelectAccountSheetModel::GetAcceptButtonLabel()
1080     const {
1081   return l10n_util::GetStringUTF16(IDS_WEBAUTHN_WELCOME_SCREEN_NEXT);
1082 }
1083 
1084 // AttestationPermissionRequestSheetModel -------------------------------------
1085 
AttestationPermissionRequestSheetModel(AuthenticatorRequestDialogModel * dialog_model)1086 AttestationPermissionRequestSheetModel::AttestationPermissionRequestSheetModel(
1087     AuthenticatorRequestDialogModel* dialog_model)
1088     : AuthenticatorSheetModelBase(dialog_model) {}
1089 
1090 AttestationPermissionRequestSheetModel::
1091     ~AttestationPermissionRequestSheetModel() = default;
1092 
OnAccept()1093 void AttestationPermissionRequestSheetModel::OnAccept() {
1094   dialog_model()->OnAttestationPermissionResponse(true);
1095 }
1096 
OnCancel()1097 void AttestationPermissionRequestSheetModel::OnCancel() {
1098   dialog_model()->OnAttestationPermissionResponse(false);
1099 }
1100 
1101 const gfx::VectorIcon&
GetStepIllustration(ImageColorScheme color_scheme) const1102 AttestationPermissionRequestSheetModel::GetStepIllustration(
1103     ImageColorScheme color_scheme) const {
1104   return color_scheme == ImageColorScheme::kDark ? kWebauthnPermissionDarkIcon
1105                                                  : kWebauthnPermissionIcon;
1106 }
1107 
GetStepTitle() const1108 base::string16 AttestationPermissionRequestSheetModel::GetStepTitle() const {
1109   return l10n_util::GetStringUTF16(
1110       IDS_WEBAUTHN_REQUEST_ATTESTATION_PERMISSION_TITLE);
1111 }
1112 
GetStepDescription() const1113 base::string16 AttestationPermissionRequestSheetModel::GetStepDescription()
1114     const {
1115   return l10n_util::GetStringFUTF16(
1116       IDS_WEBAUTHN_REQUEST_ATTESTATION_PERMISSION_DESC,
1117       GetRelyingPartyIdString(dialog_model()));
1118 }
1119 
IsBackButtonVisible() const1120 bool AttestationPermissionRequestSheetModel::IsBackButtonVisible() const {
1121   return false;
1122 }
1123 
IsAcceptButtonVisible() const1124 bool AttestationPermissionRequestSheetModel::IsAcceptButtonVisible() const {
1125   return true;
1126 }
1127 
IsAcceptButtonEnabled() const1128 bool AttestationPermissionRequestSheetModel::IsAcceptButtonEnabled() const {
1129   return true;
1130 }
1131 
GetAcceptButtonLabel() const1132 base::string16 AttestationPermissionRequestSheetModel::GetAcceptButtonLabel()
1133     const {
1134   return l10n_util::GetStringUTF16(IDS_WEBAUTHN_ALLOW_ATTESTATION);
1135 }
1136 
IsCancelButtonVisible() const1137 bool AttestationPermissionRequestSheetModel::IsCancelButtonVisible() const {
1138   return true;
1139 }
1140 
GetCancelButtonLabel() const1141 base::string16 AttestationPermissionRequestSheetModel::GetCancelButtonLabel()
1142     const {
1143   // TODO(martinkr): This should be its own string definition; but we had to
1144   // make a change post string freeze and therefore reused this.
1145   return l10n_util::GetStringUTF16(IDS_PERMISSION_DENY);
1146 }
1147 
1148 // AuthenticatorQRSheetModel --------------------------------------------------
1149 
AuthenticatorQRSheetModel(AuthenticatorRequestDialogModel * dialog_model)1150 AuthenticatorQRSheetModel::AuthenticatorQRSheetModel(
1151     AuthenticatorRequestDialogModel* dialog_model)
1152     : AuthenticatorSheetModelBase(dialog_model) {}
1153 
1154 AuthenticatorQRSheetModel::~AuthenticatorQRSheetModel() = default;
1155 
GetStepIllustration(ImageColorScheme color_scheme) const1156 const gfx::VectorIcon& AuthenticatorQRSheetModel::GetStepIllustration(
1157     ImageColorScheme color_scheme) const {
1158   return color_scheme == ImageColorScheme::kDark ? kWebauthnPhoneDarkIcon
1159                                                  : kWebauthnPhoneIcon;
1160 }
1161 
GetStepTitle() const1162 base::string16 AuthenticatorQRSheetModel::GetStepTitle() const {
1163   return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CABLE_QR_TITLE);
1164 }
1165 
GetStepDescription() const1166 base::string16 AuthenticatorQRSheetModel::GetStepDescription() const {
1167   return l10n_util::GetStringUTF16(IDS_WEBAUTHN_CABLE_QR_DESCRIPTION);
1168 }
1169