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