Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / components / proximity_auth / bluetooth_connection.cc
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.
4
5 #include "components/proximity_auth/bluetooth_connection.h"
6
7 #include "base/bind.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/numerics/safe_conversions.h"
10 #include "components/proximity_auth/bluetooth_util.h"
11 #include "components/proximity_auth/remote_device.h"
12 #include "components/proximity_auth/wire_message.h"
13 #include "device/bluetooth/bluetooth_adapter_factory.h"
14 #include "device/bluetooth/bluetooth_device.h"
15 #include "net/base/io_buffer.h"
16
17 namespace proximity_auth {
18 namespace {
19 const int kReceiveBufferSizeBytes = 1024;
20 }
21
22 BluetoothConnection::BluetoothConnection(const RemoteDevice& remote_device,
23                                          const device::BluetoothUUID& uuid)
24     : Connection(remote_device), uuid_(uuid), weak_ptr_factory_(this) {
25 }
26
27 BluetoothConnection::~BluetoothConnection() {
28   Disconnect();
29 }
30
31 void BluetoothConnection::Connect() {
32   if (status() != DISCONNECTED) {
33     VLOG(1)
34         << "[BC] Ignoring attempt to connect a non-disconnected connection.";
35     return;
36   }
37
38   if (!device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable()) {
39     VLOG(1)
40         << "[BC] Connection failed: Bluetooth is unsupported on this platform.";
41     return;
42   }
43
44   SetStatus(IN_PROGRESS);
45   device::BluetoothAdapterFactory::GetAdapter(
46       base::Bind(&BluetoothConnection::OnAdapterInitialized,
47                  weak_ptr_factory_.GetWeakPtr()));
48 }
49
50 void BluetoothConnection::Disconnect() {
51   if (status() == DISCONNECTED) {
52     VLOG(1)
53         << "[BC] Ignoring attempt to disconnect a non-connected connection.";
54     return;
55   }
56
57   // Set status as disconnected now, rather than after the socket closes, so
58   // this connection is not reused.
59   SetStatus(DISCONNECTED);
60   if (socket_.get()) {
61     socket_->Disconnect(base::Bind(&base::DoNothing));
62     socket_ = NULL;
63   }
64   if (adapter_.get()) {
65     adapter_->RemoveObserver(this);
66     adapter_ = NULL;
67   }
68 }
69
70 void BluetoothConnection::SendMessageImpl(scoped_ptr<WireMessage> message) {
71   DCHECK_EQ(status(), CONNECTED);
72
73   // Serialize the message.
74   std::string serialized_message = message->Serialize();
75   int message_length = base::checked_cast<int>(serialized_message.size());
76   scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(message_length);
77   memcpy(buffer->data(), serialized_message.c_str(), message_length);
78
79   // Send it.
80   pending_message_ = message.Pass();
81   base::WeakPtr<BluetoothConnection> weak_this = weak_ptr_factory_.GetWeakPtr();
82   socket_->Send(buffer,
83                 message_length,
84                 base::Bind(&BluetoothConnection::OnSend, weak_this),
85                 base::Bind(&BluetoothConnection::OnSendError, weak_this));
86 }
87
88 void BluetoothConnection::DeviceRemoved(device::BluetoothAdapter* adapter,
89                                         device::BluetoothDevice* device) {
90   DCHECK_EQ(adapter, adapter_.get());
91   if (device->GetAddress() != remote_device().bluetooth_address)
92     return;
93
94   DCHECK_NE(status(), DISCONNECTED);
95   VLOG(1) << "[BC] Device disconnected...";
96   Disconnect();
97 }
98
99 void BluetoothConnection::ConnectToService(
100     device::BluetoothDevice* device,
101     const device::BluetoothUUID& uuid,
102     const device::BluetoothDevice::ConnectToServiceCallback& callback,
103     const device::BluetoothDevice::ConnectToServiceErrorCallback&
104         error_callback) {
105   bluetooth_util::ConnectToServiceInsecurely(
106       device, uuid, callback, error_callback);
107 }
108
109 void BluetoothConnection::StartReceive() {
110   base::WeakPtr<BluetoothConnection> weak_this = weak_ptr_factory_.GetWeakPtr();
111   socket_->Receive(kReceiveBufferSizeBytes,
112                    base::Bind(&BluetoothConnection::OnReceive, weak_this),
113                    base::Bind(&BluetoothConnection::OnReceiveError, weak_this));
114 }
115
116 void BluetoothConnection::OnAdapterInitialized(
117     scoped_refptr<device::BluetoothAdapter> adapter) {
118   const std::string address = remote_device().bluetooth_address;
119   device::BluetoothDevice* bluetooth_device = adapter->GetDevice(address);
120   if (!bluetooth_device) {
121     VLOG(1) << "[BC] Device with address " << address
122             << " is not known to the system Bluetooth daemon.";
123     Disconnect();
124     return;
125   }
126
127   adapter_ = adapter;
128   adapter_->AddObserver(this);
129
130   base::WeakPtr<BluetoothConnection> weak_this = weak_ptr_factory_.GetWeakPtr();
131   ConnectToService(
132       bluetooth_device,
133       uuid_,
134       base::Bind(&BluetoothConnection::OnConnected, weak_this),
135       base::Bind(&BluetoothConnection::OnConnectionError, weak_this));
136 }
137
138 void BluetoothConnection::OnConnected(
139     scoped_refptr<device::BluetoothSocket> socket) {
140   if (status() != IN_PROGRESS) {
141     // This case is reachable if the client of |this| connection called
142     // |Disconnect()| while the backing Bluetooth connection was pending.
143     DCHECK_EQ(status(), DISCONNECTED);
144     VLOG(1) << "[BC] Ignoring successful backend Bluetooth connection to an "
145             << "already disconnected logical connection.";
146     return;
147   }
148
149   VLOG(1) << "[BC] Connection established with "
150           << remote_device().bluetooth_address;
151   socket_ = socket;
152   SetStatus(CONNECTED);
153   StartReceive();
154 }
155
156 void BluetoothConnection::OnConnectionError(const std::string& error_message) {
157   VLOG(1) << "[BC] Connection failed: " << error_message;
158   Disconnect();
159 }
160
161 void BluetoothConnection::OnSend(int bytes_sent) {
162   VLOG(1) << "[BC] Successfully sent " << bytes_sent << " bytes.";
163   OnDidSendMessage(*pending_message_, true);
164   pending_message_.reset();
165 }
166
167 void BluetoothConnection::OnSendError(const std::string& error_message) {
168   VLOG(1) << "[BC] Error when sending bytes: " << error_message;
169   OnDidSendMessage(*pending_message_, false);
170   pending_message_.reset();
171
172   Disconnect();
173 }
174
175 void BluetoothConnection::OnReceive(int bytes_received,
176                                     scoped_refptr<net::IOBuffer> buffer) {
177   VLOG(1) << "[BC] Received " << bytes_received << " bytes.";
178   OnBytesReceived(std::string(buffer->data(), bytes_received));
179
180   // Post a task to delay the read until the socket is available, as
181   // calling StartReceive at this point would error with ERR_IO_PENDING.
182   base::MessageLoop::current()->PostTask(
183       FROM_HERE,
184       base::Bind(&BluetoothConnection::StartReceive,
185                  weak_ptr_factory_.GetWeakPtr()));
186 }
187
188 void BluetoothConnection::OnReceiveError(
189     device::BluetoothSocket::ErrorReason error_reason,
190     const std::string& error_message) {
191   VLOG(1) << "[BC] Error receiving bytes: " << error_message;
192
193   // Post a task to delay the read until the socket is available, as
194   // calling StartReceive at this point would error with ERR_IO_PENDING.
195   base::MessageLoop::current()->PostTask(
196       FROM_HERE,
197       base::Bind(&BluetoothConnection::StartReceive,
198                  weak_ptr_factory_.GetWeakPtr()));
199 }
200
201 }  // namespace proximity_auth