1 // Copyright 2012 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/overlay_user_pref_store.h"
6
7 #include <memory>
8
9 #include "base/test/task_environment.h"
10 #include "base/values.h"
11 #include "components/prefs/persistent_pref_store_unittest.h"
12 #include "components/prefs/pref_store_observer_mock.h"
13 #include "components/prefs/testing_pref_store.h"
14 #include "testing/gmock/include/gmock/gmock.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 using ::testing::Mock;
18 using ::testing::StrEq;
19
20 namespace base {
21 namespace {
22
23 const char kBrowserWindowPlacement[] = "browser.window_placement";
24 const char kShowBookmarkBar[] = "bookmark_bar.show_on_all_tabs";
25 const char kSharedKey[] = "sync_promo.show_on_first_run_allowed";
26
27 const char* const regular_key = kBrowserWindowPlacement;
28 const char* const persistent_key = kShowBookmarkBar;
29 const char* const shared_key = kSharedKey;
30
31 } // namespace
32
33 class OverlayUserPrefStoreTest : public testing::Test {
34 protected:
OverlayUserPrefStoreTest()35 OverlayUserPrefStoreTest()
36 : underlay_(new TestingPrefStore()),
37 overlay_(new OverlayUserPrefStore(underlay_.get())) {
38 overlay_->RegisterPersistentPref(persistent_key);
39 overlay_->RegisterPersistentPref(shared_key);
40 }
41
~OverlayUserPrefStoreTest()42 ~OverlayUserPrefStoreTest() override {}
43
44 base::test::TaskEnvironment task_environment_;
45 scoped_refptr<TestingPrefStore> underlay_;
46 scoped_refptr<OverlayUserPrefStore> overlay_;
47 };
48
TEST_F(OverlayUserPrefStoreTest,Observer)49 TEST_F(OverlayUserPrefStoreTest, Observer) {
50 PrefStoreObserverMock obs;
51 overlay_->AddObserver(&obs);
52
53 // Check that underlay first value is reported.
54 underlay_->SetValue(regular_key, Value(42),
55 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
56 obs.VerifyAndResetChangedKey(regular_key);
57
58 // Check that underlay overwriting is reported.
59 underlay_->SetValue(regular_key, Value(43),
60 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
61 obs.VerifyAndResetChangedKey(regular_key);
62
63 // Check that overwriting change in overlay is reported.
64 overlay_->SetValue(regular_key, Value(44),
65 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
66 obs.VerifyAndResetChangedKey(regular_key);
67
68 // Check that hidden underlay change is not reported.
69 underlay_->SetValue(regular_key, Value(45),
70 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
71 EXPECT_TRUE(obs.changed_keys.empty());
72
73 // Check that overlay remove is reported.
74 overlay_->RemoveValue(regular_key,
75 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
76 obs.VerifyAndResetChangedKey(regular_key);
77
78 // Check that underlay remove is reported.
79 underlay_->RemoveValue(regular_key,
80 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
81 obs.VerifyAndResetChangedKey(regular_key);
82
83 // Check respecting of silence.
84 overlay_->SetValueSilently(regular_key, Value(46),
85 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
86 EXPECT_TRUE(obs.changed_keys.empty());
87
88 overlay_->RemoveObserver(&obs);
89
90 // Check successful unsubscription.
91 underlay_->SetValue(regular_key, Value(47),
92 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
93 overlay_->SetValue(regular_key, Value(48),
94 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
95 EXPECT_TRUE(obs.changed_keys.empty());
96 }
97
TEST_F(OverlayUserPrefStoreTest,GetAndSet)98 TEST_F(OverlayUserPrefStoreTest, GetAndSet) {
99 const Value* value = nullptr;
100 EXPECT_FALSE(overlay_->GetValue(regular_key, &value));
101 EXPECT_FALSE(underlay_->GetValue(regular_key, &value));
102
103 underlay_->SetValue(regular_key, Value(42),
104 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
105
106 // Value shines through:
107 EXPECT_TRUE(overlay_->GetValue(regular_key, &value));
108 EXPECT_EQ(base::Value(42), *value);
109
110 EXPECT_TRUE(underlay_->GetValue(regular_key, &value));
111 EXPECT_EQ(base::Value(42), *value);
112
113 overlay_->SetValue(regular_key, Value(43),
114 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
115
116 EXPECT_TRUE(overlay_->GetValue(regular_key, &value));
117 EXPECT_EQ(base::Value(43), *value);
118
119 EXPECT_TRUE(underlay_->GetValue(regular_key, &value));
120 EXPECT_EQ(base::Value(42), *value);
121
122 overlay_->RemoveValue(regular_key,
123 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
124
125 // Value shines through:
126 EXPECT_TRUE(overlay_->GetValue(regular_key, &value));
127 EXPECT_EQ(base::Value(42), *value);
128
129 EXPECT_TRUE(underlay_->GetValue(regular_key, &value));
130 EXPECT_EQ(base::Value(42), *value);
131 }
132
133 // Check that GetMutableValue does not return the dictionary of the underlay.
TEST_F(OverlayUserPrefStoreTest,ModifyDictionaries)134 TEST_F(OverlayUserPrefStoreTest, ModifyDictionaries) {
135 underlay_->SetValue(regular_key, base::Value(base::Value::Dict()),
136 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
137
138 Value* modify = nullptr;
139 EXPECT_TRUE(overlay_->GetMutableValue(regular_key, &modify));
140 ASSERT_TRUE(modify);
141 ASSERT_TRUE(modify->is_dict());
142 modify->GetDict().SetByDottedPath(regular_key, 42);
143
144 Value* original_in_underlay = nullptr;
145 EXPECT_TRUE(underlay_->GetMutableValue(regular_key, &original_in_underlay));
146 ASSERT_TRUE(original_in_underlay);
147 ASSERT_TRUE(original_in_underlay->is_dict());
148 EXPECT_TRUE(original_in_underlay->GetDict().empty());
149
150 Value* modified = nullptr;
151 EXPECT_TRUE(overlay_->GetMutableValue(regular_key, &modified));
152 ASSERT_TRUE(modified);
153 ASSERT_TRUE(modified->is_dict());
154 EXPECT_EQ(*modify, *modified);
155 }
156
157 // Here we consider a global preference that is not overlayed.
TEST_F(OverlayUserPrefStoreTest,GlobalPref)158 TEST_F(OverlayUserPrefStoreTest, GlobalPref) {
159 PrefStoreObserverMock obs;
160 overlay_->AddObserver(&obs);
161
162 const Value* value = nullptr;
163
164 // Check that underlay first value is reported.
165 underlay_->SetValue(persistent_key, Value(42),
166 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
167 obs.VerifyAndResetChangedKey(persistent_key);
168
169 // Check that underlay overwriting is reported.
170 underlay_->SetValue(persistent_key, Value(43),
171 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
172 obs.VerifyAndResetChangedKey(persistent_key);
173
174 // Check that we get this value from the overlay
175 EXPECT_TRUE(overlay_->GetValue(persistent_key, &value));
176 EXPECT_EQ(base::Value(43), *value);
177
178 // Check that overwriting change in overlay is reported.
179 overlay_->SetValue(persistent_key, Value(44),
180 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
181 obs.VerifyAndResetChangedKey(persistent_key);
182
183 // Check that we get this value from the overlay and the underlay.
184 EXPECT_TRUE(overlay_->GetValue(persistent_key, &value));
185 EXPECT_EQ(base::Value(44), *value);
186 EXPECT_TRUE(underlay_->GetValue(persistent_key, &value));
187 EXPECT_EQ(base::Value(44), *value);
188
189 // Check that overlay remove is reported.
190 overlay_->RemoveValue(persistent_key,
191 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
192 obs.VerifyAndResetChangedKey(persistent_key);
193
194 // Check that value was removed from overlay and underlay
195 EXPECT_FALSE(overlay_->GetValue(persistent_key, &value));
196 EXPECT_FALSE(underlay_->GetValue(persistent_key, &value));
197
198 // Check respecting of silence.
199 overlay_->SetValueSilently(persistent_key, Value(46),
200 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
201 EXPECT_TRUE(obs.changed_keys.empty());
202
203 overlay_->RemoveObserver(&obs);
204
205 // Check successful unsubscription.
206 underlay_->SetValue(persistent_key, Value(47),
207 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
208 overlay_->SetValue(persistent_key, Value(48),
209 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
210 EXPECT_TRUE(obs.changed_keys.empty());
211 }
212
TEST_F(OverlayUserPrefStoreTest,GetValues)213 TEST_F(OverlayUserPrefStoreTest, GetValues) {
214 // To check merge behavior, create underlay and overlay so each has a key the
215 // other doesn't have and they have one key in common.
216 underlay_->SetValue(persistent_key, Value(42),
217 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
218 overlay_->SetValue(regular_key, Value(43),
219 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
220 underlay_->SetValue(shared_key, Value(42),
221 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
222 overlay_->SetValue(shared_key, Value(43),
223 WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
224
225 auto values = overlay_->GetValues();
226 // Check that an overlay preference is returned.
227 const Value* value = values.FindByDottedPath(persistent_key);
228 ASSERT_TRUE(value);
229 EXPECT_EQ(base::Value(42), *value);
230
231 // Check that an underlay preference is returned.
232 value = values.FindByDottedPath(regular_key);
233 ASSERT_TRUE(value);
234 EXPECT_EQ(base::Value(43), *value);
235
236 // Check that the overlay is preferred.
237 value = values.FindByDottedPath(shared_key);
238 ASSERT_TRUE(value);
239 EXPECT_EQ(base::Value(43), *value);
240 }
241
TEST_F(OverlayUserPrefStoreTest,CommitPendingWriteWithCallback)242 TEST_F(OverlayUserPrefStoreTest, CommitPendingWriteWithCallback) {
243 TestCommitPendingWriteWithCallback(overlay_.get(), &task_environment_);
244 }
245
246 } // namespace base
247