Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(218)

Side by Side Diff: chrome/browser/extensions/api/usb/usb_api.cc

Issue 22914023: Introducing chrome.usb.getDevices/openDevice API (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@usb-interface
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/api/usb/usb_api.h" 5 #include "chrome/browser/extensions/api/usb/usb_api.h"
6 6
7 #include <string> 7 #include <string>
8 #include <vector> 8 #include <vector>
9 9
10 #include "base/memory/scoped_ptr.h" 10 #include "base/memory/scoped_ptr.h"
11 #include "base/message_loop/message_loop_proxy.h"
11 #include "chrome/browser/extensions/api/usb/usb_device_resource.h" 12 #include "chrome/browser/extensions/api/usb/usb_device_resource.h"
12 #include "chrome/browser/extensions/extension_system.h" 13 #include "chrome/browser/extensions/extension_system.h"
13 #include "chrome/browser/profiles/profile.h" 14 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/usb/usb_device_handle.h" 15 #include "chrome/browser/usb/usb_device_handle.h"
15 #include "chrome/browser/usb/usb_service.h" 16 #include "chrome/browser/usb/usb_service.h"
16 #include "chrome/common/extensions/api/usb.h" 17 #include "chrome/common/extensions/api/usb.h"
17 #include "chrome/common/extensions/permissions/permissions_data.h" 18 #include "chrome/common/extensions/permissions/permissions_data.h"
18 #include "chrome/common/extensions/permissions/usb_device_permission.h" 19 #include "chrome/common/extensions/permissions/usb_device_permission.h"
19 20
20 namespace BulkTransfer = extensions::api::usb::BulkTransfer;
21 namespace ClaimInterface = extensions::api::usb::ClaimInterface;
22 namespace ListInterfaces = extensions::api::usb::ListInterfaces;
23 namespace CloseDevice = extensions::api::usb::CloseDevice;
24 namespace ControlTransfer = extensions::api::usb::ControlTransfer;
25 namespace FindDevices = extensions::api::usb::FindDevices;
26 namespace InterruptTransfer = extensions::api::usb::InterruptTransfer;
27 namespace IsochronousTransfer = extensions::api::usb::IsochronousTransfer;
28 namespace ReleaseInterface = extensions::api::usb::ReleaseInterface;
29 namespace ResetDevice = extensions::api::usb::ResetDevice;
30 namespace SetInterfaceAlternateSetting =
31 extensions::api::usb::SetInterfaceAlternateSetting;
32 namespace usb = extensions::api::usb; 21 namespace usb = extensions::api::usb;
22 namespace BulkTransfer = usb::BulkTransfer;
23 namespace ClaimInterface = usb::ClaimInterface;
24 namespace ListInterfaces = usb::ListInterfaces;
25 namespace CloseDevice = usb::CloseDevice;
26 namespace ControlTransfer = usb::ControlTransfer;
27 namespace FindDevices = usb::FindDevices;
28 namespace InterruptTransfer = usb::InterruptTransfer;
29 namespace IsochronousTransfer = usb::IsochronousTransfer;
30 namespace ReleaseInterface = usb::ReleaseInterface;
31 namespace ResetDevice = usb::ResetDevice;
32 namespace SetInterfaceAlternateSetting = usb::SetInterfaceAlternateSetting;
33 namespace GetDevices = usb::GetDevices;
34 namespace OpenDevice = usb::OpenDevice;
asargent_no_longer_on_chrome 2013/08/22 21:06:13 nit: can you sort these alphabetically? It would m
Bei Zhang 2013/08/23 22:52:00 Done.
33 35
34 using content::BrowserThread; 36 using content::BrowserThread;
35 using std::string; 37 using std::string;
36 using std::vector; 38 using std::vector;
37 using usb::ControlTransferInfo; 39 using usb::ControlTransferInfo;
38 using usb::Device; 40 using usb::Device;
41 using usb::DeviceHandle;
39 using usb::Direction; 42 using usb::Direction;
40 using usb::EndpointDescriptor; 43 using usb::EndpointDescriptor;
41 using usb::GenericTransferInfo; 44 using usb::GenericTransferInfo;
42 using usb::InterfaceDescriptor; 45 using usb::InterfaceDescriptor;
43 using usb::IsochronousTransferInfo; 46 using usb::IsochronousTransferInfo;
44 using usb::Recipient; 47 using usb::Recipient;
45 using usb::RequestType; 48 using usb::RequestType;
46 using usb::SynchronizationType; 49 using usb::SynchronizationType;
47 using usb::TransferType; 50 using usb::TransferType;
48 using usb::UsageType; 51 using usb::UsageType;
49 52
53 typedef scoped_ptr<std::vector<scoped_refptr<UsbDevice> > > ScopedDeviceVector;
54
50 namespace { 55 namespace {
51 56
52 static const char kDataKey[] = "data"; 57 static const char kDataKey[] = "data";
53 static const char kResultCodeKey[] = "resultCode"; 58 static const char kResultCodeKey[] = "resultCode";
54 59
55 static const char kErrorCancelled[] = "Transfer was cancelled."; 60 static const char kErrorCancelled[] = "Transfer was cancelled.";
56 static const char kErrorDisconnect[] = "Device disconnected."; 61 static const char kErrorDisconnect[] = "Device disconnected.";
57 static const char kErrorGeneric[] = "Transfer failed."; 62 static const char kErrorGeneric[] = "Transfer failed.";
58 static const char kErrorOverflow[] = "Inbound transfer overflow."; 63 static const char kErrorOverflow[] = "Inbound transfer overflow.";
59 static const char kErrorStalled[] = "Transfer stalled."; 64 static const char kErrorStalled[] = "Transfer stalled.";
(...skipping 17 matching lines...) Expand all
77 static const char kErrorPermissionDenied[] = 82 static const char kErrorPermissionDenied[] =
78 "Permission to access device was denied"; 83 "Permission to access device was denied";
79 static const char kErrorInvalidTransferLength[] = "Transfer length must be a " 84 static const char kErrorInvalidTransferLength[] = "Transfer length must be a "
80 "positive number less than 104,857,600."; 85 "positive number less than 104,857,600.";
81 static const char kErrorInvalidNumberOfPackets[] = "Number of packets must be " 86 static const char kErrorInvalidNumberOfPackets[] = "Number of packets must be "
82 "a positive number less than 4,194,304."; 87 "a positive number less than 4,194,304.";
83 static const char kErrorInvalidPacketLength[] = "Packet length must be a " 88 static const char kErrorInvalidPacketLength[] = "Packet length must be a "
84 "positive number less than 65,536."; 89 "positive number less than 65,536.";
85 static const char kErrorResetDevice[] = 90 static const char kErrorResetDevice[] =
86 "Error resetting the device. The device has been closed."; 91 "Error resetting the device. The device has been closed.";
92 static const char kErrorOpen[] = "Failed to open device.";
87 93
88 static const size_t kMaxTransferLength = 100 * 1024 * 1024; 94 static const size_t kMaxTransferLength = 100 * 1024 * 1024;
89 static const int kMaxPackets = 4 * 1024 * 1024; 95 static const int kMaxPackets = 4 * 1024 * 1024;
90 static const int kMaxPacketLength = 64 * 1024; 96 static const int kMaxPacketLength = 64 * 1024;
91 97
92 static UsbDevice* device_for_test_ = NULL; 98 static UsbDevice* device_for_test_ = NULL;
93 99
94 static bool ConvertDirectionToApi(const UsbEndpointDirection& input, 100 static bool ConvertDirectionToApi(const UsbEndpointDirection& input,
95 Direction* output) { 101 Direction* output) {
96 switch (input) { 102 switch (input) {
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
297 UsbTransferStatus status, 303 UsbTransferStatus status,
298 scoped_refptr<net::IOBuffer> data, 304 scoped_refptr<net::IOBuffer> data,
299 size_t length) { 305 size_t length) {
300 base::DictionaryValue* result = new base::DictionaryValue(); 306 base::DictionaryValue* result = new base::DictionaryValue();
301 result->SetInteger(kResultCodeKey, status); 307 result->SetInteger(kResultCodeKey, status);
302 result->Set(kDataKey, base::BinaryValue::CreateWithCopiedBuffer(data->data(), 308 result->Set(kDataKey, base::BinaryValue::CreateWithCopiedBuffer(data->data(),
303 length)); 309 length));
304 return result; 310 return result;
305 } 311 }
306 312
307 static base::Value* PopulateDevice(int handle, int vendor_id, int product_id) { 313 base::Value* PopulateDeviceHandle(int resource_id,
308 Device device; 314 int vendor_id,
309 device.handle = handle; 315 int product_id) {
310 device.vendor_id = vendor_id; 316 DeviceHandle result;
311 device.product_id = product_id; 317 result.handle = resource_id;
312 return device.ToValue().release(); 318 result.vendor_id.reset(new int(vendor_id));
319 result.product_id.reset(new int(product_id));
320 return result.ToValue().release();
313 } 321 }
314 322
315 static base::Value* PopulateInterfaceDescriptor(int interface_number, 323 base::Value* PopulateDevice(UsbDevice* device) {
316 int alternate_setting, int interface_class, int interface_subclass, 324 Device result;
317 int interface_protocol, 325 result.device = device->unique_id();
318 std::vector<linked_ptr<EndpointDescriptor> >* endpoints) { 326 result.vendor_id.reset(new int(device->vendor_id()));
327 result.product_id.reset(new int(device->product_id()));
328 return result.ToValue().release();
329 }
330
331 base::Value* PopulateInterfaceDescriptor(
332 int interface_number,
333 int alternate_setting,
334 int interface_class,
335 int interface_subclass,
336 int interface_protocol,
337 std::vector<linked_ptr<EndpointDescriptor> >* endpoints) {
asargent_no_longer_on_chrome 2013/08/22 21:06:13 nit: It looks like you removed the "static" linkag
Bei Zhang 2013/08/23 22:52:00 Done.
319 InterfaceDescriptor descriptor; 338 InterfaceDescriptor descriptor;
320 descriptor.interface_number = interface_number; 339 descriptor.interface_number = interface_number;
321 descriptor.alternate_setting = alternate_setting; 340 descriptor.alternate_setting = alternate_setting;
322 descriptor.interface_class = interface_class; 341 descriptor.interface_class = interface_class;
323 descriptor.interface_subclass = interface_subclass; 342 descriptor.interface_subclass = interface_subclass;
324 descriptor.interface_protocol = interface_protocol; 343 descriptor.interface_protocol = interface_protocol;
325 descriptor.endpoints = *endpoints; 344 descriptor.endpoints = *endpoints;
326 return descriptor.ToValue().release(); 345 return descriptor.ToValue().release();
327 } 346 }
328 347
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 const bool converted = ConvertRecipient(input, output); 414 const bool converted = ConvertRecipient(input, output);
396 if (!converted) 415 if (!converted)
397 SetError(kErrorConvertRecipient); 416 SetError(kErrorConvertRecipient);
398 return converted; 417 return converted;
399 } 418 }
400 419
401 UsbFindDevicesFunction::UsbFindDevicesFunction() {} 420 UsbFindDevicesFunction::UsbFindDevicesFunction() {}
402 421
403 UsbFindDevicesFunction::~UsbFindDevicesFunction() {} 422 UsbFindDevicesFunction::~UsbFindDevicesFunction() {}
404 423
405 void UsbFindDevicesFunction::SetDeviceForTest(UsbDevice* device) {
406 device_for_test_ = device;
407 }
408
409 bool UsbFindDevicesFunction::Prepare() { 424 bool UsbFindDevicesFunction::Prepare() {
410 parameters_ = FindDevices::Params::Create(*args_); 425 parameters_ = FindDevices::Params::Create(*args_);
411 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); 426 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
412 if (!device_for_test_) 427 if (!device_for_test_)
413 set_work_thread_id(BrowserThread::FILE); 428 set_work_thread_id(BrowserThread::FILE);
414 return true; 429 return true;
415 } 430 }
416 431
417 void UsbFindDevicesFunction::AsyncWorkStart() { 432 void UsbFindDevicesFunction::AsyncWorkStart() {
418 result_.reset(new base::ListValue()); 433 result_.reset(new base::ListValue());
419 434
420 if (device_for_test_) { 435 if (device_for_test_) {
421 UsbDeviceResource* const resource = new UsbDeviceResource( 436 UsbDeviceResource* const resource = new UsbDeviceResource(
422 extension_->id(), 437 extension_->id(),
423 device_for_test_->Open()); 438 device_for_test_->Open());
424 439
425 Device device; 440 Device device;
426 result_->Append(PopulateDevice(manager_->Add(resource), 0, 0)); 441 result_->Append(PopulateDeviceHandle(manager_->Add(resource), 0, 0));
427 SetResult(result_.release()); 442 SetResult(result_.release());
428 AsyncWorkCompleted(); 443 AsyncWorkCompleted();
429 return; 444 return;
430 } 445 }
431 446
432 const uint16_t vendor_id = parameters_->options.vendor_id; 447 const uint16_t vendor_id = parameters_->options.vendor_id;
433 const uint16_t product_id = parameters_->options.product_id; 448 const uint16_t product_id = parameters_->options.product_id;
434 int interface_id = parameters_->options.interface_id.get() ? 449 int interface_id = parameters_->options.interface_id.get() ?
435 *parameters_->options.interface_id.get() : 450 *parameters_->options.interface_id.get() :
436 UsbDevicePermissionData::ANY_INTERFACE; 451 UsbDevicePermissionData::ANY_INTERFACE;
(...skipping 26 matching lines...) Expand all
463 FROM_HERE, 478 FROM_HERE,
464 base::Bind(&UsbFindDevicesFunction::OnCompleted, this)); 479 base::Bind(&UsbFindDevicesFunction::OnCompleted, this));
465 } 480 }
466 481
467 void UsbFindDevicesFunction::OnCompleted() { 482 void UsbFindDevicesFunction::OnCompleted() {
468 for (size_t i = 0; i < device_handles_.size(); ++i) { 483 for (size_t i = 0; i < device_handles_.size(); ++i) {
469 UsbDeviceHandle* const device_handle = device_handles_[i].get(); 484 UsbDeviceHandle* const device_handle = device_handles_[i].get();
470 UsbDeviceResource* const resource = 485 UsbDeviceResource* const resource =
471 new UsbDeviceResource(extension_->id(), device_handle); 486 new UsbDeviceResource(extension_->id(), device_handle);
472 487
473 result_->Append(PopulateDevice(manager_->Add(resource), 488 result_->Append(PopulateDeviceHandle(manager_->Add(resource),
474 parameters_->options.vendor_id, 489 parameters_->options.vendor_id,
475 parameters_->options.product_id)); 490 parameters_->options.product_id));
476 } 491 }
477 492
478 SetResult(result_.release()); 493 SetResult(result_.release());
479 AsyncWorkCompleted(); 494 AsyncWorkCompleted();
480 } 495 }
481 496
497 UsbGetDevicesFunction::UsbGetDevicesFunction() {
498 }
499
500 UsbGetDevicesFunction::~UsbGetDevicesFunction() {
501 }
502
503 void UsbGetDevicesFunction::SetDeviceForTest(UsbDevice* device) {
504 device_for_test_ = device;
505 }
506
507 bool UsbGetDevicesFunction::Prepare() {
508 parameters_ = GetDevices::Params::Create(*args_);
509 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
510 if (!device_for_test_)
511 set_work_thread_id(BrowserThread::FILE);
512 return true;
513 }
514
515 void UsbGetDevicesFunction::AsyncWorkStart() {
516 result_.reset(new base::ListValue());
517
518 if (device_for_test_) {
519 result_->Append(PopulateDevice(device_for_test_));
520 SetResult(result_.release());
521 AsyncWorkCompleted();
522 return;
523 }
524
525 const uint16_t vendor_id = parameters_->options.vendor_id;
526 const uint16_t product_id = parameters_->options.product_id;
527 int interface_id = parameters_->options.interface_id.get() ?
528 *parameters_->options.interface_id.get() :
529 UsbDevicePermissionData::ANY_INTERFACE;
530 UsbDevicePermission::CheckParam param(vendor_id, product_id, interface_id);
531 if (!PermissionsData::CheckAPIPermissionWithParam(
532 GetExtension(), APIPermission::kUsbDevice, &param)) {
533 LOG(WARNING) << "Insufficient permissions to access device.";
534 CompleteWithError(kErrorPermissionDenied);
535 return;
536 }
537
538 UsbService* service = UsbService::GetInstance();
539 service->FindDevices(
540 vendor_id,
541 product_id,
542 interface_id,
543 base::Bind(&UsbGetDevicesFunction::EnumerationCompletedFileThread, this));
544 }
545
546 void UsbGetDevicesFunction::EnumerationCompletedFileThread(
547 scoped_ptr<std::vector<scoped_refptr<UsbDevice> > > devices) {
548 for (size_t i = 0; i < devices->size(); ++i) {
549 result_->Append(PopulateDevice(devices->at(i).get()));
550 }
551
552 SetResult(result_.release());
553 AsyncWorkCompleted();
554 }
555
556 UsbOpenDeviceFunction::UsbOpenDeviceFunction() {}
557
558 UsbOpenDeviceFunction::~UsbOpenDeviceFunction() {}
559
560 bool UsbOpenDeviceFunction::Prepare() {
561 parameters_ = OpenDevice::Params::Create(*args_);
562 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
563 return true;
564 }
565
566 void UsbOpenDeviceFunction::AsyncWorkStart() {
567 BrowserThread::PostTask(BrowserThread::FILE,
568 FROM_HERE,
569 base::Bind(&UsbOpenDeviceFunction::OpenDeviceOnFile,
570 this));
571 }
572
573 void UsbOpenDeviceFunction::OpenDeviceOnFile() {
574 UsbService* service = UsbService::GetInstance();
575 scoped_refptr<UsbDevice> device;
576 if (device_for_test_)
577 device = device_for_test_;
578 else
579 device = service->GetDeviceById(parameters_->device.device);
580
581 if (!device) {
582 SetError(kErrorNoDevice);
583 AsyncWorkCompleted();
584 return;
585 }
586
587 if (!parameters_->device.vendor_id ||
588 *parameters_->device.vendor_id.get() != device->vendor_id()) {
589 SetError(kErrorOpen);
590 AsyncWorkCompleted();
591 return;
592 }
593
594 if (!parameters_->device.product_id ||
595 *parameters_->device.product_id.get() != device->product_id()) {
596 SetError(kErrorOpen);
597 AsyncWorkCompleted();
598 return;
599 }
600
601 handle_ = device->Open();
602 BrowserThread::PostTask(BrowserThread::IO,
603 FROM_HERE,
604 base::Bind(&UsbOpenDeviceFunction::OnCompleted,
605 this));
606 }
607
608 void UsbOpenDeviceFunction::OnCompleted() {
609 if (!handle_) {
610 SetError(kErrorOpen);
611 AsyncWorkCompleted();
612 return;
613 }
614
615 SetResult(PopulateDeviceHandle(
asargent_no_longer_on_chrome 2013/08/22 21:06:13 If the device handle could live on the FILE thread
Bei Zhang 2013/08/23 22:52:00 This is addressed by another CL. On 2013/08/22 21
616 manager_->Add(new UsbDeviceResource(extension_->id(), handle_)),
617 handle_->device()->vendor_id(),
618 handle_->device()->product_id()));
619 AsyncWorkCompleted();
620 }
621
482 UsbListInterfacesFunction::UsbListInterfacesFunction() {} 622 UsbListInterfacesFunction::UsbListInterfacesFunction() {}
483 623
484 UsbListInterfacesFunction::~UsbListInterfacesFunction() {} 624 UsbListInterfacesFunction::~UsbListInterfacesFunction() {}
485 625
486 bool UsbListInterfacesFunction::Prepare() { 626 bool UsbListInterfacesFunction::Prepare() {
487 parameters_ = ListInterfaces::Params::Create(*args_); 627 parameters_ = ListInterfaces::Params::Create(*args_);
488 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); 628 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
489 return true; 629 return true;
490 } 630 }
491 631
(...skipping 531 matching lines...) Expand 10 before | Expand all | Expand 10 after
1023 } 1163 }
1024 1164
1025 void UsbResetDeviceFunction::OnError() { 1165 void UsbResetDeviceFunction::OnError() {
1026 RemoveUsbDeviceResource(parameters_->device.handle); 1166 RemoveUsbDeviceResource(parameters_->device.handle);
1027 SetError(kErrorResetDevice); 1167 SetError(kErrorResetDevice);
1028 SetResult(new base::FundamentalValue(false)); 1168 SetResult(new base::FundamentalValue(false));
1029 AsyncWorkCompleted(); 1169 AsyncWorkCompleted();
1030 } 1170 }
1031 1171
1032 } // namespace extensions 1172 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698