blob: b004c366e41b65e4628c6ab8a68e9f2892867acb [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/webauth/virtual_authenticator_manager_impl.h"
#include <utility>
#include <vector>
#include "content/browser/webauth/virtual_authenticator.h"
#include "content/browser/webauth/virtual_fido_discovery_factory.h"
#include "device/fido/virtual_u2f_device.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
namespace content {
namespace {
mojo::PendingRemote<blink::test::mojom::VirtualAuthenticator>
GetMojoToVirtualAuthenticator(VirtualAuthenticator* authenticator) {
mojo::PendingRemote<blink::test::mojom::VirtualAuthenticator>
mojo_authenticator;
authenticator->AddReceiver(
mojo_authenticator.InitWithNewPipeAndPassReceiver());
return mojo_authenticator;
}
} // namespace
VirtualAuthenticatorManagerImpl::VirtualAuthenticatorManagerImpl() = default;
VirtualAuthenticatorManagerImpl::~VirtualAuthenticatorManagerImpl() = default;
void VirtualAuthenticatorManagerImpl::AddObserver(Observer* observer) {
observers_.AddObserver(observer);
}
void VirtualAuthenticatorManagerImpl::RemoveObserver(Observer* observer) {
observers_.RemoveObserver(observer);
}
void VirtualAuthenticatorManagerImpl::AddReceiver(
mojo::PendingReceiver<blink::test::mojom::VirtualAuthenticatorManager>
receiver) {
receivers_.Add(this, std::move(receiver));
}
VirtualAuthenticator* VirtualAuthenticatorManagerImpl::CreateU2FAuthenticator(
device::FidoTransportProtocol transport) {
if (!device::VirtualU2fDevice::IsTransportSupported(transport)) {
return nullptr;
}
return AddAuthenticator(std::make_unique<VirtualAuthenticator>(
device::ProtocolVersion::kU2f, /*ignored*/ device::Ctap2Version::kCtap2_0,
transport, device::AuthenticatorAttachment::kCrossPlatform,
/*has_resident_key=*/false,
/*has_user_verification=*/false, /*has_large_blob=*/false));
}
VirtualAuthenticator* VirtualAuthenticatorManagerImpl::CreateCTAP2Authenticator(
device::Ctap2Version ctap2_version,
device::FidoTransportProtocol transport,
device::AuthenticatorAttachment attachment,
bool has_resident_key,
bool has_user_verification,
bool has_large_blob) {
return AddAuthenticator(std::make_unique<VirtualAuthenticator>(
device::ProtocolVersion::kCtap2, ctap2_version, transport, attachment,
has_resident_key, has_user_verification, has_large_blob));
}
VirtualAuthenticator* VirtualAuthenticatorManagerImpl::GetAuthenticator(
const std::string& id) {
auto authenticator = authenticators_.find(id);
if (authenticator == authenticators_.end())
return nullptr;
return authenticator->second.get();
}
VirtualAuthenticator* VirtualAuthenticatorManagerImpl::AddAuthenticator(
std::unique_ptr<VirtualAuthenticator> authenticator) {
VirtualAuthenticator* authenticator_ptr = authenticator.get();
bool was_inserted;
std::tie(std::ignore, was_inserted) = authenticators_.insert(
{authenticator_ptr->unique_id(), std::move(authenticator)});
if (!was_inserted) {
NOTREACHED() << "unique_id() must be unique";
return nullptr;
}
for (Observer& observer : observers_) {
observer.AuthenticatorAdded(authenticator_ptr);
}
return authenticator_ptr;
}
std::vector<VirtualAuthenticator*>
VirtualAuthenticatorManagerImpl::GetAuthenticators() {
std::vector<VirtualAuthenticator*> authenticators;
for (auto& authenticator : authenticators_)
authenticators.push_back(authenticator.second.get());
return authenticators;
}
bool VirtualAuthenticatorManagerImpl::RemoveAuthenticator(
const std::string& id) {
const bool removed = authenticators_.erase(id);
if (removed) {
for (Observer& observer : observers_) {
observer.AuthenticatorRemoved(id);
}
}
return removed;
}
void VirtualAuthenticatorManagerImpl::CreateAuthenticator(
blink::test::mojom::VirtualAuthenticatorOptionsPtr options,
CreateAuthenticatorCallback callback) {
VirtualAuthenticator* authenticator = nullptr;
switch (options->protocol) {
case device::ProtocolVersion::kU2f:
authenticator = CreateU2FAuthenticator(options->transport);
break;
case device::ProtocolVersion::kCtap2:
authenticator = CreateCTAP2Authenticator(
options->ctap2_version, options->transport, options->attachment,
options->has_resident_key, options->has_user_verification,
options->has_large_blob);
break;
case device::ProtocolVersion::kUnknown:
break;
}
if (!authenticator) {
std::move(callback).Run(mojo::NullRemote());
return;
}
authenticator->SetUserPresence(options->is_user_present);
std::move(callback).Run(GetMojoToVirtualAuthenticator(authenticator));
}
void VirtualAuthenticatorManagerImpl::GetAuthenticators(
GetAuthenticatorsCallback callback) {
auto authenticators = GetAuthenticators();
std::vector<mojo::PendingRemote<blink::test::mojom::VirtualAuthenticator>>
mojo_authenticators;
for (VirtualAuthenticator* authenticator : authenticators) {
mojo_authenticators.push_back(GetMojoToVirtualAuthenticator(authenticator));
}
std::move(callback).Run(std::move(mojo_authenticators));
}
void VirtualAuthenticatorManagerImpl::RemoveAuthenticator(
const std::string& id,
RemoveAuthenticatorCallback callback) {
std::move(callback).Run(RemoveAuthenticator(id));
}
std::unique_ptr<VirtualFidoDiscoveryFactory>
VirtualAuthenticatorManagerImpl::MakeDiscoveryFactory() {
return std::make_unique<VirtualFidoDiscoveryFactory>(
weak_factory_.GetWeakPtr());
}
void VirtualAuthenticatorManagerImpl::ClearAuthenticators(
ClearAuthenticatorsCallback callback) {
for (auto& authenticator : authenticators_) {
for (Observer& observer : observers_) {
observer.AuthenticatorRemoved(authenticator.second->unique_id());
}
}
authenticators_.clear();
std::move(callback).Run();
}
} // namespace content