blob: 6965573bad667ff9a5cba66a4dc337503c821b3d [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 "services/device/public/cpp/test/fake_usb_device.h"
#include <algorithm>
#include <memory>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback.h"
#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
#include "services/device/public/cpp/test/mock_usb_mojo_device.h"
#include "services/device/public/cpp/usb/usb_utils.h"
namespace device {
// static
void FakeUsbDevice::Create(scoped_refptr<FakeUsbDeviceInfo> device,
mojom::UsbDeviceRequest request,
mojom::UsbDeviceClientPtr client) {
auto* device_object = new FakeUsbDevice(device, std::move(client));
device_object->binding_ = mojo::MakeStrongBinding(
base::WrapUnique(device_object), std::move(request));
}
FakeUsbDevice::~FakeUsbDevice() {
CloseHandle();
observer_.RemoveAll();
}
FakeUsbDevice::FakeUsbDevice(scoped_refptr<FakeUsbDeviceInfo> device,
mojom::UsbDeviceClientPtr client)
: device_(device), observer_(this), client_(std::move(client)) {
DCHECK(device_);
observer_.Add(device_.get());
if (client_) {
client_.set_connection_error_handler(base::BindOnce(
&FakeUsbDevice::OnClientConnectionError, base::Unretained(this)));
}
}
void FakeUsbDevice::CloseHandle() {
if (!is_opened_) {
return;
}
MockUsbMojoDevice* mock_device = device_->mock_device();
if (mock_device) {
mock_device->Close(base::DoNothing::Once());
return;
}
if (client_)
client_->OnDeviceClosed();
is_opened_ = false;
}
// Device implementation:
void FakeUsbDevice::Open(OpenCallback callback) {
// Go on with mock device for testing.
MockUsbMojoDevice* mock_device = device_->mock_device();
if (mock_device) {
mock_device->Open(std::move(callback));
is_opened_ = true;
return;
}
if (is_opened_) {
std::move(callback).Run(mojom::UsbOpenDeviceError::ALREADY_OPEN);
return;
}
is_opened_ = true;
if (client_)
client_->OnDeviceOpened();
std::move(callback).Run(mojom::UsbOpenDeviceError::OK);
}
void FakeUsbDevice::Close(CloseCallback callback) {
// Go on with mock device for testing.
MockUsbMojoDevice* mock_device = device_->mock_device();
if (mock_device) {
mock_device->Close(std::move(callback));
return;
}
CloseHandle();
std::move(callback).Run();
}
void FakeUsbDevice::SetConfiguration(uint8_t value,
SetConfigurationCallback callback) {
// Go on with mock device for testing.
MockUsbMojoDevice* mock_device = device_->mock_device();
if (mock_device) {
mock_device->SetConfiguration(value, std::move(callback));
return;
}
std::move(callback).Run(true);
}
void FakeUsbDevice::ClaimInterface(uint8_t interface_number,
ClaimInterfaceCallback callback) {
// Go on with mock device for testing.
MockUsbMojoDevice* mock_device = device_->mock_device();
if (mock_device) {
mock_device->ClaimInterface(interface_number, std::move(callback));
return;
}
bool success = claimed_interfaces_.insert(interface_number).second;
std::move(callback).Run(success);
}
void FakeUsbDevice::ReleaseInterface(uint8_t interface_number,
ReleaseInterfaceCallback callback) {
// Go on with mock device for testing.
MockUsbMojoDevice* mock_device = device_->mock_device();
if (mock_device) {
mock_device->ReleaseInterface(interface_number, std::move(callback));
return;
}
bool success = claimed_interfaces_.erase(interface_number) > 0;
std::move(callback).Run(success);
}
void FakeUsbDevice::SetInterfaceAlternateSetting(
uint8_t interface_number,
uint8_t alternate_setting,
SetInterfaceAlternateSettingCallback callback) {
// Go on with mock device for testing.
MockUsbMojoDevice* mock_device = device_->mock_device();
if (mock_device) {
mock_device->SetInterfaceAlternateSetting(
interface_number, alternate_setting, std::move(callback));
return;
}
std::move(callback).Run(true);
}
void FakeUsbDevice::Reset(ResetCallback callback) {
// Go on with mock device for testing.
MockUsbMojoDevice* mock_device = device_->mock_device();
if (mock_device) {
mock_device->Reset(std::move(callback));
return;
}
std::move(callback).Run(true);
}
void FakeUsbDevice::ClearHalt(uint8_t endpoint, ClearHaltCallback callback) {
// Go on with mock device for testing.
MockUsbMojoDevice* mock_device = device_->mock_device();
if (mock_device) {
mock_device->ClearHalt(endpoint, std::move(callback));
return;
}
std::move(callback).Run(true);
}
void FakeUsbDevice::ControlTransferIn(mojom::UsbControlTransferParamsPtr params,
uint32_t length,
uint32_t timeout,
ControlTransferInCallback callback) {
// Go on with mock device for testing.
MockUsbMojoDevice* mock_device = device_->mock_device();
if (mock_device) {
mock_device->ControlTransferIn(std::move(params), length, timeout,
std::move(callback));
return;
}
std::move(callback).Run(mojom::UsbTransferStatus::COMPLETED, {});
}
void FakeUsbDevice::ControlTransferOut(
mojom::UsbControlTransferParamsPtr params,
const std::vector<uint8_t>& data,
uint32_t timeout,
ControlTransferOutCallback callback) {
// Go on with mock device for testing.
MockUsbMojoDevice* mock_device = device_->mock_device();
if (mock_device) {
mock_device->ControlTransferOut(std::move(params), data, timeout,
std::move(callback));
return;
}
std::move(callback).Run(mojom::UsbTransferStatus::COMPLETED);
}
void FakeUsbDevice::GenericTransferIn(uint8_t endpoint_number,
uint32_t length,
uint32_t timeout,
GenericTransferInCallback callback) {
// Go on with mock device for testing.
MockUsbMojoDevice* mock_device = device_->mock_device();
if (mock_device) {
mock_device->GenericTransferIn(endpoint_number, length, timeout,
std::move(callback));
return;
}
std::move(callback).Run(mojom::UsbTransferStatus::COMPLETED, {});
}
void FakeUsbDevice::GenericTransferOut(uint8_t endpoint_number,
const std::vector<uint8_t>& data,
uint32_t timeout,
GenericTransferOutCallback callback) {
// Go on with mock device for testing.
MockUsbMojoDevice* mock_device = device_->mock_device();
if (mock_device) {
mock_device->GenericTransferOut(endpoint_number, data, timeout,
std::move(callback));
return;
}
std::move(callback).Run(mojom::UsbTransferStatus::COMPLETED);
}
void FakeUsbDevice::IsochronousTransferIn(
uint8_t endpoint_number,
const std::vector<uint32_t>& packet_lengths,
uint32_t timeout,
IsochronousTransferInCallback callback) {
// Go on with mock device for testing.
MockUsbMojoDevice* mock_device = device_->mock_device();
if (mock_device) {
mock_device->IsochronousTransferIn(endpoint_number, packet_lengths, timeout,
std::move(callback));
return;
}
std::move(callback).Run(
{}, BuildIsochronousPacketArray(packet_lengths,
mojom::UsbTransferStatus::COMPLETED));
}
void FakeUsbDevice::IsochronousTransferOut(
uint8_t endpoint_number,
const std::vector<uint8_t>& data,
const std::vector<uint32_t>& packet_lengths,
uint32_t timeout,
IsochronousTransferOutCallback callback) {
// Go on with mock device for testing.
MockUsbMojoDevice* mock_device = device_->mock_device();
if (mock_device) {
mock_device->IsochronousTransferOut(endpoint_number, data, packet_lengths,
timeout, std::move(callback));
return;
}
std::move(callback).Run(BuildIsochronousPacketArray(
packet_lengths, mojom::UsbTransferStatus::COMPLETED));
}
void FakeUsbDevice::OnDeviceRemoved(scoped_refptr<FakeUsbDeviceInfo> device) {
DCHECK_EQ(device_, device);
binding_->Close();
}
void FakeUsbDevice::OnClientConnectionError() {
// Close the binding with Blink when WebUsbService finds permission revoked
// from setting UI.
binding_->Close();
}
} // namespace device