blob: d1605e5b259e3fc5546eac9d7789e6ff7f210009 [file] [log] [blame]
// Copyright 2016 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/ash/policy/handlers/bluetooth_policy_handler.h"
#include <utility>
#include "base/test/task_environment.h"
#include "chrome/browser/ash/settings/scoped_testing_cros_settings.h"
#include "chrome/browser/ash/settings/stub_cros_settings_provider.h"
#include "chromeos/ash/components/login/login_state/login_state.h"
#include "device/bluetooth/bluetooth_adapter_factory.h"
#include "device/bluetooth/test/mock_bluetooth_adapter.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace policy {
class BluetoothPolicyHandlerTest : public testing::Test {
protected:
class TestingBluetoothAdapter : public device::MockBluetoothAdapter {
public:
TestingBluetoothAdapter() = default;
void Shutdown() override {
is_shutdown_ = true;
for (auto observer : GetObservers()) {
observer.AdapterPresentChanged(this, false);
}
}
void Initialize(base::OnceClosure callback) override {
is_shutdown_ = false;
adapter_observer_->AdapterPresentChanged(this, true);
std::move(callback).Run();
}
void SetPowered(bool powered,
base::OnceClosure callback,
ErrorCallback error_callback) override {
is_powered_ = powered;
adapter_observer_->AdapterPoweredChanged(this, powered);
std::move(callback).Run();
}
void SetServiceAllowList(const UUIDList& uuids,
base::OnceClosure callback,
ErrorCallback error_callback) override {
uuids_ = uuids;
}
void SetSimpleSecurePairingEnabled(bool enabled,
base::OnceClosure callback,
ErrorCallback error_callback) override {
is_simple_secure_pairing_enabled_ = enabled;
}
bool IsPresent() const override { return !is_shutdown_; }
bool IsPowered() const override { return is_powered_; }
const UUIDList& GetAllowList() const { return uuids_; }
bool IsSimpleSecurePairingEnabled() {
return is_simple_secure_pairing_enabled_;
}
void AddObserver(device::BluetoothAdapter::Observer* observer) override {
DCHECK(!adapter_observer_);
adapter_observer_ = observer;
}
protected:
~TestingBluetoothAdapter() override = default;
bool is_shutdown_ = false;
bool is_powered_ = true;
UUIDList uuids_;
bool is_simple_secure_pairing_enabled_ = false;
raw_ptr<device::BluetoothAdapter::Observer, DanglingUntriaged>
adapter_observer_ = nullptr;
};
BluetoothPolicyHandlerTest()
: adapter_(base::MakeRefCounted<TestingBluetoothAdapter>()) {}
~BluetoothPolicyHandlerTest() override = default;
// testing::Test
void SetUp() override {
testing::Test::SetUp();
device::BluetoothAdapterFactory::SetAdapterForTesting(adapter_);
ash::LoginState::Initialize();
ash::LoginState::Get()->set_always_logged_in(false);
}
void TearDown() override {
testing::Test::TearDown();
ash::LoginState::Shutdown();
}
protected:
void SetAllowBluetooth(bool allow_bluetooth) {
scoped_testing_cros_settings_.device_settings()->SetBoolean(
ash::kAllowBluetooth, allow_bluetooth);
}
void SetDeviceAllowedBluetoothServices(base::Value::List allowlist) {
scoped_testing_cros_settings_.device_settings()->Set(
ash::kDeviceAllowedBluetoothServices,
base::Value(std::move(allowlist)));
}
void SetJustWorksBluetoothPairingPolicyEnabled(bool enabled) {
scoped_testing_cros_settings_.device_settings()->SetBoolean(
ash::kDeviceBluetoothJustWorksPairingEnabled, enabled);
}
void Login() {
ash::LoginState::Get()->SetLoggedInState(
ash::LoginState::LOGGED_IN_ACTIVE,
ash::LoginState::LOGGED_IN_USER_REGULAR);
}
void Logout() {
ash::LoginState::Get()->SetLoggedInState(
ash::LoginState::LOGGED_IN_NONE, ash::LoginState::LOGGED_IN_USER_NONE);
}
base::test::TaskEnvironment task_environment_;
scoped_refptr<TestingBluetoothAdapter> adapter_;
ash::ScopedTestingCrosSettings scoped_testing_cros_settings_;
};
TEST_F(BluetoothPolicyHandlerTest, TestZeroOnOffOn) {
BluetoothPolicyHandler shutdown_policy_handler(ash::CrosSettings::Get());
EXPECT_TRUE(adapter_->IsPresent());
SetAllowBluetooth(true);
EXPECT_TRUE(adapter_->IsPresent());
SetAllowBluetooth(false);
EXPECT_FALSE(adapter_->IsPresent());
EXPECT_FALSE(adapter_->IsPowered());
// Once the Bluetooth stack goes down, it needs a reboot to come back up.
SetAllowBluetooth(true);
EXPECT_FALSE(adapter_->IsPresent());
}
TEST_F(BluetoothPolicyHandlerTest, OffDuringStartup) {
SetAllowBluetooth(false);
BluetoothPolicyHandler shutdown_policy_handler(ash::CrosSettings::Get());
EXPECT_FALSE(adapter_->IsPresent());
EXPECT_FALSE(adapter_->IsPowered());
}
TEST_F(BluetoothPolicyHandlerTest, OnDuringStartup) {
SetAllowBluetooth(true);
BluetoothPolicyHandler shutdown_policy_handler(ash::CrosSettings::Get());
EXPECT_TRUE(adapter_->IsPresent());
}
TEST_F(BluetoothPolicyHandlerTest, TestSetServiceAllowList) {
base::Value::List allowlist;
const char kTestUuid1[] = "0x1124";
const char kTestUuid2[] = "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee";
allowlist.Append(kTestUuid1);
allowlist.Append(kTestUuid2);
SetDeviceAllowedBluetoothServices(std::move(allowlist));
BluetoothPolicyHandler bluetooth_policy_handler(ash::CrosSettings::Get());
const device::BluetoothUUID test_uuid1(kTestUuid1);
const device::BluetoothUUID test_uuid2(kTestUuid2);
const std::vector<device::BluetoothUUID>& allowlist_result =
adapter_->GetAllowList();
ASSERT_EQ(2u, allowlist_result.size());
EXPECT_EQ(test_uuid1, allowlist_result[0]);
EXPECT_EQ(test_uuid2, allowlist_result[1]);
}
TEST_F(BluetoothPolicyHandlerTest, TestPolicySettingsWhileBTNotReady) {
base::Value::List allowlist;
const char kTestUuid1[] = "0x1124";
const char kTestUuid2[] = "0x1108";
std::vector<device::BluetoothUUID> allowlist_result;
const device::BluetoothUUID test_uuid1(kTestUuid1);
const device::BluetoothUUID test_uuid2(kTestUuid2);
BluetoothPolicyHandler bluetooth_policy_handler(ash::CrosSettings::Get());
allowlist.Append(kTestUuid1);
adapter_->Shutdown();
ASSERT_TRUE(!adapter_->IsPresent());
ASSERT_TRUE(adapter_->IsPowered());
SetDeviceAllowedBluetoothServices(allowlist.Clone());
// policy is not propagated to adapter since it's not yet ready.
allowlist_result = adapter_->GetAllowList();
EXPECT_EQ(0u, allowlist_result.size());
adapter_->Initialize(base::DoNothing());
ASSERT_TRUE(adapter_->IsPresent());
ASSERT_TRUE(adapter_->IsPowered());
ASSERT_TRUE(adapter_->IsInitialized());
allowlist_result = adapter_->GetAllowList();
// policy should be set to adapter after adapter is ready.
ASSERT_EQ(1u, allowlist_result.size());
EXPECT_EQ(test_uuid1, allowlist_result[0]);
adapter_->SetPowered(false, base::DoNothing(), base::DoNothing());
allowlist.Append(kTestUuid2);
SetDeviceAllowedBluetoothServices(allowlist.Clone());
// policy is not propagated to adapter since it's not powered.
allowlist_result = adapter_->GetAllowList();
ASSERT_EQ(1u, allowlist_result.size());
EXPECT_EQ(test_uuid1, allowlist_result[0]);
adapter_->SetPowered(true, base::DoNothing(), base::DoNothing());
ASSERT_TRUE(adapter_->IsPresent());
ASSERT_TRUE(adapter_->IsPowered());
ASSERT_TRUE(adapter_->IsInitialized());
// policy should be set to adapter after adapter is ready.
allowlist_result = adapter_->GetAllowList();
ASSERT_EQ(2u, allowlist_result.size());
EXPECT_EQ(test_uuid1, allowlist_result[0]);
EXPECT_EQ(test_uuid2, allowlist_result[1]);
}
TEST_F(BluetoothPolicyHandlerTest, TestSetJustWorksPairingEnabledSuccess) {
Login();
SetJustWorksBluetoothPairingPolicyEnabled(/*enabled=*/true);
BluetoothPolicyHandler bluetooth_policy_handler(ash::CrosSettings::Get());
EXPECT_TRUE(adapter_->IsSimpleSecurePairingEnabled());
}
TEST_F(BluetoothPolicyHandlerTest,
TestSetJustWorksPairingEnabledWhenNotLogggedInThenNotSet) {
SetJustWorksBluetoothPairingPolicyEnabled(/*enabled=*/true);
BluetoothPolicyHandler bluetooth_policy_handler(ash::CrosSettings::Get());
EXPECT_FALSE(adapter_->IsSimpleSecurePairingEnabled());
}
TEST_F(BluetoothPolicyHandlerTest, TestSetJustWorksPairingEnabledDelayedLogin) {
SetJustWorksBluetoothPairingPolicyEnabled(/*enabled=*/true);
BluetoothPolicyHandler bluetooth_policy_handler(ash::CrosSettings::Get());
Login();
EXPECT_TRUE(adapter_->IsSimpleSecurePairingEnabled());
}
TEST_F(BluetoothPolicyHandlerTest, TestSetJustWorksPairingDisabled) {
Login();
SetJustWorksBluetoothPairingPolicyEnabled(/*enabled=*/false);
BluetoothPolicyHandler bluetooth_policy_handler(ash::CrosSettings::Get());
EXPECT_FALSE(adapter_->IsSimpleSecurePairingEnabled());
}
TEST_F(BluetoothPolicyHandlerTest,
TestSetJustWorksPairingDisabledNotLoggedInNotSet) {
SetJustWorksBluetoothPairingPolicyEnabled(/*enabled=*/false);
BluetoothPolicyHandler bluetooth_policy_handler(ash::CrosSettings::Get());
EXPECT_FALSE(adapter_->IsSimpleSecurePairingEnabled());
}
TEST_F(BluetoothPolicyHandlerTest,
TestSetJustWorksPairingDisabledDelayedLogin) {
SetJustWorksBluetoothPairingPolicyEnabled(/*enabled=*/false);
BluetoothPolicyHandler bluetooth_policy_handler(ash::CrosSettings::Get());
Login();
EXPECT_FALSE(adapter_->IsSimpleSecurePairingEnabled());
}
TEST_F(BluetoothPolicyHandlerTest,
TestSetJustWorksPairingEnabledWhenUserLogsInAndLogsOut) {
Login();
SetJustWorksBluetoothPairingPolicyEnabled(/*enabled=*/true);
BluetoothPolicyHandler bluetooth_policy_handler(ash::CrosSettings::Get());
EXPECT_TRUE(adapter_->IsSimpleSecurePairingEnabled());
Logout();
EXPECT_FALSE(adapter_->IsSimpleSecurePairingEnabled());
}
} // namespace policy