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::SerialDeviceInfoPtr> 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 connection_->Close(); 140 delete connection_; 141 connection_ = NULL; 142 } 143 } else { 144 delete connection_; 145 connection_ = NULL; 146 } 147 148 BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, 149 base::Bind(&SerialConnectFunction::FinishConnect, 150 this)); 151 } 152 153 void SerialConnectFunction::FinishConnect() { 154 DCHECK_CURRENTLY_ON(BrowserThread::IO); 155 if (!connection_) { 156 error_ = kErrorConnectFailed; 157 } else { 158 int id = manager_->Add(connection_); 159 serial::ConnectionInfo info; 160 info.connection_id = id; 161 if (connection_->GetInfo(&info)) { 162 serial_event_dispatcher_->PollConnection(extension_->id(), id); 163 results_ = serial::Connect::Results::Create(info); 164 } else { 165 connection_->Close(); 166 RemoveSerialConnection(id); 167 error_ = kErrorConnectFailed; 168 } 169 } 170 AsyncWorkCompleted(); 171 } 172 173 SerialConnection* SerialConnectFunction::CreateSerialConnection( 174 const std::string& port, const std::string& extension_id) const { 175 return new SerialConnection(port, extension_id); 176 } 177 178 SerialUpdateFunction::SerialUpdateFunction() {} 179 180 SerialUpdateFunction::~SerialUpdateFunction() {} 181 182 bool SerialUpdateFunction::Prepare() { 183 params_ = serial::Update::Params::Create(*args_); 184 EXTENSION_FUNCTION_VALIDATE(params_.get()); 185 186 return true; 187 } 188 189 void SerialUpdateFunction::Work() { 190 SerialConnection* connection = GetSerialConnection(params_->connection_id); 191 if (!connection) { 192 error_ = kErrorSerialConnectionNotFound; 193 return; 194 } 195 bool success = connection->Configure(params_->options); 196 results_ = serial::Update::Results::Create(success); 197 } 198 199 SerialDisconnectFunction::SerialDisconnectFunction() {} 200 201 SerialDisconnectFunction::~SerialDisconnectFunction() {} 202 203 bool SerialDisconnectFunction::Prepare() { 204 params_ = serial::Disconnect::Params::Create(*args_); 205 EXTENSION_FUNCTION_VALIDATE(params_.get()); 206 207 return true; 208 } 209 210 void SerialDisconnectFunction::Work() { 211 SerialConnection* connection = GetSerialConnection(params_->connection_id); 212 if (!connection) { 213 error_ = kErrorSerialConnectionNotFound; 214 return; 215 } 216 connection->Close(); 217 RemoveSerialConnection(params_->connection_id); 218 results_ = serial::Disconnect::Results::Create(true); 219 } 220 221 SerialSendFunction::SerialSendFunction() {} 222 223 SerialSendFunction::~SerialSendFunction() {} 224 225 bool SerialSendFunction::Prepare() { 226 params_ = serial::Send::Params::Create(*args_); 227 EXTENSION_FUNCTION_VALIDATE(params_.get()); 228 229 return true; 230 } 231 232 void SerialSendFunction::AsyncWorkStart() { 233 SerialConnection* connection = GetSerialConnection(params_->connection_id); 234 if (!connection) { 235 error_ = kErrorSerialConnectionNotFound; 236 AsyncWorkCompleted(); 237 return; 238 } 239 240 if (!connection->Send(params_->data, 241 base::Bind(&SerialSendFunction::OnSendComplete, 242 this))) { 243 OnSendComplete(0, serial::SEND_ERROR_PENDING); 244 } 245 } 246 247 void SerialSendFunction::OnSendComplete(int bytes_sent, 248 serial::SendError error) { 249 serial::SendInfo send_info; 250 send_info.bytes_sent = bytes_sent; 251 send_info.error = error; 252 results_ = serial::Send::Results::Create(send_info); 253 AsyncWorkCompleted(); 254 } 255 256 SerialFlushFunction::SerialFlushFunction() {} 257 258 SerialFlushFunction::~SerialFlushFunction() {} 259 260 bool SerialFlushFunction::Prepare() { 261 params_ = serial::Flush::Params::Create(*args_); 262 EXTENSION_FUNCTION_VALIDATE(params_.get()); 263 return true; 264 } 265 266 void SerialFlushFunction::Work() { 267 SerialConnection* connection = GetSerialConnection(params_->connection_id); 268 if (!connection) { 269 error_ = kErrorSerialConnectionNotFound; 270 return; 271 } 272 273 bool success = connection->Flush(); 274 results_ = serial::Flush::Results::Create(success); 275 } 276 277 SerialSetPausedFunction::SerialSetPausedFunction() {} 278 279 SerialSetPausedFunction::~SerialSetPausedFunction() {} 280 281 bool SerialSetPausedFunction::Prepare() { 282 params_ = serial::SetPaused::Params::Create(*args_); 283 EXTENSION_FUNCTION_VALIDATE(params_.get()); 284 285 serial_event_dispatcher_ = SerialEventDispatcher::Get(browser_context()); 286 DCHECK(serial_event_dispatcher_); 287 return true; 288 } 289 290 void SerialSetPausedFunction::Work() { 291 SerialConnection* connection = GetSerialConnection(params_->connection_id); 292 if (!connection) { 293 error_ = kErrorSerialConnectionNotFound; 294 return; 295 } 296 297 if (params_->paused != connection->paused()) { 298 connection->set_paused(params_->paused); 299 if (!params_->paused) { 300 serial_event_dispatcher_->PollConnection(extension_->id(), 301 params_->connection_id); 302 } 303 } 304 305 results_ = serial::SetPaused::Results::Create(); 306 } 307 308 SerialGetInfoFunction::SerialGetInfoFunction() {} 309 310 SerialGetInfoFunction::~SerialGetInfoFunction() {} 311 312 bool SerialGetInfoFunction::Prepare() { 313 params_ = serial::GetInfo::Params::Create(*args_); 314 EXTENSION_FUNCTION_VALIDATE(params_.get()); 315 316 return true; 317 } 318 319 void SerialGetInfoFunction::Work() { 320 SerialConnection* connection = GetSerialConnection(params_->connection_id); 321 if (!connection) { 322 error_ = kErrorSerialConnectionNotFound; 323 return; 324 } 325 326 serial::ConnectionInfo info; 327 info.connection_id = params_->connection_id; 328 connection->GetInfo(&info); 329 results_ = serial::GetInfo::Results::Create(info); 330 } 331 332 SerialGetConnectionsFunction::SerialGetConnectionsFunction() {} 333 334 SerialGetConnectionsFunction::~SerialGetConnectionsFunction() {} 335 336 bool SerialGetConnectionsFunction::Prepare() { 337 return true; 338 } 339 340 void SerialGetConnectionsFunction::Work() { 341 std::vector<linked_ptr<serial::ConnectionInfo> > infos; 342 const base::hash_set<int>* connection_ids = manager_->GetResourceIds( 343 extension_->id()); 344 if (connection_ids) { 345 for (base::hash_set<int>::const_iterator it = connection_ids->begin(); 346 it != connection_ids->end(); ++it) { 347 int connection_id = *it; 348 SerialConnection *connection = GetSerialConnection(connection_id); 349 if (connection) { 350 linked_ptr<serial::ConnectionInfo> info(new serial::ConnectionInfo()); 351 info->connection_id = connection_id; 352 connection->GetInfo(info.get()); 353 infos.push_back(info); 354 } 355 } 356 } 357 results_ = serial::GetConnections::Results::Create(infos); 358 } 359 360 SerialGetControlSignalsFunction::SerialGetControlSignalsFunction() {} 361 362 SerialGetControlSignalsFunction::~SerialGetControlSignalsFunction() {} 363 364 bool SerialGetControlSignalsFunction::Prepare() { 365 params_ = serial::GetControlSignals::Params::Create(*args_); 366 EXTENSION_FUNCTION_VALIDATE(params_.get()); 367 368 return true; 369 } 370 371 void SerialGetControlSignalsFunction::Work() { 372 SerialConnection* connection = GetSerialConnection(params_->connection_id); 373 if (!connection) { 374 error_ = kErrorSerialConnectionNotFound; 375 return; 376 } 377 378 serial::DeviceControlSignals signals; 379 if (!connection->GetControlSignals(&signals)) { 380 error_ = kErrorGetControlSignalsFailed; 381 return; 382 } 383 384 results_ = serial::GetControlSignals::Results::Create(signals); 385 } 386 387 SerialSetControlSignalsFunction::SerialSetControlSignalsFunction() {} 388 389 SerialSetControlSignalsFunction::~SerialSetControlSignalsFunction() {} 390 391 bool SerialSetControlSignalsFunction::Prepare() { 392 params_ = serial::SetControlSignals::Params::Create(*args_); 393 EXTENSION_FUNCTION_VALIDATE(params_.get()); 394 395 return true; 396 } 397 398 void SerialSetControlSignalsFunction::Work() { 399 SerialConnection* connection = GetSerialConnection(params_->connection_id); 400 if (!connection) { 401 error_ = kErrorSerialConnectionNotFound; 402 return; 403 } 404 405 bool success = connection->SetControlSignals(params_->signals); 406 results_ = serial::SetControlSignals::Results::Create(success); 407 } 408 409 } // namespace api 410 411 } // namespace extensions 412 413 namespace mojo { 414 415 // static 416 linked_ptr<extensions::api::serial::DeviceInfo> 417 TypeConverter<device::SerialDeviceInfoPtr, 418 linked_ptr<extensions::api::serial::DeviceInfo> >:: 419 ConvertTo(const device::SerialDeviceInfoPtr& device) { 420 linked_ptr<extensions::api::serial::DeviceInfo> info( 421 new extensions::api::serial::DeviceInfo); 422 info->path = device->path; 423 if (device->has_vendor_id) 424 info->vendor_id.reset(new int(static_cast<int>(device->vendor_id))); 425 if (device->has_product_id) 426 info->product_id.reset(new int(static_cast<int>(device->product_id))); 427 if (device->display_name) 428 info->display_name.reset(new std::string(device->display_name)); 429 return info; 430 } 431 432 } // namespace mojo 433