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