Commit 04cac696 authored by khorimoto's avatar khorimoto Committed by Commit bot

[CrOS Tether] Create BleScanner, a class which scan BLE advertisements and...

[CrOS Tether] Create BleScanner, a class which scan BLE advertisements and identifies nearby devices.

This class provides an API for registering or unregistering RemoteDevices. As long as at least one RemoteDevice is registered, a discovery session is active. If an advertisement from a registered RemoteDevice is scanned, observers are notified.

BUG=672263

Review-Url: https://codereview.chromium.org/2604063003
Cr-Commit-Position: refs/heads/master@{#441484}
parent c1bc970e
...@@ -10,6 +10,8 @@ static_library("tether") { ...@@ -10,6 +10,8 @@ static_library("tether") {
"ble_advertisement_device_queue.h", "ble_advertisement_device_queue.h",
"ble_constants.cc", "ble_constants.cc",
"ble_constants.h", "ble_constants.h",
"ble_scanner.cc",
"ble_scanner.h",
"host_scan_scheduler.cc", "host_scan_scheduler.cc",
"host_scan_scheduler.h", "host_scan_scheduler.h",
"host_scanner.cc", "host_scanner.cc",
...@@ -25,6 +27,7 @@ static_library("tether") { ...@@ -25,6 +27,7 @@ static_library("tether") {
"//chromeos", "//chromeos",
"//components/cryptauth", "//components/cryptauth",
"//components/proximity_auth/logging", "//components/proximity_auth/logging",
"//device/bluetooth",
] ]
public_deps = [ public_deps = [
...@@ -35,7 +38,10 @@ static_library("tether") { ...@@ -35,7 +38,10 @@ static_library("tether") {
static_library("test_support") { static_library("test_support") {
testonly = true testonly = true
sources = [] sources = [
"mock_local_device_data_provider.cc",
"mock_local_device_data_provider.h",
]
public_deps = [ public_deps = [
":tether", ":tether",
...@@ -43,6 +49,7 @@ static_library("test_support") { ...@@ -43,6 +49,7 @@ static_library("test_support") {
deps = [ deps = [
"//base", "//base",
"//components/cryptauth",
"//testing/gmock", "//testing/gmock",
] ]
} }
...@@ -52,6 +59,7 @@ source_set("unit_tests") { ...@@ -52,6 +59,7 @@ source_set("unit_tests") {
sources = [ sources = [
"ble_advertisement_device_queue_unittest.cc", "ble_advertisement_device_queue_unittest.cc",
"ble_scanner_unittest.cc",
"host_scan_scheduler_unittest.cc", "host_scan_scheduler_unittest.cc",
"local_device_data_provider_unittest.cc", "local_device_data_provider_unittest.cc",
] ]
...@@ -63,6 +71,8 @@ source_set("unit_tests") { ...@@ -63,6 +71,8 @@ source_set("unit_tests") {
"//chromeos", "//chromeos",
"//components/cryptauth", "//components/cryptauth",
"//components/cryptauth:test_support", "//components/cryptauth:test_support",
"//device/bluetooth",
"//device/bluetooth:mocks",
"//testing/gmock", "//testing/gmock",
"//testing/gtest", "//testing/gtest",
] ]
......
include_rules = [ include_rules = [
"+components/cryptauth", "+components/cryptauth",
"+components/proximity_auth/logging", "+components/proximity_auth/logging",
"+device/bluetooth",
] ]
...@@ -8,7 +8,7 @@ namespace chromeos { ...@@ -8,7 +8,7 @@ namespace chromeos {
namespace tether { namespace tether {
const int kMaxConcurrentAdvertisements = 2; const uint8_t kMaxConcurrentAdvertisements = 2;
const char kAdvertisingServiceUuid[] = "0000fe50-0000-1000-8000-00805f9b34fb"; const char kAdvertisingServiceUuid[] = "0000fe50-0000-1000-8000-00805f9b34fb";
} // namespace tether } // namespace tether
......
...@@ -18,7 +18,7 @@ namespace tether { ...@@ -18,7 +18,7 @@ namespace tether {
// Note that this upper limit on concurrent advertisements is imposed due to a // Note that this upper limit on concurrent advertisements is imposed due to a
// hardware limit of advertisements (many devices have <10 total advertisement // hardware limit of advertisements (many devices have <10 total advertisement
// slots). // slots).
extern const int kMaxConcurrentAdvertisements; extern const uint8_t kMaxConcurrentAdvertisements;
// The service UUID used for BLE advertisements. // The service UUID used for BLE advertisements.
extern const char kAdvertisingServiceUuid[]; extern const char kAdvertisingServiceUuid[];
......
// Copyright 2016 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 "chromeos/components/tether/ble_scanner.h"
#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_util.h"
#include "chromeos/components/tether/ble_constants.h"
#include "components/cryptauth/proto/cryptauth_api.pb.h"
#include "components/cryptauth/remote_device.h"
#include "components/proximity_auth/logging/logging.h"
#include "device/bluetooth/bluetooth_device.h"
#include "device/bluetooth/bluetooth_discovery_session.h"
#include "device/bluetooth/bluetooth_uuid.h"
namespace chromeos {
namespace tether {
namespace {
// Minimum RSSI value to use for discovery. The -90 value was determined
// empirically and is borrowed from
// |proximity_auth::BluetoothLowEnergyConnectionFinder|.
const int kMinDiscoveryRSSI = -90;
// Valid service data must include at least 4 bytes: 2 bytes associated with the
// scanning device (used as a scan filter) and 2 bytes which identify the
// advertising device to the scanning device.
const size_t kMinNumBytesInServiceData = 4;
// Returns out |string|s data as a hex string.
std::string StringToHexOfContents(const std::string& string) {
std::stringstream ss;
ss << "0x" << std::hex;
for (size_t i = 0; i < string.size(); i++) {
ss << static_cast<int>(string.data()[i]);
}
return ss.str();
}
} // namespace
BleScanner::DelegateImpl::DelegateImpl() {}
BleScanner::DelegateImpl::~DelegateImpl() {}
bool BleScanner::DelegateImpl::IsBluetoothAdapterAvailable() const {
return device::BluetoothAdapterFactory::IsBluetoothAdapterAvailable();
}
void BleScanner::DelegateImpl::GetAdapter(
const device::BluetoothAdapterFactory::AdapterCallback& callback) {
device::BluetoothAdapterFactory::GetAdapter(callback);
}
const std::vector<uint8_t>* BleScanner::DelegateImpl::GetServiceDataForUUID(
const device::BluetoothUUID& service_uuid,
device::BluetoothDevice* bluetooth_device) {
return bluetooth_device->GetServiceDataForUUID(service_uuid);
}
BleScanner::BleScanner(
const LocalDeviceDataProvider* local_device_data_provider)
: BleScanner(base::MakeUnique<DelegateImpl>(),
cryptauth::EidGenerator::GetInstance(),
local_device_data_provider) {}
BleScanner::~BleScanner() {}
BleScanner::BleScanner(
std::unique_ptr<Delegate> delegate,
const cryptauth::EidGenerator* eid_generator,
const LocalDeviceDataProvider* local_device_data_provider)
: delegate_(std::move(delegate)),
eid_generator_(eid_generator),
local_device_data_provider_(local_device_data_provider),
is_initializing_adapter_(false),
is_initializing_discovery_session_(false),
discovery_session_(nullptr),
weak_ptr_factory_(this) {}
bool BleScanner::RegisterScanFilterForDevice(
const cryptauth::RemoteDevice& remote_device) {
if (!delegate_->IsBluetoothAdapterAvailable()) {
PA_LOG(ERROR) << "Bluetooth is not supported on this platform.";
return false;
}
if (registered_remote_devices_.size() >= kMaxConcurrentAdvertisements) {
// Each scan filter corresponds to an advertisement. Thus, the number of
// concurrent advertisements cannot exceed the maximum number of concurrent
// advertisements.
return false;
}
std::vector<cryptauth::BeaconSeed> local_device_beacon_seeds;
if (!local_device_data_provider_->GetLocalDeviceData(
nullptr, &local_device_beacon_seeds)) {
// If the local device's beacon seeds could not be fetched, a scan filter
// cannot be generated.
return false;
}
std::unique_ptr<cryptauth::EidGenerator::EidData> scan_filters =
eid_generator_->GenerateBackgroundScanFilter(local_device_beacon_seeds);
if (!scan_filters) {
// If a background scan filter cannot be generated, give up.
return false;
}
registered_remote_devices_.push_back(remote_device);
UpdateDiscoveryStatus();
return true;
}
bool BleScanner::UnregisterScanFilterForDevice(
const cryptauth::RemoteDevice& remote_device) {
for (auto it = registered_remote_devices_.begin();
it != registered_remote_devices_.end(); ++it) {
if (it->GetDeviceId() == remote_device.GetDeviceId()) {
registered_remote_devices_.erase(it);
UpdateDiscoveryStatus();
return true;
}
}
return false;
}
bool BleScanner::IsDeviceRegistered(const std::string& device_id) {
for (auto it = registered_remote_devices_.begin();
it != registered_remote_devices_.end(); ++it) {
if (it->GetDeviceId() == device_id) {
return true;
}
}
return false;
}
void BleScanner::AddObserver(Observer* observer) {
observer_list_.AddObserver(observer);
}
void BleScanner::RemoveObserver(Observer* observer) {
observer_list_.RemoveObserver(observer);
}
void BleScanner::AdapterPoweredChanged(device::BluetoothAdapter* adapter,
bool powered) {
DCHECK_EQ(adapter_.get(), adapter);
PA_LOG(INFO) << "Adapter power changed. Powered = " << powered;
UpdateDiscoveryStatus();
}
void BleScanner::DeviceAdded(device::BluetoothAdapter* adapter,
device::BluetoothDevice* bluetooth_device) {
DCHECK_EQ(adapter_.get(), adapter);
HandleDeviceUpdated(bluetooth_device);
}
void BleScanner::DeviceChanged(device::BluetoothAdapter* adapter,
device::BluetoothDevice* bluetooth_device) {
DCHECK_EQ(adapter_.get(), adapter);
HandleDeviceUpdated(bluetooth_device);
}
void BleScanner::UpdateDiscoveryStatus() {
if (registered_remote_devices_.empty()) {
StopDiscoverySession();
return;
}
if (is_initializing_adapter_) {
return;
} else if (!adapter_) {
InitializeBluetoothAdapter();
return;
}
if (!adapter_->IsPowered()) {
// If the adapter has powered off, no devices can be discovered.
StopDiscoverySession();
return;
}
if (is_initializing_discovery_session_) {
return;
} else if (!discovery_session_ ||
(discovery_session_ && !discovery_session_->IsActive())) {
StartDiscoverySession();
}
}
void BleScanner::InitializeBluetoothAdapter() {
PA_LOG(INFO) << "Initializing Bluetooth adapter.";
is_initializing_adapter_ = true;
delegate_->GetAdapter(base::Bind(&BleScanner::OnAdapterInitialized,
weak_ptr_factory_.GetWeakPtr()));
}
void BleScanner::OnAdapterInitialized(
scoped_refptr<device::BluetoothAdapter> adapter) {
DCHECK(is_initializing_adapter_ && !discovery_session_ &&
!is_initializing_discovery_session_);
PA_LOG(INFO) << "Bluetooth adapter initialized.";
is_initializing_adapter_ = false;
adapter_ = adapter;
adapter_->AddObserver(this);
UpdateDiscoveryStatus();
}
void BleScanner::StartDiscoverySession() {
DCHECK(adapter_);
PA_LOG(INFO) << "Starting discovery session.";
is_initializing_discovery_session_ = true;
// Discover only low energy (LE) devices with strong enough signal.
std::unique_ptr<device::BluetoothDiscoveryFilter> filter =
base::MakeUnique<device::BluetoothDiscoveryFilter>(
device::BLUETOOTH_TRANSPORT_LE);
filter->SetRSSI(kMinDiscoveryRSSI);
adapter_->StartDiscoverySessionWithFilter(
std::move(filter), base::Bind(&BleScanner::OnDiscoverySessionStarted,
weak_ptr_factory_.GetWeakPtr()),
base::Bind(&BleScanner::OnStartDiscoverySessionError,
weak_ptr_factory_.GetWeakPtr()));
}
void BleScanner::OnDiscoverySessionStarted(
std::unique_ptr<device::BluetoothDiscoverySession> discovery_session) {
PA_LOG(INFO) << "Discovery session started. Scanning fully initialized.";
is_initializing_discovery_session_ = false;
discovery_session_ = std::move(discovery_session);
}
void BleScanner::OnStartDiscoverySessionError() {
PA_LOG(WARNING) << "Error starting discovery session. Initialization failed.";
is_initializing_discovery_session_ = false;
}
void BleScanner::StopDiscoverySession() {
if (!discovery_session_) {
// If there is no discovery session to stop, return early.
return;
}
PA_LOG(WARNING) << "Stopping discovery session.";
discovery_session_.reset();
}
void BleScanner::HandleDeviceUpdated(
device::BluetoothDevice* bluetooth_device) {
DCHECK(bluetooth_device);
const std::vector<uint8_t>* service_data = delegate_->GetServiceDataForUUID(
device::BluetoothUUID(kAdvertisingServiceUuid), bluetooth_device);
if (!service_data || service_data->size() < kMinNumBytesInServiceData) {
// If there is no service data or the service data is of insufficient
// length, there is not enough information to create a connection.
return;
}
// Convert the service data from a std::vector<uint8_t> to a std::string.
std::string service_data_str;
char* string_contents_ptr =
base::WriteInto(&service_data_str, service_data->size() + 1);
memcpy(string_contents_ptr, service_data->data(), service_data->size() + 1);
CheckForMatchingScanFilters(bluetooth_device, service_data_str);
}
void BleScanner::CheckForMatchingScanFilters(
device::BluetoothDevice* bluetooth_device,
std::string& service_data) {
std::vector<cryptauth::BeaconSeed> beacon_seeds;
if (!local_device_data_provider_->GetLocalDeviceData(nullptr,
&beacon_seeds)) {
// If no beacon seeds are available, the scan cannot be checked for a match.
return;
}
const cryptauth::RemoteDevice* identified_device =
eid_generator_->IdentifyRemoteDeviceByAdvertisement(
service_data, registered_remote_devices_, beacon_seeds);
if (identified_device) {
PA_LOG(INFO) << "Received advertisement from remote device with ID "
<< identified_device->GetTruncatedDeviceIdForLogs() << ".";
for (auto& observer : observer_list_) {
observer.OnReceivedAdvertisementFromDevice(bluetooth_device,
*identified_device);
}
} else {
PA_LOG(INFO) << "Received advertisement remote device, but could not "
<< "identify the device. Service data: "
<< StringToHexOfContents(service_data) << ".";
}
}
} // namespace tether
} // namespace chromeos
// Copyright 2016 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 CHROMEOS_COMPONENTS_BLE_SCANNER_H_
#define CHROMEOS_COMPONENTS_BLE_SCANNER_H_
#include <map>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "chromeos/components/tether/local_device_data_provider.h"
#include "components/cryptauth/eid_generator.h"
#include "device/bluetooth/bluetooth_adapter.h"
#include "device/bluetooth/bluetooth_adapter_factory.h"
namespace device {
class BluetoothDevice;
class BluetoothDiscoverySession;
}
namespace chromeos {
namespace tether {
class BleScanner : public device::BluetoothAdapter::Observer {
public:
class Observer {
public:
virtual void OnReceivedAdvertisementFromDevice(
const device::BluetoothDevice* bluetooth_device,
cryptauth::RemoteDevice remote_device) = 0;
};
BleScanner(const LocalDeviceDataProvider* local_device_data_provider);
~BleScanner() override;
bool RegisterScanFilterForDevice(
const cryptauth::RemoteDevice& remote_device);
bool UnregisterScanFilterForDevice(
const cryptauth::RemoteDevice& remote_device);
bool IsDeviceRegistered(const std::string& device_id);
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
// device::BluetoothAdapter::Observer
void AdapterPoweredChanged(device::BluetoothAdapter* adapter,
bool powered) override;
void DeviceAdded(device::BluetoothAdapter* adapter,
device::BluetoothDevice* bluetooth_device) override;
void DeviceChanged(device::BluetoothAdapter* adapter,
device::BluetoothDevice* bluetooth_device) override;
private:
friend class BleScannerTest;
class Delegate {
public:
virtual ~Delegate() {}
virtual bool IsBluetoothAdapterAvailable() const = 0;
virtual void GetAdapter(
const device::BluetoothAdapterFactory::AdapterCallback& callback) = 0;
virtual const std::vector<uint8_t>* GetServiceDataForUUID(
const device::BluetoothUUID& service_uuid,
device::BluetoothDevice* bluetooth_device) = 0;
};
class DelegateImpl : public Delegate {
public:
DelegateImpl();
~DelegateImpl() override;
bool IsBluetoothAdapterAvailable() const override;
void GetAdapter(const device::BluetoothAdapterFactory::AdapterCallback&
callback) override;
const std::vector<uint8_t>* GetServiceDataForUUID(
const device::BluetoothUUID& service_uuid,
device::BluetoothDevice* bluetooth_device) override;
};
BleScanner(std::unique_ptr<Delegate> delegate,
const cryptauth::EidGenerator* eid_generator,
const LocalDeviceDataProvider* local_device_data_provider);
void UpdateDiscoveryStatus();
void InitializeBluetoothAdapter();
void OnAdapterInitialized(scoped_refptr<device::BluetoothAdapter> adapter);
void StartDiscoverySession();
void OnDiscoverySessionStarted(
std::unique_ptr<device::BluetoothDiscoverySession> discovery_session);
void OnStartDiscoverySessionError();
void StopDiscoverySession();
void HandleDeviceUpdated(device::BluetoothDevice* bluetooth_device);
void CheckForMatchingScanFilters(device::BluetoothDevice* bluetooth_device,
std::string& service_data);
std::unique_ptr<Delegate> delegate_;
// |eid_generator_| and |local_device_data_provider_| are not owned by this
// instance and must outlive it.
const cryptauth::EidGenerator* eid_generator_;
const LocalDeviceDataProvider* local_device_data_provider_;
bool is_initializing_adapter_;
scoped_refptr<device::BluetoothAdapter> adapter_;
bool is_initializing_discovery_session_;
std::unique_ptr<device::BluetoothDiscoverySession> discovery_session_;
std::vector<cryptauth::RemoteDevice> registered_remote_devices_;
base::ObserverList<Observer> observer_list_;
base::WeakPtrFactory<BleScanner> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(BleScanner);
};
} // namespace tether
} // namespace chromeos
#endif // CHROMEOS_COMPONENTS_BLE_SCANNER_H_
// Copyright 2016 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 "chromeos/components/tether/ble_scanner.h"
#include "base/logging.h"
#include "chromeos/components/tether/ble_constants.h"
#include "chromeos/components/tether/mock_local_device_data_provider.h"
#include "components/cryptauth/mock_eid_generator.h"
#include "components/cryptauth/proto/cryptauth_api.pb.h"
#include "components/cryptauth/remote_device_test_util.h"
#include "device/bluetooth/test/mock_bluetooth_adapter.h"
#include "device/bluetooth/test/mock_bluetooth_device.h"
#include "device/bluetooth/test/mock_bluetooth_discovery_session.h"
#include "testing/gtest/include/gtest/gtest.h"
using testing::_;
using testing::DoAll;
using testing::Eq;
using testing::Invoke;
using testing::NiceMock;
using testing::SaveArg;
using testing::Return;
namespace chromeos {
namespace tether {
namespace {
class MockBleScannerObserver : public BleScanner::Observer {
public:
MockBleScannerObserver() {}
void OnReceivedAdvertisementFromDevice(
const device::BluetoothDevice* bluetooth_device,
cryptauth::RemoteDevice remote_device) override {
bluetooth_devices_.push_back(bluetooth_device);
remote_devices_.push_back(remote_device);
}
int GetNumCalls() { return static_cast<int>(bluetooth_devices_.size()); }
std::vector<const device::BluetoothDevice*>& bluetooth_devices() {
return bluetooth_devices_;
}
std::vector<cryptauth::RemoteDevice>& remote_devices() {
return remote_devices_;
}
private:
std::vector<const device::BluetoothDevice*> bluetooth_devices_;
std::vector<cryptauth::RemoteDevice> remote_devices_;
};
class MockBluetoothDeviceWithServiceData : public device::MockBluetoothDevice {
public:
MockBluetoothDeviceWithServiceData(device::MockBluetoothAdapter* adapter,
const std::string& service_data)
: device::MockBluetoothDevice(adapter,
/* bluetooth_class */ 0,
"name",
"11:22:33:44:55:66",
false,
false) {
for (size_t i = 0; i < service_data.size(); i++) {
service_data_.push_back(static_cast<uint8_t>(service_data[i]));
}
}
const std::vector<uint8_t>* service_data() { return &service_data_; }
private:
std::vector<uint8_t> service_data_;
};
const int kExpectedDiscoveryRSSI = -90;
const size_t kMinNumBytesInServiceData = 4;
const std::string fake_local_public_key = "fakeLocalPublicKey";
const std::string current_eid_data = "currentEidData";
const int64_t current_eid_start_ms = 1000L;
const int64_t current_eid_end_ms = 2000L;
const std::string adjacent_eid_data = "adjacentEidData";
const int64_t adjacent_eid_start_ms = 2000L;
const int64_t adjacent_eid_end_ms = 3000L;
const std::string fake_beacon_seed1_data = "fakeBeaconSeed1Data";
const int64_t fake_beacon_seed1_start_ms = current_eid_start_ms;
const int64_t fake_beacon_seed1_end_ms = current_eid_end_ms;
const std::string fake_beacon_seed2_data = "fakeBeaconSeed2Data";
const int64_t fake_beacon_seed2_start_ms = adjacent_eid_start_ms;
const int64_t fake_beacon_seed2_end_ms = adjacent_eid_end_ms;
std::unique_ptr<cryptauth::EidGenerator::EidData>
CreateFakeBackgroundScanFilter() {
cryptauth::EidGenerator::DataWithTimestamp current(
current_eid_data, current_eid_start_ms, current_eid_end_ms);
std::unique_ptr<cryptauth::EidGenerator::DataWithTimestamp> adjacent =
base::MakeUnique<cryptauth::EidGenerator::DataWithTimestamp>(
adjacent_eid_data, adjacent_eid_start_ms, adjacent_eid_end_ms);
return base::MakeUnique<cryptauth::EidGenerator::EidData>(
current, std::move(adjacent));
}
std::vector<cryptauth::BeaconSeed> CreateFakeBeaconSeeds() {
cryptauth::BeaconSeed seed1;
seed1.set_data(fake_beacon_seed1_data);
seed1.set_start_time_millis(fake_beacon_seed1_start_ms);
seed1.set_start_time_millis(fake_beacon_seed1_end_ms);
cryptauth::BeaconSeed seed2;
seed2.set_data(fake_beacon_seed2_data);
seed2.set_start_time_millis(fake_beacon_seed2_start_ms);
seed2.set_start_time_millis(fake_beacon_seed2_end_ms);
std::vector<cryptauth::BeaconSeed> seeds = {seed1, seed2};
return seeds;
}
} // namespace
class BleScannerTest : public testing::Test {
protected:
class TestDelegate : public BleScanner::Delegate {
public:
TestDelegate()
: is_bluetooth_adapter_available_(true),
last_get_adapter_callback_(nullptr) {}
~TestDelegate() override {}
bool IsBluetoothAdapterAvailable() const override {
return is_bluetooth_adapter_available_;
}
void set_is_bluetooth_adapter_available(
bool is_bluetooth_adapter_available) {
is_bluetooth_adapter_available_ = is_bluetooth_adapter_available;
}
void GetAdapter(const device::BluetoothAdapterFactory::AdapterCallback&
callback) override {
last_get_adapter_callback_ = callback;
}
const device::BluetoothAdapterFactory::AdapterCallback
last_get_adapter_callback() {
return last_get_adapter_callback_;
}
const std::vector<uint8_t>* GetServiceDataForUUID(
const device::BluetoothUUID& service_uuid,
device::BluetoothDevice* bluetooth_device) override {
if (device::BluetoothUUID(kAdvertisingServiceUuid) == service_uuid) {
return reinterpret_cast<MockBluetoothDeviceWithServiceData*>(
bluetooth_device)
->service_data();
}
return nullptr;
}
private:
bool is_bluetooth_adapter_available_;
device::BluetoothAdapterFactory::AdapterCallback last_get_adapter_callback_;
};
BleScannerTest()
: test_devices_(cryptauth::GenerateTestRemoteDevices(3)),
test_beacon_seeds_(CreateFakeBeaconSeeds()) {}
void SetUp() override {
test_delegate_ = new TestDelegate();
EXPECT_TRUE(test_delegate_->IsBluetoothAdapterAvailable());
EXPECT_FALSE(test_delegate_->last_get_adapter_callback());
mock_eid_generator_ = base::MakeUnique<cryptauth::MockEidGenerator>();
mock_eid_generator_->set_background_scan_filter(
CreateFakeBackgroundScanFilter());
mock_local_device_data_provider_ =
base::MakeUnique<MockLocalDeviceDataProvider>();
mock_local_device_data_provider_->SetPublicKey(
base::MakeUnique<std::string>(fake_local_public_key));
mock_local_device_data_provider_->SetBeaconSeeds(
base::MakeUnique<std::vector<cryptauth::BeaconSeed>>(
test_beacon_seeds_));
mock_adapter_ =
make_scoped_refptr(new NiceMock<device::MockBluetoothAdapter>());
stored_discovery_filter_.reset();
stored_discovery_callback_.Reset();
stored_discovery_errback_.Reset();
ON_CALL(*mock_adapter_, StartDiscoverySessionWithFilterRaw(_, _, _))
.WillByDefault(Invoke(
this, &BleScannerTest::SaveStartDiscoverySessionWithFilterArgs));
ON_CALL(*mock_adapter_, IsPowered()).WillByDefault(Return(true));
mock_discovery_session_ = nullptr;
ble_scanner_ = base::WrapUnique(new BleScanner(
base::WrapUnique(test_delegate_), mock_eid_generator_.get(),
mock_local_device_data_provider_.get()));
mock_observer_ = base::MakeUnique<MockBleScannerObserver>();
ble_scanner_->AddObserver(mock_observer_.get());
}
void SaveStartDiscoverySessionWithFilterArgs(
const device::BluetoothDiscoveryFilter* discovery_filter,
const device::BluetoothAdapter::DiscoverySessionCallback& callback,
const device::BluetoothAdapter::ErrorCallback& errback) {
stored_discovery_filter_ =
base::MakeUnique<device::BluetoothDiscoveryFilter>(
device::BluetoothTransport::BLUETOOTH_TRANSPORT_LE);
stored_discovery_filter_->CopyFrom(*discovery_filter);
stored_discovery_callback_ = callback;
stored_discovery_errback_ = errback;
}
void InvokeAdapterCallback() {
const device::BluetoothAdapterFactory::AdapterCallback
last_get_adapter_callback = test_delegate_->last_get_adapter_callback();
ASSERT_TRUE(last_get_adapter_callback);
// Because the adapter has just been initialized, the discovery session
// should not have been started yet.
EXPECT_FALSE(stored_discovery_filter_);
EXPECT_TRUE(stored_discovery_callback_.is_null());
EXPECT_TRUE(stored_discovery_errback_.is_null());
EXPECT_CALL(*mock_adapter_, AddObserver(ble_scanner_.get()));
last_get_adapter_callback.Run(mock_adapter_);
// Once the adapter callback is returned, a discovery session should be
// started via that adapter.
AssertDiscoverySessionRequested();
}
void AssertDiscoverySessionRequested() {
// First, ensure that the correct discovery filter was passed.
EXPECT_TRUE(stored_discovery_filter_);
EXPECT_EQ(device::BluetoothTransport::BLUETOOTH_TRANSPORT_LE,
stored_discovery_filter_->GetTransport());
int16_t observed_rssi;
ASSERT_TRUE(stored_discovery_filter_->GetRSSI(&observed_rssi));
EXPECT_EQ(kExpectedDiscoveryRSSI, observed_rssi);
// Now, ensure that both a callback and errback were passed.
EXPECT_FALSE(stored_discovery_callback_.is_null());
EXPECT_FALSE(stored_discovery_errback_.is_null());
}
void InvokeDiscoveryStartedCallback() {
EXPECT_FALSE(stored_discovery_callback_.is_null());
mock_discovery_session_ = new device::MockBluetoothDiscoverySession();
stored_discovery_callback_.Run(base::WrapUnique(mock_discovery_session_));
}
std::vector<cryptauth::RemoteDevice> test_devices_;
std::vector<cryptauth::BeaconSeed> test_beacon_seeds_;
std::unique_ptr<MockBleScannerObserver> mock_observer_;
TestDelegate* test_delegate_;
std::unique_ptr<cryptauth::MockEidGenerator> mock_eid_generator_;
std::unique_ptr<MockLocalDeviceDataProvider> mock_local_device_data_provider_;
scoped_refptr<NiceMock<device::MockBluetoothAdapter>> mock_adapter_;
device::MockBluetoothDiscoverySession* mock_discovery_session_;
std::unique_ptr<device::BluetoothDiscoveryFilter> stored_discovery_filter_;
device::BluetoothAdapter::DiscoverySessionCallback stored_discovery_callback_;
device::BluetoothAdapter::ErrorCallback stored_discovery_errback_;
std::unique_ptr<BleScanner> ble_scanner_;
private:
DISALLOW_COPY_AND_ASSIGN(BleScannerTest);
};
TEST_F(BleScannerTest, TestNoBluetoothAdapter) {
test_delegate_->set_is_bluetooth_adapter_available(false);
EXPECT_FALSE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
EXPECT_FALSE(
ble_scanner_->IsDeviceRegistered(test_devices_[0].GetDeviceId()));
EXPECT_FALSE(test_delegate_->last_get_adapter_callback());
EXPECT_FALSE(mock_observer_->GetNumCalls());
}
TEST_F(BleScannerTest, TestNoLocalBeaconSeeds) {
mock_local_device_data_provider_->SetBeaconSeeds(nullptr);
EXPECT_FALSE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
EXPECT_FALSE(
ble_scanner_->IsDeviceRegistered(test_devices_[0].GetDeviceId()));
EXPECT_FALSE(test_delegate_->last_get_adapter_callback());
EXPECT_FALSE(mock_observer_->GetNumCalls());
}
TEST_F(BleScannerTest, TestNoBackgroundScanFilter) {
mock_eid_generator_->set_background_scan_filter(nullptr);
EXPECT_FALSE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
EXPECT_FALSE(
ble_scanner_->IsDeviceRegistered(test_devices_[0].GetDeviceId()));
EXPECT_FALSE(test_delegate_->last_get_adapter_callback());
EXPECT_FALSE(mock_observer_->GetNumCalls());
}
TEST_F(BleScannerTest, TestAdapterDoesNotInitialize) {
EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
EXPECT_TRUE(ble_scanner_->IsDeviceRegistered(test_devices_[0].GetDeviceId()));
EXPECT_TRUE(test_delegate_->last_get_adapter_callback());
// Do not call the last GetAdapter() callback. The device should still be able
// to be unregistered.
EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(test_devices_[0]));
EXPECT_FALSE(
ble_scanner_->IsDeviceRegistered(test_devices_[0].GetDeviceId()));
EXPECT_FALSE(mock_observer_->GetNumCalls());
}
TEST_F(BleScannerTest, TestAdapterDoesNotInitialize_MultipleDevicesRegistered) {
EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[1]));
EXPECT_TRUE(ble_scanner_->IsDeviceRegistered(test_devices_[0].GetDeviceId()));
EXPECT_TRUE(ble_scanner_->IsDeviceRegistered(test_devices_[1].GetDeviceId()));
EXPECT_TRUE(test_delegate_->last_get_adapter_callback());
// Do not call the last GetAdapter() callback. The devices should still be
// able to be unregistered.
EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(test_devices_[0]));
EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(test_devices_[1]));
EXPECT_FALSE(
ble_scanner_->IsDeviceRegistered(test_devices_[0].GetDeviceId()));
EXPECT_FALSE(
ble_scanner_->IsDeviceRegistered(test_devices_[1].GetDeviceId()));
EXPECT_FALSE(mock_observer_->GetNumCalls());
}
TEST_F(BleScannerTest, TestDiscoverySessionFailsToStart) {
EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
EXPECT_TRUE(ble_scanner_->IsDeviceRegistered(test_devices_[0].GetDeviceId()));
InvokeAdapterCallback();
stored_discovery_errback_.Run();
EXPECT_TRUE(ble_scanner_->IsDeviceRegistered(test_devices_[0].GetDeviceId()));
EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(test_devices_[0]));
EXPECT_FALSE(mock_observer_->GetNumCalls());
}
TEST_F(BleScannerTest, TestDiscoveryStartsButNoDevicesFound) {
EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
EXPECT_TRUE(ble_scanner_->IsDeviceRegistered(test_devices_[0].GetDeviceId()));
InvokeAdapterCallback();
InvokeDiscoveryStartedCallback();
// No devices found.
EXPECT_TRUE(ble_scanner_->IsDeviceRegistered(test_devices_[0].GetDeviceId()));
EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(test_devices_[0]));
EXPECT_FALSE(mock_observer_->GetNumCalls());
}
TEST_F(BleScannerTest, TestDiscovery_NoServiceData) {
std::string empty_service_data = "";
EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
EXPECT_TRUE(ble_scanner_->IsDeviceRegistered(test_devices_[0].GetDeviceId()));
InvokeAdapterCallback();
InvokeDiscoveryStartedCallback();
// Device with no service data connected. Service data is required to identify
// the advertising device.
MockBluetoothDeviceWithServiceData device1(mock_adapter_.get(),
empty_service_data);
ble_scanner_->DeviceAdded(mock_adapter_.get(), &device1);
EXPECT_FALSE(mock_eid_generator_->num_identify_calls());
EXPECT_FALSE(mock_observer_->GetNumCalls());
}
TEST_F(BleScannerTest, TestDiscovery_ServiceDataTooShort) {
std::string short_service_data = "abc";
ASSERT_TRUE(short_service_data.size() < kMinNumBytesInServiceData);
EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
EXPECT_TRUE(ble_scanner_->IsDeviceRegistered(test_devices_[0].GetDeviceId()));
InvokeAdapterCallback();
InvokeDiscoveryStartedCallback();
// Device with short service data connected. Service data of at least 4 bytes
// is required to identify the advertising device.
MockBluetoothDeviceWithServiceData device2(mock_adapter_.get(),
short_service_data);
ble_scanner_->DeviceAdded(mock_adapter_.get(), &device2);
EXPECT_FALSE(mock_eid_generator_->num_identify_calls());
EXPECT_FALSE(mock_observer_->GetNumCalls());
}
TEST_F(BleScannerTest, TestDiscovery_LocalDeviceDataCannotBeFetched) {
std::string valid_service_data_for_other_device = "abcd";
ASSERT_TRUE(valid_service_data_for_other_device.size() >=
kMinNumBytesInServiceData);
EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
EXPECT_TRUE(ble_scanner_->IsDeviceRegistered(test_devices_[0].GetDeviceId()));
InvokeAdapterCallback();
InvokeDiscoveryStartedCallback();
// Device with valid service data connected, but the local device data
// cannot be fetched.
mock_local_device_data_provider_->SetPublicKey(nullptr);
mock_local_device_data_provider_->SetBeaconSeeds(nullptr);
MockBluetoothDeviceWithServiceData device3(
mock_adapter_.get(), valid_service_data_for_other_device);
ble_scanner_->DeviceAdded(mock_adapter_.get(), &device3);
EXPECT_FALSE(mock_eid_generator_->num_identify_calls());
EXPECT_FALSE(mock_observer_->GetNumCalls());
}
TEST_F(BleScannerTest, TestDiscovery_ScanSuccessfulButNoRegisteredDevice) {
std::string valid_service_data_for_other_device = "abcd";
ASSERT_TRUE(valid_service_data_for_other_device.size() >=
kMinNumBytesInServiceData);
EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
EXPECT_TRUE(ble_scanner_->IsDeviceRegistered(test_devices_[0].GetDeviceId()));
InvokeAdapterCallback();
InvokeDiscoveryStartedCallback();
// Device with valid service data connected, but there was no registered
// device corresponding to the one that just connected.
mock_local_device_data_provider_->SetPublicKey(
base::MakeUnique<std::string>(fake_local_public_key));
mock_local_device_data_provider_->SetBeaconSeeds(
base::MakeUnique<std::vector<cryptauth::BeaconSeed>>(test_beacon_seeds_));
MockBluetoothDeviceWithServiceData device4(
mock_adapter_.get(), valid_service_data_for_other_device);
ble_scanner_->DeviceAdded(mock_adapter_.get(), &device4);
EXPECT_EQ(1, mock_eid_generator_->num_identify_calls());
EXPECT_FALSE(mock_observer_->GetNumCalls());
}
TEST_F(BleScannerTest, TestDiscovery_Success) {
std::string valid_service_data_for_registered_device = "abcde";
ASSERT_TRUE(valid_service_data_for_registered_device.size() >=
kMinNumBytesInServiceData);
EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
EXPECT_TRUE(ble_scanner_->IsDeviceRegistered(test_devices_[0].GetDeviceId()));
InvokeAdapterCallback();
InvokeDiscoveryStartedCallback();
// Registered device connects.
MockBluetoothDeviceWithServiceData device5(
mock_adapter_.get(), valid_service_data_for_registered_device);
mock_eid_generator_->set_identified_device(&test_devices_[0]);
ble_scanner_->DeviceAdded(mock_adapter_.get(), &device5);
EXPECT_EQ(1, mock_eid_generator_->num_identify_calls());
EXPECT_EQ(1, mock_observer_->GetNumCalls());
EXPECT_EQ(1, static_cast<int>(mock_observer_->bluetooth_devices().size()));
EXPECT_EQ(&device5, mock_observer_->bluetooth_devices()[0]);
EXPECT_EQ(1, static_cast<int>(mock_observer_->remote_devices().size()));
EXPECT_EQ(test_devices_[0], mock_observer_->remote_devices()[0]);
EXPECT_TRUE(ble_scanner_->IsDeviceRegistered(test_devices_[0].GetDeviceId()));
EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(test_devices_[0]));
EXPECT_EQ(1, mock_eid_generator_->num_identify_calls());
EXPECT_EQ(1, mock_observer_->GetNumCalls());
}
TEST_F(BleScannerTest, TestDiscovery_MultipleObservers) {
MockBleScannerObserver extra_observer;
ble_scanner_->AddObserver(&extra_observer);
EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
EXPECT_TRUE(ble_scanner_->IsDeviceRegistered(test_devices_[0].GetDeviceId()));
InvokeAdapterCallback();
InvokeDiscoveryStartedCallback();
MockBluetoothDeviceWithServiceData mock_bluetooth_device(mock_adapter_.get(),
"fakeServiceData");
mock_eid_generator_->set_identified_device(&test_devices_[0]);
ble_scanner_->DeviceAdded(mock_adapter_.get(), &mock_bluetooth_device);
EXPECT_EQ(1, mock_observer_->GetNumCalls());
EXPECT_EQ(1, static_cast<int>(mock_observer_->bluetooth_devices().size()));
EXPECT_EQ(&mock_bluetooth_device, mock_observer_->bluetooth_devices()[0]);
EXPECT_EQ(1, static_cast<int>(mock_observer_->remote_devices().size()));
EXPECT_EQ(test_devices_[0], mock_observer_->remote_devices()[0]);
EXPECT_EQ(1, extra_observer.GetNumCalls());
EXPECT_EQ(1, static_cast<int>(extra_observer.bluetooth_devices().size()));
EXPECT_EQ(&mock_bluetooth_device, extra_observer.bluetooth_devices()[0]);
EXPECT_EQ(1, static_cast<int>(extra_observer.remote_devices().size()));
EXPECT_EQ(test_devices_[0], extra_observer.remote_devices()[0]);
// Now, unregister both observers.
ble_scanner_->RemoveObserver(mock_observer_.get());
ble_scanner_->RemoveObserver(&extra_observer);
// Now, simulate another scan being received. The observers should not be
// notified since they are unregistered, so they should still have a call
// count of 1.
ble_scanner_->DeviceAdded(mock_adapter_.get(), &mock_bluetooth_device);
EXPECT_EQ(1, mock_observer_->GetNumCalls());
EXPECT_EQ(1, extra_observer.GetNumCalls());
EXPECT_TRUE(ble_scanner_->IsDeviceRegistered(test_devices_[0].GetDeviceId()));
EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(test_devices_[0]));
}
TEST_F(BleScannerTest, TestRegistrationLimit) {
EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
EXPECT_TRUE(ble_scanner_->IsDeviceRegistered(test_devices_[0].GetDeviceId()));
EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[1]));
EXPECT_TRUE(ble_scanner_->IsDeviceRegistered(test_devices_[1].GetDeviceId()));
// Attempt to register another device. Registration should fail since the
// maximum number of devices have already been registered.
ASSERT_EQ(2, kMaxConcurrentAdvertisements);
EXPECT_FALSE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[2]));
EXPECT_FALSE(
ble_scanner_->IsDeviceRegistered(test_devices_[2].GetDeviceId()));
// Unregistering a device which is not registered should also return false.
EXPECT_FALSE(ble_scanner_->UnregisterScanFilterForDevice(test_devices_[2]));
EXPECT_FALSE(
ble_scanner_->IsDeviceRegistered(test_devices_[2].GetDeviceId()));
// Unregister device 0.
EXPECT_TRUE(ble_scanner_->IsDeviceRegistered(test_devices_[0].GetDeviceId()));
EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(test_devices_[0]));
EXPECT_FALSE(
ble_scanner_->IsDeviceRegistered(test_devices_[0].GetDeviceId()));
// Now, device 2 can be registered.
EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[2]));
EXPECT_TRUE(ble_scanner_->IsDeviceRegistered(test_devices_[2].GetDeviceId()));
// Now, unregister the devices.
EXPECT_TRUE(ble_scanner_->IsDeviceRegistered(test_devices_[1].GetDeviceId()));
EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(test_devices_[1]));
EXPECT_FALSE(
ble_scanner_->IsDeviceRegistered(test_devices_[1].GetDeviceId()));
EXPECT_TRUE(ble_scanner_->IsDeviceRegistered(test_devices_[2].GetDeviceId()));
EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(test_devices_[2]));
EXPECT_FALSE(
ble_scanner_->IsDeviceRegistered(test_devices_[2].GetDeviceId()));
}
TEST_F(BleScannerTest, TestAdapterPoweredChanged) {
// This test starts with the adapter powered on, then turns power off before
// discovery starts, then turns power back on and allows discovery to
// complete, then turns power back off again, and finally turns it back on to
// complete another discovery session.
EXPECT_CALL(*mock_adapter_, IsPowered())
.WillOnce(Return(true))
.WillOnce(Return(false))
.WillOnce(Return(true))
.WillOnce(Return(false))
.WillOnce(Return(true));
EXPECT_TRUE(ble_scanner_->RegisterScanFilterForDevice(test_devices_[0]));
EXPECT_TRUE(ble_scanner_->IsDeviceRegistered(test_devices_[0].GetDeviceId()));
InvokeAdapterCallback();
// The discovery session should have been requested but not yet initialized.
EXPECT_TRUE(stored_discovery_filter_.get());
EXPECT_FALSE(mock_discovery_session_);
// Turn the adapter off before the discovery session starts.
ble_scanner_->AdapterPoweredChanged(mock_adapter_.get(), false);
// Turn the adapter back on, and finish initializing discovery this time.
ble_scanner_->AdapterPoweredChanged(mock_adapter_.get(), true);
InvokeDiscoveryStartedCallback();
// The session should have been started.
device::MockBluetoothDiscoverySession* session1 = mock_discovery_session_;
EXPECT_NE(nullptr, session1);
// Now turn the adapter off again.
ble_scanner_->AdapterPoweredChanged(mock_adapter_.get(), false);
// Turn the adapter back on.
ble_scanner_->AdapterPoweredChanged(mock_adapter_.get(), true);
InvokeDiscoveryStartedCallback();
// A new session should have started, so the session objects should not be the
// same.
device::MockBluetoothDiscoverySession* session2 = mock_discovery_session_;
EXPECT_NE(nullptr, session2);
EXPECT_NE(session1, session2);
// Unregister device.
EXPECT_TRUE(ble_scanner_->IsDeviceRegistered(test_devices_[0].GetDeviceId()));
EXPECT_TRUE(ble_scanner_->UnregisterScanFilterForDevice(test_devices_[0]));
EXPECT_FALSE(
ble_scanner_->IsDeviceRegistered(test_devices_[0].GetDeviceId()));
}
} // namespace tether
} // namespace chromeos
...@@ -36,7 +36,7 @@ class LocalDeviceDataProvider { ...@@ -36,7 +36,7 @@ class LocalDeviceDataProvider {
// Fetches the public key and/or the beacon seeds for the local device. // Fetches the public key and/or the beacon seeds for the local device.
// Returns whether the operation succeeded. If |nullptr| is passed as a // Returns whether the operation succeeded. If |nullptr| is passed as a
// parameter, the associated data will not be fetched. // parameter, the associated data will not be fetched.
bool GetLocalDeviceData( virtual bool GetLocalDeviceData(
std::string* public_key_out, std::string* public_key_out,
std::vector<cryptauth::BeaconSeed>* beacon_seeds_out) const; std::vector<cryptauth::BeaconSeed>* beacon_seeds_out) const;
......
// Copyright 2015 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 "chromeos/components/tether/mock_local_device_data_provider.h"
#include "components/cryptauth/cryptauth_device_manager.h"
#include "components/cryptauth/cryptauth_enrollment_manager.h"
#include "components/cryptauth/proto/cryptauth_api.pb.h"
namespace chromeos {
namespace tether {
MockLocalDeviceDataProvider::MockLocalDeviceDataProvider()
: LocalDeviceDataProvider(nullptr, nullptr) {}
MockLocalDeviceDataProvider::~MockLocalDeviceDataProvider() {}
void MockLocalDeviceDataProvider::SetPublicKey(
std::unique_ptr<std::string> public_key) {
if (public_key) {
public_key_ = std::move(public_key);
} else {
public_key_.reset();
}
}
void MockLocalDeviceDataProvider::SetBeaconSeeds(
std::unique_ptr<std::vector<cryptauth::BeaconSeed>> beacon_seeds) {
if (beacon_seeds) {
beacon_seeds_ = std::move(beacon_seeds);
} else {
beacon_seeds_.reset();
}
}
bool MockLocalDeviceDataProvider::GetLocalDeviceData(
std::string* public_key_out,
std::vector<cryptauth::BeaconSeed>* beacon_seeds_out) const {
if (public_key_ && beacon_seeds_) {
if (public_key_out) {
*public_key_out = *public_key_;
}
if (beacon_seeds_out) {
*beacon_seeds_out = *beacon_seeds_;
}
return true;
}
return false;
}
} // namespace tether
} // namespace cryptauth
// Copyright 2016 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 CHROMEOS_COMPONENTS_TETHER_MOCK_LOCAL_DEVICE_DATA_PROVIDER_H
#define CHROMEOS_COMPONENTS_TETHER_MOCK_LOCAL_DEVICE_DATA_PROVIDER_H
#include <memory>
#include <string>
#include <vector>
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "chromeos/components/tether/local_device_data_provider.h"
namespace cryptauth {
class BeaconSeed;
}
namespace chromeos {
namespace tether {
// Test double for LocalDeviceDataProvider.
class MockLocalDeviceDataProvider : public LocalDeviceDataProvider {
public:
MockLocalDeviceDataProvider();
~MockLocalDeviceDataProvider() override;
void SetPublicKey(std::unique_ptr<std::string> public_key);
void SetBeaconSeeds(
std::unique_ptr<std::vector<cryptauth::BeaconSeed>> beacon_seeds);
// LocalDeviceDataProvider:
bool GetLocalDeviceData(
std::string* public_key_out,
std::vector<cryptauth::BeaconSeed>* beacon_seeds_out) const override;
private:
std::unique_ptr<std::string> public_key_;
std::unique_ptr<std::vector<cryptauth::BeaconSeed>> beacon_seeds_;
DISALLOW_COPY_AND_ASSIGN(MockLocalDeviceDataProvider);
};
} // namespace tether
} // namespace chromeos
#endif // CHROMEOS_COMPONENTS_TETHER_MOCK_LOCAL_DEVICE_DATA_PROVIDER_H
...@@ -11,7 +11,8 @@ namespace cryptauth { ...@@ -11,7 +11,8 @@ namespace cryptauth {
MockEidGenerator::MockEidGenerator() : background_scan_filter_(nullptr), MockEidGenerator::MockEidGenerator() : background_scan_filter_(nullptr),
advertisement_(nullptr), advertisement_(nullptr),
possible_advertisements_(nullptr), possible_advertisements_(nullptr),
identified_device_(nullptr) {} identified_device_(nullptr),
num_identify_calls_(0) {}
MockEidGenerator::~MockEidGenerator() {} MockEidGenerator::~MockEidGenerator() {}
...@@ -62,6 +63,11 @@ RemoteDevice const* MockEidGenerator::IdentifyRemoteDeviceByAdvertisement( ...@@ -62,6 +63,11 @@ RemoteDevice const* MockEidGenerator::IdentifyRemoteDeviceByAdvertisement(
const std::string& advertisement_service_data, const std::string& advertisement_service_data,
const std::vector<RemoteDevice>& device_list, const std::vector<RemoteDevice>& device_list,
const std::vector<BeaconSeed>& scanning_device_beacon_seeds) const { const std::vector<BeaconSeed>& scanning_device_beacon_seeds) const {
// Increment num_identify_calls_. Since this overrides a const method, some
// hacking is needed to modify the num_identify_calls_ instance variable.
int* num_identify_calls_ptr = const_cast<int*>(&num_identify_calls_);
*num_identify_calls_ptr = *num_identify_calls_ptr + 1;
return identified_device_; return identified_device_;
} }
......
...@@ -60,11 +60,17 @@ class MockEidGenerator : public EidGenerator { ...@@ -60,11 +60,17 @@ class MockEidGenerator : public EidGenerator {
const std::vector<BeaconSeed>& scanning_device_beacon_seeds) const std::vector<BeaconSeed>& scanning_device_beacon_seeds)
const override; const override;
int num_identify_calls() {
return num_identify_calls_;
}
private: private:
std::unique_ptr<EidData> background_scan_filter_; std::unique_ptr<EidData> background_scan_filter_;
std::unique_ptr<DataWithTimestamp> advertisement_; std::unique_ptr<DataWithTimestamp> advertisement_;
std::unique_ptr<std::vector<std::string>> possible_advertisements_; std::unique_ptr<std::vector<std::string>> possible_advertisements_;
const RemoteDevice* identified_device_; const RemoteDevice* identified_device_;
int num_identify_calls_;
}; };
} // namespace cryptauth } // namespace cryptauth
......
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