#include "services/device/usb/mojo/device_manager_impl.h"
#include <stddef.h>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "build/build_config.h"
#include "mojo/public/cpp/bindings/associated_remote.h"
#include "services/device/public/cpp/usb/usb_utils.h"
#include "services/device/public/mojom/usb_device.mojom.h"
#include "services/device/public/mojom/usb_enumeration_options.mojom.h"
#include "services/device/public/mojom/usb_manager_client.mojom.h"
#include "services/device/usb/mojo/device_impl.h"
#include "services/device/usb/usb_device.h"
#include "services/device/usb/usb_service.h"
#if BUILDFLAG(IS_CHROMEOS)
#include "chromeos/dbus/permission_broker/permission_broker_client.h"
#include "services/device/usb/usb_device_linux.h"
#endif
namespace device::usb {
DeviceManagerImpl::DeviceManagerImpl()
: … { … }
DeviceManagerImpl::DeviceManagerImpl(std::unique_ptr<UsbService> usb_service)
: … { … }
DeviceManagerImpl::~DeviceManagerImpl() = default;
void DeviceManagerImpl::AddReceiver(
mojo::PendingReceiver<mojom::UsbDeviceManager> receiver) { … }
void DeviceManagerImpl::EnumerateDevicesAndSetClient(
mojo::PendingAssociatedRemote<mojom::UsbDeviceManagerClient> client,
EnumerateDevicesAndSetClientCallback callback) { … }
void DeviceManagerImpl::GetDevices(mojom::UsbEnumerationOptionsPtr options,
GetDevicesCallback callback) { … }
void DeviceManagerImpl::GetDevice(
const std::string& guid,
const std::vector<uint8_t>& blocked_interface_classes,
mojo::PendingReceiver<mojom::UsbDevice> device_receiver,
mojo::PendingRemote<mojom::UsbDeviceClient> device_client) { … }
void DeviceManagerImpl::GetSecurityKeyDevice(
const std::string& guid,
mojo::PendingReceiver<mojom::UsbDevice> device_receiver,
mojo::PendingRemote<mojom::UsbDeviceClient> device_client) { … }
#if BUILDFLAG(IS_ANDROID)
void DeviceManagerImpl::RefreshDeviceInfo(const std::string& guid,
RefreshDeviceInfoCallback callback) {
scoped_refptr<UsbDevice> device = usb_service_->GetDevice(guid);
if (!device) {
std::move(callback).Run(nullptr);
return;
}
if (device->permission_granted()) {
std::move(callback).Run(device->device_info().Clone());
return;
}
device->RequestPermission(
base::BindOnce(&DeviceManagerImpl::OnPermissionGrantedToRefresh,
weak_factory_.GetWeakPtr(), device, std::move(callback)));
}
void DeviceManagerImpl::OnPermissionGrantedToRefresh(
scoped_refptr<UsbDevice> device,
RefreshDeviceInfoCallback callback,
bool granted) {
DCHECK_EQ(granted, device->permission_granted());
if (!device->permission_granted()) {
std::move(callback).Run(nullptr);
return;
}
std::move(callback).Run(device->device_info().Clone());
}
#endif
#if BUILDFLAG(IS_CHROMEOS)
void DeviceManagerImpl::CheckAccess(const std::string& guid,
CheckAccessCallback callback) {
scoped_refptr<UsbDevice> device = usb_service_->GetDevice(guid);
if (device) {
device->CheckUsbAccess(std::move(callback));
} else {
LOG(ERROR) << "Was asked to check access to non-existent USB device: "
<< guid;
std::move(callback).Run(false);
}
}
void DeviceManagerImpl::OpenFileDescriptor(
const std::string& guid,
uint32_t drop_privileges_mask,
mojo::PlatformHandle lifeline_fd,
OpenFileDescriptorCallback callback) {
scoped_refptr<UsbDevice> device = usb_service_->GetDevice(guid);
if (!device) {
LOG(ERROR) << "Was asked to open non-existent USB device: " << guid;
std::move(callback).Run(base::File());
} else {
auto split_callback = base::SplitOnceCallback(std::move(callback));
auto devpath =
static_cast<device::UsbDeviceLinux*>(device.get())->device_path();
chromeos::PermissionBrokerClient::Get()->ClaimDevicePath(
devpath, drop_privileges_mask, lifeline_fd.GetFD().get(),
base::BindOnce(&DeviceManagerImpl::OnOpenFileDescriptor,
weak_factory_.GetWeakPtr(),
std::move(split_callback.first)),
base::BindOnce(&DeviceManagerImpl::OnOpenFileDescriptorError,
weak_factory_.GetWeakPtr(),
std::move(split_callback.second)));
}
}
void DeviceManagerImpl::OnOpenFileDescriptor(
OpenFileDescriptorCallback callback,
base::ScopedFD fd) {
std::move(callback).Run(base::File(std::move(fd)));
}
void DeviceManagerImpl::OnOpenFileDescriptorError(
OpenFileDescriptorCallback callback,
const std::string& error_name,
const std::string& message) {
LOG(ERROR) << "Failed to open USB device file: " << error_name << " "
<< message;
std::move(callback).Run(base::File());
}
#endif
void DeviceManagerImpl::SetClient(
mojo::PendingAssociatedRemote<mojom::UsbDeviceManagerClient> client) { … }
void DeviceManagerImpl::OnGetDevices(
mojom::UsbEnumerationOptionsPtr options,
mojo::PendingAssociatedRemote<mojom::UsbDeviceManagerClient> client,
GetDevicesCallback callback,
const std::vector<scoped_refptr<UsbDevice>>& devices) { … }
void DeviceManagerImpl::OnDeviceAdded(scoped_refptr<UsbDevice> device) { … }
void DeviceManagerImpl::OnDeviceRemoved(scoped_refptr<UsbDevice> device) { … }
void DeviceManagerImpl::WillDestroyUsbService() { … }
void DeviceManagerImpl::GetDeviceInternal(
const std::string& guid,
mojo::PendingReceiver<mojom::UsbDevice> device_receiver,
mojo::PendingRemote<mojom::UsbDeviceClient> device_client,
base::span<const uint8_t> blocked_interface_classes,
bool allow_security_key_requests) { … }
}