• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "chrome/browser/extensions/api/hid/hid_api.h"
6 
7 #include <string>
8 #include <vector>
9 
10 #include "chrome/common/extensions/api/hid.h"
11 #include "device/hid/hid_connection.h"
12 #include "device/hid/hid_device_info.h"
13 #include "device/hid/hid_service.h"
14 #include "extensions/browser/api/api_resource_manager.h"
15 #include "extensions/common/permissions/permissions_data.h"
16 #include "extensions/common/permissions/usb_device_permission.h"
17 #include "net/base/io_buffer.h"
18 
19 namespace hid = extensions::api::hid;
20 
21 using device::HidConnection;
22 using device::HidDeviceInfo;
23 using device::HidService;
24 
25 namespace {
26 
27 const char kErrorPermissionDenied[] = "Permission to access device was denied.";
28 const char kErrorInvalidDeviceId[] = "Invalid HID device ID.";
29 const char kErrorFailedToOpenDevice[] = "Failed to open HID device.";
30 const char kErrorConnectionNotFound[] = "Connection not established.";
31 const char kErrorTransfer[] = "Transfer failed.";
32 
PopulateHidConnection(int connection_id,scoped_refptr<HidConnection> connection)33 base::Value* PopulateHidConnection(int connection_id,
34                                    scoped_refptr<HidConnection> connection) {
35   hid::HidConnectInfo connection_value;
36   connection_value.connection_id = connection_id;
37   return connection_value.ToValue().release();
38 }
39 
40 }  // namespace
41 
42 namespace extensions {
43 
HidAsyncApiFunction()44 HidAsyncApiFunction::HidAsyncApiFunction()
45     : device_manager_(NULL), connection_manager_(NULL) {}
46 
~HidAsyncApiFunction()47 HidAsyncApiFunction::~HidAsyncApiFunction() {}
48 
PrePrepare()49 bool HidAsyncApiFunction::PrePrepare() {
50   device_manager_ = HidDeviceManager::Get(browser_context());
51   DCHECK(device_manager_);
52   connection_manager_ =
53       ApiResourceManager<HidConnectionResource>::Get(browser_context());
54   DCHECK(connection_manager_);
55   set_work_thread_id(content::BrowserThread::FILE);
56   return true;
57 }
58 
Respond()59 bool HidAsyncApiFunction::Respond() { return error_.empty(); }
60 
GetHidConnectionResource(int api_resource_id)61 HidConnectionResource* HidAsyncApiFunction::GetHidConnectionResource(
62     int api_resource_id) {
63   return connection_manager_->Get(extension_->id(), api_resource_id);
64 }
65 
RemoveHidConnectionResource(int api_resource_id)66 void HidAsyncApiFunction::RemoveHidConnectionResource(int api_resource_id) {
67   connection_manager_->Remove(extension_->id(), api_resource_id);
68 }
69 
CompleteWithError(const std::string & error)70 void HidAsyncApiFunction::CompleteWithError(const std::string& error) {
71   SetError(error);
72   AsyncWorkCompleted();
73 }
74 
HidGetDevicesFunction()75 HidGetDevicesFunction::HidGetDevicesFunction() {}
76 
~HidGetDevicesFunction()77 HidGetDevicesFunction::~HidGetDevicesFunction() {}
78 
Prepare()79 bool HidGetDevicesFunction::Prepare() {
80   parameters_ = hid::GetDevices::Params::Create(*args_);
81   EXTENSION_FUNCTION_VALIDATE(parameters_.get());
82   return true;
83 }
84 
AsyncWorkStart()85 void HidGetDevicesFunction::AsyncWorkStart() {
86   const uint16_t vendor_id = parameters_->options.vendor_id;
87   const uint16_t product_id = parameters_->options.product_id;
88   UsbDevicePermission::CheckParam param(
89       vendor_id, product_id, UsbDevicePermissionData::UNSPECIFIED_INTERFACE);
90   if (!GetExtension()->permissions_data()->CheckAPIPermissionWithParam(
91           APIPermission::kUsbDevice, &param)) {
92     LOG(WARNING) << "Insufficient permissions to access device.";
93     CompleteWithError(kErrorPermissionDenied);
94     return;
95   }
96 
97   SetResult(device_manager_->GetApiDevices(vendor_id, product_id).release());
98   AsyncWorkCompleted();
99 }
100 
HidConnectFunction()101 HidConnectFunction::HidConnectFunction() {}
102 
~HidConnectFunction()103 HidConnectFunction::~HidConnectFunction() {}
104 
Prepare()105 bool HidConnectFunction::Prepare() {
106   parameters_ = hid::Connect::Params::Create(*args_);
107   EXTENSION_FUNCTION_VALIDATE(parameters_.get());
108   return true;
109 }
110 
AsyncWorkStart()111 void HidConnectFunction::AsyncWorkStart() {
112   device::HidDeviceInfo device_info;
113   if (!device_manager_->GetDeviceInfo(parameters_->device_id, &device_info)) {
114     CompleteWithError(kErrorInvalidDeviceId);
115     return;
116   }
117 
118   UsbDevicePermission::CheckParam param(
119       device_info.vendor_id,
120       device_info.product_id,
121       UsbDevicePermissionData::UNSPECIFIED_INTERFACE);
122   if (!GetExtension()->permissions_data()->CheckAPIPermissionWithParam(
123           APIPermission::kUsbDevice, &param)) {
124     LOG(WARNING) << "Insufficient permissions to access device.";
125     CompleteWithError(kErrorPermissionDenied);
126     return;
127   }
128 
129   HidService* hid_service = HidService::GetInstance();
130   DCHECK(hid_service);
131   scoped_refptr<HidConnection> connection =
132       hid_service->Connect(device_info.device_id);
133   if (!connection) {
134     CompleteWithError(kErrorFailedToOpenDevice);
135     return;
136   }
137   int connection_id = connection_manager_->Add(
138       new HidConnectionResource(extension_->id(), connection));
139   SetResult(PopulateHidConnection(connection_id, connection));
140   AsyncWorkCompleted();
141 }
142 
HidDisconnectFunction()143 HidDisconnectFunction::HidDisconnectFunction() {}
144 
~HidDisconnectFunction()145 HidDisconnectFunction::~HidDisconnectFunction() {}
146 
Prepare()147 bool HidDisconnectFunction::Prepare() {
148   parameters_ = hid::Disconnect::Params::Create(*args_);
149   EXTENSION_FUNCTION_VALIDATE(parameters_.get());
150   return true;
151 }
152 
AsyncWorkStart()153 void HidDisconnectFunction::AsyncWorkStart() {
154   int connection_id = parameters_->connection_id;
155   HidConnectionResource* resource =
156       connection_manager_->Get(extension_->id(), connection_id);
157   if (!resource) {
158     CompleteWithError(kErrorConnectionNotFound);
159     return;
160   }
161   connection_manager_->Remove(extension_->id(), connection_id);
162   AsyncWorkCompleted();
163 }
164 
HidReceiveFunction()165 HidReceiveFunction::HidReceiveFunction() {}
166 
~HidReceiveFunction()167 HidReceiveFunction::~HidReceiveFunction() {}
168 
Prepare()169 bool HidReceiveFunction::Prepare() {
170   parameters_ = hid::Receive::Params::Create(*args_);
171   EXTENSION_FUNCTION_VALIDATE(parameters_.get());
172   return true;
173 }
174 
AsyncWorkStart()175 void HidReceiveFunction::AsyncWorkStart() {
176   int connection_id = parameters_->connection_id;
177   HidConnectionResource* resource =
178       connection_manager_->Get(extension_->id(), connection_id);
179   if (!resource) {
180     CompleteWithError(kErrorConnectionNotFound);
181     return;
182   }
183 
184   buffer_ = new net::IOBufferWithSize(parameters_->size);
185   resource->connection()->Read(
186       buffer_, base::Bind(&HidReceiveFunction::OnFinished, this));
187 }
188 
OnFinished(bool success,size_t bytes)189 void HidReceiveFunction::OnFinished(bool success, size_t bytes) {
190   if (!success) {
191     CompleteWithError(kErrorTransfer);
192     return;
193   }
194 
195   SetResult(base::BinaryValue::CreateWithCopiedBuffer(buffer_->data(), bytes));
196   AsyncWorkCompleted();
197 }
198 
HidSendFunction()199 HidSendFunction::HidSendFunction() {}
200 
~HidSendFunction()201 HidSendFunction::~HidSendFunction() {}
202 
Prepare()203 bool HidSendFunction::Prepare() {
204   parameters_ = hid::Send::Params::Create(*args_);
205   EXTENSION_FUNCTION_VALIDATE(parameters_.get());
206   return true;
207 }
208 
AsyncWorkStart()209 void HidSendFunction::AsyncWorkStart() {
210   int connection_id = parameters_->connection_id;
211   HidConnectionResource* resource =
212       connection_manager_->Get(extension_->id(), connection_id);
213   if (!resource) {
214     CompleteWithError(kErrorConnectionNotFound);
215     return;
216   }
217 
218   scoped_refptr<net::IOBufferWithSize> buffer(
219       new net::IOBufferWithSize(parameters_->data.size()));
220   memcpy(buffer->data(), parameters_->data.c_str(), parameters_->data.size());
221   resource->connection()->Write(static_cast<uint8_t>(parameters_->report_id),
222                                 buffer,
223                                 base::Bind(&HidSendFunction::OnFinished, this));
224 }
225 
OnFinished(bool success,size_t bytes)226 void HidSendFunction::OnFinished(bool success, size_t bytes) {
227   if (!success) {
228     CompleteWithError(kErrorTransfer);
229     return;
230   }
231   AsyncWorkCompleted();
232 }
233 
HidReceiveFeatureReportFunction()234 HidReceiveFeatureReportFunction::HidReceiveFeatureReportFunction() {}
235 
~HidReceiveFeatureReportFunction()236 HidReceiveFeatureReportFunction::~HidReceiveFeatureReportFunction() {}
237 
Prepare()238 bool HidReceiveFeatureReportFunction::Prepare() {
239   parameters_ = hid::ReceiveFeatureReport::Params::Create(*args_);
240   EXTENSION_FUNCTION_VALIDATE(parameters_.get());
241   return true;
242 }
243 
AsyncWorkStart()244 void HidReceiveFeatureReportFunction::AsyncWorkStart() {
245   int connection_id = parameters_->connection_id;
246   HidConnectionResource* resource =
247       connection_manager_->Get(extension_->id(), connection_id);
248   if (!resource) {
249     CompleteWithError(kErrorConnectionNotFound);
250     return;
251   }
252   buffer_ = new net::IOBufferWithSize(parameters_->size);
253   resource->connection()->GetFeatureReport(
254       static_cast<uint8_t>(parameters_->report_id),
255       buffer_,
256       base::Bind(&HidReceiveFeatureReportFunction::OnFinished, this));
257 }
258 
OnFinished(bool success,size_t bytes)259 void HidReceiveFeatureReportFunction::OnFinished(bool success, size_t bytes) {
260   if (!success) {
261     CompleteWithError(kErrorTransfer);
262     return;
263   }
264 
265   SetResult(base::BinaryValue::CreateWithCopiedBuffer(buffer_->data(), bytes));
266   AsyncWorkCompleted();
267 }
268 
HidSendFeatureReportFunction()269 HidSendFeatureReportFunction::HidSendFeatureReportFunction() {}
270 
~HidSendFeatureReportFunction()271 HidSendFeatureReportFunction::~HidSendFeatureReportFunction() {}
272 
Prepare()273 bool HidSendFeatureReportFunction::Prepare() {
274   parameters_ = hid::SendFeatureReport::Params::Create(*args_);
275   EXTENSION_FUNCTION_VALIDATE(parameters_.get());
276   return true;
277 }
278 
AsyncWorkStart()279 void HidSendFeatureReportFunction::AsyncWorkStart() {
280   int connection_id = parameters_->connection_id;
281   HidConnectionResource* resource =
282       connection_manager_->Get(extension_->id(), connection_id);
283   if (!resource) {
284     CompleteWithError(kErrorConnectionNotFound);
285     return;
286   }
287   scoped_refptr<net::IOBufferWithSize> buffer(
288       new net::IOBufferWithSize(parameters_->data.size()));
289   resource->connection()->SendFeatureReport(
290       static_cast<uint8_t>(parameters_->report_id),
291       buffer,
292       base::Bind(&HidSendFeatureReportFunction::OnFinished, this));
293 }
294 
OnFinished(bool success,size_t bytes)295 void HidSendFeatureReportFunction::OnFinished(bool success, size_t bytes) {
296   if (!success) {
297     CompleteWithError(kErrorTransfer);
298     return;
299   }
300   AsyncWorkCompleted();
301 }
302 
303 }  // namespace extensions
304