Check USB device path access when prompting users to select a device.
[chromium-blink-merge.git] / extensions / browser / api / usb / usb_api.cc
blobf1fcd239c1428d22a6df91bce31bac1dc33ea898
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"
7 #include <string>
8 #include <vector>
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;
56 using std::string;
57 using std::vector;
58 using usb::ConfigDescriptor;
59 using usb::ControlTransferInfo;
60 using usb::ConnectionHandle;
61 using usb::Device;
62 using usb::Direction;
63 using usb::EndpointDescriptor;
64 using usb::GenericTransferInfo;
65 using usb::InterfaceDescriptor;
66 using usb::IsochronousTransferInfo;
67 using usb::Recipient;
68 using usb::RequestType;
69 using usb::SynchronizationType;
70 using usb::TransferType;
71 using usb::UsageType;
73 typedef std::vector<scoped_refptr<UsbDevice> > DeviceVector;
74 typedef scoped_ptr<DeviceVector> ScopedDeviceVector;
76 namespace {
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 kErrorInvalidTimeout[] =
112 "Transfer timeout must be greater than or equal to 0.";
113 const char kErrorResetDevice[] =
114 "Error resetting the device. The device has been closed.";
116 const size_t kMaxTransferLength = 100 * 1024 * 1024;
117 const int kMaxPackets = 4 * 1024 * 1024;
118 const int kMaxPacketLength = 64 * 1024;
120 bool ConvertDirectionFromApi(const Direction& input,
121 UsbEndpointDirection* output) {
122 switch (input) {
123 case usb::DIRECTION_IN:
124 *output = device::USB_DIRECTION_INBOUND;
125 return true;
126 case usb::DIRECTION_OUT:
127 *output = device::USB_DIRECTION_OUTBOUND;
128 return true;
129 default:
130 NOTREACHED();
131 return false;
135 bool ConvertRequestTypeFromApi(const RequestType& input,
136 UsbDeviceHandle::TransferRequestType* output) {
137 switch (input) {
138 case usb::REQUEST_TYPE_STANDARD:
139 *output = UsbDeviceHandle::STANDARD;
140 return true;
141 case usb::REQUEST_TYPE_CLASS:
142 *output = UsbDeviceHandle::CLASS;
143 return true;
144 case usb::REQUEST_TYPE_VENDOR:
145 *output = UsbDeviceHandle::VENDOR;
146 return true;
147 case usb::REQUEST_TYPE_RESERVED:
148 *output = UsbDeviceHandle::RESERVED;
149 return true;
150 default:
151 NOTREACHED();
152 return false;
156 bool ConvertRecipientFromApi(const Recipient& input,
157 UsbDeviceHandle::TransferRecipient* output) {
158 switch (input) {
159 case usb::RECIPIENT_DEVICE:
160 *output = UsbDeviceHandle::DEVICE;
161 return true;
162 case usb::RECIPIENT_INTERFACE:
163 *output = UsbDeviceHandle::INTERFACE;
164 return true;
165 case usb::RECIPIENT_ENDPOINT:
166 *output = UsbDeviceHandle::ENDPOINT;
167 return true;
168 case usb::RECIPIENT_OTHER:
169 *output = UsbDeviceHandle::OTHER;
170 return true;
171 default:
172 NOTREACHED();
173 return false;
177 template <class T>
178 bool GetTransferSize(const T& input, size_t* output) {
179 if (input.direction == usb::DIRECTION_IN) {
180 const int* length = input.length.get();
181 if (length && *length >= 0 &&
182 static_cast<size_t>(*length) < kMaxTransferLength) {
183 *output = *length;
184 return true;
186 } else if (input.direction == usb::DIRECTION_OUT) {
187 if (input.data.get()) {
188 *output = input.data->size();
189 return true;
192 return false;
195 template <class T>
196 scoped_refptr<net::IOBuffer> CreateBufferForTransfer(
197 const T& input,
198 UsbEndpointDirection direction,
199 size_t size) {
200 if (size >= kMaxTransferLength)
201 return NULL;
203 // Allocate a |size|-bytes buffer, or a one-byte buffer if |size| is 0. This
204 // is due to an impedance mismatch between IOBuffer and URBs. An IOBuffer
205 // cannot represent a zero-length buffer, while an URB can.
206 scoped_refptr<net::IOBuffer> buffer =
207 new net::IOBuffer(std::max(static_cast<size_t>(1), size));
209 if (direction == device::USB_DIRECTION_INBOUND) {
210 return buffer;
211 } else if (direction == device::USB_DIRECTION_OUTBOUND) {
212 if (input.data.get() && size <= input.data->size()) {
213 memcpy(buffer->data(), input.data->data(), size);
214 return buffer;
217 NOTREACHED();
218 return NULL;
221 const char* ConvertTransferStatusToApi(const UsbTransferStatus status) {
222 switch (status) {
223 case device::USB_TRANSFER_COMPLETED:
224 return "";
225 case device::USB_TRANSFER_ERROR:
226 return kErrorGeneric;
227 case device::USB_TRANSFER_TIMEOUT:
228 return kErrorTimeout;
229 case device::USB_TRANSFER_CANCELLED:
230 return kErrorCancelled;
231 case device::USB_TRANSFER_STALLED:
232 return kErrorStalled;
233 case device::USB_TRANSFER_DISCONNECT:
234 return kErrorDisconnect;
235 case device::USB_TRANSFER_OVERFLOW:
236 return kErrorOverflow;
237 case device::USB_TRANSFER_LENGTH_SHORT:
238 return kErrorTransferLength;
239 default:
240 NOTREACHED();
241 return "";
245 void RequestUsbDevicesAccessHelper(
246 ScopedDeviceVector devices,
247 std::vector<scoped_refptr<UsbDevice> >::iterator i,
248 int interface_id,
249 const base::Callback<void(ScopedDeviceVector result)>& callback,
250 bool success) {
251 if (success) {
252 ++i;
253 } else {
254 i = devices->erase(i);
256 if (i == devices->end()) {
257 callback.Run(devices.Pass());
258 return;
260 (*i)->RequestUsbAccess(interface_id,
261 base::Bind(RequestUsbDevicesAccessHelper,
262 base::Passed(devices.Pass()),
264 interface_id,
265 callback));
268 void RequestUsbDevicesAccess(
269 ScopedDeviceVector devices,
270 int interface_id,
271 const base::Callback<void(ScopedDeviceVector result)>& callback) {
272 if (devices->empty()) {
273 callback.Run(devices.Pass());
274 return;
276 std::vector<scoped_refptr<UsbDevice> >::iterator i = devices->begin();
277 (*i)->RequestUsbAccess(interface_id,
278 base::Bind(RequestUsbDevicesAccessHelper,
279 base::Passed(devices.Pass()),
281 interface_id,
282 callback));
285 base::DictionaryValue* CreateTransferInfo(UsbTransferStatus status,
286 scoped_refptr<net::IOBuffer> data,
287 size_t length) {
288 base::DictionaryValue* result = new base::DictionaryValue();
289 result->SetInteger(kResultCodeKey, status);
290 result->Set(kDataKey,
291 base::BinaryValue::CreateWithCopiedBuffer(data->data(), length));
292 return result;
295 base::Value* PopulateConnectionHandle(int handle,
296 int vendor_id,
297 int product_id) {
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) {
306 Device result;
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) {
314 switch (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;
323 default:
324 NOTREACHED();
325 return usb::TRANSFER_TYPE_NONE;
329 Direction ConvertDirectionToApi(const UsbEndpointDirection& input) {
330 switch (input) {
331 case device::USB_DIRECTION_INBOUND:
332 return usb::DIRECTION_IN;
333 case device::USB_DIRECTION_OUTBOUND:
334 return usb::DIRECTION_OUT;
335 default:
336 NOTREACHED();
337 return usb::DIRECTION_NONE;
341 SynchronizationType ConvertSynchronizationTypeToApi(
342 const UsbSynchronizationType& input) {
343 switch (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;
352 default:
353 NOTREACHED();
354 return usb::SYNCHRONIZATION_TYPE_NONE;
358 UsageType ConvertUsageTypeToApi(const UsbUsageType& input) {
359 switch (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;
366 default:
367 NOTREACHED();
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);
433 } // namespace
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()) {
463 return true;
466 UsbDevicePermission::CheckParam param(
467 device->vendor_id(),
468 device->product_id(),
469 UsbDevicePermissionData::UNSPECIFIED_INTERFACE);
470 if (extension()->permissions_data()->CheckAPIPermissionWithParam(
471 APIPermission::kUsbDevice, &param)) {
472 return true;
475 return false;
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);
483 if (!resource) {
484 CompleteWithError(kErrorNoDevice);
485 return NULL;
488 if (!resource->device().get() || !resource->device()->GetDevice().get()) {
489 CompleteWithError(kErrorDisconnect);
490 manager_->Remove(extension_->id(), input_device_handle.handle);
491 return NULL;
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);
499 return NULL;
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) {
510 SetError(error);
511 AsyncWorkCompleted();
514 UsbAsyncApiTransferFunction::UsbAsyncApiTransferFunction() {
517 UsbAsyncApiTransferFunction::~UsbAsyncApiTransferFunction() {
520 void UsbAsyncApiTransferFunction::OnCompleted(UsbTransferStatus status,
521 scoped_refptr<net::IOBuffer> data,
522 size_t length) {
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);
534 if (!converted)
535 SetError(kErrorConvertDirection);
536 return converted;
539 bool UsbAsyncApiTransferFunction::ConvertRequestTypeSafely(
540 const RequestType& input,
541 UsbDeviceHandle::TransferRequestType* output) {
542 const bool converted = ConvertRequestTypeFromApi(input, output);
543 if (!converted)
544 SetError(kErrorConvertRequestType);
545 return converted;
548 bool UsbAsyncApiTransferFunction::ConvertRecipientSafely(
549 const Recipient& input,
550 UsbDeviceHandle::TransferRecipient* output) {
551 const bool converted = ConvertRecipientFromApi(input, output);
552 if (!converted)
553 SetError(kErrorConvertRecipient);
554 return converted;
557 UsbFindDevicesFunction::UsbFindDevicesFunction() {
560 UsbFindDevicesFunction::~UsbFindDevicesFunction() {
563 bool UsbFindDevicesFunction::Prepare() {
564 parameters_ = FindDevices::Params::Create(*args_);
565 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
566 return true;
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, &param)) {
579 LOG(WARNING) << "Insufficient permissions to access device.";
580 CompleteWithError(kErrorPermissionDenied);
581 return;
584 UsbService* service = device::DeviceClient::Get()->GetUsbService();
585 if (!service) {
586 CompleteWithError(kErrorInitService);
587 return;
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);
596 } else {
597 ++it;
601 RequestUsbDevicesAccess(
602 devices.Pass(),
603 interface_id,
604 base::Bind(&UsbFindDevicesFunction::OpenDevices, this));
607 void UsbFindDevicesFunction::OpenDevices(ScopedDeviceVector devices) {
608 base::ListValue* result = new base::ListValue();
610 for (size_t i = 0; i < devices->size(); ++i) {
611 scoped_refptr<UsbDeviceHandle> device_handle = devices->at(i)->Open();
612 if (device_handle.get())
613 device_handles_.push_back(device_handle);
616 for (size_t i = 0; i < device_handles_.size(); ++i) {
617 UsbDeviceHandle* const device_handle = device_handles_[i].get();
618 UsbDeviceResource* const resource =
619 new UsbDeviceResource(extension_->id(), device_handle);
621 result->Append(PopulateConnectionHandle(manager_->Add(resource),
622 parameters_->options.vendor_id,
623 parameters_->options.product_id));
626 SetResult(result);
627 AsyncWorkCompleted();
630 UsbGetDevicesFunction::UsbGetDevicesFunction() {
633 UsbGetDevicesFunction::~UsbGetDevicesFunction() {
636 bool UsbGetDevicesFunction::Prepare() {
637 parameters_ = GetDevices::Params::Create(*args_);
638 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
639 device_permissions_ = DevicePermissionsManager::Get(browser_context())
640 ->GetForExtension(extension()->id());
641 return true;
644 void UsbGetDevicesFunction::AsyncWorkStart() {
645 std::vector<UsbDeviceFilter> filters;
646 if (parameters_->options.filters) {
647 filters.resize(parameters_->options.filters->size());
648 for (size_t i = 0; i < parameters_->options.filters->size(); ++i) {
649 ConvertDeviceFilter(*parameters_->options.filters->at(i).get(),
650 &filters[i]);
653 if (parameters_->options.vendor_id) {
654 filters.resize(filters.size() + 1);
655 filters.back().SetVendorId(*parameters_->options.vendor_id);
656 if (parameters_->options.product_id) {
657 filters.back().SetProductId(*parameters_->options.product_id);
661 UsbService* service = device::DeviceClient::Get()->GetUsbService();
662 if (!service) {
663 CompleteWithError(kErrorInitService);
664 return;
667 DeviceVector devices;
668 service->GetDevices(&devices);
670 scoped_ptr<base::ListValue> result(new base::ListValue());
671 for (DeviceVector::iterator it = devices.begin(); it != devices.end(); ++it) {
672 scoped_refptr<UsbDevice> device = *it;
673 if ((filters.empty() || UsbDeviceFilter::MatchesAny(device, filters)) &&
674 HasDevicePermission(device)) {
675 result->Append(PopulateDevice(it->get()));
679 SetResult(result.release());
680 AsyncWorkCompleted();
683 UsbGetUserSelectedDevicesFunction::UsbGetUserSelectedDevicesFunction() {
686 UsbGetUserSelectedDevicesFunction::~UsbGetUserSelectedDevicesFunction() {
689 AsyncApiFunction::ResponseAction UsbGetUserSelectedDevicesFunction::Run() {
690 scoped_ptr<extensions::core_api::usb::GetUserSelectedDevices::Params>
691 parameters = GetUserSelectedDevices::Params::Create(*args_);
692 EXTENSION_FUNCTION_VALIDATE(parameters.get());
694 if (!user_gesture()) {
695 return RespondNow(OneArgument(new base::ListValue()));
698 bool multiple = false;
699 if (parameters->options.multiple) {
700 multiple = *parameters->options.multiple;
703 std::vector<UsbDeviceFilter> filters;
704 if (parameters->options.filters) {
705 filters.resize(parameters->options.filters->size());
706 for (size_t i = 0; i < parameters->options.filters->size(); ++i) {
707 ConvertDeviceFilter(*parameters->options.filters->at(i).get(),
708 &filters[i]);
712 prompt_ = ExtensionsAPIClient::Get()->CreateDevicePermissionsPrompt(
713 GetAssociatedWebContents());
714 if (!prompt_) {
715 return RespondNow(Error(kErrorNotSupported));
718 AddRef();
719 prompt_->AskForUsbDevices(
720 this, extension(), browser_context(), multiple, filters);
721 return RespondLater();
724 void UsbGetUserSelectedDevicesFunction::OnUsbDevicesChosen(
725 const std::vector<scoped_refptr<UsbDevice>>& devices) {
726 scoped_ptr<base::ListValue> result(new base::ListValue());
727 for (const auto& device : devices) {
728 result->Append(PopulateDevice(device.get()));
731 SetResult(result.release());
732 SendResponse(true);
733 Release();
736 UsbRequestAccessFunction::UsbRequestAccessFunction() {
739 UsbRequestAccessFunction::~UsbRequestAccessFunction() {
742 bool UsbRequestAccessFunction::Prepare() {
743 parameters_ = RequestAccess::Params::Create(*args_);
744 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
745 return true;
748 void UsbRequestAccessFunction::AsyncWorkStart() {
749 SetResult(new base::FundamentalValue(true));
750 AsyncWorkCompleted();
753 UsbOpenDeviceFunction::UsbOpenDeviceFunction() {
756 UsbOpenDeviceFunction::~UsbOpenDeviceFunction() {
759 bool UsbOpenDeviceFunction::Prepare() {
760 parameters_ = OpenDevice::Params::Create(*args_);
761 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
762 device_permissions_manager_ =
763 DevicePermissionsManager::Get(browser_context());
764 device_permissions_ =
765 device_permissions_manager_->GetForExtension(extension()->id());
766 return true;
769 void UsbOpenDeviceFunction::AsyncWorkStart() {
770 UsbService* service = device::DeviceClient::Get()->GetUsbService();
771 if (!service) {
772 CompleteWithError(kErrorInitService);
773 return;
776 device_ = service->GetDeviceById(parameters_->device.device);
777 if (!device_.get()) {
778 CompleteWithError(kErrorNoDevice);
779 return;
782 if (!HasDevicePermission(device_)) {
783 // This function must act as if there is no such device. Otherwise it can be
784 // used to fingerprint unauthorized devices.
785 CompleteWithError(kErrorNoDevice);
786 return;
789 device_->RequestUsbAccess(
790 -1, /* any interface, unused by the permission broker */
791 base::Bind(&UsbOpenDeviceFunction::OnRequestAccessComplete, this));
794 void UsbOpenDeviceFunction::OnRequestAccessComplete(bool success) {
795 if (!success) {
796 SetError(kErrorPermissionDenied);
797 AsyncWorkCompleted();
798 return;
801 scoped_refptr<UsbDeviceHandle> handle = device_->Open();
802 if (!handle.get()) {
803 SetError(kErrorOpen);
804 AsyncWorkCompleted();
805 return;
808 SetResult(PopulateConnectionHandle(
809 manager_->Add(new UsbDeviceResource(extension_->id(), handle)),
810 device_->vendor_id(), device_->product_id()));
811 AsyncWorkCompleted();
814 bool UsbOpenDeviceFunction::Respond() {
815 if (permission_entry_.get()) {
816 device_permissions_manager_->UpdateLastUsed(extension_->id(),
817 permission_entry_);
819 return UsbAsyncApiFunction::Respond();
822 UsbSetConfigurationFunction::UsbSetConfigurationFunction() {
825 UsbSetConfigurationFunction::~UsbSetConfigurationFunction() {
828 bool UsbSetConfigurationFunction::Prepare() {
829 parameters_ = SetConfiguration::Params::Create(*args_);
830 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
831 return true;
834 void UsbSetConfigurationFunction::AsyncWorkStart() {
835 scoped_refptr<UsbDeviceHandle> device_handle =
836 GetDeviceHandleOrCompleteWithError(parameters_->handle);
837 if (!device_handle.get()) {
838 return;
841 if (!device_handle->SetConfiguration(parameters_->configuration_value)) {
842 SetError(kErrorCannotSetConfiguration);
844 AsyncWorkCompleted();
847 UsbGetConfigurationFunction::UsbGetConfigurationFunction() {
850 UsbGetConfigurationFunction::~UsbGetConfigurationFunction() {
853 bool UsbGetConfigurationFunction::Prepare() {
854 parameters_ = GetConfiguration::Params::Create(*args_);
855 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
856 return true;
859 void UsbGetConfigurationFunction::AsyncWorkStart() {
860 scoped_refptr<UsbDeviceHandle> device_handle =
861 GetDeviceHandleOrCompleteWithError(parameters_->handle);
862 if (!device_handle.get()) {
863 return;
866 const UsbConfigDescriptor* config_descriptor =
867 device_handle->GetDevice()->GetConfiguration();
868 if (config_descriptor) {
869 ConfigDescriptor config;
870 ConvertConfigDescriptor(*config_descriptor, &config);
871 SetResult(config.ToValue().release());
872 } else {
873 SetError(kErrorNotConfigured);
876 AsyncWorkCompleted();
879 UsbListInterfacesFunction::UsbListInterfacesFunction() {
882 UsbListInterfacesFunction::~UsbListInterfacesFunction() {
885 bool UsbListInterfacesFunction::Prepare() {
886 parameters_ = ListInterfaces::Params::Create(*args_);
887 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
888 return true;
891 void UsbListInterfacesFunction::AsyncWorkStart() {
892 scoped_refptr<UsbDeviceHandle> device_handle =
893 GetDeviceHandleOrCompleteWithError(parameters_->handle);
894 if (!device_handle.get()) {
895 return;
898 const UsbConfigDescriptor* config_descriptor =
899 device_handle->GetDevice()->GetConfiguration();
900 if (config_descriptor) {
901 ConfigDescriptor config;
902 ConvertConfigDescriptor(*config_descriptor, &config);
904 scoped_ptr<base::ListValue> result(new base::ListValue);
905 for (size_t i = 0; i < config.interfaces.size(); ++i) {
906 result->Append(config.interfaces[i]->ToValue().release());
909 SetResult(result.release());
910 } else {
911 SetError(kErrorNotConfigured);
914 AsyncWorkCompleted();
917 UsbCloseDeviceFunction::UsbCloseDeviceFunction() {
920 UsbCloseDeviceFunction::~UsbCloseDeviceFunction() {
923 bool UsbCloseDeviceFunction::Prepare() {
924 parameters_ = CloseDevice::Params::Create(*args_);
925 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
926 return true;
929 void UsbCloseDeviceFunction::AsyncWorkStart() {
930 scoped_refptr<UsbDeviceHandle> device_handle =
931 GetDeviceHandleOrCompleteWithError(parameters_->handle);
932 if (!device_handle.get())
933 return;
935 // The device handle is closed when the resource is destroyed.
936 RemoveUsbDeviceResource(parameters_->handle.handle);
937 AsyncWorkCompleted();
940 UsbClaimInterfaceFunction::UsbClaimInterfaceFunction() {
943 UsbClaimInterfaceFunction::~UsbClaimInterfaceFunction() {
946 bool UsbClaimInterfaceFunction::Prepare() {
947 parameters_ = ClaimInterface::Params::Create(*args_);
948 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
949 return true;
952 void UsbClaimInterfaceFunction::AsyncWorkStart() {
953 scoped_refptr<UsbDeviceHandle> device_handle =
954 GetDeviceHandleOrCompleteWithError(parameters_->handle);
955 if (!device_handle.get())
956 return;
958 bool success = device_handle->ClaimInterface(parameters_->interface_number);
960 if (!success)
961 SetError(kErrorCannotClaimInterface);
962 AsyncWorkCompleted();
965 UsbReleaseInterfaceFunction::UsbReleaseInterfaceFunction() {
968 UsbReleaseInterfaceFunction::~UsbReleaseInterfaceFunction() {
971 bool UsbReleaseInterfaceFunction::Prepare() {
972 parameters_ = ReleaseInterface::Params::Create(*args_);
973 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
974 return true;
977 void UsbReleaseInterfaceFunction::AsyncWorkStart() {
978 scoped_refptr<UsbDeviceHandle> device_handle =
979 GetDeviceHandleOrCompleteWithError(parameters_->handle);
980 if (!device_handle.get())
981 return;
983 bool success = device_handle->ReleaseInterface(parameters_->interface_number);
984 if (!success)
985 SetError(kErrorCannotReleaseInterface);
986 AsyncWorkCompleted();
989 UsbSetInterfaceAlternateSettingFunction::
990 UsbSetInterfaceAlternateSettingFunction() {
993 UsbSetInterfaceAlternateSettingFunction::
994 ~UsbSetInterfaceAlternateSettingFunction() {
997 bool UsbSetInterfaceAlternateSettingFunction::Prepare() {
998 parameters_ = SetInterfaceAlternateSetting::Params::Create(*args_);
999 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
1000 return true;
1003 void UsbSetInterfaceAlternateSettingFunction::AsyncWorkStart() {
1004 scoped_refptr<UsbDeviceHandle> device_handle =
1005 GetDeviceHandleOrCompleteWithError(parameters_->handle);
1006 if (!device_handle.get())
1007 return;
1009 bool success = device_handle->SetInterfaceAlternateSetting(
1010 parameters_->interface_number, parameters_->alternate_setting);
1011 if (!success)
1012 SetError(kErrorCannotSetInterfaceAlternateSetting);
1014 AsyncWorkCompleted();
1017 UsbControlTransferFunction::UsbControlTransferFunction() {
1020 UsbControlTransferFunction::~UsbControlTransferFunction() {
1023 bool UsbControlTransferFunction::Prepare() {
1024 parameters_ = ControlTransfer::Params::Create(*args_);
1025 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
1026 return true;
1029 void UsbControlTransferFunction::AsyncWorkStart() {
1030 scoped_refptr<UsbDeviceHandle> device_handle =
1031 GetDeviceHandleOrCompleteWithError(parameters_->handle);
1032 if (!device_handle.get())
1033 return;
1035 const ControlTransferInfo& transfer = parameters_->transfer_info;
1037 UsbEndpointDirection direction;
1038 UsbDeviceHandle::TransferRequestType request_type;
1039 UsbDeviceHandle::TransferRecipient recipient;
1040 size_t size = 0;
1042 if (!ConvertDirectionSafely(transfer.direction, &direction) ||
1043 !ConvertRequestTypeSafely(transfer.request_type, &request_type) ||
1044 !ConvertRecipientSafely(transfer.recipient, &recipient)) {
1045 AsyncWorkCompleted();
1046 return;
1049 if (!GetTransferSize(transfer, &size)) {
1050 CompleteWithError(kErrorInvalidTransferLength);
1051 return;
1054 scoped_refptr<net::IOBuffer> buffer =
1055 CreateBufferForTransfer(transfer, direction, size);
1056 if (!buffer.get()) {
1057 CompleteWithError(kErrorMalformedParameters);
1058 return;
1061 int timeout = transfer.timeout ? *transfer.timeout : 0;
1062 if (timeout < 0) {
1063 CompleteWithError(kErrorInvalidTimeout);
1064 return;
1067 device_handle->ControlTransfer(
1068 direction, request_type, recipient, transfer.request, transfer.value,
1069 transfer.index, buffer.get(), size, timeout,
1070 base::Bind(&UsbControlTransferFunction::OnCompleted, this));
1073 UsbBulkTransferFunction::UsbBulkTransferFunction() {
1076 UsbBulkTransferFunction::~UsbBulkTransferFunction() {
1079 bool UsbBulkTransferFunction::Prepare() {
1080 parameters_ = BulkTransfer::Params::Create(*args_);
1081 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
1082 return true;
1085 void UsbBulkTransferFunction::AsyncWorkStart() {
1086 scoped_refptr<UsbDeviceHandle> device_handle =
1087 GetDeviceHandleOrCompleteWithError(parameters_->handle);
1088 if (!device_handle.get())
1089 return;
1091 const GenericTransferInfo& transfer = parameters_->transfer_info;
1093 UsbEndpointDirection direction;
1094 size_t size = 0;
1096 if (!ConvertDirectionSafely(transfer.direction, &direction)) {
1097 AsyncWorkCompleted();
1098 return;
1101 if (!GetTransferSize(transfer, &size)) {
1102 CompleteWithError(kErrorInvalidTransferLength);
1103 return;
1106 scoped_refptr<net::IOBuffer> buffer =
1107 CreateBufferForTransfer(transfer, direction, size);
1108 if (!buffer.get()) {
1109 CompleteWithError(kErrorMalformedParameters);
1110 return;
1113 int timeout = transfer.timeout ? *transfer.timeout : 0;
1114 if (timeout < 0) {
1115 CompleteWithError(kErrorInvalidTimeout);
1116 return;
1119 device_handle->BulkTransfer(
1120 direction, transfer.endpoint, buffer.get(), size, timeout,
1121 base::Bind(&UsbBulkTransferFunction::OnCompleted, this));
1124 UsbInterruptTransferFunction::UsbInterruptTransferFunction() {
1127 UsbInterruptTransferFunction::~UsbInterruptTransferFunction() {
1130 bool UsbInterruptTransferFunction::Prepare() {
1131 parameters_ = InterruptTransfer::Params::Create(*args_);
1132 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
1133 return true;
1136 void UsbInterruptTransferFunction::AsyncWorkStart() {
1137 scoped_refptr<UsbDeviceHandle> device_handle =
1138 GetDeviceHandleOrCompleteWithError(parameters_->handle);
1139 if (!device_handle.get())
1140 return;
1142 const GenericTransferInfo& transfer = parameters_->transfer_info;
1144 UsbEndpointDirection direction;
1145 size_t size = 0;
1147 if (!ConvertDirectionSafely(transfer.direction, &direction)) {
1148 AsyncWorkCompleted();
1149 return;
1152 if (!GetTransferSize(transfer, &size)) {
1153 CompleteWithError(kErrorInvalidTransferLength);
1154 return;
1157 scoped_refptr<net::IOBuffer> buffer =
1158 CreateBufferForTransfer(transfer, direction, size);
1159 if (!buffer.get()) {
1160 CompleteWithError(kErrorMalformedParameters);
1161 return;
1164 int timeout = transfer.timeout ? *transfer.timeout : 0;
1165 if (timeout < 0) {
1166 CompleteWithError(kErrorInvalidTimeout);
1167 return;
1170 device_handle->InterruptTransfer(
1171 direction, transfer.endpoint, buffer.get(), size, timeout,
1172 base::Bind(&UsbInterruptTransferFunction::OnCompleted, this));
1175 UsbIsochronousTransferFunction::UsbIsochronousTransferFunction() {
1178 UsbIsochronousTransferFunction::~UsbIsochronousTransferFunction() {
1181 bool UsbIsochronousTransferFunction::Prepare() {
1182 parameters_ = IsochronousTransfer::Params::Create(*args_);
1183 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
1184 return true;
1187 void UsbIsochronousTransferFunction::AsyncWorkStart() {
1188 scoped_refptr<UsbDeviceHandle> device_handle =
1189 GetDeviceHandleOrCompleteWithError(parameters_->handle);
1190 if (!device_handle.get())
1191 return;
1193 const IsochronousTransferInfo& transfer = parameters_->transfer_info;
1194 const GenericTransferInfo& generic_transfer = transfer.transfer_info;
1196 size_t size = 0;
1197 UsbEndpointDirection direction;
1199 if (!ConvertDirectionSafely(generic_transfer.direction, &direction)) {
1200 AsyncWorkCompleted();
1201 return;
1203 if (!GetTransferSize(generic_transfer, &size)) {
1204 CompleteWithError(kErrorInvalidTransferLength);
1205 return;
1207 if (transfer.packets < 0 || transfer.packets >= kMaxPackets) {
1208 CompleteWithError(kErrorInvalidNumberOfPackets);
1209 return;
1211 unsigned int packets = transfer.packets;
1212 if (transfer.packet_length < 0 ||
1213 transfer.packet_length >= kMaxPacketLength) {
1214 CompleteWithError(kErrorInvalidPacketLength);
1215 return;
1217 unsigned int packet_length = transfer.packet_length;
1218 const uint64 total_length = packets * packet_length;
1219 if (packets > size || total_length > size) {
1220 CompleteWithError(kErrorTransferLength);
1221 return;
1224 scoped_refptr<net::IOBuffer> buffer =
1225 CreateBufferForTransfer(generic_transfer, direction, size);
1226 if (!buffer.get()) {
1227 CompleteWithError(kErrorMalformedParameters);
1228 return;
1231 int timeout = generic_transfer.timeout ? *generic_transfer.timeout : 0;
1232 if (timeout < 0) {
1233 CompleteWithError(kErrorInvalidTimeout);
1234 return;
1237 device_handle->IsochronousTransfer(
1238 direction, generic_transfer.endpoint, buffer.get(), size, packets,
1239 packet_length, timeout,
1240 base::Bind(&UsbIsochronousTransferFunction::OnCompleted, this));
1243 UsbResetDeviceFunction::UsbResetDeviceFunction() {
1246 UsbResetDeviceFunction::~UsbResetDeviceFunction() {
1249 bool UsbResetDeviceFunction::Prepare() {
1250 parameters_ = ResetDevice::Params::Create(*args_);
1251 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
1252 return true;
1255 void UsbResetDeviceFunction::AsyncWorkStart() {
1256 scoped_refptr<UsbDeviceHandle> device_handle =
1257 GetDeviceHandleOrCompleteWithError(parameters_->handle);
1258 if (!device_handle.get())
1259 return;
1261 bool success = device_handle->ResetDevice();
1262 if (!success) {
1263 device_handle->Close();
1264 RemoveUsbDeviceResource(parameters_->handle.handle);
1265 SetResult(new base::FundamentalValue(false));
1266 CompleteWithError(kErrorResetDevice);
1267 return;
1270 SetResult(new base::FundamentalValue(true));
1271 AsyncWorkCompleted();
1274 } // namespace extensions