#include "ash/policy/policy_recommendation_restorer.h"
#include "ash/constants/ash_pref_names.h"
#include "ash/public/cpp/ash_prefs.h"
#include "ash/session/session_controller_impl.h"
#include "ash/session/test_session_controller_client.h"
#include "ash/shell.h"
#include "ash/test/ash_test_base.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "components/prefs/pref_notifier_impl.h"
#include "components/prefs/testing_pref_store.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "ui/base/user_activity/user_activity_detector.h"
namespace ash {
class PolicyRecommendationRestorerTest : public NoSessionAshTestBase {
public:
PolicyRecommendationRestorerTest(const PolicyRecommendationRestorerTest&) =
delete;
PolicyRecommendationRestorerTest& operator=(
const PolicyRecommendationRestorerTest&) = delete;
protected:
PolicyRecommendationRestorerTest()
: recommended_prefs_(base::MakeRefCounted<TestingPrefStore>()),
prefs_(new sync_preferences::TestingPrefServiceSyncable(
base::MakeRefCounted<TestingPrefStore>(),
base::MakeRefCounted<TestingPrefStore>(),
base::MakeRefCounted<TestingPrefStore>(),
base::MakeRefCounted<TestingPrefStore>(),
recommended_prefs_,
base::MakeRefCounted<user_prefs::PrefRegistrySyncable>(),
std::make_unique<PrefNotifierImpl>())) {}
~PolicyRecommendationRestorerTest() override = default;
void SetUp() override {
set_create_signin_pref_service(false);
NoSessionAshTestBase::SetUp();
RegisterSigninProfilePrefs(prefs_->registry(), "",
true);
restorer_ = Shell::Get()->policy_recommendation_restorer();
}
void ConnectToSigninPrefService() {
GetSessionControllerClient()->SetSigninScreenPrefService(
base::WrapUnique(prefs_.get()));
ASSERT_EQ(Shell::Get()->session_controller()->GetSigninScreenPrefService(),
prefs_);
ui::UserActivityDetector::Get()->HandleExternalUserActivity();
}
void SetRecommendedValues() {
recommended_prefs_->SetBoolean(prefs::kAccessibilityLargeCursorEnabled,
false);
recommended_prefs_->SetBoolean(prefs::kAccessibilitySpokenFeedbackEnabled,
false);
recommended_prefs_->SetBoolean(prefs::kAccessibilityHighContrastEnabled,
false);
recommended_prefs_->SetBoolean(prefs::kAccessibilityScreenMagnifierEnabled,
false);
recommended_prefs_->SetBoolean(prefs::kAccessibilityVirtualKeyboardEnabled,
false);
}
void SetUserSettings() {
prefs_->SetBoolean(prefs::kAccessibilityLargeCursorEnabled, true);
prefs_->SetBoolean(prefs::kAccessibilitySpokenFeedbackEnabled, true);
prefs_->SetBoolean(prefs::kAccessibilityHighContrastEnabled, true);
prefs_->SetBoolean(prefs::kAccessibilityScreenMagnifierEnabled, true);
prefs_->SetBoolean(prefs::kAccessibilityVirtualKeyboardEnabled, true);
}
void VerifyPrefFollowsUser(const std::string& pref_name,
const base::Value& expected_value) const {
const sync_preferences::PrefServiceSyncable::Preference* pref =
prefs_->FindPreference(pref_name);
ASSERT_TRUE(pref);
EXPECT_TRUE(pref->HasUserSetting());
const base::Value* value = pref->GetValue();
ASSERT_TRUE(value);
EXPECT_EQ(expected_value, *value);
}
void VerifyPrefsFollowUser() const {
VerifyPrefFollowsUser(prefs::kAccessibilityLargeCursorEnabled,
base::Value(true));
VerifyPrefFollowsUser(prefs::kAccessibilitySpokenFeedbackEnabled,
base::Value(true));
VerifyPrefFollowsUser(prefs::kAccessibilityHighContrastEnabled,
base::Value(true));
VerifyPrefFollowsUser(prefs::kAccessibilityScreenMagnifierEnabled,
base::Value(true));
VerifyPrefFollowsUser(prefs::kAccessibilityVirtualKeyboardEnabled,
base::Value(true));
}
void VerifyPrefFollowsRecommendation(
const std::string& pref_name,
const base::Value& expected_value) const {
const sync_preferences::PrefServiceSyncable::Preference* pref =
prefs_->FindPreference(pref_name);
ASSERT_TRUE(pref);
EXPECT_TRUE(pref->IsRecommended());
EXPECT_FALSE(pref->HasUserSetting());
const base::Value* value = pref->GetValue();
ASSERT_TRUE(value);
EXPECT_EQ(expected_value, *value);
}
void VerifyPrefsFollowRecommendation() const {
VerifyPrefFollowsRecommendation(prefs::kAccessibilityLargeCursorEnabled,
base::Value(false));
VerifyPrefFollowsRecommendation(prefs::kAccessibilitySpokenFeedbackEnabled,
base::Value(false));
VerifyPrefFollowsRecommendation(prefs::kAccessibilityHighContrastEnabled,
base::Value(false));
VerifyPrefFollowsRecommendation(prefs::kAccessibilityScreenMagnifierEnabled,
base::Value(false));
VerifyPrefFollowsRecommendation(prefs::kAccessibilityVirtualKeyboardEnabled,
base::Value(false));
}
bool RestoreTimerIsRunning() {
return restorer_->restore_timer_for_test()->IsRunning();
}
[[nodiscard]] bool TriggerRestoreTimer() {
if (!restorer_->restore_timer_for_test()->IsRunning())
return false;
restorer_->restore_timer_for_test()->FireNow();
return true;
}
raw_ptr<PolicyRecommendationRestorer, DanglingUntriaged> restorer_ = nullptr;
scoped_refptr<TestingPrefStore> recommended_prefs_;
raw_ptr<sync_preferences::TestingPrefServiceSyncable, DanglingUntriaged>
prefs_;
};
TEST_F(PolicyRecommendationRestorerTest, NoRecommendations) {
SetUserSettings();
ConnectToSigninPrefService();
VerifyPrefsFollowUser();
EXPECT_FALSE(RestoreTimerIsRunning());
}
TEST_F(PolicyRecommendationRestorerTest, RestoreOnSigninPrefInitialized) {
SetRecommendedValues();
SetUserSettings();
ConnectToSigninPrefService();
VerifyPrefsFollowRecommendation();
EXPECT_FALSE(RestoreTimerIsRunning());
}
TEST_F(PolicyRecommendationRestorerTest,
RestoreOnRecommendationChangeOnSigninScreen) {
ConnectToSigninPrefService();
EXPECT_FALSE(RestoreTimerIsRunning());
prefs_->SetBoolean(prefs::kAccessibilityLargeCursorEnabled, true);
VerifyPrefFollowsUser(prefs::kAccessibilityLargeCursorEnabled,
base::Value(true));
EXPECT_FALSE(RestoreTimerIsRunning());
recommended_prefs_->SetBoolean(prefs::kAccessibilityLargeCursorEnabled,
false);
EXPECT_TRUE(TriggerRestoreTimer());
VerifyPrefFollowsRecommendation(prefs::kAccessibilityLargeCursorEnabled,
base::Value(false));
prefs_->SetBoolean(prefs::kAccessibilitySpokenFeedbackEnabled, true);
VerifyPrefFollowsUser(prefs::kAccessibilitySpokenFeedbackEnabled,
base::Value(true));
recommended_prefs_->SetBoolean(prefs::kAccessibilitySpokenFeedbackEnabled,
false);
EXPECT_TRUE(TriggerRestoreTimer());
VerifyPrefFollowsRecommendation(prefs::kAccessibilitySpokenFeedbackEnabled,
base::Value(false));
prefs_->SetBoolean(prefs::kAccessibilityHighContrastEnabled, true);
VerifyPrefFollowsUser(prefs::kAccessibilityHighContrastEnabled,
base::Value(true));
recommended_prefs_->SetBoolean(prefs::kAccessibilityHighContrastEnabled,
false);
EXPECT_TRUE(TriggerRestoreTimer());
VerifyPrefFollowsRecommendation(prefs::kAccessibilityHighContrastEnabled,
base::Value(false));
prefs_->SetBoolean(prefs::kAccessibilityScreenMagnifierEnabled, true);
VerifyPrefFollowsUser(prefs::kAccessibilityScreenMagnifierEnabled,
base::Value(true));
recommended_prefs_->SetBoolean(prefs::kAccessibilityScreenMagnifierEnabled,
false);
EXPECT_TRUE(TriggerRestoreTimer());
VerifyPrefFollowsRecommendation(prefs::kAccessibilityScreenMagnifierEnabled,
base::Value(false));
prefs_->SetBoolean(prefs::kAccessibilityVirtualKeyboardEnabled, true);
VerifyPrefFollowsUser(prefs::kAccessibilityVirtualKeyboardEnabled,
base::Value(true));
recommended_prefs_->SetBoolean(prefs::kAccessibilityVirtualKeyboardEnabled,
false);
EXPECT_TRUE(TriggerRestoreTimer());
VerifyPrefFollowsRecommendation(prefs::kAccessibilityVirtualKeyboardEnabled,
base::Value(false));
}
TEST_F(PolicyRecommendationRestorerTest,
RestoreOnRecommendationChangeOnUserSession) {
SetUserSettings();
ConnectToSigninPrefService();
SimulateUserLogin({"user@test.com"});
VerifyPrefFollowsUser(prefs::kAccessibilityLargeCursorEnabled,
base::Value(true));
recommended_prefs_->SetBoolean(prefs::kAccessibilityLargeCursorEnabled,
false);
EXPECT_FALSE(RestoreTimerIsRunning());
VerifyPrefFollowsRecommendation(prefs::kAccessibilityLargeCursorEnabled,
base::Value(false));
VerifyPrefFollowsUser(prefs::kAccessibilitySpokenFeedbackEnabled,
base::Value(true));
recommended_prefs_->SetBoolean(prefs::kAccessibilitySpokenFeedbackEnabled,
false);
EXPECT_FALSE(RestoreTimerIsRunning());
VerifyPrefFollowsRecommendation(prefs::kAccessibilitySpokenFeedbackEnabled,
base::Value(false));
VerifyPrefFollowsUser(prefs::kAccessibilityHighContrastEnabled,
base::Value(true));
recommended_prefs_->SetBoolean(prefs::kAccessibilityHighContrastEnabled,
false);
EXPECT_FALSE(RestoreTimerIsRunning());
VerifyPrefFollowsRecommendation(prefs::kAccessibilityHighContrastEnabled,
base::Value(false));
VerifyPrefFollowsUser(prefs::kAccessibilityScreenMagnifierEnabled,
base::Value(true));
recommended_prefs_->SetBoolean(prefs::kAccessibilityScreenMagnifierEnabled,
false);
EXPECT_FALSE(RestoreTimerIsRunning());
VerifyPrefFollowsRecommendation(prefs::kAccessibilityScreenMagnifierEnabled,
base::Value(false));
VerifyPrefFollowsUser(prefs::kAccessibilityVirtualKeyboardEnabled,
base::Value(true));
recommended_prefs_->SetBoolean(prefs::kAccessibilityVirtualKeyboardEnabled,
false);
EXPECT_FALSE(RestoreTimerIsRunning());
VerifyPrefFollowsRecommendation(prefs::kAccessibilityVirtualKeyboardEnabled,
base::Value(false));
}
TEST_F(PolicyRecommendationRestorerTest, DoNothingOnUserChange) {
ConnectToSigninPrefService();
prefs_->SetBoolean(prefs::kAccessibilityMonoAudioEnabled, true);
VerifyPrefFollowsUser(prefs::kAccessibilityMonoAudioEnabled,
base::Value(true));
EXPECT_FALSE(RestoreTimerIsRunning());
}
TEST_F(PolicyRecommendationRestorerTest, RestoreOnUserChange) {
SetRecommendedValues();
ConnectToSigninPrefService();
EXPECT_FALSE(RestoreTimerIsRunning());
prefs_->SetBoolean(prefs::kAccessibilityLargeCursorEnabled, true);
VerifyPrefFollowsUser(prefs::kAccessibilityLargeCursorEnabled,
base::Value(true));
EXPECT_TRUE(TriggerRestoreTimer());
VerifyPrefFollowsRecommendation(prefs::kAccessibilityLargeCursorEnabled,
base::Value(false));
EXPECT_FALSE(RestoreTimerIsRunning());
prefs_->SetBoolean(prefs::kAccessibilitySpokenFeedbackEnabled, true);
VerifyPrefFollowsUser(prefs::kAccessibilitySpokenFeedbackEnabled,
base::Value(true));
EXPECT_TRUE(TriggerRestoreTimer());
VerifyPrefFollowsRecommendation(prefs::kAccessibilitySpokenFeedbackEnabled,
base::Value(false));
EXPECT_FALSE(RestoreTimerIsRunning());
prefs_->SetBoolean(prefs::kAccessibilityHighContrastEnabled, true);
VerifyPrefFollowsUser(prefs::kAccessibilityHighContrastEnabled,
base::Value(true));
EXPECT_TRUE(TriggerRestoreTimer());
VerifyPrefFollowsRecommendation(prefs::kAccessibilityHighContrastEnabled,
base::Value(false));
EXPECT_FALSE(RestoreTimerIsRunning());
prefs_->SetBoolean(prefs::kAccessibilityScreenMagnifierEnabled, true);
VerifyPrefFollowsUser(prefs::kAccessibilityScreenMagnifierEnabled,
base::Value(true));
EXPECT_TRUE(TriggerRestoreTimer());
VerifyPrefFollowsRecommendation(prefs::kAccessibilityScreenMagnifierEnabled,
base::Value(false));
EXPECT_FALSE(RestoreTimerIsRunning());
prefs_->SetBoolean(prefs::kAccessibilityVirtualKeyboardEnabled, true);
VerifyPrefFollowsUser(prefs::kAccessibilityVirtualKeyboardEnabled,
base::Value(true));
EXPECT_TRUE(TriggerRestoreTimer());
VerifyPrefFollowsRecommendation(prefs::kAccessibilityVirtualKeyboardEnabled,
base::Value(false));
EXPECT_FALSE(RestoreTimerIsRunning());
}
TEST_F(PolicyRecommendationRestorerTest, DoNothingOnSessionStart) {
ConnectToSigninPrefService();
SetUserSettings();
SimulateUserLogin({"user@test.com"});
VerifyPrefsFollowUser();
EXPECT_FALSE(RestoreTimerIsRunning());
}
TEST_F(PolicyRecommendationRestorerTest, UserActivityResetsTimer) {
recommended_prefs_->SetBoolean(prefs::kAccessibilityLargeCursorEnabled,
false);
ConnectToSigninPrefService();
prefs_->SetBoolean(prefs::kAccessibilityLargeCursorEnabled, true);
EXPECT_TRUE(RestoreTimerIsRunning());
restorer_->OnUserActivity(nullptr);
VerifyPrefFollowsUser(prefs::kAccessibilityLargeCursorEnabled,
base::Value(true));
EXPECT_TRUE(TriggerRestoreTimer());
VerifyPrefFollowsRecommendation(prefs::kAccessibilityLargeCursorEnabled,
base::Value(false));
EXPECT_FALSE(RestoreTimerIsRunning());
}
}