// 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 <list>
#include <memory>
#include <string>
#include <utility>
#include <vector>

#include "base/base64url.h"
#include "base/compiler_specific.h"
#include "base/containers/contains.h"
#include "base/containers/flat_set.h"
#include "base/files/file.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ptr_exclusion.h"
#include "base/path_service.h"
#include "base/rand_util.h"
#include "base/ranges/algorithm.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/strings/utf_string_conversions.h"
#include "base/system/sys_info.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/bind.h"
#include "base/test/gtest_util.h"
#include "base/test/scoped_command_line.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_mock_time_task_runner.h"
#include "base/time/tick_clock.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "components/cbor/reader.h"
#include "components/cbor/values.h"
#include "components/webauthn/content/browser/internal_authenticator_impl.h"
#include "content/browser/webauth/authenticator_common_impl.h"
#include "content/browser/webauth/authenticator_environment.h"
#include "content/browser/webauth/client_data_json.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/common/content_client.h"
#include "content/public/common/content_features.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_browser_context.h"
#include "content/test/test_render_frame_host.h"
#include "crypto/sha2.h"
#include "device/base/features.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/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_parsing_utils.h"
#include "device/fido/fido_test_data.h"
#include "device/fido/fido_transport_protocol.h"
#include "device/fido/fido_types.h"
#include "device/fido/filter.h"
#include "device/fido/hid/fake_hid_impl_for_testing.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.h"
#include "device/fido/public_key_credential_descriptor.h"
#include "device/fido/public_key_credential_user_entity.h"
#include "device/fido/test_callback_receiver.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/pending_receiver.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/network/public/mojom/network_context.mojom.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/bytestring.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/hmac.h"
#include "third_party/boringssl/src/include/openssl/obj.h"
#include "third_party/zlib/google/compression_utils.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/resource/resource_scale_factor.h"
#include "ui/base/ui_base_paths.h"
#include "url/origin.h"
#include "url/url_util.h"

#if BUILDFLAG(IS_MAC)
#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 "device/fido/win/fake_webauthn_api.h"
#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::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::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 FailureReasonCallbackReceiver =
    ::device::test::TestCallbackReceiver<InterestingFailureReason>;

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

// The size of credential IDs returned by GetTestCredentials().
constexpr size_t kTestCredentialIdLength = 32u;

constexpr char kTestOrigin1[] = "https://a.google.com";
constexpr char kTestOrigin2[] = "https://acme.org";
constexpr char kTestRelyingPartyId[] = "google.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"})";

typedef struct {
  const char* origin;
  // Either a relying party ID or a U2F AppID.
  const char* claimed_authority;
  AuthenticatorStatus expected_status;
} OriginClaimedAuthorityPair;

constexpr OriginClaimedAuthorityPair kValidRelyingPartyTestCases[] = {
    {"http://localhost", "localhost", AuthenticatorStatus::SUCCESS},
    {"https://myawesomedomain", "myawesomedomain",
     AuthenticatorStatus::SUCCESS},
    {"https://foo.bar.google.com", "foo.bar.google.com",
     AuthenticatorStatus::SUCCESS},
    {"https://foo.bar.google.com", "bar.google.com",
     AuthenticatorStatus::SUCCESS},
    {"https://foo.bar.google.com", "google.com", AuthenticatorStatus::SUCCESS},
    {"https://earth.login.awesomecompany", "login.awesomecompany",
     AuthenticatorStatus::SUCCESS},
    {"https://google.com:1337", "google.com", AuthenticatorStatus::SUCCESS},

    // Hosts with trailing dot valid for rpIds with or without trailing dot.
    // Hosts without trailing dots only matches rpIDs without trailing dot.
    // Two trailing dots only matches rpIDs with two trailing dots.
    {"https://google.com.", "google.com", AuthenticatorStatus::SUCCESS},
    {"https://google.com.", "google.com.", AuthenticatorStatus::SUCCESS},
    {"https://google.com..", "google.com..", AuthenticatorStatus::SUCCESS},

    // Leading dots are ignored in canonicalized hosts.
    {"https://.google.com", "google.com", AuthenticatorStatus::SUCCESS},
    {"https://..google.com", "google.com", AuthenticatorStatus::SUCCESS},
    {"https://.google.com", ".google.com", AuthenticatorStatus::SUCCESS},
    {"https://..google.com", ".google.com", AuthenticatorStatus::SUCCESS},
    {"https://accounts.google.com", ".google.com",
     AuthenticatorStatus::SUCCESS},
};

constexpr OriginClaimedAuthorityPair kInvalidRelyingPartyTestCases[] = {
    {"https://google.com", "com", AuthenticatorStatus::BAD_RELYING_PARTY_ID},
    {"http://google.com", "google.com", AuthenticatorStatus::INVALID_DOMAIN},
    {"http://myawesomedomain", "myawesomedomain",
     AuthenticatorStatus::INVALID_DOMAIN},
    {"https://google.com", "foo.bar.google.com",
     AuthenticatorStatus::BAD_RELYING_PARTY_ID},
    {"http://myawesomedomain", "randomdomain",
     AuthenticatorStatus::INVALID_DOMAIN},
    {"https://myawesomedomain", "randomdomain",
     AuthenticatorStatus::BAD_RELYING_PARTY_ID},
    {"https://notgoogle.com", "google.com)",
     AuthenticatorStatus::BAD_RELYING_PARTY_ID},
    {"https://not-google.com", "google.com)",
     AuthenticatorStatus::BAD_RELYING_PARTY_ID},
    {"https://evil.appspot.com", "appspot.com",
     AuthenticatorStatus::BAD_RELYING_PARTY_ID},
    {"https://evil.co.uk", "co.uk", AuthenticatorStatus::BAD_RELYING_PARTY_ID},

    {"https://google.com", "google.com.",
     AuthenticatorStatus::BAD_RELYING_PARTY_ID},
    {"https://google.com", "google.com..",
     AuthenticatorStatus::BAD_RELYING_PARTY_ID},
    {"https://google.com", ".google.com",
     AuthenticatorStatus::BAD_RELYING_PARTY_ID},
    {"https://google.com..", "google.com",
     AuthenticatorStatus::BAD_RELYING_PARTY_ID},
    {"https://.com", "com.", AuthenticatorStatus::BAD_RELYING_PARTY_ID},
    {"https://.co.uk", "co.uk.", AuthenticatorStatus::BAD_RELYING_PARTY_ID},

    {"https://1.2.3", "1.2.3", AuthenticatorStatus::INVALID_DOMAIN},
    {"https://1.2.3", "2.3", AuthenticatorStatus::INVALID_DOMAIN},

    {"https://127.0.0.1", "127.0.0.1", AuthenticatorStatus::INVALID_DOMAIN},
    {"https://127.0.0.1", "27.0.0.1", AuthenticatorStatus::INVALID_DOMAIN},
    {"https://127.0.0.1", ".0.0.1", AuthenticatorStatus::INVALID_DOMAIN},
    {"https://127.0.0.1", "0.0.1", AuthenticatorStatus::INVALID_DOMAIN},

    {"https://[::127.0.0.1]", "127.0.0.1", AuthenticatorStatus::INVALID_DOMAIN},
    {"https://[::127.0.0.1]", "[127.0.0.1]",
     AuthenticatorStatus::INVALID_DOMAIN},

    {"https://[::1]", "1", AuthenticatorStatus::INVALID_DOMAIN},
    {"https://[::1]", "1]", AuthenticatorStatus::INVALID_DOMAIN},
    {"https://[::1]", "::1", AuthenticatorStatus::INVALID_DOMAIN},
    {"https://[::1]", "[::1]", AuthenticatorStatus::INVALID_DOMAIN},
    {"https://[1::1]", "::1", AuthenticatorStatus::INVALID_DOMAIN},
    {"https://[1::1]", "::1]", AuthenticatorStatus::INVALID_DOMAIN},
    {"https://[1::1]", "[::1]", AuthenticatorStatus::INVALID_DOMAIN},

    {"http://google.com:443", "google.com",
     AuthenticatorStatus::INVALID_DOMAIN},
    {"data:google.com", "google.com", AuthenticatorStatus::OPAQUE_DOMAIN},
    {"data:text/html,google.com", "google.com",
     AuthenticatorStatus::OPAQUE_DOMAIN},
    {"ws://google.com", "google.com", AuthenticatorStatus::INVALID_PROTOCOL},
    {"gopher://google.com", "google.com", AuthenticatorStatus::OPAQUE_DOMAIN},
    {"ftp://google.com", "google.com", AuthenticatorStatus::INVALID_PROTOCOL},
    {"file:///google.com", "google.com", AuthenticatorStatus::INVALID_PROTOCOL},
    // Use of webauthn from a WSS origin may be technically valid, but we
    // prohibit use on non-HTTPS origins. (At least for now.)
    {"wss://google.com", "google.com", AuthenticatorStatus::INVALID_PROTOCOL},

    {"data:,", "", AuthenticatorStatus::OPAQUE_DOMAIN},
    {"https://google.com", "", AuthenticatorStatus::BAD_RELYING_PARTY_ID},
    {"ws:///google.com", "", AuthenticatorStatus::INVALID_PROTOCOL},
    {"wss:///google.com", "", AuthenticatorStatus::INVALID_PROTOCOL},
    {"gopher://google.com", "", AuthenticatorStatus::OPAQUE_DOMAIN},
    {"ftp://google.com", "", AuthenticatorStatus::INVALID_PROTOCOL},
    {"file:///google.com", "", AuthenticatorStatus::INVALID_PROTOCOL},

    // This case is acceptable according to spec, but both renderer
    // and browser handling currently do not permit it.
    {"https://login.awesomecompany", "awesomecompany",
     AuthenticatorStatus::BAD_RELYING_PARTY_ID},

    // These are AppID test cases, but should also be invalid relying party
    // examples too.
    {"https://example.com", "https://com/",
     AuthenticatorStatus::BAD_RELYING_PARTY_ID},
    {"https://example.com", "https://com/foo",
     AuthenticatorStatus::BAD_RELYING_PARTY_ID},
    {"https://example.com", "https://foo.com/",
     AuthenticatorStatus::BAD_RELYING_PARTY_ID},
    {"https://example.com", "http://example.com",
     AuthenticatorStatus::BAD_RELYING_PARTY_ID},
    {"http://example.com", "https://example.com",
     AuthenticatorStatus::INVALID_DOMAIN},
    {"https://127.0.0.1", "https://127.0.0.1",
     AuthenticatorStatus::INVALID_DOMAIN},
    {"https://www.notgoogle.com",
     "https://www.gstatic.com/securitykey/origins.json",
     AuthenticatorStatus::BAD_RELYING_PARTY_ID},
    {"https://www.google.com",
     "https://www.gstatic.com/securitykey/origins.json#x",
     AuthenticatorStatus::BAD_RELYING_PARTY_ID},
    {"https://www.google.com",
     "https://www.gstatic.com/securitykey/origins.json2",
     AuthenticatorStatus::BAD_RELYING_PARTY_ID},
    {"https://www.google.com", "https://gstatic.com/securitykey/origins.json",
     AuthenticatorStatus::BAD_RELYING_PARTY_ID},
    {"https://ggoogle.com", "https://www.gstatic.com/securitykey/origi",
     AuthenticatorStatus::BAD_RELYING_PARTY_ID},
    {"https://com", "https://www.gstatic.com/securitykey/origins.json",
     AuthenticatorStatus::BAD_RELYING_PARTY_ID},
};

using TestIsUvpaaCallback = device::test::ValueCallbackReceiver<bool>;
using TestMakeCredentialCallback =
    device::test::StatusAndValuesCallbackReceiver<
        AuthenticatorStatus,
        MakeCredentialAuthenticatorResponsePtr,
        WebAuthnDOMExceptionDetailsPtr>;
using TestGetAssertionCallback = device::test::StatusAndValuesCallbackReceiver<
    AuthenticatorStatus,
    GetAssertionAuthenticatorResponsePtr,
    WebAuthnDOMExceptionDetailsPtr>;
using TestRequestStartedCallback = device::test::TestCallbackReceiver<>;

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

device::PublicKeyCredentialRpEntity GetTestPublicKeyCredentialRPEntity() {
  device::PublicKeyCredentialRpEntity entity;
  entity.id = std::string(kTestRelyingPartyId);
  entity.name = "TestRP@example.com";
  return entity;
}

device::PublicKeyCredentialUserEntity GetTestPublicKeyCredentialUserEntity() {
  device::PublicKeyCredentialUserEntity entity;
  entity.display_name = "User A. Name";
  std::vector<uint8_t> id(32, 0x0A);
  entity.id = id;
  entity.name = "username@example.com";
  return entity;
}

std::vector<device::PublicKeyCredentialParams::CredentialInfo>
GetTestPublicKeyCredentialParameters(int32_t algorithm_identifier) {
  std::vector<device::PublicKeyCredentialParams::CredentialInfo> parameters;
  device::PublicKeyCredentialParams::CredentialInfo fake_parameter;
  fake_parameter.type = device::CredentialType::kPublicKey;
  fake_parameter.algorithm = algorithm_identifier;
  parameters.push_back(std::move(fake_parameter));
  return parameters;
}

device::AuthenticatorSelectionCriteria GetTestAuthenticatorSelectionCriteria() {
  return device::AuthenticatorSelectionCriteria(
      device::AuthenticatorAttachment::kAny,
      device::ResidentKeyRequirement::kDiscouraged,
      device::UserVerificationRequirement::kPreferred);
}

std::vector<device::PublicKeyCredentialDescriptor> GetTestCredentials(
    size_t num_credentials = 1) {
  std::vector<device::PublicKeyCredentialDescriptor> descriptors;
  for (size_t i = 0; i < num_credentials; i++) {
    DCHECK(i <= std::numeric_limits<uint8_t>::max());
    std::vector<uint8_t> id(kTestCredentialIdLength, static_cast<uint8_t>(i));
    base::flat_set<device::FidoTransportProtocol> transports{
        device::FidoTransportProtocol::kUsbHumanInterfaceDevice,
        device::FidoTransportProtocol::kBluetoothLowEnergy};
    descriptors.emplace_back(device::CredentialType::kPublicKey, std::move(id),
                             std::move(transports));
  }
  return descriptors;
}

PublicKeyCredentialCreationOptionsPtr
GetTestPublicKeyCredentialCreationOptions() {
  auto options = PublicKeyCredentialCreationOptions::New();
  options->relying_party = GetTestPublicKeyCredentialRPEntity();
  options->user = GetTestPublicKeyCredentialUserEntity();
  options->public_key_parameters = GetTestPublicKeyCredentialParameters(
      static_cast<int32_t>(device::CoseAlgorithmIdentifier::kEs256));
  options->challenge.assign(32, 0x0A);
  options->timeout = base::Minutes(1);
  options->authenticator_selection = GetTestAuthenticatorSelectionCriteria();
  return options;
}

PublicKeyCredentialRequestOptionsPtr
GetTestPublicKeyCredentialRequestOptions() {
  auto options = PublicKeyCredentialRequestOptions::New();
  options->extensions = AuthenticationExtensionsClientInputs::New();
  options->relying_party_id = std::string(kTestRelyingPartyId);
  options->challenge.assign(32, 0x0A);
  options->timeout = base::Minutes(1);
  options->user_verification = device::UserVerificationRequirement::kPreferred;
  options->allow_credentials = GetTestCredentials();
  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) {
  absl::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();
  absl::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) {
  absl::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(ClientDataRequestType type) {
  return BuildClientDataJson({std::move(type), 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(
                [&](absl::optional<mojo_base::BigBuffer> result) {
                  compressed = device::fido_parsing_utils::Materialize(*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(
          [&](absl::optional<mojo_base::BigBuffer> result) {
            if (result) {
              uncompressed = device::fido_parsing_utils::Materialize(*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;
  }
}

std::array<uint8_t, crypto::kSHA256Length> EvaluateHMAC(
    base::span<const uint8_t> key,
    base::span<const uint8_t> salt) {
  std::array<uint8_t, crypto::kSHA256Length> ret;
  unsigned hmac_out_length;
  HMAC(EVP_sha256(), key.data(), key.size(), salt.data(), salt.size(),
       ret.data(), &hmac_out_length);
  CHECK_EQ(hmac_out_length, ret.size());
  return ret;
}

}  // namespace

class AuthenticatorTestBase : public RenderViewHostTestHarness {
 protected:
  AuthenticatorTestBase()
      : RenderViewHostTestHarness(
            base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
  ~AuthenticatorTestBase() override = default;

  static void SetUpTestSuite() {
#if BUILDFLAG(IS_MAC)
    // Load fido_strings, which can be required for exercising the Touch ID
    // authenticator.
    base::FilePath path;
    ASSERT_TRUE(base::PathService::Get(base::DIR_ASSETS, &path));
    base::FilePath fido_test_strings =
        path.Append(FILE_PATH_LITERAL("fido_test_strings.pak"));
    ui::ResourceBundle::GetSharedInstance().AddDataPackFromPath(
        fido_test_strings, ui::kScaleFactorNone);
#endif
  }

  void SetUp() override {
    RenderViewHostTestHarness::SetUp();

    mojo::SetDefaultProcessErrorHandler(base::BindRepeating(
        &AuthenticatorTestBase::OnMojoError, base::Unretained(this)));

#if BUILDFLAG(IS_CHROMEOS)
    chromeos::TpmManagerClient::InitializeFake();
    chromeos::U2FClient::InitializeFake();
#endif

#if BUILDFLAG(IS_WIN)
    // Disable the Windows WebAuthn API integration by default. Individual tests
    // can modify this.
    fake_win_webauthn_api_.set_available(false);
#endif

    ResetVirtualDevice();
  }

  void TearDown() override {
    RenderViewHostTestHarness::TearDown();

    mojo::SetDefaultProcessErrorHandler(base::NullCallback());

    AuthenticatorEnvironment::GetInstance()->Reset();
#if BUILDFLAG(IS_CHROMEOS)
    chromeos::U2FClient::Shutdown();
    chromeos::TpmManagerClient::Shutdown();
#endif
  }

  virtual void ResetVirtualDevice() {
    auto virtual_device_factory =
        std::make_unique<device::test::VirtualFidoDeviceFactory>();
    virtual_device_factory_ = virtual_device_factory.get();
    AuthenticatorEnvironment::GetInstance()
        ->ReplaceDefaultDiscoveryFactoryForTesting(
            std::move(virtual_device_factory));
  }

  void SetMojoErrorHandler(
      base::RepeatingCallback<void(const std::string&)> callback) {
    mojo_error_handler_ = callback;
  }

  raw_ptr<device::test::VirtualFidoDeviceFactory, DanglingUntriaged>
      virtual_device_factory_;
#if BUILDFLAG(IS_WIN)
  device::FakeWinWebAuthnApi fake_win_webauthn_api_;
  device::WinWebAuthnApi::ScopedOverride win_webauthn_api_override_{
      &fake_win_webauthn_api_};
#endif

 private:
  void OnMojoError(const std::string& error) {
    if (mojo_error_handler_) {
      mojo_error_handler_.Run(error);
      return;
    }
    FAIL() << "Unhandled mojo error: " << error;
  }

  base::RepeatingCallback<void(const std::string&)> mojo_error_handler_;
};

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

  void SetUp() override {
    AuthenticatorTestBase::SetUp();
    bluetooth_global_values_->SetLESupported(true);
    device::BluetoothAdapterFactory::SetAdapterForTesting(mock_adapter_);
  }

  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() {
    TestIsUvpaaCallback cb;
    mojo::Remote<blink::mojom::Authenticator> authenticator =
        ConnectToAuthenticator();
    authenticator->IsUserVerifyingPlatformAuthenticatorAvailable(cb.callback());
    cb.WaitForCallback();
    return cb.value();
  }

  bool AuthenticatorIsConditionalMediationAvailable() {
    TestIsUvpaaCallback cb;
    mojo::Remote<blink::mojom::Authenticator> authenticator =
        ConnectToAuthenticator();
    authenticator->IsConditionalMediationAvailable(cb.callback());
    cb.WaitForCallback();
    return cb.value();
  }

  struct MakeCredentialResult {
    AuthenticatorStatus status;
    MakeCredentialAuthenticatorResponsePtr response;
  };

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

  MakeCredentialResult AuthenticatorMakeCredential(
      PublicKeyCredentialCreationOptionsPtr options) {
    mojo::Remote<blink::mojom::Authenticator> authenticator =
        ConnectToAuthenticator();
    TestMakeCredentialCallback callback_receiver;
    authenticator->MakeCredential(std::move(options),
                                  callback_receiver.callback());
    callback_receiver.WaitForCallback();
    auto [status, response, dom_exception] = callback_receiver.TakeResult();
    return {status, std::move(response)};
  }

  MakeCredentialResult AuthenticatorMakeCredentialAndWaitForTimeout(
      PublicKeyCredentialCreationOptionsPtr options) {
    mojo::Remote<blink::mojom::Authenticator> authenticator =
        ConnectToAuthenticator();
    TestMakeCredentialCallback callback_receiver;
    authenticator->MakeCredential(std::move(options),
                                  callback_receiver.callback());
    task_environment()->FastForwardBy(kTestTimeout);
    callback_receiver.WaitForCallback();
    auto [status, response, dom_exception] = callback_receiver.TakeResult();
    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();
    TestGetAssertionCallback callback_receiver;
    authenticator->GetAssertion(std::move(options),
                                callback_receiver.callback());
    callback_receiver.WaitForCallback();
    auto [status, response, dom_exception] = callback_receiver.TakeResult();
    return {status, std::move(response)};
  }

  GetAssertionResult AuthenticatorGetAssertionAndWaitForTimeout(
      PublicKeyCredentialRequestOptionsPtr options) {
    mojo::Remote<blink::mojom::Authenticator> authenticator =
        ConnectToAuthenticator();
    TestGetAssertionCallback callback_receiver;
    authenticator->GetAssertion(std::move(options),
                                callback_receiver.callback());
    task_environment()->FastForwardBy(kTestTimeout);
    auto [status, response, dom_exception] = callback_receiver.TakeResult();
    return {status, std::move(response)};
  }

  AuthenticatorStatus TryAuthenticationWithAppId(const std::string& origin,
                                                 const std::string& 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(
      const std::string& origin,
      const std::string& 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;
  }

  // HasDevicePublicKeyExtensionInAuthenticatorData returns true if `response`
  // contains a DPK extension in the authenticator data of the response.
  bool HasDevicePublicKeyExtensionInAuthenticatorData(
      const MakeCredentialAuthenticatorResponsePtr& response) {
    device::AuthenticatorData parsed_auth_data =
        AuthDataFromMakeCredentialResponse(response);

    const auto& extensions = parsed_auth_data.extensions();
    if (!extensions) {
      return false;
    }

    const cbor::Value::MapValue& extensions_map = extensions->GetMap();
    return extensions_map.find(cbor::Value(
               device::kExtensionDevicePublicKey)) != extensions_map.end();
  }

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

 private:
  std::unique_ptr<device::BluetoothAdapterFactory::GlobalValuesForTesting>
      bluetooth_global_values_ =
          device::BluetoothAdapterFactory::Get()->InitGlobalValuesForTesting();
  data_decoder::test::InProcessDataDecoder data_decoder_service_;
  url::ScopedSchemeRegistryForTests scoped_registry_;
};

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({ClientDataRequestType::kWebAuthnCreate,
                           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 ClientDataRequestType type;
    url::Origin origin;
    std::vector<uint8_t> challenge;
    bool is_cross_origin;
  } kTestCases[] = {
      {
          ClientDataRequestType::kWebAuthnGet,
          GetTestOrigin(),
          {1, 2, 3},
          false,
      },
      {
          ClientDataRequestType::kPaymentGet,
          GetTestOrigin(),
          {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.challenge, test.is_cross_origin});

    const auto parsed = base::JSONReader::Read(json);
    ASSERT_TRUE(parsed.has_value());
    std::string type_key;
    std::string expected_type;
    switch (test.type) {
      case ClientDataRequestType::kWebAuthnCreate:
        type_key = "type";
        expected_type = "webauthn.create";
        break;
      case ClientDataRequestType::kWebAuthnGet:
        type_key = "type";
        expected_type = "webauthn.get";
        break;
      case 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(
        base::StringPiece(reinterpret_cast<const char*>(test.challenge.data()),
                          test.challenge.size()),
        base::Base64UrlEncodePolicy::OMIT_PADDING, &expected_challenge);
    EXPECT_EQ(*parsed->GetDict().FindString("challenge"), expected_challenge);
    EXPECT_EQ(*parsed->GetDict().FindBool("crossOrigin"), test.is_cross_origin);
  }
}

// Verify behavior for various combinations of origins and RP IDs.
TEST_F(AuthenticatorImplTest, MakeCredentialOriginAndRpIds) {
  std::vector<OriginClaimedAuthorityPair> tests(
      &kValidRelyingPartyTestCases[0],
      &kValidRelyingPartyTestCases[std::size(kValidRelyingPartyTestCases)]);
  tests.insert(
      tests.end(), &kInvalidRelyingPartyTestCases[0],
      &kInvalidRelyingPartyTestCases[std::size(kInvalidRelyingPartyTestCases)]);

  for (const auto& test_case : tests) {
    SCOPED_TRACE(std::string(test_case.claimed_authority) + " " +
                 std::string(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);
  }
}

// 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);
}

// 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);
}

// 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(base::StringPiece subset_str,
                                    base::StringPiece test_str) {
  absl::optional<base::Value> subset = base::JSONReader::Read(subset_str);
  ASSERT_TRUE(subset);
  ASSERT_TRUE(subset->is_dict());
  const base::Value::Dict& subset_dict = subset->GetDict();
  absl::optional<base::Value> test = base::JSONReader::Read(test_str);
  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(ClientDataRequestType::kWebAuthnCreate));
}

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

TEST_F(AuthenticatorImplTest, TestMakeCredentialTimeout) {
  // 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);
}

// 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 :
       kInvalidRelyingPartyTestCases) {
    SCOPED_TRACE(std::string(test_case.claimed_authority) + " " +
                 std::string(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);
  }
}

constexpr OriginClaimedAuthorityPair kValidAppIdCases[] = {
    {"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(std::string(test_case.origin) + " " +
                 std::string(test_case.claimed_authority));

    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 : kInvalidRelyingPartyTestCases) {
    SCOPED_TRACE(std::string(test_case.origin) + " " +
                 std::string(test_case.claimed_authority));

    if (strlen(test_case.claimed_authority) == 0) {
      // 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.
  AuthenticatorEnvironment::GetInstance()
      ->ReplaceDefaultDiscoveryFactoryForTesting(
          std::make_unique<device::FidoDiscoveryFactory>());
  NavigateAndCommit(GURL(kTestOrigin1));
  PublicKeyCredentialRequestOptionsPtr options =
      GetTestPublicKeyCredentialRequestOptions();

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

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);
}

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);
}

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

  // Make first request.
  PublicKeyCredentialCreationOptionsPtr options =
      GetTestPublicKeyCredentialCreationOptions();
  TestMakeCredentialCallback callback_receiver;
  authenticator->MakeCredential(std::move(options),
                                callback_receiver.callback());

  // Make second request.
  // TODO(crbug.com/785955): Rework to ensure there are potential race
  // conditions once we have VirtualAuthenticatorEnvironment.
  PublicKeyCredentialCreationOptionsPtr options2 =
      GetTestPublicKeyCredentialCreationOptions();
  TestMakeCredentialCallback callback_receiver2;
  authenticator->MakeCredential(std::move(options2),
                                callback_receiver2.callback());
  callback_receiver2.WaitForCallback();

  EXPECT_EQ(AuthenticatorStatus::PENDING_REQUEST, callback_receiver2.status());

  callback_receiver.WaitForCallback();
}

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

  // Make first request.
  PublicKeyCredentialRequestOptionsPtr options =
      GetTestPublicKeyCredentialRequestOptions();
  TestGetAssertionCallback callback_receiver;
  authenticator->GetAssertion(std::move(options), callback_receiver.callback());

  // Make second request.
  // TODO(crbug.com/785955): Rework to ensure there are potential race
  // conditions once we have VirtualAuthenticatorEnvironment.
  PublicKeyCredentialRequestOptionsPtr options2 =
      GetTestPublicKeyCredentialRequestOptions();
  TestGetAssertionCallback callback_receiver2;
  authenticator->GetAssertion(std::move(options2),
                              callback_receiver2.callback());
  callback_receiver2.WaitForCallback();

  EXPECT_EQ(AuthenticatorStatus::PENDING_REQUEST, callback_receiver2.status());

  callback_receiver.WaitForCallback();
}

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.
  PublicKeyCredentialRequestOptionsPtr options =
      GetTestPublicKeyCredentialRequestOptions();
  TestGetAssertionCallback callback_receiver;
  authenticator->GetAssertion(std::move(options), callback_receiver.callback());

  // 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);
    // 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);
}

TEST_F(AuthenticatorImplTest, GPMPasskeys_IsConditionalMediationAvailable) {
  // Conditional mediation should always be available if gpm passkeys are
  // enabled.
  base::test::ScopedFeatureList scoped_feature_list;
  scoped_feature_list.InitWithFeatures(
      {device::kWebAuthnListSyncedPasskeys, device::kWebAuthnNewPasskeyUI},
      /*disabled_features=*/{});
  NavigateAndCommit(GURL(kTestOrigin1));
  ASSERT_TRUE(AuthenticatorIsConditionalMediationAvailable());
}

#if BUILDFLAG(IS_WIN)
TEST_F(AuthenticatorImplTest, 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");

      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)

#if BUILDFLAG(IS_WIN)
class OffTheRecordAuthenticatorImplTest : public AuthenticatorImplTest {
 protected:
  std::unique_ptr<BrowserContext> CreateBrowserContext() override {
    auto browser_context = std::make_unique<TestBrowserContext>();
    browser_context->set_is_off_the_record(true);
    return browser_context;
  }
};

// Tests that IsUVPAA returns true if the version of Windows supports an
// appropriate warning.
TEST_F(OffTheRecordAuthenticatorImplTest, WinIsUVPAAIncognito) {
  virtual_device_factory_->set_discover_win_webauthn_api_authenticator(true);
  NavigateAndCommit(GURL(kTestOrigin1));
  fake_win_webauthn_api_.set_available(true);
  fake_win_webauthn_api_.set_is_uvpaa(true);

  for (bool win_api_supports_incognito_warning : {false, true}) {
    SCOPED_TRACE(win_api_supports_incognito_warning
                     ? "supports incognito"
                     : "does not support incognito");
    fake_win_webauthn_api_.set_version(win_api_supports_incognito_warning
                                           ? WEBAUTHN_API_VERSION_4
                                           : WEBAUTHN_API_VERSION_3);
    EXPECT_EQ(AuthenticatorIsUvpaa(), win_api_supports_incognito_warning);
  }
}
#endif  // BUILDFLAG(IS_WIN)

// TestWebAuthenticationRequestProxy is a test fake implementation of the
// WebAuthenticationRequestProxy embedder interface.
class TestWebAuthenticationRequestProxy : public WebAuthenticationRequestProxy {
 public:
  struct Config {
    // If true, resolves all request event callbacks instantly.
    bool resolve_callbacks = true;

    // The return value of IsActive().
    bool is_active = true;

    // The fake response to SignalIsUVPAARequest().
    bool is_uvpaa = true;

    // Whether the request to SignalCreateRequest() should succeed.
    bool request_success = true;

    // If `request_success` is false, the name of the DOMError to be
    // returned.
    std::string request_error_name = "NotAllowedError";

    // If `request_success` is true, the fake response to be returned for an
    // onCreateRequest event.
    blink::mojom::MakeCredentialAuthenticatorResponsePtr
        make_credential_response = nullptr;

    // If `request_success` is true, the fake response to be returned for an
    // onGetRequest event.
    blink::mojom::GetAssertionAuthenticatorResponsePtr get_assertion_response =
        nullptr;
  };

  struct Observations {
    std::vector<PublicKeyCredentialCreationOptionsPtr> create_requests;
    std::vector<PublicKeyCredentialRequestOptionsPtr> get_requests;
    size_t num_isuvpaa;
    size_t num_cancel;
  };

  ~TestWebAuthenticationRequestProxy() override {
    DCHECK(!HasPendingRequest());
  }

  Config& config() { return config_; }

  Observations& observations() { return observations_; }

  bool IsActive(const url::Origin& caller_origin) override {
    return config_.is_active;
  }

  RequestId SignalCreateRequest(
      const PublicKeyCredentialCreationOptionsPtr& options,
      CreateCallback callback) override {
    DCHECK(!HasPendingRequest());

    current_request_id_++;
    observations_.create_requests.push_back(options->Clone());
    pending_create_callback_ = std::move(callback);
    if (config_.resolve_callbacks) {
      RunPendingCreateCallback();
      return current_request_id_;
    }
    return current_request_id_;
  }

  RequestId SignalGetRequest(
      const PublicKeyCredentialRequestOptionsPtr& options,
      GetCallback callback) override {
    current_request_id_++;
    observations_.get_requests.push_back(options->Clone());
    pending_get_callback_ = std::move(callback);
    if (config_.resolve_callbacks) {
      RunPendingGetCallback();
      return current_request_id_;
    }
    return current_request_id_;
  }

  RequestId SignalIsUvpaaRequest(IsUvpaaCallback callback) override {
    DCHECK(!HasPendingRequest());

    current_request_id_++;
    observations_.num_isuvpaa++;
    if (config_.resolve_callbacks) {
      base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
          FROM_HERE, base::BindOnce(std::move(callback), config_.is_uvpaa));
      return current_request_id_;
    }
    DCHECK(!pending_is_uvpaa_callback_);
    pending_is_uvpaa_callback_ = std::move(callback);
    return current_request_id_;
  }

  void CancelRequest(RequestId request_id) override {
    DCHECK_EQ(request_id, current_request_id_);
    observations_.num_cancel++;
    if (pending_create_callback_) {
      pending_create_callback_.Reset();
    }
    if (pending_get_callback_) {
      pending_get_callback_.Reset();
    }
  }

  void RunPendingCreateCallback() {
    DCHECK(pending_create_callback_);
    auto callback =
        config_.request_success
            ? base::BindOnce(std::move(pending_create_callback_),
                             current_request_id_, nullptr,
                             config_.make_credential_response.Clone())
            : base::BindOnce(std::move(pending_create_callback_),
                             current_request_id_,
                             WebAuthnDOMExceptionDetails::New(
                                 config_.request_error_name, "message"),
                             nullptr);
    base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
        FROM_HERE, std::move(callback));
  }

  void RunPendingGetCallback() {
    DCHECK(pending_get_callback_);
    auto callback =
        config_.request_success
            ? base::BindOnce(std::move(pending_get_callback_),
                             current_request_id_, nullptr,
                             config_.get_assertion_response.Clone())
            : base::BindOnce(std::move(pending_create_callback_),
                             current_request_id_,
                             WebAuthnDOMExceptionDetails::New(
                                 config_.request_error_name, "message"),
                             nullptr);
    base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
        FROM_HERE, std::move(callback));
  }

  void RunPendingIsUvpaaCallback() {
    DCHECK(pending_is_uvpaa_callback_);
    std::move(pending_is_uvpaa_callback_).Run(config_.is_uvpaa);
  }

  bool HasPendingRequest() {
    return pending_create_callback_ || pending_get_callback_ ||
           pending_is_uvpaa_callback_;
  }

 private:
  Config config_;
  Observations observations_;

  RequestId current_request_id_ = 0;
  CreateCallback pending_create_callback_;
  GetCallback pending_get_callback_;
  IsUvpaaCallback pending_is_uvpaa_callback_;
};

// TestWebAuthenticationDelegate is a test fake implementation of the
// WebAuthenticationDelegate embedder interface.
class TestWebAuthenticationDelegate : public WebAuthenticationDelegate {
 public:
  absl::optional<bool> IsUserVerifyingPlatformAuthenticatorAvailableOverride(
      RenderFrameHost*) override {
    return is_uvpaa_override;
  }

  bool OverrideCallerOriginAndRelyingPartyIdValidation(
      content::BrowserContext* browser_context,
      const url::Origin& origin,
      const std::string& rp_id) override {
    return permit_extensions && origin.scheme() == kExtensionScheme &&
           origin.host() == rp_id;
  }

  absl::optional<std::string> MaybeGetRelyingPartyIdOverride(
      const std::string& claimed_rp_id,
      const url::Origin& caller_origin) override {
    if (permit_extensions && caller_origin.scheme() == kExtensionScheme) {
      return caller_origin.Serialize();
    }
    return absl::nullopt;
  }

  bool ShouldPermitIndividualAttestation(
      content::BrowserContext* browser_context,
      const url::Origin& caller_origin,
      const std::string& relying_party_id) override {
    return permit_individual_attestation ||
           (permit_individual_attestation_for_rp_id.has_value() &&
            relying_party_id == *permit_individual_attestation_for_rp_id);
  }

  bool SupportsResidentKeys(RenderFrameHost*) override {
    return supports_resident_keys;
  }

  bool IsFocused(WebContents* web_contents) override { return is_focused; }

#if BUILDFLAG(IS_MAC)
  absl::optional<TouchIdAuthenticatorConfig> GetTouchIdAuthenticatorConfig(
      BrowserContext* browser_context) override {
    return touch_id_authenticator_config;
  }
#endif

  WebAuthenticationRequestProxy* MaybeGetRequestProxy(
      content::BrowserContext* browser_context,
      const url::Origin& caller_origin) override {
    return request_proxy && request_proxy->IsActive(caller_origin)
               ? request_proxy.get()
               : nullptr;
  }

  bool OriginMayUseRemoteDesktopClientOverride(
      content::BrowserContext* browser_context,
      const url::Origin& caller_origin) override {
    return caller_origin == remote_desktop_client_override_origin;
  }

  bool IsSecurityLevelAcceptableForWebAuthn(
      content::RenderFrameHost* rfh,
      const url::Origin& origin) override {
    return is_webauthn_security_level_acceptable;
  }

  // If set, the return value of IsUVPAA() will be overridden with this value.
  // Platform-specific implementations will not be invoked.
  absl::optional<bool> is_uvpaa_override;

  // If set, the delegate will permit WebAuthn requests from chrome-extension
  // origins.
  bool permit_extensions = false;

  // Indicates whether individual attestation should be permitted by the
  // delegate.
  bool permit_individual_attestation = false;

  // A specific RP ID for which individual attestation will be permitted.
  absl::optional<std::string> permit_individual_attestation_for_rp_id;

  // Indicates whether resident key operations should be permitted by the
  // delegate.
  bool supports_resident_keys = false;

  // The return value of the focus check issued at the end of a request.
  bool is_focused = true;

  // The return value of IsSecurityLevelAcceptableForWebAuthn.
  bool is_webauthn_security_level_acceptable = true;

#if BUILDFLAG(IS_MAC)
  // Configuration data for the macOS platform authenticator.
  absl::optional<TouchIdAuthenticatorConfig> touch_id_authenticator_config;
#endif

  // The WebAuthenticationRequestProxy returned by |MaybeGetRequestProxy|.
  std::unique_ptr<TestWebAuthenticationRequestProxy> request_proxy = nullptr;

  // The origin permitted to use the RemoteDesktopClientOverride extension.
  absl::optional<url::Origin> remote_desktop_client_override_origin;
};

enum class EnterprisePolicy {
  LISTED,
  NOT_LISTED,
};

enum class AttestationConsent {
  GRANTED,
  DENIED,
  GRANTED_FOR_ENTERPRISE_ATTESTATION,
  DENIED_FOR_ENTERPRISE_ATTESTATION,
  NOT_USED,
};

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();
      return "";
  }
}

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)";
  }
}

const char* AttestationConsentToString(AttestationConsent ac) {
  switch (ac) {
    case AttestationConsent::GRANTED:
      return "GRANTED";
    case AttestationConsent::DENIED:
      return "DENIED";
    case AttestationConsent::GRANTED_FOR_ENTERPRISE_ATTESTATION:
      return "GRANTED_FOR_ENTERPRISE_ATTESTATION";
    case AttestationConsent::DENIED_FOR_ENTERPRISE_ATTESTATION:
      return "DENIED_FOR_ENTERPRISE_ATTESTATION";
    case AttestationConsent::NOT_USED:
      return "NOT_USED";
  }
}

// TestAuthenticatorRequestDelegate is a test fake implementation of the
// AuthenticatorRequestClientDelegate embedder interface.
class TestAuthenticatorRequestDelegate
    : public AuthenticatorRequestClientDelegate {
 public:
  TestAuthenticatorRequestDelegate(
      RenderFrameHost* render_frame_host,
      base::OnceClosure action_callbacks_registered_callback,
      AttestationConsent attestation_consent,
      base::OnceClosure started_over_callback)
      : action_callbacks_registered_callback_(
            std::move(action_callbacks_registered_callback)),
        attestation_consent_(attestation_consent),
        started_over_callback_(std::move(started_over_callback)),
        does_block_request_on_failure_(!started_over_callback_.is_null()) {}

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

  ~TestAuthenticatorRequestDelegate() override {
    CHECK(attestation_consent_queried_ ||
          attestation_consent_ == AttestationConsent::NOT_USED);
  }

  void RegisterActionCallbacks(
      base::OnceClosure cancel_callback,
      base::RepeatingClosure start_over_callback,
      AccountPreselectedCallback account_preselected_callback,
      device::FidoRequestHandlerBase::RequestCallback request_callback,
      base::RepeatingClosure bluetooth_adapter_power_on_callback) override {
    ASSERT_TRUE(action_callbacks_registered_callback_)
        << "RegisterActionCallbacks called twice.";
    cancel_callback_ = std::move(cancel_callback);
    std::move(action_callbacks_registered_callback_).Run();
    if (started_over_callback_) {
      action_callbacks_registered_callback_ = std::move(started_over_callback_);
      start_over_callback_ = start_over_callback;
    }
  }

  void ShouldReturnAttestation(
      const std::string& relying_party_id,
      const device::FidoAuthenticator* authenticator,
      bool is_enterprise_attestation,
      base::OnceCallback<void(bool)> callback) override {
    bool result = false;
    switch (attestation_consent_) {
      case AttestationConsent::NOT_USED:
        CHECK(false);
        break;
      case AttestationConsent::DENIED:
        CHECK(!is_enterprise_attestation);
        break;
      case AttestationConsent::GRANTED:
        CHECK(!is_enterprise_attestation);
        result = true;
        break;
      case AttestationConsent::DENIED_FOR_ENTERPRISE_ATTESTATION:
        CHECK(is_enterprise_attestation);
        break;
      case AttestationConsent::GRANTED_FOR_ENTERPRISE_ATTESTATION:
        CHECK(is_enterprise_attestation);
        result = true;
        break;
    }

    attestation_consent_queried_ = true;
    std::move(callback).Run(result);
  }

  void OnTransportAvailabilityEnumerated(
      device::FidoRequestHandlerBase::TransportAvailabilityInfo transport_info)
      override {
    // Simulate the behaviour of Chrome's |AuthenticatorRequestDialogModel|
    // which shows a specific error when no transports are available and lets
    // the user cancel the request.
    if (transport_info.available_transports.empty()) {
      std::move(cancel_callback_).Run();
    }
  }

  bool DoesBlockRequestOnFailure(InterestingFailureReason reason) override {
    if (!does_block_request_on_failure_) {
      return false;
    }

    std::move(start_over_callback_).Run();
    does_block_request_on_failure_ = false;
    return true;
  }

  base::OnceClosure action_callbacks_registered_callback_;
  base::OnceClosure cancel_callback_;
  const AttestationConsent attestation_consent_;
  base::OnceClosure started_over_callback_;
  base::OnceClosure start_over_callback_;
  bool does_block_request_on_failure_ = false;
  bool attestation_consent_queried_ = false;
};

// TestAuthenticatorContentBrowserClient is a test fake implementation of the
// ContentBrowserClient interface that injects |TestWebAuthenticationDelegate|
// and |TestAuthenticatorRequestDelegate| instances into |AuthenticatorImpl|.
class TestAuthenticatorContentBrowserClient : public ContentBrowserClient {
 public:
  TestWebAuthenticationDelegate* GetTestWebAuthenticationDelegate() {
    return &web_authentication_delegate;
  }

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

  std::unique_ptr<AuthenticatorRequestClientDelegate>
  GetWebAuthenticationRequestDelegate(
      RenderFrameHost* render_frame_host) override {
    if (return_null_delegate) {
      return nullptr;
    }
    return std::make_unique<TestAuthenticatorRequestDelegate>(
        render_frame_host,
        action_callbacks_registered_callback
            ? std::move(action_callbacks_registered_callback)
            : base::DoNothing(),
        attestation_consent, std::move(started_over_callback_));
  }

  TestWebAuthenticationDelegate web_authentication_delegate;

  // If set, this closure will be called when the subsequently constructed
  // delegate is informed that the request has started.
  base::OnceClosure action_callbacks_registered_callback;

  AttestationConsent attestation_consent = AttestationConsent::NOT_USED;

  // This emulates scenarios where a nullptr RequestClientDelegate is returned
  // because a request is already in progress.
  bool return_null_delegate = false;

  // If started_over_callback_ is set to a non-null callback, the request will
  // be restarted after action callbacks are registered, and
  // |started_over_callback| will replace
  // |action_callbacks_registered_callback|. This should then be called the
  // second time action callbacks are registered. It also causes
  // DoesBlockRequestOnFailure to return true, once.
  base::OnceClosure started_over_callback_;
};

// 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;
    AttestationConsent attestation_consent;
    AuthenticatorStatus expected_status;
    AttestationType expected_attestation;
    const char* 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];
      if (test.attestation_consent != AttestationConsent::NOT_USED) {
        SCOPED_TRACE(test.attestation_consent == AttestationConsent::GRANTED
                         ? "consent granted"
                         : "consent denied");
      }
      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;
      test_client_.attestation_consent = test.attestation_consent;

      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);

      absl::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_STREQ("", test.expected_certificate_substring);
          break;

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

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

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

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

        case AttestationType::SELF: {
          ASSERT_STREQ("", test.expected_certificate_substring);
          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_STREQ("", test.expected_certificate_substring);
          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,
      const std::string& 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());
    base::StringPiece 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_.GetTestWebAuthenticationDelegate()
      ->is_webauthn_security_level_acceptable = false;
  PublicKeyCredentialCreationOptionsPtr options =
      GetTestPublicKeyCredentialCreationOptions();
  EXPECT_EQ(AuthenticatorMakeCredential(std::move(options)).status,
            AuthenticatorStatus::CERTIFICATE_ERROR);
}

TEST_F(AuthenticatorContentBrowserClientTest, GetAssertionTLSError) {
  NavigateAndCommit(GURL(kTestOrigin1));
  test_client_.GetTestWebAuthenticationDelegate()
      ->is_webauthn_security_level_acceptable = false;
  PublicKeyCredentialRequestOptionsPtr options =
      GetTestPublicKeyCredentialRequestOptions();
  EXPECT_EQ(AuthenticatorGetAssertion(std::move(options)).status,
            AuthenticatorStatus::CERTIFICATE_ERROR);
}

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_.GetTestWebAuthenticationDelegate()
      ->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_.GetTestWebAuthenticationDelegate()
      ->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 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,
          AttestationConsent::NOT_USED,
          AuthenticatorStatus::SUCCESS,
          AttestationType::NONE,
          "",
      },
      {
          AttestationConveyancePreference::NONE,
          EnterprisePolicy::LISTED,
          AttestationConsent::NOT_USED,
          AuthenticatorStatus::SUCCESS,
          AttestationType::NONE,
          "",
      },
      {
          AttestationConveyancePreference::INDIRECT,
          EnterprisePolicy::NOT_LISTED,
          AttestationConsent::DENIED,
          AuthenticatorStatus::SUCCESS,
          AttestationType::NONE,
          "",
      },
      {
          AttestationConveyancePreference::INDIRECT,
          EnterprisePolicy::LISTED,
          AttestationConsent::DENIED,
          AuthenticatorStatus::SUCCESS,
          AttestationType::NONE,
          "",
      },
      {
          AttestationConveyancePreference::INDIRECT,
          EnterprisePolicy::NOT_LISTED,
          AttestationConsent::GRANTED,
          AuthenticatorStatus::SUCCESS,
          AttestationType::U2F,
          kStandardCommonName,
      },
      {
          AttestationConveyancePreference::INDIRECT,
          EnterprisePolicy::LISTED,
          AttestationConsent::GRANTED,
          AuthenticatorStatus::SUCCESS,
          AttestationType::U2F,
          kStandardCommonName,
      },
      {
          AttestationConveyancePreference::DIRECT,
          EnterprisePolicy::NOT_LISTED,
          AttestationConsent::DENIED,
          AuthenticatorStatus::SUCCESS,
          AttestationType::NONE,
          "",
      },
      {
          AttestationConveyancePreference::DIRECT,
          EnterprisePolicy::LISTED,
          AttestationConsent::DENIED,
          AuthenticatorStatus::SUCCESS,
          AttestationType::NONE,
          "",
      },
      {
          AttestationConveyancePreference::DIRECT,
          EnterprisePolicy::NOT_LISTED,
          AttestationConsent::GRANTED,
          AuthenticatorStatus::SUCCESS,
          AttestationType::U2F,
          kStandardCommonName,
      },
      {
          AttestationConveyancePreference::DIRECT,
          EnterprisePolicy::LISTED,
          AttestationConsent::GRANTED,
          AuthenticatorStatus::SUCCESS,
          AttestationType::U2F,
          kStandardCommonName,
      },
      {
          // Requesting enterprise attestation and not being approved results in
          // no attestation.
          AttestationConveyancePreference::ENTERPRISE,
          EnterprisePolicy::NOT_LISTED,
          AttestationConsent::NOT_USED,
          AuthenticatorStatus::SUCCESS,
          AttestationType::NONE,
          "",
      },
      {
          AttestationConveyancePreference::ENTERPRISE,
          EnterprisePolicy::LISTED,
          AttestationConsent::NOT_USED,
          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,
            AttestationConsent::NOT_USED,
            AuthenticatorStatus::SUCCESS,
            AttestationType::PACKED,
            kIndividualCommonName,
        },
        {
            // Requesting enterprise attestation and not being approved results
            // in no attestation.
            AttestationConveyancePreference::ENTERPRISE,
            EnterprisePolicy::NOT_LISTED,
            AttestationConsent::NOT_USED,
            AuthenticatorStatus::SUCCESS,
            AttestationType::NONE,
            "",
        },
    };

    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,
            AttestationConsent::GRANTED_FOR_ENTERPRISE_ATTESTATION,
            AuthenticatorStatus::SUCCESS,
            AttestationType::PACKED,
            kIndividualCommonName,
        },
        {
            // Consent is required in the case that an enterprise attestation is
            // approved by an authenticator, however.
            AttestationConveyancePreference::ENTERPRISE,
            EnterprisePolicy::NOT_LISTED,
            AttestationConsent::DENIED_FOR_ENTERPRISE_ATTESTATION,
            AuthenticatorStatus::SUCCESS,
            AttestationType::NONE,
            "",
        },
    };

    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,
          AttestationConsent::NOT_USED,
          AuthenticatorStatus::SUCCESS,
          AttestationType::NONE,
          "",
      },
      {
          AttestationConveyancePreference::DIRECT,
          EnterprisePolicy::NOT_LISTED,
          AttestationConsent::GRANTED,
          AuthenticatorStatus::SUCCESS,
          // If individual attestation was not requested then the attestation
          // certificate will be removed, even if consent is given, because the
          // consent isn't to be tracked.
          AttestationType::NONE,
          "",
      },
      {
          AttestationConveyancePreference::ENTERPRISE,
          EnterprisePolicy::LISTED,
          AttestationConsent::NOT_USED,
          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,
          AttestationConsent::NOT_USED,
          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,
          AttestationConsent::NOT_USED,
          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,
          AttestationConsent::NOT_USED,
          AuthenticatorStatus::SUCCESS,
          AttestationType::SELF,
          "",
      },
      {
          // If attestation is requested, but denied, we'll return none
          // attestation.
          AttestationConveyancePreference::DIRECT,
          EnterprisePolicy::NOT_LISTED,
          AttestationConsent::DENIED,
          AuthenticatorStatus::SUCCESS,
          AttestationType::NONE,
          "",
      },
      {
          // If attestation is requested and granted, the self attestation will
          // be returned.
          AttestationConveyancePreference::DIRECT,
          EnterprisePolicy::NOT_LISTED,
          AttestationConsent::GRANTED,
          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,
          AttestationConsent::NOT_USED,
          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,
            test.result == AttestationType::U2F ? AttestationConsent::GRANTED
                                                : AttestationConsent::NOT_USED,
            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();

  TestRequestStartedCallback request_started;
  test_client_.action_callbacks_registered_callback =
      request_started.callback();
  authenticator->MakeCredential(std::move(options), base::DoNothing());
  request_started.WaitForCallback();
}

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

  PublicKeyCredentialRequestOptionsPtr options =
      GetTestPublicKeyCredentialRequestOptions();

  TestRequestStartedCallback request_started;
  test_client_.action_callbacks_registered_callback =
      request_started.callback();
  authenticator->GetAssertion(std::move(options), base::DoNothing());
  request_started.WaitForCallback();
}

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;

  TestRequestStartedCallback request_started;
  test_client_.action_callbacks_registered_callback =
      request_started.callback();
  TestRequestStartedCallback request_restarted;
  test_client_.started_over_callback_ = request_restarted.callback();

  authenticator->MakeCredential(std::move(options), base::DoNothing());
  request_started.WaitForCallback();
  request_restarted.WaitForCallback();

  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();

  PublicKeyCredentialRequestOptionsPtr options =
      GetTestPublicKeyCredentialRequestOptions();

  TestRequestStartedCallback request_started;
  test_client_.action_callbacks_registered_callback =
      request_started.callback();
  TestRequestStartedCallback request_restarted;
  test_client_.started_over_callback_ = request_restarted.callback();

  authenticator->GetAssertion(std::move(options), base::DoNothing());
  request_started.WaitForCallback();
  request_restarted.WaitForCallback();

  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));

  {
    TestRequestStartedCallback request_started;
    test_client_.action_callbacks_registered_callback =
        request_started.callback();

    EXPECT_EQ(
        AuthenticatorMakeCredential(GetTestPublicKeyCredentialCreationOptions())
            .status,
        AuthenticatorStatus::NOT_FOCUSED);
    EXPECT_FALSE(request_started.was_called());
  }

  {
    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);

    TestRequestStartedCallback request_started;
    test_client_.action_callbacks_registered_callback =
        request_started.callback();

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

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);
  }
}

// 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_;
  base::test::ScopedFeatureList scoped_feature_list_{
      device::kWebAuthnGoogleCorpRemoteDesktopClientPrivilege};
};

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);
  }
}

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 */,
            AttestationConsent::NOT_USED,
            /*started_over_callback=*/base::OnceClosure()),
        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(base::StringPiece));

 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();
  AuthenticatorEnvironment::GetInstance()
      ->ReplaceDefaultDiscoveryFactoryForTesting(std::move(discovery_factory));

  NavigateAndCommit(GURL(kTestOrigin1));
  PublicKeyCredentialRequestOptionsPtr options =
      GetTestPublicKeyCredentialRequestOptions();
  TestGetAssertionCallback callback_receiver;

  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->GetAssertion(std::move(options), callback_receiver.callback());
  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.
  AuthenticatorEnvironment::GetInstance()
      ->ReplaceDefaultDiscoveryFactoryForTesting(
          std::make_unique<device::FidoDiscoveryFactory>());
  NavigateAndCommit(GURL(kTestOrigin1));

  FailureReasonCallbackReceiver failure_reason_receiver;
  auto mock_delegate = std::make_unique<
      ::testing::NiceMock<MockAuthenticatorRequestDelegateObserver>>(
      failure_reason_receiver.callback());
  auto authenticator = ConnectToFakeAuthenticator(std::move(mock_delegate));

  TestGetAssertionCallback callback_receiver;
  authenticator->GetAssertion(GetTestPublicKeyCredentialRequestOptions(),
                              callback_receiver.callback());

  task_environment()->FastForwardBy(kTestTimeout);

  callback_receiver.WaitForCallback();
  EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());

  ASSERT_TRUE(failure_reason_receiver.was_called());
  EXPECT_EQ(
      AuthenticatorRequestClientDelegate::InterestingFailureReason::kTimeout,
      std::get<0>(*failure_reason_receiver.result()));
}

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

  FailureReasonCallbackReceiver failure_reason_receiver;
  auto mock_delegate = std::make_unique<
      ::testing::NiceMock<MockAuthenticatorRequestDelegateObserver>>(
      failure_reason_receiver.callback());
  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));

  TestMakeCredentialCallback callback_receiver;
  authenticator->MakeCredential(std::move(options),
                                callback_receiver.callback());

  callback_receiver.WaitForCallback();
  EXPECT_EQ(AuthenticatorStatus::CREDENTIAL_EXCLUDED,
            callback_receiver.status());

  ASSERT_TRUE(failure_reason_receiver.was_called());
  EXPECT_EQ(AuthenticatorRequestClientDelegate::InterestingFailureReason::
                kKeyAlreadyRegistered,
            std::get<0>(*failure_reason_receiver.result()));
}

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

  FailureReasonCallbackReceiver failure_reason_receiver;
  auto mock_delegate = std::make_unique<
      ::testing::NiceMock<MockAuthenticatorRequestDelegateObserver>>(
      failure_reason_receiver.callback());
  auto authenticator = ConnectToFakeAuthenticator(std::move(mock_delegate));

  TestGetAssertionCallback callback_receiver;
  authenticator->GetAssertion(GetTestPublicKeyCredentialRequestOptions(),
                              callback_receiver.callback());

  callback_receiver.WaitForCallback();
  EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());

  ASSERT_TRUE(failure_reason_receiver.was_called());
  EXPECT_EQ(AuthenticatorRequestClientDelegate::InterestingFailureReason::
                kKeyNotRegistered,
            std::get<0>(*failure_reason_receiver.result()));
}

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);
  }
}

// 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(base::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;
    absl::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, absl::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.
    absl::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;
    }

    const std::vector<uint8_t>& public_key_der =
        response->public_key_der.value();

    CBS cbs;
    CBS_init(&cbs, public_key_der.data(), public_key_der.size());
    bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_public_key(&cbs));
    EXPECT_EQ(0u, CBS_len(&cbs));
    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);
    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 {
    device::CoseAlgorithmIdentifier algo;
    // This field is not a raw_ptr<> because it was filtered by the rewriter
    // for: #global-scope
    RAW_PTR_EXCLUSION 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));

    const std::vector<uint8_t>& public_key_der =
        create_result.response->public_key_der.value();
    CBS cbs;
    CBS_init(&cbs, public_key_der.data(), public_key_der.size());
    bssl::UniquePtr<EVP_PKEY> pkey(EVP_parse_public_key(&cbs));
    EXPECT_EQ(0u, CBS_len(&cbs));
    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);
    const std::array<uint8_t, crypto::kSHA256Length> client_data_json_hash(
        crypto::SHA256Hash(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/1249057): 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 was_called = false;
  virtual_device_factory_->SetSupportedProtocol(
      device::ProtocolVersion::kCtap2);
  virtual_device_factory_->mutable_state()->simulate_press_callback =
      base::BindLambdaForTesting([&](device::VirtualFidoDevice* device) {
        was_called = 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));
    AuthenticatorEnvironment::GetInstance()
        ->ReplaceDefaultDiscoveryFactoryForTesting(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);
}

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

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

 protected:
  TestAuthenticatorContentBrowserClient test_client_;
  raw_ptr<ContentBrowserClient> old_client_ = nullptr;
};

TEST_F(AuthenticatorDevicePublicKeyTest, DevicePublicKeyMakeCredential) {
  NavigateAndCommit(GURL(kTestOrigin1));

  for (const bool dpk_support : {false, true}) {
    device::VirtualCtap2Device::Config config;
    config.device_public_key_support = dpk_support;
    config.backup_eligible = true;
    // None attestation is needed because, otherwise, zeroing the AAGUID
    // invalidates the DPK signature.
    config.none_attestation = true;
    virtual_device_factory_->SetCtap2Config(config);

    PublicKeyCredentialCreationOptionsPtr options =
        GetTestPublicKeyCredentialCreationOptions();
    options->device_public_key = blink::mojom::DevicePublicKeyRequest::New();
    MakeCredentialResult result =
        AuthenticatorMakeCredential(std::move(options));

    ASSERT_EQ(result.status, AuthenticatorStatus::SUCCESS);
    ASSERT_EQ(static_cast<bool>(result.response->device_public_key),
              dpk_support);
    ASSERT_EQ(HasDevicePublicKeyExtensionInAuthenticatorData(result.response),
              dpk_support);
    if (dpk_support) {
      ASSERT_FALSE(
          result.response->device_public_key->authenticator_output.empty());
      ASSERT_FALSE(result.response->device_public_key->signature.empty());
    }
  }
}

TEST_F(AuthenticatorDevicePublicKeyTest,
       DevicePublicKeyWithPrimaryAttestation) {
  // If the authenticator returns regular attestation and a devicePubKey
  // response, and the browser needs to strip that attesation, then the DPK
  // extension should be removed.
  NavigateAndCommit(GURL(kTestOrigin1));

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

  PublicKeyCredentialCreationOptionsPtr options =
      GetTestPublicKeyCredentialCreationOptions();
  options->device_public_key = blink::mojom::DevicePublicKeyRequest::New();
  MakeCredentialResult result = AuthenticatorMakeCredential(std::move(options));

  ASSERT_EQ(result.status, AuthenticatorStatus::SUCCESS);
  ASSERT_FALSE(static_cast<bool>(result.response->device_public_key));
  ASSERT_FALSE(HasDevicePublicKeyExtensionInAuthenticatorData(result.response));
}

TEST_F(AuthenticatorDevicePublicKeyTest,
       DevicePublicKeyMakeCredentialRequiresBackupEligible) {
  NavigateAndCommit(GURL(kTestOrigin1));

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

    PublicKeyCredentialCreationOptionsPtr options =
        GetTestPublicKeyCredentialCreationOptions();
    options->device_public_key = blink::mojom::DevicePublicKeyRequest::New();
    MakeCredentialResult result =
        AuthenticatorMakeCredential(std::move(options));

    if (backup_eligible) {
      ASSERT_EQ(result.status, AuthenticatorStatus::SUCCESS);
      ASSERT_TRUE(static_cast<bool>(result.response->device_public_key));
      ASSERT_TRUE(
          HasDevicePublicKeyExtensionInAuthenticatorData(result.response));
    } else {
      ASSERT_EQ(result.status, AuthenticatorStatus::NOT_ALLOWED_ERROR);
    }
  }
}

TEST_F(AuthenticatorDevicePublicKeyTest, DevicePublicKeyGetAssertion) {
  NavigateAndCommit(GURL(kTestOrigin1));

  bool credential_injected = false;
  for (const bool dpk_support : {false, true}) {
    device::VirtualCtap2Device::Config config;
    config.device_public_key_support = dpk_support;
    config.backup_eligible = true;
    virtual_device_factory_->SetCtap2Config(config);

    PublicKeyCredentialRequestOptionsPtr options =
        GetTestPublicKeyCredentialRequestOptions();
    if (!credential_injected) {
      ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
          options->allow_credentials[0].id, kTestRelyingPartyId));
      credential_injected = true;
    }
    options->extensions->device_public_key =
        blink::mojom::DevicePublicKeyRequest::New();
    GetAssertionResult result = AuthenticatorGetAssertion(std::move(options));

    ASSERT_EQ(result.status, AuthenticatorStatus::SUCCESS);
    ASSERT_EQ(static_cast<bool>(result.response->extensions->device_public_key),
              dpk_support);
    if (dpk_support) {
      ASSERT_FALSE(result.response->extensions->device_public_key
                       ->authenticator_output.empty());
      ASSERT_FALSE(
          result.response->extensions->device_public_key->signature.empty());
    }
  }
}

TEST_F(AuthenticatorDevicePublicKeyTest,
       DevicePublicKeyGetAssertionRequiresBackupEligible) {
  NavigateAndCommit(GURL(kTestOrigin1));

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

    PublicKeyCredentialRequestOptionsPtr options =
        GetTestPublicKeyCredentialRequestOptions();
    if (!credential_injected) {
      ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
          options->allow_credentials[0].id, kTestRelyingPartyId));
      credential_injected = true;
    }
    options->extensions->device_public_key =
        blink::mojom::DevicePublicKeyRequest::New();
    GetAssertionResult result = AuthenticatorGetAssertion(std::move(options));

    if (backup_eligible) {
      ASSERT_EQ(result.status, AuthenticatorStatus::SUCCESS);
      ASSERT_TRUE(
          static_cast<bool>(result.response->extensions->device_public_key));
    } else {
      ASSERT_EQ(result.status, AuthenticatorStatus::NOT_ALLOWED_ERROR);
    }
  }
}

TEST_F(AuthenticatorDevicePublicKeyTest, DevicePublicKeyBadResponse) {
  NavigateAndCommit(GURL(kTestOrigin1));

  bool credential_injected = false;
  for (int breakage = 0; breakage < 3; breakage++) {
    SCOPED_TRACE(::testing::Message() << "breakage=" << breakage);

    device::VirtualCtap2Device::Config config;
    config.device_public_key_support = true;
    config.backup_eligible = true;
    // None attestation is needed because, otherwise, zeroing the AAGUID
    // invalidates the DPK signature.
    config.none_attestation = true;

    switch (breakage) {
      case 0:
        break;

      case 1:
        config.device_public_key_drop_extension_response = true;
        break;

      case 2:
        config.device_public_key_drop_signature = true;
        break;

      default:
        CHECK(false);
    }
    virtual_device_factory_->SetCtap2Config(config);

    AuthenticatorStatus status;
    for (const bool is_make_credential : {false, true}) {
      SCOPED_TRACE(::testing::Message()
                   << "is_make_credential=" << is_make_credential);

      if (is_make_credential) {
        PublicKeyCredentialCreationOptionsPtr options =
            GetTestPublicKeyCredentialCreationOptions();
        options->device_public_key =
            blink::mojom::DevicePublicKeyRequest::New();
        MakeCredentialResult result =
            AuthenticatorMakeCredential(std::move(options));
        status = result.status;
      } else {
        PublicKeyCredentialRequestOptionsPtr options =
            GetTestPublicKeyCredentialRequestOptions();
        if (!credential_injected) {
          ASSERT_TRUE(
              virtual_device_factory_->mutable_state()->InjectRegistration(
                  options->allow_credentials[0].id, kTestRelyingPartyId));
          credential_injected = true;
        }
        options->extensions->device_public_key =
            blink::mojom::DevicePublicKeyRequest::New();
        GetAssertionResult result =
            AuthenticatorGetAssertion(std::move(options));
        status = result.status;
      }

      if (breakage) {
        EXPECT_NE(status, AuthenticatorStatus::SUCCESS);
      } else {
        EXPECT_EQ(status, AuthenticatorStatus::SUCCESS);
      }
    }
  }
}

TEST_F(AuthenticatorDevicePublicKeyTest,
       DevicePublicKeyMakeCredentialAttestation) {
  constexpr device::AttestationConveyancePreference req_none =
      device::AttestationConveyancePreference::kNone;
  constexpr device::AttestationConveyancePreference req_indirect =
      device::AttestationConveyancePreference::kIndirect;
  constexpr device::AttestationConveyancePreference req_direct =
      device::AttestationConveyancePreference::kDirect;
  constexpr device::AttestationConveyancePreference req_enterprise = device::
      AttestationConveyancePreference::kEnterpriseIfRPListedOnAuthenticator;
  constexpr bool no_allowlist = false;
  constexpr bool allowlisted = true;
  constexpr bool none = false;
  constexpr bool direct = true;
  constexpr bool ep = true;
  constexpr bool no_ep = false;
  constexpr AttestationConsent no_prompt = AttestationConsent::NOT_USED;
  constexpr AttestationConsent prompt_no = AttestationConsent::DENIED;
  constexpr AttestationConsent prompt_yes = AttestationConsent::GRANTED;
  constexpr AttestationConsent prompt_ep_no =
      AttestationConsent::DENIED_FOR_ENTERPRISE_ATTESTATION;
  constexpr AttestationConsent prompt_ep_yes =
      AttestationConsent::GRANTED_FOR_ENTERPRISE_ATTESTATION;

  constexpr struct {
    device::AttestationConveyancePreference requested_attestation;
    bool is_permitted_by_policy;
    bool has_attestation;
    bool enterprise_attestation_returned;
    AttestationConsent prompt;
    bool ok;
  } kTests[] = {
      // clang-format off
      // |Requested |   In policy? | Att   | Ent?  | Prompt?    |   OK? |
      // ----------------------------------------------------------------

      // No attestation requested and none provided is the simple case.
      {req_none,       no_allowlist, none,   no_ep, no_prompt,     true},

      // Any non-enterprise DPK attestation request is mapped to "none", so the
      // authenticator cannot return a DPK attestation in these cases.
      {req_none,       no_allowlist, direct, no_ep, no_prompt,     false},
      {req_indirect,   no_allowlist, direct, no_ep, no_prompt,     false},
      {req_direct,     no_allowlist, direct, no_ep, no_prompt,     false},
      // ... and certainly can't return an enterprise attestation.
      {req_none,       no_allowlist, direct, ep,    no_prompt,     false},
      {req_indirect,   no_allowlist, direct, ep,    no_prompt,     false},
      {req_direct,     no_allowlist, direct, ep,    no_prompt,     false},

      // Requesting a DPK attestation results in a prompt, same as requesting
      // a normal attestation, even if no attestation results.
      {req_indirect,   no_allowlist, none,   no_ep, prompt_yes,    true},
      {req_direct,     no_allowlist, none,   no_ep, prompt_yes,    true},

      // A failed ep=1 attestation results in a standard prompt.
      {req_enterprise, no_allowlist, none,   no_ep, prompt_yes,    true},
      // ... rejecting that prompt is ok if there's no attestation.
      {req_enterprise, no_allowlist, none,   no_ep, prompt_no,     true},
      // A successful ep=1 attestation results in a special prompt.
      {req_enterprise, no_allowlist, direct, ep,    prompt_ep_yes, true},
      // ... rejecting that prompt results in the DPK being stripped.
      {req_enterprise, no_allowlist, direct, ep,    prompt_ep_no,  true},

      // An ep=1 request should either return an enterprise attestation or
      // nothing. So a "direct" response is invalid and should fail.
      {req_enterprise, no_allowlist, direct, no_ep, no_prompt,     false},

      // RP IDs listed in policy will cause prompts, but they'll be immediately
      // resolved because of the policy allowlisting.
      {req_indirect,   allowlisted,  none,   no_ep, prompt_yes,    true},
      {req_direct,     allowlisted,  none,   no_ep, prompt_yes,    true},
      {req_enterprise, allowlisted,  none,   no_ep, prompt_yes,    true},
      {req_enterprise, allowlisted,  direct, no_ep, prompt_yes,    true},
      {req_enterprise, allowlisted,  direct, ep,    prompt_ep_yes, true},
      // clang-format on
  };

  NavigateAndCommit(GURL(kTestOrigin1));

  unsigned test_num = 0;
  for (const auto& test : kTests) {
    SCOPED_TRACE(::testing::Message() << "ok=" << test.ok);
    SCOPED_TRACE(::testing::Message()
                 << "prompt=" << AttestationConsentToString(test.prompt));
    SCOPED_TRACE(::testing::Message() << "enterprise_attestation_returned="
                                      << test.enterprise_attestation_returned);
    SCOPED_TRACE(::testing::Message()
                 << "has_attestation=" << test.has_attestation);
    SCOPED_TRACE(::testing::Message()
                 << "is_permitted_by_policy=" << test.is_permitted_by_policy);
    SCOPED_TRACE(
        ::testing::Message()
        << "requested_attestation="
        << AttestationConveyancePreferenceToString(test.requested_attestation));
    SCOPED_TRACE(::testing::Message() << "kTests[" << test_num++ << "]");

    CHECK(!test.enterprise_attestation_returned || test.has_attestation);

    device::VirtualCtap2Device::Config config;
    config.device_public_key_support = true;
    config.backup_eligible = true;
    config.device_public_key_always_return_attestation = test.has_attestation;
    config.device_public_key_always_return_enterprise_attestation =
        test.enterprise_attestation_returned;
    // None attestation is needed because, otherwise, zeroing the AAGUID
    // invalidates the DPK signature.
    config.none_attestation = true;
    virtual_device_factory_->SetCtap2Config(config);

    test_client_.GetTestWebAuthenticationDelegate()
        ->permit_individual_attestation = test.is_permitted_by_policy;
    test_client_.attestation_consent = test.prompt;

    PublicKeyCredentialCreationOptionsPtr options =
        GetTestPublicKeyCredentialCreationOptions();
    options->device_public_key = blink::mojom::DevicePublicKeyRequest::New();
    options->device_public_key->attestation = test.requested_attestation;
    MakeCredentialResult result =
        AuthenticatorMakeCredential(std::move(options));

    EXPECT_EQ(result.status == AuthenticatorStatus::SUCCESS, test.ok);
  }
}

TEST_F(AuthenticatorDevicePublicKeyTest,
       DevicePublicKeyGetAssertionAttestation) {
  constexpr device::AttestationConveyancePreference req_none =
      device::AttestationConveyancePreference::kNone;
  constexpr device::AttestationConveyancePreference req_indirect =
      device::AttestationConveyancePreference::kIndirect;
  constexpr device::AttestationConveyancePreference req_direct =
      device::AttestationConveyancePreference::kDirect;
  constexpr device::AttestationConveyancePreference req_enterprise = device::
      AttestationConveyancePreference::kEnterpriseIfRPListedOnAuthenticator;
  constexpr bool no_allowlist = false;
  constexpr bool allowlisted = true;
  constexpr bool none = false;
  constexpr bool direct = true;
  constexpr bool ep = true;
  constexpr bool no_ep = false;

  constexpr struct {
    device::AttestationConveyancePreference requested_attestation;
    bool is_permitted_by_policy;
    bool has_attestation;
    bool enterprise_attestation_returned;
    bool ok;
  } kTests[] = {
      // clang-format off
      // |Requested |   In policy? | Att   | Ent?  | OK? |
      // ----------------------------------------------------------------

      // No attestation requested and none provided is the simple case.
      {req_none,       no_allowlist, none,   no_ep, true},

      // If the authenticator doesn't provide any attestation then anything
      // works.
      {req_indirect,   no_allowlist, none,   no_ep, true},
      {req_direct,     no_allowlist, none,   no_ep, true},
      {req_enterprise, no_allowlist, none,   no_ep, true},
      {req_enterprise, allowlisted,  none,   no_ep, true},

      // If the authenticator provides attestation in unsupported cases then
      // the request should fail.
      {req_none,       no_allowlist, direct, no_ep, false},
      {req_indirect,   no_allowlist, direct, no_ep, false},
      {req_direct,     no_allowlist, direct, no_ep, false},
      {req_enterprise, no_allowlist, direct, no_ep, false},
      {req_enterprise, no_allowlist, direct, ep,    false},

      // The only supported case for DPK attestation during getAssertion is
      // via policy, when all requests should work.
      {req_indirect,   allowlisted,  direct, no_ep, true},
      {req_direct,     allowlisted,  direct, no_ep, true},
      {req_enterprise, allowlisted,  direct, no_ep, true},
      {req_enterprise, allowlisted,  direct, ep,    true},

      // But no ep responses to non-ep requests are allowed.
      {req_indirect,   allowlisted,  direct, ep,    false},
      {req_direct,     allowlisted,  direct, ep,    false},

      // clang-format on
  };

  NavigateAndCommit(GURL(kTestOrigin1));

  bool credential_injected = false;
  unsigned test_num = 0;
  for (const auto& test : kTests) {
    SCOPED_TRACE(::testing::Message() << "ok=" << test.ok);
    SCOPED_TRACE(::testing::Message() << "enterprise_attestation_returned="
                                      << test.enterprise_attestation_returned);
    SCOPED_TRACE(::testing::Message()
                 << "has_attestation=" << test.has_attestation);
    SCOPED_TRACE(::testing::Message()
                 << "is_permitted_by_policy=" << test.is_permitted_by_policy);
    SCOPED_TRACE(
        ::testing::Message()
        << "requested_attestation="
        << AttestationConveyancePreferenceToString(test.requested_attestation));
    SCOPED_TRACE(::testing::Message() << "kTests[" << test_num++ << "]");

    CHECK(!test.enterprise_attestation_returned || test.has_attestation);

    device::VirtualCtap2Device::Config config;
    config.device_public_key_support = true;
    config.backup_eligible = true;
    config.device_public_key_always_return_attestation = test.has_attestation;
    config.device_public_key_always_return_enterprise_attestation =
        test.enterprise_attestation_returned;
    virtual_device_factory_->SetCtap2Config(config);

    test_client_.GetTestWebAuthenticationDelegate()
        ->permit_individual_attestation = test.is_permitted_by_policy;

    PublicKeyCredentialRequestOptionsPtr options =
        GetTestPublicKeyCredentialRequestOptions();
    if (!credential_injected) {
      ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
          options->allow_credentials[0].id, kTestRelyingPartyId));
      credential_injected = true;
    }
    options->extensions->device_public_key =
        blink::mojom::DevicePublicKeyRequest::New();
    options->extensions->device_public_key->attestation =
        test.requested_attestation;
    GetAssertionResult result = AuthenticatorGetAssertion(std::move(options));

    EXPECT_EQ(result.status == AuthenticatorStatus::SUCCESS, test.ok);
  }
}

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

class UVTestAuthenticatorClientDelegate
    : public AuthenticatorRequestClientDelegate {
 public:
  explicit UVTestAuthenticatorClientDelegate(bool* collected_pin,
                                             uint32_t* min_pin_length,
                                             bool* did_bio_enrollment,
                                             bool cancel_bio_enrollment)
      : collected_pin_(collected_pin),
        min_pin_length_(min_pin_length),
        did_bio_enrollment_(did_bio_enrollment),
        cancel_bio_enrollment_(cancel_bio_enrollment) {
    *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 {}

 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_;
};

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);
  }

  TestWebAuthenticationDelegate web_authentication_delegate;

  bool collected_pin;
  uint32_t min_pin_length = 0;
  bool did_bio_enrollment;
  bool cancel_bio_enrollment = 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 AuthenticatorRequestClientDelegate {
 public:
  PINTestAuthenticatorRequestDelegate(
      bool supports_pin,
      const std::list<PINExpectation>& pins,
      absl::optional<InterestingFailureReason>* failure_reason)
      : supports_pin_(supports_pin),
        expected_(pins),
        failure_reason_(failure_reason) {}

  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 {
    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<absl::optional<InterestingFailureReason>> failure_reason_;
};

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);
  }

  TestWebAuthenticationDelegate web_authentication_delegate;

  bool supports_pin = true;
  std::list<PINExpectation> expected;
  absl::optional<InterestingFailureReason> failure_reason;
};

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 device::UserVerificationRequirement kUVLevel[3] = {
    device::UserVerificationRequirement::kDiscouraged,
    device::UserVerificationRequirement::kPreferred,
    device::UserVerificationRequirement::kRequired,
};

static const char* kUVDescription[3] = {"discouraged", "preferred", "required"};

static const char* kPINSupportDescription[3] = {"no PIN support", "PIN not set",
                                                "PIN set"};

TEST_F(PINAuthenticatorImplTest, MakeCredential) {
  typedef int Expectations[3][3];
  // kExpectedWithUISupport enumerates the expected behaviour when the embedder
  // supports prompting the user for a PIN.
  // clang-format off
  const Expectations kExpectedWithUISupport = {
    //                   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 = {
    //                   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);
}

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);
}

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));

  AuthenticatorEnvironment::GetInstance()
      ->ReplaceDefaultDiscoveryFactoryForTesting(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 int Expectations[3][3];
  // kExpectedWithUISupport enumerates the expected behaviour when the embedder
  // supports prompting the user for a PIN.
  // clang-format off
  const Expectations kExpectedWithUISupport = {
    //                   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 = {
    //                   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);
}

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);
}

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));

  AuthenticatorEnvironment::GetInstance()
      ->ReplaceDefaultDiscoveryFactoryForTesting(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::FidoDeviceDiscovery::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::FidoDeviceDiscovery::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));
  AuthenticatorEnvironment::GetInstance()
      ->ReplaceDefaultDiscoveryFactoryForTesting(std::move(discovery));

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

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 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);
  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 AuthenticatorRequestClientDelegate {
 public:
  BlockingAuthenticatorRequestDelegate() = default;

  void RegisterActionCallbacks(
      base::OnceClosure cancel_callback,
      base::RepeatingClosure start_over_callback,
      AccountPreselectedCallback account_preselected_callback,
      device::FidoRequestHandlerBase::RequestCallback request_callback,
      base::RepeatingClosure bluetooth_adapter_power_on_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));
  AuthenticatorEnvironment::GetInstance()
      ->ReplaceDefaultDiscoveryFactoryForTesting(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 AuthenticatorRequestClientDelegate {
 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 `SetConditional(true)` is expected to be called.
    bool expect_conditional = false;

    // If set, indicates that `DoesBlockRequestOnFailure()` is expected to be
    // called with this value.
    absl::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.
    absl::optional<std::vector<uint8_t>> preselected_credential_id;
    absl::optional<std::string> preselected_authenticator_id;
  };

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

  ~ResidentKeyTestAuthenticatorRequestDelegate() override {
    DCHECK(!config_.expect_conditional || expect_conditional_satisfied_)
        << "SetConditionalRequest() 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::RepeatingClosure start_over_callback,
      AccountPreselectedCallback account_preselected_callback,
      device::FidoRequestHandlerBase::RequestCallback request_callback,
      base::RepeatingClosure bluetooth_adapter_power_on_callback) override {
    account_preselected_callback_ = account_preselected_callback;
    request_callback_ = request_callback;
  }

  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;
    base::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.data(), user.id.size()) + ":" +
                 user.name.value_or("") + ":" + user.display_name.value_or("");
        });

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

    const auto selected = base::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 SetConditionalRequest(bool is_conditional) override {
    EXPECT_EQ(config_.expect_conditional, is_conditional);
    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);
      EXPECT_TRUE(base::Contains(
          info.recognized_credentials, *config_.preselected_credential_id,
          &device::DiscoverableCredentialMetadata::cred_id));
      std::move(account_preselected_callback_)
          .Run(device::PublicKeyCredentialDescriptor(
              device::CredentialType::kPublicKey,
              *config_.preselected_credential_id));
      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_;
};

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, 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);
}

TEST_F(ResidentKeyAuthenticatorImplTest, MakeCredentialEmptyFields) {
  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 = "";

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

  EXPECT_EQ(AuthenticatorStatus::SUCCESS, result.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}}, absl::nullopt, absl::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}}, absl::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}}, absl::nullopt, absl::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 = absl::nullopt;

  constexpr struct {
    bool large_blob_extension;
    absl::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}}, absl::nullopt, absl::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}}, absl::nullopt, absl::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) {
      absl::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}}, absl::nullopt, absl::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}}, absl::nullopt, absl::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();
            break;
          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 blink::mojom::ProtectionPolicy kMojoLevels[] = {
      blink::mojom::ProtectionPolicy::NONE,
      blink::mojom::ProtectionPolicy::UV_OR_CRED_ID_REQUIRED,
      blink::mojom::ProtectionPolicy::UV_REQUIRED,
  };
  constexpr device::CredProtect 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 absl::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}}, absl::nullopt, absl::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));

  // |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);
    PublicKeyCredentialRequestOptionsPtr options(get_credential_options());
    options->is_conditional = true;
    GetAssertionResult result = AuthenticatorGetAssertion(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) {
  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());
}
#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}, absl::nullopt, absl::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));

      absl::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);
      }
    }
  }
}

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}}, absl::nullopt, absl::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}}, absl::nullopt, absl::nullopt));

  // |SelectAccount| should not be called for conditional UI requests.
  test_client_.delegate_config.expected_accounts = "<invalid>";
  test_client_.delegate_config.expect_conditional = true;
  PublicKeyCredentialRequestOptionsPtr options(get_credential_options());
  options->is_conditional = true;
  GetAssertionResult result = AuthenticatorGetAssertion(std::move(options));
  EXPECT_EQ(AuthenticatorStatus::SUCCESS, result.status);
}

// 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) {
  device::VirtualCtap2Device::Config config;
  config.resident_key_support = true;
  config.internal_uv_support = 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> 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, absl::nullopt,
      absl::nullopt));
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectResidentKey(
      kSecondCredentialId, kTestRelyingPartyId, kSecondUserId, absl::nullopt,
      absl::nullopt));

  // |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);
  }
}

class InternalAuthenticatorImplTest : public AuthenticatorTestBase {
 protected:
  InternalAuthenticatorImplTest() = default;

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

  void TearDown() override {
    // The |RenderFrameHost| must outlive |AuthenticatorImpl|.
    internal_authenticator_impl_.reset();
    SetBrowserClientForTesting(old_client_);
    AuthenticatorTestBase::TearDown();
  }

  void NavigateAndCommit(const GURL& url) {
    // The |RenderFrameHost| must outlive |AuthenticatorImpl|.
    internal_authenticator_impl_.reset();
    RenderViewHostTestHarness::NavigateAndCommit(url);
  }

  InternalAuthenticatorImpl* GetAuthenticator(
      const url::Origin& effective_origin_url) {
    internal_authenticator_impl_ =
        std::make_unique<InternalAuthenticatorImpl>(main_rfh());
    internal_authenticator_impl_->SetEffectiveOrigin(effective_origin_url);
    return internal_authenticator_impl_.get();
  }

 protected:
  std::unique_ptr<InternalAuthenticatorImpl> internal_authenticator_impl_;
  TestAuthenticatorContentBrowserClient test_client_;
  raw_ptr<ContentBrowserClient> old_client_ = nullptr;
};

// Regression test for crbug.com/1433416.
TEST_F(InternalAuthenticatorImplTest, MakeCredentialSkipTLSCheck) {
  NavigateAndCommit(GURL(kTestOrigin1));
  InternalAuthenticatorImpl* authenticator =
      GetAuthenticator(url::Origin::Create(GURL(kTestOrigin1)));
  test_client_.GetTestWebAuthenticationDelegate()
      ->is_webauthn_security_level_acceptable = false;
  PublicKeyCredentialCreationOptionsPtr options =
      GetTestPublicKeyCredentialCreationOptions();
  TestMakeCredentialCallback callback;
  authenticator->MakeCredential(std::move(options), callback.callback());
  callback.WaitForCallback();
  EXPECT_EQ(callback.status(), blink::mojom::AuthenticatorStatus::SUCCESS);
}

// Regression test for crbug.com/1433416.
TEST_F(InternalAuthenticatorImplTest, GetAssertionSkipTLSCheck) {
  NavigateAndCommit(GURL(kTestOrigin1));
  InternalAuthenticatorImpl* authenticator =
      GetAuthenticator(url::Origin::Create(GURL(kTestOrigin1)));
  test_client_.GetTestWebAuthenticationDelegate()
      ->is_webauthn_security_level_acceptable = false;
  PublicKeyCredentialRequestOptionsPtr options =
      GetTestPublicKeyCredentialRequestOptions();
  ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
      options->allow_credentials[0].id, options->relying_party_id));
  TestGetAssertionCallback callback;
  authenticator->GetAssertion(std::move(options), callback.callback());
  callback.WaitForCallback();
  EXPECT_EQ(callback.status(), blink::mojom::AuthenticatorStatus::SUCCESS);
}

// Verify behavior for various combinations of origins and RP IDs.
TEST_F(InternalAuthenticatorImplTest, MakeCredentialOriginAndRpIds) {
  // These instances should return security errors (for circumstances
  // that would normally crash the renderer).
  for (auto test_case : kInvalidRelyingPartyTestCases) {
    SCOPED_TRACE(std::string(test_case.claimed_authority) + " " +
                 std::string(test_case.origin));

    GURL origin = GURL(test_case.origin);
    if (url::Origin::Create(origin).opaque()) {
      // Opaque origins will cause DCHECK to fail.
      continue;
    }

    NavigateAndCommit(origin);
    InternalAuthenticatorImpl* authenticator =
        GetAuthenticator(url::Origin::Create(origin));
    PublicKeyCredentialCreationOptionsPtr options =
        GetTestPublicKeyCredentialCreationOptions();
    options->relying_party.id = test_case.claimed_authority;
    TestMakeCredentialCallback callback_receiver;
    authenticator->MakeCredential(std::move(options),
                                  callback_receiver.callback());
    callback_receiver.WaitForCallback();
    EXPECT_EQ(test_case.expected_status, callback_receiver.status());
  }

  // These instances should bypass security errors, by setting the effective
  // origin to a valid one.
  for (auto test_case : kValidRelyingPartyTestCases) {
    SCOPED_TRACE(std::string(test_case.claimed_authority) + " " +
                 std::string(test_case.origin));

    NavigateAndCommit(GURL("https://this.isthewrong.origin"));
    auto* authenticator =
        GetAuthenticator(url::Origin::Create(GURL(test_case.origin)));
    PublicKeyCredentialCreationOptionsPtr options =
        GetTestPublicKeyCredentialCreationOptions();
    options->relying_party.id = test_case.claimed_authority;

    ResetVirtualDevice();
    TestMakeCredentialCallback callback_receiver;
    authenticator->MakeCredential(std::move(options),
                                  callback_receiver.callback());
    callback_receiver.WaitForCallback();
    EXPECT_EQ(test_case.expected_status, callback_receiver.status());
  }
}

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

    GURL origin = GURL(test_case.origin);
    if (url::Origin::Create(origin).opaque()) {
      // Opaque origins will cause DCHECK to fail.
      continue;
    }

    NavigateAndCommit(origin);
    InternalAuthenticatorImpl* authenticator =
        GetAuthenticator(url::Origin::Create(origin));
    PublicKeyCredentialRequestOptionsPtr options =
        GetTestPublicKeyCredentialRequestOptions();
    options->relying_party_id = test_case.claimed_authority;

    TestGetAssertionCallback callback_receiver;
    authenticator->GetAssertion(std::move(options),
                                callback_receiver.callback());
    callback_receiver.WaitForCallback();
    EXPECT_EQ(test_case.expected_status, callback_receiver.status());
  }

  // These instances should bypass security errors, by setting the effective
  // origin to a valid one.
  for (const OriginClaimedAuthorityPair& test_case :
       kValidRelyingPartyTestCases) {
    SCOPED_TRACE(std::string(test_case.claimed_authority) + " " +
                 std::string(test_case.origin));

    NavigateAndCommit(GURL("https://this.isthewrong.origin"));
    InternalAuthenticatorImpl* authenticator =
        GetAuthenticator(url::Origin::Create(GURL(test_case.origin)));
    PublicKeyCredentialRequestOptionsPtr options =
        GetTestPublicKeyCredentialRequestOptions();
    options->relying_party_id = test_case.claimed_authority;

    ResetVirtualDevice();
    ASSERT_TRUE(virtual_device_factory_->mutable_state()->InjectRegistration(
        options->allow_credentials[0].id, test_case.claimed_authority));
    TestGetAssertionCallback callback_receiver;
    authenticator->GetAssertion(std::move(options),
                                callback_receiver.callback());
    callback_receiver.WaitForCallback();
    EXPECT_EQ(test_case.expected_status, callback_receiver.status());
  }
}

#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, OptionalUv) {
  NavigateAndCommit(GURL(kTestOrigin1));
  mojo::Remote<blink::mojom::Authenticator> authenticator =
      ConnectToAuthenticator();
  for (const auto uv : {device::UserVerificationRequirement::kDiscouraged,
                        device::UserVerificationRequirement::kPreferred,
                        device::UserVerificationRequirement::kRequired}) {
    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 AuthenticatorRequestClientDelegate {
   public:
    using Callback = base::RepeatingCallback<void(
        const device::FidoRequestHandlerBase::TransportAvailabilityInfo&)>;
    explicit InspectTAIAuthenticatorRequestDelegate(Callback callback)
        : callback_(std::move(callback)) {}

    void ConfigureDiscoveries(
        const url::Origin& origin,
        const std::string& rp_id,
        RequestSource request_source,
        device::FidoRequestType request_type,
        absl::optional<device::ResidentKeyRequirement> resident_key_requirement,
        base::span<const device::CableDiscoveryData> pairings_from_extension,
        device::FidoDiscoveryFactory* fido_discovery_factory) override {
      // nswindow must be set for the iCloud Keychain authenticator to be
      // discovered.
      fido_discovery_factory->set_nswindow(
          device::fido::icloud_keychain::kFakeNSWindowForTesting);
    }

    void OnTransportAvailabilityEnumerated(
        device::FidoRequestHandlerBase::TransportAvailabilityInfo tai)
        override {
      callback_.Run(tai);
    }

   private:
    Callback callback_;
  };

  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.
    AuthenticatorEnvironment::GetInstance()->Reset();
  }

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

  void OnTransportAvailabilityEnumerated(
      const device::FidoRequestHandlerBase::TransportAvailabilityInfo& tai) {
    if (tai_callback_) {
      std::move(tai_callback_).Run(tai);
    }
  }

  static std::vector<device::DiscoverableCredentialMetadata> GetCredentials() {
    device::DiscoverableCredentialMetadata metadata(
        device::AuthenticatorType::kICloudKeychain, kTestRelyingPartyId,
        {1, 2, 3, 4}, {{5, 6, 7, 8}, "name", "displayName"});
    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, *)) {
    for (const bool feature_enabled : {false, true}) {
      SCOPED_TRACE(feature_enabled);

      base::test::ScopedFeatureList scoped_feature_list;
      std::vector<base::test::FeatureRef> empty;
      std::vector<base::test::FeatureRef> icloud_keychain_feature = {
          device::kWebAuthnICloudKeychain};
      if (feature_enabled) {
        scoped_feature_list.InitWithFeatures(icloud_keychain_feature, empty);
      } else {
        scoped_feature_list.InitWithFeatures(empty, icloud_keychain_feature);
      }

      NavigateAndCommit(GURL(kTestOrigin1));
      device::fido::icloud_keychain::ScopedTestEnvironment test_environment(
          GetCredentials());
      bool tai_seen = false;
      tai_callback_ = base::BindLambdaForTesting(
          [&tai_seen, feature_enabled](
              const device::FidoRequestHandlerBase::TransportAvailabilityInfo&
                  tai) {
            tai_seen = true;
            CHECK_EQ(tai.has_icloud_keychain, feature_enabled);
            CHECK_EQ(tai.recognized_credentials.size(),
                     feature_enabled ? 1u : 0u);
            CHECK_EQ(tai.has_icloud_keychain_credential,
                     feature_enabled
                         ? device::FidoRequestHandlerBase::
                               RecognizedCredential::kHasRecognizedCredential
                         : device::FidoRequestHandlerBase::
                               RecognizedCredential::kNoRecognizedCredential);

            if (feature_enabled) {
              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.3 for this test";
  }
}

#endif  // BUILDFLAG(IS_MAC)

// AuthenticatorCableV2Test tests features of the caBLEv2 transport and
// protocol.
class AuthenticatorCableV2Test : public AuthenticatorImplRequestDelegateTest {
 public:
  void SetUp() override {
    AuthenticatorImplTest::SetUp();

    NavigateAndCommit(GURL(kTestOrigin1));

    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 AuthenticatorRequestClientDelegate {
   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(base::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, network_context_.get(),
        qr_generator_key_, std::move(ble_advert_events_),
        /*contact_device_stream=*/nullptr,
        /*extension_contents=*/std::vector<device::CableDiscoveryData>(),
        GetPairingCallback(), GetInvalidatedPairingCallback(),
        GetEventCallback());

    AuthenticatorEnvironment::GetInstance()
        ->ReplaceDefaultDiscoveryFactoryForTesting(
            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),
            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, 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());

    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_was_called = 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_was_called, &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_was_called = 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),
              network_context_.get(), root_secret_, routing_id, tunnel_id,
              pairing_id, client_nonce, contact_id);
        });

    AuthenticatorEnvironment::GetInstance()
        ->ReplaceDefaultDiscoveryFactoryForTesting(
            std::make_unique<DiscoveryFactory>(std::move(discovery)));

    EXPECT_EQ(AuthenticatorMakeCredential().status,
              AuthenticatorStatus::SUCCESS);
    EXPECT_TRUE(contact_callback_was_called);
  }

  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_ =
      device::cablev2::NewMockTunnelServer(
          base::BindRepeating(&AuthenticatorCableV2Test::OnContact,
                              base::Unretained(this)));
  uint8_t peer_identity_x962_[device::kP256X962Length] = {0};
  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;
    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.device_public_key_support = true;
    ret.prf_support = true;
    ret.internal_account_chooser = true;
    ret.internal_uv_support = true;
    ret.always_uv = true;
    ret.backup_eligible = true;
    // None attestation is needed because, otherwise, zeroing the AAGUID
    // invalidates the DPK signature.
    ret.none_attestation = true;
    return ret;
  }
};

TEST_F(AuthenticatorCableV2Test, QRBasedWithNoPairing) {
  auto discovery = std::make_unique<device::cablev2::Discovery>(
      device::FidoRequestType::kGetAssertion, network_context_.get(),
      qr_generator_key_, std::move(ble_advert_events_),
      /*contact_device_stream=*/nullptr,
      /*extension_contents=*/std::vector<device::CableDiscoveryData>(),
      GetPairingCallback(), GetInvalidatedPairingCallback(),
      GetEventCallback());

  AuthenticatorEnvironment::GetInstance()
      ->ReplaceDefaultDiscoveryFactoryForTesting(
          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),
          network_context_.get(), root_secret_, "Test Authenticator",
          zero_qr_secret_, peer_identity_x962_,
          /*contact_id=*/absl::nullopt);

  EXPECT_EQ(AuthenticatorMakeCredential().status, AuthenticatorStatus::SUCCESS);
  EXPECT_EQ(pairings_.size(), 0u);
}

TEST_F(AuthenticatorCableV2Test, HandshakeError) {
  base::test::ScopedFeatureList scoped_feature_list{
      device::kWebAuthnNewHybridUI};
  // A handshake error should be fatal to the request with
  // `kHybridTransportError`.
  auto discovery = std::make_unique<device::cablev2::Discovery>(
      device::FidoRequestType::kGetAssertion, network_context_.get(),
      qr_generator_key_, std::move(ble_advert_events_),
      /*contact_device_stream=*/nullptr,
      /*extension_contents=*/std::vector<device::CableDiscoveryData>(),
      GetPairingCallback(), GetInvalidatedPairingCallback(),
      GetEventCallback());

  AuthenticatorEnvironment::GetInstance()
      ->ReplaceDefaultDiscoveryFactoryForTesting(
          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_.get(), zero_qr_secret_);

  FailureReasonCallbackReceiver failure_reason_receiver;
  auto mock_delegate = std::make_unique<
      ::testing::NiceMock<MockAuthenticatorRequestDelegateObserver>>(
      failure_reason_receiver.callback());
  auto authenticator = ConnectToFakeAuthenticator(std::move(mock_delegate));

  TestMakeCredentialCallback callback_receiver;
  authenticator->MakeCredential(GetTestPublicKeyCredentialCreationOptions(),
                                callback_receiver.callback());

  callback_receiver.WaitForCallback();
  EXPECT_EQ(AuthenticatorStatus::NOT_ALLOWED_ERROR, callback_receiver.status());

  ASSERT_TRUE(failure_reason_receiver.was_called());
  EXPECT_EQ(AuthenticatorRequestClientDelegate::InterestingFailureReason::
                kHybridTransportError,
            std::get<0>(*failure_reason_receiver.result()));
}

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.
  auto network_context = device::cablev2::NewMockTunnelServer(absl::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, 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());

  AuthenticatorEnvironment::GetInstance()
      ->ReplaceDefaultDiscoveryFactoryForTesting(
          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.data(), seed.size());

  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.data(), ret.secret.size());
  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, network_context_.get(),
      qr_generator_key_, std::move(ble_advert_events_),
      /*contact_device_stream=*/nullptr, extension_values, GetPairingCallback(),
      GetInvalidatedPairingCallback(), GetEventCallback());

  AuthenticatorEnvironment::GetInstance()
      ->ReplaceDefaultDiscoveryFactoryForTesting(
          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),
          network_context_.get(), root_secret_, "Test Authenticator",
          server_link.secret, server_link.peer_identity,
          /*contact_id=*/absl::nullopt);

  EXPECT_EQ(AuthenticatorMakeCredential().status, AuthenticatorStatus::SUCCESS);
  EXPECT_EQ(pairings_.size(), 0u);
}

TEST_F(AuthenticatorCableV2Test, LateLinking) {
  auto discovery = std::make_unique<device::cablev2::Discovery>(
      device::FidoRequestType::kGetAssertion, network_context_.get(),
      qr_generator_key_, std::move(ble_advert_events_),
      /*contact_device_stream=*/nullptr,
      /*extension_contents=*/std::vector<device::CableDiscoveryData>(),
      GetPairingCallback(), GetInvalidatedPairingCallback(),
      GetEventCallback());

  AuthenticatorEnvironment::GetInstance()
      ->ReplaceDefaultDiscoveryFactoryForTesting(
          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_.get(), 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, network_context_.get(),
        qr_generator_key_, std::move(ble_advert_events_),
        /*contact_device_stream=*/nullptr,
        /*extension_contents=*/std::vector<device::CableDiscoveryData>(),
        GetPairingCallback(), GetInvalidatedPairingCallback(),
        GetEventCallback());

    AuthenticatorEnvironment::GetInstance()
        ->ReplaceDefaultDiscoveryFactoryForTesting(
            std::make_unique<DiscoveryFactory>(std::move(discovery)));

    transaction_ = device::cablev2::authenticator::TransactFromQRCode(
        device::cablev2::authenticator::NewMockPlatform(
            std::move(ble_advert_callback_), &virtual_device_, this),
        network_context_.get(), root_secret_, "Test Authenticator",
        zero_qr_secret_, peer_identity_x962_,
        /*contact_id=*/absl::nullopt);
  }

 protected:
  // device::cablev2::authenticator::Observer
  void OnStatus(device::cablev2::authenticator::Platform::Status) override {}
  void OnCompleted(
      absl::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;
  absl::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, DevicePublicKeyMakeCredential) {
  auto options = GetTestPublicKeyCredentialCreationOptions();
  options->device_public_key = blink::mojom::DevicePublicKeyRequest::New();

  const auto result = AuthenticatorMakeCredential(std::move(options));

  ASSERT_EQ(result.status, AuthenticatorStatus::SUCCESS);
  EXPECT_TRUE(result.response->device_public_key);
  EXPECT_TRUE(HasDevicePublicKeyExtensionInAuthenticatorData(result.response));
}

TEST_F(AuthenticatorCableV2AuthenticatorTest, DevicePublicKeyGetAssertion) {
  auto options = GetTestPublicKeyCredentialRequestOptions();
  options->extensions->device_public_key =
      blink::mojom::DevicePublicKeyRequest::New();
  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));

  const auto result = AuthenticatorGetAssertion(std::move(options));

  ASSERT_EQ(result.status, AuthenticatorStatus::SUCCESS);
  EXPECT_TRUE(result.response->extensions->device_public_key);
}

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) {
  std::vector<uint8_t> hash_input;
  constexpr char kPrefix[] = "WebAuthn PRF";
  hash_input.insert(hash_input.end(), std::begin(kPrefix), std::end(kPrefix));
  hash_input.insert(hash_input.end(), std::begin(input), std::end(input));
  return device::fido_parsing_utils::Materialize(
      crypto::SHA256Hash(hash_input));
}

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 = EvaluateHMAC(key2, salt1);
  const std::array<uint8_t, 32> output2 = EvaluateHMAC(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),
                         device::fido_parsing_utils::Materialize(output1),
                         device::fido_parsing_utils::Materialize(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_;
  base::test::ScopedFeatureList scoped_feature_list_{
      device::kWebAuthnGoogleCorpRemoteDesktopClientPrivilege};
};

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,
            absl::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);
}

// Temporary regression test for crbug.com/1489468.
// TODO(crbug.com/1489482): Remove after passkey metadata syncing is enabled by
// default.
TEST_F(AuthenticatorImplWithRequestProxyTest,
       IsConditionalMediationAvailable_MetadataSyncing) {
  base::test::ScopedFeatureList scoped_feature_list;
  scoped_feature_list.InitWithFeatures(
      {device::kWebAuthnListSyncedPasskeys, device::kWebAuthnNewPasskeyUI}, {});

  // 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,
            absl::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, 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 :
       kInvalidRelyingPartyTestCases) {
    SCOPED_TRACE(std::string(test_case.claimed_authority) + " " +
                 std::string(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(std::string(test_case.origin) + " " +
                 std::string(test_case.claimed_authority));

    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. `kInvalidRelyingPartyTestCases`
  // contains a mix of RP ID an App ID cases, but they should all be rejected.
  for (const OriginClaimedAuthorityPair& test_case :
       kInvalidRelyingPartyTestCases) {
    SCOPED_TRACE(std::string(test_case.claimed_authority) + " " +
                 std::string(test_case.origin));

    if (strlen(test_case.claimed_authority) == 0) {
      // 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();
  request->is_conditional = 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 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 :
       kInvalidRelyingPartyTestCases) {
    SCOPED_TRACE(std::string(test_case.claimed_authority) + " " +
                 std::string(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
