Update {virtual,override,final} to follow C++11 style.
[chromium-blink-merge.git] / extensions / browser / api / usb / usb_api.cc
blob329287cd2f73536017b478553cc67e8b830a89fc
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 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) {
120 switch (input) {
121 case usb::DIRECTION_IN:
122 *output = device::USB_DIRECTION_INBOUND;
123 return true;
124 case usb::DIRECTION_OUT:
125 *output = device::USB_DIRECTION_OUTBOUND;
126 return true;
127 default:
128 NOTREACHED();
129 return false;
133 bool ConvertRequestTypeFromApi(const RequestType& input,
134 UsbDeviceHandle::TransferRequestType* output) {
135 switch (input) {
136 case usb::REQUEST_TYPE_STANDARD:
137 *output = UsbDeviceHandle::STANDARD;
138 return true;
139 case usb::REQUEST_TYPE_CLASS:
140 *output = UsbDeviceHandle::CLASS;
141 return true;
142 case usb::REQUEST_TYPE_VENDOR:
143 *output = UsbDeviceHandle::VENDOR;
144 return true;
145 case usb::REQUEST_TYPE_RESERVED:
146 *output = UsbDeviceHandle::RESERVED;
147 return true;
148 default:
149 NOTREACHED();
150 return false;
154 bool ConvertRecipientFromApi(const Recipient& input,
155 UsbDeviceHandle::TransferRecipient* output) {
156 switch (input) {
157 case usb::RECIPIENT_DEVICE:
158 *output = UsbDeviceHandle::DEVICE;
159 return true;
160 case usb::RECIPIENT_INTERFACE:
161 *output = UsbDeviceHandle::INTERFACE;
162 return true;
163 case usb::RECIPIENT_ENDPOINT:
164 *output = UsbDeviceHandle::ENDPOINT;
165 return true;
166 case usb::RECIPIENT_OTHER:
167 *output = UsbDeviceHandle::OTHER;
168 return true;
169 default:
170 NOTREACHED();
171 return false;
175 template <class T>
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) {
181 *output = *length;
182 return true;
184 } else if (input.direction == usb::DIRECTION_OUT) {
185 if (input.data.get()) {
186 *output = input.data->size();
187 return true;
190 return false;
193 template <class T>
194 scoped_refptr<net::IOBuffer> CreateBufferForTransfer(
195 const T& input,
196 UsbEndpointDirection direction,
197 size_t size) {
198 if (size >= kMaxTransferLength)
199 return NULL;
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) {
208 return buffer;
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);
212 return buffer;
215 NOTREACHED();
216 return NULL;
219 const char* ConvertTransferStatusToApi(const UsbTransferStatus status) {
220 switch (status) {
221 case device::USB_TRANSFER_COMPLETED:
222 return "";
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;
237 default:
238 NOTREACHED();
239 return "";
243 #if defined(OS_CHROMEOS)
244 void RequestUsbDevicesAccessHelper(
245 ScopedDeviceVector devices,
246 std::vector<scoped_refptr<UsbDevice> >::iterator i,
247 int interface_id,
248 const base::Callback<void(ScopedDeviceVector result)>& callback,
249 bool success) {
250 if (success) {
251 ++i;
252 } else {
253 i = devices->erase(i);
255 if (i == devices->end()) {
256 callback.Run(devices.Pass());
257 return;
259 (*i)->RequestUsbAccess(interface_id,
260 base::Bind(RequestUsbDevicesAccessHelper,
261 base::Passed(devices.Pass()),
263 interface_id,
264 callback));
267 void RequestUsbDevicesAccess(
268 ScopedDeviceVector devices,
269 int interface_id,
270 const base::Callback<void(ScopedDeviceVector result)>& callback) {
271 if (devices->empty()) {
272 callback.Run(devices.Pass());
273 return;
275 std::vector<scoped_refptr<UsbDevice> >::iterator i = devices->begin();
276 (*i)->RequestUsbAccess(interface_id,
277 base::Bind(RequestUsbDevicesAccessHelper,
278 base::Passed(devices.Pass()),
280 interface_id,
281 callback));
283 #endif // OS_CHROMEOS
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 #if defined(OS_CHROMEOS)
602 RequestUsbDevicesAccess(
603 devices.Pass(),
604 interface_id,
605 base::Bind(&UsbFindDevicesFunction::OpenDevices, this));
606 #else
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));
630 SetResult(result);
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());
645 return true;
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(),
654 &filters[i]);
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();
666 if (!service) {
667 CompleteWithError(kErrorInitService);
668 return;
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(),
712 &filters[i]);
716 prompt_ = ExtensionsAPIClient::Get()->CreateDevicePermissionsPrompt(
717 GetAssociatedWebContents());
718 if (!prompt_) {
719 return RespondNow(Error(kErrorNotSupported));
722 AddRef();
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());
736 SendResponse(true);
737 Release();
740 UsbRequestAccessFunction::UsbRequestAccessFunction() {
743 UsbRequestAccessFunction::~UsbRequestAccessFunction() {
746 bool UsbRequestAccessFunction::Prepare() {
747 parameters_ = RequestAccess::Params::Create(*args_);
748 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
749 return true;
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());
770 return true;
773 void UsbOpenDeviceFunction::AsyncWorkStart() {
774 UsbService* service = device::DeviceClient::Get()->GetUsbService();
775 if (!service) {
776 CompleteWithError(kErrorInitService);
777 return;
780 device_ = service->GetDeviceById(parameters_->device.device);
781 if (!device_.get()) {
782 CompleteWithError(kErrorNoDevice);
783 return;
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);
790 return;
793 #if defined(OS_CHROMEOS)
794 device_->RequestUsbAccess(
795 -1, /* any interface, unused by the permission broker */
796 base::Bind(&UsbOpenDeviceFunction::OnRequestAccessComplete, this));
797 #else
798 OnRequestAccessComplete(true);
799 #endif // OS_CHROMEOS
802 void UsbOpenDeviceFunction::OnRequestAccessComplete(bool success) {
803 if (!success) {
804 SetError(kErrorPermissionDenied);
805 AsyncWorkCompleted();
806 return;
809 scoped_refptr<UsbDeviceHandle> handle = device_->Open();
810 if (!handle.get()) {
811 SetError(kErrorOpen);
812 AsyncWorkCompleted();
813 return;
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(),
825 permission_entry_);
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());
839 return true;
842 void UsbSetConfigurationFunction::AsyncWorkStart() {
843 scoped_refptr<UsbDeviceHandle> device_handle =
844 GetDeviceHandleOrCompleteWithError(parameters_->handle);
845 if (!device_handle.get()) {
846 return;
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());
864 return true;
867 void UsbGetConfigurationFunction::AsyncWorkStart() {
868 scoped_refptr<UsbDeviceHandle> device_handle =
869 GetDeviceHandleOrCompleteWithError(parameters_->handle);
870 if (!device_handle.get()) {
871 return;
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());
880 } else {
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());
896 return true;
899 void UsbListInterfacesFunction::AsyncWorkStart() {
900 scoped_refptr<UsbDeviceHandle> device_handle =
901 GetDeviceHandleOrCompleteWithError(parameters_->handle);
902 if (!device_handle.get()) {
903 return;
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());
918 } else {
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());
934 return true;
937 void UsbCloseDeviceFunction::AsyncWorkStart() {
938 scoped_refptr<UsbDeviceHandle> device_handle =
939 GetDeviceHandleOrCompleteWithError(parameters_->handle);
940 if (!device_handle.get())
941 return;
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());
957 return true;
960 void UsbClaimInterfaceFunction::AsyncWorkStart() {
961 scoped_refptr<UsbDeviceHandle> device_handle =
962 GetDeviceHandleOrCompleteWithError(parameters_->handle);
963 if (!device_handle.get())
964 return;
966 bool success = device_handle->ClaimInterface(parameters_->interface_number);
968 if (!success)
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());
982 return true;
985 void UsbReleaseInterfaceFunction::AsyncWorkStart() {
986 scoped_refptr<UsbDeviceHandle> device_handle =
987 GetDeviceHandleOrCompleteWithError(parameters_->handle);
988 if (!device_handle.get())
989 return;
991 bool success = device_handle->ReleaseInterface(parameters_->interface_number);
992 if (!success)
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());
1008 return true;
1011 void UsbSetInterfaceAlternateSettingFunction::AsyncWorkStart() {
1012 scoped_refptr<UsbDeviceHandle> device_handle =
1013 GetDeviceHandleOrCompleteWithError(parameters_->handle);
1014 if (!device_handle.get())
1015 return;
1017 bool success = device_handle->SetInterfaceAlternateSetting(
1018 parameters_->interface_number, parameters_->alternate_setting);
1019 if (!success)
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());
1034 return true;
1037 void UsbControlTransferFunction::AsyncWorkStart() {
1038 scoped_refptr<UsbDeviceHandle> device_handle =
1039 GetDeviceHandleOrCompleteWithError(parameters_->handle);
1040 if (!device_handle.get())
1041 return;
1043 const ControlTransferInfo& transfer = parameters_->transfer_info;
1045 UsbEndpointDirection direction;
1046 UsbDeviceHandle::TransferRequestType request_type;
1047 UsbDeviceHandle::TransferRecipient recipient;
1048 size_t size = 0;
1050 if (!ConvertDirectionSafely(transfer.direction, &direction) ||
1051 !ConvertRequestTypeSafely(transfer.request_type, &request_type) ||
1052 !ConvertRecipientSafely(transfer.recipient, &recipient)) {
1053 AsyncWorkCompleted();
1054 return;
1057 if (!GetTransferSize(transfer, &size)) {
1058 CompleteWithError(kErrorInvalidTransferLength);
1059 return;
1062 scoped_refptr<net::IOBuffer> buffer =
1063 CreateBufferForTransfer(transfer, direction, size);
1064 if (!buffer.get()) {
1065 CompleteWithError(kErrorMalformedParameters);
1066 return;
1069 device_handle->ControlTransfer(
1070 direction,
1071 request_type,
1072 recipient,
1073 transfer.request,
1074 transfer.value,
1075 transfer.index,
1076 buffer.get(),
1077 size,
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());
1091 return true;
1094 void UsbBulkTransferFunction::AsyncWorkStart() {
1095 scoped_refptr<UsbDeviceHandle> device_handle =
1096 GetDeviceHandleOrCompleteWithError(parameters_->handle);
1097 if (!device_handle.get())
1098 return;
1100 const GenericTransferInfo& transfer = parameters_->transfer_info;
1102 UsbEndpointDirection direction;
1103 size_t size = 0;
1105 if (!ConvertDirectionSafely(transfer.direction, &direction)) {
1106 AsyncWorkCompleted();
1107 return;
1110 if (!GetTransferSize(transfer, &size)) {
1111 CompleteWithError(kErrorInvalidTransferLength);
1112 return;
1115 scoped_refptr<net::IOBuffer> buffer =
1116 CreateBufferForTransfer(transfer, direction, size);
1117 if (!buffer.get()) {
1118 CompleteWithError(kErrorMalformedParameters);
1119 return;
1122 device_handle->BulkTransfer(
1123 direction,
1124 transfer.endpoint,
1125 buffer.get(),
1126 size,
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());
1140 return true;
1143 void UsbInterruptTransferFunction::AsyncWorkStart() {
1144 scoped_refptr<UsbDeviceHandle> device_handle =
1145 GetDeviceHandleOrCompleteWithError(parameters_->handle);
1146 if (!device_handle.get())
1147 return;
1149 const GenericTransferInfo& transfer = parameters_->transfer_info;
1151 UsbEndpointDirection direction;
1152 size_t size = 0;
1154 if (!ConvertDirectionSafely(transfer.direction, &direction)) {
1155 AsyncWorkCompleted();
1156 return;
1159 if (!GetTransferSize(transfer, &size)) {
1160 CompleteWithError(kErrorInvalidTransferLength);
1161 return;
1164 scoped_refptr<net::IOBuffer> buffer =
1165 CreateBufferForTransfer(transfer, direction, size);
1166 if (!buffer.get()) {
1167 CompleteWithError(kErrorMalformedParameters);
1168 return;
1171 device_handle->InterruptTransfer(
1172 direction,
1173 transfer.endpoint,
1174 buffer.get(),
1175 size,
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());
1189 return true;
1192 void UsbIsochronousTransferFunction::AsyncWorkStart() {
1193 scoped_refptr<UsbDeviceHandle> device_handle =
1194 GetDeviceHandleOrCompleteWithError(parameters_->handle);
1195 if (!device_handle.get())
1196 return;
1198 const IsochronousTransferInfo& transfer = parameters_->transfer_info;
1199 const GenericTransferInfo& generic_transfer = transfer.transfer_info;
1201 size_t size = 0;
1202 UsbEndpointDirection direction;
1204 if (!ConvertDirectionSafely(generic_transfer.direction, &direction)) {
1205 AsyncWorkCompleted();
1206 return;
1208 if (!GetTransferSize(generic_transfer, &size)) {
1209 CompleteWithError(kErrorInvalidTransferLength);
1210 return;
1212 if (transfer.packets < 0 || transfer.packets >= kMaxPackets) {
1213 CompleteWithError(kErrorInvalidNumberOfPackets);
1214 return;
1216 unsigned int packets = transfer.packets;
1217 if (transfer.packet_length < 0 ||
1218 transfer.packet_length >= kMaxPacketLength) {
1219 CompleteWithError(kErrorInvalidPacketLength);
1220 return;
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);
1226 return;
1229 scoped_refptr<net::IOBuffer> buffer =
1230 CreateBufferForTransfer(generic_transfer, direction, size);
1231 if (!buffer.get()) {
1232 CompleteWithError(kErrorMalformedParameters);
1233 return;
1236 device_handle->IsochronousTransfer(
1237 direction,
1238 generic_transfer.endpoint,
1239 buffer.get(),
1240 size,
1241 packets,
1242 packet_length,
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());
1256 return true;
1259 void UsbResetDeviceFunction::AsyncWorkStart() {
1260 scoped_refptr<UsbDeviceHandle> device_handle =
1261 GetDeviceHandleOrCompleteWithError(parameters_->handle);
1262 if (!device_handle.get())
1263 return;
1265 bool success = device_handle->ResetDevice();
1266 if (!success) {
1267 device_handle->Close();
1268 RemoveUsbDeviceResource(parameters_->handle.handle);
1269 SetResult(new base::FundamentalValue(false));
1270 CompleteWithError(kErrorResetDevice);
1271 return;
1274 SetResult(new base::FundamentalValue(true));
1275 AsyncWorkCompleted();
1278 } // namespace extensions