Add testing/scripts/OWNERS
[chromium-blink-merge.git] / extensions / browser / api / serial / serial_connection.cc
blob7e95f5a6447625ecb67be1e26b8b91cbfc4524fd
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.
5 #include "extensions/browser/api/serial/serial_connection.h"
7 #include <string>
9 #include "base/files/file_path.h"
10 #include "base/lazy_instance.h"
11 #include "base/message_loop/message_loop.h"
12 #include "extensions/browser/api/api_resource_manager.h"
13 #include "extensions/common/api/serial.h"
15 namespace extensions {
17 namespace {
19 const int kDefaultBufferSize = 4096;
21 core_api::serial::SendError ConvertSendErrorFromMojo(
22 device::serial::SendError input) {
23 switch (input) {
24 case device::serial::SEND_ERROR_NONE:
25 return core_api::serial::SEND_ERROR_NONE;
26 case device::serial::SEND_ERROR_DISCONNECTED:
27 return core_api::serial::SEND_ERROR_DISCONNECTED;
28 case device::serial::SEND_ERROR_PENDING:
29 return core_api::serial::SEND_ERROR_PENDING;
30 case device::serial::SEND_ERROR_TIMEOUT:
31 return core_api::serial::SEND_ERROR_TIMEOUT;
32 case device::serial::SEND_ERROR_SYSTEM_ERROR:
33 return core_api::serial::SEND_ERROR_SYSTEM_ERROR;
35 return core_api::serial::SEND_ERROR_NONE;
38 core_api::serial::ReceiveError ConvertReceiveErrorFromMojo(
39 device::serial::ReceiveError input) {
40 switch (input) {
41 case device::serial::RECEIVE_ERROR_NONE:
42 return core_api::serial::RECEIVE_ERROR_NONE;
43 case device::serial::RECEIVE_ERROR_DISCONNECTED:
44 return core_api::serial::RECEIVE_ERROR_DISCONNECTED;
45 case device::serial::RECEIVE_ERROR_TIMEOUT:
46 return core_api::serial::RECEIVE_ERROR_TIMEOUT;
47 case device::serial::RECEIVE_ERROR_DEVICE_LOST:
48 return core_api::serial::RECEIVE_ERROR_DEVICE_LOST;
49 case device::serial::RECEIVE_ERROR_SYSTEM_ERROR:
50 return core_api::serial::RECEIVE_ERROR_SYSTEM_ERROR;
52 return core_api::serial::RECEIVE_ERROR_NONE;
55 core_api::serial::DataBits ConvertDataBitsFromMojo(
56 device::serial::DataBits input) {
57 switch (input) {
58 case device::serial::DATA_BITS_NONE:
59 return core_api::serial::DATA_BITS_NONE;
60 case device::serial::DATA_BITS_SEVEN:
61 return core_api::serial::DATA_BITS_SEVEN;
62 case device::serial::DATA_BITS_EIGHT:
63 return core_api::serial::DATA_BITS_EIGHT;
65 return core_api::serial::DATA_BITS_NONE;
68 device::serial::DataBits ConvertDataBitsToMojo(
69 core_api::serial::DataBits input) {
70 switch (input) {
71 case core_api::serial::DATA_BITS_NONE:
72 return device::serial::DATA_BITS_NONE;
73 case core_api::serial::DATA_BITS_SEVEN:
74 return device::serial::DATA_BITS_SEVEN;
75 case core_api::serial::DATA_BITS_EIGHT:
76 return device::serial::DATA_BITS_EIGHT;
78 return device::serial::DATA_BITS_NONE;
81 core_api::serial::ParityBit ConvertParityBitFromMojo(
82 device::serial::ParityBit input) {
83 switch (input) {
84 case device::serial::PARITY_BIT_NONE:
85 return core_api::serial::PARITY_BIT_NONE;
86 case device::serial::PARITY_BIT_ODD:
87 return core_api::serial::PARITY_BIT_ODD;
88 case device::serial::PARITY_BIT_NO:
89 return core_api::serial::PARITY_BIT_NO;
90 case device::serial::PARITY_BIT_EVEN:
91 return core_api::serial::PARITY_BIT_EVEN;
93 return core_api::serial::PARITY_BIT_NONE;
96 device::serial::ParityBit ConvertParityBitToMojo(
97 core_api::serial::ParityBit input) {
98 switch (input) {
99 case core_api::serial::PARITY_BIT_NONE:
100 return device::serial::PARITY_BIT_NONE;
101 case core_api::serial::PARITY_BIT_NO:
102 return device::serial::PARITY_BIT_NO;
103 case core_api::serial::PARITY_BIT_ODD:
104 return device::serial::PARITY_BIT_ODD;
105 case core_api::serial::PARITY_BIT_EVEN:
106 return device::serial::PARITY_BIT_EVEN;
108 return device::serial::PARITY_BIT_NONE;
111 core_api::serial::StopBits ConvertStopBitsFromMojo(
112 device::serial::StopBits input) {
113 switch (input) {
114 case device::serial::STOP_BITS_NONE:
115 return core_api::serial::STOP_BITS_NONE;
116 case device::serial::STOP_BITS_ONE:
117 return core_api::serial::STOP_BITS_ONE;
118 case device::serial::STOP_BITS_TWO:
119 return core_api::serial::STOP_BITS_TWO;
121 return core_api::serial::STOP_BITS_NONE;
124 device::serial::StopBits ConvertStopBitsToMojo(
125 core_api::serial::StopBits input) {
126 switch (input) {
127 case core_api::serial::STOP_BITS_NONE:
128 return device::serial::STOP_BITS_NONE;
129 case core_api::serial::STOP_BITS_ONE:
130 return device::serial::STOP_BITS_ONE;
131 case core_api::serial::STOP_BITS_TWO:
132 return device::serial::STOP_BITS_TWO;
134 return device::serial::STOP_BITS_NONE;
137 class SendBuffer : public device::ReadOnlyBuffer {
138 public:
139 SendBuffer(
140 const std::string& data,
141 const base::Callback<void(int, device::serial::SendError)>& callback)
142 : data_(data), callback_(callback) {}
143 ~SendBuffer() override {}
144 const char* GetData() override { return data_.c_str(); }
145 uint32_t GetSize() override { return static_cast<uint32_t>(data_.size()); }
146 void Done(uint32_t bytes_read) override {
147 callback_.Run(bytes_read, device::serial::SEND_ERROR_NONE);
149 void DoneWithError(uint32_t bytes_read, int32_t error) override {
150 callback_.Run(bytes_read, static_cast<device::serial::SendError>(error));
153 private:
154 const std::string data_;
155 const base::Callback<void(int, device::serial::SendError)> callback_;
158 class ReceiveBuffer : public device::WritableBuffer {
159 public:
160 ReceiveBuffer(
161 scoped_refptr<net::IOBuffer> buffer,
162 uint32_t size,
163 const base::Callback<void(int, device::serial::ReceiveError)>& callback)
164 : buffer_(buffer), size_(size), callback_(callback) {}
165 ~ReceiveBuffer() override {}
166 char* GetData() override { return buffer_->data(); }
167 uint32_t GetSize() override { return size_; }
168 void Done(uint32_t bytes_written) override {
169 callback_.Run(bytes_written, device::serial::RECEIVE_ERROR_NONE);
171 void DoneWithError(uint32_t bytes_written, int32_t error) override {
172 callback_.Run(bytes_written,
173 static_cast<device::serial::ReceiveError>(error));
176 private:
177 scoped_refptr<net::IOBuffer> buffer_;
178 const uint32_t size_;
179 const base::Callback<void(int, device::serial::ReceiveError)> callback_;
182 } // namespace
184 static base::LazyInstance<
185 BrowserContextKeyedAPIFactory<ApiResourceManager<SerialConnection> > >
186 g_factory = LAZY_INSTANCE_INITIALIZER;
188 // static
189 template <>
190 BrowserContextKeyedAPIFactory<ApiResourceManager<SerialConnection> >*
191 ApiResourceManager<SerialConnection>::GetFactoryInstance() {
192 return g_factory.Pointer();
195 SerialConnection::SerialConnection(const std::string& port,
196 const std::string& owner_extension_id)
197 : ApiResource(owner_extension_id),
198 port_(port),
199 persistent_(false),
200 buffer_size_(kDefaultBufferSize),
201 receive_timeout_(0),
202 send_timeout_(0),
203 paused_(false),
204 io_handler_(device::SerialIoHandler::Create(
205 content::BrowserThread::GetMessageLoopProxyForThread(
206 content::BrowserThread::FILE),
207 content::BrowserThread::GetMessageLoopProxyForThread(
208 content::BrowserThread::UI))) {
209 DCHECK_CURRENTLY_ON(BrowserThread::IO);
212 SerialConnection::~SerialConnection() {
213 io_handler_->CancelRead(device::serial::RECEIVE_ERROR_DISCONNECTED);
214 io_handler_->CancelWrite(device::serial::SEND_ERROR_DISCONNECTED);
217 bool SerialConnection::IsPersistent() const {
218 return persistent();
221 void SerialConnection::set_buffer_size(int buffer_size) {
222 buffer_size_ = buffer_size;
225 void SerialConnection::set_receive_timeout(int receive_timeout) {
226 receive_timeout_ = receive_timeout;
229 void SerialConnection::set_send_timeout(int send_timeout) {
230 send_timeout_ = send_timeout;
233 void SerialConnection::set_paused(bool paused) {
234 paused_ = paused;
235 if (paused) {
236 io_handler_->CancelRead(device::serial::RECEIVE_ERROR_NONE);
240 void SerialConnection::Open(const OpenCompleteCallback& callback) {
241 DCHECK_CURRENTLY_ON(BrowserThread::IO);
242 io_handler_->Open(port_, callback);
245 bool SerialConnection::Receive(const ReceiveCompleteCallback& callback) {
246 DCHECK_CURRENTLY_ON(BrowserThread::IO);
247 if (!receive_complete_.is_null())
248 return false;
249 receive_complete_ = callback;
250 receive_buffer_ = new net::IOBuffer(buffer_size_);
251 io_handler_->Read(scoped_ptr<device::WritableBuffer>(new ReceiveBuffer(
252 receive_buffer_,
253 buffer_size_,
254 base::Bind(&SerialConnection::OnAsyncReadComplete, AsWeakPtr()))));
255 receive_timeout_task_.reset();
256 if (receive_timeout_ > 0) {
257 receive_timeout_task_.reset(new TimeoutTask(
258 base::Bind(&SerialConnection::OnReceiveTimeout, AsWeakPtr()),
259 base::TimeDelta::FromMilliseconds(receive_timeout_)));
261 return true;
264 bool SerialConnection::Send(const std::string& data,
265 const SendCompleteCallback& callback) {
266 DCHECK_CURRENTLY_ON(BrowserThread::IO);
267 if (!send_complete_.is_null())
268 return false;
269 send_complete_ = callback;
270 io_handler_->Write(scoped_ptr<device::ReadOnlyBuffer>(new SendBuffer(
271 data, base::Bind(&SerialConnection::OnAsyncWriteComplete, AsWeakPtr()))));
272 send_timeout_task_.reset();
273 if (send_timeout_ > 0) {
274 send_timeout_task_.reset(new TimeoutTask(
275 base::Bind(&SerialConnection::OnSendTimeout, AsWeakPtr()),
276 base::TimeDelta::FromMilliseconds(send_timeout_)));
278 return true;
281 bool SerialConnection::Configure(
282 const core_api::serial::ConnectionOptions& options) {
283 DCHECK_CURRENTLY_ON(BrowserThread::IO);
284 if (options.persistent.get())
285 set_persistent(*options.persistent);
286 if (options.name.get())
287 set_name(*options.name);
288 if (options.buffer_size.get())
289 set_buffer_size(*options.buffer_size);
290 if (options.receive_timeout.get())
291 set_receive_timeout(*options.receive_timeout);
292 if (options.send_timeout.get())
293 set_send_timeout(*options.send_timeout);
294 bool success = io_handler_->ConfigurePort(
295 *device::serial::ConnectionOptions::From(options));
296 io_handler_->CancelRead(device::serial::RECEIVE_ERROR_NONE);
297 return success;
300 void SerialConnection::SetIoHandlerForTest(
301 scoped_refptr<device::SerialIoHandler> handler) {
302 io_handler_ = handler;
305 bool SerialConnection::GetInfo(core_api::serial::ConnectionInfo* info) const {
306 DCHECK_CURRENTLY_ON(BrowserThread::IO);
307 info->paused = paused_;
308 info->persistent = persistent_;
309 info->name = name_;
310 info->buffer_size = buffer_size_;
311 info->receive_timeout = receive_timeout_;
312 info->send_timeout = send_timeout_;
313 device::serial::ConnectionInfoPtr port_info = io_handler_->GetPortInfo();
314 if (!port_info)
315 return false;
317 info->bitrate.reset(new int(port_info->bitrate));
318 info->data_bits = ConvertDataBitsFromMojo(port_info->data_bits);
319 info->parity_bit = ConvertParityBitFromMojo(port_info->parity_bit);
320 info->stop_bits = ConvertStopBitsFromMojo(port_info->stop_bits);
321 info->cts_flow_control.reset(new bool(port_info->cts_flow_control));
322 return true;
325 bool SerialConnection::Flush() const {
326 return io_handler_->Flush();
329 bool SerialConnection::GetControlSignals(
330 core_api::serial::DeviceControlSignals* control_signals) const {
331 device::serial::DeviceControlSignalsPtr signals =
332 io_handler_->GetControlSignals();
333 if (!signals)
334 return false;
336 control_signals->dcd = signals->dcd;
337 control_signals->cts = signals->cts;
338 control_signals->ri = signals->ri;
339 control_signals->dsr = signals->dsr;
340 return true;
343 bool SerialConnection::SetControlSignals(
344 const core_api::serial::HostControlSignals& control_signals) {
345 return io_handler_->SetControlSignals(
346 *device::serial::HostControlSignals::From(control_signals));
349 void SerialConnection::OnReceiveTimeout() {
350 DCHECK_CURRENTLY_ON(BrowserThread::IO);
351 io_handler_->CancelRead(device::serial::RECEIVE_ERROR_TIMEOUT);
354 void SerialConnection::OnSendTimeout() {
355 DCHECK_CURRENTLY_ON(BrowserThread::IO);
356 io_handler_->CancelWrite(device::serial::SEND_ERROR_TIMEOUT);
359 void SerialConnection::OnAsyncReadComplete(int bytes_read,
360 device::serial::ReceiveError error) {
361 DCHECK_CURRENTLY_ON(BrowserThread::IO);
362 DCHECK(!receive_complete_.is_null());
363 ReceiveCompleteCallback callback = receive_complete_;
364 receive_complete_.Reset();
365 receive_timeout_task_.reset();
366 callback.Run(std::string(receive_buffer_->data(), bytes_read),
367 ConvertReceiveErrorFromMojo(error));
368 receive_buffer_ = NULL;
371 void SerialConnection::OnAsyncWriteComplete(int bytes_sent,
372 device::serial::SendError error) {
373 DCHECK_CURRENTLY_ON(BrowserThread::IO);
374 DCHECK(!send_complete_.is_null());
375 SendCompleteCallback callback = send_complete_;
376 send_complete_.Reset();
377 send_timeout_task_.reset();
378 callback.Run(bytes_sent, ConvertSendErrorFromMojo(error));
381 SerialConnection::TimeoutTask::TimeoutTask(const base::Closure& closure,
382 const base::TimeDelta& delay)
383 : weak_factory_(this), closure_(closure), delay_(delay) {
384 base::MessageLoop::current()->PostDelayedTask(
385 FROM_HERE,
386 base::Bind(&TimeoutTask::Run, weak_factory_.GetWeakPtr()),
387 delay_);
390 SerialConnection::TimeoutTask::~TimeoutTask() {
393 void SerialConnection::TimeoutTask::Run() const {
394 closure_.Run();
397 } // namespace extensions
399 namespace mojo {
401 // static
402 device::serial::HostControlSignalsPtr
403 TypeConverter<device::serial::HostControlSignalsPtr,
404 extensions::core_api::serial::HostControlSignals>::
405 Convert(const extensions::core_api::serial::HostControlSignals& input) {
406 device::serial::HostControlSignalsPtr output(
407 device::serial::HostControlSignals::New());
408 if (input.dtr.get()) {
409 output->has_dtr = true;
410 output->dtr = *input.dtr;
412 if (input.rts.get()) {
413 output->has_rts = true;
414 output->rts = *input.rts;
416 return output.Pass();
419 // static
420 device::serial::ConnectionOptionsPtr
421 TypeConverter<device::serial::ConnectionOptionsPtr,
422 extensions::core_api::serial::ConnectionOptions>::
423 Convert(const extensions::core_api::serial::ConnectionOptions& input) {
424 device::serial::ConnectionOptionsPtr output(
425 device::serial::ConnectionOptions::New());
426 if (input.bitrate.get() && *input.bitrate > 0)
427 output->bitrate = *input.bitrate;
428 output->data_bits = extensions::ConvertDataBitsToMojo(input.data_bits);
429 output->parity_bit = extensions::ConvertParityBitToMojo(input.parity_bit);
430 output->stop_bits = extensions::ConvertStopBitsToMojo(input.stop_bits);
431 if (input.cts_flow_control.get()) {
432 output->has_cts_flow_control = true;
433 output->cts_flow_control = *input.cts_flow_control;
435 return output.Pass();
438 } // namespace mojo