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