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