1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
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 "base/basictypes.h"
6#include "base/memory/ref_counted.h"
7#include "base/memory/scoped_ptr.h"
8#include "base/values.h"
9#include "chrome/browser/extensions/extension_pref_value_map.h"
10#include "chrome/common/pref_store_observer_mock.h"
11#include "testing/gmock/include/gmock/gmock.h"
12#include "testing/gtest/include/gtest/gtest.h"
13
14namespace {
15const char kExt1[] = "ext1";
16const char kExt2[] = "ext2";
17const char kExt3[] = "ext3";
18
19const char kPref1[] = "path1.subpath";
20const char kPref2[] = "path2";
21const char kPref3[] = "path3";
22const char kPref4[] = "path4";
23}  // namespace
24
25static Value* CreateVal(const char* str) {
26  return Value::CreateStringValue(str);
27}
28
29static base::Time CreateTime(int64 t) {
30  return base::Time::FromInternalValue(t);
31}
32
33template <typename BASECLASS>
34class ExtensionPrefValueMapTestBase : public BASECLASS {
35 public:
36  // Returns an empty string if the key is not set.
37  std::string GetValue(const char * key, bool incognito) const {
38    const Value *value = epvm_.GetEffectivePrefValue(key, incognito, NULL);
39    std::string string_value = "";
40    if (value)
41      value->GetAsString(&string_value);
42    return string_value;
43  }
44
45 protected:
46  ExtensionPrefValueMap epvm_;
47};
48
49class ExtensionPrefValueMapTest
50    : public ExtensionPrefValueMapTestBase<testing::Test> {
51};
52
53// A gmock-ified implementation of PrefStore::Observer.
54class ExtensionPrefValueMapObserverMock
55    : public ExtensionPrefValueMap::Observer {
56 public:
57  ExtensionPrefValueMapObserverMock() {}
58  virtual ~ExtensionPrefValueMapObserverMock() {}
59
60  MOCK_METHOD1(OnPrefValueChanged, void(const std::string&));
61  MOCK_METHOD0(OnInitializationCompleted, void());
62  MOCK_METHOD0(OnExtensionPrefValueMapDestruction, void());
63
64 private:
65  DISALLOW_COPY_AND_ASSIGN(ExtensionPrefValueMapObserverMock);
66};
67
68TEST_F(ExtensionPrefValueMapTest, SetAndGetPrefValue) {
69  epvm_.RegisterExtension(kExt1, CreateTime(10), true);
70  epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
71  EXPECT_EQ("val1", GetValue(kPref1, false));
72};
73
74TEST_F(ExtensionPrefValueMapTest, GetNotSetPrefValue) {
75  epvm_.RegisterExtension(kExt1, CreateTime(10), true);
76  EXPECT_EQ("", GetValue(kPref1, false));
77};
78
79// Make sure the last-installed extension wins for each preference.
80TEST_F(ExtensionPrefValueMapTest, Override) {
81  epvm_.RegisterExtension(kExt1, CreateTime(10), true);
82  epvm_.RegisterExtension(kExt2, CreateTime(20), true);
83  epvm_.RegisterExtension(kExt3, CreateTime(30), true);
84
85  epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
86  epvm_.SetExtensionPref(kExt2, kPref1, false, CreateVal("val2"));
87  epvm_.SetExtensionPref(kExt3, kPref1, false, CreateVal("val3"));
88
89  epvm_.SetExtensionPref(kExt1, kPref2, false, CreateVal("val4"));
90  epvm_.SetExtensionPref(kExt2, kPref2, false, CreateVal("val5"));
91
92  epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val6"));
93  epvm_.SetExtensionPref(kExt1, kPref2, false, CreateVal("val7"));
94  epvm_.SetExtensionPref(kExt1, kPref3, false, CreateVal("val8"));
95
96  EXPECT_EQ("val3", GetValue(kPref1, false));
97  EXPECT_EQ("val5", GetValue(kPref2, false));
98  EXPECT_EQ("val8", GetValue(kPref3, false));
99}
100
101TEST_F(ExtensionPrefValueMapTest, OverrideChecks) {
102  epvm_.RegisterExtension(kExt1, CreateTime(10), true);
103  epvm_.RegisterExtension(kExt2, CreateTime(20), true);
104  epvm_.RegisterExtension(kExt3, CreateTime(30), true);
105
106  EXPECT_FALSE(epvm_.DoesExtensionControlPref(kExt1, kPref1, false));
107  EXPECT_FALSE(epvm_.DoesExtensionControlPref(kExt2, kPref1, false));
108  EXPECT_FALSE(epvm_.DoesExtensionControlPref(kExt3, kPref1, false));
109  EXPECT_TRUE(epvm_.CanExtensionControlPref(kExt1, kPref1, false));
110  EXPECT_TRUE(epvm_.CanExtensionControlPref(kExt2, kPref1, false));
111  EXPECT_TRUE(epvm_.CanExtensionControlPref(kExt3, kPref1, false));
112
113  epvm_.SetExtensionPref(kExt2, kPref1, false, CreateVal("val1"));
114
115  EXPECT_FALSE(epvm_.DoesExtensionControlPref(kExt1, kPref1, false));
116  EXPECT_TRUE(epvm_.DoesExtensionControlPref(kExt2, kPref1, false));
117  EXPECT_FALSE(epvm_.DoesExtensionControlPref(kExt3, kPref1, false));
118  EXPECT_FALSE(epvm_.CanExtensionControlPref(kExt1, kPref1, false));
119  EXPECT_TRUE(epvm_.CanExtensionControlPref(kExt2, kPref1, false));
120  EXPECT_TRUE(epvm_.CanExtensionControlPref(kExt3, kPref1, false));
121}
122
123TEST_F(ExtensionPrefValueMapTest, SetAndGetPrefValueIncognito) {
124  epvm_.RegisterExtension(kExt1, CreateTime(10), true);
125  epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
126  EXPECT_EQ("val1", GetValue(kPref1, true));
127}
128
129TEST_F(ExtensionPrefValueMapTest, UninstallOnlyExtension) {
130  epvm_.RegisterExtension(kExt1, CreateTime(10), true);
131  epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
132  epvm_.UnregisterExtension(kExt1);
133
134  EXPECT_EQ("", GetValue(kPref1, false));
135}
136
137// Tests uninstalling an extension that wasn't winning for any preferences.
138TEST_F(ExtensionPrefValueMapTest, UninstallIrrelevantExtension) {
139  epvm_.RegisterExtension(kExt1, CreateTime(10), true);
140  epvm_.RegisterExtension(kExt2, CreateTime(10), true);
141
142  epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
143  epvm_.SetExtensionPref(kExt2, kPref1, false, CreateVal("val2"));
144
145  epvm_.SetExtensionPref(kExt1, kPref2, false, CreateVal("val3"));
146  epvm_.SetExtensionPref(kExt2, kPref2, false, CreateVal("val4"));
147
148  epvm_.UnregisterExtension(kExt1);
149
150  EXPECT_EQ("val2", GetValue(kPref1, false));
151  EXPECT_EQ("val4", GetValue(kPref2, false));
152}
153
154// Tests uninstalling an extension that was winning for all preferences.
155TEST_F(ExtensionPrefValueMapTest, UninstallExtensionFromTop) {
156  epvm_.RegisterExtension(kExt1, CreateTime(10), true);
157  epvm_.RegisterExtension(kExt2, CreateTime(20), true);
158  epvm_.RegisterExtension(kExt3, CreateTime(30), true);
159
160  epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
161  epvm_.SetExtensionPref(kExt2, kPref1, false, CreateVal("val2"));
162  epvm_.SetExtensionPref(kExt3, kPref1, false, CreateVal("val3"));
163
164  epvm_.SetExtensionPref(kExt1, kPref2, false, CreateVal("val4"));
165  epvm_.SetExtensionPref(kExt3, kPref2, false, CreateVal("val5"));
166
167  epvm_.UnregisterExtension(kExt3);
168
169  EXPECT_EQ("val2", GetValue(kPref1, false));
170  EXPECT_EQ("val4", GetValue(kPref2, false));
171}
172
173// Tests uninstalling an extension that was winning for only some preferences.
174TEST_F(ExtensionPrefValueMapTest, UninstallExtensionFromMiddle) {
175  epvm_.RegisterExtension(kExt1, CreateTime(10), true);
176  epvm_.RegisterExtension(kExt2, CreateTime(20), true);
177  epvm_.RegisterExtension(kExt3, CreateTime(30), true);
178
179  epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
180  epvm_.SetExtensionPref(kExt2, kPref1, false, CreateVal("val2"));
181  epvm_.SetExtensionPref(kExt3, kPref1, false, CreateVal("val3"));
182
183  epvm_.SetExtensionPref(kExt1, kPref2, false, CreateVal("val4"));
184  epvm_.SetExtensionPref(kExt2, kPref2, false, CreateVal("val5"));
185
186  epvm_.SetExtensionPref(kExt1, kPref3, false, CreateVal("val6"));
187
188  epvm_.SetExtensionPref(kExt2, kPref4, false, CreateVal("val7"));
189
190  epvm_.UnregisterExtension(kExt2);
191
192  EXPECT_EQ("val3", GetValue(kPref1, false));
193  EXPECT_EQ("val4", GetValue(kPref2, false));
194  EXPECT_EQ("val6", GetValue(kPref3, false));
195  EXPECT_EQ("", GetValue(kPref4, false));
196}
197
198// Tests triggering of notifications to registered observers.
199TEST_F(ExtensionPrefValueMapTest, NotifyWhenNeeded) {
200  using testing::_;
201  using testing::Mock;
202  using testing::StrEq;
203
204  epvm_.RegisterExtension(kExt1, CreateTime(10), true);
205
206  ExtensionPrefValueMapObserverMock observer;
207  epvm_.AddObserver(&observer);
208
209  EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1)));
210  epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
211  Mock::VerifyAndClearExpectations(&observer);
212
213  // Write the same value again.
214  EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1))).Times(0);
215  epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
216  Mock::VerifyAndClearExpectations(&observer);
217
218  // Override incognito value.
219  EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1)));
220  epvm_.SetExtensionPref(kExt1, kPref1, true, CreateVal("val2"));
221  Mock::VerifyAndClearExpectations(&observer);
222
223  // Override non-incognito value.
224  EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1)));
225  epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val3"));
226  Mock::VerifyAndClearExpectations(&observer);
227
228  // Disable.
229  EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1)));
230  epvm_.SetExtensionState(kExt1, false);
231  Mock::VerifyAndClearExpectations(&observer);
232
233  // Enable.
234  EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1)));
235  epvm_.SetExtensionState(kExt1, true);
236  Mock::VerifyAndClearExpectations(&observer);
237
238  // Uninstall
239  EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1)));
240  epvm_.UnregisterExtension(kExt1);
241  Mock::VerifyAndClearExpectations(&observer);
242
243  epvm_.RemoveObserver(&observer);
244
245  // Write new value --> no notification after removing observer.
246  EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1))).Times(0);
247  epvm_.RegisterExtension(kExt1, CreateTime(10), true);
248  epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val4"));
249  Mock::VerifyAndClearExpectations(&observer);
250}
251
252// Tests disabling an extension.
253TEST_F(ExtensionPrefValueMapTest, DisableExt) {
254  epvm_.RegisterExtension(kExt1, CreateTime(10), true);
255
256  epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
257  epvm_.SetExtensionState(kExt1, false);
258  EXPECT_EQ("", GetValue(kPref1, false));
259}
260
261// Tests disabling and reenabling an extension.
262TEST_F(ExtensionPrefValueMapTest, ReenableExt) {
263  epvm_.RegisterExtension(kExt1, CreateTime(10), true);
264
265  epvm_.SetExtensionPref(kExt1, kPref1, false, CreateVal("val1"));
266  epvm_.SetExtensionState(kExt1, false);
267  epvm_.SetExtensionState(kExt1, true);
268  EXPECT_EQ("val1", GetValue(kPref1, false));
269}
270
271struct OverrideIncognitoTestCase {
272  OverrideIncognitoTestCase(int val_ext1_regular,
273                            int val_ext1_incognito,
274                            int val_ext2_regular,
275                            int val_ext2_incognito,
276                            int effective_value_regular,
277                            int effective_value_incognito)
278      : val_ext1_regular_(val_ext1_regular),
279        val_ext1_incognito_(val_ext1_incognito),
280        val_ext2_regular_(val_ext2_regular),
281        val_ext2_incognito_(val_ext2_incognito),
282        effective_value_regular_(effective_value_regular),
283        effective_value_incognito_(effective_value_incognito) {}
284
285  int val_ext1_regular_;           // pref value of extension 1
286  int val_ext1_incognito_;         // pref value of extension 1 incognito
287  int val_ext2_regular_;           // pref value of extension 2
288  int val_ext2_incognito_;         // pref value of extension 2 incognito
289  int effective_value_regular_;    // desired winner regular
290  int effective_value_incognito_;  // desired winner incognito
291};
292
293class ExtensionPrefValueMapTestIncognitoTests
294    : public ExtensionPrefValueMapTestBase<
295          testing::TestWithParam<OverrideIncognitoTestCase> > {
296};
297
298TEST_P(ExtensionPrefValueMapTestIncognitoTests, OverrideIncognito) {
299  OverrideIncognitoTestCase test = GetParam();
300  const char* strings[] = {
301      "undefined",
302      "val1",
303      "val2",
304      "val3",
305      "val4"
306  };
307
308  epvm_.RegisterExtension(kExt1, CreateTime(10), true);
309  epvm_.RegisterExtension(kExt2, CreateTime(20), true);
310  if (test.val_ext1_regular_) {
311    epvm_.SetExtensionPref(kExt1, kPref1, false,
312                           CreateVal(strings[test.val_ext1_regular_]));
313  }
314  if (test.val_ext1_incognito_) {
315    epvm_.SetExtensionPref(kExt1, kPref1, true,
316                           CreateVal(strings[test.val_ext1_incognito_]));
317  }
318  if (test.val_ext2_regular_) {
319    epvm_.SetExtensionPref(kExt2, kPref1, false,
320                           CreateVal(strings[test.val_ext2_regular_]));
321  }
322  if (test.val_ext2_incognito_) {
323    epvm_.SetExtensionPref(kExt2, kPref1, true,
324                           CreateVal(strings[test.val_ext2_incognito_]));
325  }
326  std::string actual;
327  EXPECT_EQ(strings[test.effective_value_regular_], GetValue(kPref1, false));
328  EXPECT_EQ(strings[test.effective_value_incognito_], GetValue(kPref1, true));
329  epvm_.UnregisterExtension(kExt1);
330  epvm_.UnregisterExtension(kExt2);
331}
332
333INSTANTIATE_TEST_CASE_P(
334    ExtensionPrefValueMapTestIncognitoTestsInstance,
335    ExtensionPrefValueMapTestIncognitoTests,
336    testing::Values(
337        // e.g. (1, 0, 0, 4,  1, 4), means:
338        // ext1 regular is set to "val1", ext2 incognito is set to "val4"
339        // --> the winning regular value is "val1", the winning incognito
340        //     value is "val4".
341        OverrideIncognitoTestCase(1, 0, 0, 0,  1, 1),
342        OverrideIncognitoTestCase(1, 2, 0, 0,  1, 2),
343        OverrideIncognitoTestCase(1, 0, 3, 0,  3, 3),
344        OverrideIncognitoTestCase(1, 0, 0, 4,  1, 4),
345        // The last 3 in the following line is intentional!
346        OverrideIncognitoTestCase(1, 2, 3, 0,  3, 3),
347        OverrideIncognitoTestCase(1, 2, 0, 4,  1, 4),
348        OverrideIncognitoTestCase(1, 2, 3, 4,  3, 4)));
349