root/chrome/browser/extensions/api/serial/serial_connection.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


// Copyright 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_EXTENSIONS_API_SERIAL_SERIAL_CONNECTION_H_
#define CHROME_BROWSER_EXTENSIONS_API_SERIAL_SERIAL_CONNECTION_H_

#include <set>
#include <string>

#include "base/callback.h"
#include "base/files/file.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/time/time.h"
#include "chrome/browser/extensions/api/serial/serial_io_handler.h"
#include "chrome/common/extensions/api/serial.h"
#include "content/public/browser/browser_thread.h"
#include "extensions/browser/api/api_resource.h"
#include "extensions/browser/api/api_resource_manager.h"
#include "net/base/file_stream.h"

using content::BrowserThread;

namespace extensions {

// Encapsulates an open serial port. Platform-specific implementations are in
// _win and _posix versions of the the .cc file.
// NOTE: Instances of this object should only be constructed on the IO thread,
// and all methods should only be called on the IO thread unless otherwise
// noted.
class SerialConnection : public ApiResource,
                         public base::SupportsWeakPtr<SerialConnection> {
 public:
  typedef base::Callback<void(bool success)> OpenCompleteCallback;

  // This is the callback type expected by Receive. Note that an error result
  // does not necessarily imply an empty |data| string, since a receive may
  // complete partially before being interrupted by an error condition.
  typedef base::Callback<
      void(const std::string& data, api::serial::ReceiveError error)>
      ReceiveCompleteCallback;

  // This is the callback type expected by Send. Note that an error result
  // does not necessarily imply 0 bytes sent, since a send may complete
  // partially before being interrupted by an error condition.
  typedef base::Callback<void(int bytes_sent, api::serial::SendError error)>
      SendCompleteCallback;

  SerialConnection(const std::string& port,
                   const std::string& owner_extension_id);
  virtual ~SerialConnection();

  // ApiResource override.
  virtual bool IsPersistent() const OVERRIDE;

  void set_persistent(bool persistent) { persistent_ = persistent; }
  bool persistent() const { return persistent_; }

  void set_name(const std::string& name) { name_ = name; }
  const std::string& name() const { return name_; }

  void set_buffer_size(int buffer_size);
  int buffer_size() const { return buffer_size_; }

  void set_receive_timeout(int receive_timeout);
  int receive_timeout() const { return receive_timeout_; }

  void set_send_timeout(int send_timeout);
  int send_timeout() const { return send_timeout_; }

  void set_paused(bool paused);
  bool paused() const { return paused_; }

  // Initiates an asynchronous Open of the device. It is the caller's
  // responsibility to ensure that this SerialConnection stays alive
  // until |callback| is run.
  virtual void Open(const OpenCompleteCallback& callback);

  // Initiate a Close of the device. The SerialConnection instance will
  // have its internal state reset synchronously upon calling this, but
  // the underlying OS handle will be closed asynchronously.
  virtual void Close();

  // Begins an asynchronous receive operation. Calling this while a Receive
  // is already pending is a no-op and returns |false| without calling
  // |callback|.
  virtual bool Receive(const ReceiveCompleteCallback& callback);

  // Begins an asynchronous send operation. Calling this while a Send
  // is already pending is a no-op and returns |false| without calling
  // |callback|.
  virtual bool Send(const std::string& data,
                    const SendCompleteCallback& callback);

  // Flushes input and output buffers.
  virtual bool Flush() const;

  // Configures some subset of port options for this connection.
  // Omitted options are unchanged. Returns |true| iff the configuration
  // changes were successful.
  virtual bool Configure(const api::serial::ConnectionOptions& options);

  // Connection configuration query. Fills values in an existing
  // ConnectionInfo. Returns |true| iff the connection's information
  // was successfully retrieved.
  virtual bool GetInfo(api::serial::ConnectionInfo* info) const;

  // Reads current control signals (DCD, CTS, etc.) into an existing
  // DeviceControlSignals structure. Returns |true| iff the signals were
  // successfully read.
  virtual bool GetControlSignals(
      api::serial::DeviceControlSignals* control_signals) const;

  // Sets one or more control signals (DTR and/or RTS). Returns |true| iff
  // the signals were successfully set. Unininitialized flags in the
  // HostControlSignals structure are left unchanged.
  virtual bool SetControlSignals(
      const api::serial::HostControlSignals& control_signals);

  static const BrowserThread::ID kThreadId = BrowserThread::IO;

 protected:
  // Overrides |io_handler_| for testing.
  virtual void SetIoHandlerForTest(scoped_refptr<SerialIoHandler> handler);

  // Performs platform-specific, one-time port configuration on open.
  bool PostOpen();

  // Performs platform-specific port configuration. Returns |true| iff
  // configuration was successful.
  bool ConfigurePort(const api::serial::ConnectionOptions& options);

  // Performs a platform-specific port configuration query. Fills values in an
  // existing ConnectionInfo. Returns |true| iff port configuration was
  // successfully retrieved.
  bool GetPortInfo(api::serial::ConnectionInfo* info) const;

  // Possibly fixes up a serial port path name in a platform-specific manner.
  static std::string MaybeFixUpPortName(const std::string& port_name);

 private:
  friend class ApiResourceManager<SerialConnection>;
  static const char* service_name() { return "SerialConnectionManager"; }

  // Encapsulates a cancelable, delayed timeout task. Posts a delayed
  // task upon construction and implicitly cancels the task upon
  // destruction if it hasn't run yet.
  class TimeoutTask {
   public:
    TimeoutTask(const base::Closure& closure, const base::TimeDelta& delay);
    ~TimeoutTask();

   private:
    void Run() const;

    base::WeakPtrFactory<TimeoutTask> weak_factory_;
    base::Closure closure_;
    base::TimeDelta delay_;
  };

  // Continues an Open operation on the FILE thread.
  void StartOpen();

  // Finalizes an Open operation (continued from StartOpen) on the IO thread.
  void FinishOpen(base::File file);

  // Continues a Close operation on the FILE thread.
  static void DoClose(base::File port);

  // Handles a receive timeout.
  void OnReceiveTimeout();

  // Handles a send timeout.
  void OnSendTimeout();

  // Receives read completion notification from the |io_handler_|.
  void OnAsyncReadComplete(const std::string& data,
                           api::serial::ReceiveError error);

  // Receives write completion notification from the |io_handler_|.
  void OnAsyncWriteComplete(int bytes_sent, api::serial::SendError error);

  // The pathname of the serial device.
  std::string port_;

  // File for the opened serial device. This value is only modified from the IO
  // thread.
  base::File file_;

  // Flag indicating whether or not the connection should persist when
  // its host app is suspended.
  bool persistent_;

  // User-specified connection name.
  std::string name_;

  // Size of the receive buffer.
  int buffer_size_;

  // Amount of time (in ms) to wait for a Read to succeed before triggering a
  // timeout response via onReceiveError.
  int receive_timeout_;

  // Amount of time (in ms) to wait for a Write to succeed before triggering
  // a timeout response.
  int send_timeout_;

  // Flag indicating that the connection is paused. A paused connection will not
  // raise new onReceive events.
  bool paused_;

  // Callback to handle the completion of a pending Open() request.
  OpenCompleteCallback open_complete_;

  // Callback to handle the completion of a pending Receive() request.
  ReceiveCompleteCallback receive_complete_;

  // Callback to handle the completion of a pending Send() request.
  SendCompleteCallback send_complete_;

  // Closure which will trigger a receive timeout unless cancelled. Reset on
  // initialization and after every successful Receive().
  scoped_ptr<TimeoutTask> receive_timeout_task_;

  // Write timeout closure. Reset on initialization and after every successful
  // Send().
  scoped_ptr<TimeoutTask> send_timeout_task_;

  // Asynchronous I/O handler.
  scoped_refptr<SerialIoHandler> io_handler_;
};

}  // namespace extensions

#endif  // CHROME_BROWSER_EXTENSIONS_API_SERIAL_SERIAL_CONNECTION_H_

/* [<][>][^][v][top][bottom][index][help] */