| OLD | NEW |
| (Empty) |
| 1 // Copyright 2012 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/serial/serial_api.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 | |
| 9 #include "base/values.h" | |
| 10 #include "chrome/browser/extensions/api/serial/serial_connection.h" | |
| 11 #include "chrome/browser/extensions/api/serial/serial_event_dispatcher.h" | |
| 12 #include "chrome/browser/profiles/profile.h" | |
| 13 #include "chrome/common/extensions/api/serial.h" | |
| 14 #include "content/public/browser/browser_thread.h" | |
| 15 #include "device/serial/serial_device_enumerator.h" | |
| 16 #include "extensions/browser/extension_system.h" | |
| 17 | |
| 18 using content::BrowserThread; | |
| 19 | |
| 20 namespace extensions { | |
| 21 | |
| 22 namespace api { | |
| 23 | |
| 24 namespace { | |
| 25 | |
| 26 // It's a fool's errand to come up with a default bitrate, because we don't get | |
| 27 // to control both sides of the communication. Unless the other side has | |
| 28 // implemented auto-bitrate detection (rare), if we pick the wrong rate, then | |
| 29 // you're gonna have a bad time. Close doesn't count. | |
| 30 // | |
| 31 // But we'd like to pick something that has a chance of working, and 9600 is a | |
| 32 // good balance between popularity and speed. So 9600 it is. | |
| 33 const int kDefaultBufferSize = 4096; | |
| 34 const int kDefaultBitrate = 9600; | |
| 35 const serial::DataBits kDefaultDataBits = serial::DATA_BITS_EIGHT; | |
| 36 const serial::ParityBit kDefaultParityBit = serial::PARITY_BIT_NO; | |
| 37 const serial::StopBits kDefaultStopBits = serial::STOP_BITS_ONE; | |
| 38 const int kDefaultReceiveTimeout = 0; | |
| 39 const int kDefaultSendTimeout = 0; | |
| 40 | |
| 41 const char kErrorConnectFailed[] = "Failed to connect to the port."; | |
| 42 const char kErrorSerialConnectionNotFound[] = "Serial connection not found."; | |
| 43 const char kErrorGetControlSignalsFailed[] = "Failed to get control signals."; | |
| 44 | |
| 45 template <class T> | |
| 46 void SetDefaultScopedPtrValue(scoped_ptr<T>& ptr, const T& value) { | |
| 47 if (!ptr.get()) | |
| 48 ptr.reset(new T(value)); | |
| 49 } | |
| 50 | |
| 51 } // namespace | |
| 52 | |
| 53 SerialAsyncApiFunction::SerialAsyncApiFunction() | |
| 54 : manager_(NULL) { | |
| 55 } | |
| 56 | |
| 57 SerialAsyncApiFunction::~SerialAsyncApiFunction() {} | |
| 58 | |
| 59 bool SerialAsyncApiFunction::PrePrepare() { | |
| 60 manager_ = ApiResourceManager<SerialConnection>::Get(browser_context()); | |
| 61 DCHECK(manager_); | |
| 62 return true; | |
| 63 } | |
| 64 | |
| 65 bool SerialAsyncApiFunction::Respond() { | |
| 66 return error_.empty(); | |
| 67 } | |
| 68 | |
| 69 SerialConnection* SerialAsyncApiFunction::GetSerialConnection( | |
| 70 int api_resource_id) { | |
| 71 return manager_->Get(extension_->id(), api_resource_id); | |
| 72 } | |
| 73 | |
| 74 void SerialAsyncApiFunction::RemoveSerialConnection(int api_resource_id) { | |
| 75 manager_->Remove(extension_->id(), api_resource_id); | |
| 76 } | |
| 77 | |
| 78 SerialGetDevicesFunction::SerialGetDevicesFunction() {} | |
| 79 | |
| 80 bool SerialGetDevicesFunction::Prepare() { | |
| 81 set_work_thread_id(BrowserThread::FILE); | |
| 82 return true; | |
| 83 } | |
| 84 | |
| 85 void SerialGetDevicesFunction::Work() { | |
| 86 DCHECK_CURRENTLY_ON(BrowserThread::FILE); | |
| 87 | |
| 88 scoped_ptr<device::SerialDeviceEnumerator> enumerator = | |
| 89 device::SerialDeviceEnumerator::Create(); | |
| 90 mojo::Array<device::serial::DeviceInfoPtr> devices = enumerator->GetDevices(); | |
| 91 results_ = serial::GetDevices::Results::Create( | |
| 92 devices.To<std::vector<linked_ptr<serial::DeviceInfo> > >()); | |
| 93 } | |
| 94 | |
| 95 SerialConnectFunction::SerialConnectFunction() {} | |
| 96 | |
| 97 SerialConnectFunction::~SerialConnectFunction() {} | |
| 98 | |
| 99 bool SerialConnectFunction::Prepare() { | |
| 100 params_ = serial::Connect::Params::Create(*args_); | |
| 101 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
| 102 | |
| 103 // Fill in any omitted options to ensure a known initial configuration. | |
| 104 if (!params_->options.get()) | |
| 105 params_->options.reset(new serial::ConnectionOptions()); | |
| 106 serial::ConnectionOptions* options = params_->options.get(); | |
| 107 | |
| 108 SetDefaultScopedPtrValue(options->persistent, false); | |
| 109 SetDefaultScopedPtrValue(options->buffer_size, kDefaultBufferSize); | |
| 110 SetDefaultScopedPtrValue(options->bitrate, kDefaultBitrate); | |
| 111 SetDefaultScopedPtrValue(options->cts_flow_control, false); | |
| 112 SetDefaultScopedPtrValue(options->receive_timeout, kDefaultReceiveTimeout); | |
| 113 SetDefaultScopedPtrValue(options->send_timeout, kDefaultSendTimeout); | |
| 114 | |
| 115 if (options->data_bits == serial::DATA_BITS_NONE) | |
| 116 options->data_bits = kDefaultDataBits; | |
| 117 if (options->parity_bit == serial::PARITY_BIT_NONE) | |
| 118 options->parity_bit = kDefaultParityBit; | |
| 119 if (options->stop_bits == serial::STOP_BITS_NONE) | |
| 120 options->stop_bits = kDefaultStopBits; | |
| 121 | |
| 122 serial_event_dispatcher_ = SerialEventDispatcher::Get(browser_context()); | |
| 123 DCHECK(serial_event_dispatcher_); | |
| 124 | |
| 125 return true; | |
| 126 } | |
| 127 | |
| 128 void SerialConnectFunction::AsyncWorkStart() { | |
| 129 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 130 connection_ = CreateSerialConnection(params_->path, extension_->id()); | |
| 131 connection_->Open(base::Bind(&SerialConnectFunction::OnConnected, this)); | |
| 132 } | |
| 133 | |
| 134 void SerialConnectFunction::OnConnected(bool success) { | |
| 135 DCHECK(connection_); | |
| 136 | |
| 137 if (success) { | |
| 138 if (!connection_->Configure(*params_->options.get())) { | |
| 139 delete connection_; | |
| 140 connection_ = NULL; | |
| 141 } | |
| 142 } else { | |
| 143 delete connection_; | |
| 144 connection_ = NULL; | |
| 145 } | |
| 146 | |
| 147 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, | |
| 148 base::Bind(&SerialConnectFunction::FinishConnect, | |
| 149 this)); | |
| 150 } | |
| 151 | |
| 152 void SerialConnectFunction::FinishConnect() { | |
| 153 DCHECK_CURRENTLY_ON(BrowserThread::IO); | |
| 154 if (!connection_) { | |
| 155 error_ = kErrorConnectFailed; | |
| 156 } else { | |
| 157 int id = manager_->Add(connection_); | |
| 158 serial::ConnectionInfo info; | |
| 159 info.connection_id = id; | |
| 160 if (connection_->GetInfo(&info)) { | |
| 161 serial_event_dispatcher_->PollConnection(extension_->id(), id); | |
| 162 results_ = serial::Connect::Results::Create(info); | |
| 163 } else { | |
| 164 RemoveSerialConnection(id); | |
| 165 error_ = kErrorConnectFailed; | |
| 166 } | |
| 167 } | |
| 168 AsyncWorkCompleted(); | |
| 169 } | |
| 170 | |
| 171 SerialConnection* SerialConnectFunction::CreateSerialConnection( | |
| 172 const std::string& port, const std::string& extension_id) const { | |
| 173 return new SerialConnection(port, extension_id); | |
| 174 } | |
| 175 | |
| 176 SerialUpdateFunction::SerialUpdateFunction() {} | |
| 177 | |
| 178 SerialUpdateFunction::~SerialUpdateFunction() {} | |
| 179 | |
| 180 bool SerialUpdateFunction::Prepare() { | |
| 181 params_ = serial::Update::Params::Create(*args_); | |
| 182 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
| 183 | |
| 184 return true; | |
| 185 } | |
| 186 | |
| 187 void SerialUpdateFunction::Work() { | |
| 188 SerialConnection* connection = GetSerialConnection(params_->connection_id); | |
| 189 if (!connection) { | |
| 190 error_ = kErrorSerialConnectionNotFound; | |
| 191 return; | |
| 192 } | |
| 193 bool success = connection->Configure(params_->options); | |
| 194 results_ = serial::Update::Results::Create(success); | |
| 195 } | |
| 196 | |
| 197 SerialDisconnectFunction::SerialDisconnectFunction() {} | |
| 198 | |
| 199 SerialDisconnectFunction::~SerialDisconnectFunction() {} | |
| 200 | |
| 201 bool SerialDisconnectFunction::Prepare() { | |
| 202 params_ = serial::Disconnect::Params::Create(*args_); | |
| 203 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
| 204 | |
| 205 return true; | |
| 206 } | |
| 207 | |
| 208 void SerialDisconnectFunction::Work() { | |
| 209 SerialConnection* connection = GetSerialConnection(params_->connection_id); | |
| 210 if (!connection) { | |
| 211 error_ = kErrorSerialConnectionNotFound; | |
| 212 return; | |
| 213 } | |
| 214 RemoveSerialConnection(params_->connection_id); | |
| 215 results_ = serial::Disconnect::Results::Create(true); | |
| 216 } | |
| 217 | |
| 218 SerialSendFunction::SerialSendFunction() {} | |
| 219 | |
| 220 SerialSendFunction::~SerialSendFunction() {} | |
| 221 | |
| 222 bool SerialSendFunction::Prepare() { | |
| 223 params_ = serial::Send::Params::Create(*args_); | |
| 224 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
| 225 | |
| 226 return true; | |
| 227 } | |
| 228 | |
| 229 void SerialSendFunction::AsyncWorkStart() { | |
| 230 SerialConnection* connection = GetSerialConnection(params_->connection_id); | |
| 231 if (!connection) { | |
| 232 error_ = kErrorSerialConnectionNotFound; | |
| 233 AsyncWorkCompleted(); | |
| 234 return; | |
| 235 } | |
| 236 | |
| 237 if (!connection->Send(params_->data, | |
| 238 base::Bind(&SerialSendFunction::OnSendComplete, | |
| 239 this))) { | |
| 240 OnSendComplete(0, serial::SEND_ERROR_PENDING); | |
| 241 } | |
| 242 } | |
| 243 | |
| 244 void SerialSendFunction::OnSendComplete(int bytes_sent, | |
| 245 serial::SendError error) { | |
| 246 serial::SendInfo send_info; | |
| 247 send_info.bytes_sent = bytes_sent; | |
| 248 send_info.error = error; | |
| 249 results_ = serial::Send::Results::Create(send_info); | |
| 250 AsyncWorkCompleted(); | |
| 251 } | |
| 252 | |
| 253 SerialFlushFunction::SerialFlushFunction() {} | |
| 254 | |
| 255 SerialFlushFunction::~SerialFlushFunction() {} | |
| 256 | |
| 257 bool SerialFlushFunction::Prepare() { | |
| 258 params_ = serial::Flush::Params::Create(*args_); | |
| 259 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
| 260 return true; | |
| 261 } | |
| 262 | |
| 263 void SerialFlushFunction::Work() { | |
| 264 SerialConnection* connection = GetSerialConnection(params_->connection_id); | |
| 265 if (!connection) { | |
| 266 error_ = kErrorSerialConnectionNotFound; | |
| 267 return; | |
| 268 } | |
| 269 | |
| 270 bool success = connection->Flush(); | |
| 271 results_ = serial::Flush::Results::Create(success); | |
| 272 } | |
| 273 | |
| 274 SerialSetPausedFunction::SerialSetPausedFunction() {} | |
| 275 | |
| 276 SerialSetPausedFunction::~SerialSetPausedFunction() {} | |
| 277 | |
| 278 bool SerialSetPausedFunction::Prepare() { | |
| 279 params_ = serial::SetPaused::Params::Create(*args_); | |
| 280 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
| 281 | |
| 282 serial_event_dispatcher_ = SerialEventDispatcher::Get(browser_context()); | |
| 283 DCHECK(serial_event_dispatcher_); | |
| 284 return true; | |
| 285 } | |
| 286 | |
| 287 void SerialSetPausedFunction::Work() { | |
| 288 SerialConnection* connection = GetSerialConnection(params_->connection_id); | |
| 289 if (!connection) { | |
| 290 error_ = kErrorSerialConnectionNotFound; | |
| 291 return; | |
| 292 } | |
| 293 | |
| 294 if (params_->paused != connection->paused()) { | |
| 295 connection->set_paused(params_->paused); | |
| 296 if (!params_->paused) { | |
| 297 serial_event_dispatcher_->PollConnection(extension_->id(), | |
| 298 params_->connection_id); | |
| 299 } | |
| 300 } | |
| 301 | |
| 302 results_ = serial::SetPaused::Results::Create(); | |
| 303 } | |
| 304 | |
| 305 SerialGetInfoFunction::SerialGetInfoFunction() {} | |
| 306 | |
| 307 SerialGetInfoFunction::~SerialGetInfoFunction() {} | |
| 308 | |
| 309 bool SerialGetInfoFunction::Prepare() { | |
| 310 params_ = serial::GetInfo::Params::Create(*args_); | |
| 311 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
| 312 | |
| 313 return true; | |
| 314 } | |
| 315 | |
| 316 void SerialGetInfoFunction::Work() { | |
| 317 SerialConnection* connection = GetSerialConnection(params_->connection_id); | |
| 318 if (!connection) { | |
| 319 error_ = kErrorSerialConnectionNotFound; | |
| 320 return; | |
| 321 } | |
| 322 | |
| 323 serial::ConnectionInfo info; | |
| 324 info.connection_id = params_->connection_id; | |
| 325 connection->GetInfo(&info); | |
| 326 results_ = serial::GetInfo::Results::Create(info); | |
| 327 } | |
| 328 | |
| 329 SerialGetConnectionsFunction::SerialGetConnectionsFunction() {} | |
| 330 | |
| 331 SerialGetConnectionsFunction::~SerialGetConnectionsFunction() {} | |
| 332 | |
| 333 bool SerialGetConnectionsFunction::Prepare() { | |
| 334 return true; | |
| 335 } | |
| 336 | |
| 337 void SerialGetConnectionsFunction::Work() { | |
| 338 std::vector<linked_ptr<serial::ConnectionInfo> > infos; | |
| 339 const base::hash_set<int>* connection_ids = manager_->GetResourceIds( | |
| 340 extension_->id()); | |
| 341 if (connection_ids) { | |
| 342 for (base::hash_set<int>::const_iterator it = connection_ids->begin(); | |
| 343 it != connection_ids->end(); ++it) { | |
| 344 int connection_id = *it; | |
| 345 SerialConnection *connection = GetSerialConnection(connection_id); | |
| 346 if (connection) { | |
| 347 linked_ptr<serial::ConnectionInfo> info(new serial::ConnectionInfo()); | |
| 348 info->connection_id = connection_id; | |
| 349 connection->GetInfo(info.get()); | |
| 350 infos.push_back(info); | |
| 351 } | |
| 352 } | |
| 353 } | |
| 354 results_ = serial::GetConnections::Results::Create(infos); | |
| 355 } | |
| 356 | |
| 357 SerialGetControlSignalsFunction::SerialGetControlSignalsFunction() {} | |
| 358 | |
| 359 SerialGetControlSignalsFunction::~SerialGetControlSignalsFunction() {} | |
| 360 | |
| 361 bool SerialGetControlSignalsFunction::Prepare() { | |
| 362 params_ = serial::GetControlSignals::Params::Create(*args_); | |
| 363 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
| 364 | |
| 365 return true; | |
| 366 } | |
| 367 | |
| 368 void SerialGetControlSignalsFunction::Work() { | |
| 369 SerialConnection* connection = GetSerialConnection(params_->connection_id); | |
| 370 if (!connection) { | |
| 371 error_ = kErrorSerialConnectionNotFound; | |
| 372 return; | |
| 373 } | |
| 374 | |
| 375 serial::DeviceControlSignals signals; | |
| 376 if (!connection->GetControlSignals(&signals)) { | |
| 377 error_ = kErrorGetControlSignalsFailed; | |
| 378 return; | |
| 379 } | |
| 380 | |
| 381 results_ = serial::GetControlSignals::Results::Create(signals); | |
| 382 } | |
| 383 | |
| 384 SerialSetControlSignalsFunction::SerialSetControlSignalsFunction() {} | |
| 385 | |
| 386 SerialSetControlSignalsFunction::~SerialSetControlSignalsFunction() {} | |
| 387 | |
| 388 bool SerialSetControlSignalsFunction::Prepare() { | |
| 389 params_ = serial::SetControlSignals::Params::Create(*args_); | |
| 390 EXTENSION_FUNCTION_VALIDATE(params_.get()); | |
| 391 | |
| 392 return true; | |
| 393 } | |
| 394 | |
| 395 void SerialSetControlSignalsFunction::Work() { | |
| 396 SerialConnection* connection = GetSerialConnection(params_->connection_id); | |
| 397 if (!connection) { | |
| 398 error_ = kErrorSerialConnectionNotFound; | |
| 399 return; | |
| 400 } | |
| 401 | |
| 402 bool success = connection->SetControlSignals(params_->signals); | |
| 403 results_ = serial::SetControlSignals::Results::Create(success); | |
| 404 } | |
| 405 | |
| 406 } // namespace api | |
| 407 | |
| 408 } // namespace extensions | |
| 409 | |
| 410 namespace mojo { | |
| 411 | |
| 412 // static | |
| 413 linked_ptr<extensions::api::serial::DeviceInfo> | |
| 414 TypeConverter<device::serial::DeviceInfoPtr, | |
| 415 linked_ptr<extensions::api::serial::DeviceInfo> >:: | |
| 416 ConvertTo(const device::serial::DeviceInfoPtr& device) { | |
| 417 linked_ptr<extensions::api::serial::DeviceInfo> info( | |
| 418 new extensions::api::serial::DeviceInfo); | |
| 419 info->path = device->path; | |
| 420 if (device->has_vendor_id) | |
| 421 info->vendor_id.reset(new int(static_cast<int>(device->vendor_id))); | |
| 422 if (device->has_product_id) | |
| 423 info->product_id.reset(new int(static_cast<int>(device->product_id))); | |
| 424 if (device->display_name) | |
| 425 info->display_name.reset(new std::string(device->display_name)); | |
| 426 return info; | |
| 427 } | |
| 428 | |
| 429 } // namespace mojo | |
| OLD | NEW |