| // Copyright 2021 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 "chrome/browser/ash/crosapi/prefs_ash.h" |
| |
| #include <memory> |
| |
| #include "ash/constants/ash_pref_names.h" |
| #include "base/callback_helpers.h" |
| #include "base/test/bind.h" |
| #include "chrome/test/base/scoped_testing_local_state.h" |
| #include "chrome/test/base/testing_browser_process.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "chrome/test/base/testing_profile_manager.h" |
| #include "components/metrics/metrics_pref_names.h" |
| #include "components/prefs/pref_registry_simple.h" |
| #include "components/prefs/testing_pref_service.h" |
| #include "content/public/test/browser_task_environment.h" |
| #include "mojo/public/cpp/bindings/receiver.h" |
| #include "mojo/public/cpp/bindings/remote.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/abseil-cpp/absl/types/optional.h" |
| |
| namespace crosapi { |
| namespace { |
| |
| class TestObserver : public mojom::PrefObserver { |
| public: |
| TestObserver() = default; |
| TestObserver(const TestObserver&) = delete; |
| TestObserver& operator=(const TestObserver&) = delete; |
| ~TestObserver() override = default; |
| |
| // crosapi::mojom::PrefObserver: |
| void OnPrefChanged(base::Value value) override { value_ = std::move(value); } |
| |
| absl::optional<base::Value> value_; |
| mojo::Receiver<mojom::PrefObserver> receiver_{this}; |
| }; |
| |
| } // namespace |
| |
| class PrefsAshTest : public testing::Test { |
| public: |
| PrefsAshTest() = default; |
| PrefsAshTest(const PrefsAshTest&) = delete; |
| PrefsAshTest& operator=(const PrefsAshTest&) = delete; |
| ~PrefsAshTest() override = default; |
| |
| void SetUp() override { ASSERT_TRUE(testing_profile_manager_.SetUp()); } |
| |
| PrefService* local_state() { |
| return testing_profile_manager_.local_state()->Get(); |
| } |
| ProfileManager* profile_manager() { |
| return testing_profile_manager_.profile_manager(); |
| } |
| |
| Profile* CreateProfile() { |
| return testing_profile_manager_.CreateTestingProfile(std::string()); |
| } |
| |
| content::BrowserTaskEnvironment task_environment_; |
| |
| private: |
| TestingProfileManager testing_profile_manager_{ |
| TestingBrowserProcess::GetGlobal()}; |
| }; |
| |
| TEST_F(PrefsAshTest, LocalStatePrefs) { |
| local_state()->SetBoolean(metrics::prefs::kMetricsReportingEnabled, false); |
| PrefsAsh prefs_ash(profile_manager(), local_state()); |
| prefs_ash.OnPrimaryProfileReadyForTesting(CreateProfile()); |
| mojo::Remote<mojom::Prefs> prefs_remote; |
| prefs_ash.BindReceiver(prefs_remote.BindNewPipeAndPassReceiver()); |
| mojom::PrefPath path = mojom::PrefPath::kMetricsReportingEnabled; |
| |
| // Get returns value. |
| base::Value get_value; |
| prefs_remote->GetPref( |
| path, base::BindLambdaForTesting([&](absl::optional<base::Value> value) { |
| get_value = std::move(*value); |
| })); |
| prefs_remote.FlushForTesting(); |
| EXPECT_FALSE(get_value.GetBool()); |
| |
| // Set updates value. |
| prefs_remote->SetPref(path, base::Value(true), base::DoNothing()); |
| prefs_remote.FlushForTesting(); |
| EXPECT_TRUE( |
| local_state()->GetBoolean(metrics::prefs::kMetricsReportingEnabled)); |
| |
| // Adding an observer results in it being fired with the current state. |
| EXPECT_FALSE(prefs_ash.local_state_registrar_.IsObserved( |
| metrics::prefs::kMetricsReportingEnabled)); |
| auto observer1 = std::make_unique<TestObserver>(); |
| prefs_remote->AddObserver(path, |
| observer1->receiver_.BindNewPipeAndPassRemote()); |
| prefs_remote.FlushForTesting(); |
| EXPECT_TRUE(observer1->value_->GetBool()); |
| EXPECT_TRUE(prefs_ash.local_state_registrar_.IsObserved( |
| metrics::prefs::kMetricsReportingEnabled)); |
| EXPECT_EQ(1, prefs_ash.observers_[path].size()); |
| |
| // Multiple observers is ok. |
| auto observer2 = std::make_unique<TestObserver>(); |
| prefs_remote->AddObserver(path, |
| observer2->receiver_.BindNewPipeAndPassRemote()); |
| prefs_remote.FlushForTesting(); |
| EXPECT_TRUE(observer2->value_->GetBool()); |
| EXPECT_EQ(2, prefs_ash.observers_[path].size()); |
| |
| // Observer should be notified when value changes. |
| local_state()->SetBoolean(metrics::prefs::kMetricsReportingEnabled, false); |
| task_environment_.RunUntilIdle(); |
| EXPECT_FALSE(observer1->value_->GetBool()); |
| EXPECT_FALSE(observer2->value_->GetBool()); |
| |
| // Disconnect should remove PrefChangeRegistrar. |
| observer1.reset(); |
| prefs_remote.FlushForTesting(); |
| EXPECT_EQ(1, prefs_ash.observers_[path].size()); |
| observer2.reset(); |
| prefs_remote.FlushForTesting(); |
| EXPECT_EQ(0, prefs_ash.observers_[path].size()); |
| EXPECT_FALSE(prefs_ash.local_state_registrar_.IsObserved( |
| metrics::prefs::kMetricsReportingEnabled)); |
| } |
| |
| TEST_F(PrefsAshTest, ProfilePrefs) { |
| Profile* const profile = CreateProfile(); |
| PrefService* const profile_prefs = profile->GetPrefs(); |
| profile_prefs->SetBoolean(ash::prefs::kAccessibilitySpokenFeedbackEnabled, |
| false); |
| PrefsAsh prefs_ash(profile_manager(), local_state()); |
| prefs_ash.OnPrimaryProfileReadyForTesting(profile); |
| |
| mojo::Remote<mojom::Prefs> prefs_remote; |
| prefs_ash.BindReceiver(prefs_remote.BindNewPipeAndPassReceiver()); |
| mojom::PrefPath path = mojom::PrefPath::kAccessibilitySpokenFeedbackEnabled; |
| |
| // Get returns value. |
| base::Value get_value; |
| prefs_remote->GetPref( |
| path, base::BindLambdaForTesting([&](absl::optional<base::Value> value) { |
| get_value = std::move(*value); |
| })); |
| prefs_remote.FlushForTesting(); |
| EXPECT_FALSE(get_value.GetBool()); |
| |
| // Set updates value. |
| prefs_remote->SetPref(path, base::Value(true), base::DoNothing()); |
| prefs_remote.FlushForTesting(); |
| EXPECT_TRUE(profile_prefs->GetBoolean( |
| ash::prefs::kAccessibilitySpokenFeedbackEnabled)); |
| |
| // Adding an observer results in it being fired with the current state. |
| TestObserver observer; |
| prefs_remote->AddObserver(path, |
| observer.receiver_.BindNewPipeAndPassRemote()); |
| prefs_remote.FlushForTesting(); |
| EXPECT_TRUE(observer.value_->GetBool()); |
| } |
| |
| TEST_F(PrefsAshTest, GetUnknown) { |
| PrefsAsh prefs_ash(profile_manager(), local_state()); |
| prefs_ash.OnPrimaryProfileReadyForTesting(CreateProfile()); |
| mojo::Remote<mojom::Prefs> prefs_remote; |
| prefs_ash.BindReceiver(prefs_remote.BindNewPipeAndPassReceiver()); |
| mojom::PrefPath path = mojom::PrefPath::kUnknown; |
| |
| // Get for an unknown value returns absl::nullopt. |
| bool has_value = true; |
| prefs_remote->GetPref( |
| path, base::BindLambdaForTesting([&](absl::optional<base::Value> value) { |
| has_value = value.has_value(); |
| })); |
| prefs_remote.FlushForTesting(); |
| EXPECT_FALSE(has_value); |
| |
| // Set or AddObserver for an unknown value does nothing. |
| prefs_remote->SetPref(path, base::Value(false), base::DoNothing()); |
| TestObserver observer; |
| prefs_remote->AddObserver(path, |
| observer.receiver_.BindNewPipeAndPassRemote()); |
| prefs_remote.FlushForTesting(); |
| EXPECT_FALSE(observer.value_.has_value()); |
| } |
| |
| } // namespace crosapi |