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