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