Commit 799f491e authored by Ryan Hansberry's avatar Ryan Hansberry Committed by Commit Bot

[CrOS Multidevice] Integrate the SecureChannel API into proximity_auth::Messenger.

This injects a ClientChannel into Messenger, which is used if the
chromeos::features::kMultiDeviceApi is enabled. The ClientChannel is used
to send and receive messages with the remote device.

R=jhawkins@chromium.org, khorimoto@chromium.org

Bug: 824568, 752273
Change-Id: If927eb84d013657db823f8538d138beb9c2c16be
Reviewed-on: https://chromium-review.googlesource.com/1107482
Commit-Queue: Ryan Hansberry <hansberry@chromium.org>
Reviewed-by: default avatarKyle Horimoto <khorimoto@chromium.org>
Cr-Commit-Position: refs/heads/master@{#569798}
parent 84f58fd6
......@@ -5,6 +5,12 @@
#ifndef CHROMEOS_COMPONENTS_PROXIMITY_AUTH_MESSENGER_H_
#define CHROMEOS_COMPONENTS_PROXIMITY_AUTH_MESSENGER_H_
namespace chromeos {
namespace secure_channel {
class ClientChannel;
} // namespace secure_channel
} // namespace chromeos
namespace cryptauth {
class Connection;
class SecureContext;
......@@ -48,6 +54,8 @@ class Messenger {
// |GetSecureContext()| instead if you want to send and receive messages
// securely.
virtual cryptauth::Connection* GetConnection() const = 0;
virtual chromeos::secure_channel::ClientChannel* GetChannel() const = 0;
};
} // namespace proximity_auth
......
......@@ -15,6 +15,7 @@
#include "base/location.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "chromeos/chromeos_features.h"
#include "chromeos/components/proximity_auth/logging/logging.h"
#include "chromeos/components/proximity_auth/messenger_observer.h"
#include "chromeos/components/proximity_auth/remote_status_update.h"
......@@ -23,6 +24,7 @@
#include "components/cryptauth/wire_message.h"
namespace proximity_auth {
namespace {
// The key names of JSON fields for messages sent between the devices.
......@@ -63,17 +65,27 @@ std::string GetMessageType(const base::DictionaryValue& message) {
MessengerImpl::MessengerImpl(
std::unique_ptr<cryptauth::Connection> connection,
std::unique_ptr<cryptauth::SecureContext> secure_context)
std::unique_ptr<cryptauth::SecureContext> secure_context,
std::unique_ptr<chromeos::secure_channel::ClientChannel> channel)
: connection_(std::move(connection)),
secure_context_(std::move(secure_context)),
channel_(std::move(channel)),
weak_ptr_factory_(this) {
DCHECK(connection_->IsConnected());
connection_->AddObserver(this);
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi)) {
DCHECK(!channel_->is_disconnected());
channel_->AddObserver(this);
} else {
DCHECK(connection_->IsConnected());
connection_->AddObserver(this);
}
}
MessengerImpl::~MessengerImpl() {
if (connection_)
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi)) {
channel_->RemoveObserver(this);
} else if (connection_) {
connection_->RemoveObserver(this);
}
}
void MessengerImpl::AddObserver(MessengerObserver* observer) {
......@@ -85,6 +97,9 @@ void MessengerImpl::RemoveObserver(MessengerObserver* observer) {
}
bool MessengerImpl::SupportsSignIn() const {
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi))
return true;
return (secure_context_->GetProtocolVersion() ==
cryptauth::SecureContext::PROTOCOL_VERSION_THREE_ONE);
}
......@@ -135,14 +150,25 @@ void MessengerImpl::RequestUnlock() {
}
cryptauth::SecureContext* MessengerImpl::GetSecureContext() const {
DCHECK(!base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi));
return secure_context_.get();
}
cryptauth::Connection* MessengerImpl::GetConnection() const {
DCHECK(!base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi));
return connection_.get();
}
MessengerImpl::PendingMessage::PendingMessage() {}
chromeos::secure_channel::ClientChannel* MessengerImpl::GetChannel() const {
if (channel_->is_disconnected())
return nullptr;
return channel_.get();
}
MessengerImpl::PendingMessage::PendingMessage() = default;
MessengerImpl::PendingMessage::~PendingMessage() = default;
MessengerImpl::PendingMessage::PendingMessage(
const base::DictionaryValue& message)
......@@ -152,83 +178,41 @@ MessengerImpl::PendingMessage::PendingMessage(
MessengerImpl::PendingMessage::PendingMessage(const std::string& message)
: json_message(message), type(std::string()) {}
MessengerImpl::PendingMessage::~PendingMessage() {}
void MessengerImpl::ProcessMessageQueue() {
if (pending_message_ || queued_messages_.empty() ||
connection_->is_sending_message())
return;
pending_message_.reset(new PendingMessage(queued_messages_.front()));
queued_messages_.pop_front();
secure_context_->Encode(pending_message_->json_message,
base::Bind(&MessengerImpl::OnMessageEncoded,
weak_ptr_factory_.GetWeakPtr()));
}
void MessengerImpl::OnMessageEncoded(const std::string& encoded_message) {
connection_->SendMessage(std::make_unique<cryptauth::WireMessage>(
encoded_message, std::string(kEasyUnlockFeatureName)));
}
void MessengerImpl::OnMessageDecoded(const std::string& decoded_message) {
// The decoded message should be a JSON string.
std::unique_ptr<base::Value> message_value =
base::JSONReader::Read(decoded_message);
if (!message_value || !message_value->is_dict()) {
PA_LOG(ERROR) << "Unable to parse message as JSON:\n" << decoded_message;
if (pending_message_ || queued_messages_.empty())
return;
}
base::DictionaryValue* message;
bool success = message_value->GetAsDictionary(&message);
DCHECK(success);
std::string type;
if (!message->GetString(kTypeKey, &type)) {
PA_LOG(ERROR) << "Missing '" << kTypeKey << "' key in message:\n "
<< decoded_message;
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi) &&
channel_->is_disconnected()) {
return;
}
// Remote status updates can be received out of the blue.
if (type == kMessageTypeRemoteStatusUpdate) {
HandleRemoteStatusUpdateMessage(*message);
if (!base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi) &&
connection_->is_sending_message()) {
return;
}
// All other messages should only be received in response to a message that
// the messenger sent.
if (!pending_message_) {
PA_LOG(WARNING) << "Unexpected message received:\n" << decoded_message;
return;
}
std::string expected_type;
if (pending_message_->type == kMessageTypeDecryptRequest)
expected_type = kMessageTypeDecryptResponse;
else if (pending_message_->type == kMessageTypeUnlockRequest)
expected_type = kMessageTypeUnlockResponse;
else
NOTREACHED(); // There are no other message types that expect a response.
pending_message_.reset(new PendingMessage(queued_messages_.front()));
queued_messages_.pop_front();
if (type != expected_type) {
PA_LOG(ERROR) << "Unexpected '" << kTypeKey << "' value in message. "
<< "Expected '" << expected_type << "' but received '" << type
<< "'.";
return;
if (base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi)) {
channel_->SendMessage(
pending_message_->json_message,
base::BindOnce(&MessengerImpl::OnSendMessageResult,
weak_ptr_factory_.GetWeakPtr(), true /* success */));
} else {
secure_context_->Encode(
pending_message_->json_message,
base::BindRepeating(&MessengerImpl::OnMessageEncoded,
weak_ptr_factory_.GetWeakPtr()));
}
}
if (type == kMessageTypeDecryptResponse)
HandleDecryptResponseMessage(*message);
else if (type == kMessageTypeUnlockResponse)
HandleUnlockResponseMessage(*message);
else
NOTREACHED(); // There are no other message types that expect a response.
void MessengerImpl::OnMessageEncoded(const std::string& encoded_message) {
DCHECK(!base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi));
pending_message_.reset();
ProcessMessageQueue();
connection_->SendMessage(std::make_unique<cryptauth::WireMessage>(
encoded_message, kEasyUnlockFeatureName));
}
void MessengerImpl::HandleRemoteStatusUpdateMessage(
......@@ -270,6 +254,8 @@ void MessengerImpl::OnConnectionStatusChanged(
cryptauth::Connection* connection,
cryptauth::Connection::Status old_status,
cryptauth::Connection::Status new_status) {
DCHECK(!base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi));
DCHECK_EQ(connection, connection_.get());
if (new_status == cryptauth::Connection::Status::DISCONNECTED) {
PA_LOG(INFO) << "Secure channel disconnected...";
......@@ -284,14 +270,92 @@ void MessengerImpl::OnConnectionStatusChanged(
void MessengerImpl::OnMessageReceived(
const cryptauth::Connection& connection,
const cryptauth::WireMessage& wire_message) {
DCHECK(!base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi));
secure_context_->Decode(wire_message.payload(),
base::Bind(&MessengerImpl::OnMessageDecoded,
weak_ptr_factory_.GetWeakPtr()));
base::BindRepeating(&MessengerImpl::HandleMessage,
weak_ptr_factory_.GetWeakPtr()));
}
void MessengerImpl::OnSendCompleted(const cryptauth::Connection& connection,
const cryptauth::WireMessage& wire_message,
bool success) {
DCHECK(!base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi));
OnSendMessageResult(success);
}
void MessengerImpl::OnDisconnected() {
DCHECK(base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi));
for (auto& observer : observers_)
observer.OnDisconnected();
}
void MessengerImpl::OnMessageReceived(const std::string& payload) {
DCHECK(base::FeatureList::IsEnabled(chromeos::features::kMultiDeviceApi));
HandleMessage(payload);
}
void MessengerImpl::HandleMessage(const std::string& message) {
// The decoded message should be a JSON string.
std::unique_ptr<base::Value> message_value = base::JSONReader::Read(message);
if (!message_value || !message_value->is_dict()) {
PA_LOG(ERROR) << "Unable to parse message as JSON:\n" << message;
return;
}
base::DictionaryValue* message_dictionary;
bool success = message_value->GetAsDictionary(&message_dictionary);
DCHECK(success);
std::string type;
if (!message_dictionary->GetString(kTypeKey, &type)) {
PA_LOG(ERROR) << "Missing '" << kTypeKey << "' key in message:\n "
<< message;
return;
}
// Remote status updates can be received out of the blue.
if (type == kMessageTypeRemoteStatusUpdate) {
HandleRemoteStatusUpdateMessage(*message_dictionary);
return;
}
// All other messages should only be received in response to a message that
// the messenger sent.
if (!pending_message_) {
PA_LOG(WARNING) << "Unexpected message received: " << message;
return;
}
std::string expected_type;
if (pending_message_->type == kMessageTypeDecryptRequest)
expected_type = kMessageTypeDecryptResponse;
else if (pending_message_->type == kMessageTypeUnlockRequest)
expected_type = kMessageTypeUnlockResponse;
else
NOTREACHED(); // There are no other message types that expect a response.
if (type != expected_type) {
PA_LOG(ERROR) << "Unexpected '" << kTypeKey << "' value in message. "
<< "Expected '" << expected_type << "' but received '" << type
<< "'.";
return;
}
if (type == kMessageTypeDecryptResponse)
HandleDecryptResponseMessage(*message_dictionary);
else if (type == kMessageTypeUnlockResponse)
HandleUnlockResponseMessage(*message_dictionary);
else
NOTREACHED(); // There are no other message types that expect a response.
pending_message_.reset();
ProcessMessageQueue();
}
void MessengerImpl::OnSendMessageResult(bool success) {
if (!pending_message_) {
PA_LOG(ERROR) << "Unexpected message sent.";
return;
......
......@@ -12,6 +12,7 @@
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "chromeos/components/proximity_auth/messenger.h"
#include "chromeos/services/secure_channel/public/cpp/client/client_channel.h"
#include "components/cryptauth/connection.h"
#include "components/cryptauth/connection_observer.h"
......@@ -26,14 +27,24 @@ class SecureContext;
namespace proximity_auth {
// Concrete implementation of the Messenger interface.
class MessengerImpl : public Messenger, public cryptauth::ConnectionObserver {
class MessengerImpl : public Messenger,
public cryptauth::ConnectionObserver,
public chromeos::secure_channel::ClientChannel::Observer {
public:
// Constructs a messenger that sends and receives messages over the given
// |connection|, using the |secure_context| to encrypt and decrypt the
// messages. The |connection| must be connected. The messenger begins
// observing messages as soon as it is constructed.
MessengerImpl(std::unique_ptr<cryptauth::Connection> connection,
std::unique_ptr<cryptauth::SecureContext> secure_context);
// Constructs a messenger that sends and receives messages.
//
// If the |chromeos::features::kMultiDeviceApi| flag is enabled, messages are
// relayed over the provided |channel|, and |connection| and |secure_context|
// are ignored.
//
// If not, messages are relayed over |connection|, using the |secure_context|
// to encrypt and decrypt the messages. |channel| is ignored.
//
// The messenger begins observing messages as soon as it is constructed.
MessengerImpl(
std::unique_ptr<cryptauth::Connection> connection,
std::unique_ptr<cryptauth::SecureContext> secure_context,
std::unique_ptr<chromeos::secure_channel::ClientChannel> channel);
~MessengerImpl() override;
// Messenger:
......@@ -45,6 +56,7 @@ class MessengerImpl : public Messenger, public cryptauth::ConnectionObserver {
void RequestUnlock() override;
cryptauth::SecureContext* GetSecureContext() const override;
cryptauth::Connection* GetConnection() const override;
chromeos::secure_channel::ClientChannel* GetChannel() const override;
// Exposed for testing.
cryptauth::Connection* connection() { return connection_.get(); }
......@@ -72,9 +84,6 @@ class MessengerImpl : public Messenger, public cryptauth::ConnectionObserver {
// Called when the message is encoded so it can be sent over the connection.
void OnMessageEncoded(const std::string& encoded_message);
// Called when the message is decoded so it can be parsed.
void OnMessageDecoded(const std::string& decoded_message);
// Handles an incoming "status_update" |message|, parsing and notifying
// observers of the content.
void HandleRemoteStatusUpdateMessage(const base::DictionaryValue& message);
......@@ -98,6 +107,17 @@ class MessengerImpl : public Messenger, public cryptauth::ConnectionObserver {
const cryptauth::WireMessage& wire_message,
bool success) override;
// chromeos::secure_channel::ClientChannel::Observer:
void OnDisconnected() override;
void OnMessageReceived(const std::string& payload) override;
// Called when a message has been recevied from the remote device. The message
// should be a valid JSON string.
void HandleMessage(const std::string& message);
// Called when a message has been sent to the remote device.
void OnSendMessageResult(bool success);
// The connection used to send and receive events and status updates.
std::unique_ptr<cryptauth::Connection> connection_;
......@@ -105,6 +125,10 @@ class MessengerImpl : public Messenger, public cryptauth::ConnectionObserver {
// |connection_|.
std::unique_ptr<cryptauth::SecureContext> secure_context_;
// Authenticated end-to-end channel used to communicate with the remote
// device.
std::unique_ptr<chromeos::secure_channel::ClientChannel> channel_;
// The registered observers of |this_| messenger.
base::ObserverList<MessengerObserver> observers_;
......
......@@ -8,8 +8,11 @@
#include "base/callback.h"
#include "base/macros.h"
#include "base/test/scoped_feature_list.h"
#include "chromeos/chromeos_features.h"
#include "chromeos/components/proximity_auth/messenger_observer.h"
#include "chromeos/components/proximity_auth/remote_status_update.h"
#include "chromeos/services/secure_channel/public/cpp/client/fake_client_channel.h"
#include "components/cryptauth/connection.h"
#include "components/cryptauth/fake_connection.h"
#include "components/cryptauth/fake_secure_context.h"
......@@ -29,6 +32,7 @@ using testing::Return;
using testing::StrictMock;
namespace proximity_auth {
namespace {
const char kTestFeature[] = "testFeature";
......@@ -62,16 +66,15 @@ class MockMessengerObserver : public MessengerObserver {
class TestMessenger : public MessengerImpl {
public:
TestMessenger()
TestMessenger(
std::unique_ptr<chromeos::secure_channel::ClientChannel> channel)
: MessengerImpl(std::make_unique<cryptauth::FakeConnection>(
cryptauth::CreateRemoteDeviceRefForTest()),
std::make_unique<cryptauth::FakeSecureContext>()) {}
explicit TestMessenger(std::unique_ptr<cryptauth::Connection> connection)
: MessengerImpl(std::move(connection),
std::make_unique<cryptauth::FakeSecureContext>()) {}
std::make_unique<cryptauth::FakeSecureContext>(),
std::move(channel)) {}
~TestMessenger() override {}
// Simple getters for the mock objects owned by |this| messenger.
// Simple getters for the fake objects owned by |this| messenger_->
cryptauth::FakeConnection* GetFakeConnection() {
return static_cast<cryptauth::FakeConnection*>(connection());
}
......@@ -85,35 +88,88 @@ class TestMessenger : public MessengerImpl {
} // namespace
TEST(ProximityAuthMessengerImplTest, SupportsSignIn_ProtocolVersionThreeZero) {
TestMessenger messenger;
messenger.GetFakeSecureContext()->set_protocol_version(
class ProximityAuthMessengerImplTest : public testing::Test {
protected:
ProximityAuthMessengerImplTest() = default;
void SetMultiDeviceApiEnabled() {
scoped_feature_list_.InitAndEnableFeature(
chromeos::features::kMultiDeviceApi);
}
void CreateMessenger(bool is_multi_device_api_enabled) {
if (is_multi_device_api_enabled)
SetMultiDeviceApiEnabled();
auto fake_channel =
std::make_unique<chromeos::secure_channel::FakeClientChannel>();
fake_channel_ = fake_channel.get();
messenger_ = std::make_unique<TestMessenger>(std::move(fake_channel));
observer_ = std::make_unique<MockMessengerObserver>(messenger_.get());
}
std::string GetLastSentMessage() {
std::vector<std::pair<std::string, base::OnceClosure>>&
message_and_callbacks = fake_channel_->sent_messages();
std::move(message_and_callbacks[0].second).Run();
std::string message_copy = message_and_callbacks[0].first;
message_and_callbacks.erase(message_and_callbacks.begin());
return message_copy;
}
chromeos::secure_channel::FakeClientChannel* fake_channel_;
std::unique_ptr<TestMessenger> messenger_;
std::unique_ptr<MockMessengerObserver> observer_;
private:
base::test::ScopedFeatureList scoped_feature_list_;
DISALLOW_COPY_AND_ASSIGN(ProximityAuthMessengerImplTest);
};
TEST_F(ProximityAuthMessengerImplTest,
SupportsSignIn_ProtocolVersionThreeZero) {
CreateMessenger(false /* is_multi_device_api_enabled */);
messenger_->GetFakeSecureContext()->set_protocol_version(
cryptauth::SecureContext::PROTOCOL_VERSION_THREE_ZERO);
EXPECT_FALSE(messenger.SupportsSignIn());
EXPECT_FALSE(messenger_->SupportsSignIn());
}
TEST(ProximityAuthMessengerImplTest, SupportsSignIn_ProtocolVersionThreeOne) {
TestMessenger messenger;
messenger.GetFakeSecureContext()->set_protocol_version(
TEST_F(ProximityAuthMessengerImplTest, SupportsSignIn_ProtocolVersionThreeOne) {
CreateMessenger(false /* is_multi_device_api_enabled */);
messenger_->GetFakeSecureContext()->set_protocol_version(
cryptauth::SecureContext::PROTOCOL_VERSION_THREE_ONE);
EXPECT_TRUE(messenger.SupportsSignIn());
EXPECT_TRUE(messenger_->SupportsSignIn());
}
TEST_F(ProximityAuthMessengerImplTest, SupportsSignIn_MultiDeviceApiEnabled) {
CreateMessenger(true /* is_multi_device_api_enabled */);
EXPECT_TRUE(messenger_->SupportsSignIn());
}
TEST(ProximityAuthMessengerImplTest,
OnConnectionStatusChanged_ConnectionDisconnects) {
TestMessenger messenger;
MockMessengerObserver observer(&messenger);
TEST_F(ProximityAuthMessengerImplTest,
OnConnectionStatusChanged_ConnectionDisconnects) {
CreateMessenger(false /* is_multi_device_api_enabled */);
EXPECT_CALL(observer, OnDisconnected());
messenger.GetFakeConnection()->Disconnect();
EXPECT_CALL(*observer_, OnDisconnected());
messenger_->GetFakeConnection()->Disconnect();
}
TEST(ProximityAuthMessengerImplTest, DispatchUnlockEvent_SendsExpectedMessage) {
TestMessenger messenger;
messenger.DispatchUnlockEvent();
TEST_F(ProximityAuthMessengerImplTest,
DispatchUnlockEvent_SendsExpectedMessage) {
CreateMessenger(false /* is_multi_device_api_enabled */);
messenger_->DispatchUnlockEvent();
cryptauth::WireMessage* message =
messenger.GetFakeConnection()->current_message();
messenger_->GetFakeConnection()->current_message();
ASSERT_TRUE(message);
EXPECT_EQ(
"{"
......@@ -124,39 +180,56 @@ TEST(ProximityAuthMessengerImplTest, DispatchUnlockEvent_SendsExpectedMessage) {
EXPECT_EQ("easy_unlock", message->feature());
}
TEST(ProximityAuthMessengerImplTest, DispatchUnlockEvent_SendMessageFails) {
TestMessenger messenger;
MockMessengerObserver observer(&messenger);
messenger.DispatchUnlockEvent();
TEST_F(ProximityAuthMessengerImplTest,
DispatchUnlockEvent_SendsExpectedMessage_MultiDeviceApiEnabled) {
CreateMessenger(true /* is_multi_device_api_enabled */);
EXPECT_CALL(observer, OnUnlockEventSent(false));
messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(false);
messenger_->DispatchUnlockEvent();
EXPECT_EQ(
"{"
"\"name\":\"easy_unlock\","
"\"type\":\"event\""
"}",
GetLastSentMessage());
}
TEST(ProximityAuthMessengerImplTest, DispatchUnlockEvent_SendMessageSucceeds) {
TestMessenger messenger;
MockMessengerObserver observer(&messenger);
messenger.DispatchUnlockEvent();
TEST_F(ProximityAuthMessengerImplTest, DispatchUnlockEvent_SendMessageFails) {
CreateMessenger(false /* is_multi_device_api_enabled */);
messenger_->DispatchUnlockEvent();
EXPECT_CALL(observer, OnUnlockEventSent(true));
messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(true);
EXPECT_CALL(*observer_, OnUnlockEventSent(false));
messenger_->GetFakeConnection()->FinishSendingMessageWithSuccess(false);
}
TEST(ProximityAuthMessengerImplTest,
RequestDecryption_SignInUnsupported_DoesntSendMessage) {
TestMessenger messenger;
messenger.GetFakeSecureContext()->set_protocol_version(
TEST_F(ProximityAuthMessengerImplTest,
DispatchUnlockEvent_SendMessageSucceeds) {
CreateMessenger(false /* is_multi_device_api_enabled */);
messenger_->DispatchUnlockEvent();
EXPECT_CALL(*observer_, OnUnlockEventSent(true));
messenger_->GetFakeConnection()->FinishSendingMessageWithSuccess(true);
}
TEST_F(ProximityAuthMessengerImplTest,
RequestDecryption_SignInUnsupported_DoesntSendMessage) {
CreateMessenger(false /* is_multi_device_api_enabled */);
messenger_->GetFakeSecureContext()->set_protocol_version(
cryptauth::SecureContext::PROTOCOL_VERSION_THREE_ZERO);
messenger.RequestDecryption(kChallenge);
EXPECT_FALSE(messenger.GetFakeConnection()->current_message());
messenger_->RequestDecryption(kChallenge);
EXPECT_FALSE(messenger_->GetFakeConnection()->current_message());
}
TEST(ProximityAuthMessengerImplTest, RequestDecryption_SendsExpectedMessage) {
TestMessenger messenger;
messenger.RequestDecryption(kChallenge);
TEST_F(ProximityAuthMessengerImplTest, RequestDecryption_SendsExpectedMessage) {
CreateMessenger(false /* is_multi_device_api_enabled */);
messenger_->RequestDecryption(kChallenge);
cryptauth::WireMessage* message =
messenger.GetFakeConnection()->current_message();
messenger_->GetFakeConnection()->current_message();
ASSERT_TRUE(message);
EXPECT_EQ(
"{"
......@@ -166,13 +239,28 @@ TEST(ProximityAuthMessengerImplTest, RequestDecryption_SendsExpectedMessage) {
message->payload());
}
TEST(ProximityAuthMessengerImplTest,
RequestDecryption_SendsExpectedMessage_UsingBase64UrlEncoding) {
TestMessenger messenger;
messenger.RequestDecryption("\xFF\xE6");
TEST_F(ProximityAuthMessengerImplTest,
RequestDecryption_SendsExpectedMessage_MultiDeviceApiEnabled) {
CreateMessenger(true /* is_multi_device_api_enabled */);
messenger_->RequestDecryption(kChallenge);
EXPECT_EQ(
"{"
"\"encrypted_data\":\"YSBtb3N0IGRpZmZpY3VsdCBjaGFsbGVuZ2U=\","
"\"type\":\"decrypt_request\""
"}",
GetLastSentMessage());
}
TEST_F(ProximityAuthMessengerImplTest,
RequestDecryption_SendsExpectedMessage_UsingBase64UrlEncoding) {
CreateMessenger(false /* is_multi_device_api_enabled */);
messenger_->RequestDecryption("\xFF\xE6");
cryptauth::WireMessage* message =
messenger.GetFakeConnection()->current_message();
messenger_->GetFakeConnection()->current_message();
ASSERT_TRUE(message);
EXPECT_EQ(
"{"
......@@ -182,47 +270,73 @@ TEST(ProximityAuthMessengerImplTest,
message->payload());
}
TEST(ProximityAuthMessengerImplTest, RequestDecryption_SendMessageFails) {
TestMessenger messenger;
MockMessengerObserver observer(&messenger);
messenger.RequestDecryption(kChallenge);
TEST_F(
ProximityAuthMessengerImplTest,
RequestDecryption_SendsExpectedMessage_UsingBase64UrlEncoding_MultiDeviceApiEnabled) {
CreateMessenger(true /* is_multi_device_api_enabled */);
EXPECT_CALL(observer, OnDecryptResponseProxy(std::string()));
messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(false);
messenger_->RequestDecryption("\xFF\xE6");
EXPECT_EQ(
"{"
"\"encrypted_data\":\"_-Y=\","
"\"type\":\"decrypt_request\""
"}",
GetLastSentMessage());
}
TEST(ProximityAuthMessengerImplTest,
RequestDecryption_SendSucceeds_WaitsForReply) {
TestMessenger messenger;
MockMessengerObserver observer(&messenger);
messenger.RequestDecryption(kChallenge);
TEST_F(ProximityAuthMessengerImplTest, RequestDecryption_SendMessageFails) {
CreateMessenger(false /* is_multi_device_api_enabled */);
messenger_->RequestDecryption(kChallenge);
EXPECT_CALL(observer, OnDecryptResponseProxy(_)).Times(0);
messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(true);
EXPECT_CALL(*observer_, OnDecryptResponseProxy(std::string()));
messenger_->GetFakeConnection()->FinishSendingMessageWithSuccess(false);
}
TEST(ProximityAuthMessengerImplTest,
RequestDecryption_SendSucceeds_NotifiesObserversOnReply_NoData) {
TestMessenger messenger;
MockMessengerObserver observer(&messenger);
messenger.RequestDecryption(kChallenge);
messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(true);
TEST_F(ProximityAuthMessengerImplTest,
RequestDecryption_SendSucceeds_WaitsForReply) {
CreateMessenger(false /* is_multi_device_api_enabled */);
EXPECT_CALL(observer, OnDecryptResponseProxy(std::string()));
messenger.GetFakeConnection()->ReceiveMessage(
messenger_->RequestDecryption(kChallenge);
EXPECT_CALL(*observer_, OnDecryptResponseProxy(_)).Times(0);
messenger_->GetFakeConnection()->FinishSendingMessageWithSuccess(true);
}
TEST_F(ProximityAuthMessengerImplTest,
RequestDecryption_SendSucceeds_NotifiesObserversOnReply_NoData) {
CreateMessenger(false /* is_multi_device_api_enabled */);
messenger_->RequestDecryption(kChallenge);
messenger_->GetFakeConnection()->FinishSendingMessageWithSuccess(true);
EXPECT_CALL(*observer_, OnDecryptResponseProxy(std::string()));
messenger_->GetFakeConnection()->ReceiveMessage(
std::string(kTestFeature),
"{\"type\":\"decrypt_response\"}, but encoded");
}
TEST(ProximityAuthMessengerImplTest,
RequestDecryption_SendSucceeds_NotifiesObserversOnReply_InvalidData) {
TestMessenger messenger;
MockMessengerObserver observer(&messenger);
messenger.RequestDecryption(kChallenge);
messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(true);
TEST_F(
ProximityAuthMessengerImplTest,
RequestDecryption_SendSucceeds_NotifiesObserversOnReply_NoData_MultiDeviceApiEnabled) {
CreateMessenger(true /* is_multi_device_api_enabled */);
messenger_->RequestDecryption(kChallenge);
EXPECT_CALL(*observer_, OnDecryptResponseProxy(std::string()));
fake_channel_->NotifyMessageReceived("{\"type\":\"decrypt_response\"}");
}
TEST_F(ProximityAuthMessengerImplTest,
RequestDecryption_SendSucceeds_NotifiesObserversOnReply_InvalidData) {
CreateMessenger(false /* is_multi_device_api_enabled */);
messenger_->RequestDecryption(kChallenge);
messenger_->GetFakeConnection()->FinishSendingMessageWithSuccess(true);
EXPECT_CALL(observer, OnDecryptResponseProxy(std::string()));
messenger.GetFakeConnection()->ReceiveMessage(
EXPECT_CALL(*observer_, OnDecryptResponseProxy(std::string()));
messenger_->GetFakeConnection()->ReceiveMessage(
std::string(kTestFeature),
"{"
"\"type\":\"decrypt_response\","
......@@ -230,15 +344,30 @@ TEST(ProximityAuthMessengerImplTest,
"}, but encoded");
}
TEST(ProximityAuthMessengerImplTest,
RequestDecryption_SendSucceeds_NotifiesObserversOnReply_ValidData) {
TestMessenger messenger;
MockMessengerObserver observer(&messenger);
messenger.RequestDecryption(kChallenge);
messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(true);
TEST_F(
ProximityAuthMessengerImplTest,
RequestDecryption_SendSucceeds_NotifiesObserversOnReply_InvalidData_MultiDeviceApiEnabled) {
CreateMessenger(true /* is_multi_device_api_enabled */);
messenger_->RequestDecryption(kChallenge);
EXPECT_CALL(*observer_, OnDecryptResponseProxy(std::string()));
fake_channel_->NotifyMessageReceived(
"{"
"\"type\":\"decrypt_response\","
"\"data\":\"not a base64-encoded string\""
"}");
}
TEST_F(ProximityAuthMessengerImplTest,
RequestDecryption_SendSucceeds_NotifiesObserversOnReply_ValidData) {
CreateMessenger(false /* is_multi_device_api_enabled */);
messenger_->RequestDecryption(kChallenge);
messenger_->GetFakeConnection()->FinishSendingMessageWithSuccess(true);
EXPECT_CALL(observer, OnDecryptResponseProxy("a winner is you"));
messenger.GetFakeConnection()->ReceiveMessage(
EXPECT_CALL(*observer_, OnDecryptResponseProxy("a winner is you"));
messenger_->GetFakeConnection()->ReceiveMessage(
std::string(kTestFeature),
"{"
"\"type\":\"decrypt_response\","
......@@ -246,16 +375,31 @@ TEST(ProximityAuthMessengerImplTest,
"}, but encoded");
}
TEST_F(
ProximityAuthMessengerImplTest,
RequestDecryption_SendSucceeds_NotifiesObserversOnReply_ValidData_MultiDeviceApiEnabled) {
CreateMessenger(true /* is_multi_device_api_enabled */);
messenger_->RequestDecryption(kChallenge);
EXPECT_CALL(*observer_, OnDecryptResponseProxy("a winner is you"));
fake_channel_->NotifyMessageReceived(
"{"
"\"type\":\"decrypt_response\","
"\"data\":\"YSB3aW5uZXIgaXMgeW91\"" // "a winner is you", base64-encoded
"}");
}
// Verify that the messenger correctly parses base64url encoded data.
TEST(ProximityAuthMessengerImplTest,
RequestDecryption_SendSucceeds_ParsesBase64UrlEncodingInReply) {
TestMessenger messenger;
MockMessengerObserver observer(&messenger);
messenger.RequestDecryption(kChallenge);
messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(true);
EXPECT_CALL(observer, OnDecryptResponseProxy("\xFF\xE6"));
messenger.GetFakeConnection()->ReceiveMessage(
TEST_F(ProximityAuthMessengerImplTest,
RequestDecryption_SendSucceeds_ParsesBase64UrlEncodingInReply) {
CreateMessenger(false /* is_multi_device_api_enabled */);
messenger_->RequestDecryption(kChallenge);
messenger_->GetFakeConnection()->FinishSendingMessageWithSuccess(true);
EXPECT_CALL(*observer_, OnDecryptResponseProxy("\xFF\xE6"));
messenger_->GetFakeConnection()->ReceiveMessage(
std::string(kTestFeature),
"{"
"\"type\":\"decrypt_response\","
......@@ -263,79 +407,126 @@ TEST(ProximityAuthMessengerImplTest,
"}, but encoded");
}
TEST(ProximityAuthMessengerImplTest,
RequestUnlock_SignInUnsupported_DoesntSendMessage) {
TestMessenger messenger;
messenger.GetFakeSecureContext()->set_protocol_version(
TEST_F(
ProximityAuthMessengerImplTest,
RequestDecryption_SendSucceeds_ParsesBase64UrlEncodingInReply_MultiDeviceApiEnabled) {
CreateMessenger(true /* is_multi_device_api_enabled */);
messenger_->RequestDecryption(kChallenge);
EXPECT_CALL(*observer_, OnDecryptResponseProxy("\xFF\xE6"));
fake_channel_->NotifyMessageReceived(
"{"
"\"type\":\"decrypt_response\","
"\"data\":\"_-Y=\"" // "\0xFF\0xE6", base64url-encoded.
"}");
}
TEST_F(ProximityAuthMessengerImplTest,
RequestUnlock_SignInUnsupported_DoesntSendMessage) {
CreateMessenger(false /* is_multi_device_api_enabled */);
messenger_->GetFakeSecureContext()->set_protocol_version(
cryptauth::SecureContext::PROTOCOL_VERSION_THREE_ZERO);
messenger.RequestUnlock();
EXPECT_FALSE(messenger.GetFakeConnection()->current_message());
messenger_->RequestUnlock();
EXPECT_FALSE(messenger_->GetFakeConnection()->current_message());
}
TEST(ProximityAuthMessengerImplTest, RequestUnlock_SendsExpectedMessage) {
TestMessenger messenger;
messenger.RequestUnlock();
TEST_F(ProximityAuthMessengerImplTest, RequestUnlock_SendsExpectedMessage) {
CreateMessenger(false /* is_multi_device_api_enabled */);
messenger_->RequestUnlock();
cryptauth::WireMessage* message =
messenger.GetFakeConnection()->current_message();
messenger_->GetFakeConnection()->current_message();
ASSERT_TRUE(message);
EXPECT_EQ("{\"type\":\"unlock_request\"}, but encoded", message->payload());
}
TEST(ProximityAuthMessengerImplTest, RequestUnlock_SendMessageFails) {
TestMessenger messenger;
MockMessengerObserver observer(&messenger);
messenger.RequestUnlock();
TEST_F(ProximityAuthMessengerImplTest,
RequestUnlock_SendsExpectedMessage_MultiDeviceApiEnabled) {
CreateMessenger(true /* is_multi_device_api_enabled */);
EXPECT_CALL(observer, OnUnlockResponse(false));
messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(false);
messenger_->RequestUnlock();
EXPECT_EQ("{\"type\":\"unlock_request\"}", GetLastSentMessage());
}
TEST(ProximityAuthMessengerImplTest, RequestUnlock_SendSucceeds_WaitsForReply) {
TestMessenger messenger;
MockMessengerObserver observer(&messenger);
messenger.RequestUnlock();
TEST_F(ProximityAuthMessengerImplTest, RequestUnlock_SendMessageFails) {
CreateMessenger(false /* is_multi_device_api_enabled */);
messenger_->RequestUnlock();
EXPECT_CALL(observer, OnUnlockResponse(_)).Times(0);
messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(true);
EXPECT_CALL(*observer_, OnUnlockResponse(false));
messenger_->GetFakeConnection()->FinishSendingMessageWithSuccess(false);
}
TEST(ProximityAuthMessengerImplTest,
RequestUnlock_SendSucceeds_NotifiesObserversOnReply) {
TestMessenger messenger;
MockMessengerObserver observer(&messenger);
messenger.RequestUnlock();
messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(true);
TEST_F(ProximityAuthMessengerImplTest,
RequestUnlock_SendSucceeds_WaitsForReply) {
CreateMessenger(false /* is_multi_device_api_enabled */);
messenger_->RequestUnlock();
EXPECT_CALL(observer, OnUnlockResponse(true));
messenger.GetFakeConnection()->ReceiveMessage(
EXPECT_CALL(*observer_, OnUnlockResponse(_)).Times(0);
messenger_->GetFakeConnection()->FinishSendingMessageWithSuccess(true);
}
TEST_F(ProximityAuthMessengerImplTest,
RequestUnlock_SendSucceeds_NotifiesObserversOnReply) {
CreateMessenger(false /* is_multi_device_api_enabled */);
messenger_->RequestUnlock();
messenger_->GetFakeConnection()->FinishSendingMessageWithSuccess(true);
EXPECT_CALL(*observer_, OnUnlockResponse(true));
messenger_->GetFakeConnection()->ReceiveMessage(
std::string(kTestFeature), "{\"type\":\"unlock_response\"}, but encoded");
}
TEST(ProximityAuthMessengerImplTest,
OnMessageReceived_RemoteStatusUpdate_Invalid) {
TestMessenger messenger;
MockMessengerObserver observer(&messenger);
TEST_F(
ProximityAuthMessengerImplTest,
RequestUnlock_SendSucceeds_NotifiesObserversOnReply_MultiDeviceApiEnabled) {
CreateMessenger(true /* is_multi_device_api_enabled */);
messenger_->RequestUnlock();
EXPECT_CALL(*observer_, OnUnlockResponse(true));
fake_channel_->NotifyMessageReceived("{\"type\":\"unlock_response\"}");
}
TEST_F(ProximityAuthMessengerImplTest,
OnMessageReceived_RemoteStatusUpdate_Invalid) {
CreateMessenger(false /* is_multi_device_api_enabled */);
// Receive a status update message that's missing all the data.
EXPECT_CALL(*observer_, OnRemoteStatusUpdate(_)).Times(0);
messenger_->GetFakeConnection()->ReceiveMessage(
std::string(kTestFeature), "{\"type\":\"status_update\"}, but encoded");
}
// ryan
TEST_F(ProximityAuthMessengerImplTest,
OnMessageReceived_RemoteStatusUpdate_Invalid_MultiDeviceApiEnabled) {
CreateMessenger(true /* is_multi_device_api_enabled */);
// Receive a status update message that's missing all the data.
EXPECT_CALL(observer, OnRemoteStatusUpdate(_)).Times(0);
messenger.GetFakeConnection()->ReceiveMessage(
EXPECT_CALL(*observer_, OnRemoteStatusUpdate(_)).Times(0);
messenger_->GetFakeConnection()->ReceiveMessage(
std::string(kTestFeature), "{\"type\":\"status_update\"}, but encoded");
}
TEST(ProximityAuthMessengerImplTest,
OnMessageReceived_RemoteStatusUpdate_Valid) {
TestMessenger messenger;
MockMessengerObserver observer(&messenger);
TEST_F(ProximityAuthMessengerImplTest,
OnMessageReceived_RemoteStatusUpdate_Valid) {
CreateMessenger(false /* is_multi_device_api_enabled */);
EXPECT_CALL(observer,
EXPECT_CALL(*observer_,
OnRemoteStatusUpdate(
AllOf(Field(&RemoteStatusUpdate::user_presence, USER_PRESENT),
Field(&RemoteStatusUpdate::secure_screen_lock_state,
SECURE_SCREEN_LOCK_ENABLED),
Field(&RemoteStatusUpdate::trust_agent_state,
TRUST_AGENT_UNSUPPORTED))));
messenger.GetFakeConnection()->ReceiveMessage(
messenger_->GetFakeConnection()->ReceiveMessage(
std::string(kTestFeature),
"{"
"\"type\":\"status_update\","
......@@ -345,61 +536,132 @@ TEST(ProximityAuthMessengerImplTest,
"}, but encoded");
}
TEST(ProximityAuthMessengerImplTest, OnMessageReceived_InvalidJSON) {
TestMessenger messenger;
StrictMock<MockMessengerObserver> observer(&messenger);
messenger.RequestUnlock();
messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(true);
TEST_F(ProximityAuthMessengerImplTest,
OnMessageReceived_RemoteStatusUpdate_Valid_MultiDeviceApiEnabled) {
CreateMessenger(true /* is_multi_device_api_enabled */);
EXPECT_CALL(*observer_,
OnRemoteStatusUpdate(
AllOf(Field(&RemoteStatusUpdate::user_presence, USER_PRESENT),
Field(&RemoteStatusUpdate::secure_screen_lock_state,
SECURE_SCREEN_LOCK_ENABLED),
Field(&RemoteStatusUpdate::trust_agent_state,
TRUST_AGENT_UNSUPPORTED))));
fake_channel_->NotifyMessageReceived(
"{"
"\"type\":\"status_update\","
"\"user_presence\":\"present\","
"\"secure_screen_lock\":\"enabled\","
"\"trust_agent\":\"unsupported\""
"}");
}
TEST_F(ProximityAuthMessengerImplTest, OnMessageReceived_InvalidJSON) {
CreateMessenger(false /* is_multi_device_api_enabled */);
StrictMock<MockMessengerObserver> observer(messenger_.get());
messenger_->RequestUnlock();
messenger_->GetFakeConnection()->FinishSendingMessageWithSuccess(true);
// The StrictMock will verify that no observer methods are called.
messenger_->GetFakeConnection()->ReceiveMessage(std::string(kTestFeature),
"Not JSON, but encoded");
}
TEST_F(ProximityAuthMessengerImplTest,
OnMessageReceived_InvalidJSON_MultiDeviceApiEnabled) {
CreateMessenger(true /* is_multi_device_api_enabled */);
StrictMock<MockMessengerObserver> observer(messenger_.get());
messenger_->RequestUnlock();
// The StrictMock will verify that no observer methods are called.
messenger.GetFakeConnection()->ReceiveMessage(std::string(kTestFeature),
"Not JSON, but encoded");
fake_channel_->NotifyMessageReceived("Not JSON");
}
TEST(ProximityAuthMessengerImplTest, OnMessageReceived_MissingTypeField) {
TestMessenger messenger;
StrictMock<MockMessengerObserver> observer(&messenger);
messenger.RequestUnlock();
messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(true);
TEST_F(ProximityAuthMessengerImplTest, OnMessageReceived_MissingTypeField) {
CreateMessenger(false /* is_multi_device_api_enabled */);
StrictMock<MockMessengerObserver> observer(messenger_.get());
messenger_->RequestUnlock();
messenger_->GetFakeConnection()->FinishSendingMessageWithSuccess(true);
// The StrictMock will verify that no observer methods are called.
messenger.GetFakeConnection()->ReceiveMessage(
messenger_->GetFakeConnection()->ReceiveMessage(
std::string(kTestFeature),
"{\"some key that's not 'type'\":\"some value\"}, but encoded");
}
TEST(ProximityAuthMessengerImplTest, OnMessageReceived_UnexpectedReply) {
TestMessenger messenger;
StrictMock<MockMessengerObserver> observer(&messenger);
TEST_F(ProximityAuthMessengerImplTest,
OnMessageReceived_MissingTypeField_MultiDeviceApiEnabled) {
CreateMessenger(true /* is_multi_device_api_enabled */);
StrictMock<MockMessengerObserver> observer(messenger_.get());
messenger_->RequestUnlock();
// The StrictMock will verify that no observer methods are called.
messenger.GetFakeConnection()->ReceiveMessage(
fake_channel_->NotifyMessageReceived(
"{\"some key that's not 'type'\":\"some value\"}");
}
TEST_F(ProximityAuthMessengerImplTest, OnMessageReceived_UnexpectedReply) {
CreateMessenger(false /* is_multi_device_api_enabled */);
StrictMock<MockMessengerObserver> observer(messenger_.get());
// The StrictMock will verify that no observer methods are called.
messenger_->GetFakeConnection()->ReceiveMessage(
std::string(kTestFeature), "{\"type\":\"unlock_response\"}, but encoded");
}
TEST(ProximityAuthMessengerImplTest,
OnMessageReceived_MismatchedReply_UnlockInReplyToDecrypt) {
TestMessenger messenger;
StrictMock<MockMessengerObserver> observer(&messenger);
TEST_F(ProximityAuthMessengerImplTest,
OnMessageReceived_UnexpectedReply_MultiDeviceApiEnabled) {
CreateMessenger(true /* is_multi_device_api_enabled */);
messenger.RequestDecryption(kChallenge);
messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(true);
StrictMock<MockMessengerObserver> observer(messenger_.get());
// The StrictMock will verify that no observer methods are called.
messenger.GetFakeConnection()->ReceiveMessage(
fake_channel_->NotifyMessageReceived("{\"type\":\"unlock_response\"}");
}
TEST_F(ProximityAuthMessengerImplTest,
OnMessageReceived_MismatchedReply_UnlockInReplyToDecrypt) {
CreateMessenger(false /* is_multi_device_api_enabled */);
StrictMock<MockMessengerObserver> observer(messenger_.get());
messenger_->RequestDecryption(kChallenge);
messenger_->GetFakeConnection()->FinishSendingMessageWithSuccess(true);
// The StrictMock will verify that no observer methods are called.
messenger_->GetFakeConnection()->ReceiveMessage(
std::string(kTestFeature), "{\"type\":\"unlock_response\"}, but encoded");
}
TEST(ProximityAuthMessengerImplTest,
OnMessageReceived_MismatchedReply_DecryptInReplyToUnlock) {
TestMessenger messenger;
StrictMock<MockMessengerObserver> observer(&messenger);
TEST_F(
ProximityAuthMessengerImplTest,
OnMessageReceived_MismatchedReply_UnlockInReplyToDecrypt_MultiDeviceApiEnabled) {
CreateMessenger(true /* is_multi_device_api_enabled */);
StrictMock<MockMessengerObserver> observer(messenger_.get());
messenger.RequestUnlock();
messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(true);
messenger_->RequestDecryption(kChallenge);
// The StrictMock will verify that no observer methods are called.
messenger.GetFakeConnection()->ReceiveMessage(
fake_channel_->NotifyMessageReceived("{\"type\":\"unlock_response\"}");
}
TEST_F(ProximityAuthMessengerImplTest,
OnMessageReceived_MismatchedReply_DecryptInReplyToUnlock) {
CreateMessenger(false /* is_multi_device_api_enabled */);
StrictMock<MockMessengerObserver> observer(messenger_.get());
messenger_->RequestUnlock();
messenger_->GetFakeConnection()->FinishSendingMessageWithSuccess(true);
// The StrictMock will verify that no observer methods are called.
messenger_->GetFakeConnection()->ReceiveMessage(
std::string(kTestFeature),
"{"
"\"type\":\"decrypt_response\","
......@@ -407,37 +669,52 @@ TEST(ProximityAuthMessengerImplTest,
"}, but encoded");
}
TEST(ProximityAuthMessengerImplTest, BuffersMessages_WhileSending) {
TestMessenger messenger;
MockMessengerObserver observer(&messenger);
TEST_F(
ProximityAuthMessengerImplTest,
OnMessageReceived_MismatchedReply_DecryptInReplyToUnlock_MultiDeviceApiEnabled) {
CreateMessenger(true /* is_multi_device_api_enabled */);
StrictMock<MockMessengerObserver> observer(messenger_.get());
messenger_->RequestUnlock();
// The StrictMock will verify that no observer methods are called.
fake_channel_->NotifyMessageReceived(
"{"
"\"type\":\"decrypt_response\","
"\"data\":\"YSB3aW5uZXIgaXMgeW91\""
"}");
}
TEST_F(ProximityAuthMessengerImplTest, BuffersMessages_WhileSending) {
CreateMessenger(false /* is_multi_device_api_enabled */);
// Initiate a decryption request, and then initiate an unlock request before
// the decryption request is even finished sending.
messenger.RequestDecryption(kChallenge);
messenger.RequestUnlock();
messenger_->RequestDecryption(kChallenge);
messenger_->RequestUnlock();
EXPECT_CALL(observer, OnDecryptResponseProxy(std::string()));
messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(false);
EXPECT_CALL(*observer_, OnDecryptResponseProxy(std::string()));
messenger_->GetFakeConnection()->FinishSendingMessageWithSuccess(false);
EXPECT_CALL(observer, OnUnlockResponse(false));
messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(false);
EXPECT_CALL(*observer_, OnUnlockResponse(false));
messenger_->GetFakeConnection()->FinishSendingMessageWithSuccess(false);
}
TEST(ProximityAuthMessengerImplTest, BuffersMessages_WhileAwaitingReply) {
TestMessenger messenger;
MockMessengerObserver observer(&messenger);
TEST_F(ProximityAuthMessengerImplTest, BuffersMessages_WhileAwaitingReply) {
CreateMessenger(false /* is_multi_device_api_enabled */);
// Initiate a decryption request, and allow the message to be sent.
messenger.RequestDecryption(kChallenge);
messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(true);
messenger_->RequestDecryption(kChallenge);
messenger_->GetFakeConnection()->FinishSendingMessageWithSuccess(true);
// At this point, the messenger is awaiting a reply to the decryption message.
// While it's waiting, initiate an unlock request.
messenger.RequestUnlock();
messenger_->RequestUnlock();
// Now simulate a response arriving for the original decryption request.
EXPECT_CALL(observer, OnDecryptResponseProxy("a winner is you"));
messenger.GetFakeConnection()->ReceiveMessage(
EXPECT_CALL(*observer_, OnDecryptResponseProxy("a winner is you"));
messenger_->GetFakeConnection()->ReceiveMessage(
std::string(kTestFeature),
"{"
"\"type\":\"decrypt_response\","
......@@ -446,8 +723,33 @@ TEST(ProximityAuthMessengerImplTest, BuffersMessages_WhileAwaitingReply) {
// The unlock request should have remained buffered, and should only now be
// sent.
EXPECT_CALL(observer, OnUnlockResponse(false));
messenger.GetFakeConnection()->FinishSendingMessageWithSuccess(false);
EXPECT_CALL(*observer_, OnUnlockResponse(false));
messenger_->GetFakeConnection()->FinishSendingMessageWithSuccess(false);
}
TEST_F(ProximityAuthMessengerImplTest, BuffersMessages_MultiDeviceApiEnabled) {
CreateMessenger(true /* is_multi_device_api_enabled */);
// Initiate a decryption request, and allow the message to be sent.
messenger_->RequestDecryption(kChallenge);
// At this point, the messenger is awaiting a reply to the decryption message.
// While it's waiting, initiate an unlock request.
messenger_->RequestUnlock();
// Now simulate a response arriving for the original decryption request.
EXPECT_CALL(*observer_, OnDecryptResponseProxy("a winner is you"));
fake_channel_->NotifyMessageReceived(
"{"
"\"type\":\"decrypt_response\","
"\"data\":\"YSB3aW5uZXIgaXMgeW91\""
"}");
// The unlock request should have remained buffered, and should only now be
// sent.
EXPECT_CALL(*observer_, OnUnlockResponse(true));
GetLastSentMessage();
fake_channel_->NotifyMessageReceived("{\"type\":\"unlock_response\"}");
}
} // namespace proximity_auth
......@@ -148,9 +148,12 @@ void RemoteDeviceLifeCycleImpl::OnAuthenticationResult(
void RemoteDeviceLifeCycleImpl::CreateMessenger() {
DCHECK(state_ == RemoteDeviceLifeCycle::State::AUTHENTICATING);
DCHECK(secure_context_);
messenger_.reset(
new MessengerImpl(std::move(connection_), std::move(secure_context_)));
// TODO(crbug.com/752273): Inject a real ClientChannel.
messenger_.reset(new MessengerImpl(std::move(connection_),
std::move(secure_context_),
nullptr /* channel */));
messenger_->AddObserver(this);
TransitionToState(RemoteDeviceLifeCycle::State::SECURE_CHANNEL_ESTABLISHED);
......
......@@ -69,6 +69,7 @@ class MockMessenger : public Messenger {
MOCK_METHOD0(RequestUnlock, void());
MOCK_CONST_METHOD0(GetSecureContext, cryptauth::SecureContext*());
MOCK_CONST_METHOD0(GetConnection, cryptauth::Connection*());
MOCK_CONST_METHOD0(GetChannel, chromeos::secure_channel::ClientChannel*());
private:
DISALLOW_COPY_AND_ASSIGN(MockMessenger);
......
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