blob: 18d68a24d4e3af8bcbf3d02c7660339419c7ee6d [file] [log] [blame]
// Copyright 2019 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_fido_discovery_factory.h"
#include <utility>
#include <vector>
#include "base/command_line.h"
#include "base/stl_util.h"
#include "content/browser/webauth/virtual_authenticator.h"
#include "content/browser/webauth/virtual_discovery.h"
#include "content/public/common/content_switches.h"
#include "device/fido/fido_discovery_base.h"
#include "device/fido/virtual_ctap2_device.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
VirtualFidoDiscoveryFactory::VirtualFidoDiscoveryFactory()
: virtual_device_state_(new device::VirtualFidoDevice::State) {}
VirtualFidoDiscoveryFactory::~VirtualFidoDiscoveryFactory() = default;
VirtualAuthenticator* VirtualFidoDiscoveryFactory::CreateAuthenticator(
device::ProtocolVersion protocol,
device::FidoTransportProtocol transport,
device::AuthenticatorAttachment attachment,
bool has_resident_key,
bool has_user_verification) {
if (protocol == device::ProtocolVersion::kU2f &&
!device::VirtualU2fDevice::IsTransportSupported(transport)) {
return nullptr;
}
auto authenticator = std::make_unique<VirtualAuthenticator>(
protocol, transport, attachment, has_resident_key, has_user_verification);
auto* authenticator_ptr = authenticator.get();
authenticators_.emplace(authenticator_ptr->unique_id(),
std::move(authenticator));
for (auto* discovery : discoveries_) {
if (discovery->transport() != authenticator_ptr->transport())
continue;
discovery->AddVirtualDevice(authenticator_ptr->ConstructDevice());
}
return authenticator_ptr;
}
VirtualAuthenticator* VirtualFidoDiscoveryFactory::GetAuthenticator(
const std::string& id) {
auto authenticator = authenticators_.find(id);
if (authenticator == authenticators_.end())
return nullptr;
return authenticator->second.get();
}
std::vector<VirtualAuthenticator*>
VirtualFidoDiscoveryFactory::GetAuthenticators() {
std::vector<VirtualAuthenticator*> authenticators;
for (auto& authenticator : authenticators_)
authenticators.push_back(authenticator.second.get());
return authenticators;
}
bool VirtualFidoDiscoveryFactory::RemoveAuthenticator(const std::string& id) {
const bool removed = authenticators_.erase(id);
if (removed) {
for (auto* discovery : discoveries_)
discovery->RemoveVirtualDevice(id);
}
return removed;
}
void VirtualFidoDiscoveryFactory::AddReceiver(
mojo::PendingReceiver<blink::test::mojom::VirtualAuthenticatorManager>
receiver) {
receivers_.Add(this, std::move(receiver));
}
void VirtualFidoDiscoveryFactory::OnDiscoveryDestroyed(
VirtualFidoDiscovery* discovery) {
if (base::Contains(discoveries_, discovery))
discoveries_.erase(discovery);
}
std::unique_ptr<::device::FidoDiscoveryBase>
VirtualFidoDiscoveryFactory::Create(device::FidoTransportProtocol transport) {
auto discovery = std::make_unique<VirtualFidoDiscovery>(transport);
for (auto& authenticator : authenticators_) {
if (discovery->transport() != authenticator.second->transport())
continue;
discovery->AddVirtualDevice(authenticator.second->ConstructDevice());
}
discoveries_.insert(discovery.get());
return discovery;
}
void VirtualFidoDiscoveryFactory::CreateAuthenticator(
blink::test::mojom::VirtualAuthenticatorOptionsPtr options,
CreateAuthenticatorCallback callback) {
auto* authenticator = CreateAuthenticator(
options->protocol, options->transport, options->attachment,
options->has_resident_key, options->has_user_verification);
authenticator->SetUserPresence(options->is_user_present);
std::move(callback).Run(GetMojoToVirtualAuthenticator(authenticator));
}
void VirtualFidoDiscoveryFactory::GetAuthenticators(
GetAuthenticatorsCallback callback) {
std::vector<mojo::PendingRemote<blink::test::mojom::VirtualAuthenticator>>
mojo_authenticators;
for (auto& authenticator : authenticators_) {
mojo_authenticators.push_back(
GetMojoToVirtualAuthenticator(authenticator.second.get()));
}
std::move(callback).Run(std::move(mojo_authenticators));
}
void VirtualFidoDiscoveryFactory::RemoveAuthenticator(
const std::string& id,
RemoveAuthenticatorCallback callback) {
std::move(callback).Run(RemoveAuthenticator(id));
}
void VirtualFidoDiscoveryFactory::ClearAuthenticators(
ClearAuthenticatorsCallback callback) {
for (auto& authenticator : authenticators_) {
for (auto* discovery : discoveries_) {
discovery->RemoveVirtualDevice(authenticator.second->unique_id());
}
}
authenticators_.clear();
std::move(callback).Run();
}
} // namespace content