Finish refactoring of DomCodeToUsLayoutKeyboardCode().
[chromium-blink-merge.git] / extensions / browser / api / usb / usb_api.cc
blob9977cb0824c03f0c0945d7b5dcfd18984cc1f06d
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/barrier_closure.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "device/core/device_client.h"
13 #include "device/usb/usb_descriptors.h"
14 #include "device/usb/usb_device_handle.h"
15 #include "device/usb/usb_service.h"
16 #include "extensions/browser/api/device_permissions_manager.h"
17 #include "extensions/browser/api/device_permissions_prompt.h"
18 #include "extensions/browser/api/extensions_api_client.h"
19 #include "extensions/browser/api/usb/usb_device_resource.h"
20 #include "extensions/browser/api/usb/usb_guid_map.h"
21 #include "extensions/browser/extension_system.h"
22 #include "extensions/common/api/usb.h"
23 #include "extensions/common/permissions/permissions_data.h"
24 #include "extensions/common/permissions/usb_device_permission.h"
26 namespace usb = extensions::core_api::usb;
27 namespace BulkTransfer = usb::BulkTransfer;
28 namespace ClaimInterface = usb::ClaimInterface;
29 namespace CloseDevice = usb::CloseDevice;
30 namespace ControlTransfer = usb::ControlTransfer;
31 namespace FindDevices = usb::FindDevices;
32 namespace GetDevices = usb::GetDevices;
33 namespace GetUserSelectedDevices = usb::GetUserSelectedDevices;
34 namespace InterruptTransfer = usb::InterruptTransfer;
35 namespace IsochronousTransfer = usb::IsochronousTransfer;
36 namespace SetConfiguration = usb::SetConfiguration;
37 namespace GetConfiguration = usb::GetConfiguration;
38 namespace ListInterfaces = usb::ListInterfaces;
39 namespace OpenDevice = usb::OpenDevice;
40 namespace ReleaseInterface = usb::ReleaseInterface;
41 namespace RequestAccess = usb::RequestAccess;
42 namespace ResetDevice = usb::ResetDevice;
43 namespace SetInterfaceAlternateSetting = usb::SetInterfaceAlternateSetting;
45 using content::BrowserThread;
46 using device::UsbConfigDescriptor;
47 using device::UsbDevice;
48 using device::UsbDeviceFilter;
49 using device::UsbDeviceHandle;
50 using device::UsbEndpointDescriptor;
51 using device::UsbEndpointDirection;
52 using device::UsbInterfaceDescriptor;
53 using device::UsbService;
54 using device::UsbSynchronizationType;
55 using device::UsbTransferStatus;
56 using device::UsbTransferType;
57 using device::UsbUsageType;
58 using std::string;
59 using std::vector;
60 using usb::ConfigDescriptor;
61 using usb::ControlTransferInfo;
62 using usb::ConnectionHandle;
63 using usb::Device;
64 using usb::Direction;
65 using usb::EndpointDescriptor;
66 using usb::GenericTransferInfo;
67 using usb::InterfaceDescriptor;
68 using usb::IsochronousTransferInfo;
69 using usb::Recipient;
70 using usb::RequestType;
71 using usb::SynchronizationType;
72 using usb::TransferType;
73 using usb::UsageType;
75 namespace extensions {
77 namespace {
79 const char kDataKey[] = "data";
80 const char kResultCodeKey[] = "resultCode";
82 const char kErrorInitService[] = "Failed to initialize USB service.";
84 const char kErrorOpen[] = "Failed to open device.";
85 const char kErrorCancelled[] = "Transfer was cancelled.";
86 const char kErrorDisconnect[] = "Device disconnected.";
87 const char kErrorGeneric[] = "Transfer failed.";
88 const char kErrorNotSupported[] = "Not supported on this platform.";
89 const char kErrorNotConfigured[] = "The device is not in a configured state.";
90 const char kErrorOverflow[] = "Inbound transfer overflow.";
91 const char kErrorStalled[] = "Transfer stalled.";
92 const char kErrorTimeout[] = "Transfer timed out.";
93 const char kErrorTransferLength[] = "Transfer length is insufficient.";
94 const char kErrorCannotSetConfiguration[] =
95 "Error setting device configuration.";
96 const char kErrorCannotClaimInterface[] = "Error claiming interface.";
97 const char kErrorCannotReleaseInterface[] = "Error releasing interface.";
98 const char kErrorCannotSetInterfaceAlternateSetting[] =
99 "Error setting alternate interface setting.";
100 const char kErrorConvertDirection[] = "Invalid transfer direction.";
101 const char kErrorConvertRecipient[] = "Invalid transfer recipient.";
102 const char kErrorConvertRequestType[] = "Invalid request type.";
103 const char kErrorMalformedParameters[] = "Error parsing parameters.";
104 const char kErrorNoConnection[] = "No such connection.";
105 const char kErrorNoDevice[] = "No such device.";
106 const char kErrorPermissionDenied[] = "Permission to access device was denied";
107 const char kErrorInvalidTransferLength[] =
108 "Transfer length must be a positive number less than 104,857,600.";
109 const char kErrorInvalidNumberOfPackets[] =
110 "Number of packets must be a positive number less than 4,194,304.";
111 const char kErrorInvalidPacketLength[] =
112 "Packet length must be a positive number less than 65,536.";
113 const char kErrorInvalidTimeout[] =
114 "Transfer timeout must be greater than or equal to 0.";
115 const char kErrorResetDevice[] =
116 "Error resetting the device. The device has been closed.";
118 const size_t kMaxTransferLength = 100 * 1024 * 1024;
119 const int kMaxPackets = 4 * 1024 * 1024;
120 const int kMaxPacketLength = 64 * 1024;
122 bool ConvertDirectionFromApi(const Direction& input,
123 UsbEndpointDirection* output) {
124 switch (input) {
125 case usb::DIRECTION_IN:
126 *output = device::USB_DIRECTION_INBOUND;
127 return true;
128 case usb::DIRECTION_OUT:
129 *output = device::USB_DIRECTION_OUTBOUND;
130 return true;
131 default:
132 NOTREACHED();
133 return false;
137 bool ConvertRequestTypeFromApi(const RequestType& input,
138 UsbDeviceHandle::TransferRequestType* output) {
139 switch (input) {
140 case usb::REQUEST_TYPE_STANDARD:
141 *output = UsbDeviceHandle::STANDARD;
142 return true;
143 case usb::REQUEST_TYPE_CLASS:
144 *output = UsbDeviceHandle::CLASS;
145 return true;
146 case usb::REQUEST_TYPE_VENDOR:
147 *output = UsbDeviceHandle::VENDOR;
148 return true;
149 case usb::REQUEST_TYPE_RESERVED:
150 *output = UsbDeviceHandle::RESERVED;
151 return true;
152 default:
153 NOTREACHED();
154 return false;
158 bool ConvertRecipientFromApi(const Recipient& input,
159 UsbDeviceHandle::TransferRecipient* output) {
160 switch (input) {
161 case usb::RECIPIENT_DEVICE:
162 *output = UsbDeviceHandle::DEVICE;
163 return true;
164 case usb::RECIPIENT_INTERFACE:
165 *output = UsbDeviceHandle::INTERFACE;
166 return true;
167 case usb::RECIPIENT_ENDPOINT:
168 *output = UsbDeviceHandle::ENDPOINT;
169 return true;
170 case usb::RECIPIENT_OTHER:
171 *output = UsbDeviceHandle::OTHER;
172 return true;
173 default:
174 NOTREACHED();
175 return false;
179 template <class T>
180 bool GetTransferSize(const T& input, size_t* output) {
181 if (input.direction == usb::DIRECTION_IN) {
182 const int* length = input.length.get();
183 if (length && *length >= 0 &&
184 static_cast<size_t>(*length) < kMaxTransferLength) {
185 *output = *length;
186 return true;
188 } else if (input.direction == usb::DIRECTION_OUT) {
189 if (input.data.get()) {
190 *output = input.data->size();
191 return true;
194 return false;
197 template <class T>
198 scoped_refptr<net::IOBuffer> CreateBufferForTransfer(
199 const T& input,
200 UsbEndpointDirection direction,
201 size_t size) {
202 if (size >= kMaxTransferLength)
203 return NULL;
205 // Allocate a |size|-bytes buffer, or a one-byte buffer if |size| is 0. This
206 // is due to an impedance mismatch between IOBuffer and URBs. An IOBuffer
207 // cannot represent a zero-length buffer, while an URB can.
208 scoped_refptr<net::IOBuffer> buffer =
209 new net::IOBuffer(std::max(static_cast<size_t>(1), size));
211 if (direction == device::USB_DIRECTION_INBOUND) {
212 return buffer;
213 } else if (direction == device::USB_DIRECTION_OUTBOUND) {
214 if (input.data.get() && size <= input.data->size()) {
215 memcpy(buffer->data(), input.data->data(), size);
216 return buffer;
219 NOTREACHED();
220 return NULL;
223 const char* ConvertTransferStatusToApi(const UsbTransferStatus status) {
224 switch (status) {
225 case device::USB_TRANSFER_COMPLETED:
226 return "";
227 case device::USB_TRANSFER_ERROR:
228 return kErrorGeneric;
229 case device::USB_TRANSFER_TIMEOUT:
230 return kErrorTimeout;
231 case device::USB_TRANSFER_CANCELLED:
232 return kErrorCancelled;
233 case device::USB_TRANSFER_STALLED:
234 return kErrorStalled;
235 case device::USB_TRANSFER_DISCONNECT:
236 return kErrorDisconnect;
237 case device::USB_TRANSFER_OVERFLOW:
238 return kErrorOverflow;
239 case device::USB_TRANSFER_LENGTH_SHORT:
240 return kErrorTransferLength;
241 default:
242 NOTREACHED();
243 return "";
247 base::Value* PopulateConnectionHandle(int handle,
248 int vendor_id,
249 int product_id) {
250 ConnectionHandle result;
251 result.handle = handle;
252 result.vendor_id = vendor_id;
253 result.product_id = product_id;
254 return result.ToValue().release();
257 base::Value* PopulateDevice(const UsbDevice* device, int id) {
258 Device result;
259 result.device = id;
260 result.vendor_id = device->vendor_id();
261 result.product_id = device->product_id();
262 return result.ToValue().release();
265 TransferType ConvertTransferTypeToApi(const UsbTransferType& input) {
266 switch (input) {
267 case device::USB_TRANSFER_CONTROL:
268 return usb::TRANSFER_TYPE_CONTROL;
269 case device::USB_TRANSFER_INTERRUPT:
270 return usb::TRANSFER_TYPE_INTERRUPT;
271 case device::USB_TRANSFER_ISOCHRONOUS:
272 return usb::TRANSFER_TYPE_ISOCHRONOUS;
273 case device::USB_TRANSFER_BULK:
274 return usb::TRANSFER_TYPE_BULK;
275 default:
276 NOTREACHED();
277 return usb::TRANSFER_TYPE_NONE;
281 Direction ConvertDirectionToApi(const UsbEndpointDirection& input) {
282 switch (input) {
283 case device::USB_DIRECTION_INBOUND:
284 return usb::DIRECTION_IN;
285 case device::USB_DIRECTION_OUTBOUND:
286 return usb::DIRECTION_OUT;
287 default:
288 NOTREACHED();
289 return usb::DIRECTION_NONE;
293 SynchronizationType ConvertSynchronizationTypeToApi(
294 const UsbSynchronizationType& input) {
295 switch (input) {
296 case device::USB_SYNCHRONIZATION_NONE:
297 return usb::SYNCHRONIZATION_TYPE_NONE;
298 case device::USB_SYNCHRONIZATION_ASYNCHRONOUS:
299 return usb::SYNCHRONIZATION_TYPE_ASYNCHRONOUS;
300 case device::USB_SYNCHRONIZATION_ADAPTIVE:
301 return usb::SYNCHRONIZATION_TYPE_ADAPTIVE;
302 case device::USB_SYNCHRONIZATION_SYNCHRONOUS:
303 return usb::SYNCHRONIZATION_TYPE_SYNCHRONOUS;
304 default:
305 NOTREACHED();
306 return usb::SYNCHRONIZATION_TYPE_NONE;
310 UsageType ConvertUsageTypeToApi(const UsbUsageType& input) {
311 switch (input) {
312 case device::USB_USAGE_DATA:
313 return usb::USAGE_TYPE_DATA;
314 case device::USB_USAGE_FEEDBACK:
315 return usb::USAGE_TYPE_FEEDBACK;
316 case device::USB_USAGE_EXPLICIT_FEEDBACK:
317 return usb::USAGE_TYPE_EXPLICITFEEDBACK;
318 default:
319 NOTREACHED();
320 return usb::USAGE_TYPE_NONE;
324 void ConvertEndpointDescriptor(const UsbEndpointDescriptor& input,
325 EndpointDescriptor* output) {
326 output->address = input.address;
327 output->type = ConvertTransferTypeToApi(input.transfer_type);
328 output->direction = ConvertDirectionToApi(input.direction);
329 output->maximum_packet_size = input.maximum_packet_size;
330 output->synchronization =
331 ConvertSynchronizationTypeToApi(input.synchronization_type);
332 output->usage = ConvertUsageTypeToApi(input.usage_type);
333 output->polling_interval.reset(new int(input.polling_interval));
334 output->extra_data.assign(input.extra_data.begin(), input.extra_data.end());
337 void ConvertInterfaceDescriptor(const UsbInterfaceDescriptor& input,
338 InterfaceDescriptor* output) {
339 output->interface_number = input.interface_number;
340 output->alternate_setting = input.alternate_setting;
341 output->interface_class = input.interface_class;
342 output->interface_subclass = input.interface_subclass;
343 output->interface_protocol = input.interface_protocol;
344 for (const UsbEndpointDescriptor& input_endpoint : input.endpoints) {
345 linked_ptr<EndpointDescriptor> endpoint(new EndpointDescriptor);
346 ConvertEndpointDescriptor(input_endpoint, endpoint.get());
347 output->endpoints.push_back(endpoint);
349 output->extra_data.assign(input.extra_data.begin(), input.extra_data.end());
352 void ConvertConfigDescriptor(const UsbConfigDescriptor& input,
353 ConfigDescriptor* output) {
354 output->configuration_value = input.configuration_value;
355 output->self_powered = input.self_powered;
356 output->remote_wakeup = input.remote_wakeup;
357 output->max_power = input.maximum_power;
358 for (const UsbInterfaceDescriptor& input_interface : input.interfaces) {
359 linked_ptr<InterfaceDescriptor> interface(new InterfaceDescriptor);
360 ConvertInterfaceDescriptor(input_interface, interface.get());
361 output->interfaces.push_back(interface);
363 output->extra_data.assign(input.extra_data.begin(), input.extra_data.end());
366 void ConvertDeviceFilter(const usb::DeviceFilter& input,
367 UsbDeviceFilter* output) {
368 if (input.vendor_id) {
369 output->SetVendorId(*input.vendor_id);
371 if (input.product_id) {
372 output->SetProductId(*input.product_id);
374 if (input.interface_class) {
375 output->SetInterfaceClass(*input.interface_class);
377 if (input.interface_subclass) {
378 output->SetInterfaceSubclass(*input.interface_subclass);
380 if (input.interface_protocol) {
381 output->SetInterfaceProtocol(*input.interface_protocol);
385 } // namespace
387 UsbPermissionCheckingFunction::UsbPermissionCheckingFunction()
388 : device_permissions_manager_(nullptr) {
391 UsbPermissionCheckingFunction::~UsbPermissionCheckingFunction() {
394 bool UsbPermissionCheckingFunction::HasDevicePermission(
395 scoped_refptr<UsbDevice> device) {
396 if (!device_permissions_manager_) {
397 device_permissions_manager_ =
398 DevicePermissionsManager::Get(browser_context());
401 DevicePermissions* device_permissions =
402 device_permissions_manager_->GetForExtension(extension_id());
403 DCHECK(device_permissions);
405 permission_entry_ = device_permissions->FindUsbDeviceEntry(device);
406 if (permission_entry_.get()) {
407 return true;
410 UsbDevicePermission::CheckParam param(
411 device->vendor_id(),
412 device->product_id(),
413 UsbDevicePermissionData::UNSPECIFIED_INTERFACE);
414 if (extension()->permissions_data()->CheckAPIPermissionWithParam(
415 APIPermission::kUsbDevice, &param)) {
416 return true;
419 return false;
422 void UsbPermissionCheckingFunction::RecordDeviceLastUsed() {
423 if (permission_entry_.get()) {
424 device_permissions_manager_->UpdateLastUsed(extension_id(),
425 permission_entry_);
429 UsbConnectionFunction::UsbConnectionFunction() {
432 UsbConnectionFunction::~UsbConnectionFunction() {
435 scoped_refptr<device::UsbDeviceHandle> UsbConnectionFunction::GetDeviceHandle(
436 const extensions::core_api::usb::ConnectionHandle& handle) {
437 ApiResourceManager<UsbDeviceResource>* manager =
438 ApiResourceManager<UsbDeviceResource>::Get(browser_context());
439 if (!manager) {
440 return nullptr;
443 UsbDeviceResource* resource = manager->Get(extension_id(), handle.handle);
444 if (!resource) {
445 return nullptr;
448 return resource->device();
451 void UsbConnectionFunction::ReleaseDeviceHandle(
452 const extensions::core_api::usb::ConnectionHandle& handle) {
453 ApiResourceManager<UsbDeviceResource>* manager =
454 ApiResourceManager<UsbDeviceResource>::Get(browser_context());
455 manager->Remove(extension_id(), handle.handle);
458 UsbTransferFunction::UsbTransferFunction() {
461 UsbTransferFunction::~UsbTransferFunction() {
464 void UsbTransferFunction::OnCompleted(UsbTransferStatus status,
465 scoped_refptr<net::IOBuffer> data,
466 size_t length) {
467 scoped_ptr<base::DictionaryValue> transfer_info(new base::DictionaryValue());
468 transfer_info->SetInteger(kResultCodeKey, status);
469 transfer_info->Set(kDataKey, base::BinaryValue::CreateWithCopiedBuffer(
470 data->data(), length));
472 if (status == device::USB_TRANSFER_COMPLETED) {
473 Respond(OneArgument(transfer_info.release()));
474 } else {
475 scoped_ptr<base::ListValue> error_args(new base::ListValue());
476 error_args->Append(transfer_info.release());
477 // Returning arguments with an error is wrong but we're stuck with it.
478 Respond(ErrorWithArguments(error_args.Pass(),
479 ConvertTransferStatusToApi(status)));
483 UsbFindDevicesFunction::UsbFindDevicesFunction() {
486 UsbFindDevicesFunction::~UsbFindDevicesFunction() {
489 ExtensionFunction::ResponseAction UsbFindDevicesFunction::Run() {
490 scoped_ptr<extensions::core_api::usb::FindDevices::Params> parameters =
491 FindDevices::Params::Create(*args_);
492 EXTENSION_FUNCTION_VALIDATE(parameters.get());
494 vendor_id_ = parameters->options.vendor_id;
495 product_id_ = parameters->options.product_id;
496 int interface_id = parameters->options.interface_id.get()
497 ? *parameters->options.interface_id.get()
498 : UsbDevicePermissionData::ANY_INTERFACE;
499 UsbDevicePermission::CheckParam param(vendor_id_, product_id_, interface_id);
500 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
501 APIPermission::kUsbDevice, &param)) {
502 return RespondNow(Error(kErrorPermissionDenied));
505 UsbService* service = device::DeviceClient::Get()->GetUsbService();
506 if (!service) {
507 return RespondNow(Error(kErrorInitService));
510 service->GetDevices(
511 base::Bind(&UsbFindDevicesFunction::OnGetDevicesComplete, this));
512 return RespondLater();
515 void UsbFindDevicesFunction::OnGetDevicesComplete(
516 const std::vector<scoped_refptr<UsbDevice>>& devices) {
517 result_.reset(new base::ListValue());
518 barrier_ = base::BarrierClosure(
519 devices.size(), base::Bind(&UsbFindDevicesFunction::OpenComplete, this));
521 for (const scoped_refptr<UsbDevice>& device : devices) {
522 if (device->vendor_id() != vendor_id_ ||
523 device->product_id() != product_id_) {
524 barrier_.Run();
525 } else {
526 device->Open(base::Bind(&UsbFindDevicesFunction::OnDeviceOpened, this));
531 void UsbFindDevicesFunction::OnDeviceOpened(
532 scoped_refptr<UsbDeviceHandle> device_handle) {
533 if (device_handle.get()) {
534 ApiResourceManager<UsbDeviceResource>* manager =
535 ApiResourceManager<UsbDeviceResource>::Get(browser_context());
536 UsbDeviceResource* resource =
537 new UsbDeviceResource(extension_id(), device_handle);
538 scoped_refptr<UsbDevice> device = device_handle->GetDevice();
539 result_->Append(PopulateConnectionHandle(
540 manager->Add(resource), device->vendor_id(), device->product_id()));
542 barrier_.Run();
545 void UsbFindDevicesFunction::OpenComplete() {
546 Respond(OneArgument(result_.release()));
549 UsbGetDevicesFunction::UsbGetDevicesFunction() {
552 UsbGetDevicesFunction::~UsbGetDevicesFunction() {
555 ExtensionFunction::ResponseAction UsbGetDevicesFunction::Run() {
556 scoped_ptr<extensions::core_api::usb::GetDevices::Params> parameters =
557 GetDevices::Params::Create(*args_);
558 EXTENSION_FUNCTION_VALIDATE(parameters.get());
560 if (parameters->options.filters) {
561 filters_.resize(parameters->options.filters->size());
562 for (size_t i = 0; i < parameters->options.filters->size(); ++i) {
563 ConvertDeviceFilter(*parameters->options.filters->at(i).get(),
564 &filters_[i]);
567 if (parameters->options.vendor_id) {
568 filters_.resize(filters_.size() + 1);
569 filters_.back().SetVendorId(*parameters->options.vendor_id);
570 if (parameters->options.product_id) {
571 filters_.back().SetProductId(*parameters->options.product_id);
575 UsbService* service = device::DeviceClient::Get()->GetUsbService();
576 if (!service) {
577 return RespondNow(Error(kErrorInitService));
580 service->GetDevices(
581 base::Bind(&UsbGetDevicesFunction::OnGetDevicesComplete, this));
582 return RespondLater();
585 void UsbGetDevicesFunction::OnGetDevicesComplete(
586 const std::vector<scoped_refptr<UsbDevice>>& devices) {
587 scoped_ptr<base::ListValue> result(new base::ListValue());
588 UsbGuidMap* guid_map = UsbGuidMap::Get(browser_context());
589 for (const scoped_refptr<UsbDevice>& device : devices) {
590 if ((filters_.empty() || UsbDeviceFilter::MatchesAny(device, filters_)) &&
591 HasDevicePermission(device)) {
592 result->Append(PopulateDevice(device.get(),
593 guid_map->GetIdFromGuid(device->guid())));
597 Respond(OneArgument(result.release()));
600 UsbGetUserSelectedDevicesFunction::UsbGetUserSelectedDevicesFunction() {
603 UsbGetUserSelectedDevicesFunction::~UsbGetUserSelectedDevicesFunction() {
606 ExtensionFunction::ResponseAction UsbGetUserSelectedDevicesFunction::Run() {
607 scoped_ptr<extensions::core_api::usb::GetUserSelectedDevices::Params>
608 parameters = GetUserSelectedDevices::Params::Create(*args_);
609 EXTENSION_FUNCTION_VALIDATE(parameters.get());
611 if (!user_gesture()) {
612 return RespondNow(OneArgument(new base::ListValue()));
615 bool multiple = false;
616 if (parameters->options.multiple) {
617 multiple = *parameters->options.multiple;
620 std::vector<UsbDeviceFilter> filters;
621 if (parameters->options.filters) {
622 filters.resize(parameters->options.filters->size());
623 for (size_t i = 0; i < parameters->options.filters->size(); ++i) {
624 ConvertDeviceFilter(*parameters->options.filters->at(i).get(),
625 &filters[i]);
629 prompt_ = ExtensionsAPIClient::Get()->CreateDevicePermissionsPrompt(
630 GetAssociatedWebContents());
631 if (!prompt_) {
632 return RespondNow(Error(kErrorNotSupported));
635 prompt_->AskForUsbDevices(
636 extension(), browser_context(), multiple, filters,
637 base::Bind(&UsbGetUserSelectedDevicesFunction::OnDevicesChosen, this));
638 return RespondLater();
641 void UsbGetUserSelectedDevicesFunction::OnDevicesChosen(
642 const std::vector<scoped_refptr<UsbDevice>>& devices) {
643 scoped_ptr<base::ListValue> result(new base::ListValue());
644 UsbGuidMap* guid_map = UsbGuidMap::Get(browser_context());
645 for (const auto& device : devices) {
646 result->Append(
647 PopulateDevice(device.get(), guid_map->GetIdFromGuid(device->guid())));
650 Respond(OneArgument(result.release()));
653 UsbRequestAccessFunction::UsbRequestAccessFunction() {
656 UsbRequestAccessFunction::~UsbRequestAccessFunction() {
659 ExtensionFunction::ResponseAction UsbRequestAccessFunction::Run() {
660 scoped_ptr<extensions::core_api::usb::RequestAccess::Params> parameters =
661 RequestAccess::Params::Create(*args_);
662 EXTENSION_FUNCTION_VALIDATE(parameters.get());
663 return RespondNow(OneArgument(new base::FundamentalValue(true)));
666 UsbOpenDeviceFunction::UsbOpenDeviceFunction() {
669 UsbOpenDeviceFunction::~UsbOpenDeviceFunction() {
672 ExtensionFunction::ResponseAction UsbOpenDeviceFunction::Run() {
673 scoped_ptr<extensions::core_api::usb::OpenDevice::Params> parameters =
674 OpenDevice::Params::Create(*args_);
675 EXTENSION_FUNCTION_VALIDATE(parameters.get());
677 UsbService* service = device::DeviceClient::Get()->GetUsbService();
678 if (!service) {
679 return RespondNow(Error(kErrorInitService));
682 std::string guid;
683 if (!UsbGuidMap::Get(browser_context())
684 ->GetGuidFromId(parameters->device.device, &guid)) {
685 return RespondNow(Error(kErrorNoDevice));
688 scoped_refptr<UsbDevice> device = service->GetDevice(guid);
689 if (!device.get()) {
690 return RespondNow(Error(kErrorNoDevice));
693 if (!HasDevicePermission(device)) {
694 // This function must act as if there is no such device. Otherwise it can be
695 // used to fingerprint unauthorized devices.
696 return RespondNow(Error(kErrorNoDevice));
699 device->Open(base::Bind(&UsbOpenDeviceFunction::OnDeviceOpened, this));
700 return RespondLater();
703 void UsbOpenDeviceFunction::OnDeviceOpened(
704 scoped_refptr<UsbDeviceHandle> device_handle) {
705 if (!device_handle.get()) {
706 Respond(Error(kErrorOpen));
707 return;
710 RecordDeviceLastUsed();
712 ApiResourceManager<UsbDeviceResource>* manager =
713 ApiResourceManager<UsbDeviceResource>::Get(browser_context());
714 scoped_refptr<UsbDevice> device = device_handle->GetDevice();
715 Respond(OneArgument(PopulateConnectionHandle(
716 manager->Add(new UsbDeviceResource(extension_id(), device_handle)),
717 device->vendor_id(), device->product_id())));
720 UsbSetConfigurationFunction::UsbSetConfigurationFunction() {
723 UsbSetConfigurationFunction::~UsbSetConfigurationFunction() {
726 ExtensionFunction::ResponseAction UsbSetConfigurationFunction::Run() {
727 scoped_ptr<extensions::core_api::usb::SetConfiguration::Params> parameters =
728 SetConfiguration::Params::Create(*args_);
729 EXTENSION_FUNCTION_VALIDATE(parameters.get());
731 scoped_refptr<UsbDeviceHandle> device_handle =
732 GetDeviceHandle(parameters->handle);
733 if (!device_handle.get()) {
734 return RespondNow(Error(kErrorNoConnection));
737 device_handle->SetConfiguration(
738 parameters->configuration_value,
739 base::Bind(&UsbSetConfigurationFunction::OnComplete, this));
740 return RespondLater();
743 void UsbSetConfigurationFunction::OnComplete(bool success) {
744 if (success) {
745 Respond(NoArguments());
746 } else {
747 Respond(Error(kErrorCannotSetConfiguration));
751 UsbGetConfigurationFunction::UsbGetConfigurationFunction() {
754 UsbGetConfigurationFunction::~UsbGetConfigurationFunction() {
757 ExtensionFunction::ResponseAction UsbGetConfigurationFunction::Run() {
758 scoped_ptr<extensions::core_api::usb::GetConfiguration::Params> parameters =
759 GetConfiguration::Params::Create(*args_);
760 EXTENSION_FUNCTION_VALIDATE(parameters.get());
762 scoped_refptr<UsbDeviceHandle> device_handle =
763 GetDeviceHandle(parameters->handle);
764 if (!device_handle.get()) {
765 return RespondNow(Error(kErrorNoConnection));
768 const UsbConfigDescriptor* config_descriptor =
769 device_handle->GetDevice()->GetConfiguration();
770 if (config_descriptor) {
771 ConfigDescriptor config;
772 ConvertConfigDescriptor(*config_descriptor, &config);
773 return RespondNow(OneArgument(config.ToValue().release()));
774 } else {
775 return RespondNow(Error(kErrorNotConfigured));
779 UsbListInterfacesFunction::UsbListInterfacesFunction() {
782 UsbListInterfacesFunction::~UsbListInterfacesFunction() {
785 ExtensionFunction::ResponseAction UsbListInterfacesFunction::Run() {
786 scoped_ptr<extensions::core_api::usb::ListInterfaces::Params> parameters =
787 ListInterfaces::Params::Create(*args_);
788 EXTENSION_FUNCTION_VALIDATE(parameters.get());
790 scoped_refptr<UsbDeviceHandle> device_handle =
791 GetDeviceHandle(parameters->handle);
792 if (!device_handle.get()) {
793 return RespondNow(Error(kErrorNoConnection));
796 const UsbConfigDescriptor* config_descriptor =
797 device_handle->GetDevice()->GetConfiguration();
798 if (config_descriptor) {
799 ConfigDescriptor config;
800 ConvertConfigDescriptor(*config_descriptor, &config);
802 scoped_ptr<base::ListValue> result(new base::ListValue);
803 for (size_t i = 0; i < config.interfaces.size(); ++i) {
804 result->Append(config.interfaces[i]->ToValue().release());
807 return RespondNow(OneArgument(result.release()));
808 } else {
809 return RespondNow(Error(kErrorNotConfigured));
813 UsbCloseDeviceFunction::UsbCloseDeviceFunction() {
816 UsbCloseDeviceFunction::~UsbCloseDeviceFunction() {
819 ExtensionFunction::ResponseAction UsbCloseDeviceFunction::Run() {
820 scoped_ptr<extensions::core_api::usb::CloseDevice::Params> parameters =
821 CloseDevice::Params::Create(*args_);
822 EXTENSION_FUNCTION_VALIDATE(parameters.get());
824 scoped_refptr<UsbDeviceHandle> device_handle =
825 GetDeviceHandle(parameters->handle);
826 if (!device_handle.get()) {
827 return RespondNow(Error(kErrorNoConnection));
830 // The device handle is closed when the resource is destroyed.
831 ReleaseDeviceHandle(parameters->handle);
832 return RespondNow(NoArguments());
835 UsbClaimInterfaceFunction::UsbClaimInterfaceFunction() {
838 UsbClaimInterfaceFunction::~UsbClaimInterfaceFunction() {
841 ExtensionFunction::ResponseAction UsbClaimInterfaceFunction::Run() {
842 scoped_ptr<extensions::core_api::usb::ClaimInterface::Params> parameters =
843 ClaimInterface::Params::Create(*args_);
844 EXTENSION_FUNCTION_VALIDATE(parameters.get());
846 scoped_refptr<UsbDeviceHandle> device_handle =
847 GetDeviceHandle(parameters->handle);
848 if (!device_handle.get()) {
849 return RespondNow(Error(kErrorNoConnection));
852 device_handle->ClaimInterface(
853 parameters->interface_number,
854 base::Bind(&UsbClaimInterfaceFunction::OnComplete, this));
855 return RespondLater();
858 void UsbClaimInterfaceFunction::OnComplete(bool success) {
859 if (success) {
860 Respond(NoArguments());
861 } else {
862 Respond(Error(kErrorCannotClaimInterface));
866 UsbReleaseInterfaceFunction::UsbReleaseInterfaceFunction() {
869 UsbReleaseInterfaceFunction::~UsbReleaseInterfaceFunction() {
872 ExtensionFunction::ResponseAction UsbReleaseInterfaceFunction::Run() {
873 scoped_ptr<extensions::core_api::usb::ReleaseInterface::Params> parameters =
874 ReleaseInterface::Params::Create(*args_);
875 EXTENSION_FUNCTION_VALIDATE(parameters.get());
877 scoped_refptr<UsbDeviceHandle> device_handle =
878 GetDeviceHandle(parameters->handle);
879 if (!device_handle.get()) {
880 return RespondNow(Error(kErrorNoConnection));
883 if (device_handle->ReleaseInterface(parameters->interface_number)) {
884 return RespondNow(NoArguments());
885 } else {
886 return RespondNow(Error(kErrorCannotReleaseInterface));
890 UsbSetInterfaceAlternateSettingFunction::
891 UsbSetInterfaceAlternateSettingFunction() {
894 UsbSetInterfaceAlternateSettingFunction::
895 ~UsbSetInterfaceAlternateSettingFunction() {
898 ExtensionFunction::ResponseAction
899 UsbSetInterfaceAlternateSettingFunction::Run() {
900 scoped_ptr<extensions::core_api::usb::SetInterfaceAlternateSetting::Params>
901 parameters = SetInterfaceAlternateSetting::Params::Create(*args_);
902 EXTENSION_FUNCTION_VALIDATE(parameters.get());
904 scoped_refptr<UsbDeviceHandle> device_handle =
905 GetDeviceHandle(parameters->handle);
906 if (!device_handle.get()) {
907 return RespondNow(Error(kErrorNoConnection));
910 device_handle->SetInterfaceAlternateSetting(
911 parameters->interface_number, parameters->alternate_setting,
912 base::Bind(&UsbSetInterfaceAlternateSettingFunction::OnComplete, this));
913 return RespondLater();
916 void UsbSetInterfaceAlternateSettingFunction::OnComplete(bool success) {
917 if (success) {
918 Respond(NoArguments());
919 } else {
920 Respond(Error(kErrorCannotSetInterfaceAlternateSetting));
924 UsbControlTransferFunction::UsbControlTransferFunction() {
927 UsbControlTransferFunction::~UsbControlTransferFunction() {
930 ExtensionFunction::ResponseAction UsbControlTransferFunction::Run() {
931 scoped_ptr<extensions::core_api::usb::ControlTransfer::Params> parameters =
932 ControlTransfer::Params::Create(*args_);
933 EXTENSION_FUNCTION_VALIDATE(parameters.get());
935 scoped_refptr<UsbDeviceHandle> device_handle =
936 GetDeviceHandle(parameters->handle);
937 if (!device_handle.get()) {
938 return RespondNow(Error(kErrorNoConnection));
941 const ControlTransferInfo& transfer = parameters->transfer_info;
942 UsbEndpointDirection direction = device::USB_DIRECTION_INBOUND;
943 UsbDeviceHandle::TransferRequestType request_type;
944 UsbDeviceHandle::TransferRecipient recipient;
945 size_t size = 0;
947 if (!ConvertDirectionFromApi(transfer.direction, &direction)) {
948 return RespondNow(Error(kErrorConvertDirection));
951 if (!ConvertRequestTypeFromApi(transfer.request_type, &request_type)) {
952 return RespondNow(Error(kErrorConvertRequestType));
955 if (!ConvertRecipientFromApi(transfer.recipient, &recipient)) {
956 return RespondNow(Error(kErrorConvertRecipient));
959 if (!GetTransferSize(transfer, &size)) {
960 return RespondNow(Error(kErrorInvalidTransferLength));
963 scoped_refptr<net::IOBuffer> buffer =
964 CreateBufferForTransfer(transfer, direction, size);
965 if (!buffer.get()) {
966 return RespondNow(Error(kErrorMalformedParameters));
969 int timeout = transfer.timeout ? *transfer.timeout : 0;
970 if (timeout < 0) {
971 return RespondNow(Error(kErrorInvalidTimeout));
974 device_handle->ControlTransfer(
975 direction, request_type, recipient, transfer.request, transfer.value,
976 transfer.index, buffer.get(), size, timeout,
977 base::Bind(&UsbControlTransferFunction::OnCompleted, this));
978 return RespondLater();
981 UsbBulkTransferFunction::UsbBulkTransferFunction() {
984 UsbBulkTransferFunction::~UsbBulkTransferFunction() {
987 ExtensionFunction::ResponseAction UsbBulkTransferFunction::Run() {
988 scoped_ptr<extensions::core_api::usb::BulkTransfer::Params> parameters =
989 BulkTransfer::Params::Create(*args_);
990 EXTENSION_FUNCTION_VALIDATE(parameters.get());
992 scoped_refptr<UsbDeviceHandle> device_handle =
993 GetDeviceHandle(parameters->handle);
994 if (!device_handle.get()) {
995 return RespondNow(Error(kErrorNoConnection));
998 const GenericTransferInfo& transfer = parameters->transfer_info;
999 UsbEndpointDirection direction = device::USB_DIRECTION_INBOUND;
1000 size_t size = 0;
1002 if (!ConvertDirectionFromApi(transfer.direction, &direction)) {
1003 return RespondNow(Error(kErrorConvertDirection));
1006 if (!GetTransferSize(transfer, &size)) {
1007 return RespondNow(Error(kErrorInvalidTransferLength));
1010 scoped_refptr<net::IOBuffer> buffer =
1011 CreateBufferForTransfer(transfer, direction, size);
1012 if (!buffer.get()) {
1013 return RespondNow(Error(kErrorMalformedParameters));
1016 int timeout = transfer.timeout ? *transfer.timeout : 0;
1017 if (timeout < 0) {
1018 return RespondNow(Error(kErrorInvalidTimeout));
1021 device_handle->BulkTransfer(
1022 direction, transfer.endpoint, buffer.get(), size, timeout,
1023 base::Bind(&UsbBulkTransferFunction::OnCompleted, this));
1024 return RespondLater();
1027 UsbInterruptTransferFunction::UsbInterruptTransferFunction() {
1030 UsbInterruptTransferFunction::~UsbInterruptTransferFunction() {
1033 ExtensionFunction::ResponseAction UsbInterruptTransferFunction::Run() {
1034 scoped_ptr<extensions::core_api::usb::InterruptTransfer::Params> parameters =
1035 InterruptTransfer::Params::Create(*args_);
1036 EXTENSION_FUNCTION_VALIDATE(parameters.get());
1038 scoped_refptr<UsbDeviceHandle> device_handle =
1039 GetDeviceHandle(parameters->handle);
1040 if (!device_handle.get()) {
1041 return RespondNow(Error(kErrorNoConnection));
1044 const GenericTransferInfo& transfer = parameters->transfer_info;
1045 UsbEndpointDirection direction = device::USB_DIRECTION_INBOUND;
1046 size_t size = 0;
1048 if (!ConvertDirectionFromApi(transfer.direction, &direction)) {
1049 return RespondNow(Error(kErrorConvertDirection));
1052 if (!GetTransferSize(transfer, &size)) {
1053 return RespondNow(Error(kErrorInvalidTransferLength));
1056 scoped_refptr<net::IOBuffer> buffer =
1057 CreateBufferForTransfer(transfer, direction, size);
1058 if (!buffer.get()) {
1059 return RespondNow(Error(kErrorMalformedParameters));
1062 int timeout = transfer.timeout ? *transfer.timeout : 0;
1063 if (timeout < 0) {
1064 return RespondNow(Error(kErrorInvalidTimeout));
1067 device_handle->InterruptTransfer(
1068 direction, transfer.endpoint, buffer.get(), size, timeout,
1069 base::Bind(&UsbInterruptTransferFunction::OnCompleted, this));
1070 return RespondLater();
1073 UsbIsochronousTransferFunction::UsbIsochronousTransferFunction() {
1076 UsbIsochronousTransferFunction::~UsbIsochronousTransferFunction() {
1079 ExtensionFunction::ResponseAction UsbIsochronousTransferFunction::Run() {
1080 scoped_ptr<extensions::core_api::usb::IsochronousTransfer::Params>
1081 parameters = IsochronousTransfer::Params::Create(*args_);
1082 EXTENSION_FUNCTION_VALIDATE(parameters.get());
1084 scoped_refptr<UsbDeviceHandle> device_handle =
1085 GetDeviceHandle(parameters->handle);
1086 if (!device_handle.get()) {
1087 return RespondNow(Error(kErrorNoConnection));
1090 const IsochronousTransferInfo& transfer = parameters->transfer_info;
1091 const GenericTransferInfo& generic_transfer = transfer.transfer_info;
1092 size_t size = 0;
1093 UsbEndpointDirection direction = device::USB_DIRECTION_INBOUND;
1095 if (!ConvertDirectionFromApi(generic_transfer.direction, &direction)) {
1096 return RespondNow(Error(kErrorConvertDirection));
1099 if (!GetTransferSize(generic_transfer, &size)) {
1100 return RespondNow(Error(kErrorInvalidTransferLength));
1103 if (transfer.packets < 0 || transfer.packets >= kMaxPackets) {
1104 return RespondNow(Error(kErrorInvalidNumberOfPackets));
1107 unsigned int packets = transfer.packets;
1108 if (transfer.packet_length < 0 ||
1109 transfer.packet_length >= kMaxPacketLength) {
1110 return RespondNow(Error(kErrorInvalidPacketLength));
1113 unsigned int packet_length = transfer.packet_length;
1114 const uint64 total_length = packets * packet_length;
1115 if (packets > size || total_length > size) {
1116 return RespondNow(Error(kErrorTransferLength));
1119 scoped_refptr<net::IOBuffer> buffer =
1120 CreateBufferForTransfer(generic_transfer, direction, size);
1121 if (!buffer.get()) {
1122 return RespondNow(Error(kErrorMalformedParameters));
1125 int timeout = generic_transfer.timeout ? *generic_transfer.timeout : 0;
1126 if (timeout < 0) {
1127 return RespondNow(Error(kErrorInvalidTimeout));
1130 device_handle->IsochronousTransfer(
1131 direction, generic_transfer.endpoint, buffer.get(), size, packets,
1132 packet_length, timeout,
1133 base::Bind(&UsbIsochronousTransferFunction::OnCompleted, this));
1134 return RespondLater();
1137 UsbResetDeviceFunction::UsbResetDeviceFunction() {
1140 UsbResetDeviceFunction::~UsbResetDeviceFunction() {
1143 ExtensionFunction::ResponseAction UsbResetDeviceFunction::Run() {
1144 parameters_ = ResetDevice::Params::Create(*args_);
1145 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
1147 scoped_refptr<UsbDeviceHandle> device_handle =
1148 GetDeviceHandle(parameters_->handle);
1149 if (!device_handle.get()) {
1150 return RespondNow(Error(kErrorNoConnection));
1153 device_handle->ResetDevice(
1154 base::Bind(&UsbResetDeviceFunction::OnComplete, this));
1155 return RespondLater();
1158 void UsbResetDeviceFunction::OnComplete(bool success) {
1159 if (success) {
1160 Respond(OneArgument(new base::FundamentalValue(true)));
1161 } else {
1162 scoped_refptr<UsbDeviceHandle> device_handle =
1163 GetDeviceHandle(parameters_->handle);
1164 if (device_handle.get()) {
1165 device_handle->Close();
1167 ReleaseDeviceHandle(parameters_->handle);
1169 scoped_ptr<base::ListValue> error_args(new base::ListValue());
1170 error_args->AppendBoolean(false);
1171 // Returning arguments with an error is wrong but we're stuck with it.
1172 Respond(ErrorWithArguments(error_args.Pass(), kErrorResetDevice));
1176 } // namespace extensions