| // Copyright 2024 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_WEBAUTHN_AUTHENTICATOR_REQUEST_DIALOG_CONTROLLER_H_ |
| #define CHROME_BROWSER_WEBAUTHN_AUTHENTICATOR_REQUEST_DIALOG_CONTROLLER_H_ |
| |
| #include <cstdint> |
| #include <memory> |
| #include <optional> |
| #include <string> |
| #include <vector> |
| |
| #include "base/functional/callback_forward.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/memory/weak_ptr.h" |
| #include "base/scoped_observation.h" |
| #include "base/timer/timer.h" |
| #include "chrome/browser/ui/webauthn/passkey_upgrade_request_controller.h" |
| #include "chrome/browser/webauthn/authenticator_reference.h" |
| #include "chrome/browser/webauthn/authenticator_request_dialog_model.h" |
| #include "chrome/browser/webauthn/authenticator_transport.h" |
| #include "chrome/browser/webauthn/observable_authenticator_list.h" |
| #include "chrome/browser/webauthn/password_credential_controller.h" |
| #include "components/webauthn/core/browser/passkey_model.h" |
| #include "components/webauthn/core/browser/passkey_model_change.h" |
| #include "content/public/browser/authenticator_request_client_delegate.h" |
| #include "content/public/browser/global_routing_id.h" |
| #include "third_party/blink/public/mojom/credentialmanagement/credential_type_flags.mojom.h" |
| #include "url/gurl.h" |
| |
| class ChallengeUrlFetcher; |
| class PasskeyUpgradeRequestController; |
| class Profile; |
| |
| namespace content { |
| class RenderFrameHost; |
| } // namespace content |
| |
| // Encapsulates the logic behind the WebAuthn UI flow. |
| // flow. This is essentially a state machine going through the states defined in |
| // the `Step` enumeration. |
| class AuthenticatorRequestDialogController |
| : public AuthenticatorRequestDialogModel::Observer, |
| public webauthn::PasskeyModel::Observer, |
| public PasskeyUpgradeRequestController::Delegate { |
| public: |
| using RequestCallback = device::FidoRequestHandlerBase::RequestCallback; |
| using BlePermissionCallback = base::RepeatingCallback<void( |
| device::FidoRequestHandlerBase::BlePermissionCallback)>; |
| using EnclaveRequestCallback = base::RepeatingCallback<void( |
| std::unique_ptr<device::enclave::CredentialRequest>)>; |
| |
| AuthenticatorRequestDialogController( |
| AuthenticatorRequestDialogModel* model, |
| content::RenderFrameHost* render_frame_host); |
| |
| AuthenticatorRequestDialogController( |
| const AuthenticatorRequestDialogController&) = delete; |
| AuthenticatorRequestDialogController& operator=( |
| const AuthenticatorRequestDialogController&) = delete; |
| |
| ~AuthenticatorRequestDialogController() override; |
| |
| AuthenticatorRequestDialogModel* model() const; |
| |
| // AuthenticatorRequestDialogModel::Observer: |
| void OnModelDestroyed(AuthenticatorRequestDialogModel* model) override; |
| void StartOver() override; |
| void OnCreatePasskeyAccepted() override; |
| void OnRecoverSecurityDomainClosed() override; |
| void ContinueWithFlowAfterBleAdapterPowered() override; |
| void PowerOnBleAdapter() override; |
| void OpenBlePreferences() override; |
| void OnOffTheRecordInterstitialAccepted() override; |
| void CancelAuthenticatorRequest() override; |
| void OnRequestComplete() override; |
| void OnResidentCredentialConfirmed() override; |
| void OnHavePIN(std::u16string pin) override; |
| void EnclaveEnabledStatusChanged(EnclaveEnabledStatus status) override; |
| void OnAccountSelected(size_t index) override; |
| void OnAccountPreselectedIndex(size_t index) override; |
| void OnBioEnrollmentDone() override; |
| void OnUserConfirmedPriorityMechanism() override; |
| |
| // webauthn::PasskeyModel::Observer: |
| void OnPasskeysChanged( |
| const std::vector<webauthn::PasskeyModelChange>& changes) override; |
| void OnPasskeyModelShuttingDown() override; |
| void OnPasskeyModelIsReady(bool is_ready) override; |
| |
| // PasskeyUpgradeRequestController::Delegate: |
| void PasskeyUpgradeSucceeded() override; |
| void PasskeyUpgradeFailed() override; |
| |
| // Hides the dialog. A subsequent call to SetCurrentStep() will unhide it. |
| void HideDialog(); |
| |
| // Returns whether the UI is in a state at which the |request_| member of |
| // AuthenticatorImpl has completed processing. Note that the request callback |
| // is only resolved after the UI is dismissed. |
| bool is_request_complete() const; |
| |
| // Starts the UX flow, by either showing the transport or password selection |
| // screen or the guided flow for the most likely transport. |
| // |
| // Valid action when at step: kNotStarted. |
| void StartFlow(device::FidoRequestHandlerBase::TransportAvailabilityInfo |
| transport_availability, |
| PasswordCredentialController::PasswordCredentials passwords); |
| |
| // Starts a modal WebAuthn flow (i.e. what you normally get if you call |
| // WebAuthn with no mediation parameter) from a conditional request. |
| // |
| // Valid action when at step: kPasskeyAutofill. |
| void TransitionToModalWebAuthnRequest(); |
| |
| // Starts the UX flow. Tries to figure out the most likely transport to be |
| // used, and starts the guided flow for that transport; or shows the manual |
| // transport selection screen if the transport could not be uniquely |
| // identified. |
| // |
| // Valid action when at step: kNotStarted. |
| void StartGuidedFlowForMostLikelyTransportOrShowMechanismSelection(); |
| |
| bool StartGuidedFlowForHint(AuthenticatorTransport transport); |
| |
| // Proceeds straight to the platform authenticator prompt. If `type` is |
| // `nullopt` then it actives the default platform authenticator. Otherwise it |
| // actives the platform authenticator of the given type. |
| void HideDialogAndDispatchToPlatformAuthenticator( |
| std::optional<device::AuthenticatorType> type = std::nullopt); |
| |
| // Called when some caBLE event (e.g. receiving a BLE message, connecting to |
| // the tunnel server, etc) happens. |
| void OnCableEvent(device::cablev2::Event event); |
| |
| // Called when `cable_connecting_sheet_timer_` completes. |
| void OnCableConnectingTimerComplete(); |
| |
| // StartPhonePairing triggers the display of a QR code for pairing a new |
| // phone. |
| void StartPhonePairing(); |
| |
| // Ensures that the Bluetooth adapter is powered before executing |action|. |
| // -- If the adapter is powered, run |action| directly. |
| // -- If Chrome does not have Bluetooth permissions, show an error (macOS). |
| // -- If Chrome has not requested Bluetooth permissions yet, trigger a |
| // permission prompt (macOS). |
| // -- If the adapter is not powered, but Chrome can turn it automatically, |
| // then advanced to the flow to turn on Bluetooth automatically. |
| // -- Otherwise advanced to the manual Bluetooth power on flow. |
| // |
| // Valid action whenever contacting a phone or showing the QR code screen is |
| // possible. |
| void EnsureBleAdapterIsPoweredAndContinue(base::OnceClosure action); |
| void OnBleStatusKnown(device::FidoRequestHandlerBase::BleStatus ble_status); |
| |
| // Tries if a USB device is present -- the user claims they plugged it in. |
| // |
| // Valid action when at step: kUsbInsert. |
| void TryUsbDevice(); |
| |
| // Tries to dispatch to the platform authenticator -- either because the |
| // request requires it or because the user told us to. May show an error for |
| // unrecognized credential, or an Incognito mode interstitial, or proceed |
| // straight to the platform authenticator prompt. |
| // |
| // Valid action when at all steps. |
| void StartPlatformAuthenticatorFlow(); |
| |
| // To be called when Web Authentication request times-out. |
| void OnRequestTimeout(); |
| |
| // To be called when the user activates a security key that does not recognize |
| // any of the allowed credentials (during a GetAssertion request). |
| void OnActivatedKeyNotRegistered(); |
| |
| // To be called when the user activates a security key that does recognize |
| // one of excluded credentials (during a MakeCredential request). |
| void OnActivatedKeyAlreadyRegistered(); |
| |
| // To be called when the selected authenticator cannot currently handle PIN |
| // requests because it needs a power-cycle due to too many failures. |
| void OnSoftPINBlock(); |
| |
| // To be called when the selected authenticator must be reset before |
| // performing any PIN operations because of too many failures. |
| void OnHardPINBlock(); |
| |
| // To be called when the selected authenticator was removed while |
| // waiting for a PIN to be entered. |
| void OnAuthenticatorRemovedDuringPINEntry(); |
| |
| // To be called when the selected authenticator doesn't have the requested |
| // resident key capability. |
| void OnAuthenticatorMissingResidentKeys(); |
| |
| // To be called when the selected authenticator doesn't have the requested |
| // user verification capability. |
| void OnAuthenticatorMissingUserVerification(); |
| |
| // To be called when the selected authenticator doesn't have the requested |
| // large blob capability. |
| void OnAuthenticatorMissingLargeBlob(); |
| |
| // To be called when the selected authenticator doesn't support any of the |
| // COSEAlgorithmIdentifiers requested by the RP. |
| void OnNoCommonAlgorithms(); |
| |
| // To be called when the selected authenticator cannot create a resident |
| // credential because of insufficient storage. |
| void OnAuthenticatorStorageFull(); |
| |
| // To be called when the user denies consent, e.g. by canceling out of the |
| // system's platform authenticator prompt. |
| void OnUserConsentDenied(); |
| |
| // To be called when the user clicks "Cancel" in the native Windows UI. |
| // Returns true if the event was handled. |
| bool OnWinUserCancelled(); |
| |
| // To be called when a hybrid connection fails. Returns true if the event |
| // was handled. |
| bool OnHybridTransportError(); |
| |
| // To be called when an enclave transaction fails. Returns true if the event |
| // was handled. |
| bool OnEnclaveError(); |
| |
| // To be called when there are no passkeys from an internal authenticator. |
| // This is a rare case but can happen when the user grants passkeys permission |
| // on macOS as part of a request flow and then Chromium realises that the |
| // request should never have been sent to iCloud Keychain in the first place. |
| bool OnNoPasskeys(); |
| |
| // To be called when fetching a challenge from a provided URL failed. |
| void OnChallengeUrlFailure(); |
| |
| // To be called when the Bluetooth adapter status changes. |
| void BluetoothAdapterStatusChanged( |
| device::FidoRequestHandlerBase::BleStatus ble_status); |
| |
| void SetRequestCallback(RequestCallback request_callback); |
| void SetAccountPreselectedCallback( |
| content::AuthenticatorRequestClientDelegate::AccountPreselectedCallback |
| callback); |
| void SetBluetoothAdapterPowerOnCallback( |
| base::RepeatingClosure bluetooth_adapter_power_on_callback); |
| void SetRequestBlePermissionCallback(BlePermissionCallback callback); |
| |
| // Called when the user needs to retry user verification with the number of |
| // |attempts| remaining. |
| void OnRetryUserVerification(int attempts); |
| |
| // Adds or removes an authenticator to the list of known authenticators. The |
| // first authenticator added with transport `kInternal` (or without a |
| // transport) is considered to be the default platform authenticator. |
| void AddAuthenticator(const device::FidoAuthenticator& authenticator); |
| void RemoveAuthenticator(std::string_view authenticator_id); |
| |
| // SelectAccount is called to trigger an account selection dialog. |
| void SelectAccount( |
| std::vector<device::AuthenticatorGetAssertionResponse> responses, |
| base::OnceCallback<void(device::AuthenticatorGetAssertionResponse)> |
| callback); |
| |
| // OnAccountPreselected is called when the user selects a discoverable |
| // credential from a platform authenticator prior to providing user |
| // authentication. `crededential_id` must match one of the credentials in |
| // `transport_availability_.recognized_credentials`. Returns the source of the |
| // credential. |
| // |
| // Note: it's important not to pass a reference to `credential_id` here |
| // because this function clears `model_->creds`, which is where such a |
| // reference would often point. |
| device::AuthenticatorType OnAccountPreselected( |
| const std::vector<uint8_t> credential_id); |
| |
| void SetSelectedAuthenticatorForTesting(AuthenticatorReference authenticator); |
| |
| // StartTransportFlowForTesting moves the UI to focus on the given transport. |
| // UI should use |mechanisms()| to enumerate the user-visible mechanisms and |
| // use the callbacks therein. |
| void StartTransportFlowForTesting(AuthenticatorTransport transport); |
| |
| // SetCurrentStepForTesting forces the model to the specified step. This |
| // performs the little extra processing that this Controller does before |
| // setting the model's Step. In most cases tests can set the Step on the |
| // model directly. |
| void SetCurrentStepForTesting(AuthenticatorRequestDialogModel::Step step); |
| |
| device::FidoRequestHandlerBase::TransportAvailabilityInfo& |
| transport_availability_for_testing() { |
| return transport_availability_; |
| } |
| |
| ObservableAuthenticatorList& saved_authenticators() { |
| return ephemeral_state_.saved_authenticators_; |
| } |
| |
| const base::flat_set<AuthenticatorTransport>& available_transports() { |
| return transport_availability_.available_transports; |
| } |
| |
| void CollectPIN(device::pin::PINEntryReason reason, |
| device::pin::PINEntryError error, |
| uint32_t min_pin_length, |
| int attempts, |
| base::OnceCallback<void(std::u16string)> provide_pin_cb); |
| void FinishCollectToken(); |
| |
| void StartInlineBioEnrollment(base::OnceClosure next_callback); |
| void OnSampleCollected(int bio_samples_remaining); |
| |
| void set_is_non_webauthn_request(bool is_non_webauthn_request) { |
| is_non_webauthn_request_ = is_non_webauthn_request; |
| } |
| |
| void SetHints( |
| const content::AuthenticatorRequestClientDelegate::Hints& hints) { |
| hints_ = hints; |
| } |
| |
| void set_cable_transport_info( |
| std::optional<bool> extension_is_v2, |
| const std::optional<std::string>& cable_qr_string); |
| |
| bool win_native_api_enabled() const { |
| return transport_availability_.has_win_native_api_authenticator; |
| } |
| |
| void set_allow_icloud_keychain(bool); |
| void set_should_create_in_icloud_keychain(bool); |
| |
| #if BUILDFLAG(IS_MAC) |
| void RecordMacOsStartedHistogram(); |
| void RecordMacOsSuccessHistogram(device::FidoRequestType, |
| device::AuthenticatorType); |
| void set_is_active_profile_authenticator_user(bool); |
| void set_has_icloud_drive_enabled(bool); |
| #endif |
| |
| void SetCredentialTypes(int types); |
| |
| content::AuthenticatorRequestClientDelegate::UIPresentation ui_presentation() |
| const; |
| void SetUIPresentation( |
| content::AuthenticatorRequestClientDelegate::UIPresentation modality); |
| |
| void ProvideChallengeUrl( |
| const GURL& url, |
| base::OnceCallback<void(std::optional<base::span<const uint8_t>>)> |
| callback); |
| |
| void InitializeEnclaveRequestCallback( |
| device::FidoDiscoveryFactory* discovery_factory); |
| |
| base::WeakPtr<AuthenticatorRequestDialogController> GetWeakPtr(); |
| |
| private: |
| FRIEND_TEST_ALL_PREFIXES(AuthenticatorRequestDialogControllerTest, |
| DeduplicateAccounts); |
| |
| // Contains the state that will be reset when calling StartOver(). StartOver() |
| // might be called at an arbitrary point of execution. |
| struct EphemeralState { |
| EphemeralState(); |
| EphemeralState(EphemeralState&&); |
| EphemeralState& operator=(EphemeralState&&); |
| ~EphemeralState(); |
| |
| // Stores a list of |AuthenticatorReference| values such that a request can |
| // be dispatched dispatched after some UI interaction. This is useful for |
| // platform authenticators (and Windows) where dispatch to the authenticator |
| // immediately results in modal UI to appear. |
| ObservableAuthenticatorList saved_authenticators_; |
| |
| // responses_ contains possible responses to select between after an |
| // authenticator has responded to a request. |
| std::vector<device::AuthenticatorGetAssertionResponse> responses_; |
| |
| // When a request has been dispatched to a platform authenticator, this |
| // contains the `AuthenticatorType`. std::nullopt at all other times. |
| std::optional<device::AuthenticatorType> |
| dispatched_platform_authenticator_type_ = std::nullopt; |
| |
| // did_invoke_platform_despite_no_priority_mechanism_ is true if a platform |
| // authenticator was triggered despite there not being a |
| // `priority_mechanism_index_` set. For example, this can happen if there's |
| // an allowlist match. |
| bool did_invoke_platform_despite_no_priority_mechanism_ = false; |
| }; |
| |
| void ResetEphemeralState(); |
| |
| void SetCurrentStep(AuthenticatorRequestDialogModel::Step step); |
| |
| // Requests that the step-by-step wizard flow commence, guiding the user |
| // through using the Secutity Key with the given |transport|. |
| // |
| // Valid action when at step: kNotStarted. kMechanismSelection, and steps |
| // where the other transports menu is shown, namely, kUsbInsertAndActivate, |
| // kCableActivate. |
| void StartGuidedFlowForTransport(AuthenticatorTransport transport); |
| |
| // Starts the flow for adding an unlisted phone by showing a QR code. |
| void StartGuidedFlowForAddPhone(); |
| |
| // Displays a resident-key warning if needed and then calls |
| // |HideDialogAndDispatchToNativeWindowsApi|. |
| void StartWinNativeApi(); |
| |
| void StartICloudKeychain(); |
| void StartEnclave(); |
| |
| // Triggers gaia account reauth to restore sync to working order. |
| void ReauthForSyncRestore(); |
| |
| void StartAutofillRequest(); |
| void StartPasskeyUpgradeRequest(); |
| |
| void DispatchRequestAsync(AuthenticatorReference* authenticator); |
| |
| // SortRecognizedCredentials sorts |
| // `transport_availability_.recognized_credentials` into username order. |
| void SortRecognizedCredentials(); |
| |
| // PopulateMechanisms fills in |model_->mechanisms|. |
| void PopulateMechanisms(); |
| |
| // Adds a button that triggers Windows Hello with the specified string ID and |
| // transport icon. |
| void AddWindowsButton(int label, AuthenticatorTransport transport); |
| |
| // IndexOfPriorityMechanism returns the index, in |model_->mechanisms|, of the |
| // Mechanism that should be triggered immediately, if any. |
| std::optional<size_t> IndexOfPriorityMechanism(); |
| |
| std::optional<size_t> IndexOfGetAssertionPriorityMechanism(); |
| std::optional<size_t> IndexOfImmediateGetPriorityMechanism(); |
| std::optional<size_t> IndexOfMakeCredentialPriorityMechanism(); |
| |
| // Sets correct step for entering GPM pin based on `gpm_pin_is_arbitrary_`. |
| void PromptForGPMPin(); |
| |
| // Returns true if this request could pick the enclave authenticator by |
| // default. This only makes sense for a create() call. |
| bool CanDefaultToEnclave(Profile* profile); |
| |
| // Returns the render frame host associated with this request. The render |
| // frame host indirectly owns the controller, and so it should outlive it. |
| content::RenderFrameHost* GetRenderFrameHost() const; |
| |
| // Lazy creation accessor. |
| ChallengeUrlFetcher* GetChallengeUrlFetcher(); |
| |
| void MaybeStartChallengeFetch(); |
| void OnChallengeFetched(); |
| |
| void PopulatePasswords(); |
| |
| raw_ptr<AuthenticatorRequestDialogModel> model_; |
| |
| // Identifier for the RenderFrameHost of the frame that initiated the current |
| // request. |
| EphemeralState ephemeral_state_; |
| |
| // is_non_webauthn_request_ is true if the current request came from Secure |
| // Payment Confirmation, or from credit-card autofill. |
| bool is_non_webauthn_request_ = false; |
| |
| // started_ records whether |StartFlow| has been called. |
| bool started_ = false; |
| |
| // pending_step_ holds requested steps until the UI is shown. The UI is only |
| // shown once the TransportAvailabilityInfo is available, but authenticators |
| // may request, e.g., PIN entry prior to that. |
| std::optional<AuthenticatorRequestDialogModel::Step> pending_step_; |
| |
| // after_off_the_record_interstitial_ contains the closure to run if the user |
| // accepts the interstitial that warns that platform/caBLE authenticators may |
| // record information even in incognito mode. |
| base::OnceClosure after_off_the_record_interstitial_; |
| |
| // after_ble_adapter_powered_ contains the closure to run if the user |
| // accepts the interstitial that requests to turn on the BLE adapter. |
| base::OnceClosure after_ble_adapter_powered_; |
| |
| // This field is only filled out once the UX flow is started. |
| device::FidoRequestHandlerBase::TransportAvailabilityInfo |
| transport_availability_; |
| |
| PasswordCredentialController::PasswordCredentials passwords_; |
| |
| content::AuthenticatorRequestClientDelegate::AccountPreselectedCallback |
| account_preselected_callback_; |
| RequestCallback request_callback_; |
| base::RepeatingClosure bluetooth_adapter_power_on_callback_; |
| |
| // Triggers a permission prompt on macOS if ble_status is |
| // kPendingPermissionRequest and returns the bluetooth status. |
| BlePermissionCallback request_ble_permission_callback_; |
| |
| base::OnceClosure bio_enrollment_callback_; |
| |
| base::OnceCallback<void(std::u16string)> pin_callback_; |
| |
| base::OnceCallback<void(device::AuthenticatorGetAssertionResponse)> |
| selection_callback_; |
| |
| // cable_extension_provided_ indicates whether the request included a caBLE |
| // extension. |
| bool cable_extension_provided_ = false; |
| |
| // cable_device_ready_ is true if a CTAP-level request has been sent to a |
| // caBLE device. At this point we assume that any transport errors are |
| // cancellations on the device, not networking errors. |
| bool cable_device_ready_ = false; |
| |
| // cable_connecting_sheet_timer_ is started when we start displaying |
| // the "connecting..." sheet for a caBLE connection. To avoid flashing the UI, |
| // the sheet won't be automatically replaced until it completes. |
| base::OneShotTimer cable_connecting_sheet_timer_; |
| |
| // cable_connecting_ready_to_advance_ is set to true if we are ready to |
| // advance the "connecting" sheet but are waiting for |
| // `cable_connecting_sheet_timer_` to complete. |
| bool cable_connecting_ready_to_advance_ = false; |
| |
| // allow_icloud_keychain_ is true if iCloud Keychain can be used for this |
| // request. It is disabled for Secure Payment Confirmation and other non- |
| // WebAuthn cases, for example. |
| bool allow_icloud_keychain_ = false; |
| |
| // should_create_in_icloud_keychain is true if creation requests with |
| // attachment=platform should default to iCloud Keychain rather than the |
| // profile authenticator. |
| bool should_create_in_icloud_keychain_ = false; |
| |
| // enclave_enabled_status_ determines whether Google Password Manager entries |
| // should be offered both for `makeCredential` or `getAssertion`. If reauth |
| // needed, instead of offering the actual passkeys or creating a passkey, |
| // re-authentication to Google is offered. |
| EnclaveEnabledStatus enclave_enabled_status_ = |
| EnclaveEnabledStatus::kDisabled; |
| |
| // The RP's hints. See |
| // https://w3c.github.io/webauthn/#enumdef-publickeycredentialhints |
| content::AuthenticatorRequestClientDelegate::Hints hints_; |
| |
| // True when the priority mechanism was determined to be the enclave. |
| bool enclave_was_priority_mechanism_ = false; |
| |
| #if BUILDFLAG(IS_MAC) |
| // did_record_macos_start_histogram_ is set to true if a histogram record of |
| // starting the current request was made. Any later successful completion will |
| // only be recorded if a start event was recorded first. |
| bool did_record_macos_start_histogram_ = false; |
| |
| // is_active_profile_authenticator_user_ is true if the current profile has |
| // recently used the platform authenticator on macOS that saves credentials |
| // into the profile. |
| bool is_active_profile_authenticator_user_ = false; |
| |
| // has_icloud_drive_enabled_ is true if the current system has iCloud Drive |
| // enabled. This is used as an approximation for whether iCloud Keychain |
| // syncing is enabled. |
| bool has_icloud_drive_enabled_ = false; |
| #endif |
| |
| // The credential types that are being asked for. |
| int credential_types_ = |
| static_cast<int>(blink::mojom::CredentialTypeFlags::kNone); |
| |
| // ChallengeUrl support. The URL is the destination to fetch the challenge |
| // and the callback is invoked when the challenge is received. |
| GURL challenge_url_; |
| base::OnceCallback<void(std::optional<base::span<const uint8_t>>)> |
| challenge_callback_; |
| |
| std::unique_ptr<ChallengeUrlFetcher> challenge_url_fetcher_; |
| |
| const content::GlobalRenderFrameHostId frame_host_id_; |
| |
| base::ScopedObservation<webauthn::PasskeyModel, |
| webauthn::PasskeyModel::Observer> |
| passkey_model_observation_{this}; |
| |
| EnclaveRequestCallback enclave_request_callback_; |
| std::unique_ptr<PasskeyUpgradeRequestController> |
| passkey_upgrade_request_controller_; |
| |
| base::WeakPtrFactory<AuthenticatorRequestDialogController> weak_factory_{ |
| this}; |
| }; |
| |
| #endif // CHROME_BROWSER_WEBAUTHN_AUTHENTICATOR_REQUEST_DIALOG_CONTROLLER_H_ |