123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269 |
- // Copyright 2017 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 "device/fido/hid/fake_hid_impl_for_testing.h"
- #include <utility>
- #include "base/callback_helpers.h"
- #include "base/containers/contains.h"
- #include "device/fido/fido_parsing_utils.h"
- #include "device/fido/hid/fido_hid_discovery.h"
- #include "mojo/public/cpp/bindings/pending_associated_remote.h"
- #include "mojo/public/cpp/bindings/pending_receiver.h"
- #include "services/device/public/cpp/hid/hid_blocklist.h"
- #include "services/device/public/mojom/hid.mojom.h"
- namespace device {
- namespace {
- MATCHER_P(IsCtapHidCommand, expected_command, "") {
- return arg.size() >= 5 &&
- arg[4] == (0x80 | static_cast<uint8_t>(expected_command));
- }
- } // namespace
- MockFidoHidConnection::MockFidoHidConnection(
- device::mojom::HidDeviceInfoPtr device,
- mojo::PendingReceiver<device::mojom::HidConnection> receiver,
- std::array<uint8_t, 4> connection_channel_id)
- : receiver_(this, std::move(receiver)),
- device_(std::move(device)),
- connection_channel_id_(connection_channel_id) {}
- MockFidoHidConnection::~MockFidoHidConnection() {}
- void MockFidoHidConnection::Read(ReadCallback callback) {
- return ReadPtr(&callback);
- }
- void MockFidoHidConnection::Write(uint8_t report_id,
- const std::vector<uint8_t>& buffer,
- WriteCallback callback) {
- return WritePtr(report_id, buffer, &callback);
- }
- void MockFidoHidConnection::GetFeatureReport(
- uint8_t report_id,
- GetFeatureReportCallback callback) {
- NOTREACHED();
- }
- void MockFidoHidConnection::SendFeatureReport(
- uint8_t report_id,
- const std::vector<uint8_t>& buffer,
- SendFeatureReportCallback callback) {
- NOTREACHED();
- }
- void MockFidoHidConnection::SetNonce(base::span<uint8_t const> nonce) {
- nonce_ = std::vector<uint8_t>(nonce.begin(), nonce.end());
- }
- void MockFidoHidConnection::ExpectWriteHidInit() {
- ExpectWriteHidInit(testing::Sequence());
- }
- void MockFidoHidConnection::ExpectWriteHidInit(
- const testing::Sequence& sequence) {
- EXPECT_CALL(*this, WritePtr(::testing::_,
- IsCtapHidCommand(FidoHidDeviceCommand::kInit),
- ::testing::_))
- .InSequence(sequence)
- .WillOnce(::testing::Invoke(
- [&](auto&&, const std::vector<uint8_t>& buffer,
- device::mojom::HidConnection::WriteCallback* cb) {
- ASSERT_EQ(64u, buffer.size());
- // First 7 bytes are 4 bytes of channel id, one byte representing
- // HID command, 2 bytes for payload length.
- SetNonce(base::make_span(buffer).subspan(7, 8));
- std::move(*cb).Run(true);
- }));
- }
- void MockFidoHidConnection::ExpectHidWriteWithCommand(
- FidoHidDeviceCommand cmd) {
- ExpectHidWriteWithCommand(testing::Sequence(), cmd);
- }
- void MockFidoHidConnection::ExpectHidWriteWithCommand(
- const testing::Sequence& sequence,
- FidoHidDeviceCommand cmd) {
- EXPECT_CALL(*this,
- WritePtr(::testing::_, IsCtapHidCommand(cmd), ::testing::_))
- .InSequence(sequence)
- .WillOnce(::testing::Invoke(
- [&](auto&&, const std::vector<uint8_t>& buffer,
- device::mojom::HidConnection::WriteCallback* cb) {
- std::move(*cb).Run(true);
- }));
- }
- void MockFidoHidConnection::ExpectReadAndReplyWith(
- const testing::Sequence& sequence,
- std::vector<uint8_t> response) {
- EXPECT_CALL(*this, ReadPtr(testing::_))
- .InSequence(sequence)
- .WillOnce(::testing::Invoke(
- [response](device::mojom::HidConnection::ReadCallback* cb) {
- std::move(*cb).Run(true, 0, std::move(response));
- }));
- }
- bool FakeFidoHidConnection::mock_connection_error_ = false;
- FakeFidoHidConnection::FakeFidoHidConnection(
- device::mojom::HidDeviceInfoPtr device)
- : device_(std::move(device)) {}
- FakeFidoHidConnection::~FakeFidoHidConnection() = default;
- void FakeFidoHidConnection::Read(ReadCallback callback) {
- std::vector<uint8_t> buffer = {'F', 'a', 'k', 'e', ' ', 'H', 'i', 'd'};
- std::move(callback).Run(true, 0, buffer);
- }
- void FakeFidoHidConnection::Write(uint8_t report_id,
- const std::vector<uint8_t>& buffer,
- WriteCallback callback) {
- if (mock_connection_error_) {
- std::move(callback).Run(false);
- return;
- }
- std::move(callback).Run(true);
- }
- void FakeFidoHidConnection::GetFeatureReport(
- uint8_t report_id,
- GetFeatureReportCallback callback) {
- NOTREACHED();
- }
- void FakeFidoHidConnection::SendFeatureReport(
- uint8_t report_id,
- const std::vector<uint8_t>& buffer,
- SendFeatureReportCallback callback) {
- NOTREACHED();
- }
- FakeFidoHidManager::FakeFidoHidManager() = default;
- FakeFidoHidManager::~FakeFidoHidManager() = default;
- void FakeFidoHidManager::AddReceiver(
- mojo::PendingReceiver<device::mojom::HidManager> receiver) {
- receivers_.Add(this, std::move(receiver));
- }
- void FakeFidoHidManager::AddFidoHidDevice(std::string guid) {
- auto c_info = device::mojom::HidCollectionInfo::New();
- c_info->usage = device::mojom::HidUsageAndPage::New(1, 0xf1d0);
- c_info->input_reports.push_back(device::mojom::HidReportDescription::New());
- auto device = device::mojom::HidDeviceInfo::New();
- device->guid = std::move(guid);
- device->product_name = "Test Fido Device";
- device->serial_number = "123FIDO";
- device->bus_type = device::mojom::HidBusType::kHIDBusTypeUSB;
- device->collections.push_back(std::move(c_info));
- device->max_input_report_size = 64;
- device->max_output_report_size = 64;
- device->protected_input_report_ids =
- HidBlocklist::Get().GetProtectedReportIds(
- HidBlocklist::kReportTypeInput, device->vendor_id, device->product_id,
- device->collections);
- device->protected_output_report_ids =
- HidBlocklist::Get().GetProtectedReportIds(
- HidBlocklist::kReportTypeOutput, device->vendor_id,
- device->product_id, device->collections);
- device->protected_feature_report_ids =
- HidBlocklist::Get().GetProtectedReportIds(
- HidBlocklist::kReportTypeFeature, device->vendor_id,
- device->product_id, device->collections);
- device->is_excluded_by_blocklist = HidBlocklist::Get().IsVendorProductBlocked(
- device->vendor_id, device->product_id);
- AddDevice(std::move(device));
- }
- void FakeFidoHidManager::GetDevicesAndSetClient(
- mojo::PendingAssociatedRemote<device::mojom::HidManagerClient> client,
- GetDevicesCallback callback) {
- GetDevices(std::move(callback));
- clients_.Add(std::move(client));
- }
- void FakeFidoHidManager::GetDevices(GetDevicesCallback callback) {
- std::vector<device::mojom::HidDeviceInfoPtr> device_list;
- for (auto& map_entry : devices_)
- device_list.push_back(map_entry.second->Clone());
- std::move(callback).Run(std::move(device_list));
- }
- void FakeFidoHidManager::Connect(
- const std::string& device_guid,
- mojo::PendingRemote<mojom::HidConnectionClient> connection_client,
- mojo::PendingRemote<mojom::HidConnectionWatcher> watcher,
- bool allow_protected_reports,
- bool allow_fido_reports,
- ConnectCallback callback) {
- auto device_it = devices_.find(device_guid);
- auto connection_it = connections_.find(device_guid);
- if (device_it == devices_.end() || connection_it == connections_.end()) {
- std::move(callback).Run(mojo::NullRemote());
- return;
- }
- std::move(callback).Run(std::move(connection_it->second));
- }
- void FakeFidoHidManager::AddDevice(device::mojom::HidDeviceInfoPtr device) {
- DCHECK(!base::Contains(devices_, device->guid));
- device::mojom::HidDeviceInfo* device_info = device.get();
- for (auto& client : clients_)
- client->DeviceAdded(device_info->Clone());
- devices_[device->guid] = std::move(device);
- }
- void FakeFidoHidManager::AddDeviceAndSetConnection(
- device::mojom::HidDeviceInfoPtr device,
- mojo::PendingRemote<device::mojom::HidConnection> connection) {
- connections_[device->guid] = std::move(connection);
- AddDevice(std::move(device));
- }
- void FakeFidoHidManager::RemoveDevice(const std::string device_guid) {
- auto it = devices_.find(device_guid);
- if (it == devices_.end())
- return;
- device::mojom::HidDeviceInfo* device_info = it->second.get();
- for (auto& client : clients_)
- client->DeviceRemoved(device_info->Clone());
- devices_.erase(it);
- }
- void FakeFidoHidManager::ChangeDevice(device::mojom::HidDeviceInfoPtr device) {
- DCHECK(base::Contains(devices_, device->guid));
- device::mojom::HidDeviceInfo* device_info = device.get();
- for (auto& client : clients_)
- client->DeviceChanged(device_info->Clone());
- devices_[device->guid] = std::move(device);
- }
- ScopedFakeFidoHidManager::ScopedFakeFidoHidManager() {
- FidoHidDiscovery::SetHidManagerBinder(base::BindRepeating(
- &FakeFidoHidManager::AddReceiver, base::Unretained(this)));
- }
- ScopedFakeFidoHidManager::~ScopedFakeFidoHidManager() {
- FidoHidDiscovery::SetHidManagerBinder(base::NullCallback());
- }
- } // namespace device
|