1 // Copyright 2010 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/prefs/pref_change_registrar.h"
6
7 #include <memory>
8 #include <string_view>
9
10 #include "base/functional/bind.h"
11 #include "base/functional/callback_helpers.h"
12 #include "components/prefs/pref_observer.h"
13 #include "components/prefs/pref_registry_simple.h"
14 #include "components/prefs/testing_pref_service.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace base {
19 namespace {
20
21 using testing::Mock;
22
23 const char kHomePage[] = "homepage";
24 const char kHomePageIsNewTabPage[] = "homepage_is_newtabpage";
25 const char kApplicationLocale[] = "intl.app_locale";
26
27 // A mock provider that allows us to capture pref observer changes.
28 class MockPrefService : public TestingPrefServiceSimple {
29 public:
30 MockPrefService() = default;
31 ~MockPrefService() override = default;
32
33 MOCK_METHOD(void,
34 AddPrefObserver,
35 (std::string_view, PrefObserver*),
36 (override));
37 MOCK_METHOD(void,
38 RemovePrefObserver,
39 (std::string_view, PrefObserver*),
40 (override));
41 };
42
43 // Due to overloads, base::DoNothing() cannot be passed directly to
44 // PrefChangeRegistrar::Add() as it is convertible to all callbacks.
DoNothingClosure()45 base::RepeatingClosure DoNothingClosure() {
46 return base::DoNothing();
47 }
48
49 } // namespace
50
51 class PrefChangeRegistrarTest : public testing::Test {
52 public:
53 PrefChangeRegistrarTest() = default;
54 ~PrefChangeRegistrarTest() override = default;
55
56 protected:
57 void SetUp() override;
58
service() const59 MockPrefService* service() const { return service_.get(); }
60
61 private:
62 std::unique_ptr<MockPrefService> service_;
63 };
64
SetUp()65 void PrefChangeRegistrarTest::SetUp() {
66 service_ = std::make_unique<MockPrefService>();
67 }
68
TEST_F(PrefChangeRegistrarTest,AddAndRemove)69 TEST_F(PrefChangeRegistrarTest, AddAndRemove) {
70 PrefChangeRegistrar registrar;
71 registrar.Init(service());
72
73 // Test adding.
74 EXPECT_CALL(*service(), AddPrefObserver("test.pref.1", ®istrar));
75 EXPECT_CALL(*service(), AddPrefObserver("test.pref.2", ®istrar));
76 registrar.Add("test.pref.1", DoNothingClosure());
77 registrar.Add("test.pref.2", DoNothingClosure());
78 EXPECT_FALSE(registrar.IsEmpty());
79
80 // Test removing.
81 Mock::VerifyAndClearExpectations(service());
82 EXPECT_CALL(*service(), RemovePrefObserver("test.pref.1", ®istrar));
83 EXPECT_CALL(*service(), RemovePrefObserver("test.pref.2", ®istrar));
84 registrar.Remove("test.pref.1");
85 registrar.Remove("test.pref.2");
86 EXPECT_TRUE(registrar.IsEmpty());
87
88 // Explicitly check the expectations now to make sure that the Removes
89 // worked (rather than the registrar destructor doing the work).
90 Mock::VerifyAndClearExpectations(service());
91 }
92
TEST_F(PrefChangeRegistrarTest,AutoRemove)93 TEST_F(PrefChangeRegistrarTest, AutoRemove) {
94 PrefChangeRegistrar registrar;
95 registrar.Init(service());
96
97 // Setup of auto-remove.
98 EXPECT_CALL(*service(), AddPrefObserver("test.pref.1", ®istrar));
99 registrar.Add("test.pref.1", DoNothingClosure());
100 Mock::VerifyAndClearExpectations(service());
101 EXPECT_FALSE(registrar.IsEmpty());
102
103 // Test auto-removing.
104 EXPECT_CALL(*service(), RemovePrefObserver("test.pref.1", ®istrar));
105 }
106
TEST_F(PrefChangeRegistrarTest,RemoveAll)107 TEST_F(PrefChangeRegistrarTest, RemoveAll) {
108 PrefChangeRegistrar registrar;
109 registrar.Init(service());
110
111 EXPECT_CALL(*service(), AddPrefObserver("test.pref.1", ®istrar));
112 EXPECT_CALL(*service(), AddPrefObserver("test.pref.2", ®istrar));
113 registrar.Add("test.pref.1", DoNothingClosure());
114 registrar.Add("test.pref.2", DoNothingClosure());
115 Mock::VerifyAndClearExpectations(service());
116
117 EXPECT_CALL(*service(), RemovePrefObserver("test.pref.1", ®istrar));
118 EXPECT_CALL(*service(), RemovePrefObserver("test.pref.2", ®istrar));
119 registrar.RemoveAll();
120 EXPECT_TRUE(registrar.IsEmpty());
121
122 // Explicitly check the expectations now to make sure that the RemoveAll
123 // worked (rather than the registrar destructor doing the work).
124 Mock::VerifyAndClearExpectations(service());
125 }
126
127 class ObserveSetOfPreferencesTest : public testing::Test {
128 public:
SetUp()129 void SetUp() override {
130 pref_service_ = std::make_unique<TestingPrefServiceSimple>();
131 PrefRegistrySimple* registry = pref_service_->registry();
132 registry->RegisterStringPref(kHomePage, "http://google.com");
133 registry->RegisterBooleanPref(kHomePageIsNewTabPage, false);
134 registry->RegisterStringPref(kApplicationLocale, std::string());
135 }
136
CreatePrefChangeRegistrar()137 PrefChangeRegistrar* CreatePrefChangeRegistrar() {
138 PrefChangeRegistrar* pref_set = new PrefChangeRegistrar();
139 pref_set->Init(pref_service_.get());
140 pref_set->Add(kHomePage, DoNothingClosure());
141 pref_set->Add(kHomePageIsNewTabPage, DoNothingClosure());
142 return pref_set;
143 }
144
145 MOCK_METHOD1(OnPreferenceChanged, void(const std::string&));
146
147 std::unique_ptr<TestingPrefServiceSimple> pref_service_;
148 };
149
TEST_F(ObserveSetOfPreferencesTest,IsObserved)150 TEST_F(ObserveSetOfPreferencesTest, IsObserved) {
151 std::unique_ptr<PrefChangeRegistrar> pref_set(CreatePrefChangeRegistrar());
152 EXPECT_TRUE(pref_set->IsObserved(kHomePage));
153 EXPECT_TRUE(pref_set->IsObserved(kHomePageIsNewTabPage));
154 EXPECT_FALSE(pref_set->IsObserved(kApplicationLocale));
155 }
156
TEST_F(ObserveSetOfPreferencesTest,Observe)157 TEST_F(ObserveSetOfPreferencesTest, Observe) {
158 using testing::_;
159 using testing::Mock;
160
161 PrefChangeRegistrar pref_set;
162 PrefChangeRegistrar::NamedChangeCallback callback =
163 base::BindRepeating(&ObserveSetOfPreferencesTest::OnPreferenceChanged,
164 base::Unretained(this));
165 pref_set.Init(pref_service_.get());
166 pref_set.Add(kHomePage, callback);
167 pref_set.Add(kHomePageIsNewTabPage, callback);
168
169 EXPECT_CALL(*this, OnPreferenceChanged(kHomePage));
170 pref_service_->SetUserPref(kHomePage,
171 std::make_unique<Value>("http://crbug.com"));
172 Mock::VerifyAndClearExpectations(this);
173
174 EXPECT_CALL(*this, OnPreferenceChanged(kHomePageIsNewTabPage));
175 pref_service_->SetUserPref(kHomePageIsNewTabPage,
176 std::make_unique<Value>(true));
177 Mock::VerifyAndClearExpectations(this);
178
179 EXPECT_CALL(*this, OnPreferenceChanged(_)).Times(0);
180 pref_service_->SetUserPref(kApplicationLocale,
181 std::make_unique<Value>("en_US.utf8"));
182 Mock::VerifyAndClearExpectations(this);
183 }
184
185 } // namespace base
186