Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / extensions / browser / api / usb / usb_api.cc
blob4bec87e97a86ba7a3cb93d155601d9c5d61f7336
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_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 namespace {
75 const char kDataKey[] = "data";
76 const char kResultCodeKey[] = "resultCode";
78 const char kErrorInitService[] = "Failed to initialize USB service.";
80 const char kErrorOpen[] = "Failed to open device.";
81 const char kErrorCancelled[] = "Transfer was cancelled.";
82 const char kErrorDisconnect[] = "Device disconnected.";
83 const char kErrorGeneric[] = "Transfer failed.";
84 const char kErrorNotSupported[] = "Not supported on this platform.";
85 const char kErrorNotConfigured[] = "The device is not in a configured state.";
86 const char kErrorOverflow[] = "Inbound transfer overflow.";
87 const char kErrorStalled[] = "Transfer stalled.";
88 const char kErrorTimeout[] = "Transfer timed out.";
89 const char kErrorTransferLength[] = "Transfer length is insufficient.";
90 const char kErrorCannotSetConfiguration[] =
91 "Error setting device configuration.";
92 const char kErrorCannotClaimInterface[] = "Error claiming interface.";
93 const char kErrorCannotReleaseInterface[] = "Error releasing interface.";
94 const char kErrorCannotSetInterfaceAlternateSetting[] =
95 "Error setting alternate interface setting.";
96 const char kErrorConvertDirection[] = "Invalid transfer direction.";
97 const char kErrorConvertRecipient[] = "Invalid transfer recipient.";
98 const char kErrorConvertRequestType[] = "Invalid request type.";
99 const char kErrorMalformedParameters[] = "Error parsing parameters.";
100 const char kErrorNoConnection[] = "No such connection.";
101 const char kErrorNoDevice[] = "No such device.";
102 const char kErrorPermissionDenied[] = "Permission to access device was denied";
103 const char kErrorInvalidTransferLength[] =
104 "Transfer length must be a positive number less than 104,857,600.";
105 const char kErrorInvalidNumberOfPackets[] =
106 "Number of packets must be a positive number less than 4,194,304.";
107 const char kErrorInvalidPacketLength[] =
108 "Packet length must be a positive number less than 65,536.";
109 const char kErrorInvalidTimeout[] =
110 "Transfer timeout must be greater than or equal to 0.";
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 base::Value* PopulateConnectionHandle(int handle,
244 int vendor_id,
245 int product_id) {
246 ConnectionHandle result;
247 result.handle = handle;
248 result.vendor_id = vendor_id;
249 result.product_id = product_id;
250 return result.ToValue().release();
253 base::Value* PopulateDevice(const UsbDevice* device) {
254 Device result;
255 result.device = device->unique_id();
256 result.vendor_id = device->vendor_id();
257 result.product_id = device->product_id();
258 return result.ToValue().release();
261 TransferType ConvertTransferTypeToApi(const UsbTransferType& input) {
262 switch (input) {
263 case device::USB_TRANSFER_CONTROL:
264 return usb::TRANSFER_TYPE_CONTROL;
265 case device::USB_TRANSFER_INTERRUPT:
266 return usb::TRANSFER_TYPE_INTERRUPT;
267 case device::USB_TRANSFER_ISOCHRONOUS:
268 return usb::TRANSFER_TYPE_ISOCHRONOUS;
269 case device::USB_TRANSFER_BULK:
270 return usb::TRANSFER_TYPE_BULK;
271 default:
272 NOTREACHED();
273 return usb::TRANSFER_TYPE_NONE;
277 Direction ConvertDirectionToApi(const UsbEndpointDirection& input) {
278 switch (input) {
279 case device::USB_DIRECTION_INBOUND:
280 return usb::DIRECTION_IN;
281 case device::USB_DIRECTION_OUTBOUND:
282 return usb::DIRECTION_OUT;
283 default:
284 NOTREACHED();
285 return usb::DIRECTION_NONE;
289 SynchronizationType ConvertSynchronizationTypeToApi(
290 const UsbSynchronizationType& input) {
291 switch (input) {
292 case device::USB_SYNCHRONIZATION_NONE:
293 return usb::SYNCHRONIZATION_TYPE_NONE;
294 case device::USB_SYNCHRONIZATION_ASYNCHRONOUS:
295 return usb::SYNCHRONIZATION_TYPE_ASYNCHRONOUS;
296 case device::USB_SYNCHRONIZATION_ADAPTIVE:
297 return usb::SYNCHRONIZATION_TYPE_ADAPTIVE;
298 case device::USB_SYNCHRONIZATION_SYNCHRONOUS:
299 return usb::SYNCHRONIZATION_TYPE_SYNCHRONOUS;
300 default:
301 NOTREACHED();
302 return usb::SYNCHRONIZATION_TYPE_NONE;
306 UsageType ConvertUsageTypeToApi(const UsbUsageType& input) {
307 switch (input) {
308 case device::USB_USAGE_DATA:
309 return usb::USAGE_TYPE_DATA;
310 case device::USB_USAGE_FEEDBACK:
311 return usb::USAGE_TYPE_FEEDBACK;
312 case device::USB_USAGE_EXPLICIT_FEEDBACK:
313 return usb::USAGE_TYPE_EXPLICITFEEDBACK;
314 default:
315 NOTREACHED();
316 return usb::USAGE_TYPE_NONE;
320 void ConvertEndpointDescriptor(const UsbEndpointDescriptor& input,
321 EndpointDescriptor* output) {
322 output->address = input.address;
323 output->type = ConvertTransferTypeToApi(input.transfer_type);
324 output->direction = ConvertDirectionToApi(input.direction);
325 output->maximum_packet_size = input.maximum_packet_size;
326 output->synchronization =
327 ConvertSynchronizationTypeToApi(input.synchronization_type);
328 output->usage = ConvertUsageTypeToApi(input.usage_type);
329 output->polling_interval.reset(new int(input.polling_interval));
330 output->extra_data.assign(input.extra_data.begin(), input.extra_data.end());
333 void ConvertInterfaceDescriptor(const UsbInterfaceDescriptor& input,
334 InterfaceDescriptor* output) {
335 output->interface_number = input.interface_number;
336 output->alternate_setting = input.alternate_setting;
337 output->interface_class = input.interface_class;
338 output->interface_subclass = input.interface_subclass;
339 output->interface_protocol = input.interface_protocol;
340 for (const UsbEndpointDescriptor& input_endpoint : input.endpoints) {
341 linked_ptr<EndpointDescriptor> endpoint(new EndpointDescriptor);
342 ConvertEndpointDescriptor(input_endpoint, endpoint.get());
343 output->endpoints.push_back(endpoint);
345 output->extra_data.assign(input.extra_data.begin(), input.extra_data.end());
348 void ConvertConfigDescriptor(const UsbConfigDescriptor& input,
349 ConfigDescriptor* output) {
350 output->configuration_value = input.configuration_value;
351 output->self_powered = input.self_powered;
352 output->remote_wakeup = input.remote_wakeup;
353 output->max_power = input.maximum_power;
354 for (const UsbInterfaceDescriptor& input_interface : input.interfaces) {
355 linked_ptr<InterfaceDescriptor> interface(new InterfaceDescriptor);
356 ConvertInterfaceDescriptor(input_interface, interface.get());
357 output->interfaces.push_back(interface);
359 output->extra_data.assign(input.extra_data.begin(), input.extra_data.end());
362 void ConvertDeviceFilter(const usb::DeviceFilter& input,
363 UsbDeviceFilter* output) {
364 if (input.vendor_id) {
365 output->SetVendorId(*input.vendor_id);
367 if (input.product_id) {
368 output->SetProductId(*input.product_id);
370 if (input.interface_class) {
371 output->SetInterfaceClass(*input.interface_class);
373 if (input.interface_subclass) {
374 output->SetInterfaceSubclass(*input.interface_subclass);
376 if (input.interface_protocol) {
377 output->SetInterfaceProtocol(*input.interface_protocol);
381 } // namespace
383 namespace extensions {
385 UsbPermissionCheckingFunction::UsbPermissionCheckingFunction()
386 : device_permissions_manager_(nullptr) {
389 UsbPermissionCheckingFunction::~UsbPermissionCheckingFunction() {
392 bool UsbPermissionCheckingFunction::HasDevicePermission(
393 scoped_refptr<UsbDevice> device) {
394 if (!device_permissions_manager_) {
395 device_permissions_manager_ =
396 DevicePermissionsManager::Get(browser_context());
399 DevicePermissions* device_permissions =
400 device_permissions_manager_->GetForExtension(extension_id());
401 DCHECK(device_permissions);
403 permission_entry_ = device_permissions->FindUsbDeviceEntry(device);
404 if (permission_entry_.get()) {
405 return true;
408 UsbDevicePermission::CheckParam param(
409 device->vendor_id(),
410 device->product_id(),
411 UsbDevicePermissionData::UNSPECIFIED_INTERFACE);
412 if (extension()->permissions_data()->CheckAPIPermissionWithParam(
413 APIPermission::kUsbDevice, &param)) {
414 return true;
417 return false;
420 void UsbPermissionCheckingFunction::RecordDeviceLastUsed() {
421 if (permission_entry_.get()) {
422 device_permissions_manager_->UpdateLastUsed(extension_id(),
423 permission_entry_);
427 UsbConnectionFunction::UsbConnectionFunction() {
430 UsbConnectionFunction::~UsbConnectionFunction() {
433 scoped_refptr<device::UsbDeviceHandle> UsbConnectionFunction::GetDeviceHandle(
434 const extensions::core_api::usb::ConnectionHandle& handle) {
435 ApiResourceManager<UsbDeviceResource>* manager =
436 ApiResourceManager<UsbDeviceResource>::Get(browser_context());
437 if (!manager) {
438 return nullptr;
441 UsbDeviceResource* resource = manager->Get(extension_id(), handle.handle);
442 if (!resource) {
443 return nullptr;
446 return resource->device();
449 void UsbConnectionFunction::ReleaseDeviceHandle(
450 const extensions::core_api::usb::ConnectionHandle& handle) {
451 ApiResourceManager<UsbDeviceResource>* manager =
452 ApiResourceManager<UsbDeviceResource>::Get(browser_context());
453 manager->Remove(extension_id(), handle.handle);
456 UsbTransferFunction::UsbTransferFunction() {
459 UsbTransferFunction::~UsbTransferFunction() {
462 void UsbTransferFunction::OnCompleted(UsbTransferStatus status,
463 scoped_refptr<net::IOBuffer> data,
464 size_t length) {
465 scoped_ptr<base::DictionaryValue> transfer_info(new base::DictionaryValue());
466 transfer_info->SetInteger(kResultCodeKey, status);
467 transfer_info->Set(kDataKey, base::BinaryValue::CreateWithCopiedBuffer(
468 data->data(), length));
470 if (status == device::USB_TRANSFER_COMPLETED) {
471 Respond(OneArgument(transfer_info.release()));
472 } else {
473 scoped_ptr<base::ListValue> error_args(new base::ListValue());
474 error_args->Append(transfer_info.release());
475 // Returning arguments with an error is wrong but we're stuck with it.
476 Respond(ErrorWithArguments(error_args.Pass(),
477 ConvertTransferStatusToApi(status)));
481 UsbFindDevicesFunction::UsbFindDevicesFunction() {
484 UsbFindDevicesFunction::~UsbFindDevicesFunction() {
487 ExtensionFunction::ResponseAction UsbFindDevicesFunction::Run() {
488 scoped_ptr<extensions::core_api::usb::FindDevices::Params> parameters =
489 FindDevices::Params::Create(*args_);
490 EXTENSION_FUNCTION_VALIDATE(parameters.get());
492 vendor_id_ = parameters->options.vendor_id;
493 product_id_ = parameters->options.product_id;
494 interface_id_ = parameters->options.interface_id.get()
495 ? *parameters->options.interface_id.get()
496 : UsbDevicePermissionData::ANY_INTERFACE;
497 UsbDevicePermission::CheckParam param(vendor_id_, product_id_, interface_id_);
498 if (!extension()->permissions_data()->CheckAPIPermissionWithParam(
499 APIPermission::kUsbDevice, &param)) {
500 return RespondNow(Error(kErrorPermissionDenied));
503 UsbService* service = device::DeviceClient::Get()->GetUsbService();
504 if (!service) {
505 return RespondNow(Error(kErrorInitService));
508 service->GetDevices(
509 base::Bind(&UsbFindDevicesFunction::OnGetDevicesComplete, this));
510 return RespondLater();
513 void UsbFindDevicesFunction::OnGetDevicesComplete(
514 const std::vector<scoped_refptr<UsbDevice>>& devices) {
515 result_.reset(new base::ListValue());
516 barrier_ = base::BarrierClosure(
517 devices.size(), base::Bind(&UsbFindDevicesFunction::OpenComplete, this));
519 for (const scoped_refptr<UsbDevice>& device : devices) {
520 if (device->vendor_id() != vendor_id_ ||
521 device->product_id() != product_id_) {
522 barrier_.Run();
523 } else {
524 device->RequestUsbAccess(
525 interface_id_,
526 base::Bind(&UsbFindDevicesFunction::OnRequestAccessComplete, this,
527 device));
532 void UsbFindDevicesFunction::OnRequestAccessComplete(
533 scoped_refptr<UsbDevice> device,
534 bool success) {
535 if (success) {
536 device->Open(base::Bind(&UsbFindDevicesFunction::OnDeviceOpened, this));
537 } else {
538 barrier_.Run();
542 void UsbFindDevicesFunction::OnDeviceOpened(
543 scoped_refptr<UsbDeviceHandle> device_handle) {
544 if (device_handle.get()) {
545 ApiResourceManager<UsbDeviceResource>* manager =
546 ApiResourceManager<UsbDeviceResource>::Get(browser_context());
547 UsbDeviceResource* resource =
548 new UsbDeviceResource(extension_id(), device_handle);
549 scoped_refptr<UsbDevice> device = device_handle->GetDevice();
550 result_->Append(PopulateConnectionHandle(
551 manager->Add(resource), device->vendor_id(), device->product_id()));
553 barrier_.Run();
556 void UsbFindDevicesFunction::OpenComplete() {
557 Respond(OneArgument(result_.release()));
560 UsbGetDevicesFunction::UsbGetDevicesFunction() {
563 UsbGetDevicesFunction::~UsbGetDevicesFunction() {
566 ExtensionFunction::ResponseAction UsbGetDevicesFunction::Run() {
567 scoped_ptr<extensions::core_api::usb::GetDevices::Params> parameters =
568 GetDevices::Params::Create(*args_);
569 EXTENSION_FUNCTION_VALIDATE(parameters.get());
571 if (parameters->options.filters) {
572 filters_.resize(parameters->options.filters->size());
573 for (size_t i = 0; i < parameters->options.filters->size(); ++i) {
574 ConvertDeviceFilter(*parameters->options.filters->at(i).get(),
575 &filters_[i]);
578 if (parameters->options.vendor_id) {
579 filters_.resize(filters_.size() + 1);
580 filters_.back().SetVendorId(*parameters->options.vendor_id);
581 if (parameters->options.product_id) {
582 filters_.back().SetProductId(*parameters->options.product_id);
586 UsbService* service = device::DeviceClient::Get()->GetUsbService();
587 if (!service) {
588 return RespondNow(Error(kErrorInitService));
591 service->GetDevices(
592 base::Bind(&UsbGetDevicesFunction::OnGetDevicesComplete, this));
593 return RespondLater();
596 void UsbGetDevicesFunction::OnGetDevicesComplete(
597 const std::vector<scoped_refptr<UsbDevice>>& devices) {
598 scoped_ptr<base::ListValue> result(new base::ListValue());
599 for (const scoped_refptr<UsbDevice>& device : devices) {
600 if ((filters_.empty() || UsbDeviceFilter::MatchesAny(device, filters_)) &&
601 HasDevicePermission(device)) {
602 result->Append(PopulateDevice(device.get()));
606 Respond(OneArgument(result.release()));
609 UsbGetUserSelectedDevicesFunction::UsbGetUserSelectedDevicesFunction() {
612 UsbGetUserSelectedDevicesFunction::~UsbGetUserSelectedDevicesFunction() {
615 ExtensionFunction::ResponseAction UsbGetUserSelectedDevicesFunction::Run() {
616 scoped_ptr<extensions::core_api::usb::GetUserSelectedDevices::Params>
617 parameters = GetUserSelectedDevices::Params::Create(*args_);
618 EXTENSION_FUNCTION_VALIDATE(parameters.get());
620 if (!user_gesture()) {
621 return RespondNow(OneArgument(new base::ListValue()));
624 bool multiple = false;
625 if (parameters->options.multiple) {
626 multiple = *parameters->options.multiple;
629 std::vector<UsbDeviceFilter> filters;
630 if (parameters->options.filters) {
631 filters.resize(parameters->options.filters->size());
632 for (size_t i = 0; i < parameters->options.filters->size(); ++i) {
633 ConvertDeviceFilter(*parameters->options.filters->at(i).get(),
634 &filters[i]);
638 prompt_ = ExtensionsAPIClient::Get()->CreateDevicePermissionsPrompt(
639 GetAssociatedWebContents());
640 if (!prompt_) {
641 return RespondNow(Error(kErrorNotSupported));
644 prompt_->AskForUsbDevices(
645 extension(), browser_context(), multiple, filters,
646 base::Bind(&UsbGetUserSelectedDevicesFunction::OnDevicesChosen, this));
647 return RespondLater();
650 void UsbGetUserSelectedDevicesFunction::OnDevicesChosen(
651 const std::vector<scoped_refptr<UsbDevice>>& devices) {
652 scoped_ptr<base::ListValue> result(new base::ListValue());
653 for (const auto& device : devices) {
654 result->Append(PopulateDevice(device.get()));
657 Respond(OneArgument(result.release()));
660 UsbRequestAccessFunction::UsbRequestAccessFunction() {
663 UsbRequestAccessFunction::~UsbRequestAccessFunction() {
666 ExtensionFunction::ResponseAction UsbRequestAccessFunction::Run() {
667 scoped_ptr<extensions::core_api::usb::RequestAccess::Params> parameters =
668 RequestAccess::Params::Create(*args_);
669 EXTENSION_FUNCTION_VALIDATE(parameters.get());
670 return RespondNow(OneArgument(new base::FundamentalValue(true)));
673 UsbOpenDeviceFunction::UsbOpenDeviceFunction() {
676 UsbOpenDeviceFunction::~UsbOpenDeviceFunction() {
679 ExtensionFunction::ResponseAction UsbOpenDeviceFunction::Run() {
680 scoped_ptr<extensions::core_api::usb::OpenDevice::Params> parameters =
681 OpenDevice::Params::Create(*args_);
682 EXTENSION_FUNCTION_VALIDATE(parameters.get());
684 UsbService* service = device::DeviceClient::Get()->GetUsbService();
685 if (!service) {
686 return RespondNow(Error(kErrorInitService));
689 scoped_refptr<UsbDevice> device =
690 service->GetDeviceById(parameters->device.device);
691 if (!device.get()) {
692 return RespondNow(Error(kErrorNoDevice));
695 if (!HasDevicePermission(device)) {
696 // This function must act as if there is no such device. Otherwise it can be
697 // used to fingerprint unauthorized devices.
698 return RespondNow(Error(kErrorNoDevice));
701 device->RequestUsbAccess(
702 -1, /* any interface, unused by the permission broker */
703 base::Bind(&UsbOpenDeviceFunction::OnRequestAccessComplete, this,
704 device));
705 return RespondLater();
708 void UsbOpenDeviceFunction::OnRequestAccessComplete(
709 scoped_refptr<UsbDevice> device,
710 bool success) {
711 if (success) {
712 device->Open(base::Bind(&UsbOpenDeviceFunction::OnDeviceOpened, this));
713 } else {
714 Respond(Error(kErrorPermissionDenied));
718 void UsbOpenDeviceFunction::OnDeviceOpened(
719 scoped_refptr<UsbDeviceHandle> device_handle) {
720 if (!device_handle.get()) {
721 Respond(Error(kErrorOpen));
722 return;
725 RecordDeviceLastUsed();
727 ApiResourceManager<UsbDeviceResource>* manager =
728 ApiResourceManager<UsbDeviceResource>::Get(browser_context());
729 scoped_refptr<UsbDevice> device = device_handle->GetDevice();
730 Respond(OneArgument(PopulateConnectionHandle(
731 manager->Add(new UsbDeviceResource(extension_id(), device_handle)),
732 device->vendor_id(), device->product_id())));
735 UsbSetConfigurationFunction::UsbSetConfigurationFunction() {
738 UsbSetConfigurationFunction::~UsbSetConfigurationFunction() {
741 ExtensionFunction::ResponseAction UsbSetConfigurationFunction::Run() {
742 scoped_ptr<extensions::core_api::usb::SetConfiguration::Params> parameters =
743 SetConfiguration::Params::Create(*args_);
744 EXTENSION_FUNCTION_VALIDATE(parameters.get());
746 scoped_refptr<UsbDeviceHandle> device_handle =
747 GetDeviceHandle(parameters->handle);
748 if (!device_handle.get()) {
749 return RespondNow(Error(kErrorNoConnection));
752 device_handle->SetConfiguration(
753 parameters->configuration_value,
754 base::Bind(&UsbSetConfigurationFunction::OnComplete, this));
755 return RespondLater();
758 void UsbSetConfigurationFunction::OnComplete(bool success) {
759 if (success) {
760 Respond(NoArguments());
761 } else {
762 Respond(Error(kErrorCannotSetConfiguration));
766 UsbGetConfigurationFunction::UsbGetConfigurationFunction() {
769 UsbGetConfigurationFunction::~UsbGetConfigurationFunction() {
772 ExtensionFunction::ResponseAction UsbGetConfigurationFunction::Run() {
773 scoped_ptr<extensions::core_api::usb::GetConfiguration::Params> parameters =
774 GetConfiguration::Params::Create(*args_);
775 EXTENSION_FUNCTION_VALIDATE(parameters.get());
777 scoped_refptr<UsbDeviceHandle> device_handle =
778 GetDeviceHandle(parameters->handle);
779 if (!device_handle.get()) {
780 return RespondNow(Error(kErrorNoConnection));
783 const UsbConfigDescriptor* config_descriptor =
784 device_handle->GetDevice()->GetConfiguration();
785 if (config_descriptor) {
786 ConfigDescriptor config;
787 ConvertConfigDescriptor(*config_descriptor, &config);
788 return RespondNow(OneArgument(config.ToValue().release()));
789 } else {
790 return RespondNow(Error(kErrorNotConfigured));
794 UsbListInterfacesFunction::UsbListInterfacesFunction() {
797 UsbListInterfacesFunction::~UsbListInterfacesFunction() {
800 ExtensionFunction::ResponseAction UsbListInterfacesFunction::Run() {
801 scoped_ptr<extensions::core_api::usb::ListInterfaces::Params> parameters =
802 ListInterfaces::Params::Create(*args_);
803 EXTENSION_FUNCTION_VALIDATE(parameters.get());
805 scoped_refptr<UsbDeviceHandle> device_handle =
806 GetDeviceHandle(parameters->handle);
807 if (!device_handle.get()) {
808 return RespondNow(Error(kErrorNoConnection));
811 const UsbConfigDescriptor* config_descriptor =
812 device_handle->GetDevice()->GetConfiguration();
813 if (config_descriptor) {
814 ConfigDescriptor config;
815 ConvertConfigDescriptor(*config_descriptor, &config);
817 scoped_ptr<base::ListValue> result(new base::ListValue);
818 for (size_t i = 0; i < config.interfaces.size(); ++i) {
819 result->Append(config.interfaces[i]->ToValue().release());
822 return RespondNow(OneArgument(result.release()));
823 } else {
824 return RespondNow(Error(kErrorNotConfigured));
828 UsbCloseDeviceFunction::UsbCloseDeviceFunction() {
831 UsbCloseDeviceFunction::~UsbCloseDeviceFunction() {
834 ExtensionFunction::ResponseAction UsbCloseDeviceFunction::Run() {
835 scoped_ptr<extensions::core_api::usb::CloseDevice::Params> parameters =
836 CloseDevice::Params::Create(*args_);
837 EXTENSION_FUNCTION_VALIDATE(parameters.get());
839 scoped_refptr<UsbDeviceHandle> device_handle =
840 GetDeviceHandle(parameters->handle);
841 if (!device_handle.get()) {
842 return RespondNow(Error(kErrorNoConnection));
845 // The device handle is closed when the resource is destroyed.
846 ReleaseDeviceHandle(parameters->handle);
847 return RespondNow(NoArguments());
850 UsbClaimInterfaceFunction::UsbClaimInterfaceFunction() {
853 UsbClaimInterfaceFunction::~UsbClaimInterfaceFunction() {
856 ExtensionFunction::ResponseAction UsbClaimInterfaceFunction::Run() {
857 scoped_ptr<extensions::core_api::usb::ClaimInterface::Params> parameters =
858 ClaimInterface::Params::Create(*args_);
859 EXTENSION_FUNCTION_VALIDATE(parameters.get());
861 scoped_refptr<UsbDeviceHandle> device_handle =
862 GetDeviceHandle(parameters->handle);
863 if (!device_handle.get()) {
864 return RespondNow(Error(kErrorNoConnection));
867 device_handle->ClaimInterface(
868 parameters->interface_number,
869 base::Bind(&UsbClaimInterfaceFunction::OnComplete, this));
870 return RespondLater();
873 void UsbClaimInterfaceFunction::OnComplete(bool success) {
874 if (success) {
875 Respond(NoArguments());
876 } else {
877 Respond(Error(kErrorCannotClaimInterface));
881 UsbReleaseInterfaceFunction::UsbReleaseInterfaceFunction() {
884 UsbReleaseInterfaceFunction::~UsbReleaseInterfaceFunction() {
887 ExtensionFunction::ResponseAction UsbReleaseInterfaceFunction::Run() {
888 scoped_ptr<extensions::core_api::usb::ReleaseInterface::Params> parameters =
889 ReleaseInterface::Params::Create(*args_);
890 EXTENSION_FUNCTION_VALIDATE(parameters.get());
892 scoped_refptr<UsbDeviceHandle> device_handle =
893 GetDeviceHandle(parameters->handle);
894 if (!device_handle.get()) {
895 return RespondNow(Error(kErrorNoConnection));
898 if (device_handle->ReleaseInterface(parameters->interface_number)) {
899 return RespondNow(NoArguments());
900 } else {
901 return RespondNow(Error(kErrorCannotReleaseInterface));
905 UsbSetInterfaceAlternateSettingFunction::
906 UsbSetInterfaceAlternateSettingFunction() {
909 UsbSetInterfaceAlternateSettingFunction::
910 ~UsbSetInterfaceAlternateSettingFunction() {
913 ExtensionFunction::ResponseAction
914 UsbSetInterfaceAlternateSettingFunction::Run() {
915 scoped_ptr<extensions::core_api::usb::SetInterfaceAlternateSetting::Params>
916 parameters = SetInterfaceAlternateSetting::Params::Create(*args_);
917 EXTENSION_FUNCTION_VALIDATE(parameters.get());
919 scoped_refptr<UsbDeviceHandle> device_handle =
920 GetDeviceHandle(parameters->handle);
921 if (!device_handle.get()) {
922 return RespondNow(Error(kErrorNoConnection));
925 device_handle->SetInterfaceAlternateSetting(
926 parameters->interface_number, parameters->alternate_setting,
927 base::Bind(&UsbSetInterfaceAlternateSettingFunction::OnComplete, this));
928 return RespondLater();
931 void UsbSetInterfaceAlternateSettingFunction::OnComplete(bool success) {
932 if (success) {
933 Respond(NoArguments());
934 } else {
935 Respond(Error(kErrorCannotSetInterfaceAlternateSetting));
939 UsbControlTransferFunction::UsbControlTransferFunction() {
942 UsbControlTransferFunction::~UsbControlTransferFunction() {
945 ExtensionFunction::ResponseAction UsbControlTransferFunction::Run() {
946 scoped_ptr<extensions::core_api::usb::ControlTransfer::Params> parameters =
947 ControlTransfer::Params::Create(*args_);
948 EXTENSION_FUNCTION_VALIDATE(parameters.get());
950 scoped_refptr<UsbDeviceHandle> device_handle =
951 GetDeviceHandle(parameters->handle);
952 if (!device_handle.get()) {
953 return RespondNow(Error(kErrorNoConnection));
956 const ControlTransferInfo& transfer = parameters->transfer_info;
957 UsbEndpointDirection direction;
958 UsbDeviceHandle::TransferRequestType request_type;
959 UsbDeviceHandle::TransferRecipient recipient;
960 size_t size = 0;
962 if (!ConvertDirectionFromApi(transfer.direction, &direction)) {
963 return RespondNow(Error(kErrorConvertDirection));
966 if (!ConvertRequestTypeFromApi(transfer.request_type, &request_type)) {
967 return RespondNow(Error(kErrorConvertRequestType));
970 if (!ConvertRecipientFromApi(transfer.recipient, &recipient)) {
971 return RespondNow(Error(kErrorConvertRecipient));
974 if (!GetTransferSize(transfer, &size)) {
975 return RespondNow(Error(kErrorInvalidTransferLength));
978 scoped_refptr<net::IOBuffer> buffer =
979 CreateBufferForTransfer(transfer, direction, size);
980 if (!buffer.get()) {
981 return RespondNow(Error(kErrorMalformedParameters));
984 int timeout = transfer.timeout ? *transfer.timeout : 0;
985 if (timeout < 0) {
986 return RespondNow(Error(kErrorInvalidTimeout));
989 device_handle->ControlTransfer(
990 direction, request_type, recipient, transfer.request, transfer.value,
991 transfer.index, buffer.get(), size, timeout,
992 base::Bind(&UsbControlTransferFunction::OnCompleted, this));
993 return RespondLater();
996 UsbBulkTransferFunction::UsbBulkTransferFunction() {
999 UsbBulkTransferFunction::~UsbBulkTransferFunction() {
1002 ExtensionFunction::ResponseAction UsbBulkTransferFunction::Run() {
1003 scoped_ptr<extensions::core_api::usb::BulkTransfer::Params> parameters =
1004 BulkTransfer::Params::Create(*args_);
1005 EXTENSION_FUNCTION_VALIDATE(parameters.get());
1007 scoped_refptr<UsbDeviceHandle> device_handle =
1008 GetDeviceHandle(parameters->handle);
1009 if (!device_handle.get()) {
1010 return RespondNow(Error(kErrorNoConnection));
1013 const GenericTransferInfo& transfer = parameters->transfer_info;
1014 UsbEndpointDirection direction;
1015 size_t size = 0;
1017 if (!ConvertDirectionFromApi(transfer.direction, &direction)) {
1018 return RespondNow(Error(kErrorConvertDirection));
1021 if (!GetTransferSize(transfer, &size)) {
1022 return RespondNow(Error(kErrorInvalidTransferLength));
1025 scoped_refptr<net::IOBuffer> buffer =
1026 CreateBufferForTransfer(transfer, direction, size);
1027 if (!buffer.get()) {
1028 return RespondNow(Error(kErrorMalformedParameters));
1031 int timeout = transfer.timeout ? *transfer.timeout : 0;
1032 if (timeout < 0) {
1033 return RespondNow(Error(kErrorInvalidTimeout));
1036 device_handle->BulkTransfer(
1037 direction, transfer.endpoint, buffer.get(), size, timeout,
1038 base::Bind(&UsbBulkTransferFunction::OnCompleted, this));
1039 return RespondLater();
1042 UsbInterruptTransferFunction::UsbInterruptTransferFunction() {
1045 UsbInterruptTransferFunction::~UsbInterruptTransferFunction() {
1048 ExtensionFunction::ResponseAction UsbInterruptTransferFunction::Run() {
1049 scoped_ptr<extensions::core_api::usb::InterruptTransfer::Params> parameters =
1050 InterruptTransfer::Params::Create(*args_);
1051 EXTENSION_FUNCTION_VALIDATE(parameters.get());
1053 scoped_refptr<UsbDeviceHandle> device_handle =
1054 GetDeviceHandle(parameters->handle);
1055 if (!device_handle.get()) {
1056 return RespondNow(Error(kErrorNoConnection));
1059 const GenericTransferInfo& transfer = parameters->transfer_info;
1060 UsbEndpointDirection direction;
1061 size_t size = 0;
1063 if (!ConvertDirectionFromApi(transfer.direction, &direction)) {
1064 return RespondNow(Error(kErrorConvertDirection));
1067 if (!GetTransferSize(transfer, &size)) {
1068 return RespondNow(Error(kErrorInvalidTransferLength));
1071 scoped_refptr<net::IOBuffer> buffer =
1072 CreateBufferForTransfer(transfer, direction, size);
1073 if (!buffer.get()) {
1074 return RespondNow(Error(kErrorMalformedParameters));
1077 int timeout = transfer.timeout ? *transfer.timeout : 0;
1078 if (timeout < 0) {
1079 return RespondNow(Error(kErrorInvalidTimeout));
1082 device_handle->InterruptTransfer(
1083 direction, transfer.endpoint, buffer.get(), size, timeout,
1084 base::Bind(&UsbInterruptTransferFunction::OnCompleted, this));
1085 return RespondLater();
1088 UsbIsochronousTransferFunction::UsbIsochronousTransferFunction() {
1091 UsbIsochronousTransferFunction::~UsbIsochronousTransferFunction() {
1094 ExtensionFunction::ResponseAction UsbIsochronousTransferFunction::Run() {
1095 scoped_ptr<extensions::core_api::usb::IsochronousTransfer::Params>
1096 parameters = IsochronousTransfer::Params::Create(*args_);
1097 EXTENSION_FUNCTION_VALIDATE(parameters.get());
1099 scoped_refptr<UsbDeviceHandle> device_handle =
1100 GetDeviceHandle(parameters->handle);
1101 if (!device_handle.get()) {
1102 return RespondNow(Error(kErrorNoConnection));
1105 const IsochronousTransferInfo& transfer = parameters->transfer_info;
1106 const GenericTransferInfo& generic_transfer = transfer.transfer_info;
1107 size_t size = 0;
1108 UsbEndpointDirection direction;
1110 if (!ConvertDirectionFromApi(generic_transfer.direction, &direction)) {
1111 return RespondNow(Error(kErrorConvertDirection));
1114 if (!GetTransferSize(generic_transfer, &size)) {
1115 return RespondNow(Error(kErrorInvalidTransferLength));
1118 if (transfer.packets < 0 || transfer.packets >= kMaxPackets) {
1119 return RespondNow(Error(kErrorInvalidNumberOfPackets));
1122 unsigned int packets = transfer.packets;
1123 if (transfer.packet_length < 0 ||
1124 transfer.packet_length >= kMaxPacketLength) {
1125 return RespondNow(Error(kErrorInvalidPacketLength));
1128 unsigned int packet_length = transfer.packet_length;
1129 const uint64 total_length = packets * packet_length;
1130 if (packets > size || total_length > size) {
1131 return RespondNow(Error(kErrorTransferLength));
1134 scoped_refptr<net::IOBuffer> buffer =
1135 CreateBufferForTransfer(generic_transfer, direction, size);
1136 if (!buffer.get()) {
1137 return RespondNow(Error(kErrorMalformedParameters));
1140 int timeout = generic_transfer.timeout ? *generic_transfer.timeout : 0;
1141 if (timeout < 0) {
1142 return RespondNow(Error(kErrorInvalidTimeout));
1145 device_handle->IsochronousTransfer(
1146 direction, generic_transfer.endpoint, buffer.get(), size, packets,
1147 packet_length, timeout,
1148 base::Bind(&UsbIsochronousTransferFunction::OnCompleted, this));
1149 return RespondLater();
1152 UsbResetDeviceFunction::UsbResetDeviceFunction() {
1155 UsbResetDeviceFunction::~UsbResetDeviceFunction() {
1158 ExtensionFunction::ResponseAction UsbResetDeviceFunction::Run() {
1159 parameters_ = ResetDevice::Params::Create(*args_);
1160 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
1162 scoped_refptr<UsbDeviceHandle> device_handle =
1163 GetDeviceHandle(parameters_->handle);
1164 if (!device_handle.get()) {
1165 return RespondNow(Error(kErrorNoConnection));
1168 device_handle->ResetDevice(
1169 base::Bind(&UsbResetDeviceFunction::OnComplete, this));
1170 return RespondLater();
1173 void UsbResetDeviceFunction::OnComplete(bool success) {
1174 if (success) {
1175 Respond(OneArgument(new base::FundamentalValue(true)));
1176 } else {
1177 scoped_refptr<UsbDeviceHandle> device_handle =
1178 GetDeviceHandle(parameters_->handle);
1179 if (device_handle.get()) {
1180 device_handle->Close();
1182 ReleaseDeviceHandle(parameters_->handle);
1184 scoped_ptr<base::ListValue> error_args(new base::ListValue());
1185 error_args->AppendBoolean(false);
1186 // Returning arguments with an error is wrong but we're stuck with it.
1187 Respond(ErrorWithArguments(error_args.Pass(), kErrorResetDevice));
1191 } // namespace extensions