1// Copyright 2013 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 DEVICE_BLUETOOTH_BLUETOOTH_SOCKET_CHROMEOS_H_
6#define DEVICE_BLUETOOTH_BLUETOOTH_SOCKET_CHROMEOS_H_
7
8#include <queue>
9#include <string>
10
11#include "base/memory/linked_ptr.h"
12#include "base/memory/scoped_ptr.h"
13#include "chromeos/chromeos_export.h"
14#include "chromeos/dbus/bluetooth_profile_manager_client.h"
15#include "chromeos/dbus/bluetooth_profile_service_provider.h"
16#include "dbus/object_path.h"
17#include "device/bluetooth/bluetooth_adapter.h"
18#include "device/bluetooth/bluetooth_socket.h"
19#include "device/bluetooth/bluetooth_socket_net.h"
20#include "device/bluetooth/bluetooth_uuid.h"
21
22namespace dbus {
23class FileDescriptor;
24}  // namespace dbus
25
26namespace chromeos {
27
28class BluetoothDeviceChromeOS;
29
30// The BluetoothSocketChromeOS class implements BluetoothSocket for the
31// Chrome OS platform.
32class CHROMEOS_EXPORT BluetoothSocketChromeOS
33    : public device::BluetoothSocketNet,
34      public device::BluetoothAdapter::Observer,
35      public BluetoothProfileServiceProvider::Delegate {
36 public:
37  enum SecurityLevel {
38    SECURITY_LEVEL_LOW,
39    SECURITY_LEVEL_MEDIUM
40  };
41
42  static scoped_refptr<BluetoothSocketChromeOS> CreateBluetoothSocket(
43      scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
44      scoped_refptr<device::BluetoothSocketThread> socket_thread);
45
46  // Connects this socket to the service on |device| published as UUID |uuid|,
47  // the underlying protocol and PSM or Channel is obtained through service
48  // discovery. On a successful connection the socket properties will be updated
49  // and |success_callback| called. On failure |error_callback| will be called
50  // with a message explaining the cause of the failure.
51  virtual void Connect(const BluetoothDeviceChromeOS* device,
52                       const device::BluetoothUUID& uuid,
53                       SecurityLevel security_level,
54                       const base::Closure& success_callback,
55                       const ErrorCompletionCallback& error_callback);
56
57  // Listens using this socket using a service published on |adapter|. The
58  // service is either RFCOMM or L2CAP depending on |socket_type| and published
59  // as UUID |uuid|. The |service_options| argument is interpreted according to
60  // |socket_type|. |success_callback| will be called if the service is
61  // successfully registered, |error_callback| on failure with a message
62  // explaining the cause.
63  enum SocketType { kRfcomm, kL2cap };
64  virtual void Listen(
65      scoped_refptr<device::BluetoothAdapter> adapter,
66      SocketType socket_type,
67      const device::BluetoothUUID& uuid,
68      const device::BluetoothAdapter::ServiceOptions& service_options,
69      const base::Closure& success_callback,
70      const ErrorCompletionCallback& error_callback);
71
72  // BluetoothSocket:
73  virtual void Close() OVERRIDE;
74  virtual void Disconnect(const base::Closure& callback) OVERRIDE;
75  virtual void Accept(const AcceptCompletionCallback& success_callback,
76                      const ErrorCompletionCallback& error_callback) OVERRIDE;
77
78  // Returns the object path of the socket.
79  const dbus::ObjectPath& object_path() const { return object_path_; }
80
81 protected:
82  virtual ~BluetoothSocketChromeOS();
83
84 private:
85  BluetoothSocketChromeOS(
86      scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
87      scoped_refptr<device::BluetoothSocketThread> socket_thread);
88
89  // Register the underlying profile client object with the Bluetooth Daemon.
90  void RegisterProfile(const base::Closure& success_callback,
91                       const ErrorCompletionCallback& error_callback);
92  void OnRegisterProfile(const base::Closure& success_callback,
93                         const ErrorCompletionCallback& error_callback);
94  void OnRegisterProfileError(const ErrorCompletionCallback& error_callback,
95                              const std::string& error_name,
96                              const std::string& error_message);
97
98  // Called by dbus:: on completion of the ConnectProfile() method.
99  void OnConnectProfile(const base::Closure& success_callback);
100  void OnConnectProfileError(const ErrorCompletionCallback& error_callback,
101                             const std::string& error_name,
102                             const std::string& error_message);
103
104  // BluetoothAdapter::Observer:
105  virtual void AdapterPresentChanged(device::BluetoothAdapter* adapter,
106                                     bool present) OVERRIDE;
107
108  // Called by dbus:: on completion of the RegisterProfile() method call
109  // triggered as a result of the adapter becoming present again.
110  void OnInternalRegisterProfile();
111  void OnInternalRegisterProfileError(const std::string& error_name,
112                                      const std::string& error_message);
113
114  // BluetoothProfileServiceProvider::Delegate:
115  virtual void Released() OVERRIDE;
116  virtual void NewConnection(
117      const dbus::ObjectPath& device_path,
118      scoped_ptr<dbus::FileDescriptor> fd,
119      const BluetoothProfileServiceProvider::Delegate::Options& options,
120      const ConfirmationCallback& callback) OVERRIDE;
121  virtual void RequestDisconnection(
122      const dbus::ObjectPath& device_path,
123      const ConfirmationCallback& callback) OVERRIDE;
124  virtual void Cancel() OVERRIDE;
125
126  // Method run to accept a single incoming connection.
127  void AcceptConnectionRequest();
128
129  // Method run on the socket thread to validate the file descriptor of a new
130  // connection and set up the underlying net::TCPSocket() for it.
131  void DoNewConnection(
132      const dbus::ObjectPath& device_path,
133      scoped_ptr<dbus::FileDescriptor> fd,
134      const BluetoothProfileServiceProvider::Delegate::Options& options,
135      const ConfirmationCallback& callback);
136
137  // Method run on the UI thread after a new connection has been accepted and
138  // a socket allocated in |socket|. Takes care of calling the Accept()
139  // callback and |callback| with the right arguments based on |status|.
140  void OnNewConnection(scoped_refptr<BluetoothSocket> socket,
141                       const ConfirmationCallback& callback,
142                       Status status);
143
144  // Method run on the socket thread with a valid file descriptor |fd|, once
145  // complete calls |callback| on the UI thread with an appropriate argument
146  // indicating success or failure.
147  void DoConnect(scoped_ptr<dbus::FileDescriptor> fd,
148                 const ConfirmationCallback& callback);
149
150  // Method run to clean-up a listening socket.
151  void DoCloseListening();
152
153  // Unregister the underlying profile client object from the Bluetooth Daemon.
154  void UnregisterProfile();
155  void OnUnregisterProfile(const dbus::ObjectPath& object_path);
156  void OnUnregisterProfileError(const dbus::ObjectPath& object_path,
157                                const std::string& error_name,
158                                const std::string& error_message);
159
160  // Adapter the profile is registered against; this is only present when the
161  // socket is listening.
162  scoped_refptr<device::BluetoothAdapter> adapter_;
163
164  // Address and D-Bus object path of the device being connected to, empty and
165  // ignored if the socket is listening.
166  std::string device_address_;
167  dbus::ObjectPath device_path_;
168
169  // UUID of the profile being connected to, or listening on.
170  device::BluetoothUUID uuid_;
171
172  // Copy of the profile options used for registering the profile.
173  scoped_ptr<BluetoothProfileManagerClient::Options> options_;
174
175  // Object path of the local profile D-Bus object.
176  dbus::ObjectPath object_path_;
177
178  // Local profile D-Bus object used for receiving profile delegate methods
179  // from BlueZ.
180  scoped_ptr<BluetoothProfileServiceProvider> profile_;
181
182  // Pending request to an Accept() call.
183  struct AcceptRequest {
184    AcceptRequest();
185    ~AcceptRequest();
186
187    AcceptCompletionCallback success_callback;
188    ErrorCompletionCallback error_callback;
189  };
190  scoped_ptr<AcceptRequest> accept_request_;
191
192  // Queue of incoming connection requests.
193  struct ConnectionRequest {
194    ConnectionRequest();
195    ~ConnectionRequest();
196
197    dbus::ObjectPath device_path;
198    scoped_ptr<dbus::FileDescriptor> fd;
199    BluetoothProfileServiceProvider::Delegate::Options options;
200    ConfirmationCallback callback;
201    bool accepting;
202    bool cancelled;
203  };
204  std::queue<linked_ptr<ConnectionRequest> > connection_request_queue_;
205
206  DISALLOW_COPY_AND_ASSIGN(BluetoothSocketChromeOS);
207};
208
209}  // namespace chromeos
210
211#endif  // DEVICE_BLUETOOTH_BLUETOOTH_SOCKET_CHROMEOS_H_
212