1 // Copyright (c) 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 "base/values.h" 8 #include "chrome/browser/extensions/extension_system.h" 9 #include "chrome/browser/extensions/api/serial/serial_connection.h" 10 #include "chrome/browser/extensions/api/serial/serial_port_enumerator.h" 11 #include "content/public/browser/browser_thread.h" 12 13 using content::BrowserThread; 14 15 namespace extensions { 16 17 const char kConnectionIdKey[] = "connectionId"; 18 const char kDataKey[] = "data"; 19 const char kBytesReadKey[] = "bytesRead"; 20 const char kBytesWrittenKey[] = "bytesWritten"; 21 const char kBitrateKey[] = "bitrate"; 22 const char kSuccessKey[] = "success"; 23 const char kDcdKey[] = "dcd"; 24 const char kCtsKey[] = "cts"; 25 26 const char kErrorGetControlSignalsFailed[] = "Failed to get control signals."; 27 const char kErrorSetControlSignalsFailed[] = "Failed to set control signals."; 28 const char kSerialReadInvalidBytesToRead[] = "Number of bytes to read must " 29 "be a positive number less than 1,048,576."; 30 31 SerialAsyncApiFunction::SerialAsyncApiFunction() 32 : manager_(NULL) { 33 } 34 35 SerialAsyncApiFunction::~SerialAsyncApiFunction() { 36 } 37 38 bool SerialAsyncApiFunction::PrePrepare() { 39 manager_ = ApiResourceManager<SerialConnection>::Get(profile()); 40 DCHECK(manager_); 41 return true; 42 } 43 44 SerialConnection* SerialAsyncApiFunction::GetSerialConnection( 45 int api_resource_id) { 46 return manager_->Get(extension_->id(), api_resource_id); 47 } 48 49 void SerialAsyncApiFunction::RemoveSerialConnection(int api_resource_id) { 50 manager_->Remove(extension_->id(), api_resource_id); 51 } 52 53 SerialGetPortsFunction::SerialGetPortsFunction() {} 54 55 bool SerialGetPortsFunction::Prepare() { 56 set_work_thread_id(BrowserThread::FILE); 57 return true; 58 } 59 60 void SerialGetPortsFunction::Work() { 61 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 62 63 base::ListValue* ports = new base::ListValue(); 64 SerialPortEnumerator::StringSet port_names = 65 SerialPortEnumerator::GenerateValidSerialPortNames(); 66 SerialPortEnumerator::StringSet::const_iterator i = port_names.begin(); 67 while (i != port_names.end()) { 68 ports->Append(Value::CreateStringValue(*i++)); 69 } 70 71 SetResult(ports); 72 } 73 74 bool SerialGetPortsFunction::Respond() { 75 return true; 76 } 77 78 // It's a fool's errand to come up with a default bitrate, because we don't get 79 // to control both sides of the communication. Unless the other side has 80 // implemented auto-bitrate detection (rare), if we pick the wrong rate, then 81 // you're gonna have a bad time. Close doesn't count. 82 // 83 // But we'd like to pick something that has a chance of working, and 9600 is a 84 // good balance between popularity and speed. So 9600 it is. 85 SerialOpenFunction::SerialOpenFunction() 86 : bitrate_(9600) { 87 } 88 89 SerialOpenFunction::~SerialOpenFunction() { 90 } 91 92 bool SerialOpenFunction::Prepare() { 93 set_work_thread_id(BrowserThread::FILE); 94 95 params_ = api::serial::Open::Params::Create(*args_); 96 EXTENSION_FUNCTION_VALIDATE(params_.get()); 97 98 if (params_->options.get()) { 99 scoped_ptr<base::DictionaryValue> options = params_->options->ToValue(); 100 if (options->HasKey(kBitrateKey)) 101 EXTENSION_FUNCTION_VALIDATE(options->GetInteger(kBitrateKey, &bitrate_)); 102 } 103 104 return true; 105 } 106 107 void SerialOpenFunction::AsyncWorkStart() { 108 Work(); 109 } 110 111 void SerialOpenFunction::Work() { 112 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 113 const SerialPortEnumerator::StringSet name_set( 114 SerialPortEnumerator::GenerateValidSerialPortNames()); 115 if (DoesPortExist(params_->port)) { 116 SerialConnection* serial_connection = CreateSerialConnection( 117 params_->port, 118 bitrate_, 119 extension_->id()); 120 CHECK(serial_connection); 121 int id = manager_->Add(serial_connection); 122 CHECK(id); 123 124 bool open_result = serial_connection->Open(); 125 if (!open_result) { 126 serial_connection->Close(); 127 RemoveSerialConnection(id); 128 id = -1; 129 } 130 131 base::DictionaryValue* result = new base::DictionaryValue(); 132 result->SetInteger(kConnectionIdKey, id); 133 SetResult(result); 134 AsyncWorkCompleted(); 135 } else { 136 base::DictionaryValue* result = new base::DictionaryValue(); 137 result->SetInteger(kConnectionIdKey, -1); 138 SetResult(result); 139 AsyncWorkCompleted(); 140 } 141 } 142 143 SerialConnection* SerialOpenFunction::CreateSerialConnection( 144 const std::string& port, 145 int bitrate, 146 const std::string& owner_extension_id) { 147 return new SerialConnection(port, bitrate, owner_extension_id); 148 } 149 150 bool SerialOpenFunction::DoesPortExist(const std::string& port) { 151 const SerialPortEnumerator::StringSet name_set( 152 SerialPortEnumerator::GenerateValidSerialPortNames()); 153 return SerialPortEnumerator::DoesPortExist(name_set, params_->port); 154 } 155 156 bool SerialOpenFunction::Respond() { 157 return true; 158 } 159 160 SerialCloseFunction::SerialCloseFunction() { 161 } 162 163 SerialCloseFunction::~SerialCloseFunction() { 164 } 165 166 bool SerialCloseFunction::Prepare() { 167 set_work_thread_id(BrowserThread::FILE); 168 169 params_ = api::serial::Close::Params::Create(*args_); 170 EXTENSION_FUNCTION_VALIDATE(params_.get()); 171 172 return true; 173 } 174 175 void SerialCloseFunction::Work() { 176 bool close_result = false; 177 SerialConnection* serial_connection = GetSerialConnection( 178 params_->connection_id); 179 if (serial_connection) { 180 serial_connection->Close(); 181 RemoveSerialConnection(params_->connection_id); 182 close_result = true; 183 } 184 185 SetResult(Value::CreateBooleanValue(close_result)); 186 } 187 188 bool SerialCloseFunction::Respond() { 189 return true; 190 } 191 192 SerialReadFunction::SerialReadFunction() { 193 } 194 195 SerialReadFunction::~SerialReadFunction() { 196 } 197 198 bool SerialReadFunction::Prepare() { 199 set_work_thread_id(BrowserThread::FILE); 200 201 params_ = api::serial::Read::Params::Create(*args_); 202 EXTENSION_FUNCTION_VALIDATE(params_.get()); 203 if (params_->bytes_to_read <= 0 || params_->bytes_to_read >= 1024 * 1024) { 204 error_ = kSerialReadInvalidBytesToRead; 205 return false; 206 } 207 208 return true; 209 } 210 211 void SerialReadFunction::Work() { 212 int bytes_read = -1; 213 scoped_refptr<net::IOBufferWithSize> io_buffer( 214 new net::IOBufferWithSize(params_->bytes_to_read)); 215 SerialConnection* serial_connection(GetSerialConnection( 216 params_->connection_id)); 217 218 if (serial_connection) 219 bytes_read = serial_connection->Read(io_buffer); 220 221 base::DictionaryValue* result = new base::DictionaryValue(); 222 223 // The API is defined to require a 'data' value, so we will always 224 // create a BinaryValue, even if it's zero-length. 225 if (bytes_read < 0) 226 bytes_read = 0; 227 result->SetInteger(kBytesReadKey, bytes_read); 228 result->Set(kDataKey, base::BinaryValue::CreateWithCopiedBuffer( 229 io_buffer->data(), bytes_read)); 230 SetResult(result); 231 } 232 233 bool SerialReadFunction::Respond() { 234 return true; 235 } 236 237 SerialWriteFunction::SerialWriteFunction() 238 : io_buffer_(NULL), io_buffer_size_(0) { 239 } 240 241 SerialWriteFunction::~SerialWriteFunction() { 242 } 243 244 bool SerialWriteFunction::Prepare() { 245 set_work_thread_id(BrowserThread::FILE); 246 247 params_ = api::serial::Write::Params::Create(*args_); 248 EXTENSION_FUNCTION_VALIDATE(params_.get()); 249 250 io_buffer_size_ = params_->data.size(); 251 io_buffer_ = new net::WrappedIOBuffer(params_->data.data()); 252 253 return true; 254 } 255 256 void SerialWriteFunction::Work() { 257 int bytes_written = -1; 258 SerialConnection* serial_connection = GetSerialConnection( 259 params_->connection_id); 260 if (serial_connection) 261 bytes_written = serial_connection->Write(io_buffer_, io_buffer_size_); 262 else 263 error_ = kSerialConnectionNotFoundError; 264 265 base::DictionaryValue* result = new base::DictionaryValue(); 266 result->SetInteger(kBytesWrittenKey, bytes_written); 267 SetResult(result); 268 } 269 270 bool SerialWriteFunction::Respond() { 271 return true; 272 } 273 274 SerialFlushFunction::SerialFlushFunction() { 275 } 276 277 SerialFlushFunction::~SerialFlushFunction() { 278 } 279 280 bool SerialFlushFunction::Prepare() { 281 set_work_thread_id(BrowserThread::FILE); 282 283 params_ = api::serial::Flush::Params::Create(*args_); 284 EXTENSION_FUNCTION_VALIDATE(params_.get()); 285 return true; 286 } 287 288 void SerialFlushFunction::Work() { 289 bool flush_result = false; 290 SerialConnection* serial_connection = GetSerialConnection( 291 params_->connection_id); 292 if (serial_connection) { 293 serial_connection->Flush(); 294 flush_result = true; 295 } 296 297 SetResult(Value::CreateBooleanValue(flush_result)); 298 } 299 300 bool SerialFlushFunction::Respond() { 301 return true; 302 } 303 304 SerialGetControlSignalsFunction::SerialGetControlSignalsFunction() 305 : api_response_(false) { 306 } 307 308 SerialGetControlSignalsFunction::~SerialGetControlSignalsFunction() { 309 } 310 311 bool SerialGetControlSignalsFunction::Prepare() { 312 set_work_thread_id(BrowserThread::FILE); 313 314 params_ = api::serial::GetControlSignals::Params::Create(*args_); 315 EXTENSION_FUNCTION_VALIDATE(params_.get()); 316 317 return true; 318 } 319 320 void SerialGetControlSignalsFunction::Work() { 321 base::DictionaryValue *result = new base::DictionaryValue(); 322 SerialConnection* serial_connection = GetSerialConnection( 323 params_->connection_id); 324 if (serial_connection) { 325 SerialConnection::ControlSignals control_signals = { 0 }; 326 if (serial_connection->GetControlSignals(control_signals)) { 327 api_response_ = true; 328 result->SetBoolean(kDcdKey, control_signals.dcd); 329 result->SetBoolean(kCtsKey, control_signals.cts); 330 } else { 331 error_ = kErrorGetControlSignalsFailed; 332 } 333 } else { 334 error_ = kSerialConnectionNotFoundError; 335 result->SetBoolean(kSuccessKey, false); 336 } 337 338 SetResult(result); 339 } 340 341 bool SerialGetControlSignalsFunction::Respond() { 342 return api_response_; 343 } 344 345 SerialSetControlSignalsFunction::SerialSetControlSignalsFunction() { 346 } 347 348 SerialSetControlSignalsFunction::~SerialSetControlSignalsFunction() { 349 } 350 351 bool SerialSetControlSignalsFunction::Prepare() { 352 set_work_thread_id(BrowserThread::FILE); 353 354 params_ = api::serial::SetControlSignals::Params::Create(*args_); 355 EXTENSION_FUNCTION_VALIDATE(params_.get()); 356 357 return true; 358 } 359 360 void SerialSetControlSignalsFunction::Work() { 361 SerialConnection* serial_connection = GetSerialConnection( 362 params_->connection_id); 363 if (serial_connection) { 364 SerialConnection::ControlSignals control_signals = { 0 }; 365 control_signals.should_set_dtr = params_->options.dtr.get() != NULL; 366 if (control_signals.should_set_dtr) 367 control_signals.dtr = *(params_->options.dtr); 368 control_signals.should_set_rts = params_->options.rts.get() != NULL; 369 if (control_signals.should_set_rts) 370 control_signals.rts = *(params_->options.rts); 371 if (serial_connection->SetControlSignals(control_signals)) { 372 SetResult(Value::CreateBooleanValue(true)); 373 } else { 374 error_ = kErrorSetControlSignalsFailed; 375 SetResult(Value::CreateBooleanValue(false)); 376 } 377 } else { 378 error_ = kSerialConnectionNotFoundError; 379 SetResult(Value::CreateBooleanValue(false)); 380 } 381 } 382 383 bool SerialSetControlSignalsFunction::Respond() { 384 return true; 385 } 386 387 } // namespace extensions 388