1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/api/hid/hid_api.h"
10 #include "chrome/browser/extensions/api/api_resource_manager.h"
11 #include "chrome/browser/extensions/api/hid/hid_device_resource.h"
12 #include "chrome/common/extensions/api/hid.h"
13 #include "chrome/common/extensions/permissions/usb_device_permission.h"
14 #include "device/hid/hid_connection.h"
15 #include "device/hid/hid_device_info.h"
16 #include "device/hid/hid_service.h"
17 #include "extensions/common/permissions/permissions_data.h"
18 #include "net/base/io_buffer.h"
20 namespace hid = extensions::api::hid;
22 using device::HidConnection;
23 using device::HidService;
24 using device::HidDeviceInfo;
28 const char kErrorPermissionDenied[] = "Permission to access device was denied.";
29 const char kErrorServiceFailed[] = "HID service failed be created.";
30 const char kErrorDeviceNotFound[] = "HID device not found.";
31 const char kErrorFailedToOpenDevice[] = "Failed to open HID device.";
32 const char kErrorConnectionNotFound[] = "Connection not established.";
33 const char kErrorTransfer[] = "Transfer failed.";
35 base::Value* PopulateHidDevice(const HidDeviceInfo& info) {
36 hid::HidDeviceInfo device_info;
37 device_info.path = info.device_id;
38 device_info.product_id = info.product_id;
39 device_info.vendor_id = info.vendor_id;
40 return device_info.ToValue().release();
43 base::Value* PopulateHidConnection(int connection_id,
44 scoped_refptr<HidConnection> connection) {
45 hid::HidConnectInfo connection_value;
46 connection_value.connection_id = connection_id;
47 return connection_value.ToValue().release();
52 namespace extensions {
54 HidAsyncApiFunction::HidAsyncApiFunction() : manager_(NULL) {
57 HidAsyncApiFunction::~HidAsyncApiFunction() {}
59 bool HidAsyncApiFunction::PrePrepare() {
60 manager_ = ApiResourceManager<HidConnectionResource>::Get(GetProfile());
61 if (!manager_) return false;
62 set_work_thread_id(content::BrowserThread::FILE);
66 bool HidAsyncApiFunction::Respond() { return error_.empty(); }
68 HidConnectionResource* HidAsyncApiFunction::GetHidConnectionResource(
69 int api_resource_id) {
70 return manager_->Get(extension_->id(), api_resource_id);
73 void HidAsyncApiFunction::RemoveHidConnectionResource(int api_resource_id) {
74 manager_->Remove(extension_->id(), api_resource_id);
77 void HidAsyncApiFunction::CompleteWithError(const std::string& error) {
82 HidGetDevicesFunction::HidGetDevicesFunction() {}
84 HidGetDevicesFunction::~HidGetDevicesFunction() {}
86 bool HidGetDevicesFunction::Prepare() {
87 parameters_ = hid::GetDevices::Params::Create(*args_);
88 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
92 void HidGetDevicesFunction::AsyncWorkStart() {
93 const uint16_t vendor_id = parameters_->options.vendor_id;
94 const uint16_t product_id = parameters_->options.product_id;
95 UsbDevicePermission::CheckParam param(
96 vendor_id, product_id, UsbDevicePermissionData::UNSPECIFIED_INTERFACE);
97 if (!PermissionsData::CheckAPIPermissionWithParam(
98 GetExtension(), APIPermission::kUsbDevice, ¶m)) {
99 LOG(WARNING) << "Insufficient permissions to access device.";
100 CompleteWithError(kErrorPermissionDenied);
104 HidService* service = HidService::GetInstance();
106 CompleteWithError(kErrorServiceFailed);
109 std::vector<HidDeviceInfo> devices;
110 service->GetDevices(&devices);
112 scoped_ptr<base::ListValue> result(new base::ListValue());
113 for (std::vector<HidDeviceInfo>::iterator it = devices.begin();
114 it != devices.end(); it++) {
115 if (it->product_id == product_id &&
116 it->vendor_id == vendor_id)
117 result->Append(PopulateHidDevice(*it));
119 SetResult(result.release());
120 AsyncWorkCompleted();
123 HidConnectFunction::HidConnectFunction() {}
125 HidConnectFunction::~HidConnectFunction() {}
127 bool HidConnectFunction::Prepare() {
128 parameters_ = hid::Connect::Params::Create(*args_);
129 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
133 void HidConnectFunction::AsyncWorkStart() {
134 HidService* service = HidService::GetInstance();
136 CompleteWithError(kErrorServiceFailed);
139 HidDeviceInfo device;
140 if (!service->GetInfo(parameters_->device_info.path, &device)) {
141 CompleteWithError(kErrorDeviceNotFound);
144 if (device.vendor_id != parameters_->device_info.vendor_id ||
145 device.product_id != parameters_->device_info.product_id) {
146 CompleteWithError(kErrorDeviceNotFound);
149 scoped_refptr<HidConnection> connection = service->Connect(device.device_id);
151 CompleteWithError(kErrorFailedToOpenDevice);
155 manager_->Add(new HidConnectionResource(extension_->id(), connection));
156 SetResult(PopulateHidConnection(connection_id, connection));
157 AsyncWorkCompleted();
160 HidDisconnectFunction::HidDisconnectFunction() {}
162 HidDisconnectFunction::~HidDisconnectFunction() {}
164 bool HidDisconnectFunction::Prepare() {
165 parameters_ = hid::Disconnect::Params::Create(*args_);
166 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
170 void HidDisconnectFunction::AsyncWorkStart() {
171 int connection_id = parameters_->connection_id;
172 HidConnectionResource* resource =
173 manager_->Get(extension_->id(), connection_id);
175 CompleteWithError(kErrorConnectionNotFound);
178 manager_->Remove(extension_->id(), connection_id);
179 AsyncWorkCompleted();
182 HidReceiveFunction::HidReceiveFunction() {}
184 HidReceiveFunction::~HidReceiveFunction() {}
186 bool HidReceiveFunction::Prepare() {
187 parameters_ = hid::Receive::Params::Create(*args_);
188 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
192 void HidReceiveFunction::AsyncWorkStart() {
193 int connection_id = parameters_->connection_id;
194 HidConnectionResource* resource =
195 manager_->Get(extension_->id(), connection_id);
197 CompleteWithError(kErrorConnectionNotFound);
201 buffer_ = new net::IOBuffer(parameters_->size);
202 resource->connection()->Read(
205 base::Bind(&HidReceiveFunction::OnFinished, this));
208 void HidReceiveFunction::OnFinished(bool success, size_t bytes) {
210 CompleteWithError(kErrorTransfer);
214 SetResult(base::BinaryValue::CreateWithCopiedBuffer(buffer_->data(), bytes));
215 AsyncWorkCompleted();
218 HidSendFunction::HidSendFunction() {}
220 HidSendFunction::~HidSendFunction() {}
222 bool HidSendFunction::Prepare() {
223 parameters_ = hid::Send::Params::Create(*args_);
224 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
228 void HidSendFunction::AsyncWorkStart() {
229 int connection_id = parameters_->connection_id;
230 HidConnectionResource* resource =
231 manager_->Get(extension_->id(), connection_id);
233 CompleteWithError(kErrorConnectionNotFound);
237 scoped_refptr<net::IOBuffer> buffer(
238 new net::WrappedIOBuffer(parameters_->data.c_str()));
239 memcpy(buffer->data(),
240 parameters_->data.c_str(),
241 parameters_->data.size());
242 resource->connection()->Write(
244 parameters_->data.size(),
245 base::Bind(&HidSendFunction::OnFinished, this));
248 void HidSendFunction::OnFinished(bool success, size_t bytes) {
250 CompleteWithError(kErrorTransfer);
253 AsyncWorkCompleted();
256 HidReceiveFeatureReportFunction::HidReceiveFeatureReportFunction() {}
258 HidReceiveFeatureReportFunction::~HidReceiveFeatureReportFunction() {}
260 bool HidReceiveFeatureReportFunction::Prepare() {
261 parameters_ = hid::ReceiveFeatureReport::Params::Create(*args_);
262 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
266 void HidReceiveFeatureReportFunction::AsyncWorkStart() {
267 int connection_id = parameters_->connection_id;
268 HidConnectionResource* resource =
269 manager_->Get(extension_->id(), connection_id);
271 CompleteWithError(kErrorConnectionNotFound);
274 buffer_ = new net::IOBuffer(parameters_->size);
275 resource->connection()->GetFeatureReport(
278 base::Bind(&HidReceiveFeatureReportFunction::OnFinished, this));
281 void HidReceiveFeatureReportFunction::OnFinished(bool success, size_t bytes) {
283 CompleteWithError(kErrorTransfer);
287 SetResult(base::BinaryValue::CreateWithCopiedBuffer(buffer_->data(), bytes));
288 AsyncWorkCompleted();
291 HidSendFeatureReportFunction::HidSendFeatureReportFunction() {}
293 HidSendFeatureReportFunction::~HidSendFeatureReportFunction() {}
295 bool HidSendFeatureReportFunction::Prepare() {
296 parameters_ = hid::SendFeatureReport::Params::Create(*args_);
297 EXTENSION_FUNCTION_VALIDATE(parameters_.get());
301 void HidSendFeatureReportFunction::AsyncWorkStart() {
302 int connection_id = parameters_->connection_id;
303 HidConnectionResource* resource =
304 manager_->Get(extension_->id(), connection_id);
306 CompleteWithError(kErrorConnectionNotFound);
309 scoped_refptr<net::IOBuffer> buffer(
310 new net::WrappedIOBuffer(parameters_->data.c_str()));
311 resource->connection()->SendFeatureReport(
313 parameters_->data.size(),
314 base::Bind(&HidSendFeatureReportFunction::OnFinished, this));
317 void HidSendFeatureReportFunction::OnFinished(bool success, size_t bytes) {
319 CompleteWithError(kErrorTransfer);
322 AsyncWorkCompleted();
325 } // namespace extensions