| 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 323f6bf22a4bdf33854dfb2ae0511bd3e902b83b..d118621744dd6eadc21dc0b004088ba609f4639c 100644
|
| --- a/chrome/browser/extensions/api/usb/usb_api.cc
|
| +++ b/chrome/browser/extensions/api/usb/usb_api.cc
|
| @@ -23,6 +23,7 @@ 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 OpenDevice = extensions::api::usb::OpenDevice;
|
| namespace InterruptTransfer = extensions::api::usb::InterruptTransfer;
|
| namespace IsochronousTransfer = extensions::api::usb::IsochronousTransfer;
|
| namespace ReleaseInterface = extensions::api::usb::ReleaseInterface;
|
| @@ -35,6 +36,7 @@ using std::string;
|
| using std::vector;
|
| using usb::ControlTransferInfo;
|
| using usb::Device;
|
| +using usb::DeviceHandle;
|
| using usb::Direction;
|
| using usb::EndpointDescriptor;
|
| using usb::GenericTransferInfo;
|
| @@ -88,7 +90,7 @@ static const size_t kMaxTransferLength = 100 * 1024 * 1024;
|
| static const int kMaxPackets = 4 * 1024 * 1024;
|
| static const int kMaxPacketLength = 64 * 1024;
|
|
|
| -static UsbDevice* device_for_test_ = NULL;
|
| +static UsbDeviceHandle* device_for_test_ = NULL;
|
|
|
| static bool ConvertDirectionToApi(const UsbEndpointDirection& input,
|
| Direction* output) {
|
| @@ -183,19 +185,19 @@ static bool ConvertDirection(const Direction& input,
|
| }
|
|
|
| static bool ConvertRequestType(const RequestType& input,
|
| - UsbDevice::TransferRequestType* output) {
|
| + UsbDeviceHandle::TransferRequestType* output) {
|
| switch (input) {
|
| case usb::REQUEST_TYPE_STANDARD:
|
| - *output = UsbDevice::STANDARD;
|
| + *output = UsbDeviceHandle::STANDARD;
|
| return true;
|
| case usb::REQUEST_TYPE_CLASS:
|
| - *output = UsbDevice::CLASS;
|
| + *output = UsbDeviceHandle::CLASS;
|
| return true;
|
| case usb::REQUEST_TYPE_VENDOR:
|
| - *output = UsbDevice::VENDOR;
|
| + *output = UsbDeviceHandle::VENDOR;
|
| return true;
|
| case usb::REQUEST_TYPE_RESERVED:
|
| - *output = UsbDevice::RESERVED;
|
| + *output = UsbDeviceHandle::RESERVED;
|
| return true;
|
| default:
|
| NOTREACHED();
|
| @@ -204,19 +206,19 @@ static bool ConvertRequestType(const RequestType& input,
|
| }
|
|
|
| static bool ConvertRecipient(const Recipient& input,
|
| - UsbDevice::TransferRecipient* output) {
|
| + UsbDeviceHandle::TransferRecipient* output) {
|
| switch (input) {
|
| case usb::RECIPIENT_DEVICE:
|
| - *output = UsbDevice::DEVICE;
|
| + *output = UsbDeviceHandle::DEVICE;
|
| return true;
|
| case usb::RECIPIENT_INTERFACE:
|
| - *output = UsbDevice::INTERFACE;
|
| + *output = UsbDeviceHandle::INTERFACE;
|
| return true;
|
| case usb::RECIPIENT_ENDPOINT:
|
| - *output = UsbDevice::ENDPOINT;
|
| + *output = UsbDeviceHandle::ENDPOINT;
|
| return true;
|
| case usb::RECIPIENT_OTHER:
|
| - *output = UsbDevice::OTHER;
|
| + *output = UsbDeviceHandle::OTHER;
|
| return true;
|
| default:
|
| NOTREACHED();
|
| @@ -298,14 +300,18 @@ static base::DictionaryValue* CreateTransferInfo(
|
| size_t length) {
|
| base::DictionaryValue* result = new base::DictionaryValue();
|
| result->SetInteger(kResultCodeKey, status);
|
| - result->Set(kDataKey, base::BinaryValue::CreateWithCopiedBuffer(data->data(),
|
| - length));
|
| + if (data.get()) {
|
| + result->Set(
|
| + kDataKey,
|
| + base::BinaryValue::CreateWithCopiedBuffer(data->data(), length));
|
| + }
|
| return result;
|
| }
|
|
|
| -static base::Value* PopulateDevice(int handle, int vendor_id, int product_id) {
|
| +static base::Value* PopulateDevice(
|
| + int device_id, int vendor_id, int product_id) {
|
| Device device;
|
| - device.handle = handle;
|
| + device.device = device_id;
|
| device.vendor_id = vendor_id;
|
| device.product_id = product_id;
|
| return device.ToValue().release();
|
| @@ -347,7 +353,26 @@ bool UsbAsyncApiFunction::Respond() {
|
|
|
| UsbDeviceResource* UsbAsyncApiFunction::GetUsbDeviceResource(
|
| int api_resource_id) {
|
| - return manager_->Get(extension_->id(), api_resource_id);
|
| + UsbDeviceResource* resource =
|
| + manager_->Get(extension_->id(), api_resource_id);
|
| +
|
| + if (resource == NULL)
|
| + return NULL;
|
| +
|
| + if (device_for_test_) {
|
| + return resource;
|
| + }
|
| +
|
| + // TODO(ikarienator): Instead of doing this check and release the object
|
| + // lazily, find a way to inform the ApiResourceManager from the resource that
|
| + // a it is closed.
|
| + if (resource->device()->handle() == NULL) {
|
| + // If the device handle is closed, then remove the resource.
|
| + manager_->Remove(extension_->id(), api_resource_id);
|
| + return NULL;
|
| + }
|
| +
|
| + return resource;
|
| }
|
|
|
| void UsbAsyncApiFunction::RemoveUsbDeviceResource(int api_resource_id) {
|
| @@ -382,7 +407,7 @@ bool UsbAsyncApiTransferFunction::ConvertDirectionSafely(
|
| }
|
|
|
| bool UsbAsyncApiTransferFunction::ConvertRequestTypeSafely(
|
| - const RequestType& input, UsbDevice::TransferRequestType* output) {
|
| + const RequestType& input, UsbDeviceHandle::TransferRequestType* output) {
|
| const bool converted = ConvertRequestType(input, output);
|
| if (!converted)
|
| SetError(kErrorConvertRequestType);
|
| @@ -390,21 +415,32 @@ bool UsbAsyncApiTransferFunction::ConvertRequestTypeSafely(
|
| }
|
|
|
| bool UsbAsyncApiTransferFunction::ConvertRecipientSafely(
|
| - const Recipient& input, UsbDevice::TransferRecipient* output) {
|
| + const Recipient& input, UsbDeviceHandle::TransferRecipient* output) {
|
| const bool converted = ConvertRecipient(input, output);
|
| if (!converted)
|
| SetError(kErrorConvertRecipient);
|
| return converted;
|
| }
|
|
|
| -UsbFindDevicesFunction::UsbFindDevicesFunction() {}
|
| +UsbFindDevicesFunction::UsbFindDevicesFunction()
|
| + : service_(NULL) {}
|
|
|
| UsbFindDevicesFunction::~UsbFindDevicesFunction() {}
|
|
|
| -void UsbFindDevicesFunction::SetDeviceForTest(UsbDevice* device) {
|
| +void UsbFindDevicesFunction::SetDeviceForTest(UsbDeviceHandle* device) {
|
| device_for_test_ = device;
|
| }
|
|
|
| +bool UsbFindDevicesFunction::PrePrepare() {
|
| + service_ = UsbServiceFactory::GetInstance()->GetForProfile(profile());
|
| + if (service_ == NULL) {
|
| + LOG(WARNING) << "Could not get UsbService for active profile.";
|
| + SetError(kErrorNoDevice);
|
| + return false;
|
| + }
|
| + return UsbAsyncApiFunction::PrePrepare();
|
| +}
|
| +
|
| bool UsbFindDevicesFunction::Prepare() {
|
| parameters_ = FindDevices::Params::Create(*args_);
|
| EXTENSION_FUNCTION_VALIDATE(parameters_.get());
|
| @@ -415,12 +451,8 @@ void UsbFindDevicesFunction::AsyncWorkStart() {
|
| result_.reset(new base::ListValue());
|
|
|
| if (device_for_test_) {
|
| - UsbDeviceResource* const resource = new UsbDeviceResource(
|
| - extension_->id(),
|
| - device_for_test_);
|
| -
|
| Device device;
|
| - result_->Append(PopulateDevice(manager_->Add(resource), 0, 0));
|
| + result_->Append(PopulateDevice(device_for_test_->device(), 0, 0));
|
| SetResult(result_.release());
|
| AsyncWorkCompleted();
|
| return;
|
| @@ -439,26 +471,18 @@ void UsbFindDevicesFunction::AsyncWorkStart() {
|
| return;
|
| }
|
|
|
| - UsbService* const service = UsbServiceFactory::GetInstance()->GetForProfile(
|
| - profile());
|
| - if (!service) {
|
| - LOG(WARNING) << "Could not get UsbService for active profile.";
|
| - CompleteWithError(kErrorNoDevice);
|
| - return;
|
| - }
|
| -
|
| - service->FindDevices(vendor_id, product_id, interface_id, &devices_,
|
| - base::Bind(&UsbFindDevicesFunction::OnCompleted, this));
|
| + BrowserThread::PostTask(
|
| + BrowserThread::FILE,
|
| + FROM_HERE,
|
| + base::Bind(&UsbService::FindDevices,
|
| + base::Unretained(service_),
|
| + vendor_id, product_id, interface_id, &devices_,
|
| + base::Bind(&UsbFindDevicesFunction::OnCompleted, this)));
|
| }
|
|
|
| void UsbFindDevicesFunction::OnCompleted() {
|
| for (size_t i = 0; i < devices_.size(); ++i) {
|
| - UsbDevice* const device = devices_[i].get();
|
| - UsbDeviceResource* const resource =
|
| - new UsbDeviceResource(extension_->id(), device);
|
| -
|
| - Device js_device;
|
| - result_->Append(PopulateDevice(manager_->Add(resource),
|
| + result_->Append(PopulateDevice(devices_[i],
|
| parameters_->options.vendor_id,
|
| parameters_->options.product_id));
|
| }
|
| @@ -467,6 +491,72 @@ void UsbFindDevicesFunction::OnCompleted() {
|
| AsyncWorkCompleted();
|
| }
|
|
|
| +UsbOpenDeviceFunction::UsbOpenDeviceFunction() : service_(NULL) {}
|
| +
|
| +UsbOpenDeviceFunction::~UsbOpenDeviceFunction() {}
|
| +
|
| +bool UsbOpenDeviceFunction::PrePrepare() {
|
| + service_ = UsbServiceFactory::GetInstance()->GetForProfile(profile());
|
| + if (service_ == NULL) {
|
| + LOG(WARNING) << "Could not get UsbService for active profile.";
|
| + SetError(kErrorNoDevice);
|
| + return false;
|
| + }
|
| + return UsbAsyncApiFunction::PrePrepare();
|
| +}
|
| +
|
| +bool UsbOpenDeviceFunction::Prepare() {
|
| + parameters_ = OpenDevice::Params::Create(*args_);
|
| + EXTENSION_FUNCTION_VALIDATE(parameters_.get());
|
| + return true;
|
| +}
|
| +
|
| +void UsbOpenDeviceFunction::AsyncWorkStart() {
|
| + if (device_for_test_) {
|
| + DeviceHandle handle;
|
| + UsbDeviceResource* const resource = new UsbDeviceResource(
|
| + extension_->id(),
|
| + device_for_test_);
|
| + handle.handle = manager_->Add(resource);
|
| + SetResult(handle.ToValue().release());
|
| + AsyncWorkCompleted();
|
| + return;
|
| + }
|
| + BrowserThread::PostTask(
|
| + BrowserThread::FILE,
|
| + FROM_HERE,
|
| + base::Bind(&UsbService::OpenDevice,
|
| + base::Unretained(service_),
|
| + parameters_->device.device,
|
| + base::Bind(
|
| + &UsbOpenDeviceFunction::OnOpened,
|
| + this)));
|
| +}
|
| +
|
| +void UsbOpenDeviceFunction::OnOpened(scoped_refptr<UsbDeviceHandle> handle) {
|
| + if (!handle.get()) {
|
| + CompleteWithError(kErrorDisconnect);
|
| + return;
|
| + }
|
| + BrowserThread::PostTask(
|
| + BrowserThread::IO,
|
| + FROM_HERE,
|
| + base::Bind(&UsbOpenDeviceFunction::OnCompleted,
|
| + this,
|
| + handle));
|
| +}
|
| +
|
| +void UsbOpenDeviceFunction::OnCompleted(scoped_refptr<UsbDeviceHandle> handle) {
|
| + UsbDeviceResource* const resource = new UsbDeviceResource(
|
| + extension_->id(),
|
| + handle);
|
| + DeviceHandle result;
|
| + result.handle = manager_->Add(resource);
|
| + SetResult(result.ToValue().release());
|
| + AsyncWorkCompleted();
|
| + return;
|
| +}
|
| +
|
| UsbListInterfacesFunction::UsbListInterfacesFunction() {}
|
|
|
| UsbListInterfacesFunction::~UsbListInterfacesFunction() {}
|
| @@ -479,7 +569,7 @@ bool UsbListInterfacesFunction::Prepare() {
|
|
|
| void UsbListInterfacesFunction::AsyncWorkStart() {
|
| UsbDeviceResource* const resource = GetUsbDeviceResource(
|
| - parameters_->device.handle);
|
| + parameters_->handle.handle);
|
| if (!resource) {
|
| CompleteWithError(kErrorNoDevice);
|
| return;
|
| @@ -604,15 +694,15 @@ bool UsbCloseDeviceFunction::Prepare() {
|
|
|
| void UsbCloseDeviceFunction::AsyncWorkStart() {
|
| UsbDeviceResource* const resource = GetUsbDeviceResource(
|
| - parameters_->device.handle);
|
| + parameters_->handle.handle);
|
| if (!resource) {
|
| CompleteWithError(kErrorNoDevice);
|
| return;
|
| }
|
|
|
| - resource->device()->Close(base::Bind(&UsbCloseDeviceFunction::OnCompleted,
|
| - this));
|
| - RemoveUsbDeviceResource(parameters_->device.handle);
|
| + resource->device()->Close(
|
| + base::Bind(&UsbCloseDeviceFunction::OnCompleted, this));
|
| + RemoveUsbDeviceResource(parameters_->handle.handle);
|
| }
|
|
|
| void UsbCloseDeviceFunction::OnCompleted() {
|
| @@ -631,7 +721,7 @@ bool UsbClaimInterfaceFunction::Prepare() {
|
|
|
| void UsbClaimInterfaceFunction::AsyncWorkStart() {
|
| UsbDeviceResource* resource =
|
| - GetUsbDeviceResource(parameters_->device.handle);
|
| + GetUsbDeviceResource(parameters_->handle.handle);
|
| if (!resource) {
|
| CompleteWithError(kErrorNoDevice);
|
| return;
|
| @@ -659,7 +749,7 @@ bool UsbReleaseInterfaceFunction::Prepare() {
|
|
|
| void UsbReleaseInterfaceFunction::AsyncWorkStart() {
|
| UsbDeviceResource* resource =
|
| - GetUsbDeviceResource(parameters_->device.handle);
|
| + GetUsbDeviceResource(parameters_->handle.handle);
|
| if (!resource) {
|
| CompleteWithError(kErrorNoDevice);
|
| return;
|
| @@ -689,7 +779,7 @@ bool UsbSetInterfaceAlternateSettingFunction::Prepare() {
|
|
|
| void UsbSetInterfaceAlternateSettingFunction::AsyncWorkStart() {
|
| UsbDeviceResource* resource =
|
| - GetUsbDeviceResource(parameters_->device.handle);
|
| + GetUsbDeviceResource(parameters_->handle.handle);
|
| if (!resource) {
|
| CompleteWithError(kErrorNoDevice);
|
| return;
|
| @@ -719,7 +809,7 @@ bool UsbControlTransferFunction::Prepare() {
|
|
|
| void UsbControlTransferFunction::AsyncWorkStart() {
|
| UsbDeviceResource* const resource = GetUsbDeviceResource(
|
| - parameters_->device.handle);
|
| + parameters_->handle.handle);
|
| if (!resource) {
|
| CompleteWithError(kErrorNoDevice);
|
| return;
|
| @@ -728,8 +818,8 @@ void UsbControlTransferFunction::AsyncWorkStart() {
|
| const ControlTransferInfo& transfer = parameters_->transfer_info;
|
|
|
| UsbEndpointDirection direction;
|
| - UsbDevice::TransferRequestType request_type;
|
| - UsbDevice::TransferRecipient recipient;
|
| + UsbDeviceHandle::TransferRequestType request_type;
|
| + UsbDeviceHandle::TransferRecipient recipient;
|
| size_t size = 0;
|
|
|
| if (!ConvertDirectionSafely(transfer.direction, &direction) ||
|
| @@ -776,7 +866,7 @@ bool UsbBulkTransferFunction::Prepare() {
|
|
|
| void UsbBulkTransferFunction::AsyncWorkStart() {
|
| UsbDeviceResource* const resource = GetUsbDeviceResource(
|
| - parameters_->device.handle);
|
| + parameters_->handle.handle);
|
| if (!resource) {
|
| CompleteWithError(kErrorNoDevice);
|
| return;
|
| @@ -825,7 +915,7 @@ bool UsbInterruptTransferFunction::Prepare() {
|
|
|
| void UsbInterruptTransferFunction::AsyncWorkStart() {
|
| UsbDeviceResource* const resource = GetUsbDeviceResource(
|
| - parameters_->device.handle);
|
| + parameters_->handle.handle);
|
| if (!resource) {
|
| CompleteWithError(kErrorNoDevice);
|
| return;
|
| @@ -874,7 +964,7 @@ bool UsbIsochronousTransferFunction::Prepare() {
|
|
|
| void UsbIsochronousTransferFunction::AsyncWorkStart() {
|
| UsbDeviceResource* const resource = GetUsbDeviceResource(
|
| - parameters_->device.handle);
|
| + parameters_->handle.handle);
|
| if (!resource) {
|
| CompleteWithError(kErrorNoDevice);
|
| return;
|
| @@ -941,7 +1031,7 @@ bool UsbResetDeviceFunction::Prepare() {
|
|
|
| void UsbResetDeviceFunction::AsyncWorkStart() {
|
| UsbDeviceResource* const resource = GetUsbDeviceResource(
|
| - parameters_->device.handle);
|
| + parameters_->handle.handle);
|
| if (!resource) {
|
| CompleteWithError(kErrorNoDevice);
|
| return;
|
| @@ -970,7 +1060,7 @@ void UsbResetDeviceFunction::OnCompleted(bool success) {
|
| DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
|
| if (!success) {
|
| UsbDeviceResource* const resource = GetUsbDeviceResource(
|
| - parameters_->device.handle);
|
| + parameters_->handle.handle);
|
| if (!resource) {
|
| CompleteWithError(kErrorNoDevice);
|
| return;
|
| @@ -986,7 +1076,7 @@ void UsbResetDeviceFunction::OnCompleted(bool success) {
|
| }
|
|
|
| void UsbResetDeviceFunction::OnError() {
|
| - RemoveUsbDeviceResource(parameters_->device.handle);
|
| + RemoveUsbDeviceResource(parameters_->handle.handle);
|
| SetError(kErrorResetDevice);
|
| SetResult(Value::CreateBooleanValue(false));
|
| AsyncWorkCompleted();
|
|
|