Commit f750e14e authored by Ryan Hansberry's avatar Ryan Hansberry Committed by Commit Bot

[Nearby] Create and use Bluetooth Mojo ServerSocket.

Implement bluetooth::mojom::ServerSocket and a corresponding method to
create one, bluetooth::mojom::Adapter::CreateRfcommService(). Use this
new interface to implement a concrete
location::nearby::api::BluetoothServerSocket, created via the newly
implement BluetoothClassicMedium::ListenForService().

api::BluetoothClassicMedium and api::BluetoothServerSocket are both
synchronous interfaces, so these new implementations consume the
synchronous signatures of their respective dependencies.

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

Bug: b:154849933, b:157484631
Change-Id: I2b5fbe053fb9f38fbf2a999ff8ad4791a7d227fc
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2358129
Commit-Queue: Ryan Hansberry <hansberry@chromium.org>
Reviewed-by: default avatarReilly Grant <reillyg@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Reviewed-by: default avatarJames Vecore <vecore@google.com>
Reviewed-by: default avatarAlex Chau <alexchau@chromium.org>
Cr-Commit-Position: refs/heads/master@{#800008}
parent e512ea31
...@@ -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_server_socket.cc",
"bluetooth_server_socket.h",
"bluetooth_socket.cc", "bluetooth_socket.cc",
"bluetooth_socket.h", "bluetooth_socket.h",
"condition_variable.cc", "condition_variable.cc",
...@@ -63,6 +65,7 @@ source_set("unit_tests") { ...@@ -63,6 +65,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_server_socket_unittest.cc",
"bluetooth_socket_unittest.cc", "bluetooth_socket_unittest.cc",
"condition_variable_unittest.cc", "condition_variable_unittest.cc",
"count_down_latch_unittest.cc", "count_down_latch_unittest.cc",
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#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_server_socket.h"
#include "chrome/services/sharing/nearby/platform_v2/bluetooth_socket.h" #include "chrome/services/sharing/nearby/platform_v2/bluetooth_socket.h"
#include "device/bluetooth/public/cpp/bluetooth_uuid.h" #include "device/bluetooth/public/cpp/bluetooth_uuid.h"
...@@ -98,8 +99,15 @@ std::unique_ptr<api::BluetoothSocket> BluetoothClassicMedium::ConnectToService( ...@@ -98,8 +99,15 @@ std::unique_ptr<api::BluetoothSocket> BluetoothClassicMedium::ConnectToService(
std::unique_ptr<api::BluetoothServerSocket> std::unique_ptr<api::BluetoothServerSocket>
BluetoothClassicMedium::ListenForService(const std::string& service_name, BluetoothClassicMedium::ListenForService(const std::string& service_name,
const std::string& service_uuid) { const std::string& service_uuid) {
// TODO(b/154849933): Implement this in a subsequent CL. mojo::PendingRemote<bluetooth::mojom::ServerSocket> server_socket;
NOTIMPLEMENTED(); bool success = adapter_->CreateRfcommService(
service_name, device::BluetoothUUID(service_uuid), &server_socket);
if (success && server_socket) {
return std::make_unique<chrome::BluetoothServerSocket>(
std::move(server_socket));
}
return nullptr; return nullptr;
} }
......
...@@ -25,6 +25,7 @@ const char kDeviceAddress1[] = "DeviceAddress1"; ...@@ -25,6 +25,7 @@ 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 char kNearbySharingServiceName[] = "NearbySharing";
const device::BluetoothUUID kNearbySharingServiceUuid = const device::BluetoothUUID kNearbySharingServiceUuid =
device::BluetoothUUID("a82efa21-ae5c-3dde-9bbc-f16da7b16c5a"); device::BluetoothUUID("a82efa21-ae5c-3dde-9bbc-f16da7b16c5a");
} // namespace } // namespace
...@@ -210,7 +211,7 @@ TEST_F(BluetoothClassicMediumTest, TestConnectToService_Success) { ...@@ -210,7 +211,7 @@ TEST_F(BluetoothClassicMediumTest, TestConnectToService_Success) {
EXPECT_TRUE(bluetooth_socket->Close().Ok()); EXPECT_TRUE(bluetooth_socket->Close().Ok());
} }
TEST_F(BluetoothClassicMediumTest, TestConnectToService_ConnectionFailure) { TEST_F(BluetoothClassicMediumTest, TestConnectToService_Failure) {
StartDiscovery(); StartDiscovery();
NotifyDeviceAdded(kDeviceAddress1, kDeviceName1); NotifyDeviceAdded(kDeviceAddress1, kDeviceName1);
NotifyDeviceAdded(kDeviceAddress2, kDeviceName2); NotifyDeviceAdded(kDeviceAddress2, kDeviceName2);
...@@ -224,6 +225,24 @@ TEST_F(BluetoothClassicMediumTest, TestConnectToService_ConnectionFailure) { ...@@ -224,6 +225,24 @@ TEST_F(BluetoothClassicMediumTest, TestConnectToService_ConnectionFailure) {
*last_device_discovered_, kNearbySharingServiceUuid.value())); *last_device_discovered_, kNearbySharingServiceUuid.value()));
} }
TEST_F(BluetoothClassicMediumTest, TestListenForService_Success) {
fake_adapter_->AllowIncomingConnectionForServiceNameAndUuidPair(
kNearbySharingServiceName, kNearbySharingServiceUuid);
EXPECT_TRUE(bluetooth_classic_medium_->ListenForService(
kNearbySharingServiceName, kNearbySharingServiceUuid.value()));
}
TEST_F(BluetoothClassicMediumTest, TestListenForService_Failure) {
fake_adapter_->AllowIncomingConnectionForServiceNameAndUuidPair(
"DifferentServiceName", kNearbySharingServiceUuid);
fake_adapter_->AllowIncomingConnectionForServiceNameAndUuidPair(
kNearbySharingServiceName, device::BluetoothUUID("DifferentServiceId"));
EXPECT_FALSE(bluetooth_classic_medium_->ListenForService(
kNearbySharingServiceName, kNearbySharingServiceUuid.value()));
}
} // namespace chrome } // namespace chrome
} // namespace nearby } // namespace nearby
} // namespace location } // namespace location
// 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_server_socket.h"
#include "chrome/services/sharing/nearby/platform_v2/bluetooth_socket.h"
#include "third_party/nearby/src/cpp/platform_v2/base/exception.h"
namespace location {
namespace nearby {
namespace chrome {
BluetoothServerSocket::BluetoothServerSocket(
mojo::PendingRemote<bluetooth::mojom::ServerSocket> server_socket)
: server_socket_(std::move(server_socket)) {}
BluetoothServerSocket::~BluetoothServerSocket() = default;
std::unique_ptr<api::BluetoothSocket> BluetoothServerSocket::Accept() {
bluetooth::mojom::AcceptConnectionResultPtr result;
bool success = server_socket_->Accept(&result);
if (success && result) {
return std::make_unique<chrome::BluetoothSocket>(
std::move(result->device), std::move(result->socket),
std::move(result->receive_stream), std::move(result->send_stream));
}
return nullptr;
}
Exception BluetoothServerSocket::Close() {
// TODO(b/154849933): Implement this in a subsequent CL.
server_socket_.reset();
return {Exception::kSuccess};
}
} // namespace chrome
} // namespace nearby
} // namespace location
// 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_SERVER_SOCKET_H_
#define CHROME_SERVICES_SHARING_NEARBY_PLATFORM_V2_BLUETOOTH_SERVER_SOCKET_H_
#include <memory>
#include "device/bluetooth/public/mojom/adapter.mojom.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/nearby/src/cpp/platform_v2/api/bluetooth_classic.h"
namespace location {
namespace nearby {
namespace chrome {
// Concrete BluetoothServerSocket implementation.
class BluetoothServerSocket : public api::BluetoothServerSocket {
public:
explicit BluetoothServerSocket(
mojo::PendingRemote<bluetooth::mojom::ServerSocket> server_socket);
~BluetoothServerSocket() override;
BluetoothServerSocket(const BluetoothServerSocket&) = delete;
BluetoothServerSocket& operator=(const BluetoothServerSocket&) = delete;
// api::BluetoothServerSocket:
std::unique_ptr<api::BluetoothSocket> Accept() override;
Exception Close() override;
private:
mojo::Remote<bluetooth::mojom::ServerSocket> server_socket_;
};
} // namespace chrome
} // namespace nearby
} // namespace location
#endif // CHROME_SERVICES_SHARING_NEARBY_PLATFORM_V2_BLUETOOTH_SERVER_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_server_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 "chrome/services/sharing/nearby/platform_v2/bluetooth_socket.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 kDeviceAddress[] = "DeviceAddress";
const char kDeviceName[] = "DeviceName";
class FakeSocket : public bluetooth::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:
// bluetooth::mojom::Socket:
void Disconnect(DisconnectCallback callback) override {
std::move(callback).Run();
}
mojo::ScopedDataPipeProducerHandle receive_stream_;
mojo::ScopedDataPipeConsumerHandle send_stream_;
};
class FakeServerSocket : public bluetooth::mojom::ServerSocket {
public:
FakeServerSocket() = default;
~FakeServerSocket() override {
if (on_destroy_callback_)
std::move(on_destroy_callback_).Run();
}
void SetAcceptConnectionResult(
bluetooth::mojom::AcceptConnectionResultPtr result) {
accept_connection_result_ = std::move(result);
}
void SetOnDestroyCallback(base::OnceClosure callback) {
on_destroy_callback_ = std::move(callback);
}
private:
// bluetooth::mojom::ServerSocket:
void Accept(AcceptCallback callback) override {
std::move(callback).Run(std::move(accept_connection_result_));
}
bluetooth::mojom::AcceptConnectionResultPtr accept_connection_result_;
base::OnceClosure on_destroy_callback_;
};
} // namespace
class BluetoothServerSocketTest : public testing::Test {
public:
BluetoothServerSocketTest() = default;
~BluetoothServerSocketTest() override = default;
BluetoothServerSocketTest(const BluetoothServerSocketTest&) = delete;
BluetoothServerSocketTest& operator=(const BluetoothServerSocketTest&) =
delete;
void SetUp() override {
auto fake_server_socket = std::make_unique<FakeServerSocket>();
fake_server_socket_ = fake_server_socket.get();
mojo::PendingRemote<bluetooth::mojom::ServerSocket> pending_server_socket;
mojo::MakeSelfOwnedReceiver(
std::move(fake_server_socket),
pending_server_socket.InitWithNewPipeAndPassReceiver());
bluetooth_server_socket_ = std::make_unique<BluetoothServerSocket>(
std::move(pending_server_socket));
}
protected:
FakeServerSocket* fake_server_socket_ = nullptr;
std::unique_ptr<BluetoothServerSocket> bluetooth_server_socket_;
private:
base::test::TaskEnvironment task_environment_;
};
TEST_F(BluetoothServerSocketTest, TestAccept_Success) {
auto accept_connection_result =
bluetooth::mojom::AcceptConnectionResult::New();
accept_connection_result->device = bluetooth::mojom::DeviceInfo::New();
accept_connection_result->device->address = kDeviceAddress;
accept_connection_result->device->name_for_display = kDeviceName;
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<bluetooth::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());
accept_connection_result->socket = std::move(pending_socket);
accept_connection_result->receive_stream =
std::move(receive_pipe_consumer_handle);
accept_connection_result->send_stream = std::move(send_pipe_producer_handle);
fake_server_socket_->SetAcceptConnectionResult(
std::move(accept_connection_result));
auto bluetooth_socket = bluetooth_server_socket_->Accept();
ASSERT_TRUE(bluetooth_socket);
EXPECT_EQ(kDeviceName, bluetooth_socket->GetRemoteDevice()->GetName());
}
TEST_F(BluetoothServerSocketTest, TestAccept_NoConnection) {
EXPECT_FALSE(bluetooth_server_socket_->Accept());
}
TEST_F(BluetoothServerSocketTest, TestClose) {
base::RunLoop run_loop;
fake_server_socket_->SetOnDestroyCallback(run_loop.QuitClosure());
bluetooth_server_socket_->Close();
run_loop.Run();
}
TEST_F(BluetoothServerSocketTest, TestDestroy) {
base::RunLoop run_loop;
fake_server_socket_->SetOnDestroyCallback(run_loop.QuitClosure());
bluetooth_server_socket_.reset();
run_loop.Run();
}
} // namespace chrome
} // namespace nearby
} // namespace location
...@@ -213,32 +213,26 @@ class OutputStreamImpl : public OutputStream { ...@@ -213,32 +213,26 @@ class OutputStreamImpl : public OutputStream {
} // namespace } // namespace
BluetoothSocket::BluetoothSocket( BluetoothSocket::BluetoothSocket(
api::BluetoothDevice& remote_device, bluetooth::mojom::DeviceInfoPtr device,
mojo::PendingRemote<bluetooth::mojom::Socket> socket, mojo::PendingRemote<bluetooth::mojom::Socket> socket,
mojo::ScopedDataPipeConsumerHandle receive_stream, mojo::ScopedDataPipeConsumerHandle receive_stream,
mojo::ScopedDataPipeProducerHandle send_stream) mojo::ScopedDataPipeProducerHandle send_stream)
: remote_device_(remote_device), : remote_device_(std::move(device)),
task_runner_(base::ThreadPool::CreateSequencedTaskRunner({})) { remote_device_ref_(*remote_device_),
socket_.Bind(std::move(socket)); task_runner_(base::ThreadPool::CreateSequencedTaskRunner({})),
socket_(std::move(socket)) {
// These properties must be created on the same sequence they are later run InitializeStreams(std::move(receive_stream), std::move(send_stream));
// on. See |task_runner_|. }
CountDownLatch latch(2);
auto count_down_latch_callback = base::BindRepeating(
[](CountDownLatch* latch) { latch->CountDown(); }, &latch);
task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&BluetoothSocket::CreateInputStream,
base::Unretained(this), std::move(receive_stream),
count_down_latch_callback));
task_runner_->PostTask(
FROM_HERE, base::BindOnce(&BluetoothSocket::CreateOutputStream,
base::Unretained(this), std::move(send_stream),
count_down_latch_callback));
latch.Await(); BluetoothSocket::BluetoothSocket(
api::BluetoothDevice& remote_device,
mojo::PendingRemote<bluetooth::mojom::Socket> socket,
mojo::ScopedDataPipeConsumerHandle receive_stream,
mojo::ScopedDataPipeProducerHandle send_stream)
: remote_device_ref_(remote_device),
task_runner_(base::ThreadPool::CreateSequencedTaskRunner({})),
socket_(std::move(socket)) {
InitializeStreams(std::move(receive_stream), std::move(send_stream));
} }
BluetoothSocket::~BluetoothSocket() { BluetoothSocket::~BluetoothSocket() {
...@@ -280,7 +274,30 @@ Exception BluetoothSocket::Close() { ...@@ -280,7 +274,30 @@ Exception BluetoothSocket::Close() {
} }
api::BluetoothDevice* BluetoothSocket::GetRemoteDevice() { api::BluetoothDevice* BluetoothSocket::GetRemoteDevice() {
return &remote_device_; return &remote_device_ref_;
}
void BluetoothSocket::InitializeStreams(
mojo::ScopedDataPipeConsumerHandle receive_stream,
mojo::ScopedDataPipeProducerHandle send_stream) {
// These properties must be created on the same sequence they are later run
// on. See |task_runner_|.
CountDownLatch latch(2);
auto count_down_latch_callback = base::BindRepeating(
[](CountDownLatch* latch) { latch->CountDown(); }, &latch);
task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&BluetoothSocket::CreateInputStream,
base::Unretained(this), std::move(receive_stream),
count_down_latch_callback));
task_runner_->PostTask(
FROM_HERE, base::BindOnce(&BluetoothSocket::CreateOutputStream,
base::Unretained(this), std::move(send_stream),
count_down_latch_callback));
latch.Await();
} }
void BluetoothSocket::CreateInputStream( void BluetoothSocket::CreateInputStream(
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
#include <string> #include <string>
#include "base/optional.h"
#include "chrome/services/sharing/nearby/platform_v2/bluetooth_device.h"
#include "device/bluetooth/public/mojom/adapter.mojom.h" #include "device/bluetooth/public/mojom/adapter.mojom.h"
#include "mojo/public/cpp/bindings/remote.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/api/bluetooth_classic.h"
...@@ -49,6 +51,10 @@ namespace chrome { ...@@ -49,6 +51,10 @@ namespace chrome {
// |task_runner_|) so that blocking on the calling thread will not deadlock. // |task_runner_|) so that blocking on the calling thread will not deadlock.
class BluetoothSocket : public api::BluetoothSocket { class BluetoothSocket : public api::BluetoothSocket {
public: public:
BluetoothSocket(bluetooth::mojom::DeviceInfoPtr device,
mojo::PendingRemote<bluetooth::mojom::Socket> socket,
mojo::ScopedDataPipeConsumerHandle receive_stream,
mojo::ScopedDataPipeProducerHandle send_stream);
BluetoothSocket(api::BluetoothDevice& remote_device, BluetoothSocket(api::BluetoothDevice& remote_device,
mojo::PendingRemote<bluetooth::mojom::Socket> socket, mojo::PendingRemote<bluetooth::mojom::Socket> socket,
mojo::ScopedDataPipeConsumerHandle receive_stream, mojo::ScopedDataPipeConsumerHandle receive_stream,
...@@ -65,6 +71,9 @@ class BluetoothSocket : public api::BluetoothSocket { ...@@ -65,6 +71,9 @@ class BluetoothSocket : public api::BluetoothSocket {
api::BluetoothDevice* GetRemoteDevice() override; api::BluetoothDevice* GetRemoteDevice() override;
private: private:
void InitializeStreams(mojo::ScopedDataPipeConsumerHandle receive_stream,
mojo::ScopedDataPipeProducerHandle send_stream);
// These methods must be run on |task_runner_|, because the // These methods must be run on |task_runner_|, because the
// mojo::SimpleWatcher members of |input_stream_| and |output_stream_| expect // mojo::SimpleWatcher members of |input_stream_| and |output_stream_| expect
// to be created on the same sequence they are later run on. See // to be created on the same sequence they are later run on. See
...@@ -76,7 +85,15 @@ class BluetoothSocket : public api::BluetoothSocket { ...@@ -76,7 +85,15 @@ class BluetoothSocket : public api::BluetoothSocket {
base::OnceClosure callback); base::OnceClosure callback);
void DestroyOutputStream(base::OnceClosure callback); void DestroyOutputStream(base::OnceClosure callback);
api::BluetoothDevice& remote_device_; // If this BluetoothSocket is created by connecting to a discovered device, a
// reference to that device will be provided to set |remote_device_ref_|, and
// |remote_device_| will be left unset.
// On the other hand, if this BluetoothSocket is created by an incoming
// connection, there is no previous owner of that device object, and therefore
// BluetoothSocket is expected to own it (within |remote_device_|). In this
// case, |remote_device_ref_| is a reference to |remote_device_|.
base::Optional<chrome::BluetoothDevice> remote_device_;
api::BluetoothDevice& remote_device_ref_;
// The public methods which are overridden by BluetoothSocket's subclasses // The public methods which are overridden by BluetoothSocket's subclasses
// InputStreamImpl and OutputStreamImpl are expected to block the caller // InputStreamImpl and OutputStreamImpl are expected to block the caller
......
...@@ -48,6 +48,18 @@ class FakeSocket : public mojom::Socket { ...@@ -48,6 +48,18 @@ class FakeSocket : public mojom::Socket {
mojo::ScopedDataPipeConsumerHandle send_stream_; mojo::ScopedDataPipeConsumerHandle send_stream_;
}; };
class FakeServerSocket : public mojom::ServerSocket {
public:
FakeServerSocket() = default;
~FakeServerSocket() override = default;
private:
// mojom::ServerSocket:
void Accept(AcceptCallback callback) override {
std::move(callback).Run(/*result=*/nullptr);
}
};
} // namespace } // namespace
FakeAdapter::FakeAdapter() = default; FakeAdapter::FakeAdapter() = default;
...@@ -146,6 +158,24 @@ void FakeAdapter::ConnectToServiceInsecurely( ...@@ -146,6 +158,24 @@ void FakeAdapter::ConnectToServiceInsecurely(
std::move(callback).Run(std::move(connect_to_service_result)); std::move(callback).Run(std::move(connect_to_service_result));
} }
void FakeAdapter::CreateRfcommService(const std::string& service_name,
const device::BluetoothUUID& service_uuid,
CreateRfcommServiceCallback callback) {
if (!base::Contains(allowed_connections_for_service_name_and_uuid_pair_,
std::make_pair(service_name, service_uuid))) {
std::move(callback).Run(/*server_socket=*/mojo::NullRemote());
return;
}
mojo::PendingRemote<mojom::ServerSocket> pending_server_socket;
mojo::MakeSelfOwnedReceiver(
std::make_unique<FakeServerSocket>(),
pending_server_socket.InitWithNewPipeAndPassReceiver());
std::move(callback).Run(std::move(pending_server_socket));
}
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;
} }
...@@ -177,6 +207,13 @@ void FakeAdapter::AllowConnectionForAddressAndUuidPair( ...@@ -177,6 +207,13 @@ void FakeAdapter::AllowConnectionForAddressAndUuidPair(
allowed_connections_for_address_and_uuid_pair_.emplace(address, service_uuid); allowed_connections_for_address_and_uuid_pair_.emplace(address, service_uuid);
} }
void FakeAdapter::AllowIncomingConnectionForServiceNameAndUuidPair(
const std::string& service_name,
const device::BluetoothUUID& service_uuid) {
allowed_connections_for_service_name_and_uuid_pair_.emplace(service_name,
service_uuid);
}
void FakeAdapter::OnDiscoverySessionDestroyed() { void FakeAdapter::OnDiscoverySessionDestroyed() {
DCHECK(discovery_session_); DCHECK(discovery_session_);
discovery_session_ = nullptr; discovery_session_ = nullptr;
......
...@@ -34,6 +34,9 @@ class FakeAdapter : public mojom::Adapter { ...@@ -34,6 +34,9 @@ class FakeAdapter : public mojom::Adapter {
const std::string& address, const std::string& address,
const device::BluetoothUUID& service_uuid, const device::BluetoothUUID& service_uuid,
ConnectToServiceInsecurelyCallback callback) override; ConnectToServiceInsecurelyCallback callback) override;
void CreateRfcommService(const std::string& service_name,
const device::BluetoothUUID& service_uuid,
CreateRfcommServiceCallback callback) override;
void SetShouldDiscoverySucceed(bool should_discovery_succeed); void SetShouldDiscoverySucceed(bool should_discovery_succeed);
void SetDiscoverySessionDestroyedCallback(base::OnceClosure callback); void SetDiscoverySessionDestroyedCallback(base::OnceClosure callback);
...@@ -44,6 +47,9 @@ class FakeAdapter : public mojom::Adapter { ...@@ -44,6 +47,9 @@ class FakeAdapter : public mojom::Adapter {
void AllowConnectionForAddressAndUuidPair( void AllowConnectionForAddressAndUuidPair(
const std::string& address, const std::string& address,
const device::BluetoothUUID& service_uuid); const device::BluetoothUUID& service_uuid);
void AllowIncomingConnectionForServiceNameAndUuidPair(
const std::string& service_name,
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";
...@@ -60,6 +66,8 @@ class FakeAdapter : public mojom::Adapter { ...@@ -60,6 +66,8 @@ class FakeAdapter : public mojom::Adapter {
base::OnceClosure on_discovery_session_destroyed_callback_; base::OnceClosure on_discovery_session_destroyed_callback_;
std::set<std::pair<std::string, device::BluetoothUUID>> std::set<std::pair<std::string, device::BluetoothUUID>>
allowed_connections_for_address_and_uuid_pair_; allowed_connections_for_address_and_uuid_pair_;
std::set<std::pair<std::string, device::BluetoothUUID>>
allowed_connections_for_service_name_and_uuid_pair_;
mojo::Remote<mojom::AdapterClient> client_; mojo::Remote<mojom::AdapterClient> client_;
}; };
......
...@@ -144,6 +144,10 @@ BluetoothInternalsTest.prototype = { ...@@ -144,6 +144,10 @@ BluetoothInternalsTest.prototype = {
return {result: null}; return {result: null};
} }
async createRfcommService(service_name, service_uuid) {
return {result: null};
}
setTestConnectResult(connectResult) { setTestConnectResult(connectResult) {
this.connectResult_ = connectResult; this.connectResult_ = connectResult;
} }
......
...@@ -41,6 +41,7 @@ test("device_unittests") { ...@@ -41,6 +41,7 @@ test("device_unittests") {
"bluetooth/bluetooth_task_manager_win_unittest.cc", "bluetooth/bluetooth_task_manager_win_unittest.cc",
"bluetooth/device_unittest.cc", "bluetooth/device_unittest.cc",
"bluetooth/public/cpp/bluetooth_uuid_unittest.cc", "bluetooth/public/cpp/bluetooth_uuid_unittest.cc",
"bluetooth/server_socket_unittest.cc",
"bluetooth/socket_unittest.cc", "bluetooth/socket_unittest.cc",
"bluetooth/string_util_icu_unittest.cc", "bluetooth/string_util_icu_unittest.cc",
"bluetooth/test/bluetooth_gatt_server_test.cc", "bluetooth/test/bluetooth_gatt_server_test.cc",
...@@ -101,6 +102,7 @@ test("device_unittests") { ...@@ -101,6 +102,7 @@ test("device_unittests") {
"//device/base/synchronization", "//device/base/synchronization",
"//device/bluetooth", "//device/bluetooth",
"//device/bluetooth:deprecated_experimental_mojo", "//device/bluetooth:deprecated_experimental_mojo",
"//device/bluetooth:fake_bluetooth",
"//device/bluetooth:mocks", "//device/bluetooth:mocks",
"//device/fido", "//device/fido",
"//device/fido:test_support", "//device/fido:test_support",
......
...@@ -40,6 +40,8 @@ source_set("deprecated_experimental_mojo") { ...@@ -40,6 +40,8 @@ source_set("deprecated_experimental_mojo") {
"device.h", "device.h",
"discovery_session.cc", "discovery_session.cc",
"discovery_session.h", "discovery_session.h",
"server_socket.cc",
"server_socket.h",
"socket.cc", "socket.cc",
"socket.h", "socket.h",
] ]
...@@ -70,6 +72,8 @@ source_set("fake_bluetooth") { ...@@ -70,6 +72,8 @@ source_set("fake_bluetooth") {
sources = [ sources = [
"test/fake_bluetooth.cc", "test/fake_bluetooth.cc",
"test/fake_bluetooth.h", "test/fake_bluetooth.h",
"test/fake_bluetooth_socket.cc",
"test/fake_bluetooth_socket.h",
"test/fake_central.cc", "test/fake_central.cc",
"test/fake_central.h", "test/fake_central.h",
"test/fake_peripheral.cc", "test/fake_peripheral.cc",
...@@ -89,6 +93,7 @@ source_set("fake_bluetooth") { ...@@ -89,6 +93,7 @@ source_set("fake_bluetooth") {
"//device/bluetooth/public/cpp", "//device/bluetooth/public/cpp",
"//device/bluetooth/public/mojom:fake_bluetooth_interfaces", "//device/bluetooth/public/mojom:fake_bluetooth_interfaces",
"//mojo/public/cpp/bindings", "//mojo/public/cpp/bindings",
"//net",
] ]
} }
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "device/bluetooth/discovery_session.h" #include "device/bluetooth/discovery_session.h"
#include "device/bluetooth/public/cpp/bluetooth_uuid.h" #include "device/bluetooth/public/cpp/bluetooth_uuid.h"
#include "device/bluetooth/public/mojom/connect_result_type_converter.h" #include "device/bluetooth/public/mojom/connect_result_type_converter.h"
#include "device/bluetooth/server_socket.h"
#include "device/bluetooth/socket.h" #include "device/bluetooth/socket.h"
#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"
...@@ -127,6 +128,21 @@ void Adapter::ConnectToServiceInsecurely( ...@@ -127,6 +128,21 @@ void Adapter::ConnectToServiceInsecurely(
weak_ptr_factory_.GetWeakPtr(), copyable_callback)); weak_ptr_factory_.GetWeakPtr(), copyable_callback));
} }
void Adapter::CreateRfcommService(const std::string& service_name,
const device::BluetoothUUID& service_uuid,
CreateRfcommServiceCallback callback) {
device::BluetoothAdapter::ServiceOptions service_options;
service_options.name = std::make_unique<std::string>(service_name);
auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback));
adapter_->CreateRfcommService(
service_uuid, service_options,
base::BindOnce(&Adapter::OnCreateRfcommService,
weak_ptr_factory_.GetWeakPtr(), copyable_callback),
base::BindOnce(&Adapter::OnCreateRfcommServiceError,
weak_ptr_factory_.GetWeakPtr(), copyable_callback));
}
void Adapter::AdapterPresentChanged(device::BluetoothAdapter* adapter, void Adapter::AdapterPresentChanged(device::BluetoothAdapter* adapter,
bool present) { bool present) {
if (client_) if (client_)
...@@ -248,7 +264,6 @@ void Adapter::OnConnectToService( ...@@ -248,7 +264,6 @@ void Adapter::OnConnectToService(
} }
mojo::PendingRemote<mojom::Socket> pending_socket; mojo::PendingRemote<mojom::Socket> pending_socket;
mojo::MakeSelfOwnedReceiver( mojo::MakeSelfOwnedReceiver(
std::make_unique<Socket>(std::move(socket), std::make_unique<Socket>(std::move(socket),
std::move(receive_pipe_producer_handle), std::move(receive_pipe_producer_handle),
...@@ -271,4 +286,20 @@ void Adapter::OnConnectToServiceError( ...@@ -271,4 +286,20 @@ void Adapter::OnConnectToServiceError(
std::move(callback).Run(/*result=*/nullptr); std::move(callback).Run(/*result=*/nullptr);
} }
void Adapter::OnCreateRfcommService(
CreateRfcommServiceCallback callback,
scoped_refptr<device::BluetoothSocket> socket) {
mojo::PendingRemote<mojom::ServerSocket> pending_server_socket;
mojo::MakeSelfOwnedReceiver(
std::make_unique<ServerSocket>(std::move(socket)),
pending_server_socket.InitWithNewPipeAndPassReceiver());
std::move(callback).Run(std::move(pending_server_socket));
}
void Adapter::OnCreateRfcommServiceError(CreateRfcommServiceCallback callback,
const std::string& message) {
LOG(ERROR) << "Failed to create service: '" << message << "'";
std::move(callback).Run(/*server_socket=*/mojo::NullRemote());
}
} // namespace bluetooth } // namespace bluetooth
...@@ -47,6 +47,9 @@ class Adapter : public mojom::Adapter, ...@@ -47,6 +47,9 @@ class Adapter : public mojom::Adapter,
const std::string& address, const std::string& address,
const device::BluetoothUUID& service_uuid, const device::BluetoothUUID& service_uuid,
ConnectToServiceInsecurelyCallback callback) override; ConnectToServiceInsecurelyCallback callback) override;
void CreateRfcommService(const std::string& service_name,
const device::BluetoothUUID& service_uuid,
CreateRfcommServiceCallback callback) override;
// device::BluetoothAdapter::Observer overrides: // device::BluetoothAdapter::Observer overrides:
void AdapterPresentChanged(device::BluetoothAdapter* adapter, void AdapterPresentChanged(device::BluetoothAdapter* adapter,
...@@ -87,6 +90,11 @@ class Adapter : public mojom::Adapter, ...@@ -87,6 +90,11 @@ class Adapter : public mojom::Adapter,
void OnConnectToServiceError(ConnectToServiceInsecurelyCallback callback, void OnConnectToServiceError(ConnectToServiceInsecurelyCallback callback,
const std::string& message); const std::string& message);
void OnCreateRfcommService(CreateRfcommServiceCallback callback,
scoped_refptr<device::BluetoothSocket> socket);
void OnCreateRfcommServiceError(CreateRfcommServiceCallback callback,
const std::string& message);
// The current Bluetooth adapter. // The current Bluetooth adapter.
scoped_refptr<device::BluetoothAdapter> adapter_; scoped_refptr<device::BluetoothAdapter> adapter_;
......
...@@ -29,6 +29,14 @@ struct ConnectToServiceResult { ...@@ -29,6 +29,14 @@ struct ConnectToServiceResult {
handle<data_pipe_producer> send_stream; handle<data_pipe_producer> send_stream;
}; };
// The results of a successful connection via ServerSocket::Accept().
struct AcceptConnectionResult {
DeviceInfo device;
pending_remote<Socket> socket;
handle<data_pipe_consumer> receive_stream;
handle<data_pipe_producer> send_stream;
};
struct AdapterInfo { struct AdapterInfo {
// TODO(crbug.com/1112886): Use fixed-size array, not string, for address. // TODO(crbug.com/1112886): Use fixed-size array, not string, for address.
string address; string address;
...@@ -82,6 +90,18 @@ interface Socket { ...@@ -82,6 +90,18 @@ interface Socket {
Disconnect() => (); Disconnect() => ();
}; };
// Represents a pending connecting from a remote device. Releasing it will
// stop listening for an incoming connection.
// Note: Methods which are declared [Sync] are for use by
// //chrome/services/sharing/nearby; all other usage of their synchronous
// signatures is strongly discouraged.
interface ServerSocket {
// Accept the next incoming connection from a remote device. If something
// goes wrong, the returned |result| will be null.
[Sync]
Accept() => (AcceptConnectionResult? result);
};
// Handles requests to either query Bluetooth adapter capabilities or state, or // Handles requests to either query Bluetooth adapter capabilities or state, or
// find or connect to remote devices. Backed by //device/bluetooth. // find or connect to remote devices. Backed by //device/bluetooth.
// Note: Methods which are declared [Sync] are for use by // Note: Methods which are declared [Sync] are for use by
...@@ -127,12 +147,21 @@ interface Adapter { ...@@ -127,12 +147,21 @@ interface Adapter {
// Attempts to initiate an insecure outgoing L2CAP or RFCOMM connection to the // Attempts to initiate an insecure outgoing L2CAP or RFCOMM connection to the
// advertised service on this device matching |service_uuid|. This method is // advertised service on this device matching |service_uuid|. This method is
// marked as "Insecurely" because the outgoing connection will not request // marked as "Insecurely" because the outgoing connection will not request
// bonding (pairing) to the remote device. All return values will be null if // bonding (pairing) to the remote device. If the connection attempt fails,
// the connection attempt fails. // the returned |result| will be null. See Socket for details on how to close
// the connection.
// TODO(crbug.com/1112886): Use fixed-size array, not string, for address. // TODO(crbug.com/1112886): Use fixed-size array, not string, for address.
[Sync] [Sync]
ConnectToServiceInsecurely(string address, UUID service_uuid) ConnectToServiceInsecurely(string address, UUID service_uuid)
=> (ConnectToServiceResult? result); => (ConnectToServiceResult? result);
// Creates an RFCOMM service on this adapter advertised with |service_name|
// and |service_uuid|. If the service creation attempt fails, the returned
// |server_socket| will be null. See ServerSocket for details on how to stop
// listening.
[Sync]
CreateRfcommService(string service_name, UUID service_uuid)
=> (pending_remote<ServerSocket>? server_socket);
}; };
interface AdapterClient { interface AdapterClient {
......
// 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 "device/bluetooth/server_socket.h"
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/memory/ptr_util.h"
#include "device/bluetooth/bluetooth_device.h"
#include "device/bluetooth/bluetooth_socket.h"
#include "device/bluetooth/device.h"
#include "device/bluetooth/socket.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "net/base/io_buffer.h"
namespace bluetooth {
ServerSocket::ServerSocket(
scoped_refptr<device::BluetoothSocket> bluetooth_socket)
: server_socket_(std::move(bluetooth_socket)) {}
ServerSocket::~ServerSocket() {
server_socket_->Close();
}
void ServerSocket::Accept(AcceptCallback callback) {
auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback));
server_socket_->Accept(
base::BindOnce(&ServerSocket::OnAccept, weak_ptr_factory_.GetWeakPtr(),
copyable_callback),
base::BindOnce(&ServerSocket::OnAcceptError,
weak_ptr_factory_.GetWeakPtr(), copyable_callback));
}
void ServerSocket::OnAccept(
AcceptCallback callback,
const device::BluetoothDevice* device,
scoped_refptr<device::BluetoothSocket> bluetooth_socket) {
mojo::ScopedDataPipeProducerHandle receive_pipe_producer_handle;
mojo::ScopedDataPipeConsumerHandle receive_pipe_consumer_handle;
MojoResult result =
mojo::CreateDataPipe(/*options=*/nullptr, &receive_pipe_producer_handle,
&receive_pipe_consumer_handle);
if (result != MOJO_RESULT_OK) {
bluetooth_socket->Close();
OnAcceptError(std::move(callback), "Failed to create receiving DataPipe.");
return;
}
mojo::ScopedDataPipeProducerHandle send_pipe_producer_handle;
mojo::ScopedDataPipeConsumerHandle send_pipe_consumer_handle;
result = mojo::CreateDataPipe(/*options=*/nullptr, &send_pipe_producer_handle,
&send_pipe_consumer_handle);
if (result != MOJO_RESULT_OK) {
bluetooth_socket->Close();
OnAcceptError(std::move(callback), "Failed to create sending DataPipe.");
return;
}
mojo::PendingRemote<mojom::Socket> pending_socket;
mojo::MakeSelfOwnedReceiver(
std::make_unique<Socket>(std::move(bluetooth_socket),
std::move(receive_pipe_producer_handle),
std::move(send_pipe_consumer_handle)),
pending_socket.InitWithNewPipeAndPassReceiver());
mojom::AcceptConnectionResultPtr accept_connection_result =
mojom::AcceptConnectionResult::New();
accept_connection_result->device = Device::ConstructDeviceInfoStruct(device);
accept_connection_result->socket = std::move(pending_socket);
accept_connection_result->receive_stream =
std::move(receive_pipe_consumer_handle);
accept_connection_result->send_stream = std::move(send_pipe_producer_handle);
std::move(callback).Run(std::move(accept_connection_result));
}
void ServerSocket::OnAcceptError(AcceptCallback callback,
const std::string& error_message) {
LOG(ERROR) << "Failed to accept incoming connection: " << error_message;
std::move(callback).Run(/*result=*/nullptr);
}
} // namespace bluetooth
// 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 DEVICE_BLUETOOTH_SERVER_SOCKET_H_
#define DEVICE_BLUETOOTH_SERVER_SOCKET_H_
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "device/bluetooth/public/mojom/adapter.mojom.h"
namespace device {
class BluetoothDevice;
class BluetoothSocket;
} // namespace device
namespace bluetooth {
// Implementation of Mojo ServerSocket in
// device/bluetooth/public/mojom/adapter.mojom.
// It handles requests to accept incoming connections from remote devices,
// returning a Socket.
// Uses the platform abstraction of //device/bluetooth.
// An instance of this class is constructed by Adapter. When the instance is
// destroyed, the underlying BluetoothSocket is destroyed.
class ServerSocket : public mojom::ServerSocket {
public:
explicit ServerSocket(
scoped_refptr<device::BluetoothSocket> bluetooth_socket);
~ServerSocket() override;
ServerSocket(const ServerSocket&) = delete;
ServerSocket& operator=(const ServerSocket&) = delete;
// mojom::ServerSocket:
void Accept(AcceptCallback callback) override;
private:
void OnAccept(AcceptCallback callback,
const device::BluetoothDevice* device,
scoped_refptr<device::BluetoothSocket> socket);
void OnAcceptError(AcceptCallback callback, const std::string& error_message);
scoped_refptr<device::BluetoothSocket> server_socket_;
base::WeakPtrFactory<ServerSocket> weak_ptr_factory_{this};
};
} // namespace bluetooth
#endif // DEVICE_BLUETOOTH_SERVER_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 "device/bluetooth/server_socket.h"
#include <memory>
#include <tuple>
#include <vector>
#include "base/callback_helpers.h"
#include "base/location.h"
#include "base/optional.h"
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "device/bluetooth/bluetooth_socket.h"
#include "device/bluetooth/socket.h"
#include "device/bluetooth/test/fake_bluetooth_socket.h"
#include "device/bluetooth/test/mock_bluetooth_adapter.h"
#include "device/bluetooth/test/mock_bluetooth_device.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/io_buffer.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace bluetooth {
class ServerSocketTest : public testing::Test {
public:
ServerSocketTest() = default;
~ServerSocketTest() override = default;
ServerSocketTest(const ServerSocketTest&) = delete;
ServerSocketTest& operator=(const ServerSocketTest&) = delete;
void SetUp() override {
mock_bluetooth_adapter_ =
base::MakeRefCounted<testing::NiceMock<device::MockBluetoothAdapter>>();
mock_bluetooth_device_ =
std::make_unique<testing::NiceMock<device::MockBluetoothDevice>>(
mock_bluetooth_adapter_.get(),
/*class=*/0, "DeviceName", "DeviceAddress",
/*paired=*/false,
/*connected=*/false);
fake_bluetooth_server_socket_ =
base::MakeRefCounted<device::FakeBluetoothSocket>();
server_socket_ =
std::make_unique<ServerSocket>(fake_bluetooth_server_socket_);
}
protected:
void Accept() {
server_socket_->Accept(
base::BindOnce(&ServerSocketTest::OnAccept, base::Unretained(this)));
EXPECT_TRUE(fake_bluetooth_server_socket_->HasAcceptArgs());
}
std::unique_ptr<ServerSocket> server_socket_;
scoped_refptr<device::FakeBluetoothSocket> fake_bluetooth_server_socket_;
scoped_refptr<testing::NiceMock<device::MockBluetoothAdapter>>
mock_bluetooth_adapter_;
std::unique_ptr<testing::NiceMock<device::MockBluetoothDevice>>
mock_bluetooth_device_;
mojom::AcceptConnectionResultPtr accept_connection_result_;
private:
void OnAccept(mojom::AcceptConnectionResultPtr result) {
accept_connection_result_ = std::move(result);
}
base::test::SingleThreadTaskEnvironment task_environment;
};
TEST_F(ServerSocketTest, TestOnDestroyCallsClose) {
// When destroyed, |server_socket_| is expected to tear down its
// BluetoothSocket.
server_socket_.reset();
EXPECT_TRUE(fake_bluetooth_server_socket_->called_close());
}
TEST_F(ServerSocketTest, TestAccept_Success) {
Accept();
auto accept_args = fake_bluetooth_server_socket_->TakeAcceptArgs();
auto success_callback = std::move(std::get<0>(*accept_args));
auto fake_bluetooth_client_socket =
base::MakeRefCounted<device::FakeBluetoothSocket>();
std::move(success_callback)
.Run(/*device=*/mock_bluetooth_device_.get(),
/*bluetooth_socket=*/fake_bluetooth_client_socket);
EXPECT_TRUE(accept_connection_result_);
EXPECT_EQ(mock_bluetooth_device_->GetName(),
accept_connection_result_->device->name);
auto pending_socket = std::move(accept_connection_result_->socket);
EXPECT_TRUE(pending_socket.is_valid());
EXPECT_TRUE(accept_connection_result_->receive_stream.is_valid());
EXPECT_TRUE(accept_connection_result_->send_stream.is_valid());
// Ensure that the underlying BluetoothSocket is
// |fake_bluetooth_client_socket|.
mojo::Remote<mojom::Socket> socket(std::move(pending_socket));
base::RunLoop run_loop;
socket->Disconnect(run_loop.QuitClosure());
run_loop.Run();
EXPECT_TRUE(fake_bluetooth_client_socket->called_disconnect());
EXPECT_FALSE(fake_bluetooth_server_socket_->HasAcceptArgs());
}
TEST_F(ServerSocketTest, TestAccept_Error) {
Accept();
auto accept_args = fake_bluetooth_server_socket_->TakeAcceptArgs();
auto error_callback = std::move(std::get<1>(*accept_args));
std::move(error_callback).Run("ErrorMessage");
EXPECT_FALSE(accept_connection_result_);
EXPECT_FALSE(fake_bluetooth_server_socket_->HasAcceptArgs());
}
} // namespace bluetooth
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include "base/test/gmock_callback_support.h" #include "base/test/gmock_callback_support.h"
#include "base/test/task_environment.h" #include "base/test/task_environment.h"
#include "device/bluetooth/bluetooth_socket.h" #include "device/bluetooth/bluetooth_socket.h"
#include "device/bluetooth/test/fake_bluetooth_socket.h"
#include "mojo/public/cpp/system/simple_watcher.h" #include "mojo/public/cpp/system/simple_watcher.h"
#include "net/base/io_buffer.h" #include "net/base/io_buffer.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
...@@ -21,74 +22,6 @@ ...@@ -21,74 +22,6 @@
namespace bluetooth { namespace bluetooth {
namespace {
class FakeBluetoothSocket : public device::BluetoothSocket {
public:
using ReceiveArgs = std::
tuple<int, ReceiveCompletionCallback, ReceiveErrorCompletionCallback>;
using SendArgs = std::tuple<scoped_refptr<net::IOBuffer>,
int,
SendCompletionCallback,
ErrorCompletionCallback>;
FakeBluetoothSocket() = default;
FakeBluetoothSocket(const FakeBluetoothSocket&) = delete;
FakeBluetoothSocket& operator=(const FakeBluetoothSocket&) = delete;
// device::BluetoothSocket:
void Close() override { called_close_ = true; }
void Disconnect(base::OnceClosure success_callback) override {
called_disconnect_ = true;
std::move(success_callback).Run();
}
void Receive(int buffer_size,
ReceiveCompletionCallback success_callback,
ReceiveErrorCompletionCallback error_callback) override {
EXPECT_FALSE(receive_args_);
receive_args_ = std::make_unique<ReceiveArgs>(
buffer_size, std::move(success_callback), std::move(error_callback));
}
void Send(scoped_refptr<net::IOBuffer> buffer,
int buffer_size,
SendCompletionCallback success_callback,
ErrorCompletionCallback error_callback) override {
EXPECT_FALSE(send_args_);
send_args_ = std::make_unique<SendArgs>(std::move(buffer), buffer_size,
std::move(success_callback),
std::move(error_callback));
}
void Accept(AcceptCompletionCallback success_callback,
ErrorCompletionCallback error_callback) override {
// TODO(hansberry): To be implemented in a subsequent CL.
NOTIMPLEMENTED();
}
bool called_close() { return called_close_; }
bool called_disconnect() { return called_disconnect_; }
bool HasReceiveArgs() { return receive_args_.get(); }
bool HasSendArgs() { return send_args_.get(); }
std::unique_ptr<ReceiveArgs> TakeReceiveArgs() {
return std::move(receive_args_);
}
std::unique_ptr<SendArgs> TakeSendArgs() { return std::move(send_args_); }
protected:
~FakeBluetoothSocket() override = default;
private:
bool called_close_ = false;
bool called_disconnect_ = false;
std::unique_ptr<ReceiveArgs> receive_args_;
std::unique_ptr<SendArgs> send_args_;
};
} // namespace
class SocketTest : public testing::Test { class SocketTest : public testing::Test {
public: public:
SocketTest() = default; SocketTest() = default;
...@@ -113,7 +46,8 @@ class SocketTest : public testing::Test { ...@@ -113,7 +46,8 @@ class SocketTest : public testing::Test {
receive_stream_ = std::move(receive_pipe_consumer_handle); receive_stream_ = std::move(receive_pipe_consumer_handle);
send_stream_ = std::move(send_pipe_producer_handle); send_stream_ = std::move(send_pipe_producer_handle);
fake_bluetooth_socket_ = base::MakeRefCounted<FakeBluetoothSocket>(); fake_bluetooth_socket_ =
base::MakeRefCounted<device::FakeBluetoothSocket>();
socket_ = std::make_unique<Socket>(fake_bluetooth_socket_, socket_ = std::make_unique<Socket>(fake_bluetooth_socket_,
std::move(receive_pipe_producer_handle), std::move(receive_pipe_producer_handle),
std::move(send_pipe_consumer_handle)); std::move(send_pipe_consumer_handle));
...@@ -216,7 +150,7 @@ class SocketTest : public testing::Test { ...@@ -216,7 +150,7 @@ class SocketTest : public testing::Test {
} }
protected: protected:
scoped_refptr<FakeBluetoothSocket> fake_bluetooth_socket_; scoped_refptr<device::FakeBluetoothSocket> fake_bluetooth_socket_;
mojo::ScopedDataPipeConsumerHandle receive_stream_; mojo::ScopedDataPipeConsumerHandle receive_stream_;
mojo::ScopedDataPipeProducerHandle send_stream_; mojo::ScopedDataPipeProducerHandle send_stream_;
std::unique_ptr<Socket> socket_; std::unique_ptr<Socket> socket_;
......
// 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 "device/bluetooth/test/fake_bluetooth_socket.h"
namespace device {
FakeBluetoothSocket::FakeBluetoothSocket() = default;
FakeBluetoothSocket::~FakeBluetoothSocket() = default;
void FakeBluetoothSocket::Close() {
called_close_ = true;
}
void FakeBluetoothSocket::Disconnect(base::OnceClosure success_callback) {
called_disconnect_ = true;
std::move(success_callback).Run();
}
void FakeBluetoothSocket::Receive(
int buffer_size,
ReceiveCompletionCallback success_callback,
ReceiveErrorCompletionCallback error_callback) {
DCHECK(!receive_args_);
receive_args_ = std::make_unique<ReceiveArgs>(
buffer_size, std::move(success_callback), std::move(error_callback));
}
void FakeBluetoothSocket::Send(scoped_refptr<net::IOBuffer> buffer,
int buffer_size,
SendCompletionCallback success_callback,
ErrorCompletionCallback error_callback) {
DCHECK(!send_args_);
send_args_ = std::make_unique<SendArgs>(std::move(buffer), buffer_size,
std::move(success_callback),
std::move(error_callback));
}
void FakeBluetoothSocket::Accept(AcceptCompletionCallback success_callback,
ErrorCompletionCallback error_callback) {
DCHECK(!accept_args_);
accept_args_ = std::make_unique<AcceptArgs>(std::move(success_callback),
std::move(error_callback));
}
} // namespace device
// 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 DEVICE_BLUETOOTH_TEST_FAKE_BLUETOOTH_SOCKET_H_
#define DEVICE_BLUETOOTH_TEST_FAKE_BLUETOOTH_SOCKET_H_
#include <string>
#include "device/bluetooth/bluetooth_socket.h"
#include "device/bluetooth/public/cpp/bluetooth_uuid.h"
#include "net/base/io_buffer.h"
namespace device {
class FakeBluetoothSocket : public BluetoothSocket {
public:
using ReceiveArgs = std::
tuple<int, ReceiveCompletionCallback, ReceiveErrorCompletionCallback>;
using SendArgs = std::tuple<scoped_refptr<net::IOBuffer>,
int,
SendCompletionCallback,
ErrorCompletionCallback>;
using AcceptArgs =
std::tuple<AcceptCompletionCallback, ErrorCompletionCallback>;
FakeBluetoothSocket();
FakeBluetoothSocket(const FakeBluetoothSocket&) = delete;
FakeBluetoothSocket& operator=(const FakeBluetoothSocket&) = delete;
// BluetoothSocket:
void Close() override;
void Disconnect(base::OnceClosure success_callback) override;
void Receive(int buffer_size,
ReceiveCompletionCallback success_callback,
ReceiveErrorCompletionCallback error_callback) override;
void Send(scoped_refptr<net::IOBuffer> buffer,
int buffer_size,
SendCompletionCallback success_callback,
ErrorCompletionCallback error_callback) override;
void Accept(AcceptCompletionCallback success_callback,
ErrorCompletionCallback error_callback) override;
bool called_close() { return called_close_; }
bool called_disconnect() { return called_disconnect_; }
bool HasReceiveArgs() { return receive_args_.get(); }
bool HasSendArgs() { return send_args_.get(); }
bool HasAcceptArgs() { return accept_args_.get(); }
std::unique_ptr<ReceiveArgs> TakeReceiveArgs() {
return std::move(receive_args_);
}
std::unique_ptr<SendArgs> TakeSendArgs() { return std::move(send_args_); }
std::unique_ptr<AcceptArgs> TakeAcceptArgs() {
return std::move(accept_args_);
}
protected:
~FakeBluetoothSocket() override;
private:
bool called_close_ = false;
bool called_disconnect_ = false;
std::unique_ptr<ReceiveArgs> receive_args_;
std::unique_ptr<SendArgs> send_args_;
std::unique_ptr<AcceptArgs> accept_args_;
};
} // namespace device
#endif // DEVICE_BLUETOOTH_TEST_FAKE_BLUETOOTH_SOCKET_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment