// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "content/browser/webauth/authenticator_impl.h"

#include <algorithm>
#include <array>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <iterator>
#include <list>
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <string_view>
#include <tuple>
#include <utility>
#include <vector>

#include "base/apple/owned_objc.h"
#include "base/base64url.h"
#include "base/check.h"
#include "base/check_op.h"
#include "base/compiler_specific.h"
#include "base/containers/flat_set.h"
#include "base/containers/span.h"
#include "base/containers/to_vector.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/functional/callback_forward.h"
#include "base/functional/callback_helpers.h"
#include "base/json/json_reader.h"
#include "base/location.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/stack_allocated.h"
#include "base/notreached.h"
#include "base/rand_util.h"
#include "base/run_loop.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_command_line.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "base/test/test_future.h"
#include "base/time/time.h"
#include "base/values.h"
#include "build/build_config.h"
#include "components/cbor/reader.h"
#include "components/cbor/values.h"
#include "components/ukm/test_ukm_recorder.h"
#include "content/browser/renderer_host/frame_tree_node.h"
#include "content/browser/webauth/authenticator_common_impl.h"
#include "content/browser/webauth/authenticator_environment.h"
#include "content/browser/webauth/authenticator_request_outcome_enums.h"
#include "content/browser/webauth/authenticator_test_base.h"
#include "content/browser/webauth/client_data_json.h"
#include "content/browser/webauth/default_authenticator_request_client_delegate.h"
#include "content/browser/webauth/virtual_authenticator.h"
#include "content/browser/webauth/virtual_authenticator_manager_impl.h"
#include "content/browser/webauth/webauth_request_security_checker.h"
#include "content/public/browser/authenticator_request_client_delegate.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_authentication_delegate.h"
#include "content/public/browser/web_authentication_request_proxy.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/navigation_simulator.h"
#include "content/public/test/test_renderer_host.h"
#include "crypto/evp.h"
#include "crypto/hash.h"
#include "crypto/hmac.h"
#include "device/bluetooth/bluetooth_adapter_factory.h"
#include "device/bluetooth/test/mock_bluetooth_adapter.h"
#include "device/fido/attested_credential_data.h"
#include "device/fido/authenticator_data.h"
#include "device/fido/authenticator_get_assertion_response.h"
#include "device/fido/authenticator_selection_criteria.h"
#include "device/fido/cable/cable_discovery_data.h"
#include "device/fido/cable/fido_tunnel_device.h"
#include "device/fido/cable/v2_authenticator.h"
#include "device/fido/cable/v2_constants.h"
#include "device/fido/cable/v2_discovery.h"
#include "device/fido/cable/v2_handshake.h"
#include "device/fido/cable/v2_test_util.h"
#include "device/fido/discoverable_credential_metadata.h"
#include "device/fido/fake_fido_discovery.h"
#include "device/fido/features.h"
#include "device/fido/fido_authenticator.h"
#include "device/fido/fido_constants.h"
#include "device/fido/fido_device_authenticator.h"
#include "device/fido/fido_discovery_base.h"
#include "device/fido/fido_request_handler_base.h"
#include "device/fido/fido_transport_protocol.h"
#include "device/fido/fido_types.h"
#include "device/fido/filter.h"
#include "device/fido/large_blob.h"
#include "device/fido/mock_fido_device.h"
#include "device/fido/multiple_virtual_fido_device_factory.h"
#include "device/fido/pin.h"
#include "device/fido/public_key_credential_descriptor.h"
#include "device/fido/public_key_credential_params.h"
#include "device/fido/public_key_credential_rp_entity.h"
#include "device/fido/public_key_credential_user_entity.h"
#include "device/fido/virtual_ctap2_device.h"
#include "device/fido/virtual_fido_device.h"
#include "device/fido/virtual_fido_device_factory.h"
#include "mojo/public/cpp/base/big_buffer.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/system/functions.h"
#include "services/data_decoder/gzipper.h"
#include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
#include "services/metrics/public/cpp/ukm_builders.h"
#include "services/metrics/public/cpp/ukm_source.h"
#include "services/network/public/cpp/permissions_policy/permissions_policy_declaration.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/permissions_policy/permissions_policy_feature.mojom-shared.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/mojom/webauthn/authenticator.mojom.h"
#include "third_party/boringssl/src/include/openssl/base.h"
#include "third_party/boringssl/src/include/openssl/ec.h"
#include "third_party/boringssl/src/include/openssl/ec_key.h"
#include "third_party/boringssl/src/include/openssl/evp.h"
#include "third_party/boringssl/src/include/openssl/obj.h"
#include "url/origin.h"
#include "url/url_util.h"

#if BUILDFLAG(IS_MAC)
#include "base/files/file_path.h"
#include "base/path_service.h"
#include "crypto/apple/scoped_fake_keychain_v2.h"
#include "device/fido/mac/authenticator_config.h"
#include "device/fido/mac/credential_store.h"
#include "device/fido/mac/icloud_keychain.h"
#include "device/fido/mac/scoped_icloud_keychain_test_environment.h"
#include "device/fido/mac/scoped_touch_id_test_environment.h"
#endif

#if BUILDFLAG(IS_WIN)
#include "content/public/test/test_browser_context.h"
#include "device/fido/fido_test_data.h"
#include "device/fido/win/fake_webauthn_api.h"
#include "device/fido/win/util.h"
#include "third_party/microsoft_webauthn/src/webauthn.h"  // nogncheck
#endif

#if BUILDFLAG(IS_CHROMEOS)
#include "chromeos/dbus/tpm_manager/tpm_manager_client.h"
#include "chromeos/dbus/u2f/u2f_client.h"
#endif

namespace content {

using ::testing::_;

using blink::mojom::AttestationConveyancePreference;
using blink::mojom::AuthenticationExtensionsClientInputs;
using blink::mojom::AuthenticationExtensionsClientOutputs;
using blink::mojom::AuthenticatorSelectionCriteria;
using blink::mojom::AuthenticatorSelectionCriteriaPtr;
using blink::mojom::AuthenticatorStatus;
using blink::mojom::AuthenticatorTransport;
using blink::mojom::CableAuthentication;
using blink::mojom::CableAuthenticationPtr;
using blink::mojom::CommonCredentialInfo;
using blink::mojom::GetAssertionAuthenticatorResponse;
using blink::mojom::GetAssertionAuthenticatorResponsePtr;
using blink::mojom::GetCredentialOptions;
using blink::mojom::GetCredentialOptionsPtr;
using blink::mojom::MakeCredentialAuthenticatorResponse;
using blink::mojom::MakeCredentialAuthenticatorResponsePtr;
using blink::mojom::PublicKeyCredentialCreationOptions;
using blink::mojom::PublicKeyCredentialCreationOptionsPtr;
using blink::mojom::PublicKeyCredentialDescriptor;
using blink::mojom::PublicKeyCredentialDescriptorPtr;
using blink::mojom::PublicKeyCredentialParameters;
using blink::mojom::PublicKeyCredentialParametersPtr;
using blink::mojom::PublicKeyCredentialReportOptions;
using blink::mojom::PublicKeyCredentialReportOptionsPtr;
using blink::mojom::PublicKeyCredentialRequestOptions;
using blink::mojom::PublicKeyCredentialRequestOptionsPtr;
using blink::mojom::PublicKeyCredentialRpEntity;
using blink::mojom::PublicKeyCredentialRpEntityPtr;
using blink::mojom::PublicKeyCredentialType;
using blink::mojom::PublicKeyCredentialUserEntity;
using blink::mojom::PublicKeyCredentialUserEntityPtr;
using blink::mojom::RemoteDesktopClientOverride;
using blink::mojom::RemoteDesktopClientOverridePtr;
using blink::mojom::WebAuthnDOMExceptionDetails;
using blink::mojom::WebAuthnDOMExceptionDetailsPtr;
using cbor::Reader;
using cbor::Value;
using device::VirtualCtap2Device;
using device::VirtualFidoDevice;
using device::cablev2::Event;

namespace {

using InterestingFailureReason =
    AuthenticatorRequestClientDelegate::InterestingFailureReason;
using FailureReasonFuture = base::test::TestFuture<InterestingFailureReason>;

constexpr base::TimeDelta kTestTimeout = base::Minutes(1);

constexpr char kTestOrigin1[] = "https://a.google.com";
constexpr char kTestOrigin2[] = "https://acme.org";
constexpr char kDifferentTestRelyingPartyId[] = "different-rp.com";
constexpr char kExtensionScheme[] = "chrome-extension";
static constexpr char kCorpCrdOrigin[] =
    "https://remotedesktop.corp.google.com";

constexpr uint8_t kTestChallengeBytes[] = {
    0x68, 0x71, 0x34, 0x96, 0x82, 0x22, 0xEC, 0x17, 0x20, 0x2E, 0x42,
    0x50, 0x5F, 0x8E, 0xD2, 0xB1, 0x6A, 0xE2, 0x2F, 0x16, 0xBB, 0x05,
    0xB8, 0x8C, 0x25, 0xDB, 0x9E, 0x60, 0x26, 0x45, 0xF1, 0x41};

constexpr char kTestRegisterClientDataJsonString[] =
    R"({"challenge":"aHE0loIi7BcgLkJQX47SsWriLxa7BbiMJdueYCZF8UE","origin":)"
    R"("https://a.google.com", "type":"webauthn.create"})";

constexpr char kTestSignClientDataJsonString[] =
    R"({"challenge":"aHE0loIi7BcgLkJQX47SsWriLxa7BbiMJdueYCZF8UE","origin":)"
    R"("https://a.google.com", "type":"webauthn.get"})";

using TestGetClientCapabilityFuture = base::test::TestFuture<
    std::vector<blink::mojom::WebAuthnClientCapabilityPtr>>;
using TestIsUvpaaFuture = base::test::TestFuture<bool>;
using TestMakeCredentialFuture =
    base::test::TestFuture<AuthenticatorStatus,
                           MakeCredentialAuthenticatorResponsePtr,
                           WebAuthnDOMExceptionDetailsPtr>;
using TestGetAssertionFuture =
    base::test::TestFuture<AuthenticatorStatus,
                           GetAssertionAuthenticatorResponsePtr,
                           WebAuthnDOMExceptionDetailsPtr>;
using TestGetCredentialFuture =
    base::test::TestFuture<blink::mojom::GetCredentialResponsePtr>;
using TestRequestStartedFuture = base::test::TestFuture<void>;
using TestReportFuture =
    base::test::TestFuture<AuthenticatorStatus, WebAuthnDOMExceptionDetailsPtr>;

std::vector<uint8_t> GetTestChallengeBytes() {
  return std::vector<uint8_t>(std::begin(kTestChallengeBytes),
                              std::end(kTestChallengeBytes));
}

PublicKeyCredentialReportOptionsPtr GetTestPublicKeyCredentialReportOptions() {
  auto options = PublicKeyCredentialReportOptions::New();
  options->relying_party_id = std::string(kTestRelyingPartyId);
  return options;
}

std::vector<device::CableDiscoveryData> GetTestCableExtension() {
  device::CableDiscoveryData cable;
  cable.version = device::CableDiscoveryData::Version::V1;
  cable.v1.emplace();
  cable.v1->client_eid.fill(0x01);
  cable.v1->authenticator_eid.fill(0x02);
  cable.v1->session_pre_key.fill(0x03);

  std::vector<device::CableDiscoveryData> ret;
  ret.emplace_back(std::move(cable));
  return ret;
}

device::AuthenticatorData AuthDataFromMakeCredentialResponse(
    const MakeCredentialAuthenticatorResponsePtr& response) {
  std::optional<Value> attestation_value =
      Reader::Read(response->attestation_object);
  CHECK(attestation_value);
  const auto& attestation = attestation_value->GetMap();

  const auto auth_data_it = attestation.find(Value(device::kAuthDataKey));
  CHECK(auth_data_it != attestation.end());
  const std::vector<uint8_t>& auth_data = auth_data_it->second.GetBytestring();
  std::optional<device::AuthenticatorData> parsed_auth_data =
      device::AuthenticatorData::DecodeAuthenticatorData(auth_data);
  return std::move(parsed_auth_data.value());
}

bool HasUV(const MakeCredentialAuthenticatorResponsePtr& response) {
  return AuthDataFromMakeCredentialResponse(response)
      .obtained_user_verification();
}

bool HasUV(const GetAssertionAuthenticatorResponsePtr& response) {
  std::optional<device::AuthenticatorData> auth_data =
      device::AuthenticatorData::DecodeAuthenticatorData(
          response->info->authenticator_data);
  return auth_data->obtained_user_verification();
}

url::Origin GetTestOrigin() {
  const GURL test_relying_party_url(kTestOrigin1);
  CHECK(test_relying_party_url.is_valid());
  return url::Origin::Create(test_relying_party_url);
}

std::string GetTestClientDataJSON(webauthn::ClientDataRequestType type) {
  return BuildClientDataJson({std::move(type), GetTestOrigin(), GetTestOrigin(),
                              GetTestChallengeBytes(),
                              /*is_cross_origin_iframe=*/false});
}

device::LargeBlob CompressLargeBlob(base::span<const uint8_t> blob) {
  data_decoder::Gzipper gzipper;
  std::vector<uint8_t> compressed;
  base::RunLoop run_loop;
  gzipper.Deflate(blob, base::BindLambdaForTesting(
                            [&](std::optional<mojo_base::BigBuffer> result) {
                              compressed = base::ToVector(*result);
                              run_loop.Quit();
                            }));
  run_loop.Run();
  return device::LargeBlob(std::move(compressed), blob.size());
}

std::vector<uint8_t> UncompressLargeBlob(device::LargeBlob blob) {
  data_decoder::Gzipper gzipper;
  std::vector<uint8_t> uncompressed;
  base::RunLoop run_loop;
  gzipper.Inflate(
      {blob.compressed_data}, blob.original_size,
      base::BindLambdaForTesting(
          [&](std::optional<mojo_base::BigBuffer> result) {
            if (result) {
              uncompressed = base::ToVector(*result);
            } else {
              // Magic value to indicate failure.
              const char kErrorMsg[] = "decompress error";
              uncompressed.assign(
                  reinterpret_cast<const uint8_t*>(kErrorMsg),
                  reinterpret_cast<const uint8_t*>(std::end(kErrorMsg)));
            }
            run_loop.Quit();
          }));
  run_loop.Run();
  return uncompressed;
}

// Convert a blink::mojom::AttestationConveyancePreference to a
// device::AtttestationConveyancePreference.
device::AttestationConveyancePreference ConvertAttestationConveyancePreference(
    AttestationConveyancePreference in) {
  switch (in) {
    case AttestationConveyancePreference::NONE:
      return ::device::AttestationConveyancePreference::kNone;
    case AttestationConveyancePreference::INDIRECT:
      return ::device::AttestationConveyancePreference::kIndirect;
    case AttestationConveyancePreference::DIRECT:
      return ::device::AttestationConveyancePreference::kDirect;
    case AttestationConveyancePreference::ENTERPRISE:
      return ::device::AttestationConveyancePreference::
          kEnterpriseIfRPListedOnAuthenticator;
  }
}

}  // namespace

class AuthenticatorImplTest : public AuthenticatorTestBase {
 protected:
  AuthenticatorImplTest() {
    url::AddStandardScheme("chrome-extension", url::SCHEME_WITH_HOST);
  }
  ~AuthenticatorImplTest() override = default;

  void SetUp() override {
    AuthenticatorTestBase::SetUp();
    SetBluetoothLESupported(true);
    device::BluetoothAdapterFactory::SetAdapterForTesting(mock_adapter_);
  }

  void SetBluetoothLESupported(bool supported) {
    bluetooth_global_values_->SetLESupported(supported);
  }

  void NavigateAndCommit(const GURL& url) {
    RenderViewHostTestHarness::NavigateAndCommit(url);
  }

  mojo::Remote<blink::mojom::Authenticator> ConnectToAuthenticator() {
    mojo::Remote<blink::mojom::Authenticator> authenticator;
    static_cast<RenderFrameHostImpl*>(main_rfh())
        ->GetWebAuthenticationService(
            authenticator.BindNewPipeAndPassReceiver());
    return authenticator;
  }

  bool AuthenticatorIsUvpaa() {
    TestIsUvpaaFuture future;
    mojo::Remote<blink::mojom::Authenticator> authenticator =
        ConnectToAuthenticator();
    authenticator->IsUserVerifyingPlatformAuthenticatorAvailable(
        future.GetCallback());
    EXPECT_TRUE(future.Wait());
    return future.Get();
  }

  using ClientCapabilitiesList =
      std::vector<blink::mojom::WebAuthnClientCapabilityPtr>;

  ClientCapabilitiesList AuthenticatorGetClientCapabilities() {
    mojo::Remote<blink::mojom::Authenticator> authenticator =
        ConnectToAuthenticator();
    TestGetClientCapabilityFuture future;
    authenticator->GetClientCapabilities(future.GetCallback());
    EXPECT_TRUE(future.Wait());
    return future.Take();
  }

  void ExpectCapability(
      const std::vector<blink::mojom::WebAuthnClientCapabilityPtr>&
          capabilities,
      std::string_view capability_name,
      std::optional<bool> supported) {
    auto capability_it =
        std::find_if(capabilities.begin(), capabilities.end(),
                     [&capability_name](const auto& capability) {
                       return capability->name == capability_name;
                     });

    if (supported.has_value()) {
      ASSERT_NE(capability_it, capabilities.end());
      EXPECT_EQ(supported, (*capability_it)->supported);
    } else {
      EXPECT_EQ(capability_it, capabilities.end());
    }
  }

  bool AuthenticatorIsConditionalMediationAvailable() {
    TestIsUvpaaFuture future;
    mojo::Remote<blink::mojom::Authenticator> authenticator =
        ConnectToAuthenticator();
    authenticator->IsConditionalMediationAvailable(future.GetCallback());
    EXPECT_TRUE(future.Wait());
    return future.Get();
  }

  struct MakeCredentialResult {
    AuthenticatorStatus status;
    MakeCredentialAuthenticatorResponsePtr response;
  };

  MakeCredentialResult AuthenticatorMakeCredential() {
    return AuthenticatorMakeCredential(
        GetTestPublicKeyCredentialCreationOptions());
  }

  MakeCredentialResult AuthenticatorMakeCredential(
      PublicKeyCredentialCreationOptionsPtr options) {
    mojo::Remote<blink::mojom::Authenticator> authenticator =
        ConnectToAuthenticator();
    TestMakeCredentialFuture future;
    authenticator->MakeCredential(std::move(options), future.GetCallback());
    EXPECT_TRUE(future.Wait());
    auto [status, response, dom_exception] = future.Take();
    return {status, std::move(response)};
  }

  MakeCredentialResult AuthenticatorMakeCredentialAndWaitForTimeout(
      PublicKeyCredentialCreationOptionsPtr options) {
    mojo::Remote<blink::mojom::Authenticator> authenticator =
        ConnectToAuthenticator();
    TestMakeCredentialFuture future;
    authenticator->MakeCredential(std::move(options), future.GetCallback());
    task_environment()->FastForwardBy(kTestTimeout);
    EXPECT_TRUE(future.Wait());
    auto [status, response, dom_exception] = future.Take();
    return {status, std::move(response)};
  }

  struct GetAssertionResult {
    AuthenticatorStatus status;
    GetAssertionAuthenticatorResponsePtr response;
  };

  GetAssertionResult AuthenticatorGetAssertion() {
    return AuthenticatorGetAssertion(
        GetTestPublicKeyCredentialRequestOptions());
  }

  GetAssertionResult AuthenticatorGetAssertion(
      PublicKeyCredentialRequestOptionsPtr options) {
    mojo::Remote<blink::mojom::Authenticator> authenticator =
        ConnectToAuthenticator();
    TestGetCredentialFuture future;
    GetCredentialOptionsPtr get_credential_options =
        GetCredentialOptions::New();
    get_credential_options->public_key = std::move(options);
    authenticator->GetCredential(std::move(get_credential_options),
                                 future.GetCallback());
    EXPECT_TRUE(future.Wait());
    auto get_assertion_response =
        std::move(future.Take()->get_get_assertion_response());
    return {get_assertion_response->status,
            std::move(get_assertion_response->credential)};
  }

  GetAssertionResult AuthenticatorGetAssertionAndWaitForTimeout(
      PublicKeyCredentialRequestOptionsPtr options) {
    mojo::Remote<blink::mojom::Authenticator> authenticator =
        ConnectToAuthenticator();
    TestGetCredentialFuture future;
    GetCredentialOptionsPtr get_credential_options =
        GetCredentialOptions::New();
    get_credential_options->public_key = std::move(options);
    authenticator->GetCredential(std::move(get_credential_options),
                                 future.GetCallback());
    task_environment()->FastForwardBy(kTestTimeout);
    auto get_assertion_response =
        std::move(future.Take()->get_get_assertion_response());
    return {get_assertion_response->status,
            std::move(get_assertion_response->credential)};
  }

  GetAssertionResult AuthenticatorGetCredential(
      GetCredentialOptionsPtr options) {
    mojo::Remote<blink::mojom::Authenticator> authenticator =
        ConnectToAuthenticator();
    TestGetCredentialFuture future;
    authenticator->GetCredential(std::move(options), future.GetCallback());
    task_environment()->FastForwardBy(kTestTimeout);
    auto get_assertion_response =
        std::move(future.Take()->get_get_assertion_response());
    return {get_assertion_response->status,
            std::move(get_assertion_response->credential)};
  }

  AuthenticatorStatus AuthenticatorReport(
      PublicKeyCredentialReportOptionsPtr options) {
    mojo::Remote<blink::mojom::Authenticator> authenticator =
        ConnectToAuthenticator();
    TestReportFuture future;
    authenticator->Report(std::move(options), future.GetCallback());
    EXPECT_TRUE(future.Wait());
    auto [status, dom_exception] = future.Take();
    return status;
  }

  AuthenticatorStatus TryAuthenticationWithAppId(std::string_view origin,
                                                 std::string_view appid) {
    const GURL origin_url(origin);
    NavigateAndCommit(origin_url);

    PublicKeyCredentialRequestOptionsPtr options =
        GetTestPublicKeyCredentialRequestOptions();
    options->relying_party_id = origin_url.host();
    options->extensions->appid = appid;

    return AuthenticatorGetAssertion(std::move(options)).status;
  }

  AuthenticatorStatus TryRegistrationWithAppIdExclude(
      std::string_view origin,
      std::string_view appid_exclude) {
    const GURL origin_url(origin);
    NavigateAndCommit(origin_url);

    PublicKeyCredentialCreationOptionsPtr options =
        GetTestPublicKeyCredentialCreationOptions();
    options->relying_party.id = origin_url.host();
    options->appid_exclude = appid_exclude;

    return AuthenticatorMakeCredential(std::move(options)).status;
  }

  ukm::TestUkmRecorder* GetTestUkmRecorder() { return &test_ukm_recorder_; }

  void VerifyGetAssertionOutcomeUkm(uint32_t index,
                                    GetAssertionOutcome outcome,
                                    AuthenticationRequestMode mode) {
    auto entries = GetTestUkmRecorder()->GetEntriesByName(
        ukm::builders::WebAuthn_SignCompletion::kEntryName);
    ASSERT_GT(entries.size(), index);
    GetTestUkmRecorder()->ExpectEntryMetric(
        entries[index], "SignCompletionResult", static_cast<int64_t>(outcome));
    GetTestUkmRecorder()->ExpectEntryMetric(entries[index], "RequestMode",
                                            static_cast<int64_t>(mode));
  }

  void VerifyMakeCredentialOutcomeUkm(uint32_t index,
                                      MakeCredentialOutcome outcome,
                                      AuthenticationRequestMode mode) {
    auto entries = GetTestUkmRecorder()->GetEntriesByName(
        ukm::builders::WebAuthn_RegisterCompletion::kEntryName);
    ASSERT_GT(entries.size(), index);
    GetTestUkmRecorder()->ExpectEntryMetric(entries[index],
                                            "RegisterCompletionResult",
                                            static_cast<int64_t>(outcome));
    GetTestUkmRecorder()->ExpectEntryMetric(entries[index], "RequestMode",
                                            static_cast<int64_t>(mode));
  }

  // Replaces the virtual authenticator with a multiple discovery for all
  // transports.
  void InjectVirtualAuthenticatorForAllTransports() {
    EXPECT_CALL(*mock_adapter_, IsPresent())
        .WillRepeatedly(::testing::Return(true));
    auto discovery =
        std::make_unique<device::test::MultipleVirtualFidoDeviceFactory>();
    for (device::FidoTransportProtocol transport : {
             device::FidoTransportProtocol::kUsbHumanInterfaceDevice,
             device::FidoTransportProtocol::kNearFieldCommunication,
             device::FidoTransportProtocol::kBluetoothLowEnergy,
             device::FidoTransportProtocol::kHybrid,
             device::FidoTransportProtocol::kInternal,
         }) {
      device::test::MultipleVirtualFidoDeviceFactory::DeviceDetails device;
      device.transport = transport;
      device.state->transport = transport;
      ASSERT_TRUE(device.state->InjectResidentKey(
          /*credential_id=*/{{1, 2, 3, 4}}, kTestRelyingPartyId,
          /*user_id=*/{{1, 1, 1, 1}}, "test@example.com", "Test User"));
      discovery->AddDevice(std::move(device));
    }
    ReplaceDiscoveryFactory(std::move(discovery));
  }

  scoped_refptr<::testing::NiceMock<device::MockBluetoothAdapter>>
      mock_adapter_ = base::MakeRefCounted<
          ::testing::NiceMock<device::MockBluetoothAdapter>>();

 private:
  std::unique_ptr<device::BluetoothAdapterFactory::GlobalOverrideValues>
      bluetooth_global_values_ =
          device::BluetoothAdapterFactory::Get()->InitGlobalOverrideValues();
  data_decoder::test::InProcessDataDecoder data_decoder_service_;
  url::ScopedSchemeRegistryForTests scoped_registry_;
  ukm::TestAutoSetUkmRecorder test_ukm_recorder_;
};

TEST_F(AuthenticatorImplTest, ClientDataJSONSerialization) {
  // First test that the output is in the expected form. Some verifiers may be
  // depending on the exact JSON serialisation. Since the serialisation may add
  // extra elements, this can only test that the expected value is a prefix of
  // the returned value.
  std::vector<uint8_t> challenge_bytes = {1, 2, 3};
  EXPECT_EQ(
      BuildClientDataJson({webauthn::ClientDataRequestType::kWebAuthnCreate,
                           GetTestOrigin(), GetTestOrigin(), challenge_bytes,
                           false})
          .find(
              "{\"type\":\"webauthn.create\",\"challenge\":\"AQID\",\"origin\":"
              "\"https://a.google.com\",\"crossOrigin\":false"),
      0u);

  // Second, check that a generic JSON parser correctly parses the result.
  static const struct {
    const webauthn::ClientDataRequestType type;
    url::Origin origin;
    url::Origin top_origin;
    std::vector<uint8_t> challenge;
    bool is_cross_origin;
  } kTestCases[] = {
      {
          webauthn::ClientDataRequestType::kWebAuthnGet,
          GetTestOrigin(),
          GetTestOrigin(),
          {1, 2, 3},
          false,
      },
      {
          webauthn::ClientDataRequestType::kPaymentGet,
          GetTestOrigin(),
          GetTestOrigin(),
          {1, 2, 3},
          false,
      },
      {
          webauthn::ClientDataRequestType::kWebAuthnCreate,
          GetTestOrigin(),
          url::Origin::Create(GURL("https://toplevel.example")),
          {1, 2, 3},
          false,
      },
  };

  size_t num = 0;
  for (const auto& test : kTestCases) {
    SCOPED_TRACE(num++);

    const std::string json =
        BuildClientDataJson({test.type, test.origin, test.top_origin,
                             test.challenge, test.is_cross_origin});

    const auto parsed =
        base::JSONReader::Read(json, base::JSON_PARSE_CHROMIUM_EXTENSIONS);
    ASSERT_TRUE(parsed.has_value());
    std::string type_key;
    std::string expected_type;
    switch (test.type) {
      case webauthn::ClientDataRequestType::kWebAuthnCreate:
        type_key = "type";
        expected_type = "webauthn.create";
        break;
      case webauthn::ClientDataRequestType::kWebAuthnGet:
        type_key = "type";
        expected_type = "webauthn.get";
        break;
      case webauthn::ClientDataRequestType::kPaymentGet:
        type_key = "type";
        expected_type = "payment.get";
        break;
    }
    ASSERT_TRUE(parsed->is_dict());
    EXPECT_EQ(*parsed->GetDict().FindString(type_key), expected_type);
    EXPECT_EQ(*parsed->GetDict().FindString("origin"), test.origin.Serialize());
    std::string expected_challenge;
    base::Base64UrlEncode(test.challenge,
                          base::Base64UrlEncodePolicy::OMIT_PADDING,
                          &expected_challenge);
    EXPECT_EQ(*parsed->GetDict().FindString("challenge"), expected_challenge);
    EXPECT_EQ(*parsed->GetDict().FindBool("crossOrigin"), test.is_cross_origin);
    if (test.is_cross_origin) {
      EXPECT_EQ(*parsed->GetDict().FindString("topOrigin"),
                test.top_origin.Serialize());
    } else {
      EXPECT_EQ(parsed->GetDict().FindString("topOrigin"), nullptr);
    }
  }
}

// Verify behavior for various combinations of origins and RP IDs.
TEST_F(AuthenticatorImplTest, MakeCredentialOriginAndRpIds) {
  std::vector<OriginClaimedAuthorityPair> tests;
  std::ranges::copy(kValidRpTestCases, std::back_inserter(tests));
  std::ranges::copy(kInvalidRpTestCases, std::back_inserter(tests));

  int test_case_count = 0;
  for (const auto& test_case : tests) {
    SCOPED_TRACE(
        base::StrCat({test_case.claimed_authority, " ", test_case.origin}));

    NavigateAndCommit(GURL(test_case.origin));
    PublicKeyCredentialCreationOptionsPtr options =
        GetTestPublicKeyCredentialCreationOptions();
    options->relying_party.id = test_case.claimed_authority;

    EXPECT_EQ(AuthenticatorMakeCredential(std::move(options)).status,
              test_case.expected_status);
    VerifyMakeCredentialOutcomeUkm(
        test_case_count++,
        (test_case.expected_status == AuthenticatorStatus::SUCCESS)
            ? MakeCredentialOutcome::kSuccess
            : MakeCredentialOutcome::kSecurityError,
        AuthenticationRequestMode::kModalWebAuthn);
  }
}

// Test that MakeCredential request times out with NOT_ALLOWED_ERROR if user
// verification is required for U2F devices.
TEST_F(AuthenticatorImplTest, MakeCredentialUserVerification) {
  NavigateAndCommit(GURL(kTestOrigin1));

  PublicKeyCredentialCreationOptionsPtr options =
      GetTestPublicKeyCredentialCreationOptions();
  options->authenticator_selection->user_verification_requirement =
      device::UserVerificationRequirement::kRequired;

  EXPECT_EQ(
      AuthenticatorMakeCredentialAndWaitForTimeout(std::move(options)).status,
      AuthenticatorStatus::NOT_ALLOWED_ERROR);
}

TEST_F(AuthenticatorImplTest, MakeCredentialResidentKeyUnsupported) {
  NavigateAndCommit(GURL(kTestOrigin1));

  PublicKeyCredentialCreationOptionsPtr options =
      GetTestPublicKeyCredentialCreationOptions();
  options->authenticator_selection->resident_key =
      device::ResidentKeyRequirement::kRequired;

  EXPECT_EQ(AuthenticatorMakeCredential(std::move(options)).status,
            AuthenticatorStatus::RESIDENT_CREDENTIALS_UNSUPPORTED);
  VerifyMakeCredentialOutcomeUkm(0, MakeCredentialOutcome::kRkNotSupported,
                                 AuthenticationRequestMode::kModalWebAuthn);
}

// Test that MakeCredential request times out with NOT_ALLOWED_ERROR if a
// platform authenticator is requested for U2F devices.
TEST_F(AuthenticatorImplTest, MakeCredentialPlatformAuthenticator) {
  NavigateAndCommit(GURL(kTestOrigin1));

  PublicKeyCredentialCreationOptionsPtr options =
      GetTestPublicKeyCredentialCreationOptions();
  options->authenticator_selection->authenticator_attachment =
      device::AuthenticatorAttachment::kPlatform;

  EXPECT_EQ(
      AuthenticatorMakeCredentialAndWaitForTimeout(std::move(options)).status,
      AuthenticatorStatus::NOT_ALLOWED_ERROR);
  VerifyMakeCredentialOutcomeUkm(0, MakeCredentialOutcome::kUiTimeout,
                                 AuthenticationRequestMode::kModalWebAuthn);
}

TEST_F(AuthenticatorImplTest, GetClientCapabilities) {
  base::test::ScopedFeatureList feature_list;
  feature_list.InitWithFeatureState(device::kWebAuthnImmediateGet, false);

  NavigateAndCommit(GURL(kTestOrigin1));

  ClientCapabilitiesList capabilities = AuthenticatorGetClientCapabilities();

  std::vector<std::string> capability_names;
  std::ranges::transform(
      capabilities, std::back_inserter(capability_names),
      [](const auto& capability) { return capability->name; });

  const std::vector<std::string_view> kRequiredCapabilities = {
      client_capabilities::kConditionalGet,
      client_capabilities::kHybridTransport,
      client_capabilities::kPasskeyPlatformAuthenticator,
      client_capabilities::kUserVerifyingPlatformAuthenticator,
      client_capabilities::kRelatedOrigins,
      client_capabilities::kConditionalCreate,
      client_capabilities::kSignalAllAcceptedCredentials,
      client_capabilities::kSignalCurrentUserDetails,
      client_capabilities::kSignalUnknownCredential,
  };

  // Ensure no extra capabilities
  EXPECT_EQ(kRequiredCapabilities.size(), capabilities.size());

  // Check that each required capability is present exactly once.
  for (const auto& capability : kRequiredCapabilities) {
    EXPECT_EQ(1u, static_cast<size_t>(
                      std::ranges::count(capability_names, capability)));
  }
}

TEST_F(AuthenticatorImplTest, GetClientCapabilities_HybridTransportSupported) {
  NavigateAndCommit(GURL(kTestOrigin1));
  EXPECT_CALL(*mock_adapter_, IsPresent()).WillOnce(::testing::Return(true));
  ClientCapabilitiesList capabilities = AuthenticatorGetClientCapabilities();
  ExpectCapability(capabilities, client_capabilities::kHybridTransport, true);
}

TEST_F(AuthenticatorImplTest,
       GetClientCapabilities_HybridTransport_NoBluetoothAdapter) {
  NavigateAndCommit(GURL(kTestOrigin1));
  EXPECT_CALL(*mock_adapter_, IsPresent()).WillOnce(::testing::Return(false));
  ClientCapabilitiesList capabilities = AuthenticatorGetClientCapabilities();
  ExpectCapability(capabilities, client_capabilities::kHybridTransport, false);
}

TEST_F(AuthenticatorImplTest,
       GetClientCapabilities_HybridTransport_LowEnergyNotSupported) {
  SetBluetoothLESupported(false);

  NavigateAndCommit(GURL(kTestOrigin1));
  EXPECT_CALL(*mock_adapter_, IsPresent).Times(0);
  ClientCapabilitiesList capabilities = AuthenticatorGetClientCapabilities();
  ExpectCapability(capabilities, client_capabilities::kHybridTransport, false);
}

TEST_F(AuthenticatorImplTest, GetClientCapabilities_RelatedOrigins) {
  NavigateAndCommit(GURL(kTestOrigin1));
  ClientCapabilitiesList capabilities = AuthenticatorGetClientCapabilities();
  ExpectCapability(capabilities, client_capabilities::kRelatedOrigins, true);
}

TEST_F(AuthenticatorImplTest, GetClientCapabilities_ConditionalCreate) {
  for (const bool enabled : {false, true}) {
    base::test::ScopedFeatureList feature_list;
    feature_list.InitWithFeatureState(device::kWebAuthnPasskeyUpgrade, enabled);
    NavigateAndCommit(GURL(kTestOrigin1));
    ClientCapabilitiesList capabilities = AuthenticatorGetClientCapabilities();
    ExpectCapability(capabilities, client_capabilities::kConditionalCreate,
                     enabled);
  }
}

TEST_F(AuthenticatorImplTest, GetClientCapabilities_ImmediateGet) {
  for (const bool enabled : {false, true}) {
    base::test::ScopedFeatureList feature_list;
    feature_list.InitWithFeatureState(device::kWebAuthnImmediateGet, enabled);
    NavigateAndCommit(GURL(kTestOrigin1));
    ClientCapabilitiesList capabilities = AuthenticatorGetClientCapabilities();
    ExpectCapability(capabilities, client_capabilities::kImmediateGet,
                     enabled ? std::optional<bool>(true) : std::nullopt);
  }
}

TEST_F(AuthenticatorImplTest, GetClientCapabilities_SignalApi) {
  NavigateAndCommit(GURL(kTestOrigin1));
  ClientCapabilitiesList capabilities = AuthenticatorGetClientCapabilities();
  ExpectCapability(capabilities,
                   client_capabilities::kSignalAllAcceptedCredentials, true);
  ExpectCapability(capabilities, client_capabilities::kRelatedOrigins, true);
  ExpectCapability(capabilities, client_capabilities::kRelatedOrigins, true);
}

// Parses its arguments as JSON and expects that all the keys in the first are
// also in the second, and with the same value.
static void CheckJSONIsSubsetOfJSON(std::string_view subset_str,
                                    std::string_view test_str) {
  std::optional<base::Value> subset =
      base::JSONReader::Read(subset_str, base::JSON_PARSE_CHROMIUM_EXTENSIONS);
  ASSERT_TRUE(subset);
  ASSERT_TRUE(subset->is_dict());
  const base::Value::Dict& subset_dict = subset->GetDict();
  std::optional<base::Value> test =
      base::JSONReader::Read(test_str, base::JSON_PARSE_CHROMIUM_EXTENSIONS);
  ASSERT_TRUE(test);
  ASSERT_TRUE(test->is_dict());
  const base::Value::Dict& test_dict = test->GetDict();

  for (auto item : subset_dict) {
    const base::Value* test_value = test_dict.Find(item.first);
    if (test_value == nullptr) {
      ADD_FAILURE() << item.first << " does not exist in the test dictionary";
      continue;
    }

    EXPECT_EQ(item.second, *test_value);
  }
}

// Test that client data serializes to JSON properly.
TEST(ClientDataSerializationTest, Register) {
  CheckJSONIsSubsetOfJSON(
      kTestRegisterClientDataJsonString,
      GetTestClientDataJSON(webauthn::ClientDataRequestType::kWebAuthnCreate));
}

TEST(ClientDataSerializationTest, Sign) {
  CheckJSONIsSubsetOfJSON(
      kTestSignClientDataJsonString,
      GetTestClientDataJSON(webauthn::ClientDataRequestType::kWebAuthnGet));
}

TEST_F(AuthenticatorImplTest, TestMakeCredentialTimeout) {
  base::HistogramTester histogram_tester;

  // Don't provide an authenticator tap so the request times out.
  virtual_device_factory_->mutable_state()->simulate_press_callback =
      base::BindLambdaForTesting(
          [&](device::VirtualFidoDevice* device) { return false; });
  NavigateAndCommit(GURL(kTestOrigin1));

  PublicKeyCredentialCreationOptionsPtr options =
      GetTestPublicKeyCredentialCreationOptions();

  EXPECT_EQ(
      AuthenticatorMakeCredentialAndWaitForTimeout(std::move(options)).status,
      AuthenticatorStatus::NOT_ALLOWED_ERROR);
  histogram_tester.ExpectUniqueSample(
      "WebAuthentication.MakeCredential.Result",
      AuthenticatorCommonImpl::CredentialRequestResult::kTimeout, 1);
  VerifyMakeCredentialOutcomeUkm(0, MakeCredentialOutcome::kUiTimeout,
                                 AuthenticationRequestMode::kModalWebAuthn);
}

// Verify behavior for various combinations of origins and RP IDs.
TEST_F(AuthenticatorImplTest, GetAssertionOriginAndRpIds) {
  // These instances should return security errors (for circumstances
  // that would normally crash the renderer).
  for (const OriginClaimedAuthorityPair& test_case : kInvalidRpTestCases) {
    SCOPED_TRACE(
        base::StrCat({test_case.claimed_authority, " ", test_case.origin}));

    NavigateAndCommit(GURL(test_case.origin));

    PublicKeyCredentialRequestOptionsPtr options =
        GetTestPublicKeyCredentialRequestOptions();
    options->relying_party_id = test_case.claimed_authority;

    EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
              test_case.expected_status);
  }
}

// Verify behavior for various combinations of origins and RP IDs.
TEST_F(AuthenticatorImplTest, ReportOriginAndRpIds) {
  // These instances should return security errors (for circumstances
  // that would normally crash the renderer).
  for (const OriginClaimedAuthorityPair& test_case : kInvalidRpTestCases) {
    SCOPED_TRACE(
        base::StrCat({test_case.claimed_authority, " ", test_case.origin}));

    NavigateAndCommit(GURL(test_case.origin));
    PublicKeyCredentialReportOptionsPtr options =
        GetTestPublicKeyCredentialReportOptions();
    options->relying_party_id = test_case.claimed_authority;
    options->unknown_credential_id = std::vector<uint8_t>(32, 0x0A);

    EXPECT_EQ(AuthenticatorReport(std::move(options)),
              test_case.expected_status);
  }
}

constexpr auto kValidAppIdCases = std::to_array<OriginClaimedAuthorityPair>({
    {"https://example.com", "https://example.com",
     AuthenticatorStatus::SUCCESS},
    {"https://www.example.com", "https://example.com",
     AuthenticatorStatus::SUCCESS},
    {"https://example.com", "https://www.example.com",
     AuthenticatorStatus::SUCCESS},
    {"https://example.com", "https://foo.bar.example.com",
     AuthenticatorStatus::SUCCESS},
    {"https://example.com", "https://foo.bar.example.com/foo/bar",
     AuthenticatorStatus::SUCCESS},
    {"https://google.com", "https://www.gstatic.com/securitykey/origins.json",
     AuthenticatorStatus::SUCCESS},
    {"https://www.google.com",
     "https://www.gstatic.com/securitykey/origins.json",
     AuthenticatorStatus::SUCCESS},
    {"https://www.google.com",
     "https://www.gstatic.com/securitykey/a/google.com/origins.json",
     AuthenticatorStatus::SUCCESS},
    {"https://accounts.google.com",
     "https://www.gstatic.com/securitykey/origins.json",
     AuthenticatorStatus::SUCCESS},
});

// Verify behavior for various combinations of origins and RP IDs.
TEST_F(AuthenticatorImplTest, AppIdExtensionValues) {
  for (const auto& test_case : kValidAppIdCases) {
    SCOPED_TRACE(
        base::StrCat({test_case.claimed_authority, " ", test_case.origin}));

    EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR,
              TryAuthenticationWithAppId(test_case.origin,
                                         test_case.claimed_authority));

    EXPECT_EQ(AuthenticatorStatus::SUCCESS,
              TryRegistrationWithAppIdExclude(test_case.origin,
                                              test_case.claimed_authority));
  }

  // All the invalid relying party test cases should also be invalid as AppIDs.
  for (const auto& test_case : kInvalidRpTestCases) {
    SCOPED_TRACE(
        base::StrCat({test_case.claimed_authority, " ", test_case.origin}));

    if (test_case.claimed_authority.empty()) {
      // In this case, no AppID is actually being tested.
      continue;
    }

    AuthenticatorStatus test_status = TryAuthenticationWithAppId(
        test_case.origin, test_case.claimed_authority);
    EXPECT_TRUE(test_status == AuthenticatorStatus::INVALID_DOMAIN ||
                test_status == test_case.expected_status);

    test_status = TryRegistrationWithAppIdExclude(test_case.origin,
                                                  test_case.claimed_authority);
    EXPECT_TRUE(test_status == AuthenticatorStatus::INVALID_DOMAIN ||
                test_status == test_case.expected_status);
  }
}

// Verify that a credential registered with U2F can be used via webauthn.
TEST_F(AuthenticatorImplTest, AppIdExtension) {
  NavigateAndCommit(GURL(kTestOrigin1));

  {
    // First, test that the appid extension isn't echoed at all when not
    // requested.
    PublicKeyCredentialRequestOptionsPtr options =
        GetTestPublicKeyCredentialRequestOptions();
    ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
        options->allow_credentials[0].id, kTestRelyingPartyId));

    GetAssertionResult result = AuthenticatorGetAssertion(std::move(options));
    ASSERT_EQ(result.status, AuthenticatorStatus::SUCCESS);
    EXPECT_EQ(result.response->extensions->echo_appid_extension, false);
  }

  {
    // Second, test that the appid extension is echoed, but is false, when appid
    // is requested but not used.
    ResetVirtualDevice();
    PublicKeyCredentialRequestOptionsPtr options =
        GetTestPublicKeyCredentialRequestOptions();
    ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
        options->allow_credentials[0].id, kTestRelyingPartyId));

    // This AppID won't be used because the RP ID will be tried (successfully)
    // first.
    options->extensions->appid = kTestOrigin1;

    GetAssertionResult result = AuthenticatorGetAssertion(std::move(options));
    ASSERT_EQ(result.status, AuthenticatorStatus::SUCCESS);
    EXPECT_EQ(result.response->extensions->echo_appid_extension, true);
    EXPECT_EQ(result.response->extensions->appid_extension, false);
  }

  {
    // Lastly, when used, the appid extension result should be "true".
    ResetVirtualDevice();
    PublicKeyCredentialRequestOptionsPtr options =
        GetTestPublicKeyCredentialRequestOptions();
    // Inject a registration for the URL (which is a U2F AppID).
    ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
        options->allow_credentials[0].id, kTestOrigin1));

    options->extensions->appid = kTestOrigin1;

    GetAssertionResult result = AuthenticatorGetAssertion(std::move(options));
    ASSERT_EQ(result.status, AuthenticatorStatus::SUCCESS);
    EXPECT_EQ(result.response->extensions->echo_appid_extension, true);
    EXPECT_EQ(result.response->extensions->appid_extension, true);
  }

  {
    // AppID should still work when the authenticator supports credProtect.
    ResetVirtualDevice();
    device::VirtualCtap2Device::Config config;
    config.u2f_support = true;
    config.pin_support = true;
    config.resident_key_support = true;
    config.cred_protect_support = true;

    virtual_device_factory_->SetCtap2Config(config);

    // Inject a registration for the URL (which is a U2F AppID).
    PublicKeyCredentialRequestOptionsPtr options =
        GetTestPublicKeyCredentialRequestOptions();
    ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
        options->allow_credentials[0].id, kTestOrigin1));

    options->extensions->appid = kTestOrigin1;

    GetAssertionResult result = AuthenticatorGetAssertion(std::move(options));
    ASSERT_EQ(result.status, AuthenticatorStatus::SUCCESS);
    EXPECT_EQ(result.response->extensions->echo_appid_extension, true);
    EXPECT_EQ(result.response->extensions->appid_extension, true);
  }
}

TEST_F(AuthenticatorImplTest, AppIdExcludeExtension) {
  NavigateAndCommit(GURL(kTestOrigin1));

  // Attempt to register a credential using the appidExclude extension. It
  // should fail when the registration already exists on the authenticator.
  for (bool credential_already_exists : {false, true}) {
    SCOPED_TRACE(credential_already_exists);

    for (bool is_ctap2 : {false, true}) {
      SCOPED_TRACE(is_ctap2);

      ResetVirtualDevice();
      virtual_device_factory_->SetSupportedProtocol(
          is_ctap2 ? device::ProtocolVersion::kCtap2
                   : device::ProtocolVersion::kU2f);

      PublicKeyCredentialCreationOptionsPtr options =
          GetTestPublicKeyCredentialCreationOptions();
      options->appid_exclude = kTestOrigin1;
      options->exclude_credentials = GetTestCredentials();

      if (credential_already_exists) {
        ASSERT_TRUE(
            virtual_device_factory_->mutable_state()->InjectRegistration(
                options->exclude_credentials[0].id, kTestOrigin1));
      }

      MakeCredentialResult result =
          AuthenticatorMakeCredential(std::move(options));

      if (credential_already_exists) {
        ASSERT_EQ(result.status, AuthenticatorStatus::CREDENTIAL_EXCLUDED);
      } else {
        ASSERT_EQ(result.status, AuthenticatorStatus::SUCCESS);
      }
    }
  }

  {
    // Using appidExclude with an empty exclude list previously caused a crash.
    // See https://bugs.chromium.org/p/chromium/issues/detail?id=1054499.
    virtual_device_factory_->SetSupportedProtocol(
        device::ProtocolVersion::kCtap2);
    PublicKeyCredentialCreationOptionsPtr options =
        GetTestPublicKeyCredentialCreationOptions();
    options->appid_exclude = kTestOrigin1;
    options->exclude_credentials.clear();
    EXPECT_EQ(AuthenticatorMakeCredential(std::move(options)).status,
              AuthenticatorStatus::SUCCESS);
  }

  {
    // Also test the case where all credential IDs are eliminated because of
    // their size.
    device::VirtualCtap2Device::Config config;
    config.max_credential_count_in_list = 1;
    config.max_credential_id_length = 1;
    virtual_device_factory_->SetCtap2Config(config);

    PublicKeyCredentialCreationOptionsPtr options =
        GetTestPublicKeyCredentialCreationOptions();
    options->appid_exclude = kTestOrigin1;
    options->exclude_credentials = GetTestCredentials();

    for (const auto& cred : options->exclude_credentials) {
      ASSERT_GT(cred.id.size(), config.max_credential_id_length);
    }

    EXPECT_EQ(AuthenticatorMakeCredential(std::move(options)).status,
              AuthenticatorStatus::SUCCESS);
  }
}

TEST_F(AuthenticatorImplTest, TestGetAssertionTimeout) {
  // The VirtualFidoAuthenticator simulates a tap immediately after it gets the
  // request. Replace by the real discovery that will wait until timeout.
  ReplaceDiscoveryFactory(std::make_unique<device::FidoDiscoveryFactory>());

  NavigateAndCommit(GURL(kTestOrigin1));
  base::HistogramTester histogram_tester;
  PublicKeyCredentialRequestOptionsPtr options =
      GetTestPublicKeyCredentialRequestOptions();

  EXPECT_EQ(
      AuthenticatorGetAssertionAndWaitForTimeout(std::move(options)).status,
      AuthenticatorStatus::NOT_ALLOWED_ERROR);
  histogram_tester.ExpectUniqueSample(
      "WebAuthentication.GetAssertion.Result",
      AuthenticatorCommonImpl::CredentialRequestResult::kTimeout, 1);
  VerifyGetAssertionOutcomeUkm(0, GetAssertionOutcome::kUiTimeout,
                               AuthenticationRequestMode::kModalWebAuthn);
}

TEST_F(AuthenticatorImplTest, OversizedCredentialId) {
  // 255 is the maximum size of a U2F credential ID. We also test one greater
  // (256) to ensure that nothing untoward happens.
  const std::vector<size_t> kSizes = {255, 256};

  for (const size_t size : kSizes) {
    SCOPED_TRACE(size);

    NavigateAndCommit(GURL(kTestOrigin1));
    PublicKeyCredentialRequestOptionsPtr options =
        GetTestPublicKeyCredentialRequestOptions();
    device::PublicKeyCredentialDescriptor credential;
    credential.credential_type = device::CredentialType::kPublicKey;
    credential.id.resize(size);
    credential.transports.emplace(
        device::FidoTransportProtocol::kUsbHumanInterfaceDevice);

    const bool should_be_valid = size < 256;
    if (should_be_valid) {
      ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
          credential.id, kTestRelyingPartyId));
    }

    options->allow_credentials.emplace_back(credential);

    EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
              should_be_valid ? AuthenticatorStatus::SUCCESS
                              : AuthenticatorStatus::NOT_ALLOWED_ERROR);
  }
}

TEST_F(AuthenticatorImplTest, NoSilentAuthenticationForCable) {
  // https://crbug.com/954355
  NavigateAndCommit(GURL(kTestOrigin1));

  for (bool is_cable_device : {false, true}) {
    ResetVirtualDevice();
    device::VirtualCtap2Device::Config config;
    config.reject_silent_authentication_requests = true;
    virtual_device_factory_->SetCtap2Config(config);

    PublicKeyCredentialRequestOptionsPtr options =
        GetTestPublicKeyCredentialRequestOptions();
    options->allow_credentials = GetTestCredentials(/*num_credentials=*/2);
    options->extensions->cable_authentication_data = GetTestCableExtension();

    if (is_cable_device) {
      virtual_device_factory_->SetTransport(
          device::FidoTransportProtocol::kHybrid);
      for (auto& cred : options->allow_credentials) {
        cred.transports.clear();
        cred.transports.emplace(device::FidoTransportProtocol::kHybrid);
      }
    }

    ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
        options->allow_credentials[0].id, kTestRelyingPartyId));

    // If a caBLE device is not simulated then silent requests should be used.
    // The virtual device will return an error because
    // |reject_silent_authentication_requests| is true and then it'll
    // immediately resolve the touch request.
    EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
              is_cable_device ? AuthenticatorStatus::SUCCESS
                              : AuthenticatorStatus::NOT_ALLOWED_ERROR);
  }
}

TEST_F(AuthenticatorImplTest, GuessAtTransportsForCable) {
  // Even without any reported transports, if the transaction was done over
  // hybrid, we should guess at the transports and report them.

  NavigateAndCommit(GURL(kTestOrigin1));

  ResetVirtualDevice();
  device::VirtualCtap2Device::Config config;
  config.include_transports_in_attestation_certificate = false;
  virtual_device_factory_->SetCtap2Config(config);
  virtual_device_factory_->SetTransport(device::FidoTransportProtocol::kHybrid);

  const auto result = AuthenticatorMakeCredential();
  ASSERT_EQ(result.status, AuthenticatorStatus::SUCCESS);
  EXPECT_THAT(
      result.response->transports,
      testing::UnorderedElementsAre(device::FidoTransportProtocol::kHybrid,
                                    device::FidoTransportProtocol::kInternal));
}

TEST_F(AuthenticatorImplTest, TestGetAssertionU2fDeviceBackwardsCompatibility) {
  NavigateAndCommit(GURL(kTestOrigin1));
  PublicKeyCredentialRequestOptionsPtr options =
      GetTestPublicKeyCredentialRequestOptions();
  // Inject credential ID to the virtual device so that successful sign in is
  // possible.
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
      options->allow_credentials[0].id, kTestRelyingPartyId));

  EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
            AuthenticatorStatus::SUCCESS);
}

TEST_F(AuthenticatorImplTest, GetAssertionWithEmptyAllowCredentials) {
  NavigateAndCommit(GURL(kTestOrigin1));
  PublicKeyCredentialRequestOptionsPtr options =
      GetTestPublicKeyCredentialRequestOptions();
  options->allow_credentials.clear();

  EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
            AuthenticatorStatus::RESIDENT_CREDENTIALS_UNSUPPORTED);
  VerifyGetAssertionOutcomeUkm(0, GetAssertionOutcome::kRkNotSupported,
                               AuthenticationRequestMode::kModalWebAuthn);
}

TEST_F(AuthenticatorImplTest, MakeCredentialAlreadyRegistered) {
  NavigateAndCommit(GURL(kTestOrigin1));
  PublicKeyCredentialCreationOptionsPtr options =
      GetTestPublicKeyCredentialCreationOptions();

  // Exclude the one already registered credential.
  options->exclude_credentials = GetTestCredentials();
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
      options->exclude_credentials[0].id, kTestRelyingPartyId));

  EXPECT_EQ(AuthenticatorMakeCredential(std::move(options)).status,
            AuthenticatorStatus::CREDENTIAL_EXCLUDED);
  VerifyMakeCredentialOutcomeUkm(0, MakeCredentialOutcome::kCredentialExcluded,
                                 AuthenticationRequestMode::kModalWebAuthn);
}

TEST_F(AuthenticatorImplTest, MakeCredentialPendingRequest) {
  NavigateAndCommit(GURL(kTestOrigin1));
  mojo::Remote<blink::mojom::Authenticator> authenticator =
      ConnectToAuthenticator();

  // Make first request.
  PublicKeyCredentialCreationOptionsPtr options =
      GetTestPublicKeyCredentialCreationOptions();
  TestMakeCredentialFuture future;
  authenticator->MakeCredential(std::move(options), future.GetCallback());

  // Make second request.
  // TODO(crbug.com/41355992): Rework to ensure there are potential race
  // conditions once we have VirtualAuthenticatorEnvironment.
  PublicKeyCredentialCreationOptionsPtr options2 =
      GetTestPublicKeyCredentialCreationOptions();
  TestMakeCredentialFuture future2;
  authenticator->MakeCredential(std::move(options2), future2.GetCallback());
  EXPECT_TRUE(future2.Wait());

  EXPECT_EQ(AuthenticatorStatus::PENDING_REQUEST, std::get<0>(future2.Get()));

  EXPECT_TRUE(future.Wait());
}

TEST_F(AuthenticatorImplTest, GetAssertionPendingRequest) {
  NavigateAndCommit(GURL(kTestOrigin1));
  mojo::Remote<blink::mojom::Authenticator> authenticator =
      ConnectToAuthenticator();

  // Make first request.
  GetCredentialOptionsPtr options = GetTestGetCredentialOptions();
  TestGetCredentialFuture future;
  authenticator->GetCredential(std::move(options), future.GetCallback());

  // Make second request.
  // TODO(crbug.com/41355992): Rework to ensure there are potential race
  // conditions once we have VirtualAuthenticatorEnvironment.
  GetCredentialOptionsPtr options2 = GetTestGetCredentialOptions();
  TestGetCredentialFuture future2;
  authenticator->GetCredential(std::move(options2), future2.GetCallback());
  EXPECT_TRUE(future2.Wait());

  EXPECT_EQ(AuthenticatorStatus::PENDING_REQUEST,
            future2.Get()->get_get_assertion_response()->status);

  EXPECT_TRUE(future.Wait());
}

TEST_F(AuthenticatorImplTest, ReportPendingRequest) {
  NavigateAndCommit(GURL(kTestOrigin1));
  mojo::Remote<blink::mojom::Authenticator> authenticator =
      ConnectToAuthenticator();

  // Make first request.
  GetCredentialOptionsPtr options = GetTestGetCredentialOptions();
  TestGetCredentialFuture future;
  authenticator->GetCredential(std::move(options), future.GetCallback());

  // Make second request.
  PublicKeyCredentialReportOptionsPtr options2 =
      GetTestPublicKeyCredentialReportOptions();
  TestReportFuture future2;
  authenticator->Report(std::move(options2), future2.GetCallback());
  EXPECT_TRUE(future2.Wait());

  EXPECT_EQ(AuthenticatorStatus::PENDING_REQUEST, std::get<0>(future2.Get()));

  EXPECT_TRUE(future.Wait());
}

TEST_F(AuthenticatorImplTest, NavigationDuringOperation) {
  NavigateAndCommit(GURL(kTestOrigin1));
  mojo::Remote<blink::mojom::Authenticator> authenticator =
      ConnectToAuthenticator();

  base::RunLoop run_loop;
  authenticator.set_disconnect_handler(run_loop.QuitClosure());

  // Make first request.
  GetCredentialOptionsPtr options = GetTestGetCredentialOptions();
  TestGetCredentialFuture future;
  authenticator->GetCredential(std::move(options), future.GetCallback());

  // Simulate a navigation while waiting for the user to press the token.
  virtual_device_factory_->mutable_state()->simulate_press_callback =
      base::BindLambdaForTesting([&](device::VirtualFidoDevice* device) {
        base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
            FROM_HERE, base::BindLambdaForTesting(
                           [&]() { NavigateAndCommit(GURL(kTestOrigin2)); }));
        return false;
      });

  run_loop.Run();
}

TEST_F(AuthenticatorImplTest, InvalidResponse) {
  virtual_device_factory_->mutable_state()->simulate_invalid_response = true;
  NavigateAndCommit(GURL(kTestOrigin1));

  {
    PublicKeyCredentialRequestOptionsPtr options =
        GetTestPublicKeyCredentialRequestOptions();
    EXPECT_EQ(
        AuthenticatorGetAssertionAndWaitForTimeout(std::move(options)).status,
        AuthenticatorStatus::NOT_ALLOWED_ERROR);
  }

  {
    PublicKeyCredentialCreationOptionsPtr options =
        GetTestPublicKeyCredentialCreationOptions();
    EXPECT_EQ(
        AuthenticatorMakeCredentialAndWaitForTimeout(std::move(options)).status,
        AuthenticatorStatus::NOT_ALLOWED_ERROR);
  }
}

TEST_F(AuthenticatorImplTest, Ctap2AssertionWithUnknownCredential) {
  NavigateAndCommit(GURL(kTestOrigin1));

  for (bool return_immediate_invalid_credential_error : {false, true}) {
    SCOPED_TRACE(::testing::Message()
                 << "return_immediate_invalid_credential_error="
                 << return_immediate_invalid_credential_error);

    device::VirtualCtap2Device::Config config;
    config.return_immediate_invalid_credential_error =
        return_immediate_invalid_credential_error;
    virtual_device_factory_->SetCtap2Config(config);

    bool pressed = false;
    virtual_device_factory_->mutable_state()->simulate_press_callback =
        base::BindRepeating(
            [](bool* flag, device::VirtualFidoDevice* device) {
              *flag = true;
              return true;
            },
            &pressed);

    EXPECT_EQ(
        AuthenticatorGetAssertion(GetTestPublicKeyCredentialRequestOptions())
            .status,
        AuthenticatorStatus::NOT_ALLOWED_ERROR);
    VerifyGetAssertionOutcomeUkm(0,
                                 GetAssertionOutcome::kCredentialNotRecognized,
                                 AuthenticationRequestMode::kModalWebAuthn);
    // The user must have pressed the authenticator for the operation to
    // resolve.
    EXPECT_TRUE(pressed);
  }
}

TEST_F(AuthenticatorImplTest, GetAssertionResponseWithAttestedCredentialData) {
  device::VirtualCtap2Device::Config config;
  config.return_attested_cred_data_in_get_assertion_response = true;
  virtual_device_factory_->SetCtap2Config(config);
  PublicKeyCredentialRequestOptionsPtr options =
      GetTestPublicKeyCredentialRequestOptions();
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
      options->allow_credentials[0].id, kTestRelyingPartyId));

  NavigateAndCommit(GURL(kTestOrigin1));

  EXPECT_EQ(
      AuthenticatorGetAssertionAndWaitForTimeout(std::move(options)).status,
      AuthenticatorStatus::NOT_ALLOWED_ERROR);
}

#if BUILDFLAG(IS_WIN)
TEST_F(AuthenticatorImplTest, Win_IsUVPAA) {
  virtual_device_factory_->set_discover_win_webauthn_api_authenticator(true);
  NavigateAndCommit(GURL(kTestOrigin1));
  mojo::Remote<blink::mojom::Authenticator> authenticator =
      ConnectToAuthenticator();

  for (const bool enable_win_webauthn_api : {false, true}) {
    SCOPED_TRACE(enable_win_webauthn_api ? "enable_win_webauthn_api"
                                         : "!enable_win_webauthn_api");
    for (const bool is_uvpaa : {false, true}) {
      SCOPED_TRACE(is_uvpaa ? "is_uvpaa" : "!is_uvpaa");
      for (bool is_off_the_record : {true, false}) {
        SCOPED_TRACE(is_off_the_record ? "off the record" : "on the record");
        static_cast<TestBrowserContext*>(GetBrowserContext())
            ->set_is_off_the_record(is_off_the_record);
        fake_win_webauthn_api_.set_available(enable_win_webauthn_api);
        fake_win_webauthn_api_.set_is_uvpaa(is_uvpaa);
        EXPECT_EQ(AuthenticatorIsUvpaa(), enable_win_webauthn_api && is_uvpaa);
      }
    }
  }
}
#endif  // BUILDFLAG(IS_WIN)

#if BUILDFLAG(IS_CHROMEOS)
TEST_F(AuthenticatorImplTest, IsUVPAA) {
  NavigateAndCommit(GURL(kTestOrigin1));
  EXPECT_FALSE(AuthenticatorIsUvpaa());
}
#endif  // BUILDFLAG(IS_CHROMEOS)

enum class EnterprisePolicy {
  LISTED,
  NOT_LISTED,
};

enum class AttestationType {
  ANY,
  NONE,
  NONE_WITH_NONZERO_AAGUID,
  U2F,
  SELF,
  SELF_WITH_NONZERO_AAGUID,
  PACKED,
};

const char* AttestationConveyancePreferenceToString(
    AttestationConveyancePreference v) {
  switch (v) {
    case AttestationConveyancePreference::NONE:
      return "none";
    case AttestationConveyancePreference::INDIRECT:
      return "indirect";
    case AttestationConveyancePreference::DIRECT:
      return "direct";
    case AttestationConveyancePreference::ENTERPRISE:
      return "enterprise";
    default:
      NOTREACHED();
  }
}

const char* AttestationConveyancePreferenceToString(
    device::AttestationConveyancePreference v) {
  switch (v) {
    case device::AttestationConveyancePreference::kNone:
      return "none";
    case device::AttestationConveyancePreference::kIndirect:
      return "indirect";
    case device::AttestationConveyancePreference::kDirect:
      return "direct";
    case device::AttestationConveyancePreference::
        kEnterpriseIfRPListedOnAuthenticator:
      return "enterprise(ep=1)";
    case device::AttestationConveyancePreference::kEnterpriseApprovedByBrowser:
      return "enterprise(ep=2)";
  }
}

// A test class that installs and removes an
// |TestAuthenticatorContentBrowserClient| automatically and can run tests
// against simulated attestation results.
class AuthenticatorContentBrowserClientTest : public AuthenticatorImplTest {
 public:
  AuthenticatorContentBrowserClientTest() = default;

  AuthenticatorContentBrowserClientTest(
      const AuthenticatorContentBrowserClientTest&) = delete;
  AuthenticatorContentBrowserClientTest& operator=(
      const AuthenticatorContentBrowserClientTest&) = delete;

  struct TestCase {
    AttestationConveyancePreference attestation_requested;
    EnterprisePolicy enterprise_policy;
    AuthenticatorStatus expected_status;
    AttestationType expected_attestation;
    std::string_view expected_certificate_substring;
  };

  void SetUp() override {
    AuthenticatorImplTest::SetUp();
    old_client_ = SetBrowserClientForTesting(&test_client_);
  }

  void TearDown() override {
    SetBrowserClientForTesting(old_client_);
    AuthenticatorImplTest::TearDown();
  }

  void RunTestCases(const std::vector<TestCase>& tests) {
    for (size_t i = 0; i < tests.size(); i++) {
      const auto& test = tests[i];
      SCOPED_TRACE(test.enterprise_policy == EnterprisePolicy::LISTED
                       ? "individual attestation"
                       : "no individual attestation");
      SCOPED_TRACE(
          AttestationConveyancePreferenceToString(test.attestation_requested));
      SCOPED_TRACE(i);

      test_client_.GetTestWebAuthenticationDelegate()
          ->permit_individual_attestation =
          test.enterprise_policy == EnterprisePolicy::LISTED;

      PublicKeyCredentialCreationOptionsPtr options =
          GetTestPublicKeyCredentialCreationOptions();
      options->relying_party.id = "example.com";
      options->timeout = base::Seconds(1);
      options->attestation =
          ConvertAttestationConveyancePreference(test.attestation_requested);

      MakeCredentialResult result =
          AuthenticatorMakeCredential(std::move(options));
      EXPECT_EQ(result.status, test.expected_status);

      if (test.expected_status != AuthenticatorStatus::SUCCESS) {
        ASSERT_EQ(AttestationType::ANY, test.expected_attestation);
        continue;
      }

      const device::AuthenticatorData auth_data =
          AuthDataFromMakeCredentialResponse(result.response);

      std::optional<Value> attestation_value =
          Reader::Read(result.response->attestation_object);
      ASSERT_TRUE(attestation_value);
      ASSERT_TRUE(attestation_value->is_map());
      const auto& attestation = attestation_value->GetMap();

      switch (test.expected_attestation) {
        case AttestationType::ANY:
          ASSERT_TRUE(test.expected_certificate_substring.empty());
          break;

        case AttestationType::NONE:
          ASSERT_TRUE(test.expected_certificate_substring.empty());
          ExpectMapHasKeyWithStringValue(attestation, "fmt", "none");
          EXPECT_TRUE(auth_data.attested_data()->IsAaguidZero());
          break;

        case AttestationType::NONE_WITH_NONZERO_AAGUID:
          ASSERT_TRUE(test.expected_certificate_substring.empty());
          ExpectMapHasKeyWithStringValue(attestation, "fmt", "none");
          EXPECT_FALSE(auth_data.attested_data()->IsAaguidZero());
          break;

        case AttestationType::U2F:
          ExpectMapHasKeyWithStringValue(attestation, "fmt", "fido-u2f");
          if (!test.expected_certificate_substring.empty()) {
            ExpectCertificateContainingSubstring(
                attestation, test.expected_certificate_substring);
          }
          break;

        case AttestationType::PACKED:
          ExpectMapHasKeyWithStringValue(attestation, "fmt", "packed");
          if (!test.expected_certificate_substring.empty()) {
            ExpectCertificateContainingSubstring(
                attestation, test.expected_certificate_substring);
          }
          break;

        case AttestationType::SELF: {
          ASSERT_TRUE(test.expected_certificate_substring.empty());
          ExpectMapHasKeyWithStringValue(attestation, "fmt", "packed");

          // A self-attestation should not include an X.509 chain nor ECDAA key.
          const auto attestation_statement_it =
              attestation.find(Value("attStmt"));
          ASSERT_TRUE(attestation_statement_it != attestation.end());
          ASSERT_TRUE(attestation_statement_it->second.is_map());
          const auto& attestation_statement =
              attestation_statement_it->second.GetMap();

          ASSERT_TRUE(attestation_statement.find(Value("x5c")) ==
                      attestation_statement.end());
          ASSERT_TRUE(attestation_statement.find(Value("ecdaaKeyId")) ==
                      attestation_statement.end());
          EXPECT_TRUE(auth_data.attested_data()->IsAaguidZero());
          break;
        }
        case AttestationType::SELF_WITH_NONZERO_AAGUID: {
          ASSERT_TRUE(test.expected_certificate_substring.empty());
          ExpectMapHasKeyWithStringValue(attestation, "fmt", "packed");

          // A self-attestation should not include an X.509 chain nor ECDAA key.
          const auto attestation_statement_it =
              attestation.find(Value("attStmt"));
          ASSERT_TRUE(attestation_statement_it != attestation.end());
          ASSERT_TRUE(attestation_statement_it->second.is_map());
          const auto& attestation_statement =
              attestation_statement_it->second.GetMap();

          ASSERT_TRUE(attestation_statement.find(Value("x5c")) ==
                      attestation_statement.end());
          ASSERT_TRUE(attestation_statement.find(Value("ecdaaKeyId")) ==
                      attestation_statement.end());
          EXPECT_FALSE(auth_data.attested_data()->IsAaguidZero());
          break;
        }
      }
    }
  }

 protected:
  TestAuthenticatorContentBrowserClient test_client_;

  // Expects that |map| contains the given key with a string-value equal to
  // |expected|.
  static void ExpectMapHasKeyWithStringValue(const Value::MapValue& map,
                                             const char* key,
                                             const char* expected) {
    const auto it = map.find(Value(key));
    ASSERT_TRUE(it != map.end()) << "No such key '" << key << "'";
    const auto& value = it->second;
    EXPECT_TRUE(value.is_string())
        << "Value of '" << key << "' has type "
        << static_cast<int>(value.type()) << ", but expected to find a string";
    EXPECT_EQ(std::string(expected), value.GetString())
        << "Value of '" << key << "' is '" << value.GetString()
        << "', but expected to find '" << expected << "'";
  }

  // Asserts that the webauthn attestation CBOR map in |attestation| contains a
  // single X.509 certificate containing |substring|.
  static void ExpectCertificateContainingSubstring(
      const Value::MapValue& attestation,
      std::string_view substring) {
    const auto& attestation_statement_it = attestation.find(Value("attStmt"));
    ASSERT_TRUE(attestation_statement_it != attestation.end());
    ASSERT_TRUE(attestation_statement_it->second.is_map());
    const auto& attestation_statement =
        attestation_statement_it->second.GetMap();
    const auto& x5c_it = attestation_statement.find(Value("x5c"));
    ASSERT_TRUE(x5c_it != attestation_statement.end());
    ASSERT_TRUE(x5c_it->second.is_array());
    const auto& x5c = x5c_it->second.GetArray();
    ASSERT_EQ(1u, x5c.size());
    ASSERT_TRUE(x5c[0].is_bytestring());
    std::string_view cert = x5c[0].GetBytestringAsString();
    EXPECT_TRUE(cert.find(substring) != cert.npos);
  }

  raw_ptr<ContentBrowserClient> old_client_ = nullptr;
};

TEST_F(AuthenticatorContentBrowserClientTest, MakeCredentialTLSError) {
  NavigateAndCommit(GURL(kTestOrigin1));
  test_client_.is_webauthn_security_level_acceptable = false;
  PublicKeyCredentialCreationOptionsPtr options =
      GetTestPublicKeyCredentialCreationOptions();
  EXPECT_EQ(AuthenticatorMakeCredential(std::move(options)).status,
            AuthenticatorStatus::CERTIFICATE_ERROR);
  VerifyMakeCredentialOutcomeUkm(0, MakeCredentialOutcome::kOtherFailure,
                                 AuthenticationRequestMode::kModalWebAuthn);
}

TEST_F(AuthenticatorContentBrowserClientTest, GetAssertionTLSError) {
  NavigateAndCommit(GURL(kTestOrigin1));
  test_client_.is_webauthn_security_level_acceptable = false;
  PublicKeyCredentialRequestOptionsPtr options =
      GetTestPublicKeyCredentialRequestOptions();
  EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
            AuthenticatorStatus::CERTIFICATE_ERROR);
  VerifyGetAssertionOutcomeUkm(0, GetAssertionOutcome::kOtherFailure,
                               AuthenticationRequestMode::kModalWebAuthn);
}

TEST_F(AuthenticatorContentBrowserClientTest,
       MakeCredentialSkipTLSCheckWithVirtualEnvironment) {
  NavigateAndCommit(GURL(kTestOrigin1));
  content::AuthenticatorEnvironment::GetInstance()
      ->EnableVirtualAuthenticatorFor(
          static_cast<content::RenderFrameHostImpl*>(main_rfh())
              ->frame_tree_node(),
          /*enable_ui=*/false);
  test_client_.is_webauthn_security_level_acceptable = false;
  PublicKeyCredentialCreationOptionsPtr options =
      GetTestPublicKeyCredentialCreationOptions();
  EXPECT_EQ(AuthenticatorMakeCredential(std::move(options)).status,
            AuthenticatorStatus::SUCCESS);
}

TEST_F(AuthenticatorContentBrowserClientTest,
       GetAssertionSkipTLSCheckWithVirtualEnvironment) {
  NavigateAndCommit(GURL(kTestOrigin1));
  content::AuthenticatorEnvironment::GetInstance()
      ->EnableVirtualAuthenticatorFor(
          static_cast<content::RenderFrameHostImpl*>(main_rfh())
              ->frame_tree_node(),
          /*enable_ui=*/false);
  test_client_.is_webauthn_security_level_acceptable = false;
  PublicKeyCredentialRequestOptionsPtr options =
      GetTestPublicKeyCredentialRequestOptions();
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
      options->allow_credentials[0].id, kTestRelyingPartyId));
  EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
            AuthenticatorStatus::SUCCESS);
}

TEST_F(AuthenticatorContentBrowserClientTest, TestGetAssertionCancel) {
  NavigateAndCommit(GURL(kTestOrigin1));
  test_client_.simulate_user_cancelled_ = true;
  base::HistogramTester histogram_tester;

  EXPECT_EQ(AuthenticatorGetAssertion().status,
            AuthenticatorStatus::NOT_ALLOWED_ERROR);
  histogram_tester.ExpectUniqueSample(
      "WebAuthentication.GetAssertion.Result",
      AuthenticatorCommonImpl::CredentialRequestResult::kUserCancelled, 1);
  VerifyGetAssertionOutcomeUkm(0, GetAssertionOutcome::kUserCancellation,
                               AuthenticationRequestMode::kModalWebAuthn);
}

TEST_F(AuthenticatorContentBrowserClientTest, TestMakeCredentialCancel) {
  NavigateAndCommit(GURL(kTestOrigin1));
  test_client_.simulate_user_cancelled_ = true;
  base::HistogramTester histogram_tester;

  EXPECT_EQ(AuthenticatorMakeCredential().status,
            AuthenticatorStatus::NOT_ALLOWED_ERROR);
  histogram_tester.ExpectUniqueSample(
      "WebAuthentication.MakeCredential.Result",
      AuthenticatorCommonImpl::CredentialRequestResult::kUserCancelled, 1);
  VerifyMakeCredentialOutcomeUkm(0, MakeCredentialOutcome::kUserCancellation,
                                 AuthenticationRequestMode::kModalWebAuthn);
}

// Tests that the enclave authenticator should only be discovered for make
// credential requests it can fulfill.
TEST_F(AuthenticatorContentBrowserClientTest,
       DiscoverEnclaveAuthenticatorMakeCredential) {
  NavigateAndCommit(GURL(kTestOrigin1));
  struct TestCase {
    bool available;
    device::AuthenticatorAttachment attachment;
    bool expected_discovered;
  } kTestCases[] = {
      {false, device::AuthenticatorAttachment::kAny, false},
      {true, device::AuthenticatorAttachment::kCrossPlatform, false},
      {true, device::AuthenticatorAttachment::kAny, true},
      {true, device::AuthenticatorAttachment::kPlatform, true},
  };
  for (const auto& test_case : kTestCases) {
    SCOPED_TRACE(testing::Message() << "available=" << test_case.available);
    SCOPED_TRACE(testing::Message()
                 << "attachment=" << static_cast<int>(test_case.attachment));
    test_client_.GetTestWebAuthenticationDelegate()
        ->browser_provided_passkeys_available = test_case.available;
    PublicKeyCredentialCreationOptionsPtr options =
        GetTestPublicKeyCredentialCreationOptions();
    options->authenticator_selection->authenticator_attachment =
        test_case.attachment;
    AuthenticatorMakeCredential(std::move(options));
    ASSERT_TRUE(
        test_client_.enclave_authenticator_should_be_discovered_.has_value());
    EXPECT_EQ(*test_client_.enclave_authenticator_should_be_discovered_,
              test_case.expected_discovered);
  }
}

// Tests that the enclave authenticator should only be discovered for get
// assertion requests it can fulfill.
TEST_F(AuthenticatorContentBrowserClientTest,
       DiscoverEnclaveAuthenticatorGetAssertion) {
  NavigateAndCommit(GURL(kTestOrigin1));
  device::PublicKeyCredentialDescriptor internal_cred(
      device::CredentialType::kPublicKey,
      std::vector<uint8_t>(kTestCredentialIdLength, 1),
      {device::FidoTransportProtocol::kInternal});
  device::PublicKeyCredentialDescriptor sk_cred(
      device::CredentialType::kPublicKey,
      std::vector<uint8_t>(kTestCredentialIdLength, 2),
      {device::FidoTransportProtocol::kUsbHumanInterfaceDevice});
  device::PublicKeyCredentialDescriptor unknown_cred(
      device::CredentialType::kPublicKey,
      std::vector<uint8_t>(kTestCredentialIdLength, 3), {});
  struct TestCase {
    bool available;
    std::vector<device::PublicKeyCredentialDescriptor> creds;
    bool expected_discovered;
  } kTestCases[] = {
      {false, {internal_cred}, false},
      {true, {sk_cred}, false},
      {true, {internal_cred}, true},
      {true, {unknown_cred}, true},
  };
  for (const auto& test_case : kTestCases) {
    SCOPED_TRACE(testing::Message() << "available=" << test_case.available);
    testing::Message creds_trace;
    creds_trace << "creds=[";
    if (test_case.creds.empty()) {
      creds_trace << "empty]";
    } else {
      creds_trace << test_case.creds.at(0).id.at(0) << "]";
    }
    SCOPED_TRACE(creds_trace);
    test_client_.GetTestWebAuthenticationDelegate()
        ->browser_provided_passkeys_available = test_case.available;
    PublicKeyCredentialRequestOptionsPtr options =
        GetTestPublicKeyCredentialRequestOptions();
    options->allow_credentials = std::move(test_case.creds);
    AuthenticatorGetAssertion(std::move(options));
    ASSERT_TRUE(
        test_client_.enclave_authenticator_should_be_discovered_.has_value());
    EXPECT_EQ(*test_client_.enclave_authenticator_should_be_discovered_,
              test_case.expected_discovered);
  }
}

TEST_F(AuthenticatorContentBrowserClientTest, TransportsFromAllowList) {
  NavigateAndCommit(GURL(kTestOrigin1));
  InjectVirtualAuthenticatorForAllTransports();
  device::PublicKeyCredentialDescriptor internal_cred(
      device::CredentialType::kPublicKey, {1, 2, 3, 4},
      {device::FidoTransportProtocol::kInternal});
  device::PublicKeyCredentialDescriptor sk_cred(
      device::CredentialType::kPublicKey, {1, 2, 3, 4},
      {device::FidoTransportProtocol::kUsbHumanInterfaceDevice});
  PublicKeyCredentialRequestOptionsPtr options =
      GetTestPublicKeyCredentialRequestOptions();
  options->allow_credentials = {std::move(internal_cred), std::move(sk_cred)};
  AuthenticatorGetAssertion(std::move(options));
  EXPECT_THAT(test_client_.discovered_transports_,
              testing::UnorderedElementsAre(
                  device::FidoTransportProtocol::kUsbHumanInterfaceDevice,
                  device::FidoTransportProtocol::kInternal));
}

TEST_F(AuthenticatorContentBrowserClientTest,
       AllTransportsAllowedIfHasAllowedCredentialWithEmptyTransportsList) {
  NavigateAndCommit(GURL(kTestOrigin1));
  InjectVirtualAuthenticatorForAllTransports();
  device::PublicKeyCredentialDescriptor cred(device::CredentialType::kPublicKey,
                                             {1, 2, 3, 4}, {});
  PublicKeyCredentialRequestOptionsPtr options =
      GetTestPublicKeyCredentialRequestOptions();
  options->allow_credentials = {std::move(cred)};
  AuthenticatorGetAssertion(std::move(options));
  EXPECT_THAT(test_client_.discovered_transports_,
              testing::UnorderedElementsAre(
                  device::FidoTransportProtocol::kUsbHumanInterfaceDevice,
                  device::FidoTransportProtocol::kNearFieldCommunication,
                  device::FidoTransportProtocol::kBluetoothLowEnergy,
                  device::FidoTransportProtocol::kHybrid,
                  device::FidoTransportProtocol::kInternal));
}

TEST_F(AuthenticatorContentBrowserClientTest,
       AllTransportsAllowedIfAllowCredentialsListIsEmpty) {
  test_client_.web_authentication_delegate.supports_resident_keys = true;
  NavigateAndCommit(GURL(kTestOrigin1));
  InjectVirtualAuthenticatorForAllTransports();
  PublicKeyCredentialRequestOptionsPtr options =
      GetTestPublicKeyCredentialRequestOptions();
  options->allow_credentials.clear();
  AuthenticatorGetAssertion(std::move(options));
  EXPECT_THAT(test_client_.discovered_transports_,
              testing::UnorderedElementsAre(
                  device::FidoTransportProtocol::kUsbHumanInterfaceDevice,
                  device::FidoTransportProtocol::kNearFieldCommunication,
                  device::FidoTransportProtocol::kBluetoothLowEnergy,
                  device::FidoTransportProtocol::kHybrid,
                  device::FidoTransportProtocol::kInternal));
}

// Test that credentials can be created and used from an extension origin when
// permitted by the delegate.
TEST_F(AuthenticatorContentBrowserClientTest, ChromeExtensions) {
  constexpr char kExtensionId[] = "abcdefg";
  static const std::string kExtensionOrigin =
      std::string(kExtensionScheme) + "://" + kExtensionId;

  NavigateAndCommit(GURL(kExtensionOrigin + "/test.html"));

  for (bool permit_webauthn_in_extensions : {false, true}) {
    SCOPED_TRACE(testing::Message()
                 << "permit=" << permit_webauthn_in_extensions);
    test_client_.GetTestWebAuthenticationDelegate()->permit_extensions =
        permit_webauthn_in_extensions;

    std::vector<uint8_t> credential_id;
    {
      PublicKeyCredentialCreationOptionsPtr options =
          GetTestPublicKeyCredentialCreationOptions();
      options->relying_party.id = kExtensionId;

      MakeCredentialResult result =
          AuthenticatorMakeCredential(std::move(options));
      if (permit_webauthn_in_extensions) {
        EXPECT_EQ(result.status, AuthenticatorStatus::SUCCESS);
        credential_id = result.response->info->raw_id;
      } else {
        EXPECT_EQ(result.status, AuthenticatorStatus::INVALID_PROTOCOL);
      }
    }

    {
      PublicKeyCredentialRequestOptionsPtr options =
          GetTestPublicKeyCredentialRequestOptions();
      options->relying_party_id = kExtensionId;
      options->allow_credentials[0] = device::PublicKeyCredentialDescriptor(
          device::CredentialType::kPublicKey, std::move(credential_id));

      EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
                permit_webauthn_in_extensions
                    ? AuthenticatorStatus::SUCCESS
                    : AuthenticatorStatus::INVALID_PROTOCOL);
    }
  }
}

TEST_F(AuthenticatorContentBrowserClientTest, ChromeExtensionBadRpIds) {
  // Permit WebAuthn in extensions.
  static const std::string kExtensionOrigin =
      base::StrCat({kExtensionScheme, "://abcdefg"});
  test_client_.GetTestWebAuthenticationDelegate()->permit_extensions = true;

  // Extensions are not permitted to assert RP IDs different from their
  // extension ID.
  for (auto* rp_id : {"", "xyz", "localhost", "xyz.com",
                      "chrome-extension://abcdefg", "https://abcdefg"}) {
    NavigateAndCommit(GURL(kExtensionOrigin + "/test.html"));
    {
      PublicKeyCredentialCreationOptionsPtr options =
          GetTestPublicKeyCredentialCreationOptions();
      options->relying_party.id = rp_id;

      MakeCredentialResult result =
          AuthenticatorMakeCredential(std::move(options));
      EXPECT_EQ(result.status, AuthenticatorStatus::INVALID_PROTOCOL);
    }

    {
      PublicKeyCredentialRequestOptionsPtr options =
          GetTestPublicKeyCredentialRequestOptions();
      options->relying_party_id = rp_id;
      GetAssertionResult result = AuthenticatorGetAssertion(std::move(options));
      EXPECT_EQ(result.status, AuthenticatorStatus::INVALID_PROTOCOL);
    }
  }
}

TEST_F(AuthenticatorContentBrowserClientTest, AttestationBehaviour) {
  const char kStandardCommonName[] = "U2F Attestation";
  const char kIndividualCommonName[] = "Individual Cert";

  const std::vector<TestCase> kTests = {
      {
          AttestationConveyancePreference::NONE,
          EnterprisePolicy::NOT_LISTED,
          AuthenticatorStatus::SUCCESS,
          AttestationType::NONE,
          "",
      },
      {
          AttestationConveyancePreference::NONE,
          EnterprisePolicy::LISTED,
          AuthenticatorStatus::SUCCESS,
          AttestationType::NONE,
          "",
      },
      {
          AttestationConveyancePreference::INDIRECT,
          EnterprisePolicy::NOT_LISTED,
          AuthenticatorStatus::SUCCESS,
          AttestationType::U2F,
          kStandardCommonName,
      },
      {
          AttestationConveyancePreference::INDIRECT,
          EnterprisePolicy::LISTED,
          AuthenticatorStatus::SUCCESS,
          AttestationType::U2F,
          kStandardCommonName,
      },
      {
          AttestationConveyancePreference::DIRECT,
          EnterprisePolicy::NOT_LISTED,
          AuthenticatorStatus::SUCCESS,
          AttestationType::U2F,
          kStandardCommonName,
      },
      {
          AttestationConveyancePreference::DIRECT,
          EnterprisePolicy::LISTED,
          AuthenticatorStatus::SUCCESS,
          AttestationType::U2F,
          kStandardCommonName,
      },
      {
          AttestationConveyancePreference::ENTERPRISE,
          EnterprisePolicy::NOT_LISTED,
          AuthenticatorStatus::SUCCESS,
          AttestationType::U2F,
          kStandardCommonName,
      },
      {
          AttestationConveyancePreference::ENTERPRISE,
          EnterprisePolicy::LISTED,
          AuthenticatorStatus::SUCCESS,
          AttestationType::U2F,
          kIndividualCommonName,
      },
  };

  virtual_device_factory_->mutable_state()->attestation_cert_common_name =
      kStandardCommonName;
  virtual_device_factory_->mutable_state()
      ->individual_attestation_cert_common_name = kIndividualCommonName;
  NavigateAndCommit(GURL("https://example.com"));

  RunTestCases(kTests);
}

TEST_F(AuthenticatorContentBrowserClientTest, Ctap2EnterpriseAttestation) {
  const char kStandardCommonName[] = "U2F Attestation";
  const char kIndividualCommonName[] = "Individual Cert";
  virtual_device_factory_->mutable_state()->attestation_cert_common_name =
      kStandardCommonName;
  virtual_device_factory_->mutable_state()
      ->individual_attestation_cert_common_name = kIndividualCommonName;
  NavigateAndCommit(GURL("https://example.com"));

  {
    SCOPED_TRACE("Without RP listed");

    device::VirtualCtap2Device::Config config;
    config.support_enterprise_attestation = true;
    virtual_device_factory_->SetCtap2Config(config);

    const std::vector<TestCase> kTests = {
        {
            AttestationConveyancePreference::ENTERPRISE,
            EnterprisePolicy::LISTED,
            AuthenticatorStatus::SUCCESS,
            AttestationType::PACKED,
            kIndividualCommonName,
        },
        {
            AttestationConveyancePreference::ENTERPRISE,
            EnterprisePolicy::NOT_LISTED,
            AuthenticatorStatus::SUCCESS,
            AttestationType::PACKED,
            kStandardCommonName,
        },
    };

    RunTestCases(kTests);
  }

  {
    SCOPED_TRACE("With RP listed");

    device::VirtualCtap2Device::Config config;
    config.support_enterprise_attestation = true;
    config.enterprise_attestation_rps = {"example.com"};
    virtual_device_factory_->SetCtap2Config(config);

    const std::vector<TestCase> kTests = {
        {
            // Despite not being listed in enterprise policy, since the
            // authenticator recognises the RP ID, attestation should still be
            // returned.
            AttestationConveyancePreference::ENTERPRISE,
            EnterprisePolicy::NOT_LISTED,
            AuthenticatorStatus::SUCCESS,
            AttestationType::PACKED,
            kIndividualCommonName,
        },
        {
            AttestationConveyancePreference::ENTERPRISE,
            EnterprisePolicy::LISTED,
            AuthenticatorStatus::SUCCESS,
            AttestationType::PACKED,
            kIndividualCommonName,
        },
    };

    RunTestCases(kTests);
  }
}

TEST_F(AuthenticatorContentBrowserClientTest,
       Ctap2EnterpriseAttestationUnsolicited) {
  NavigateAndCommit(GURL(kTestOrigin1));

  device::VirtualCtap2Device::Config config;
  config.support_enterprise_attestation = true;
  virtual_device_factory_->SetCtap2Config(config);

  {
    EXPECT_EQ(
        AuthenticatorMakeCredential(GetTestPublicKeyCredentialCreationOptions())
            .status,
        AuthenticatorStatus::SUCCESS);
  }

  config.always_return_enterprise_attestation = true;
  virtual_device_factory_->SetCtap2Config(config);

  {
    EXPECT_EQ(
        AuthenticatorMakeCredential(GetTestPublicKeyCredentialCreationOptions())
            .status,
        AuthenticatorStatus::NOT_ALLOWED_ERROR);
  }
}

TEST_F(AuthenticatorContentBrowserClientTest,
       InappropriatelyIdentifyingAttestation) {
  // This common name is used by several devices that have inappropriately
  // identifying attestation certificates.
  const char kCommonName[] = "FT FIDO 0100";

  const std::vector<TestCase> kTests = {
      {
          AttestationConveyancePreference::ENTERPRISE,
          EnterprisePolicy::NOT_LISTED,
          AuthenticatorStatus::SUCCESS,
          AttestationType::NONE,
          "",
      },
      {
          AttestationConveyancePreference::ENTERPRISE,
          EnterprisePolicy::LISTED,
          AuthenticatorStatus::SUCCESS,
          AttestationType::U2F,
          kCommonName,
      },
  };

  virtual_device_factory_->mutable_state()->attestation_cert_common_name =
      kCommonName;
  virtual_device_factory_->mutable_state()
      ->individual_attestation_cert_common_name = kCommonName;
  NavigateAndCommit(GURL("https://example.com"));

  RunTestCases(kTests);
}

// Test attestation erasure for an authenticator that uses self-attestation
// (which requires a zero AAGUID), but has a non-zero AAGUID. This mirrors the
// behavior of the Touch ID platform authenticator.
TEST_F(AuthenticatorContentBrowserClientTest,
       PlatformAuthenticatorAttestation) {
  test_client_.GetTestWebAuthenticationDelegate()->is_uvpaa_override = true;
  virtual_device_factory_->SetSupportedProtocol(
      device::ProtocolVersion::kCtap2);
  virtual_device_factory_->SetTransport(
      device::FidoTransportProtocol::kInternal);
  virtual_device_factory_->mutable_state()->self_attestation = true;
  virtual_device_factory_->mutable_state()
      ->non_zero_aaguid_with_self_attestation = true;
  NavigateAndCommit(GURL("https://example.com"));

  const std::vector<TestCase> kTests = {
      {
          // Self-attestation is defined as having a zero AAGUID, but
          // |non_zero_aaguid_with_self_attestation| is set above. Thus, if no
          // attestation is requested, the self-attestation will be removed but,
          // because the transport is kInternal, the AAGUID will be preserved.
          AttestationConveyancePreference::NONE,
          EnterprisePolicy::NOT_LISTED,
          AuthenticatorStatus::SUCCESS,
          AttestationType::NONE_WITH_NONZERO_AAGUID,
          "",
      },
      {
          // Attestation is always returned if requested because it is privacy
          // preserving. The AttestationConsent value is irrelevant.
          AttestationConveyancePreference::DIRECT,
          EnterprisePolicy::NOT_LISTED,
          AuthenticatorStatus::SUCCESS,
          AttestationType::SELF_WITH_NONZERO_AAGUID,
          "",
      },
  };

  RunTestCases(kTests);
}

TEST_F(AuthenticatorContentBrowserClientTest, Ctap2SelfAttestation) {
  virtual_device_factory_->SetSupportedProtocol(
      device::ProtocolVersion::kCtap2);
  virtual_device_factory_->mutable_state()->self_attestation = true;
  NavigateAndCommit(GURL("https://example.com"));

  const std::vector<TestCase> kTests = {
      {
          // If no attestation is requested, we'll return the self attestation
          // rather than erasing it.
          AttestationConveyancePreference::NONE,
          EnterprisePolicy::NOT_LISTED,
          AuthenticatorStatus::SUCCESS,
          AttestationType::SELF,
          "",
      },
      {
          // And if direct attestation was requested.
          AttestationConveyancePreference::DIRECT,
          EnterprisePolicy::NOT_LISTED,
          AuthenticatorStatus::SUCCESS,
          AttestationType::SELF,
          "",
      },
  };

  RunTestCases(kTests);
}

TEST_F(AuthenticatorContentBrowserClientTest,
       Ctap2SelfAttestationNonZeroAaguid) {
  virtual_device_factory_->SetSupportedProtocol(
      device::ProtocolVersion::kCtap2);
  virtual_device_factory_->mutable_state()->self_attestation = true;
  virtual_device_factory_->mutable_state()
      ->non_zero_aaguid_with_self_attestation = true;
  NavigateAndCommit(GURL("https://example.com"));

  const std::vector<TestCase> kTests = {
      {
          // Since the virtual device is configured to set a non-zero AAGUID the
          // self-attestation should still be replaced with a "none"
          // attestation.
          AttestationConveyancePreference::NONE,
          EnterprisePolicy::NOT_LISTED,
          AuthenticatorStatus::SUCCESS,
          AttestationType::NONE,
          "",
      },
  };

  RunTestCases(kTests);
}

TEST_F(AuthenticatorContentBrowserClientTest, BlockedAttestation) {
  NavigateAndCommit(GURL("https://foo.example.com"));

  static constexpr struct {
    const char* filter_json;
    AttestationConveyancePreference attestation;
    EnterprisePolicy enterprise_policy;
    AttestationType result;
  } kTests[] = {
      // Empty or nonsense filter doesn't block anything.
      {
          "",
          AttestationConveyancePreference::DIRECT,
          EnterprisePolicy::NOT_LISTED,
          AttestationType::U2F,
      },
      {
          R"({"filters": []})",
          AttestationConveyancePreference::DIRECT,
          EnterprisePolicy::NOT_LISTED,
          AttestationType::U2F,
      },
      // Direct listing of domain blocks...
      {
          R"({"filters": [{
            "operation": "mc",
            "rp_id": "example.com",
            "action": "no-attestation"
          }]})",
          AttestationConveyancePreference::DIRECT,
          EnterprisePolicy::NOT_LISTED,
          AttestationType::NONE,
      },
      // ... unless attestation is permitted by policy.
      {
          R"({"filters": [{
            "operation": "mc",
            "rp_id": "example.com",
            "action": "no-attestation"
          }]})",
          AttestationConveyancePreference::DIRECT,
          EnterprisePolicy::LISTED,
          AttestationType::U2F,
      },
      // The whole domain can be blocked. (Note, blocking a domain would
      // normally want to list both the base domain and a pattern for
      // subdomains because the below also matches fooexample.com.)
      {
          R"({"filters": [{
            "operation": "mc",
            "rp_id": "*example.com",
            "action": "no-attestation"
          }]})",
          AttestationConveyancePreference::DIRECT,
          EnterprisePolicy::NOT_LISTED,
          AttestationType::NONE,
      },
      // Policy again overrides
      {
          R"({"filters": [{
            "operation": "mc",
            "rp_id": "*example.com",
            "action": "no-attestation"
          }]})",
          AttestationConveyancePreference::DIRECT,
          EnterprisePolicy::LISTED,
          AttestationType::U2F,
      },
      // An explicit wildcard will match everything, be careful. (Omitting
      // both RP ID and device is a parse error, however.)
      {
          R"({"filters": [{
            "operation": "mc",
            "rp_id": "*",
            "action": "no-attestation"
          }]})",
          AttestationConveyancePreference::DIRECT,
          EnterprisePolicy::NOT_LISTED,
          AttestationType::NONE,
      },
  };

  int test_num = 0;
  for (const auto& test : kTests) {
    SCOPED_TRACE(test_num++);
    SCOPED_TRACE(test.filter_json);

    device::fido_filter::ScopedFilterForTesting filter(test.filter_json);

    const std::vector<TestCase> kTestCase = {
        {
            test.attestation,
            test.enterprise_policy,
            AuthenticatorStatus::SUCCESS,
            test.result,
            "",
        },
    };

    RunTestCases(kTestCase);
  }
}

TEST_F(AuthenticatorContentBrowserClientTest, FilteringMakeCredential) {
  static const struct {
    const char* filter_json;
    bool expect_make_credential_success;
  } kTests[] = {
      {
          R"()",
          true,
      },
      // Block by device.
      {
          R"({"filters": [{
          "operation": "mc",
          "device": "VirtualFidoDevice-*",
          "action": "block",
          }]})",
          false,
      },
      // Shouldn't block when the device is unrelated.
      {
          R"({"filters": [{
          "operation": "mc",
          "device": "OtherDevice-*",
          "action": "block",
          }]})",
          true,
      },
      // Block by RP ID.
      {
          R"({"filters": [{
          "operation": "mc",
          "rp_id": "google.com",
          "action": "block",
          }]})",
          false,
      },
      // Unrelated RP ID.
      {
          R"({"filters": [{
          "operation": "mc",
          "rp_id": "other.com",
          "action": "block",
          }]})",
          true,
      },
      // Block specific user ID.
      {
          R"({"filters": [{
          "operation": "mc",
          "rp_id": "*",
          "id_type": "user",
          "id": "0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A",
          "action": "block",
          }]})",
          false,
      },
      // Different user ID.
      {
          R"({"filters": [{
          "operation": "mc",
          "rp_id": "*",
          "id_type": "user",
          "id": "FF0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A0A",
          "action": "block",
          }]})",
          true,
      },
      // Block by user ID length.
      {
          R"({"filters": [{
          "operation": "mc",
          "rp_id": "*",
          "id_type": "user",
          "id_min_size": 32,
          "id_max_size": 32,
          "action": "block",
          }]})",
          false,
      },
      // Block user IDs that are longer than specified by
      // |GetTestPublicKeyCredentialUserEntity|.
      {
          R"({"filters": [{
          "operation": "mc",
          "rp_id": "*",
          "id_type": "user",
          "id_min_size": 33,
          "action": "block",
          }]})",
          true,
      },
      // Block excluded credential ID.
      {
          R"({"filters": [{
          "operation": "mc",
          "rp_id": "*",
          "id_type": "cred",
          "id": "0000000000000000000000000000000000000000000000000000000000000000",
          "action": "block",
          }]})",
          false,
      },
      // Block different credential ID.
      {
          R"({"filters": [{
          "operation": "mc",
          "rp_id": "*",
          "id_type": "cred",
          "id": "FF00000000000000000000000000000000000000000000000000000000000000",
          "action": "block",
          }]})",
          true,
      },
      // Block by excluded credential ID length.
      {
          R"({"filters": [{
          "operation": "mc",
          "rp_id": "*",
          "id_type": "cred",
          "id_min_size": 32,
          "id_max_size": 32,
          "action": "block",
          }]})",
          false,
      },
      // Block longer credentials IDs than are used.
      {
          R"({"filters": [{
          "operation": "mc",
          "rp_id": "*",
          "id_type": "cred",
          "id_min_size": 33,
          "action": "block",
          }]})",
          true,
      },
  };

  NavigateAndCommit(GURL(kTestOrigin1));

  int test_num = 0;
  for (const auto& test : kTests) {
    SCOPED_TRACE(test_num++);
    SCOPED_TRACE(test.filter_json);
    device::fido_filter::ScopedFilterForTesting filter(test.filter_json);

    PublicKeyCredentialCreationOptionsPtr options =
        GetTestPublicKeyCredentialCreationOptions();
    options->exclude_credentials = GetTestCredentials();
    EXPECT_EQ(AuthenticatorMakeCredentialAndWaitForTimeout(std::move(options))
                      .status == AuthenticatorStatus::SUCCESS,
              test.expect_make_credential_success);
  }
}

TEST_F(AuthenticatorContentBrowserClientTest, FilteringGetAssertion) {
  static const struct {
    const char* filter_json;
    bool expect_get_assertion_success;
  } kTests[] = {
      {
          R"()",
          true,
      },
      // Block by device.
      {
          R"({"filters": [{
          "operation": "ga",
          "device": "VirtualFidoDevice-*",
          "action": "block",
          }]})",
          false,
      },
      // Shouldn't block when the device is unrelated.
      {
          R"({"filters": [{
          "operation": "ga",
          "device": "OtherDevice-*",
          "action": "block",
          }]})",
          true,
      },
      // Block by RP ID.
      {
          R"({"filters": [{
          "operation": "ga",
          "rp_id": "google.com",
          "action": "block",
          }]})",
          false,
      },
      // Unrelated RP ID.
      {
          R"({"filters": [{
          "operation": "ga",
          "rp_id": "other.com",
          "action": "block",
          }]})",
          true,
      },
      // Block allowList credential ID.
      {
          R"({"filters": [{
          "operation": "ga",
          "rp_id": "*",
          "id_type": "cred",
          "id": "0000000000000000000000000000000000000000000000000000000000000000",
          "action": "block",
          }]})",
          false,
      },
      // Block different credential ID.
      {
          R"({"filters": [{
          "operation": "ga",
          "rp_id": "*",
          "id_type": "cred",
          "id": "FF00000000000000000000000000000000000000000000000000000000000000",
          "action": "block",
          }]})",
          true,
      },
      // Block by allowList credential ID length for credentials returned by
      // |GetTestCredentials|.
      {
          R"({"filters": [{
          "operation": "ga",
          "rp_id": "*",
          "id_type": "cred",
          "id_min_size": 32,
          "id_max_size": 32,
          "action": "block",
          }]})",
          false,
      },
      // Block longer credentials IDs than are used.
      {
          R"({"filters": [{
          "operation": "ga",
          "rp_id": "*",
          "id_type": "cred",
          "id_min_size": 33,
          "action": "block",
          }]})",
          true,
      },
  };

  NavigateAndCommit(GURL(kTestOrigin1));

  int test_num = 0;
  bool credential_added = false;
  for (const auto& test : kTests) {
    SCOPED_TRACE(test_num++);
    SCOPED_TRACE(test.filter_json);
    device::fido_filter::ScopedFilterForTesting filter(test.filter_json);

    PublicKeyCredentialRequestOptionsPtr options =
        GetTestPublicKeyCredentialRequestOptions();
    if (!credential_added) {
      ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
          options->allow_credentials[0].id, kTestRelyingPartyId));
      credential_added = true;
    }

    EXPECT_EQ(
        AuthenticatorGetAssertionAndWaitForTimeout(std::move(options)).status ==
            AuthenticatorStatus::SUCCESS,
        test.expect_get_assertion_success);
  }
}

TEST_F(AuthenticatorContentBrowserClientTest, FilteringFailsOpen) {
  // Setting the filter to invalid JSON should not filter anything.
  device::fido_filter::ScopedFilterForTesting filter(
      "nonsense",
      device::fido_filter::ScopedFilterForTesting::PermitInvalidJSON::kYes);

  NavigateAndCommit(GURL(kTestOrigin1));
  PublicKeyCredentialCreationOptionsPtr options =
      GetTestPublicKeyCredentialCreationOptions();
  options->exclude_credentials = GetTestCredentials();
  EXPECT_EQ(
      AuthenticatorMakeCredentialAndWaitForTimeout(std::move(options)).status,
      AuthenticatorStatus::SUCCESS);
}

TEST_F(AuthenticatorContentBrowserClientTest,
       MakeCredentialRequestStartedCallback) {
  NavigateAndCommit(GURL(kTestOrigin1));
  mojo::Remote<blink::mojom::Authenticator> authenticator =
      ConnectToAuthenticator();

  PublicKeyCredentialCreationOptionsPtr options =
      GetTestPublicKeyCredentialCreationOptions();

  TestRequestStartedFuture request_started_future;
  test_client_.action_callbacks_registered_callback =
      request_started_future.GetCallback();
  authenticator->MakeCredential(std::move(options), base::DoNothing());
  EXPECT_TRUE(request_started_future.Wait());
}

TEST_F(AuthenticatorContentBrowserClientTest,
       GetAssertionRequestStartedCallback) {
  NavigateAndCommit(GURL(kTestOrigin1));
  mojo::Remote<blink::mojom::Authenticator> authenticator =
      ConnectToAuthenticator();

  GetCredentialOptionsPtr options = GetTestGetCredentialOptions();

  TestRequestStartedFuture request_started_future;
  test_client_.action_callbacks_registered_callback =
      request_started_future.GetCallback();
  authenticator->GetCredential(std::move(options), base::DoNothing());
  EXPECT_TRUE(request_started_future.Wait());
}

TEST_F(AuthenticatorContentBrowserClientTest, MakeCredentialStartOver) {
  NavigateAndCommit(GURL(kTestOrigin1));
  mojo::Remote<blink::mojom::Authenticator> authenticator =
      ConnectToAuthenticator();

  PublicKeyCredentialCreationOptionsPtr options =
      GetTestPublicKeyCredentialCreationOptions();
  // Make the request fail so that it's started over.
  options->authenticator_selection->user_verification_requirement =
      device::UserVerificationRequirement::kRequired;

  TestRequestStartedFuture request_started_future;
  test_client_.action_callbacks_registered_callback =
      request_started_future.GetCallback();
  TestRequestStartedFuture request_restarted_future;
  test_client_.started_over_callback_ = request_restarted_future.GetCallback();

  authenticator->MakeCredential(std::move(options), base::DoNothing());
  EXPECT_TRUE(request_started_future.Wait());
  EXPECT_TRUE(request_restarted_future.Wait());

  const auto& discoveries_trace = virtual_device_factory_->trace()->discoveries;
  ASSERT_EQ(discoveries_trace.size(), 2u);
  EXPECT_TRUE(discoveries_trace[0].is_stopped);
  EXPECT_TRUE(discoveries_trace[0].is_destroyed);
  EXPECT_FALSE(discoveries_trace[1].is_stopped);
  EXPECT_FALSE(discoveries_trace[1].is_destroyed);
}

TEST_F(AuthenticatorContentBrowserClientTest, GetAssertionStartOver) {
  NavigateAndCommit(GURL(kTestOrigin1));
  mojo::Remote<blink::mojom::Authenticator> authenticator =
      ConnectToAuthenticator();

  GetCredentialOptionsPtr options = GetTestGetCredentialOptions();

  TestRequestStartedFuture request_started_future;
  test_client_.action_callbacks_registered_callback =
      request_started_future.GetCallback();
  TestRequestStartedFuture request_restarted_future;
  test_client_.started_over_callback_ = request_restarted_future.GetCallback();

  authenticator->GetCredential(std::move(options), base::DoNothing());
  EXPECT_TRUE(request_started_future.Wait());
  EXPECT_TRUE(request_restarted_future.Wait());

  const auto& discoveries_trace = virtual_device_factory_->trace()->discoveries;
  ASSERT_EQ(discoveries_trace.size(), 2u);
  EXPECT_TRUE(discoveries_trace[0].is_stopped);
  EXPECT_TRUE(discoveries_trace[0].is_destroyed);
  EXPECT_FALSE(discoveries_trace[1].is_stopped);
  EXPECT_FALSE(discoveries_trace[1].is_destroyed);
}

TEST_F(AuthenticatorContentBrowserClientTest, Unfocused) {
  // When the |ContentBrowserClient| considers the tab to be unfocused,
  // registration requests should fail with a |NOT_FOCUSED| error, but getting
  // assertions should still work.
  test_client_.GetTestWebAuthenticationDelegate()->is_focused = false;

  NavigateAndCommit(GURL(kTestOrigin1));

  {
    TestRequestStartedFuture request_started_future;
    test_client_.action_callbacks_registered_callback =
        request_started_future.GetCallback();

    EXPECT_EQ(
        AuthenticatorMakeCredential(GetTestPublicKeyCredentialCreationOptions())
            .status,
        AuthenticatorStatus::NOT_FOCUSED);
    EXPECT_FALSE(request_started_future.IsReady());
  }

  {
    device::PublicKeyCredentialDescriptor credential;
    credential.credential_type = device::CredentialType::kPublicKey;
    credential.id.resize(16);
    credential.transports = {
        device::FidoTransportProtocol::kUsbHumanInterfaceDevice};

    ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
        credential.id, kTestRelyingPartyId));
    PublicKeyCredentialRequestOptionsPtr options =
        GetTestPublicKeyCredentialRequestOptions();
    options->allow_credentials.emplace_back(credential);

    TestRequestStartedFuture request_started_future;
    test_client_.action_callbacks_registered_callback =
        request_started_future.GetCallback();

    EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
              AuthenticatorStatus::SUCCESS);
    EXPECT_TRUE(request_started_future.IsReady());
  }
}

TEST_F(AuthenticatorContentBrowserClientTest,
       NullDelegate_RejectsWithPendingRequest) {
  test_client_.return_null_delegate = true;
  NavigateAndCommit(GURL(kTestOrigin1));

  {
    PublicKeyCredentialCreationOptionsPtr options =
        GetTestPublicKeyCredentialCreationOptions();
    EXPECT_EQ(AuthenticatorMakeCredential(std::move(options)).status,
              AuthenticatorStatus::PENDING_REQUEST);
  }

  {
    PublicKeyCredentialRequestOptionsPtr options =
        GetTestPublicKeyCredentialRequestOptions();
    EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
              AuthenticatorStatus::PENDING_REQUEST);
  }
}

TEST_F(AuthenticatorContentBrowserClientTest, IsUVPAAOverride) {
  NavigateAndCommit(GURL(kTestOrigin1));

  for (const bool is_uvpaa : {false, true}) {
    SCOPED_TRACE(::testing::Message() << "is_uvpaa=" << is_uvpaa);
    test_client_.GetTestWebAuthenticationDelegate()->is_uvpaa_override =
        is_uvpaa;

    EXPECT_EQ(AuthenticatorIsUvpaa(), is_uvpaa);
  }
}

TEST_F(AuthenticatorContentBrowserClientTest,
       GetClientCapabilities_CheckUvpaaPlumbing) {
  NavigateAndCommit(GURL(kTestOrigin1));

  for (const bool is_uvpaa : {false, true}) {
    SCOPED_TRACE(::testing::Message() << "is_uvpaa=" << is_uvpaa);
    test_client_.GetTestWebAuthenticationDelegate()->is_uvpaa_override =
        is_uvpaa;

    ClientCapabilitiesList capabilities = AuthenticatorGetClientCapabilities();
    ExpectCapability(capabilities,
                     client_capabilities::kUserVerifyingPlatformAuthenticator,
                     is_uvpaa);
  }
}

TEST_F(AuthenticatorContentBrowserClientTest,
       GetClientCapabilities_CheckPPAAPlumbing) {
  NavigateAndCommit(GURL(kTestOrigin1));

  // Verify: PPAA == `is_uvpaa` || HybridTransport (false).
  for (const bool is_uvpaa : {false, true}) {
    SCOPED_TRACE(::testing::Message() << "is_uvpaa=" << is_uvpaa);
    test_client_.GetTestWebAuthenticationDelegate()->is_uvpaa_override =
        is_uvpaa;
    // Simulate `hybrid_transport = false`.
    EXPECT_CALL(*mock_adapter_, IsPresent()).WillOnce(::testing::Return(false));

    ClientCapabilitiesList capabilities = AuthenticatorGetClientCapabilities();
    ExpectCapability(capabilities,
                     client_capabilities::kPasskeyPlatformAuthenticator,
                     is_uvpaa);
  }

  // Verify: PPAA == isUVPAA (false) || `hybrid_transport`.
  for (const bool hybrid_transport : {false, true}) {
    SCOPED_TRACE(::testing::Message()
                 << "hybrid_transport=" << hybrid_transport);
    // Simulate `isUVPAA = false`.
    test_client_.GetTestWebAuthenticationDelegate()->is_uvpaa_override = false;

    EXPECT_CALL(*mock_adapter_, IsPresent())
        .WillOnce(::testing::Return(hybrid_transport));

    ClientCapabilitiesList capabilities = AuthenticatorGetClientCapabilities();
    ExpectCapability(capabilities,
                     client_capabilities::kPasskeyPlatformAuthenticator,
                     hybrid_transport);
  }
}

TEST_F(AuthenticatorContentBrowserClientTest,
       GetClientCapabilities_ConditionalGet_ReturnsFalse) {
  NavigateAndCommit(GURL(kTestOrigin1));
  ClientCapabilitiesList capabilities = AuthenticatorGetClientCapabilities();
  ExpectCapability(capabilities, client_capabilities::kConditionalGet, true);
}

TEST_F(AuthenticatorContentBrowserClientTest,
       GPMPasskeys_IsConditionalMediationAvailable) {
  NavigateAndCommit(GURL(kTestOrigin1));
  ASSERT_TRUE(AuthenticatorIsConditionalMediationAvailable());
}

// AuthenticatorImplRemoteDesktopClientOverrideTest exercises the
// RemoteDesktopClientOverride extension, which is used by remote desktop
// applications exercising requests on behalf of other origins.
class AuthenticatorImplRemoteDesktopClientOverrideTest
    : public AuthenticatorContentBrowserClientTest {
 protected:
  static constexpr char kOtherRdpOrigin[] = "https://myrdp.test";
  static constexpr char kExampleOrigin[] = "https://example.test";
  static constexpr char kExampleRpId[] = "example.test";
  static constexpr char kExampleAppid[] = "https://example.test/appid.json";
  static constexpr char kOtherRpId[] = "other.test";
  static constexpr char kOtherAppid[] = "https://other.test/appid.json";

  void SetUp() override {
    AuthenticatorContentBrowserClientTest::SetUp();
    // Authorize `kCorpCrdOrigin` to exercise the extension. In //chrome, this
    // is controlled by the `WebAuthenticationRemoteProxiedRequestsAllowed`
    // enterprise policy.
    test_client_.GetTestWebAuthenticationDelegate()
        ->remote_desktop_client_override_origin =
        url::Origin::Create(GURL(kCorpCrdOrigin));
    // Controls the Blink feature gating the extension.
    scoped_command_line_.GetProcessCommandLine()->AppendSwitch(
        switches::kWebAuthRemoteDesktopSupport);
  }

  base::test::ScopedCommandLine scoped_command_line_;
};

TEST_F(AuthenticatorImplRemoteDesktopClientOverrideTest, MakeCredential) {
  // Verify that an authorized origin may use the extension. Regular RP ID
  // processing applies, i.e. the origin override must be authorized to claim
  // the specified RP ID.
  const struct TestCase {
    std::string local_origin;
    std::string remote_origin;
    std::string rp_id;
    bool success;
  } test_cases[] = {
      {kCorpCrdOrigin, kExampleOrigin, kExampleRpId, true},
      {kOtherRdpOrigin, kExampleOrigin, kExampleRpId, false},
      {kOtherRdpOrigin, kExampleOrigin, kOtherRpId, false},
      {kExampleOrigin, kExampleOrigin, kExampleRpId, false},
  };

  for (const auto& test : test_cases) {
    SCOPED_TRACE(testing::Message()
                 << "local=" << test.local_origin
                 << " remote=" << test.remote_origin << " rp=" << test.rp_id);
    NavigateAndCommit(GURL(test.local_origin));

    PublicKeyCredentialCreationOptionsPtr options =
        GetTestPublicKeyCredentialCreationOptions();
    options->relying_party.id = test.rp_id;
    options->remote_desktop_client_override = RemoteDesktopClientOverride::New(
        url::Origin::Create(GURL(test.remote_origin)), true);

    EXPECT_EQ(AuthenticatorMakeCredential(std::move(options)).status,
              test.success ? AuthenticatorStatus::SUCCESS
                           : AuthenticatorStatus::
                                 REMOTE_DESKTOP_CLIENT_OVERRIDE_NOT_AUTHORIZED);
  }
}

TEST_F(AuthenticatorImplRemoteDesktopClientOverrideTest, GetAssertion) {
  // Verify that an authorized origin may use the extension. Regular RP ID
  // processing applies, i.e. the origin override must be authorized to claim
  // the specified RP ID.
  const struct TestCase {
    std::string local_origin;
    std::string remote_origin;
    std::string rp_id;
    bool success;
  } test_cases[] = {
      {kCorpCrdOrigin, kExampleOrigin, kExampleRpId, true},
      {kOtherRdpOrigin, kExampleOrigin, kExampleRpId, false},
      {kOtherRdpOrigin, kExampleOrigin, kOtherRpId, false},
      {kExampleOrigin, kExampleOrigin, kExampleRpId, false},
  };

  for (const auto& test : test_cases) {
    SCOPED_TRACE(testing::Message()
                 << "local=" << test.local_origin
                 << " remote=" << test.remote_origin << " rp=" << test.rp_id);
    ResetVirtualDevice();
    NavigateAndCommit(GURL(test.local_origin));

    PublicKeyCredentialRequestOptionsPtr options =
        GetTestPublicKeyCredentialRequestOptions();
    options->relying_party_id = test.rp_id;
    options->extensions->remote_desktop_client_override =
        RemoteDesktopClientOverride::New(
            url::Origin::Create(GURL(test.remote_origin)), true);

    ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
        options->allow_credentials[0].id, test.rp_id));

    EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
              test.success ? AuthenticatorStatus::SUCCESS
                           : AuthenticatorStatus::
                                 REMOTE_DESKTOP_CLIENT_OVERRIDE_NOT_AUTHORIZED);
  }
}

TEST_F(AuthenticatorImplRemoteDesktopClientOverrideTest, MakeCredentialAppid) {
  // Verify that origin overriding extends to the appidExclude extension. If the
  // caller origin is authorized to use the extension, App ID processing is
  // applied to the overridden origin.
  const struct TestCase {
    std::string local_origin;
    std::string remote_origin;
    std::string rp_id;
    std::string app_id;
    AuthenticatorStatus expected;
  } test_cases[] = {
      {kCorpCrdOrigin, kExampleOrigin, kExampleRpId, kExampleAppid,
       AuthenticatorStatus::SUCCESS},
      {kCorpCrdOrigin, kExampleOrigin, kExampleRpId, kOtherAppid,
       AuthenticatorStatus::INVALID_DOMAIN},
      {kOtherRdpOrigin, kExampleOrigin, kExampleRpId, kExampleAppid,
       AuthenticatorStatus::REMOTE_DESKTOP_CLIENT_OVERRIDE_NOT_AUTHORIZED},
      {kOtherRdpOrigin, kExampleOrigin, kExampleRpId, kOtherAppid,
       AuthenticatorStatus::REMOTE_DESKTOP_CLIENT_OVERRIDE_NOT_AUTHORIZED},
      {kExampleOrigin, kExampleOrigin, kExampleRpId, kExampleAppid,
       AuthenticatorStatus::REMOTE_DESKTOP_CLIENT_OVERRIDE_NOT_AUTHORIZED},
      {kExampleOrigin, kExampleOrigin, kExampleRpId, kOtherAppid,
       AuthenticatorStatus::REMOTE_DESKTOP_CLIENT_OVERRIDE_NOT_AUTHORIZED},
  };

  for (const auto& test : test_cases) {
    SCOPED_TRACE(testing::Message()
                 << "local=" << test.local_origin
                 << " remote=" << test.remote_origin << " rp=" << test.rp_id
                 << " appid=" << test.app_id);
    NavigateAndCommit(GURL(test.local_origin));

    PublicKeyCredentialCreationOptionsPtr options =
        GetTestPublicKeyCredentialCreationOptions();
    options->relying_party.id = test.rp_id;
    options->appid_exclude = test.app_id;
    options->remote_desktop_client_override = RemoteDesktopClientOverride::New(
        url::Origin::Create(GURL(test.remote_origin)), true);

    auto result = AuthenticatorMakeCredential(std::move(options));
    EXPECT_EQ(result.status, test.expected);
  }
}

TEST_F(AuthenticatorImplRemoteDesktopClientOverrideTest, GetAssertionAppid) {
  // Verify that origin overriding extends to the appid extension. If the
  // caller origin is authorized to use the extension, App ID processing is
  // applied to the overridden origin.
  const struct TestCase {
    std::string local_origin;
    std::string remote_origin;
    std::string rp_id;
    std::string app_id;
    AuthenticatorStatus expected;
  } test_cases[] = {
      {kCorpCrdOrigin, kExampleOrigin, kExampleRpId, kExampleAppid,
       AuthenticatorStatus::SUCCESS},
      {kCorpCrdOrigin, kExampleOrigin, kExampleRpId, kOtherAppid,
       AuthenticatorStatus::INVALID_DOMAIN},
      {kOtherRdpOrigin, kExampleOrigin, kExampleRpId, kExampleAppid,
       AuthenticatorStatus::REMOTE_DESKTOP_CLIENT_OVERRIDE_NOT_AUTHORIZED},
      {kOtherRdpOrigin, kExampleOrigin, kExampleRpId, kOtherAppid,
       AuthenticatorStatus::REMOTE_DESKTOP_CLIENT_OVERRIDE_NOT_AUTHORIZED},
      {kExampleOrigin, kExampleOrigin, kExampleRpId, kExampleAppid,
       AuthenticatorStatus::REMOTE_DESKTOP_CLIENT_OVERRIDE_NOT_AUTHORIZED},
      {kExampleOrigin, kExampleOrigin, kExampleRpId, kOtherAppid,
       AuthenticatorStatus::REMOTE_DESKTOP_CLIENT_OVERRIDE_NOT_AUTHORIZED},
  };

  for (const auto& test : test_cases) {
    SCOPED_TRACE(testing::Message()
                 << "local=" << test.local_origin
                 << " remote=" << test.remote_origin << " rp=" << test.rp_id
                 << " appid=" << test.app_id);
    ResetVirtualDevice();
    NavigateAndCommit(GURL(test.local_origin));

    PublicKeyCredentialRequestOptionsPtr options =
        GetTestPublicKeyCredentialRequestOptions();
    options->relying_party_id = test.rp_id;
    options->extensions->appid = test.app_id;
    options->extensions->remote_desktop_client_override =
        RemoteDesktopClientOverride::New(
            url::Origin::Create(GURL(test.remote_origin)), true);

    ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
        options->allow_credentials[0].id, test.rp_id));

    auto result = AuthenticatorGetAssertion(std::move(options));
    EXPECT_EQ(result.status, test.expected);
  }
}

TEST_F(AuthenticatorImplRemoteDesktopClientOverrideTest,
       GetAssertionImmediateMediation) {
  // Verify that an authorized origin may not use the extension with immediate
  // mediation.
  NavigateAndCommit(GURL(kCorpCrdOrigin));

  PublicKeyCredentialRequestOptionsPtr options =
      GetTestPublicKeyCredentialRequestOptions();
  options->allow_credentials.clear();
  options->relying_party_id = kExampleRpId;
  options->extensions->remote_desktop_client_override =
      RemoteDesktopClientOverride::New(
          url::Origin::Create(GURL(kExampleOrigin)), true);

  mojo::Remote<blink::mojom::Authenticator> authenticator =
      ConnectToAuthenticator();
  base::test::TestFuture<void> mojo_error_future;
  SetMojoErrorHandler(base::BindLambdaForTesting([&](const std::string& error) {
    EXPECT_EQ(error,
              "Immediate mediation cannot be used with a remote desktop "
              "override request");
    mojo_error_future.SetValue();
  }));

  auto get_credential_options = GetCredentialOptions::New();
  get_credential_options->public_key = std::move(options);
  get_credential_options->mediation = blink::mojom::Mediation::IMMEDIATE;
  authenticator->GetCredential(std::move(get_credential_options),
                               base::DoNothing());
  EXPECT_TRUE(mojo_error_future.Wait());
}

class MockAuthenticatorRequestDelegateObserver
    : public TestAuthenticatorRequestDelegate {
 public:
  using InterestingFailureReasonCallback =
      base::OnceCallback<void(InterestingFailureReason)>;

  explicit MockAuthenticatorRequestDelegateObserver(
      InterestingFailureReasonCallback failure_reasons_callback =
          base::DoNothing())
      : TestAuthenticatorRequestDelegate(
            nullptr /* render_frame_host */,
            base::DoNothing() /* did_start_request_callback */,
            /*started_over_callback=*/base::OnceClosure(),
            /*simulate_user_cancelled=*/false,
            /*enclave_discovered_callback=*/base::DoNothing(),
            /*transports_discovered_callback=*/base::DoNothing()),
        failure_reasons_callback_(std::move(failure_reasons_callback)) {}

  MockAuthenticatorRequestDelegateObserver(
      const MockAuthenticatorRequestDelegateObserver&) = delete;
  MockAuthenticatorRequestDelegateObserver& operator=(
      const MockAuthenticatorRequestDelegateObserver&) = delete;

  ~MockAuthenticatorRequestDelegateObserver() override = default;

  bool DoesBlockRequestOnFailure(InterestingFailureReason reason) override {
    CHECK(failure_reasons_callback_);
    std::move(failure_reasons_callback_).Run(reason);
    return false;
  }

  MOCK_METHOD1(
      OnTransportAvailabilityEnumerated,
      void(device::FidoRequestHandlerBase::TransportAvailabilityInfo data));
  MOCK_METHOD1(EmbedderControlsAuthenticatorDispatch,
               bool(const device::FidoAuthenticator&));
  MOCK_METHOD1(FidoAuthenticatorAdded, void(const device::FidoAuthenticator&));
  MOCK_METHOD1(FidoAuthenticatorRemoved, void(std::string_view));

 private:
  InterestingFailureReasonCallback failure_reasons_callback_;
};

// Fake test construct that shares all other behavior with
// AuthenticatorCommonImpl except that:
//  - FakeAuthenticatorCommonImpl does not trigger UI activity.
//  - MockAuthenticatorRequestDelegateObserver is injected to
//  |request_delegate_|
//    instead of ChromeAuthenticatorRequestDelegate.
class FakeAuthenticatorCommonImpl : public AuthenticatorCommonImpl {
 public:
  explicit FakeAuthenticatorCommonImpl(
      RenderFrameHost* render_frame_host,
      std::unique_ptr<MockAuthenticatorRequestDelegateObserver> mock_delegate)
      : AuthenticatorCommonImpl(render_frame_host,
                                ServingRequestsFor::kWebContents),
        mock_delegate_(std::move(mock_delegate)) {}
  ~FakeAuthenticatorCommonImpl() override = default;

  std::unique_ptr<AuthenticatorRequestClientDelegate>
  MaybeCreateRequestDelegate() override {
    DCHECK(mock_delegate_);
    return std::move(mock_delegate_);
  }

 private:
  friend class AuthenticatorImplRequestDelegateTest;

  std::unique_ptr<MockAuthenticatorRequestDelegateObserver> mock_delegate_;
};

class AuthenticatorImplRequestDelegateTest : public AuthenticatorImplTest {
 public:
  AuthenticatorImplRequestDelegateTest() = default;
  ~AuthenticatorImplRequestDelegateTest() override = default;

  mojo::Remote<blink::mojom::Authenticator> ConnectToFakeAuthenticator(
      std::unique_ptr<MockAuthenticatorRequestDelegateObserver> delegate) {
    mojo::Remote<blink::mojom::Authenticator> authenticator;
    // AuthenticatorImpl owns itself. It self-destructs when the RenderFrameHost
    // navigates or is deleted.
    AuthenticatorImpl::CreateForTesting(
        *main_rfh(), authenticator.BindNewPipeAndPassReceiver(),
        std::make_unique<FakeAuthenticatorCommonImpl>(main_rfh(),
                                                      std::move(delegate)));
    return authenticator;
  }
};

TEST_F(AuthenticatorImplRequestDelegateTest,
       TestRequestDelegateObservesFidoRequestHandler) {
  EXPECT_CALL(*mock_adapter_, IsPresent())
      .WillRepeatedly(::testing::Return(true));

  auto discovery_factory =
      std::make_unique<device::test::FakeFidoDiscoveryFactory>();
  auto* fake_hid_discovery = discovery_factory->ForgeNextHidDiscovery();
  ReplaceDiscoveryFactory(std::move(discovery_factory));

  NavigateAndCommit(GURL(kTestOrigin1));
  GetCredentialOptionsPtr options = GetTestGetCredentialOptions();
  TestGetCredentialFuture future;

  auto mock_delegate =
      std::make_unique<MockAuthenticatorRequestDelegateObserver>();
  auto* const mock_delegate_ptr = mock_delegate.get();
  auto authenticator = ConnectToFakeAuthenticator(std::move(mock_delegate));

  auto mock_usb_device = device::MockFidoDevice::MakeCtap();
  mock_usb_device->StubGetId();
  mock_usb_device->SetDeviceTransport(
      device::FidoTransportProtocol::kUsbHumanInterfaceDevice);
  const auto device_id = mock_usb_device->GetId();

  EXPECT_CALL(*mock_delegate_ptr, OnTransportAvailabilityEnumerated(_));
  EXPECT_CALL(*mock_delegate_ptr, EmbedderControlsAuthenticatorDispatch(_))
      .WillOnce(testing::Return(true));

  base::RunLoop usb_device_found_done;
  EXPECT_CALL(*mock_delegate_ptr, FidoAuthenticatorAdded(_))
      .WillOnce(testing::InvokeWithoutArgs(
          [&usb_device_found_done]() { usb_device_found_done.Quit(); }));

  base::RunLoop usb_device_lost_done;
  EXPECT_CALL(*mock_delegate_ptr, FidoAuthenticatorRemoved(_))
      .WillOnce(testing::InvokeWithoutArgs(
          [&usb_device_lost_done]() { usb_device_lost_done.Quit(); }));

  authenticator->GetCredential(std::move(options), future.GetCallback());
  fake_hid_discovery->WaitForCallToStartAndSimulateSuccess();
  fake_hid_discovery->AddDevice(std::move(mock_usb_device));
  usb_device_found_done.Run();

  fake_hid_discovery->RemoveDevice(device_id);
  usb_device_lost_done.Run();
  base::RunLoop().RunUntilIdle();
}

TEST_F(AuthenticatorImplRequestDelegateTest, FailureReasonForTimeout) {
  // The VirtualFidoAuthenticator simulates a tap immediately after it gets the
  // request. Replace by the real discovery that will wait until timeout.
  ReplaceDiscoveryFactory(std::make_unique<device::FidoDiscoveryFactory>());

  NavigateAndCommit(GURL(kTestOrigin1));

  FailureReasonFuture failure_reason_future;
  auto mock_delegate = std::make_unique<
      ::testing::NiceMock<MockAuthenticatorRequestDelegateObserver>>(
      failure_reason_future.GetCallback());
  auto authenticator = ConnectToFakeAuthenticator(std::move(mock_delegate));

  TestGetCredentialFuture future;
  authenticator->GetCredential(GetTestGetCredentialOptions(),
                               future.GetCallback());

  task_environment()->FastForwardBy(kTestTimeout);

  EXPECT_TRUE(future.Wait());
  EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR,
            future.Get()->get_get_assertion_response()->status);

  ASSERT_TRUE(failure_reason_future.IsReady());
  EXPECT_EQ(
      AuthenticatorRequestClientDelegate::InterestingFailureReason::kTimeout,
      failure_reason_future.Get());
}

TEST_F(AuthenticatorImplRequestDelegateTest,
       FailureReasonForDuplicateRegistration) {
  NavigateAndCommit(GURL(kTestOrigin1));

  FailureReasonFuture failure_reason_future;
  auto mock_delegate = std::make_unique<
      ::testing::NiceMock<MockAuthenticatorRequestDelegateObserver>>(
      failure_reason_future.GetCallback());
  auto authenticator = ConnectToFakeAuthenticator(std::move(mock_delegate));

  PublicKeyCredentialCreationOptionsPtr options =
      GetTestPublicKeyCredentialCreationOptions();
  options->exclude_credentials = GetTestCredentials();
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
      options->exclude_credentials[0].id, kTestRelyingPartyId));

  TestMakeCredentialFuture future;
  authenticator->MakeCredential(std::move(options), future.GetCallback());

  EXPECT_TRUE(future.Wait());
  EXPECT_EQ(AuthenticatorStatus::CREDENTIAL_EXCLUDED,
            std::get<0>(future.Get()));

  ASSERT_TRUE(failure_reason_future.IsReady());
  EXPECT_EQ(AuthenticatorRequestClientDelegate::InterestingFailureReason::
                kKeyAlreadyRegistered,
            failure_reason_future.Get());
}

TEST_F(AuthenticatorImplRequestDelegateTest,
       FailureReasonForMissingRegistration) {
  NavigateAndCommit(GURL(kTestOrigin1));

  FailureReasonFuture failure_reason_future;
  auto mock_delegate = std::make_unique<
      ::testing::NiceMock<MockAuthenticatorRequestDelegateObserver>>(
      failure_reason_future.GetCallback());
  auto authenticator = ConnectToFakeAuthenticator(std::move(mock_delegate));

  TestGetCredentialFuture future;
  authenticator->GetCredential(GetTestGetCredentialOptions(),
                               future.GetCallback());

  EXPECT_TRUE(future.Wait());
  EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR,
            future.Get()->get_get_assertion_response()->status);

  ASSERT_TRUE(failure_reason_future.IsReady());
  EXPECT_EQ(AuthenticatorRequestClientDelegate::InterestingFailureReason::
                kKeyNotRegistered,
            failure_reason_future.Get());
}

TEST_F(AuthenticatorImplTest, NoNonAuthoritativeTransports) {
  NavigateAndCommit(GURL(kTestOrigin1));
  virtual_device_factory_->SetSupportedProtocol(
      device::ProtocolVersion::kCtap2);
  device::VirtualCtap2Device::Config config;
  // If there are no transports in the attestation certificate, and none from
  // getInfo, then none should be reported because there isn't enough
  // information to say.
  config.include_transports_in_attestation_certificate = false;
  virtual_device_factory_->SetCtap2Config(config);

  MakeCredentialResult result = AuthenticatorMakeCredential();
  ASSERT_EQ(result.status, AuthenticatorStatus::SUCCESS);

  EXPECT_TRUE(result.response->transports.empty());
}

TEST_F(AuthenticatorImplTest, TransportsFromGetInfo) {
  NavigateAndCommit(GURL(kTestOrigin1));
  virtual_device_factory_->SetSupportedProtocol(
      device::ProtocolVersion::kCtap2);
  device::VirtualCtap2Device::Config config;
  config.include_transports_in_attestation_certificate = false;
  config.transports_in_get_info = {
      device::FidoTransportProtocol::kBluetoothLowEnergy};
  virtual_device_factory_->SetCtap2Config(config);

  MakeCredentialResult result = AuthenticatorMakeCredential();
  ASSERT_EQ(result.status, AuthenticatorStatus::SUCCESS);

  base::flat_set<device::FidoTransportProtocol> reported(
      result.response->transports.begin(), result.response->transports.end());
  EXPECT_EQ(reported.size(), 2u);
  // The transports from the getInfo are authoritative and so they should be
  // reported. In addition to 'ble' from getInfo, 'usb' should be included
  // because that's what was used to communicate with the virtual authenticator.
  EXPECT_TRUE(
      reported.contains(device::FidoTransportProtocol::kBluetoothLowEnergy));
  EXPECT_TRUE(reported.contains(
      device::FidoTransportProtocol::kUsbHumanInterfaceDevice));
}

TEST_F(AuthenticatorImplTest, TransportsInAttestationCertificate) {
  NavigateAndCommit(GURL(kTestOrigin1));

  for (auto protocol :
       {device::ProtocolVersion::kU2f, device::ProtocolVersion::kCtap2}) {
    SCOPED_TRACE(static_cast<int>(protocol));
    virtual_device_factory_->SetSupportedProtocol(protocol);

    for (const auto transport : std::map<device::FidoTransportProtocol,
                                         blink::mojom::AuthenticatorTransport>(
             {{device::FidoTransportProtocol::kUsbHumanInterfaceDevice,
               blink::mojom::AuthenticatorTransport::USB},
              {device::FidoTransportProtocol::kBluetoothLowEnergy,
               blink::mojom::AuthenticatorTransport::BLE},
              {device::FidoTransportProtocol::kNearFieldCommunication,
               blink::mojom::AuthenticatorTransport::NFC}})) {
      virtual_device_factory_->SetTransport(transport.first);

      MakeCredentialResult result = AuthenticatorMakeCredential();
      EXPECT_EQ(result.status, AuthenticatorStatus::SUCCESS);

      const std::vector<device::FidoTransportProtocol>& transports(
          result.response->transports);
      ASSERT_EQ(1u, transports.size());
      EXPECT_EQ(transport.first, transports[0]);
    }
  }
}

TEST_F(AuthenticatorImplTest, ExtensionHMACSecret) {
  NavigateAndCommit(GURL(kTestOrigin1));

  for (const bool include_extension : {false, true}) {
    for (const bool authenticator_support : {false, true}) {
      for (const bool pin_support : {false, true}) {
        SCOPED_TRACE(include_extension);
        SCOPED_TRACE(authenticator_support);
        SCOPED_TRACE(pin_support);

        device::VirtualCtap2Device::Config config;
        config.hmac_secret_support = authenticator_support;
        config.pin_support = pin_support;
        virtual_device_factory_->SetCtap2Config(config);

        PublicKeyCredentialCreationOptionsPtr options =
            GetTestPublicKeyCredentialCreationOptions();
        options->hmac_create_secret = include_extension;
        MakeCredentialResult result =
            AuthenticatorMakeCredential(std::move(options));
        EXPECT_EQ(result.status, AuthenticatorStatus::SUCCESS);

        device::AuthenticatorData parsed_auth_data =
            AuthDataFromMakeCredentialResponse(result.response);

        // The virtual CTAP2 device always echos the hmac-secret extension on
        // registrations. Therefore, if |hmac_secret| was set above it should be
        // serialised in the CBOR and correctly passed all the way back around
        // to the reply's authenticator data.
        bool has_hmac_secret = false;
        const auto& extensions = parsed_auth_data.extensions();
        if (extensions) {
          CHECK(extensions->is_map());
          const cbor::Value::MapValue& extensions_map = extensions->GetMap();
          const auto hmac_secret_it =
              extensions_map.find(cbor::Value(device::kExtensionHmacSecret));
          if (hmac_secret_it != extensions_map.end()) {
            ASSERT_TRUE(hmac_secret_it->second.is_bool());
            EXPECT_TRUE(hmac_secret_it->second.GetBool());
            has_hmac_secret = true;
          }
        }

        EXPECT_EQ(include_extension && authenticator_support && pin_support,
                  has_hmac_secret);
      }
    }
  }
}

// Tests that for an authenticator that does not support batching, credential
// lists get probed silently to work around authenticators rejecting exclude
// lists exceeding a certain size.
TEST_F(AuthenticatorImplTest, MakeCredentialWithLargeExcludeList) {
  NavigateAndCommit(GURL(kTestOrigin1));

  for (bool has_excluded_credential : {false, true}) {
    SCOPED_TRACE(::testing::Message()
                 << "has_excluded_credential=" << has_excluded_credential);

    ResetVirtualDevice();
    device::VirtualCtap2Device::Config config;
    config.reject_large_allow_and_exclude_lists = true;
    virtual_device_factory_->SetCtap2Config(config);

    PublicKeyCredentialCreationOptionsPtr options =
        GetTestPublicKeyCredentialCreationOptions();
    options->exclude_credentials = GetTestCredentials(/*num_credentials=*/10);
    if (has_excluded_credential) {
      ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
          options->exclude_credentials.back().id, kTestRelyingPartyId));
    }

    EXPECT_EQ(AuthenticatorMakeCredential(std::move(options)).status,
              has_excluded_credential ? AuthenticatorStatus::CREDENTIAL_EXCLUDED
                                      : AuthenticatorStatus::SUCCESS);
  }
}

TEST_F(AuthenticatorImplTest, GetAssertionResultMetricError) {
  NavigateAndCommit(GURL(kTestOrigin1));

  base::HistogramTester histogram_tester;
  PublicKeyCredentialRequestOptionsPtr options =
      GetTestPublicKeyCredentialRequestOptions();
  EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
            AuthenticatorStatus::NOT_ALLOWED_ERROR);
  histogram_tester.ExpectUniqueSample(
      "WebAuthentication.GetAssertion.Result",
      AuthenticatorCommonImpl::CredentialRequestResult::kOtherError, 1);
}

TEST_F(AuthenticatorImplTest, GetAssertionResultMetricSuccess) {
  NavigateAndCommit(GURL(kTestOrigin1));

  base::HistogramTester histogram_tester;
  PublicKeyCredentialRequestOptionsPtr options =
      GetTestPublicKeyCredentialRequestOptions();
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
      options->allow_credentials.back().id, kTestRelyingPartyId));
  EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
            AuthenticatorStatus::SUCCESS);
  histogram_tester.ExpectUniqueSample(
      "WebAuthentication.GetAssertion.Result",
      AuthenticatorCommonImpl::CredentialRequestResult::kOtherSuccess, 1);
}

TEST_F(AuthenticatorImplTest, MakeCredentialResultMetricError) {
  NavigateAndCommit(GURL(kTestOrigin1));

  base::HistogramTester histogram_tester;
  PublicKeyCredentialCreationOptionsPtr options =
      GetTestPublicKeyCredentialCreationOptions();
  options->exclude_credentials = GetTestCredentials();
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
      options->exclude_credentials[0].id, kTestRelyingPartyId));
  EXPECT_EQ(AuthenticatorMakeCredential(std::move(options)).status,
            AuthenticatorStatus::CREDENTIAL_EXCLUDED);
  histogram_tester.ExpectUniqueSample(
      "WebAuthentication.MakeCredential.Result",
      AuthenticatorCommonImpl::CredentialRequestResult::kOtherError, 1);
}

TEST_F(AuthenticatorImplTest, MakeCredentialResultMetricSuccess) {
  NavigateAndCommit(GURL(kTestOrigin1));

  base::HistogramTester histogram_tester;
  EXPECT_EQ(AuthenticatorMakeCredential().status, AuthenticatorStatus::SUCCESS);
  histogram_tester.ExpectUniqueSample(
      "WebAuthentication.MakeCredential.Result",
      AuthenticatorCommonImpl::CredentialRequestResult::kOtherSuccess, 1);
}

// Tests that for an authenticator that does not support batching, credential
// lists get probed silently to work around authenticators rejecting allow lists
// exceeding a certain size.
TEST_F(AuthenticatorImplTest, GetAssertionWithLargeAllowList) {
  NavigateAndCommit(GURL(kTestOrigin1));

  for (bool has_allowed_credential : {false, true}) {
    SCOPED_TRACE(::testing::Message()
                 << "has_allowed_credential=" << has_allowed_credential);

    ResetVirtualDevice();
    device::VirtualCtap2Device::Config config;
    config.reject_large_allow_and_exclude_lists = true;
    virtual_device_factory_->SetCtap2Config(config);

    PublicKeyCredentialRequestOptionsPtr options =
        GetTestPublicKeyCredentialRequestOptions();
    options->allow_credentials = GetTestCredentials(/*num_credentials=*/10);
    if (has_allowed_credential) {
      ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
          options->allow_credentials.back().id, kTestRelyingPartyId));
    }

    EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
              has_allowed_credential ? AuthenticatorStatus::SUCCESS
                                     : AuthenticatorStatus::NOT_ALLOWED_ERROR);
  }
}

// Tests that, regardless of batching support, GetAssertion requests with a
// single allowed credential ID don't result in a silent probing request.
TEST_F(AuthenticatorImplTest, GetAssertionSingleElementAllowListDoesNotProbe) {
  NavigateAndCommit(GURL(kTestOrigin1));

  for (bool supports_batching : {false, true}) {
    SCOPED_TRACE(::testing::Message()
                 << "supports_batching=" << supports_batching);

    ResetVirtualDevice();
    device::VirtualCtap2Device::Config config;
    if (supports_batching) {
      config.max_credential_id_length = kTestCredentialIdLength;
      config.max_credential_count_in_list = 10;
    }
    config.reject_silent_authentication_requests = true;
    virtual_device_factory_->SetCtap2Config(config);

    auto test_credentials = GetTestCredentials(/*num_credentials=*/1);
    ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
        test_credentials.front().id, kTestRelyingPartyId));

    PublicKeyCredentialRequestOptionsPtr options =
        GetTestPublicKeyCredentialRequestOptions();
    options->allow_credentials = std::move(test_credentials);

    EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
              AuthenticatorStatus::SUCCESS);
  }
}

// Tests that an allow list that fits into a single batch does not result in a
// silent probing request.
TEST_F(AuthenticatorImplTest, GetAssertionSingleBatchListDoesNotProbe) {
  NavigateAndCommit(GURL(kTestOrigin1));

  for (bool allow_list_fits_single_batch : {false, true}) {
    SCOPED_TRACE(::testing::Message() << "allow_list_fits_single_batch="
                                      << allow_list_fits_single_batch);

    ResetVirtualDevice();
    device::VirtualCtap2Device::Config config;
    config.max_credential_id_length = kTestCredentialIdLength;
    constexpr size_t kBatchSize = 10;
    config.max_credential_count_in_list = kBatchSize;
    config.reject_silent_authentication_requests = true;
    virtual_device_factory_->SetCtap2Config(config);

    auto test_credentials = GetTestCredentials(
        /*num_credentials=*/kBatchSize +
        (allow_list_fits_single_batch ? 0 : 1));
    ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
        test_credentials.back().id, kTestRelyingPartyId));

    PublicKeyCredentialRequestOptionsPtr options =
        GetTestPublicKeyCredentialRequestOptions();
    options->allow_credentials = std::move(test_credentials);

    EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
              allow_list_fits_single_batch
                  ? AuthenticatorStatus::SUCCESS
                  : AuthenticatorStatus::NOT_ALLOWED_ERROR);
  }
}

TEST_F(AuthenticatorImplTest, OptionalCredentialInAssertionResponse) {
  // This test exercises the unfortunate optionality in the CTAP2 spec r.e.
  // whether an authenticator returns credential information when the allowlist
  // only has a single entry.
  NavigateAndCommit(GURL(kTestOrigin1));

  for (const auto behavior :
       {device::VirtualCtap2Device::Config::IncludeCredential::ONLY_IF_NEEDED,
        device::VirtualCtap2Device::Config::IncludeCredential::ALWAYS,
        device::VirtualCtap2Device::Config::IncludeCredential::NEVER}) {
    SCOPED_TRACE(static_cast<int>(behavior));

    ResetVirtualDevice();
    device::VirtualCtap2Device::Config config;
    config.include_credential_in_assertion_response = behavior;
    config.max_credential_count_in_list = 10;
    config.max_credential_id_length = 256;
    virtual_device_factory_->SetCtap2Config(config);

    size_t num_credentials;
    bool should_timeout = false;
    switch (behavior) {
      case device::VirtualCtap2Device::Config::IncludeCredential::
          ONLY_IF_NEEDED:
        // The behaviour to test for |ONLY_IF_NEEDED| is that an omitted
        // credential in the response is handled correctly.
        num_credentials = 1;
        break;
      case device::VirtualCtap2Device::Config::IncludeCredential::ALWAYS:
        // Also test that a technically-superfluous credential in the response
        // is handled.
        num_credentials = 1;
        break;
      case device::VirtualCtap2Device::Config::IncludeCredential::NEVER:
        // Test that omitting a credential in an ambiguous context causes a
        // failure.
        num_credentials = 2;
        should_timeout = true;
        break;
    }

    auto test_credentials = GetTestCredentials(num_credentials);
    for (const auto& cred : test_credentials) {
      ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
          cred.id, kTestRelyingPartyId));
    }

    PublicKeyCredentialRequestOptionsPtr options =
        GetTestPublicKeyCredentialRequestOptions();
    options->allow_credentials = std::move(test_credentials);

    if (should_timeout) {
      EXPECT_EQ(
          AuthenticatorGetAssertionAndWaitForTimeout(std::move(options)).status,
          AuthenticatorStatus::NOT_ALLOWED_ERROR);
    } else {
      EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
                AuthenticatorStatus::SUCCESS);
    }
  }
}

// Tests that an allowList with only credential IDs of a length exceeding the
// maxCredentialIdLength parameter is not mistakenly interpreted as an empty
// allow list.
TEST_F(AuthenticatorImplTest, AllowListWithOnlyOversizedCredentialIds) {
  NavigateAndCommit(GURL(kTestOrigin1));

  device::VirtualCtap2Device::Config config;
  config.u2f_support = true;
  config.max_credential_id_length = kTestCredentialIdLength;
  config.max_credential_count_in_list = 10;
  virtual_device_factory_->SetCtap2Config(config);

  const std::vector<uint8_t> cred_id(kTestCredentialIdLength + 1, 0);
  // Inject registration so that the test will fail (because of a successful
  // response) if the oversized credential ID is sent.
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
      cred_id, kTestRelyingPartyId));

  for (const bool has_app_id : {false, true}) {
    SCOPED_TRACE(has_app_id);
    virtual_device_factory_->mutable_state()->allow_list_history.clear();

    PublicKeyCredentialRequestOptionsPtr options =
        GetTestPublicKeyCredentialRequestOptions();
    if (has_app_id) {
      options->extensions->appid = kTestOrigin1;
    }
    options->allow_credentials = {device::PublicKeyCredentialDescriptor(
        device::CredentialType::kPublicKey, cred_id)};

    EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
              AuthenticatorStatus::NOT_ALLOWED_ERROR);
    const auto& allow_list_history =
        virtual_device_factory_->mutable_state()->allow_list_history;
    // No empty allow-list requests should have been made.
    EXPECT_TRUE(std::ranges::none_of(
        allow_list_history,
        [](const std::vector<device::PublicKeyCredentialDescriptor>&
               allow_list) { return allow_list.empty(); }));
  }
}

// Tests that duplicate credential IDs are filtered from an assertion allow_list
// parameter.
TEST_F(AuthenticatorImplTest, AllowListWithDuplicateCredentialIds) {
  NavigateAndCommit(GURL(kTestOrigin1));

  device::VirtualCtap2Device::Config config;
  config.u2f_support = true;
  config.max_credential_id_length = kTestCredentialIdLength;
  config.max_credential_count_in_list = 10;
  virtual_device_factory_->SetCtap2Config(config);

  device::PublicKeyCredentialDescriptor cred_a(
      device::CredentialType::kPublicKey,
      std::vector<uint8_t>(kTestCredentialIdLength, 1), {});
  device::PublicKeyCredentialDescriptor cred_b(
      device::CredentialType::kPublicKey,
      std::vector<uint8_t>(kTestCredentialIdLength, 2),
      {device::FidoTransportProtocol::kUsbHumanInterfaceDevice});
  // Same ID as `cred_a` and `cred_b` but with different transports. Transport
  // hints from descriptors with equal IDs should be merged.
  device::PublicKeyCredentialDescriptor cred_c(
      device::CredentialType::kPublicKey,
      std::vector<uint8_t>(kTestCredentialIdLength, 1),
      {device::FidoTransportProtocol::kBluetoothLowEnergy});
  device::PublicKeyCredentialDescriptor cred_d(
      device::CredentialType::kPublicKey,
      std::vector<uint8_t>(kTestCredentialIdLength, 2),
      {device::FidoTransportProtocol::kBluetoothLowEnergy});

  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
      cred_b.id, kTestRelyingPartyId));

  PublicKeyCredentialRequestOptionsPtr options =
      GetTestPublicKeyCredentialRequestOptions();
  options->allow_credentials.clear();
  options->allow_credentials.insert(options->allow_credentials.end(), 5,
                                    cred_a);
  options->allow_credentials.push_back(cred_b);
  options->allow_credentials.insert(options->allow_credentials.end(), 3,
                                    cred_c);
  options->allow_credentials.insert(options->allow_credentials.end(), 2,
                                    cred_d);

  EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
            AuthenticatorStatus::SUCCESS);
  EXPECT_EQ(virtual_device_factory_->mutable_state()->allow_list_history.size(),
            1u);
  device::PublicKeyCredentialDescriptor cred_a_and_c(
      device::CredentialType::kPublicKey,
      std::vector<uint8_t>(kTestCredentialIdLength, 1));
  device::PublicKeyCredentialDescriptor cred_b_and_d(
      device::CredentialType::kPublicKey,
      std::vector<uint8_t>(kTestCredentialIdLength, 2));
  EXPECT_THAT(
      virtual_device_factory_->mutable_state()->allow_list_history.at(0),
      testing::UnorderedElementsAre(cred_a_and_c, cred_b_and_d));
}

// Tests that duplicate credential IDs are filtered from a registration
// exclude_list parameter.
TEST_F(AuthenticatorImplTest, ExcludeListWithDuplicateCredentialIds) {
  NavigateAndCommit(GURL(kTestOrigin1));

  device::VirtualCtap2Device::Config config;
  config.u2f_support = true;
  config.max_credential_id_length = kTestCredentialIdLength;
  config.max_credential_count_in_list = 100;
  virtual_device_factory_->SetCtap2Config(config);

  device::PublicKeyCredentialDescriptor cred_a(
      device::CredentialType::kPublicKey,
      std::vector<uint8_t>(kTestCredentialIdLength, 1), {});
  device::PublicKeyCredentialDescriptor cred_b(
      device::CredentialType::kPublicKey,
      std::vector<uint8_t>(kTestCredentialIdLength, 2),
      {device::FidoTransportProtocol::kUsbHumanInterfaceDevice});
  // Same ID as `cred_a` and `cred_b` but with different transports. Transport
  // hints from descriptors with equal IDs should be merged.
  device::PublicKeyCredentialDescriptor cred_c(
      device::CredentialType::kPublicKey,
      std::vector<uint8_t>(kTestCredentialIdLength, 1),
      {device::FidoTransportProtocol::kBluetoothLowEnergy});
  device::PublicKeyCredentialDescriptor cred_d(
      device::CredentialType::kPublicKey,
      std::vector<uint8_t>(kTestCredentialIdLength, 2),
      {device::FidoTransportProtocol::kBluetoothLowEnergy});

  PublicKeyCredentialCreationOptionsPtr options =
      GetTestPublicKeyCredentialCreationOptions();
  options->exclude_credentials.clear();
  options->exclude_credentials.insert(options->exclude_credentials.end(), 5,
                                      cred_a);
  options->exclude_credentials.push_back(cred_b);
  options->exclude_credentials.insert(options->exclude_credentials.end(), 3,
                                      cred_c);
  options->exclude_credentials.insert(options->exclude_credentials.end(), 2,
                                      cred_d);

  EXPECT_EQ(AuthenticatorMakeCredential(std::move(options)).status,
            AuthenticatorStatus::SUCCESS);
  EXPECT_EQ(
      virtual_device_factory_->mutable_state()->exclude_list_history.size(),
      1u);
  device::PublicKeyCredentialDescriptor cred_a_and_c(
      device::CredentialType::kPublicKey,
      std::vector<uint8_t>(kTestCredentialIdLength, 1));
  device::PublicKeyCredentialDescriptor cred_b_and_d(
      device::CredentialType::kPublicKey,
      std::vector<uint8_t>(kTestCredentialIdLength, 2));
  EXPECT_THAT(
      virtual_device_factory_->mutable_state()->exclude_list_history.at(0),
      testing::UnorderedElementsAre(cred_a_and_c, cred_b_and_d));
}

// Test that allow lists over 64 entries are verboten.
TEST_F(AuthenticatorImplTest, OversizedAllowList) {
  NavigateAndCommit(GURL(kTestOrigin1));

  device::VirtualCtap2Device::Config config;
  config.u2f_support = true;
  config.max_credential_id_length = kTestCredentialIdLength;
  config.max_credential_count_in_list = 100;
  virtual_device_factory_->SetCtap2Config(config);

  auto test_credentials = GetTestCredentials(
      /*num_credentials=*/blink::mojom::
          kPublicKeyCredentialDescriptorListMaxSize +
      1);
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
      test_credentials.at(0).id, kTestRelyingPartyId));

  PublicKeyCredentialRequestOptionsPtr options =
      GetTestPublicKeyCredentialRequestOptions();
  options->allow_credentials = test_credentials;

  bool has_mojo_error = false;
  SetMojoErrorHandler(base::BindLambdaForTesting(
      [&](const std::string& error) { has_mojo_error = true; }));

  EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
            AuthenticatorStatus::NOT_ALLOWED_ERROR);
  EXPECT_TRUE(has_mojo_error);
}

// Test that exclude lists over 64 entries are verboten.
TEST_F(AuthenticatorImplTest, OversizedExcludeList) {
  NavigateAndCommit(GURL(kTestOrigin1));

  device::VirtualCtap2Device::Config config;
  config.u2f_support = true;
  config.max_credential_id_length = kTestCredentialIdLength;
  config.max_credential_count_in_list = 100;
  virtual_device_factory_->SetCtap2Config(config);

  auto test_credentials = GetTestCredentials(
      /*num_credentials=*/blink::mojom::
          kPublicKeyCredentialDescriptorListMaxSize +
      1);

  PublicKeyCredentialCreationOptionsPtr options =
      GetTestPublicKeyCredentialCreationOptions();
  options->exclude_credentials = test_credentials;

  bool has_mojo_error = false;
  SetMojoErrorHandler(base::BindLambdaForTesting(
      [&](const std::string& error) { has_mojo_error = true; }));

  EXPECT_EQ(AuthenticatorMakeCredential(std::move(options)).status,
            AuthenticatorStatus::NOT_ALLOWED_ERROR);
  EXPECT_TRUE(has_mojo_error);
}

TEST_F(AuthenticatorImplTest, NoUnexpectedAuthenticatorExtensions) {
  NavigateAndCommit(GURL(kTestOrigin1));

  device::VirtualCtap2Device::Config config;
  config.add_extra_extension = true;
  virtual_device_factory_->SetCtap2Config(config);

  // Check that extra authenticator extensions are rejected when creating a
  // credential.
  EXPECT_EQ(AuthenticatorMakeCredential().status,
            AuthenticatorStatus::NOT_ALLOWED_ERROR);

  // Extensions should also be rejected when getting an assertion.
  PublicKeyCredentialRequestOptionsPtr assertion_options =
      GetTestPublicKeyCredentialRequestOptions();
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
      assertion_options->allow_credentials.back().id, kTestRelyingPartyId));
  EXPECT_EQ(AuthenticatorGetAssertion(std::move(assertion_options)).status,
            AuthenticatorStatus::NOT_ALLOWED_ERROR);
}

TEST_F(AuthenticatorImplTest, NoUnexpectedClientExtensions) {
  NavigateAndCommit(GURL(kTestOrigin1));

  device::VirtualCtap2Device::Config config;
  config.reject_all_extensions = true;
  virtual_device_factory_->SetCtap2Config(config);

  // Check that no unexpected client extensions are sent to the authenticator.
  EXPECT_EQ(AuthenticatorMakeCredential().status, AuthenticatorStatus::SUCCESS);

  // No extensions should be sent when getting an assertion either.
  PublicKeyCredentialRequestOptionsPtr assertion_options =
      GetTestPublicKeyCredentialRequestOptions();
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
      assertion_options->allow_credentials.back().id, kTestRelyingPartyId));
  EXPECT_EQ(AuthenticatorGetAssertion(std::move(assertion_options)).status,
            AuthenticatorStatus::SUCCESS);
}

// Tests that on an authenticator that supports batching, exclude lists that fit
// into a single batch are sent without probing.
TEST_F(AuthenticatorImplTest, ExcludeListBatching) {
  NavigateAndCommit(GURL(kTestOrigin1));

  for (bool authenticator_has_excluded_credential : {false, true}) {
    SCOPED_TRACE(::testing::Message()
                 << "authenticator_has_excluded_credential="
                 << authenticator_has_excluded_credential);

    ResetVirtualDevice();
    device::VirtualCtap2Device::Config config;
    config.max_credential_id_length = kTestCredentialIdLength;
    constexpr size_t kBatchSize = 10;
    config.max_credential_count_in_list = kBatchSize;
    // Reject silent authentication requests to ensure we are not probing
    // credentials silently, since the exclude list should fit into a single
    // batch.
    config.reject_silent_authentication_requests = true;
    virtual_device_factory_->SetCtap2Config(config);

    auto test_credentials = GetTestCredentials(kBatchSize);
    test_credentials.insert(
        test_credentials.end() - 1,
        {device::CredentialType::kPublicKey,
         std::vector<uint8_t>(kTestCredentialIdLength + 1, 1)});
    if (authenticator_has_excluded_credential) {
      ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
          test_credentials.back().id, kTestRelyingPartyId));
    }

    PublicKeyCredentialCreationOptionsPtr options =
        GetTestPublicKeyCredentialCreationOptions();
    options->exclude_credentials = std::move(test_credentials);
    EXPECT_EQ(AuthenticatorMakeCredential(std::move(options)).status,
              authenticator_has_excluded_credential
                  ? AuthenticatorStatus::CREDENTIAL_EXCLUDED
                  : AuthenticatorStatus::SUCCESS);
  }
}

TEST_F(AuthenticatorImplTest, GetPublicKey) {
  NavigateAndCommit(GURL(kTestOrigin1));

  static constexpr struct {
    device::CoseAlgorithmIdentifier algo;
    std::optional<int> evp_id;
  } kTests[] = {
      {device::CoseAlgorithmIdentifier::kEs256, EVP_PKEY_EC},
      {device::CoseAlgorithmIdentifier::kRs256, EVP_PKEY_RSA},
      {device::CoseAlgorithmIdentifier::kEdDSA, EVP_PKEY_ED25519},
      {device::CoseAlgorithmIdentifier::kInvalidForTesting, std::nullopt},
  };

  std::vector<device::CoseAlgorithmIdentifier> advertised_algorithms;
  for (const auto& test : kTests) {
    advertised_algorithms.push_back(test.algo);
  }

  device::VirtualCtap2Device::Config config;
  config.advertised_algorithms = std::move(advertised_algorithms);
  virtual_device_factory_->SetCtap2Config(config);

  for (const auto& test : kTests) {
    PublicKeyCredentialCreationOptionsPtr options =
        GetTestPublicKeyCredentialCreationOptions();
    options->public_key_parameters =
        GetTestPublicKeyCredentialParameters(static_cast<int32_t>(test.algo));

    MakeCredentialResult result =
        AuthenticatorMakeCredential(std::move(options));
    ASSERT_EQ(result.status, AuthenticatorStatus::SUCCESS);
    const auto& response = result.response;
    EXPECT_EQ(response->public_key_algo, static_cast<int32_t>(test.algo));

    // The value of the parsed authenticator data should match what's in
    // the attestation object.
    std::optional<Value> attestation_value =
        Reader::Read(response->attestation_object);
    CHECK(attestation_value);
    const auto& attestation = attestation_value->GetMap();
    const auto auth_data_it = attestation.find(Value(device::kAuthDataKey));
    CHECK(auth_data_it != attestation.end());
    const std::vector<uint8_t>& auth_data =
        auth_data_it->second.GetBytestring();
    EXPECT_EQ(auth_data, response->info->authenticator_data);

    ASSERT_EQ(test.evp_id.has_value(), response->public_key_der.has_value());
    if (!test.evp_id) {
      continue;
    }

    bssl::UniquePtr<EVP_PKEY> pkey =
        crypto::evp::PublicKeyFromBytes(response->public_key_der.value());
    ASSERT_TRUE(pkey.get());

    EXPECT_EQ(test.evp_id.value(), EVP_PKEY_id(pkey.get()));
  }
}

TEST_F(AuthenticatorImplTest, AlgorithmsOmitted) {
  // Some CTAP 2.0 security keys shipped support for algorithms other than
  // ECDSA P-256 but the algorithms field didn't exist then. makeCredential
  // requests should get routed to them anyway.

  device::VirtualCtap2Device::Config config;
  // Remove the algorithms field from the getInfo.
  config.advertised_algorithms.clear();
  virtual_device_factory_->SetCtap2Config(config);
  NavigateAndCommit(GURL(kTestOrigin1));

  // Test that an Ed25519 credential can still be created. (The virtual
  // authenticator supports that algorithm.)
  {
    const int32_t algo =
        static_cast<int32_t>(device::CoseAlgorithmIdentifier::kEdDSA);
    PublicKeyCredentialCreationOptionsPtr options =
        GetTestPublicKeyCredentialCreationOptions();
    options->public_key_parameters = GetTestPublicKeyCredentialParameters(algo);
    MakeCredentialResult result =
        AuthenticatorMakeCredential(std::move(options));
    ASSERT_EQ(result.status, AuthenticatorStatus::SUCCESS);
    const auto& response = result.response;
    EXPECT_EQ(response->public_key_algo, algo);
  }

  // Test that requesting an unsupported algorithm still collects a touch.
  {
    bool touched = false;
    virtual_device_factory_->mutable_state()->simulate_press_callback =
        base::BindLambdaForTesting([&](device::VirtualFidoDevice* device) {
          touched = true;
          return true;
        });

    const int32_t algo = static_cast<int32_t>(
        device::CoseAlgorithmIdentifier::kInvalidForTesting);
    PublicKeyCredentialCreationOptionsPtr options =
        GetTestPublicKeyCredentialCreationOptions();
    options->public_key_parameters = GetTestPublicKeyCredentialParameters(algo);
    MakeCredentialResult result =
        AuthenticatorMakeCredential(std::move(options));
    EXPECT_EQ(result.status, AuthenticatorStatus::NOT_ALLOWED_ERROR);
    VerifyMakeCredentialOutcomeUkm(
        1, MakeCredentialOutcome::kAlgorithmNotSupported,
        AuthenticationRequestMode::kModalWebAuthn);
    EXPECT_TRUE(touched);
  }
}

TEST_F(AuthenticatorImplTest, VirtualAuthenticatorPublicKeyAlgos) {
  // Exercise all the public key types in the virtual authenticator for create()
  // and get().
  NavigateAndCommit(GURL(kTestOrigin1));

  static const struct {
    STACK_ALLOCATED();

   public:
    device::CoseAlgorithmIdentifier algo;
    const EVP_MD* digest;
  } kTests[] = {
      {device::CoseAlgorithmIdentifier::kEs256, EVP_sha256()},
      {device::CoseAlgorithmIdentifier::kRs256, EVP_sha256()},
      {device::CoseAlgorithmIdentifier::kEdDSA, nullptr},
  };

  std::vector<device::CoseAlgorithmIdentifier> advertised_algorithms;
  for (const auto& test : kTests) {
    advertised_algorithms.push_back(test.algo);
  }

  device::VirtualCtap2Device::Config config;
  config.advertised_algorithms = std::move(advertised_algorithms);
  virtual_device_factory_->SetCtap2Config(config);

  for (const auto& test : kTests) {
    SCOPED_TRACE(static_cast<int>(test.algo));

    PublicKeyCredentialCreationOptionsPtr create_options =
        GetTestPublicKeyCredentialCreationOptions();
    create_options->public_key_parameters =
        GetTestPublicKeyCredentialParameters(static_cast<int32_t>(test.algo));

    MakeCredentialResult create_result =
        AuthenticatorMakeCredential(std::move(create_options));
    ASSERT_EQ(create_result.status, AuthenticatorStatus::SUCCESS);
    EXPECT_EQ(create_result.response->public_key_algo,
              static_cast<int32_t>(test.algo));

    bssl::UniquePtr<EVP_PKEY> pkey = crypto::evp::PublicKeyFromBytes(
        create_result.response->public_key_der.value());
    ASSERT_TRUE(pkey.get());

    PublicKeyCredentialRequestOptionsPtr get_options =
        GetTestPublicKeyCredentialRequestOptions();
    device::PublicKeyCredentialDescriptor public_key(
        device::CredentialType::kPublicKey,
        create_result.response->info->raw_id,
        {device::FidoTransportProtocol::kUsbHumanInterfaceDevice});
    get_options->allow_credentials = {std::move(public_key)};
    GetAssertionResult get_result =
        AuthenticatorGetAssertion(std::move(get_options));
    ASSERT_EQ(get_result.status, AuthenticatorStatus::SUCCESS);
    base::span<const uint8_t> signature(get_result.response->signature);
    std::vector<uint8_t> signed_data(
        get_result.response->info->authenticator_data);
    std::array<uint8_t, crypto::hash::kSha256Size> client_data_json_hash =
        crypto::hash::Sha256(get_result.response->info->client_data_json);
    signed_data.insert(signed_data.end(), client_data_json_hash.begin(),
                       client_data_json_hash.end());

    bssl::ScopedEVP_MD_CTX md_ctx;
    ASSERT_EQ(EVP_DigestVerifyInit(md_ctx.get(), /*pctx=*/nullptr, test.digest,
                                   /*e=*/nullptr, pkey.get()),
              1);
    EXPECT_EQ(EVP_DigestVerify(md_ctx.get(), signature.data(), signature.size(),
                               signed_data.data(), signed_data.size()),
              1);
  }
}

TEST_F(AuthenticatorImplTest, TestAuthenticationTransport) {
  // TODO(crbug.com/40197472): handle case where the transport is unknown.
  NavigateAndCommit(GURL(kTestOrigin1));
  // Verify transport used during authentication is correctly being returned
  // to the renderer layer.
  for (const device::FidoTransportProtocol transport :
       {device::FidoTransportProtocol::kUsbHumanInterfaceDevice,
        device::FidoTransportProtocol::kBluetoothLowEnergy,
        device::FidoTransportProtocol::kNearFieldCommunication,
        device::FidoTransportProtocol::kInternal}) {
    device::AuthenticatorAttachment attachment =
        (transport == device::FidoTransportProtocol::kInternal
             ? device::AuthenticatorAttachment::kPlatform
             : device::AuthenticatorAttachment::kCrossPlatform);
    ResetVirtualDevice();
    virtual_device_factory_->SetSupportedProtocol(
        device::ProtocolVersion::kCtap2);
    virtual_device_factory_->SetTransport(transport);
    virtual_device_factory_->mutable_state()->transport = transport;

    PublicKeyCredentialCreationOptionsPtr create_options =
        GetTestPublicKeyCredentialCreationOptions();
    MakeCredentialResult create_result =
        AuthenticatorMakeCredential(std::move(create_options));
    ASSERT_EQ(create_result.status, AuthenticatorStatus::SUCCESS);
    EXPECT_EQ(create_result.response->authenticator_attachment, attachment);

    PublicKeyCredentialRequestOptionsPtr get_options =
        GetTestPublicKeyCredentialRequestOptions();
    device::PublicKeyCredentialDescriptor public_key(
        device::CredentialType::kPublicKey,
        create_result.response->info->raw_id, {transport});
    get_options->allow_credentials = {std::move(public_key)};
    GetAssertionResult get_result =
        AuthenticatorGetAssertion(std::move(get_options));
    ASSERT_EQ(get_result.status, AuthenticatorStatus::SUCCESS);
    EXPECT_EQ(get_result.response->authenticator_attachment, attachment);
  }
}

TEST_F(AuthenticatorImplTest, ResetDiscoveryFactoryOverride) {
  // This is a regression test for crbug.com/1087158.
  NavigateAndCommit(GURL(kTestOrigin1));

  // Make the entire discovery factory disappear mid-request.
  bool IsReady = false;
  virtual_device_factory_->SetSupportedProtocol(
      device::ProtocolVersion::kCtap2);
  virtual_device_factory_->mutable_state()->simulate_press_callback =
      base::BindLambdaForTesting([&](device::VirtualFidoDevice* device) {
        IsReady = true;
        ResetVirtualDevice();
        return false;
      });

  PublicKeyCredentialCreationOptionsPtr options =
      GetTestPublicKeyCredentialCreationOptions();
  EXPECT_EQ(
      AuthenticatorMakeCredentialAndWaitForTimeout(std::move(options)).status,
      AuthenticatorStatus::NOT_ALLOWED_ERROR);
}

TEST_F(AuthenticatorImplTest, InvalidU2FPublicKey) {
  NavigateAndCommit(GURL(kTestOrigin1));
  virtual_device_factory_->SetSupportedProtocol(device::ProtocolVersion::kU2f);
  virtual_device_factory_->mutable_state()->u2f_invalid_public_key = true;

  PublicKeyCredentialCreationOptionsPtr options =
      GetTestPublicKeyCredentialCreationOptions();
  EXPECT_EQ(AuthenticatorMakeCredential(std::move(options)).status,
            AuthenticatorStatus::NOT_ALLOWED_ERROR);
}

TEST_F(AuthenticatorImplTest, InvalidU2FSignature) {
  NavigateAndCommit(GURL(kTestOrigin1));
  virtual_device_factory_->SetSupportedProtocol(device::ProtocolVersion::kU2f);
  virtual_device_factory_->mutable_state()->u2f_invalid_signature = true;

  PublicKeyCredentialRequestOptionsPtr options =
      GetTestPublicKeyCredentialRequestOptions();
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
      options->allow_credentials[0].id, kTestOrigin1));
  options->extensions->appid = kTestOrigin1;

  EXPECT_EQ(
      AuthenticatorGetAssertionAndWaitForTimeout(std::move(options)).status,
      AuthenticatorStatus::NOT_ALLOWED_ERROR);
}

TEST_F(AuthenticatorImplTest, CredBlob) {
  NavigateAndCommit(GURL(kTestOrigin1));

  device::VirtualCtap2Device::Config config;
  config.cred_blob_support = true;
  // credProtect is required for credBlob per CTAP 2.1.
  config.cred_protect_support = true;
  virtual_device_factory_->SetCtap2Config(config);

  const std::vector<uint8_t> cred_blob = {1, 2, 3, 4};

  std::vector<uint8_t> credential_id;
  // Create a credential with a credBlob set.
  {
    PublicKeyCredentialCreationOptionsPtr options =
        GetTestPublicKeyCredentialCreationOptions();
    options->cred_blob = cred_blob;
    auto result = AuthenticatorMakeCredential(std::move(options));
    ASSERT_EQ(result.status, AuthenticatorStatus::SUCCESS);
    credential_id = std::move(result.response->info->raw_id);
    EXPECT_TRUE(result.response->echo_cred_blob);
    EXPECT_TRUE(result.response->cred_blob);
  }

  // Expect to be able to fetch the credBlob with an assertion.
  {
    PublicKeyCredentialRequestOptionsPtr options =
        GetTestPublicKeyCredentialRequestOptions();
    options->allow_credentials[0] = device::PublicKeyCredentialDescriptor(
        device::CredentialType::kPublicKey, std::move(credential_id));
    options->extensions->get_cred_blob = true;

    auto result = AuthenticatorGetAssertion(std::move(options));
    ASSERT_EQ(result.status, AuthenticatorStatus::SUCCESS);
    EXPECT_EQ(result.response->extensions->get_cred_blob, cred_blob);
  }
}

TEST_F(AuthenticatorImplTest, MinPINLength) {
  NavigateAndCommit(GURL(kTestOrigin1));

  for (const bool min_pin_length_supported : {false, true}) {
    device::VirtualCtap2Device::Config config;
    config.min_pin_length_extension_support = min_pin_length_supported;
    virtual_device_factory_->SetCtap2Config(config);

    for (const bool min_pin_length_requested : {false, true}) {
      PublicKeyCredentialCreationOptionsPtr options =
          GetTestPublicKeyCredentialCreationOptions();
      options->min_pin_length_requested = min_pin_length_requested;
      auto result = AuthenticatorMakeCredential(std::move(options));
      ASSERT_EQ(result.status, AuthenticatorStatus::SUCCESS);

      const device::AuthenticatorData auth_data =
          AuthDataFromMakeCredentialResponse(result.response);
      bool has_min_pin_length = false;
      if (auth_data.extensions().has_value()) {
        const cbor::Value::MapValue& extensions =
            auth_data.extensions()->GetMap();
        const auto it =
            extensions.find(cbor::Value(device::kExtensionMinPINLength));
        has_min_pin_length = it != extensions.end() && it->second.is_unsigned();
      }
      ASSERT_EQ(has_min_pin_length,
                min_pin_length_supported && min_pin_length_requested);
    }
  }
}

// Regression test for crbug.com/1257281.
// Tests that a request is not cancelled when an authenticator returns
// CTAP2_ERR_KEEPALIVE_CANCEL after selecting another authenticator for a
// request.
TEST_F(AuthenticatorImplTest, CancellingAuthenticatorDoesNotTerminateRequest) {
  NavigateAndCommit(GURL(kTestOrigin1));
  for (auto request_type : {device::FidoRequestType::kMakeCredential,
                            device::FidoRequestType::kGetAssertion}) {
    SCOPED_TRACE(::testing::Message()
                 << "request_type="
                 << (request_type == device::FidoRequestType::kMakeCredential
                         ? "make_credential"
                         : "get_assertion"));
    // Make a device that supports getting a PUAT with UV.
    auto discovery =
        std::make_unique<device::test::MultipleVirtualFidoDeviceFactory>();
    device::test::MultipleVirtualFidoDeviceFactory::DeviceDetails device_1;
    device_1.config.internal_uv_support = true;
    device_1.config.pin_uv_auth_token_support = true;
    device_1.config.user_verification_succeeds = true;
    device_1.config.ctap2_versions = {device::Ctap2Version::kCtap2_1};
    device_1.state->fingerprints_enrolled = true;
    PublicKeyCredentialRequestOptionsPtr dummy_options =
        GetTestPublicKeyCredentialRequestOptions();
    ASSERT_TRUE(device_1.state->InjectRegistration(
        dummy_options->allow_credentials[0].id, kTestRelyingPartyId));
    discovery->AddDevice(std::move(device_1));

    // Make a device that does not support PUATs but can still handle the
    // request. This device will not respond to the request.
    device::test::MultipleVirtualFidoDeviceFactory::DeviceDetails device_2;
    device_2.config.internal_uv_support = false;
    device_2.config.pin_uv_auth_token_support = false;
    device_2.config.ctap2_versions = {device::Ctap2Version::kCtap2_0};
    device_2.state->simulate_press_callback =
        base::BindRepeating([](VirtualFidoDevice* ignore) { return false; });
    discovery->AddDevice(std::move(device_2));
    ReplaceDiscoveryFactory(std::move(discovery));

    if (request_type == device::FidoRequestType::kMakeCredential) {
      MakeCredentialResult result = AuthenticatorMakeCredential();
      EXPECT_EQ(result.status, AuthenticatorStatus::SUCCESS);
    } else {
      GetAssertionResult result = AuthenticatorGetAssertion();
      EXPECT_EQ(result.status, AuthenticatorStatus::SUCCESS);
    }
  }
}

TEST_F(AuthenticatorImplTest, PRFWithoutSupport) {
  // This tests that the PRF extension doesn't trigger any DCHECKs or crashes
  // when used with an authenticator doesn't doesn't support hmac-secret.
  NavigateAndCommit(GURL(kTestOrigin1));

  auto prf_value = blink::mojom::PRFValues::New();
  const std::vector<uint8_t> salt1(32, 1);
  prf_value->first = salt1;
  std::vector<blink::mojom::PRFValuesPtr> prf_inputs;
  prf_inputs.emplace_back(std::move(prf_value));

  PublicKeyCredentialRequestOptionsPtr options =
      GetTestPublicKeyCredentialRequestOptions();
  options->extensions->prf = true;
  options->extensions->prf_inputs = std::move(prf_inputs);

  GetAssertionResult result = AuthenticatorGetAssertion(std::move(options));

  EXPECT_EQ(result.status, AuthenticatorStatus::NOT_ALLOWED_ERROR);
}

// These test verify that the virtual authenticator supports the Signal API.
class VirtualAuthenticatorSignalTest : public AuthenticatorImplTest {
 public:
  static constexpr char kUsername[] = "reimu";
  static constexpr char kDisplayName[] = "Reimu Hakurei";
  const std::vector<uint8_t> kUserId = {2};

  void SetUp() override {
    AuthenticatorImplTest::SetUp();
    NavigateAndCommit(GURL(kTestOrigin1));

    // These tests need an AuthenticatorEnvironment set up.
    virtual_device_factory_ = nullptr;
    content::AuthenticatorEnvironment* authenticator_environment =
        content::AuthenticatorEnvironment::GetInstance();
    authenticator_environment->Reset();
    FrameTreeNode* frame_tree_node =
        static_cast<content::RenderFrameHostImpl*>(main_rfh())
            ->frame_tree_node();
    authenticator_environment->EnableVirtualAuthenticatorFor(
        frame_tree_node,
        /*enable_ui=*/false);
    VirtualAuthenticatorManagerImpl* virtual_authenticator_manager =
        authenticator_environment->MaybeGetVirtualAuthenticatorManager(
            frame_tree_node);
    VirtualAuthenticator::Options virt_auth_options;
    virt_auth_options.protocol = device::ProtocolVersion::kCtap2;
    virt_auth_options.transport = device::FidoTransportProtocol::kInternal;
    virt_auth_options.has_resident_key = true;
    authenticator_ =
        virtual_authenticator_manager
            ->AddAuthenticatorAndReturnNonOwningPointer(virt_auth_options);

    // Make a credential.
    PublicKeyCredentialCreationOptionsPtr options =
        GetTestPublicKeyCredentialCreationOptions();
    options->user.id = kUserId;
    options->user.name = kUsername;
    options->user.display_name = kDisplayName;
    options->authenticator_selection->resident_key =
        device::ResidentKeyRequirement::kRequired;
    MakeCredentialResult result =
        AuthenticatorMakeCredential(std::move(options));
    ASSERT_EQ(result.status, AuthenticatorStatus::SUCCESS);
    credential_id_ = result.response->info->raw_id;
  }

  void TearDown() override {
    authenticator_ = nullptr;
    AuthenticatorImplTest::TearDown();
  }

 protected:
  // The id of the credential created during test setup.
  std::vector<uint8_t> credential_id_;

  raw_ptr<VirtualAuthenticator> authenticator_;
};

TEST_F(VirtualAuthenticatorSignalTest, SignalUnknownCredentialId) {
  {
    // Verify that we do not remove passkeys that don't match the rp id.
    PublicKeyCredentialReportOptionsPtr options =
        GetTestPublicKeyCredentialReportOptions();
    options->relying_party_id = kDifferentTestRelyingPartyId;
    options->unknown_credential_id = credential_id_;
    AuthenticatorReport(std::move(options));
    EXPECT_TRUE(
        base::Contains(authenticator_->registrations(), credential_id_));
  }
  {
    // Verify that we do not remove passkeys that don't match the cred id.
    PublicKeyCredentialReportOptionsPtr options =
        GetTestPublicKeyCredentialReportOptions();
    options->relying_party_id = kTestRelyingPartyId;
    options->unknown_credential_id = std::vector<uint8_t>{4, 3, 2, 1};
    AuthenticatorReport(std::move(options));
    EXPECT_TRUE(
        base::Contains(authenticator_->registrations(), credential_id_));
  }
  {
    // Remove the passkey when the rp id and credential id match.
    PublicKeyCredentialReportOptionsPtr options =
        GetTestPublicKeyCredentialReportOptions();
    options->relying_party_id = kTestRelyingPartyId;
    options->unknown_credential_id = credential_id_;
    AuthenticatorReport(std::move(options));
    EXPECT_FALSE(
        base::Contains(authenticator_->registrations(), credential_id_));
  }
}

TEST_F(VirtualAuthenticatorSignalTest, SignalAllAcceptableCredentials) {
  {
    // Verify that we do not remove passkeys that don't match the rp id.
    PublicKeyCredentialReportOptionsPtr options =
        GetTestPublicKeyCredentialReportOptions();
    options->relying_party_id = kDifferentTestRelyingPartyId;
    options->all_accepted_credentials =
        blink::mojom::AllAcceptedCredentialsOptions::New(
            kUserId, std::vector<std::vector<uint8_t>>{});
    AuthenticatorReport(std::move(options));
    EXPECT_TRUE(
        base::Contains(authenticator_->registrations(), credential_id_));
  }
  {
    // Verify that we do not remove passkeys that don't match the user id.
    PublicKeyCredentialReportOptionsPtr options =
        GetTestPublicKeyCredentialReportOptions();
    options->relying_party_id = kTestRelyingPartyId;
    options->all_accepted_credentials =
        blink::mojom::AllAcceptedCredentialsOptions::New(
            std::vector<uint8_t>{99}, std::vector<std::vector<uint8_t>>{});
    AuthenticatorReport(std::move(options));
    EXPECT_TRUE(
        base::Contains(authenticator_->registrations(), credential_id_));
  }
  {
    // Verify that we do not remove passkeys that are present on the list.
    PublicKeyCredentialReportOptionsPtr options =
        GetTestPublicKeyCredentialReportOptions();
    options->relying_party_id = kTestRelyingPartyId;
    options->all_accepted_credentials =
        blink::mojom::AllAcceptedCredentialsOptions::New(
            kUserId, std::vector<std::vector<uint8_t>>{credential_id_});
    AuthenticatorReport(std::move(options));
    EXPECT_TRUE(
        base::Contains(authenticator_->registrations(), credential_id_));
  }
  {
    // Verify that we remove passkeys that are not present on the list.
    PublicKeyCredentialReportOptionsPtr options =
        GetTestPublicKeyCredentialReportOptions();
    options->relying_party_id = kTestRelyingPartyId;
    options->all_accepted_credentials =
        blink::mojom::AllAcceptedCredentialsOptions::New(
            kUserId, std::vector<std::vector<uint8_t>>{});
    AuthenticatorReport(std::move(options));
    EXPECT_FALSE(
        base::Contains(authenticator_->registrations(), credential_id_));
  }
}

TEST_F(VirtualAuthenticatorSignalTest, SignalCurrentUserDetails) {
  constexpr char kNewUsername[] = "marisa";
  constexpr char kNewDisplayName[] = "Marisa Kirisame";
  {
    // Verify that we do not update passkeys that don't match the rp id.
    PublicKeyCredentialReportOptionsPtr options =
        GetTestPublicKeyCredentialReportOptions();
    options->relying_party_id = kDifferentTestRelyingPartyId;
    options->current_user_details =
        blink::mojom::CurrentUserDetailsOptions::New(kUserId, kNewUsername,
                                                     kNewDisplayName);
    AuthenticatorReport(std::move(options));
    const auto& cred =
        authenticator_->registrations().find(credential_id_)->second;
    EXPECT_EQ(cred.user->name, kUsername);
    EXPECT_EQ(cred.user->display_name, kDisplayName);
  }
  {
    // Verify that we do not update passkeys that don't match the user id.
    PublicKeyCredentialReportOptionsPtr options =
        GetTestPublicKeyCredentialReportOptions();
    options->relying_party_id = kTestRelyingPartyId;
    options->current_user_details =
        blink::mojom::CurrentUserDetailsOptions::New(
            std::vector<uint8_t>{9}, kNewUsername, kNewDisplayName);
    AuthenticatorReport(std::move(options));
    const auto& cred =
        authenticator_->registrations().find(credential_id_)->second;
    EXPECT_EQ(cred.user->name, kUsername);
    EXPECT_EQ(cred.user->display_name, kDisplayName);
  }
  {
    // Verify that we do update passkeys that match.
    PublicKeyCredentialReportOptionsPtr options =
        GetTestPublicKeyCredentialReportOptions();
    options->relying_party_id = kTestRelyingPartyId;
    options->current_user_details =
        blink::mojom::CurrentUserDetailsOptions::New(kUserId, kNewUsername,
                                                     kNewDisplayName);
    AuthenticatorReport(std::move(options));
    const auto& cred =
        authenticator_->registrations().find(credential_id_)->second;
    EXPECT_EQ(cred.user->name, kNewUsername);
    EXPECT_EQ(cred.user->display_name, kNewDisplayName);
  }
}

static constexpr char kTestPIN[] = "1234";
static constexpr char16_t kTestPIN16[] = u"1234";

class UVTestAuthenticatorClientDelegate
    : public DefaultAuthenticatorRequestClientDelegate {
 public:
  explicit UVTestAuthenticatorClientDelegate(bool* collected_pin,
                                             uint32_t* min_pin_length,
                                             bool* did_bio_enrollment,
                                             bool cancel_bio_enrollment,
                                             bool block_request_on_failure_once)
      : collected_pin_(collected_pin),
        min_pin_length_(min_pin_length),
        did_bio_enrollment_(did_bio_enrollment),
        cancel_bio_enrollment_(cancel_bio_enrollment),
        block_request_on_failure_once_(block_request_on_failure_once) {
    *collected_pin_ = false;
    *did_bio_enrollment_ = false;
  }

  bool SupportsPIN() const override { return true; }

  void CollectPIN(
      CollectPINOptions options,
      base::OnceCallback<void(std::u16string)> provide_pin_cb) override {
    *collected_pin_ = true;
    *min_pin_length_ = options.min_pin_length;
    base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
        FROM_HERE, base::BindOnce(std::move(provide_pin_cb), kTestPIN16));
  }

  void StartBioEnrollment(base::OnceClosure next_callback) override {
    *did_bio_enrollment_ = true;
    if (cancel_bio_enrollment_) {
      base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
          FROM_HERE, std::move(next_callback));
      return;
    }
    bio_callback_ = std::move(next_callback);
  }

  void OnSampleCollected(int remaining_samples) override {
    if (remaining_samples <= 0) {
      base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
          FROM_HERE, std::move(bio_callback_));
    }
  }

  void FinishCollectToken() override {}

  bool DoesBlockRequestOnFailure(InterestingFailureReason reason) override {
    bool block = block_request_on_failure_once_;
    block_request_on_failure_once_ = false;
    return block;
  }

 private:
  raw_ptr<bool> collected_pin_;
  raw_ptr<uint32_t> min_pin_length_;
  base::OnceClosure bio_callback_;
  raw_ptr<bool> did_bio_enrollment_;
  bool cancel_bio_enrollment_;
  bool block_request_on_failure_once_;
};

class UVTestAuthenticatorContentBrowserClient : public ContentBrowserClient {
 public:
  // ContentBrowserClient:
  WebAuthenticationDelegate* GetWebAuthenticationDelegate() override {
    return &web_authentication_delegate;
  }

  std::unique_ptr<AuthenticatorRequestClientDelegate>
  GetWebAuthenticationRequestDelegate(
      RenderFrameHost* render_frame_host) override {
    return std::make_unique<UVTestAuthenticatorClientDelegate>(
        &collected_pin, &min_pin_length, &did_bio_enrollment,
        cancel_bio_enrollment, block_request_on_failure_once);
  }

  TestWebAuthenticationDelegate web_authentication_delegate;

  bool collected_pin;
  uint32_t min_pin_length = 0;
  bool did_bio_enrollment;
  bool cancel_bio_enrollment = false;
  bool block_request_on_failure_once = false;
};

class UVAuthenticatorImplTest : public AuthenticatorImplTest {
 public:
  UVAuthenticatorImplTest() = default;

  UVAuthenticatorImplTest(const UVAuthenticatorImplTest&) = delete;
  UVAuthenticatorImplTest& operator=(const UVAuthenticatorImplTest&) = delete;

  void SetUp() override {
    AuthenticatorImplTest::SetUp();
    old_client_ = SetBrowserClientForTesting(&test_client_);
  }

  void TearDown() override {
    SetBrowserClientForTesting(old_client_);
    AuthenticatorImplTest::TearDown();
  }

 protected:
  static PublicKeyCredentialCreationOptionsPtr make_credential_options(
      device::UserVerificationRequirement uv =
          device::UserVerificationRequirement::kRequired,
      bool exclude_credentials = false,
      bool appid_exclude = false) {
    PublicKeyCredentialCreationOptionsPtr options =
        GetTestPublicKeyCredentialCreationOptions();
    if (exclude_credentials) {
      options->exclude_credentials = GetTestCredentials(/*num_credentials=*/1);
    }
    if (appid_exclude) {
      CHECK(exclude_credentials);
      options->appid_exclude = kTestOrigin1;
    }
    options->authenticator_selection->user_verification_requirement = uv;
    return options;
  }

  static PublicKeyCredentialRequestOptionsPtr get_credential_options(
      device::UserVerificationRequirement uv =
          device::UserVerificationRequirement::kRequired) {
    PublicKeyCredentialRequestOptionsPtr options =
        GetTestPublicKeyCredentialRequestOptions();
    options->user_verification = uv;
    return options;
  }

  static const char* UVToString(device::UserVerificationRequirement uv) {
    switch (uv) {
      case device::UserVerificationRequirement::kDiscouraged:
        return "discouraged";
      case device::UserVerificationRequirement::kPreferred:
        return "preferred";
      case device::UserVerificationRequirement::kRequired:
        return "required";
    }
  }

  UVTestAuthenticatorContentBrowserClient test_client_;

 private:
  raw_ptr<ContentBrowserClient> old_client_ = nullptr;
};

using PINReason = device::pin::PINEntryReason;
using PINError = device::pin::PINEntryError;

// PINExpectation represent expected |mode|, |attempts|, |min_pin_length| and
// the PIN to answer with.
struct PINExpectation {
  PINReason reason;
  std::u16string pin;
  int attempts;
  uint32_t min_pin_length = device::kMinPinLength;
  PINError error = PINError::kNoError;
};

class PINTestAuthenticatorRequestDelegate
    : public DefaultAuthenticatorRequestClientDelegate {
 public:
  PINTestAuthenticatorRequestDelegate(
      bool supports_pin,
      const std::list<PINExpectation>& pins,
      std::optional<InterestingFailureReason>* failure_reason,
      base::RepeatingCallback<bool()> collect_pin_cb)
      : supports_pin_(supports_pin),
        expected_(pins),
        failure_reason_(failure_reason),
        collect_pin_cb_(collect_pin_cb) {}

  PINTestAuthenticatorRequestDelegate(
      const PINTestAuthenticatorRequestDelegate&) = delete;
  PINTestAuthenticatorRequestDelegate& operator=(
      const PINTestAuthenticatorRequestDelegate&) = delete;

  ~PINTestAuthenticatorRequestDelegate() override {
    DCHECK(expected_.empty())
        << expected_.size() << " unsatisifed PIN expectations";
  }

  bool SupportsPIN() const override { return supports_pin_; }

  void CollectPIN(
      CollectPINOptions options,
      base::OnceCallback<void(std::u16string)> provide_pin_cb) override {
    if (collect_pin_cb_ && !collect_pin_cb_.Run()) {
      return;
    }
    DCHECK(supports_pin_);
    DCHECK(!expected_.empty()) << "unexpected PIN request";
    if (expected_.front().reason == PINReason::kChallenge) {
      DCHECK(options.attempts == expected_.front().attempts)
          << "got: " << options.attempts
          << " expected: " << expected_.front().attempts;
    }
    DCHECK_EQ(expected_.front().min_pin_length, options.min_pin_length);
    DCHECK_EQ(expected_.front().reason, options.reason);
    DCHECK_EQ(expected_.front().error, options.error);
    std::u16string pin = std::move(expected_.front().pin);
    expected_.pop_front();

    base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
        FROM_HERE, base::BindOnce(std::move(provide_pin_cb), std::move(pin)));
  }

  void FinishCollectToken() override {}

  bool DoesBlockRequestOnFailure(InterestingFailureReason reason) override {
    *failure_reason_ = reason;
    return AuthenticatorRequestClientDelegate::DoesBlockRequestOnFailure(
        reason);
  }

 private:
  const bool supports_pin_;
  std::list<PINExpectation> expected_;
  const raw_ptr<std::optional<InterestingFailureReason>> failure_reason_;
  // collect_pin_cb_ is optional. If present, it returns whether `CollectPIN`
  // should continue and invoke its main callback.
  base::RepeatingCallback<bool()> collect_pin_cb_;
};

class PINTestAuthenticatorContentBrowserClient : public ContentBrowserClient {
 public:
  // ContentBrowserClient:
  WebAuthenticationDelegate* GetWebAuthenticationDelegate() override {
    return &web_authentication_delegate;
  }

  std::unique_ptr<AuthenticatorRequestClientDelegate>
  GetWebAuthenticationRequestDelegate(
      RenderFrameHost* render_frame_host) override {
    return std::make_unique<PINTestAuthenticatorRequestDelegate>(
        supports_pin, expected, &failure_reason, collect_pin_cb);
  }

  TestWebAuthenticationDelegate web_authentication_delegate;

  bool supports_pin = true;
  std::list<PINExpectation> expected;
  std::optional<InterestingFailureReason> failure_reason;
  base::RepeatingCallback<bool()> collect_pin_cb;
};

class PINAuthenticatorImplTest : public UVAuthenticatorImplTest {
 public:
  PINAuthenticatorImplTest() = default;

  PINAuthenticatorImplTest(const PINAuthenticatorImplTest&) = delete;
  PINAuthenticatorImplTest& operator=(const PINAuthenticatorImplTest&) = delete;

  void SetUp() override {
    UVAuthenticatorImplTest::SetUp();
    old_client_ = SetBrowserClientForTesting(&test_client_);
    device::VirtualCtap2Device::Config config;
    config.pin_support = true;
    virtual_device_factory_->SetCtap2Config(config);
    NavigateAndCommit(GURL(kTestOrigin1));
  }

  void TearDown() override {
    SetBrowserClientForTesting(old_client_);
    UVAuthenticatorImplTest::TearDown();
  }

 protected:
  PINTestAuthenticatorContentBrowserClient test_client_;

  // An enumerate of outcomes for PIN tests.
  enum {
    kFailure,
    kNoPIN,
    kSetPIN,
    kUsePIN,
  };

  void ConfigureVirtualDevice(device::PINUVAuthProtocol pin_protocol,
                              bool pin_uv_auth_token,
                              int support_level) {
    device::VirtualCtap2Device::Config config;
    config.pin_protocol = pin_protocol;
    config.pin_uv_auth_token_support = pin_uv_auth_token;
    config.ctap2_versions = {device::Ctap2Version::kCtap2_0,
                             device::Ctap2Version::kCtap2_1};
    switch (support_level) {
      case 0:
        // No support.
        config.pin_support = false;
        virtual_device_factory_->mutable_state()->pin = "";
        virtual_device_factory_->mutable_state()->pin_retries = 0;
        break;

      case 1:
        // PIN supported, but no PIN set.
        config.pin_support = true;
        virtual_device_factory_->mutable_state()->pin = "";
        virtual_device_factory_->mutable_state()->pin_retries = 0;
        break;

      case 2:
        // PIN set.
        config.pin_support = true;
        virtual_device_factory_->mutable_state()->pin = kTestPIN;
        virtual_device_factory_->mutable_state()->pin_retries =
            device::kMaxPinRetries;
        break;

      default:
        NOTREACHED();
    }

    virtual_device_factory_->SetCtap2Config(config);
  }

 private:
  raw_ptr<ContentBrowserClient> old_client_ = nullptr;
};

static constexpr std::array<device::UserVerificationRequirement, 3> kUVLevel = {
    device::UserVerificationRequirement::kDiscouraged,
    device::UserVerificationRequirement::kPreferred,
    device::UserVerificationRequirement::kRequired,
};

static const std::array<std::string_view, 3> kUVDescription = {
    "discouraged", "preferred", "required"};

static const std::array<std::string_view, 3> kPINSupportDescription = {
    "no PIN support", "PIN not set", "PIN set"};

TEST_F(PINAuthenticatorImplTest, MakeCredential) {
  typedef std::array<int, 3> UvRequirement;
  typedef std::array<UvRequirement, 3> Expectations;
  // kExpectedWithUISupport enumerates the expected behaviour when the embedder
  // supports prompting the user for a PIN.
  // clang-format off
  const Expectations kExpectedWithUISupport = std::to_array<UvRequirement>({
    //                   discouraged | preferred | required
    /* No support */  {    kNoPIN,      kNoPIN,     kFailure },
    /* PIN not set */ {    kNoPIN,      kNoPIN,     kSetPIN  },
    /* PIN set */     {    kUsePIN,     kUsePIN,    kUsePIN  },
    //                        ^
    //                        |
    //            VirtualCtap2Device cannot fall back to U2F.
  });
  // clang-format on

  // kExpectedWithoutUISupport enumerates the expected behaviour when the
  // embedder cannot prompt the user for a PIN.
  // clang-format off
  const Expectations kExpectedWithoutUISupport = std::to_array<UvRequirement>({
    //                   discouraged | preferred | required
    /* No support */  {    kNoPIN,      kNoPIN,     kFailure },
    /* PIN not set */ {    kNoPIN,      kNoPIN,     kFailure },
    /* PIN set */     {    kFailure,    kFailure,   kFailure },
    //                        ^            ^
    //                        |            |
    //            VirtualCtap2Device cannot fall back to U2F and
    //            a PIN is required to create credentials once set
    //            in CTAP 2.0.
  });
  // clang-format on

  for (bool pin_uv_auth_token : {false, true}) {
    SCOPED_TRACE(::testing::Message()
                 << "pin_uv_auth_token=" << pin_uv_auth_token);
    for (bool ui_support : {false, true}) {
      SCOPED_TRACE(::testing::Message() << "ui_support=" << ui_support);
      const Expectations& expected =
          ui_support ? kExpectedWithUISupport : kExpectedWithoutUISupport;
      test_client_.supports_pin = ui_support;

      for (int support_level = 0; support_level <= 2; support_level++) {
        for (const auto pin_protocol :
             {device::PINUVAuthProtocol::kV1, device::PINUVAuthProtocol::kV2}) {
          SCOPED_TRACE(testing::Message()
                       << "support_level="
                       << kPINSupportDescription[support_level]
                       << ", pin_protocol=" << static_cast<int>(pin_protocol));
          for (const bool excluded_credentials : {false, true}) {
            SCOPED_TRACE(::testing::Message()
                         << "excluded_credentials=" << excluded_credentials);
            for (const bool appid_exclude : {false, true}) {
              if (appid_exclude && !excluded_credentials) {
                continue;
              }
              SCOPED_TRACE(::testing::Message()
                           << "appid_exclude=" << appid_exclude);

              for (const bool always_uv : {false, true}) {
                if (always_uv &&
                    (!ui_support ||
                     virtual_device_factory_->mutable_state()->pin.empty())) {
                  continue;
                }
                SCOPED_TRACE(::testing::Message() << "always_uv=" << always_uv);

                ConfigureVirtualDevice(pin_protocol, pin_uv_auth_token,
                                       support_level);

                for (int uv_level = 0; uv_level <= 2; uv_level++) {
                  SCOPED_TRACE(kUVDescription[uv_level]);

                  switch (expected[support_level][uv_level]) {
                    case kNoPIN:
                    case kFailure:
                      // There shouldn't be any PIN prompts.
                      test_client_.expected.clear();
                      break;

                    case kSetPIN:
                      // A single PIN prompt to set a PIN is expected.
                      test_client_.expected = {{PINReason::kSet, kTestPIN16}};
                      break;

                    case kUsePIN:
                      // A single PIN prompt to get the PIN is expected.
                      test_client_.expected = {
                          {PINReason::kChallenge, kTestPIN16, 8}};
                      break;

                    default:
                      NOTREACHED();
                  }

                  MakeCredentialResult result =
                      AuthenticatorMakeCredential(make_credential_options(
                          kUVLevel[uv_level], excluded_credentials,
                          appid_exclude));

                  switch (expected[support_level][uv_level]) {
                    case kFailure:
                      EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR,
                                result.status);
                      break;

                    case kNoPIN:
                      ASSERT_EQ(AuthenticatorStatus::SUCCESS, result.status);
                      EXPECT_EQ("",
                                virtual_device_factory_->mutable_state()->pin);
                      EXPECT_FALSE(HasUV(result.response));
                      break;

                    case kSetPIN:
                    case kUsePIN:
                      ASSERT_EQ(AuthenticatorStatus::SUCCESS, result.status);
                      EXPECT_EQ(kTestPIN,
                                virtual_device_factory_->mutable_state()->pin);
                      EXPECT_TRUE(HasUV(result.response));
                      break;

                    default:
                      NOTREACHED();
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

TEST_F(PINAuthenticatorImplTest, MakeCredentialSoftLock) {
  virtual_device_factory_->mutable_state()->pin = kTestPIN;
  virtual_device_factory_->mutable_state()->pin_retries =
      device::kMaxPinRetries;

  test_client_.expected = {{PINReason::kChallenge, u"wrong", 8},
                           {PINReason::kChallenge, u"wrong", 7,
                            device::kMinPinLength, PINError::kWrongPIN},
                           {PINReason::kChallenge, u"wrong", 6,
                            device::kMinPinLength, PINError::kWrongPIN}};
  EXPECT_EQ(AuthenticatorMakeCredential(make_credential_options()).status,
            AuthenticatorStatus::NOT_ALLOWED_ERROR);
  EXPECT_EQ(5, virtual_device_factory_->mutable_state()->pin_retries);
  EXPECT_TRUE(virtual_device_factory_->mutable_state()->soft_locked);
  ASSERT_TRUE(test_client_.failure_reason.has_value());
  EXPECT_EQ(InterestingFailureReason::kSoftPINBlock,
            *test_client_.failure_reason);
  VerifyMakeCredentialOutcomeUkm(0, MakeCredentialOutcome::kSoftPinBlock,
                                 AuthenticationRequestMode::kModalWebAuthn);
}

TEST_F(PINAuthenticatorImplTest, MakeCredentialHardLock) {
  virtual_device_factory_->mutable_state()->pin = kTestPIN;
  virtual_device_factory_->mutable_state()->pin_retries = 1;

  test_client_.expected = {{PINReason::kChallenge, u"wrong", 1}};
  EXPECT_EQ(AuthenticatorMakeCredential().status,
            AuthenticatorStatus::NOT_ALLOWED_ERROR);
  EXPECT_EQ(0, virtual_device_factory_->mutable_state()->pin_retries);
  ASSERT_TRUE(test_client_.failure_reason.has_value());
  EXPECT_EQ(InterestingFailureReason::kHardPINBlock,
            *test_client_.failure_reason);
  VerifyMakeCredentialOutcomeUkm(0, MakeCredentialOutcome::kHardPinBlock,
                                 AuthenticationRequestMode::kModalWebAuthn);
}

TEST_F(PINAuthenticatorImplTest, MakeCredentialWrongPINFirst) {
  virtual_device_factory_->mutable_state()->pin = kTestPIN;
  virtual_device_factory_->mutable_state()->pin_retries =
      device::kMaxPinRetries;

  // Test that we can successfully get a PIN token after a failure.
  test_client_.expected = {{PINReason::kChallenge, u"wrong", 8},
                           {PINReason::kChallenge, kTestPIN16, 7,
                            device::kMinPinLength, PINError::kWrongPIN}};
  EXPECT_EQ(AuthenticatorMakeCredential().status, AuthenticatorStatus::SUCCESS);
  EXPECT_EQ(static_cast<int>(device::kMaxPinRetries),
            virtual_device_factory_->mutable_state()->pin_retries);
}

TEST_F(PINAuthenticatorImplTest, MakeCredentialSkipPINTouch) {
  virtual_device_factory_->mutable_state()->pin = kTestPIN;
  int taps = 0;
  virtual_device_factory_->mutable_state()->simulate_press_callback =
      base::BindLambdaForTesting([&](device::VirtualFidoDevice* device) {
        ++taps;
        return true;
      });
  virtual_device_factory_->mutable_state()->pin_retries =
      device::kMaxPinRetries;
  test_client_.expected = {
      {PINReason::kChallenge, kTestPIN16, device::kMaxPinRetries}};
  EXPECT_EQ(AuthenticatorMakeCredential().status, AuthenticatorStatus::SUCCESS);
  EXPECT_EQ(taps, 1);
}

TEST_F(PINAuthenticatorImplTest, MakeCredentialDontSkipPINTouch) {
  // Create two devices. Both are candidates but only the second one will
  // respond to touches.
  auto discovery =
      std::make_unique<device::test::MultipleVirtualFidoDeviceFactory>();
  device::test::MultipleVirtualFidoDeviceFactory::DeviceDetails device_1;
  device_1.config.pin_support = true;
  device_1.state->simulate_press_callback =
      base::BindRepeating([](VirtualFidoDevice* ignore) { return false; });
  discovery->AddDevice(std::move(device_1));

  int taps = 0;
  device::test::MultipleVirtualFidoDeviceFactory::DeviceDetails device_2;
  device_2.state->pin = kTestPIN;
  device_2.config.pin_support = true;
  device_2.state->simulate_press_callback =
      base::BindLambdaForTesting([&](VirtualFidoDevice* ignore) {
        ++taps;
        return true;
      });
  discovery->AddDevice(std::move(device_2));

  ReplaceDiscoveryFactory(std::move(discovery));

  test_client_.expected = {
      {PINReason::kChallenge, kTestPIN16, device::kMaxPinRetries}};
  EXPECT_EQ(AuthenticatorMakeCredential().status, AuthenticatorStatus::SUCCESS);
  EXPECT_EQ(taps, 2);
}

TEST_F(PINAuthenticatorImplTest, MakeCredentialAlwaysUv) {
  // Test that if an authenticator is reporting alwaysUv = 1, UV is attempted
  // even if the user verification requirement is discouraged.
  device::VirtualCtap2Device::Config config;
  config.pin_support = true;
  config.always_uv = true;

  // Enable u2f support. Normally, this would allow chrome to create a
  // credential without internal user verification, but we should not attempt
  // that with the alwaysUv flag on.
  config.u2f_support = true;
  virtual_device_factory_->SetCtap2Config(config);
  virtual_device_factory_->mutable_state()->pin = kTestPIN;
  test_client_.expected = {
      {PINReason::kChallenge, kTestPIN16, device::kMaxPinRetries}};

  MakeCredentialResult result =
      AuthenticatorMakeCredential(make_credential_options(
          device::UserVerificationRequirement::kDiscouraged));
  EXPECT_EQ(result.status, AuthenticatorStatus::SUCCESS);
  EXPECT_TRUE(HasUV(result.response));
}

TEST_F(PINAuthenticatorImplTest, MakeCredentialMinPINLengthNewPIN) {
  // Test that an authenticator advertising a min PIN length other than the
  // default makes it all the way to CollectPIN when setting a new PIN.
  device::VirtualCtap2Device::Config config;
  config.pin_support = true;
  config.min_pin_length_support = true;
  config.pin_uv_auth_token_support = true;
  config.ctap2_versions = {device::Ctap2Version::kCtap2_1};
  virtual_device_factory_->SetCtap2Config(config);
  virtual_device_factory_->mutable_state()->min_pin_length = 6;
  test_client_.expected = {{PINReason::kSet, u"123456", 0, 6}};

  MakeCredentialResult result =
      AuthenticatorMakeCredential(make_credential_options());
  EXPECT_EQ(result.status, AuthenticatorStatus::SUCCESS);
}

TEST_F(PINAuthenticatorImplTest, MakeCredentialMinPINLengthExistingPIN) {
  // Test that an authenticator advertising a min PIN length other than the
  // default makes it all the way to CollectPIN when using an existing PIN and
  // the forcePINChange flag is false.
  device::VirtualCtap2Device::Config config;
  config.pin_support = true;
  config.min_pin_length_support = true;
  config.pin_uv_auth_token_support = true;
  config.ctap2_versions = {device::Ctap2Version::kCtap2_1};
  virtual_device_factory_->SetCtap2Config(config);
  virtual_device_factory_->mutable_state()->min_pin_length = 6;
  virtual_device_factory_->mutable_state()->pin = "123456";
  test_client_.expected = {
      {PINReason::kChallenge, u"123456", device::kMaxPinRetries, 6}};

  MakeCredentialResult result =
      AuthenticatorMakeCredential(make_credential_options());
  EXPECT_EQ(result.status, AuthenticatorStatus::SUCCESS);
}

TEST_F(PINAuthenticatorImplTest, MakeCredentialForcePINChange) {
  // Test that an authenticator with the forcePINChange flag set to true updates
  // the PIN before attempting to make a credential. When querying for an
  // existing PIN, the default min PIN length should be asked since there is no
  // way to know the current PIN length.
  device::VirtualCtap2Device::Config config;
  config.pin_support = true;
  config.min_pin_length_support = true;
  config.pin_uv_auth_token_support = true;
  config.ctap2_versions = {device::Ctap2Version::kCtap2_1};
  virtual_device_factory_->SetCtap2Config(config);
  virtual_device_factory_->mutable_state()->force_pin_change = true;
  virtual_device_factory_->mutable_state()->pin = kTestPIN;
  virtual_device_factory_->mutable_state()->pin_retries =
      device::kMaxPinRetries;
  virtual_device_factory_->mutable_state()->min_pin_length = 6;
  test_client_.expected = {{PINReason::kChallenge, kTestPIN16,
                            device::kMaxPinRetries, device::kMinPinLength},
                           {PINReason::kChange, u"567890", 0, 6}};

  MakeCredentialResult result =
      AuthenticatorMakeCredential(make_credential_options());
  EXPECT_EQ(result.status, AuthenticatorStatus::SUCCESS);
  EXPECT_EQ("567890", virtual_device_factory_->mutable_state()->pin);
}

TEST_F(PINAuthenticatorImplTest, MakeCredUvNotRqd) {
  // Test that on an authenticator with the makeCredUvNotRqd option enabled,
  // non-discoverable credentials can be created without requiring a PIN.
  for (bool discoverable : {false, true}) {
    for (bool request_uv : {false, true}) {
      SCOPED_TRACE(testing::Message() << "discoverable=" << discoverable
                                      << " request_uv=" << request_uv);

      test_client_.web_authentication_delegate.supports_resident_keys = true;
      ResetVirtualDevice();
      device::VirtualCtap2Device::Config config;
      config.u2f_support = true;
      config.pin_support = true;
      config.resident_key_support = true;
      config.pin_uv_auth_token_support = true;
      config.allow_non_resident_credential_creation_without_uv = true;
      config.ctap2_versions = {device::Ctap2Version::kCtap2_1};
      virtual_device_factory_->SetCtap2Config(config);
      virtual_device_factory_->mutable_state()->pin = kTestPIN;
      // PIN is still required for discoverable credentials, or if the caller
      // requests it.
      if (discoverable || request_uv) {
        test_client_.expected = {{PINReason::kChallenge, kTestPIN16,
                                  device::kMaxPinRetries,
                                  device::kMinPinLength}};
      } else {
        test_client_.expected = {};
      }

      PublicKeyCredentialCreationOptionsPtr request = make_credential_options();
      request->authenticator_selection->user_verification_requirement =
          request_uv ? device::UserVerificationRequirement::kPreferred
                     : device::UserVerificationRequirement::kDiscouraged;
      request->authenticator_selection->resident_key =
          discoverable ? device::ResidentKeyRequirement::kPreferred
                       : device::ResidentKeyRequirement::kDiscouraged;

      MakeCredentialResult result =
          AuthenticatorMakeCredential(std::move(request));
      EXPECT_EQ(result.status, AuthenticatorStatus::SUCCESS);
      // Requests shouldn't fall back to creating U2F credentials.
      EXPECT_FALSE(virtual_device_factory_->mutable_state()
                       ->registrations.begin()
                       ->second.is_u2f);
    }
  }
}

TEST_F(PINAuthenticatorImplTest, MakeCredUvNotRqdAndAlwaysUv) {
  // makeCredUvNotRqd and alwaysUv can be combined even though they contradict
  // each other. In that case, makeCredUvNotRqd should be ignored and PIN/UV
  // should be collected before creating non-discoverable credentials. If PIN/UV
  // isn't configured, that should be taken care of first.
  for (bool pin_set : {false, true}) {
    SCOPED_TRACE(testing::Message() << "pin_set=" << pin_set);

    ResetVirtualDevice();
    device::VirtualCtap2Device::Config config;
    config.pin_support = true;
    config.pin_uv_auth_token_support = true;
    config.always_uv = true;
    config.allow_non_resident_credential_creation_without_uv = true;
    config.ctap2_versions = {device::Ctap2Version::kCtap2_1};
    virtual_device_factory_->SetCtap2Config(config);
    if (pin_set) {
      virtual_device_factory_->mutable_state()->pin = kTestPIN;
      test_client_.expected = {{PINReason::kChallenge, kTestPIN16,
                                device::kMaxPinRetries, device::kMinPinLength}};
    } else {
      test_client_.expected = {{PINReason::kSet, kTestPIN16,
                                device::kMaxPinRetries, device::kMinPinLength}};
    }

    MakeCredentialResult result =
        AuthenticatorMakeCredential(make_credential_options());
    EXPECT_EQ(result.status, AuthenticatorStatus::SUCCESS);
  }
}

TEST_F(PINAuthenticatorImplTest, MakeCredentialHMACSecret) {
  // uv=preferred is more preferred when hmac-secret is in use so that the
  // PRF is consistent. (Security keys have two PRFs per credential: one for
  // UV and one for non-UV assertions.)
  struct TestCase {
    device::UserVerificationRequirement uv;
    bool hmac_secret;
    bool should_configure_uv;
  };

  constexpr TestCase kTests[] = {
      {device::UserVerificationRequirement::kDiscouraged, false, false},
      {device::UserVerificationRequirement::kPreferred, false, false},
      {device::UserVerificationRequirement::kRequired, false, true},
      {device::UserVerificationRequirement::kDiscouraged, true, true},
      {device::UserVerificationRequirement::kPreferred, true, true},
      {device::UserVerificationRequirement::kRequired, true, true},
  };

  NavigateAndCommit(GURL(kTestOrigin1));
  unsigned index = 0;
  for (const TestCase& test : kTests) {
    SCOPED_TRACE(index++);

    ResetVirtualDevice();
    device::VirtualCtap2Device::Config config;
    config.hmac_secret_support = true;
    config.pin_support = true;
    config.pin_uv_auth_token_support = true;
    config.allow_non_resident_credential_creation_without_uv = true;
    config.ctap2_versions = {device::Ctap2Version::kCtap2_1};
    virtual_device_factory_->SetCtap2Config(config);

    if (test.should_configure_uv) {
      test_client_.expected = {{PINReason::kSet, kTestPIN16,
                                device::kMaxPinRetries, device::kMinPinLength}};
    } else {
      test_client_.expected.clear();
    }

    auto options = make_credential_options(test.uv);
    options->hmac_create_secret = test.hmac_secret;
    MakeCredentialResult result =
        AuthenticatorMakeCredential(std::move(options));
    EXPECT_EQ(result.status, AuthenticatorStatus::SUCCESS);
  }
}

TEST_F(PINAuthenticatorImplTest, GetAssertion) {
  typedef std::array<int, 3> UvRequirement;
  typedef std::array<UvRequirement, 3> Expectations;
  // kExpectedWithUISupport enumerates the expected behaviour when the embedder
  // supports prompting the user for a PIN.
  // clang-format off
  const Expectations kExpectedWithUISupport = std::to_array<UvRequirement>({
    //                   discouraged | preferred | required
    /* No support */  {    kNoPIN,      kNoPIN,     kFailure },
    /* PIN not set */ {    kNoPIN,      kNoPIN,     kFailure },
    /* PIN set */     {    kNoPIN,      kUsePIN,    kUsePIN  },
  });
  // clang-format on

  // kExpectedWithoutUISupport enumerates the expected behaviour when the
  // embedder cannot prompt the user for a PIN.
  // clang-format off
  const Expectations kExpectedWithoutUISupport = std::to_array<UvRequirement>({
    //                   discouraged | preferred | required
    /* No support */  {    kNoPIN,      kNoPIN,     kFailure },
    /* PIN not set */ {    kNoPIN,      kNoPIN,     kFailure },
    /* PIN set */     {    kNoPIN,      kNoPIN,     kFailure },
  });
  // clang-format on

  PublicKeyCredentialRequestOptionsPtr dummy_options = get_credential_options();
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
      dummy_options->allow_credentials[0].id, kTestRelyingPartyId));

  for (bool pin_uv_auth_token : {false, true}) {
    for (bool ui_support : {false, true}) {
      SCOPED_TRACE(::testing::Message() << "ui_support=" << ui_support);
      const Expectations& expected =
          ui_support ? kExpectedWithUISupport : kExpectedWithoutUISupport;
      test_client_.supports_pin = ui_support;

      for (int support_level = 0; support_level <= 2; support_level++) {
        SCOPED_TRACE(kPINSupportDescription[support_level]);
        for (const auto pin_protocol :
             {device::PINUVAuthProtocol::kV1, device::PINUVAuthProtocol::kV2}) {
          SCOPED_TRACE(testing::Message()
                       << "support_level="
                       << kPINSupportDescription[support_level]
                       << ", pin_protocol=" << static_cast<int>(pin_protocol));
          ConfigureVirtualDevice(pin_protocol, pin_uv_auth_token,
                                 support_level);

          for (int uv_level = 0; uv_level <= 2; uv_level++) {
            SCOPED_TRACE(kUVDescription[uv_level]);

            switch (expected[support_level][uv_level]) {
              case kNoPIN:
              case kFailure:
                // No PIN prompts are expected.
                test_client_.expected.clear();
                break;

              case kUsePIN:
                // A single prompt to get the PIN is expected.
                test_client_.expected = {
                    {PINReason::kChallenge, kTestPIN16, 8}};
                break;

              default:
                NOTREACHED();
            }

            GetAssertionResult result = AuthenticatorGetAssertion(
                get_credential_options(kUVLevel[uv_level]));

            switch (expected[support_level][uv_level]) {
              case kFailure:
                EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR,
                          result.status);
                break;

              case kNoPIN:
                EXPECT_EQ(AuthenticatorStatus::SUCCESS, result.status);
                EXPECT_FALSE(HasUV(result.response));
                break;

              case kUsePIN:
                EXPECT_EQ(AuthenticatorStatus::SUCCESS, result.status);
                EXPECT_EQ(kTestPIN,
                          virtual_device_factory_->mutable_state()->pin);
                EXPECT_TRUE(HasUV(result.response));
                break;

              default:
                NOTREACHED();
            }
          }
        }
      }
    }
  }
}

TEST_F(PINAuthenticatorImplTest, GetAssertionSoftLock) {
  virtual_device_factory_->mutable_state()->pin = kTestPIN;
  virtual_device_factory_->mutable_state()->pin_retries =
      device::kMaxPinRetries;

  PublicKeyCredentialRequestOptionsPtr options = get_credential_options();
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
      options->allow_credentials[0].id, kTestRelyingPartyId));

  test_client_.expected = {{PINReason::kChallenge, u"wrong", 8},
                           {PINReason::kChallenge, u"wrong", 7,
                            device::kMinPinLength, PINError::kWrongPIN},
                           {PINReason::kChallenge, u"wrong", 6,
                            device::kMinPinLength, PINError::kWrongPIN}};
  EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
            AuthenticatorStatus::NOT_ALLOWED_ERROR);
  EXPECT_EQ(5, virtual_device_factory_->mutable_state()->pin_retries);
  EXPECT_TRUE(virtual_device_factory_->mutable_state()->soft_locked);
  ASSERT_TRUE(test_client_.failure_reason.has_value());
  EXPECT_EQ(InterestingFailureReason::kSoftPINBlock,
            *test_client_.failure_reason);
  VerifyGetAssertionOutcomeUkm(0, GetAssertionOutcome::kSoftPinBlock,
                               AuthenticationRequestMode::kModalWebAuthn);
}

TEST_F(PINAuthenticatorImplTest, GetAssertionHardLock) {
  virtual_device_factory_->mutable_state()->pin = kTestPIN;
  virtual_device_factory_->mutable_state()->pin_retries = 1;

  PublicKeyCredentialRequestOptionsPtr options = get_credential_options();
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
      options->allow_credentials[0].id, kTestRelyingPartyId));

  test_client_.expected = {{PINReason::kChallenge, u"wrong", 1}};
  EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
            AuthenticatorStatus::NOT_ALLOWED_ERROR);
  EXPECT_EQ(0, virtual_device_factory_->mutable_state()->pin_retries);
  ASSERT_TRUE(test_client_.failure_reason.has_value());
  EXPECT_EQ(InterestingFailureReason::kHardPINBlock,
            *test_client_.failure_reason);
  VerifyGetAssertionOutcomeUkm(0, GetAssertionOutcome::kHardPinBlock,
                               AuthenticationRequestMode::kModalWebAuthn);
}

TEST_F(PINAuthenticatorImplTest, GetAssertionSkipPINTouch) {
  virtual_device_factory_->mutable_state()->pin = kTestPIN;
  int taps = 0;
  virtual_device_factory_->mutable_state()->simulate_press_callback =
      base::BindLambdaForTesting([&](device::VirtualFidoDevice* device) {
        ++taps;
        return true;
      });
  PublicKeyCredentialRequestOptionsPtr options = get_credential_options();
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
      options->allow_credentials[0].id, kTestRelyingPartyId));
  test_client_.expected = {
      {PINReason::kChallenge, kTestPIN16, device::kMaxPinRetries}};
  EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
            AuthenticatorStatus::SUCCESS);
  EXPECT_EQ(taps, 1);
}

TEST_F(PINAuthenticatorImplTest, GetAssertionDontSkipPINTouch) {
  // Create two devices. Both are candidates but only the second one will
  // respond to touches.
  auto discovery =
      std::make_unique<device::test::MultipleVirtualFidoDeviceFactory>();
  device::test::MultipleVirtualFidoDeviceFactory::DeviceDetails device_1;
  device_1.config.pin_support = true;
  device_1.state->simulate_press_callback =
      base::BindRepeating([](VirtualFidoDevice* ignore) { return false; });
  discovery->AddDevice(std::move(device_1));

  int taps = 0;
  device::test::MultipleVirtualFidoDeviceFactory::DeviceDetails device_2;
  device_2.state->pin = kTestPIN;
  device_2.config.pin_support = true;
  device_2.state->simulate_press_callback =
      base::BindLambdaForTesting([&](VirtualFidoDevice* ignore) {
        ++taps;
        return true;
      });
  PublicKeyCredentialRequestOptionsPtr options = get_credential_options();
  ASSERT_TRUE(device_2.state->InjectRegistration(
      options->allow_credentials[0].id, kTestRelyingPartyId));
  discovery->AddDevice(std::move(device_2));

  ReplaceDiscoveryFactory(std::move(discovery));

  test_client_.expected = {
      {PINReason::kChallenge, kTestPIN16, device::kMaxPinRetries}};
  EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
            AuthenticatorStatus::SUCCESS);
  EXPECT_EQ(taps, 2);
}

TEST_F(PINAuthenticatorImplTest, GetAssertionAlwaysUv) {
  // Test that if an authenticator is reporting alwaysUv = 1, UV is attempted
  // even if the user verification requirement is discouraged.
  device::VirtualCtap2Device::Config config;
  config.pin_support = true;
  config.always_uv = true;
  config.u2f_support = true;
  virtual_device_factory_->SetCtap2Config(config);
  virtual_device_factory_->mutable_state()->pin = kTestPIN;
  PublicKeyCredentialRequestOptionsPtr options =
      get_credential_options(device::UserVerificationRequirement::kDiscouraged);
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
      options->allow_credentials[0].id, kTestRelyingPartyId));
  test_client_.expected = {
      {PINReason::kChallenge, kTestPIN16, device::kMaxPinRetries}};

  GetAssertionResult result = AuthenticatorGetAssertion(std::move(options));
  EXPECT_EQ(result.status, AuthenticatorStatus::SUCCESS);
  EXPECT_TRUE(HasUV(result.response));
}

TEST_F(PINAuthenticatorImplTest, MakeCredentialNoSupportedAlgorithm) {
  NavigateAndCommit(GURL(kTestOrigin1));

  for (int i = 0; i < 3; i++) {
    SCOPED_TRACE(i);

    test_client_.expected.clear();
    bool expected_to_succeed = false;
    if (i == 0) {
      device::VirtualCtap2Device::Config config;
      // The first config is a CTAP2 device that doesn't support the
      // kInvalidForTesting algorithm. A dummy touch should be requested in this
      // case.
      virtual_device_factory_->SetCtap2Config(config);
    } else if (i == 1) {
      device::VirtualCtap2Device::Config config;
      // The second config is a device with a PIN set that _does_ support the
      // algorithm. Since the PIN is set, we might convert the makeCredential
      // request to U2F, but shouldn't because the algorithm cannot be
      // represented in U2F.
      config.u2f_support = true;
      config.pin_support = true;
      config.advertised_algorithms = {
          device::CoseAlgorithmIdentifier::kInvalidForTesting};
      virtual_device_factory_->mutable_state()->pin = kTestPIN;
      virtual_device_factory_->mutable_state()->pin_retries =
          device::kMaxPinRetries;
      virtual_device_factory_->SetCtap2Config(config);
      test_client_.expected = {
          {PINReason::kChallenge, kTestPIN16, device::kMaxPinRetries}};
      // Since converting to U2F isn't possible, this will trigger a PIN prompt
      // and succeed because the device does actually support the algorithm.
      expected_to_succeed = true;
    } else if (i == 2) {
      // The third case is a plain U2F authenticator, which implicitly only
      // supports ES256.
      virtual_device_factory_->SetSupportedProtocol(
          device::ProtocolVersion::kU2f);
    }

    PublicKeyCredentialCreationOptionsPtr options =
        GetTestPublicKeyCredentialCreationOptions();
    // Set uv=discouraged so that U2F fallback is possible.
    options->authenticator_selection->user_verification_requirement =
        device::UserVerificationRequirement::kDiscouraged;
    options->public_key_parameters =
        GetTestPublicKeyCredentialParameters(static_cast<int32_t>(
            device::CoseAlgorithmIdentifier::kInvalidForTesting));

    EXPECT_EQ(AuthenticatorMakeCredential(std::move(options)).status,
              expected_to_succeed ? AuthenticatorStatus::SUCCESS
                                  : AuthenticatorStatus::NOT_ALLOWED_ERROR);
  }
}

TEST_F(PINAuthenticatorImplTest, PRFCreatedOnCTAP2) {
  // Check that credential creation requests that include the PRF extension use
  // CTAP2 if possible.
  NavigateAndCommit(GURL(kTestOrigin1));

  for (int i = 0; i < 3; i++) {
    SCOPED_TRACE(i);

    device::VirtualCtap2Device::Config config;
    config.u2f_support = true;
    config.pin_support = true;
    config.hmac_secret_support = true;
    virtual_device_factory_->mutable_state()->pin = kTestPIN;
    virtual_device_factory_->mutable_state()->pin_retries =
        device::kMaxPinRetries;

    PublicKeyCredentialCreationOptionsPtr options =
        GetTestPublicKeyCredentialCreationOptions();
    // Set uv=discouraged so that U2F fallback is possible.
    options->authenticator_selection->user_verification_requirement =
        device::UserVerificationRequirement::kDiscouraged;

    if (i == 0) {
      // Sanity check: request should fallback to U2F. (If it doesn't fallback
      // to U2F then the PIN test infrastructure will CHECK because
      // |test_client_.expected| is empty.)
      test_client_.expected.clear();
    } else if (i == 1) {
      // If PRF is requested, the fallback to U2F should not happen because the
      // PRF request is higher priority than avoiding a PIN prompt. (The PIN
      // test infrastructure will CHECK if |expected| is set and not used.)
      options->prf_enable = true;
      test_client_.expected = {
          {PINReason::kChallenge, kTestPIN16, device::kMaxPinRetries}};
    } else {
      // If PRF is requested, but the authenticator doesn't support it, then we
      // should still use U2F.
      options->prf_enable = true;
      config.hmac_secret_support = false;
      test_client_.expected.clear();
    }

    virtual_device_factory_->SetCtap2Config(config);

    EXPECT_EQ(AuthenticatorMakeCredential(std::move(options)).status,
              AuthenticatorStatus::SUCCESS);
  }
}

// Test that pinUvAuthToken gets sent with every single batch of an exclude
// list. If it wasn't, any batch after the first would be unable to match
// credProtect=uvRequired credentials.
TEST_F(PINAuthenticatorImplTest, ExcludeListBatchesIncludePinToken) {
  NavigateAndCommit(GURL(kTestOrigin1));

  // Set up a CTAP 2.1 authenticator with pinUvAuthToken and exclude list
  // batching.
  device::VirtualCtap2Device::Config config;
  config.max_credential_id_length = kTestCredentialIdLength;
  constexpr size_t kBatchSize = 10;
  config.max_credential_count_in_list = kBatchSize;
  config.pin_support = true;
  config.pin_uv_auth_token_support = true;
  config.ctap2_versions = {device::Ctap2Version::kCtap2_0,
                           device::Ctap2Version::kCtap2_1};
  virtual_device_factory_->SetCtap2Config(config);
  virtual_device_factory_->mutable_state()->pin = kTestPIN;
  virtual_device_factory_->mutable_state()->pin_retries =
      device::kMaxPinRetries;

  test_client_.expected = {
      {PINReason::kChallenge, kTestPIN16, device::kMaxPinRetries}};

  // Craft an exclude list that is large enough to trigger batched probing and
  // includes one match for a credProtect=uvRequired credential.
  auto test_credentials = GetTestCredentials(kBatchSize + 1);

  device::VirtualFidoDevice::RegistrationData cred_protect_credential(
      kTestRelyingPartyId);
  cred_protect_credential.protection = device::CredProtect::kUVRequired;
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
      test_credentials.back().id, std::move(cred_protect_credential)));

  // The request should fail because the exclude list matches.
  PublicKeyCredentialCreationOptionsPtr options =
      GetTestPublicKeyCredentialCreationOptions();
  options->exclude_credentials = std::move(test_credentials);
  EXPECT_EQ(AuthenticatorMakeCredential(std::move(options)).status,
            AuthenticatorStatus::CREDENTIAL_EXCLUDED);
}

TEST_F(PINAuthenticatorImplTest, RemoveSecondAuthenticator) {
  // Create two PIN-capable devices. Touch one of them to trigger a prompt for
  // a PIN. Remove the other. Don't crash.
  base::RepeatingCallback<void(bool)> disconnect_1, disconnect_2;

  device::test::MultipleVirtualFidoDeviceFactory::DeviceDetails device_1;
  device_1.state->pin = kTestPIN;
  device_1.config.pin_support = true;
  std::tie(disconnect_1, device_1.disconnect_events) =
      device::FidoDiscoveryBase::EventStream<bool>::New();

  device::test::MultipleVirtualFidoDeviceFactory::DeviceDetails device_2;
  device_2.state->pin = kTestPIN;
  device_2.config.pin_support = true;
  std::tie(disconnect_2, device_2.disconnect_events) =
      device::FidoDiscoveryBase::EventStream<bool>::New();

  int callbacks = 0;
  auto touch_callback = [&](int device_num) -> bool {
    callbacks++;
    if (callbacks == 1) {
      // Wait for the other authenticator to be triggered.
      return false;
    } else if (callbacks == 2) {
      // Touch authenticator to collect a PIN.
      return true;
    } else {
      CHECK_EQ(callbacks, 3);

      // Disconnect other authenticator then complete with a touch.
      if (device_num == 1) {
        disconnect_2.Run(false);
      } else {
        disconnect_1.Run(false);
      }
      return true;
    }
  };

  device_1.state->simulate_press_callback = base::BindLambdaForTesting(
      [&](VirtualFidoDevice* ignore) -> bool { return touch_callback(1); });
  device_2.state->simulate_press_callback = base::BindLambdaForTesting(
      [&](VirtualFidoDevice* ignore) -> bool { return touch_callback(2); });

  auto discovery =
      std::make_unique<device::test::MultipleVirtualFidoDeviceFactory>();
  discovery->AddDevice(std::move(device_1));
  discovery->AddDevice(std::move(device_2));
  ReplaceDiscoveryFactory(std::move(discovery));

  test_client_.expected = {
      {PINReason::kChallenge, kTestPIN16, device::kMaxPinRetries}};
  EXPECT_EQ(AuthenticatorMakeCredential().status, AuthenticatorStatus::SUCCESS);
}

TEST_F(PINAuthenticatorImplTest,
       RemoveAuthenticatorDuringRegistrationPINPrompt) {
  // Regression test for crbug.com/370000838: removing an authenticator while
  // the PIN prompt was showing would crash.
  base::RepeatingCallback<void(bool)> disconnect_1;
  device::test::MultipleVirtualFidoDeviceFactory::DeviceDetails device_1;
  device_1.state->pin = kTestPIN;
  device_1.config.pin_support = true;
  std::tie(disconnect_1, device_1.disconnect_events) =
      device::FidoDiscoveryBase::EventStream<bool>::New();

  auto discovery =
      std::make_unique<device::test::MultipleVirtualFidoDeviceFactory>();
  discovery->AddDevice(std::move(device_1));
  ReplaceDiscoveryFactory(std::move(discovery));

  test_client_.collect_pin_cb =
      base::BindLambdaForTesting([&disconnect_1]() -> bool {
        disconnect_1.Run(false);
        return false;
      });

  EXPECT_EQ(AuthenticatorMakeCredential().status,
            AuthenticatorStatus::NOT_ALLOWED_ERROR);
}

TEST_F(PINAuthenticatorImplTest, RemoveAuthenticatorDuringAssertionPINPrompt) {
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
      get_credential_options()->allow_credentials[0].id, kTestRelyingPartyId));

  base::RepeatingCallback<void(bool)> disconnect_1;
  device::test::MultipleVirtualFidoDeviceFactory::DeviceDetails device_1;
  device_1.state->pin = kTestPIN;
  device_1.config.pin_support = true;
  std::tie(disconnect_1, device_1.disconnect_events) =
      device::FidoDiscoveryBase::EventStream<bool>::New();

  auto discovery =
      std::make_unique<device::test::MultipleVirtualFidoDeviceFactory>();
  discovery->AddDevice(std::move(device_1));
  ReplaceDiscoveryFactory(std::move(discovery));

  test_client_.collect_pin_cb =
      base::BindLambdaForTesting([&disconnect_1]() -> bool {
        disconnect_1.Run(false);
        return false;
      });

  PublicKeyCredentialRequestOptionsPtr options =
      GetTestPublicKeyCredentialRequestOptions();
  options->user_verification = device::UserVerificationRequirement::kRequired;
  EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
            AuthenticatorStatus::NOT_ALLOWED_ERROR);
}

TEST_F(PINAuthenticatorImplTest, AppIdExcludeExtensionWithPinRequiredError) {
  // Some alwaysUv authenticators apply the alwaysUv logic even when up=false.
  // That causes them to return `kCtap2ErrPinRequired` to appIdExclude probes
  // which broke makeCredential at one point. See crbug.com/1443039.
  NavigateAndCommit(GURL(kTestOrigin1));

  device::VirtualCtap2Device::Config config;
  config.always_uv = true;
  config.always_uv_for_up_false = true;
  config.pin_support = true;
  config.pin_uv_auth_token_support = true;
  config.ctap2_versions = {device::Ctap2Version::kCtap2_1};
  virtual_device_factory_->SetCtap2Config(config);

  test_client_.expected = {{PINReason::kSet, kTestPIN16}};

  PublicKeyCredentialCreationOptionsPtr options =
      GetTestPublicKeyCredentialCreationOptions();
  options->authenticator_selection->user_verification_requirement =
      device::UserVerificationRequirement::kRequired;
  options->appid_exclude = kTestOrigin1;
  options->exclude_credentials = GetTestCredentials();

  EXPECT_EQ(AuthenticatorMakeCredential(std::move(options)).status,
            AuthenticatorStatus::SUCCESS);
}

class InternalUVAuthenticatorImplTest : public UVAuthenticatorImplTest {
 public:
  struct TestCase {
    const bool fingerprints_enrolled;
    const bool supports_pin;
    const device::UserVerificationRequirement uv;
  };

  InternalUVAuthenticatorImplTest() = default;

  InternalUVAuthenticatorImplTest(const InternalUVAuthenticatorImplTest&) =
      delete;
  InternalUVAuthenticatorImplTest& operator=(
      const InternalUVAuthenticatorImplTest&) = delete;

  void SetUp() override {
    UVAuthenticatorImplTest::SetUp();
    NavigateAndCommit(GURL(kTestOrigin1));
  }

  std::vector<TestCase> GetTestCases() {
    std::vector<TestCase> test_cases;
    for (const bool fingerprints_enrolled : {true, false}) {
      for (const bool supports_pin : {true, false}) {
        // Avoid just testing for PIN.
        if (!fingerprints_enrolled && supports_pin) {
          continue;
        }
        for (const auto uv : {device::UserVerificationRequirement::kDiscouraged,
                              device::UserVerificationRequirement::kPreferred,
                              device::UserVerificationRequirement::kRequired}) {
          test_cases.push_back({fingerprints_enrolled, supports_pin, uv});
        }
      }
    }
    return test_cases;
  }

  void ConfigureDevice(const TestCase& test_case) {
    device::VirtualCtap2Device::Config config;
    config.internal_uv_support = true;
    config.u2f_support = true;
    config.pin_support = test_case.supports_pin;
    virtual_device_factory_->mutable_state()->pin = kTestPIN;
    virtual_device_factory_->mutable_state()->pin_retries =
        device::kMaxPinRetries;
    virtual_device_factory_->mutable_state()->fingerprints_enrolled =
        test_case.fingerprints_enrolled;
    virtual_device_factory_->SetCtap2Config(config);
    SCOPED_TRACE(::testing::Message() << "fingerprints_enrolled="
                                      << test_case.fingerprints_enrolled);
    SCOPED_TRACE(::testing::Message()
                 << "supports_pin=" << test_case.supports_pin);
    SCOPED_TRACE(UVToString(test_case.uv));
  }
};

TEST_F(InternalUVAuthenticatorImplTest, MakeCredential) {
  for (const auto test_case : GetTestCases()) {
    ConfigureDevice(test_case);

    auto options = make_credential_options(test_case.uv);
    // UV cannot be satisfied without fingerprints.
    const bool should_timeout =
        !test_case.fingerprints_enrolled &&
        test_case.uv == device::UserVerificationRequirement::kRequired;
    if (should_timeout) {
      options->timeout = base::Milliseconds(100);
    }

    MakeCredentialResult result =
        AuthenticatorMakeCredential(std::move(options));

    if (should_timeout) {
      EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, result.status);
    } else {
      EXPECT_EQ(AuthenticatorStatus::SUCCESS, result.status);
      EXPECT_EQ(test_case.fingerprints_enrolled, HasUV(result.response));
    }
  }
}

// Test falling back to PIN for devices that support internal user verification
// but not uv token.
TEST_F(InternalUVAuthenticatorImplTest, MakeCredentialFallBackToPin) {
  device::VirtualCtap2Device::Config config;
  config.internal_uv_support = true;
  config.pin_support = true;
  config.user_verification_succeeds = false;
  virtual_device_factory_->mutable_state()->pin = kTestPIN;
  virtual_device_factory_->mutable_state()->pin_retries =
      device::kMaxPinRetries;
  virtual_device_factory_->mutable_state()->fingerprints_enrolled = true;
  virtual_device_factory_->SetCtap2Config(config);

  auto options =
      make_credential_options(device::UserVerificationRequirement::kRequired);

  MakeCredentialResult result = AuthenticatorMakeCredential(std::move(options));

  EXPECT_EQ(AuthenticatorStatus::SUCCESS, result.status);
  EXPECT_TRUE(HasUV(result.response));
  EXPECT_TRUE(test_client_.collected_pin);
  EXPECT_EQ(device::kMinPinLength, test_client_.min_pin_length);
}

// Test making a credential on an authenticator that supports biometric
// enrollment but has no fingerprints enrolled.
TEST_F(InternalUVAuthenticatorImplTest, MakeCredentialInlineBioEnrollment) {
  device::VirtualCtap2Device::Config config;
  config.internal_uv_support = true;
  config.pin_support = true;
  config.user_verification_succeeds = true;
  config.bio_enrollment_support = true;
  virtual_device_factory_->mutable_state()->pin = kTestPIN;
  virtual_device_factory_->mutable_state()->pin_retries =
      device::kMaxPinRetries;
  virtual_device_factory_->mutable_state()->fingerprints_enrolled = false;
  virtual_device_factory_->SetCtap2Config(config);

  MakeCredentialResult result = AuthenticatorMakeCredential(
      make_credential_options(device::UserVerificationRequirement::kRequired));

  EXPECT_EQ(AuthenticatorStatus::SUCCESS, result.status);
  EXPECT_TRUE(HasUV(result.response));
  EXPECT_TRUE(test_client_.collected_pin);
  EXPECT_EQ(device::kMinPinLength, test_client_.min_pin_length);
  EXPECT_TRUE(test_client_.did_bio_enrollment);
  EXPECT_TRUE(virtual_device_factory_->mutable_state()->fingerprints_enrolled);
}

// Test having an authenticator report an error during inline biometrics
// enrollment. Regression test for crbug.com/410985009.
TEST_F(InternalUVAuthenticatorImplTest,
       MakeCredentialInlineBioEnrollmentError) {
  device::VirtualCtap2Device::Config config;
  config.internal_uv_support = true;
  config.pin_support = true;
  config.user_verification_succeeds = true;
  config.bio_enrollment_support = true;
  config.override_response_map
      [device::CtapRequestCommand::kAuthenticatorBioEnrollment] =
      std::make_pair(device::CtapDeviceResponseCode::kCtap2ErrUserActionTimeout,
                     std::nullopt);
  virtual_device_factory_->mutable_state()->pin = kTestPIN;
  virtual_device_factory_->mutable_state()->pin_retries =
      device::kMaxPinRetries;
  virtual_device_factory_->mutable_state()->fingerprints_enrolled = false;
  virtual_device_factory_->SetCtap2Config(config);

  MakeCredentialResult result = AuthenticatorMakeCredential(
      make_credential_options(device::UserVerificationRequirement::kRequired));

  EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, result.status);
  EXPECT_TRUE(test_client_.collected_pin);
  EXPECT_EQ(device::kMinPinLength, test_client_.min_pin_length);
  EXPECT_TRUE(test_client_.did_bio_enrollment);
  EXPECT_FALSE(virtual_device_factory_->mutable_state()->fingerprints_enrolled);
}

// Regression test for https://crbug.com/442489275.
// Tests that removing the authenticator during bio enrollment does not leave a
// dangling pointer.
TEST_F(InternalUVAuthenticatorImplTest,
       InlineBioEnrollmentRemoveAuthenticator) {
  device::VirtualCtap2Device::Config config;
  config.internal_uv_support = true;
  config.pin_support = true;
  config.user_verification_succeeds = true;
  config.bio_enrollment_support = true;
  virtual_device_factory_->mutable_state()->pin = kTestPIN;
  virtual_device_factory_->mutable_state()->pin_retries =
      device::kMaxPinRetries;
  virtual_device_factory_->mutable_state()->fingerprints_enrolled = false;
  virtual_device_factory_->SetCtap2Config(config);

  // Stall the biometric enrollment so we can disconnect the authenticator.
  base::test::TestFuture<void> touch_fingerprint_future;
  virtual_device_factory_->mutable_state()->simulate_press_callback =
      base::BindLambdaForTesting([&](device::VirtualFidoDevice* device) {
        touch_fingerprint_future.SetValue();
        return false;
      });

  // Block the request on failure, otherwise the request ends immediately and
  // the bug doesn't trigger.
  test_client_.block_request_on_failure_once = true;

  // Make a credential and wait for the touch.
  mojo::Remote<blink::mojom::Authenticator> authenticator =
      ConnectToAuthenticator();
  TestMakeCredentialFuture request_future;
  authenticator->MakeCredential(
      make_credential_options(device::UserVerificationRequirement::kRequired),
      request_future.GetCallback());
  ASSERT_TRUE(touch_fingerprint_future.Wait());

  // Disconnect the device, which should clean up the bio enroller.
  virtual_device_factory_->DisconnectDevice();

  // Time the request out.
  task_environment()->FastForwardBy(kTestTimeout);
  ASSERT_TRUE(request_future.Wait());
  // No crashes due to dangling pointers.
}

// Test making a credential skipping biometric enrollment during credential
// creation.
TEST_F(InternalUVAuthenticatorImplTest, MakeCredentialSkipInlineBioEnrollment) {
  test_client_.cancel_bio_enrollment = true;

  device::VirtualCtap2Device::Config config;
  config.internal_uv_support = true;
  config.pin_support = true;
  config.user_verification_succeeds = true;
  config.bio_enrollment_support = true;
  virtual_device_factory_->mutable_state()->pin = kTestPIN;
  virtual_device_factory_->mutable_state()->pin_retries =
      device::kMaxPinRetries;
  virtual_device_factory_->mutable_state()->fingerprints_enrolled = false;
  virtual_device_factory_->SetCtap2Config(config);

  MakeCredentialResult result = AuthenticatorMakeCredential(
      make_credential_options(device::UserVerificationRequirement::kRequired));

  EXPECT_EQ(AuthenticatorStatus::SUCCESS, result.status);
  EXPECT_TRUE(HasUV(result.response));
  EXPECT_TRUE(test_client_.collected_pin);
  EXPECT_EQ(device::kMinPinLength, test_client_.min_pin_length);
  EXPECT_TRUE(test_client_.did_bio_enrollment);
  EXPECT_FALSE(virtual_device_factory_->mutable_state()->fingerprints_enrolled);
}

TEST_F(InternalUVAuthenticatorImplTest, MakeCredUvNotRqd) {
  // Test that on an authenticator with the makeCredUvNotRqd option enabled,
  // non-discoverable credentials can be created without requiring UV or a PIN.
  for (bool discoverable : {false, true}) {
    for (bool request_uv : {false, true}) {
      SCOPED_TRACE(testing::Message() << "discoverable=" << discoverable
                                      << " request_uv=" << request_uv);

      test_client_.web_authentication_delegate.supports_resident_keys = true;
      ResetVirtualDevice();
      device::VirtualCtap2Device::Config config;
      config.u2f_support = true;
      config.internal_uv_support = true;
      config.user_verification_succeeds = true;
      config.pin_support = true;
      config.resident_key_support = true;
      config.pin_uv_auth_token_support = true;
      config.allow_non_resident_credential_creation_without_uv = true;
      config.ctap2_versions = {device::Ctap2Version::kCtap2_1};
      virtual_device_factory_->SetCtap2Config(config);
      virtual_device_factory_->mutable_state()->pin = kTestPIN;
      virtual_device_factory_->mutable_state()->fingerprints_enrolled = true;

      PublicKeyCredentialCreationOptionsPtr request = make_credential_options();
      request->authenticator_selection->user_verification_requirement =
          request_uv ? device::UserVerificationRequirement::kPreferred
                     : device::UserVerificationRequirement::kDiscouraged;
      request->authenticator_selection->resident_key =
          discoverable ? device::ResidentKeyRequirement::kPreferred
                       : device::ResidentKeyRequirement::kDiscouraged;

      MakeCredentialResult result =
          AuthenticatorMakeCredential(std::move(request));
      EXPECT_EQ(result.status, AuthenticatorStatus::SUCCESS);
      EXPECT_EQ(HasUV(result.response), discoverable || request_uv);
      EXPECT_FALSE(test_client_.collected_pin);
      // Requests shouldn't fall back to creating U2F credentials.
      EXPECT_FALSE(virtual_device_factory_->mutable_state()
                       ->registrations.begin()
                       ->second.is_u2f);
    }
  }
}

TEST_F(InternalUVAuthenticatorImplTest, GetAssertion) {
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
      get_credential_options()->allow_credentials[0].id, kTestRelyingPartyId));

  for (const auto test_case : GetTestCases()) {
    ConfigureDevice(test_case);
    // Without a fingerprint enrolled we assume that a UV=required request
    // cannot be satisfied by an authenticator that cannot do UV. It is
    // possible for a credential to be created without UV and then later
    // asserted with UV=required, but that would be bizarre behaviour from
    // an RP and we currently don't worry about it.
    const bool should_be_unrecognized =
        !test_case.fingerprints_enrolled &&
        test_case.uv == device::UserVerificationRequirement::kRequired;

    GetAssertionResult result =
        AuthenticatorGetAssertion(get_credential_options(test_case.uv));

    if (should_be_unrecognized) {
      EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, result.status);
    } else {
      EXPECT_EQ(AuthenticatorStatus::SUCCESS, result.status);
      EXPECT_EQ(
          test_case.fingerprints_enrolled &&
              test_case.uv != device::UserVerificationRequirement::kDiscouraged,
          HasUV(result.response));
    }
  }
}

// Test falling back to PIN for devices that support internal user verification
// but not uv token.
TEST_F(InternalUVAuthenticatorImplTest, GetAssertionFallbackToPIN) {
  device::VirtualCtap2Device::Config config;
  config.internal_uv_support = true;
  config.pin_support = true;
  config.user_verification_succeeds = false;
  virtual_device_factory_->mutable_state()->pin = kTestPIN;
  virtual_device_factory_->mutable_state()->pin_retries =
      device::kMaxPinRetries;
  virtual_device_factory_->mutable_state()->fingerprints_enrolled = true;
  virtual_device_factory_->SetCtap2Config(config);

  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
      get_credential_options()->allow_credentials[0].id, kTestRelyingPartyId));

  GetAssertionResult result = AuthenticatorGetAssertion(
      get_credential_options(device::UserVerificationRequirement::kRequired));

  EXPECT_EQ(AuthenticatorStatus::SUCCESS, result.status);
  EXPECT_TRUE(HasUV(result.response));
  EXPECT_TRUE(test_client_.collected_pin);
  EXPECT_EQ(device::kMinPinLength, test_client_.min_pin_length);
}

class UVTokenAuthenticatorImplTest : public UVAuthenticatorImplTest {
 public:
  UVTokenAuthenticatorImplTest() = default;
  UVTokenAuthenticatorImplTest(const UVTokenAuthenticatorImplTest&) = delete;

  void SetUp() override {
    UVAuthenticatorImplTest::SetUp();
    device::VirtualCtap2Device::Config config;
    config.ctap2_versions = {device::Ctap2Version::kCtap2_1};
    config.internal_uv_support = true;
    config.pin_uv_auth_token_support = true;
    virtual_device_factory_->SetCtap2Config(config);
    NavigateAndCommit(GURL(kTestOrigin1));
  }
};

TEST_F(UVTokenAuthenticatorImplTest, GetAssertionUVToken) {
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
      get_credential_options()->allow_credentials[0].id, kTestRelyingPartyId));

  for (const auto fingerprints_enrolled : {false, true}) {
    SCOPED_TRACE(::testing::Message()
                 << "fingerprints_enrolled=" << fingerprints_enrolled);
    virtual_device_factory_->mutable_state()->fingerprints_enrolled =
        fingerprints_enrolled;

    for (auto uv : {device::UserVerificationRequirement::kDiscouraged,
                    device::UserVerificationRequirement::kPreferred,
                    device::UserVerificationRequirement::kRequired}) {
      SCOPED_TRACE(UVToString(uv));

      // Without a fingerprint enrolled we assume that a UV=required request
      // cannot be satisfied by an authenticator that cannot do UV. It is
      // possible for a credential to be created without UV and then later
      // asserted with UV=required, but that would be bizarre behaviour from
      // an RP and we currently don't worry about it.
      const bool should_be_unrecognized =
          !fingerprints_enrolled &&
          uv == device::UserVerificationRequirement::kRequired;

      GetAssertionResult result =
          AuthenticatorGetAssertion(get_credential_options(uv));

      if (should_be_unrecognized) {
        EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, result.status);
      } else {
        EXPECT_EQ(AuthenticatorStatus::SUCCESS, result.status);
        EXPECT_EQ(fingerprints_enrolled &&
                      uv != device::UserVerificationRequirement::kDiscouraged,
                  HasUV(result.response));
      }
    }
  }
}

// Test exhausting all internal user verification attempts on an authenticator
// that does not support PINs.
TEST_F(UVTokenAuthenticatorImplTest, GetAssertionUvFails) {
  device::VirtualCtap2Device::Config config;
  config.ctap2_versions = {device::Ctap2Version::kCtap2_1};
  config.internal_uv_support = true;
  config.pin_uv_auth_token_support = true;
  config.user_verification_succeeds = false;
  config.pin_support = false;
  virtual_device_factory_->SetCtap2Config(config);
  virtual_device_factory_->mutable_state()->fingerprints_enrolled = true;
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
      get_credential_options()->allow_credentials[0].id, kTestRelyingPartyId));

  int expected_retries = 5;
  virtual_device_factory_->mutable_state()->uv_retries = expected_retries;
  virtual_device_factory_->mutable_state()->simulate_press_callback =
      base::BindLambdaForTesting([&](device::VirtualFidoDevice* device) {
        EXPECT_EQ(--expected_retries,
                  virtual_device_factory_->mutable_state()->uv_retries);
        return true;
      });

  EXPECT_EQ(AuthenticatorGetAssertion(get_credential_options()).status,
            AuthenticatorStatus::NOT_ALLOWED_ERROR);
  VerifyGetAssertionOutcomeUkm(0, GetAssertionOutcome::kUvNotSupported,
                               AuthenticationRequestMode::kModalWebAuthn);
  EXPECT_EQ(0, expected_retries);
}

// Test exhausting all internal user verification attempts on an authenticator
// that supports PINs.
TEST_F(UVTokenAuthenticatorImplTest, GetAssertionFallBackToPin) {
  device::VirtualCtap2Device::Config config;
  config.ctap2_versions = {device::Ctap2Version::kCtap2_1};
  config.internal_uv_support = true;
  config.pin_uv_auth_token_support = true;
  config.user_verification_succeeds = false;
  config.pin_support = true;
  virtual_device_factory_->SetCtap2Config(config);
  virtual_device_factory_->mutable_state()->fingerprints_enrolled = true;
  virtual_device_factory_->mutable_state()->pin = kTestPIN;
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
      get_credential_options()->allow_credentials[0].id, kTestRelyingPartyId));

  int taps = 0;
  virtual_device_factory_->mutable_state()->uv_retries = 5;
  virtual_device_factory_->mutable_state()->simulate_press_callback =
      base::BindLambdaForTesting([&](device::VirtualFidoDevice* device) {
        ++taps;
        return true;
      });

  EXPECT_EQ(AuthenticatorGetAssertion(get_credential_options()).status,
            AuthenticatorStatus::SUCCESS);
  // 5 retries + 1 tap for the actual get assertion request.
  EXPECT_EQ(taps, 6);
  EXPECT_TRUE(test_client_.collected_pin);
  EXPECT_EQ(device::kMinPinLength, test_client_.min_pin_length);
  EXPECT_EQ(5, virtual_device_factory_->mutable_state()->uv_retries);
}

// Tests that a device supporting UV token with UV blocked at the start of a get
// assertion request gets a touch and then falls back to PIN.
TEST_F(UVTokenAuthenticatorImplTest, GetAssertionUvBlockedFallBackToPin) {
  device::VirtualCtap2Device::Config config;
  config.ctap2_versions = {device::Ctap2Version::kCtap2_1};
  config.internal_uv_support = true;
  config.pin_uv_auth_token_support = true;
  config.user_verification_succeeds = false;
  config.pin_support = true;

  virtual_device_factory_->SetCtap2Config(config);
  virtual_device_factory_->mutable_state()->uv_retries = 0;
  virtual_device_factory_->mutable_state()->fingerprints_enrolled = true;
  virtual_device_factory_->mutable_state()->pin = kTestPIN;
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
      get_credential_options()->allow_credentials[0].id, kTestRelyingPartyId));

  EXPECT_EQ(AuthenticatorGetAssertion(get_credential_options()).status,
            AuthenticatorStatus::SUCCESS);
  EXPECT_TRUE(test_client_.collected_pin);
  EXPECT_EQ(device::kMinPinLength, test_client_.min_pin_length);
  EXPECT_EQ(5, virtual_device_factory_->mutable_state()->uv_retries);
}

TEST_F(UVTokenAuthenticatorImplTest, MakeCredentialUVToken) {
  for (const auto fingerprints_enrolled : {false, true}) {
    SCOPED_TRACE(::testing::Message()
                 << "fingerprints_enrolled=" << fingerprints_enrolled);
    virtual_device_factory_->mutable_state()->fingerprints_enrolled =
        fingerprints_enrolled;

    for (const auto uv : {device::UserVerificationRequirement::kDiscouraged,
                          device::UserVerificationRequirement::kPreferred,
                          device::UserVerificationRequirement::kRequired}) {
      SCOPED_TRACE(UVToString(uv));

      // UV cannot be satisfied without fingerprints.
      const bool should_timeout =
          !fingerprints_enrolled &&
          uv == device::UserVerificationRequirement::kRequired;

      if (should_timeout) {
        EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR,
                  AuthenticatorMakeCredentialAndWaitForTimeout(
                      make_credential_options(uv))
                      .status);
      } else {
        MakeCredentialResult result =
            AuthenticatorMakeCredential(make_credential_options(uv));
        EXPECT_EQ(AuthenticatorStatus::SUCCESS, result.status);
        EXPECT_EQ(fingerprints_enrolled, HasUV(result.response));
      }
    }
  }
}

// Test exhausting all internal user verification attempts on an authenticator
// that does not support PINs.
TEST_F(UVTokenAuthenticatorImplTest, MakeCredentialUvFails) {
  device::VirtualCtap2Device::Config config;
  config.ctap2_versions = {device::Ctap2Version::kCtap2_1};
  config.internal_uv_support = true;
  config.pin_uv_auth_token_support = true;
  config.user_verification_succeeds = false;
  config.pin_support = false;
  virtual_device_factory_->SetCtap2Config(config);
  virtual_device_factory_->mutable_state()->fingerprints_enrolled = true;
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
      get_credential_options()->allow_credentials[0].id, kTestRelyingPartyId));

  int expected_retries = 5;
  virtual_device_factory_->mutable_state()->uv_retries = expected_retries;
  virtual_device_factory_->mutable_state()->simulate_press_callback =
      base::BindLambdaForTesting([&](device::VirtualFidoDevice* device) {
        EXPECT_EQ(--expected_retries,
                  virtual_device_factory_->mutable_state()->uv_retries);
        return true;
      });

  EXPECT_EQ(AuthenticatorMakeCredential(make_credential_options()).status,
            AuthenticatorStatus::NOT_ALLOWED_ERROR);
  EXPECT_EQ(0, expected_retries);
}

// Test exhausting all internal user verification attempts on an authenticator
// that supports PINs.
TEST_F(UVTokenAuthenticatorImplTest, MakeCredentialFallBackToPin) {
  device::VirtualCtap2Device::Config config;
  config.ctap2_versions = {device::Ctap2Version::kCtap2_1};
  config.internal_uv_support = true;
  config.pin_uv_auth_token_support = true;
  config.user_verification_succeeds = false;
  config.pin_support = true;
  virtual_device_factory_->SetCtap2Config(config);
  virtual_device_factory_->mutable_state()->fingerprints_enrolled = true;
  virtual_device_factory_->mutable_state()->pin = kTestPIN;
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
      get_credential_options()->allow_credentials[0].id, kTestRelyingPartyId));

  int taps = 0;
  virtual_device_factory_->mutable_state()->uv_retries = 5;
  virtual_device_factory_->mutable_state()->simulate_press_callback =
      base::BindLambdaForTesting([&](device::VirtualFidoDevice* device) {
        ++taps;
        return true;
      });

  EXPECT_EQ(AuthenticatorMakeCredential(make_credential_options()).status,
            AuthenticatorStatus::SUCCESS);
  // 5 retries + 1 tap for the actual get assertion request.
  EXPECT_EQ(taps, 6);
  EXPECT_TRUE(test_client_.collected_pin);
  EXPECT_EQ(device::kMinPinLength, test_client_.min_pin_length);
  EXPECT_EQ(5, virtual_device_factory_->mutable_state()->uv_retries);
}

// Tests that a device supporting UV token with UV blocked at the start of a get
// assertion request gets a touch and then falls back to PIN.
TEST_F(UVTokenAuthenticatorImplTest, MakeCredentialUvBlockedFallBackToPin) {
  device::VirtualCtap2Device::Config config;
  config.ctap2_versions = {device::Ctap2Version::kCtap2_1};
  config.internal_uv_support = true;
  config.pin_uv_auth_token_support = true;
  config.user_verification_succeeds = false;
  config.pin_support = true;

  virtual_device_factory_->SetCtap2Config(config);
  virtual_device_factory_->mutable_state()->uv_retries = 0;
  virtual_device_factory_->mutable_state()->fingerprints_enrolled = true;
  virtual_device_factory_->mutable_state()->pin = kTestPIN;
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
      get_credential_options()->allow_credentials[0].id, kTestRelyingPartyId));

  EXPECT_EQ(AuthenticatorMakeCredential(make_credential_options()).status,
            AuthenticatorStatus::SUCCESS);
  EXPECT_TRUE(test_client_.collected_pin);
  EXPECT_EQ(device::kMinPinLength, test_client_.min_pin_length);
  EXPECT_EQ(5, virtual_device_factory_->mutable_state()->uv_retries);
}

class BlockingAuthenticatorRequestDelegate
    : public DefaultAuthenticatorRequestClientDelegate {
 public:
  BlockingAuthenticatorRequestDelegate() = default;

  void RegisterActionCallbacks(
      base::OnceClosure cancel_callback,
      base::OnceClosure immediate_not_found_callback,
      base::RepeatingClosure start_over_callback,
      AccountPreselectedCallback account_preselected_callback,
      PasswordSelectedCallback password_selected_callback,
      device::FidoRequestHandlerBase::RequestCallback request_callback,
      base::OnceClosure cancel_ui_timeout_callback,
      base::RepeatingClosure bluetooth_adapter_power_on_callback,
      base::RepeatingCallback<
          void(device::FidoRequestHandlerBase::BlePermissionCallback)>
          ble_status_callback) override {
    cancel_callback_ = std::move(cancel_callback);
  }

  bool DoesBlockRequestOnFailure(InterestingFailureReason reason) override {
    // Post a task to cancel the request to give the second authenticator a
    // chance to return a status from the cancelled request.
    base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
        FROM_HERE, std::move(cancel_callback_));
    return true;
  }

 private:
  base::OnceClosure cancel_callback_;
};

class BlockingDelegateContentBrowserClient : public ContentBrowserClient {
 public:
  BlockingDelegateContentBrowserClient() = default;

  WebAuthenticationDelegate* GetWebAuthenticationDelegate() override {
    return &web_authentication_delegate_;
  }

  std::unique_ptr<AuthenticatorRequestClientDelegate>
  GetWebAuthenticationRequestDelegate(
      RenderFrameHost* render_frame_host) override {
    auto ret = std::make_unique<BlockingAuthenticatorRequestDelegate>();
    delegate_ = ret.get();
    return ret;
  }

 private:
  TestWebAuthenticationDelegate web_authentication_delegate_;
  raw_ptr<BlockingAuthenticatorRequestDelegate, AcrossTasksDanglingUntriaged>
      delegate_ = nullptr;
};

class BlockingDelegateAuthenticatorImplTest : public AuthenticatorImplTest {
 public:
  BlockingDelegateAuthenticatorImplTest() = default;

  BlockingDelegateAuthenticatorImplTest(
      const BlockingDelegateAuthenticatorImplTest&) = delete;
  BlockingDelegateAuthenticatorImplTest& operator=(
      const BlockingDelegateAuthenticatorImplTest&) = delete;

  void SetUp() override {
    AuthenticatorImplTest::SetUp();
    old_client_ = SetBrowserClientForTesting(&test_client_);
    NavigateAndCommit(GURL(kTestOrigin1));
  }

  void TearDown() override {
    SetBrowserClientForTesting(old_client_);
    AuthenticatorImplTest::TearDown();
  }

 protected:
  BlockingDelegateContentBrowserClient test_client_;

 private:
  raw_ptr<ContentBrowserClient> old_client_ = nullptr;
};

TEST_F(BlockingDelegateAuthenticatorImplTest, PostCancelMessage) {
  // Create a fingerprint-reading device and a UP-only device. Advance the
  // first till it's waiting for a fingerprint then simulate a touch on the
  // UP device that claims that it failed due to an excluded credential.
  // This will cancel the request on the fingerprint device, which will resolve
  // the UV with an error. Don't crash (crbug.com/1225899).
  PublicKeyCredentialCreationOptionsPtr options =
      GetTestPublicKeyCredentialCreationOptions();
  options->exclude_credentials = GetTestCredentials();

  device::test::MultipleVirtualFidoDeviceFactory::DeviceDetails device_1;
  scoped_refptr<VirtualFidoDevice::State> state_1 = device_1.state;
  device_1.state->simulate_press_callback =
      base::BindLambdaForTesting([&](VirtualFidoDevice* ignore) -> bool {
        // Drop all makeCredential requests. The reply will be sent when
        // the second authenticator is asked for a fingerprint.
        return false;
      });

  device::test::MultipleVirtualFidoDeviceFactory::DeviceDetails device_2;
  scoped_refptr<VirtualFidoDevice::State> state_2 = device_2.state;
  device_2.config.internal_uv_support = true;
  device_2.config.pin_support = true;
  device_2.config.pin_uv_auth_token_support = true;
  device_2.config.ctap2_versions = {device::Ctap2Version::kCtap2_1};
  device_2.state->pin = kTestPIN;
  device_2.state->fingerprints_enrolled = true;
  device_2.state->uv_retries = 8;
  device_2.state->cancel_response_code =
      device::CtapDeviceResponseCode::kCtap2ErrOperationDenied;
  device_2.state->simulate_press_callback =
      base::BindLambdaForTesting([&](VirtualFidoDevice* ignore) -> bool {
        // If asked for a fingerprint, fail the makeCredential request by
        // simulating a matched excluded credential by the other authenticator.
        base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
            FROM_HERE, base::BindOnce(std::move(state_1->transact_callback),
                                      std::vector<uint8_t>{static_cast<uint8_t>(
                                          device::CtapDeviceResponseCode::
                                              kCtap2ErrCredentialExcluded)}));
        return false;
      });

  auto discovery =
      std::make_unique<device::test::MultipleVirtualFidoDeviceFactory>();
  discovery->AddDevice(std::move(device_1));
  discovery->AddDevice(std::move(device_2));
  ReplaceDiscoveryFactory(std::move(discovery));

  EXPECT_EQ(AuthenticatorMakeCredential(std::move(options)).status,
            AuthenticatorStatus::CREDENTIAL_EXCLUDED);
}

// ResidentKeyTestAuthenticatorRequestDelegate is a delegate that:
//   a) always returns |kTestPIN| when asked for a PIN.
//   b) sorts potential resident-key accounts by user ID, maps them to a string
//      form ("<hex user ID>:<user name>:<display name>"), joins the strings
//      with "/", and compares the result against |expected_accounts|.
//   c) auto-selects the account with the user ID matching |selected_user_id|.
class ResidentKeyTestAuthenticatorRequestDelegate
    : public DefaultAuthenticatorRequestClientDelegate {
 public:
  struct Config {
    // A string representation of the accounts expected to be passed to
    // `SelectAccount()`.
    std::string expected_accounts;

    // The user ID of the account that should be selected by `SelectAccount()`.
    std::vector<uint8_t> selected_user_id;

    // Indicates whether `SetUIPresentation(kAutofill)` is expected to be
    // called.
    bool expect_conditional = false;

    // Indicates whether `RegisterActionCallbacks()` should run the cancel UI
    // timeout callback.
    bool run_cancel_ui_timeout_callback = false;

    // If set, indicates that `DoesBlockRequestOnFailure()` is expected to be
    // called with this value.
    std::optional<AuthenticatorRequestClientDelegate::InterestingFailureReason>
        expected_failure_reason;

    // If set, indicates that the `AccountPreselectCallback` should be invoked
    // with this credential ID at the beginning of the request.
    // `preselected_authenticator_id` contains the authenticator ID to which the
    // request should be dispatched in this case.
    std::optional<std::vector<uint8_t>> preselected_credential_id;
    std::optional<std::string> preselected_authenticator_id;
  };

  explicit ResidentKeyTestAuthenticatorRequestDelegate(Config config)
      : config_(std::move(config)) {}

  ~ResidentKeyTestAuthenticatorRequestDelegate() override {
    CHECK(!config_.expect_conditional || expect_conditional_satisfied_)
        << "SetUIPresentation(kAutofill) expected but not called";
    DCHECK(!config_.expected_failure_reason ||
           expected_failure_reason_satisfied_)
        << "DoesRequestBlockOnFailure() expected but not called";
  }

  ResidentKeyTestAuthenticatorRequestDelegate(
      const ResidentKeyTestAuthenticatorRequestDelegate&) = delete;
  ResidentKeyTestAuthenticatorRequestDelegate& operator=(
      const ResidentKeyTestAuthenticatorRequestDelegate&) = delete;

  bool SupportsPIN() const override { return true; }

  void CollectPIN(
      CollectPINOptions options,
      base::OnceCallback<void(std::u16string)> provide_pin_cb) override {
    base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
        FROM_HERE, base::BindOnce(std::move(provide_pin_cb), kTestPIN16));
  }

  void FinishCollectToken() override {}

  void RegisterActionCallbacks(
      base::OnceClosure cancel_callback,
      base::OnceClosure immediate_not_found_callback,
      base::RepeatingClosure start_over_callback,
      AccountPreselectedCallback account_preselected_callback,
      PasswordSelectedCallback password_selected_callback,
      device::FidoRequestHandlerBase::RequestCallback request_callback,
      base::OnceClosure cancel_ui_timeout_callback,
      base::RepeatingClosure bluetooth_adapter_power_on_callback,
      base::RepeatingCallback<
          void(device::FidoRequestHandlerBase::BlePermissionCallback)>
          ble_status_callback) override {
    account_preselected_callback_ = account_preselected_callback;
    request_callback_ = request_callback;
    if (config_.run_cancel_ui_timeout_callback) {
      std::move(cancel_ui_timeout_callback).Run();
    }
  }

  void SelectAccount(
      std::vector<device::AuthenticatorGetAssertionResponse> responses,
      base::OnceCallback<void(device::AuthenticatorGetAssertionResponse)>
          callback) override {
    std::sort(responses.begin(), responses.end(),
              [](const device::AuthenticatorGetAssertionResponse& a,
                 const device::AuthenticatorGetAssertionResponse& b) {
                return a.user_entity->id < b.user_entity->id;
              });

    std::vector<std::string> string_reps;
    std::ranges::transform(
        responses, std::back_inserter(string_reps),
        [](const device::AuthenticatorGetAssertionResponse& response) {
          const device::PublicKeyCredentialUserEntity& user =
              response.user_entity.value();
          return base::HexEncode(user.id) + ":" + user.name.value_or("") + ":" +
                 user.display_name.value_or("");
        });

    EXPECT_EQ(config_.expected_accounts, base::JoinString(string_reps, "/"));

    const auto selected = std::ranges::find(
        responses, config_.selected_user_id,
        [](const device::AuthenticatorGetAssertionResponse& response) {
          return response.user_entity->id;
        });
    ASSERT_TRUE(selected != responses.end());

    base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
        FROM_HERE, base::BindOnce(std::move(callback), std::move(*selected)));
  }

  bool DoesBlockRequestOnFailure(InterestingFailureReason reason) override {
    if (config_.expected_failure_reason) {
      EXPECT_EQ(*config_.expected_failure_reason, reason);
      expected_failure_reason_satisfied_ = true;
    }
    return AuthenticatorRequestClientDelegate::DoesBlockRequestOnFailure(
        reason);
  }

  void SetUIPresentation(UIPresentation ui_presentation) override {
    if (config_.expect_conditional) {
      EXPECT_EQ(ui_presentation, UIPresentation::kAutofill);
    } else {
      EXPECT_TRUE(ui_presentation == UIPresentation::kModal ||
                  ui_presentation == UIPresentation::kModalImmediate);
    }
    EXPECT_TRUE(!expect_conditional_satisfied_);
    expect_conditional_satisfied_ = true;
  }

  bool EmbedderControlsAuthenticatorDispatch(
      const device::FidoAuthenticator& authenticator) override {
    // Don't instantly dispatch platform authenticator requests if the test is
    // exercising platform credential preselection.
    // `OnTransportAvailabilityEnumerated()` will run the `request_callback_` in
    // this case to mimic behavior of the real UI.
    return authenticator.AuthenticatorTransport() ==
               device::FidoTransportProtocol::kInternal &&
           config_.preselected_credential_id;
  }

  void OnTransportAvailabilityEnumerated(
      device::FidoRequestHandlerBase::TransportAvailabilityInfo info) override {
    if (config_.preselected_credential_id) {
      DCHECK(config_.preselected_authenticator_id);
      EXPECT_EQ(info.has_platform_authenticator_credential,
                device::FidoRequestHandlerBase::RecognizedCredential::
                    kHasRecognizedCredential);
      const auto cred = std::ranges::find(
          info.recognized_credentials, *config_.preselected_credential_id,
          &device::DiscoverableCredentialMetadata::cred_id);
      ASSERT_NE(cred, info.recognized_credentials.end());
      std::move(account_preselected_callback_).Run(*cred);
      request_callback_.Run(*config_.preselected_authenticator_id);
    }
  }

 private:
  const Config config_;
  bool expect_conditional_satisfied_ = false;
  bool expected_failure_reason_satisfied_ = false;
  device::FidoRequestHandlerBase::RequestCallback request_callback_;
  AccountPreselectedCallback account_preselected_callback_;
  base::OnceClosure cancel_ui_timeout_callback_;
};

class ResidentKeyTestAuthenticatorContentBrowserClient
    : public ContentBrowserClient {
 public:
  ResidentKeyTestAuthenticatorContentBrowserClient() {
    web_authentication_delegate.supports_resident_keys = true;
  }

  WebAuthenticationDelegate* GetWebAuthenticationDelegate() override {
    return &web_authentication_delegate;
  }

  std::unique_ptr<AuthenticatorRequestClientDelegate>
  GetWebAuthenticationRequestDelegate(
      RenderFrameHost* render_frame_host) override {
    return std::make_unique<ResidentKeyTestAuthenticatorRequestDelegate>(
        delegate_config);
  }

  TestWebAuthenticationDelegate web_authentication_delegate;

  ResidentKeyTestAuthenticatorRequestDelegate::Config delegate_config;
};

class ResidentKeyAuthenticatorImplTest : public UVAuthenticatorImplTest {
 public:
  ResidentKeyAuthenticatorImplTest(const ResidentKeyAuthenticatorImplTest&) =
      delete;
  ResidentKeyAuthenticatorImplTest& operator=(
      const ResidentKeyAuthenticatorImplTest&) = delete;

 protected:
  ResidentKeyAuthenticatorImplTest() = default;

  void SetUp() override {
    UVAuthenticatorImplTest::SetUp();
    old_client_ = SetBrowserClientForTesting(&test_client_);
    device::VirtualCtap2Device::Config config;
    config.pin_support = true;
    config.resident_key_support = true;
    virtual_device_factory_->SetCtap2Config(config);
    virtual_device_factory_->mutable_state()->pin = kTestPIN;
    virtual_device_factory_->mutable_state()->pin_retries =
        device::kMaxPinRetries;
    NavigateAndCommit(GURL(kTestOrigin1));
  }

  void TearDown() override {
    SetBrowserClientForTesting(old_client_);
    UVAuthenticatorImplTest::TearDown();
  }

  static PublicKeyCredentialCreationOptionsPtr make_credential_options(
      device::ResidentKeyRequirement resident_key =
          device::ResidentKeyRequirement::kRequired) {
    PublicKeyCredentialCreationOptionsPtr options =
        UVAuthenticatorImplTest::make_credential_options();
    options->authenticator_selection->resident_key = resident_key;
    options->user.id = {1, 2, 3, 4};
    return options;
  }

  static PublicKeyCredentialRequestOptionsPtr get_credential_options() {
    PublicKeyCredentialRequestOptionsPtr options =
        UVAuthenticatorImplTest::get_credential_options();
    options->allow_credentials.clear();
    return options;
  }

  ResidentKeyTestAuthenticatorContentBrowserClient test_client_;

 private:
  raw_ptr<ContentBrowserClient> old_client_ = nullptr;
};

TEST_F(ResidentKeyAuthenticatorImplTest, MakeCredentialRkRequired) {
  for (const bool internal_uv : {false, true}) {
    SCOPED_TRACE(::testing::Message() << "internal_uv=" << internal_uv);

    if (internal_uv) {
      device::VirtualCtap2Device::Config config;
      config.resident_key_support = true;
      config.internal_uv_support = true;
      virtual_device_factory_->SetCtap2Config(config);
      virtual_device_factory_->mutable_state()->fingerprints_enrolled = true;
    }

    MakeCredentialResult result =
        AuthenticatorMakeCredential(make_credential_options());

    EXPECT_EQ(AuthenticatorStatus::SUCCESS, result.status);
    EXPECT_TRUE(HasUV(result.response));
    ASSERT_EQ(1u,
              virtual_device_factory_->mutable_state()->registrations.size());
    const device::VirtualFidoDevice::RegistrationData& registration =
        virtual_device_factory_->mutable_state()->registrations.begin()->second;
    EXPECT_TRUE(registration.is_resident);
    ASSERT_TRUE(registration.user.has_value());
    const auto options = make_credential_options();
    EXPECT_EQ(options->user.name, registration.user->name);
    EXPECT_EQ(options->user.display_name, registration.user->display_name);
    EXPECT_EQ(options->user.id, registration.user->id);
  }
}

TEST_F(ResidentKeyAuthenticatorImplTest, MakeCredentialRkPreferred) {
  for (const bool supports_rk : {false, true}) {
    SCOPED_TRACE(::testing::Message() << "supports_rk=" << supports_rk);
    ResetVirtualDevice();

    device::VirtualCtap2Device::Config config;
    config.internal_uv_support = true;
    config.resident_key_support = supports_rk;
    virtual_device_factory_->SetCtap2Config(config);
    virtual_device_factory_->mutable_state()->fingerprints_enrolled = true;

    MakeCredentialResult result = AuthenticatorMakeCredential(
        make_credential_options(device::ResidentKeyRequirement::kPreferred));

    ASSERT_EQ(AuthenticatorStatus::SUCCESS, result.status);
    EXPECT_TRUE(HasUV(result.response));
    ASSERT_EQ(1u,
              virtual_device_factory_->mutable_state()->registrations.size());
    const device::VirtualFidoDevice::RegistrationData& registration =
        virtual_device_factory_->mutable_state()->registrations.begin()->second;
    EXPECT_EQ(registration.is_resident, supports_rk);
  }
}

TEST_F(ResidentKeyAuthenticatorImplTest, MakeCredentialRkPreferredStorageFull) {
  // Making a credential on an authenticator with full storage falls back to
  // making a non-resident key.
  for (bool is_ctap_2_1 : {false, true}) {
    ResetVirtualDevice();

    size_t num_taps = 0;
    virtual_device_factory_->mutable_state()->simulate_press_callback =
        base::BindLambdaForTesting(
            [&num_taps](device::VirtualFidoDevice* device) {
              num_taps++;
              return true;
            });

    device::VirtualCtap2Device::Config config;
    if (is_ctap_2_1) {
      config.ctap2_versions = {std::begin(device::kCtap2Versions2_1),
                               std::end(device::kCtap2Versions2_1)};
    }

    config.internal_uv_support = true;
    config.resident_key_support = true;
    config.resident_credential_storage = 0;
    virtual_device_factory_->SetCtap2Config(config);
    virtual_device_factory_->mutable_state()->fingerprints_enrolled = true;

    MakeCredentialResult result = AuthenticatorMakeCredential(
        make_credential_options(device::ResidentKeyRequirement::kPreferred));

    ASSERT_EQ(AuthenticatorStatus::SUCCESS, result.status);
    EXPECT_TRUE(HasUV(result.response));
    ASSERT_EQ(1u,
              virtual_device_factory_->mutable_state()->registrations.size());
    const device::VirtualFidoDevice::RegistrationData& registration =
        virtual_device_factory_->mutable_state()->registrations.begin()->second;
    EXPECT_EQ(registration.is_resident, false);
    // In CTAP 2.0, the first request with rk=false fails due to exhausted
    // storage and then needs to be retried with rk=false, requiring a second
    // tap. In 2.1 remaining storage capacity can be checked up front such that
    // the request is sent with rk=false right away.
    EXPECT_EQ(num_taps, is_ctap_2_1 ? 1u : 2u);
  }
}

TEST_F(ResidentKeyAuthenticatorImplTest,
       MakeCredentialRkPreferredStorageFull_LargeBlob) {
  device::VirtualCtap2Device::Config config;
  config.ctap2_versions = {std::begin(device::kCtap2Versions2_1),
                           std::end(device::kCtap2Versions2_1)};
  config.internal_uv_support = true;
  config.resident_key_support = true;
  config.resident_credential_storage = 0;
  config.large_blob_support = true;
  config.pin_uv_auth_token_support = true;
  virtual_device_factory_->SetCtap2Config(config);
  virtual_device_factory_->mutable_state()->fingerprints_enrolled = true;
  {
    PublicKeyCredentialCreationOptionsPtr options =
        make_credential_options(device::ResidentKeyRequirement::kPreferred);
    options->large_blob_enable = device::LargeBlobSupport::kRequired;
    MakeCredentialResult result =
        AuthenticatorMakeCredential(std::move(options));
    EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, result.status);
  }
  {
    PublicKeyCredentialCreationOptionsPtr options =
        make_credential_options(device::ResidentKeyRequirement::kPreferred);
    options->large_blob_enable = device::LargeBlobSupport::kPreferred;
    MakeCredentialResult result =
        AuthenticatorMakeCredential(std::move(options));
    ASSERT_EQ(AuthenticatorStatus::SUCCESS, result.status);
    EXPECT_TRUE(result.response->echo_large_blob);
    EXPECT_FALSE(result.response->supports_large_blob);
    EXPECT_EQ(1u,
              virtual_device_factory_->mutable_state()->registrations.size());
    const device::VirtualFidoDevice::RegistrationData& registration =
        virtual_device_factory_->mutable_state()->registrations.begin()->second;
    EXPECT_FALSE(registration.is_resident);
    EXPECT_FALSE(registration.large_blob);
    EXPECT_FALSE(registration.large_blob_key);
  }
}

TEST_F(ResidentKeyAuthenticatorImplTest, MakeCredentialRkPreferredSetsPIN) {
  device::VirtualCtap2Device::Config config;
  config.pin_support = true;
  config.internal_uv_support = false;
  config.resident_key_support = true;
  virtual_device_factory_->SetCtap2Config(config);
  virtual_device_factory_->mutable_state()->pin = "";

  MakeCredentialResult result = AuthenticatorMakeCredential(
      make_credential_options(device::ResidentKeyRequirement::kPreferred));

  EXPECT_EQ(AuthenticatorStatus::SUCCESS, result.status);
  EXPECT_TRUE(HasUV(result.response));
  ASSERT_EQ(1u, virtual_device_factory_->mutable_state()->registrations.size());
  const device::VirtualFidoDevice::RegistrationData& registration =
      virtual_device_factory_->mutable_state()->registrations.begin()->second;
  EXPECT_EQ(registration.is_resident, true);
  EXPECT_EQ(virtual_device_factory_->mutable_state()->pin, kTestPIN);
}

TEST_F(ResidentKeyAuthenticatorImplTest, StorageFull) {
  device::VirtualCtap2Device::Config config;
  config.resident_key_support = true;
  config.internal_uv_support = true;
  config.resident_credential_storage = 1;
  virtual_device_factory_->SetCtap2Config(config);
  virtual_device_factory_->mutable_state()->fingerprints_enrolled = true;

  // Add a resident key to fill the authenticator.
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectResidentKey(
      /*credential_id=*/{{4, 3, 2, 1}}, kTestRelyingPartyId,
      /*user_id=*/{{1, 1, 1, 1}}, "test@example.com", "Test User"));

  test_client_.delegate_config.expected_failure_reason =
      AuthenticatorRequestClientDelegate::InterestingFailureReason::
          kStorageFull;
  EXPECT_EQ(AuthenticatorMakeCredential(make_credential_options()).status,
            AuthenticatorStatus::NOT_ALLOWED_ERROR);
  VerifyMakeCredentialOutcomeUkm(0, MakeCredentialOutcome::kStorageFull,
                                 AuthenticationRequestMode::kModalWebAuthn);
}

TEST_F(ResidentKeyAuthenticatorImplTest,
       MakeCredentialEmptyFields_SecurityKey) {
  VirtualCtap2Device::Config config;
  config.pin_support = true;
  config.resident_key_support = true;
  config.reject_empty_display_name = true;
  virtual_device_factory_->SetCtap2Config(std::move(config));
  virtual_device_factory_->SetTransport(
      device::FidoTransportProtocol::kUsbHumanInterfaceDevice);

  PublicKeyCredentialCreationOptionsPtr options = make_credential_options();

  // This value is perfectly legal, but our VirtualCtap2Device simulates
  // some security keys in rejecting empty values. CBOR serialisation should
  // omit these values rather than send empty ones.
  options->user.display_name = "";

  EXPECT_EQ(AuthenticatorStatus::SUCCESS,
            AuthenticatorMakeCredential(std::move(options)).status);
}

// Regression test for crbug.com/346835891.
TEST_F(ResidentKeyAuthenticatorImplTest, MakeCredentialEmptyFields_Phone) {
  // iPhones reject a request with a missing display name.
  VirtualCtap2Device::Config config;
  config.pin_support = true;
  config.resident_key_support = true;
  config.reject_missing_display_name = true;
  virtual_device_factory_->SetCtap2Config(std::move(config));
  virtual_device_factory_->SetTransport(device::FidoTransportProtocol::kHybrid);

  PublicKeyCredentialCreationOptionsPtr options = make_credential_options();
  options->user.display_name = "";

  EXPECT_EQ(AuthenticatorStatus::SUCCESS,
            AuthenticatorMakeCredential(std::move(options)).status);
}

TEST_F(ResidentKeyAuthenticatorImplTest, GetAssertionSingleNoPII) {
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectResidentKey(
      /*credential_id=*/{{4, 3, 2, 1}}, kTestRelyingPartyId,
      /*user_id=*/{{1, 2, 3, 4}}, std::nullopt, std::nullopt));

  // |SelectAccount| should not be called when there's only a single response
  // with no identifying user info because the UI is bad in that case: we can
  // only display the single choice of "Unknown user".
  test_client_.delegate_config.expected_accounts = "<invalid>";
  GetAssertionResult result =
      AuthenticatorGetAssertion(get_credential_options());

  EXPECT_EQ(AuthenticatorStatus::SUCCESS, result.status);
  EXPECT_TRUE(HasUV(result.response));
}

TEST_F(ResidentKeyAuthenticatorImplTest, GetAssertionUserSelected) {
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectResidentKey(
      /*credential_id=*/{{4, 3, 2, 1}}, kTestRelyingPartyId,
      /*user_id=*/{{1, 2, 3, 4}}, "Test", "User"));

  for (const bool internal_account_chooser : {false, true}) {
    SCOPED_TRACE(internal_account_chooser);

    device::VirtualCtap2Device::Config config;
    config.pin_support = true;
    config.resident_key_support = true;
    config.internal_account_chooser = internal_account_chooser;
    virtual_device_factory_->SetCtap2Config(config);

    // |SelectAccount| should not be called when userSelected is set.
    if (internal_account_chooser) {
      test_client_.delegate_config.expected_accounts = "<invalid>";
    } else {
      test_client_.delegate_config.expected_accounts = "01020304:Test:User";
      test_client_.delegate_config.selected_user_id = {1, 2, 3, 4};
    }
    GetAssertionResult result =
        AuthenticatorGetAssertion(get_credential_options());

    EXPECT_EQ(AuthenticatorStatus::SUCCESS, result.status);
    EXPECT_TRUE(HasUV(result.response));
  }
}

TEST_F(ResidentKeyAuthenticatorImplTest, GetAssertionSingleWithPII) {
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectResidentKey(
      /*credential_id=*/{{4, 3, 2, 1}}, kTestRelyingPartyId,
      /*user_id=*/{{1, 2, 3, 4}}, std::nullopt, "Test User"));

  // |SelectAccount| should be called when PII is available.
  test_client_.delegate_config.expected_accounts = "01020304::Test User";
  test_client_.delegate_config.selected_user_id = {1, 2, 3, 4};
  GetAssertionResult result =
      AuthenticatorGetAssertion(get_credential_options());
  EXPECT_EQ(AuthenticatorStatus::SUCCESS, result.status);
  EXPECT_TRUE(HasUV(result.response));
}

TEST_F(ResidentKeyAuthenticatorImplTest, GetAssertionMulti) {
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectResidentKey(
      /*credential_id=*/{{4, 3, 2, 1}}, kTestRelyingPartyId,
      /*user_id=*/{{1, 2, 3, 4}}, "test@example.com", "Test User"));
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectResidentKey(
      /*credential_id=*/{{4, 3, 2, 2}}, kTestRelyingPartyId,
      /*user_id=*/{{5, 6, 7, 8}}, "test2@example.com", "Test User 2"));

  test_client_.delegate_config.expected_accounts =
      "01020304:test@example.com:Test User/"
      "05060708:test2@example.com:Test User 2";
  test_client_.delegate_config.selected_user_id = {1, 2, 3, 4};

  GetAssertionResult result =
      AuthenticatorGetAssertion(get_credential_options());

  EXPECT_EQ(AuthenticatorStatus::SUCCESS, result.status);
  EXPECT_TRUE(HasUV(result.response));
}

TEST_F(ResidentKeyAuthenticatorImplTest, GetAssertionUVDiscouraged) {
  device::VirtualCtap2Device::Config config;
  config.resident_key_support = true;
  config.internal_uv_support = true;
  config.u2f_support = true;
  virtual_device_factory_->SetCtap2Config(config);
  virtual_device_factory_->mutable_state()->fingerprints_enrolled = true;

  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectResidentKey(
      /*credential_id=*/{{4, 3, 2, 1}}, kTestRelyingPartyId,
      /*user_id=*/{{1, 2, 3, 4}}, std::nullopt, std::nullopt));

  // |SelectAccount| should not be called when there's only a single response
  // without identifying information.
  test_client_.delegate_config.expected_accounts = "<invalid>";
  PublicKeyCredentialRequestOptionsPtr options(get_credential_options());
  options->user_verification =
      device::UserVerificationRequirement::kDiscouraged;

  GetAssertionResult result = AuthenticatorGetAssertion(std::move(options));

  EXPECT_EQ(AuthenticatorStatus::SUCCESS, result.status);
  // The UV=discouraged should have been ignored for a resident-credential
  // request.
  EXPECT_TRUE(HasUV(result.response));
}

static const char* BlobSupportDescription(device::LargeBlobSupport support) {
  switch (support) {
    case device::LargeBlobSupport::kNotRequested:
      return "Blob not requested";
    case device::LargeBlobSupport::kPreferred:
      return "Blob preferred";
    case device::LargeBlobSupport::kRequired:
      return "Blob required";
  }
}

TEST_F(ResidentKeyAuthenticatorImplTest, MakeCredentialLargeBlob) {
  constexpr auto BlobRequired = device::LargeBlobSupport::kRequired;
  constexpr auto BlobPreferred = device::LargeBlobSupport::kPreferred;
  constexpr auto BlobNotRequested = device::LargeBlobSupport::kNotRequested;
  constexpr auto nullopt = std::nullopt;

  constexpr struct {
    bool large_blob_extension;
    std::optional<bool> large_blob_support;
    bool rk_required;
    device::LargeBlobSupport large_blob_enable;
    bool request_success;
    bool did_create_large_blob;
  } kLargeBlobTestCases[] = {
      // clang-format off
      // ext,  support,  rk,    enabled,          success, did create
      { false, true,     true,  BlobRequired,     true,    true},
      { false, true,     true,  BlobPreferred,    true,    true},
      { false, true,     true,  BlobNotRequested, true,    false},
      { false, true,     false, BlobRequired,     false,   false},
      { false, true,     false, BlobPreferred,    true,    false},
      { false, true,     true,  BlobNotRequested, true,    false},
      { false, false,    true,  BlobRequired,     false,   false},
      { false, false,    true,  BlobPreferred,    true,    false},
      { false, true,     true,  BlobNotRequested, true,    false},

      { true,  true,     true,  BlobRequired,     true,    true},
      { true,  true,     true,  BlobPreferred,    true,    true},
      { true,  true,     true,  BlobNotRequested, true,    false},
      { true,  true,     false, BlobRequired,     false,   false},
      { true,  true,     false, BlobPreferred,    true,    false},
      { true,  true,     true,  BlobNotRequested, true,    false},
      { true,  nullopt,  true,  BlobRequired,     false,   false},
      { true,  nullopt,  true,  BlobPreferred,    true,    false},
      { true,  true,     true,  BlobNotRequested, true,    false},
      { true,  false,    true,  BlobPreferred,    true,    false},
      { true,  false,    true,  BlobRequired,     false,   false},
      // clang-format on
  };
  for (auto& test : kLargeBlobTestCases) {
    if (test.large_blob_support) {
      SCOPED_TRACE(::testing::Message()
                   << "support=" << *test.large_blob_support);
    } else {
      SCOPED_TRACE(::testing::Message() << "support={}");
    }
    SCOPED_TRACE(::testing::Message() << "rk_required=" << test.rk_required);
    SCOPED_TRACE(::testing::Message()
                 << "enabled="
                 << BlobSupportDescription(test.large_blob_enable));
    SCOPED_TRACE(::testing::Message() << "success=" << test.request_success);
    SCOPED_TRACE(::testing::Message()
                 << "did create=" << test.did_create_large_blob);
    SCOPED_TRACE(::testing::Message()
                 << "large_blob_extension=" << test.large_blob_extension);

    device::VirtualCtap2Device::Config config;
    config.pin_support = true;
    config.pin_uv_auth_token_support = true;
    config.resident_key_support = true;
    config.ctap2_versions = {std::begin(device::kCtap2Versions2_1),
                             std::end(device::kCtap2Versions2_1)};
    if (test.large_blob_extension) {
      config.large_blob_extension_support = test.large_blob_support;
    } else {
      config.large_blob_support = *test.large_blob_support;
    }
    virtual_device_factory_->SetCtap2Config(config);

    PublicKeyCredentialCreationOptionsPtr options = make_credential_options(
        test.rk_required ? device::ResidentKeyRequirement::kRequired
                         : device::ResidentKeyRequirement::kDiscouraged);
    options->large_blob_enable = test.large_blob_enable;
    MakeCredentialResult result =
        AuthenticatorMakeCredential(std::move(options));

    if (test.request_success) {
      ASSERT_EQ(AuthenticatorStatus::SUCCESS, result.status);
      ASSERT_EQ(1u,
                virtual_device_factory_->mutable_state()->registrations.size());
      const device::VirtualFidoDevice::RegistrationData& registration =
          virtual_device_factory_->mutable_state()
              ->registrations.begin()
              ->second;
      EXPECT_EQ(test.did_create_large_blob && !test.large_blob_extension,
                registration.large_blob_key.has_value());
      EXPECT_EQ(test.large_blob_enable != BlobNotRequested,
                result.response->echo_large_blob);
      EXPECT_EQ(test.did_create_large_blob,
                result.response->supports_large_blob);
    } else {
      ASSERT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, result.status);
      ASSERT_EQ(0u,
                virtual_device_factory_->mutable_state()->registrations.size());
    }
    virtual_device_factory_->mutable_state()->registrations.clear();
    virtual_device_factory_->mutable_state()->ClearLargeBlobs();
  }
}

TEST_F(ResidentKeyAuthenticatorImplTest, GetAssertionLargeBlobRead) {
  constexpr struct {
    bool large_blob_support;
    bool large_blob_set;
    bool large_blob_key_set;
    bool did_read_large_blob;
  } kLargeBlobTestCases[] = {
      // clang-format off
      // support,  set,   key_set, did_read
       { true,     true,  true,    true  },
       { true,     false, false,   false },
       { true,     false, true,    false },
       { false,    false, false,   false },
      // clang-format on
  };
  for (auto& test : kLargeBlobTestCases) {
    SCOPED_TRACE(::testing::Message() << "support=" << test.large_blob_support);
    SCOPED_TRACE(::testing::Message() << "set=" << test.large_blob_set);
    SCOPED_TRACE(::testing::Message() << "key_set=" << test.large_blob_key_set);
    SCOPED_TRACE(::testing::Message()
                 << "did_read=" << test.did_read_large_blob);

    const std::vector<uint8_t> large_blob = {'b', 'l', 'o', 'b'};
    device::VirtualCtap2Device::Config config;
    config.pin_support = true;
    config.pin_uv_auth_token_support = true;
    config.resident_key_support = true;
    config.ctap2_versions = {std::begin(device::kCtap2Versions2_1),
                             std::end(device::kCtap2Versions2_1)};
    config.large_blob_support = test.large_blob_support;
    virtual_device_factory_->SetCtap2Config(config);
    ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectResidentKey(
        /*credential_id=*/{{4, 3, 2, 1}}, kTestRelyingPartyId,
        /*user_id=*/{{1, 2, 3, 4}}, std::nullopt, std::nullopt));

    if (test.large_blob_set) {
      virtual_device_factory_->mutable_state()->InjectLargeBlob(
          &virtual_device_factory_->mutable_state()
               ->registrations.begin()
               ->second,
          CompressLargeBlob(large_blob));
    } else if (test.large_blob_key_set) {
      virtual_device_factory_->mutable_state()
          ->registrations.begin()
          ->second.large_blob_key = {{0}};
    }

    PublicKeyCredentialRequestOptionsPtr options = get_credential_options();
    options->extensions->large_blob_read = true;
    GetAssertionResult result = AuthenticatorGetAssertion(std::move(options));

    ASSERT_EQ(AuthenticatorStatus::SUCCESS, result.status);
    EXPECT_TRUE(result.response->extensions->echo_large_blob);
    EXPECT_FALSE(result.response->extensions->echo_large_blob_written);
    if (test.did_read_large_blob) {
      EXPECT_EQ(large_blob, *result.response->extensions->large_blob);
    } else {
      EXPECT_FALSE(result.response->extensions->large_blob.has_value());
    }
    virtual_device_factory_->mutable_state()->registrations.clear();
    virtual_device_factory_->mutable_state()->ClearLargeBlobs();
  }
}

TEST_F(ResidentKeyAuthenticatorImplTest, GetAssertionLargeBlobWrite) {
  constexpr struct {
    bool large_blob_support;
    bool large_blob_set;
    bool large_blob_key_set;
    bool did_write_large_blob;
  } kLargeBlobTestCases[] = {
      // clang-format off
      // support,  set,   key_set, did_write
       { true,     true,  true,    true  },
       { true,     false, false,   false },
       { true,     false, true,    true  },
       { false,    false, false,   false },
      // clang-format on
  };
  for (auto& test : kLargeBlobTestCases) {
    SCOPED_TRACE(::testing::Message() << "support=" << test.large_blob_support);
    SCOPED_TRACE(::testing::Message() << "set=" << test.large_blob_set);
    SCOPED_TRACE(::testing::Message() << "key_set=" << test.large_blob_key_set);
    SCOPED_TRACE(::testing::Message()
                 << "did_write=" << test.did_write_large_blob);

    const std::vector<uint8_t> large_blob = {'b', 'l', 'o', 'b'};
    device::VirtualCtap2Device::Config config;
    config.pin_support = true;
    config.pin_uv_auth_token_support = true;
    config.resident_key_support = true;
    config.ctap2_versions = {std::begin(device::kCtap2Versions2_1),
                             std::end(device::kCtap2Versions2_1)};
    config.large_blob_support = test.large_blob_support;
    virtual_device_factory_->SetCtap2Config(config);
    const std::vector<uint8_t> cred_id = {4, 3, 2, 1};
    ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectResidentKey(
        cred_id, kTestRelyingPartyId,
        /*user_id=*/{{1, 2, 3, 4}}, std::nullopt, std::nullopt));

    if (test.large_blob_set) {
      virtual_device_factory_->mutable_state()->InjectLargeBlob(
          &virtual_device_factory_->mutable_state()
               ->registrations.begin()
               ->second,
          CompressLargeBlob(large_blob));
    } else if (test.large_blob_key_set) {
      virtual_device_factory_->mutable_state()
          ->registrations.begin()
          ->second.large_blob_key = {{0}};
    }

    PublicKeyCredentialRequestOptionsPtr options = get_credential_options();
    options->allow_credentials = {device::PublicKeyCredentialDescriptor(
        device::CredentialType::kPublicKey, cred_id)};
    options->extensions->large_blob_write = large_blob;
    GetAssertionResult result = AuthenticatorGetAssertion(std::move(options));

    ASSERT_EQ(AuthenticatorStatus::SUCCESS, result.status);
    EXPECT_TRUE(result.response->extensions->echo_large_blob);
    EXPECT_FALSE(result.response->extensions->large_blob.has_value());
    EXPECT_TRUE(result.response->extensions->echo_large_blob_written);
    EXPECT_EQ(test.did_write_large_blob,
              result.response->extensions->large_blob_written);
    if (test.did_write_large_blob) {
      std::optional<device::LargeBlob> compressed_blob =
          virtual_device_factory_->mutable_state()->GetLargeBlob(
              virtual_device_factory_->mutable_state()
                  ->registrations.begin()
                  ->second);
      EXPECT_EQ(large_blob, UncompressLargeBlob(*compressed_blob));
    }
    virtual_device_factory_->mutable_state()->registrations.clear();
    virtual_device_factory_->mutable_state()->ClearLargeBlobs();
  }
}

TEST_F(ResidentKeyAuthenticatorImplTest,
       GetAssertionLargeBlobExtensionNoSupport) {
  device::VirtualCtap2Device::Config config;
  config.pin_support = true;
  config.pin_uv_auth_token_support = true;
  config.resident_key_support = true;
  config.ctap2_versions = {std::begin(device::kCtap2Versions2_1),
                           std::end(device::kCtap2Versions2_1)};
  virtual_device_factory_->SetCtap2Config(config);

  const std::vector<uint8_t> cred_id = {4, 3, 2, 1};
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectResidentKey(
      cred_id, kTestRelyingPartyId,
      /*user_id=*/{{1, 2, 3, 4}}, std::nullopt, std::nullopt));

  // Try to read a large blob that doesn't exist and couldn't exist because the
  // authenticator doesn't support large blobs.
  PublicKeyCredentialRequestOptionsPtr options = get_credential_options();
  options->allow_credentials = {device::PublicKeyCredentialDescriptor(
      device::CredentialType::kPublicKey, cred_id)};
  options->extensions->large_blob_read = true;
  GetAssertionResult result = AuthenticatorGetAssertion(std::move(options));
  ASSERT_EQ(AuthenticatorStatus::SUCCESS, result.status);
  EXPECT_TRUE(result.response->extensions->echo_large_blob);
  EXPECT_FALSE(result.response->extensions->echo_large_blob_written);
  ASSERT_FALSE(result.response->extensions->large_blob);
}

TEST_F(ResidentKeyAuthenticatorImplTest, GetAssertionLargeBlobExtension) {
  device::VirtualCtap2Device::Config config;
  config.pin_support = true;
  config.pin_uv_auth_token_support = true;
  config.resident_key_support = true;
  config.large_blob_extension_support = true;
  config.ctap2_versions = {std::begin(device::kCtap2Versions2_1),
                           std::end(device::kCtap2Versions2_1)};
  virtual_device_factory_->SetCtap2Config(config);

  const std::vector<uint8_t> large_blob = {'b', 'l', 'o', 'b'};
  const std::vector<uint8_t> cred_id = {4, 3, 2, 1};
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectResidentKey(
      cred_id, kTestRelyingPartyId,
      /*user_id=*/{{1, 2, 3, 4}}, std::nullopt, std::nullopt));

  {
    // Try to read a large blob that doesn't exist.
    PublicKeyCredentialRequestOptionsPtr options = get_credential_options();
    options->allow_credentials = {device::PublicKeyCredentialDescriptor(
        device::CredentialType::kPublicKey, cred_id)};
    options->extensions->large_blob_read = true;
    GetAssertionResult result = AuthenticatorGetAssertion(std::move(options));
    ASSERT_EQ(AuthenticatorStatus::SUCCESS, result.status);
    EXPECT_TRUE(result.response->extensions->echo_large_blob);
    EXPECT_FALSE(result.response->extensions->echo_large_blob_written);
    ASSERT_FALSE(result.response->extensions->large_blob);
  }

  {
    // Write a large blob.
    PublicKeyCredentialRequestOptionsPtr options = get_credential_options();
    options->allow_credentials = {device::PublicKeyCredentialDescriptor(
        device::CredentialType::kPublicKey, cred_id)};
    options->extensions->large_blob_write = large_blob;
    GetAssertionResult result = AuthenticatorGetAssertion(std::move(options));
    ASSERT_EQ(AuthenticatorStatus::SUCCESS, result.status);
    EXPECT_TRUE(result.response->extensions->echo_large_blob);
    EXPECT_TRUE(result.response->extensions->echo_large_blob_written);
    EXPECT_FALSE(result.response->extensions->large_blob);
  }

  {
    // Read it back.
    PublicKeyCredentialRequestOptionsPtr options = get_credential_options();
    options->allow_credentials = {device::PublicKeyCredentialDescriptor(
        device::CredentialType::kPublicKey, cred_id)};
    options->extensions->large_blob_read = true;
    GetAssertionResult result = AuthenticatorGetAssertion(std::move(options));
    ASSERT_EQ(AuthenticatorStatus::SUCCESS, result.status);
    EXPECT_TRUE(result.response->extensions->echo_large_blob);
    EXPECT_FALSE(result.response->extensions->echo_large_blob_written);
    ASSERT_TRUE(result.response->extensions->large_blob);
    EXPECT_EQ(large_blob, *result.response->extensions->large_blob);
  }

  // Corrupt the large blob data and attempt to read it back. The invalid
  // large blob should be ignored.
  virtual_device_factory_->mutable_state()
      ->registrations.begin()
      ->second.large_blob->compressed_data = {1, 2, 3, 4};

  {
    PublicKeyCredentialRequestOptionsPtr options = get_credential_options();
    options->allow_credentials = {device::PublicKeyCredentialDescriptor(
        device::CredentialType::kPublicKey, cred_id)};
    options->extensions->large_blob_read = true;
    GetAssertionResult result = AuthenticatorGetAssertion(std::move(options));
    ASSERT_EQ(AuthenticatorStatus::SUCCESS, result.status);
    EXPECT_TRUE(result.response->extensions->echo_large_blob);
    EXPECT_FALSE(result.response->extensions->echo_large_blob_written);
    ASSERT_FALSE(result.response->extensions->large_blob);
  }
}

static const char* ProtectionPolicyDescription(
    blink::mojom::ProtectionPolicy p) {
  switch (p) {
    case blink::mojom::ProtectionPolicy::UNSPECIFIED:
      return "UNSPECIFIED";
    case blink::mojom::ProtectionPolicy::NONE:
      return "NONE";
    case blink::mojom::ProtectionPolicy::UV_OR_CRED_ID_REQUIRED:
      return "UV_OR_CRED_ID_REQUIRED";
    case blink::mojom::ProtectionPolicy::UV_REQUIRED:
      return "UV_REQUIRED";
  }
}

static const char* CredProtectDescription(device::CredProtect cred_protect) {
  switch (cred_protect) {
    case device::CredProtect::kUVOptional:
      return "UV optional";
    case device::CredProtect::kUVOrCredIDRequired:
      return "UV or cred ID required";
    case device::CredProtect::kUVRequired:
      return "UV required";
  }
}

TEST_F(ResidentKeyAuthenticatorImplTest, CredProtectRegistration) {
  const auto UNSPECIFIED = blink::mojom::ProtectionPolicy::UNSPECIFIED;
  const auto NONE = blink::mojom::ProtectionPolicy::NONE;
  const auto UV_OR_CRED =
      blink::mojom::ProtectionPolicy::UV_OR_CRED_ID_REQUIRED;
  const auto UV_REQ = blink::mojom::ProtectionPolicy::UV_REQUIRED;
  const int kOk = 0;
  const int kNonsense = 1;
  const int kNotAllow = 2;
  const device::UserVerificationRequirement kUV =
      device::UserVerificationRequirement::kRequired;
  const device::UserVerificationRequirement kUP =
      device::UserVerificationRequirement::kDiscouraged;
  const device::UserVerificationRequirement kUVPref =
      device::UserVerificationRequirement::kPreferred;

  const struct {
    bool supported_by_authenticator;
    bool is_resident;
    blink::mojom::ProtectionPolicy protection;
    bool enforce;
    device::UserVerificationRequirement uv;
    int expected_outcome;
    blink::mojom::ProtectionPolicy resulting_policy;
  } kExpectations[] = {
      // clang-format off
    // Support | Resdnt | Level      | Enf  |  UV  || Result   | Prot level
    {  false,   false,   UNSPECIFIED, false, kUP,     kOk,       NONE},
    {  false,   false,   UNSPECIFIED, true,  kUP,     kNonsense, UNSPECIFIED},
    {  false,   false,   UNSPECIFIED, false, kUVPref, kOk,       NONE},
    {  false,   false,   NONE,        false, kUP,     kNonsense, UNSPECIFIED},
    {  false,   false,   NONE,        true,  kUP,     kNonsense, UNSPECIFIED},
    {  false,   false,   UV_OR_CRED,  false, kUP,     kOk,       NONE},
    {  false,   false,   UV_OR_CRED,  true,  kUP,     kNotAllow, UNSPECIFIED},
    {  false,   false,   UV_OR_CRED,  false, kUV,     kOk,       NONE},
    {  false,   false,   UV_OR_CRED,  true,  kUV,     kNotAllow, UNSPECIFIED},
    {  false,   false,   UV_REQ,      false, kUP,     kNonsense, UNSPECIFIED},
    {  false,   false,   UV_REQ,      false, kUV,     kOk,       NONE},
    {  false,   false,   UV_REQ,      true,  kUP,     kNonsense, UNSPECIFIED},
    {  false,   false,   UV_REQ,      true,  kUV,     kNotAllow, UNSPECIFIED},
    {  false,   true,    UNSPECIFIED, false, kUP,     kOk,       NONE},
    {  false,   true,    UNSPECIFIED, true,  kUP,     kNonsense, UNSPECIFIED},
    {  false,   true,    NONE,        false, kUP,     kOk,       NONE},
    {  false,   true,    NONE,        true,  kUP,     kNonsense, UNSPECIFIED},
    {  false,   true,    UV_OR_CRED,  false, kUP,     kOk,       NONE},
    {  false,   true,    UV_OR_CRED,  true,  kUP,     kNotAllow, UNSPECIFIED},
    {  false,   true,    UV_REQ,      false, kUP,     kNonsense, UNSPECIFIED},
    {  false,   true,    UV_REQ,      false, kUV,     kOk,       NONE},
    {  false,   true,    UV_REQ,      true,  kUP,     kNonsense, UNSPECIFIED},
    {  false,   true,    UV_REQ,      true,  kUV,     kNotAllow, UNSPECIFIED},

    // For the case where the authenticator supports credProtect we do not
    // repeat the cases above that are |kNonsense| on the assumption that
    // authenticator support is irrelevant. Therefore these are just the non-
    // kNonsense cases from the prior block.
    {  true,    false,   UNSPECIFIED, false, kUP,     kOk,       NONE},
    {  true,    false,   UV_OR_CRED,  false, kUP,     kOk,       UV_OR_CRED},
    {  true,    false,   UV_OR_CRED,  true,  kUP,     kOk,       UV_OR_CRED},
    {  true,    false,   UV_OR_CRED,  false, kUV,     kOk,       UV_OR_CRED},
    {  true,    false,   UV_OR_CRED,  true,  kUV,     kOk,       UV_OR_CRED},
    {  true,    false,   UV_REQ,      false, kUV,     kOk,       UV_REQ},
    {  true,    false,   UV_REQ,      true,  kUV,     kOk,       UV_REQ},
    {  true,    true,    UNSPECIFIED, false, kUP,     kOk,       UV_OR_CRED},
    {  true,    true,    UNSPECIFIED, false, kUVPref, kOk,       UV_REQ},
    {  true,    true,    NONE,        false, kUP,     kOk,       NONE},
    {  true,    true,    NONE,        false, kUVPref, kOk,       NONE},
    {  true,    true,    UV_OR_CRED,  false, kUP,     kOk,       UV_OR_CRED},
    {  true,    true,    UV_OR_CRED,  true,  kUP,     kOk,       UV_OR_CRED},
    {  true,    true,    UV_OR_CRED,  false, kUVPref, kOk,       UV_OR_CRED},
    {  true,    true,    UV_REQ,      false, kUV,     kOk,       UV_REQ},
    {  true,    true,    UV_REQ,      true,  kUV,     kOk,       UV_REQ},
      // clang-format on
  };

  for (const auto& test : kExpectations) {
    device::VirtualCtap2Device::Config config;
    config.pin_support = true;
    config.resident_key_support = true;
    config.cred_protect_support = test.supported_by_authenticator;
    virtual_device_factory_->SetCtap2Config(config);
    virtual_device_factory_->mutable_state()->registrations.clear();

    SCOPED_TRACE(::testing::Message() << "uv=" << UVToString(test.uv));
    SCOPED_TRACE(::testing::Message() << "enforce=" << test.enforce);
    SCOPED_TRACE(::testing::Message()
                 << "level=" << ProtectionPolicyDescription(test.protection));
    SCOPED_TRACE(::testing::Message() << "resident=" << test.is_resident);
    SCOPED_TRACE(::testing::Message()
                 << "support=" << test.supported_by_authenticator);

    PublicKeyCredentialCreationOptionsPtr options = make_credential_options();
    options->authenticator_selection->resident_key =
        test.is_resident ? device::ResidentKeyRequirement::kRequired
                         : device::ResidentKeyRequirement::kDiscouraged;
    options->protection_policy = test.protection;
    options->enforce_protection_policy = test.enforce;
    options->authenticator_selection->user_verification_requirement = test.uv;

    AuthenticatorStatus status =
        AuthenticatorMakeCredential(std::move(options)).status;

    switch (test.expected_outcome) {
      case kOk: {
        EXPECT_EQ(AuthenticatorStatus::SUCCESS, status);
        ASSERT_EQ(
            1u, virtual_device_factory_->mutable_state()->registrations.size());
        const device::CredProtect result =
            virtual_device_factory_->mutable_state()
                ->registrations.begin()
                ->second.protection;

        switch (test.resulting_policy) {
          case UNSPECIFIED:
            NOTREACHED();
          case NONE:
            EXPECT_EQ(device::CredProtect::kUVOptional, result);
            break;
          case UV_OR_CRED:
            EXPECT_EQ(device::CredProtect::kUVOrCredIDRequired, result);
            break;
          case UV_REQ:
            EXPECT_EQ(device::CredProtect::kUVRequired, result);
            break;
        }
        break;
      }
      case kNonsense:
        EXPECT_EQ(AuthenticatorStatus::PROTECTION_POLICY_INCONSISTENT, status);
        break;
      case kNotAllow:
        EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, status);
        break;
      default:
        NOTREACHED();
    }
  }
}

TEST_F(ResidentKeyAuthenticatorImplTest, AuthenticatorSetsCredProtect) {
  // Some authenticators are expected to set the credProtect extension ad
  // libitum. Therefore we should only require that the returned extension is at
  // least as restrictive as requested, but perhaps not exactly equal.
  constexpr std::array<blink::mojom::ProtectionPolicy, 3> kMojoLevels = {
      blink::mojom::ProtectionPolicy::NONE,
      blink::mojom::ProtectionPolicy::UV_OR_CRED_ID_REQUIRED,
      blink::mojom::ProtectionPolicy::UV_REQUIRED,
  };
  constexpr std::array<device::CredProtect, 3> kDeviceLevels = {
      device::CredProtect::kUVOptional,
      device::CredProtect::kUVOrCredIDRequired,
      device::CredProtect::kUVRequired,
  };

  for (int requested_level = 0; requested_level < 3; requested_level++) {
    for (int forced_level = 1; forced_level < 3; forced_level++) {
      SCOPED_TRACE(::testing::Message() << "requested=" << requested_level);
      SCOPED_TRACE(::testing::Message() << "forced=" << forced_level);
      device::VirtualCtap2Device::Config config;
      config.pin_support = true;
      config.resident_key_support = true;
      config.cred_protect_support = true;
      config.force_cred_protect = kDeviceLevels[forced_level];
      virtual_device_factory_->SetCtap2Config(config);
      virtual_device_factory_->mutable_state()->registrations.clear();

      PublicKeyCredentialCreationOptionsPtr options = make_credential_options();
      options->authenticator_selection->resident_key =
          device::ResidentKeyRequirement::kRequired;
      options->protection_policy = kMojoLevels[requested_level];
      options->authenticator_selection->user_verification_requirement =
          device::UserVerificationRequirement::kRequired;

      AuthenticatorStatus status =
          AuthenticatorMakeCredential(std::move(options)).status;

      if (requested_level <= forced_level) {
        EXPECT_EQ(AuthenticatorStatus::SUCCESS, status);
        ASSERT_EQ(
            1u, virtual_device_factory_->mutable_state()->registrations.size());
        const std::optional<device::CredProtect> result =
            virtual_device_factory_->mutable_state()
                ->registrations.begin()
                ->second.protection;
        EXPECT_EQ(*result, config.force_cred_protect);
      } else {
        EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, status);
      }
    }
  }
}

TEST_F(ResidentKeyAuthenticatorImplTest, AuthenticatorDefaultCredProtect) {
  // Some authenticators may have a default credProtect level that isn't
  // kUVOptional. This has complex interactions that are tested here.
  constexpr struct {
    blink::mojom::ProtectionPolicy requested_level;
    device::CredProtect authenticator_default;
    device::CredProtect result;
  } kExpectations[] = {
      // Standard case: normal authenticator and nothing specified. Chrome sets
      // a default of kUVOrCredIDRequired for discoverable credentials.
      {
          blink::mojom::ProtectionPolicy::UNSPECIFIED,
          device::CredProtect::kUVOptional,
          device::CredProtect::kUVOrCredIDRequired,
      },
      // Chrome's default of |kUVOrCredIDRequired| should not prevent a site
      // from requesting |kUVRequired| from a normal authenticator.
      {
          blink::mojom::ProtectionPolicy::UV_REQUIRED,
          device::CredProtect::kUVOptional,
          device::CredProtect::kUVRequired,
      },
      // Authenticator has a non-standard default, which should work fine.
      {
          blink::mojom::ProtectionPolicy::UNSPECIFIED,
          device::CredProtect::kUVOrCredIDRequired,
          device::CredProtect::kUVOrCredIDRequired,
      },
      // Authenticators can have a default of kUVRequired, but Chrome has a
      // default of kUVOrCredIDRequired for discoverable credentials. We should
      // not get a lesser protection level because of that.
      {
          blink::mojom::ProtectionPolicy::UNSPECIFIED,
          device::CredProtect::kUVRequired,
          device::CredProtect::kUVRequired,
      },
      // Site should be able to explicitly set credProtect kUVOptional despite
      // an authenticator default.
      {
          blink::mojom::ProtectionPolicy::NONE,
          device::CredProtect::kUVOrCredIDRequired,
          device::CredProtect::kUVOptional,
      },
  };

  device::VirtualCtap2Device::Config config;
  config.pin_support = true;
  config.resident_key_support = true;
  config.cred_protect_support = true;

  for (const auto& test : kExpectations) {
    config.default_cred_protect = test.authenticator_default;
    virtual_device_factory_->SetCtap2Config(config);
    virtual_device_factory_->mutable_state()->registrations.clear();

    SCOPED_TRACE(::testing::Message()
                 << "result=" << CredProtectDescription(test.result));
    SCOPED_TRACE(::testing::Message()
                 << "default="
                 << CredProtectDescription(test.authenticator_default));
    SCOPED_TRACE(::testing::Message()
                 << "request="
                 << ProtectionPolicyDescription(test.requested_level));

    PublicKeyCredentialCreationOptionsPtr options = make_credential_options();
    options->authenticator_selection->resident_key =
        device::ResidentKeyRequirement::kRequired;
    options->protection_policy = test.requested_level;
    options->authenticator_selection->user_verification_requirement =
        device::UserVerificationRequirement::kRequired;

    EXPECT_EQ(AuthenticatorMakeCredential(std::move(options)).status,
              AuthenticatorStatus::SUCCESS);
    ASSERT_EQ(1u,
              virtual_device_factory_->mutable_state()->registrations.size());
    const device::CredProtect result = virtual_device_factory_->mutable_state()
                                           ->registrations.begin()
                                           ->second.protection;

    EXPECT_EQ(result, test.result) << CredProtectDescription(result);
  }
}

TEST_F(ResidentKeyAuthenticatorImplTest, ProtectedNonResidentCreds) {
  // Until we have UVToken, there's a danger that we'll preflight UV-required
  // credential IDs such that the authenticator denies knowledge of all of them
  // for silent requests and then we fail the whole request.
  device::VirtualCtap2Device::Config config;
  config.pin_support = true;
  config.resident_key_support = true;
  config.cred_protect_support = true;
  virtual_device_factory_->SetCtap2Config(config);
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
      /*credential_id=*/{{4, 3, 2, 1}}, kTestRelyingPartyId));
  ASSERT_EQ(1u, virtual_device_factory_->mutable_state()->registrations.size());
  virtual_device_factory_->mutable_state()
      ->registrations.begin()
      ->second.protection = device::CredProtect::kUVRequired;

  // |SelectAccount| should not be called when there's only a single response.
  test_client_.delegate_config.expected_accounts = "<invalid>";

  PublicKeyCredentialRequestOptionsPtr options = get_credential_options();
  options->allow_credentials = GetTestCredentials(5);
  options->allow_credentials[0].id = {4, 3, 2, 1};

  GetAssertionResult result = AuthenticatorGetAssertion(std::move(options));

  EXPECT_EQ(AuthenticatorStatus::SUCCESS, result.status);
  EXPECT_TRUE(HasUV(result.response));
}

TEST_F(ResidentKeyAuthenticatorImplTest, WithAppIDExtension) {
  // Setting an AppID value for a resident-key request should be ignored.
  device::VirtualCtap2Device::Config config;
  config.u2f_support = true;
  config.pin_support = true;
  config.resident_key_support = true;
  config.cred_protect_support = true;
  virtual_device_factory_->SetCtap2Config(config);
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectResidentKey(
      /*credential_id=*/{{4, 3, 2, 1}}, kTestRelyingPartyId,
      /*user_id=*/{{1, 2, 3, 4}}, std::nullopt, std::nullopt));

  // |SelectAccount| should not be called when there's only a single response
  // without identifying information.
  test_client_.delegate_config.expected_accounts = "<invalid>";

  PublicKeyCredentialRequestOptionsPtr options = get_credential_options();
  options->extensions->appid = kTestOrigin1;

  GetAssertionResult result = AuthenticatorGetAssertion(std::move(options));

  EXPECT_EQ(AuthenticatorStatus::SUCCESS, result.status);
  EXPECT_TRUE(HasUV(result.response));
}

#if BUILDFLAG(IS_WIN)
// Requests with a credProtect extension that have |enforce_protection_policy|
// set should be rejected if the Windows WebAuthn API doesn't support
// credProtect.
TEST_F(ResidentKeyAuthenticatorImplTest, WinCredProtectApiVersion) {
  // The canned response returned by the Windows API fake is for acme.com.
  virtual_device_factory_->set_discover_win_webauthn_api_authenticator(true);
  fake_win_webauthn_api_.set_available(true);
  NavigateAndCommit(GURL("https://acme.com"));
  for (const bool supports_cred_protect : {false, true}) {
    SCOPED_TRACE(testing::Message()
                 << "supports_cred_protect: " << supports_cred_protect);

    fake_win_webauthn_api_.set_version(supports_cred_protect
                                           ? WEBAUTHN_API_VERSION_2
                                           : WEBAUTHN_API_VERSION_1);

    PublicKeyCredentialCreationOptionsPtr options = make_credential_options();
    options->relying_party = device::PublicKeyCredentialRpEntity();
    options->relying_party.id = device::test_data::kRelyingPartyId;
    options->relying_party.name = "";
    options->authenticator_selection->user_verification_requirement =
        device::UserVerificationRequirement::kRequired;
    options->authenticator_selection->resident_key =
        device::ResidentKeyRequirement::kRequired;
    options->protection_policy =
        blink::mojom::ProtectionPolicy::UV_OR_CRED_ID_REQUIRED;
    options->enforce_protection_policy = true;

    EXPECT_EQ(AuthenticatorMakeCredential(std::move(options)).status,
              supports_cred_protect ? AuthenticatorStatus::SUCCESS
                                    : AuthenticatorStatus::NOT_ALLOWED_ERROR);
  }
}

// Tests that the incognito flag is plumbed through conditional UI requests.
TEST_F(ResidentKeyAuthenticatorImplTest, ConditionalUI_Incognito) {
  virtual_device_factory_->set_discover_win_webauthn_api_authenticator(true);
  fake_win_webauthn_api_.set_available(true);
  fake_win_webauthn_api_.set_version(WEBAUTHN_API_VERSION_4);
  fake_win_webauthn_api_.set_supports_silent_discovery(true);
  device::PublicKeyCredentialRpEntity rp(kTestRelyingPartyId);
  device::PublicKeyCredentialUserEntity user({1, 2, 3, 4});
  fake_win_webauthn_api_.InjectDiscoverableCredential(
      /*credential_id=*/{{4, 3, 2, 1}}, std::move(rp), std::move(user),
      /*provider_name=*/std::nullopt);

  // |SelectAccount| should not be called for conditional UI requests.
  test_client_.delegate_config.expected_accounts = "<invalid>";
  test_client_.delegate_config.expect_conditional = true;

  for (bool is_off_the_record : {true, false}) {
    SCOPED_TRACE(is_off_the_record ? "off the record" : "on the record");
    static_cast<TestBrowserContext*>(GetBrowserContext())
        ->set_is_off_the_record(is_off_the_record);
    auto options = GetCredentialOptions::New();
    PublicKeyCredentialRequestOptionsPtr public_key(get_credential_options());
    options->mediation = blink::mojom::Mediation::CONDITIONAL;
    options->public_key = std::move(public_key);
    GetAssertionResult result = AuthenticatorGetCredential(std::move(options));
    EXPECT_EQ(AuthenticatorStatus::SUCCESS, result.status);
    ASSERT_TRUE(fake_win_webauthn_api_.last_get_credentials_options());
    EXPECT_EQ(fake_win_webauthn_api_.last_get_credentials_options()
                  ->bBrowserInPrivateMode,
              is_off_the_record);
  }
}

// Tests that attempting to make a credential with large blob = required and
// attachment = platform on Windows fails and the request is not sent to the
// WebAuthn API.
// This is because largeBlob = required is ignored by the Windows platform
// authenticator at the time of writing (Feb 2023).
TEST_F(ResidentKeyAuthenticatorImplTest, MakeCredentialLargeBlobWinPlatform) {
  virtual_device_factory_->set_discover_win_webauthn_api_authenticator(true);
  fake_win_webauthn_api_.set_available(true);
  fake_win_webauthn_api_.set_version(WEBAUTHN_API_VERSION_3);
  PublicKeyCredentialCreationOptionsPtr options =
      GetTestPublicKeyCredentialCreationOptions();
  options->large_blob_enable = device::LargeBlobSupport::kRequired;
  options->authenticator_selection->resident_key =
      device::ResidentKeyRequirement::kRequired;
  options->authenticator_selection->authenticator_attachment =
      device::AuthenticatorAttachment::kPlatform;
  MakeCredentialResult result = AuthenticatorMakeCredential(std::move(options));
  EXPECT_EQ(result.status, AuthenticatorStatus::NOT_ALLOWED_ERROR);
  EXPECT_FALSE(fake_win_webauthn_api_.last_make_credential_options());
}

// Tests that attempting to make a credential with large blob = preferred does
// not fail the request on Windows.
// Regression test for crbug.com/325934997.
TEST_F(ResidentKeyAuthenticatorImplTest, MakeCredentialLargeBlobWinPreferred) {
  virtual_device_factory_->set_discover_win_webauthn_api_authenticator(true);
  fake_win_webauthn_api_.set_available(true);
  fake_win_webauthn_api_.set_version(WEBAUTHN_API_VERSION_3);
  for (bool large_blob_supported : {false, true}) {
    fake_win_webauthn_api_.set_large_blob_supported(large_blob_supported);
    SCOPED_TRACE(large_blob_supported);
    PublicKeyCredentialCreationOptionsPtr options =
        GetTestPublicKeyCredentialCreationOptions();
    options->large_blob_enable = device::LargeBlobSupport::kPreferred;
    options->authenticator_selection->resident_key =
        device::ResidentKeyRequirement::kRequired;
    options->authenticator_selection->authenticator_attachment =
        device::AuthenticatorAttachment::kCrossPlatform;
    MakeCredentialResult result =
        AuthenticatorMakeCredential(std::move(options));
    ASSERT_EQ(result.status, AuthenticatorStatus::SUCCESS);
    EXPECT_TRUE(result.response->echo_large_blob);
    EXPECT_EQ(result.response->supports_large_blob, large_blob_supported);
  }
}

// Tests that the AAGUID is not zeroed out for Windows Hello on Windows versions
// where Chrome can learn the transport used.
// Regression test for crbug.com/446157740.
TEST_F(ResidentKeyAuthenticatorImplTest,
       WinPlatformAuthenticatorAttestationAAGUID) {
  enum Test {
    kWindowsReportsUsb,
    kWindowsReportsInternal,
    kWindowsDoesNotReportTransport
  };
  virtual_device_factory_->set_discover_win_webauthn_api_authenticator(true);
  fake_win_webauthn_api_.set_available(true);
  for (Test test : {kWindowsReportsUsb, kWindowsReportsInternal,
                    kWindowsDoesNotReportTransport}) {
    SCOPED_TRACE(test);
    fake_win_webauthn_api_.set_version(test == kWindowsDoesNotReportTransport
                                           ? WEBAUTHN_API_VERSION_5
                                           : WEBAUTHN_API_VERSION_6);
    fake_win_webauthn_api_.set_transport(test == kWindowsReportsInternal
                                             ? WEBAUTHN_CTAP_TRANSPORT_INTERNAL
                                             : WEBAUTHN_CTAP_TRANSPORT_USB);
    PublicKeyCredentialCreationOptionsPtr options =
        GetTestPublicKeyCredentialCreationOptions();
    MakeCredentialResult result =
        AuthenticatorMakeCredential(std::move(options));
    ASSERT_EQ(result.status, AuthenticatorStatus::SUCCESS);

    const device::AuthenticatorData auth_data =
        AuthDataFromMakeCredentialResponse(result.response);

    std::optional<Value> attestation_value =
        Reader::Read(result.response->attestation_object);
    ASSERT_TRUE(attestation_value);
    ASSERT_TRUE(attestation_value->is_map());
    if (test == kWindowsReportsInternal) {
      EXPECT_EQ(auth_data.attested_data()->aaguid(),
                device::FakeWinWebAuthnApi::kTestWindowsAaguid);
    } else {
      EXPECT_TRUE(auth_data.attested_data()->IsAaguidZero());
    }
  }
}
#endif  // BUILDFLAG(IS_WIN)

// Tests that chrome does not attempt setting the PRF extension during a
// PinUvAuthToken GetAssertion request if it is not supported by the
// authenticator.
// Regression test for crbug.com/1408786.
TEST_F(ResidentKeyAuthenticatorImplTest, PRFNotSupportedWithPinUvAuthToken) {
  NavigateAndCommit(GURL(kTestOrigin1));

  device::VirtualCtap2Device::Config config;
  config.resident_key_support = true;
  config.u2f_support = true;
  config.pin_support = true;
  config.pin_uv_auth_token_support = true;
  config.hmac_secret_support = false;
  config.ctap2_versions = {device::Ctap2Version::kCtap2_1};
  virtual_device_factory_->mutable_state()->pin = kTestPIN;
  virtual_device_factory_->mutable_state()->pin_retries =
      device::kMaxPinRetries;
  virtual_device_factory_->SetCtap2Config(config);

  PublicKeyCredentialRequestOptionsPtr options =
      GetTestPublicKeyCredentialRequestOptions();
  options->user_verification = device::UserVerificationRequirement::kRequired;
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectResidentKey(
      options->allow_credentials[0].id, options->relying_party_id,
      std::vector<uint8_t>{1, 2, 3, 4}, std::nullopt, std::nullopt));

  auto prf_value = blink::mojom::PRFValues::New();
  prf_value->first = std::vector<uint8_t>(32, 1);
  std::vector<blink::mojom::PRFValuesPtr> inputs;
  inputs.emplace_back(std::move(prf_value));
  options->extensions->prf = true;
  options->extensions->prf_inputs = std::move(inputs);
  options->allow_credentials.clear();
  EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
            AuthenticatorStatus::SUCCESS);
}

TEST_F(ResidentKeyAuthenticatorImplTest, PRFExtension) {
  NavigateAndCommit(GURL(kTestOrigin1));

  for (bool use_prf_extension_instead : {false, true}) {
    for (const auto pin_protocol :
         {device::PINUVAuthProtocol::kV1, device::PINUVAuthProtocol::kV2}) {
      SCOPED_TRACE(use_prf_extension_instead);
      SCOPED_TRACE(static_cast<unsigned>(pin_protocol));

      std::optional<device::PublicKeyCredentialDescriptor> credential;
      for (bool authenticator_support : {false, true}) {
        // Setting the PRF extension on an authenticator that doesn't support it
        // should cause the extension to be echoed, but with enabled=false.
        // Otherwise, enabled should be true.
        device::VirtualCtap2Device::Config config;
        if (authenticator_support) {
          config.prf_support = use_prf_extension_instead;
          config.hmac_secret_support = !use_prf_extension_instead;
        }
        config.internal_account_chooser = config.prf_support;
        config.always_uv = config.prf_support;
        config.max_credential_count_in_list = 3;
        config.max_credential_id_length = 256;
        config.pin_support = true;
        config.pin_protocol = pin_protocol;
        config.resident_key_support = true;
        virtual_device_factory_->SetCtap2Config(config);

        PublicKeyCredentialCreationOptionsPtr options =
            GetTestPublicKeyCredentialCreationOptions();
        options->prf_enable = true;
        options->authenticator_selection->resident_key =
            authenticator_support
                ? device::ResidentKeyRequirement::kRequired
                : device::ResidentKeyRequirement::kDiscouraged;
        options->user.id = {1, 2, 3, 4};
        options->user.name = "name";
        options->user.display_name = "displayName";
        MakeCredentialResult result =
            AuthenticatorMakeCredential(std::move(options));
        EXPECT_EQ(result.status, AuthenticatorStatus::SUCCESS);

        ASSERT_TRUE(result.response->echo_prf);
        ASSERT_EQ(result.response->prf, authenticator_support);

        if (authenticator_support) {
          device::AuthenticatorData auth_data =
              AuthDataFromMakeCredentialResponse(result.response);
          credential.emplace(device::CredentialType::kPublicKey,
                             auth_data.GetCredentialId());
        }
      }

      auto assertion = [&](std::vector<blink::mojom::PRFValuesPtr> inputs,
                           unsigned allow_list_size = 1,
                           device::UserVerificationRequirement uv =
                               device::UserVerificationRequirement::kPreferred)
          -> blink::mojom::PRFValuesPtr {
        PublicKeyCredentialRequestOptionsPtr options =
            GetTestPublicKeyCredentialRequestOptions();
        options->extensions->prf = true;
        options->extensions->prf_inputs = std::move(inputs);
        options->allow_credentials.clear();
        options->user_verification = uv;
        if (allow_list_size >= 1) {
          for (unsigned i = 0; i < allow_list_size - 1; i++) {
            std::vector<uint8_t> random_credential_id(32,
                                                      static_cast<uint8_t>(i));
            options->allow_credentials.emplace_back(
                device::CredentialType::kPublicKey,
                std::move(random_credential_id));
          }
          options->allow_credentials.push_back(*credential);
        }

        GetAssertionResult result =
            AuthenticatorGetAssertion(std::move(options));

        EXPECT_EQ(result.status, AuthenticatorStatus::SUCCESS);
        CHECK(result.response->extensions->prf_results);
        CHECK(!result.response->extensions->prf_results->id);
        return std::move(result.response->extensions->prf_results);
      };

      const std::vector<uint8_t> salt1(32, 1);
      const std::vector<uint8_t> salt2(32, 2);
      std::vector<uint8_t> salt1_eval;
      std::vector<uint8_t> salt2_eval;

      {
        auto prf_value = blink::mojom::PRFValues::New();
        prf_value->first = salt1;
        std::vector<blink::mojom::PRFValuesPtr> inputs;
        inputs.emplace_back(std::move(prf_value));
        auto result = assertion(std::move(inputs));
        salt1_eval = std::move(result->first);
      }

      // The result should be consistent
      {
        auto prf_value = blink::mojom::PRFValues::New();
        prf_value->first = salt1;
        std::vector<blink::mojom::PRFValuesPtr> inputs;
        inputs.emplace_back(std::move(prf_value));
        auto result = assertion(std::move(inputs));
        ASSERT_EQ(result->first, salt1_eval);
      }

      // Security keys will use a different PRF if UV isn't done. But the PRF
      // extension should always get the UV PRF so uv=discouraged shouldn't
      // change the output.
      {
        auto prf_value = blink::mojom::PRFValues::New();
        prf_value->first = salt1;
        std::vector<blink::mojom::PRFValuesPtr> inputs;
        inputs.emplace_back(std::move(prf_value));
        auto result =
            assertion(std::move(inputs), 1,
                      device::UserVerificationRequirement::kDiscouraged);
        ASSERT_EQ(result->first, salt1_eval);
      }

      // Should be able to evaluate two points at once.
      {
        auto prf_value = blink::mojom::PRFValues::New();
        prf_value->first = salt1;
        prf_value->second = salt2;
        std::vector<blink::mojom::PRFValuesPtr> inputs;
        inputs.emplace_back(std::move(prf_value));
        auto result = assertion(std::move(inputs));
        ASSERT_EQ(result->first, salt1_eval);
        ASSERT_TRUE(result->second);
        salt2_eval = std::move(*result->second);
        ASSERT_NE(salt1_eval, salt2_eval);
      }

      // Should be consistent if swapped.
      {
        auto prf_value = blink::mojom::PRFValues::New();
        prf_value->first = salt2;
        prf_value->second = salt1;
        std::vector<blink::mojom::PRFValuesPtr> inputs;
        inputs.emplace_back(std::move(prf_value));
        auto result = assertion(std::move(inputs));
        ASSERT_EQ(result->first, salt2_eval);
        ASSERT_TRUE(result->second);
        ASSERT_EQ(*result->second, salt1_eval);
      }

      // Should still trigger if the credential ID is specified
      {
        auto prf_value = blink::mojom::PRFValues::New();
        prf_value->id.emplace(credential->id);
        prf_value->first = salt1;
        prf_value->second = salt2;
        std::vector<blink::mojom::PRFValuesPtr> inputs;
        inputs.emplace_back(std::move(prf_value));
        auto result = assertion(std::move(inputs));
        ASSERT_EQ(result->first, salt1_eval);
        ASSERT_TRUE(result->second);
        ASSERT_EQ(*result->second, salt2_eval);
      }

      // And the specified credential ID should override any default inputs.
      {
        auto prf_value1 = blink::mojom::PRFValues::New();
        prf_value1->first = std::vector<uint8_t>(32, 3);
        auto prf_value2 = blink::mojom::PRFValues::New();
        prf_value2->id.emplace(credential->id);
        prf_value2->first = salt1;
        prf_value2->second = salt2;
        std::vector<blink::mojom::PRFValuesPtr> inputs;
        inputs.emplace_back(std::move(prf_value1));
        inputs.emplace_back(std::move(prf_value2));
        auto result = assertion(std::move(inputs));
        ASSERT_EQ(result->first, salt1_eval);
        ASSERT_TRUE(result->second);
        ASSERT_EQ(*result->second, salt2_eval);
      }

      // ... and that should still be true if there there are lots of dummy
      // entries in the allowlist. Note that the virtual authenticator was
      // configured such that this will cause multiple batches.
      {
        auto prf_value = blink::mojom::PRFValues::New();
        prf_value->id.emplace(credential->id);
        prf_value->first = salt1;
        prf_value->second = salt2;
        std::vector<blink::mojom::PRFValuesPtr> inputs;
        inputs.emplace_back(std::move(prf_value));
        auto result = assertion(std::move(inputs), /*allowlist_size=*/20);
        ASSERT_EQ(result->first, salt1_eval);
        ASSERT_TRUE(result->second);
        ASSERT_EQ(*result->second, salt2_eval);
      }

      // Default PRF values should be passed down when the allowlist is empty.
      {
        auto prf_value = blink::mojom::PRFValues::New();
        prf_value->first = salt1;
        prf_value->second = salt2;
        test_client_.delegate_config.expected_accounts =
            "01020304:name:displayName";
        test_client_.delegate_config.selected_user_id = {1, 2, 3, 4};
        std::vector<blink::mojom::PRFValuesPtr> inputs;
        inputs.emplace_back(std::move(prf_value));
        auto result = assertion(std::move(inputs), /*allowlist_size=*/0);
        ASSERT_EQ(result->first, salt1_eval);
        ASSERT_TRUE(result->second);
        ASSERT_EQ(*result->second, salt2_eval);
      }

      // And the default PRF values should be used if none of the specific
      // values match.
      {
        auto prf_value1 = blink::mojom::PRFValues::New();
        prf_value1->first = salt1;
        auto prf_value2 = blink::mojom::PRFValues::New();
        prf_value2->first = std::vector<uint8_t>(32, 3);
        prf_value2->id = std::vector<uint8_t>(32, 4);
        std::vector<blink::mojom::PRFValuesPtr> inputs;
        inputs.emplace_back(std::move(prf_value1));
        inputs.emplace_back(std::move(prf_value2));
        auto result = assertion(std::move(inputs), /*allowlist_size=*/20);
        ASSERT_EQ(result->first, salt1_eval);
        ASSERT_FALSE(result->second);
      }
    }
  }
}

// Tests that the PRF function is evaluated for all credentials in an empty
// allow-list request. Regression test for crbug.com/1520646.
TEST_F(ResidentKeyAuthenticatorImplTest, PRFEvaluationForMultipleCreds) {
  NavigateAndCommit(GURL(kTestOrigin1));
  device::PublicKeyCredentialDescriptor cred1;
  device::PublicKeyCredentialDescriptor cred2;
  device::VirtualCtap2Device::Config config;
  config.prf_support = false;
  config.hmac_secret_support = true;
  config.pin_support = true;
  config.resident_key_support = true;
  virtual_device_factory_->SetCtap2Config(config);
  {
    PublicKeyCredentialCreationOptionsPtr options =
        GetTestPublicKeyCredentialCreationOptions();
    options->prf_enable = true;
    options->authenticator_selection->resident_key =
        device::ResidentKeyRequirement::kRequired;
    options->user.id = {1};
    options->user.name = "noah";
    options->user.display_name = "Noah";
    MakeCredentialResult result =
        AuthenticatorMakeCredential(std::move(options));
    EXPECT_EQ(result.status, AuthenticatorStatus::SUCCESS);
    ASSERT_TRUE(result.response->echo_prf);
    ASSERT_EQ(result.response->prf, true);
    device::AuthenticatorData auth_data =
        AuthDataFromMakeCredentialResponse(result.response);
    cred1 = device::PublicKeyCredentialDescriptor(
        device::CredentialType::kPublicKey, auth_data.GetCredentialId());
  }
  {
    PublicKeyCredentialCreationOptionsPtr options =
        GetTestPublicKeyCredentialCreationOptions();
    options->prf_enable = true;
    options->authenticator_selection->resident_key =
        device::ResidentKeyRequirement::kRequired;
    options->user.id = {2};
    options->user.name = "mio";
    options->user.display_name = "Mio";
    MakeCredentialResult result =
        AuthenticatorMakeCredential(std::move(options));
    EXPECT_EQ(result.status, AuthenticatorStatus::SUCCESS);
    ASSERT_TRUE(result.response->echo_prf);
    ASSERT_EQ(result.response->prf, true);
    device::AuthenticatorData auth_data =
        AuthDataFromMakeCredentialResponse(result.response);
    cred2 = device::PublicKeyCredentialDescriptor(
        device::CredentialType::kPublicKey, auth_data.GetCredentialId());
  }

  const std::vector<uint8_t> salt(32, 1);
  std::vector<uint8_t> salt1_eval;
  std::vector<uint8_t> salt2_eval;
  {
    PublicKeyCredentialRequestOptionsPtr options =
        GetTestPublicKeyCredentialRequestOptions();
    options->extensions->prf = true;
    auto prf_value = blink::mojom::PRFValues::New();
    prf_value->first = salt;
    std::vector<blink::mojom::PRFValuesPtr> inputs;
    inputs.emplace_back(std::move(prf_value));
    options->extensions->prf_inputs = std::move(inputs);
    options->allow_credentials.clear();
    test_client_.delegate_config.expected_accounts = "01:noah:Noah/02:mio:Mio";
    test_client_.delegate_config.selected_user_id = {1};
    GetAssertionResult result = AuthenticatorGetAssertion(std::move(options));
    EXPECT_EQ(result.status, AuthenticatorStatus::SUCCESS);
    ASSERT_TRUE(result.response->extensions->prf_results);
    ASSERT_FALSE(result.response->extensions->prf_results->id);
    salt1_eval = result.response->extensions->prf_results->first;
  }
  {
    PublicKeyCredentialRequestOptionsPtr options =
        GetTestPublicKeyCredentialRequestOptions();
    options->extensions->prf = true;
    auto prf_value = blink::mojom::PRFValues::New();
    prf_value->first = salt;
    std::vector<blink::mojom::PRFValuesPtr> inputs;
    inputs.emplace_back(std::move(prf_value));
    options->extensions->prf_inputs = std::move(inputs);
    options->allow_credentials.clear();
    test_client_.delegate_config.expected_accounts = "01:noah:Noah/02:mio:Mio";
    test_client_.delegate_config.selected_user_id = {2};
    GetAssertionResult result = AuthenticatorGetAssertion(std::move(options));
    EXPECT_EQ(result.status, AuthenticatorStatus::SUCCESS);
    ASSERT_TRUE(result.response->extensions->prf_results);
    ASSERT_FALSE(result.response->extensions->prf_results->id);
    salt2_eval = result.response->extensions->prf_results->first;
  }
  EXPECT_NE(salt1_eval, salt2_eval);
}

TEST_F(ResidentKeyAuthenticatorImplTest, PRFEvaluationDuringMakeCredential) {
  // The WebAuthn "prf" extension supports evaluating the PRF when making a
  // credential. The hmac-secret extension does not support this, but hybrid
  // devices (and our virtual authenticator) can support it using the
  // CTAP2-level "prf" extension.
  NavigateAndCommit(GURL(kTestOrigin1));

  device::VirtualCtap2Device::Config config;
  config.prf_support = true;
  config.internal_account_chooser = true;
  config.always_uv = true;
  config.pin_support = true;
  config.resident_key_support = true;
  virtual_device_factory_->SetCtap2Config(config);

  PublicKeyCredentialCreationOptionsPtr options =
      GetTestPublicKeyCredentialCreationOptions();
  options->prf_enable = true;
  options->authenticator_selection->resident_key =
      device::ResidentKeyRequirement::kRequired;
  options->user.id = {1, 2, 3, 4};
  options->user.name = "name";
  options->user.display_name = "displayName";
  options->prf_input = blink::mojom::PRFValues::New();
  const std::vector<uint8_t> salt1(32, 1);
  const std::vector<uint8_t> salt2(32, 2);
  options->prf_input->first = salt1;
  options->prf_input->second = salt2;

  MakeCredentialResult result = AuthenticatorMakeCredential(std::move(options));
  EXPECT_EQ(result.status, AuthenticatorStatus::SUCCESS);

  EXPECT_TRUE(result.response->echo_prf);
  EXPECT_TRUE(result.response->prf);
  ASSERT_TRUE(result.response->prf_results);
  EXPECT_EQ(result.response->prf_results->first.size(), 32u);
  EXPECT_EQ(result.response->prf_results->second->size(), 32u);
}

TEST_F(ResidentKeyAuthenticatorImplTest, MakeCredentialPRFExtension) {
  NavigateAndCommit(GURL(kTestOrigin1));
}

TEST_F(ResidentKeyAuthenticatorImplTest,
       PRFExtensionOnUnconfiguredAuthenticator) {
  // If a credential is on a UV-capable, but not UV-configured authenticator and
  // then an assertion with `prf` is requested there shouldn't be a result
  // because it would be from the wrong PRF. (This state should only happen when
  // the credential was created without the `prf` extension, which is an RP
  // issue.)
  device::VirtualCtap2Device::Config config;
  config.hmac_secret_support = true;
  config.internal_uv_support = true;
  config.pin_uv_auth_token_support = true;
  config.ctap2_versions = {device::Ctap2Version::kCtap2_1};
  config.resident_key_support = true;
  virtual_device_factory_->SetCtap2Config(config);

  PublicKeyCredentialRequestOptionsPtr options =
      GetTestPublicKeyCredentialRequestOptions();
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectResidentKey(
      options->allow_credentials[0].id, kTestRelyingPartyId,
      /*user_id=*/{{1, 2, 3, 4}}, std::nullopt, std::nullopt));
  device::VirtualFidoDevice::RegistrationData& registration =
      virtual_device_factory_->mutable_state()->registrations.begin()->second;
  const std::array<uint8_t, 32> key1 = {1};
  const std::array<uint8_t, 32> key2 = {2};
  registration.hmac_key.emplace(key1, key2);

  auto prf_value = blink::mojom::PRFValues::New();
  const std::vector<uint8_t> salt1(32, 1);
  prf_value->first = salt1;
  std::vector<blink::mojom::PRFValuesPtr> inputs;
  inputs.emplace_back(std::move(prf_value));

  options->extensions->prf = true;
  options->extensions->prf_inputs = std::move(inputs);
  options->user_verification =
      device::UserVerificationRequirement::kDiscouraged;
  GetAssertionResult result = AuthenticatorGetAssertion(std::move(options));

  EXPECT_EQ(result.status, AuthenticatorStatus::SUCCESS);
  EXPECT_FALSE(result.response->extensions->prf_results);
}

TEST_F(ResidentKeyAuthenticatorImplTest, ConditionalUI) {
  device::VirtualCtap2Device::Config config;
  config.resident_key_support = true;
  config.internal_uv_support = true;
  virtual_device_factory_->SetCtap2Config(config);
  virtual_device_factory_->mutable_state()->fingerprints_enrolled = true;

  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectResidentKey(
      /*credential_id=*/{{4, 3, 2, 1}}, kTestRelyingPartyId,
      /*user_id=*/{{1, 2, 3, 4}}, std::nullopt, std::nullopt));

  // |SelectAccount| should not be called for conditional UI requests.
  test_client_.delegate_config.expected_accounts = "<invalid>";
  test_client_.delegate_config.expect_conditional = true;
  auto options = GetCredentialOptions::New();
  PublicKeyCredentialRequestOptionsPtr public_key(get_credential_options());
  options->mediation = blink::mojom::Mediation::CONDITIONAL;
  options->public_key = std::move(public_key);
  GetAssertionResult result = AuthenticatorGetCredential(std::move(options));
  EXPECT_EQ(AuthenticatorStatus::SUCCESS, result.status);
  VerifyGetAssertionOutcomeUkm(0, GetAssertionOutcome::kSuccess,
                               AuthenticationRequestMode::kConditional);
}

// Tests that the AuthenticatorRequestDelegate can choose a known platform
// authentictor credential as "preselected", which causes the request to be
// specialized to the chosen credential ID and post-request account selection UI
// to be skipped.
TEST_F(ResidentKeyAuthenticatorImplTest, PreselectDiscoverableCredential) {
  virtual_device_factory_->SetTransport(
      device::FidoTransportProtocol::kInternal);
  virtual_device_factory_->mutable_state()->fingerprints_enrolled = true;
  constexpr char kAuthenticatorId[] = "internal-authenticator";
  virtual_device_factory_->mutable_state()->device_id_override =
      kAuthenticatorId;
  std::vector<uint8_t> kFirstCredentialId{{1, 2, 3, 4}};
  std::vector<uint8_t> kSecondCredentialId{{10, 20, 30, 40}};
  std::vector<uint8_t> kFirstUserId{{2, 3, 4, 5}};
  std::vector<uint8_t> kSecondUserId{{20, 30, 40, 50}};

  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectResidentKey(
      kFirstCredentialId, kTestRelyingPartyId, kFirstUserId, std::nullopt,
      std::nullopt));
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectResidentKey(
      kSecondCredentialId, kTestRelyingPartyId, kSecondUserId, std::nullopt,
      std::nullopt));
  for (bool has_pin_uv_auth_token : {false, true}) {
    SCOPED_TRACE(has_pin_uv_auth_token);
    device::VirtualCtap2Device::Config config;
    config.pin_uv_auth_token_support = has_pin_uv_auth_token;
    config.ctap2_versions = {device::Ctap2Version::kCtap2_1};
    config.resident_key_support = true;
    config.internal_uv_support = true;
    virtual_device_factory_->SetCtap2Config(std::move(config));

    // |SelectAccount| should not be called if an account was chosen from
    // pre-select UI.
    test_client_.delegate_config.expected_accounts = "<invalid>";

    for (const auto& id : {kFirstCredentialId, kSecondCredentialId}) {
      test_client_.delegate_config.preselected_credential_id = id;
      test_client_.delegate_config.preselected_authenticator_id =
          kAuthenticatorId;
      PublicKeyCredentialRequestOptionsPtr options(get_credential_options());
      GetAssertionResult result = AuthenticatorGetAssertion(std::move(options));
      EXPECT_EQ(result.status, AuthenticatorStatus::SUCCESS);
      EXPECT_EQ(result.response->info->raw_id, id);
    }
  }
}

// Tests that preselecting a credential sets the response user entity to that of
// the credential metadata if it is not present in the response.
// Regression test for crbug.com/329412574.
TEST_F(ResidentKeyAuthenticatorImplTest, PreselectCredentialUserEntity) {
  device::VirtualCtap2Device::Config config;
  config.resident_key_support = true;
  config.internal_uv_support = true;
  config.omit_user_entity_on_allow_credentials_requests = true;
  virtual_device_factory_->SetCtap2Config(config);
  virtual_device_factory_->SetTransport(
      device::FidoTransportProtocol::kInternal);
  virtual_device_factory_->mutable_state()->fingerprints_enrolled = true;
  constexpr char kAuthenticatorId[] = "internal-authenticator";
  virtual_device_factory_->mutable_state()->device_id_override =
      kAuthenticatorId;
  std::vector<uint8_t> kCredId{{1, 2, 3, 4}};
  std::vector<uint8_t> kUserId{{5, 6, 7, 8}};

  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectResidentKey(
      kCredId, kTestRelyingPartyId, kUserId, std::nullopt, std::nullopt));

  // |SelectAccount| should not be called if an account was chosen from
  // pre-select UI.
  test_client_.delegate_config.expected_accounts = "<invalid>";

  test_client_.delegate_config.preselected_credential_id = kCredId;
  test_client_.delegate_config.preselected_authenticator_id = kAuthenticatorId;
  PublicKeyCredentialRequestOptionsPtr options(get_credential_options());
  GetAssertionResult result = AuthenticatorGetAssertion(std::move(options));
  EXPECT_EQ(result.status, AuthenticatorStatus::SUCCESS);
  EXPECT_EQ(result.response->info->raw_id, kCredId);
  EXPECT_EQ(result.response->user_handle, kUserId);
}

#if BUILDFLAG(IS_MAC)
class TouchIdAuthenticatorImplTest : public AuthenticatorImplTest {
 protected:
  using Credential = device::fido::mac::Credential;
  using CredentialMetadata = device::fido::mac::CredentialMetadata;

  void SetUp() override {
    AuthenticatorImplTest::SetUp();
    test_client_.web_authentication_delegate.touch_id_authenticator_config =
        config_;
    test_client_.web_authentication_delegate.supports_resident_keys = true;
    old_client_ = SetBrowserClientForTesting(&test_client_);
  }

  void TearDown() override {
    SetBrowserClientForTesting(old_client_);
    AuthenticatorImplTest::TearDown();
  }

  void ResetVirtualDevice() override {}

  std::vector<Credential> GetCredentials(const std::string& rp_id) {
    return device::fido::mac::TouchIdCredentialStore::FindCredentialsForTesting(
        config_, rp_id);
  }

  TestAuthenticatorContentBrowserClient test_client_;
  raw_ptr<ContentBrowserClient> old_client_ = nullptr;
  device::fido::mac::AuthenticatorConfig config_{
      .keychain_access_group = "test-keychain-access-group",
      .metadata_secret = "TestMetadataSecret"};
  device::fido::mac::ScopedTouchIdTestEnvironment touch_id_test_environment_{
      config_};
};

TEST_F(TouchIdAuthenticatorImplTest, IsUVPAA) {
  NavigateAndCommit(GURL(kTestOrigin1));
  for (const bool touch_id_available : {false, true}) {
    SCOPED_TRACE(::testing::Message()
                 << "touch_id_available=" << touch_id_available);
    touch_id_test_environment_.SetTouchIdAvailable(touch_id_available);
    EXPECT_EQ(AuthenticatorIsUvpaa(), touch_id_available);
  }
}

TEST_F(TouchIdAuthenticatorImplTest, MakeCredential) {
  NavigateAndCommit(GURL(kTestOrigin1));
  mojo::Remote<blink::mojom::Authenticator> authenticator =
      ConnectToAuthenticator();
  auto options = GetTestPublicKeyCredentialCreationOptions();
  options->authenticator_selection->authenticator_attachment =
      device::AuthenticatorAttachment::kPlatform;
  touch_id_test_environment_.SimulateTouchIdPromptSuccess();
  EXPECT_EQ(AuthenticatorMakeCredential(std::move(options)).status,
            AuthenticatorStatus::SUCCESS);
  auto credentials = GetCredentials(kTestRelyingPartyId);
  EXPECT_EQ(credentials.size(), 1u);
  const CredentialMetadata& metadata = credentials.at(0).metadata;
  // New credentials are always created discoverable.
  EXPECT_TRUE(metadata.is_resident);
  auto expected_user = GetTestPublicKeyCredentialUserEntity();
  EXPECT_EQ(metadata.ToPublicKeyCredentialUserEntity(), expected_user);
}

TEST_F(TouchIdAuthenticatorImplTest, MakeCredentialUnsupportedAlgorithm) {
  // crbug.com/362766319
  NavigateAndCommit(GURL(kTestOrigin1));
  mojo::Remote<blink::mojom::Authenticator> authenticator =
      ConnectToAuthenticator();
  auto options = GetTestPublicKeyCredentialCreationOptions();
  options->authenticator_selection->authenticator_attachment =
      device::AuthenticatorAttachment::kPlatform;
  options->public_key_parameters = GetTestPublicKeyCredentialParameters(
      static_cast<int32_t>(device::CoseAlgorithmIdentifier::kEdDSA));
  touch_id_test_environment_.SimulateTouchIdPromptSuccess();
  EXPECT_EQ(AuthenticatorMakeCredential(std::move(options)).status,
            AuthenticatorStatus::NOT_ALLOWED_ERROR);
}

TEST_F(TouchIdAuthenticatorImplTest, OptionalUv) {
  NavigateAndCommit(GURL(kTestOrigin1));
  mojo::Remote<blink::mojom::Authenticator> authenticator =
      ConnectToAuthenticator();
  // Disable biometrics to verify that requests without uv required do not
  // prompt the user for their macOS password.
  touch_id_test_environment_.keychain()->SetUVMethod(
      crypto::apple::ScopedFakeKeychainV2::UVMethod::kPasswordOnly);
  for (const auto uv : {device::UserVerificationRequirement::kDiscouraged,
                        device::UserVerificationRequirement::kPreferred,
                        device::UserVerificationRequirement::kRequired}) {
    SCOPED_TRACE(static_cast<int>(uv));
    auto options = GetTestPublicKeyCredentialCreationOptions();
    options->authenticator_selection->authenticator_attachment =
        device::AuthenticatorAttachment::kPlatform;
    // Set rk to required. On platform authenticators Chrome should not
    // universally require UV to make make a resident/discoverable credential,
    // like it would on a security key.
    options->authenticator_selection->resident_key =
        device::ResidentKeyRequirement::kRequired;
    options->authenticator_selection->user_verification_requirement = uv;
    bool requires_uv = uv == device::UserVerificationRequirement::kRequired;
    if (requires_uv) {
      touch_id_test_environment_.SimulateTouchIdPromptSuccess();
    } else {
      touch_id_test_environment_.DoNotResolveNextPrompt();
    }
    auto result = AuthenticatorMakeCredential(std::move(options));
    EXPECT_EQ(result.status, AuthenticatorStatus::SUCCESS);
    EXPECT_EQ(HasUV(result.response), requires_uv);
    auto credentials = GetCredentials(kTestRelyingPartyId);
    EXPECT_EQ(credentials.size(), 1u);

    auto assertion_options = GetTestPublicKeyCredentialRequestOptions();
    assertion_options->user_verification = uv;
    assertion_options->allow_credentials =
        std::vector<device::PublicKeyCredentialDescriptor>(
            {{device::CredentialType::kPublicKey,
              credentials[0].credential_id}});
    if (requires_uv) {
      touch_id_test_environment_.SimulateTouchIdPromptSuccess();
    } else {
      touch_id_test_environment_.DoNotResolveNextPrompt();
    }
    auto assertion = AuthenticatorGetAssertion(std::move(assertion_options));
    EXPECT_EQ(assertion.status, AuthenticatorStatus::SUCCESS);
    EXPECT_EQ(HasUV(assertion.response), requires_uv);
  }
}

TEST_F(TouchIdAuthenticatorImplTest, MakeCredential_Resident) {
  NavigateAndCommit(GURL(kTestOrigin1));
  mojo::Remote<blink::mojom::Authenticator> authenticator =
      ConnectToAuthenticator();
  auto options = GetTestPublicKeyCredentialCreationOptions();
  options->authenticator_selection->authenticator_attachment =
      device::AuthenticatorAttachment::kPlatform;
  options->authenticator_selection->resident_key =
      device::ResidentKeyRequirement::kRequired;
  touch_id_test_environment_.SimulateTouchIdPromptSuccess();
  EXPECT_EQ(AuthenticatorMakeCredential(std::move(options)).status,
            AuthenticatorStatus::SUCCESS);
  auto credentials = GetCredentials(kTestRelyingPartyId);
  EXPECT_EQ(credentials.size(), 1u);
  EXPECT_TRUE(credentials.at(0).metadata.is_resident);
}

TEST_F(TouchIdAuthenticatorImplTest, MakeCredential_Eviction) {
  NavigateAndCommit(GURL(kTestOrigin1));
  mojo::Remote<blink::mojom::Authenticator> authenticator =
      ConnectToAuthenticator();

  // A resident credential will overwrite the non-resident one.
  auto options = GetTestPublicKeyCredentialCreationOptions();
  options->authenticator_selection->authenticator_attachment =
      device::AuthenticatorAttachment::kPlatform;
  options->authenticator_selection->resident_key =
      device::ResidentKeyRequirement::kRequired;
  touch_id_test_environment_.SimulateTouchIdPromptSuccess();
  EXPECT_EQ(AuthenticatorMakeCredential(options->Clone()).status,
            AuthenticatorStatus::SUCCESS);
  EXPECT_EQ(GetCredentials(kTestRelyingPartyId).size(), 1u);

  // Another resident credential for the same user will evict the previous one.
  touch_id_test_environment_.SimulateTouchIdPromptSuccess();
  EXPECT_EQ(AuthenticatorMakeCredential(options->Clone()).status,
            AuthenticatorStatus::SUCCESS);
  EXPECT_EQ(GetCredentials(kTestRelyingPartyId).size(), 1u);

  // But a resident credential for a different user shouldn't.
  touch_id_test_environment_.SimulateTouchIdPromptSuccess();
  options->user.id = std::vector<uint8_t>({99});
  EXPECT_EQ(AuthenticatorMakeCredential(std::move(options)).status,
            AuthenticatorStatus::SUCCESS);
  EXPECT_EQ(GetCredentials(kTestRelyingPartyId).size(), 2u);

  // Neither should a credential for a different RP.
  touch_id_test_environment_.SimulateTouchIdPromptSuccess();
  options = GetTestPublicKeyCredentialCreationOptions();
  options->authenticator_selection->authenticator_attachment =
      device::AuthenticatorAttachment::kPlatform;
  options->relying_party.id = "a.google.com";
  EXPECT_EQ(AuthenticatorMakeCredential(std::move(options)).status,
            AuthenticatorStatus::SUCCESS);
  EXPECT_EQ(GetCredentials(kTestRelyingPartyId).size(), 2u);
}

class ICloudKeychainAuthenticatorImplTest : public AuthenticatorImplTest {
 protected:
  class InspectTAIAuthenticatorRequestDelegate
      : public DefaultAuthenticatorRequestClientDelegate {
   public:
    using Callback = base::RepeatingCallback<void(
        const device::FidoRequestHandlerBase::TransportAvailabilityInfo&,
        const std::optional<std::string>& icloud_keychain_id,
        device::FidoRequestHandlerBase::RequestCallback request_callback)>;
    explicit InspectTAIAuthenticatorRequestDelegate(Callback callback)
        : callback_(std::move(callback)) {}

    void RegisterActionCallbacks(
        base::OnceClosure cancel_callback,
        base::OnceClosure immediate_not_found_callback,
        base::RepeatingClosure start_over_callback,
        AccountPreselectedCallback account_preselected_callback,
        PasswordSelectedCallback password_selected_callback,
        device::FidoRequestHandlerBase::RequestCallback request_callback,
        base::OnceClosure cancel_ui_timeout_callback,
        base::RepeatingClosure bluetooth_adapter_power_on_callback,
        base::RepeatingCallback<
            void(device::FidoRequestHandlerBase::BlePermissionCallback)>
            request_ble_permission_callback) override {
      request_callback_ = std::move(request_callback);
    }

    void ConfigureDiscoveries(
        const url::Origin& origin,
        const std::string& rp_id,
        RequestSource request_source,
        device::FidoRequestType request_type,
        std::optional<device::ResidentKeyRequirement> resident_key_requirement,
        device::UserVerificationRequirement user_verification_requirement,
        std::optional<std::string_view> user_name,
        base::span<const device::CableDiscoveryData> pairings_from_extension,
        bool is_enclave_authenticator_available,
        device::FidoDiscoveryFactory* fido_discovery_factory) override {
      fido_discovery_factory->set_allow_no_nswindow_for_testing(true);
    }

    void OnTransportAvailabilityEnumerated(
        device::FidoRequestHandlerBase::TransportAvailabilityInfo tai)
        override {
      callback_.Run(tai, icloud_keychain_id_, request_callback_);
    }

    void FidoAuthenticatorAdded(
        const device::FidoAuthenticator& authenticator) override {
      if (authenticator.GetType() ==
          device::AuthenticatorType::kICloudKeychain) {
        CHECK(!icloud_keychain_id_);
        icloud_keychain_id_ = authenticator.GetId();
      }
    }

   private:
    Callback callback_;
    device::FidoRequestHandlerBase::RequestCallback request_callback_;
    std::optional<std::string> icloud_keychain_id_;
  };

  class InspectTAIContentBrowserClient : public ContentBrowserClient {
   public:
    explicit InspectTAIContentBrowserClient(
        InspectTAIAuthenticatorRequestDelegate::Callback callback)
        : callback_(std::move(callback)) {}

    std::unique_ptr<AuthenticatorRequestClientDelegate>
    GetWebAuthenticationRequestDelegate(
        RenderFrameHost* render_frame_host) override {
      return std::make_unique<InspectTAIAuthenticatorRequestDelegate>(
          callback_);
    }

   private:
    InspectTAIAuthenticatorRequestDelegate::Callback callback_;
  };

  void SetUp() override {
    AuthenticatorImplTest::SetUp();
    old_client_ = SetBrowserClientForTesting(&test_client_);
    // This test uses the real discoveries and sets the transports on an
    // allowlist entry to limit it to kInternal.
    virtual_device_factory_ = nullptr;
    AuthenticatorEnvironment::GetInstance()->Reset();
  }

  void TearDown() override {
    SetBrowserClientForTesting(old_client_);
    AuthenticatorImplTest::TearDown();
  }

  void OnTransportAvailabilityEnumerated(
      const device::FidoRequestHandlerBase::TransportAvailabilityInfo& tai,
      const std::optional<std::string>& icloud_keychain_id,
      device::FidoRequestHandlerBase::RequestCallback request_callback) {
    if (tai_callback_) {
      std::move(tai_callback_).Run(tai, icloud_keychain_id, request_callback);
    }
  }

  static std::vector<device::DiscoverableCredentialMetadata> GetCredentials() {
    device::DiscoverableCredentialMetadata metadata(
        device::AuthenticatorType::kICloudKeychain, kTestRelyingPartyId,
        {1, 2, 3, 4}, {{5, 6, 7, 8}, "name", "displayName"},
        /*provider_name=*/std::nullopt);
    return {std::move(metadata)};
  }

  InspectTAIContentBrowserClient test_client_{base::BindRepeating(
      &ICloudKeychainAuthenticatorImplTest::OnTransportAvailabilityEnumerated,
      base::Unretained(this))};
  raw_ptr<ContentBrowserClient> old_client_ = nullptr;
  InspectTAIAuthenticatorRequestDelegate::Callback tai_callback_;
};

TEST_F(ICloudKeychainAuthenticatorImplTest, Discovery) {
  if (__builtin_available(macOS 13.5, *)) {
    NavigateAndCommit(GURL(kTestOrigin1));
    device::fido::icloud_keychain::ScopedTestEnvironment test_environment(
        GetCredentials());
    bool tai_seen = false;
    tai_callback_ = base::BindLambdaForTesting(
        [&tai_seen](
            const device::FidoRequestHandlerBase::TransportAvailabilityInfo&
                tai,
            const std::optional<std::string>& icloud_keychain_id,
            device::FidoRequestHandlerBase::RequestCallback request_callback) {
          tai_seen = true;
          CHECK_EQ(tai.has_icloud_keychain, true);
          CHECK_EQ(tai.recognized_credentials.size(), 1u);
          CHECK_EQ(tai.has_icloud_keychain_credential,
                   device::FidoRequestHandlerBase::RecognizedCredential::
                       kHasRecognizedCredential);

          CHECK_EQ(tai.recognized_credentials[0].user.name.value(), "name");
        });

    auto options = GetTestPublicKeyCredentialRequestOptions();
    options->allow_credentials.clear();
    options->allow_credentials.push_back(device::PublicKeyCredentialDescriptor(
        device::CredentialType::kPublicKey, {1, 2, 3, 4},
        {device::FidoTransportProtocol::kInternal}));
    const auto result = AuthenticatorGetAssertion(std::move(options));
    EXPECT_EQ(result.status, AuthenticatorStatus::NOT_ALLOWED_ERROR);
    EXPECT_TRUE(tai_seen);
  } else {
    GTEST_SKIP() << "Need macOS 13.5 for this test";
  }
}

TEST_F(ICloudKeychainAuthenticatorImplTest, PRFOnCreate) {
  if (__builtin_available(macOS 15.0, *)) {
    NavigateAndCommit(GURL(kTestOrigin1));
    device::fido::icloud_keychain::ScopedTestEnvironment test_environment(
        GetCredentials());

    auto prf_value = blink::mojom::PRFValues::New();
    const std::vector<uint8_t> input1(8, 1);
    const std::vector<uint8_t> input2(8, 2);
    prf_value->first = input1;
    prf_value->second = input2;

    bool callback_was_called = false;
    test_environment.SetMakeCredentialCallback(base::BindLambdaForTesting(
        [&input1, &input2, &callback_was_called](
            const device::CtapMakeCredentialRequest& request) {
          CHECK(request.prf);
          CHECK(request.prf_input.has_value());
          CHECK(input1 == request.prf_input->input1);
          CHECK(input2 == request.prf_input->input2);
          callback_was_called = true;
        }));

    auto options = GetTestPublicKeyCredentialCreationOptions();
    options->prf_enable = true;
    options->prf_input = std::move(prf_value);

    const auto result = AuthenticatorMakeCredential(std::move(options));
    EXPECT_EQ(result.status, AuthenticatorStatus::NOT_ALLOWED_ERROR);
    EXPECT_TRUE(callback_was_called);
  } else {
    GTEST_SKIP() << "Need macOS 15.0 for this test";
  }
}

TEST_F(ICloudKeychainAuthenticatorImplTest, PRFOnGet) {
  if (__builtin_available(macOS 15.0, *)) {
    NavigateAndCommit(GURL(kTestOrigin1));
    device::fido::icloud_keychain::ScopedTestEnvironment test_environment(
        GetCredentials());

    auto prf_value = blink::mojom::PRFValues::New();
    const std::vector<uint8_t> input1(8, 1);
    const std::vector<uint8_t> input2(8, 2);
    prf_value->first = input1;
    prf_value->second = input2;
    std::vector<blink::mojom::PRFValuesPtr> prf_inputs;
    prf_inputs.emplace_back(std::move(prf_value));

    bool callback_was_called = false;
    test_environment.SetGetAssertionCallback(base::BindLambdaForTesting(
        [&input1, &input2,
         &callback_was_called](const device::CtapGetAssertionRequest& request) {
          CHECK_EQ(request.prf_inputs.size(), 1u);
          CHECK(input1 == request.prf_inputs[0].input1);
          CHECK(input2 == request.prf_inputs[0].input2);
          callback_was_called = true;
        }));

    tai_callback_ = base::BindLambdaForTesting(
        [](const device::FidoRequestHandlerBase::TransportAvailabilityInfo& tai,
           const std::optional<std::string>& icloud_keychain_id,
           device::FidoRequestHandlerBase::RequestCallback request_callback) {
          CHECK_EQ(tai.has_icloud_keychain, true);
          CHECK(icloud_keychain_id.has_value());
          base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
              FROM_HERE, base::BindOnce(request_callback, *icloud_keychain_id));
        });

    auto options = GetTestPublicKeyCredentialRequestOptions();
    options->extensions->prf = true;
    options->extensions->prf_inputs = std::move(prf_inputs);
    options->allow_credentials.clear();
    options->allow_credentials.push_back(device::PublicKeyCredentialDescriptor(
        device::CredentialType::kPublicKey, {1, 2, 3, 4},
        {device::FidoTransportProtocol::kInternal}));

    const auto result = AuthenticatorGetAssertion(std::move(options));
    EXPECT_EQ(result.status, AuthenticatorStatus::NOT_ALLOWED_ERROR);
    EXPECT_TRUE(callback_was_called);
  } else {
    GTEST_SKIP() << "Need macOS 15.0 for this test";
  }
}

#endif  // BUILDFLAG(IS_MAC)

TEST_F(ResidentKeyAuthenticatorImplTest,
       GetAssertionImmediateMediationTimeout_NoUI) {
  base::HistogramTester histogram_tester;
  base::test::ScopedFeatureList feature_list;
  base::FieldTrialParams feature_params;
  constexpr base::TimeDelta kImmediateTimeout = base::Milliseconds(10);
  feature_params["timeout_ms"] =
      base::NumberToString(kImmediateTimeout.InMilliseconds());
  feature_list.InitAndEnableFeatureWithParameters(device::kWebAuthnImmediateGet,
                                                  feature_params);

  ReplaceDiscoveryFactory(std::make_unique<device::FidoDiscoveryFactory>());

  GetCredentialOptionsPtr options = GetTestGetCredentialOptions();
  options->mediation = blink::mojom::Mediation::IMMEDIATE;
  options->public_key->allow_credentials.clear();
  options->public_key->timeout = kTestTimeout;

  mojo::Remote<blink::mojom::Authenticator> authenticator =
      ConnectToAuthenticator();
  TestGetCredentialFuture future;
  authenticator->GetCredential(std::move(options), future.GetCallback());

  task_environment()->FastForwardBy(kImmediateTimeout);

  EXPECT_TRUE(future.Wait());
  ASSERT_TRUE(future.Get()->is_get_assertion_response());
  auto& get_assertion_response = future.Get()->get_get_assertion_response();
  EXPECT_EQ(get_assertion_response->status,
            AuthenticatorStatus::IMMEDIATE_NOT_FOUND);
  histogram_tester.ExpectUniqueSample(
      "WebAuthentication.GetAssertion.Immediate.TimeoutWhileWaitingForUi", true,
      1);
}

TEST_F(ResidentKeyAuthenticatorImplTest,
       GetAssertionImmediateMediationTimeout_WithUiThenNoImmediateTimeout) {
  base::HistogramTester histogram_tester;
  test_client_.delegate_config.run_cancel_ui_timeout_callback = true;
  base::test::ScopedFeatureList feature_list;
  base::FieldTrialParams feature_params;
  constexpr base::TimeDelta kImmediateTimeout = base::Milliseconds(10);
  feature_params["timeout_ms"] =
      base::NumberToString(kImmediateTimeout.InMilliseconds());
  feature_list.InitAndEnableFeatureWithParameters(device::kWebAuthnImmediateGet,
                                                  feature_params);

  ReplaceDiscoveryFactory(std::make_unique<device::FidoDiscoveryFactory>());

  auto options = GetTestGetCredentialOptions();
  options->mediation = blink::mojom::Mediation::IMMEDIATE;
  options->public_key->allow_credentials.clear();
  options->public_key->timeout = kTestTimeout;

  mojo::Remote<blink::mojom::Authenticator> authenticator =
      ConnectToAuthenticator();
  TestGetCredentialFuture future;

  authenticator->GetCredential(std::move(options), future.GetCallback());
  // Fast forward by the immediate mediation timeout.
  task_environment()->FastForwardBy(kImmediateTimeout + base::Milliseconds(1));

  // The request should NOT be complete yet because UI is displayed,
  // which bypasses the immediate timeout.
  EXPECT_FALSE(future.IsReady());
  histogram_tester.ExpectUniqueSample(
      "WebAuthentication.GetAssertion.Immediate.TimeoutWhileWaitingForUi",
      false, 1);
  test_client_.delegate_config.run_cancel_ui_timeout_callback = false;
}

// AuthenticatorCableV2Test tests features of the caBLEv2 transport and
// protocol.
class AuthenticatorCableV2Test : public AuthenticatorImplRequestDelegateTest {
 public:
  void SetUp() override {
    AuthenticatorImplTest::SetUp();

    NavigateAndCommit(GURL(kTestOrigin1));
    ResetNetworkService();

    old_client_ = SetBrowserClientForTesting(&browser_client_);

    bssl::UniquePtr<EC_GROUP> p256(
        EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
    bssl::UniquePtr<EC_KEY> peer_identity(EC_KEY_derive_from_secret(
        p256.get(), zero_seed_.data(), zero_seed_.size()));
    CHECK_EQ(sizeof(peer_identity_x962_),
             EC_POINT_point2oct(
                 p256.get(), EC_KEY_get0_public_key(peer_identity.get()),
                 POINT_CONVERSION_UNCOMPRESSED, peer_identity_x962_,
                 sizeof(peer_identity_x962_), /*ctx=*/nullptr));

    std::tie(ble_advert_callback_, ble_advert_events_) =
        device::cablev2::Discovery::AdvertEventStream::New();
  }

  void TearDown() override {
    // Ensure that all pending caBLE connections have timed out and closed.
    task_environment()->FastForwardBy(base::Minutes(10));

    SetBrowserClientForTesting(old_client_);
    AuthenticatorImplTest::TearDown();

    // All `EstablishedConnection` instances should have been destroyed.
    CHECK_EQ(device::cablev2::FidoTunnelDevice::
                 GetNumEstablishedConnectionInstancesForTesting(),
             0);
  }

  base::RepeatingCallback<void(std::unique_ptr<device::cablev2::Pairing>)>
  GetPairingCallback() {
    return base::BindRepeating(&AuthenticatorCableV2Test::OnNewPairing,
                               base::Unretained(this));
  }

  base::RepeatingCallback<void(std::unique_ptr<device::cablev2::Pairing>)>
  GetInvalidatedPairingCallback() {
    return base::BindRepeating(&AuthenticatorCableV2Test::OnInvalidatedPairing,
                               base::Unretained(this));
  }

  base::RepeatingCallback<void(Event)> GetEventCallback() {
    return base::BindRepeating(&AuthenticatorCableV2Test::OnCableEvent,
                               base::Unretained(this));
  }

  void EnableConnectionSignalAtTunnelServer() {
    // Recreate the tunnel server so that it supports the connection signal.
    network_context_ = device::cablev2::NewMockTunnelServer(
        base::BindRepeating(&AuthenticatorCableV2Test::OnContact,
                            base::Unretained(this)),
        /*supports_connect_signal=*/true);
  }

 protected:
  class DiscoveryFactory : public device::FidoDiscoveryFactory {
   public:
    explicit DiscoveryFactory(
        std::unique_ptr<device::cablev2::Discovery> discovery)
        : discovery_(std::move(discovery)) {}

    std::vector<std::unique_ptr<device::FidoDiscoveryBase>> Create(
        device::FidoTransportProtocol transport) override {
      if (transport != device::FidoTransportProtocol::kHybrid || !discovery_) {
        return {};
      }

      return SingleDiscovery(std::move(discovery_));
    }

   private:
    std::unique_ptr<device::cablev2::Discovery> discovery_;
  };

  class TestAuthenticationDelegate : public WebAuthenticationDelegate {
   public:
    bool SupportsResidentKeys(RenderFrameHost*) override { return true; }

    bool IsFocused(WebContents* web_contents) override { return true; }
  };

  class ContactWhenReadyAuthenticatorRequestDelegate
      : public DefaultAuthenticatorRequestClientDelegate {
   public:
    explicit ContactWhenReadyAuthenticatorRequestDelegate(
        base::RepeatingClosure callback)
        : callback_(callback) {}
    ~ContactWhenReadyAuthenticatorRequestDelegate() override = default;

    void OnTransportAvailabilityEnumerated(
        device::FidoRequestHandlerBase::TransportAvailabilityInfo) override {
      callback_.Run();
    }

   private:
    base::RepeatingClosure callback_;
  };

  class ContactWhenReadyContentBrowserClient : public ContentBrowserClient {
   public:
    explicit ContactWhenReadyContentBrowserClient(
        base::RepeatingClosure callback)
        : callback_(callback) {}

    std::unique_ptr<AuthenticatorRequestClientDelegate>
    GetWebAuthenticationRequestDelegate(
        RenderFrameHost* render_frame_host) override {
      return std::make_unique<ContactWhenReadyAuthenticatorRequestDelegate>(
          callback_);
    }

    WebAuthenticationDelegate* GetWebAuthenticationDelegate() override {
      return &authentication_delegate_;
    }

   private:
    base::RepeatingClosure callback_;
    TestAuthenticationDelegate authentication_delegate_;
  };

  // MaybeContactPhones is called when OnTransportAvailabilityEnumerated is
  // called by the request handler.
  void MaybeContactPhones() {
    if (maybe_contact_phones_callback_) {
      std::move(maybe_contact_phones_callback_).Run();
    }
  }

  void OnContact(
      base::span<const uint8_t, device::cablev2::kTunnelIdSize> tunnel_id,
      base::span<const uint8_t, device::cablev2::kPairingIDSize> pairing_id,
      base::span<const uint8_t, device::cablev2::kClientNonceSize> client_nonce,
      const std::string& request_type_hint) {
    std::move(contact_callback_)
        .Run(tunnel_id, pairing_id, client_nonce, request_type_hint);
  }

  void OnNewPairing(std::unique_ptr<device::cablev2::Pairing> pairing) {
    pairings_.emplace_back(std::move(pairing));
  }

  void OnInvalidatedPairing(
      std::unique_ptr<device::cablev2::Pairing> disabled_pairing) {
    pairings_.erase(std::ranges::find_if(
        pairings_, [&disabled_pairing](const auto& pairing) {
          return device::cablev2::Pairing::EqualPublicKeys(pairing,
                                                           disabled_pairing);
        }));
  }

  void OnCableEvent(Event event) { events_.push_back(event); }

  void DoPairingConnection() {
    // First do unpaired exchange to get pairing data.
    auto discovery = std::make_unique<device::cablev2::Discovery>(
        device::FidoRequestType::kGetAssertion,
        base::BindLambdaForTesting([&]() { return network_context_.get(); }),
        qr_generator_key_, std::move(ble_advert_events_),
        /*contact_device_stream=*/nullptr,
        /*extension_contents=*/std::vector<device::CableDiscoveryData>(),
        GetPairingCallback(), GetInvalidatedPairingCallback(),
        GetEventCallback(), /*must_support_ctap=*/true);

    ReplaceDiscoveryFactory(
        std::make_unique<DiscoveryFactory>(std::move(discovery)));

    const std::vector<uint8_t> contact_id(/*count=*/200, /*value=*/1);
    std::unique_ptr<device::cablev2::authenticator::Transaction> transaction =
        device::cablev2::authenticator::TransactFromQRCode(
            device::cablev2::authenticator::NewMockPlatform(
                std::move(ble_advert_callback_), &virtual_device_,
                /*observer=*/nullptr),
            base::BindLambdaForTesting(
                [&]() { return network_context_.get(); }),
            root_secret_, "Test Authenticator", zero_qr_secret_,
            peer_identity_x962_, contact_id);

    EXPECT_EQ(AuthenticatorMakeCredential().status,
              AuthenticatorStatus::SUCCESS);
    EXPECT_EQ(pairings_.size(), 1u);

    // Now do a pairing-based exchange. Generate a random request type hint to
    // ensure that all values work.
    device::FidoRequestType request_type =
        device::FidoRequestType::kMakeCredential;
    std::string expected_request_type_string = "mc";
    if (base::RandDouble() < 0.5) {
      request_type = device::FidoRequestType::kGetAssertion;
      expected_request_type_string = "ga";
    }

    std::tie(ble_advert_callback_, ble_advert_events_) =
        device::cablev2::Discovery::EventStream<
            base::span<const uint8_t, device::cablev2::kAdvertSize>>::New();
    auto callback_and_event_stream = device::cablev2::Discovery::EventStream<
        std::unique_ptr<device::cablev2::Pairing>>::New();
    discovery = std::make_unique<device::cablev2::Discovery>(
        request_type,
        base::BindLambdaForTesting([&]() { return network_context_.get(); }),
        qr_generator_key_, std::move(ble_advert_events_),
        std::move(callback_and_event_stream.second),
        /*extension_contents=*/std::vector<device::CableDiscoveryData>(),
        GetPairingCallback(), GetInvalidatedPairingCallback(),
        GetEventCallback(), /*must_support_ctap=*/true);

    maybe_contact_phones_callback_ = base::BindLambdaForTesting([&]() {
      callback_and_event_stream.first.Run(
          std::make_unique<device::cablev2::Pairing>(*pairings_[0]));
    });

    const std::array<uint8_t, device::cablev2::kRoutingIdSize> routing_id = {0};
    bool contact_callback_IsReady = false;
    // When the |cablev2::Discovery| starts it'll make a connection to the
    // tunnel service with the contact ID from the pairing data. This will be
    // handled by the |TestNetworkContext| and turned into a call to
    // |contact_callback_|. This simulates the tunnel server sending a cloud
    // message to a phone. Given the information from the connection, a
    // transaction can be created.
    contact_callback_ = base::BindLambdaForTesting(
        [this, &transaction, routing_id, contact_id, &contact_callback_IsReady,
         &expected_request_type_string](
            base::span<const uint8_t, device::cablev2::kTunnelIdSize> tunnel_id,
            base::span<const uint8_t, device::cablev2::kPairingIDSize>
                pairing_id,
            base::span<const uint8_t, device::cablev2::kClientNonceSize>
                client_nonce,
            const std::string& request_type_hint) -> void {
          contact_callback_IsReady = true;
          CHECK_EQ(request_type_hint, expected_request_type_string);
          transaction = device::cablev2::authenticator::TransactFromFCM(
              device::cablev2::authenticator::NewMockPlatform(
                  std::move(ble_advert_callback_), &virtual_device_,
                  /*observer=*/nullptr),
              base::BindLambdaForTesting(
                  [&]() { return network_context_.get(); }),
              root_secret_, routing_id, tunnel_id, pairing_id, client_nonce,
              contact_id);
        });

    ReplaceDiscoveryFactory(
        std::make_unique<DiscoveryFactory>(std::move(discovery)));

    EXPECT_EQ(AuthenticatorMakeCredential().status,
              AuthenticatorStatus::SUCCESS);
    EXPECT_TRUE(contact_callback_IsReady);
  }

  void ResetNetworkService() {
    network_context_ = device::cablev2::NewMockTunnelServer(base::BindRepeating(
        &AuthenticatorCableV2Test::OnContact, base::Unretained(this)));
  }

  const std::array<uint8_t, device::cablev2::kRootSecretSize> root_secret_ = {
      0};
  const std::array<uint8_t, device::cablev2::kQRKeySize> qr_generator_key_ = {
      0};
  const std::array<uint8_t, device::cablev2::kQRSecretSize> zero_qr_secret_ = {
      0};
  const std::array<uint8_t, device::cablev2::kQRSeedSize> zero_seed_ = {0};

  std::unique_ptr<network::mojom::NetworkContext> network_context_;
  uint8_t peer_identity_x962_[device::kP256X962Length] = {};
  device::VirtualCtap2Device virtual_device_{DeviceState(), DeviceConfig()};
  std::vector<std::unique_ptr<device::cablev2::Pairing>> pairings_;
  base::OnceCallback<void(
      base::span<const uint8_t, device::cablev2::kTunnelIdSize> tunnel_id,
      base::span<const uint8_t, device::cablev2::kPairingIDSize> pairing_id,
      base::span<const uint8_t, device::cablev2::kClientNonceSize> client_nonce,
      const std::string& request_type_hint)>
      contact_callback_;
  std::unique_ptr<device::cablev2::Discovery::AdvertEventStream>
      ble_advert_events_;
  device::cablev2::Discovery::AdvertEventStream::Callback ble_advert_callback_;
  ContactWhenReadyContentBrowserClient browser_client_{
      base::BindRepeating(&AuthenticatorCableV2Test::MaybeContactPhones,
                          base::Unretained(this))};
  raw_ptr<ContentBrowserClient> old_client_ = nullptr;
  base::OnceClosure maybe_contact_phones_callback_;
  std::vector<Event> events_;

 private:
  static VirtualCtap2Device::State* DeviceState() {
    VirtualCtap2Device::State* state = new VirtualCtap2Device::State;
    state->fingerprints_enrolled = true;
    state->default_backup_eligibility = true;
    return state;
  }

  static VirtualCtap2Device::Config DeviceConfig() {
    // `MockPlatform` uses a virtual device to answer requests, but it can't
    // handle the credential ID being omitted in responses.
    VirtualCtap2Device::Config ret;
    ret.include_credential_in_assertion_response =
        VirtualCtap2Device::Config::IncludeCredential::ALWAYS;
    ret.prf_support = true;
    ret.internal_account_chooser = true;
    ret.internal_uv_support = true;
    ret.always_uv = true;
    return ret;
  }
};

TEST_F(AuthenticatorCableV2Test, QRBasedWithNoPairing) {
  auto discovery = std::make_unique<device::cablev2::Discovery>(
      device::FidoRequestType::kGetAssertion,
      base::BindLambdaForTesting([&]() { return network_context_.get(); }),
      qr_generator_key_, std::move(ble_advert_events_),
      /*contact_device_stream=*/nullptr,
      /*extension_contents=*/std::vector<device::CableDiscoveryData>(),
      GetPairingCallback(), GetInvalidatedPairingCallback(), GetEventCallback(),
      /*must_support_ctap=*/true);

  ReplaceDiscoveryFactory(
      std::make_unique<DiscoveryFactory>(std::move(discovery)));

  std::unique_ptr<device::cablev2::authenticator::Transaction> transaction =
      device::cablev2::authenticator::TransactFromQRCode(
          device::cablev2::authenticator::NewMockPlatform(
              std::move(ble_advert_callback_), &virtual_device_,
              /*observer=*/nullptr),
          base::BindLambdaForTesting([&]() { return network_context_.get(); }),
          root_secret_, "Test Authenticator", zero_qr_secret_,
          peer_identity_x962_,
          /*contact_id=*/std::nullopt);

  EXPECT_EQ(AuthenticatorMakeCredential().status, AuthenticatorStatus::SUCCESS);
  EXPECT_EQ(pairings_.size(), 0u);
}

TEST_F(AuthenticatorCableV2Test, HandshakeError) {
  // A handshake error should be fatal to the request with
  // `kHybridTransportError`.
  auto network_context_factory =
      base::BindLambdaForTesting([&]() { return network_context_.get(); });
  auto discovery = std::make_unique<device::cablev2::Discovery>(
      device::FidoRequestType::kGetAssertion, network_context_factory,
      qr_generator_key_, std::move(ble_advert_events_),
      /*contact_device_stream=*/nullptr,
      /*extension_contents=*/std::vector<device::CableDiscoveryData>(),
      GetPairingCallback(), GetInvalidatedPairingCallback(), GetEventCallback(),
      /*must_support_ctap=*/true);

  ReplaceDiscoveryFactory(
      std::make_unique<DiscoveryFactory>(std::move(discovery)));

  std::unique_ptr<device::cablev2::authenticator::Transaction> transaction =
      device::cablev2::authenticator::NewHandshakeErrorDevice(
          device::cablev2::authenticator::NewMockPlatform(
              std::move(ble_advert_callback_), &virtual_device_,
              /*observer=*/nullptr),
          network_context_factory, zero_qr_secret_);

  FailureReasonFuture failure_reason_future;
  auto mock_delegate = std::make_unique<
      ::testing::NiceMock<MockAuthenticatorRequestDelegateObserver>>(
      failure_reason_future.GetCallback());
  auto authenticator = ConnectToFakeAuthenticator(std::move(mock_delegate));

  TestMakeCredentialFuture future;
  authenticator->MakeCredential(GetTestPublicKeyCredentialCreationOptions(),
                                future.GetCallback());

  EXPECT_TRUE(future.Wait());
  EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, std::get<0>(future.Get()));

  ASSERT_TRUE(failure_reason_future.IsReady());
  EXPECT_EQ(AuthenticatorRequestClientDelegate::InterestingFailureReason::
                kHybridTransportError,
            failure_reason_future.Get());
}

// Test having the network service crash between creating a discovery and
// performing a cable transaction. Regression test for crbug.com/332724843.
TEST_F(AuthenticatorCableV2Test, NetworkServiceCrash) {
  auto discovery = std::make_unique<device::cablev2::Discovery>(
      device::FidoRequestType::kGetAssertion,
      base::BindLambdaForTesting([&]() { return network_context_.get(); }),
      qr_generator_key_, std::move(ble_advert_events_),
      /*contact_device_stream=*/nullptr,
      /*extension_contents=*/std::vector<device::CableDiscoveryData>(),
      GetPairingCallback(), GetInvalidatedPairingCallback(), GetEventCallback(),
      /*must_support_ctap=*/true);

  ReplaceDiscoveryFactory(
      std::make_unique<DiscoveryFactory>(std::move(discovery)));

  // Simulate the network service restarting.
  ResetNetworkService();

  std::unique_ptr<device::cablev2::authenticator::Transaction> transaction =
      device::cablev2::authenticator::TransactFromQRCode(
          device::cablev2::authenticator::NewMockPlatform(
              std::move(ble_advert_callback_), &virtual_device_,
              /*observer=*/nullptr),
          base::BindLambdaForTesting([&]() { return network_context_.get(); }),
          root_secret_, "Test Authenticator", zero_qr_secret_,
          peer_identity_x962_,
          /*contact_id=*/std::nullopt);

  EXPECT_EQ(AuthenticatorMakeCredential().status, AuthenticatorStatus::SUCCESS);
  EXPECT_EQ(pairings_.size(), 0u);
}

TEST_F(AuthenticatorCableV2Test, PairingBased) {
  DoPairingConnection();

  const std::vector<Event> kExpectedEvents = {
      // From the QR connection
      Event::kBLEAdvertReceived,
      Event::kReady,
      // From the paired connection
      Event::kBLEAdvertReceived,
      Event::kReady,
  };
  EXPECT_EQ(events_, kExpectedEvents);
}

TEST_F(AuthenticatorCableV2Test, PairingBasedWithConnectionSignal) {
  EnableConnectionSignalAtTunnelServer();
  DoPairingConnection();

  const std::vector<Event> kExpectedEvents = {
      // From the QR connection
      Event::kBLEAdvertReceived,
      Event::kReady,
      // From the paired connection
      Event::kPhoneConnected,
      Event::kBLEAdvertReceived,
      Event::kReady,
  };
  EXPECT_EQ(events_, kExpectedEvents);
}

static std::unique_ptr<device::cablev2::Pairing> DummyPairing() {
  auto ret = std::make_unique<device::cablev2::Pairing>();
  ret->tunnel_server_domain = device::cablev2::kTunnelServer;
  ret->contact_id = {1, 2, 3, 4, 5};
  ret->id = {6, 7, 8, 9};
  ret->secret = {10, 11, 12, 13};
  std::fill(ret->peer_public_key_x962.begin(), ret->peer_public_key_x962.end(),
            22);
  ret->name = __func__;

  return ret;
}

TEST_F(AuthenticatorCableV2Test, ContactIDDisabled) {
  // Passing |nullopt| as the callback here causes all contact IDs to be
  // rejected.
  network_context_ = device::cablev2::NewMockTunnelServer(std::nullopt);
  auto callback_and_event_stream = device::cablev2::Discovery::EventStream<
      std::unique_ptr<device::cablev2::Pairing>>::New();
  auto discovery = std::make_unique<device::cablev2::Discovery>(
      device::FidoRequestType::kGetAssertion,
      base::BindLambdaForTesting([&]() { return network_context_.get(); }),
      qr_generator_key_, std::move(ble_advert_events_),
      std::move(callback_and_event_stream.second),
      /*extension_contents=*/std::vector<device::CableDiscoveryData>(),
      GetPairingCallback(), GetInvalidatedPairingCallback(), GetEventCallback(),
      /*must_support_ctap=*/true);

  ReplaceDiscoveryFactory(
      std::make_unique<DiscoveryFactory>(std::move(discovery)));

  maybe_contact_phones_callback_ =
      base::BindLambdaForTesting([&callback_and_event_stream]() {
        callback_and_event_stream.first.Run(DummyPairing());
      });

  pairings_.emplace_back(DummyPairing());
  ASSERT_EQ(pairings_.size(), 1u);
  EXPECT_EQ(AuthenticatorMakeCredentialAndWaitForTimeout(
                GetTestPublicKeyCredentialCreationOptions())
                .status,
            AuthenticatorStatus::NOT_ALLOWED_ERROR);
  // The pairing should be been erased because of the signal from the tunnel
  // server.
  ASSERT_EQ(pairings_.size(), 0u);
}

// ServerLinkValues contains keys that mimic those created by a site doing
// caBLEv2 server-link.
struct ServerLinkValues {
  // This value would be provided by the site to the desktop, in a caBLE
  // extension in the get() call.
  device::CableDiscoveryData desktop_side;

  // These values would be provided to the phone via a custom mechanism.
  std::array<uint8_t, device::cablev2::kQRSecretSize> secret;
  std::array<uint8_t, device::kP256X962Length> peer_identity;
};

// CreateServerLink simulates a site doing caBLEv2 server-link and calculates
// server-link values that could be sent to the desktop and phone sides of a
// transaction.
static ServerLinkValues CreateServerLink() {
  std::vector<uint8_t> seed(device::cablev2::kQRSeedSize);
  base::RandBytes(seed);

  bssl::UniquePtr<EC_GROUP> p256(
      EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
  bssl::UniquePtr<EC_KEY> ec_key(
      EC_KEY_derive_from_secret(p256.get(), seed.data(), seed.size()));

  ServerLinkValues ret;
  base::RandBytes(ret.secret);
  CHECK_EQ(ret.peer_identity.size(),
           EC_POINT_point2oct(p256.get(), EC_KEY_get0_public_key(ec_key.get()),
                              POINT_CONVERSION_UNCOMPRESSED,
                              ret.peer_identity.data(),
                              ret.peer_identity.size(), /*ctx=*/nullptr));

  ret.desktop_side.version = device::CableDiscoveryData::Version::V2;
  ret.desktop_side.v2.emplace(seed, std::vector<uint8_t>());
  ret.desktop_side.v2->server_link_data.insert(
      ret.desktop_side.v2->server_link_data.end(), ret.secret.begin(),
      ret.secret.end());

  return ret;
}

TEST_F(AuthenticatorCableV2Test, ServerLink) {
  const ServerLinkValues server_link_1 = CreateServerLink();
  const ServerLinkValues server_link_2 = CreateServerLink();
  const std::vector<device::CableDiscoveryData> extension_values = {
      server_link_1.desktop_side, server_link_2.desktop_side};

  auto discovery = std::make_unique<device::cablev2::Discovery>(
      device::FidoRequestType::kGetAssertion,
      base::BindLambdaForTesting([&]() { return network_context_.get(); }),
      qr_generator_key_, std::move(ble_advert_events_),
      /*contact_device_stream=*/nullptr, extension_values, GetPairingCallback(),
      GetInvalidatedPairingCallback(), GetEventCallback(),
      /*must_support_ctap=*/true);

  ReplaceDiscoveryFactory(
      std::make_unique<DiscoveryFactory>(std::move(discovery)));

  // Both extension values should work, but we can only do a single transaction
  // per test because a lot of state is setup for a test. Therefore pick one of
  // the two to check, at random.
  const auto& server_link =
      (base::RandUint64() & 1) ? server_link_1 : server_link_2;

  std::unique_ptr<device::cablev2::authenticator::Transaction> transaction =
      device::cablev2::authenticator::TransactFromQRCode(
          device::cablev2::authenticator::NewMockPlatform(
              std::move(ble_advert_callback_), &virtual_device_,
              /*observer=*/nullptr),
          base::BindLambdaForTesting([&]() { return network_context_.get(); }),
          root_secret_, "Test Authenticator", server_link.secret,
          server_link.peer_identity,
          /*contact_id=*/std::nullopt);

  EXPECT_EQ(AuthenticatorMakeCredential().status, AuthenticatorStatus::SUCCESS);
  EXPECT_EQ(pairings_.size(), 0u);
}

TEST_F(AuthenticatorCableV2Test, LateLinking) {
  auto network_context_factory =
      base::BindLambdaForTesting([&]() { return network_context_.get(); });
  auto discovery = std::make_unique<device::cablev2::Discovery>(
      device::FidoRequestType::kGetAssertion, network_context_factory,
      qr_generator_key_, std::move(ble_advert_events_),
      /*contact_device_stream=*/nullptr,
      /*extension_contents=*/std::vector<device::CableDiscoveryData>(),
      GetPairingCallback(), GetInvalidatedPairingCallback(), GetEventCallback(),
      /*must_support_ctap=*/true);

  ReplaceDiscoveryFactory(
      std::make_unique<DiscoveryFactory>(std::move(discovery)));

  const std::vector<uint8_t> contact_id(/*count=*/200, /*value=*/1);
  std::unique_ptr<device::cablev2::authenticator::Transaction> transaction =
      device::cablev2::authenticator::NewLateLinkingDevice(
          device::CtapDeviceResponseCode::kCtap2ErrOperationDenied,
          device::cablev2::authenticator::NewMockPlatform(
              std::move(ble_advert_callback_), &virtual_device_,
              /*observer=*/nullptr),
          network_context_factory, zero_qr_secret_, peer_identity_x962_);

  EXPECT_EQ(AuthenticatorMakeCredential().status,
            AuthenticatorStatus::NOT_ALLOWED_ERROR);

  // There should not be any pairing at this point because the device shouldn't
  // have sent the information yet.
  EXPECT_EQ(pairings_.size(), 0u);

  // After 30 seconds, a pairing should have been recorded even though the
  // WebAuthn request has completed.
  task_environment()->FastForwardBy(base::Seconds(30));
  EXPECT_EQ(pairings_.size(), 1u);
}

// AuthenticatorCableV2AuthenticatorTest tests aspects of the authenticator
// implementation, rather than of the underlying caBLEv2 transport.
class AuthenticatorCableV2AuthenticatorTest
    : public AuthenticatorCableV2Test,
      public device::cablev2::authenticator::Observer {
 public:
  void SetUp() override {
    AuthenticatorCableV2Test::SetUp();

    auto discovery = std::make_unique<device::cablev2::Discovery>(
        device::FidoRequestType::kGetAssertion,
        base::BindLambdaForTesting([&]() { return network_context_.get(); }),
        qr_generator_key_, std::move(ble_advert_events_),
        /*contact_device_stream=*/nullptr,
        /*extension_contents=*/std::vector<device::CableDiscoveryData>(),
        GetPairingCallback(), GetInvalidatedPairingCallback(),
        GetEventCallback(), /*must_support_ctap=*/true);

    ReplaceDiscoveryFactory(
        std::make_unique<DiscoveryFactory>(std::move(discovery)));

    transaction_ = device::cablev2::authenticator::TransactFromQRCode(
        device::cablev2::authenticator::NewMockPlatform(
            std::move(ble_advert_callback_), &virtual_device_, this),
        base::BindLambdaForTesting([&]() { return network_context_.get(); }),
        root_secret_, "Test Authenticator", zero_qr_secret_,
        peer_identity_x962_,
        /*contact_id=*/std::nullopt);
  }

 protected:
  // device::cablev2::authenticator::Observer
  void OnStatus(device::cablev2::authenticator::Platform::Status) override {}
  void OnCompleted(
      std::optional<device::cablev2::authenticator::Platform::Error> error)
      override {
    CHECK(!did_complete_);
    did_complete_ = true;
    error_ = error;
  }

  std::unique_ptr<device::cablev2::authenticator::Transaction> transaction_;
  bool did_complete_ = false;
  std::optional<device::cablev2::authenticator::Platform::Error> error_;
};

TEST_F(AuthenticatorCableV2AuthenticatorTest, GetAssertion) {
  PublicKeyCredentialRequestOptionsPtr options =
      GetTestPublicKeyCredentialRequestOptions();
  options->allow_credentials[0].transports.insert(
      device::FidoTransportProtocol::kHybrid);
  ASSERT_TRUE(virtual_device_.mutable_state()->InjectRegistration(
      options->allow_credentials[0].id, options->relying_party_id));

  EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
            AuthenticatorStatus::SUCCESS);
}

TEST_F(AuthenticatorCableV2AuthenticatorTest, MakeDiscoverableCredential) {
  auto options = GetTestPublicKeyCredentialCreationOptions();
  options->authenticator_selection->resident_key =
      device::ResidentKeyRequirement::kRequired;
  EXPECT_EQ(
      AuthenticatorMakeCredentialAndWaitForTimeout(std::move(options)).status,
      AuthenticatorStatus::NOT_ALLOWED_ERROR);

  ASSERT_TRUE(did_complete_);
  ASSERT_TRUE(error_.has_value());
  EXPECT_EQ(*error_, device::cablev2::authenticator::Platform::Error::
                         DISCOVERABLE_CREDENTIALS_REQUEST);
}

TEST_F(AuthenticatorCableV2AuthenticatorTest, EmptyAllowList) {
  auto options = GetTestPublicKeyCredentialRequestOptions();
  options->allow_credentials.clear();
  EXPECT_EQ(
      AuthenticatorGetAssertionAndWaitForTimeout(std::move(options)).status,
      AuthenticatorStatus::NOT_ALLOWED_ERROR);

  ASSERT_TRUE(did_complete_);
  ASSERT_TRUE(error_.has_value());
  EXPECT_EQ(*error_, device::cablev2::authenticator::Platform::Error::
                         DISCOVERABLE_CREDENTIALS_REQUEST);
}

TEST_F(AuthenticatorCableV2AuthenticatorTest, PRFMakeCredential) {
  auto options = GetTestPublicKeyCredentialCreationOptions();
  options->prf_enable = true;

  const auto result = AuthenticatorMakeCredential(std::move(options));

  ASSERT_EQ(result.status, AuthenticatorStatus::SUCCESS);
  EXPECT_TRUE(result.response->echo_prf);
  EXPECT_TRUE(result.response->prf);
}

static std::vector<uint8_t> HashPRFInput(base::span<const uint8_t> input) {
  crypto::hash::Hasher hasher(crypto::hash::kSha256);
  // clang-format off
  constexpr auto kPrefix = std::to_array<uint8_t>({
      'W', 'e', 'b', 'A', 'u', 't', 'h', 'n',
      ' ', 'P', 'R', 'F',
      0x00,
  });
  // clang-format on
  hasher.Update(kPrefix);
  hasher.Update(input);
  std::array<uint8_t, crypto::hash::kSha256Size> result;
  hasher.Finish(result);
  return base::ToVector(result);
}

static std::tuple<PublicKeyCredentialRequestOptionsPtr,
                  std::vector<uint8_t>,
                  std::vector<uint8_t>>
BuildPRFGetAssertion(device::VirtualCtap2Device& virtual_device,
                     bool use_eval_by_credential) {
  const std::vector<uint8_t> input1(32, 1);
  const std::vector<uint8_t> input2(32, 2);
  const std::vector<uint8_t> salt1 = HashPRFInput(input1);
  const std::vector<uint8_t> salt2 = HashPRFInput(input2);
  const std::array<uint8_t, 32> key1 = {1};
  const std::array<uint8_t, 32> key2 = {2};
  const std::array<uint8_t, 32> output1 = crypto::hmac::SignSha256(key2, salt1);
  const std::array<uint8_t, 32> output2 = crypto::hmac::SignSha256(key2, salt2);
  auto options = GetTestPublicKeyCredentialRequestOptions();

  CHECK(virtual_device.mutable_state()->InjectRegistration(
      options->allow_credentials[0].id, options->relying_party_id));
  virtual_device.mutable_state()
      ->registrations.begin()
      ->second.hmac_key.emplace(key1, key2);

  std::vector<blink::mojom::PRFValuesPtr> prf_inputs;
  auto prf_value = blink::mojom::PRFValues::New();
  prf_value->first = input1;
  prf_value->second = input2;
  if (use_eval_by_credential) {
    prf_value->id = options->allow_credentials[0].id;
  }
  prf_inputs.emplace_back(std::move(prf_value));

  options->allow_credentials[0].transports.insert(
      device::FidoTransportProtocol::kHybrid);
  options->extensions->prf = true;
  options->extensions->prf_inputs = std::move(prf_inputs);
  options->user_verification = device::UserVerificationRequirement::kRequired;

  return std::make_tuple(std::move(options), base::ToVector(output1),
                         base::ToVector(output2));
}

TEST_F(AuthenticatorCableV2AuthenticatorTest, PRFGetAssertion) {
  PublicKeyCredentialRequestOptionsPtr options;
  std::vector<uint8_t> output1, output2;
  std::tie(options, output1, output2) = BuildPRFGetAssertion(
      virtual_device_, /* use_eval_by_credential= */ false);

  const auto result = AuthenticatorGetAssertion(std::move(options));

  ASSERT_EQ(result.status, AuthenticatorStatus::SUCCESS);
  EXPECT_TRUE(result.response->extensions->echo_prf);
  EXPECT_TRUE(result.response->extensions->prf_results);
  EXPECT_EQ(result.response->extensions->prf_results->first, output1);
  ASSERT_TRUE(result.response->extensions->prf_results->second.has_value());
  EXPECT_EQ(*result.response->extensions->prf_results->second, output2);
}

TEST_F(AuthenticatorCableV2AuthenticatorTest, PRFGetAssertionByCredential) {
  PublicKeyCredentialRequestOptionsPtr options;
  std::vector<uint8_t> output1, output2;
  std::tie(options, output1, output2) =
      BuildPRFGetAssertion(virtual_device_, /* use_eval_by_credential= */ true);

  const auto result = AuthenticatorGetAssertion(std::move(options));

  ASSERT_EQ(result.status, AuthenticatorStatus::SUCCESS);
  EXPECT_TRUE(result.response->extensions->echo_prf);
  EXPECT_TRUE(result.response->extensions->prf_results);
  EXPECT_EQ(result.response->extensions->prf_results->first, output1);
  ASSERT_TRUE(result.response->extensions->prf_results->second.has_value());
  EXPECT_EQ(*result.response->extensions->prf_results->second, output2);
}

// AuthenticatorImplWithRequestProxyTest tests behavior with an installed
// TestWebAuthenticationRequestProxy that takes over WebAuthn request handling.
class AuthenticatorImplWithRequestProxyTest : public AuthenticatorImplTest {
 protected:
  void SetUp() override {
    AuthenticatorImplTest::SetUp();
    old_client_ = SetBrowserClientForTesting(&test_client_);
    test_client_.GetTestWebAuthenticationDelegate()->request_proxy =
        std::make_unique<TestWebAuthenticationRequestProxy>();
  }

  void TearDown() override {
    SetBrowserClientForTesting(old_client_);
    AuthenticatorImplTest::TearDown();
  }

  TestWebAuthenticationRequestProxy& request_proxy() {
    return static_cast<TestWebAuthenticationRequestProxy&>(
        *test_client_.GetTestWebAuthenticationDelegate()->request_proxy);
  }

  raw_ptr<ContentBrowserClient> old_client_ = nullptr;
  TestAuthenticatorContentBrowserClient test_client_;
};

TEST_F(AuthenticatorImplWithRequestProxyTest, Inactive) {
  request_proxy().config().is_active = false;
  NavigateAndCommit(GURL(kTestOrigin1));
  AuthenticatorIsUvpaa();
  EXPECT_EQ(request_proxy().observations().num_isuvpaa, 0u);
}

TEST_F(AuthenticatorImplWithRequestProxyTest, IsUVPAA) {
  size_t i = 0;
  for (const bool is_uvpaa : {false, true}) {
    SCOPED_TRACE(testing::Message() << "is_uvpaa=" << is_uvpaa);
    request_proxy().config().is_uvpaa = is_uvpaa;
    NavigateAndCommit(GURL(kTestOrigin1));
    EXPECT_EQ(AuthenticatorIsUvpaa(), is_uvpaa);
    EXPECT_EQ(request_proxy().observations().num_isuvpaa, ++i);
  }
}

TEST_F(AuthenticatorImplWithRequestProxyTest, IsConditionalMediationAvailable) {
  // We can't autofill credentials over the request proxy. Hence, conditional
  // mediation is unavailable, even if IsUVPAA returns true.
  NavigateAndCommit(GURL(kTestOrigin1));

  // Ensure there is no test override set and we're testing the real
  // implementation.
  ASSERT_EQ(test_client_.GetTestWebAuthenticationDelegate()->is_uvpaa_override,
            std::nullopt);

  // Proxy says `IsUVPAA()` is true.
  request_proxy().config().is_uvpaa = true;
  EXPECT_TRUE(AuthenticatorIsUvpaa());
  EXPECT_EQ(request_proxy().observations().num_isuvpaa, 1u);

  // But `IsConditionalMediationAvailable()` still returns false, bypassing the
  // proxy.
  EXPECT_FALSE(AuthenticatorIsConditionalMediationAvailable());
  EXPECT_EQ(request_proxy().observations().num_isuvpaa, 1u);
}

TEST_F(AuthenticatorImplWithRequestProxyTest,
       GetClientCapabilities_ConditionalGet_ReturnsFalse) {
  // We can't autofill credentials over the request proxy. Hence, conditional
  // mediation is unavailable, even if IsUVPAA returns true.
  NavigateAndCommit(GURL(kTestOrigin1));
  ASSERT_EQ(test_client_.GetTestWebAuthenticationDelegate()->is_uvpaa_override,
            std::nullopt);
  request_proxy().config().is_uvpaa = true;

  // Internally, `IsConditionalMediationAvailable()` should returns `false`,
  // bypassing the proxy.
  ClientCapabilitiesList capabilities = AuthenticatorGetClientCapabilities();
  ExpectCapability(capabilities, client_capabilities::kConditionalGet, false);
}

TEST_F(AuthenticatorImplWithRequestProxyTest, MakeCredential) {
  request_proxy().config().request_success = true;
  request_proxy().config().make_credential_response =
      MakeCredentialAuthenticatorResponse::New();
  request_proxy().config().make_credential_response->info =
      CommonCredentialInfo::New();

  NavigateAndCommit(GURL(kTestOrigin1));
  auto request = GetTestPublicKeyCredentialCreationOptions();
  MakeCredentialResult result = AuthenticatorMakeCredential(request->Clone());

  EXPECT_EQ(result.status, AuthenticatorStatus::SUCCESS);
  EXPECT_EQ(request_proxy().observations().num_cancel, 0u);
  EXPECT_EQ(request_proxy().observations().create_requests.size(), 1u);

  auto expected = request->Clone();
  expected->remote_desktop_client_override = RemoteDesktopClientOverride::New();
  expected->remote_desktop_client_override->origin =
      url::Origin::Create(GURL(kTestOrigin1));
  expected->remote_desktop_client_override->same_origin_with_ancestors = true;
  EXPECT_EQ(request_proxy().observations().create_requests.at(0), expected);
}

// Verify requests with an attached proxy run RP ID checks.
TEST_F(AuthenticatorImplWithRequestProxyTest, MakeCredentialOriginAndRpIds) {
  request_proxy().config().request_success = true;
  request_proxy().config().make_credential_response =
      MakeCredentialAuthenticatorResponse::New();
  request_proxy().config().make_credential_response->info =
      CommonCredentialInfo::New();

  for (const OriginClaimedAuthorityPair& test_case : kInvalidRpTestCases) {
    SCOPED_TRACE(
        base::StrCat({test_case.claimed_authority, " ", test_case.origin}));

    NavigateAndCommit(GURL(test_case.origin));
    BrowserContext* context = main_rfh()->GetBrowserContext();
    ASSERT_TRUE(
        test_client_.GetWebAuthenticationDelegate()->MaybeGetRequestProxy(
            context, url::Origin::Create(GURL(test_case.origin))));

    PublicKeyCredentialCreationOptionsPtr options =
        GetTestPublicKeyCredentialCreationOptions();
    options->relying_party.id = test_case.claimed_authority;

    EXPECT_EQ(AuthenticatorMakeCredential(std::move(options)).status,
              test_case.expected_status);
    EXPECT_EQ(request_proxy().observations().create_requests.size(), 0u);
  }
}

// Tests that attempting to make a credential when a request is already proxied
// fails with NotAllowedError.
TEST_F(AuthenticatorImplWithRequestProxyTest, MakeCredentialAlreadyProxied) {
  GURL origin(kCorpCrdOrigin);
  test_client_.GetTestWebAuthenticationDelegate()
      ->remote_desktop_client_override_origin = url::Origin::Create(origin);
  NavigateAndCommit(origin);
  auto request = GetTestPublicKeyCredentialCreationOptions();
  request->remote_desktop_client_override =
      RemoteDesktopClientOverride::New(url::Origin::Create(origin), true);
  MakeCredentialResult result = AuthenticatorMakeCredential(std::move(request));

  EXPECT_EQ(result.status, AuthenticatorStatus::NOT_ALLOWED_ERROR);
  EXPECT_EQ(request_proxy().observations().create_requests.size(), 0u);
}

TEST_F(AuthenticatorImplWithRequestProxyTest, AppId) {
  request_proxy().config().request_success = true;
  request_proxy().config().make_credential_response =
      MakeCredentialAuthenticatorResponse::New();
  request_proxy().config().make_credential_response->info =
      CommonCredentialInfo::New();

  for (const auto& test_case : kValidAppIdCases) {
    SCOPED_TRACE(
        base::StrCat({test_case.claimed_authority, " ", test_case.origin}));

    BrowserContext* context = main_rfh()->GetBrowserContext();
    ASSERT_TRUE(
        test_client_.GetWebAuthenticationDelegate()->MaybeGetRequestProxy(
            context, url::Origin::Create(GURL(test_case.origin))));

    EXPECT_EQ(TryAuthenticationWithAppId(test_case.origin,
                                         test_case.claimed_authority),
              AuthenticatorStatus::SUCCESS);
    EXPECT_EQ(request_proxy().observations().get_requests.size(), 1u);
    request_proxy().observations().get_requests.clear();

    EXPECT_EQ(TryRegistrationWithAppIdExclude(test_case.origin,
                                              test_case.claimed_authority),
              AuthenticatorStatus::SUCCESS);
    EXPECT_EQ(request_proxy().observations().create_requests.size(), 1u);
    request_proxy().observations().create_requests.clear();
  }

  // Test invalid cases that should be rejected. `kInvalidRpTestCases`
  // contains a mix of RP ID an App ID cases, but they should all be rejected.
  for (const OriginClaimedAuthorityPair& test_case : kInvalidRpTestCases) {
    SCOPED_TRACE(
        base::StrCat({test_case.claimed_authority, " ", test_case.origin}));

    if (test_case.claimed_authority.empty()) {
      // In this case, no AppID is actually being tested.
      continue;
    }

    BrowserContext* context = main_rfh()->GetBrowserContext();
    ASSERT_TRUE(
        test_client_.GetWebAuthenticationDelegate()->MaybeGetRequestProxy(
            context, url::Origin::Create(GURL(test_case.origin))));

    AuthenticatorStatus test_status = TryAuthenticationWithAppId(
        test_case.origin, test_case.claimed_authority);
    EXPECT_TRUE(test_status == AuthenticatorStatus::INVALID_DOMAIN ||
                test_status == test_case.expected_status);
    EXPECT_EQ(request_proxy().observations().get_requests.size(), 0u);

    test_status = TryRegistrationWithAppIdExclude(test_case.origin,
                                                  test_case.claimed_authority);
    EXPECT_TRUE(test_status == AuthenticatorStatus::INVALID_DOMAIN ||
                test_status == test_case.expected_status);
    EXPECT_EQ(request_proxy().observations().create_requests.size(), 0u);
  }
}

TEST_F(AuthenticatorImplWithRequestProxyTest, MakeCredential_Timeout) {
  request_proxy().config().resolve_callbacks = false;
  request_proxy().config().request_success = true;
  request_proxy().config().make_credential_response =
      MakeCredentialAuthenticatorResponse::New();
  request_proxy().config().make_credential_response->info =
      CommonCredentialInfo::New();

  NavigateAndCommit(GURL(kTestOrigin1));
  MakeCredentialResult result = AuthenticatorMakeCredentialAndWaitForTimeout(
      GetTestPublicKeyCredentialCreationOptions());

  EXPECT_EQ(result.status, AuthenticatorStatus::NOT_ALLOWED_ERROR);
  EXPECT_EQ(request_proxy().observations().create_requests.size(), 1u);
  EXPECT_EQ(request_proxy().observations().num_cancel, 1u);

  // Proxy should not hold a pending request after cancellation.
  EXPECT_FALSE(request_proxy().HasPendingRequest());
}

TEST_F(AuthenticatorImplWithRequestProxyTest, GetAssertion) {
  request_proxy().config().request_success = true;
  request_proxy().config().get_assertion_response =
      GetAssertionAuthenticatorResponse::New();
  request_proxy().config().get_assertion_response->info =
      CommonCredentialInfo::New();
  request_proxy().config().get_assertion_response->extensions =
      AuthenticationExtensionsClientOutputs::New();

  NavigateAndCommit(GURL(kTestOrigin1));
  auto request = GetTestPublicKeyCredentialRequestOptions();
  GetAssertionResult result = AuthenticatorGetAssertion(request->Clone());

  EXPECT_EQ(result.status, AuthenticatorStatus::SUCCESS);
  EXPECT_EQ(request_proxy().observations().num_cancel, 0u);
  EXPECT_EQ(request_proxy().observations().get_requests.size(), 1u);

  auto expected = request->Clone();
  expected->extensions->remote_desktop_client_override =
      RemoteDesktopClientOverride::New();
  expected->extensions->remote_desktop_client_override->origin =
      url::Origin::Create(GURL(kTestOrigin1));
  expected->extensions->remote_desktop_client_override
      ->same_origin_with_ancestors = true;
  EXPECT_EQ(request_proxy().observations().get_requests.at(0), expected);
}

// Tests that attempting to get an assertion when a request is already proxied
// fails with NotAllowedError.
TEST_F(AuthenticatorImplWithRequestProxyTest, GetAssertionAlreadyProxied) {
  GURL origin(kCorpCrdOrigin);
  test_client_.GetTestWebAuthenticationDelegate()
      ->remote_desktop_client_override_origin = url::Origin::Create(origin);
  NavigateAndCommit(origin);
  auto request = GetTestPublicKeyCredentialRequestOptions();
  request->extensions->remote_desktop_client_override =
      RemoteDesktopClientOverride::New(url::Origin::Create(origin), true);
  GetAssertionResult result = AuthenticatorGetAssertion(std::move(request));

  EXPECT_EQ(result.status, AuthenticatorStatus::NOT_ALLOWED_ERROR);
  EXPECT_EQ(request_proxy().observations().get_requests.size(), 0u);
}

// Verify that Conditional UI requests are not proxied.
TEST_F(AuthenticatorImplWithRequestProxyTest, GetAssertionConditionalUI) {
  NavigateAndCommit(GURL(kTestOrigin1));
  auto request = GetTestPublicKeyCredentialRequestOptions();
  auto options = GetCredentialOptions::New();
  options->mediation = blink::mojom::Mediation::CONDITIONAL;
  options->public_key = std::move(request);
  GetAssertionResult result = AuthenticatorGetCredential(std::move(options));

  EXPECT_EQ(result.status, AuthenticatorStatus::NOT_ALLOWED_ERROR);
  EXPECT_EQ(request_proxy().observations().get_requests.size(), 0u);
}

// Verify requests with an attached proxy run RP ID checks.
TEST_F(AuthenticatorImplWithRequestProxyTest, GetAssertionOriginAndRpIds) {
  request_proxy().config().request_success = true;
  request_proxy().config().get_assertion_response =
      GetAssertionAuthenticatorResponse::New();
  request_proxy().config().get_assertion_response->info =
      CommonCredentialInfo::New();

  for (const OriginClaimedAuthorityPair& test_case : kInvalidRpTestCases) {
    SCOPED_TRACE(
        base::StrCat({test_case.claimed_authority, " ", test_case.origin}));

    NavigateAndCommit(GURL(test_case.origin));
    BrowserContext* context = main_rfh()->GetBrowserContext();
    ASSERT_TRUE(
        test_client_.GetWebAuthenticationDelegate()->MaybeGetRequestProxy(
            context, url::Origin::Create(GURL(test_case.origin))));

    PublicKeyCredentialRequestOptionsPtr options =
        GetTestPublicKeyCredentialRequestOptions();
    options->relying_party_id = test_case.claimed_authority;

    EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
              test_case.expected_status);
    EXPECT_EQ(request_proxy().observations().get_requests.size(), 0u);
  }
}

TEST_F(AuthenticatorImplWithRequestProxyTest, GetAssertion_Timeout) {
  request_proxy().config().resolve_callbacks = false;
  request_proxy().config().request_success = true;
  request_proxy().config().get_assertion_response =
      GetAssertionAuthenticatorResponse::New();
  request_proxy().config().get_assertion_response->info =
      CommonCredentialInfo::New();

  NavigateAndCommit(GURL(kTestOrigin1));
  GetAssertionResult result = AuthenticatorGetAssertionAndWaitForTimeout(
      GetTestPublicKeyCredentialRequestOptions());

  EXPECT_EQ(result.status, AuthenticatorStatus::NOT_ALLOWED_ERROR);
  EXPECT_EQ(request_proxy().observations().get_requests.size(), 1u);
  EXPECT_EQ(request_proxy().observations().num_cancel, 1u);

  // Proxy should not hold a pending request after cancellation.
  EXPECT_FALSE(request_proxy().HasPendingRequest());
}

TEST_F(AuthenticatorImplWithRequestProxyTest,
       VirtualAuthenticatorTakesPrecedence) {
  // With the virtual authenticator enabled, no requests should hit the proxy.
  content::AuthenticatorEnvironment::GetInstance()
      ->EnableVirtualAuthenticatorFor(
          static_cast<content::RenderFrameHostImpl*>(main_rfh())
              ->frame_tree_node(),
          /*enable_ui=*/false);
  test_client_.GetTestWebAuthenticationDelegate()->is_uvpaa_override = true;

  NavigateAndCommit(GURL(kTestOrigin1));
  ASSERT_TRUE(
      request_proxy().IsActive(url::Origin::Create(GURL(kTestOrigin1))));

  {
    MakeCredentialResult result = AuthenticatorMakeCredential(
        GetTestPublicKeyCredentialCreationOptions());
    EXPECT_EQ(result.status, AuthenticatorStatus::SUCCESS);
    EXPECT_EQ(request_proxy().observations().create_requests.size(), 0u);
  }

  {
    GetAssertionResult result =
        AuthenticatorGetAssertion(GetTestPublicKeyCredentialRequestOptions());
    EXPECT_EQ(result.status, AuthenticatorStatus::NOT_ALLOWED_ERROR);
    EXPECT_EQ(request_proxy().observations().get_requests.size(), 0u);
  }

  EXPECT_TRUE(AuthenticatorIsUvpaa());
  EXPECT_EQ(request_proxy().observations().num_isuvpaa, 0u);
  EXPECT_TRUE(AuthenticatorIsConditionalMediationAvailable());
  EXPECT_EQ(request_proxy().observations().num_isuvpaa, 0u);
}

}  // namespace content
