fido_ble_connection_unittest.cc 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788
  1. // Copyright 2017 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "device/fido/cable/fido_ble_connection.h"
  5. #include <bitset>
  6. #include <utility>
  7. #include "base/bind.h"
  8. #include "base/callback_helpers.h"
  9. #include "base/memory/ptr_util.h"
  10. #include "base/memory/raw_ptr.h"
  11. #include "base/run_loop.h"
  12. #include "base/strings/string_piece.h"
  13. #include "base/test/task_environment.h"
  14. #include "base/threading/thread_task_runner_handle.h"
  15. #include "build/build_config.h"
  16. #include "device/bluetooth/bluetooth_adapter_factory.h"
  17. #include "device/bluetooth/test/bluetooth_test.h"
  18. #include "device/bluetooth/test/mock_bluetooth_adapter.h"
  19. #include "device/bluetooth/test/mock_bluetooth_device.h"
  20. #include "device/bluetooth/test/mock_bluetooth_gatt_characteristic.h"
  21. #include "device/bluetooth/test/mock_bluetooth_gatt_connection.h"
  22. #include "device/bluetooth/test/mock_bluetooth_gatt_notify_session.h"
  23. #include "device/bluetooth/test/mock_bluetooth_gatt_service.h"
  24. #include "device/fido/cable/fido_ble_uuids.h"
  25. #include "device/fido/test_callback_receiver.h"
  26. #include "testing/gmock/include/gmock/gmock.h"
  27. #include "testing/gtest/include/gtest/gtest.h"
  28. #if BUILDFLAG(IS_ANDROID)
  29. #include "device/bluetooth/test/bluetooth_test_android.h"
  30. #elif BUILDFLAG(IS_MAC)
  31. #include "device/bluetooth/test/bluetooth_test_mac.h"
  32. #elif BUILDFLAG(IS_WIN)
  33. #include "device/bluetooth/test/bluetooth_test_win.h"
  34. #elif BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX)
  35. #include "device/bluetooth/test/bluetooth_test_bluez.h"
  36. #elif BUILDFLAG(IS_FUCHSIA)
  37. #include "device/bluetooth/test/bluetooth_test_fuchsia.h"
  38. #endif
  39. namespace device {
  40. using ::testing::_;
  41. using ::testing::ElementsAre;
  42. using ::testing::Invoke;
  43. using ::testing::IsEmpty;
  44. using ::testing::Return;
  45. using NiceMockBluetoothAdapter = ::testing::NiceMock<MockBluetoothAdapter>;
  46. using NiceMockBluetoothDevice = ::testing::NiceMock<MockBluetoothDevice>;
  47. using NiceMockBluetoothGattService =
  48. ::testing::NiceMock<MockBluetoothGattService>;
  49. using NiceMockBluetoothGattCharacteristic =
  50. ::testing::NiceMock<MockBluetoothGattCharacteristic>;
  51. using NiceMockBluetoothGattConnection =
  52. ::testing::NiceMock<MockBluetoothGattConnection>;
  53. using NiceMockBluetoothGattNotifySession =
  54. ::testing::NiceMock<MockBluetoothGattNotifySession>;
  55. namespace {
  56. constexpr auto kDefaultServiceRevision =
  57. static_cast<uint8_t>(FidoBleConnection::ServiceRevision::kFido2);
  58. std::vector<uint8_t> ToByteVector(base::StringPiece str) {
  59. return std::vector<uint8_t>(str.begin(), str.end());
  60. }
  61. BluetoothDevice* GetMockDevice(MockBluetoothAdapter* adapter,
  62. const std::string& address) {
  63. const std::vector<BluetoothDevice*> devices = adapter->GetMockDevices();
  64. auto found = std::find_if(devices.begin(), devices.end(),
  65. [&address](const auto* device) {
  66. return device->GetAddress() == address;
  67. });
  68. return found != devices.end() ? *found : nullptr;
  69. }
  70. class TestReadCallback {
  71. public:
  72. void OnRead(std::vector<uint8_t> value) {
  73. value_ = std::move(value);
  74. run_loop_->Quit();
  75. }
  76. const std::vector<uint8_t> WaitForResult() {
  77. run_loop_->Run();
  78. run_loop_.emplace();
  79. return value_;
  80. }
  81. FidoBleConnection::ReadCallback GetCallback() {
  82. return base::BindRepeating(&TestReadCallback::OnRead,
  83. base::Unretained(this));
  84. }
  85. private:
  86. std::vector<uint8_t> value_;
  87. absl::optional<base::RunLoop> run_loop_{absl::in_place};
  88. };
  89. using TestConnectionCallbackReceiver = test::ValueCallbackReceiver<bool>;
  90. using TestReadControlPointLengthCallback =
  91. test::ValueCallbackReceiver<absl::optional<uint16_t>>;
  92. using TestReadServiceRevisionsCallback =
  93. test::ValueCallbackReceiver<std::set<FidoBleConnection::ServiceRevision>>;
  94. using TestWriteCallback = test::ValueCallbackReceiver<bool>;
  95. } // namespace
  96. class FidoBleConnectionTest : public ::testing::Test {
  97. public:
  98. FidoBleConnectionTest() {
  99. ON_CALL(*adapter_, GetDevice(_))
  100. .WillByDefault(Invoke([this](const std::string& address) {
  101. return GetMockDevice(adapter_.get(), address);
  102. }));
  103. BluetoothAdapterFactory::SetAdapterForTesting(adapter_);
  104. }
  105. BluetoothAdapter* adapter() { return adapter_.get(); }
  106. MockBluetoothDevice* device() { return fido_device_; }
  107. void AddFidoDevice(const std::string& device_address) {
  108. auto fido_device = std::make_unique<NiceMockBluetoothDevice>(
  109. adapter_.get(), /* bluetooth_class */ 0u,
  110. BluetoothTest::kTestDeviceNameU2f, device_address, /* paired */ true,
  111. /* connected */ false);
  112. fido_device_ = fido_device.get();
  113. adapter_->AddMockDevice(std::move(fido_device));
  114. ON_CALL(*fido_device_, GetGattServices())
  115. .WillByDefault(
  116. Invoke(fido_device_.get(), &MockBluetoothDevice::GetMockServices));
  117. ON_CALL(*fido_device_, GetGattService(_))
  118. .WillByDefault(
  119. Invoke(fido_device_.get(), &MockBluetoothDevice::GetMockService));
  120. AddFidoService();
  121. }
  122. void SetupConnectingFidoDevice(const std::string& device_address) {
  123. ON_CALL(*fido_device_, CreateGattConnection_)
  124. .WillByDefault(Invoke([this, &device_address](auto& callback) {
  125. connection_ =
  126. new NiceMockBluetoothGattConnection(adapter_, device_address);
  127. std::move(callback).Run(
  128. std::move(base::WrapUnique(connection_.get())),
  129. /*error_code=*/absl::nullopt);
  130. }));
  131. ON_CALL(*fido_device_, IsGattServicesDiscoveryComplete)
  132. .WillByDefault(Return(true));
  133. ON_CALL(*fido_service_revision_bitfield_, ReadRemoteCharacteristic_)
  134. .WillByDefault(Invoke(
  135. [=](BluetoothRemoteGattCharacteristic::ValueCallback& callback) {
  136. base::ThreadTaskRunnerHandle::Get()->PostTask(
  137. FROM_HERE, base::BindOnce(std::move(callback),
  138. /*error_code=*/absl::nullopt,
  139. std::vector<uint8_t>(
  140. {kDefaultServiceRevision})));
  141. }));
  142. ON_CALL(*fido_service_revision_bitfield_, WriteRemoteCharacteristic_)
  143. .WillByDefault(Invoke(
  144. [=](auto&, BluetoothRemoteGattCharacteristic::WriteType,
  145. base::OnceClosure& callback,
  146. const BluetoothRemoteGattCharacteristic::ErrorCallback&) {
  147. base::ThreadTaskRunnerHandle::Get()->PostTask(
  148. FROM_HERE, std::move(callback));
  149. }));
  150. ON_CALL(*fido_status_, StartNotifySession_(_, _))
  151. .WillByDefault(Invoke(
  152. [this](BluetoothRemoteGattCharacteristic::NotifySessionCallback&
  153. callback,
  154. BluetoothRemoteGattCharacteristic::ErrorCallback&) {
  155. notify_session_ = new NiceMockBluetoothGattNotifySession(
  156. fido_status_->GetWeakPtr());
  157. std::move(callback).Run(base::WrapUnique(notify_session_.get()));
  158. }));
  159. }
  160. void SimulateGattDiscoveryComplete(bool complete) {
  161. EXPECT_CALL(*fido_device_, IsGattServicesDiscoveryComplete)
  162. .WillOnce(Return(complete));
  163. }
  164. void SimulateGattConnectionError() {
  165. EXPECT_CALL(*fido_device_, CreateGattConnection_)
  166. .WillOnce(Invoke([](auto&& callback) {
  167. base::ThreadTaskRunnerHandle::Get()->PostTask(
  168. FROM_HERE, base::BindOnce(std::move(callback),
  169. /*connection=*/nullptr,
  170. BluetoothDevice::ERROR_FAILED));
  171. }));
  172. }
  173. void SimulateGattNotifySessionStartError() {
  174. EXPECT_CALL(*fido_status_, StartNotifySession_(_, _))
  175. .WillOnce(Invoke(
  176. [](auto&&,
  177. BluetoothGattCharacteristic::ErrorCallback& error_callback) {
  178. base::ThreadTaskRunnerHandle::Get()->PostTask(
  179. FROM_HERE,
  180. base::BindOnce(std::move(error_callback),
  181. BluetoothGattService::GATT_ERROR_FAILED));
  182. }));
  183. }
  184. void NotifyStatusChanged(const std::vector<uint8_t>& value) {
  185. for (auto& observer : adapter_->GetObservers())
  186. observer.GattCharacteristicValueChanged(adapter_.get(), fido_status_,
  187. value);
  188. }
  189. void NotifyGattServicesDiscovered() {
  190. adapter_->NotifyGattServicesDiscovered(fido_device_);
  191. }
  192. void ChangeDeviceAddressAndNotifyObservers(std::string new_address) {
  193. auto old_address = fido_device_->GetAddress();
  194. EXPECT_CALL(*fido_device_, GetAddress)
  195. .WillRepeatedly(::testing::Return(new_address));
  196. for (auto& observer : adapter_->GetObservers())
  197. observer.DeviceAddressChanged(adapter_.get(), fido_device_, old_address);
  198. }
  199. void SetNextReadControlPointLengthReponse(bool success,
  200. const std::vector<uint8_t>& value) {
  201. EXPECT_CALL(*fido_control_point_length_, ReadRemoteCharacteristic_(_))
  202. .WillOnce(Invoke(
  203. [success, value](
  204. BluetoothRemoteGattCharacteristic::ValueCallback& callback) {
  205. absl::optional<BluetoothGattService::GattErrorCode> error_code;
  206. if (!success)
  207. error_code = BluetoothGattService::GATT_ERROR_FAILED;
  208. base::ThreadTaskRunnerHandle::Get()->PostTask(
  209. FROM_HERE,
  210. base::BindOnce(std::move(callback), error_code, value));
  211. }));
  212. }
  213. void SetNextReadServiceRevisionResponse(bool success,
  214. const std::vector<uint8_t>& value) {
  215. EXPECT_CALL(*fido_service_revision_, ReadRemoteCharacteristic_(_))
  216. .WillOnce(Invoke(
  217. [success, value](
  218. BluetoothRemoteGattCharacteristic::ValueCallback& callback) {
  219. absl::optional<BluetoothGattService::GattErrorCode> error_code;
  220. if (!success)
  221. error_code = BluetoothGattService::GATT_ERROR_FAILED;
  222. base::ThreadTaskRunnerHandle::Get()->PostTask(
  223. FROM_HERE,
  224. base::BindOnce(std::move(callback), error_code, value));
  225. }));
  226. }
  227. void SetNextReadServiceRevisionBitfieldResponse(
  228. bool success,
  229. const std::vector<uint8_t>& value) {
  230. EXPECT_CALL(*fido_service_revision_bitfield_, ReadRemoteCharacteristic_(_))
  231. .WillOnce(Invoke(
  232. [success, value](
  233. BluetoothRemoteGattCharacteristic::ValueCallback& callback) {
  234. auto error_code =
  235. success ? absl::nullopt
  236. : absl::make_optional(
  237. BluetoothGattService::GATT_ERROR_FAILED);
  238. base::ThreadTaskRunnerHandle::Get()->PostTask(
  239. FROM_HERE,
  240. base::BindOnce(std::move(callback), error_code, value));
  241. }));
  242. }
  243. void SetNextWriteControlPointResponse(bool success) {
  244. EXPECT_CALL(
  245. *fido_control_point_,
  246. WriteRemoteCharacteristic_(
  247. _, BluetoothRemoteGattCharacteristic::WriteType::kWithoutResponse,
  248. _, _))
  249. .WillOnce(Invoke([success](
  250. const auto& data,
  251. BluetoothRemoteGattCharacteristic::WriteType,
  252. base::OnceClosure& callback,
  253. BluetoothRemoteGattCharacteristic::ErrorCallback&
  254. error_callback) {
  255. base::ThreadTaskRunnerHandle::Get()->PostTask(
  256. FROM_HERE,
  257. success
  258. ? std::move(callback)
  259. : base::BindOnce(std::move(error_callback),
  260. BluetoothGattService::GATT_ERROR_FAILED));
  261. }));
  262. }
  263. void SetNextWriteServiceRevisionResponse(std::vector<uint8_t> expected_data,
  264. bool success) {
  265. EXPECT_CALL(
  266. *fido_service_revision_bitfield_,
  267. WriteRemoteCharacteristic_(
  268. expected_data,
  269. BluetoothRemoteGattCharacteristic::WriteType::kWithResponse, _, _))
  270. .WillOnce(Invoke([success](
  271. const auto& data,
  272. BluetoothRemoteGattCharacteristic::WriteType,
  273. base::OnceClosure& callback,
  274. BluetoothRemoteGattCharacteristic::ErrorCallback&
  275. error_callback) {
  276. base::ThreadTaskRunnerHandle::Get()->PostTask(
  277. FROM_HERE,
  278. success
  279. ? std::move(callback)
  280. : base::BindOnce(std::move(error_callback),
  281. BluetoothGattService::GATT_ERROR_FAILED));
  282. }));
  283. }
  284. void AddFidoService() {
  285. auto fido_service = std::make_unique<NiceMockBluetoothGattService>(
  286. fido_device_, "fido_service", BluetoothUUID(kFidoServiceUUID),
  287. /*is_primary=*/true);
  288. fido_service_ = fido_service.get();
  289. fido_device_->AddMockService(std::move(fido_service));
  290. {
  291. auto fido_control_point =
  292. std::make_unique<NiceMockBluetoothGattCharacteristic>(
  293. fido_service_, "fido_control_point",
  294. BluetoothUUID(kFidoControlPointUUID),
  295. BluetoothGattCharacteristic::PROPERTY_WRITE_WITHOUT_RESPONSE,
  296. BluetoothGattCharacteristic::PERMISSION_NONE);
  297. fido_control_point_ = fido_control_point.get();
  298. fido_service_->AddMockCharacteristic(std::move(fido_control_point));
  299. }
  300. {
  301. auto fido_status = std::make_unique<NiceMockBluetoothGattCharacteristic>(
  302. fido_service_, "fido_status", BluetoothUUID(kFidoStatusUUID),
  303. BluetoothGattCharacteristic::PROPERTY_NOTIFY,
  304. BluetoothGattCharacteristic::PERMISSION_NONE);
  305. fido_status_ = fido_status.get();
  306. fido_service_->AddMockCharacteristic(std::move(fido_status));
  307. }
  308. {
  309. auto fido_control_point_length =
  310. std::make_unique<NiceMockBluetoothGattCharacteristic>(
  311. fido_service_, "fido_control_point_length",
  312. BluetoothUUID(kFidoControlPointLengthUUID),
  313. BluetoothGattCharacteristic::PROPERTY_READ,
  314. BluetoothGattCharacteristic::PERMISSION_NONE);
  315. fido_control_point_length_ = fido_control_point_length.get();
  316. fido_service_->AddMockCharacteristic(
  317. std::move(fido_control_point_length));
  318. }
  319. {
  320. auto fido_service_revision =
  321. std::make_unique<NiceMockBluetoothGattCharacteristic>(
  322. fido_service_, "fido_service_revision",
  323. BluetoothUUID(kFidoServiceRevisionUUID),
  324. BluetoothGattCharacteristic::PROPERTY_READ,
  325. BluetoothGattCharacteristic::PERMISSION_NONE);
  326. fido_service_revision_ = fido_service_revision.get();
  327. fido_service_->AddMockCharacteristic(std::move(fido_service_revision));
  328. }
  329. {
  330. auto fido_service_revision_bitfield =
  331. std::make_unique<NiceMockBluetoothGattCharacteristic>(
  332. fido_service_, "fido_service_revision_bitfield",
  333. BluetoothUUID(kFidoServiceRevisionBitfieldUUID),
  334. BluetoothGattCharacteristic::PROPERTY_READ |
  335. BluetoothGattCharacteristic::PROPERTY_WRITE,
  336. BluetoothGattCharacteristic::PERMISSION_NONE);
  337. fido_service_revision_bitfield_ = fido_service_revision_bitfield.get();
  338. fido_service_->AddMockCharacteristic(
  339. std::move(fido_service_revision_bitfield));
  340. }
  341. }
  342. protected:
  343. static BluetoothUUID uuid() { return BluetoothUUID(kFidoServiceUUID); }
  344. private:
  345. base::test::TaskEnvironment task_environment_;
  346. scoped_refptr<MockBluetoothAdapter> adapter_ =
  347. base::MakeRefCounted<NiceMockBluetoothAdapter>();
  348. raw_ptr<MockBluetoothDevice> fido_device_;
  349. raw_ptr<MockBluetoothGattService> fido_service_;
  350. raw_ptr<MockBluetoothGattCharacteristic> fido_control_point_;
  351. raw_ptr<MockBluetoothGattCharacteristic> fido_status_;
  352. raw_ptr<MockBluetoothGattCharacteristic> fido_control_point_length_;
  353. raw_ptr<MockBluetoothGattCharacteristic> fido_service_revision_;
  354. raw_ptr<MockBluetoothGattCharacteristic> fido_service_revision_bitfield_;
  355. raw_ptr<MockBluetoothGattConnection> connection_;
  356. raw_ptr<MockBluetoothGattNotifySession> notify_session_;
  357. };
  358. TEST_F(FidoBleConnectionTest, Address) {
  359. const std::string device_address = BluetoothTest::kTestDeviceAddress1;
  360. FidoBleConnection connection(adapter(), device_address, uuid(),
  361. base::DoNothing());
  362. connection.Connect(base::DoNothing());
  363. EXPECT_EQ(device_address, connection.address());
  364. }
  365. TEST_F(FidoBleConnectionTest, DeviceNotPresent) {
  366. const std::string device_address = BluetoothTest::kTestDeviceAddress1;
  367. FidoBleConnection connection(adapter(), device_address, uuid(),
  368. base::DoNothing());
  369. TestConnectionCallbackReceiver connection_callback_receiver;
  370. connection.Connect(connection_callback_receiver.callback());
  371. connection_callback_receiver.WaitForCallback();
  372. EXPECT_FALSE(connection_callback_receiver.value());
  373. }
  374. TEST_F(FidoBleConnectionTest, PreConnected) {
  375. const std::string device_address = BluetoothTest::kTestDeviceAddress1;
  376. AddFidoDevice(device_address);
  377. SetupConnectingFidoDevice(device_address);
  378. FidoBleConnection connection(adapter(), device_address, uuid(),
  379. base::DoNothing());
  380. TestConnectionCallbackReceiver connection_callback_receiver;
  381. connection.Connect(connection_callback_receiver.callback());
  382. connection_callback_receiver.WaitForCallback();
  383. EXPECT_TRUE(connection_callback_receiver.value());
  384. }
  385. TEST_F(FidoBleConnectionTest, NoConnectionWithoutCompletedGattDiscovery) {
  386. const std::string device_address = BluetoothTest::kTestDeviceAddress1;
  387. AddFidoDevice(device_address);
  388. SetupConnectingFidoDevice(device_address);
  389. FidoBleConnection connection(adapter(), device_address, uuid(),
  390. base::DoNothing());
  391. SimulateGattDiscoveryComplete(false);
  392. TestConnectionCallbackReceiver connection_callback_receiver;
  393. connection.Connect(connection_callback_receiver.callback());
  394. base::RunLoop().RunUntilIdle();
  395. EXPECT_FALSE(connection_callback_receiver.was_called());
  396. NotifyGattServicesDiscovered();
  397. connection_callback_receiver.WaitForCallback();
  398. EXPECT_TRUE(connection_callback_receiver.value());
  399. }
  400. TEST_F(FidoBleConnectionTest, GattServicesDiscoveredIgnoredBeforeConnection) {
  401. const std::string device_address = BluetoothTest::kTestDeviceAddress1;
  402. AddFidoDevice(device_address);
  403. SetupConnectingFidoDevice(device_address);
  404. FidoBleConnection connection(adapter(), device_address, uuid(),
  405. base::DoNothing());
  406. NotifyGattServicesDiscovered();
  407. SimulateGattDiscoveryComplete(false);
  408. TestConnectionCallbackReceiver connection_callback_receiver;
  409. connection.Connect(connection_callback_receiver.callback());
  410. base::RunLoop().RunUntilIdle();
  411. EXPECT_FALSE(connection_callback_receiver.was_called());
  412. NotifyGattServicesDiscovered();
  413. connection_callback_receiver.WaitForCallback();
  414. EXPECT_TRUE(connection_callback_receiver.value());
  415. }
  416. TEST_F(FidoBleConnectionTest, GattServicesDiscoveredAgain) {
  417. const std::string device_address = BluetoothTest::kTestDeviceAddress1;
  418. AddFidoDevice(device_address);
  419. SetupConnectingFidoDevice(device_address);
  420. FidoBleConnection connection(adapter(), device_address, uuid(),
  421. base::DoNothing());
  422. TestConnectionCallbackReceiver connection_callback_receiver;
  423. connection.Connect(connection_callback_receiver.callback());
  424. NotifyGattServicesDiscovered();
  425. connection_callback_receiver.WaitForCallback();
  426. EXPECT_TRUE(connection_callback_receiver.value());
  427. // A second call to the event handler should not trigger another attempt to
  428. // obtain Gatt Services.
  429. EXPECT_CALL(*device(), GetGattServices).Times(0);
  430. EXPECT_CALL(*device(), GetGattService).Times(0);
  431. NotifyGattServicesDiscovered();
  432. }
  433. TEST_F(FidoBleConnectionTest, SimulateGattConnectionError) {
  434. const std::string device_address = BluetoothTest::kTestDeviceAddress1;
  435. AddFidoDevice(device_address);
  436. SetupConnectingFidoDevice(device_address);
  437. FidoBleConnection connection(adapter(), device_address, uuid(),
  438. base::DoNothing());
  439. SimulateGattConnectionError();
  440. TestConnectionCallbackReceiver connection_callback_receiver;
  441. connection.Connect(connection_callback_receiver.callback());
  442. connection_callback_receiver.WaitForCallback();
  443. EXPECT_FALSE(connection_callback_receiver.value());
  444. }
  445. TEST_F(FidoBleConnectionTest, SimulateGattNotifySessionStartError) {
  446. const std::string device_address = BluetoothTest::kTestDeviceAddress1;
  447. AddFidoDevice(device_address);
  448. SetupConnectingFidoDevice(device_address);
  449. FidoBleConnection connection(adapter(), device_address, uuid(),
  450. base::DoNothing());
  451. SimulateGattNotifySessionStartError();
  452. TestConnectionCallbackReceiver connection_callback_receiver;
  453. connection.Connect(connection_callback_receiver.callback());
  454. connection_callback_receiver.WaitForCallback();
  455. EXPECT_FALSE(connection_callback_receiver.value());
  456. }
  457. TEST_F(FidoBleConnectionTest, MultipleServiceRevisions) {
  458. const std::string device_address = BluetoothTest::kTestDeviceAddress1;
  459. AddFidoDevice(device_address);
  460. SetupConnectingFidoDevice(device_address);
  461. static constexpr struct {
  462. std::bitset<8> supported_revisions;
  463. std::bitset<8> selected_revision;
  464. } test_cases[] = {
  465. // Only U2F 1.1 is supported, pick it.
  466. {0b1000'0000, 0b1000'0000},
  467. // Only U2F 1.2 is supported, pick it.
  468. {0b0100'0000, 0b0100'0000},
  469. // U2F 1.1 and U2F 1.2 are supported, pick U2F 1.2.
  470. {0b1100'0000, 0b0100'0000},
  471. // Only FIDO2 is supported, pick it.
  472. {0b0010'0000, 0b0010'0000},
  473. // U2F 1.1 and FIDO2 are supported, pick FIDO2.
  474. {0b1010'0000, 0b0010'0000},
  475. // U2F 1.2 and FIDO2 are supported, pick FIDO2.
  476. {0b0110'0000, 0b0010'0000},
  477. // U2F 1.1, U2F 1.2 and FIDO2 are supported, pick FIDO2.
  478. {0b1110'0000, 0b0010'0000},
  479. // U2F 1.1 and a future revision are supported, pick U2F 1.1.
  480. {0b1000'1000, 0b1000'0000},
  481. // U2F 1.2 and a future revision are supported, pick U2F 1.2.
  482. {0b0100'1000, 0b0100'0000},
  483. // FIDO2 and a future revision are supported, pick FIDO2.
  484. {0b0010'1000, 0b0010'0000},
  485. };
  486. for (const auto& test_case : test_cases) {
  487. SCOPED_TRACE(::testing::Message()
  488. << "Supported Revisions: " << test_case.supported_revisions
  489. << ", Selected Revision: " << test_case.selected_revision);
  490. SetNextReadServiceRevisionBitfieldResponse(
  491. true, {static_cast<uint8_t>(test_case.supported_revisions.to_ulong())});
  492. SetNextWriteServiceRevisionResponse(
  493. {static_cast<uint8_t>(test_case.selected_revision.to_ulong())}, true);
  494. FidoBleConnection connection(adapter(), device_address, uuid(),
  495. base::DoNothing());
  496. TestConnectionCallbackReceiver connection_callback_receiver;
  497. connection.Connect(connection_callback_receiver.callback());
  498. connection_callback_receiver.WaitForCallback();
  499. EXPECT_TRUE(connection_callback_receiver.value());
  500. }
  501. }
  502. TEST_F(FidoBleConnectionTest, UnsupportedServiceRevisions) {
  503. const std::string device_address = BluetoothTest::kTestDeviceAddress1;
  504. AddFidoDevice(device_address);
  505. SetupConnectingFidoDevice(device_address);
  506. // Test failure cases.
  507. static constexpr struct {
  508. std::bitset<8> supported_revisions;
  509. } test_cases[] = {
  510. {0b0000'0000}, // No Service Revision.
  511. {0b0001'0000}, // Unsupported Service Revision (4th bit).
  512. {0b0000'1000}, // Unsupported Service Revision (3th bit).
  513. {0b0000'0100}, // Unsupported Service Revision (2th bit).
  514. {0b0000'0010}, // Unsupported Service Revision (1th bit).
  515. {0b0000'0001}, // Unsupported Service Revision (0th bit).
  516. };
  517. for (const auto& test_case : test_cases) {
  518. SCOPED_TRACE(::testing::Message()
  519. << "Supported Revisions: " << test_case.supported_revisions);
  520. SetNextReadServiceRevisionBitfieldResponse(
  521. true, {static_cast<uint8_t>(test_case.supported_revisions.to_ulong())});
  522. FidoBleConnection connection(adapter(), device_address, uuid(),
  523. base::DoNothing());
  524. TestConnectionCallbackReceiver connection_callback_receiver;
  525. connection.Connect(connection_callback_receiver.callback());
  526. connection_callback_receiver.WaitForCallback();
  527. EXPECT_FALSE(connection_callback_receiver.value());
  528. }
  529. }
  530. TEST_F(FidoBleConnectionTest, ReadServiceRevisionsFails) {
  531. const std::string device_address = BluetoothTest::kTestDeviceAddress1;
  532. AddFidoDevice(device_address);
  533. SetupConnectingFidoDevice(device_address);
  534. SetNextReadServiceRevisionBitfieldResponse(false, {});
  535. FidoBleConnection connection(adapter(), device_address, uuid(),
  536. base::DoNothing());
  537. TestConnectionCallbackReceiver connection_callback_receiver;
  538. connection.Connect(connection_callback_receiver.callback());
  539. connection_callback_receiver.WaitForCallback();
  540. EXPECT_FALSE(connection_callback_receiver.value());
  541. }
  542. TEST_F(FidoBleConnectionTest, WriteServiceRevisionsFails) {
  543. const std::string device_address = BluetoothTest::kTestDeviceAddress1;
  544. AddFidoDevice(device_address);
  545. SetupConnectingFidoDevice(device_address);
  546. SetNextReadServiceRevisionBitfieldResponse(true, {kDefaultServiceRevision});
  547. SetNextWriteServiceRevisionResponse({kDefaultServiceRevision}, false);
  548. FidoBleConnection connection(adapter(), device_address, uuid(),
  549. base::DoNothing());
  550. TestConnectionCallbackReceiver connection_callback_receiver;
  551. connection.Connect(connection_callback_receiver.callback());
  552. connection_callback_receiver.WaitForCallback();
  553. EXPECT_FALSE(connection_callback_receiver.value());
  554. }
  555. TEST_F(FidoBleConnectionTest, ReadStatusNotifications) {
  556. const std::string device_address = BluetoothTest::kTestDeviceAddress1;
  557. TestReadCallback read_callback;
  558. AddFidoDevice(device_address);
  559. SetupConnectingFidoDevice(device_address);
  560. FidoBleConnection connection(adapter(), device_address, uuid(),
  561. read_callback.GetCallback());
  562. TestConnectionCallbackReceiver connection_callback_receiver;
  563. connection.Connect(connection_callback_receiver.callback());
  564. connection_callback_receiver.WaitForCallback();
  565. EXPECT_TRUE(connection_callback_receiver.value());
  566. std::vector<uint8_t> payload = ToByteVector("foo");
  567. NotifyStatusChanged(payload);
  568. EXPECT_EQ(payload, read_callback.WaitForResult());
  569. payload = ToByteVector("bar");
  570. NotifyStatusChanged(payload);
  571. EXPECT_EQ(payload, read_callback.WaitForResult());
  572. }
  573. TEST_F(FidoBleConnectionTest, ReadControlPointLength) {
  574. const std::string device_address = BluetoothTest::kTestDeviceAddress1;
  575. AddFidoDevice(device_address);
  576. SetupConnectingFidoDevice(device_address);
  577. FidoBleConnection connection(adapter(), device_address, uuid(),
  578. base::DoNothing());
  579. TestConnectionCallbackReceiver connection_callback_receiver;
  580. connection.Connect(connection_callback_receiver.callback());
  581. connection_callback_receiver.WaitForCallback();
  582. EXPECT_TRUE(connection_callback_receiver.value());
  583. {
  584. TestReadControlPointLengthCallback length_callback;
  585. SetNextReadControlPointLengthReponse(false, {});
  586. connection.ReadControlPointLength(length_callback.callback());
  587. length_callback.WaitForCallback();
  588. EXPECT_EQ(absl::nullopt, length_callback.value());
  589. }
  590. // The Control Point Length should consist of exactly two bytes, hence we
  591. // EXPECT_EQ(absl::nullopt) for payloads of size 0, 1 and 3.
  592. {
  593. TestReadControlPointLengthCallback length_callback;
  594. SetNextReadControlPointLengthReponse(true, {});
  595. connection.ReadControlPointLength(length_callback.callback());
  596. length_callback.WaitForCallback();
  597. EXPECT_EQ(absl::nullopt, length_callback.value());
  598. }
  599. {
  600. TestReadControlPointLengthCallback length_callback;
  601. SetNextReadControlPointLengthReponse(true, {0xAB});
  602. connection.ReadControlPointLength(length_callback.callback());
  603. length_callback.WaitForCallback();
  604. EXPECT_EQ(absl::nullopt, length_callback.value());
  605. }
  606. {
  607. TestReadControlPointLengthCallback length_callback;
  608. SetNextReadControlPointLengthReponse(true, {0xAB, 0xCD});
  609. connection.ReadControlPointLength(length_callback.callback());
  610. length_callback.WaitForCallback();
  611. EXPECT_EQ(0xABCD, *length_callback.value());
  612. }
  613. {
  614. TestReadControlPointLengthCallback length_callback;
  615. SetNextReadControlPointLengthReponse(true, {0xAB, 0xCD, 0xEF});
  616. connection.ReadControlPointLength(length_callback.callback());
  617. length_callback.WaitForCallback();
  618. EXPECT_EQ(absl::nullopt, length_callback.value());
  619. }
  620. }
  621. TEST_F(FidoBleConnectionTest, WriteControlPoint) {
  622. const std::string device_address = BluetoothTest::kTestDeviceAddress1;
  623. AddFidoDevice(device_address);
  624. SetupConnectingFidoDevice(device_address);
  625. FidoBleConnection connection(adapter(), device_address, uuid(),
  626. base::DoNothing());
  627. TestConnectionCallbackReceiver connection_callback_receiver;
  628. connection.Connect(connection_callback_receiver.callback());
  629. connection_callback_receiver.WaitForCallback();
  630. EXPECT_TRUE(connection_callback_receiver.value());
  631. {
  632. TestWriteCallback write_callback;
  633. SetNextWriteControlPointResponse(false);
  634. connection.WriteControlPoint({}, write_callback.callback());
  635. write_callback.WaitForCallback();
  636. EXPECT_FALSE(write_callback.value());
  637. }
  638. {
  639. TestWriteCallback write_callback;
  640. SetNextWriteControlPointResponse(true);
  641. connection.WriteControlPoint({}, write_callback.callback());
  642. write_callback.WaitForCallback();
  643. EXPECT_TRUE(write_callback.value());
  644. }
  645. }
  646. TEST_F(FidoBleConnectionTest, ReadsAndWriteFailWhenDisconnected) {
  647. const std::string device_address = BluetoothTest::kTestDeviceAddress1;
  648. AddFidoDevice(device_address);
  649. SetupConnectingFidoDevice(device_address);
  650. FidoBleConnection connection(adapter(), device_address, uuid(),
  651. base::DoNothing());
  652. SimulateGattConnectionError();
  653. TestConnectionCallbackReceiver connection_callback_receiver;
  654. connection.Connect(connection_callback_receiver.callback());
  655. connection_callback_receiver.WaitForCallback();
  656. EXPECT_FALSE(connection_callback_receiver.value());
  657. // Reads should always fail on a disconnected device.
  658. TestReadControlPointLengthCallback length_callback;
  659. connection.ReadControlPointLength(length_callback.callback());
  660. length_callback.WaitForCallback();
  661. EXPECT_EQ(absl::nullopt, length_callback.value());
  662. // Writes should always fail on a disconnected device.
  663. TestWriteCallback write_callback;
  664. connection.WriteControlPoint({}, write_callback.callback());
  665. write_callback.WaitForCallback();
  666. EXPECT_FALSE(write_callback.value());
  667. }
  668. TEST_F(FidoBleConnectionTest, ConnectionAddressChangeWhenDeviceAddressChanges) {
  669. const std::string device_address = BluetoothTest::kTestDeviceAddress1;
  670. static constexpr char kTestDeviceAddress2[] = "test_device_address_2";
  671. AddFidoDevice(device_address);
  672. SetupConnectingFidoDevice(device_address);
  673. FidoBleConnection connection(adapter(), device_address, uuid(),
  674. base::DoNothing());
  675. ChangeDeviceAddressAndNotifyObservers(kTestDeviceAddress2);
  676. EXPECT_EQ(kTestDeviceAddress2, connection.address());
  677. }
  678. } // namespace device