Remove linux_chromium_gn_dbg from the chromium CQ.
[chromium-blink-merge.git] / extensions / browser / api / usb / usb_api.cc
blob697986848f61b7d427b3ccce18dbb858c3819a81
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::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 GetConfigurations = usb::GetConfigurations;
33 namespace GetDevices = usb::GetDevices;
34 namespace GetUserSelectedDevices = usb::GetUserSelectedDevices;
35 namespace InterruptTransfer = usb::InterruptTransfer;
36 namespace IsochronousTransfer = usb::IsochronousTransfer;
37 namespace SetConfiguration = usb::SetConfiguration;
38 namespace GetConfiguration = usb::GetConfiguration;
39 namespace ListInterfaces = usb::ListInterfaces;
40 namespace OpenDevice = usb::OpenDevice;
41 namespace ReleaseInterface = usb::ReleaseInterface;
42 namespace RequestAccess = usb::RequestAccess;
43 namespace ResetDevice = usb::ResetDevice;
44 namespace SetInterfaceAlternateSetting = usb::SetInterfaceAlternateSetting;
46 using content::BrowserThread;
47 using device::UsbConfigDescriptor;
48 using device::UsbDevice;
49 using device::UsbDeviceFilter;
50 using device::UsbDeviceHandle;
51 using device::UsbEndpointDescriptor;
52 using device::UsbEndpointDirection;
53 using device::UsbInterfaceDescriptor;
54 using device::UsbService;
55 using device::UsbSynchronizationType;
56 using device::UsbTransferStatus;
57 using device::UsbTransferType;
58 using device::UsbUsageType;
59 using std::string;
60 using std::vector;
61 using usb::ConfigDescriptor;
62 using usb::ControlTransferInfo;
63 using usb::ConnectionHandle;
64 using usb::Device;
65 using usb::Direction;
66 using usb::EndpointDescriptor;
67 using usb::GenericTransferInfo;
68 using usb::InterfaceDescriptor;
69 using usb::IsochronousTransferInfo;
70 using usb::Recipient;
71 using usb::RequestType;
72 using usb::SynchronizationType;
73 using usb::TransferType;
74 using usb::UsageType;
76 namespace extensions {
78 namespace {
80 const char kDataKey[] = "data";
81 const char kResultCodeKey[] = "resultCode";
83 const char kErrorInitService[] = "Failed to initialize USB service.";
85 const char kErrorOpen[] = "Failed to open device.";
86 const char kErrorCancelled[] = "Transfer was cancelled.";
87 const char kErrorDisconnect[] = "Device disconnected.";
88 const char kErrorGeneric[] = "Transfer failed.";
89 const char kErrorNotSupported[] = "Not supported on this platform.";
90 const char kErrorNotConfigured[] = "The device is not in a configured state.";
91 const char kErrorOverflow[] = "Inbound transfer overflow.";
92 const char kErrorStalled[] = "Transfer stalled.";
93 const char kErrorTimeout[] = "Transfer timed out.";
94 const char kErrorTransferLength[] = "Transfer length is insufficient.";
95 const char kErrorCannotSetConfiguration[] =
96 "Error setting device configuration.";
97 const char kErrorCannotClaimInterface[] = "Error claiming interface.";
98 const char kErrorCannotReleaseInterface[] = "Error releasing interface.";
99 const char kErrorCannotSetInterfaceAlternateSetting[] =
100 "Error setting alternate interface setting.";
101 const char kErrorConvertDirection[] = "Invalid transfer direction.";
102 const char kErrorConvertRecipient[] = "Invalid transfer recipient.";
103 const char kErrorConvertRequestType[] = "Invalid request type.";
104 const char kErrorMalformedParameters[] = "Error parsing parameters.";
105 const char kErrorNoConnection[] = "No such connection.";
106 const char kErrorNoDevice[] = "No such device.";
107 const char kErrorPermissionDenied[] = "Permission to access device was denied";
108 const char kErrorInvalidTransferLength[] =
109 "Transfer length must be a positive number less than 104,857,600.";
110 const char kErrorInvalidNumberOfPackets[] =
111 "Number of packets must be a positive number less than 4,194,304.";
112 const char kErrorInvalidPacketLength[] =
113 "Packet length must be a positive number less than 65,536.";
114 const char kErrorInvalidTimeout[] =
115 "Transfer timeout must be greater than or equal to 0.";
116 const char kErrorResetDevice[] =
117 "Error resetting the device. The device has been closed.";
119 const size_t kMaxTransferLength = 100 * 1024 * 1024;
120 const int kMaxPackets = 4 * 1024 * 1024;
121 const int kMaxPacketLength = 64 * 1024;
123 bool ConvertDirectionFromApi(const Direction& input,
124 UsbEndpointDirection* output) {
125 switch (input) {
126 case usb::DIRECTION_IN:
127 *output = device::USB_DIRECTION_INBOUND;
128 return true;
129 case usb::DIRECTION_OUT:
130 *output = device::USB_DIRECTION_OUTBOUND;
131 return true;
132 default:
133 NOTREACHED();
134 return false;
138 bool ConvertRequestTypeFromApi(const RequestType& input,
139 UsbDeviceHandle::TransferRequestType* output) {
140 switch (input) {
141 case usb::REQUEST_TYPE_STANDARD:
142 *output = UsbDeviceHandle::STANDARD;
143 return true;
144 case usb::REQUEST_TYPE_CLASS:
145 *output = UsbDeviceHandle::CLASS;
146 return true;
147 case usb::REQUEST_TYPE_VENDOR:
148 *output = UsbDeviceHandle::VENDOR;
149 return true;
150 case usb::REQUEST_TYPE_RESERVED:
151 *output = UsbDeviceHandle::RESERVED;
152 return true;
153 default:
154 NOTREACHED();
155 return false;
159 bool ConvertRecipientFromApi(const Recipient& input,
160 UsbDeviceHandle::TransferRecipient* output) {
161 switch (input) {
162 case usb::RECIPIENT_DEVICE:
163 *output = UsbDeviceHandle::DEVICE;
164 return true;
165 case usb::RECIPIENT_INTERFACE:
166 *output = UsbDeviceHandle::INTERFACE;
167 return true;
168 case usb::RECIPIENT_ENDPOINT:
169 *output = UsbDeviceHandle::ENDPOINT;
170 return true;
171 case usb::RECIPIENT_OTHER:
172 *output = UsbDeviceHandle::OTHER;
173 return true;
174 default:
175 NOTREACHED();
176 return false;
180 template <class T>
181 bool GetTransferSize(const T& input, size_t* output) {
182 if (input.direction == usb::DIRECTION_IN) {
183 const int* length = input.length.get();
184 if (length && *length >= 0 &&
185 static_cast<size_t>(*length) < kMaxTransferLength) {
186 *output = *length;
187 return true;
189 } else if (input.direction == usb::DIRECTION_OUT) {
190 if (input.data.get()) {
191 *output = input.data->size();
192 return true;
195 return false;
198 template <class T>
199 scoped_refptr<net::IOBuffer> CreateBufferForTransfer(
200 const T& input,
201 UsbEndpointDirection direction,
202 size_t size) {
203 if (size >= kMaxTransferLength)
204 return NULL;
206 // Allocate a |size|-bytes buffer, or a one-byte buffer if |size| is 0. This
207 // is due to an impedance mismatch between IOBuffer and URBs. An IOBuffer
208 // cannot represent a zero-length buffer, while an URB can.
209 scoped_refptr<net::IOBuffer> buffer =
210 new net::IOBuffer(std::max(static_cast<size_t>(1), size));
212 if (direction == device::USB_DIRECTION_INBOUND) {
213 return buffer;
214 } else if (direction == device::USB_DIRECTION_OUTBOUND) {
215 if (input.data.get() && size <= input.data->size()) {
216 memcpy(buffer->data(), input.data->data(), size);
217 return buffer;
220 NOTREACHED();
221 return NULL;
224 const char* ConvertTransferStatusToApi(const UsbTransferStatus status) {
225 switch (status) {
226 case device::USB_TRANSFER_COMPLETED:
227 return "";
228 case device::USB_TRANSFER_ERROR:
229 return kErrorGeneric;
230 case device::USB_TRANSFER_TIMEOUT:
231 return kErrorTimeout;
232 case device::USB_TRANSFER_CANCELLED:
233 return kErrorCancelled;
234 case device::USB_TRANSFER_STALLED:
235 return kErrorStalled;
236 case device::USB_TRANSFER_DISCONNECT:
237 return kErrorDisconnect;
238 case device::USB_TRANSFER_OVERFLOW:
239 return kErrorOverflow;
240 case device::USB_TRANSFER_LENGTH_SHORT:
241 return kErrorTransferLength;
242 default:
243 NOTREACHED();
244 return "";
248 base::Value* PopulateConnectionHandle(int handle,
249 int vendor_id,
250 int product_id) {
251 ConnectionHandle result;
252 result.handle = handle;
253 result.vendor_id = vendor_id;
254 result.product_id = product_id;
255 return result.ToValue().release();
258 TransferType ConvertTransferTypeToApi(const UsbTransferType& input) {
259 switch (input) {
260 case device::USB_TRANSFER_CONTROL:
261 return usb::TRANSFER_TYPE_CONTROL;
262 case device::USB_TRANSFER_INTERRUPT:
263 return usb::TRANSFER_TYPE_INTERRUPT;
264 case device::USB_TRANSFER_ISOCHRONOUS:
265 return usb::TRANSFER_TYPE_ISOCHRONOUS;
266 case device::USB_TRANSFER_BULK:
267 return usb::TRANSFER_TYPE_BULK;
268 default:
269 NOTREACHED();
270 return usb::TRANSFER_TYPE_NONE;
274 Direction ConvertDirectionToApi(const UsbEndpointDirection& input) {
275 switch (input) {
276 case device::USB_DIRECTION_INBOUND:
277 return usb::DIRECTION_IN;
278 case device::USB_DIRECTION_OUTBOUND:
279 return usb::DIRECTION_OUT;
280 default:
281 NOTREACHED();
282 return usb::DIRECTION_NONE;
286 SynchronizationType ConvertSynchronizationTypeToApi(
287 const UsbSynchronizationType& input) {
288 switch (input) {
289 case device::USB_SYNCHRONIZATION_NONE:
290 return usb::SYNCHRONIZATION_TYPE_NONE;
291 case device::USB_SYNCHRONIZATION_ASYNCHRONOUS:
292 return usb::SYNCHRONIZATION_TYPE_ASYNCHRONOUS;
293 case device::USB_SYNCHRONIZATION_ADAPTIVE:
294 return usb::SYNCHRONIZATION_TYPE_ADAPTIVE;
295 case device::USB_SYNCHRONIZATION_SYNCHRONOUS:
296 return usb::SYNCHRONIZATION_TYPE_SYNCHRONOUS;
297 default:
298 NOTREACHED();
299 return usb::SYNCHRONIZATION_TYPE_NONE;
303 UsageType ConvertUsageTypeToApi(const UsbUsageType& input) {
304 switch (input) {
305 case device::USB_USAGE_DATA:
306 return usb::USAGE_TYPE_DATA;
307 case device::USB_USAGE_FEEDBACK:
308 return usb::USAGE_TYPE_FEEDBACK;
309 case device::USB_USAGE_EXPLICIT_FEEDBACK:
310 return usb::USAGE_TYPE_EXPLICITFEEDBACK;
311 default:
312 NOTREACHED();
313 return usb::USAGE_TYPE_NONE;
317 void ConvertEndpointDescriptor(const UsbEndpointDescriptor& input,
318 EndpointDescriptor* output) {
319 output->address = input.address;
320 output->type = ConvertTransferTypeToApi(input.transfer_type);
321 output->direction = ConvertDirectionToApi(input.direction);
322 output->maximum_packet_size = input.maximum_packet_size;
323 output->synchronization =
324 ConvertSynchronizationTypeToApi(input.synchronization_type);
325 output->usage = ConvertUsageTypeToApi(input.usage_type);
326 output->polling_interval.reset(new int(input.polling_interval));
327 output->extra_data.assign(input.extra_data.begin(), input.extra_data.end());
330 void ConvertInterfaceDescriptor(const UsbInterfaceDescriptor& input,
331 InterfaceDescriptor* output) {
332 output->interface_number = input.interface_number;
333 output->alternate_setting = input.alternate_setting;
334 output->interface_class = input.interface_class;
335 output->interface_subclass = input.interface_subclass;
336 output->interface_protocol = input.interface_protocol;
337 for (const UsbEndpointDescriptor& input_endpoint : input.endpoints) {
338 linked_ptr<EndpointDescriptor> endpoint(new EndpointDescriptor);
339 ConvertEndpointDescriptor(input_endpoint, endpoint.get());
340 output->endpoints.push_back(endpoint);
342 output->extra_data.assign(input.extra_data.begin(), input.extra_data.end());
345 void ConvertConfigDescriptor(const UsbConfigDescriptor& input,
346 ConfigDescriptor* output) {
347 output->configuration_value = input.configuration_value;
348 output->self_powered = input.self_powered;
349 output->remote_wakeup = input.remote_wakeup;
350 output->max_power = input.maximum_power;
351 for (const UsbInterfaceDescriptor& input_interface : input.interfaces) {
352 linked_ptr<InterfaceDescriptor> interface(new InterfaceDescriptor);
353 ConvertInterfaceDescriptor(input_interface, interface.get());
354 output->interfaces.push_back(interface);
356 output->extra_data.assign(input.extra_data.begin(), input.extra_data.end());
359 void ConvertDeviceFilter(const usb::DeviceFilter& input,
360 UsbDeviceFilter* output) {
361 if (input.vendor_id) {
362 output->SetVendorId(*input.vendor_id);
364 if (input.product_id) {
365 output->SetProductId(*input.product_id);
367 if (input.interface_class) {
368 output->SetInterfaceClass(*input.interface_class);
370 if (input.interface_subclass) {
371 output->SetInterfaceSubclass(*input.interface_subclass);
373 if (input.interface_protocol) {
374 output->SetInterfaceProtocol(*input.interface_protocol);
378 } // namespace
380 UsbPermissionCheckingFunction::UsbPermissionCheckingFunction()
381 : device_permissions_manager_(nullptr) {
384 UsbPermissionCheckingFunction::~UsbPermissionCheckingFunction() {
387 bool UsbPermissionCheckingFunction::HasDevicePermission(
388 scoped_refptr<UsbDevice> device) {
389 if (!device_permissions_manager_) {
390 device_permissions_manager_ =
391 DevicePermissionsManager::Get(browser_context());
394 DevicePermissions* device_permissions =
395 device_permissions_manager_->GetForExtension(extension_id());
396 DCHECK(device_permissions);
398 permission_entry_ = device_permissions->FindUsbDeviceEntry(device);
399 if (permission_entry_.get()) {
400 return true;
403 UsbDevicePermission::CheckParam param(
404 device->vendor_id(),
405 device->product_id(),
406 UsbDevicePermissionData::UNSPECIFIED_INTERFACE);
407 if (extension()->permissions_data()->CheckAPIPermissionWithParam(
408 APIPermission::kUsbDevice, &param)) {
409 return true;
412 return false;
415 void UsbPermissionCheckingFunction::RecordDeviceLastUsed() {
416 if (permission_entry_.get()) {
417 device_permissions_manager_->UpdateLastUsed(extension_id(),
418 permission_entry_);
422 UsbConnectionFunction::UsbConnectionFunction() {
425 UsbConnectionFunction::~UsbConnectionFunction() {
428 scoped_refptr<device::UsbDeviceHandle> UsbConnectionFunction::GetDeviceHandle(
429 const extensions::api::usb::ConnectionHandle& handle) {
430 ApiResourceManager<UsbDeviceResource>* manager =
431 ApiResourceManager<UsbDeviceResource>::Get(browser_context());
432 if (!manager) {
433 return nullptr;
436 UsbDeviceResource* resource = manager->Get(extension_id(), handle.handle);
437 if (!resource) {
438 return nullptr;
441 return resource->device();
444 void UsbConnectionFunction::ReleaseDeviceHandle(
445 const extensions::api::usb::ConnectionHandle& handle) {
446 ApiResourceManager<UsbDeviceResource>* manager =
447 ApiResourceManager<UsbDeviceResource>::Get(browser_context());
448 manager->Remove(extension_id(), handle.handle);
451 UsbTransferFunction::UsbTransferFunction() {
454 UsbTransferFunction::~UsbTransferFunction() {
457 void UsbTransferFunction::OnCompleted(UsbTransferStatus status,
458 scoped_refptr<net::IOBuffer> data,
459 size_t length) {
460 scoped_ptr<base::DictionaryValue> transfer_info(new base::DictionaryValue());
461 transfer_info->SetInteger(kResultCodeKey, status);
462 transfer_info->Set(kDataKey, base::BinaryValue::CreateWithCopiedBuffer(
463 data->data(), length));
465 if (status == device::USB_TRANSFER_COMPLETED) {
466 Respond(OneArgument(transfer_info.Pass()));
467 } else {
468 scoped_ptr<base::ListValue> error_args(new base::ListValue());
469 error_args->Append(transfer_info.Pass());
470 // Returning arguments with an error is wrong but we're stuck with it.
471 Respond(ErrorWithArguments(error_args.Pass(),
472 ConvertTransferStatusToApi(status)));
476 UsbFindDevicesFunction::UsbFindDevicesFunction() {
479 UsbFindDevicesFunction::~UsbFindDevicesFunction() {
482 ExtensionFunction::ResponseAction UsbFindDevicesFunction::Run() {
483 scoped_ptr<extensions::api::usb::FindDevices::Params> parameters =
484 FindDevices::Params::Create(*args_);
485 EXTENSION_FUNCTION_VALIDATE(parameters.get());
487 vendor_id_ = parameters->options.vendor_id;
488 product_id_ = parameters->options.product_id;
489 int interface_id = parameters->options.interface_id.get()
490 ? *parameters->options.interface_id.get()
491 : UsbDevicePermissionData::ANY_INTERFACE;
492 UsbDevicePermission::CheckParam param(vendor_id_, product_id_, interface_id);
493 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
494 APIPermission::kUsbDevice, &param)) {
495 return RespondNow(Error(kErrorPermissionDenied));
498 UsbService* service = device::DeviceClient::Get()->GetUsbService();
499 if (!service) {
500 return RespondNow(Error(kErrorInitService));
503 service->GetDevices(
504 base::Bind(&UsbFindDevicesFunction::OnGetDevicesComplete, this));
505 return RespondLater();
508 void UsbFindDevicesFunction::OnGetDevicesComplete(
509 const std::vector<scoped_refptr<UsbDevice>>& devices) {
510 result_.reset(new base::ListValue());
511 barrier_ = base::BarrierClosure(
512 devices.size(), base::Bind(&UsbFindDevicesFunction::OpenComplete, this));
514 for (const scoped_refptr<UsbDevice>& device : devices) {
515 if (device->vendor_id() != vendor_id_ ||
516 device->product_id() != product_id_) {
517 barrier_.Run();
518 } else {
519 device->Open(base::Bind(&UsbFindDevicesFunction::OnDeviceOpened, this));
524 void UsbFindDevicesFunction::OnDeviceOpened(
525 scoped_refptr<UsbDeviceHandle> device_handle) {
526 if (device_handle.get()) {
527 ApiResourceManager<UsbDeviceResource>* manager =
528 ApiResourceManager<UsbDeviceResource>::Get(browser_context());
529 UsbDeviceResource* resource =
530 new UsbDeviceResource(extension_id(), device_handle);
531 scoped_refptr<UsbDevice> device = device_handle->GetDevice();
532 result_->Append(PopulateConnectionHandle(
533 manager->Add(resource), device->vendor_id(), device->product_id()));
535 barrier_.Run();
538 void UsbFindDevicesFunction::OpenComplete() {
539 Respond(OneArgument(result_.Pass()));
542 UsbGetDevicesFunction::UsbGetDevicesFunction() {
545 UsbGetDevicesFunction::~UsbGetDevicesFunction() {
548 ExtensionFunction::ResponseAction UsbGetDevicesFunction::Run() {
549 scoped_ptr<extensions::api::usb::GetDevices::Params> parameters =
550 GetDevices::Params::Create(*args_);
551 EXTENSION_FUNCTION_VALIDATE(parameters.get());
553 if (parameters->options.filters) {
554 filters_.resize(parameters->options.filters->size());
555 for (size_t i = 0; i < parameters->options.filters->size(); ++i) {
556 ConvertDeviceFilter(*parameters->options.filters->at(i).get(),
557 &filters_[i]);
560 if (parameters->options.vendor_id) {
561 filters_.resize(filters_.size() + 1);
562 filters_.back().SetVendorId(*parameters->options.vendor_id);
563 if (parameters->options.product_id) {
564 filters_.back().SetProductId(*parameters->options.product_id);
568 UsbService* service = device::DeviceClient::Get()->GetUsbService();
569 if (!service) {
570 return RespondNow(Error(kErrorInitService));
573 service->GetDevices(
574 base::Bind(&UsbGetDevicesFunction::OnGetDevicesComplete, this));
575 return RespondLater();
578 void UsbGetDevicesFunction::OnGetDevicesComplete(
579 const std::vector<scoped_refptr<UsbDevice>>& devices) {
580 scoped_ptr<base::ListValue> result(new base::ListValue());
581 UsbGuidMap* guid_map = UsbGuidMap::Get(browser_context());
582 for (const scoped_refptr<UsbDevice>& device : devices) {
583 if ((filters_.empty() || UsbDeviceFilter::MatchesAny(device, filters_)) &&
584 HasDevicePermission(device)) {
585 Device api_device;
586 guid_map->GetApiDevice(device, &api_device);
587 result->Append(api_device.ToValue());
591 Respond(OneArgument(result.Pass()));
594 UsbGetUserSelectedDevicesFunction::UsbGetUserSelectedDevicesFunction() {
597 UsbGetUserSelectedDevicesFunction::~UsbGetUserSelectedDevicesFunction() {
600 ExtensionFunction::ResponseAction UsbGetUserSelectedDevicesFunction::Run() {
601 scoped_ptr<extensions::api::usb::GetUserSelectedDevices::Params> parameters =
602 GetUserSelectedDevices::Params::Create(*args_);
603 EXTENSION_FUNCTION_VALIDATE(parameters.get());
605 if (!user_gesture()) {
606 return RespondNow(OneArgument(new base::ListValue()));
609 bool multiple = false;
610 if (parameters->options.multiple) {
611 multiple = *parameters->options.multiple;
614 std::vector<UsbDeviceFilter> filters;
615 if (parameters->options.filters) {
616 filters.resize(parameters->options.filters->size());
617 for (size_t i = 0; i < parameters->options.filters->size(); ++i) {
618 ConvertDeviceFilter(*parameters->options.filters->at(i).get(),
619 &filters[i]);
623 prompt_ = ExtensionsAPIClient::Get()->CreateDevicePermissionsPrompt(
624 GetAssociatedWebContents());
625 if (!prompt_) {
626 return RespondNow(Error(kErrorNotSupported));
629 prompt_->AskForUsbDevices(
630 extension(), browser_context(), multiple, filters,
631 base::Bind(&UsbGetUserSelectedDevicesFunction::OnDevicesChosen, this));
632 return RespondLater();
635 void UsbGetUserSelectedDevicesFunction::OnDevicesChosen(
636 const std::vector<scoped_refptr<UsbDevice>>& devices) {
637 scoped_ptr<base::ListValue> result(new base::ListValue());
638 UsbGuidMap* guid_map = UsbGuidMap::Get(browser_context());
639 for (const auto& device : devices) {
640 Device api_device;
641 guid_map->GetApiDevice(device, &api_device);
642 result->Append(api_device.ToValue());
645 Respond(OneArgument(result.Pass()));
648 UsbGetConfigurationsFunction::UsbGetConfigurationsFunction() {}
650 UsbGetConfigurationsFunction::~UsbGetConfigurationsFunction() {}
652 ExtensionFunction::ResponseAction UsbGetConfigurationsFunction::Run() {
653 scoped_ptr<extensions::api::usb::GetConfigurations::Params> parameters =
654 GetConfigurations::Params::Create(*args_);
655 EXTENSION_FUNCTION_VALIDATE(parameters.get());
657 UsbService* service = device::DeviceClient::Get()->GetUsbService();
658 if (!service) {
659 return RespondNow(Error(kErrorInitService));
662 std::string guid;
663 if (!UsbGuidMap::Get(browser_context())
664 ->GetGuidFromId(parameters->device.device, &guid)) {
665 return RespondNow(Error(kErrorNoDevice));
668 scoped_refptr<UsbDevice> device = service->GetDevice(guid);
669 if (!device.get()) {
670 return RespondNow(Error(kErrorNoDevice));
673 if (!HasDevicePermission(device)) {
674 // This function must act as if there is no such device. Otherwise it can be
675 // used to fingerprint unauthorized devices.
676 return RespondNow(Error(kErrorNoDevice));
679 scoped_ptr<base::ListValue> configs(new base::ListValue());
680 const UsbConfigDescriptor* active_config = device->GetActiveConfiguration();
681 for (const UsbConfigDescriptor& config : device->configurations()) {
682 ConfigDescriptor api_config;
683 ConvertConfigDescriptor(config, &api_config);
684 if (active_config &&
685 config.configuration_value == active_config->configuration_value) {
686 api_config.active = true;
688 configs->Append(api_config.ToValue());
690 return RespondNow(OneArgument(configs.Pass()));
693 UsbRequestAccessFunction::UsbRequestAccessFunction() {
696 UsbRequestAccessFunction::~UsbRequestAccessFunction() {
699 ExtensionFunction::ResponseAction UsbRequestAccessFunction::Run() {
700 scoped_ptr<extensions::api::usb::RequestAccess::Params> parameters =
701 RequestAccess::Params::Create(*args_);
702 EXTENSION_FUNCTION_VALIDATE(parameters.get());
703 return RespondNow(OneArgument(new base::FundamentalValue(true)));
706 UsbOpenDeviceFunction::UsbOpenDeviceFunction() {
709 UsbOpenDeviceFunction::~UsbOpenDeviceFunction() {
712 ExtensionFunction::ResponseAction UsbOpenDeviceFunction::Run() {
713 scoped_ptr<extensions::api::usb::OpenDevice::Params> parameters =
714 OpenDevice::Params::Create(*args_);
715 EXTENSION_FUNCTION_VALIDATE(parameters.get());
717 UsbService* service = device::DeviceClient::Get()->GetUsbService();
718 if (!service) {
719 return RespondNow(Error(kErrorInitService));
722 std::string guid;
723 if (!UsbGuidMap::Get(browser_context())
724 ->GetGuidFromId(parameters->device.device, &guid)) {
725 return RespondNow(Error(kErrorNoDevice));
728 scoped_refptr<UsbDevice> device = service->GetDevice(guid);
729 if (!device.get()) {
730 return RespondNow(Error(kErrorNoDevice));
733 if (!HasDevicePermission(device)) {
734 // This function must act as if there is no such device. Otherwise it can be
735 // used to fingerprint unauthorized devices.
736 return RespondNow(Error(kErrorNoDevice));
739 device->Open(base::Bind(&UsbOpenDeviceFunction::OnDeviceOpened, this));
740 return RespondLater();
743 void UsbOpenDeviceFunction::OnDeviceOpened(
744 scoped_refptr<UsbDeviceHandle> device_handle) {
745 if (!device_handle.get()) {
746 Respond(Error(kErrorOpen));
747 return;
750 RecordDeviceLastUsed();
752 ApiResourceManager<UsbDeviceResource>* manager =
753 ApiResourceManager<UsbDeviceResource>::Get(browser_context());
754 scoped_refptr<UsbDevice> device = device_handle->GetDevice();
755 Respond(OneArgument(PopulateConnectionHandle(
756 manager->Add(new UsbDeviceResource(extension_id(), device_handle)),
757 device->vendor_id(), device->product_id())));
760 UsbSetConfigurationFunction::UsbSetConfigurationFunction() {
763 UsbSetConfigurationFunction::~UsbSetConfigurationFunction() {
766 ExtensionFunction::ResponseAction UsbSetConfigurationFunction::Run() {
767 scoped_ptr<extensions::api::usb::SetConfiguration::Params> parameters =
768 SetConfiguration::Params::Create(*args_);
769 EXTENSION_FUNCTION_VALIDATE(parameters.get());
771 scoped_refptr<UsbDeviceHandle> device_handle =
772 GetDeviceHandle(parameters->handle);
773 if (!device_handle.get()) {
774 return RespondNow(Error(kErrorNoConnection));
777 device_handle->SetConfiguration(
778 parameters->configuration_value,
779 base::Bind(&UsbSetConfigurationFunction::OnComplete, this));
780 return RespondLater();
783 void UsbSetConfigurationFunction::OnComplete(bool success) {
784 if (success) {
785 Respond(NoArguments());
786 } else {
787 Respond(Error(kErrorCannotSetConfiguration));
791 UsbGetConfigurationFunction::UsbGetConfigurationFunction() {
794 UsbGetConfigurationFunction::~UsbGetConfigurationFunction() {
797 ExtensionFunction::ResponseAction UsbGetConfigurationFunction::Run() {
798 scoped_ptr<extensions::api::usb::GetConfiguration::Params> parameters =
799 GetConfiguration::Params::Create(*args_);
800 EXTENSION_FUNCTION_VALIDATE(parameters.get());
802 scoped_refptr<UsbDeviceHandle> device_handle =
803 GetDeviceHandle(parameters->handle);
804 if (!device_handle.get()) {
805 return RespondNow(Error(kErrorNoConnection));
808 const UsbConfigDescriptor* config_descriptor =
809 device_handle->GetDevice()->GetActiveConfiguration();
810 if (config_descriptor) {
811 ConfigDescriptor config;
812 ConvertConfigDescriptor(*config_descriptor, &config);
813 config.active = true;
814 return RespondNow(OneArgument(config.ToValue()));
815 } else {
816 return RespondNow(Error(kErrorNotConfigured));
820 UsbListInterfacesFunction::UsbListInterfacesFunction() {
823 UsbListInterfacesFunction::~UsbListInterfacesFunction() {
826 ExtensionFunction::ResponseAction UsbListInterfacesFunction::Run() {
827 scoped_ptr<extensions::api::usb::ListInterfaces::Params> parameters =
828 ListInterfaces::Params::Create(*args_);
829 EXTENSION_FUNCTION_VALIDATE(parameters.get());
831 scoped_refptr<UsbDeviceHandle> device_handle =
832 GetDeviceHandle(parameters->handle);
833 if (!device_handle.get()) {
834 return RespondNow(Error(kErrorNoConnection));
837 const UsbConfigDescriptor* config_descriptor =
838 device_handle->GetDevice()->GetActiveConfiguration();
839 if (config_descriptor) {
840 ConfigDescriptor config;
841 ConvertConfigDescriptor(*config_descriptor, &config);
843 scoped_ptr<base::ListValue> result(new base::ListValue);
844 for (size_t i = 0; i < config.interfaces.size(); ++i) {
845 result->Append(config.interfaces[i]->ToValue());
848 return RespondNow(OneArgument(result.Pass()));
849 } else {
850 return RespondNow(Error(kErrorNotConfigured));
854 UsbCloseDeviceFunction::UsbCloseDeviceFunction() {
857 UsbCloseDeviceFunction::~UsbCloseDeviceFunction() {
860 ExtensionFunction::ResponseAction UsbCloseDeviceFunction::Run() {
861 scoped_ptr<extensions::api::usb::CloseDevice::Params> parameters =
862 CloseDevice::Params::Create(*args_);
863 EXTENSION_FUNCTION_VALIDATE(parameters.get());
865 scoped_refptr<UsbDeviceHandle> device_handle =
866 GetDeviceHandle(parameters->handle);
867 if (!device_handle.get()) {
868 return RespondNow(Error(kErrorNoConnection));
871 // The device handle is closed when the resource is destroyed.
872 ReleaseDeviceHandle(parameters->handle);
873 return RespondNow(NoArguments());
876 UsbClaimInterfaceFunction::UsbClaimInterfaceFunction() {
879 UsbClaimInterfaceFunction::~UsbClaimInterfaceFunction() {
882 ExtensionFunction::ResponseAction UsbClaimInterfaceFunction::Run() {
883 scoped_ptr<extensions::api::usb::ClaimInterface::Params> parameters =
884 ClaimInterface::Params::Create(*args_);
885 EXTENSION_FUNCTION_VALIDATE(parameters.get());
887 scoped_refptr<UsbDeviceHandle> device_handle =
888 GetDeviceHandle(parameters->handle);
889 if (!device_handle.get()) {
890 return RespondNow(Error(kErrorNoConnection));
893 device_handle->ClaimInterface(
894 parameters->interface_number,
895 base::Bind(&UsbClaimInterfaceFunction::OnComplete, this));
896 return RespondLater();
899 void UsbClaimInterfaceFunction::OnComplete(bool success) {
900 if (success) {
901 Respond(NoArguments());
902 } else {
903 Respond(Error(kErrorCannotClaimInterface));
907 UsbReleaseInterfaceFunction::UsbReleaseInterfaceFunction() {
910 UsbReleaseInterfaceFunction::~UsbReleaseInterfaceFunction() {
913 ExtensionFunction::ResponseAction UsbReleaseInterfaceFunction::Run() {
914 scoped_ptr<extensions::api::usb::ReleaseInterface::Params> parameters =
915 ReleaseInterface::Params::Create(*args_);
916 EXTENSION_FUNCTION_VALIDATE(parameters.get());
918 scoped_refptr<UsbDeviceHandle> device_handle =
919 GetDeviceHandle(parameters->handle);
920 if (!device_handle.get()) {
921 return RespondNow(Error(kErrorNoConnection));
924 if (device_handle->ReleaseInterface(parameters->interface_number)) {
925 return RespondNow(NoArguments());
926 } else {
927 return RespondNow(Error(kErrorCannotReleaseInterface));
931 UsbSetInterfaceAlternateSettingFunction::
932 UsbSetInterfaceAlternateSettingFunction() {
935 UsbSetInterfaceAlternateSettingFunction::
936 ~UsbSetInterfaceAlternateSettingFunction() {
939 ExtensionFunction::ResponseAction
940 UsbSetInterfaceAlternateSettingFunction::Run() {
941 scoped_ptr<extensions::api::usb::SetInterfaceAlternateSetting::Params>
942 parameters = SetInterfaceAlternateSetting::Params::Create(*args_);
943 EXTENSION_FUNCTION_VALIDATE(parameters.get());
945 scoped_refptr<UsbDeviceHandle> device_handle =
946 GetDeviceHandle(parameters->handle);
947 if (!device_handle.get()) {
948 return RespondNow(Error(kErrorNoConnection));
951 device_handle->SetInterfaceAlternateSetting(
952 parameters->interface_number, parameters->alternate_setting,
953 base::Bind(&UsbSetInterfaceAlternateSettingFunction::OnComplete, this));
954 return RespondLater();
957 void UsbSetInterfaceAlternateSettingFunction::OnComplete(bool success) {
958 if (success) {
959 Respond(NoArguments());
960 } else {
961 Respond(Error(kErrorCannotSetInterfaceAlternateSetting));
965 UsbControlTransferFunction::UsbControlTransferFunction() {
968 UsbControlTransferFunction::~UsbControlTransferFunction() {
971 ExtensionFunction::ResponseAction UsbControlTransferFunction::Run() {
972 scoped_ptr<extensions::api::usb::ControlTransfer::Params> parameters =
973 ControlTransfer::Params::Create(*args_);
974 EXTENSION_FUNCTION_VALIDATE(parameters.get());
976 scoped_refptr<UsbDeviceHandle> device_handle =
977 GetDeviceHandle(parameters->handle);
978 if (!device_handle.get()) {
979 return RespondNow(Error(kErrorNoConnection));
982 const ControlTransferInfo& transfer = parameters->transfer_info;
983 UsbEndpointDirection direction = device::USB_DIRECTION_INBOUND;
984 UsbDeviceHandle::TransferRequestType request_type;
985 UsbDeviceHandle::TransferRecipient recipient;
986 size_t size = 0;
988 if (!ConvertDirectionFromApi(transfer.direction, &direction)) {
989 return RespondNow(Error(kErrorConvertDirection));
992 if (!ConvertRequestTypeFromApi(transfer.request_type, &request_type)) {
993 return RespondNow(Error(kErrorConvertRequestType));
996 if (!ConvertRecipientFromApi(transfer.recipient, &recipient)) {
997 return RespondNow(Error(kErrorConvertRecipient));
1000 if (!GetTransferSize(transfer, &size)) {
1001 return RespondNow(Error(kErrorInvalidTransferLength));
1004 scoped_refptr<net::IOBuffer> buffer =
1005 CreateBufferForTransfer(transfer, direction, size);
1006 if (!buffer.get()) {
1007 return RespondNow(Error(kErrorMalformedParameters));
1010 int timeout = transfer.timeout ? *transfer.timeout : 0;
1011 if (timeout < 0) {
1012 return RespondNow(Error(kErrorInvalidTimeout));
1015 device_handle->ControlTransfer(
1016 direction, request_type, recipient, transfer.request, transfer.value,
1017 transfer.index, buffer.get(), size, timeout,
1018 base::Bind(&UsbControlTransferFunction::OnCompleted, this));
1019 return RespondLater();
1022 UsbBulkTransferFunction::UsbBulkTransferFunction() {
1025 UsbBulkTransferFunction::~UsbBulkTransferFunction() {
1028 ExtensionFunction::ResponseAction UsbBulkTransferFunction::Run() {
1029 scoped_ptr<extensions::api::usb::BulkTransfer::Params> parameters =
1030 BulkTransfer::Params::Create(*args_);
1031 EXTENSION_FUNCTION_VALIDATE(parameters.get());
1033 scoped_refptr<UsbDeviceHandle> device_handle =
1034 GetDeviceHandle(parameters->handle);
1035 if (!device_handle.get()) {
1036 return RespondNow(Error(kErrorNoConnection));
1039 const GenericTransferInfo& transfer = parameters->transfer_info;
1040 UsbEndpointDirection direction = device::USB_DIRECTION_INBOUND;
1041 size_t size = 0;
1043 if (!ConvertDirectionFromApi(transfer.direction, &direction)) {
1044 return RespondNow(Error(kErrorConvertDirection));
1047 if (!GetTransferSize(transfer, &size)) {
1048 return RespondNow(Error(kErrorInvalidTransferLength));
1051 scoped_refptr<net::IOBuffer> buffer =
1052 CreateBufferForTransfer(transfer, direction, size);
1053 if (!buffer.get()) {
1054 return RespondNow(Error(kErrorMalformedParameters));
1057 int timeout = transfer.timeout ? *transfer.timeout : 0;
1058 if (timeout < 0) {
1059 return RespondNow(Error(kErrorInvalidTimeout));
1062 device_handle->GenericTransfer(
1063 direction, transfer.endpoint, buffer.get(), size, timeout,
1064 base::Bind(&UsbBulkTransferFunction::OnCompleted, this));
1065 return RespondLater();
1068 UsbInterruptTransferFunction::UsbInterruptTransferFunction() {
1071 UsbInterruptTransferFunction::~UsbInterruptTransferFunction() {
1074 ExtensionFunction::ResponseAction UsbInterruptTransferFunction::Run() {
1075 scoped_ptr<extensions::api::usb::InterruptTransfer::Params> parameters =
1076 InterruptTransfer::Params::Create(*args_);
1077 EXTENSION_FUNCTION_VALIDATE(parameters.get());
1079 scoped_refptr<UsbDeviceHandle> device_handle =
1080 GetDeviceHandle(parameters->handle);
1081 if (!device_handle.get()) {
1082 return RespondNow(Error(kErrorNoConnection));
1085 const GenericTransferInfo& transfer = parameters->transfer_info;
1086 UsbEndpointDirection direction = device::USB_DIRECTION_INBOUND;
1087 size_t size = 0;
1089 if (!ConvertDirectionFromApi(transfer.direction, &direction)) {
1090 return RespondNow(Error(kErrorConvertDirection));
1093 if (!GetTransferSize(transfer, &size)) {
1094 return RespondNow(Error(kErrorInvalidTransferLength));
1097 scoped_refptr<net::IOBuffer> buffer =
1098 CreateBufferForTransfer(transfer, direction, size);
1099 if (!buffer.get()) {
1100 return RespondNow(Error(kErrorMalformedParameters));
1103 int timeout = transfer.timeout ? *transfer.timeout : 0;
1104 if (timeout < 0) {
1105 return RespondNow(Error(kErrorInvalidTimeout));
1108 device_handle->GenericTransfer(
1109 direction, transfer.endpoint, buffer.get(), size, timeout,
1110 base::Bind(&UsbInterruptTransferFunction::OnCompleted, this));
1111 return RespondLater();
1114 UsbIsochronousTransferFunction::UsbIsochronousTransferFunction() {
1117 UsbIsochronousTransferFunction::~UsbIsochronousTransferFunction() {
1120 ExtensionFunction::ResponseAction UsbIsochronousTransferFunction::Run() {
1121 scoped_ptr<extensions::api::usb::IsochronousTransfer::Params> parameters =
1122 IsochronousTransfer::Params::Create(*args_);
1123 EXTENSION_FUNCTION_VALIDATE(parameters.get());
1125 scoped_refptr<UsbDeviceHandle> device_handle =
1126 GetDeviceHandle(parameters->handle);
1127 if (!device_handle.get()) {
1128 return RespondNow(Error(kErrorNoConnection));
1131 const IsochronousTransferInfo& transfer = parameters->transfer_info;
1132 const GenericTransferInfo& generic_transfer = transfer.transfer_info;
1133 size_t size = 0;
1134 UsbEndpointDirection direction = device::USB_DIRECTION_INBOUND;
1136 if (!ConvertDirectionFromApi(generic_transfer.direction, &direction)) {
1137 return RespondNow(Error(kErrorConvertDirection));
1140 if (!GetTransferSize(generic_transfer, &size)) {
1141 return RespondNow(Error(kErrorInvalidTransferLength));
1144 if (transfer.packets < 0 || transfer.packets >= kMaxPackets) {
1145 return RespondNow(Error(kErrorInvalidNumberOfPackets));
1148 unsigned int packets = transfer.packets;
1149 if (transfer.packet_length < 0 ||
1150 transfer.packet_length >= kMaxPacketLength) {
1151 return RespondNow(Error(kErrorInvalidPacketLength));
1154 unsigned int packet_length = transfer.packet_length;
1155 const uint64 total_length = packets * packet_length;
1156 if (packets > size || total_length > size) {
1157 return RespondNow(Error(kErrorTransferLength));
1160 scoped_refptr<net::IOBuffer> buffer =
1161 CreateBufferForTransfer(generic_transfer, direction, size);
1162 if (!buffer.get()) {
1163 return RespondNow(Error(kErrorMalformedParameters));
1166 int timeout = generic_transfer.timeout ? *generic_transfer.timeout : 0;
1167 if (timeout < 0) {
1168 return RespondNow(Error(kErrorInvalidTimeout));
1171 device_handle->IsochronousTransfer(
1172 direction, generic_transfer.endpoint, buffer.get(), size, packets,
1173 packet_length, timeout,
1174 base::Bind(&UsbIsochronousTransferFunction::OnCompleted, this));
1175 return RespondLater();
1178 UsbResetDeviceFunction::UsbResetDeviceFunction() {
1181 UsbResetDeviceFunction::~UsbResetDeviceFunction() {
1184 ExtensionFunction::ResponseAction UsbResetDeviceFunction::Run() {
1185 parameters_ = ResetDevice::Params::Create(*args_);
1186 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
1188 scoped_refptr<UsbDeviceHandle> device_handle =
1189 GetDeviceHandle(parameters_->handle);
1190 if (!device_handle.get()) {
1191 return RespondNow(Error(kErrorNoConnection));
1194 device_handle->ResetDevice(
1195 base::Bind(&UsbResetDeviceFunction::OnComplete, this));
1196 return RespondLater();
1199 void UsbResetDeviceFunction::OnComplete(bool success) {
1200 if (success) {
1201 Respond(OneArgument(new base::FundamentalValue(true)));
1202 } else {
1203 scoped_refptr<UsbDeviceHandle> device_handle =
1204 GetDeviceHandle(parameters_->handle);
1205 if (device_handle.get()) {
1206 device_handle->Close();
1208 ReleaseDeviceHandle(parameters_->handle);
1210 scoped_ptr<base::ListValue> error_args(new base::ListValue());
1211 error_args->AppendBoolean(false);
1212 // Returning arguments with an error is wrong but we're stuck with it.
1213 Respond(ErrorWithArguments(error_args.Pass(), kErrorResetDevice));
1217 } // namespace extensions