blob: 992f911fc36ce6c00d6b034359f84588994df3a5 [file] [log] [blame]
// Copyright 2018 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/scoped_virtual_authenticator_environment.h"
#include <utility>
#include "base/stl_util.h"
#include "content/browser/webauth/authenticator_type_converters.h"
#include "content/browser/webauth/virtual_authenticator.h"
#include "content/browser/webauth/virtual_discovery.h"
#include "device/fido/virtual_ctap2_device.h"
namespace content {
namespace {
blink::test::mojom::VirtualAuthenticatorPtr GetMojoPtrToVirtualAuthenticator(
VirtualAuthenticator* authenticator) {
blink::test::mojom::VirtualAuthenticatorPtr mojo_authenticator_ptr;
authenticator->AddBinding(mojo::MakeRequest(&mojo_authenticator_ptr));
return mojo_authenticator_ptr;
}
} // namespace
// static
ScopedVirtualAuthenticatorEnvironment*
ScopedVirtualAuthenticatorEnvironment::GetInstance() {
static base::NoDestructor<ScopedVirtualAuthenticatorEnvironment> environment;
return environment.get();
}
ScopedVirtualAuthenticatorEnvironment::ScopedVirtualAuthenticatorEnvironment()
: virtual_device_state_(new device::VirtualFidoDevice::State) {}
ScopedVirtualAuthenticatorEnvironment::
~ScopedVirtualAuthenticatorEnvironment() = default;
void ScopedVirtualAuthenticatorEnvironment::AddBinding(
blink::test::mojom::VirtualAuthenticatorManagerRequest request) {
bindings_.AddBinding(this, std::move(request));
}
void ScopedVirtualAuthenticatorEnvironment::CreateAuthenticator(
blink::test::mojom::VirtualAuthenticatorOptionsPtr options,
CreateAuthenticatorCallback callback) {
auto authenticator = std::make_unique<VirtualAuthenticator>(
mojo::ConvertTo<::device::FidoTransportProtocol>(options->transport));
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());
}
std::move(callback).Run(GetMojoPtrToVirtualAuthenticator(authenticator_ptr));
}
void ScopedVirtualAuthenticatorEnvironment::GetAuthenticators(
GetAuthenticatorsCallback callback) {
std::vector<blink::test::mojom::VirtualAuthenticatorPtrInfo>
mojo_authenticators;
for (auto& authenticator : authenticators_) {
mojo_authenticators.push_back(
GetMojoPtrToVirtualAuthenticator(authenticator.second.get())
.PassInterface());
}
std::move(callback).Run(std::move(mojo_authenticators));
}
void ScopedVirtualAuthenticatorEnvironment::RemoveAuthenticator(
const std::string& id,
RemoveAuthenticatorCallback callback) {
const bool removed = authenticators_.erase(id);
if (removed) {
for (auto* discovery : discoveries_)
discovery->RemoveVirtualDevice(id);
}
std::move(callback).Run(removed);
}
void ScopedVirtualAuthenticatorEnvironment::ClearAuthenticators(
ClearAuthenticatorsCallback callback) {
for (auto& authenticator : authenticators_) {
for (auto* discovery : discoveries_) {
discovery->RemoveVirtualDevice(authenticator.second->unique_id());
}
}
authenticators_.clear();
std::move(callback).Run();
}
std::unique_ptr<::device::FidoDiscoveryBase>
ScopedVirtualAuthenticatorEnvironment::CreateFidoDiscovery(
device::FidoTransportProtocol transport,
::service_manager::Connector* connector) {
auto discovery = std::make_unique<VirtualFidoDiscovery>(this, transport);
if (bindings_.empty()) {
// If no bindings are active then create a virtual device. This is useful
// for web-platform tests which assume that they can make webauthn calls,
// but which don't implement the Chromium-specific mock Mojo interfaces.
device::VirtualCtap2Device::Config default_config;
auto device = std::make_unique<device::VirtualCtap2Device>(
virtual_device_state_, default_config);
discovery->AddVirtualDevice(std::move(device));
} else {
for (auto& authenticator : authenticators_) {
if (discovery->transport() != authenticator.second->transport())
continue;
discovery->AddVirtualDevice(authenticator.second->ConstructDevice());
}
}
discoveries_.insert(discovery.get());
return discovery;
}
void ScopedVirtualAuthenticatorEnvironment::OnDiscoveryDestroyed(
VirtualFidoDiscovery* discovery) {
DCHECK(base::ContainsKey(discoveries_, discovery));
discoveries_.erase(discovery);
}
} // namespace content