• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>
SetDefaultScopedPtrValue(scoped_ptr<T> & ptr,const T & value)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 
SerialAsyncApiFunction()53 SerialAsyncApiFunction::SerialAsyncApiFunction()
54     : manager_(NULL) {
55 }
56 
~SerialAsyncApiFunction()57 SerialAsyncApiFunction::~SerialAsyncApiFunction() {}
58 
PrePrepare()59 bool SerialAsyncApiFunction::PrePrepare() {
60   manager_ = ApiResourceManager<SerialConnection>::Get(browser_context());
61   DCHECK(manager_);
62   return true;
63 }
64 
Respond()65 bool SerialAsyncApiFunction::Respond() {
66   return error_.empty();
67 }
68 
GetSerialConnection(int api_resource_id)69 SerialConnection* SerialAsyncApiFunction::GetSerialConnection(
70     int api_resource_id) {
71   return manager_->Get(extension_->id(), api_resource_id);
72 }
73 
RemoveSerialConnection(int api_resource_id)74 void SerialAsyncApiFunction::RemoveSerialConnection(int api_resource_id) {
75   manager_->Remove(extension_->id(), api_resource_id);
76 }
77 
SerialGetDevicesFunction()78 SerialGetDevicesFunction::SerialGetDevicesFunction() {}
79 
Prepare()80 bool SerialGetDevicesFunction::Prepare() {
81   set_work_thread_id(BrowserThread::FILE);
82   return true;
83 }
84 
Work()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 
SerialConnectFunction()95 SerialConnectFunction::SerialConnectFunction() {}
96 
~SerialConnectFunction()97 SerialConnectFunction::~SerialConnectFunction() {}
98 
Prepare()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 
AsyncWorkStart()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 
OnConnected(bool success)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 
FinishConnect()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 
CreateSerialConnection(const std::string & port,const std::string & extension_id) const173 SerialConnection* SerialConnectFunction::CreateSerialConnection(
174     const std::string& port, const std::string& extension_id) const {
175   return new SerialConnection(port, extension_id);
176 }
177 
SerialUpdateFunction()178 SerialUpdateFunction::SerialUpdateFunction() {}
179 
~SerialUpdateFunction()180 SerialUpdateFunction::~SerialUpdateFunction() {}
181 
Prepare()182 bool SerialUpdateFunction::Prepare() {
183   params_ = serial::Update::Params::Create(*args_);
184   EXTENSION_FUNCTION_VALIDATE(params_.get());
185 
186   return true;
187 }
188 
Work()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 
SerialDisconnectFunction()199 SerialDisconnectFunction::SerialDisconnectFunction() {}
200 
~SerialDisconnectFunction()201 SerialDisconnectFunction::~SerialDisconnectFunction() {}
202 
Prepare()203 bool SerialDisconnectFunction::Prepare() {
204   params_ = serial::Disconnect::Params::Create(*args_);
205   EXTENSION_FUNCTION_VALIDATE(params_.get());
206 
207   return true;
208 }
209 
Work()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 
SerialSendFunction()221 SerialSendFunction::SerialSendFunction() {}
222 
~SerialSendFunction()223 SerialSendFunction::~SerialSendFunction() {}
224 
Prepare()225 bool SerialSendFunction::Prepare() {
226   params_ = serial::Send::Params::Create(*args_);
227   EXTENSION_FUNCTION_VALIDATE(params_.get());
228 
229   return true;
230 }
231 
AsyncWorkStart()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 
OnSendComplete(int bytes_sent,serial::SendError error)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 
SerialFlushFunction()256 SerialFlushFunction::SerialFlushFunction() {}
257 
~SerialFlushFunction()258 SerialFlushFunction::~SerialFlushFunction() {}
259 
Prepare()260 bool SerialFlushFunction::Prepare() {
261   params_ = serial::Flush::Params::Create(*args_);
262   EXTENSION_FUNCTION_VALIDATE(params_.get());
263   return true;
264 }
265 
Work()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 
SerialSetPausedFunction()277 SerialSetPausedFunction::SerialSetPausedFunction() {}
278 
~SerialSetPausedFunction()279 SerialSetPausedFunction::~SerialSetPausedFunction() {}
280 
Prepare()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 
Work()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 
SerialGetInfoFunction()308 SerialGetInfoFunction::SerialGetInfoFunction() {}
309 
~SerialGetInfoFunction()310 SerialGetInfoFunction::~SerialGetInfoFunction() {}
311 
Prepare()312 bool SerialGetInfoFunction::Prepare() {
313   params_ = serial::GetInfo::Params::Create(*args_);
314   EXTENSION_FUNCTION_VALIDATE(params_.get());
315 
316   return true;
317 }
318 
Work()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 
SerialGetConnectionsFunction()332 SerialGetConnectionsFunction::SerialGetConnectionsFunction() {}
333 
~SerialGetConnectionsFunction()334 SerialGetConnectionsFunction::~SerialGetConnectionsFunction() {}
335 
Prepare()336 bool SerialGetConnectionsFunction::Prepare() {
337   return true;
338 }
339 
Work()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 
SerialGetControlSignalsFunction()360 SerialGetControlSignalsFunction::SerialGetControlSignalsFunction() {}
361 
~SerialGetControlSignalsFunction()362 SerialGetControlSignalsFunction::~SerialGetControlSignalsFunction() {}
363 
Prepare()364 bool SerialGetControlSignalsFunction::Prepare() {
365   params_ = serial::GetControlSignals::Params::Create(*args_);
366   EXTENSION_FUNCTION_VALIDATE(params_.get());
367 
368   return true;
369 }
370 
Work()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 
SerialSetControlSignalsFunction()387 SerialSetControlSignalsFunction::SerialSetControlSignalsFunction() {}
388 
~SerialSetControlSignalsFunction()389 SerialSetControlSignalsFunction::~SerialSetControlSignalsFunction() {}
390 
Prepare()391 bool SerialSetControlSignalsFunction::Prepare() {
392   params_ = serial::SetControlSignals::Params::Create(*args_);
393   EXTENSION_FUNCTION_VALIDATE(params_.get());
394 
395   return true;
396 }
397 
Work()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> >::
ConvertTo(const device::SerialDeviceInfoPtr & device)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