1 // Copyright 2014 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.
5 #include "extensions/browser/api/usb/usb_api.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/message_loop/message_loop_proxy.h"
12 #include "device/core/device_client.h"
13 #include "device/usb/usb_device_handle.h"
14 #include "device/usb/usb_service.h"
15 #include "extensions/browser/api/device_permissions_manager.h"
16 #include "extensions/browser/api/device_permissions_prompt.h"
17 #include "extensions/browser/api/extensions_api_client.h"
18 #include "extensions/browser/api/usb/usb_device_resource.h"
19 #include "extensions/browser/extension_system.h"
20 #include "extensions/common/api/usb.h"
21 #include "extensions/common/permissions/permissions_data.h"
22 #include "extensions/common/permissions/usb_device_permission.h"
24 namespace usb
= extensions::core_api::usb
;
25 namespace BulkTransfer
= usb::BulkTransfer
;
26 namespace ClaimInterface
= usb::ClaimInterface
;
27 namespace CloseDevice
= usb::CloseDevice
;
28 namespace ControlTransfer
= usb::ControlTransfer
;
29 namespace FindDevices
= usb::FindDevices
;
30 namespace GetDevices
= usb::GetDevices
;
31 namespace GetUserSelectedDevices
= usb::GetUserSelectedDevices
;
32 namespace InterruptTransfer
= usb::InterruptTransfer
;
33 namespace IsochronousTransfer
= usb::IsochronousTransfer
;
34 namespace SetConfiguration
= usb::SetConfiguration
;
35 namespace GetConfiguration
= usb::GetConfiguration
;
36 namespace ListInterfaces
= usb::ListInterfaces
;
37 namespace OpenDevice
= usb::OpenDevice
;
38 namespace ReleaseInterface
= usb::ReleaseInterface
;
39 namespace RequestAccess
= usb::RequestAccess
;
40 namespace ResetDevice
= usb::ResetDevice
;
41 namespace SetInterfaceAlternateSetting
= usb::SetInterfaceAlternateSetting
;
43 using content::BrowserThread
;
44 using device::UsbConfigDescriptor
;
45 using device::UsbDevice
;
46 using device::UsbDeviceFilter
;
47 using device::UsbDeviceHandle
;
48 using device::UsbEndpointDescriptor
;
49 using device::UsbEndpointDirection
;
50 using device::UsbInterfaceDescriptor
;
51 using device::UsbService
;
52 using device::UsbSynchronizationType
;
53 using device::UsbTransferStatus
;
54 using device::UsbTransferType
;
55 using device::UsbUsageType
;
58 using usb::ConfigDescriptor
;
59 using usb::ControlTransferInfo
;
60 using usb::ConnectionHandle
;
63 using usb::EndpointDescriptor
;
64 using usb::GenericTransferInfo
;
65 using usb::InterfaceDescriptor
;
66 using usb::IsochronousTransferInfo
;
68 using usb::RequestType
;
69 using usb::SynchronizationType
;
70 using usb::TransferType
;
73 typedef std::vector
<scoped_refptr
<UsbDevice
> > DeviceVector
;
74 typedef scoped_ptr
<DeviceVector
> ScopedDeviceVector
;
78 const char kDataKey
[] = "data";
79 const char kResultCodeKey
[] = "resultCode";
81 const char kErrorInitService
[] = "Failed to initialize USB service.";
83 const char kErrorOpen
[] = "Failed to open device.";
84 const char kErrorCancelled
[] = "Transfer was cancelled.";
85 const char kErrorDisconnect
[] = "Device disconnected.";
86 const char kErrorGeneric
[] = "Transfer failed.";
87 const char kErrorNotSupported
[] = "Not supported on this platform.";
88 const char kErrorNotConfigured
[] = "The device is not in a configured state.";
89 const char kErrorOverflow
[] = "Inbound transfer overflow.";
90 const char kErrorStalled
[] = "Transfer stalled.";
91 const char kErrorTimeout
[] = "Transfer timed out.";
92 const char kErrorTransferLength
[] = "Transfer length is insufficient.";
93 const char kErrorCannotSetConfiguration
[] =
94 "Error setting device configuration.";
95 const char kErrorCannotClaimInterface
[] = "Error claiming interface.";
96 const char kErrorCannotReleaseInterface
[] = "Error releasing interface.";
97 const char kErrorCannotSetInterfaceAlternateSetting
[] =
98 "Error setting alternate interface setting.";
99 const char kErrorConvertDirection
[] = "Invalid transfer direction.";
100 const char kErrorConvertRecipient
[] = "Invalid transfer recipient.";
101 const char kErrorConvertRequestType
[] = "Invalid request type.";
102 const char kErrorMalformedParameters
[] = "Error parsing parameters.";
103 const char kErrorNoDevice
[] = "No such device.";
104 const char kErrorPermissionDenied
[] = "Permission to access device was denied";
105 const char kErrorInvalidTransferLength
[] =
106 "Transfer length must be a positive number less than 104,857,600.";
107 const char kErrorInvalidNumberOfPackets
[] =
108 "Number of packets must be a positive number less than 4,194,304.";
109 const char kErrorInvalidPacketLength
[] =
110 "Packet length must be a positive number less than 65,536.";
111 const char kErrorResetDevice
[] =
112 "Error resetting the device. The device has been closed.";
114 const size_t kMaxTransferLength
= 100 * 1024 * 1024;
115 const int kMaxPackets
= 4 * 1024 * 1024;
116 const int kMaxPacketLength
= 64 * 1024;
118 bool ConvertDirectionFromApi(const Direction
& input
,
119 UsbEndpointDirection
* output
) {
121 case usb::DIRECTION_IN
:
122 *output
= device::USB_DIRECTION_INBOUND
;
124 case usb::DIRECTION_OUT
:
125 *output
= device::USB_DIRECTION_OUTBOUND
;
133 bool ConvertRequestTypeFromApi(const RequestType
& input
,
134 UsbDeviceHandle::TransferRequestType
* output
) {
136 case usb::REQUEST_TYPE_STANDARD
:
137 *output
= UsbDeviceHandle::STANDARD
;
139 case usb::REQUEST_TYPE_CLASS
:
140 *output
= UsbDeviceHandle::CLASS
;
142 case usb::REQUEST_TYPE_VENDOR
:
143 *output
= UsbDeviceHandle::VENDOR
;
145 case usb::REQUEST_TYPE_RESERVED
:
146 *output
= UsbDeviceHandle::RESERVED
;
154 bool ConvertRecipientFromApi(const Recipient
& input
,
155 UsbDeviceHandle::TransferRecipient
* output
) {
157 case usb::RECIPIENT_DEVICE
:
158 *output
= UsbDeviceHandle::DEVICE
;
160 case usb::RECIPIENT_INTERFACE
:
161 *output
= UsbDeviceHandle::INTERFACE
;
163 case usb::RECIPIENT_ENDPOINT
:
164 *output
= UsbDeviceHandle::ENDPOINT
;
166 case usb::RECIPIENT_OTHER
:
167 *output
= UsbDeviceHandle::OTHER
;
176 bool GetTransferSize(const T
& input
, size_t* output
) {
177 if (input
.direction
== usb::DIRECTION_IN
) {
178 const int* length
= input
.length
.get();
179 if (length
&& *length
>= 0 &&
180 static_cast<size_t>(*length
) < kMaxTransferLength
) {
184 } else if (input
.direction
== usb::DIRECTION_OUT
) {
185 if (input
.data
.get()) {
186 *output
= input
.data
->size();
194 scoped_refptr
<net::IOBuffer
> CreateBufferForTransfer(
196 UsbEndpointDirection direction
,
198 if (size
>= kMaxTransferLength
)
201 // Allocate a |size|-bytes buffer, or a one-byte buffer if |size| is 0. This
202 // is due to an impedance mismatch between IOBuffer and URBs. An IOBuffer
203 // cannot represent a zero-length buffer, while an URB can.
204 scoped_refptr
<net::IOBuffer
> buffer
=
205 new net::IOBuffer(std::max(static_cast<size_t>(1), size
));
207 if (direction
== device::USB_DIRECTION_INBOUND
) {
209 } else if (direction
== device::USB_DIRECTION_OUTBOUND
) {
210 if (input
.data
.get() && size
<= input
.data
->size()) {
211 memcpy(buffer
->data(), input
.data
->data(), size
);
219 const char* ConvertTransferStatusToApi(const UsbTransferStatus status
) {
221 case device::USB_TRANSFER_COMPLETED
:
223 case device::USB_TRANSFER_ERROR
:
224 return kErrorGeneric
;
225 case device::USB_TRANSFER_TIMEOUT
:
226 return kErrorTimeout
;
227 case device::USB_TRANSFER_CANCELLED
:
228 return kErrorCancelled
;
229 case device::USB_TRANSFER_STALLED
:
230 return kErrorStalled
;
231 case device::USB_TRANSFER_DISCONNECT
:
232 return kErrorDisconnect
;
233 case device::USB_TRANSFER_OVERFLOW
:
234 return kErrorOverflow
;
235 case device::USB_TRANSFER_LENGTH_SHORT
:
236 return kErrorTransferLength
;
243 #if defined(OS_CHROMEOS)
244 void RequestUsbDevicesAccessHelper(
245 ScopedDeviceVector devices
,
246 std::vector
<scoped_refptr
<UsbDevice
> >::iterator i
,
248 const base::Callback
<void(ScopedDeviceVector result
)>& callback
,
253 i
= devices
->erase(i
);
255 if (i
== devices
->end()) {
256 callback
.Run(devices
.Pass());
259 (*i
)->RequestUsbAccess(interface_id
,
260 base::Bind(RequestUsbDevicesAccessHelper
,
261 base::Passed(devices
.Pass()),
267 void RequestUsbDevicesAccess(
268 ScopedDeviceVector devices
,
270 const base::Callback
<void(ScopedDeviceVector result
)>& callback
) {
271 if (devices
->empty()) {
272 callback
.Run(devices
.Pass());
275 std::vector
<scoped_refptr
<UsbDevice
> >::iterator i
= devices
->begin();
276 (*i
)->RequestUsbAccess(interface_id
,
277 base::Bind(RequestUsbDevicesAccessHelper
,
278 base::Passed(devices
.Pass()),
283 #endif // OS_CHROMEOS
285 base::DictionaryValue
* CreateTransferInfo(UsbTransferStatus status
,
286 scoped_refptr
<net::IOBuffer
> data
,
288 base::DictionaryValue
* result
= new base::DictionaryValue();
289 result
->SetInteger(kResultCodeKey
, status
);
290 result
->Set(kDataKey
,
291 base::BinaryValue::CreateWithCopiedBuffer(data
->data(), length
));
295 base::Value
* PopulateConnectionHandle(int handle
,
298 ConnectionHandle result
;
299 result
.handle
= handle
;
300 result
.vendor_id
= vendor_id
;
301 result
.product_id
= product_id
;
302 return result
.ToValue().release();
305 base::Value
* PopulateDevice(const UsbDevice
* device
) {
307 result
.device
= device
->unique_id();
308 result
.vendor_id
= device
->vendor_id();
309 result
.product_id
= device
->product_id();
310 return result
.ToValue().release();
313 TransferType
ConvertTransferTypeToApi(const UsbTransferType
& input
) {
315 case device::USB_TRANSFER_CONTROL
:
316 return usb::TRANSFER_TYPE_CONTROL
;
317 case device::USB_TRANSFER_INTERRUPT
:
318 return usb::TRANSFER_TYPE_INTERRUPT
;
319 case device::USB_TRANSFER_ISOCHRONOUS
:
320 return usb::TRANSFER_TYPE_ISOCHRONOUS
;
321 case device::USB_TRANSFER_BULK
:
322 return usb::TRANSFER_TYPE_BULK
;
325 return usb::TRANSFER_TYPE_NONE
;
329 Direction
ConvertDirectionToApi(const UsbEndpointDirection
& input
) {
331 case device::USB_DIRECTION_INBOUND
:
332 return usb::DIRECTION_IN
;
333 case device::USB_DIRECTION_OUTBOUND
:
334 return usb::DIRECTION_OUT
;
337 return usb::DIRECTION_NONE
;
341 SynchronizationType
ConvertSynchronizationTypeToApi(
342 const UsbSynchronizationType
& input
) {
344 case device::USB_SYNCHRONIZATION_NONE
:
345 return usb::SYNCHRONIZATION_TYPE_NONE
;
346 case device::USB_SYNCHRONIZATION_ASYNCHRONOUS
:
347 return usb::SYNCHRONIZATION_TYPE_ASYNCHRONOUS
;
348 case device::USB_SYNCHRONIZATION_ADAPTIVE
:
349 return usb::SYNCHRONIZATION_TYPE_ADAPTIVE
;
350 case device::USB_SYNCHRONIZATION_SYNCHRONOUS
:
351 return usb::SYNCHRONIZATION_TYPE_SYNCHRONOUS
;
354 return usb::SYNCHRONIZATION_TYPE_NONE
;
358 UsageType
ConvertUsageTypeToApi(const UsbUsageType
& input
) {
360 case device::USB_USAGE_DATA
:
361 return usb::USAGE_TYPE_DATA
;
362 case device::USB_USAGE_FEEDBACK
:
363 return usb::USAGE_TYPE_FEEDBACK
;
364 case device::USB_USAGE_EXPLICIT_FEEDBACK
:
365 return usb::USAGE_TYPE_EXPLICITFEEDBACK
;
368 return usb::USAGE_TYPE_NONE
;
372 void ConvertEndpointDescriptor(const UsbEndpointDescriptor
& input
,
373 EndpointDescriptor
* output
) {
374 output
->address
= input
.address
;
375 output
->type
= ConvertTransferTypeToApi(input
.transfer_type
);
376 output
->direction
= ConvertDirectionToApi(input
.direction
);
377 output
->maximum_packet_size
= input
.maximum_packet_size
;
378 output
->synchronization
=
379 ConvertSynchronizationTypeToApi(input
.synchronization_type
);
380 output
->usage
= ConvertUsageTypeToApi(input
.usage_type
);
381 output
->polling_interval
.reset(new int(input
.polling_interval
));
382 output
->extra_data
.assign(input
.extra_data
.begin(), input
.extra_data
.end());
385 void ConvertInterfaceDescriptor(const UsbInterfaceDescriptor
& input
,
386 InterfaceDescriptor
* output
) {
387 output
->interface_number
= input
.interface_number
;
388 output
->alternate_setting
= input
.alternate_setting
;
389 output
->interface_class
= input
.interface_class
;
390 output
->interface_subclass
= input
.interface_subclass
;
391 output
->interface_protocol
= input
.interface_protocol
;
392 for (const UsbEndpointDescriptor
& input_endpoint
: input
.endpoints
) {
393 linked_ptr
<EndpointDescriptor
> endpoint(new EndpointDescriptor
);
394 ConvertEndpointDescriptor(input_endpoint
, endpoint
.get());
395 output
->endpoints
.push_back(endpoint
);
397 output
->extra_data
.assign(input
.extra_data
.begin(), input
.extra_data
.end());
400 void ConvertConfigDescriptor(const UsbConfigDescriptor
& input
,
401 ConfigDescriptor
* output
) {
402 output
->configuration_value
= input
.configuration_value
;
403 output
->self_powered
= input
.self_powered
;
404 output
->remote_wakeup
= input
.remote_wakeup
;
405 output
->max_power
= input
.maximum_power
;
406 for (const UsbInterfaceDescriptor
& input_interface
: input
.interfaces
) {
407 linked_ptr
<InterfaceDescriptor
> interface(new InterfaceDescriptor
);
408 ConvertInterfaceDescriptor(input_interface
, interface
.get());
409 output
->interfaces
.push_back(interface
);
411 output
->extra_data
.assign(input
.extra_data
.begin(), input
.extra_data
.end());
414 void ConvertDeviceFilter(const usb::DeviceFilter
& input
,
415 UsbDeviceFilter
* output
) {
416 if (input
.vendor_id
) {
417 output
->SetVendorId(*input
.vendor_id
);
419 if (input
.product_id
) {
420 output
->SetProductId(*input
.product_id
);
422 if (input
.interface_class
) {
423 output
->SetInterfaceClass(*input
.interface_class
);
425 if (input
.interface_subclass
) {
426 output
->SetInterfaceSubclass(*input
.interface_subclass
);
428 if (input
.interface_protocol
) {
429 output
->SetInterfaceProtocol(*input
.interface_protocol
);
435 namespace extensions
{
437 UsbAsyncApiFunction::UsbAsyncApiFunction() : manager_(NULL
) {
440 UsbAsyncApiFunction::~UsbAsyncApiFunction() {
443 bool UsbAsyncApiFunction::PrePrepare() {
444 manager_
= ApiResourceManager
<UsbDeviceResource
>::Get(browser_context());
445 set_work_thread_id(BrowserThread::FILE);
446 return manager_
!= NULL
;
449 bool UsbAsyncApiFunction::Respond() {
450 return error_
.empty();
453 bool UsbAsyncApiFunction::HasDevicePermission(scoped_refptr
<UsbDevice
> device
) {
454 DCHECK(device_permissions_
);
456 // Check the DevicePermissionsManager first so that if an entry is found
457 // it can be stored for later. This requires the serial number.
458 base::string16 serial_number
;
459 device
->GetSerialNumber(&serial_number
);
461 permission_entry_
= device_permissions_
->FindEntry(device
, serial_number
);
462 if (permission_entry_
.get()) {
466 UsbDevicePermission::CheckParam
param(
468 device
->product_id(),
469 UsbDevicePermissionData::UNSPECIFIED_INTERFACE
);
470 if (extension()->permissions_data()->CheckAPIPermissionWithParam(
471 APIPermission::kUsbDevice
, ¶m
)) {
478 scoped_refptr
<UsbDeviceHandle
>
479 UsbAsyncApiFunction::GetDeviceHandleOrCompleteWithError(
480 const ConnectionHandle
& input_device_handle
) {
481 UsbDeviceResource
* resource
=
482 manager_
->Get(extension_
->id(), input_device_handle
.handle
);
484 CompleteWithError(kErrorNoDevice
);
488 if (!resource
->device().get() || !resource
->device()->GetDevice().get()) {
489 CompleteWithError(kErrorDisconnect
);
490 manager_
->Remove(extension_
->id(), input_device_handle
.handle
);
494 if (resource
->device()->GetDevice()->vendor_id() !=
495 input_device_handle
.vendor_id
||
496 resource
->device()->GetDevice()->product_id() !=
497 input_device_handle
.product_id
) {
498 CompleteWithError(kErrorNoDevice
);
502 return resource
->device();
505 void UsbAsyncApiFunction::RemoveUsbDeviceResource(int api_resource_id
) {
506 manager_
->Remove(extension_
->id(), api_resource_id
);
509 void UsbAsyncApiFunction::CompleteWithError(const std::string
& error
) {
511 AsyncWorkCompleted();
514 UsbAsyncApiTransferFunction::UsbAsyncApiTransferFunction() {
517 UsbAsyncApiTransferFunction::~UsbAsyncApiTransferFunction() {
520 void UsbAsyncApiTransferFunction::OnCompleted(UsbTransferStatus status
,
521 scoped_refptr
<net::IOBuffer
> data
,
523 if (status
!= device::USB_TRANSFER_COMPLETED
)
524 SetError(ConvertTransferStatusToApi(status
));
526 SetResult(CreateTransferInfo(status
, data
, length
));
527 AsyncWorkCompleted();
530 bool UsbAsyncApiTransferFunction::ConvertDirectionSafely(
531 const Direction
& input
,
532 UsbEndpointDirection
* output
) {
533 const bool converted
= ConvertDirectionFromApi(input
, output
);
535 SetError(kErrorConvertDirection
);
539 bool UsbAsyncApiTransferFunction::ConvertRequestTypeSafely(
540 const RequestType
& input
,
541 UsbDeviceHandle::TransferRequestType
* output
) {
542 const bool converted
= ConvertRequestTypeFromApi(input
, output
);
544 SetError(kErrorConvertRequestType
);
548 bool UsbAsyncApiTransferFunction::ConvertRecipientSafely(
549 const Recipient
& input
,
550 UsbDeviceHandle::TransferRecipient
* output
) {
551 const bool converted
= ConvertRecipientFromApi(input
, output
);
553 SetError(kErrorConvertRecipient
);
557 UsbFindDevicesFunction::UsbFindDevicesFunction() {
560 UsbFindDevicesFunction::~UsbFindDevicesFunction() {
563 bool UsbFindDevicesFunction::Prepare() {
564 parameters_
= FindDevices::Params::Create(*args_
);
565 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
569 void UsbFindDevicesFunction::AsyncWorkStart() {
570 scoped_ptr
<base::ListValue
> result(new base::ListValue());
571 const uint16_t vendor_id
= parameters_
->options
.vendor_id
;
572 const uint16_t product_id
= parameters_
->options
.product_id
;
573 int interface_id
= parameters_
->options
.interface_id
.get()
574 ? *parameters_
->options
.interface_id
.get()
575 : UsbDevicePermissionData::ANY_INTERFACE
;
576 UsbDevicePermission::CheckParam
param(vendor_id
, product_id
, interface_id
);
577 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
578 APIPermission::kUsbDevice
, ¶m
)) {
579 LOG(WARNING
) << "Insufficient permissions to access device.";
580 CompleteWithError(kErrorPermissionDenied
);
584 UsbService
* service
= device::DeviceClient::Get()->GetUsbService();
586 CompleteWithError(kErrorInitService
);
590 ScopedDeviceVector
devices(new DeviceVector());
591 service
->GetDevices(devices
.get());
593 for (DeviceVector::iterator it
= devices
->begin(); it
!= devices
->end();) {
594 if ((*it
)->vendor_id() != vendor_id
|| (*it
)->product_id() != product_id
) {
595 it
= devices
->erase(it
);
601 #if defined(OS_CHROMEOS)
602 RequestUsbDevicesAccess(
605 base::Bind(&UsbFindDevicesFunction::OpenDevices
, this));
607 OpenDevices(devices
.Pass());
608 #endif // OS_CHROMEOS
611 void UsbFindDevicesFunction::OpenDevices(ScopedDeviceVector devices
) {
612 base::ListValue
* result
= new base::ListValue();
614 for (size_t i
= 0; i
< devices
->size(); ++i
) {
615 scoped_refptr
<UsbDeviceHandle
> device_handle
= devices
->at(i
)->Open();
616 if (device_handle
.get())
617 device_handles_
.push_back(device_handle
);
620 for (size_t i
= 0; i
< device_handles_
.size(); ++i
) {
621 UsbDeviceHandle
* const device_handle
= device_handles_
[i
].get();
622 UsbDeviceResource
* const resource
=
623 new UsbDeviceResource(extension_
->id(), device_handle
);
625 result
->Append(PopulateConnectionHandle(manager_
->Add(resource
),
626 parameters_
->options
.vendor_id
,
627 parameters_
->options
.product_id
));
631 AsyncWorkCompleted();
634 UsbGetDevicesFunction::UsbGetDevicesFunction() {
637 UsbGetDevicesFunction::~UsbGetDevicesFunction() {
640 bool UsbGetDevicesFunction::Prepare() {
641 parameters_
= GetDevices::Params::Create(*args_
);
642 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
643 device_permissions_
= DevicePermissionsManager::Get(browser_context())
644 ->GetForExtension(extension()->id());
648 void UsbGetDevicesFunction::AsyncWorkStart() {
649 std::vector
<UsbDeviceFilter
> filters
;
650 if (parameters_
->options
.filters
) {
651 filters
.resize(parameters_
->options
.filters
->size());
652 for (size_t i
= 0; i
< parameters_
->options
.filters
->size(); ++i
) {
653 ConvertDeviceFilter(*parameters_
->options
.filters
->at(i
).get(),
657 if (parameters_
->options
.vendor_id
) {
658 filters
.resize(filters
.size() + 1);
659 filters
.back().SetVendorId(*parameters_
->options
.vendor_id
);
660 if (parameters_
->options
.product_id
) {
661 filters
.back().SetProductId(*parameters_
->options
.product_id
);
665 UsbService
* service
= device::DeviceClient::Get()->GetUsbService();
667 CompleteWithError(kErrorInitService
);
671 DeviceVector devices
;
672 service
->GetDevices(&devices
);
674 scoped_ptr
<base::ListValue
> result(new base::ListValue());
675 for (DeviceVector::iterator it
= devices
.begin(); it
!= devices
.end(); ++it
) {
676 scoped_refptr
<UsbDevice
> device
= *it
;
677 if ((filters
.empty() || UsbDeviceFilter::MatchesAny(device
, filters
)) &&
678 HasDevicePermission(device
)) {
679 result
->Append(PopulateDevice(it
->get()));
683 SetResult(result
.release());
684 AsyncWorkCompleted();
687 UsbGetUserSelectedDevicesFunction::UsbGetUserSelectedDevicesFunction() {
690 UsbGetUserSelectedDevicesFunction::~UsbGetUserSelectedDevicesFunction() {
693 AsyncApiFunction::ResponseAction
UsbGetUserSelectedDevicesFunction::Run() {
694 scoped_ptr
<extensions::core_api::usb::GetUserSelectedDevices::Params
>
695 parameters
= GetUserSelectedDevices::Params::Create(*args_
);
696 EXTENSION_FUNCTION_VALIDATE(parameters
.get());
698 if (!user_gesture()) {
699 return RespondNow(OneArgument(new base::ListValue()));
702 bool multiple
= false;
703 if (parameters
->options
.multiple
) {
704 multiple
= *parameters
->options
.multiple
;
707 std::vector
<UsbDeviceFilter
> filters
;
708 if (parameters
->options
.filters
) {
709 filters
.resize(parameters
->options
.filters
->size());
710 for (size_t i
= 0; i
< parameters
->options
.filters
->size(); ++i
) {
711 ConvertDeviceFilter(*parameters
->options
.filters
->at(i
).get(),
716 prompt_
= ExtensionsAPIClient::Get()->CreateDevicePermissionsPrompt(
717 GetAssociatedWebContents());
719 return RespondNow(Error(kErrorNotSupported
));
723 prompt_
->AskForUsbDevices(
724 this, extension(), browser_context(), multiple
, filters
);
725 return RespondLater();
728 void UsbGetUserSelectedDevicesFunction::OnUsbDevicesChosen(
729 const std::vector
<scoped_refptr
<UsbDevice
>>& devices
) {
730 scoped_ptr
<base::ListValue
> result(new base::ListValue());
731 for (const auto& device
: devices
) {
732 result
->Append(PopulateDevice(device
.get()));
735 SetResult(result
.release());
740 UsbRequestAccessFunction::UsbRequestAccessFunction() {
743 UsbRequestAccessFunction::~UsbRequestAccessFunction() {
746 bool UsbRequestAccessFunction::Prepare() {
747 parameters_
= RequestAccess::Params::Create(*args_
);
748 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
752 void UsbRequestAccessFunction::AsyncWorkStart() {
753 SetResult(new base::FundamentalValue(true));
754 AsyncWorkCompleted();
757 UsbOpenDeviceFunction::UsbOpenDeviceFunction() {
760 UsbOpenDeviceFunction::~UsbOpenDeviceFunction() {
763 bool UsbOpenDeviceFunction::Prepare() {
764 parameters_
= OpenDevice::Params::Create(*args_
);
765 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
766 device_permissions_manager_
=
767 DevicePermissionsManager::Get(browser_context());
768 device_permissions_
=
769 device_permissions_manager_
->GetForExtension(extension()->id());
773 void UsbOpenDeviceFunction::AsyncWorkStart() {
774 UsbService
* service
= device::DeviceClient::Get()->GetUsbService();
776 CompleteWithError(kErrorInitService
);
780 device_
= service
->GetDeviceById(parameters_
->device
.device
);
781 if (!device_
.get()) {
782 CompleteWithError(kErrorNoDevice
);
786 if (!HasDevicePermission(device_
)) {
787 // This function must act as if there is no such device. Otherwise it can be
788 // used to fingerprint unauthorized devices.
789 CompleteWithError(kErrorNoDevice
);
793 #if defined(OS_CHROMEOS)
794 device_
->RequestUsbAccess(
795 -1, /* any interface, unused by the permission broker */
796 base::Bind(&UsbOpenDeviceFunction::OnRequestAccessComplete
, this));
798 OnRequestAccessComplete(true);
799 #endif // OS_CHROMEOS
802 void UsbOpenDeviceFunction::OnRequestAccessComplete(bool success
) {
804 SetError(kErrorPermissionDenied
);
805 AsyncWorkCompleted();
809 scoped_refptr
<UsbDeviceHandle
> handle
= device_
->Open();
811 SetError(kErrorOpen
);
812 AsyncWorkCompleted();
816 SetResult(PopulateConnectionHandle(
817 manager_
->Add(new UsbDeviceResource(extension_
->id(), handle
)),
818 device_
->vendor_id(), device_
->product_id()));
819 AsyncWorkCompleted();
822 bool UsbOpenDeviceFunction::Respond() {
823 if (permission_entry_
.get()) {
824 device_permissions_manager_
->UpdateLastUsed(extension_
->id(),
827 return UsbAsyncApiFunction::Respond();
830 UsbSetConfigurationFunction::UsbSetConfigurationFunction() {
833 UsbSetConfigurationFunction::~UsbSetConfigurationFunction() {
836 bool UsbSetConfigurationFunction::Prepare() {
837 parameters_
= SetConfiguration::Params::Create(*args_
);
838 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
842 void UsbSetConfigurationFunction::AsyncWorkStart() {
843 scoped_refptr
<UsbDeviceHandle
> device_handle
=
844 GetDeviceHandleOrCompleteWithError(parameters_
->handle
);
845 if (!device_handle
.get()) {
849 if (!device_handle
->SetConfiguration(parameters_
->configuration_value
)) {
850 SetError(kErrorCannotSetConfiguration
);
852 AsyncWorkCompleted();
855 UsbGetConfigurationFunction::UsbGetConfigurationFunction() {
858 UsbGetConfigurationFunction::~UsbGetConfigurationFunction() {
861 bool UsbGetConfigurationFunction::Prepare() {
862 parameters_
= GetConfiguration::Params::Create(*args_
);
863 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
867 void UsbGetConfigurationFunction::AsyncWorkStart() {
868 scoped_refptr
<UsbDeviceHandle
> device_handle
=
869 GetDeviceHandleOrCompleteWithError(parameters_
->handle
);
870 if (!device_handle
.get()) {
874 const UsbConfigDescriptor
* config_descriptor
=
875 device_handle
->GetDevice()->GetConfiguration();
876 if (config_descriptor
) {
877 ConfigDescriptor config
;
878 ConvertConfigDescriptor(*config_descriptor
, &config
);
879 SetResult(config
.ToValue().release());
881 SetError(kErrorNotConfigured
);
884 AsyncWorkCompleted();
887 UsbListInterfacesFunction::UsbListInterfacesFunction() {
890 UsbListInterfacesFunction::~UsbListInterfacesFunction() {
893 bool UsbListInterfacesFunction::Prepare() {
894 parameters_
= ListInterfaces::Params::Create(*args_
);
895 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
899 void UsbListInterfacesFunction::AsyncWorkStart() {
900 scoped_refptr
<UsbDeviceHandle
> device_handle
=
901 GetDeviceHandleOrCompleteWithError(parameters_
->handle
);
902 if (!device_handle
.get()) {
906 const UsbConfigDescriptor
* config_descriptor
=
907 device_handle
->GetDevice()->GetConfiguration();
908 if (config_descriptor
) {
909 ConfigDescriptor config
;
910 ConvertConfigDescriptor(*config_descriptor
, &config
);
912 scoped_ptr
<base::ListValue
> result(new base::ListValue
);
913 for (size_t i
= 0; i
< config
.interfaces
.size(); ++i
) {
914 result
->Append(config
.interfaces
[i
]->ToValue().release());
917 SetResult(result
.release());
919 SetError(kErrorNotConfigured
);
922 AsyncWorkCompleted();
925 UsbCloseDeviceFunction::UsbCloseDeviceFunction() {
928 UsbCloseDeviceFunction::~UsbCloseDeviceFunction() {
931 bool UsbCloseDeviceFunction::Prepare() {
932 parameters_
= CloseDevice::Params::Create(*args_
);
933 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
937 void UsbCloseDeviceFunction::AsyncWorkStart() {
938 scoped_refptr
<UsbDeviceHandle
> device_handle
=
939 GetDeviceHandleOrCompleteWithError(parameters_
->handle
);
940 if (!device_handle
.get())
943 // The device handle is closed when the resource is destroyed.
944 RemoveUsbDeviceResource(parameters_
->handle
.handle
);
945 AsyncWorkCompleted();
948 UsbClaimInterfaceFunction::UsbClaimInterfaceFunction() {
951 UsbClaimInterfaceFunction::~UsbClaimInterfaceFunction() {
954 bool UsbClaimInterfaceFunction::Prepare() {
955 parameters_
= ClaimInterface::Params::Create(*args_
);
956 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
960 void UsbClaimInterfaceFunction::AsyncWorkStart() {
961 scoped_refptr
<UsbDeviceHandle
> device_handle
=
962 GetDeviceHandleOrCompleteWithError(parameters_
->handle
);
963 if (!device_handle
.get())
966 bool success
= device_handle
->ClaimInterface(parameters_
->interface_number
);
969 SetError(kErrorCannotClaimInterface
);
970 AsyncWorkCompleted();
973 UsbReleaseInterfaceFunction::UsbReleaseInterfaceFunction() {
976 UsbReleaseInterfaceFunction::~UsbReleaseInterfaceFunction() {
979 bool UsbReleaseInterfaceFunction::Prepare() {
980 parameters_
= ReleaseInterface::Params::Create(*args_
);
981 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
985 void UsbReleaseInterfaceFunction::AsyncWorkStart() {
986 scoped_refptr
<UsbDeviceHandle
> device_handle
=
987 GetDeviceHandleOrCompleteWithError(parameters_
->handle
);
988 if (!device_handle
.get())
991 bool success
= device_handle
->ReleaseInterface(parameters_
->interface_number
);
993 SetError(kErrorCannotReleaseInterface
);
994 AsyncWorkCompleted();
997 UsbSetInterfaceAlternateSettingFunction::
998 UsbSetInterfaceAlternateSettingFunction() {
1001 UsbSetInterfaceAlternateSettingFunction::
1002 ~UsbSetInterfaceAlternateSettingFunction() {
1005 bool UsbSetInterfaceAlternateSettingFunction::Prepare() {
1006 parameters_
= SetInterfaceAlternateSetting::Params::Create(*args_
);
1007 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
1011 void UsbSetInterfaceAlternateSettingFunction::AsyncWorkStart() {
1012 scoped_refptr
<UsbDeviceHandle
> device_handle
=
1013 GetDeviceHandleOrCompleteWithError(parameters_
->handle
);
1014 if (!device_handle
.get())
1017 bool success
= device_handle
->SetInterfaceAlternateSetting(
1018 parameters_
->interface_number
, parameters_
->alternate_setting
);
1020 SetError(kErrorCannotSetInterfaceAlternateSetting
);
1022 AsyncWorkCompleted();
1025 UsbControlTransferFunction::UsbControlTransferFunction() {
1028 UsbControlTransferFunction::~UsbControlTransferFunction() {
1031 bool UsbControlTransferFunction::Prepare() {
1032 parameters_
= ControlTransfer::Params::Create(*args_
);
1033 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
1037 void UsbControlTransferFunction::AsyncWorkStart() {
1038 scoped_refptr
<UsbDeviceHandle
> device_handle
=
1039 GetDeviceHandleOrCompleteWithError(parameters_
->handle
);
1040 if (!device_handle
.get())
1043 const ControlTransferInfo
& transfer
= parameters_
->transfer_info
;
1045 UsbEndpointDirection direction
;
1046 UsbDeviceHandle::TransferRequestType request_type
;
1047 UsbDeviceHandle::TransferRecipient recipient
;
1050 if (!ConvertDirectionSafely(transfer
.direction
, &direction
) ||
1051 !ConvertRequestTypeSafely(transfer
.request_type
, &request_type
) ||
1052 !ConvertRecipientSafely(transfer
.recipient
, &recipient
)) {
1053 AsyncWorkCompleted();
1057 if (!GetTransferSize(transfer
, &size
)) {
1058 CompleteWithError(kErrorInvalidTransferLength
);
1062 scoped_refptr
<net::IOBuffer
> buffer
=
1063 CreateBufferForTransfer(transfer
, direction
, size
);
1064 if (!buffer
.get()) {
1065 CompleteWithError(kErrorMalformedParameters
);
1069 device_handle
->ControlTransfer(
1079 base::Bind(&UsbControlTransferFunction::OnCompleted
, this));
1082 UsbBulkTransferFunction::UsbBulkTransferFunction() {
1085 UsbBulkTransferFunction::~UsbBulkTransferFunction() {
1088 bool UsbBulkTransferFunction::Prepare() {
1089 parameters_
= BulkTransfer::Params::Create(*args_
);
1090 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
1094 void UsbBulkTransferFunction::AsyncWorkStart() {
1095 scoped_refptr
<UsbDeviceHandle
> device_handle
=
1096 GetDeviceHandleOrCompleteWithError(parameters_
->handle
);
1097 if (!device_handle
.get())
1100 const GenericTransferInfo
& transfer
= parameters_
->transfer_info
;
1102 UsbEndpointDirection direction
;
1105 if (!ConvertDirectionSafely(transfer
.direction
, &direction
)) {
1106 AsyncWorkCompleted();
1110 if (!GetTransferSize(transfer
, &size
)) {
1111 CompleteWithError(kErrorInvalidTransferLength
);
1115 scoped_refptr
<net::IOBuffer
> buffer
=
1116 CreateBufferForTransfer(transfer
, direction
, size
);
1117 if (!buffer
.get()) {
1118 CompleteWithError(kErrorMalformedParameters
);
1122 device_handle
->BulkTransfer(
1128 base::Bind(&UsbBulkTransferFunction::OnCompleted
, this));
1131 UsbInterruptTransferFunction::UsbInterruptTransferFunction() {
1134 UsbInterruptTransferFunction::~UsbInterruptTransferFunction() {
1137 bool UsbInterruptTransferFunction::Prepare() {
1138 parameters_
= InterruptTransfer::Params::Create(*args_
);
1139 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
1143 void UsbInterruptTransferFunction::AsyncWorkStart() {
1144 scoped_refptr
<UsbDeviceHandle
> device_handle
=
1145 GetDeviceHandleOrCompleteWithError(parameters_
->handle
);
1146 if (!device_handle
.get())
1149 const GenericTransferInfo
& transfer
= parameters_
->transfer_info
;
1151 UsbEndpointDirection direction
;
1154 if (!ConvertDirectionSafely(transfer
.direction
, &direction
)) {
1155 AsyncWorkCompleted();
1159 if (!GetTransferSize(transfer
, &size
)) {
1160 CompleteWithError(kErrorInvalidTransferLength
);
1164 scoped_refptr
<net::IOBuffer
> buffer
=
1165 CreateBufferForTransfer(transfer
, direction
, size
);
1166 if (!buffer
.get()) {
1167 CompleteWithError(kErrorMalformedParameters
);
1171 device_handle
->InterruptTransfer(
1177 base::Bind(&UsbInterruptTransferFunction::OnCompleted
, this));
1180 UsbIsochronousTransferFunction::UsbIsochronousTransferFunction() {
1183 UsbIsochronousTransferFunction::~UsbIsochronousTransferFunction() {
1186 bool UsbIsochronousTransferFunction::Prepare() {
1187 parameters_
= IsochronousTransfer::Params::Create(*args_
);
1188 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
1192 void UsbIsochronousTransferFunction::AsyncWorkStart() {
1193 scoped_refptr
<UsbDeviceHandle
> device_handle
=
1194 GetDeviceHandleOrCompleteWithError(parameters_
->handle
);
1195 if (!device_handle
.get())
1198 const IsochronousTransferInfo
& transfer
= parameters_
->transfer_info
;
1199 const GenericTransferInfo
& generic_transfer
= transfer
.transfer_info
;
1202 UsbEndpointDirection direction
;
1204 if (!ConvertDirectionSafely(generic_transfer
.direction
, &direction
)) {
1205 AsyncWorkCompleted();
1208 if (!GetTransferSize(generic_transfer
, &size
)) {
1209 CompleteWithError(kErrorInvalidTransferLength
);
1212 if (transfer
.packets
< 0 || transfer
.packets
>= kMaxPackets
) {
1213 CompleteWithError(kErrorInvalidNumberOfPackets
);
1216 unsigned int packets
= transfer
.packets
;
1217 if (transfer
.packet_length
< 0 ||
1218 transfer
.packet_length
>= kMaxPacketLength
) {
1219 CompleteWithError(kErrorInvalidPacketLength
);
1222 unsigned int packet_length
= transfer
.packet_length
;
1223 const uint64 total_length
= packets
* packet_length
;
1224 if (packets
> size
|| total_length
> size
) {
1225 CompleteWithError(kErrorTransferLength
);
1229 scoped_refptr
<net::IOBuffer
> buffer
=
1230 CreateBufferForTransfer(generic_transfer
, direction
, size
);
1231 if (!buffer
.get()) {
1232 CompleteWithError(kErrorMalformedParameters
);
1236 device_handle
->IsochronousTransfer(
1238 generic_transfer
.endpoint
,
1244 base::Bind(&UsbIsochronousTransferFunction::OnCompleted
, this));
1247 UsbResetDeviceFunction::UsbResetDeviceFunction() {
1250 UsbResetDeviceFunction::~UsbResetDeviceFunction() {
1253 bool UsbResetDeviceFunction::Prepare() {
1254 parameters_
= ResetDevice::Params::Create(*args_
);
1255 EXTENSION_FUNCTION_VALIDATE(parameters_
.get());
1259 void UsbResetDeviceFunction::AsyncWorkStart() {
1260 scoped_refptr
<UsbDeviceHandle
> device_handle
=
1261 GetDeviceHandleOrCompleteWithError(parameters_
->handle
);
1262 if (!device_handle
.get())
1265 bool success
= device_handle
->ResetDevice();
1267 device_handle
->Close();
1268 RemoveUsbDeviceResource(parameters_
->handle
.handle
);
1269 SetResult(new base::FundamentalValue(false));
1270 CompleteWithError(kErrorResetDevice
);
1274 SetResult(new base::FundamentalValue(true));
1275 AsyncWorkCompleted();
1278 } // namespace extensions