blob: 11b4b8cda09c4b83f9d5195c28605333a48adfd8 [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/webauthn/android/cable_registration_state.h"
#include "base/functional/callback.h"
#include "base/logging.h"
#include "device/fido/cable/v2_handshake.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/boringssl/src/include/openssl/ec.h"
#include "third_party/boringssl/src/include/openssl/ec_key.h"
#include "third_party/boringssl/src/include/openssl/obj.h"
using device::cablev2::authenticator::Registration;
namespace webauthn::authenticator {
namespace {
class TestRegistration : public Registration {
public:
TestRegistration(
base::OnceCallback<void()> on_ready,
base::RepeatingCallback<void(std::unique_ptr<Registration::Event>)>
event_callback)
: on_ready_(std::move(on_ready)), on_event_(std::move(event_callback)) {}
~TestRegistration() override = default;
void PrepareContactID() override {}
void RotateContactID() override {}
std::optional<std::vector<uint8_t>> contact_id() const override {
return contact_id_;
}
static constexpr std::vector<uint8_t> ContactID() { return {1, 2, 3, 4}; }
base::OnceCallback<void()> on_ready_;
const base::RepeatingCallback<void(std::unique_ptr<Registration::Event>)>
on_event_;
std::optional<std::vector<uint8_t>> contact_id_ = ContactID();
};
class TestSystemInterface : public RegistrationState::SystemInterface {
public:
~TestSystemInterface() override = default;
std::unique_ptr<Registration> NewRegistration(
Registration::Type type,
base::OnceCallback<void()> on_ready,
base::RepeatingCallback<void(std::unique_ptr<Registration::Event>)>
event_callback) override {
auto registration = std::make_unique<TestRegistration>(
std::move(on_ready), std::move(event_callback));
if (type == Registration::Type::LINKING) {
linking_registration_ = registration.get();
} else {
syncing_registration_ = registration.get();
}
return registration;
}
void CanDeviceSupportCable(base::OnceCallback<void(bool)> callback) override {
CHECK(!support_callback_);
support_callback_ = std::move(callback);
}
void AmInWorkProfile(base::OnceCallback<void(bool)> callback) override {
CHECK(!work_profile_callback_);
work_profile_callback_ = std::move(callback);
}
void RefreshLocalDeviceInfo() override {
refresh_local_device_info_called_ = true;
}
void GetPrelinkFromPlayServices(
base::OnceCallback<void(std::optional<std::vector<uint8_t>>)> callback)
override {
CHECK(!prelink_callback_);
prelink_callback_ = std::move(callback);
}
raw_ptr<TestRegistration> linking_registration_ = nullptr;
raw_ptr<TestRegistration> syncing_registration_ = nullptr;
bool refresh_local_device_info_called_ = false;
base::OnceCallback<void(bool)> support_callback_;
base::OnceCallback<void(bool)> work_profile_callback_;
base::OnceCallback<void(std::optional<std::vector<uint8_t>>)>
prelink_callback_;
};
class CableRegistrationStateTest : public testing::Test {
void SetUp() override {
auto interface = std::make_unique<TestSystemInterface>();
interface_ = interface.get();
state_ = std::make_unique<RegistrationState>(std::move(interface));
}
protected:
static bssl::UniquePtr<EC_KEY> FakeKey() {
bssl::UniquePtr<EC_GROUP> p256(
EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1));
return bssl::UniquePtr<EC_KEY>(
EC_KEY_derive_from_secret(p256.get(), nullptr, 0));
}
raw_ptr<TestSystemInterface> interface_ = nullptr;
std::unique_ptr<RegistrationState> state_;
};
TEST_F(CableRegistrationStateTest, HaveDataForSync) {
state_->Register();
EXPECT_FALSE(state_->have_data_for_sync());
std::move(interface_->support_callback_).Run(true);
EXPECT_FALSE(state_->have_data_for_sync());
EXPECT_FALSE(interface_->refresh_local_device_info_called_);
state_->SignalSyncWhenReady();
EXPECT_FALSE(state_->have_data_for_sync());
state_->SignalSyncWhenReady();
EXPECT_FALSE(state_->have_data_for_sync());
std::move(interface_->prelink_callback_).Run(std::nullopt);
EXPECT_FALSE(interface_->refresh_local_device_info_called_);
EXPECT_FALSE(state_->have_data_for_sync());
std::move(interface_->work_profile_callback_).Run(true);
EXPECT_TRUE(interface_->refresh_local_device_info_called_);
EXPECT_TRUE(state_->have_data_for_sync());
EXPECT_TRUE(state_->device_supports_cable());
EXPECT_TRUE(state_->am_in_work_profile());
EXPECT_FALSE(state_->link_data_from_play_services().has_value());
}
} // namespace
} // namespace webauthn::authenticator