Commit 6bb53282 authored by Kyle Horimoto's avatar Kyle Horimoto Committed by Commit Bot

[CrOS MultiDevice] Add AuthenticatedChannel.

This class represents a two-way communication channel which is
authenticated and encrypted.

This CL also integrates this class with the rest of the classes in
//chromeos/services/secure_channel.

Bug: 824568, 752273
Change-Id: Ic72a026002f2c229d20b9b355078e8b43c281119
Reviewed-on: https://chromium-review.googlesource.com/1058834
Commit-Queue: Kyle Horimoto <khorimoto@chromium.org>
Reviewed-by: default avatarRyan Hansberry <hansberry@chromium.org>
Cr-Commit-Position: refs/heads/master@{#558899}
parent fda35097
......@@ -6,6 +6,10 @@ assert(is_chromeos, "Non-ChromeOS builds cannot depend on //chromeos")
static_library("secure_channel") {
sources = [
"authenticated_channel.cc",
"authenticated_channel.h",
"authenticated_channel_impl.cc",
"authenticated_channel_impl.h",
"connect_to_device_operation.h",
"connect_to_device_operation_base.h",
"connect_to_device_operation_factory.h",
......@@ -31,6 +35,8 @@ static_library("test_support") {
testonly = true
sources = [
"fake_authenticated_channel.cc",
"fake_authenticated_channel.h",
"fake_connect_to_device_operation.cc",
"fake_connect_to_device_operation.h",
"fake_connect_to_device_operation_factory.cc",
......@@ -59,6 +65,7 @@ source_set("unit_tests") {
testonly = true
sources = [
"authenticated_channel_impl_unittest.cc",
"connect_to_device_operation_base_unittest.cc",
"connect_to_device_operation_factory_base_unittest.cc",
"connection_attempt_base_unittest.cc",
......
// 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/authenticated_channel.h"
#include "base/callback.h"
#include "base/guid.h"
namespace chromeos {
namespace secure_channel {
AuthenticatedChannel::Observer::~Observer() = default;
AuthenticatedChannel::AuthenticatedChannel()
: channel_id_(base::GenerateGUID()) {}
AuthenticatedChannel::~AuthenticatedChannel() = default;
bool AuthenticatedChannel::SendMessage(const std::string& feature,
const std::string& payload,
base::OnceClosure on_sent_callback) {
if (is_disconnected_)
return false;
PerformSendMessage(feature, payload, std::move(on_sent_callback));
return true;
}
void AuthenticatedChannel::AddObserver(Observer* observer) {
observer_list_.AddObserver(observer);
}
void AuthenticatedChannel::RemoveObserver(Observer* observer) {
observer_list_.RemoveObserver(observer);
}
void AuthenticatedChannel::NotifyDisconnected() {
is_disconnected_ = true;
// Make a copy before notifying observers to ensure that if one observer
// deletes |this| before the next observer is able to be processed, a segfault
// is prevented.
const std::string channel_id_copy = channel_id_;
for (auto& observer : observer_list_)
observer.OnDisconnected(channel_id_copy);
}
void AuthenticatedChannel::NotifyMessageReceived(const std::string& feature,
const std::string& payload) {
// Make a copy before notifying observers to ensure that if one observer
// deletes |this| before the next observer is able to be processed, a segfault
// is prevented.
const std::string channel_id_copy = channel_id_;
const std::string feature_copy = feature;
const std::string payload_copy = payload;
for (auto& observer : observer_list_)
observer.OnMessageReceived(channel_id_copy, feature_copy, payload_copy);
}
} // namespace secure_channel
} // namespace chromeos
// 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_AUTHENTICATED_CHANNEL_H_
#define CHROMEOS_SERVICES_SECURE_CHANNEL_AUTHENTICATED_CHANNEL_H_
#include <string>
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/observer_list.h"
namespace chromeos {
namespace secure_channel {
// A full-duplex communication channel which is guaranteed to be authenticated
// (i.e., the two sides of the channel both belong to the same underlying user).
// All messages sent and received over the channel are encrypted.
class AuthenticatedChannel {
public:
class Observer {
public:
virtual ~Observer();
virtual void OnDisconnected(const std::string& channel_id) = 0;
virtual void OnMessageReceived(const std::string& channel_id,
const std::string& feature,
const std::string& payload) = 0;
};
virtual ~AuthenticatedChannel();
// Sends a message with the specified |feature| and |payload|. Once the
// message has been sent, |on_sent_callback| will be invoked. Returns whether
// this AuthenticatedChannel was able to start sending the message; this
// function only fails if the underlying connection has been disconnected.
bool SendMessage(const std::string& feature,
const std::string& payload,
base::OnceClosure on_sent_callback);
// Note: Channel ID is guaranteed to be unique among all channels.
const std::string& channel_id() const { return channel_id_; }
bool is_disconnected() const { return is_disconnected_; }
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
protected:
AuthenticatedChannel();
// Performs the actual logic of sending the message. By the time this function
// is called, it has already been confirmed that the channel has not been
// disconnected.
virtual void PerformSendMessage(const std::string& feature,
const std::string& payload,
base::OnceClosure on_sent_callback) = 0;
void NotifyDisconnected();
void NotifyMessageReceived(const std::string& feature,
const std::string& payload);
private:
const std::string channel_id_;
base::ObserverList<Observer> observer_list_;
bool is_disconnected_ = false;
DISALLOW_COPY_AND_ASSIGN(AuthenticatedChannel);
};
} // namespace secure_channel
} // namespace chromeos
#endif // CHROMEOS_SERVICES_SECURE_CHANNEL_AUTHENTICATED_CHANNEL_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/authenticated_channel_impl.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/no_destructor.h"
#include "chromeos/components/proximity_auth/logging/logging.h"
namespace chromeos {
namespace secure_channel {
// static
AuthenticatedChannelImpl::Factory*
AuthenticatedChannelImpl::Factory::test_factory_ = nullptr;
// static
AuthenticatedChannelImpl::Factory* AuthenticatedChannelImpl::Factory::Get() {
if (test_factory_)
return test_factory_;
static base::NoDestructor<AuthenticatedChannelImpl::Factory> factory;
return factory.get();
}
// static
void AuthenticatedChannelImpl::Factory::SetFactoryForTesting(
Factory* test_factory) {
test_factory_ = test_factory;
}
std::unique_ptr<AuthenticatedChannel>
AuthenticatedChannelImpl::Factory::BuildInstance(
std::unique_ptr<cryptauth::SecureChannel> secure_channel) {
return base::WrapUnique(
new AuthenticatedChannelImpl(std::move(secure_channel)));
}
AuthenticatedChannelImpl::AuthenticatedChannelImpl(
std::unique_ptr<cryptauth::SecureChannel> secure_channel)
: AuthenticatedChannel(), secure_channel_(std::move(secure_channel)) {
// |secure_channel_| should be a valid and already authenticated.
DCHECK(secure_channel_);
DCHECK_EQ(secure_channel_->status(),
cryptauth::SecureChannel::Status::AUTHENTICATED);
secure_channel_->AddObserver(this);
}
AuthenticatedChannelImpl::~AuthenticatedChannelImpl() {
secure_channel_->RemoveObserver(this);
}
void AuthenticatedChannelImpl::PerformSendMessage(
const std::string& feature,
const std::string& payload,
base::OnceClosure on_sent_callback) {
DCHECK_EQ(secure_channel_->status(),
cryptauth::SecureChannel::Status::AUTHENTICATED);
int sequence_number = secure_channel_->SendMessage(feature, payload);
if (base::ContainsKey(sequence_number_to_callback_map_, sequence_number)) {
PA_LOG(ERROR) << "AuthenticatedChannelImpl::SendMessage(): Started sending "
<< "a message whose sequence number already exists in the "
<< "map.";
NOTREACHED();
}
sequence_number_to_callback_map_[sequence_number] =
std::move(on_sent_callback);
}
void AuthenticatedChannelImpl::OnSecureChannelStatusChanged(
cryptauth::SecureChannel* secure_channel,
const cryptauth::SecureChannel::Status& old_status,
const cryptauth::SecureChannel::Status& new_status) {
DCHECK_EQ(secure_channel_.get(), secure_channel);
// The only expected status change is AUTHENTICATED => DISCONNECTED.
DCHECK_EQ(old_status, cryptauth::SecureChannel::Status::AUTHENTICATED);
DCHECK_EQ(new_status, cryptauth::SecureChannel::Status::DISCONNECTED);
NotifyDisconnected();
}
void AuthenticatedChannelImpl::OnMessageReceived(
cryptauth::SecureChannel* secure_channel,
const std::string& feature,
const std::string& payload) {
DCHECK_EQ(secure_channel_.get(), secure_channel);
NotifyMessageReceived(feature, payload);
}
void AuthenticatedChannelImpl::OnMessageSent(
cryptauth::SecureChannel* secure_channel,
int sequence_number) {
DCHECK_EQ(secure_channel_.get(), secure_channel);
if (!base::ContainsKey(sequence_number_to_callback_map_, sequence_number)) {
PA_LOG(WARNING) << "AuthenticatedChannelImpl::OnMessageSent(): Sent a "
<< "message whose sequence number did not exist in the "
<< "map. Disregarding.";
// Note: No DCHECK() is performed here, since |secure_channel_| could have
// already been in the process of sending a message before the
// AuthenticatedChannelImpl object was created.
return;
}
std::move(sequence_number_to_callback_map_[sequence_number]).Run();
sequence_number_to_callback_map_.erase(sequence_number);
}
} // namespace secure_channel
} // namespace chromeos
// 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_AUTHENTICATED_CHANNEL_IMPL_H_
#define CHROMEOS_SERVICES_SECURE_CHANNEL_AUTHENTICATED_CHANNEL_IMPL_H_
#include <string>
#include "base/macros.h"
#include "chromeos/services/secure_channel/authenticated_channel.h"
#include "components/cryptauth/secure_channel.h"
namespace cryptauth {
class SecureChannel;
} // namespace cryptauth
namespace chromeos {
namespace secure_channel {
// Concrete AuthenticatedChannel implementation, whose send/receive mechanisms
// are implemented via SecureChannel.
class AuthenticatedChannelImpl : public AuthenticatedChannel,
public cryptauth::SecureChannel::Observer {
public:
class Factory {
public:
static Factory* Get();
static void SetFactoryForTesting(Factory* test_factory);
virtual std::unique_ptr<AuthenticatedChannel> BuildInstance(
std::unique_ptr<cryptauth::SecureChannel> secure_channel);
private:
static Factory* test_factory_;
};
~AuthenticatedChannelImpl() override;
// AuthenticatedChannel:
void PerformSendMessage(const std::string& feature,
const std::string& payload,
base::OnceClosure on_sent_callback) final;
private:
AuthenticatedChannelImpl(
std::unique_ptr<cryptauth::SecureChannel> secure_channel);
// cryptauth::SecureChannel::Observer:
void OnSecureChannelStatusChanged(
cryptauth::SecureChannel* secure_channel,
const cryptauth::SecureChannel::Status& old_status,
const cryptauth::SecureChannel::Status& new_status) override;
void OnMessageReceived(cryptauth::SecureChannel* secure_channel,
const std::string& feature,
const std::string& payload) override;
void OnMessageSent(cryptauth::SecureChannel* secure_channel,
int sequence_number) override;
std::unique_ptr<cryptauth::SecureChannel> secure_channel_;
std::unordered_map<int, base::OnceClosure> sequence_number_to_callback_map_;
DISALLOW_COPY_AND_ASSIGN(AuthenticatedChannelImpl);
};
} // namespace secure_channel
} // namespace chromeos
#endif // CHROMEOS_SERVICES_SECURE_CHANNEL_AUTHENTICATED_CHANNEL_IMPL_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/authenticated_channel_impl.h"
#include <memory>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include "base/bind.h"
#include "base/stl_util.h"
#include "base/test/scoped_task_environment.h"
#include "chromeos/services/secure_channel/fake_authenticated_channel.h"
#include "components/cryptauth/fake_connection.h"
#include "components/cryptauth/fake_secure_channel.h"
#include "components/cryptauth/remote_device_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
namespace secure_channel {
class SecureChannelAuthenticatedChannelImplTest : public testing::Test {
protected:
SecureChannelAuthenticatedChannelImplTest()
: test_device_(cryptauth::CreateRemoteDeviceForTest()) {}
~SecureChannelAuthenticatedChannelImplTest() override = default;
void SetUp() override {
auto fake_secure_channel = std::make_unique<cryptauth::FakeSecureChannel>(
std::make_unique<cryptauth::FakeConnection>(test_device_),
nullptr /* cryptauth_service */);
fake_secure_channel->ChangeStatus(
cryptauth::SecureChannel::Status::AUTHENTICATED);
fake_secure_channel_ = fake_secure_channel.get();
channel_ = AuthenticatedChannelImpl::Factory::Get()->BuildInstance(
std::move(fake_secure_channel));
test_observer_ = std::make_unique<FakeAuthenticatedChannelObserver>(
channel_->channel_id());
channel_->AddObserver(test_observer_.get());
}
void TearDown() override { channel_->RemoveObserver(test_observer_.get()); }
// Returns the sequence number for this SendMessageAndVerifyResults() call.
// To determine if the message has finished being sent, use
// HasMessageBeenSent(). If |expected_to_succeed| is false, -1 is returned.
int SendMessageAndVerifyResults(const std::string& feature,
const std::string& payload,
bool expected_to_succeed = true) {
size_t num_sent_messages_before_call =
fake_secure_channel_->sent_messages().size();
// Note: This relies on an implicit assumption that FakeSecureChannel starts
// its counter at 0. If that ever changes, this test needs to be updated.
int sequence_number = num_times_send_message_called_++;
bool success = channel_->SendMessage(
feature, payload,
base::BindOnce(
&SecureChannelAuthenticatedChannelImplTest::OnMessageSent,
base::Unretained(this), sequence_number));
EXPECT_EQ(expected_to_succeed, success);
if (!expected_to_succeed)
return -1;
std::vector<cryptauth::FakeSecureChannel::SentMessage> sent_messages =
fake_secure_channel_->sent_messages();
EXPECT_EQ(num_sent_messages_before_call + 1u, sent_messages.size());
EXPECT_EQ(feature, sent_messages.back().feature);
EXPECT_EQ(payload, sent_messages.back().payload);
return sequence_number;
}
bool HasMessageBeenSent(int sequence_number) {
// -1 is returned by SendMessageAndVerifyResults() when
// |expected_to_succeed| is false.
EXPECT_NE(-1, sequence_number);
return base::ContainsKey(sent_sequence_numbers_, sequence_number);
}
cryptauth::FakeSecureChannel* fake_secure_channel() {
return fake_secure_channel_;
}
FakeAuthenticatedChannelObserver* test_observer() {
return test_observer_.get();
}
private:
void OnMessageSent(int sequence_number) {
sent_sequence_numbers_.insert(sequence_number);
}
const base::test::ScopedTaskEnvironment scoped_task_environment_;
const cryptauth::RemoteDevice test_device_;
int num_times_send_message_called_ = 0;
std::unordered_set<int> sent_sequence_numbers_;
cryptauth::FakeSecureChannel* fake_secure_channel_;
std::unique_ptr<FakeAuthenticatedChannelObserver> test_observer_;
std::unique_ptr<AuthenticatedChannel> channel_;
DISALLOW_COPY_AND_ASSIGN(SecureChannelAuthenticatedChannelImplTest);
};
TEST_F(SecureChannelAuthenticatedChannelImplTest, SendReceiveAndDisconnect) {
const auto& received_messages = test_observer()->received_messages();
int sequence_number_1 = SendMessageAndVerifyResults("feature1", "payload1");
EXPECT_FALSE(HasMessageBeenSent(sequence_number_1));
fake_secure_channel()->CompleteSendingMessage(sequence_number_1);
EXPECT_TRUE(HasMessageBeenSent(sequence_number_1));
fake_secure_channel()->ReceiveMessage("feature1", "payload2");
EXPECT_EQ(1u, received_messages.size());
EXPECT_EQ("feature1", received_messages[0].first);
EXPECT_EQ("payload2", received_messages[0].second);
int sequence_number_2 = SendMessageAndVerifyResults("feature1", "payload3");
EXPECT_FALSE(HasMessageBeenSent(sequence_number_2));
fake_secure_channel()->CompleteSendingMessage(sequence_number_2);
EXPECT_TRUE(HasMessageBeenSent(sequence_number_2));
fake_secure_channel()->ReceiveMessage("feature1", "payload4");
EXPECT_EQ(2u, received_messages.size());
EXPECT_EQ("feature1", received_messages[1].first);
EXPECT_EQ("payload4", received_messages[1].second);
EXPECT_FALSE(test_observer()->has_been_notified_of_disconnection());
fake_secure_channel()->ChangeStatus(
cryptauth::SecureChannel::Status::DISCONNECTED);
EXPECT_TRUE(test_observer()->has_been_notified_of_disconnection());
SendMessageAndVerifyResults("feature1", "payload5",
false /* expected_to_succeed */);
}
TEST_F(SecureChannelAuthenticatedChannelImplTest, SendReceive_Async) {
const auto& received_messages = test_observer()->received_messages();
// Start sending a message, but do not complete it.
int sequence_number_1 = SendMessageAndVerifyResults("feature1", "payload1");
EXPECT_FALSE(HasMessageBeenSent(sequence_number_1));
// Receive a message for a different feature.
fake_secure_channel()->ReceiveMessage("feature2", "payload2");
EXPECT_EQ(1u, received_messages.size());
EXPECT_EQ("feature2", received_messages[0].first);
EXPECT_EQ("payload2", received_messages[0].second);
// Finish sending the first message.
EXPECT_FALSE(HasMessageBeenSent(sequence_number_1));
fake_secure_channel()->CompleteSendingMessage(sequence_number_1);
EXPECT_TRUE(HasMessageBeenSent(sequence_number_1));
// Start sending a second message for a different feature, but do not complete
// it.
int sequence_number_2 = SendMessageAndVerifyResults("feature3", "payload3");
EXPECT_FALSE(HasMessageBeenSent(sequence_number_2));
// Receive a message for yet another feature.
fake_secure_channel()->ReceiveMessage("feature4", "payload4");
EXPECT_EQ(2u, received_messages.size());
EXPECT_EQ("feature4", received_messages[1].first);
EXPECT_EQ("payload4", received_messages[1].second);
// Finish sending the second message.
EXPECT_FALSE(HasMessageBeenSent(sequence_number_2));
fake_secure_channel()->CompleteSendingMessage(sequence_number_2);
EXPECT_TRUE(HasMessageBeenSent(sequence_number_2));
}
} // namespace secure_channel
} // namespace chromeos
......@@ -9,14 +9,12 @@
#include "base/macros.h"
#include "chromeos/components/proximity_auth/logging/logging.h"
namespace cryptauth {
class SecureChannel;
} // namespace cryptauth
namespace chromeos {
namespace secure_channel {
class AuthenticatedChannel;
// Performs an operation which creates a connection to a remote device. A
// ConnectToDeviceOperation can only be used for a single connection attempt; if
// clients wish to retry a failed connection attempt, a new
......@@ -25,7 +23,7 @@ template <typename FailureDetailType>
class ConnectToDeviceOperation {
public:
using ConnectionSuccessCallback =
base::OnceCallback<void(std::unique_ptr<cryptauth::SecureChannel>)>;
base::OnceCallback<void(std::unique_ptr<AuthenticatedChannel>)>;
using ConnectionFailedCallback = base::OnceCallback<void(FailureDetailType)>;
virtual ~ConnectToDeviceOperation() {
......@@ -60,7 +58,7 @@ class ConnectToDeviceOperation {
virtual void PerformCancellation() = 0;
void OnSuccessfulConnectionAttempt(
std::unique_ptr<cryptauth::SecureChannel> authenticated_channel) {
std::unique_ptr<AuthenticatedChannel> authenticated_channel) {
if (!is_active_) {
PA_LOG(ERROR) << "ConnectToDeviceOperation::"
<< "OnSuccessfulConnectionAttempt(): Tried to "
......
......@@ -10,8 +10,7 @@
#include "base/memory/ref_counted.h"
#include "base/test/scoped_task_environment.h"
#include "base/test/test_simple_task_runner.h"
#include "components/cryptauth/fake_connection.h"
#include "components/cryptauth/fake_secure_channel.h"
#include "chromeos/services/secure_channel/fake_authenticated_channel.h"
#include "components/cryptauth/remote_device_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
......@@ -122,8 +121,8 @@ class SecureChannelConnectToDeviceOperationBaseTest : public testing::Test {
return test_operation_.get();
}
const cryptauth::SecureChannel* last_secure_channel() const {
return last_secure_channel_.get();
const AuthenticatedChannel* last_authenticated_channel() const {
return last_authenticated_channel_.get();
}
const std::string& last_failure_detail() const {
......@@ -134,8 +133,8 @@ class SecureChannelConnectToDeviceOperationBaseTest : public testing::Test {
private:
void OnSuccessfulConnectionAttempt(
std::unique_ptr<cryptauth::SecureChannel> secure_channel) {
last_secure_channel_ = std::move(secure_channel);
std::unique_ptr<AuthenticatedChannel> authenticated_channel) {
last_authenticated_channel_ = std::move(authenticated_channel);
}
void OnFailedConnectionAttempt(std::string failure_detail) {
......@@ -147,7 +146,7 @@ class SecureChannelConnectToDeviceOperationBaseTest : public testing::Test {
const base::test::ScopedTaskEnvironment scoped_task_environment_;
const cryptauth::RemoteDevice test_device_;
std::unique_ptr<cryptauth::SecureChannel> last_secure_channel_;
std::unique_ptr<AuthenticatedChannel> last_authenticated_channel_;
std::string last_failure_detail_;
bool destructor_callback_called_ = false;
......@@ -157,13 +156,12 @@ class SecureChannelConnectToDeviceOperationBaseTest : public testing::Test {
};
TEST_F(SecureChannelConnectToDeviceOperationBaseTest, Success) {
auto fake_secure_channel = std::make_unique<cryptauth::FakeSecureChannel>(
std::make_unique<cryptauth::FakeConnection>(test_device()),
nullptr /* cryptauth_service */);
auto* fake_secure_channel_raw = fake_secure_channel.get();
auto fake_authenticated_channel =
std::make_unique<FakeAuthenticatedChannel>();
auto* fake_authenticated_channel_raw = fake_authenticated_channel.get();
test_operation()->OnSuccessfulConnectionAttempt(
std::move(fake_secure_channel));
EXPECT_EQ(fake_secure_channel_raw, last_secure_channel());
std::move(fake_authenticated_channel));
EXPECT_EQ(fake_authenticated_channel_raw, last_authenticated_channel());
}
TEST_F(SecureChannelConnectToDeviceOperationBaseTest, Failure) {
......
......@@ -8,6 +8,7 @@
#include "base/bind_helpers.h"
#include "base/test/gtest_util.h"
#include "chromeos/services/secure_channel/authenticated_channel.h"
#include "chromeos/services/secure_channel/fake_connect_to_device_operation.h"
#include "components/cryptauth/remote_device_test_util.h"
#include "components/cryptauth/secure_channel.h"
......
......@@ -10,14 +10,12 @@
#include "chromeos/services/secure_channel/connection_attempt_delegate.h"
#include "chromeos/services/secure_channel/pending_connection_request.h"
namespace cryptauth {
class SecureChannel;
} // namespace cryptauth
namespace chromeos {
namespace secure_channel {
class AuthenticatedChannel;
// ConnectionAttempt represents an ongoing attempt to connect to a given device
// over a given medium. Each ConnectionAttempt is comprised of one or
// more PendingConnectionRequests and notifies its delegate when the attempt has
......@@ -64,7 +62,7 @@ class ConnectionAttempt {
std::unique_ptr<PendingConnectionRequest<FailureDetailType>> request) = 0;
void OnConnectionAttemptSucceeded(
std::unique_ptr<cryptauth::SecureChannel> secure_channel) {
std::unique_ptr<AuthenticatedChannel> authenticated_channel) {
if (has_notified_delegate_) {
PA_LOG(ERROR) << "ConnectionAttempt::OnConnectionAttemptSucceeded(): "
<< "Tried to alert delegate of a successful connection, "
......@@ -74,7 +72,7 @@ class ConnectionAttempt {
has_notified_delegate_ = true;
delegate_->OnConnectionAttemptSucceeded(attempt_id_,
std::move(secure_channel));
std::move(authenticated_channel));
}
void OnConnectionAttemptFinishedWithoutConnection() {
......
......@@ -24,6 +24,8 @@ namespace chromeos {
namespace secure_channel {
class AuthenticatedChannel;
// ConnectionAttempt implementation which stays active for as long as at least
// one of its requests has not yet completed. While a ConnectionAttemptBase is
// active, it starts one or more operations to connect to the device. If an
......@@ -114,10 +116,10 @@ class ConnectionAttemptBase : public ConnectionAttempt<FailureDetailType>,
}
void OnConnectToDeviceOperationSuccess(
std::unique_ptr<cryptauth::SecureChannel> secure_channel) {
std::unique_ptr<AuthenticatedChannel> authenticated_channel) {
DCHECK(current_operation_);
current_operation_.reset();
this->OnConnectionAttemptSucceeded(std::move(secure_channel));
this->OnConnectionAttemptSucceeded(std::move(authenticated_channel));
}
void OnConnectToDeviceOperationFailure(FailureDetailType failure_detail) {
......
......@@ -9,14 +9,12 @@
#include "base/bind.h"
#include "base/test/scoped_task_environment.h"
#include "base/test/test_simple_task_runner.h"
#include "chromeos/services/secure_channel/fake_authenticated_channel.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_pending_connection_request.h"
#include "chromeos/services/secure_channel/pending_connection_request_delegate.h"
#include "components/cryptauth/fake_connection.h"
#include "components/cryptauth/fake_secure_channel.h"
#include "components/cryptauth/remote_device_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
......@@ -50,10 +48,7 @@ class SecureChannelConnectionAttemptBaseTest : public testing::Test {
~SecureChannelConnectionAttemptBaseTest() override = default;
void SetUp() override {
fake_secure_channel_ = std::make_unique<cryptauth::FakeSecureChannel>(
std::make_unique<cryptauth::FakeConnection>(
cryptauth::CreateRemoteDeviceForTest()),
nullptr /* cryptauth_service */);
fake_authenticated_channel_ = std::make_unique<FakeAuthenticatedChannel>();
auto factory = std::make_unique<FakeConnectToDeviceOperationFactory>();
fake_operation_factory_ = factory.get();
......@@ -150,16 +145,19 @@ class SecureChannelConnectionAttemptBaseTest : public testing::Test {
}
void FinishOperationSuccessfully(FakeConnectToDeviceOperation* operation) {
EXPECT_TRUE(fake_secure_channel_);
auto* fake_secure_channel_raw = fake_secure_channel_.get();
EXPECT_TRUE(fake_authenticated_channel_);
auto* fake_authenticated_channel_raw = fake_authenticated_channel_.get();
EXPECT_EQ(active_operation_, operation);
operation->OnSuccessfulConnectionAttempt(std::move(fake_secure_channel_));
operation->OnSuccessfulConnectionAttempt(
std::move(fake_authenticated_channel_));
active_operation_ = nullptr;
// |fake_delegate_|'s delegate should have received the SecureChannel.
// |fake_delegate_|'s delegate should have received the
// AuthenticatedChannel.
EXPECT_EQ(connection_attempt_->attempt_id(), fake_delegate_->attempt_id());
EXPECT_EQ(fake_secure_channel_raw, fake_delegate_->secure_channel());
EXPECT_EQ(fake_authenticated_channel_raw,
fake_delegate_->authenticated_channel());
}
void RunNextOperationTask() {
......@@ -174,9 +172,9 @@ class SecureChannelConnectionAttemptBaseTest : public testing::Test {
void VerifyDelegateNotifiedOfFailure() {
// |fake_delegate_| should have received the failing attempt's ID but no
// SecureChannel.
// AuthenticatedChannel.
EXPECT_EQ(connection_attempt_->attempt_id(), fake_delegate_->attempt_id());
EXPECT_FALSE(fake_delegate_->secure_channel());
EXPECT_FALSE(fake_delegate_->authenticated_channel());
}
private:
......@@ -190,7 +188,7 @@ class SecureChannelConnectionAttemptBaseTest : public testing::Test {
std::unique_ptr<FakeConnectionAttemptDelegate> fake_delegate_;
scoped_refptr<base::TestSimpleTaskRunner> test_task_runner_;
std::unique_ptr<cryptauth::FakeSecureChannel> fake_secure_channel_;
std::unique_ptr<FakeAuthenticatedChannel> fake_authenticated_channel_;
std::set<FakePendingConnectionRequest*> active_requests_;
FakeConnectToDeviceOperation* active_operation_ = nullptr;
bool was_active_operation_canceled_in_teardown_ = false;
......
......@@ -10,14 +10,12 @@
#include "base/macros.h"
namespace cryptauth {
class SecureChannel;
} // namespace cryptauth
namespace chromeos {
namespace secure_channel {
class AuthenticatedChannel;
class ConnectionAttemptDelegate {
public:
ConnectionAttemptDelegate() = default;
......@@ -28,7 +26,7 @@ class ConnectionAttemptDelegate {
// ConnectionAttempt::attempt_id().
virtual void OnConnectionAttemptSucceeded(
const std::string& attempt_id,
std::unique_ptr<cryptauth::SecureChannel> secure_channel) = 0;
std::unique_ptr<AuthenticatedChannel> authenticated_channel) = 0;
// Invoked when a ConnectionAttempt has finished without achieving a
// connection to the remote device (due to cancellation by the client or
......
// 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/fake_authenticated_channel.h"
namespace chromeos {
namespace secure_channel {
FakeAuthenticatedChannel::FakeAuthenticatedChannel() : AuthenticatedChannel() {}
FakeAuthenticatedChannel::~FakeAuthenticatedChannel() = default;
void FakeAuthenticatedChannel::PerformSendMessage(
const std::string& feature,
const std::string& payload,
base::OnceClosure on_sent_callback) {
sent_messages_.push_back(
std::make_tuple(feature, payload, std::move(on_sent_callback)));
}
FakeAuthenticatedChannelObserver::FakeAuthenticatedChannelObserver(
const std::string& expected_channel_id)
: expected_channel_id_(expected_channel_id) {}
FakeAuthenticatedChannelObserver::~FakeAuthenticatedChannelObserver() = default;
void FakeAuthenticatedChannelObserver::OnDisconnected(
const std::string& channel_id) {
DCHECK_EQ(expected_channel_id_, channel_id);
has_been_notified_of_disconnection_ = true;
}
void FakeAuthenticatedChannelObserver::OnMessageReceived(
const std::string& channel_id,
const std::string& feature,
const std::string& payload) {
DCHECK_EQ(expected_channel_id_, channel_id);
received_messages_.push_back(std::make_pair(feature, payload));
}
} // namespace secure_channel
} // namespace chromeos
// 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_AUTHENTICATED_CHANNEL_H_
#define CHROMEOS_SERVICES_SECURE_CHANNEL_FAKE_AUTHENTICATED_CHANNEL_H_
#include <string>
#include <tuple>
#include <vector>
#include "base/callback.h"
#include "base/logging.h"
#include "base/macros.h"
#include "chromeos/services/secure_channel/authenticated_channel.h"
namespace chromeos {
namespace secure_channel {
// Test AuthenticatedChannel implementation.
class FakeAuthenticatedChannel : public AuthenticatedChannel {
public:
FakeAuthenticatedChannel();
~FakeAuthenticatedChannel() override;
const std::vector<std::tuple<std::string, std::string, base::OnceClosure>>&
sent_messages() {
return sent_messages_;
}
// AuthenticatedChannel:
void PerformSendMessage(const std::string& feature,
const std::string& payload,
base::OnceClosure on_sent_callback) override;
// Make Notify{Disconnected|MessageReceived}() public for testing.
using AuthenticatedChannel::NotifyDisconnected;
using AuthenticatedChannel::NotifyMessageReceived;
private:
std::vector<std::tuple<std::string, std::string, base::OnceClosure>>
sent_messages_;
DISALLOW_COPY_AND_ASSIGN(FakeAuthenticatedChannel);
};
// Test AuthenticatedChannel::Observer implementation.
class FakeAuthenticatedChannelObserver : public AuthenticatedChannel::Observer {
public:
FakeAuthenticatedChannelObserver(const std::string& expected_channel_id);
~FakeAuthenticatedChannelObserver() override;
bool has_been_notified_of_disconnection() {
return has_been_notified_of_disconnection_;
}
const std::vector<std::pair<std::string, std::string>>& received_messages() {
return received_messages_;
}
// AuthenticatedChannel::Observer:
void OnDisconnected(const std::string& channel_id) override;
void OnMessageReceived(const std::string& channel_id,
const std::string& feature,
const std::string& payload) override;
private:
const std::string expected_channel_id_;
bool has_been_notified_of_disconnection_ = false;
std::vector<std::pair<std::string, std::string>> received_messages_;
};
} // namespace secure_channel
} // namespace chromeos
#endif // CHROMEOS_SERVICES_SECURE_CHANNEL_FAKE_AUTHENTICATED_CHANNEL_H_
......@@ -5,7 +5,7 @@
#include "chromeos/services/secure_channel/fake_connection_attempt_delegate.h"
#include "base/logging.h"
#include "components/cryptauth/secure_channel.h"
#include "chromeos/services/secure_channel/authenticated_channel.h"
namespace chromeos {
......@@ -17,12 +17,12 @@ FakeConnectionAttemptDelegate::~FakeConnectionAttemptDelegate() = default;
void FakeConnectionAttemptDelegate::OnConnectionAttemptSucceeded(
const std::string& attempt_id,
std::unique_ptr<cryptauth::SecureChannel> secure_channel) {
std::unique_ptr<AuthenticatedChannel> authenticated_channel) {
DCHECK(attempt_id_.empty());
DCHECK(!attempt_id.empty());
attempt_id_ = attempt_id;
secure_channel_ = std::move(secure_channel);
authenticated_channel_ = std::move(authenticated_channel);
}
void FakeConnectionAttemptDelegate::
......
......@@ -10,21 +10,19 @@
#include "base/macros.h"
#include "chromeos/services/secure_channel/connection_attempt_delegate.h"
namespace cryptauth {
class SecureChannel;
} // namespace cryptauth
namespace chromeos {
namespace secure_channel {
class AuthenticatedChannel;
class FakeConnectionAttemptDelegate : public ConnectionAttemptDelegate {
public:
FakeConnectionAttemptDelegate();
~FakeConnectionAttemptDelegate() override;
const cryptauth::SecureChannel* secure_channel() const {
return secure_channel_.get();
const AuthenticatedChannel* authenticated_channel() const {
return authenticated_channel_.get();
}
const std::string& attempt_id() const { return attempt_id_; }
......@@ -33,12 +31,12 @@ class FakeConnectionAttemptDelegate : public ConnectionAttemptDelegate {
// ConnectionAttemptDelegate:
void OnConnectionAttemptSucceeded(
const std::string& attempt_id,
std::unique_ptr<cryptauth::SecureChannel> secure_channel) override;
std::unique_ptr<AuthenticatedChannel> authenticated_channel) override;
void OnConnectionAttemptFinishedWithoutConnection(
const std::string& attempt_id) override;
std::string attempt_id_;
std::unique_ptr<cryptauth::SecureChannel> secure_channel_;
std::unique_ptr<AuthenticatedChannel> authenticated_channel_;
DISALLOW_COPY_AND_ASSIGN(FakeConnectionAttemptDelegate);
};
......
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