OLD | NEW |
---|---|
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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, ¶m)) { | |
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 Loading... | |
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 |
OLD | NEW |