Index: device/devices_app/usb/device_impl.cc |
diff --git a/device/devices_app/usb/device_impl.cc b/device/devices_app/usb/device_impl.cc |
index 1516c76fd14af7b520c74542c070f7297c70aad0..7f64cc6d3e3537de68d28d138e9f8acd0ed2bd9b 100644 |
--- a/device/devices_app/usb/device_impl.cc |
+++ b/device/devices_app/usb/device_impl.cc |
@@ -31,38 +31,26 @@ base::Callback<void(Args...)> WrapMojoCallback( |
return base::Bind(&CallMojoCallback<Args...>, callback); |
} |
+void OnPermissionCheckComplete( |
+ const base::Callback<void(bool)>& callback, |
+ const base::Callback<void(const base::Callback<void(bool)>&)>& action, |
+ bool allowed) { |
+ if (allowed) |
+ action.Run(callback); |
+ else |
+ callback.Run(false); |
+} |
+ |
scoped_refptr<net::IOBuffer> CreateTransferBuffer(size_t size) { |
scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer( |
std::max(static_cast<size_t>(1u), static_cast<size_t>(size))); |
return buffer; |
} |
-} // namespace |
- |
-DeviceImpl::DeviceImpl(scoped_refptr<UsbDevice> device, |
- mojo::InterfaceRequest<Device> request) |
- : binding_(this, request.Pass()), device_(device), weak_factory_(this) {} |
- |
-DeviceImpl::~DeviceImpl() { |
- CloseHandle(); |
-} |
- |
-void DeviceImpl::CloseHandle() { |
- if (device_handle_) |
- device_handle_->Close(); |
- device_handle_ = nullptr; |
-} |
- |
-void DeviceImpl::OnOpen(const OpenCallback& callback, |
- scoped_refptr<UsbDeviceHandle> handle) { |
- device_handle_ = handle; |
- callback.Run(handle ? OPEN_DEVICE_ERROR_OK : OPEN_DEVICE_ERROR_ACCESS_DENIED); |
-} |
- |
-void DeviceImpl::OnTransferIn(const MojoTransferInCallback& callback, |
- UsbTransferStatus status, |
- scoped_refptr<net::IOBuffer> buffer, |
- size_t buffer_size) { |
+void OnTransferIn(const DeviceImpl::MojoTransferInCallback& callback, |
+ UsbTransferStatus status, |
+ scoped_refptr<net::IOBuffer> buffer, |
+ size_t buffer_size) { |
mojo::Array<uint8_t> data; |
if (buffer) { |
// TODO(rockot/reillyg): We should change UsbDeviceHandle to use a |
@@ -75,15 +63,58 @@ void DeviceImpl::OnTransferIn(const MojoTransferInCallback& callback, |
callback.Run(mojo::ConvertTo<TransferStatus>(status), data.Pass()); |
} |
-void DeviceImpl::OnTransferOut(const MojoTransferOutCallback& callback, |
- UsbTransferStatus status, |
- scoped_refptr<net::IOBuffer> buffer, |
- size_t buffer_size) { |
+void OnControlTransferInPermissionCheckComplete( |
+ scoped_refptr<UsbDeviceHandle> device_handle, |
+ ControlTransferParamsPtr params, |
+ int length, |
+ int timeout, |
+ const Device::ControlTransferInCallback& callback, |
+ bool allowed) { |
+ if (allowed) { |
+ scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(length); |
+ device_handle->ControlTransfer( |
+ USB_DIRECTION_INBOUND, |
+ mojo::ConvertTo<UsbDeviceHandle::TransferRequestType>(params->type), |
+ mojo::ConvertTo<UsbDeviceHandle::TransferRecipient>(params->recipient), |
+ params->request, params->value, params->index, buffer, length, timeout, |
+ base::Bind(&OnTransferIn, callback)); |
+ } else { |
+ mojo::Array<uint8_t> data; |
+ callback.Run(TRANSFER_STATUS_PERMISSION_DENIED, data.Pass()); |
+ } |
+} |
+ |
+void OnTransferOut(const DeviceImpl::MojoTransferOutCallback& callback, |
+ UsbTransferStatus status, |
+ scoped_refptr<net::IOBuffer> buffer, |
+ size_t buffer_size) { |
callback.Run(mojo::ConvertTo<TransferStatus>(status)); |
} |
-void DeviceImpl::OnIsochronousTransferIn( |
- const IsochronousTransferInCallback& callback, |
+void OnControlTransferOutPermissionCheckComplete( |
+ scoped_refptr<UsbDeviceHandle> device_handle, |
+ ControlTransferParamsPtr params, |
+ mojo::Array<uint8_t> data, |
+ int timeout, |
+ const Device::ControlTransferOutCallback& callback, |
+ bool allowed) { |
+ if (allowed) { |
+ scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(data.size()); |
+ const std::vector<uint8_t>& storage = data.storage(); |
+ std::copy(storage.begin(), storage.end(), buffer->data()); |
+ device_handle->ControlTransfer( |
+ USB_DIRECTION_OUTBOUND, |
+ mojo::ConvertTo<UsbDeviceHandle::TransferRequestType>(params->type), |
+ mojo::ConvertTo<UsbDeviceHandle::TransferRecipient>(params->recipient), |
+ params->request, params->value, params->index, buffer, data.size(), |
+ timeout, base::Bind(&OnTransferOut, callback)); |
+ } else { |
+ callback.Run(TRANSFER_STATUS_PERMISSION_DENIED); |
+ } |
+} |
+ |
+void OnIsochronousTransferIn( |
+ const Device::IsochronousTransferInCallback& callback, |
uint32_t packet_size, |
UsbTransferStatus status, |
scoped_refptr<net::IOBuffer> buffer, |
@@ -102,14 +133,81 @@ void DeviceImpl::OnIsochronousTransferIn( |
callback.Run(mojo::ConvertTo<TransferStatus>(status), packets.Pass()); |
} |
-void DeviceImpl::OnIsochronousTransferOut( |
- const MojoTransferOutCallback& callback, |
+void OnIsochronousTransferOut( |
+ const Device::IsochronousTransferOutCallback& callback, |
UsbTransferStatus status, |
scoped_refptr<net::IOBuffer> buffer, |
size_t buffer_size) { |
callback.Run(mojo::ConvertTo<TransferStatus>(status)); |
} |
+} // namespace |
+ |
+DeviceImpl::DeviceImpl(scoped_refptr<UsbDevice> device, |
+ PermissionProviderPtr permission_provider, |
+ mojo::InterfaceRequest<Device> request) |
+ : binding_(this, request.Pass()), |
+ device_(device), |
+ permission_provider_(permission_provider.Pass()), |
+ weak_factory_(this) { |
+ // This object owns itself and will be destroyed if either the message pipe |
+ // it is bound to is closed or the PermissionProvider it depends on is |
+ // unavailable. |
+ binding_.set_connection_error_handler([this]() { delete this; }); |
+ permission_provider_.set_connection_error_handler([this]() { delete this; }); |
+} |
+ |
+DeviceImpl::~DeviceImpl() { |
+ CloseHandle(); |
+} |
+ |
+void DeviceImpl::CloseHandle() { |
+ if (device_handle_) |
+ device_handle_->Close(); |
+ device_handle_ = nullptr; |
+} |
+ |
+void DeviceImpl::HasControlTransferPermission( |
+ ControlTransferRecipient recipient, |
+ uint16_t index, |
+ const base::Callback<void(bool)>& callback) { |
+ DCHECK(device_handle_); |
+ const UsbConfigDescriptor* config = device_->GetActiveConfiguration(); |
+ |
+ if (recipient == CONTROL_TRANSFER_RECIPIENT_INTERFACE || |
+ recipient == CONTROL_TRANSFER_RECIPIENT_ENDPOINT) { |
+ if (!config) { |
+ callback.Run(false); |
+ return; |
+ } |
+ |
+ uint8_t interface_number = index & 0xff; |
+ if (recipient == CONTROL_TRANSFER_RECIPIENT_ENDPOINT) { |
+ if (!device_handle_->FindInterfaceByEndpoint(index & 0xff, |
+ &interface_number)) { |
+ callback.Run(false); |
+ return; |
+ } |
+ } |
+ |
+ permission_provider_->HasInterfacePermission( |
+ interface_number, config->configuration_value, |
+ DeviceInfo::From(*device_), callback); |
+ } else if (config) { |
+ permission_provider_->HasConfigurationPermission( |
+ config->configuration_value, DeviceInfo::From(*device_), callback); |
+ } else { |
+ // Client must already have device permission to have gotten this far. |
+ callback.Run(true); |
+ } |
+} |
+ |
+void DeviceImpl::OnOpen(const OpenCallback& callback, |
+ scoped_refptr<UsbDeviceHandle> handle) { |
+ device_handle_ = handle; |
+ callback.Run(handle ? OPEN_DEVICE_ERROR_OK : OPEN_DEVICE_ERROR_ACCESS_DENIED); |
+} |
+ |
void DeviceImpl::GetDeviceInfo(const GetDeviceInfoCallback& callback) { |
callback.Run(DeviceInfo::From(*device_)); |
} |
@@ -136,7 +234,12 @@ void DeviceImpl::SetConfiguration(uint8_t value, |
return; |
} |
- device_handle_->SetConfiguration(value, WrapMojoCallback(callback)); |
+ auto set_configuration = |
+ base::Bind(&UsbDeviceHandle::SetConfiguration, device_handle_, value); |
+ permission_provider_->HasConfigurationPermission( |
+ value, DeviceInfo::From(*device_), |
+ base::Bind(&OnPermissionCheckComplete, WrapMojoCallback(callback), |
+ set_configuration)); |
} |
void DeviceImpl::ClaimInterface(uint8_t interface_number, |
@@ -146,7 +249,18 @@ void DeviceImpl::ClaimInterface(uint8_t interface_number, |
return; |
} |
- device_handle_->ClaimInterface(interface_number, WrapMojoCallback(callback)); |
+ const UsbConfigDescriptor* config = device_->GetActiveConfiguration(); |
+ if (!config) { |
+ callback.Run(false); |
+ return; |
+ } |
+ |
+ auto claim_interface = base::Bind(&UsbDeviceHandle::ClaimInterface, |
+ device_handle_, interface_number); |
+ permission_provider_->HasInterfacePermission( |
+ interface_number, config->configuration_value, DeviceInfo::From(*device_), |
+ base::Bind(&OnPermissionCheckComplete, WrapMojoCallback(callback), |
+ claim_interface)); |
} |
void DeviceImpl::ReleaseInterface(uint8_t interface_number, |
@@ -200,14 +314,12 @@ void DeviceImpl::ControlTransferIn(ControlTransferParamsPtr params, |
return; |
} |
- scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(length); |
- device_handle_->ControlTransfer( |
- USB_DIRECTION_INBOUND, |
- mojo::ConvertTo<UsbDeviceHandle::TransferRequestType>(params->type), |
- mojo::ConvertTo<UsbDeviceHandle::TransferRecipient>(params->recipient), |
- params->request, params->value, params->index, buffer, length, timeout, |
- base::Bind(&DeviceImpl::OnTransferIn, weak_factory_.GetWeakPtr(), |
- callback)); |
+ ControlTransferRecipient recipient = params->recipient; |
+ uint16_t index = params->index; |
+ HasControlTransferPermission( |
+ recipient, index, |
+ base::Bind(&OnControlTransferInPermissionCheckComplete, device_handle_, |
+ base::Passed(¶ms), length, timeout, callback)); |
} |
void DeviceImpl::ControlTransferOut( |
@@ -220,16 +332,12 @@ void DeviceImpl::ControlTransferOut( |
return; |
} |
- scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(data.size()); |
- const std::vector<uint8_t>& storage = data.storage(); |
- std::copy(storage.begin(), storage.end(), buffer->data()); |
- device_handle_->ControlTransfer( |
- USB_DIRECTION_OUTBOUND, |
- mojo::ConvertTo<UsbDeviceHandle::TransferRequestType>(params->type), |
- mojo::ConvertTo<UsbDeviceHandle::TransferRecipient>(params->recipient), |
- params->request, params->value, params->index, buffer, data.size(), |
- timeout, base::Bind(&DeviceImpl::OnTransferOut, |
- weak_factory_.GetWeakPtr(), callback)); |
+ ControlTransferRecipient recipient = params->recipient; |
+ uint16_t index = params->index; |
+ HasControlTransferPermission( |
+ recipient, index, base::Bind(&OnControlTransferOutPermissionCheckComplete, |
+ device_handle_, base::Passed(¶ms), |
+ base::Passed(&data), timeout, callback)); |
} |
void DeviceImpl::GenericTransferIn(uint8_t endpoint_number, |
@@ -243,10 +351,9 @@ void DeviceImpl::GenericTransferIn(uint8_t endpoint_number, |
uint8_t endpoint_address = endpoint_number | 0x80; |
scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(length); |
- device_handle_->GenericTransfer( |
- USB_DIRECTION_INBOUND, endpoint_address, buffer, length, timeout, |
- base::Bind(&DeviceImpl::OnTransferIn, weak_factory_.GetWeakPtr(), |
- callback)); |
+ device_handle_->GenericTransfer(USB_DIRECTION_INBOUND, endpoint_address, |
+ buffer, length, timeout, |
+ base::Bind(&OnTransferIn, callback)); |
} |
void DeviceImpl::GenericTransferOut( |
@@ -263,10 +370,9 @@ void DeviceImpl::GenericTransferOut( |
scoped_refptr<net::IOBuffer> buffer = CreateTransferBuffer(data.size()); |
const std::vector<uint8_t>& storage = data.storage(); |
std::copy(storage.begin(), storage.end(), buffer->data()); |
- device_handle_->GenericTransfer( |
- USB_DIRECTION_OUTBOUND, endpoint_address, buffer, data.size(), timeout, |
- base::Bind(&DeviceImpl::OnTransferOut, weak_factory_.GetWeakPtr(), |
- callback)); |
+ device_handle_->GenericTransfer(USB_DIRECTION_OUTBOUND, endpoint_address, |
+ buffer, data.size(), timeout, |
+ base::Bind(&OnTransferOut, callback)); |
} |
void DeviceImpl::IsochronousTransferIn( |
@@ -286,8 +392,7 @@ void DeviceImpl::IsochronousTransferIn( |
device_handle_->IsochronousTransfer( |
USB_DIRECTION_INBOUND, endpoint_address, buffer, transfer_size, |
num_packets, packet_length, timeout, |
- base::Bind(&DeviceImpl::OnIsochronousTransferIn, |
- weak_factory_.GetWeakPtr(), callback, packet_length)); |
+ base::Bind(&OnIsochronousTransferIn, callback, packet_length)); |
} |
void DeviceImpl::IsochronousTransferOut( |
@@ -318,8 +423,7 @@ void DeviceImpl::IsochronousTransferOut( |
device_handle_->IsochronousTransfer( |
USB_DIRECTION_OUTBOUND, endpoint_address, buffer, transfer_size, |
static_cast<uint32_t>(packets.size()), packet_size, timeout, |
- base::Bind(&DeviceImpl::OnIsochronousTransferOut, |
- weak_factory_.GetWeakPtr(), callback)); |
+ base::Bind(&OnIsochronousTransferOut, callback)); |
} |
} // namespace usb |