1 // Copyright 2020 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 "ash/login/security_token_request_controller.h"
6
7 #include <utility>
8
9 #include "ash/login/ui/pin_request_widget.h"
10 #include "ash/public/cpp/login_types.h"
11 #include "ash/strings/grit/ash_strings.h"
12 #include "base/bind.h"
13 #include "base/i18n/number_formatting.h"
14 #include "base/strings/string16.h"
15 #include "chromeos/components/security_token_pin/error_generator.h"
16 #include "ui/base/l10n/l10n_util.h"
17
18 namespace ash {
19
20 namespace {
21
GetTitle()22 base::string16 GetTitle() {
23 return l10n_util::GetStringUTF16(
24 IDS_ASH_LOGIN_SECURITY_TOKEN_REQUEST_DIALOG_TITLE);
25 }
26
GetDescription()27 base::string16 GetDescription() {
28 return l10n_util::GetStringUTF16(
29 IDS_ASH_LOGIN_SECURITY_TOKEN_REQUEST_DIALOG_DESCRIPTION);
30 }
31
GetAccessibleTitle()32 base::string16 GetAccessibleTitle() {
33 return l10n_util::GetStringUTF16(
34 IDS_ASH_LOGIN_SECURITY_TOKEN_REQUEST_DIALOG_TITLE);
35 }
36
37 } // namespace
38
39 SecurityTokenRequestController::SecurityTokenRequestController() = default;
40
~SecurityTokenRequestController()41 SecurityTokenRequestController::~SecurityTokenRequestController() {
42 ClosePinUi();
43 }
44
ResetRequestCanceled()45 void SecurityTokenRequestController::ResetRequestCanceled() {
46 request_canceled_ = false;
47 }
48
OnPinSubmitted(const std::string & code)49 PinRequestView::SubmissionResult SecurityTokenRequestController::OnPinSubmitted(
50 const std::string& code) {
51 if (!on_pin_submitted_.is_null()) {
52 std::move(on_pin_submitted_).Run(code);
53 }
54 return PinRequestView::SubmissionResult::kSubmitPending;
55 }
56
OnBack()57 void SecurityTokenRequestController::OnBack() {
58 request_canceled_ = true;
59 if (!on_canceled_by_user_.is_null()) {
60 std::move(on_canceled_by_user_).Run();
61 }
62 ClosePinUi();
63 }
64
OnHelp(gfx::NativeWindow parent_window)65 void SecurityTokenRequestController::OnHelp(gfx::NativeWindow parent_window) {
66 NOTREACHED();
67 }
68
SetPinUiState(SecurityTokenPinRequest request)69 bool SecurityTokenRequestController::SetPinUiState(
70 SecurityTokenPinRequest request) {
71 // Unable to request a PIN while the PinRequestWidget is already used for
72 // something that is not a SecurityTokenPinRequest.
73 // Also deny the request when the user has just canceled another request: For
74 // example, logging in with smart cards usually requires two requests for the
75 // same PIN. When the user has canceled the first one, we do not show another
76 // right afterwards.
77 if ((PinRequestWidget::Get() && !security_token_request_in_progress_) ||
78 request_canceled_) {
79 std::move(request.pin_ui_closed_callback).Run();
80 return false;
81 }
82
83 on_pin_submitted_ = std::move(request.pin_entered_callback);
84 on_canceled_by_user_ = std::move(request.pin_ui_closed_callback);
85
86 // If this is a new request, open a PIN widget. Otherwise, just update the
87 // existing widget.
88 if (!security_token_request_in_progress_) {
89 security_token_request_in_progress_ = true;
90 PinRequest pin_request;
91 pin_request.on_pin_request_done = base::DoNothing::Once<bool>();
92 pin_request.pin_keyboard_always_enabled = true;
93 pin_request.extra_dimmer = true;
94 pin_request.title = GetTitle();
95 pin_request.description = GetDescription();
96 pin_request.accessible_title = GetAccessibleTitle();
97 PinRequestWidget::Show(std::move(pin_request), this);
98 }
99
100 PinRequestWidget::Get()->ClearInput();
101 PinRequestWidget::Get()->SetPinInputEnabled(request.enable_user_input);
102
103 if (request.error_label == chromeos::security_token_pin::ErrorLabel::kNone) {
104 PinRequestWidget::Get()->UpdateState(PinRequestViewState::kNormal,
105 GetTitle(), GetDescription());
106 } else {
107 PinRequestWidget::Get()->UpdateState(
108 PinRequestViewState::kError,
109 /*title=*/
110 chromeos::security_token_pin::GenerateErrorMessage(
111 request.error_label, request.attempts_left,
112 request.enable_user_input),
113 /*description=*/base::string16());
114 }
115 return true;
116 }
117
ClosePinUi()118 void SecurityTokenRequestController::ClosePinUi() {
119 if (!security_token_request_in_progress_)
120 return;
121
122 if (PinRequestWidget::Get()) {
123 PinRequestWidget::Get()->Close(false); // Parameter will be ignored.
124 }
125 on_pin_submitted_.Reset();
126 on_canceled_by_user_.Reset();
127 security_token_request_in_progress_ = false;
128 }
129
130 } // namespace ash
131