Chromium Code Reviews| 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() {} |