Index: chrome/browser/extensions/api/usb/usb_api.cc |
diff --git a/chrome/browser/extensions/api/usb/usb_api.cc b/chrome/browser/extensions/api/usb/usb_api.cc |
index b6a54d2f0813aa6b2b01d075997268ea737cbba9..259ecfb63f8592cddffad274e84b21baf93d7c08 100644 |
--- a/chrome/browser/extensions/api/usb/usb_api.cc |
+++ b/chrome/browser/extensions/api/usb/usb_api.cc |
@@ -8,6 +8,7 @@ |
#include <vector> |
#include "base/memory/scoped_ptr.h" |
+#include "base/message_loop/message_loop_proxy.h" |
#include "chrome/browser/extensions/api/usb/usb_device_resource.h" |
#include "chrome/browser/extensions/extension_system.h" |
#include "chrome/browser/profiles/profile.h" |
@@ -17,25 +18,27 @@ |
#include "chrome/common/extensions/permissions/permissions_data.h" |
#include "chrome/common/extensions/permissions/usb_device_permission.h" |
-namespace BulkTransfer = extensions::api::usb::BulkTransfer; |
-namespace ClaimInterface = extensions::api::usb::ClaimInterface; |
-namespace ListInterfaces = extensions::api::usb::ListInterfaces; |
-namespace CloseDevice = extensions::api::usb::CloseDevice; |
-namespace ControlTransfer = extensions::api::usb::ControlTransfer; |
-namespace FindDevices = extensions::api::usb::FindDevices; |
-namespace InterruptTransfer = extensions::api::usb::InterruptTransfer; |
-namespace IsochronousTransfer = extensions::api::usb::IsochronousTransfer; |
-namespace ReleaseInterface = extensions::api::usb::ReleaseInterface; |
-namespace ResetDevice = extensions::api::usb::ResetDevice; |
-namespace SetInterfaceAlternateSetting = |
- extensions::api::usb::SetInterfaceAlternateSetting; |
namespace usb = extensions::api::usb; |
+namespace BulkTransfer = usb::BulkTransfer; |
+namespace ClaimInterface = usb::ClaimInterface; |
+namespace ListInterfaces = usb::ListInterfaces; |
+namespace CloseDevice = usb::CloseDevice; |
+namespace ControlTransfer = usb::ControlTransfer; |
+namespace FindDevices = usb::FindDevices; |
+namespace InterruptTransfer = usb::InterruptTransfer; |
+namespace IsochronousTransfer = usb::IsochronousTransfer; |
+namespace ReleaseInterface = usb::ReleaseInterface; |
+namespace ResetDevice = usb::ResetDevice; |
+namespace SetInterfaceAlternateSetting = usb::SetInterfaceAlternateSetting; |
+namespace GetDevices = usb::GetDevices; |
+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.
|
using content::BrowserThread; |
using std::string; |
using std::vector; |
using usb::ControlTransferInfo; |
using usb::Device; |
+using usb::DeviceHandle; |
using usb::Direction; |
using usb::EndpointDescriptor; |
using usb::GenericTransferInfo; |
@@ -47,6 +50,8 @@ using usb::SynchronizationType; |
using usb::TransferType; |
using usb::UsageType; |
+typedef scoped_ptr<std::vector<scoped_refptr<UsbDevice> > > ScopedDeviceVector; |
+ |
namespace { |
static const char kDataKey[] = "data"; |
@@ -84,6 +89,7 @@ static const char kErrorInvalidPacketLength[] = "Packet length must be a " |
"positive number less than 65,536."; |
static const char kErrorResetDevice[] = |
"Error resetting the device. The device has been closed."; |
+static const char kErrorOpen[] = "Failed to open device."; |
static const size_t kMaxTransferLength = 100 * 1024 * 1024; |
static const int kMaxPackets = 4 * 1024 * 1024; |
@@ -304,18 +310,31 @@ static base::DictionaryValue* CreateTransferInfo( |
return result; |
} |
-static base::Value* PopulateDevice(int handle, int vendor_id, int product_id) { |
- Device device; |
- device.handle = handle; |
- device.vendor_id = vendor_id; |
- device.product_id = product_id; |
- return device.ToValue().release(); |
+base::Value* PopulateDeviceHandle(int resource_id, |
+ int vendor_id, |
+ int product_id) { |
+ DeviceHandle result; |
+ result.handle = resource_id; |
+ result.vendor_id.reset(new int(vendor_id)); |
+ result.product_id.reset(new int(product_id)); |
+ return result.ToValue().release(); |
+} |
+ |
+base::Value* PopulateDevice(UsbDevice* device) { |
+ Device result; |
+ result.device = device->unique_id(); |
+ result.vendor_id.reset(new int(device->vendor_id())); |
+ result.product_id.reset(new int(device->product_id())); |
+ return result.ToValue().release(); |
} |
-static base::Value* PopulateInterfaceDescriptor(int interface_number, |
- int alternate_setting, int interface_class, int interface_subclass, |
- int interface_protocol, |
- std::vector<linked_ptr<EndpointDescriptor> >* endpoints) { |
+base::Value* PopulateInterfaceDescriptor( |
+ int interface_number, |
+ int alternate_setting, |
+ int interface_class, |
+ int interface_subclass, |
+ int interface_protocol, |
+ 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.
|
InterfaceDescriptor descriptor; |
descriptor.interface_number = interface_number; |
descriptor.alternate_setting = alternate_setting; |
@@ -402,10 +421,6 @@ UsbFindDevicesFunction::UsbFindDevicesFunction() {} |
UsbFindDevicesFunction::~UsbFindDevicesFunction() {} |
-void UsbFindDevicesFunction::SetDeviceForTest(UsbDevice* device) { |
- device_for_test_ = device; |
-} |
- |
bool UsbFindDevicesFunction::Prepare() { |
parameters_ = FindDevices::Params::Create(*args_); |
EXTENSION_FUNCTION_VALIDATE(parameters_.get()); |
@@ -423,7 +438,7 @@ void UsbFindDevicesFunction::AsyncWorkStart() { |
device_for_test_->Open()); |
Device device; |
- result_->Append(PopulateDevice(manager_->Add(resource), 0, 0)); |
+ result_->Append(PopulateDeviceHandle(manager_->Add(resource), 0, 0)); |
SetResult(result_.release()); |
AsyncWorkCompleted(); |
return; |
@@ -470,7 +485,7 @@ void UsbFindDevicesFunction::OnCompleted() { |
UsbDeviceResource* const resource = |
new UsbDeviceResource(extension_->id(), device_handle); |
- result_->Append(PopulateDevice(manager_->Add(resource), |
+ result_->Append(PopulateDeviceHandle(manager_->Add(resource), |
parameters_->options.vendor_id, |
parameters_->options.product_id)); |
} |
@@ -479,6 +494,131 @@ void UsbFindDevicesFunction::OnCompleted() { |
AsyncWorkCompleted(); |
} |
+UsbGetDevicesFunction::UsbGetDevicesFunction() { |
+} |
+ |
+UsbGetDevicesFunction::~UsbGetDevicesFunction() { |
+} |
+ |
+void UsbGetDevicesFunction::SetDeviceForTest(UsbDevice* device) { |
+ device_for_test_ = device; |
+} |
+ |
+bool UsbGetDevicesFunction::Prepare() { |
+ parameters_ = GetDevices::Params::Create(*args_); |
+ EXTENSION_FUNCTION_VALIDATE(parameters_.get()); |
+ if (!device_for_test_) |
+ set_work_thread_id(BrowserThread::FILE); |
+ return true; |
+} |
+ |
+void UsbGetDevicesFunction::AsyncWorkStart() { |
+ result_.reset(new base::ListValue()); |
+ |
+ if (device_for_test_) { |
+ result_->Append(PopulateDevice(device_for_test_)); |
+ SetResult(result_.release()); |
+ AsyncWorkCompleted(); |
+ return; |
+ } |
+ |
+ const uint16_t vendor_id = parameters_->options.vendor_id; |
+ const uint16_t product_id = parameters_->options.product_id; |
+ int interface_id = parameters_->options.interface_id.get() ? |
+ *parameters_->options.interface_id.get() : |
+ UsbDevicePermissionData::ANY_INTERFACE; |
+ UsbDevicePermission::CheckParam param(vendor_id, product_id, interface_id); |
+ if (!PermissionsData::CheckAPIPermissionWithParam( |
+ GetExtension(), APIPermission::kUsbDevice, ¶m)) { |
+ LOG(WARNING) << "Insufficient permissions to access device."; |
+ CompleteWithError(kErrorPermissionDenied); |
+ return; |
+ } |
+ |
+ UsbService* service = UsbService::GetInstance(); |
+ service->FindDevices( |
+ vendor_id, |
+ product_id, |
+ interface_id, |
+ base::Bind(&UsbGetDevicesFunction::EnumerationCompletedFileThread, this)); |
+} |
+ |
+void UsbGetDevicesFunction::EnumerationCompletedFileThread( |
+ scoped_ptr<std::vector<scoped_refptr<UsbDevice> > > devices) { |
+ for (size_t i = 0; i < devices->size(); ++i) { |
+ result_->Append(PopulateDevice(devices->at(i).get())); |
+ } |
+ |
+ SetResult(result_.release()); |
+ AsyncWorkCompleted(); |
+} |
+ |
+UsbOpenDeviceFunction::UsbOpenDeviceFunction() {} |
+ |
+UsbOpenDeviceFunction::~UsbOpenDeviceFunction() {} |
+ |
+bool UsbOpenDeviceFunction::Prepare() { |
+ parameters_ = OpenDevice::Params::Create(*args_); |
+ EXTENSION_FUNCTION_VALIDATE(parameters_.get()); |
+ return true; |
+} |
+ |
+void UsbOpenDeviceFunction::AsyncWorkStart() { |
+ BrowserThread::PostTask(BrowserThread::FILE, |
+ FROM_HERE, |
+ base::Bind(&UsbOpenDeviceFunction::OpenDeviceOnFile, |
+ this)); |
+} |
+ |
+void UsbOpenDeviceFunction::OpenDeviceOnFile() { |
+ UsbService* service = UsbService::GetInstance(); |
+ scoped_refptr<UsbDevice> device; |
+ if (device_for_test_) |
+ device = device_for_test_; |
+ else |
+ device = service->GetDeviceById(parameters_->device.device); |
+ |
+ if (!device) { |
+ SetError(kErrorNoDevice); |
+ AsyncWorkCompleted(); |
+ return; |
+ } |
+ |
+ if (!parameters_->device.vendor_id || |
+ *parameters_->device.vendor_id.get() != device->vendor_id()) { |
+ SetError(kErrorOpen); |
+ AsyncWorkCompleted(); |
+ return; |
+ } |
+ |
+ if (!parameters_->device.product_id || |
+ *parameters_->device.product_id.get() != device->product_id()) { |
+ SetError(kErrorOpen); |
+ AsyncWorkCompleted(); |
+ return; |
+ } |
+ |
+ handle_ = device->Open(); |
+ BrowserThread::PostTask(BrowserThread::IO, |
+ FROM_HERE, |
+ base::Bind(&UsbOpenDeviceFunction::OnCompleted, |
+ this)); |
+} |
+ |
+void UsbOpenDeviceFunction::OnCompleted() { |
+ if (!handle_) { |
+ SetError(kErrorOpen); |
+ AsyncWorkCompleted(); |
+ return; |
+ } |
+ |
+ 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
|
+ manager_->Add(new UsbDeviceResource(extension_->id(), handle_)), |
+ handle_->device()->vendor_id(), |
+ handle_->device()->product_id())); |
+ AsyncWorkCompleted(); |
+} |
+ |
UsbListInterfacesFunction::UsbListInterfacesFunction() {} |
UsbListInterfacesFunction::~UsbListInterfacesFunction() {} |