Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / api / hid / hid_api.cc
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/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"
19
20 namespace hid = extensions::api::hid;
21
22 using device::HidConnection;
23 using device::HidService;
24 using device::HidDeviceInfo;
25
26 namespace {
27
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.";
34
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();
41 }
42
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();
48 }
49
50 }  // namespace
51
52 namespace extensions {
53
54 HidAsyncApiFunction::HidAsyncApiFunction() : manager_(NULL) {
55 }
56
57 HidAsyncApiFunction::~HidAsyncApiFunction() {}
58
59 bool HidAsyncApiFunction::PrePrepare() {
60   manager_ = ApiResourceManager<HidConnectionResource>::Get(GetProfile());
61   if (!manager_) return false;
62   set_work_thread_id(content::BrowserThread::FILE);
63   return true;
64 }
65
66 bool HidAsyncApiFunction::Respond() { return error_.empty(); }
67
68 HidConnectionResource* HidAsyncApiFunction::GetHidConnectionResource(
69     int api_resource_id) {
70   return manager_->Get(extension_->id(), api_resource_id);
71 }
72
73 void HidAsyncApiFunction::RemoveHidConnectionResource(int api_resource_id) {
74   manager_->Remove(extension_->id(), api_resource_id);
75 }
76
77 void HidAsyncApiFunction::CompleteWithError(const std::string& error) {
78   SetError(error);
79   AsyncWorkCompleted();
80 }
81
82 HidGetDevicesFunction::HidGetDevicesFunction() {}
83
84 HidGetDevicesFunction::~HidGetDevicesFunction() {}
85
86 bool HidGetDevicesFunction::Prepare() {
87   parameters_ = hid::GetDevices::Params::Create(*args_);
88   EXTENSION_FUNCTION_VALIDATE(parameters_.get());
89   return true;
90 }
91
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, &param)) {
99     LOG(WARNING) << "Insufficient permissions to access device.";
100     CompleteWithError(kErrorPermissionDenied);
101     return;
102   }
103
104   HidService* service = HidService::GetInstance();
105   if (!service) {
106     CompleteWithError(kErrorServiceFailed);
107     return;
108   }
109   std::vector<HidDeviceInfo> devices;
110   service->GetDevices(&devices);
111
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));
118   }
119   SetResult(result.release());
120   AsyncWorkCompleted();
121 }
122
123 HidConnectFunction::HidConnectFunction() {}
124
125 HidConnectFunction::~HidConnectFunction() {}
126
127 bool HidConnectFunction::Prepare() {
128   parameters_ = hid::Connect::Params::Create(*args_);
129   EXTENSION_FUNCTION_VALIDATE(parameters_.get());
130   return true;
131 }
132
133 void HidConnectFunction::AsyncWorkStart() {
134   HidService* service = HidService::GetInstance();
135   if (!service) {
136     CompleteWithError(kErrorServiceFailed);
137     return;
138   }
139   HidDeviceInfo device;
140   if (!service->GetInfo(parameters_->device_info.path, &device)) {
141     CompleteWithError(kErrorDeviceNotFound);
142     return;
143   }
144   if (device.vendor_id != parameters_->device_info.vendor_id ||
145       device.product_id != parameters_->device_info.product_id) {
146     CompleteWithError(kErrorDeviceNotFound);
147     return;
148   }
149   scoped_refptr<HidConnection> connection = service->Connect(device.device_id);
150   if (!connection) {
151     CompleteWithError(kErrorFailedToOpenDevice);
152     return;
153   }
154   int connection_id =
155       manager_->Add(new HidConnectionResource(extension_->id(), connection));
156   SetResult(PopulateHidConnection(connection_id, connection));
157   AsyncWorkCompleted();
158 }
159
160 HidDisconnectFunction::HidDisconnectFunction() {}
161
162 HidDisconnectFunction::~HidDisconnectFunction() {}
163
164 bool HidDisconnectFunction::Prepare() {
165   parameters_ = hid::Disconnect::Params::Create(*args_);
166   EXTENSION_FUNCTION_VALIDATE(parameters_.get());
167   return true;
168 }
169
170 void HidDisconnectFunction::AsyncWorkStart() {
171   int connection_id = parameters_->connection_id;
172   HidConnectionResource* resource =
173       manager_->Get(extension_->id(), connection_id);
174   if (!resource) {
175     CompleteWithError(kErrorConnectionNotFound);
176     return;
177   }
178   manager_->Remove(extension_->id(), connection_id);
179   AsyncWorkCompleted();
180 }
181
182 HidReceiveFunction::HidReceiveFunction() {}
183
184 HidReceiveFunction::~HidReceiveFunction() {}
185
186 bool HidReceiveFunction::Prepare() {
187   parameters_ = hid::Receive::Params::Create(*args_);
188   EXTENSION_FUNCTION_VALIDATE(parameters_.get());
189   return true;
190 }
191
192 void HidReceiveFunction::AsyncWorkStart() {
193   int connection_id = parameters_->connection_id;
194   HidConnectionResource* resource =
195       manager_->Get(extension_->id(), connection_id);
196   if (!resource) {
197     CompleteWithError(kErrorConnectionNotFound);
198     return;
199   }
200
201   buffer_ = new net::IOBuffer(parameters_->size);
202   resource->connection()->Read(
203       buffer_,
204       parameters_->size,
205       base::Bind(&HidReceiveFunction::OnFinished, this));
206 }
207
208 void HidReceiveFunction::OnFinished(bool success, size_t bytes) {
209   if (!success) {
210     CompleteWithError(kErrorTransfer);
211     return;
212   }
213
214   SetResult(base::BinaryValue::CreateWithCopiedBuffer(buffer_->data(), bytes));
215   AsyncWorkCompleted();
216 }
217
218 HidSendFunction::HidSendFunction() {}
219
220 HidSendFunction::~HidSendFunction() {}
221
222 bool HidSendFunction::Prepare() {
223   parameters_ = hid::Send::Params::Create(*args_);
224   EXTENSION_FUNCTION_VALIDATE(parameters_.get());
225   return true;
226 }
227
228 void HidSendFunction::AsyncWorkStart() {
229   int connection_id = parameters_->connection_id;
230   HidConnectionResource* resource =
231       manager_->Get(extension_->id(), connection_id);
232   if (!resource) {
233     CompleteWithError(kErrorConnectionNotFound);
234     return;
235   }
236
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(
243       buffer,
244       parameters_->data.size(),
245       base::Bind(&HidSendFunction::OnFinished, this));
246 }
247
248 void HidSendFunction::OnFinished(bool success, size_t bytes) {
249   if (!success) {
250     CompleteWithError(kErrorTransfer);
251     return;
252   }
253   AsyncWorkCompleted();
254 }
255
256 HidReceiveFeatureReportFunction::HidReceiveFeatureReportFunction() {}
257
258 HidReceiveFeatureReportFunction::~HidReceiveFeatureReportFunction() {}
259
260 bool HidReceiveFeatureReportFunction::Prepare() {
261   parameters_ = hid::ReceiveFeatureReport::Params::Create(*args_);
262   EXTENSION_FUNCTION_VALIDATE(parameters_.get());
263   return true;
264 }
265
266 void HidReceiveFeatureReportFunction::AsyncWorkStart() {
267   int connection_id = parameters_->connection_id;
268   HidConnectionResource* resource =
269       manager_->Get(extension_->id(), connection_id);
270   if (!resource) {
271     CompleteWithError(kErrorConnectionNotFound);
272     return;
273   }
274   buffer_ = new net::IOBuffer(parameters_->size);
275   resource->connection()->GetFeatureReport(
276       buffer_,
277       parameters_->size,
278       base::Bind(&HidReceiveFeatureReportFunction::OnFinished, this));
279 }
280
281 void HidReceiveFeatureReportFunction::OnFinished(bool success, size_t bytes) {
282   if (!success) {
283     CompleteWithError(kErrorTransfer);
284     return;
285   }
286
287   SetResult(base::BinaryValue::CreateWithCopiedBuffer(buffer_->data(), bytes));
288   AsyncWorkCompleted();
289 }
290
291 HidSendFeatureReportFunction::HidSendFeatureReportFunction() {}
292
293 HidSendFeatureReportFunction::~HidSendFeatureReportFunction() {}
294
295 bool HidSendFeatureReportFunction::Prepare() {
296   parameters_ = hid::SendFeatureReport::Params::Create(*args_);
297   EXTENSION_FUNCTION_VALIDATE(parameters_.get());
298   return true;
299 }
300
301 void HidSendFeatureReportFunction::AsyncWorkStart() {
302   int connection_id = parameters_->connection_id;
303   HidConnectionResource* resource =
304       manager_->Get(extension_->id(), connection_id);
305   if (!resource) {
306     CompleteWithError(kErrorConnectionNotFound);
307     return;
308   }
309   scoped_refptr<net::IOBuffer> buffer(
310       new net::WrappedIOBuffer(parameters_->data.c_str()));
311   resource->connection()->SendFeatureReport(
312       buffer,
313       parameters_->data.size(),
314       base::Bind(&HidSendFeatureReportFunction::OnFinished, this));
315 }
316
317 void HidSendFeatureReportFunction::OnFinished(bool success, size_t bytes) {
318   if (!success) {
319     CompleteWithError(kErrorTransfer);
320     return;
321   }
322   AsyncWorkCompleted();
323 }
324
325 }  // namespace extensions