Commit 216b806d authored by Kyle Horimoto's avatar Kyle Horimoto Committed by Commit Bot

[CrOS MultiDevice] Add HostVerifier.

This class verifies that this device can connect to the currently-set
MultiDevice host. The verification process consists of creating a
Bluetooth connection to the device, performing an authentication
handshake, and enabling the per-device features which are supported.

This CL adds an abstract class, test double, and stub implementation.
The actual implementation is left as a TODO; this CL unblocks some
higher-priority work.

Bug: 824568
Change-Id: I457a5dae5edf2182f565f782ab201c5505ffb702
Reviewed-on: https://chromium-review.googlesource.com/1112936
Commit-Queue: Kyle Horimoto <khorimoto@chromium.org>
Reviewed-by: default avatarRyan Hansberry <hansberry@chromium.org>
Cr-Commit-Position: refs/heads/master@{#570142}
parent f187e15a
......@@ -18,6 +18,10 @@ static_library("multidevice_setup") {
"host_backend_delegate.h",
"host_backend_delegate_impl.cc",
"host_backend_delegate_impl.h",
"host_verifier.cc",
"host_verifier.h",
"host_verifier_impl.cc",
"host_verifier_impl.h",
"multidevice_setup_base.cc",
"multidevice_setup_base.h",
"multidevice_setup_impl.cc",
......@@ -60,6 +64,8 @@ static_library("test_support") {
"fake_account_status_change_delegate_notifier.h",
"fake_host_backend_delegate.cc",
"fake_host_backend_delegate.h",
"fake_host_verifier.cc",
"fake_host_verifier.h",
"fake_multidevice_setup.cc",
"fake_multidevice_setup.h",
"fake_setup_flow_completion_recorder.cc",
......@@ -82,6 +88,7 @@ source_set("unit_tests") {
sources = [
"account_status_change_delegate_notifier_impl_unittest.cc",
"host_backend_delegate_impl_unittest.cc",
"host_verifier_impl_unittest.cc",
"multidevice_setup_impl_unittest.cc",
"multidevice_setup_service_unittest.cc",
"setup_flow_completion_recorder_impl_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/multidevice_setup/fake_host_verifier.h"
namespace chromeos {
namespace multidevice_setup {
FakeHostVerifier::FakeHostVerifier() = default;
FakeHostVerifier::~FakeHostVerifier() = default;
bool FakeHostVerifier::IsHostVerified() {
return is_host_verified_;
}
void FakeHostVerifier::PerformAttemptVerificationNow() {
++num_verify_now_attempts_;
}
FakeHostVerifierObserver::FakeHostVerifierObserver() = default;
FakeHostVerifierObserver::~FakeHostVerifierObserver() = default;
void FakeHostVerifierObserver::OnHostVerified() {
++num_host_verifications_;
}
} // namespace multidevice_setup
} // 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_MULTIDEVICE_SETUP_FAKE_HOST_VERIFIER_H_
#define CHROMEOS_SERVICES_MULTIDEVICE_SETUP_FAKE_HOST_VERIFIER_H_
#include "base/macros.h"
#include "chromeos/services/multidevice_setup/host_verifier.h"
namespace chromeos {
namespace multidevice_setup {
// Test HostVerifier implementation.
class FakeHostVerifier : public HostVerifier {
public:
FakeHostVerifier();
~FakeHostVerifier() override;
void set_is_host_verified(bool is_host_verified) {
is_host_verified_ = is_host_verified;
}
size_t num_verify_now_attempts() { return num_verify_now_attempts_; }
using HostVerifier::NotifyHostVerified;
private:
// HostVerifier:
bool IsHostVerified() override;
void PerformAttemptVerificationNow() override;
bool is_host_verified_ = false;
size_t num_verify_now_attempts_ = 0u;
DISALLOW_COPY_AND_ASSIGN(FakeHostVerifier);
};
// Test HostVerifier::Observer implementation.
class FakeHostVerifierObserver : public HostVerifier::Observer {
public:
FakeHostVerifierObserver();
~FakeHostVerifierObserver() override;
size_t num_host_verifications() { return num_host_verifications_; }
private:
// HostVerifier::Observer:
void OnHostVerified() override;
size_t num_host_verifications_ = 0u;
DISALLOW_COPY_AND_ASSIGN(FakeHostVerifierObserver);
};
} // namespace multidevice_setup
} // namespace chromeos
#endif // CHROMEOS_SERVICES_MULTIDEVICE_SETUP_FAKE_HOST_VERIFIER_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/multidevice_setup/host_verifier.h"
#include "base/logging.h"
#include "chromeos/components/proximity_auth/logging/logging.h"
namespace chromeos {
namespace multidevice_setup {
HostVerifier::HostVerifier() = default;
HostVerifier::~HostVerifier() = default;
void HostVerifier::AttemptVerificationNow() {
if (IsHostVerified()) {
PA_LOG(ERROR) << "HostVerifier::AttemptVerificationNow(): Attempted to "
<< "start verification, but the current host has already "
<< "been verified.";
NOTREACHED();
}
PerformAttemptVerificationNow();
}
void HostVerifier::AddObserver(Observer* observer) {
observer_list_.AddObserver(observer);
}
void HostVerifier::RemoveObserver(Observer* observer) {
observer_list_.RemoveObserver(observer);
}
void HostVerifier::NotifyHostVerified() {
for (auto& observer : observer_list_)
observer.OnHostVerified();
}
} // namespace multidevice_setup
} // 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_MULTIDEVICE_SETUP_HOST_VERIFIER_H_
#define CHROMEOS_SERVICES_MULTIDEVICE_SETUP_HOST_VERIFIER_H_
#include "base/macros.h"
#include "base/observer_list.h"
namespace chromeos {
namespace multidevice_setup {
// Verifies that this device can connect to the currently-set MultiDevice host.
// The verification process consists of creating a Bluetooth connection to the
// device, performing an authentication handshake, and enabling the per-device
// features which are supported.
class HostVerifier {
public:
class Observer {
public:
virtual ~Observer() = default;
virtual void OnHostVerified() = 0;
};
virtual ~HostVerifier();
// Returns whether the host has completed verification; note that if
// verification is still in the process of being completed but has not
// finished, this function still returns false.
virtual bool IsHostVerified() = 0;
// Attempts the verification flow; successful completion of the flow is
// communicated via the OnHostVerified() delegate callback.
void AttemptVerificationNow();
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
protected:
HostVerifier();
virtual void PerformAttemptVerificationNow() = 0;
void NotifyHostVerified();
private:
base::ObserverList<Observer> observer_list_;
DISALLOW_COPY_AND_ASSIGN(HostVerifier);
};
} // namespace multidevice_setup
} // namespace chromeos
#endif // CHROMEOS_SERVICES_MULTIDEVICE_SETUP_HOST_VERIFIER_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/multidevice_setup/host_verifier_impl.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/no_destructor.h"
#include "chromeos/services/device_sync/public/cpp/device_sync_client.h"
#include "chromeos/services/secure_channel/public/cpp/client/secure_channel_client.h"
namespace chromeos {
namespace multidevice_setup {
// static
HostVerifierImpl::Factory* HostVerifierImpl::Factory::test_factory_ = nullptr;
// static
HostVerifierImpl::Factory* HostVerifierImpl::Factory::Get() {
if (test_factory_)
return test_factory_;
static base::NoDestructor<Factory> factory;
return factory.get();
}
// static
void HostVerifierImpl::Factory::SetFactoryForTesting(Factory* test_factory) {
test_factory_ = test_factory;
}
HostVerifierImpl::Factory::~Factory() = default;
std::unique_ptr<HostVerifier> HostVerifierImpl::Factory::BuildInstance(
HostBackendDelegate* host_backend_delegate,
device_sync::DeviceSyncClient* device_sync_client,
secure_channel::SecureChannelClient* secure_channel_client) {
return base::WrapUnique(new HostVerifierImpl(
host_backend_delegate, device_sync_client, secure_channel_client));
}
HostVerifierImpl::HostVerifierImpl(
HostBackendDelegate* host_backend_delegate,
device_sync::DeviceSyncClient* device_sync_client,
secure_channel::SecureChannelClient* secure_channel_client)
: host_backend_delegate_(host_backend_delegate),
device_sync_client_(device_sync_client),
secure_channel_client_(secure_channel_client) {
host_backend_delegate_->AddObserver(this);
}
HostVerifierImpl::~HostVerifierImpl() {
host_backend_delegate_->RemoveObserver(this);
}
bool HostVerifierImpl::IsHostVerified() {
NOTIMPLEMENTED();
// Use both |device_sync_client_| and |secure_channel_client_| to prevent
// unused field compiler warning.
return static_cast<void*>(device_sync_client_) ==
static_cast<void*>(secure_channel_client_);
}
void HostVerifierImpl::PerformAttemptVerificationNow() {
NOTIMPLEMENTED();
}
void HostVerifierImpl::OnHostChangedOnBackend() {
NOTIMPLEMENTED();
}
} // namespace multidevice_setup
} // 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_MULTIDEVICE_SETUP_HOST_VERIFIER_IMPL_H_
#define CHROMEOS_SERVICES_MULTIDEVICE_SETUP_HOST_VERIFIER_IMPL_H_
#include "base/macros.h"
#include "chromeos/services/multidevice_setup/host_backend_delegate.h"
#include "chromeos/services/multidevice_setup/host_verifier.h"
namespace chromeos {
namespace device_sync {
class DeviceSyncClient;
} // namespace device_sync
namespace secure_channel {
class SecureChannelClient;
} // namespace secure_channel
namespace multidevice_setup {
// Concrete HostVerifier implementation, which starts trying to verify a host as
// soon as it is set on the back-end. If verification fails, HostVerifierImpl
// uses an exponential back-off to retry verification until it succeeds.
//
// If the MultiDevice host is changed while verification is in progress, the
// previous verification attempt is canceled and a new attempt begins with the
// updated device.
//
// TODO(khorimoto): Fill out implementation.
class HostVerifierImpl : public HostVerifier,
public HostBackendDelegate::Observer {
public:
class Factory {
public:
static Factory* Get();
static void SetFactoryForTesting(Factory* test_factory);
virtual ~Factory();
virtual std::unique_ptr<HostVerifier> BuildInstance(
HostBackendDelegate* host_backend_delegate,
device_sync::DeviceSyncClient* device_sync_client,
secure_channel::SecureChannelClient* secure_channel_client);
private:
static Factory* test_factory_;
};
~HostVerifierImpl() override;
private:
HostVerifierImpl(HostBackendDelegate* host_backend_delegate,
device_sync::DeviceSyncClient* device_sync_client,
secure_channel::SecureChannelClient* secure_channel_client);
// HostVerifier:
bool IsHostVerified() override;
void PerformAttemptVerificationNow() override;
// HostBackendDelegate::Observer:
void OnHostChangedOnBackend() override;
HostBackendDelegate* host_backend_delegate_;
device_sync::DeviceSyncClient* device_sync_client_;
secure_channel::SecureChannelClient* secure_channel_client_;
DISALLOW_COPY_AND_ASSIGN(HostVerifierImpl);
};
} // namespace multidevice_setup
} // namespace chromeos
#endif // CHROMEOS_SERVICES_MULTIDEVICE_SETUP_HOST_VERIFIER_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/multidevice_setup/host_verifier_impl.h"
#include <memory>
#include "base/macros.h"
#include "chromeos/services/device_sync/public/cpp/fake_device_sync_client.h"
#include "chromeos/services/multidevice_setup/fake_host_backend_delegate.h"
#include "chromeos/services/multidevice_setup/fake_host_verifier.h"
#include "chromeos/services/secure_channel/public/cpp/client/fake_secure_channel_client.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace chromeos {
namespace multidevice_setup {
class MultiDeviceSetupHostVerifierImplTest : public testing::Test {
protected:
MultiDeviceSetupHostVerifierImplTest() = default;
~MultiDeviceSetupHostVerifierImplTest() override = default;
// testing::Test:
void SetUp() override {
fake_host_backend_delegate_ = std::make_unique<FakeHostBackendDelegate>();
fake_device_sync_client_ =
std::make_unique<device_sync::FakeDeviceSyncClient>();
fake_secure_channel_client_ =
std::make_unique<secure_channel::FakeSecureChannelClient>();
host_verifier_ = HostVerifierImpl::Factory::Get()->BuildInstance(
fake_host_backend_delegate_.get(), fake_device_sync_client_.get(),
fake_secure_channel_client_.get());
fake_observer_ = std::make_unique<FakeHostVerifierObserver>();
host_verifier_->AddObserver(fake_observer_.get());
}
void TearDown() override {
host_verifier_->RemoveObserver(fake_observer_.get());
}
private:
std::unique_ptr<FakeHostVerifierObserver> fake_observer_;
std::unique_ptr<FakeHostBackendDelegate> fake_host_backend_delegate_;
std::unique_ptr<device_sync::FakeDeviceSyncClient> fake_device_sync_client_;
std::unique_ptr<secure_channel::FakeSecureChannelClient>
fake_secure_channel_client_;
std::unique_ptr<HostVerifier> host_verifier_;
DISALLOW_COPY_AND_ASSIGN(MultiDeviceSetupHostVerifierImplTest);
};
TEST_F(MultiDeviceSetupHostVerifierImplTest, Test) {}
} // namespace multidevice_setup
} // namespace chromeos
......@@ -10,6 +10,7 @@
#include "chromeos/components/proximity_auth/logging/logging.h"
#include "chromeos/services/multidevice_setup/account_status_change_delegate_notifier_impl.h"
#include "chromeos/services/multidevice_setup/host_backend_delegate_impl.h"
#include "chromeos/services/multidevice_setup/host_verifier_impl.h"
#include "chromeos/services/multidevice_setup/setup_flow_completion_recorder_impl.h"
namespace chromeos {
......@@ -54,6 +55,10 @@ MultiDeviceSetupImpl::MultiDeviceSetupImpl(
HostBackendDelegateImpl::Factory::Get()->BuildInstance(
pref_service,
device_sync_client)),
host_verifier_(HostVerifierImpl::Factory::Get()->BuildInstance(
host_backend_delegate_.get(),
device_sync_client,
secure_channel_client)),
setup_flow_completion_recorder_(
SetupFlowCompletionRecorderImpl::Factory::Get()->BuildInstance(
pref_service,
......
......@@ -26,6 +26,7 @@ namespace multidevice_setup {
class AccountStatusChangeDelegateNotifier;
class HostBackendDelegate;
class HostVerifier;
class SetupFlowCompletionRecorder;
// Concrete MultiDeviceSetup implementation.
......@@ -61,6 +62,7 @@ class MultiDeviceSetupImpl : public mojom::MultiDeviceSetup {
TriggerEventForDebuggingCallback callback) override;
std::unique_ptr<HostBackendDelegate> host_backend_delegate_;
std::unique_ptr<HostVerifier> host_verifier_;
std::unique_ptr<SetupFlowCompletionRecorder> setup_flow_completion_recorder_;
std::unique_ptr<AccountStatusChangeDelegateNotifier> delegate_notifier_;
......
......@@ -11,8 +11,10 @@
#include "chromeos/services/multidevice_setup/fake_account_status_change_delegate.h"
#include "chromeos/services/multidevice_setup/fake_account_status_change_delegate_notifier.h"
#include "chromeos/services/multidevice_setup/fake_host_backend_delegate.h"
#include "chromeos/services/multidevice_setup/fake_host_verifier.h"
#include "chromeos/services/multidevice_setup/fake_setup_flow_completion_recorder.h"
#include "chromeos/services/multidevice_setup/host_backend_delegate_impl.h"
#include "chromeos/services/multidevice_setup/host_verifier_impl.h"
#include "chromeos/services/multidevice_setup/multidevice_setup_impl.h"
#include "chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.h"
#include "chromeos/services/multidevice_setup/setup_flow_completion_recorder_impl.h"
......@@ -62,6 +64,46 @@ class FakeHostBackendDelegateFactory : public HostBackendDelegateImpl::Factory {
DISALLOW_COPY_AND_ASSIGN(FakeHostBackendDelegateFactory);
};
class FakeHostVerifierFactory : public HostVerifierImpl::Factory {
public:
FakeHostVerifierFactory(
FakeHostBackendDelegateFactory* fake_host_backend_delegate_factory,
device_sync::FakeDeviceSyncClient* expected_device_sync_client,
secure_channel::FakeSecureChannelClient* expected_secure_channel_client)
: fake_host_backend_delegate_factory_(fake_host_backend_delegate_factory),
expected_device_sync_client_(expected_device_sync_client),
expected_secure_channel_client_(expected_secure_channel_client) {}
~FakeHostVerifierFactory() override = default;
FakeHostVerifier* instance() { return instance_; }
private:
// HostVerifierImpl::Factory:
std::unique_ptr<HostVerifier> BuildInstance(
HostBackendDelegate* host_backend_delegate,
device_sync::DeviceSyncClient* device_sync_client,
secure_channel::SecureChannelClient* secure_channel_client) override {
EXPECT_FALSE(instance_);
EXPECT_EQ(fake_host_backend_delegate_factory_->instance(),
host_backend_delegate);
EXPECT_EQ(expected_device_sync_client_, device_sync_client);
EXPECT_EQ(expected_secure_channel_client_, secure_channel_client);
auto instance = std::make_unique<FakeHostVerifier>();
instance_ = instance.get();
return instance;
}
FakeHostBackendDelegateFactory* fake_host_backend_delegate_factory_;
device_sync::FakeDeviceSyncClient* expected_device_sync_client_;
secure_channel::FakeSecureChannelClient* expected_secure_channel_client_;
FakeHostVerifier* instance_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(FakeHostVerifierFactory);
};
class FakeSetupFlowCompletionRecorderFactory
: public SetupFlowCompletionRecorderImpl::Factory {
public:
......@@ -161,6 +203,12 @@ class MultiDeviceSetupImplTest : public testing::Test {
HostBackendDelegateImpl::Factory::SetFactoryForTesting(
fake_host_backend_delegate_factory_.get());
fake_host_verifier_factory_ = std::make_unique<FakeHostVerifierFactory>(
fake_host_backend_delegate_factory_.get(),
fake_device_sync_client_.get(), fake_secure_channel_client_.get());
HostVerifierImpl::Factory::SetFactoryForTesting(
fake_host_verifier_factory_.get());
fake_setup_flow_completion_recorder_factory_ =
std::make_unique<FakeSetupFlowCompletionRecorderFactory>(
test_pref_service_.get());
......@@ -181,6 +229,7 @@ class MultiDeviceSetupImplTest : public testing::Test {
void TearDown() override {
HostBackendDelegateImpl::Factory::SetFactoryForTesting(nullptr);
HostVerifierImpl::Factory::SetFactoryForTesting(nullptr);
SetupFlowCompletionRecorderImpl::Factory::SetFactoryForTesting(nullptr);
AccountStatusChangeDelegateNotifierImpl::Factory::SetFactoryForTesting(
nullptr);
......@@ -242,6 +291,7 @@ class MultiDeviceSetupImplTest : public testing::Test {
std::unique_ptr<FakeHostBackendDelegateFactory>
fake_host_backend_delegate_factory_;
std::unique_ptr<FakeHostVerifierFactory> fake_host_verifier_factory_;
std::unique_ptr<FakeSetupFlowCompletionRecorderFactory>
fake_setup_flow_completion_recorder_factory_;
std::unique_ptr<FakeAccountStatusChangeDelegateNotifierFactory>
......
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