1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "content/browser/webauth/virtual_fido_discovery_factory.h"
6
7 #include <utility>
8 #include <vector>
9
10 #include "base/command_line.h"
11 #include "base/stl_util.h"
12 #include "content/browser/webauth/virtual_authenticator.h"
13 #include "content/browser/webauth/virtual_discovery.h"
14 #include "content/public/common/content_switches.h"
15 #include "device/fido/fido_discovery_base.h"
16 #include "device/fido/virtual_ctap2_device.h"
17 #include "device/fido/virtual_u2f_device.h"
18 #include "mojo/public/cpp/bindings/pending_remote.h"
19
20 namespace content {
21
22 namespace {
23
24 mojo::PendingRemote<blink::test::mojom::VirtualAuthenticator>
GetMojoToVirtualAuthenticator(VirtualAuthenticator * authenticator)25 GetMojoToVirtualAuthenticator(VirtualAuthenticator* authenticator) {
26 mojo::PendingRemote<blink::test::mojom::VirtualAuthenticator>
27 mojo_authenticator;
28 authenticator->AddReceiver(
29 mojo_authenticator.InitWithNewPipeAndPassReceiver());
30 return mojo_authenticator;
31 }
32
33 } // namespace
34
VirtualFidoDiscoveryFactory()35 VirtualFidoDiscoveryFactory::VirtualFidoDiscoveryFactory()
36 : virtual_device_state_(new device::VirtualFidoDevice::State) {}
37
38 VirtualFidoDiscoveryFactory::~VirtualFidoDiscoveryFactory() = default;
39
CreateAuthenticator(device::ProtocolVersion protocol,device::FidoTransportProtocol transport,device::AuthenticatorAttachment attachment,bool has_resident_key,bool has_user_verification)40 VirtualAuthenticator* VirtualFidoDiscoveryFactory::CreateAuthenticator(
41 device::ProtocolVersion protocol,
42 device::FidoTransportProtocol transport,
43 device::AuthenticatorAttachment attachment,
44 bool has_resident_key,
45 bool has_user_verification) {
46 if (protocol == device::ProtocolVersion::kU2f &&
47 !device::VirtualU2fDevice::IsTransportSupported(transport)) {
48 return nullptr;
49 }
50 auto authenticator = std::make_unique<VirtualAuthenticator>(
51 protocol, transport, attachment, has_resident_key, has_user_verification);
52 auto* authenticator_ptr = authenticator.get();
53 authenticators_.emplace(authenticator_ptr->unique_id(),
54 std::move(authenticator));
55
56 for (auto* discovery : discoveries_) {
57 if (discovery->transport() != authenticator_ptr->transport())
58 continue;
59 discovery->AddVirtualDevice(authenticator_ptr->ConstructDevice());
60 }
61 return authenticator_ptr;
62 }
63
GetAuthenticator(const std::string & id)64 VirtualAuthenticator* VirtualFidoDiscoveryFactory::GetAuthenticator(
65 const std::string& id) {
66 auto authenticator = authenticators_.find(id);
67 if (authenticator == authenticators_.end())
68 return nullptr;
69 return authenticator->second.get();
70 }
71
72 std::vector<VirtualAuthenticator*>
GetAuthenticators()73 VirtualFidoDiscoveryFactory::GetAuthenticators() {
74 std::vector<VirtualAuthenticator*> authenticators;
75 for (auto& authenticator : authenticators_)
76 authenticators.push_back(authenticator.second.get());
77 return authenticators;
78 }
79
RemoveAuthenticator(const std::string & id)80 bool VirtualFidoDiscoveryFactory::RemoveAuthenticator(const std::string& id) {
81 const bool removed = authenticators_.erase(id);
82 if (removed) {
83 for (auto* discovery : discoveries_)
84 discovery->RemoveVirtualDevice(id);
85 }
86
87 return removed;
88 }
89
AddReceiver(mojo::PendingReceiver<blink::test::mojom::VirtualAuthenticatorManager> receiver)90 void VirtualFidoDiscoveryFactory::AddReceiver(
91 mojo::PendingReceiver<blink::test::mojom::VirtualAuthenticatorManager>
92 receiver) {
93 receivers_.Add(this, std::move(receiver));
94 }
95
OnDiscoveryDestroyed(VirtualFidoDiscovery * discovery)96 void VirtualFidoDiscoveryFactory::OnDiscoveryDestroyed(
97 VirtualFidoDiscovery* discovery) {
98 if (base::Contains(discoveries_, discovery))
99 discoveries_.erase(discovery);
100 }
101
102 std::unique_ptr<::device::FidoDiscoveryBase>
Create(device::FidoTransportProtocol transport)103 VirtualFidoDiscoveryFactory::Create(device::FidoTransportProtocol transport) {
104 auto discovery = std::make_unique<VirtualFidoDiscovery>(transport);
105
106 for (auto& authenticator : authenticators_) {
107 if (discovery->transport() != authenticator.second->transport())
108 continue;
109 discovery->AddVirtualDevice(authenticator.second->ConstructDevice());
110 }
111
112 discoveries_.insert(discovery.get());
113 return discovery;
114 }
115
CreateAuthenticator(blink::test::mojom::VirtualAuthenticatorOptionsPtr options,CreateAuthenticatorCallback callback)116 void VirtualFidoDiscoveryFactory::CreateAuthenticator(
117 blink::test::mojom::VirtualAuthenticatorOptionsPtr options,
118 CreateAuthenticatorCallback callback) {
119 auto* authenticator = CreateAuthenticator(
120 options->protocol, options->transport, options->attachment,
121 options->has_resident_key, options->has_user_verification);
122 authenticator->SetUserPresence(options->is_user_present);
123
124 std::move(callback).Run(GetMojoToVirtualAuthenticator(authenticator));
125 }
126
GetAuthenticators(GetAuthenticatorsCallback callback)127 void VirtualFidoDiscoveryFactory::GetAuthenticators(
128 GetAuthenticatorsCallback callback) {
129 std::vector<mojo::PendingRemote<blink::test::mojom::VirtualAuthenticator>>
130 mojo_authenticators;
131 for (auto& authenticator : authenticators_) {
132 mojo_authenticators.push_back(
133 GetMojoToVirtualAuthenticator(authenticator.second.get()));
134 }
135
136 std::move(callback).Run(std::move(mojo_authenticators));
137 }
138
RemoveAuthenticator(const std::string & id,RemoveAuthenticatorCallback callback)139 void VirtualFidoDiscoveryFactory::RemoveAuthenticator(
140 const std::string& id,
141 RemoveAuthenticatorCallback callback) {
142 std::move(callback).Run(RemoveAuthenticator(id));
143 }
144
ClearAuthenticators(ClearAuthenticatorsCallback callback)145 void VirtualFidoDiscoveryFactory::ClearAuthenticators(
146 ClearAuthenticatorsCallback callback) {
147 for (auto& authenticator : authenticators_) {
148 for (auto* discovery : discoveries_) {
149 discovery->RemoveVirtualDevice(authenticator.second->unique_id());
150 }
151 }
152 authenticators_.clear();
153
154 std::move(callback).Run();
155 }
156
157 } // namespace content
158