Commit fb6ed9e6 authored by Kyle Horimoto's avatar Kyle Horimoto Committed by Commit Bot

[CrOS PhoneHub] Wait for disconnection event before invoking callback

Previously, we'd just call DisconnectFromEndpoint() and invoke the
callback immediately. This CL adds a "disconnecting" state which waits
for the OnDisconnected() callback to be called. This works around a race
condition in the Nearby Connections library during shutdown.

Because we're now waiting for an event to be called, this CL also adds
timeouts for each step of this flow.

This CL also tweaks the log level for a few logs to help with
debugging.

Bug: 1152609
Change-Id: Ib23c606e4658f5ad1f5fbf013891d80888683530
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2561469Reviewed-by: default avatarJames Vecore <vecore@google.com>
Commit-Queue: Kyle Horimoto <khorimoto@chromium.org>
Cr-Commit-Position: refs/heads/master@{#831160}
parent 81e85b20
......@@ -21,7 +21,7 @@ class FakeNearbyConnectionBroker : public NearbyConnectionBroker {
~FakeNearbyConnectionBroker() override;
using NearbyConnectionBroker::bluetooth_public_address;
using NearbyConnectionBroker::Disconnect;
using NearbyConnectionBroker::InvokeDisconnectedCallback;
using NearbyConnectionBroker::NotifyConnected;
using NearbyConnectionBroker::NotifyMessageReceived;
......
......@@ -6,6 +6,8 @@
#include "base/bind.h"
#include "base/check.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
namespace chromeos {
namespace secure_channel {
......@@ -22,18 +24,16 @@ NearbyConnectionBroker::NearbyConnectionBroker(
on_connected_callback_(std::move(on_connected_callback)),
on_disconnected_callback_(std::move(on_disconnected_callback)) {
message_sender_receiver_.set_disconnect_handler(base::BindOnce(
&NearbyConnectionBroker::Disconnect, base::Unretained(this)));
&NearbyConnectionBroker::OnMojoDisconnection, base::Unretained(this)));
message_receiver_remote_.set_disconnect_handler(base::BindOnce(
&NearbyConnectionBroker::Disconnect, base::Unretained(this)));
&NearbyConnectionBroker::OnMojoDisconnection, base::Unretained(this)));
}
NearbyConnectionBroker::~NearbyConnectionBroker() = default;
void NearbyConnectionBroker::Disconnect() {
void NearbyConnectionBroker::InvokeDisconnectedCallback() {
message_sender_receiver_.reset();
message_receiver_remote_.reset();
if (on_disconnected_callback_)
std::move(on_disconnected_callback_).Run();
}
......
......@@ -42,7 +42,11 @@ class NearbyConnectionBroker : public mojom::NearbyMessageSender {
return bluetooth_public_address_;
}
void Disconnect();
// Can be overridden by derived classes to handle MessageSender and
// MessageReceiver Mojo pipes being disconnected.
virtual void OnMojoDisconnection() {}
void InvokeDisconnectedCallback();
void NotifyConnected();
void NotifyMessageReceived(const std::string& received_message);
......
......@@ -15,6 +15,9 @@ namespace {
NearbyConnectionBrokerImpl::Factory* g_test_factory = nullptr;
constexpr base::TimeDelta kConnectionStatusChangeTimeout =
base::TimeDelta::FromSeconds(10);
using location::nearby::connections::mojom::BytesPayload;
using location::nearby::connections::mojom::ConnectionInfoPtr;
using location::nearby::connections::mojom::ConnectionOptions;
......@@ -28,14 +31,6 @@ using location::nearby::connections::mojom::PayloadPtr;
using location::nearby::connections::mojom::PayloadTransferUpdatePtr;
using location::nearby::connections::mojom::Status;
void OnDisconnectFromEndpointResult(const std::string& endpoint_id,
Status status) {
if (status != Status::kSuccess) {
PA_LOG(WARNING) << "Failed to disconnect from endpoint with ID "
<< endpoint_id;
}
}
} // namespace
// static
......@@ -47,20 +42,21 @@ NearbyConnectionBrokerImpl::Factory::Create(
mojo::PendingRemote<mojom::NearbyMessageReceiver> message_receiver_remote,
const mojo::SharedRemote<NearbyConnections>& nearby_connections,
base::OnceClosure on_connected_callback,
base::OnceClosure on_disconnected_callback) {
base::OnceClosure on_disconnected_callback,
std::unique_ptr<base::OneShotTimer> timer) {
if (g_test_factory) {
return g_test_factory->CreateInstance(
bluetooth_public_address, endpoint_finder,
std::move(message_sender_receiver), std::move(message_receiver_remote),
nearby_connections, std::move(on_connected_callback),
std::move(on_disconnected_callback));
std::move(on_disconnected_callback), std::move(timer));
}
return base::WrapUnique(new NearbyConnectionBrokerImpl(
bluetooth_public_address, endpoint_finder,
std::move(message_sender_receiver), std::move(message_receiver_remote),
nearby_connections, std::move(on_connected_callback),
std::move(on_disconnected_callback)));
std::move(on_disconnected_callback), std::move(timer)));
}
// static
......@@ -76,14 +72,16 @@ NearbyConnectionBrokerImpl::NearbyConnectionBrokerImpl(
mojo::PendingRemote<mojom::NearbyMessageReceiver> message_receiver_remote,
const mojo::SharedRemote<NearbyConnections>& nearby_connections,
base::OnceClosure on_connected_callback,
base::OnceClosure on_disconnected_callback)
base::OnceClosure on_disconnected_callback,
std::unique_ptr<base::OneShotTimer> timer)
: NearbyConnectionBroker(bluetooth_public_address,
std::move(message_sender_receiver),
std::move(message_receiver_remote),
std::move(on_connected_callback),
std::move(on_disconnected_callback)),
endpoint_finder_(endpoint_finder),
nearby_connections_(nearby_connections) {
nearby_connections_(nearby_connections),
timer_(std::move(timer)) {
TransitionToStatus(ConnectionStatus::kDiscoveringEndpoint);
endpoint_finder_->FindEndpoint(
bluetooth_public_address,
......@@ -93,27 +91,55 @@ NearbyConnectionBrokerImpl::NearbyConnectionBrokerImpl(
base::Unretained(this)));
}
NearbyConnectionBrokerImpl::~NearbyConnectionBrokerImpl() {
if (is_connection_active_) {
DCHECK(!remote_endpoint_id_.empty());
PA_LOG(VERBOSE) << "Disconnecting from endpoint with ID "
<< remote_endpoint_id_;
nearby_connections_->DisconnectFromEndpoint(
mojom::kServiceId, remote_endpoint_id_,
base::BindOnce(&OnDisconnectFromEndpointResult, remote_endpoint_id_));
}
}
NearbyConnectionBrokerImpl::~NearbyConnectionBrokerImpl() = default;
void NearbyConnectionBrokerImpl::TransitionToStatus(
ConnectionStatus connection_status) {
PA_LOG(VERBOSE) << "Nearby Connection status: " << connection_status_
<< " => " << connection_status;
PA_LOG(INFO) << "Nearby Connection status: " << connection_status_ << " => "
<< connection_status;
connection_status_ = connection_status;
timer_->Stop();
// The connected and disconnected states do not expect any further state
// changes.
if (connection_status_ == ConnectionStatus::kConnected ||
connection_status_ == ConnectionStatus::kDisconnected) {
return;
}
// If the state does not change within |kConnectionStatusChangeTimeout|, time
// out and give up on the connection.
timer_->Start(
FROM_HERE, kConnectionStatusChangeTimeout,
base::BindOnce(
&NearbyConnectionBrokerImpl::OnConnectionStatusChangeTimeout,
weak_ptr_factory_.GetWeakPtr()));
}
void NearbyConnectionBrokerImpl::Disconnect() {
if (!need_to_disconnect_endpoint_) {
TransitionToDisconnectedAndInvokeCallback();
return;
}
if (connection_status_ == ConnectionStatus::kDisconnecting)
return;
TransitionToStatus(ConnectionStatus::kDisconnecting);
nearby_connections_->DisconnectFromEndpoint(
mojom::kServiceId, remote_endpoint_id_,
base::BindOnce(
&NearbyConnectionBrokerImpl::OnDisconnectFromEndpointResult,
weak_ptr_factory_.GetWeakPtr()));
}
void NearbyConnectionBrokerImpl::TransitionToDisconnected() {
void NearbyConnectionBrokerImpl::TransitionToDisconnectedAndInvokeCallback() {
if (connection_status_ == ConnectionStatus::kDisconnected)
return;
TransitionToStatus(ConnectionStatus::kDisconnected);
Disconnect();
InvokeDisconnectedCallback();
}
void NearbyConnectionBrokerImpl::OnEndpointDiscovered(
......@@ -139,7 +165,7 @@ void NearbyConnectionBrokerImpl::OnEndpointDiscovered(
void NearbyConnectionBrokerImpl::OnDiscoveryFailure() {
DCHECK_EQ(ConnectionStatus::kDiscoveringEndpoint, connection_status_);
TransitionToDisconnected();
Disconnect();
}
void NearbyConnectionBrokerImpl::OnRequestConnectionResult(Status status) {
......@@ -149,7 +175,7 @@ void NearbyConnectionBrokerImpl::OnRequestConnectionResult(Status status) {
return;
PA_LOG(WARNING) << "RequestConnection() failed: " << status;
TransitionToDisconnected();
Disconnect();
}
void NearbyConnectionBrokerImpl::OnAcceptConnectionResult(Status status) {
......@@ -161,7 +187,7 @@ void NearbyConnectionBrokerImpl::OnAcceptConnectionResult(Status status) {
}
PA_LOG(WARNING) << "AcceptConnection() failed: " << status;
TransitionToDisconnected();
Disconnect();
}
void NearbyConnectionBrokerImpl::OnSendPayloadResult(
......@@ -174,7 +200,40 @@ void NearbyConnectionBrokerImpl::OnSendPayloadResult(
return;
PA_LOG(WARNING) << "OnSendPayloadResult() failed: " << status;
TransitionToDisconnected();
Disconnect();
}
void NearbyConnectionBrokerImpl::OnDisconnectFromEndpointResult(Status status) {
// If the disconnection was successful, wait for the OnDisconnected()
// callback.
if (status == Status::kSuccess)
return;
PA_LOG(WARNING) << "Failed to disconnect from endpoint with ID "
<< remote_endpoint_id_ << ": " << status;
need_to_disconnect_endpoint_ = false;
Disconnect();
}
void NearbyConnectionBrokerImpl::OnConnectionStatusChangeTimeout() {
if (connection_status_ == ConnectionStatus::kDisconnecting) {
PA_LOG(WARNING) << "Timeout disconnecting from endpoint";
TransitionToDisconnectedAndInvokeCallback();
return;
}
// If there is a timeout requesting a connection, we should still try to
// disconnect from the endpoint in case the endpoint was almost about to be
// connected before the timeout occurred.
if (connection_status_ == ConnectionStatus::kRequestingConnection)
need_to_disconnect_endpoint_ = true;
PA_LOG(WARNING) << "Timeout changing connection status";
Disconnect();
}
void NearbyConnectionBrokerImpl::OnMojoDisconnection() {
Disconnect();
}
void NearbyConnectionBrokerImpl::SendMessage(const std::string& message,
......@@ -214,7 +273,7 @@ void NearbyConnectionBrokerImpl::OnConnectionInitiated(
DCHECK_EQ(ConnectionStatus::kRequestingConnection, connection_status_);
TransitionToStatus(ConnectionStatus::kAcceptingConnection);
is_connection_active_ = true;
need_to_disconnect_endpoint_ = true;
nearby_connections_->AcceptConnection(
mojom::kServiceId, remote_endpoint_id_,
......@@ -248,7 +307,7 @@ void NearbyConnectionBrokerImpl::OnConnectionRejected(
}
PA_LOG(WARNING) << "Connection rejected: " << status;
TransitionToDisconnected();
Disconnect();
}
void NearbyConnectionBrokerImpl::OnDisconnected(
......@@ -259,9 +318,11 @@ void NearbyConnectionBrokerImpl::OnDisconnected(
return;
}
PA_LOG(WARNING) << "Connection disconnected";
is_connection_active_ = false;
TransitionToDisconnected();
if (connection_status_ != ConnectionStatus::kDisconnecting) {
PA_LOG(WARNING) << "Connection disconnected unexpectedly";
}
need_to_disconnect_endpoint_ = false;
Disconnect();
}
void NearbyConnectionBrokerImpl::OnBandwidthChanged(
......@@ -273,7 +334,7 @@ void NearbyConnectionBrokerImpl::OnBandwidthChanged(
return;
}
PA_LOG(VERBOSE) << "Bandwidth changed: " << medium;
PA_LOG(INFO) << "Bandwidth changed: " << medium;
}
void NearbyConnectionBrokerImpl::OnPayloadReceived(
......@@ -288,7 +349,7 @@ void NearbyConnectionBrokerImpl::OnPayloadReceived(
if (!payload->content->is_bytes()) {
PA_LOG(WARNING) << "OnPayloadReceived(): Received unexpected payload type "
<< "(was expecting bytes type). Disconnecting.";
TransitionToDisconnected();
Disconnect();
return;
}
......@@ -322,6 +383,9 @@ std::ostream& operator<<(std::ostream& stream,
case NearbyConnectionBrokerImpl::ConnectionStatus::kConnected:
stream << "[Connected]";
break;
case NearbyConnectionBrokerImpl::ConnectionStatus::kDisconnecting:
stream << "[Disconnecting]";
break;
case NearbyConnectionBrokerImpl::ConnectionStatus::kDisconnected:
stream << "[Disconnected]";
break;
......
......@@ -8,7 +8,9 @@
#include <memory>
#include <ostream>
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/timer/timer.h"
#include "chrome/browser/chromeos/secure_channel/nearby_connection_broker.h"
#include "chromeos/services/nearby/public/mojom/nearby_connections.mojom.h"
#include "mojo/public/cpp/bindings/shared_remote.h"
......@@ -28,8 +30,6 @@ class NearbyEndpointFinder;
//
// Deleting an instance of this class tears down any active connection and
// performs cleanup if necessary.
//
// TODO(khorimoto): Add the ability to upgrade bandwidth to WebRTC.
class NearbyConnectionBrokerImpl
: public NearbyConnectionBroker,
public location::nearby::connections::mojom::ConnectionLifecycleListener,
......@@ -48,7 +48,9 @@ class NearbyConnectionBrokerImpl
location::nearby::connections::mojom::NearbyConnections>&
nearby_connections,
base::OnceClosure on_connected_callback,
base::OnceClosure on_disconnected_callback);
base::OnceClosure on_disconnected_callback,
std::unique_ptr<base::OneShotTimer> timer =
std::make_unique<base::OneShotTimer>());
static void SetFactoryForTesting(Factory* test_factory);
virtual ~Factory() = default;
......@@ -65,7 +67,8 @@ class NearbyConnectionBrokerImpl
location::nearby::connections::mojom::NearbyConnections>&
nearby_connections,
base::OnceClosure on_connected_callback,
base::OnceClosure on_disconnected_callback) = 0;
base::OnceClosure on_disconnected_callback,
std::unique_ptr<base::OneShotTimer> timer) = 0;
};
~NearbyConnectionBrokerImpl() override;
......@@ -78,6 +81,7 @@ class NearbyConnectionBrokerImpl
kAcceptingConnection,
kWaitingForConnectionToBeAcceptedByRemoteDevice,
kConnected,
kDisconnecting,
kDisconnected,
};
friend std::ostream& operator<<(
......@@ -93,10 +97,12 @@ class NearbyConnectionBrokerImpl
location::nearby::connections::mojom::NearbyConnections>&
nearby_connections,
base::OnceClosure on_connected_callback,
base::OnceClosure on_disconnected_callback);
base::OnceClosure on_disconnected_callback,
std::unique_ptr<base::OneShotTimer> timer);
void TransitionToStatus(ConnectionStatus connection_status);
void TransitionToDisconnected();
void Disconnect();
void TransitionToDisconnectedAndInvokeCallback();
void OnEndpointDiscovered(
const std::string& endpoint_id,
......@@ -109,6 +115,12 @@ class NearbyConnectionBrokerImpl
location::nearby::connections::mojom::Status status);
void OnSendPayloadResult(SendMessageCallback callback,
location::nearby::connections::mojom::Status status);
void OnDisconnectFromEndpointResult(
location::nearby::connections::mojom::Status status);
void OnConnectionStatusChangeTimeout();
// NearbyConnectionBroker:
void OnMojoDisconnection() override;
// mojom::NearbyMessageSender:
void SendMessage(const std::string& message,
......@@ -141,6 +153,7 @@ class NearbyConnectionBrokerImpl
NearbyEndpointFinder* endpoint_finder_;
mojo::SharedRemote<location::nearby::connections::mojom::NearbyConnections>
nearby_connections_;
std::unique_ptr<base::OneShotTimer> timer_;
mojo::Receiver<
location::nearby::connections::mojom::ConnectionLifecycleListener>
......@@ -155,7 +168,7 @@ class NearbyConnectionBrokerImpl
// Starts as false; set to true in OnConnectionInitiated() and back to false
// in OnDisconnected().
bool is_connection_active_ = false;
bool need_to_disconnect_endpoint_ = false;
base::WeakPtrFactory<NearbyConnectionBrokerImpl> weak_ptr_factory_{this};
};
......
......@@ -12,6 +12,7 @@
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
#include "base/timer/mock_timer.h"
#include "chrome/browser/chromeos/secure_channel/fake_nearby_endpoint_finder.h"
#include "chromeos/services/nearby/public/cpp/mock_nearby_connections.h"
#include "chromeos/services/secure_channel/public/mojom/nearby_connector.mojom.h"
......@@ -63,6 +64,9 @@ class NearbyConnectionBrokerImplTest : public testing::Test,
// testing::Test:
void SetUp() override {
auto mock_timer = std::make_unique<base::MockOneShotTimer>();
mock_timer_ = mock_timer.get();
broker_ = NearbyConnectionBrokerImpl::Factory::Create(
GetBluetoothAddress(), &fake_endpoint_finder_,
message_sender_.BindNewPipeAndPassReceiver(),
......@@ -71,7 +75,8 @@ class NearbyConnectionBrokerImplTest : public testing::Test,
base::BindOnce(&NearbyConnectionBrokerImplTest::OnConnected,
base::Unretained(this)),
base::BindOnce(&NearbyConnectionBrokerImplTest::OnDisconnected,
base::Unretained(this)));
base::Unretained(this)),
std::move(mock_timer));
EXPECT_EQ(GetBluetoothAddress(),
fake_endpoint_finder_.remote_device_bluetooth_address());
}
......@@ -141,7 +146,8 @@ class NearbyConnectionBrokerImplTest : public testing::Test,
void InvokeAcceptConnectionCallback(bool success) {
if (!success) {
base::RunLoop run_loop;
on_disconnected_closure_ = run_loop.QuitClosure();
on_disconnect_from_endpoint_closure_ = run_loop.QuitClosure();
ExpectDisconnectFromEndpoint();
std::move(accept_connection_callback_).Run(Status::kError);
run_loop.Run();
return;
......@@ -169,7 +175,7 @@ class NearbyConnectionBrokerImplTest : public testing::Test,
NotifyConnectionAccepted();
}
void InvokeDisconnectionCallback() {
void InvokeDisconnectedCallback() {
base::RunLoop disconnect_run_loop;
on_disconnected_closure_ = disconnect_run_loop.QuitClosure();
connection_lifecycle_listener_->OnDisconnected(kEndpointId);
......@@ -215,7 +221,8 @@ class NearbyConnectionBrokerImplTest : public testing::Test,
// Failure to send should disconnect the ongoing connection.
base::RunLoop disconnect_run_loop;
on_disconnected_closure_ = disconnect_run_loop.QuitClosure();
on_disconnect_from_endpoint_closure_ = disconnect_run_loop.QuitClosure();
ExpectDisconnectFromEndpoint();
std::move(send_payload_callback).Run(Status::kError);
send_message_response_run_loop.Run();
disconnect_run_loop.Run();
......@@ -238,8 +245,9 @@ class NearbyConnectionBrokerImplTest : public testing::Test,
}
void ReceiveInvalidPayloadType() {
base::RunLoop disconnect_run_loop;
on_disconnected_closure_ = disconnect_run_loop.QuitClosure();
base::RunLoop payload_run_loop;
on_disconnect_from_endpoint_closure_ = payload_run_loop.QuitClosure();
ExpectDisconnectFromEndpoint();
// Create fake file to receive.
const std::vector<uint8_t> kFakeFileContent{0x01, 0x02, 0x03};
......@@ -260,30 +268,68 @@ class NearbyConnectionBrokerImplTest : public testing::Test,
Payload::New(
/*id=*/kInvalidPayloadTypeId,
PayloadContent::NewFile(FilePayload::New(std::move(input_file)))));
disconnect_run_loop.Run();
payload_run_loop.Run();
}
void DeleteBroker(bool expected_to_disconnect) {
void DisconnectMojoBindings(bool expected_to_disconnect) {
if (!expected_to_disconnect) {
base::RunLoop disconnect_run_loop;
on_disconnected_closure_ = disconnect_run_loop.QuitClosure();
EXPECT_CALL(mock_nearby_connections_, DisconnectFromEndpoint(_, _, _))
.Times(0);
broker_.reset();
message_sender_.reset();
disconnect_run_loop.Run();
return;
}
base::RunLoop run_loop;
base::RunLoop disconnect_from_endpoint_run_loop;
on_disconnect_from_endpoint_closure_ =
disconnect_from_endpoint_run_loop.QuitClosure();
ExpectDisconnectFromEndpoint();
message_sender_.reset();
disconnect_from_endpoint_run_loop.Run();
}
void InvokeDisconnectedFromEndpointCallback(bool success) {
if (success) {
std::move(disconnect_from_endpoint_callback_).Run(Status::kSuccess);
// Ensure that callback result is received; cannot use external event
// because the success callback only updates internal state.
base::RunLoop().RunUntilIdle();
return;
}
base::RunLoop disconnect_run_loop;
on_disconnected_closure_ = disconnect_run_loop.QuitClosure();
std::move(disconnect_from_endpoint_callback_).Run(Status::kError);
disconnect_run_loop.Run();
}
void SimulateTimeout(bool expected_to_disconnect) {
if (!expected_to_disconnect) {
base::RunLoop disconnect_run_loop;
on_disconnected_closure_ = disconnect_run_loop.QuitClosure();
EXPECT_CALL(mock_nearby_connections_, DisconnectFromEndpoint(_, _, _))
.WillOnce(Invoke(
[&](const std::string& service_id, const std::string& endpoint_id,
NearbyConnectionsMojom::StopDiscoveryCallback callback) {
std::move(callback).Run(Status::kSuccess);
run_loop.Quit();
}));
.Times(0);
mock_timer_->Fire();
disconnect_run_loop.Run();
return;
}
broker_.reset();
run_loop.Run();
base::RunLoop disconnect_from_endpoint_run_loop;
on_disconnect_from_endpoint_closure_ =
disconnect_from_endpoint_run_loop.QuitClosure();
ExpectDisconnectFromEndpoint();
mock_timer_->Fire();
disconnect_from_endpoint_run_loop.Run();
}
NearbyConnectionsMojom::RequestConnectionCallback
request_connection_callback_;
NearbyConnectionsMojom::AcceptConnectionCallback accept_connection_callback_;
NearbyConnectionsMojom::DisconnectFromEndpointCallback
disconnect_from_endpoint_callback_;
private:
// mojom::NearbyMessageReceiver:
void OnMessageReceived(const std::string& message) override {
......@@ -291,6 +337,17 @@ class NearbyConnectionBrokerImplTest : public testing::Test,
std::move(on_message_received_closure_).Run();
}
void ExpectDisconnectFromEndpoint() {
EXPECT_CALL(mock_nearby_connections_, DisconnectFromEndpoint(_, _, _))
.WillOnce(Invoke(
[&](const std::string& service_id, const std::string& endpoint_id,
NearbyConnectionsMojom::DisconnectFromEndpointCallback
callback) {
disconnect_from_endpoint_callback_ = std::move(callback);
std::move(on_disconnect_from_endpoint_closure_).Run();
}));
}
void OnConnected() { std::move(on_connected_closure_).Run(); }
void OnDisconnected() { std::move(on_disconnected_closure_).Run(); }
......@@ -304,13 +361,12 @@ class NearbyConnectionBrokerImplTest : public testing::Test,
std::unique_ptr<NearbyConnectionBroker> broker_;
base::MockOneShotTimer* mock_timer_ = nullptr;
base::OnceClosure on_connected_closure_;
base::OnceClosure on_disconnected_closure_;
base::OnceClosure on_message_received_closure_;
NearbyConnectionsMojom::RequestConnectionCallback
request_connection_callback_;
NearbyConnectionsMojom::AcceptConnectionCallback accept_connection_callback_;
base::OnceClosure on_disconnect_from_endpoint_closure_;
mojo::Remote<ConnectionLifecycleListener> connection_lifecycle_listener_;
mojo::Remote<PayloadListener> payload_listener_;
......@@ -324,36 +380,83 @@ TEST_F(NearbyConnectionBrokerImplTest, SendAndReceive) {
SendMessage("test2", /*success=*/true);
ReceiveMessage("test3");
ReceiveMessage("test4");
DeleteBroker(/*expected_to_disconnect=*/true);
DisconnectMojoBindings(/*expected_to_disconnect=*/true);
InvokeDisconnectedFromEndpointCallback(/*success=*/true);
InvokeDisconnectedCallback();
}
TEST_F(NearbyConnectionBrokerImplTest, FailToDisconnect) {
SetUpFullConnection();
DisconnectMojoBindings(/*expected_to_disconnect=*/true);
InvokeDisconnectedFromEndpointCallback(/*success=*/false);
}
TEST_F(NearbyConnectionBrokerImplTest, FailToDisconnect_Timeout) {
SetUpFullConnection();
DisconnectMojoBindings(/*expected_to_disconnect=*/true);
SimulateTimeout(/*expected_to_disconnect=*/false);
}
TEST_F(NearbyConnectionBrokerImplTest, DisconnectsUnexpectedly) {
SetUpFullConnection();
InvokeDisconnectionCallback();
DeleteBroker(/*expected_to_disconnect=*/false);
InvokeDisconnectedCallback();
}
TEST_F(NearbyConnectionBrokerImplTest, ReceiveInvalidPayloadType) {
SetUpFullConnection();
ReceiveInvalidPayloadType();
DeleteBroker(/*expected_to_disconnect=*/true);
InvokeDisconnectedFromEndpointCallback(/*success=*/true);
InvokeDisconnectedCallback();
}
TEST_F(NearbyConnectionBrokerImplTest, FailToSend) {
SetUpFullConnection();
SendMessage("test", /*success=*/false);
DeleteBroker(/*expected_to_disconnect=*/true);
InvokeDisconnectedFromEndpointCallback(/*success=*/true);
InvokeDisconnectedCallback();
}
TEST_F(NearbyConnectionBrokerImplTest, FailDiscovery) {
FailDiscovery();
DeleteBroker(/*expected_to_disconnect=*/false);
}
TEST_F(NearbyConnectionBrokerImplTest, FailDiscovery_Timeout) {
SimulateTimeout(/*expected_to_disconnect=*/false);
}
TEST_F(NearbyConnectionBrokerImplTest, MojoDisconnectionAfterDiscovery) {
DiscoverEndpoint();
DisconnectMojoBindings(/*expected_to_disconnect=*/false);
// Run callback to prevent DCHECK() crash that ensures all Mojo callbacks are
// invoked.
std::move(request_connection_callback_).Run(Status::kError);
}
TEST_F(NearbyConnectionBrokerImplTest, FailRequestingConnection) {
DiscoverEndpoint();
InvokeRequestConnectionCallback(/*success=*/false);
DeleteBroker(/*expected_to_disconnect=*/false);
}
TEST_F(NearbyConnectionBrokerImplTest, FailRequestingConnection_Timeout) {
DiscoverEndpoint();
SimulateTimeout(/*expected_to_disconnect=*/true);
InvokeDisconnectedFromEndpointCallback(/*success=*/true);
InvokeDisconnectedCallback();
}
TEST_F(NearbyConnectionBrokerImplTest,
MojoDisconnectionAfterRequestConnection) {
DiscoverEndpoint();
InvokeRequestConnectionCallback(/*success=*/true);
NotifyConnectionInitiated();
DisconnectMojoBindings(/*expected_to_disconnect=*/true);
InvokeDisconnectedFromEndpointCallback(/*success=*/true);
InvokeDisconnectedCallback();
// Run callback to prevent DCHECK() crash that ensures all Mojo callbacks are
// invoked.
std::move(accept_connection_callback_).Run(Status::kError);
}
TEST_F(NearbyConnectionBrokerImplTest, FailAcceptingConnection) {
......@@ -361,7 +464,17 @@ TEST_F(NearbyConnectionBrokerImplTest, FailAcceptingConnection) {
InvokeRequestConnectionCallback(/*success=*/true);
NotifyConnectionInitiated();
InvokeAcceptConnectionCallback(/*success=*/false);
DeleteBroker(/*expected_to_disconnect=*/true);
InvokeDisconnectedFromEndpointCallback(/*success=*/true);
InvokeDisconnectedCallback();
}
TEST_F(NearbyConnectionBrokerImplTest, FailAcceptingConnection_Timeout) {
DiscoverEndpoint();
InvokeRequestConnectionCallback(/*success=*/true);
NotifyConnectionInitiated();
SimulateTimeout(/*expected_to_disconnect=*/true);
InvokeDisconnectedFromEndpointCallback(/*success=*/true);
InvokeDisconnectedCallback();
}
} // namespace secure_channel
......
......@@ -63,7 +63,8 @@ class FakeConnectionBrokerFactory : public NearbyConnectionBrokerImpl::Factory {
location::nearby::connections::mojom::NearbyConnections>&
nearby_connections,
base::OnceClosure on_connected_callback,
base::OnceClosure on_disconnected_callback) override {
base::OnceClosure on_disconnected_callback,
std::unique_ptr<base::OneShotTimer> timer) override {
auto instance = std::make_unique<FakeNearbyConnectionBroker>(
bluetooth_public_address, std::move(message_sender_receiver),
std::move(message_receiver_remote), std::move(on_connected_callback),
......@@ -204,7 +205,7 @@ TEST_F(NearbyConnectorImplTest, ConnectAndTransferMessages) {
// Disconnect.
base::RunLoop disconnect_run_loop;
receiver.SetMojoDisconnectHandler(disconnect_run_loop.QuitClosure());
broker->Disconnect();
broker->InvokeDisconnectedCallback();
disconnect_run_loop.Run();
EXPECT_EQ(0u, fake_nearby_process_manager_.GetNumActiveReferences());
}
......@@ -246,14 +247,14 @@ TEST_F(NearbyConnectorImplTest, TwoConnections) {
// there is still an active connection.
base::RunLoop disconnect_run_loop1;
receiver1.SetMojoDisconnectHandler(disconnect_run_loop1.QuitClosure());
broker1->Disconnect();
broker1->InvokeDisconnectedCallback();
disconnect_run_loop1.Run();
EXPECT_EQ(1u, fake_nearby_process_manager_.GetNumActiveReferences());
// Disconnect connection 2. The process reference should have been released.
base::RunLoop disconnect_run_loop2;
receiver2.SetMojoDisconnectHandler(disconnect_run_loop2.QuitClosure());
broker2->Disconnect();
broker2->InvokeDisconnectedCallback();
disconnect_run_loop2.Run();
EXPECT_EQ(0u, fake_nearby_process_manager_.GetNumActiveReferences());
}
......@@ -271,7 +272,7 @@ TEST_F(NearbyConnectorImplTest, FailToConnect) {
on_connect_ = connect_run_loop.QuitClosure();
base::RunLoop disconnect_run_loop;
receiver.SetMojoDisconnectHandler(disconnect_run_loop.QuitClosure());
broker->Disconnect();
broker->InvokeDisconnectedCallback();
connect_run_loop.Run();
disconnect_run_loop.Run();
......
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