File: chrome_webauthn_credentials_delegate.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 (142 lines) | stat: -rw-r--r-- 5,722 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
// Copyright 2021 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_PASSWORD_MANAGER_CHROME_WEBAUTHN_CREDENTIALS_DELEGATE_H_
#define CHROME_BROWSER_PASSWORD_MANAGER_CHROME_WEBAUTHN_CREDENTIALS_DELEGATE_H_

#include <optional>

#include "base/functional/callback.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observation.h"
#include "base/timer/timer.h"
#include "base/types/expected.h"
#include "base/types/strong_alias.h"
#include "build/build_config.h"
#include "components/password_manager/core/browser/passkey_credential.h"
#include "components/password_manager/core/browser/webauthn_credentials_delegate.h"

#if !BUILDFLAG(IS_ANDROID)
#include "chrome/browser/webauthn/authenticator_request_dialog_model.h"
#endif  // !BUILDFLAG(IS_ANDROID)

namespace base {
class ElapsedTimer;
}

namespace content {
class WebContents;
}

// Chrome implementation of WebAuthnCredentialsDelegate.
class ChromeWebAuthnCredentialsDelegate final :
#if !BUILDFLAG(IS_ANDROID)
    public AuthenticatorRequestDialogModel::Observer,
#endif  //! BUILDFLAG(IS_ANDROID)
    public password_manager::WebAuthnCredentialsDelegate {
 public:
  using SecurityKeyOrHybridFlowAvailable =
      base::StrongAlias<struct SecurityKeyOrHybridFlowAvailableTag, bool>;

  explicit ChromeWebAuthnCredentialsDelegate(
      content::WebContents* web_contents);
  ~ChromeWebAuthnCredentialsDelegate() override;
  ChromeWebAuthnCredentialsDelegate(const ChromeWebAuthnCredentialsDelegate&) =
      delete;
  ChromeWebAuthnCredentialsDelegate operator=(
      const ChromeWebAuthnCredentialsDelegate&) = delete;

  // password_manager::WebAuthnCredentialsDelegate:
  void LaunchSecurityKeyOrHybridFlow() override;
  void SelectPasskey(
      const std::string& backend_id,
      password_manager::WebAuthnCredentialsDelegate::OnPasskeySelectedCallback
          callback) override;
  base::expected<const std::vector<password_manager::PasskeyCredential>*,
                 PasskeysUnavailableReason>
  GetPasskeys() const override;
  void NotifyForPasskeysDisplay() override;
  bool IsSecurityKeyOrHybridFlowAvailable() const override;
  void RequestNotificationWhenPasskeysReady(
      base::OnceClosure callback) override;
  bool HasPendingPasskeySelection() override;
  base::WeakPtr<WebAuthnCredentialsDelegate> AsWeakPtr() override;

#if !BUILDFLAG(IS_ANDROID)
  // AuthenticatorRequestDialogModel::Observer:
  void OnStepTransition() override;
#endif  // !BUILDFLAG(IS_ANDROID)

  // Method for providing a list of WebAuthn user entities that can be provided
  // as autofill suggestions. This is called when a WebAuthn Conditional UI
  // request is received. The `security_key_or_hybrid_flow_available`
  // argument determines whether an autofill option to use a passkey from
  // another device should be offered.
  void OnCredentialsReceived(
      std::vector<password_manager::PasskeyCredential> credentials,
      SecurityKeyOrHybridFlowAvailable security_key_or_hybrid_flow_available);

  // Lets the delegate know that a WebAuthn request has been aborted, and so
  // WebAuthn options should no longer show up on the autofill popup.
  void NotifyWebAuthnRequestAborted();

 protected:
  const raw_ptr<content::WebContents> web_contents_;

 private:
  void RecordPasskeyRetrievalDelay();
  void NotifyClientsOfPasskeyAvailability();

  // List of passkeys populated from authenticators. It is returned to the
  // client via GetPasskeys. |passkeys_| is nullopt until populated by a
  // WebAuthn request.
  std::optional<std::vector<password_manager::PasskeyCredential>> passkeys_;

  // TODO(crbug.com/368283817): Check if this is required. While
  // SecurityKeyOrHybridFlowAvailable flows are always available on desktop
  // platforms, they still require a conditional request from the RP.
  SecurityKeyOrHybridFlowAvailable security_key_or_hybrid_flow_available_ =
#if !BUILDFLAG(IS_ANDROID)
      SecurityKeyOrHybridFlowAvailable(true);
#else
      SecurityKeyOrHybridFlowAvailable(false);
#endif  // !BUILDFLAG(IS_ANDROID)

  std::vector<base::OnceClosure> passkeys_available_callbacks_;
  std::unique_ptr<base::ElapsedTimer> passkey_retrieval_timer_;

#if !BUILDFLAG(IS_ANDROID)
  // Callback to be run to dismiss the autofill popup. The popup will be shown
  // while the observed model displays no UI or until the request is completed.
  OnPasskeySelectedCallback passkey_selected_callback_;
  base::ScopedObservation<AuthenticatorRequestDialogModel,
                          AuthenticatorRequestDialogModel::Observer>
      authenticator_observation_{this};
  base::OneShotTimer flickering_timer_;
#endif  // !BUILDFLAG(IS_ANDROID)

  // Set to true when an autofill surface that could have contained passkeys
  // has been displayed for the current page. Used for the
  // PasskeysArrivedAfterAutofillDisplay metric.
  bool passkey_display_has_happened_ = false;

  // Set to true when the PasskeysArrivedAfterAutofillDisplay metric has been
  // recorded.
  bool passkeys_after_fill_recorded_ = false;

  // Set to true when the timer for the PasskeyRetrievalWaitDuration metric has
  // been started, since we only want to use it once.
  bool passkey_retrieval_timer_started_ = false;

  // Set when `NotifyWebAuthnRequestAborted` has been called. It is reset if
  // passkeys are provided again after that, indicating that an additional
  // request has been made.
  bool last_request_was_aborted_ = false;

  base::WeakPtrFactory<ChromeWebAuthnCredentialsDelegate> weak_ptr_factory_{
      this};
};

#endif  // CHROME_BROWSER_PASSWORD_MANAGER_CHROME_WEBAUTHN_CREDENTIALS_DELEGATE_H_