OLD | NEW |
| (Empty) |
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 | |
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 | |
44 HidAsyncApiFunction::HidAsyncApiFunction() | |
45 : device_manager_(NULL), connection_manager_(NULL) {} | |
46 | |
47 HidAsyncApiFunction::~HidAsyncApiFunction() {} | |
48 | |
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 | |
59 bool HidAsyncApiFunction::Respond() { return error_.empty(); } | |
60 | |
61 HidConnectionResource* HidAsyncApiFunction::GetHidConnectionResource( | |
62 int api_resource_id) { | |
63 return connection_manager_->Get(extension_->id(), api_resource_id); | |
64 } | |
65 | |
66 void HidAsyncApiFunction::RemoveHidConnectionResource(int api_resource_id) { | |
67 connection_manager_->Remove(extension_->id(), api_resource_id); | |
68 } | |
69 | |
70 void HidAsyncApiFunction::CompleteWithError(const std::string& error) { | |
71 SetError(error); | |
72 AsyncWorkCompleted(); | |
73 } | |
74 | |
75 HidGetDevicesFunction::HidGetDevicesFunction() {} | |
76 | |
77 HidGetDevicesFunction::~HidGetDevicesFunction() {} | |
78 | |
79 bool HidGetDevicesFunction::Prepare() { | |
80 parameters_ = hid::GetDevices::Params::Create(*args_); | |
81 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | |
82 return true; | |
83 } | |
84 | |
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, ¶m)) { | |
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 | |
101 HidConnectFunction::HidConnectFunction() {} | |
102 | |
103 HidConnectFunction::~HidConnectFunction() {} | |
104 | |
105 bool HidConnectFunction::Prepare() { | |
106 parameters_ = hid::Connect::Params::Create(*args_); | |
107 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | |
108 return true; | |
109 } | |
110 | |
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, ¶m)) { | |
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 | |
143 HidDisconnectFunction::HidDisconnectFunction() {} | |
144 | |
145 HidDisconnectFunction::~HidDisconnectFunction() {} | |
146 | |
147 bool HidDisconnectFunction::Prepare() { | |
148 parameters_ = hid::Disconnect::Params::Create(*args_); | |
149 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | |
150 return true; | |
151 } | |
152 | |
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 | |
165 HidReceiveFunction::HidReceiveFunction() {} | |
166 | |
167 HidReceiveFunction::~HidReceiveFunction() {} | |
168 | |
169 bool HidReceiveFunction::Prepare() { | |
170 parameters_ = hid::Receive::Params::Create(*args_); | |
171 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | |
172 return true; | |
173 } | |
174 | |
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 | |
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 | |
199 HidSendFunction::HidSendFunction() {} | |
200 | |
201 HidSendFunction::~HidSendFunction() {} | |
202 | |
203 bool HidSendFunction::Prepare() { | |
204 parameters_ = hid::Send::Params::Create(*args_); | |
205 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | |
206 return true; | |
207 } | |
208 | |
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 | |
226 void HidSendFunction::OnFinished(bool success, size_t bytes) { | |
227 if (!success) { | |
228 CompleteWithError(kErrorTransfer); | |
229 return; | |
230 } | |
231 AsyncWorkCompleted(); | |
232 } | |
233 | |
234 HidReceiveFeatureReportFunction::HidReceiveFeatureReportFunction() {} | |
235 | |
236 HidReceiveFeatureReportFunction::~HidReceiveFeatureReportFunction() {} | |
237 | |
238 bool HidReceiveFeatureReportFunction::Prepare() { | |
239 parameters_ = hid::ReceiveFeatureReport::Params::Create(*args_); | |
240 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | |
241 return true; | |
242 } | |
243 | |
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 | |
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 | |
269 HidSendFeatureReportFunction::HidSendFeatureReportFunction() {} | |
270 | |
271 HidSendFeatureReportFunction::~HidSendFeatureReportFunction() {} | |
272 | |
273 bool HidSendFeatureReportFunction::Prepare() { | |
274 parameters_ = hid::SendFeatureReport::Params::Create(*args_); | |
275 EXTENSION_FUNCTION_VALIDATE(parameters_.get()); | |
276 return true; | |
277 } | |
278 | |
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 | |
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 | |
OLD | NEW |