• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef CHROME_BROWSER_EXTENSIONS_API_SERIAL_SERIAL_CONNECTION_H_
6 #define CHROME_BROWSER_EXTENSIONS_API_SERIAL_SERIAL_CONNECTION_H_
7 
8 #include <set>
9 #include <string>
10 
11 #include "base/callback.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/memory/weak_ptr.h"
14 #include "base/message_loop/message_loop.h"
15 #include "base/platform_file.h"
16 #include "base/time/time.h"
17 #include "chrome/browser/extensions/api/api_resource.h"
18 #include "chrome/browser/extensions/api/api_resource_manager.h"
19 #include "chrome/browser/extensions/api/serial/serial_io_handler.h"
20 #include "chrome/common/extensions/api/serial.h"
21 #include "content/public/browser/browser_thread.h"
22 #include "net/base/file_stream.h"
23 
24 using content::BrowserThread;
25 
26 namespace extensions {
27 
28 // Encapsulates an open serial port. Platform-specific implementations are in
29 // _win and _posix versions of the the .cc file.
30 // NOTE: Instances of this object should only be constructed on the IO thread,
31 // and all methods should only be called on the IO thread unless otherwise
32 // noted.
33 class SerialConnection : public ApiResource,
34                          public base::SupportsWeakPtr<SerialConnection> {
35  public:
36   typedef base::Callback<void(bool success)> OpenCompleteCallback;
37 
38   // This is the callback type expected by Receive. Note that an error result
39   // does not necessarily imply an empty |data| string, since a receive may
40   // complete partially before being interrupted by an error condition.
41   typedef base::Callback<void(const std::string& data,
42                               api::serial::ReceiveError error)>
43       ReceiveCompleteCallback;
44 
45   // This is the callback type expected by Send. Note that an error result
46   // does not necessarily imply 0 bytes sent, since a send may complete
47   // partially before being interrupted by an error condition.
48   typedef base::Callback<void(int bytes_sent,
49                               api::serial::SendError error)>
50       SendCompleteCallback;
51 
52   SerialConnection(const std::string& port,
53                    const std::string& owner_extension_id);
54   virtual ~SerialConnection();
55 
56   // ApiResource override.
57   virtual bool IsPersistent() const OVERRIDE;
58 
set_persistent(bool persistent)59   void set_persistent(bool persistent) { persistent_ = persistent; }
persistent()60   bool persistent() const { return persistent_; }
61 
set_name(const std::string & name)62   void set_name(const std::string& name) { name_ = name; }
name()63   const std::string& name() const { return name_; }
64 
65   void set_buffer_size(int buffer_size);
buffer_size()66   int buffer_size() const { return buffer_size_; }
67 
68   void set_receive_timeout(int receive_timeout);
receive_timeout()69   int receive_timeout() const { return receive_timeout_; }
70 
71   void set_send_timeout(int send_timeout);
send_timeout()72   int send_timeout() const { return send_timeout_; }
73 
74   void set_paused(bool paused);
paused()75   bool paused() const { return paused_; }
76 
77   // Initiates an asynchronous Open of the device. It is the caller's
78   // responsibility to ensure that this SerialConnection stays alive
79   // until |callback| is run.
80   virtual void Open(const OpenCompleteCallback& callback);
81 
82   // Initiate a Close of the device. The SerialConnection instance will
83   // have its internal state reset synchronously upon calling this, but
84   // the underlying OS handle will be closed asynchronously.
85   virtual void Close();
86 
87   // Begins an asynchronous receive operation. Calling this while a Receive
88   // is already pending is a no-op and returns |false| without calling
89   // |callback|.
90   virtual bool Receive(const ReceiveCompleteCallback& callback);
91 
92   // Begins an asynchronous send operation. Calling this while a Send
93   // is already pending is a no-op and returns |false| without calling
94   // |callback|.
95   virtual bool Send(const std::string& data,
96                     const SendCompleteCallback& callback);
97 
98   // Flushes input and output buffers.
99   virtual bool Flush() const;
100 
101   // Configures some subset of port options for this connection.
102   // Omitted options are unchanged. Returns |true| iff the configuration
103   // changes were successful.
104   virtual bool Configure(const api::serial::ConnectionOptions& options);
105 
106   // Connection configuration query. Fills values in an existing
107   // ConnectionInfo. Returns |true| iff the connection's information
108   // was successfully retrieved.
109   virtual bool GetInfo(api::serial::ConnectionInfo* info) const;
110 
111   // Reads current control signals (DCD, CTS, etc.) into an existing
112   // DeviceControlSignals structure. Returns |true| iff the signals were
113   // successfully read.
114   virtual bool GetControlSignals(api::serial::DeviceControlSignals*
115                                  control_signals) const;
116 
117   // Sets one or more control signals (DTR and/or RTS). Returns |true| iff
118   // the signals were successfully set. Unininitialized flags in the
119   // HostControlSignals structure are left unchanged.
120   virtual bool SetControlSignals(
121       const api::serial::HostControlSignals& control_signals);
122 
123   static const BrowserThread::ID kThreadId = BrowserThread::IO;
124 
125  protected:
126   // Overrides |io_handler_| for testing.
127   virtual void SetIoHandlerForTest(scoped_refptr<SerialIoHandler> handler);
128 
129   // Performs platform-specific, one-time port configuration on open.
130   bool PostOpen();
131 
132   // Performs platform-specific port configuration. Returns |true| iff
133   // configuration was successful.
134   bool ConfigurePort(const api::serial::ConnectionOptions& options);
135 
136   // Performs a platform-specific port configuration query. Fills values in an
137   // existing ConnectionInfo. Returns |true| iff port configuration was
138   // successfully retrieved.
139   bool GetPortInfo(api::serial::ConnectionInfo* info) const;
140 
141   // Possibly fixes up a serial port path name in a platform-specific manner.
142   static std::string MaybeFixUpPortName(const std::string &port_name);
143 
144  private:
145   friend class ApiResourceManager<SerialConnection>;
service_name()146   static const char* service_name() {
147     return "SerialConnectionManager";
148   }
149 
150   // Encapsulates a cancelable, delayed timeout task. Posts a delayed
151   // task upon construction and implicitly cancels the task upon
152   // destruction if it hasn't run yet.
153   class TimeoutTask {
154    public:
155     TimeoutTask(const base::Closure& closure, const base::TimeDelta& delay);
156     ~TimeoutTask();
157 
158    private:
159     void Run() const;
160 
161     base::WeakPtrFactory<TimeoutTask> weak_factory_;
162     base::Closure closure_;
163     base::TimeDelta delay_;
164   };
165 
166   // Continues an Open operation on the FILE thread.
167   void StartOpen();
168 
169   // Finalizes an Open operation (continued from StartOpen) on the IO thread.
170   void FinishOpen(base::PlatformFile file);
171 
172   // Continues a Close operation on the FILE thread.
173   static void DoClose(base::PlatformFile port);
174 
175   // Handles a receive timeout.
176   void OnReceiveTimeout();
177 
178   // Handles a send timeout.
179   void OnSendTimeout();
180 
181   // Receives read completion notification from the |io_handler_|.
182   void OnAsyncReadComplete(const std::string& data,
183                            api::serial::ReceiveError error);
184 
185   // Receives write completion notification from the |io_handler_|.
186   void OnAsyncWriteComplete(int bytes_sent, api::serial::SendError error);
187 
188   // The pathname of the serial device.
189   std::string port_;
190 
191   // File handle for the opened serial device. This value is only modified from
192   // the IO thread.
193   base::PlatformFile file_;
194 
195   // Flag indicating whether or not the connection should persist when
196   // its host app is suspended.
197   bool persistent_;
198 
199   // User-specified connection name.
200   std::string name_;
201 
202   // Size of the receive buffer.
203   int buffer_size_;
204 
205   // Amount of time (in ms) to wait for a Read to succeed before triggering a
206   // timeout response via onReceiveError.
207   int receive_timeout_;
208 
209   // Amount of time (in ms) to wait for a Write to succeed before triggering
210   // a timeout response.
211   int send_timeout_;
212 
213   // Flag indicating that the connection is paused. A paused connection will not
214   // raise new onReceive events.
215   bool paused_;
216 
217   // Callback to handle the completion of a pending Open() request.
218   OpenCompleteCallback open_complete_;
219 
220   // Callback to handle the completion of a pending Receive() request.
221   ReceiveCompleteCallback receive_complete_;
222 
223   // Callback to handle the completion of a pending Send() request.
224   SendCompleteCallback send_complete_;
225 
226   // Closure which will trigger a receive timeout unless cancelled. Reset on
227   // initialization and after every successful Receive().
228   scoped_ptr<TimeoutTask> receive_timeout_task_;
229 
230   // Write timeout closure. Reset on initialization and after every successful
231   // Send().
232   scoped_ptr<TimeoutTask> send_timeout_task_;
233 
234   // Asynchronous I/O handler.
235   scoped_refptr<SerialIoHandler> io_handler_;
236 };
237 
238 }  // namespace extensions
239 
240 #endif  // CHROME_BROWSER_EXTENSIONS_API_SERIAL_SERIAL_CONNECTION_H_
241