File: pin_dialog_manager.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (207 lines) | stat: -rw-r--r-- 8,738 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_CERTIFICATE_PROVIDER_PIN_DIALOG_MANAGER_H_
#define CHROME_BROWSER_CERTIFICATE_PROVIDER_PIN_DIALOG_MANAGER_H_

#include <map>
#include <optional>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "chrome/browser/certificate_provider/security_token_pin_dialog_host.h"
#include "chrome/browser/certificate_provider/security_token_pin_dialog_host_popup_impl.h"
#include "chromeos/components/security_token_pin/constants.h"
#include "components/account_id/account_id.h"

namespace chromeos {

// Manages the state of the dialog that requests the PIN from user. Used by the
// extensions that need to request the PIN. Implemented as requirement for
// crbug.com/612886
class PinDialogManager final {
 public:
  enum class RequestPinResult {
    kSuccess,
    kInvalidId,
    kOtherFlowInProgress,
    kDialogDisplayedAlready,
  };

  enum class StopPinRequestResult {
    kSuccess,
    kNoActiveDialog,
    kNoUserInput,
  };

  using RequestPinCallback =
      base::OnceCallback<void(const std::string& user_input)>;
  using StopPinRequestCallback = base::OnceClosure;

  PinDialogManager();
  PinDialogManager(const PinDialogManager&) = delete;
  PinDialogManager& operator=(const PinDialogManager&) = delete;
  ~PinDialogManager();

  // Stores internally the |signRequestId| along with current timestamp.
  void AddSignRequestId(
      const std::string& extension_id,
      int sign_request_id,
      const std::optional<AccountId>& authenticating_user_account_id);

  // Removes the specified sign request, aborting both the current and the
  // future PIN dialogs related to it.
  void RemoveSignRequest(const std::string& extension_id, int sign_request_id);

  // Returns the number of pending sign requests stored in sign_requests_
  int StoredSignRequestsForTesting() const;

  // Creates and displays a new PIN dialog, or reuses the old dialog with just
  // updating the parameters if active one exists.
  // |extension_id| - the ID of the extension requesting the dialog.
  // |extension_name| - the name of the extension requesting the dialog.
  // |sign_request_id| - the ID given by Chrome when the extension was asked to
  //     sign the data. It should be a valid, not expired ID at the time the
  //     extension is requesting PIN the first time.
  // |code_type| - the type of input requested: either "PIN" or "PUK".
  // |error_label| - the error template to be displayed inside the dialog. If
  //     |kNone|, no error is displayed.
  // |attempts_left| - the number of attempts the user has to try the code. It
  //     is informational only, and enforced on Chrome side only in case it's
  //     zero. In that case the textfield is disabled and the user can't provide
  //     any input to extension. If -1 the textfield from the dialog is enabled
  //     but no information about the attepts left is not given to the user.
  // |callback| - used to notify about the user input in the text_field from the
  //     dialog.
  // Returns |kSuccess| if the dialog is displayed and extension owns it.
  // Otherwise the specific error is returned.
  RequestPinResult RequestPin(const std::string& extension_id,
                              const std::string& extension_name,
                              int sign_request_id,
                              security_token_pin::CodeType code_type,
                              security_token_pin::ErrorLabel error_label,
                              int attempts_left,
                              RequestPinCallback callback);

  // Updates the existing dialog with the error message. Returns whether the
  // provided |extension_id| matches the extension owning the active dialog.
  // When it is, the |callback| will be executed once the UI is completed (e.g.,
  // the dialog with the error message is closed by the user).
  StopPinRequestResult StopPinRequestWithError(
      const std::string& extension_id,
      security_token_pin::ErrorLabel error_label,
      StopPinRequestCallback callback);

  // Returns whether the last PIN dialog from this extension was closed by the
  // user.
  bool LastPinDialogClosed(const std::string& extension_id) const;

  // Called when extension calls the stopPinRequest method. The active dialog is
  // closed if the |extension_id| matches the |active_dialog_extension_id_|.
  // Returns whether the dialog was closed.
  bool CloseDialog(const std::string& extension_id);

  // Resets the manager data related to the extension.
  void ExtensionUnloaded(const std::string& extension_id);

  // Dynamically adds the dialog host that can be used by this instance for
  // showing new dialogs. There may be multiple hosts added, in which case the
  // most recently added is used. Before any hosts have been added, the default
  // (popup-based) host is used.
  void AddPinDialogHost(SecurityTokenPinDialogHost* pin_dialog_host);
  // Removes the previously added dialog host. If a dialog is still opened in
  // this host, closes it beforehand.
  void RemovePinDialogHost(SecurityTokenPinDialogHost* pin_dialog_host);

  SecurityTokenPinDialogHostPopupImpl* default_dialog_host_for_testing() {
    return &default_dialog_host_;
  }

 private:
  struct SignRequestState {
    SignRequestState(
        base::Time begin_time,
        const std::optional<AccountId>& authenticating_user_account_id);
    SignRequestState(const SignRequestState&);
    SignRequestState& operator=(const SignRequestState&);
    ~SignRequestState();

    base::Time begin_time;
    std::optional<AccountId> authenticating_user_account_id;
  };

  // Holds information related to the currently opened PIN dialog.
  struct ActiveDialogState {
    ActiveDialogState(SecurityTokenPinDialogHost* host,
                      const std::string& extension_id,
                      const std::string& extension_name,
                      int sign_request_id,
                      security_token_pin::CodeType code_type);
    ~ActiveDialogState();

    // Remember the host that was used to open the active dialog, as new hosts
    // could have been added since the dialog was opened, but we want to
    // continue calling the same host when dealing with the same active dialog.
    const raw_ptr<SecurityTokenPinDialogHost> host;

    const std::string extension_id;
    const std::string extension_name;
    const int sign_request_id;
    const security_token_pin::CodeType code_type;
    RequestPinCallback request_pin_callback;
    StopPinRequestCallback stop_pin_request_callback;
  };

  using ExtensionNameRequestIdPair = std::pair<std::string, int>;

  // Returns the sign request state for the given key, or null if not found.
  SignRequestState* FindSignRequestState(const std::string& extension_id,
                                         int sign_request_id);

  // The callback that gets invoked once the user sends some input into the PIN
  // dialog.
  void OnPinEntered(const std::string& user_input);
  // The callback that gets invoked once the PIN dialog gets closed.
  void OnPinDialogClosed();

  // Returns the dialog host that should own the new dialog. Currently returns
  // the most recently added dialog host (falling back to the default one when
  // no host has been added).
  SecurityTokenPinDialogHost* GetHostForNewDialog();

  // Closes the active dialog, if there's any, and runs the necessary callbacks.
  void CloseActiveDialog();

  // Tells whether user closed the last request PIN dialog issued by an
  // extension. The extension_id is the key and value is true if user closed the
  // dialog. Used to determine if the limit of dialogs rejected by the user has
  // been exceeded.
  std::unordered_map<std::string, bool> last_response_closed_;

  // The map from extension_id and an active sign request id to the state of the
  // request.
  std::map<ExtensionNameRequestIdPair, SignRequestState> sign_requests_;

  SecurityTokenPinDialogHostPopupImpl default_dialog_host_;
  // The list of dynamically added dialog hosts, in the same order as they were
  // added.
  std::vector<raw_ptr<SecurityTokenPinDialogHost, VectorExperimental>>
      added_dialog_hosts_;

  // There can be only one active dialog to request the PIN at any point of
  // time.
  std::optional<ActiveDialogState> active_dialog_state_;

  base::WeakPtrFactory<PinDialogManager> weak_factory_{this};
};

}  // namespace chromeos

#endif  // CHROME_BROWSER_CERTIFICATE_PROVIDER_PIN_DIALOG_MANAGER_H_