Commit 5fed877b authored by Kyle Horimoto's avatar Kyle Horimoto Committed by Commit Bot

[CrOS MultiDevice] Update ConnectionAttempt.

Now, ConnectionAttempt uses a single ConnectToDeviceOperation throughout
its lifetime, which drastically cleans up the code and removes the
ConnectToDeviceOperationFactory, which is not really needed.

This CL removes ConnectToDeviceOperationFactory entirely.

Bug: 824568, 752273
Change-Id: Iaf8182da258e864b1377aa94cefa1ed9440e8bd1
Reviewed-on: https://chromium-review.googlesource.com/1103337
Commit-Queue: Kyle Horimoto <khorimoto@chromium.org>
Reviewed-by: default avatarRyan Hansberry <hansberry@chromium.org>
Cr-Commit-Position: refs/heads/master@{#568181}
parent b5db59bc
...@@ -51,8 +51,6 @@ static_library("secure_channel") { ...@@ -51,8 +51,6 @@ static_library("secure_channel") {
"client_connection_parameters_impl.h", "client_connection_parameters_impl.h",
"connect_to_device_operation.h", "connect_to_device_operation.h",
"connect_to_device_operation_base.h", "connect_to_device_operation_base.h",
"connect_to_device_operation_factory.h",
"connect_to_device_operation_factory_base.h",
"connection_attempt.h", "connection_attempt.h",
"connection_attempt_base.h", "connection_attempt_base.h",
"connection_attempt_delegate.h", "connection_attempt_delegate.h",
...@@ -146,7 +144,6 @@ static_library("test_support") { ...@@ -146,7 +144,6 @@ static_library("test_support") {
"fake_client_connection_parameters.cc", "fake_client_connection_parameters.cc",
"fake_client_connection_parameters.h", "fake_client_connection_parameters.h",
"fake_connect_to_device_operation.h", "fake_connect_to_device_operation.h",
"fake_connect_to_device_operation_factory.h",
"fake_connection_attempt.h", "fake_connection_attempt.h",
"fake_connection_attempt_delegate.cc", "fake_connection_attempt_delegate.cc",
"fake_connection_attempt_delegate.h", "fake_connection_attempt_delegate.h",
...@@ -201,7 +198,6 @@ source_set("unit_tests") { ...@@ -201,7 +198,6 @@ source_set("unit_tests") {
"ble_synchronizer_unittest.cc", "ble_synchronizer_unittest.cc",
"client_connection_parameters_impl_unittest.cc", "client_connection_parameters_impl_unittest.cc",
"connect_to_device_operation_base_unittest.cc", "connect_to_device_operation_base_unittest.cc",
"connect_to_device_operation_factory_base_unittest.cc",
"connection_attempt_base_unittest.cc", "connection_attempt_base_unittest.cc",
"error_tolerant_ble_advertisement_impl_unittest.cc", "error_tolerant_ble_advertisement_impl_unittest.cc",
"multiplexed_channel_impl_unittest.cc", "multiplexed_channel_impl_unittest.cc",
......
...@@ -37,15 +37,14 @@ std::unique_ptr<ConnectToDeviceOperation<BleInitiatorFailureType>> ...@@ -37,15 +37,14 @@ std::unique_ptr<ConnectToDeviceOperation<BleInitiatorFailureType>>
BleInitiatorOperation::Factory::BuildInstance( BleInitiatorOperation::Factory::BuildInstance(
ConnectToDeviceOperation<BleInitiatorFailureType>::ConnectionSuccessCallback ConnectToDeviceOperation<BleInitiatorFailureType>::ConnectionSuccessCallback
success_callback, success_callback,
ConnectToDeviceOperation<BleInitiatorFailureType>::ConnectionFailedCallback const ConnectToDeviceOperation<
failure_callback, BleInitiatorFailureType>::ConnectionFailedCallback& failure_callback,
const DeviceIdPair& device_id_pair, const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority, ConnectionPriority connection_priority,
base::OnceClosure destructor_callback,
scoped_refptr<base::TaskRunner> task_runner) { scoped_refptr<base::TaskRunner> task_runner) {
return base::WrapUnique(new BleInitiatorOperation( return base::WrapUnique(new BleInitiatorOperation(
std::move(success_callback), std::move(failure_callback), device_id_pair, std::move(success_callback), std::move(failure_callback), device_id_pair,
connection_priority, std::move(destructor_callback), task_runner)); connection_priority, task_runner));
} }
BleInitiatorOperation::~BleInitiatorOperation() = default; BleInitiatorOperation::~BleInitiatorOperation() = default;
...@@ -53,18 +52,16 @@ BleInitiatorOperation::~BleInitiatorOperation() = default; ...@@ -53,18 +52,16 @@ BleInitiatorOperation::~BleInitiatorOperation() = default;
BleInitiatorOperation::BleInitiatorOperation( BleInitiatorOperation::BleInitiatorOperation(
ConnectToDeviceOperation<BleInitiatorFailureType>::ConnectionSuccessCallback ConnectToDeviceOperation<BleInitiatorFailureType>::ConnectionSuccessCallback
success_callback, success_callback,
ConnectToDeviceOperation<BleInitiatorFailureType>::ConnectionFailedCallback const ConnectToDeviceOperation<
failure_callback, BleInitiatorFailureType>::ConnectionFailedCallback& failure_callback,
const DeviceIdPair& device_id_pair, const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority, ConnectionPriority connection_priority,
base::OnceClosure destructor_callback,
scoped_refptr<base::TaskRunner> task_runner) scoped_refptr<base::TaskRunner> task_runner)
: ConnectToDeviceOperationBase<BleInitiatorFailureType>( : ConnectToDeviceOperationBase<BleInitiatorFailureType>(
std::move(success_callback), std::move(success_callback),
std::move(failure_callback), std::move(failure_callback),
device_id_pair, device_id_pair,
connection_priority, connection_priority,
std::move(destructor_callback),
task_runner) {} task_runner) {}
void BleInitiatorOperation::AttemptConnectionToDevice( void BleInitiatorOperation::AttemptConnectionToDevice(
......
...@@ -30,11 +30,10 @@ class BleInitiatorOperation ...@@ -30,11 +30,10 @@ class BleInitiatorOperation
virtual std::unique_ptr<ConnectToDeviceOperation<BleInitiatorFailureType>> virtual std::unique_ptr<ConnectToDeviceOperation<BleInitiatorFailureType>>
BuildInstance(ConnectToDeviceOperation<BleInitiatorFailureType>:: BuildInstance(ConnectToDeviceOperation<BleInitiatorFailureType>::
ConnectionSuccessCallback success_callback, ConnectionSuccessCallback success_callback,
ConnectToDeviceOperation<BleInitiatorFailureType>:: const ConnectToDeviceOperation<BleInitiatorFailureType>::
ConnectionFailedCallback failure_callback, ConnectionFailedCallback& failure_callback,
const DeviceIdPair& device_id_pair, const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority, ConnectionPriority connection_priority,
base::OnceClosure destructor_callback,
scoped_refptr<base::TaskRunner> task_runner = scoped_refptr<base::TaskRunner> task_runner =
base::ThreadTaskRunnerHandle::Get()); base::ThreadTaskRunnerHandle::Get());
...@@ -48,11 +47,10 @@ class BleInitiatorOperation ...@@ -48,11 +47,10 @@ class BleInitiatorOperation
BleInitiatorOperation( BleInitiatorOperation(
ConnectToDeviceOperation< ConnectToDeviceOperation<
BleInitiatorFailureType>::ConnectionSuccessCallback success_callback, BleInitiatorFailureType>::ConnectionSuccessCallback success_callback,
ConnectToDeviceOperation< const ConnectToDeviceOperation<
BleInitiatorFailureType>::ConnectionFailedCallback failure_callback, BleInitiatorFailureType>::ConnectionFailedCallback& failure_callback,
const DeviceIdPair& device_id_pair, const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority, ConnectionPriority connection_priority,
base::OnceClosure destructor_callback,
scoped_refptr<base::TaskRunner> task_runner); scoped_refptr<base::TaskRunner> task_runner);
// ConnectToDeviceOperationBase<BleInitiatorFailureType>: // ConnectToDeviceOperationBase<BleInitiatorFailureType>:
......
...@@ -37,15 +37,14 @@ std::unique_ptr<ConnectToDeviceOperation<BleListenerFailureType>> ...@@ -37,15 +37,14 @@ std::unique_ptr<ConnectToDeviceOperation<BleListenerFailureType>>
BleListenerOperation::Factory::BuildInstance( BleListenerOperation::Factory::BuildInstance(
ConnectToDeviceOperation<BleListenerFailureType>::ConnectionSuccessCallback ConnectToDeviceOperation<BleListenerFailureType>::ConnectionSuccessCallback
success_callback, success_callback,
ConnectToDeviceOperation<BleListenerFailureType>::ConnectionFailedCallback const ConnectToDeviceOperation<
failure_callback, BleListenerFailureType>::ConnectionFailedCallback& failure_callback,
const DeviceIdPair& device_id_pair, const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority, ConnectionPriority connection_priority,
base::OnceClosure destructor_callback,
scoped_refptr<base::TaskRunner> task_runner) { scoped_refptr<base::TaskRunner> task_runner) {
return base::WrapUnique(new BleListenerOperation( return base::WrapUnique(new BleListenerOperation(
std::move(success_callback), std::move(failure_callback), device_id_pair, std::move(success_callback), std::move(failure_callback), device_id_pair,
connection_priority, std::move(destructor_callback), task_runner)); connection_priority, task_runner));
} }
BleListenerOperation::~BleListenerOperation() = default; BleListenerOperation::~BleListenerOperation() = default;
...@@ -53,18 +52,16 @@ BleListenerOperation::~BleListenerOperation() = default; ...@@ -53,18 +52,16 @@ BleListenerOperation::~BleListenerOperation() = default;
BleListenerOperation::BleListenerOperation( BleListenerOperation::BleListenerOperation(
ConnectToDeviceOperation<BleListenerFailureType>::ConnectionSuccessCallback ConnectToDeviceOperation<BleListenerFailureType>::ConnectionSuccessCallback
success_callback, success_callback,
ConnectToDeviceOperation<BleListenerFailureType>::ConnectionFailedCallback const ConnectToDeviceOperation<
failure_callback, BleListenerFailureType>::ConnectionFailedCallback& failure_callback,
const DeviceIdPair& device_id_pair, const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority, ConnectionPriority connection_priority,
base::OnceClosure destructor_callback,
scoped_refptr<base::TaskRunner> task_runner) scoped_refptr<base::TaskRunner> task_runner)
: ConnectToDeviceOperationBase<BleListenerFailureType>( : ConnectToDeviceOperationBase<BleListenerFailureType>(
std::move(success_callback), std::move(success_callback),
std::move(failure_callback), std::move(failure_callback),
device_id_pair, device_id_pair,
connection_priority, connection_priority,
std::move(destructor_callback),
task_runner) {} task_runner) {}
void BleListenerOperation::AttemptConnectionToDevice( void BleListenerOperation::AttemptConnectionToDevice(
......
...@@ -31,11 +31,10 @@ class BleListenerOperation ...@@ -31,11 +31,10 @@ class BleListenerOperation
BuildInstance( BuildInstance(
ConnectToDeviceOperation< ConnectToDeviceOperation<
BleListenerFailureType>::ConnectionSuccessCallback success_callback, BleListenerFailureType>::ConnectionSuccessCallback success_callback,
ConnectToDeviceOperation< const ConnectToDeviceOperation<
BleListenerFailureType>::ConnectionFailedCallback failure_callback, BleListenerFailureType>::ConnectionFailedCallback& failure_callback,
const DeviceIdPair& device_id_pair, const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority, ConnectionPriority connection_priority,
base::OnceClosure destructor_callback,
scoped_refptr<base::TaskRunner> task_runner = scoped_refptr<base::TaskRunner> task_runner =
base::ThreadTaskRunnerHandle::Get()); base::ThreadTaskRunnerHandle::Get());
...@@ -49,11 +48,10 @@ class BleListenerOperation ...@@ -49,11 +48,10 @@ class BleListenerOperation
BleListenerOperation( BleListenerOperation(
ConnectToDeviceOperation< ConnectToDeviceOperation<
BleListenerFailureType>::ConnectionSuccessCallback success_callback, BleListenerFailureType>::ConnectionSuccessCallback success_callback,
ConnectToDeviceOperation<BleListenerFailureType>::ConnectionFailedCallback const ConnectToDeviceOperation<
failure_callback, BleListenerFailureType>::ConnectionFailedCallback& failure_callback,
const DeviceIdPair& device_id_pair, const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority, ConnectionPriority connection_priority,
base::OnceClosure destructor_callback,
scoped_refptr<base::TaskRunner> task_runner); scoped_refptr<base::TaskRunner> task_runner);
// ConnectToDeviceOperationBase<BleListenerFailureType>: // ConnectToDeviceOperationBase<BleListenerFailureType>:
......
...@@ -26,10 +26,11 @@ class ConnectToDeviceOperation { ...@@ -26,10 +26,11 @@ class ConnectToDeviceOperation {
public: public:
using ConnectionSuccessCallback = using ConnectionSuccessCallback =
base::OnceCallback<void(std::unique_ptr<AuthenticatedChannel>)>; base::OnceCallback<void(std::unique_ptr<AuthenticatedChannel>)>;
using ConnectionFailedCallback = base::OnceCallback<void(FailureDetailType)>; using ConnectionFailedCallback =
base::RepeatingCallback<void(FailureDetailType)>;
virtual ~ConnectToDeviceOperation() { virtual ~ConnectToDeviceOperation() {
if (!is_active_) if (has_finished_)
return; return;
PA_LOG(ERROR) << "ConnectToDeviceOperation::~ConnectToDeviceOperation(): " PA_LOG(ERROR) << "ConnectToDeviceOperation::~ConnectToDeviceOperation(): "
...@@ -39,7 +40,7 @@ class ConnectToDeviceOperation { ...@@ -39,7 +40,7 @@ class ConnectToDeviceOperation {
// Updates the priority for this operation. // Updates the priority for this operation.
void UpdateConnectionPriority(ConnectionPriority connection_priority) { void UpdateConnectionPriority(ConnectionPriority connection_priority) {
if (!is_active_) { if (has_finished_) {
PA_LOG(ERROR) << "ConnectToDeviceOperation::UpdateConnectionPriority(): " PA_LOG(ERROR) << "ConnectToDeviceOperation::UpdateConnectionPriority(): "
<< "Connection priority update requested, but the " << "Connection priority update requested, but the "
<< "operation was no longer active."; << "operation was no longer active.";
...@@ -54,14 +55,14 @@ class ConnectToDeviceOperation { ...@@ -54,14 +55,14 @@ class ConnectToDeviceOperation {
// Note: Canceling an ongoing connection attempt will not cause either of the // Note: Canceling an ongoing connection attempt will not cause either of the
// success/failure callbacks passed to the constructor to be invoked. // success/failure callbacks passed to the constructor to be invoked.
void Cancel() { void Cancel() {
if (!is_active_) { if (has_finished_) {
PA_LOG(ERROR) << "ConnectToDeviceOperation::Cancel(): Tried to cancel " PA_LOG(ERROR) << "ConnectToDeviceOperation::Cancel(): Tried to cancel "
<< "operation after it had already finished."; << "operation after it had already finished.";
NOTREACHED(); NOTREACHED();
return; return;
} }
is_active_ = false; has_finished_ = true;
PerformCancellation(); PerformCancellation();
} }
...@@ -71,10 +72,10 @@ class ConnectToDeviceOperation { ...@@ -71,10 +72,10 @@ class ConnectToDeviceOperation {
protected: protected:
ConnectToDeviceOperation(ConnectionSuccessCallback success_callback, ConnectToDeviceOperation(ConnectionSuccessCallback success_callback,
ConnectionFailedCallback failure_callback, const ConnectionFailedCallback& failure_callback,
ConnectionPriority connection_priority) ConnectionPriority connection_priority)
: success_callback_(std::move(success_callback)), : success_callback_(std::move(success_callback)),
failure_callback_(std::move(failure_callback)), failure_callback_(failure_callback),
connection_priority_(connection_priority) {} connection_priority_(connection_priority) {}
virtual void PerformCancellation() = 0; virtual void PerformCancellation() = 0;
...@@ -83,31 +84,23 @@ class ConnectToDeviceOperation { ...@@ -83,31 +84,23 @@ class ConnectToDeviceOperation {
void OnSuccessfulConnectionAttempt( void OnSuccessfulConnectionAttempt(
std::unique_ptr<AuthenticatedChannel> authenticated_channel) { std::unique_ptr<AuthenticatedChannel> authenticated_channel) {
if (!is_active_) { if (has_finished_) {
PA_LOG(ERROR) << "ConnectToDeviceOperation::" PA_LOG(ERROR) << "ConnectToDeviceOperation::"
<< "OnSuccessfulConnectionAttempt(): Tried to " << "OnSuccessfulConnectionAttempt(): Tried to "
<< "complete operation after it had already finished."; << "complete operation after it had already finished.";
return; return;
} }
is_active_ = false; has_finished_ = true;
std::move(success_callback_).Run(std::move(authenticated_channel)); std::move(success_callback_).Run(std::move(authenticated_channel));
} }
void OnFailedConnectionAttempt(FailureDetailType failure_detail) { void OnFailedConnectionAttempt(FailureDetailType failure_detail) {
if (!is_active_) { failure_callback_.Run(failure_detail);
PA_LOG(ERROR) << "ConnectToDeviceOperation::"
<< "OnFailedConnectionAttempt(): Tried to "
<< "complete operation after it had already finished.";
return;
}
is_active_ = false;
std::move(failure_callback_).Run(failure_detail);
} }
private: private:
bool is_active_ = true; bool has_finished_ = false;
ConnectionSuccessCallback success_callback_; ConnectionSuccessCallback success_callback_;
ConnectionFailedCallback failure_callback_; ConnectionFailedCallback failure_callback_;
......
...@@ -34,14 +34,12 @@ class ConnectToDeviceOperationBase ...@@ -34,14 +34,12 @@ class ConnectToDeviceOperationBase
FailureDetailType>::ConnectionFailedCallback failure_callback, FailureDetailType>::ConnectionFailedCallback failure_callback,
const DeviceIdPair& device_id_pair, const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority, ConnectionPriority connection_priority,
base::OnceClosure destructor_callback,
scoped_refptr<base::TaskRunner> task_runner = scoped_refptr<base::TaskRunner> task_runner =
base::ThreadTaskRunnerHandle::Get()) base::ThreadTaskRunnerHandle::Get())
: ConnectToDeviceOperation<FailureDetailType>(std::move(success_callback), : ConnectToDeviceOperation<FailureDetailType>(std::move(success_callback),
std::move(failure_callback), std::move(failure_callback),
connection_priority), connection_priority),
device_id_pair_(device_id_pair), device_id_pair_(device_id_pair),
destructor_callback_(std::move(destructor_callback)),
task_runner_(task_runner), task_runner_(task_runner),
weak_ptr_factory_(this) { weak_ptr_factory_(this) {
// Attempt a connection; however, post this as a task to be run after the // Attempt a connection; however, post this as a task to be run after the
...@@ -54,9 +52,7 @@ class ConnectToDeviceOperationBase ...@@ -54,9 +52,7 @@ class ConnectToDeviceOperationBase
weak_ptr_factory_.GetWeakPtr(), connection_priority)); weak_ptr_factory_.GetWeakPtr(), connection_priority));
} }
~ConnectToDeviceOperationBase() override { ~ConnectToDeviceOperationBase() override = default;
std::move(destructor_callback_).Run();
}
virtual void AttemptConnectionToDevice( virtual void AttemptConnectionToDevice(
ConnectionPriority connection_priority) = 0; ConnectionPriority connection_priority) = 0;
...@@ -65,7 +61,6 @@ class ConnectToDeviceOperationBase ...@@ -65,7 +61,6 @@ class ConnectToDeviceOperationBase
private: private:
const DeviceIdPair& device_id_pair_; const DeviceIdPair& device_id_pair_;
base::OnceClosure destructor_callback_;
scoped_refptr<base::TaskRunner> task_runner_; scoped_refptr<base::TaskRunner> task_runner_;
base::WeakPtrFactory<ConnectToDeviceOperationBase> weak_ptr_factory_; base::WeakPtrFactory<ConnectToDeviceOperationBase> weak_ptr_factory_;
......
...@@ -20,7 +20,6 @@ namespace secure_channel { ...@@ -20,7 +20,6 @@ namespace secure_channel {
namespace { namespace {
const char kTestFailureReason[] = "testFailureReason";
const char kTestRemoteDeviceId[] = "testRemoteDeviceId"; const char kTestRemoteDeviceId[] = "testRemoteDeviceId";
const char kTestLocalDeviceId[] = "testLocalDeviceId"; const char kTestLocalDeviceId[] = "testLocalDeviceId";
...@@ -32,16 +31,14 @@ class TestConnectToDeviceOperation ...@@ -32,16 +31,14 @@ class TestConnectToDeviceOperation
static std::unique_ptr<TestConnectToDeviceOperation> Create( static std::unique_ptr<TestConnectToDeviceOperation> Create(
ConnectToDeviceOperation<std::string>::ConnectionSuccessCallback ConnectToDeviceOperation<std::string>::ConnectionSuccessCallback
success_callback, success_callback,
ConnectToDeviceOperation<std::string>::ConnectionFailedCallback const ConnectToDeviceOperation<std::string>::ConnectionFailedCallback&
failure_callback, failure_callback,
const DeviceIdPair& device_id_pair, const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority, ConnectionPriority connection_priority) {
base::OnceClosure destructor_callback) {
auto test_task_runner = base::MakeRefCounted<base::TestSimpleTaskRunner>(); auto test_task_runner = base::MakeRefCounted<base::TestSimpleTaskRunner>();
auto operation = base::WrapUnique(new TestConnectToDeviceOperation( auto operation = base::WrapUnique(new TestConnectToDeviceOperation(
std::move(success_callback), std::move(failure_callback), std::move(success_callback), std::move(failure_callback),
device_id_pair, connection_priority, std::move(destructor_callback), device_id_pair, connection_priority, test_task_runner));
test_task_runner));
test_task_runner->RunUntilIdle(); test_task_runner->RunUntilIdle();
return operation; return operation;
} }
...@@ -70,19 +67,16 @@ class TestConnectToDeviceOperation ...@@ -70,19 +67,16 @@ class TestConnectToDeviceOperation
TestConnectToDeviceOperation( TestConnectToDeviceOperation(
ConnectToDeviceOperation<std::string>::ConnectionSuccessCallback ConnectToDeviceOperation<std::string>::ConnectionSuccessCallback
success_callback, success_callback,
ConnectToDeviceOperation<std::string>::ConnectionFailedCallback const ConnectToDeviceOperation<std::string>::ConnectionFailedCallback&
failure_callback, failure_callback,
const DeviceIdPair& device_id_pair, const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority, ConnectionPriority connection_priority,
base::OnceClosure destructor_callback,
scoped_refptr<base::TestSimpleTaskRunner> test_task_runner) scoped_refptr<base::TestSimpleTaskRunner> test_task_runner)
: ConnectToDeviceOperationBase<std::string>( : ConnectToDeviceOperationBase<std::string>(std::move(success_callback),
std::move(success_callback), std::move(failure_callback),
std::move(failure_callback), device_id_pair,
device_id_pair, connection_priority,
connection_priority, test_task_runner) {}
std::move(destructor_callback),
test_task_runner) {}
bool has_attempted_connection_ = false; bool has_attempted_connection_ = false;
bool has_canceled_connection_ = false; bool has_canceled_connection_ = false;
...@@ -97,25 +91,15 @@ class SecureChannelConnectToDeviceOperationBaseTest : public testing::Test { ...@@ -97,25 +91,15 @@ class SecureChannelConnectToDeviceOperationBaseTest : public testing::Test {
~SecureChannelConnectToDeviceOperationBaseTest() override = default; ~SecureChannelConnectToDeviceOperationBaseTest() override = default;
// testing::Test:
void TearDown() override {
EXPECT_FALSE(destructor_callback_called_);
test_operation_.reset();
EXPECT_TRUE(destructor_callback_called_);
}
void CreateOperation(ConnectionPriority connection_priority) { void CreateOperation(ConnectionPriority connection_priority) {
test_operation_ = TestConnectToDeviceOperation::Create( test_operation_ = TestConnectToDeviceOperation::Create(
base::BindOnce(&SecureChannelConnectToDeviceOperationBaseTest:: base::BindOnce(&SecureChannelConnectToDeviceOperationBaseTest::
OnSuccessfulConnectionAttempt, OnSuccessfulConnectionAttempt,
base::Unretained(this)), base::Unretained(this)),
base::BindOnce(&SecureChannelConnectToDeviceOperationBaseTest:: base::BindRepeating(&SecureChannelConnectToDeviceOperationBaseTest::
OnFailedConnectionAttempt, OnFailedConnectionAttempt,
base::Unretained(this)), base::Unretained(this)),
test_device_id_pair_, connection_priority, test_device_id_pair_, connection_priority);
base::BindOnce(
&SecureChannelConnectToDeviceOperationBaseTest::OnOperationDeleted,
base::Unretained(this)));
EXPECT_TRUE(test_operation_->has_attempted_connection()); EXPECT_TRUE(test_operation_->has_attempted_connection());
} }
...@@ -141,14 +125,11 @@ class SecureChannelConnectToDeviceOperationBaseTest : public testing::Test { ...@@ -141,14 +125,11 @@ class SecureChannelConnectToDeviceOperationBaseTest : public testing::Test {
last_failure_detail_ = failure_detail; last_failure_detail_ = failure_detail;
} }
void OnOperationDeleted() { destructor_callback_called_ = true; }
const base::test::ScopedTaskEnvironment scoped_task_environment_; const base::test::ScopedTaskEnvironment scoped_task_environment_;
const DeviceIdPair test_device_id_pair_; const DeviceIdPair test_device_id_pair_;
std::unique_ptr<AuthenticatedChannel> last_authenticated_channel_; std::unique_ptr<AuthenticatedChannel> last_authenticated_channel_;
std::string last_failure_detail_; std::string last_failure_detail_;
bool destructor_callback_called_ = false;
std::unique_ptr<TestConnectToDeviceOperation> test_operation_; std::unique_ptr<TestConnectToDeviceOperation> test_operation_;
...@@ -177,8 +158,14 @@ TEST_F(SecureChannelConnectToDeviceOperationBaseTest, Success) { ...@@ -177,8 +158,14 @@ TEST_F(SecureChannelConnectToDeviceOperationBaseTest, Success) {
TEST_F(SecureChannelConnectToDeviceOperationBaseTest, Failure) { TEST_F(SecureChannelConnectToDeviceOperationBaseTest, Failure) {
CreateOperation(ConnectionPriority::kLow); CreateOperation(ConnectionPriority::kLow);
test_operation()->OnFailedConnectionAttempt(kTestFailureReason);
EXPECT_EQ(kTestFailureReason, last_failure_detail()); test_operation()->OnFailedConnectionAttempt("failureReason1");
EXPECT_EQ("failureReason1", last_failure_detail());
test_operation()->OnFailedConnectionAttempt("failureReason2");
EXPECT_EQ("failureReason2", last_failure_detail());
test_operation()->Cancel();
} }
TEST_F(SecureChannelConnectToDeviceOperationBaseTest, Cancelation) { TEST_F(SecureChannelConnectToDeviceOperationBaseTest, Cancelation) {
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMEOS_SERVICES_SECURE_CHANNEL_CONNECT_TO_DEVICE_OPERATION_FACTORY_H_
#define CHROMEOS_SERVICES_SECURE_CHANNEL_CONNECT_TO_DEVICE_OPERATION_FACTORY_H_
#include "base/callback_forward.h"
#include "base/macros.h"
#include "chromeos/services/secure_channel/connect_to_device_operation.h"
#include "chromeos/services/secure_channel/device_id_pair.h"
#include "chromeos/services/secure_channel/public/cpp/shared/connection_priority.h"
namespace chromeos {
namespace secure_channel {
// Factory for creating ConnectToDeviceOperation instances.
template <typename FailureDetailType>
class ConnectToDeviceOperationFactory {
public:
virtual ~ConnectToDeviceOperationFactory() = default;
virtual std::unique_ptr<ConnectToDeviceOperation<FailureDetailType>>
CreateOperation(
const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority,
typename ConnectToDeviceOperation<
FailureDetailType>::ConnectionSuccessCallback success_callback,
typename ConnectToDeviceOperation<
FailureDetailType>::ConnectionFailedCallback failure_callback) = 0;
protected:
ConnectToDeviceOperationFactory() = default;
private:
DISALLOW_COPY_AND_ASSIGN(ConnectToDeviceOperationFactory);
};
} // namespace secure_channel
} // namespace chromeos
#endif // CHROMEOS_SERVICES_SECURE_CHANNEL_CONNECT_TO_DEVICE_OPERATION_FACTORY_H_
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMEOS_SERVICES_SECURE_CHANNEL_CONNECT_TO_DEVICE_OPERATION_FACTORY_BASE_H_
#define CHROMEOS_SERVICES_SECURE_CHANNEL_CONNECT_TO_DEVICE_OPERATION_FACTORY_BASE_H_
#include "base/bind.h"
#include "base/callback_forward.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "chromeos/services/secure_channel/connect_to_device_operation_factory.h"
#include "chromeos/services/secure_channel/device_id_pair.h"
namespace chromeos {
namespace secure_channel {
// ConnectToDeviceOperationFactory implementation, which ensures that only one
// operation can be active at a time.
template <typename FailureDetailType>
class ConnectToDeviceOperationFactoryBase
: public ConnectToDeviceOperationFactory<FailureDetailType> {
public:
~ConnectToDeviceOperationFactoryBase() override = default;
protected:
ConnectToDeviceOperationFactoryBase(const DeviceIdPair& device_id_pair)
: device_id_pair_(device_id_pair), weak_ptr_factory_(this) {}
// Derived types should overload this function, passing the provided
// parameters to the constructor of a type derived from
// ConnectToDeviceOperationBase.
virtual std::unique_ptr<ConnectToDeviceOperation<FailureDetailType>>
PerformCreateOperation(
const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority,
typename ConnectToDeviceOperation<
FailureDetailType>::ConnectionSuccessCallback success_callback,
typename ConnectToDeviceOperation<
FailureDetailType>::ConnectionFailedCallback failure_callback,
base::OnceClosure destructor_callback) = 0;
private:
// ConnectToDeviceOperationFactory<FailureDetailType>:
std::unique_ptr<ConnectToDeviceOperation<FailureDetailType>> CreateOperation(
const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority,
typename ConnectToDeviceOperation<
FailureDetailType>::ConnectionSuccessCallback success_callback,
typename ConnectToDeviceOperation<FailureDetailType>::
ConnectionFailedCallback failure_callback) override {
if (is_last_operation_active_) {
PA_LOG(ERROR) << "ConnectToDeviceOperationFactoryBase::CreateOperation():"
<< " Requested new operation before the previous one was "
<< "finished.";
NOTREACHED();
return nullptr;
}
is_last_operation_active_ = true;
return PerformCreateOperation(
device_id_pair_, connection_priority, std::move(success_callback),
std::move(failure_callback),
base::BindOnce(&ConnectToDeviceOperationFactoryBase<
FailureDetailType>::OnPreviousOperationDeleted,
weak_ptr_factory_.GetWeakPtr()));
}
void OnPreviousOperationDeleted() { is_last_operation_active_ = false; }
const DeviceIdPair device_id_pair_;
bool is_last_operation_active_ = false;
base::WeakPtrFactory<ConnectToDeviceOperationFactoryBase> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(ConnectToDeviceOperationFactoryBase);
};
} // namespace secure_channel
} // namespace chromeos
#endif // CHROMEOS_SERVICES_SECURE_CHANNEL_CONNECT_TO_DEVICE_OPERATION_FACTORY_BASE_H_
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chromeos/services/secure_channel/connect_to_device_operation_factory_base.h"
#include <memory>
#include "base/bind_helpers.h"
#include "base/test/gtest_util.h"
#include "chromeos/services/secure_channel/device_id_pair.h"
#include "chromeos/services/secure_channel/fake_connect_to_device_operation.h"
#include "chromeos/services/secure_channel/public/cpp/shared/authenticated_channel.h"
#include "components/cryptauth/secure_channel.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
namespace secure_channel {
namespace {
constexpr const ConnectionPriority kTestPriority = ConnectionPriority::kLow;
const char kTestRemoteDeviceId[] = "testRemoteDeviceId";
const char kTestLocalDeviceId[] = "testLocalDeviceId";
// Since ConnectToDeviceOperationFactoryBase is templatized, a concrete
// implementation is needed for its test.
class TestConnectToDeviceOperationFactory
: public ConnectToDeviceOperationFactoryBase<std::string> {
public:
TestConnectToDeviceOperationFactory(const DeviceIdPair& device_id_pair)
: ConnectToDeviceOperationFactoryBase<std::string>(device_id_pair),
device_id_pair_(device_id_pair) {}
~TestConnectToDeviceOperationFactory() override = default;
void InvokePendingDestructorCallback() {
EXPECT_TRUE(last_destructor_callback_);
std::move(last_destructor_callback_).Run();
}
// ConnectToDeviceOperationFactoryBase<std::string>:
std::unique_ptr<ConnectToDeviceOperation<std::string>> PerformCreateOperation(
const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority,
typename ConnectToDeviceOperation<std::string>::ConnectionSuccessCallback
success_callback,
typename ConnectToDeviceOperation<std::string>::ConnectionFailedCallback
failure_callback,
base::OnceClosure destructor_callback) override {
// The previous destructor callback should have been invoked by the time
// this function runs.
EXPECT_FALSE(last_destructor_callback_);
last_destructor_callback_ = std::move(destructor_callback);
EXPECT_EQ(kTestPriority, connection_priority);
EXPECT_EQ(device_id_pair_, device_id_pair);
return std::make_unique<FakeConnectToDeviceOperation<std::string>>(
std::move(success_callback), std::move(failure_callback),
connection_priority);
}
private:
const DeviceIdPair device_id_pair_;
base::OnceClosure last_destructor_callback_;
};
} // namespace
class SecureChannelConnectToDeviceOperationFactoryBaseTest
: public testing::Test {
protected:
SecureChannelConnectToDeviceOperationFactoryBaseTest()
: test_device_id_pair_(kTestRemoteDeviceId, kTestLocalDeviceId) {}
~SecureChannelConnectToDeviceOperationFactoryBaseTest() override = default;
void SetUp() override {
test_factory_ = std::make_unique<TestConnectToDeviceOperationFactory>(
test_device_id_pair_);
}
std::unique_ptr<ConnectToDeviceOperation<std::string>> CallCreateOperation() {
// Use a pointer to ConnectToDeviceOperationFactory, since
// ConnectToDeviceOperationFactoryBase makes CreateOperation private.
ConnectToDeviceOperationFactory<std::string>* factory = test_factory_.get();
return factory->CreateOperation(test_device_id_pair_, kTestPriority,
base::DoNothing() /* success_callback */,
base::DoNothing() /* failure_callback */);
}
void FinishActiveOperation(
std::unique_ptr<ConnectToDeviceOperation<std::string>>
operation_to_finish) {
EXPECT_TRUE(operation_to_finish);
// Use a pointer to FakeConnectToDeviceOperation, since
// ConnectToDeviceOperation makes OnSuccessfulConnectionAttempt() protected.
FakeConnectToDeviceOperation<std::string>* operation =
static_cast<FakeConnectToDeviceOperation<std::string>*>(
operation_to_finish.get());
operation->OnFailedConnectionAttempt(
"arbitraryFailureDetail" /* failure_detail */);
test_factory_->InvokePendingDestructorCallback();
}
private:
const DeviceIdPair test_device_id_pair_;
std::unique_ptr<TestConnectToDeviceOperationFactory> test_factory_;
DISALLOW_COPY_AND_ASSIGN(
SecureChannelConnectToDeviceOperationFactoryBaseTest);
};
TEST_F(SecureChannelConnectToDeviceOperationFactoryBaseTest,
UseFactoryCorrectly) {
auto operation1 = CallCreateOperation();
EXPECT_TRUE(operation1);
// Invoke the destructor callback and try again.
FinishActiveOperation(std::move(operation1));
auto operation2 = CallCreateOperation();
EXPECT_TRUE(operation2);
// Invoke the destructor callback and try again.
FinishActiveOperation(std::move(operation2));
auto operation3 = CallCreateOperation();
EXPECT_TRUE(operation3);
FinishActiveOperation(std::move(operation3));
}
TEST_F(SecureChannelConnectToDeviceOperationFactoryBaseTest,
UseFactoryIncorrectly) {
// First operation should always complete successfully.
auto operation = CallCreateOperation();
EXPECT_TRUE(operation);
// The first operation's destructor callback has not yet been invoked, so
// creating another should fail.
EXPECT_DCHECK_DEATH(CallCreateOperation());
FinishActiveOperation(std::move(operation));
}
} // namespace secure_channel
} // namespace chromeos
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "chromeos/services/secure_channel/connection_attempt_details.h" #include "chromeos/services/secure_channel/connection_attempt_details.h"
#include "chromeos/services/secure_channel/connection_details.h" #include "chromeos/services/secure_channel/connection_details.h"
#include "chromeos/services/secure_channel/pending_connection_request.h" #include "chromeos/services/secure_channel/pending_connection_request.h"
#include "chromeos/services/secure_channel/pending_connection_request_delegate.h"
namespace chromeos { namespace chromeos {
...@@ -29,7 +30,7 @@ class AuthenticatedChannel; ...@@ -29,7 +30,7 @@ class AuthenticatedChannel;
// more PendingConnectionRequests and notifies its delegate when the attempt has // more PendingConnectionRequests and notifies its delegate when the attempt has
// succeeded or failed. // succeeded or failed.
template <typename FailureDetailType> template <typename FailureDetailType>
class ConnectionAttempt { class ConnectionAttempt : public PendingConnectionRequestDelegate {
public: public:
// Extracts all of the ClientConnectionParameters owned by |attempt|'s // Extracts all of the ClientConnectionParameters owned by |attempt|'s
// PendingConnectionRequests. This function deletes |attempt| as part of this // PendingConnectionRequests. This function deletes |attempt| as part of this
...@@ -57,7 +58,7 @@ class ConnectionAttempt { ...@@ -57,7 +58,7 @@ class ConnectionAttempt {
return false; return false;
} }
if (has_notified_delegate_) { if (has_notified_delegate_of_success_) {
PA_LOG(ERROR) << "ConnectionAttempt::AddPendingConnectionRequest(): " PA_LOG(ERROR) << "ConnectionAttempt::AddPendingConnectionRequest(): "
<< "Tried to add an additional request,but the attempt had " << "Tried to add an additional request,but the attempt had "
<< "already finished."; << "already finished.";
...@@ -88,21 +89,21 @@ class ConnectionAttempt { ...@@ -88,21 +89,21 @@ class ConnectionAttempt {
void OnConnectionAttemptSucceeded( void OnConnectionAttemptSucceeded(
std::unique_ptr<AuthenticatedChannel> authenticated_channel) { std::unique_ptr<AuthenticatedChannel> authenticated_channel) {
if (has_notified_delegate_) { if (has_notified_delegate_of_success_) {
PA_LOG(ERROR) << "ConnectionAttempt::OnConnectionAttemptSucceeded(): " PA_LOG(ERROR) << "ConnectionAttempt::OnConnectionAttemptSucceeded(): "
<< "Tried to alert delegate of a successful connection, " << "Tried to alert delegate of a successful connection, "
<< "but the attempt had already finished."; << "but the attempt had already finished.";
return; return;
} }
has_notified_delegate_ = true; has_notified_delegate_of_success_ = true;
delegate_->OnConnectionAttemptSucceeded( delegate_->OnConnectionAttemptSucceeded(
connection_attempt_details_.GetAssociatedConnectionDetails(), connection_attempt_details_.GetAssociatedConnectionDetails(),
std::move(authenticated_channel)); std::move(authenticated_channel));
} }
void OnConnectionAttemptFinishedWithoutConnection() { void OnConnectionAttemptFinishedWithoutConnection() {
if (has_notified_delegate_) { if (has_notified_delegate_of_success_) {
PA_LOG(ERROR) << "ConnectionAttempt::" PA_LOG(ERROR) << "ConnectionAttempt::"
<< "OnConnectionAttemptFinishedWithoutConnection(): " << "OnConnectionAttemptFinishedWithoutConnection(): "
<< "Tried to alert delegate of a failed connection, " << "Tried to alert delegate of a failed connection, "
...@@ -110,7 +111,6 @@ class ConnectionAttempt { ...@@ -110,7 +111,6 @@ class ConnectionAttempt {
return; return;
} }
has_notified_delegate_ = true;
delegate_->OnConnectionAttemptFinishedWithoutConnection( delegate_->OnConnectionAttemptFinishedWithoutConnection(
connection_attempt_details_); connection_attempt_details_);
} }
...@@ -119,7 +119,7 @@ class ConnectionAttempt { ...@@ -119,7 +119,7 @@ class ConnectionAttempt {
ConnectionAttemptDelegate* delegate_; ConnectionAttemptDelegate* delegate_;
const ConnectionAttemptDetails connection_attempt_details_; const ConnectionAttemptDetails connection_attempt_details_;
bool has_notified_delegate_ = false; bool has_notified_delegate_of_success_ = false;
DISALLOW_COPY_AND_ASSIGN(ConnectionAttempt); DISALLOW_COPY_AND_ASSIGN(ConnectionAttempt);
}; };
......
...@@ -5,22 +5,19 @@ ...@@ -5,22 +5,19 @@
#ifndef CHROMEOS_SERVICES_SECURE_CHANNEL_CONNECTION_ATTEMPT_BASE_H_ #ifndef CHROMEOS_SERVICES_SECURE_CHANNEL_CONNECTION_ATTEMPT_BASE_H_
#define CHROMEOS_SERVICES_SECURE_CHANNEL_CONNECTION_ATTEMPT_BASE_H_ #define CHROMEOS_SERVICES_SECURE_CHANNEL_CONNECTION_ATTEMPT_BASE_H_
#include <unordered_map> #include "base/containers/flat_map.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "base/observer_list.h" #include "base/observer_list.h"
#include "base/stl_util.h" #include "base/stl_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "chromeos/components/proximity_auth/logging/logging.h" #include "chromeos/components/proximity_auth/logging/logging.h"
#include "chromeos/services/secure_channel/connect_to_device_operation.h" #include "chromeos/services/secure_channel/connect_to_device_operation.h"
#include "chromeos/services/secure_channel/connect_to_device_operation_factory.h"
#include "chromeos/services/secure_channel/connection_attempt.h" #include "chromeos/services/secure_channel/connection_attempt.h"
#include "chromeos/services/secure_channel/connection_attempt_details.h" #include "chromeos/services/secure_channel/connection_attempt_details.h"
#include "chromeos/services/secure_channel/connection_details.h" #include "chromeos/services/secure_channel/connection_details.h"
#include "chromeos/services/secure_channel/pending_connection_request.h" #include "chromeos/services/secure_channel/pending_connection_request.h"
#include "chromeos/services/secure_channel/pending_connection_request_delegate.h" #include "chromeos/services/secure_channel/public/cpp/shared/authenticated_channel.h"
#include "chromeos/services/secure_channel/public/cpp/shared/connection_priority.h" #include "chromeos/services/secure_channel/public/cpp/shared/connection_priority.h"
#include "chromeos/services/secure_channel/public/mojom/secure_channel.mojom.h" #include "chromeos/services/secure_channel/public/mojom/secure_channel.mojom.h"
...@@ -47,28 +44,29 @@ class AuthenticatedChannel; ...@@ -47,28 +44,29 @@ class AuthenticatedChannel;
// ConnectionAttempt simply starts up a new operation and retries the // ConnectionAttempt simply starts up a new operation and retries the
// connection. // connection.
template <typename FailureDetailType> template <typename FailureDetailType>
class ConnectionAttemptBase : public ConnectionAttempt<FailureDetailType>, class ConnectionAttemptBase : public ConnectionAttempt<FailureDetailType> {
public PendingConnectionRequestDelegate {
protected: protected:
ConnectionAttemptBase( ConnectionAttemptBase(
std::unique_ptr<ConnectToDeviceOperationFactory<FailureDetailType>>
connect_to_device_operation_factory,
ConnectionAttemptDelegate* delegate, ConnectionAttemptDelegate* delegate,
const ConnectionAttemptDetails& connection_attempt_details, const ConnectionAttemptDetails& connection_attempt_details)
scoped_refptr<base::TaskRunner> task_runner =
base::ThreadTaskRunnerHandle::Get())
: ConnectionAttempt<FailureDetailType>(delegate, : ConnectionAttempt<FailureDetailType>(delegate,
connection_attempt_details), connection_attempt_details),
connect_to_device_operation_factory_(
std::move(connect_to_device_operation_factory)),
task_runner_(task_runner),
weak_ptr_factory_(this) {} weak_ptr_factory_(this) {}
~ConnectionAttemptBase() override { ~ConnectionAttemptBase() override {
if (current_operation_) if (operation_)
current_operation_->Cancel(); operation_->Cancel();
} }
virtual std::unique_ptr<ConnectToDeviceOperation<FailureDetailType>>
CreateConnectToDeviceOperation(
const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority,
typename ConnectToDeviceOperation<
FailureDetailType>::ConnectionSuccessCallback success_callback,
const typename ConnectToDeviceOperation<
FailureDetailType>::ConnectionFailedCallback& failure_callback) = 0;
private: private:
// ConnectionAttempt<FailureDetailType>: // ConnectionAttempt<FailureDetailType>:
void ProcessAddingNewConnectionRequest( void ProcessAddingNewConnectionRequest(
...@@ -88,16 +86,26 @@ class ConnectionAttemptBase : public ConnectionAttempt<FailureDetailType>, ...@@ -88,16 +86,26 @@ class ConnectionAttemptBase : public ConnectionAttempt<FailureDetailType>,
id_to_request_map_[request->GetRequestId()] = std::move(request); id_to_request_map_[request->GetRequestId()] = std::move(request);
// In the case that this ConnectionAttempt was just created and had not yet // In the case that this ConnectionAttempt was just created and had not yet
// received a request yet, start up an operation. // received a request yet, start up its operation.
if (was_empty) { if (was_empty) {
StartNextConnectToDeviceOperation(); operation_ = CreateConnectToDeviceOperation(
this->connection_attempt_details().device_id_pair(),
GetHighestRemainingConnectionPriority(),
base::BindOnce(
&ConnectionAttemptBase<
FailureDetailType>::OnConnectToDeviceOperationSuccess,
weak_ptr_factory_.GetWeakPtr()),
base::BindRepeating(
&ConnectionAttemptBase<
FailureDetailType>::OnConnectToDeviceOperationFailure,
weak_ptr_factory_.GetWeakPtr()));
return; return;
} }
ConnectionPriority priority_after_add = ConnectionPriority priority_after_add =
GetHighestRemainingConnectionPriority(); GetHighestRemainingConnectionPriority();
if (priority_before_add != priority_after_add) if (priority_before_add != priority_after_add)
current_operation_->UpdateConnectionPriority(priority_after_add); operation_->UpdateConnectionPriority(priority_after_add);
} }
std::vector<std::unique_ptr<ClientConnectionParameters>> std::vector<std::unique_ptr<ClientConnectionParameters>>
...@@ -130,51 +138,21 @@ class ConnectionAttemptBase : public ConnectionAttempt<FailureDetailType>, ...@@ -130,51 +138,21 @@ class ConnectionAttemptBase : public ConnectionAttempt<FailureDetailType>,
ConnectionPriority priority_after_removal = ConnectionPriority priority_after_removal =
GetHighestRemainingConnectionPriority(); GetHighestRemainingConnectionPriority();
if (priority_before_removal != priority_after_removal) if (priority_before_removal != priority_after_removal)
current_operation_->UpdateConnectionPriority(priority_after_removal); operation_->UpdateConnectionPriority(priority_after_removal);
// If there are no longer any active entries, this attempt is finished. // If there are no longer any active entries, this attempt is finished.
if (id_to_request_map_.empty()) if (id_to_request_map_.empty())
this->OnConnectionAttemptFinishedWithoutConnection(); this->OnConnectionAttemptFinishedWithoutConnection();
} }
void StartNextConnectToDeviceOperation() {
DCHECK(!current_operation_);
current_operation_ = connect_to_device_operation_factory_->CreateOperation(
this->connection_attempt_details().device_id_pair(),
GetHighestRemainingConnectionPriority(),
base::BindOnce(
&ConnectionAttemptBase<
FailureDetailType>::OnConnectToDeviceOperationSuccess,
weak_ptr_factory_.GetWeakPtr()),
base::BindOnce(
&ConnectionAttemptBase<
FailureDetailType>::OnConnectToDeviceOperationFailure,
weak_ptr_factory_.GetWeakPtr()));
}
void OnConnectToDeviceOperationSuccess( void OnConnectToDeviceOperationSuccess(
std::unique_ptr<AuthenticatedChannel> authenticated_channel) { std::unique_ptr<AuthenticatedChannel> authenticated_channel) {
DCHECK(current_operation_); DCHECK(operation_);
current_operation_.reset(); operation_.reset();
this->OnConnectionAttemptSucceeded(std::move(authenticated_channel)); this->OnConnectionAttemptSucceeded(std::move(authenticated_channel));
} }
void OnConnectToDeviceOperationFailure(FailureDetailType failure_detail) { void OnConnectToDeviceOperationFailure(FailureDetailType failure_detail) {
DCHECK(current_operation_);
current_operation_.reset();
// After all requests have been notified of the failure (below), start a
// retry attempt. If all requests give up without a connection, this
// instance's delegate will be notified and will, in response, delete
// |this|. Thus, the retry attempt is posted as a task using a WeakPtr to
// ensure that a segfault will not occur.
task_runner_->PostTask(
FROM_HERE,
base::BindOnce(
&ConnectionAttemptBase<
FailureDetailType>::StartNextConnectToDeviceOperation,
weak_ptr_factory_.GetWeakPtr()));
for (auto& map_entry : id_to_request_map_) for (auto& map_entry : id_to_request_map_)
map_entry.second->HandleConnectionFailure(failure_detail); map_entry.second->HandleConnectionFailure(failure_detail);
} }
...@@ -188,17 +166,10 @@ class ConnectionAttemptBase : public ConnectionAttempt<FailureDetailType>, ...@@ -188,17 +166,10 @@ class ConnectionAttemptBase : public ConnectionAttempt<FailureDetailType>,
return highest_priority; return highest_priority;
} }
std::unique_ptr<ConnectToDeviceOperationFactory<FailureDetailType>> std::unique_ptr<ConnectToDeviceOperation<FailureDetailType>> operation_;
connect_to_device_operation_factory_; base::flat_map<base::UnguessableToken,
std::unique_ptr<PendingConnectionRequest<FailureDetailType>>>
std::unique_ptr<ConnectToDeviceOperation<FailureDetailType>>
current_operation_;
std::unordered_map<
base::UnguessableToken,
std::unique_ptr<PendingConnectionRequest<FailureDetailType>>,
base::UnguessableTokenHash>
id_to_request_map_; id_to_request_map_;
scoped_refptr<base::TaskRunner> task_runner_;
base::WeakPtrFactory<ConnectionAttemptBase<FailureDetailType>> base::WeakPtrFactory<ConnectionAttemptBase<FailureDetailType>>
weak_ptr_factory_; weak_ptr_factory_;
......
...@@ -18,7 +18,6 @@ ...@@ -18,7 +18,6 @@
#include "chromeos/services/secure_channel/device_id_pair.h" #include "chromeos/services/secure_channel/device_id_pair.h"
#include "chromeos/services/secure_channel/fake_client_connection_parameters.h" #include "chromeos/services/secure_channel/fake_client_connection_parameters.h"
#include "chromeos/services/secure_channel/fake_connect_to_device_operation.h" #include "chromeos/services/secure_channel/fake_connect_to_device_operation.h"
#include "chromeos/services/secure_channel/fake_connect_to_device_operation_factory.h"
#include "chromeos/services/secure_channel/fake_connection_attempt_delegate.h" #include "chromeos/services/secure_channel/fake_connection_attempt_delegate.h"
#include "chromeos/services/secure_channel/fake_connection_delegate.h" #include "chromeos/services/secure_channel/fake_connection_delegate.h"
#include "chromeos/services/secure_channel/fake_pending_connection_request.h" #include "chromeos/services/secure_channel/fake_pending_connection_request.h"
...@@ -41,20 +40,44 @@ const char kTestLocalDeviceId[] = "testLocalDeviceId"; ...@@ -41,20 +40,44 @@ const char kTestLocalDeviceId[] = "testLocalDeviceId";
class TestConnectionAttempt class TestConnectionAttempt
: public ConnectionAttemptBase<BleInitiatorFailureType> { : public ConnectionAttemptBase<BleInitiatorFailureType> {
public: public:
TestConnectionAttempt( TestConnectionAttempt(FakeConnectionAttemptDelegate* delegate)
std::unique_ptr<FakeConnectToDeviceOperationFactory<
BleInitiatorFailureType>> connect_to_device_operation_factory,
FakeConnectionAttemptDelegate* delegate,
scoped_refptr<base::TestSimpleTaskRunner> task_runner)
: ConnectionAttemptBase<BleInitiatorFailureType>( : ConnectionAttemptBase<BleInitiatorFailureType>(
std::move(connect_to_device_operation_factory),
delegate, delegate,
ConnectionAttemptDetails(kTestRemoteDeviceId, ConnectionAttemptDetails(kTestRemoteDeviceId,
kTestLocalDeviceId, kTestLocalDeviceId,
ConnectionMedium::kBluetoothLowEnergy, ConnectionMedium::kBluetoothLowEnergy,
ConnectionRole::kListenerRole), ConnectionRole::kListenerRole)) {}
task_runner) {}
~TestConnectionAttempt() override = default; ~TestConnectionAttempt() override = default;
FakeConnectToDeviceOperation<BleInitiatorFailureType>* fake_operation() {
return fake_operation_;
}
private:
// ConnectionAttemptBase<BleInitiatorFailureType>:
std::unique_ptr<ConnectToDeviceOperation<BleInitiatorFailureType>>
CreateConnectToDeviceOperation(
const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority,
ConnectToDeviceOperation<
BleInitiatorFailureType>::ConnectionSuccessCallback success_callback,
const ConnectToDeviceOperation<BleInitiatorFailureType>::
ConnectionFailedCallback& failure_callback) override {
EXPECT_FALSE(fake_operation_);
auto fake_operation =
std::make_unique<FakeConnectToDeviceOperation<BleInitiatorFailureType>>(
std::move(success_callback), failure_callback, connection_priority);
fake_operation_ = fake_operation.get();
return std::move(fake_operation);
}
FakeConnectToDeviceOperation<BleInitiatorFailureType>* fake_operation_ =
nullptr;
DISALLOW_COPY_AND_ASSIGN(TestConnectionAttempt);
}; };
} // namespace } // namespace
...@@ -67,17 +90,10 @@ class SecureChannelConnectionAttemptBaseTest : public testing::Test { ...@@ -67,17 +90,10 @@ class SecureChannelConnectionAttemptBaseTest : public testing::Test {
void SetUp() override { void SetUp() override {
fake_authenticated_channel_ = std::make_unique<FakeAuthenticatedChannel>(); fake_authenticated_channel_ = std::make_unique<FakeAuthenticatedChannel>();
auto fake_operation_factory = std::make_unique<
FakeConnectToDeviceOperationFactory<BleInitiatorFailureType>>();
fake_operation_factory_ = fake_operation_factory.get();
fake_delegate_ = std::make_unique<FakeConnectionAttemptDelegate>(); fake_delegate_ = std::make_unique<FakeConnectionAttemptDelegate>();
test_task_runner_ = base::MakeRefCounted<base::TestSimpleTaskRunner>(); connection_attempt_ =
std::make_unique<TestConnectionAttempt>(fake_delegate_.get());
connection_attempt_ = std::make_unique<TestConnectionAttempt>(
std::move(fake_operation_factory), fake_delegate_.get(),
test_task_runner_);
} }
void TearDown() override { void TearDown() override {
...@@ -86,25 +102,24 @@ class SecureChannelConnectionAttemptBaseTest : public testing::Test { ...@@ -86,25 +102,24 @@ class SecureChannelConnectionAttemptBaseTest : public testing::Test {
if (is_extract_client_data_test_) if (is_extract_client_data_test_)
return; return;
bool should_test_active_operation_canceled = active_operation_ != nullptr; // If the operation did not complete successfully, the operation should be
// canceled.
bool should_operation_be_canceled_in_destructor =
fake_delegate_->authenticated_channel() == nullptr;
if (should_test_active_operation_canceled) { if (should_operation_be_canceled_in_destructor) {
EXPECT_FALSE(active_operation_->canceled()); EXPECT_FALSE(fake_operation()->canceled());
EXPECT_FALSE(was_active_operation_canceled_in_teardown_); EXPECT_FALSE(was_operation_canceled_in_tear_down_);
active_operation_->set_destructor_callback( fake_operation()->set_cancel_callback(
base::BindOnce(&SecureChannelConnectionAttemptBaseTest:: base::BindOnce(&SecureChannelConnectionAttemptBaseTest::
OnActiveOperationDeletedInTeardown, OnOperationCanceledInTeardown,
base::Unretained(this))); base::Unretained(this)));
} }
connection_attempt_.reset(); connection_attempt_.reset();
if (should_test_active_operation_canceled) if (should_operation_be_canceled_in_destructor)
EXPECT_TRUE(was_active_operation_canceled_in_teardown_); EXPECT_TRUE(was_operation_canceled_in_tear_down_);
// Ensure that running any posted tasks after |connection_attempt_| is
// deleted do not cause segfaults.
test_task_runner_->RunUntilIdle();
} }
FakePendingConnectionRequest<BleInitiatorFailureType>* AddNewRequest( FakePendingConnectionRequest<BleInitiatorFailureType>* AddNewRequest(
...@@ -130,24 +145,7 @@ class SecureChannelConnectionAttemptBaseTest : public testing::Test { ...@@ -130,24 +145,7 @@ class SecureChannelConnectionAttemptBaseTest : public testing::Test {
EXPECT_EQ(1u, active_requests_.erase(request)); EXPECT_EQ(1u, active_requests_.erase(request));
} }
FakeConnectToDeviceOperation<BleInitiatorFailureType>* void FailOperation() {
GetLastCreatedOperation(size_t expected_num_created) {
VerifyNumOperationsCreated(expected_num_created);
active_operation_ = fake_operation_factory_->last_created_instance();
return active_operation_;
}
void VerifyNumOperationsCreated(size_t expected_num_created) {
EXPECT_EQ(expected_num_created,
fake_operation_factory_->num_instances_created());
}
// If |should_run_next_operation| is true, the next operation is started
// after the current one has failed. |should_run_next_operation| should be
// false if the test requires that request failures be processed.
void FailOperation(
FakeConnectToDeviceOperation<BleInitiatorFailureType>* operation,
bool should_run_next_operation = true) {
// Before failing the operation, check to see how many failure details each // Before failing the operation, check to see how many failure details each
// request has been passed. // request has been passed.
std::unordered_map<base::UnguessableToken, size_t, std::unordered_map<base::UnguessableToken, size_t,
...@@ -158,10 +156,8 @@ class SecureChannelConnectionAttemptBaseTest : public testing::Test { ...@@ -158,10 +156,8 @@ class SecureChannelConnectionAttemptBaseTest : public testing::Test {
request->handled_failure_details().size(); request->handled_failure_details().size();
} }
EXPECT_EQ(active_operation_, operation); fake_operation()->OnFailedConnectionAttempt(
operation->OnFailedConnectionAttempt(
BleInitiatorFailureType::kAuthenticationError); BleInitiatorFailureType::kAuthenticationError);
active_operation_ = nullptr;
// Now, ensure that each active request had one additional failure detail // Now, ensure that each active request had one additional failure detail
// added, and verify that it was kAuthenticationError. // added, and verify that it was kAuthenticationError.
...@@ -171,20 +167,14 @@ class SecureChannelConnectionAttemptBaseTest : public testing::Test { ...@@ -171,20 +167,14 @@ class SecureChannelConnectionAttemptBaseTest : public testing::Test {
EXPECT_EQ(BleInitiatorFailureType::kAuthenticationError, EXPECT_EQ(BleInitiatorFailureType::kAuthenticationError,
request->handled_failure_details().back()); request->handled_failure_details().back());
} }
if (should_run_next_operation)
RunNextOperationTask();
} }
void FinishOperationSuccessfully( void FinishOperationSuccessfully() {
FakeConnectToDeviceOperation<BleInitiatorFailureType>* operation) {
EXPECT_TRUE(fake_authenticated_channel_); EXPECT_TRUE(fake_authenticated_channel_);
auto* fake_authenticated_channel_raw = fake_authenticated_channel_.get(); auto* fake_authenticated_channel_raw = fake_authenticated_channel_.get();
EXPECT_EQ(active_operation_, operation); fake_operation()->OnSuccessfulConnectionAttempt(
operation->OnSuccessfulConnectionAttempt(
std::move(fake_authenticated_channel_)); std::move(fake_authenticated_channel_));
active_operation_ = nullptr;
// |fake_delegate_|'s delegate should have received the // |fake_delegate_|'s delegate should have received the
// AuthenticatedChannel. // AuthenticatedChannel.
...@@ -195,12 +185,6 @@ class SecureChannelConnectionAttemptBaseTest : public testing::Test { ...@@ -195,12 +185,6 @@ class SecureChannelConnectionAttemptBaseTest : public testing::Test {
fake_delegate_->authenticated_channel()); fake_delegate_->authenticated_channel());
} }
void RunNextOperationTask() {
// This function should only be run if there actually is a pending task.
EXPECT_EQ(1u, test_task_runner_->NumPendingTasks());
test_task_runner_->RunPendingTasks();
}
void VerifyDelegateNotNotified() { void VerifyDelegateNotNotified() {
EXPECT_FALSE(fake_delegate_->connection_details()); EXPECT_FALSE(fake_delegate_->connection_details());
EXPECT_FALSE(fake_delegate_->connection_attempt_details()); EXPECT_FALSE(fake_delegate_->connection_attempt_details());
...@@ -222,24 +206,23 @@ class SecureChannelConnectionAttemptBaseTest : public testing::Test { ...@@ -222,24 +206,23 @@ class SecureChannelConnectionAttemptBaseTest : public testing::Test {
ExtractClientConnectionParameters(std::move(connection_attempt_)); ExtractClientConnectionParameters(std::move(connection_attempt_));
} }
FakeConnectToDeviceOperation<BleInitiatorFailureType>* fake_operation() {
return connection_attempt_->fake_operation();
}
private: private:
void OnActiveOperationDeletedInTeardown() { void OnOperationCanceledInTeardown() {
was_active_operation_canceled_in_teardown_ = true; was_operation_canceled_in_tear_down_ = true;
} }
const base::test::ScopedTaskEnvironment scoped_task_environment_; const base::test::ScopedTaskEnvironment scoped_task_environment_;
FakeConnectToDeviceOperationFactory<BleInitiatorFailureType>*
fake_operation_factory_;
std::unique_ptr<FakeConnectionAttemptDelegate> fake_delegate_; std::unique_ptr<FakeConnectionAttemptDelegate> fake_delegate_;
scoped_refptr<base::TestSimpleTaskRunner> test_task_runner_;
std::unique_ptr<FakeAuthenticatedChannel> fake_authenticated_channel_; std::unique_ptr<FakeAuthenticatedChannel> fake_authenticated_channel_;
std::set<FakePendingConnectionRequest<BleInitiatorFailureType>*> std::set<FakePendingConnectionRequest<BleInitiatorFailureType>*>
active_requests_; active_requests_;
FakeConnectToDeviceOperation<BleInitiatorFailureType>* active_operation_ = bool was_operation_canceled_in_tear_down_ = false;
nullptr;
bool was_active_operation_canceled_in_teardown_ = false;
bool is_extract_client_data_test_ = false; bool is_extract_client_data_test_ = false;
...@@ -250,22 +233,18 @@ class SecureChannelConnectionAttemptBaseTest : public testing::Test { ...@@ -250,22 +233,18 @@ class SecureChannelConnectionAttemptBaseTest : public testing::Test {
TEST_F(SecureChannelConnectionAttemptBaseTest, SingleRequest_Success) { TEST_F(SecureChannelConnectionAttemptBaseTest, SingleRequest_Success) {
AddNewRequest(ConnectionPriority::kLow); AddNewRequest(ConnectionPriority::kLow);
FakeConnectToDeviceOperation<BleInitiatorFailureType>* operation = EXPECT_EQ(ConnectionPriority::kLow, fake_operation()->connection_priority());
GetLastCreatedOperation(1u /* expected_num_created */); FinishOperationSuccessfully();
EXPECT_EQ(ConnectionPriority::kLow, operation->connection_priority());
FinishOperationSuccessfully(operation);
} }
TEST_F(SecureChannelConnectionAttemptBaseTest, SingleRequest_Fails) { TEST_F(SecureChannelConnectionAttemptBaseTest, SingleRequest_Fails) {
FakePendingConnectionRequest<BleInitiatorFailureType>* request = FakePendingConnectionRequest<BleInitiatorFailureType>* request =
AddNewRequest(ConnectionPriority::kLow); AddNewRequest(ConnectionPriority::kLow);
FakeConnectToDeviceOperation<BleInitiatorFailureType>* operation = EXPECT_EQ(ConnectionPriority::kLow, fake_operation()->connection_priority());
GetLastCreatedOperation(1u /* expected_num_created */);
EXPECT_EQ(ConnectionPriority::kLow, operation->connection_priority());
// Fail the operation; the delegate should not have been notified since no // Fail the operation; the delegate should not have been notified since no
// request has yet indicated failure. // request has yet indicated failure.
FailOperation(operation, false /* should_run_next_operation */); FailOperation();
VerifyDelegateNotNotified(); VerifyDelegateNotNotified();
FinishRequestWithoutConnection( FinishRequestWithoutConnection(
...@@ -286,49 +265,39 @@ TEST_F(SecureChannelConnectionAttemptBaseTest, SingleRequest_Canceled) { ...@@ -286,49 +265,39 @@ TEST_F(SecureChannelConnectionAttemptBaseTest, SingleRequest_Canceled) {
TEST_F(SecureChannelConnectionAttemptBaseTest, SingleRequest_FailThenSuccess) { TEST_F(SecureChannelConnectionAttemptBaseTest, SingleRequest_FailThenSuccess) {
AddNewRequest(ConnectionPriority::kLow); AddNewRequest(ConnectionPriority::kLow);
FakeConnectToDeviceOperation<BleInitiatorFailureType>* operation1 = EXPECT_EQ(ConnectionPriority::kLow, fake_operation()->connection_priority());
GetLastCreatedOperation(1u /* expected_num_created */);
EXPECT_EQ(ConnectionPriority::kLow, operation1->connection_priority());
// Fail the operation; the delegate should not have been notified since no // Fail the operation; the delegate should not have been notified since no
// request has yet indicated failure. // request has yet indicated failure.
FailOperation(operation1); FailOperation();
VerifyDelegateNotNotified(); VerifyDelegateNotNotified();
FakeConnectToDeviceOperation<BleInitiatorFailureType>* operation2 = EXPECT_EQ(ConnectionPriority::kLow, fake_operation()->connection_priority());
GetLastCreatedOperation(2u /* expected_num_created */); FinishOperationSuccessfully();
EXPECT_EQ(ConnectionPriority::kLow, operation2->connection_priority());
FinishOperationSuccessfully(operation2);
} }
TEST_F(SecureChannelConnectionAttemptBaseTest, TwoRequests_Success) { TEST_F(SecureChannelConnectionAttemptBaseTest, TwoRequests_Success) {
AddNewRequest(ConnectionPriority::kLow); AddNewRequest(ConnectionPriority::kLow);
FakeConnectToDeviceOperation<BleInitiatorFailureType>* operation = EXPECT_EQ(ConnectionPriority::kLow, fake_operation()->connection_priority());
GetLastCreatedOperation(1u /* expected_num_created */);
EXPECT_EQ(ConnectionPriority::kLow, operation->connection_priority());
// Add a second request; the first operation should still be active. // Add a second request; the first operation should still be active.
AddNewRequest(ConnectionPriority::kLow); AddNewRequest(ConnectionPriority::kLow);
VerifyNumOperationsCreated(1u /* expected_num_created */);
FinishOperationSuccessfully(operation); FinishOperationSuccessfully();
} }
TEST_F(SecureChannelConnectionAttemptBaseTest, TwoRequests_Fails) { TEST_F(SecureChannelConnectionAttemptBaseTest, TwoRequests_Fails) {
FakePendingConnectionRequest<BleInitiatorFailureType>* request1 = FakePendingConnectionRequest<BleInitiatorFailureType>* request1 =
AddNewRequest(ConnectionPriority::kLow); AddNewRequest(ConnectionPriority::kLow);
FakeConnectToDeviceOperation<BleInitiatorFailureType>* operation = EXPECT_EQ(ConnectionPriority::kLow, fake_operation()->connection_priority());
GetLastCreatedOperation(1u /* expected_num_created */);
EXPECT_EQ(ConnectionPriority::kLow, operation->connection_priority());
// Add a second request; the first operation should still be active. // Add a second request.
FakePendingConnectionRequest<BleInitiatorFailureType>* request2 = FakePendingConnectionRequest<BleInitiatorFailureType>* request2 =
AddNewRequest(ConnectionPriority::kLow); AddNewRequest(ConnectionPriority::kLow);
VerifyNumOperationsCreated(1u /* expected_num_created */);
// Fail the operation; the delegate should not have been notified since no // Fail the operation; the delegate should not have been notified since no
// request has yet indicated failure. // request has yet indicated failure.
FailOperation(operation, false /* should_run_next_operation */); FailOperation();
VerifyDelegateNotNotified(); VerifyDelegateNotNotified();
// Finish the first request; since a second request remains, the delegate // Finish the first request; since a second request remains, the delegate
...@@ -348,10 +317,8 @@ TEST_F(SecureChannelConnectionAttemptBaseTest, TwoRequests_Fails) { ...@@ -348,10 +317,8 @@ TEST_F(SecureChannelConnectionAttemptBaseTest, TwoRequests_Fails) {
TEST_F(SecureChannelConnectionAttemptBaseTest, TwoRequests_Canceled) { TEST_F(SecureChannelConnectionAttemptBaseTest, TwoRequests_Canceled) {
FakePendingConnectionRequest<BleInitiatorFailureType>* request1 = FakePendingConnectionRequest<BleInitiatorFailureType>* request1 =
AddNewRequest(ConnectionPriority::kLow); AddNewRequest(ConnectionPriority::kLow);
VerifyNumOperationsCreated(1u /* expected_num_created */);
FakePendingConnectionRequest<BleInitiatorFailureType>* request2 = FakePendingConnectionRequest<BleInitiatorFailureType>* request2 =
AddNewRequest(ConnectionPriority::kLow); AddNewRequest(ConnectionPriority::kLow);
VerifyNumOperationsCreated(1u /* expected_num_created */);
FinishRequestWithoutConnection( FinishRequestWithoutConnection(
request1, PendingConnectionRequestDelegate::FailedConnectionReason:: request1, PendingConnectionRequestDelegate::FailedConnectionReason::
...@@ -367,23 +334,17 @@ TEST_F(SecureChannelConnectionAttemptBaseTest, TwoRequests_Canceled) { ...@@ -367,23 +334,17 @@ TEST_F(SecureChannelConnectionAttemptBaseTest, TwoRequests_Canceled) {
TEST_F(SecureChannelConnectionAttemptBaseTest, TwoRequests_FailThenSuccess) { TEST_F(SecureChannelConnectionAttemptBaseTest, TwoRequests_FailThenSuccess) {
FakePendingConnectionRequest<BleInitiatorFailureType>* request1 = FakePendingConnectionRequest<BleInitiatorFailureType>* request1 =
AddNewRequest(ConnectionPriority::kLow); AddNewRequest(ConnectionPriority::kLow);
FakeConnectToDeviceOperation<BleInitiatorFailureType>* operation1 = EXPECT_EQ(ConnectionPriority::kLow, fake_operation()->connection_priority());
GetLastCreatedOperation(1u /* expected_num_created */);
EXPECT_EQ(ConnectionPriority::kLow, operation1->connection_priority());
// Fail the operation; a new operation should have been created. // Fail the operation.
FailOperation(operation1); FailOperation();
VerifyDelegateNotNotified(); VerifyDelegateNotNotified();
FakeConnectToDeviceOperation<BleInitiatorFailureType>* operation2 = EXPECT_EQ(ConnectionPriority::kLow, fake_operation()->connection_priority());
GetLastCreatedOperation(2u /* expected_num_created */);
EXPECT_EQ(ConnectionPriority::kLow, operation2->connection_priority());
// Add a second request; this should not result in a new operation. // Add a second request.
AddNewRequest(ConnectionPriority::kLow); AddNewRequest(ConnectionPriority::kLow);
VerifyNumOperationsCreated(2u /* expected_num_created */);
// Fail the second operation. FailOperation();
FailOperation(operation2, false /* should_run_next_operation */);
VerifyDelegateNotNotified(); VerifyDelegateNotNotified();
// Simulate the first request finishing due to failures; since a second // Simulate the first request finishing due to failures; since a second
...@@ -393,44 +354,40 @@ TEST_F(SecureChannelConnectionAttemptBaseTest, TwoRequests_FailThenSuccess) { ...@@ -393,44 +354,40 @@ TEST_F(SecureChannelConnectionAttemptBaseTest, TwoRequests_FailThenSuccess) {
PendingConnectionRequestDelegate::FailedConnectionReason::kRequestFailed); PendingConnectionRequestDelegate::FailedConnectionReason::kRequestFailed);
VerifyDelegateNotNotified(); VerifyDelegateNotNotified();
// Start the next operation running, and simulate it finishing successfully. EXPECT_EQ(ConnectionPriority::kLow, fake_operation()->connection_priority());
RunNextOperationTask(); FinishOperationSuccessfully();
FakeConnectToDeviceOperation<BleInitiatorFailureType>* operation3 =
GetLastCreatedOperation(3u /* expected_num_created */);
EXPECT_EQ(ConnectionPriority::kLow, operation3->connection_priority());
FinishOperationSuccessfully(operation3);
} }
TEST_F(SecureChannelConnectionAttemptBaseTest, ManyRequests_UpdatePriority) { TEST_F(SecureChannelConnectionAttemptBaseTest, ManyRequests_UpdatePriority) {
AddNewRequest(ConnectionPriority::kLow); AddNewRequest(ConnectionPriority::kLow);
FakeConnectToDeviceOperation<BleInitiatorFailureType>* operation = EXPECT_EQ(ConnectionPriority::kLow, fake_operation()->connection_priority());
GetLastCreatedOperation(1u /* expected_num_created */);
EXPECT_EQ(ConnectionPriority::kLow, operation->connection_priority());
// Add a medium-priority request. This should update the operation's priority // Add a medium-priority request. This should update the operation's priority
// as well. // as well.
FakePendingConnectionRequest<BleInitiatorFailureType>* request2 = FakePendingConnectionRequest<BleInitiatorFailureType>* request2 =
AddNewRequest(ConnectionPriority::kMedium); AddNewRequest(ConnectionPriority::kMedium);
EXPECT_EQ(ConnectionPriority::kMedium, operation->connection_priority()); EXPECT_EQ(ConnectionPriority::kMedium,
fake_operation()->connection_priority());
// Add a high-priority request and verify that the operation is updated. // Add a high-priority request and verify that the operation is updated.
FakePendingConnectionRequest<BleInitiatorFailureType>* request3 = FakePendingConnectionRequest<BleInitiatorFailureType>* request3 =
AddNewRequest(ConnectionPriority::kHigh); AddNewRequest(ConnectionPriority::kHigh);
EXPECT_EQ(ConnectionPriority::kHigh, operation->connection_priority()); EXPECT_EQ(ConnectionPriority::kHigh, fake_operation()->connection_priority());
// Remote the high-priority request; the operation should go back to medium. // Remote the high-priority request; the operation should go back to medium.
FinishRequestWithoutConnection( FinishRequestWithoutConnection(
request3, PendingConnectionRequestDelegate::FailedConnectionReason:: request3, PendingConnectionRequestDelegate::FailedConnectionReason::
kRequestCanceledByClient); kRequestCanceledByClient);
EXPECT_EQ(ConnectionPriority::kMedium, operation->connection_priority()); EXPECT_EQ(ConnectionPriority::kMedium,
fake_operation()->connection_priority());
// Remote the medium-priority request; the operation should go back to low. // Remote the medium-priority request; the operation should go back to low.
FinishRequestWithoutConnection( FinishRequestWithoutConnection(
request2, PendingConnectionRequestDelegate::FailedConnectionReason:: request2, PendingConnectionRequestDelegate::FailedConnectionReason::
kRequestCanceledByClient); kRequestCanceledByClient);
EXPECT_EQ(ConnectionPriority::kLow, operation->connection_priority()); EXPECT_EQ(ConnectionPriority::kLow, fake_operation()->connection_priority());
FinishOperationSuccessfully(operation); FinishOperationSuccessfully();
} }
TEST_F(SecureChannelConnectionAttemptBaseTest, TEST_F(SecureChannelConnectionAttemptBaseTest,
......
...@@ -42,6 +42,10 @@ class FakeConnectToDeviceOperation ...@@ -42,6 +42,10 @@ class FakeConnectToDeviceOperation
destructor_callback_ = std::move(destructor_callback); destructor_callback_ = std::move(destructor_callback);
} }
void set_cancel_callback(base::OnceClosure cancel_callback) {
cancel_callback_ = std::move(cancel_callback);
}
// Make On{Successful|Failed}ConnectionAttempt() public for testing. // Make On{Successful|Failed}ConnectionAttempt() public for testing.
using ConnectToDeviceOperation< using ConnectToDeviceOperation<
FailureDetailType>::OnSuccessfulConnectionAttempt; FailureDetailType>::OnSuccessfulConnectionAttempt;
...@@ -49,7 +53,12 @@ class FakeConnectToDeviceOperation ...@@ -49,7 +53,12 @@ class FakeConnectToDeviceOperation
private: private:
// ConnectToDeviceOperation<FailureDetailType>: // ConnectToDeviceOperation<FailureDetailType>:
void PerformCancellation() override { canceled_ = true; } void PerformCancellation() override {
canceled_ = true;
if (cancel_callback_)
std::move(cancel_callback_).Run();
}
void PerformUpdateConnectionPriority( void PerformUpdateConnectionPriority(
ConnectionPriority connection_priority) override { ConnectionPriority connection_priority) override {
...@@ -59,6 +68,7 @@ class FakeConnectToDeviceOperation ...@@ -59,6 +68,7 @@ class FakeConnectToDeviceOperation
bool canceled_ = false; bool canceled_ = false;
base::Optional<ConnectionPriority> updated_priority_; base::Optional<ConnectionPriority> updated_priority_;
base::OnceClosure destructor_callback_; base::OnceClosure destructor_callback_;
base::OnceClosure cancel_callback_;
DISALLOW_COPY_AND_ASSIGN(FakeConnectToDeviceOperation); DISALLOW_COPY_AND_ASSIGN(FakeConnectToDeviceOperation);
}; };
......
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROMEOS_SERVICES_SECURE_CHANNEL_FAKE_CONNECT_TO_DEVICE_OPERATION_FACTORY_H_
#define CHROMEOS_SERVICES_SECURE_CHANNEL_FAKE_CONNECT_TO_DEVICE_OPERATION_FACTORY_H_
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/optional.h"
#include "chromeos/services/secure_channel/connect_to_device_operation_factory.h"
#include "chromeos/services/secure_channel/device_id_pair.h"
#include "chromeos/services/secure_channel/fake_connect_to_device_operation_factory.h"
#include "chromeos/services/secure_channel/public/cpp/shared/connection_priority.h"
namespace chromeos {
namespace secure_channel {
// Fake ConnectToDeviceOperationFactory implementation.
template <typename FailureDetailType>
class FakeConnectToDeviceOperationFactory
: public ConnectToDeviceOperationFactory<FailureDetailType> {
public:
FakeConnectToDeviceOperationFactory() = default;
~FakeConnectToDeviceOperationFactory() override = default;
FakeConnectToDeviceOperation<FailureDetailType>* last_created_instance() {
return last_created_instance_;
}
const base::Optional<ConnectionPriority>& last_created_priority() const {
return last_created_priority_;
}
size_t num_instances_created() const { return num_instances_created_; }
private:
// ConnectToDeviceOperationFactory<FailureDetailType>:
std::unique_ptr<ConnectToDeviceOperation<FailureDetailType>> CreateOperation(
const DeviceIdPair& device_id_pair,
ConnectionPriority connection_priority,
typename ConnectToDeviceOperation<
FailureDetailType>::ConnectionSuccessCallback success_callback,
typename ConnectToDeviceOperation<FailureDetailType>::
ConnectionFailedCallback failure_callback) override {
auto instance =
std::make_unique<FakeConnectToDeviceOperation<FailureDetailType>>(
std::move(success_callback), std::move(failure_callback),
connection_priority);
last_created_instance_ = instance.get();
++num_instances_created_;
return instance;
}
FakeConnectToDeviceOperation<FailureDetailType>* last_created_instance_ =
nullptr;
base::Optional<ConnectionPriority> last_created_priority_;
size_t num_instances_created_ = 0u;
DISALLOW_COPY_AND_ASSIGN(FakeConnectToDeviceOperationFactory);
};
} // namespace secure_channel
} // namespace chromeos
#endif // CHROMEOS_SERVICES_SECURE_CHANNEL_FAKE_CONNECT_TO_DEVICE_OPERATION_FACTORY_H_
...@@ -58,6 +58,12 @@ class FakeConnectionAttempt : public ConnectionAttempt<FailureDetailType> { ...@@ -58,6 +58,12 @@ class FakeConnectionAttempt : public ConnectionAttempt<FailureDetailType> {
id_to_request_map_[request->GetRequestId()] = std::move(request); id_to_request_map_[request->GetRequestId()] = std::move(request);
} }
// PendingConnectionRequestDelegate:
void OnRequestFinishedWithoutConnection(
const base::UnguessableToken& request_id,
PendingConnectionRequestDelegate::FailedConnectionReason reason)
override {}
std::vector<std::unique_ptr<ClientConnectionParameters>> std::vector<std::unique_ptr<ClientConnectionParameters>>
ExtractClientConnectionParameters() override { ExtractClientConnectionParameters() override {
return std::move(client_data_for_extraction_); return std::move(client_data_for_extraction_);
......
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