Commit 6860d6ff authored by James Hawkins's avatar James Hawkins Committed by Commit Bot

components/proximity_auth: Remove unused BluetoothConnection*.

These classes represented Bluetooth Classic connections, which are no longer used.

R=khorimoto@chromium.org

Bug: none
Test: none
Change-Id: I8223f3afca936cf3711f4a73334e9d8aed80d9e1
Reviewed-on: https://chromium-review.googlesource.com/964624
Commit-Queue: James Hawkins <jhawkins@chromium.org>
Reviewed-by: default avatarKyle Horimoto <khorimoto@chromium.org>
Cr-Commit-Position: refs/heads/master@{#543530}
parent 1bbbdca3
......@@ -8,10 +8,6 @@ assert(is_chromeos, "ProximityAuth is Chrome OS only")
static_library("proximity_auth") {
sources = [
"bluetooth_connection.cc",
"bluetooth_connection.h",
"bluetooth_connection_finder.cc",
"bluetooth_connection_finder.h",
"bluetooth_low_energy_connection_finder.cc",
"bluetooth_low_energy_connection_finder.h",
"bluetooth_low_energy_setup_connection_finder.cc",
......@@ -99,8 +95,6 @@ static_library("test_support") {
source_set("unit_tests") {
testonly = true
sources = [
"bluetooth_connection_finder_unittest.cc",
"bluetooth_connection_unittest.cc",
"bluetooth_low_energy_connection_finder_unittest.cc",
"messenger_impl_unittest.cc",
"promotion_manager_unittests.cc",
......
// Copyright 2014 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.
#include "components/proximity_auth/bluetooth_connection.h"
#include <utility>
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/location.h"
#include "base/numerics/safe_conversions.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/cryptauth/remote_device.h"
#include "components/cryptauth/wire_message.h"
#include "components/proximity_auth/logging/logging.h"
#include "device/bluetooth/bluetooth_adapter_factory.h"
#include "device/bluetooth/bluetooth_device.h"
#include "net/base/io_buffer.h"
namespace proximity_auth {
namespace {
const int kReceiveBufferSizeBytes = 1024;
}
BluetoothConnection::BluetoothConnection(
const cryptauth::RemoteDevice& remote_device,
const device::BluetoothUUID& uuid)
: cryptauth::Connection(remote_device),
uuid_(uuid),
weak_ptr_factory_(this) {}
BluetoothConnection::~BluetoothConnection() {
if (status() != DISCONNECTED)
Disconnect();
}
void BluetoothConnection::Connect() {
if (status() != DISCONNECTED) {
PA_LOG(WARNING)
<< "Ignoring attempt to connect a non-disconnected connection.";
return;
}
if (!device::BluetoothAdapterFactory::IsBluetoothSupported()) {
PA_LOG(WARNING)
<< "Connection failed: Bluetooth is unsupported on this platform.";
return;
}
SetStatus(IN_PROGRESS);
device::BluetoothAdapterFactory::GetAdapter(
base::Bind(&BluetoothConnection::OnAdapterInitialized,
weak_ptr_factory_.GetWeakPtr()));
}
void BluetoothConnection::Disconnect() {
if (status() == DISCONNECTED) {
PA_LOG(WARNING)
<< "Ignoring attempt to disconnect a non-connected connection.";
return;
}
// Set status as disconnected now, rather than after the socket closes, so
// this connection is not reused.
SetStatus(DISCONNECTED);
if (socket_.get()) {
socket_->Disconnect(base::DoNothing());
socket_ = nullptr;
}
if (adapter_.get()) {
adapter_->RemoveObserver(this);
adapter_ = nullptr;
}
}
void BluetoothConnection::SendMessageImpl(
std::unique_ptr<cryptauth::WireMessage> message) {
DCHECK_EQ(status(), CONNECTED);
// Serialize the message.
std::string serialized_message = message->Serialize();
int message_length = base::checked_cast<int>(serialized_message.size());
scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(message_length);
memcpy(buffer->data(), serialized_message.c_str(), message_length);
// Send it.
pending_message_ = std::move(message);
base::WeakPtr<BluetoothConnection> weak_this = weak_ptr_factory_.GetWeakPtr();
socket_->Send(buffer,
message_length,
base::Bind(&BluetoothConnection::OnSend, weak_this),
base::Bind(&BluetoothConnection::OnSendError, weak_this));
}
void BluetoothConnection::DeviceChanged(device::BluetoothAdapter* adapter,
device::BluetoothDevice* device) {
DCHECK_EQ(adapter, adapter_.get());
if (device->GetAddress() == remote_device().bluetooth_address &&
status() != DISCONNECTED && !device->IsConnected()) {
PA_LOG(INFO) << "Device disconnected...";
Disconnect();
}
}
void BluetoothConnection::DeviceRemoved(device::BluetoothAdapter* adapter,
device::BluetoothDevice* device) {
DCHECK_EQ(adapter, adapter_.get());
if (device->GetAddress() != remote_device().bluetooth_address)
return;
DCHECK_NE(status(), DISCONNECTED);
PA_LOG(INFO) << "Device disconnected...";
if (status() != DISCONNECTED)
Disconnect();
}
void BluetoothConnection::StartReceive() {
base::WeakPtr<BluetoothConnection> weak_this = weak_ptr_factory_.GetWeakPtr();
socket_->Receive(kReceiveBufferSizeBytes,
base::Bind(&BluetoothConnection::OnReceive, weak_this),
base::Bind(&BluetoothConnection::OnReceiveError, weak_this));
}
void BluetoothConnection::OnAdapterInitialized(
scoped_refptr<device::BluetoothAdapter> adapter) {
const std::string address = remote_device().bluetooth_address;
device::BluetoothDevice* bluetooth_device = adapter->GetDevice(address);
if (!bluetooth_device) {
PA_LOG(WARNING) << "Device with address " << address
<< " is not known to the system Bluetooth daemon.";
// TODO(isherman): Optimistically attempt to seek the device and connect
// anyway, as was previously implemented in BluetoothConnectionFinder.
Disconnect();
return;
}
adapter_ = adapter;
adapter_->AddObserver(this);
base::WeakPtr<BluetoothConnection> weak_this = weak_ptr_factory_.GetWeakPtr();
bluetooth_device->ConnectToServiceInsecurely(
uuid_,
base::Bind(&BluetoothConnection::OnConnected, weak_this),
base::Bind(&BluetoothConnection::OnConnectionError, weak_this));
}
void BluetoothConnection::OnConnected(
scoped_refptr<device::BluetoothSocket> socket) {
if (status() != IN_PROGRESS) {
// This case is reachable if the client of |this| connection called
// |Disconnect()| while the backing Bluetooth connection was pending.
DCHECK_EQ(status(), DISCONNECTED);
PA_LOG(WARNING) << "Ignoring successful backend Bluetooth connection to an "
<< "already disconnected logical connection.";
return;
}
PA_LOG(INFO) << "Connection established with "
<< remote_device().bluetooth_address;
socket_ = socket;
SetStatus(CONNECTED);
StartReceive();
}
void BluetoothConnection::OnConnectionError(const std::string& error_message) {
PA_LOG(WARNING) << "Connection failed: " << error_message;
Disconnect();
}
void BluetoothConnection::OnSend(int bytes_sent) {
PA_LOG(INFO) << "Successfully sent " << bytes_sent << " bytes.";
OnDidSendMessage(*pending_message_, true);
pending_message_.reset();
}
void BluetoothConnection::OnSendError(const std::string& error_message) {
PA_LOG(WARNING) << "Error when sending bytes: " << error_message;
OnDidSendMessage(*pending_message_, false);
pending_message_.reset();
Disconnect();
}
void BluetoothConnection::OnReceive(int bytes_received,
scoped_refptr<net::IOBuffer> buffer) {
PA_LOG(INFO) << "Received " << bytes_received << " bytes.";
OnBytesReceived(std::string(buffer->data(), bytes_received));
// Post a task to delay the read until the socket is available, as
// calling StartReceive at this point would error with ERR_IO_PENDING.
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::Bind(&BluetoothConnection::StartReceive,
weak_ptr_factory_.GetWeakPtr()));
}
void BluetoothConnection::OnReceiveError(
device::BluetoothSocket::ErrorReason error_reason,
const std::string& error_message) {
PA_LOG(WARNING) << "Error receiving bytes: " << error_message;
// Post a task to delay the read until the socket is available, as
// calling StartReceive at this point would error with ERR_IO_PENDING.
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::Bind(&BluetoothConnection::StartReceive,
weak_ptr_factory_.GetWeakPtr()));
}
} // namespace proximity_auth
// Copyright 2014 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 COMPONENTS_PROXIMITY_AUTH_BLUETOOTH_CONNECTION_H
#define COMPONENTS_PROXIMITY_AUTH_BLUETOOTH_CONNECTION_H
#include <string>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "components/cryptauth/connection.h"
#include "device/bluetooth/bluetooth_adapter.h"
#include "device/bluetooth/bluetooth_device.h"
#include "device/bluetooth/bluetooth_socket.h"
#include "device/bluetooth/bluetooth_uuid.h"
namespace net {
class IOBuffer;
}
namespace cryptauth {
struct RemoteDevice;
}
namespace proximity_auth {
// Represents a Bluetooth connection with a remote device. The connection is a
// persistent bidirectional channel for sending and receiving wire messages.
class BluetoothConnection : public cryptauth::Connection,
public device::BluetoothAdapter::Observer {
public:
// Constructs a Bluetooth connection to the service with |uuid| on the
// |remote_device|. The |remote_device| must already be known to the system
// Bluetooth daemon.
BluetoothConnection(const cryptauth::RemoteDevice& remote_device,
const device::BluetoothUUID& uuid);
~BluetoothConnection() override;
// Connection:
void Connect() override;
void Disconnect() override;
protected:
// Connection:
void SendMessageImpl(
std::unique_ptr<cryptauth::WireMessage> message) override;
// BluetoothAdapter::Observer:
void DeviceChanged(device::BluetoothAdapter* adapter,
device::BluetoothDevice* device) override;
void DeviceRemoved(device::BluetoothAdapter* adapter,
device::BluetoothDevice* device) override;
private:
// Registers receive callbacks with the backing |socket_|.
void StartReceive();
// Callbacks for asynchronous Bluetooth operations.
void OnAdapterInitialized(scoped_refptr<device::BluetoothAdapter> adapter);
void OnConnected(scoped_refptr<device::BluetoothSocket> socket);
void OnConnectionError(const std::string& error_message);
void OnSend(int bytes_sent);
void OnSendError(const std::string& error_message);
void OnReceive(int bytes_received, scoped_refptr<net::IOBuffer> buffer);
void OnReceiveError(device::BluetoothSocket::ErrorReason error_reason,
const std::string& error_message);
// The UUID (universally unique identifier) of the Bluetooth service on the
// remote device that |this| connection should connect to.
const device::BluetoothUUID uuid_;
// The Bluetooth adapter over which this connection is made. Non-null iff
// |this| connection is registered as an observer of the |adapter_|.
scoped_refptr<device::BluetoothAdapter> adapter_;
// The Bluetooth socket that backs this connection. NULL iff the connection is
// not in a connected state.
scoped_refptr<device::BluetoothSocket> socket_;
// The message that was sent over the backing |socket_|. NULL iff there is no
// send operation in progress.
std::unique_ptr<cryptauth::WireMessage> pending_message_;
base::WeakPtrFactory<BluetoothConnection> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(BluetoothConnection);
};
} // namespace proximity_auth
#endif // COMPONENTS_PROXIMITY_AUTH_BLUETOOTH_CONNECTION_H
// Copyright 2014 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.
#include "components/proximity_auth/bluetooth_connection_finder.h"
#include <utility>
#include "base/bind.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/cryptauth/connection.h"
#include "components/proximity_auth/bluetooth_connection.h"
#include "components/proximity_auth/logging/logging.h"
#include "device/bluetooth/bluetooth_adapter_factory.h"
using device::BluetoothAdapter;
namespace proximity_auth {
BluetoothConnectionFinder::BluetoothConnectionFinder(
const cryptauth::RemoteDevice& remote_device,
const device::BluetoothUUID& uuid,
const base::TimeDelta& polling_interval)
: remote_device_(remote_device),
uuid_(uuid),
polling_interval_(polling_interval),
has_delayed_poll_scheduled_(false),
weak_ptr_factory_(this) {}
BluetoothConnectionFinder::~BluetoothConnectionFinder() {
UnregisterAsObserver();
}
void BluetoothConnectionFinder::Find(
const cryptauth::ConnectionFinder::ConnectionCallback&
connection_callback) {
if (!device::BluetoothAdapterFactory::IsBluetoothSupported()) {
PA_LOG(WARNING) << "Bluetooth is unsupported on this platform. Aborting.";
return;
}
DCHECK(start_time_.is_null());
start_time_ = base::TimeTicks::Now();
connection_callback_ = connection_callback;
device::BluetoothAdapterFactory::GetAdapter(
base::Bind(&BluetoothConnectionFinder::OnAdapterInitialized,
weak_ptr_factory_.GetWeakPtr()));
}
std::unique_ptr<cryptauth::Connection>
BluetoothConnectionFinder::CreateConnection() {
return std::unique_ptr<cryptauth::Connection>(
new BluetoothConnection(remote_device_, uuid_));
}
void BluetoothConnectionFinder::SeekDeviceByAddress(
const std::string& bluetooth_address,
const base::Closure& callback,
const bluetooth_util::ErrorCallback& error_callback) {
bluetooth_util::SeekDeviceByAddress(
bluetooth_address, callback, error_callback,
base::ThreadTaskRunnerHandle::Get().get());
}
bool BluetoothConnectionFinder::IsReadyToPoll() {
bool is_adapter_available =
adapter_.get() && adapter_->IsPresent() && adapter_->IsPowered();
PA_LOG(INFO) << "Readiness: adapter="
<< (is_adapter_available ? "available" : "unavailable");
return is_adapter_available;
}
void BluetoothConnectionFinder::PollIfReady() {
if (!IsReadyToPoll())
return;
// If there is a pending task to poll at a later time, the time requisite
// timeout has not yet elapsed since the previous polling attempt. In that
// case, keep waiting until the delayed task comes in.
if (has_delayed_poll_scheduled_)
return;
// If the |connection_| is pending, wait for it to connect or fail prior to
// polling again.
if (connection_ &&
connection_->status() != cryptauth::Connection::DISCONNECTED)
return;
// This SeekDeviceByAddress operation is needed to connect to a device if
// it is not already known to the adapter.
if (!adapter_->GetDevice(remote_device_.bluetooth_address)) {
PA_LOG(INFO) << "Remote device [" << remote_device_.bluetooth_address
<< "] is not known. "
<< "Seeking device directly by address...";
SeekDeviceByAddress(
remote_device_.bluetooth_address,
base::Bind(&BluetoothConnectionFinder::OnSeekedDeviceByAddress,
weak_ptr_factory_.GetWeakPtr()),
base::Bind(&BluetoothConnectionFinder::OnSeekedDeviceByAddressError,
weak_ptr_factory_.GetWeakPtr()));
} else {
PA_LOG(INFO) << "Remote device known, connecting...";
connection_ = CreateConnection();
connection_->AddObserver(this);
connection_->Connect();
}
}
void BluetoothConnectionFinder::PostDelayedPoll() {
if (has_delayed_poll_scheduled_) {
PA_LOG(WARNING) << "Delayed poll already scheduled, skipping.";
return;
}
PA_LOG(INFO) << "Posting delayed poll..";
has_delayed_poll_scheduled_ = true;
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, base::Bind(&BluetoothConnectionFinder::OnDelayedPoll,
weak_ptr_factory_.GetWeakPtr()),
polling_interval_);
}
void BluetoothConnectionFinder::OnDelayedPoll() {
// Note that there is no longer a pending task, and therefore polling is
// permitted.
has_delayed_poll_scheduled_ = false;
PollIfReady();
}
void BluetoothConnectionFinder::OnSeekedDeviceByAddress() {
// Sanity check that the remote device is now known by the adapter.
if (adapter_->GetDevice(remote_device_.bluetooth_address))
PollIfReady();
else
PostDelayedPoll();
}
void BluetoothConnectionFinder::OnSeekedDeviceByAddressError(
const std::string& error_message) {
PA_LOG(ERROR) << "Failed to seek device: " << error_message;
PostDelayedPoll();
}
void BluetoothConnectionFinder::UnregisterAsObserver() {
if (connection_) {
connection_->RemoveObserver(this);
// The connection is about to be released or destroyed, so no need to clear
// it explicitly here.
}
if (adapter_.get()) {
adapter_->RemoveObserver(this);
adapter_ = nullptr;
}
}
void BluetoothConnectionFinder::OnAdapterInitialized(
scoped_refptr<BluetoothAdapter> adapter) {
adapter_ = adapter;
adapter_->AddObserver(this);
PollIfReady();
}
void BluetoothConnectionFinder::AdapterPresentChanged(BluetoothAdapter* adapter,
bool present) {
PollIfReady();
}
void BluetoothConnectionFinder::AdapterPoweredChanged(BluetoothAdapter* adapter,
bool powered) {
PollIfReady();
}
void BluetoothConnectionFinder::OnConnectionStatusChanged(
cryptauth::Connection* connection,
cryptauth::Connection::Status old_status,
cryptauth::Connection::Status new_status) {
DCHECK_EQ(connection, connection_.get());
if (connection_->IsConnected()) {
base::TimeDelta elapsed = base::TimeTicks::Now() - start_time_;
PA_LOG(WARNING) << "Connection found! Elapsed Time: "
<< elapsed.InMilliseconds() << "ms.";
UnregisterAsObserver();
// If we invoke the callback now, the callback function may install its own
// observer to |connection_|. Because we are in the
// cryptauth::ConnectionObserver
// callstack, this new observer will receive this connection event.
// Therefore, we need to invoke the callback asynchronously.
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::Bind(&BluetoothConnectionFinder::InvokeCallbackAsync,
weak_ptr_factory_.GetWeakPtr()));
} else if (old_status == cryptauth::Connection::IN_PROGRESS) {
PA_LOG(WARNING)
<< "Connection failed! Scheduling another polling iteration.";
PostDelayedPoll();
}
}
void BluetoothConnectionFinder::InvokeCallbackAsync() {
connection_callback_.Run(std::move(connection_));
}
} // namespace proximity_auth
// Copyright 2014 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 COMPONENTS_PROXIMITY_AUTH_BLUETOOTH_CONNECTION_FINDER_H
#define COMPONENTS_PROXIMITY_AUTH_BLUETOOTH_CONNECTION_FINDER_H
#include <memory>
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "components/cryptauth/connection.h"
#include "components/cryptauth/connection_finder.h"
#include "components/cryptauth/connection_observer.h"
#include "components/cryptauth/remote_device.h"
#include "components/proximity_auth/bluetooth_util.h"
#include "device/bluetooth/bluetooth_adapter.h"
#include "device/bluetooth/bluetooth_uuid.h"
namespace proximity_auth {
// This cryptauth::ConnectionFinder implementation tries to find a Bluetooth
// connection to
// the remote device by polling at a fixed interval.
class BluetoothConnectionFinder : public cryptauth::ConnectionFinder,
public cryptauth::ConnectionObserver,
public device::BluetoothAdapter::Observer {
public:
BluetoothConnectionFinder(const cryptauth::RemoteDevice& remote_device,
const device::BluetoothUUID& uuid,
const base::TimeDelta& polling_interval);
~BluetoothConnectionFinder() override;
// cryptauth::ConnectionFinder:
void Find(const cryptauth::ConnectionFinder::ConnectionCallback&
connection_callback) override;
protected:
// Exposed for mocking out the connection in tests.
virtual std::unique_ptr<cryptauth::Connection> CreateConnection();
// Calls bluetooth_util::SeekDeviceByAddress. Exposed for testing, as this
// utility function is platform dependent.
virtual void SeekDeviceByAddress(
const std::string& bluetooth_address,
const base::Closure& callback,
const bluetooth_util::ErrorCallback& error_callback);
// BluetoothAdapter::Observer:
void AdapterPresentChanged(device::BluetoothAdapter* adapter,
bool present) override;
void AdapterPoweredChanged(device::BluetoothAdapter* adapter,
bool powered) override;
private:
// Returns true iff the Bluetooth adapter is ready to make connections.
bool IsReadyToPoll();
// Attempts to connect to the |remote_device_| if the system is ready for
// another iteration of polling.
void PollIfReady();
// Posts a delayed task to call |PollIfReady|. |OnDelayedPoll()| will be
// called when the task fires.
void PostDelayedPoll();
void OnDelayedPoll();
// Callbacks for bluetooth_util::SeekDeviceByAddress().
void OnSeekedDeviceByAddress();
void OnSeekedDeviceByAddressError(const std::string& error_message);
// Unregisters |this| instance as an observer from all objects that it might
// have registered with.
void UnregisterAsObserver();
// Callback to be called when the Bluetooth adapter is initialized.
void OnAdapterInitialized(scoped_refptr<device::BluetoothAdapter> adapter);
// ConnectionObserver:
void OnConnectionStatusChanged(
cryptauth::Connection* connection,
cryptauth::Connection::Status old_status,
cryptauth::Connection::Status new_status) override;
// Used to invoke |connection_callback_| asynchronously, decoupling the
// callback invocation from the ConnectionObserver callstack.
void InvokeCallbackAsync();
// The remote device to connect to.
const cryptauth::RemoteDevice remote_device_;
// The UUID of the service on the remote device.
const device::BluetoothUUID uuid_;
// The time to wait between polling attempts.
const base::TimeDelta polling_interval_;
// Records the time at which the finder began searching for connections.
base::TimeTicks start_time_;
// The callback that should be called upon a successful connection.
cryptauth::ConnectionFinder::ConnectionCallback connection_callback_;
// The Bluetooth adapter over which the Bluetooth connection will be made.
scoped_refptr<device::BluetoothAdapter> adapter_;
// The Bluetooth connection that will be opened.
std::unique_ptr<cryptauth::Connection> connection_;
// Whether there is currently a polling task scheduled.
bool has_delayed_poll_scheduled_;
// Used to schedule everything else.
base::WeakPtrFactory<BluetoothConnectionFinder> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(BluetoothConnectionFinder);
};
// TODO(isherman): Make sure to wire up the controller to listen for screen lock
// state change events, and create or destroy the connection finder as
// appropriate.
} // namespace proximity_auth
#endif // COMPONENTS_PROXIMITY_AUTH_BLUETOOTH_CONNECTION_FINDER_H
// Copyright 2014 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.
#include "components/proximity_auth/bluetooth_connection_finder.h"
#include <memory>
#include <utility>
#include "base/bind.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/time/time.h"
#include "components/cryptauth/cryptauth_test_util.h"
#include "components/cryptauth/remote_device.h"
#include "components/cryptauth/wire_message.h"
#include "device/bluetooth/bluetooth_adapter_factory.h"
#include "device/bluetooth/bluetooth_uuid.h"
#include "device/bluetooth/test/mock_bluetooth_adapter.h"
#include "device/bluetooth/test/mock_bluetooth_device.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using testing::_;
using testing::NiceMock;
using testing::Return;
using testing::StrictMock;
namespace proximity_auth {
namespace {
const char kUuid[] = "DEADBEEF-CAFE-FEED-FOOD-D15EA5EBEEF";
class MockConnection : public cryptauth::Connection {
public:
MockConnection()
: Connection(cryptauth::CreateClassicRemoteDeviceForTest()),
do_not_destroy_(false) {}
~MockConnection() override { EXPECT_FALSE(do_not_destroy_); }
MOCK_METHOD0(Connect, void());
void SetStatus(cryptauth::Connection::Status status) {
// This object should not be destroyed after setting the status and calling
// observers.
do_not_destroy_ = true;
cryptauth::Connection::SetStatus(status);
do_not_destroy_ = false;
}
private:
void Disconnect() override {}
void SendMessageImpl(
std::unique_ptr<cryptauth::WireMessage> message) override {}
// If true, we do not expect |this| object to be destroyed until this value is
// toggled back to false.
bool do_not_destroy_;
DISALLOW_COPY_AND_ASSIGN(MockConnection);
};
class MockBluetoothConnectionFinder : public BluetoothConnectionFinder {
public:
MockBluetoothConnectionFinder()
: BluetoothConnectionFinder(cryptauth::CreateClassicRemoteDeviceForTest(),
device::BluetoothUUID(kUuid),
base::TimeDelta()) {}
~MockBluetoothConnectionFinder() override {}
MOCK_METHOD0(CreateConnectionProxy, cryptauth::Connection*());
// Creates a mock connection and sets an expectation that the mock connection
// finder's CreateConnection() method will be called and will return the
// created connection. Returns a reference to the created connection.
// NOTE: The returned connection's lifetime is managed by the connection
// finder.
MockConnection* ExpectCreateConnection() {
std::unique_ptr<MockConnection> connection(new NiceMock<MockConnection>());
MockConnection* connection_alias = connection.get();
EXPECT_CALL(*this, CreateConnectionProxy())
.WillOnce(Return(connection.release()));
return connection_alias;
}
using BluetoothConnectionFinder::AdapterPresentChanged;
using BluetoothConnectionFinder::AdapterPoweredChanged;
void ClearSeekCallbacks() {
seek_callback_ = base::Closure();
seek_error_callback_ = bluetooth_util::ErrorCallback();
}
const base::Closure& seek_callback() { return seek_callback_; }
const bluetooth_util::ErrorCallback& seek_error_callback() {
return seek_error_callback_;
}
protected:
// BluetoothConnectionFinder:
std::unique_ptr<cryptauth::Connection> CreateConnection() override {
return base::WrapUnique(CreateConnectionProxy());
}
void SeekDeviceByAddress(
const std::string& bluetooth_address,
const base::Closure& callback,
const bluetooth_util::ErrorCallback& error_callback) override {
EXPECT_EQ(cryptauth::kTestRemoteDeviceBluetoothAddress, bluetooth_address);
seek_callback_ = callback;
seek_error_callback_ = error_callback;
}
private:
base::Closure seek_callback_;
bluetooth_util::ErrorCallback seek_error_callback_;
DISALLOW_COPY_AND_ASSIGN(MockBluetoothConnectionFinder);
};
} // namespace
class ProximityAuthBluetoothConnectionFinderTest : public testing::Test {
protected:
ProximityAuthBluetoothConnectionFinderTest()
: adapter_(new NiceMock<device::MockBluetoothAdapter>),
bluetooth_device_(new NiceMock<device::MockBluetoothDevice>(
adapter_.get(),
static_cast<uint32_t>(device::BluetoothDeviceType::PHONE),
cryptauth::kTestRemoteDeviceName,
cryptauth::kTestRemoteDeviceBluetoothAddress,
true,
false)),
connection_callback_(base::Bind(
&ProximityAuthBluetoothConnectionFinderTest::OnConnectionFound,
base::Unretained(this))) {
device::BluetoothAdapterFactory::SetAdapterForTesting(adapter_);
// By default, configure the environment to allow polling. Individual tests
// can override this as needed.
ON_CALL(*adapter_, IsPresent()).WillByDefault(Return(true));
ON_CALL(*adapter_, IsPowered()).WillByDefault(Return(true));
// By default, the remote device is known to |adapter_| so
// |SeekDeviceByAddress()| will not be called.
ON_CALL(*adapter_, GetDevice(cryptauth::kTestRemoteDeviceBluetoothAddress))
.WillByDefault(Return(bluetooth_device_.get()));
}
MOCK_METHOD1(OnConnectionFoundProxy, void(cryptauth::Connection* connection));
void OnConnectionFound(std::unique_ptr<cryptauth::Connection> connection) {
OnConnectionFoundProxy(connection.get());
last_found_connection_ = std::move(connection);
}
// Starts |connection_finder_|. If |expect_connection| is true, then we set an
// expectation that an in-progress connection will be created and returned.
MockConnection* StartConnectionFinder(bool expect_connection) {
MockConnection* connection = nullptr;
if (expect_connection)
connection = connection_finder_.ExpectCreateConnection();
connection_finder_.Find(connection_callback_);
return connection;
}
// Given an in-progress |connection| returned by |StartConnectionFinder()|,
// simulate it transitioning to the CONNECTED state.
void SimulateDeviceConnection(MockConnection* connection) {
connection->SetStatus(cryptauth::Connection::IN_PROGRESS);
base::RunLoop run_loop;
EXPECT_CALL(*this, OnConnectionFoundProxy(_));
connection->SetStatus(cryptauth::Connection::CONNECTED);
run_loop.RunUntilIdle();
}
scoped_refptr<device::MockBluetoothAdapter> adapter_;
StrictMock<MockBluetoothConnectionFinder> connection_finder_;
std::unique_ptr<device::MockBluetoothDevice> bluetooth_device_;
cryptauth::ConnectionFinder::ConnectionCallback connection_callback_;
private:
// Save a pointer to the last found connection, to extend its lifetime.
std::unique_ptr<cryptauth::Connection> last_found_connection_;
base::MessageLoop message_loop_;
};
TEST_F(ProximityAuthBluetoothConnectionFinderTest,
ConstructAndDestroyDoesntCrash) {
// Destroying a BluetoothConnectionFinder for which Find() has not been called
// should not crash.
BluetoothConnectionFinder connection_finder(
cryptauth::CreateClassicRemoteDeviceForTest(),
device::BluetoothUUID(kUuid), base::TimeDelta::FromMilliseconds(1));
}
TEST_F(ProximityAuthBluetoothConnectionFinderTest, Find_NoBluetoothAdapter) {
// Some platforms do not support Bluetooth. This test is only meaningful on
// those platforms.
adapter_ = nullptr;
if (device::BluetoothAdapterFactory::IsBluetoothSupported())
return;
// The StrictMock will verify that no connection is created.
StartConnectionFinder(false);
}
TEST_F(ProximityAuthBluetoothConnectionFinderTest,
Find_BluetoothAdapterNotPresent) {
// The StrictMock will verify that no connection is created.
ON_CALL(*adapter_, IsPresent()).WillByDefault(Return(false));
StartConnectionFinder(false);
}
TEST_F(ProximityAuthBluetoothConnectionFinderTest,
Find_BluetoothAdapterNotPowered) {
ON_CALL(*adapter_, IsPowered()).WillByDefault(Return(false));
// The StrictMock will verify that no connection is created.
StartConnectionFinder(false);
}
TEST_F(ProximityAuthBluetoothConnectionFinderTest, Find_ConnectionSucceeds) {
MockConnection* connection = StartConnectionFinder(true);
SimulateDeviceConnection(connection);
}
TEST_F(ProximityAuthBluetoothConnectionFinderTest,
Find_ConnectionSucceeds_UnregistersAsObserver) {
MockConnection* connection = StartConnectionFinder(true);
SimulateDeviceConnection(connection);
// If for some reason the connection sends more status updates, they should
// be ignored.
base::RunLoop run_loop;
EXPECT_CALL(*this, OnConnectionFoundProxy(_)).Times(0);
connection->SetStatus(cryptauth::Connection::IN_PROGRESS);
connection->SetStatus(cryptauth::Connection::CONNECTED);
run_loop.RunUntilIdle();
}
TEST_F(ProximityAuthBluetoothConnectionFinderTest,
Find_ConnectionFails_PostsTaskToPollAgain) {
MockConnection* connection = StartConnectionFinder(true);
// Simulate a connection that fails to connect.
connection->SetStatus(cryptauth::Connection::IN_PROGRESS);
connection->SetStatus(cryptauth::Connection::DISCONNECTED);
// A task should have been posted to poll again.
base::RunLoop run_loop;
connection_finder_.ExpectCreateConnection();
run_loop.RunUntilIdle();
}
TEST_F(ProximityAuthBluetoothConnectionFinderTest, Find_PollsOnAdapterPresent) {
ON_CALL(*adapter_, IsPresent()).WillByDefault(Return(false));
EXPECT_CALL(connection_finder_, CreateConnectionProxy()).Times(0);
connection_finder_.Find(connection_callback_);
ON_CALL(*adapter_, IsPresent()).WillByDefault(Return(true));
connection_finder_.ExpectCreateConnection();
connection_finder_.AdapterPresentChanged(adapter_.get(), true);
}
TEST_F(ProximityAuthBluetoothConnectionFinderTest, Find_PollsOnAdapterPowered) {
ON_CALL(*adapter_, IsPowered()).WillByDefault(Return(false));
EXPECT_CALL(connection_finder_, CreateConnectionProxy()).Times(0);
connection_finder_.Find(connection_callback_);
ON_CALL(*adapter_, IsPowered()).WillByDefault(Return(true));
connection_finder_.ExpectCreateConnection();
connection_finder_.AdapterPoweredChanged(adapter_.get(), true);
}
TEST_F(ProximityAuthBluetoothConnectionFinderTest,
Find_DoesNotPollIfConnectionPending) {
MockConnection* connection = StartConnectionFinder(true);
connection->SetStatus(cryptauth::Connection::IN_PROGRESS);
// At this point, there is a pending connection in progress. Hence, an event
// that would normally trigger a new polling iteration should not do so now,
// because the delay interval between successive polling attempts has not yet
// expired.
EXPECT_CALL(connection_finder_, CreateConnectionProxy()).Times(0);
connection_finder_.AdapterPresentChanged(adapter_.get(), true);
}
TEST_F(ProximityAuthBluetoothConnectionFinderTest,
Find_ConnectionFails_PostsTaskToPollAgain_PollWaitsForTask) {
MockConnection* connection = StartConnectionFinder(true);
connection->SetStatus(cryptauth::Connection::IN_PROGRESS);
connection->SetStatus(cryptauth::Connection::DISCONNECTED);
// At this point, there is a pending poll scheduled. Hence, an event that
// would normally trigger a new polling iteration should not do so now,
// because the delay interval between successive polling attempts has not yet
// expired.
EXPECT_CALL(connection_finder_, CreateConnectionProxy()).Times(0);
connection_finder_.AdapterPresentChanged(adapter_.get(), true);
// Now, allow the pending task to run, but fail early, so that no new task is
// posted.
ON_CALL(*adapter_, IsPresent()).WillByDefault(Return(false));
base::RunLoop run_loop;
run_loop.RunUntilIdle();
ON_CALL(*adapter_, IsPresent()).WillByDefault(Return(true));
// Now that there is no pending task, events should once again trigger new
// polling iterations.
connection_finder_.ExpectCreateConnection();
connection_finder_.AdapterPresentChanged(adapter_.get(), true);
}
TEST_F(ProximityAuthBluetoothConnectionFinderTest,
Find_DeviceNotKnown_SeekDeviceSucceeds) {
// If the BluetoothDevice is not known by the adapter, |connection_finder|
// will call SeekDeviceByAddress() first to make it known.
ON_CALL(*adapter_, GetDevice(cryptauth::kTestRemoteDeviceBluetoothAddress))
.WillByDefault(Return(nullptr));
connection_finder_.Find(connection_callback_);
ASSERT_FALSE(connection_finder_.seek_callback().is_null());
EXPECT_FALSE(connection_finder_.seek_error_callback().is_null());
// After seeking is successful, the normal flow should resume.
ON_CALL(*adapter_, GetDevice(cryptauth::kTestRemoteDeviceBluetoothAddress))
.WillByDefault(Return(bluetooth_device_.get()));
MockConnection* connection = connection_finder_.ExpectCreateConnection();
connection_finder_.seek_callback().Run();
SimulateDeviceConnection(connection);
}
TEST_F(ProximityAuthBluetoothConnectionFinderTest,
Find_DeviceNotKnown_SeekDeviceFailThenSucceeds) {
// If the BluetoothDevice is not known by the adapter, |connection_finder|
// will call SeekDeviceByAddress() first to make it known.
ON_CALL(*adapter_, GetDevice(cryptauth::kTestRemoteDeviceBluetoothAddress))
.WillByDefault(Return(nullptr));
connection_finder_.Find(connection_callback_);
EXPECT_FALSE(connection_finder_.seek_callback().is_null());
ASSERT_FALSE(connection_finder_.seek_error_callback().is_null());
// If the seek fails, then |connection_finder| will post a delayed poll to
// reattempt the seek.
connection_finder_.seek_error_callback().Run("Seek failed for test.");
connection_finder_.ClearSeekCallbacks();
EXPECT_TRUE(connection_finder_.seek_callback().is_null());
EXPECT_TRUE(connection_finder_.seek_error_callback().is_null());
// Check that seek is reattempted.
base::RunLoop run_loop;
run_loop.RunUntilIdle();
ASSERT_FALSE(connection_finder_.seek_callback().is_null());
EXPECT_FALSE(connection_finder_.seek_error_callback().is_null());
// Successfully connect to the Bluetooth device.
ON_CALL(*adapter_, GetDevice(cryptauth::kTestRemoteDeviceBluetoothAddress))
.WillByDefault(Return(bluetooth_device_.get()));
MockConnection* connection = connection_finder_.ExpectCreateConnection();
connection_finder_.seek_callback().Run();
SimulateDeviceConnection(connection);
}
} // namespace proximity_auth
// Copyright 2014 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.
#include "components/proximity_auth/bluetooth_connection.h"
#include <utility>
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
#include "base/numerics/safe_conversions.h"
#include "base/run_loop.h"
#include "components/cryptauth/cryptauth_test_util.h"
#include "components/cryptauth/remote_device.h"
#include "components/cryptauth/wire_message.h"
#include "device/bluetooth/bluetooth_adapter_factory.h"
#include "device/bluetooth/bluetooth_uuid.h"
#include "device/bluetooth/test/mock_bluetooth_adapter.h"
#include "device/bluetooth/test/mock_bluetooth_device.h"
#include "device/bluetooth/test/mock_bluetooth_socket.h"
#include "net/base/io_buffer.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using testing::_;
using testing::AnyNumber;
using testing::NiceMock;
using testing::Ref;
using testing::Return;
using testing::SaveArg;
using testing::StrictMock;
namespace proximity_auth {
namespace {
const char kOtherDeviceName[] = "Other device name";
const char kOtherBluetoothAddress[] = "FF:BB:CC:DD:EE:FF";
const char kSerializedMessage[] = "Yarrr, this be a serialized message. Yarr!";
const int kSerializedMessageLength = strlen(kSerializedMessage);
const char kUuid[] = "DEADBEEF-CAFE-FEED-FOOD-D15EA5EBEEF";
const int kReceiveBufferSize = 6;
const char kReceiveBufferContents[] = "bytes";
// Create a buffer for testing received data.
scoped_refptr<net::IOBuffer> CreateReceiveBuffer() {
scoped_refptr<net::IOBuffer> buffer = new net::IOBuffer(kReceiveBufferSize);
memcpy(buffer->data(), kReceiveBufferContents, kReceiveBufferSize);
return buffer;
}
class MockBluetoothConnection : public BluetoothConnection {
public:
MockBluetoothConnection()
: BluetoothConnection(cryptauth::CreateClassicRemoteDeviceForTest(),
device::BluetoothUUID(kUuid)) {}
// Calls back into the parent Connection class.
MOCK_METHOD1(SetStatusProxy, void(Status status));
MOCK_METHOD1(OnBytesReceived, void(const std::string& bytes));
MOCK_METHOD2(OnDidSendMessage,
void(const cryptauth::WireMessage& message, bool success));
void SetStatus(Status status) override {
SetStatusProxy(status);
BluetoothConnection::SetStatus(status);
}
using BluetoothConnection::status;
using BluetoothConnection::Connect;
using BluetoothConnection::DeviceChanged;
using BluetoothConnection::DeviceRemoved;
using BluetoothConnection::Disconnect;
private:
DISALLOW_COPY_AND_ASSIGN(MockBluetoothConnection);
};
class TestWireMessage : public cryptauth::WireMessage {
public:
TestWireMessage() : cryptauth::WireMessage("payload", "feature") {}
~TestWireMessage() override {}
std::string Serialize() const override { return kSerializedMessage; }
private:
DISALLOW_COPY_AND_ASSIGN(TestWireMessage);
};
} // namespace
class ProximityAuthBluetoothConnectionTest : public testing::Test {
public:
ProximityAuthBluetoothConnectionTest()
: adapter_(new device::MockBluetoothAdapter),
device_(adapter_.get(),
0,
cryptauth::kTestRemoteDeviceName,
cryptauth::kTestRemoteDeviceBluetoothAddress,
true,
true),
socket_(new StrictMock<device::MockBluetoothSocket>),
uuid_(kUuid) {
device::BluetoothAdapterFactory::SetAdapterForTesting(adapter_);
// Suppress uninteresting Gmock call warnings.
EXPECT_CALL(*adapter_, GetDevice(_)).Times(AnyNumber());
}
// Transition the connection into an in-progress state.
void BeginConnecting(MockBluetoothConnection* connection) {
EXPECT_EQ(cryptauth::Connection::DISCONNECTED, connection->status());
ON_CALL(device_, IsConnected()).WillByDefault(Return(false));
ON_CALL(*adapter_, GetDevice(_)).WillByDefault(Return(&device_));
EXPECT_CALL(*connection,
SetStatusProxy(cryptauth::Connection::IN_PROGRESS));
EXPECT_CALL(*adapter_, AddObserver(connection));
EXPECT_CALL(device_, ConnectToServiceInsecurely(uuid_, _, _));
connection->Connect();
EXPECT_EQ(cryptauth::Connection::IN_PROGRESS, connection->status());
}
// Transition the connection into a connected state.
// Saves the success and error callbacks passed into OnReceive(), which can be
// accessed via receive_callback() and receive_success_callback().
void Connect(MockBluetoothConnection* connection) {
EXPECT_EQ(cryptauth::Connection::DISCONNECTED, connection->status());
device::BluetoothDevice::ConnectToServiceCallback callback;
ON_CALL(*adapter_, GetDevice(_)).WillByDefault(Return(&device_));
EXPECT_CALL(*connection,
SetStatusProxy(cryptauth::Connection::IN_PROGRESS));
EXPECT_CALL(*adapter_, AddObserver(connection));
EXPECT_CALL(device_, ConnectToServiceInsecurely(_, _, _))
.WillOnce(SaveArg<1>(&callback));
connection->Connect();
ASSERT_FALSE(callback.is_null());
EXPECT_CALL(*connection, SetStatusProxy(cryptauth::Connection::CONNECTED));
EXPECT_CALL(*socket_, Receive(_, _, _))
.WillOnce(DoAll(SaveArg<1>(&receive_callback_),
SaveArg<2>(&receive_error_callback_)));
callback.Run(socket_);
EXPECT_EQ(cryptauth::Connection::CONNECTED, connection->status());
ON_CALL(device_, IsConnected()).WillByDefault(Return(true));
}
device::BluetoothSocket::ReceiveCompletionCallback* receive_callback() {
return &receive_callback_;
}
device::BluetoothSocket::ReceiveErrorCompletionCallback*
receive_error_callback() {
return &receive_error_callback_;
}
protected:
// Mocks used for verifying interactions with the Bluetooth subsystem.
scoped_refptr<device::MockBluetoothAdapter> adapter_;
NiceMock<device::MockBluetoothDevice> device_;
scoped_refptr<StrictMock<device::MockBluetoothSocket>> socket_;
device::BluetoothUUID uuid_;
private:
base::MessageLoop message_loop_;
device::BluetoothSocket::ReceiveCompletionCallback receive_callback_;
device::BluetoothSocket::ReceiveErrorCompletionCallback
receive_error_callback_;
};
TEST_F(ProximityAuthBluetoothConnectionTest, Connect_ConnectionWasInProgress) {
// Create an in-progress connection.
StrictMock<MockBluetoothConnection> connection;
BeginConnecting(&connection);
// A second call to Connect() should be ignored.
EXPECT_CALL(connection, SetStatusProxy(_)).Times(0);
connection.Connect();
// The connection cleans up after itself upon destruction.
EXPECT_CALL(*adapter_, RemoveObserver(&connection));
}
TEST_F(ProximityAuthBluetoothConnectionTest, Connect_ConnectionWasConnected) {
// Create a connected connection.
StrictMock<MockBluetoothConnection> connection;
Connect(&connection);
// A second call to Connect() should be ignored.
EXPECT_CALL(connection, SetStatusProxy(_)).Times(0);
connection.Connect();
// The connection disconnects and unregisters as an observer upon destruction.
EXPECT_CALL(*socket_, Disconnect(_));
EXPECT_CALL(*adapter_, RemoveObserver(&connection));
}
TEST_F(ProximityAuthBluetoothConnectionTest, Connect_NoBluetoothAdapter) {
// Some platforms do not support Bluetooth. This test is only meaningful on
// those platforms.
adapter_ = nullptr;
if (device::BluetoothAdapterFactory::IsBluetoothSupported())
return;
StrictMock<MockBluetoothConnection> connection;
EXPECT_CALL(connection, SetStatusProxy(_)).Times(0);
connection.Connect();
}
TEST_F(ProximityAuthBluetoothConnectionTest, Connect_DeviceMissing) {
StrictMock<MockBluetoothConnection> connection;
ON_CALL(*adapter_, GetDevice(_)).WillByDefault(Return(nullptr));
EXPECT_CALL(connection, SetStatusProxy(cryptauth::Connection::IN_PROGRESS));
EXPECT_CALL(connection, SetStatusProxy(cryptauth::Connection::DISCONNECTED));
connection.Connect();
}
TEST_F(ProximityAuthBluetoothConnectionTest,
Connect_DeviceRemovedWhileConnecting) {
// Create an in-progress connection.
StrictMock<MockBluetoothConnection> connection;
BeginConnecting(&connection);
// Remove the device while the connection is in-progress. This should cause
// the connection to disconnect.
EXPECT_CALL(connection, SetStatusProxy(cryptauth::Connection::DISCONNECTED));
EXPECT_CALL(*adapter_, RemoveObserver(&connection));
connection.DeviceRemoved(adapter_.get(), &device_);
}
TEST_F(ProximityAuthBluetoothConnectionTest,
Connect_OtherDeviceRemovedWhileConnecting) {
// Create an in-progress connection.
StrictMock<MockBluetoothConnection> connection;
BeginConnecting(&connection);
// Remove a device other than the one that is being connected to. This should
// not have any effect on the connection.
NiceMock<device::MockBluetoothDevice> other_device(
adapter_.get(), 0, kOtherDeviceName, kOtherBluetoothAddress, true, true);
EXPECT_CALL(connection, SetStatusProxy(_)).Times(0);
connection.DeviceRemoved(adapter_.get(), &other_device);
// The connection removes itself as an observer when it is destroyed.
EXPECT_CALL(*adapter_, RemoveObserver(&connection));
}
TEST_F(ProximityAuthBluetoothConnectionTest, Connect_ConnectionFails) {
StrictMock<MockBluetoothConnection> connection;
device::BluetoothDevice::ConnectToServiceErrorCallback error_callback;
ON_CALL(*adapter_, GetDevice(_)).WillByDefault(Return(&device_));
EXPECT_CALL(connection, SetStatusProxy(cryptauth::Connection::IN_PROGRESS));
EXPECT_CALL(*adapter_, AddObserver(&connection));
EXPECT_CALL(device_, ConnectToServiceInsecurely(uuid_, _, _))
.WillOnce(SaveArg<2>(&error_callback));
connection.Connect();
ASSERT_FALSE(error_callback.is_null());
EXPECT_CALL(connection, SetStatusProxy(cryptauth::Connection::DISCONNECTED));
EXPECT_CALL(*adapter_, RemoveObserver(&connection));
error_callback.Run("super descriptive error message");
}
TEST_F(ProximityAuthBluetoothConnectionTest, Connect_ConnectionSucceeds) {
StrictMock<MockBluetoothConnection> connection;
Connect(&connection);
// The connection disconnects and unregisters as an observer upon destruction.
EXPECT_CALL(*socket_, Disconnect(_));
EXPECT_CALL(*adapter_, RemoveObserver(&connection));
}
TEST_F(ProximityAuthBluetoothConnectionTest,
Connect_ConnectionSucceeds_ThenDeviceRemoved) {
StrictMock<MockBluetoothConnection> connection;
Connect(&connection);
EXPECT_CALL(connection, SetStatusProxy(cryptauth::Connection::DISCONNECTED));
EXPECT_CALL(*socket_, Disconnect(_));
EXPECT_CALL(*adapter_, RemoveObserver(&connection));
connection.DeviceRemoved(adapter_.get(), &device_);
}
TEST_F(ProximityAuthBluetoothConnectionTest,
Connect_ConnectionSucceeds_ReceiveData) {
StrictMock<MockBluetoothConnection> connection;
Connect(&connection);
ASSERT_TRUE(receive_callback() && !receive_callback()->is_null());
// Receive some data. Once complete, the connection should re-register to be
// ready receive more data.
scoped_refptr<net::IOBuffer> buffer = CreateReceiveBuffer();
EXPECT_CALL(
connection,
OnBytesReceived(std::string(kReceiveBufferContents, kReceiveBufferSize)));
EXPECT_CALL(*socket_, Receive(_, _, _));
receive_callback()->Run(kReceiveBufferSize, buffer);
base::RunLoop run_loop;
run_loop.RunUntilIdle();
// The connection disconnects and unregisters as an observer upon destruction.
EXPECT_CALL(*socket_, Disconnect(_));
EXPECT_CALL(*adapter_, RemoveObserver(&connection));
}
TEST_F(ProximityAuthBluetoothConnectionTest,
Connect_ConnectionSucceeds_ReceiveDataAfterReceiveError) {
StrictMock<MockBluetoothConnection> connection;
Connect(&connection);
ASSERT_TRUE(receive_error_callback() && !receive_error_callback()->is_null());
// Simulate an error while receiving data. The connection should re-register
// to be ready receive more data despite the error.
device::BluetoothSocket::ReceiveCompletionCallback receive_callback;
EXPECT_CALL(*socket_, Receive(_, _, _))
.WillOnce(SaveArg<1>(&receive_callback));
receive_error_callback()->Run(device::BluetoothSocket::kSystemError,
"The system is down. They're taking over!");
base::RunLoop run_loop;
run_loop.RunUntilIdle();
ASSERT_FALSE(receive_callback.is_null());
// Receive some data.
scoped_refptr<net::IOBuffer> buffer = CreateReceiveBuffer();
EXPECT_CALL(
connection,
OnBytesReceived(std::string(kReceiveBufferContents, kReceiveBufferSize)));
EXPECT_CALL(*socket_, Receive(_, _, _));
receive_callback.Run(kReceiveBufferSize, buffer);
base::RunLoop run_loop2;
run_loop2.RunUntilIdle();
// The connection disconnects and unregisters as an observer upon destruction.
EXPECT_CALL(*socket_, Disconnect(_));
EXPECT_CALL(*adapter_, RemoveObserver(&connection));
}
TEST_F(ProximityAuthBluetoothConnectionTest,
Disconnect_ConnectionWasAlreadyDisconnected) {
StrictMock<MockBluetoothConnection> connection;
EXPECT_CALL(connection, SetStatusProxy(_)).Times(0);
connection.Disconnect();
}
TEST_F(ProximityAuthBluetoothConnectionTest,
Disconnect_ConnectionWasInProgress) {
// Create an in-progress connection.
StrictMock<MockBluetoothConnection> connection;
BeginConnecting(&connection);
EXPECT_CALL(connection, SetStatusProxy(cryptauth::Connection::DISCONNECTED));
EXPECT_CALL(*adapter_, RemoveObserver(&connection));
connection.Disconnect();
}
TEST_F(ProximityAuthBluetoothConnectionTest,
Disconnect_ConnectionWasConnected) {
// Create a connected connection.
StrictMock<MockBluetoothConnection> connection;
Connect(&connection);
EXPECT_CALL(connection, SetStatusProxy(cryptauth::Connection::DISCONNECTED));
EXPECT_CALL(*socket_, Disconnect(_));
EXPECT_CALL(*adapter_, RemoveObserver(&connection));
connection.Disconnect();
}
TEST_F(ProximityAuthBluetoothConnectionTest,
Connect_ThenDisconnectWhileInProgress_ThenBackingConnectionSucceeds) {
StrictMock<MockBluetoothConnection> connection;
device::BluetoothDevice::ConnectToServiceCallback callback;
ON_CALL(*adapter_, GetDevice(_)).WillByDefault(Return(&device_));
EXPECT_CALL(connection, SetStatusProxy(cryptauth::Connection::IN_PROGRESS));
EXPECT_CALL(*adapter_, AddObserver(&connection));
EXPECT_CALL(device_, ConnectToServiceInsecurely(uuid_, _, _))
.WillOnce(SaveArg<1>(&callback));
connection.Connect();
ASSERT_FALSE(callback.is_null());
EXPECT_CALL(connection, SetStatusProxy(cryptauth::Connection::DISCONNECTED));
EXPECT_CALL(*adapter_, RemoveObserver(&connection));
connection.Disconnect();
EXPECT_CALL(connection, SetStatusProxy(_)).Times(0);
EXPECT_CALL(*socket_, Receive(_, _, _)).Times(0);
callback.Run(socket_);
}
TEST_F(ProximityAuthBluetoothConnectionTest,
SendMessage_SendsExpectedDataOverTheWire) {
// Create a connected connection.
StrictMock<MockBluetoothConnection> connection;
Connect(&connection);
scoped_refptr<net::IOBuffer> buffer;
std::unique_ptr<TestWireMessage> wire_message(new TestWireMessage);
EXPECT_CALL(*socket_, Send(_, kSerializedMessageLength, _, _))
.WillOnce(SaveArg<0>(&buffer));
connection.SendMessage(std::move(wire_message));
ASSERT_TRUE(buffer.get());
EXPECT_EQ(kSerializedMessage,
std::string(buffer->data(), kSerializedMessageLength));
// The connection disconnects and unregisters as an observer upon destruction.
EXPECT_CALL(*socket_, Disconnect(_));
EXPECT_CALL(*adapter_, RemoveObserver(&connection));
}
TEST_F(ProximityAuthBluetoothConnectionTest, SendMessage_Success) {
// Create a connected connection.
StrictMock<MockBluetoothConnection> connection;
Connect(&connection);
std::unique_ptr<TestWireMessage> wire_message(new TestWireMessage);
// Ownership will be transfered below, so grab a reference here.
TestWireMessage* expected_wire_message = wire_message.get();
device::BluetoothSocket::SendCompletionCallback callback;
EXPECT_CALL(*socket_, Send(_, _, _, _)).WillOnce(SaveArg<2>(&callback));
connection.SendMessage(std::move(wire_message));
ASSERT_FALSE(callback.is_null());
EXPECT_CALL(connection, OnDidSendMessage(Ref(*expected_wire_message), true));
callback.Run(kSerializedMessageLength);
// The connection disconnects and unregisters as an observer upon destruction.
EXPECT_CALL(*socket_, Disconnect(_));
EXPECT_CALL(*adapter_, RemoveObserver(&connection));
}
TEST_F(ProximityAuthBluetoothConnectionTest, SendMessage_Failure) {
// Create a connected connection.
StrictMock<MockBluetoothConnection> connection;
Connect(&connection);
std::unique_ptr<TestWireMessage> wire_message(new TestWireMessage);
// Ownership will be transfered below, so grab a reference here.
TestWireMessage* expected_wire_message = wire_message.get();
device::BluetoothSocket::ErrorCompletionCallback error_callback;
EXPECT_CALL(*socket_, Send(_, _, _, _)).WillOnce(SaveArg<3>(&error_callback));
connection.SendMessage(std::move(wire_message));
ASSERT_FALSE(error_callback.is_null());
EXPECT_CALL(connection, OnDidSendMessage(Ref(*expected_wire_message), false));
EXPECT_CALL(connection, SetStatusProxy(cryptauth::Connection::DISCONNECTED));
EXPECT_CALL(*socket_, Disconnect(_));
EXPECT_CALL(*adapter_, RemoveObserver(&connection));
error_callback.Run("The most helpful of error messages");
}
TEST_F(ProximityAuthBluetoothConnectionTest, DeviceChanged_Disconnected) {
// Create a connected connection.
StrictMock<MockBluetoothConnection> connection;
Connect(&connection);
EXPECT_TRUE(connection.IsConnected());
// If the remote device disconnects, |connection| should also disconnect.
ON_CALL(device_, IsConnected()).WillByDefault(Return(false));
EXPECT_CALL(connection, SetStatusProxy(cryptauth::Connection::DISCONNECTED));
EXPECT_CALL(*socket_, Disconnect(_));
EXPECT_CALL(*adapter_, RemoveObserver(&connection));
connection.DeviceChanged(adapter_.get(), &device_);
EXPECT_FALSE(connection.IsConnected());
}
TEST_F(ProximityAuthBluetoothConnectionTest, DeviceChanged_NotDisconnected) {
// Nothing should happen if DeviceChanged is called, but the remote device is
// not disconnected.
StrictMock<MockBluetoothConnection> connection;
Connect(&connection);
EXPECT_TRUE(connection.IsConnected());
connection.DeviceChanged(adapter_.get(), &device_);
EXPECT_TRUE(connection.IsConnected());
// The connection disconnects and unregisters as an observer upon destruction.
EXPECT_CALL(*socket_, Disconnect(_));
EXPECT_CALL(*adapter_, RemoveObserver(&connection));
}
} // namespace proximity_auth
......@@ -16,8 +16,6 @@
#include "components/cryptauth/device_to_device_authenticator.h"
#include "components/cryptauth/secure_context.h"
#include "components/cryptauth/secure_message_delegate.h"
#include "components/proximity_auth/bluetooth_connection.h"
#include "components/proximity_auth/bluetooth_connection_finder.h"
#include "components/proximity_auth/bluetooth_low_energy_connection_finder.h"
#include "components/proximity_auth/logging/logging.h"
#include "components/proximity_auth/messenger_impl.h"
......
......@@ -22,7 +22,6 @@
#include "components/cryptauth/secure_context.h"
#include "components/cryptauth/secure_message_delegate.h"
#include "components/prefs/pref_service.h"
#include "components/proximity_auth/bluetooth_connection_finder.h"
#include "components/proximity_auth/logging/logging.h"
#include "components/proximity_auth/messenger.h"
#include "components/proximity_auth/remote_device_life_cycle_impl.h"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment