Commit 261661bb authored by Ryan Hansberry's avatar Ryan Hansberry Committed by Commit Bot

[Nearby] Create concrete BluetoothSocket and implement ConnectToService.

Implement a concrete location::nearby::api::BluetoothSocket, created via
a bluetooth::mojom::Socket and Mojo DataPipes supplied by the newly
implemented BluetoothClassicMedium::ConnectToService().

Nearby Connections uses this BluetoothSocket to communicate with a
remote device. At a high-level, it first exchanges frames to encrypt
the connection, then delegates to its caller (e.g., Nearby Share)
to authenticate the connection, and finally expects its caller to
send and receive application-level messages. The following precautions
are taken to handle untrusted bytes received from remote devices:
  * Nearby Connections (including the code being added in this CL) is
    hosted in a Nearby utility process.
  * Whenever Nearby Connections provides bytes received from a remote
    device to its caller, even after it has been authenticated, the
    caller must not trust those bytes, and is responsible for first
    passing those bytes through the trusted NearbyDecoder interface
    (see go/nearby-chrome-mojo). NearbyDecoder is hosted in the same
    Nearby utility process.

api::BluetoothSocket is a synchronous interface, so this
implementation consumes the synchronous signatures of
bluetooth::mojom::Socket methods.

api::BluetoothSocket's subclasses are also synchronous interfaces,
but the Mojo DataPipes they consume only provide asynchronous
interfaces. This is reconciled by blocking on the caller thread when
waiting (via a mojo::SimpleWatcher) for the DataPipes to become
readable or writable (this is expected by the callers of
api::BluetoothSocket's subclasses). Mojo DataPipe operations are
handled on a separate task runner so that blocking on the calling
thread will not deadlock.

Please see design doc go/nearby-chrome-bt for more details.

Bug: b:154849033, b:158848873
Change-Id: I2e945277aa1f75b4ca378d0b961f7682ff25d812
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2322166
Commit-Queue: Ryan Hansberry <hansberry@chromium.org>
Reviewed-by: default avatarAlex Chau <alexchau@chromium.org>
Reviewed-by: default avatarJames Vecore <vecore@google.com>
Reviewed-by: default avatarReilly Grant <reillyg@chromium.org>
Cr-Commit-Position: refs/heads/master@{#797758}
parent f7ead7d4
...@@ -14,6 +14,8 @@ source_set("platform_v2") { ...@@ -14,6 +14,8 @@ source_set("platform_v2") {
"bluetooth_classic_medium.h", "bluetooth_classic_medium.h",
"bluetooth_device.cc", "bluetooth_device.cc",
"bluetooth_device.h", "bluetooth_device.h",
"bluetooth_socket.cc",
"bluetooth_socket.h",
"condition_variable.cc", "condition_variable.cc",
"condition_variable.h", "condition_variable.h",
"count_down_latch.cc", "count_down_latch.cc",
...@@ -61,6 +63,7 @@ source_set("unit_tests") { ...@@ -61,6 +63,7 @@ source_set("unit_tests") {
"atomic_uint32_unittest.cc", "atomic_uint32_unittest.cc",
"bluetooth_adapter_unittest.cc", "bluetooth_adapter_unittest.cc",
"bluetooth_classic_medium_unittest.cc", "bluetooth_classic_medium_unittest.cc",
"bluetooth_socket_unittest.cc",
"condition_variable_unittest.cc", "condition_variable_unittest.cc",
"count_down_latch_unittest.cc", "count_down_latch_unittest.cc",
"crypto_unittest.cc", "crypto_unittest.cc",
......
...@@ -3,6 +3,7 @@ ...@@ -3,6 +3,7 @@
# found in the LICENSE file. # found in the LICENSE file.
include_rules = [ include_rules = [
'+device/bluetooth/public',
'+third_party/abseil-cpp/absl/strings/string_view.h', '+third_party/abseil-cpp/absl/strings/string_view.h',
'+third_party/abseil-cpp/absl/time/time.h', '+third_party/abseil-cpp/absl/time/time.h',
] ]
...@@ -15,7 +15,7 @@ namespace nearby { ...@@ -15,7 +15,7 @@ namespace nearby {
namespace chrome { namespace chrome {
// Concrete BluetoothAdapter implementation. // Concrete BluetoothAdapter implementation.
// api::BluetoothAdapter is a synchronous interface, so this implementation of // api::BluetoothAdapter is a synchronous interface, so this implementation
// consumes the synchronous signatures of bluetooth::mojom::Adapter methods. // consumes the synchronous signatures of bluetooth::mojom::Adapter methods.
class BluetoothAdapter : public api::BluetoothAdapter { class BluetoothAdapter : public api::BluetoothAdapter {
public: public:
......
...@@ -4,6 +4,9 @@ ...@@ -4,6 +4,9 @@
#include "chrome/services/sharing/nearby/platform_v2/bluetooth_classic_medium.h" #include "chrome/services/sharing/nearby/platform_v2/bluetooth_classic_medium.h"
#include "chrome/services/sharing/nearby/platform_v2/bluetooth_socket.h"
#include "device/bluetooth/public/cpp/bluetooth_uuid.h"
namespace location { namespace location {
namespace nearby { namespace nearby {
namespace chrome { namespace chrome {
...@@ -69,8 +72,26 @@ bool BluetoothClassicMedium::StopDiscovery() { ...@@ -69,8 +72,26 @@ bool BluetoothClassicMedium::StopDiscovery() {
std::unique_ptr<api::BluetoothSocket> BluetoothClassicMedium::ConnectToService( std::unique_ptr<api::BluetoothSocket> BluetoothClassicMedium::ConnectToService(
api::BluetoothDevice& remote_device, api::BluetoothDevice& remote_device,
const std::string& service_uuid) { const std::string& service_uuid) {
// TODO(b/154849933): Implement this in a subsequent CL. // TODO(hansberry): This currently assumes that the device was discovered via
NOTIMPLEMENTED(); // Bluetooth Classic (the remote device is in high visibility mode), meaning
// this address is the expected permanent BT MAC address. Once an
// implementation is in place to scan for devices over BLE, a new mechanism
// to query for the remote device's permanent BT MAC address from stored
// certificates.
// We provided this |remote_device|, so we can safely downcast it.
const std::string& address =
static_cast<chrome::BluetoothDevice&>(remote_device).GetAddress();
bluetooth::mojom::ConnectToServiceResultPtr result;
bool success = adapter_->ConnectToServiceInsecurely(
address, device::BluetoothUUID(service_uuid), &result);
if (success && result) {
return std::make_unique<chrome::BluetoothSocket>(
remote_device, std::move(result->socket),
std::move(result->receive_stream), std::move(result->send_stream));
}
return nullptr; return nullptr;
} }
......
...@@ -25,6 +25,8 @@ const char kDeviceAddress1[] = "DeviceAddress1"; ...@@ -25,6 +25,8 @@ const char kDeviceAddress1[] = "DeviceAddress1";
const char kDeviceAddress2[] = "DeviceAddress2"; const char kDeviceAddress2[] = "DeviceAddress2";
const char kDeviceName1[] = "DeviceName1"; const char kDeviceName1[] = "DeviceName1";
const char kDeviceName2[] = "DeviceName2"; const char kDeviceName2[] = "DeviceName2";
const device::BluetoothUUID kNearbySharingServiceUuid =
device::BluetoothUUID("a82efa21-ae5c-3dde-9bbc-f16da7b16c5a");
} // namespace } // namespace
class BluetoothClassicMediumTest : public testing::Test { class BluetoothClassicMediumTest : public testing::Test {
...@@ -193,6 +195,35 @@ TEST_F(BluetoothClassicMediumTest, TestDiscovery_DeviceLost) { ...@@ -193,6 +195,35 @@ TEST_F(BluetoothClassicMediumTest, TestDiscovery_DeviceLost) {
StopDiscovery(); StopDiscovery();
} }
TEST_F(BluetoothClassicMediumTest, TestConnectToService_Success) {
StartDiscovery();
NotifyDeviceAdded(kDeviceAddress1, kDeviceName1);
StopDiscovery();
fake_adapter_->AllowConnectionForAddressAndUuidPair(
kDeviceAddress1, kNearbySharingServiceUuid);
auto bluetooth_socket = bluetooth_classic_medium_->ConnectToService(
*last_device_discovered_, kNearbySharingServiceUuid.value());
EXPECT_EQ(last_device_discovered_, bluetooth_socket->GetRemoteDevice());
EXPECT_TRUE(bluetooth_socket->Close().Ok());
}
TEST_F(BluetoothClassicMediumTest, TestConnectToService_ConnectionFailure) {
StartDiscovery();
NotifyDeviceAdded(kDeviceAddress1, kDeviceName1);
NotifyDeviceAdded(kDeviceAddress2, kDeviceName2);
StopDiscovery();
// Do not allow "Device 2".
fake_adapter_->AllowConnectionForAddressAndUuidPair(
kDeviceAddress1, kNearbySharingServiceUuid);
EXPECT_FALSE(bluetooth_classic_medium_->ConnectToService(
*last_device_discovered_, kNearbySharingServiceUuid.value()));
}
} // namespace chrome } // namespace chrome
} // namespace nearby } // namespace nearby
} // namespace location } // namespace location
This diff is collapsed.
// Copyright 2020 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 CHROME_SERVICES_SHARING_NEARBY_PLATFORM_V2_BLUETOOTH_SOCKET_H_
#define CHROME_SERVICES_SHARING_NEARBY_PLATFORM_V2_BLUETOOTH_SOCKET_H_
#include <string>
#include "device/bluetooth/public/mojom/adapter.mojom.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/nearby/src/cpp/platform_v2/api/bluetooth_classic.h"
#include "third_party/nearby/src/cpp/platform_v2/base/input_stream.h"
#include "third_party/nearby/src/cpp/platform_v2/base/output_stream.h"
namespace base {
class SequencedTaskRunner;
} // namespace base
namespace location {
namespace nearby {
namespace chrome {
// Concrete BluetoothSocket implementation.
//
// Nearby Connections uses this BluetoothSocket to communicate with a remote
// device. At a high-level, it first exchanges frames to encrypt the connection,
// then delegates to its caller (e.g., Nearby Share) to authenticate the
// connection, and finally expects its caller to send and receive
// application-level messages. The following precautions are taken to handle
// untrusted bytes received from remote devices:
// * Nearby Connections (which this class is a piece of) is hosted in a
// Nearby utility process.
// * Whenever Nearby Connections provides bytes received from a remote device
// to its caller, even after it has been authenticated, the caller must not
// trust those bytes, and is responsible for first passing those bytes
// through the trusted NearbyDecoder interface (see go/nearby-chrome-mojo).
// NearbyDecoder is hosted in the same Nearby utility process.
//
// api::BluetoothSocket is a synchronous interface, so this implementation
// consumes the synchronous signatures of bluetooth::mojom::Socket methods.
//
// api::BluetoothSocket's subclasses are also synchronous interfaces, but the
// Mojo DataPipes they consume only provide asynchronous interfaces. This is
// reconciled by blocking on the caller thread when waiting (via a
// mojo::SimpleWatcher) for the DataPipes to become readable or writable (this
// is expected by the callers of api::BluetoothSocket's subclasses). Mojo
// DataPipe operations are handled on a separate task runner (see
// |task_runner_|) so that blocking on the calling thread will not deadlock.
class BluetoothSocket : public api::BluetoothSocket {
public:
BluetoothSocket(api::BluetoothDevice& remote_device,
mojo::PendingRemote<bluetooth::mojom::Socket> socket,
mojo::ScopedDataPipeConsumerHandle receive_stream,
mojo::ScopedDataPipeProducerHandle send_stream);
~BluetoothSocket() override;
BluetoothSocket(const BluetoothSocket&) = delete;
BluetoothSocket& operator=(const BluetoothSocket&) = delete;
// api::BluetoothSocket:
InputStream& GetInputStream() override;
OutputStream& GetOutputStream() override;
Exception Close() override;
api::BluetoothDevice* GetRemoteDevice() override;
private:
// These methods must be run on |task_runner_|, because the
// mojo::SimpleWatcher members of |input_stream_| and |output_stream_| expect
// to be created on the same sequence they are later run on. See
// |task_runner_|.
void CreateInputStream(mojo::ScopedDataPipeConsumerHandle receive_stream,
base::OnceClosure callback);
void DestroyInputStream(base::OnceClosure callback);
void CreateOutputStream(mojo::ScopedDataPipeProducerHandle send_stream,
base::OnceClosure callback);
void DestroyOutputStream(base::OnceClosure callback);
api::BluetoothDevice& remote_device_;
// The public methods which are overridden by BluetoothSocket's subclasses
// InputStreamImpl and OutputStreamImpl are expected to block the caller
// thread. While that thread is blocked, |task_runner_| handles read and write
// operations on |input_stream_| and |output_stream_|. Because of that,
// |input_stream_| (and its mojo::SimpleWatcher) and |output_stream_| (and
// its mojo::SimpleWatcher), must be created and destroyed on |task_runner_|
// (see respective helper Create* and Destroy* methods).
scoped_refptr<base::SequencedTaskRunner> task_runner_;
// These properties must be created on |task_runner_|. See |task_runner_|.
mojo::Remote<bluetooth::mojom::Socket> socket_;
std::unique_ptr<InputStream> input_stream_;
std::unique_ptr<OutputStream> output_stream_;
};
} // namespace chrome
} // namespace nearby
} // namespace location
#endif // CHROME_SERVICES_SHARING_NEARBY_PLATFORM_V2_BLUETOOTH_SOCKET_H_
// Copyright 2020 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 "chrome/services/sharing/nearby/platform_v2/bluetooth_socket.h"
#include <memory>
#include "base/bind.h"
#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
#include "base/test/task_environment.h"
#include "chrome/services/sharing/nearby/platform_v2/bluetooth_device.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace location {
namespace nearby {
namespace chrome {
namespace {
const char kDeviceAddress1[] = "DeviceAddress1";
const char kDeviceName1[] = "DeviceName1";
class FakeSocket : public bluetooth::mojom::Socket {
public:
FakeSocket() = default;
~FakeSocket() override {
EXPECT_TRUE(called_disconnect_);
if (on_destroy_callback_)
std::move(on_destroy_callback_).Run();
}
void SetOnDestroyCallback(base::OnceClosure callback) {
on_destroy_callback_ = std::move(callback);
}
private:
// bluetooth::mojom::Socket:
void Disconnect(DisconnectCallback callback) override {
called_disconnect_ = true;
std::move(callback).Run();
}
bool called_disconnect_ = false;
base::OnceClosure on_destroy_callback_;
};
} // namespace
class BluetoothSocketTest : public testing::Test {
public:
BluetoothSocketTest() = default;
~BluetoothSocketTest() override = default;
BluetoothSocketTest(const BluetoothSocketTest&) = delete;
BluetoothSocketTest& operator=(const BluetoothSocketTest&) = delete;
void SetUp() override {
bluetooth_device_ = std::make_unique<chrome::BluetoothDevice>(
CreateDeviceInfo(kDeviceAddress1, kDeviceName1));
mojo::ScopedDataPipeProducerHandle receive_pipe_producer_handle;
mojo::ScopedDataPipeConsumerHandle receive_pipe_consumer_handle;
ASSERT_EQ(
MOJO_RESULT_OK,
mojo::CreateDataPipe(/*options=*/nullptr, &receive_pipe_producer_handle,
&receive_pipe_consumer_handle));
mojo::ScopedDataPipeProducerHandle send_pipe_producer_handle;
mojo::ScopedDataPipeConsumerHandle send_pipe_consumer_handle;
ASSERT_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(/*options=*/nullptr,
&send_pipe_producer_handle,
&send_pipe_consumer_handle));
auto fake_socket = std::make_unique<FakeSocket>();
fake_socket_ = fake_socket.get();
mojo::PendingRemote<bluetooth::mojom::Socket> pending_socket;
mojo::MakeSelfOwnedReceiver(
std::move(fake_socket),
pending_socket.InitWithNewPipeAndPassReceiver());
bluetooth_socket_ = std::make_unique<BluetoothSocket>(
*bluetooth_device_, std::move(pending_socket),
std::move(receive_pipe_consumer_handle),
std::move(send_pipe_producer_handle));
receive_stream_ = std::move(receive_pipe_producer_handle);
send_stream_ = std::move(send_pipe_consumer_handle);
}
void TearDown() override {
// Destroy here, not in BluetoothSocketTest's destructor, because this is
// blocking.
bluetooth_socket_.reset();
}
protected:
std::unique_ptr<chrome::BluetoothDevice> bluetooth_device_;
FakeSocket* fake_socket_ = nullptr;
std::unique_ptr<BluetoothSocket> bluetooth_socket_;
mojo::ScopedDataPipeProducerHandle receive_stream_;
mojo::ScopedDataPipeConsumerHandle send_stream_;
private:
bluetooth::mojom::DeviceInfoPtr CreateDeviceInfo(const std::string& address,
const std::string& name) {
auto device_info = bluetooth::mojom::DeviceInfo::New();
device_info->address = address;
device_info->name = name;
device_info->name_for_display = name;
return device_info;
}
base::test::TaskEnvironment task_environment_;
};
TEST_F(BluetoothSocketTest, TestGetRemoteDevice) {
EXPECT_EQ(bluetooth_device_.get(), bluetooth_socket_->GetRemoteDevice());
}
TEST_F(BluetoothSocketTest, TestClose) {
ASSERT_TRUE(fake_socket_);
base::RunLoop run_loop;
fake_socket_->SetOnDestroyCallback(run_loop.QuitClosure());
EXPECT_TRUE(bluetooth_socket_->Close().Ok());
run_loop.Run();
}
TEST_F(BluetoothSocketTest, TestDestroy) {
ASSERT_TRUE(fake_socket_);
base::RunLoop run_loop;
fake_socket_->SetOnDestroyCallback(run_loop.QuitClosure());
bluetooth_socket_.reset();
run_loop.Run();
}
TEST_F(BluetoothSocketTest, TestInputStream) {
InputStream& input_stream = bluetooth_socket_->GetInputStream();
std::string message = "ReceivedMessage";
uint32_t message_size = message.size();
EXPECT_EQ(MOJO_RESULT_OK,
receive_stream_->WriteData(message.data(), &message_size,
MOJO_WRITE_DATA_FLAG_NONE));
EXPECT_EQ(message.size(), message_size);
ExceptionOr<ByteArray> exception_or_byte_array =
input_stream.Read(message_size);
ASSERT_TRUE(exception_or_byte_array.ok());
ByteArray& byte_array = exception_or_byte_array.result();
std::string received_string(byte_array);
EXPECT_EQ(message, received_string);
EXPECT_EQ(Exception::kSuccess, input_stream.Close().value);
}
TEST_F(BluetoothSocketTest, TestOutputStream) {
OutputStream& output_stream = bluetooth_socket_->GetOutputStream();
std::string message = "SentMessage";
ByteArray byte_array(message);
EXPECT_EQ(Exception::kSuccess, output_stream.Write(byte_array).value);
const uint32_t max_buffer_size = 1024;
uint32_t buffer_size = max_buffer_size;
std::vector<char> buffer(max_buffer_size);
EXPECT_EQ(MOJO_RESULT_OK, send_stream_->ReadData(buffer.data(), &buffer_size,
MOJO_READ_DATA_FLAG_NONE));
std::string sent_string(buffer.data(), buffer_size);
EXPECT_EQ(message, sent_string);
EXPECT_EQ(Exception::kSuccess, output_stream.Flush().value);
EXPECT_EQ(Exception::kSuccess, output_stream.Close().value);
}
} // namespace chrome
} // namespace nearby
} // namespace location
include_rules = [
"+device/bluetooth/public",
]
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace bluetooth { namespace bluetooth {
...@@ -20,7 +21,7 @@ class FakeDiscoverySession : public mojom::DiscoverySession { ...@@ -20,7 +21,7 @@ class FakeDiscoverySession : public mojom::DiscoverySession {
~FakeDiscoverySession() override { std::move(on_destroy_callback_).Run(); } ~FakeDiscoverySession() override { std::move(on_destroy_callback_).Run(); }
private: private:
// mojom::FakeDiscoverySession: // mojom::DiscoverySession:
void IsActive(IsActiveCallback callback) override { void IsActive(IsActiveCallback callback) override {
std::move(callback).Run(true); std::move(callback).Run(true);
} }
...@@ -29,6 +30,24 @@ class FakeDiscoverySession : public mojom::DiscoverySession { ...@@ -29,6 +30,24 @@ class FakeDiscoverySession : public mojom::DiscoverySession {
base::OnceClosure on_destroy_callback_; base::OnceClosure on_destroy_callback_;
}; };
class FakeSocket : public mojom::Socket {
public:
FakeSocket(mojo::ScopedDataPipeProducerHandle receive_stream,
mojo::ScopedDataPipeConsumerHandle send_stream)
: receive_stream_(std::move(receive_stream)),
send_stream_(std::move(send_stream)) {}
~FakeSocket() override = default;
private:
// mojom::Socket:
void Disconnect(DisconnectCallback callback) override {
std::move(callback).Run();
}
mojo::ScopedDataPipeProducerHandle receive_stream_;
mojo::ScopedDataPipeConsumerHandle send_stream_;
};
} // namespace } // namespace
FakeAdapter::FakeAdapter() = default; FakeAdapter::FakeAdapter() = default;
...@@ -77,6 +96,45 @@ void FakeAdapter::StartDiscoverySession( ...@@ -77,6 +96,45 @@ void FakeAdapter::StartDiscoverySession(
std::move(callback).Run(std::move(pending_session)); std::move(callback).Run(std::move(pending_session));
} }
void FakeAdapter::ConnectToServiceInsecurely(
const std::string& address,
const device::BluetoothUUID& service_uuid,
ConnectToServiceInsecurelyCallback callback) {
if (!base::Contains(allowed_connections_for_address_and_uuid_pair_,
std::make_pair(address, service_uuid))) {
std::move(callback).Run(/*result=*/nullptr);
return;
}
mojo::ScopedDataPipeProducerHandle receive_pipe_producer_handle;
mojo::ScopedDataPipeConsumerHandle receive_pipe_consumer_handle;
ASSERT_EQ(
MOJO_RESULT_OK,
mojo::CreateDataPipe(/*options=*/nullptr, &receive_pipe_producer_handle,
&receive_pipe_consumer_handle));
mojo::ScopedDataPipeProducerHandle send_pipe_producer_handle;
mojo::ScopedDataPipeConsumerHandle send_pipe_consumer_handle;
ASSERT_EQ(MOJO_RESULT_OK, mojo::CreateDataPipe(/*options=*/nullptr,
&send_pipe_producer_handle,
&send_pipe_consumer_handle));
mojo::PendingRemote<mojom::Socket> pending_socket;
mojo::MakeSelfOwnedReceiver(
std::make_unique<FakeSocket>(std::move(receive_pipe_producer_handle),
std::move(send_pipe_consumer_handle)),
pending_socket.InitWithNewPipeAndPassReceiver());
mojom::ConnectToServiceResultPtr connect_to_service_result =
mojom::ConnectToServiceResult::New();
connect_to_service_result->socket = std::move(pending_socket);
connect_to_service_result->receive_stream =
std::move(receive_pipe_consumer_handle);
connect_to_service_result->send_stream = std::move(send_pipe_producer_handle);
std::move(callback).Run(std::move(connect_to_service_result));
}
void FakeAdapter::SetShouldDiscoverySucceed(bool should_discovery_succeed) { void FakeAdapter::SetShouldDiscoverySucceed(bool should_discovery_succeed) {
should_discovery_succeed_ = should_discovery_succeed; should_discovery_succeed_ = should_discovery_succeed;
} }
...@@ -102,6 +160,12 @@ void FakeAdapter::NotifyDeviceRemoved(mojom::DeviceInfoPtr device_info) { ...@@ -102,6 +160,12 @@ void FakeAdapter::NotifyDeviceRemoved(mojom::DeviceInfoPtr device_info) {
client_->DeviceRemoved(std::move(device_info)); client_->DeviceRemoved(std::move(device_info));
} }
void FakeAdapter::AllowConnectionForAddressAndUuidPair(
const std::string& address,
const device::BluetoothUUID& service_uuid) {
allowed_connections_for_address_and_uuid_pair_.emplace(address, service_uuid);
}
void FakeAdapter::OnDiscoverySessionDestroyed() { void FakeAdapter::OnDiscoverySessionDestroyed() {
DCHECK(discovery_session_); DCHECK(discovery_session_);
discovery_session_ = nullptr; discovery_session_ = nullptr;
...@@ -109,9 +173,4 @@ void FakeAdapter::OnDiscoverySessionDestroyed() { ...@@ -109,9 +173,4 @@ void FakeAdapter::OnDiscoverySessionDestroyed() {
std::move(on_discovery_session_destroyed_callback_).Run(); std::move(on_discovery_session_destroyed_callback_).Run();
} }
void FakeAdapter::ConnectToServiceInsecurely(
const std::string& address,
const device::BluetoothUUID& service_uuid,
ConnectToServiceInsecurelyCallback callback) {}
} // namespace bluetooth } // namespace bluetooth
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#ifndef CHROME_SERVICES_SHARING_NEARBY_TEST_SUPPORT_FAKE_ADAPTER_H_ #ifndef CHROME_SERVICES_SHARING_NEARBY_TEST_SUPPORT_FAKE_ADAPTER_H_
#define CHROME_SERVICES_SHARING_NEARBY_TEST_SUPPORT_FAKE_ADAPTER_H_ #define CHROME_SERVICES_SHARING_NEARBY_TEST_SUPPORT_FAKE_ADAPTER_H_
#include "device/bluetooth/public/cpp/bluetooth_uuid.h"
#include "device/bluetooth/public/mojom/adapter.mojom.h" #include "device/bluetooth/public/mojom/adapter.mojom.h"
#include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote_set.h" #include "mojo/public/cpp/bindings/remote_set.h"
...@@ -37,6 +38,9 @@ class FakeAdapter : public mojom::Adapter { ...@@ -37,6 +38,9 @@ class FakeAdapter : public mojom::Adapter {
void NotifyDeviceAdded(mojom::DeviceInfoPtr device_info); void NotifyDeviceAdded(mojom::DeviceInfoPtr device_info);
void NotifyDeviceChanged(mojom::DeviceInfoPtr device_info); void NotifyDeviceChanged(mojom::DeviceInfoPtr device_info);
void NotifyDeviceRemoved(mojom::DeviceInfoPtr device_info); void NotifyDeviceRemoved(mojom::DeviceInfoPtr device_info);
void AllowConnectionForAddressAndUuidPair(
const std::string& address,
const device::BluetoothUUID& service_uuid);
mojo::Receiver<mojom::Adapter> adapter_{this}; mojo::Receiver<mojom::Adapter> adapter_{this};
std::string name_ = "AdapterName"; std::string name_ = "AdapterName";
...@@ -51,6 +55,8 @@ class FakeAdapter : public mojom::Adapter { ...@@ -51,6 +55,8 @@ class FakeAdapter : public mojom::Adapter {
mojom::DiscoverySession* discovery_session_ = nullptr; mojom::DiscoverySession* discovery_session_ = nullptr;
bool should_discovery_succeed_ = true; bool should_discovery_succeed_ = true;
base::OnceClosure on_discovery_session_destroyed_callback_; base::OnceClosure on_discovery_session_destroyed_callback_;
std::set<std::pair<std::string, device::BluetoothUUID>>
allowed_connections_for_address_and_uuid_pair_;
mojo::Remote<mojom::AdapterClient> client_; mojo::Remote<mojom::AdapterClient> client_;
}; };
......
...@@ -38,6 +38,8 @@ class Adapter : public mojom::Adapter, ...@@ -38,6 +38,8 @@ class Adapter : public mojom::Adapter,
void SetClient(mojo::PendingRemote<mojom::AdapterClient> client, void SetClient(mojo::PendingRemote<mojom::AdapterClient> client,
SetClientCallback callback) override; SetClientCallback callback) override;
void StartDiscoverySession(StartDiscoverySessionCallback callback) override; void StartDiscoverySession(StartDiscoverySessionCallback callback) override;
// TODO(b/162975217): Add a mechanism to allowlist which address and UUID
// pairs clients are allowed to create a connection to.
void ConnectToServiceInsecurely( void ConnectToServiceInsecurely(
const std::string& address, const std::string& address,
const device::BluetoothUUID& service_uuid, const device::BluetoothUUID& service_uuid,
......
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