| 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 |