1// Copyright 2014 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/prefs/pref_store_observer_mock.h"
9#include "base/values.h"
10#include "extensions/browser/extension_pref_value_map.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 base::Value* CreateVal(const char* str) {
26  return new base::StringValue(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  static const extensions::ExtensionPrefsScope kRegular =
37      extensions::kExtensionPrefsScopeRegular;
38  static const extensions::ExtensionPrefsScope kRegularOnly =
39      extensions::kExtensionPrefsScopeRegularOnly;
40  static const extensions::ExtensionPrefsScope kIncognitoPersistent =
41      extensions::kExtensionPrefsScopeIncognitoPersistent;
42  static const extensions::ExtensionPrefsScope kIncognitoSessionOnly =
43      extensions::kExtensionPrefsScopeIncognitoSessionOnly;
44
45  // Returns an empty string if the key is not set.
46  std::string GetValue(const char * key, bool incognito) const {
47    const base::Value *value =
48        epvm_.GetEffectivePrefValue(key, incognito, NULL);
49    std::string string_value;
50    if (value)
51      value->GetAsString(&string_value);
52    return string_value;
53  }
54
55  // Registers the extension as enabled but without incognito permission.
56  void RegisterExtension(const std::string& ext_id,
57                         const base::Time& install_time) {
58    epvm_.RegisterExtension(
59        ext_id, install_time, true /*enabled*/, false /*incognito*/);
60  }
61
62 protected:
63  ExtensionPrefValueMap epvm_;
64};
65
66class ExtensionPrefValueMapTest
67    : public ExtensionPrefValueMapTestBase<testing::Test> {
68};
69
70// A gmock-ified implementation of PrefStore::Observer.
71class ExtensionPrefValueMapObserverMock
72    : public ExtensionPrefValueMap::Observer {
73 public:
74  ExtensionPrefValueMapObserverMock() {}
75  virtual ~ExtensionPrefValueMapObserverMock() {}
76
77  MOCK_METHOD1(OnPrefValueChanged, void(const std::string&));
78  MOCK_METHOD0(OnInitializationCompleted, void());
79  MOCK_METHOD0(OnExtensionPrefValueMapDestruction, void());
80
81 private:
82  DISALLOW_COPY_AND_ASSIGN(ExtensionPrefValueMapObserverMock);
83};
84
85TEST_F(ExtensionPrefValueMapTest, SetAndGetPrefValue) {
86  RegisterExtension(kExt1, CreateTime(10));
87  epvm_.SetExtensionPref(kExt1, kPref1, kRegular, CreateVal("val1"));
88  EXPECT_EQ("val1", GetValue(kPref1, false));
89};
90
91TEST_F(ExtensionPrefValueMapTest, GetNotSetPrefValue) {
92  RegisterExtension(kExt1, CreateTime(10));
93  EXPECT_EQ(std::string(), GetValue(kPref1, false));
94};
95
96// Make sure the last-installed extension wins for each preference.
97TEST_F(ExtensionPrefValueMapTest, Override) {
98  RegisterExtension(kExt1, CreateTime(10));
99  RegisterExtension(kExt2, CreateTime(20));
100  RegisterExtension(kExt3, CreateTime(30));
101
102  epvm_.SetExtensionPref(kExt1, kPref1, kRegular, CreateVal("val1"));
103  epvm_.SetExtensionPref(kExt2, kPref1, kRegular, CreateVal("val2"));
104  epvm_.SetExtensionPref(kExt3, kPref1, kRegular, CreateVal("val3"));
105
106  epvm_.SetExtensionPref(kExt1, kPref2, kRegular, CreateVal("val4"));
107  epvm_.SetExtensionPref(kExt2, kPref2, kRegular, CreateVal("val5"));
108
109  epvm_.SetExtensionPref(kExt1, kPref1, kRegular, CreateVal("val6"));
110  epvm_.SetExtensionPref(kExt1, kPref2, kRegular, CreateVal("val7"));
111  epvm_.SetExtensionPref(kExt1, kPref3, kRegular, CreateVal("val8"));
112
113  EXPECT_EQ("val3", GetValue(kPref1, false));
114  EXPECT_EQ("val5", GetValue(kPref2, false));
115  EXPECT_EQ("val8", GetValue(kPref3, false));
116}
117
118TEST_F(ExtensionPrefValueMapTest, OverrideChecks) {
119  RegisterExtension(kExt1, CreateTime(10));
120  RegisterExtension(kExt2, CreateTime(20));
121  RegisterExtension(kExt3, CreateTime(30));
122
123  EXPECT_FALSE(epvm_.DoesExtensionControlPref(kExt1, kPref1, NULL));
124  EXPECT_FALSE(epvm_.DoesExtensionControlPref(kExt2, kPref1, NULL));
125  EXPECT_FALSE(epvm_.DoesExtensionControlPref(kExt3, kPref1, NULL));
126  EXPECT_TRUE(epvm_.CanExtensionControlPref(kExt1, kPref1, false));
127  EXPECT_TRUE(epvm_.CanExtensionControlPref(kExt2, kPref1, false));
128  EXPECT_TRUE(epvm_.CanExtensionControlPref(kExt3, kPref1, false));
129
130  epvm_.SetExtensionPref(kExt2, kPref1, kRegular, CreateVal("val1"));
131
132  EXPECT_FALSE(epvm_.DoesExtensionControlPref(kExt1, kPref1, NULL));
133  EXPECT_TRUE(epvm_.DoesExtensionControlPref(kExt2, kPref1, NULL));
134  EXPECT_FALSE(epvm_.DoesExtensionControlPref(kExt3, kPref1, NULL));
135  EXPECT_FALSE(epvm_.CanExtensionControlPref(kExt1, kPref1, false));
136  EXPECT_TRUE(epvm_.CanExtensionControlPref(kExt2, kPref1, false));
137  EXPECT_TRUE(epvm_.CanExtensionControlPref(kExt3, kPref1, false));
138}
139
140TEST_F(ExtensionPrefValueMapTest, SetAndGetPrefValueIncognito) {
141  RegisterExtension(kExt1, CreateTime(10));
142  epvm_.SetExtensionPref(kExt1, kPref1, kRegular, CreateVal("val1"));
143  // Check that the value is not propagated until the extension gets incognito
144  // permission.
145  EXPECT_EQ(std::string(), GetValue(kPref1, true));
146  epvm_.SetExtensionIncognitoState(kExt1, true);
147  EXPECT_EQ("val1", GetValue(kPref1, true));
148  epvm_.SetExtensionIncognitoState(kExt1, false);
149  EXPECT_EQ(std::string(), GetValue(kPref1, true));
150}
151
152TEST_F(ExtensionPrefValueMapTest, UninstallOnlyExtension) {
153  RegisterExtension(kExt1, CreateTime(10));
154  epvm_.SetExtensionPref(kExt1, kPref1, kRegular, CreateVal("val1"));
155  epvm_.UnregisterExtension(kExt1);
156
157  EXPECT_EQ(std::string(), GetValue(kPref1, false));
158}
159
160// Tests uninstalling an extension that wasn't winning for any preferences.
161TEST_F(ExtensionPrefValueMapTest, UninstallIrrelevantExtension) {
162  RegisterExtension(kExt1, CreateTime(10));
163  RegisterExtension(kExt2, CreateTime(10));
164
165  epvm_.SetExtensionPref(kExt1, kPref1, kRegular, CreateVal("val1"));
166  epvm_.SetExtensionPref(kExt2, kPref1, kRegular, CreateVal("val2"));
167
168  epvm_.SetExtensionPref(kExt1, kPref2, kRegular, CreateVal("val3"));
169  epvm_.SetExtensionPref(kExt2, kPref2, kRegular, CreateVal("val4"));
170
171  epvm_.UnregisterExtension(kExt1);
172
173  EXPECT_EQ("val2", GetValue(kPref1, false));
174  EXPECT_EQ("val4", GetValue(kPref2, false));
175}
176
177// Tests uninstalling an extension that was winning for all preferences.
178TEST_F(ExtensionPrefValueMapTest, UninstallExtensionFromTop) {
179  RegisterExtension(kExt1, CreateTime(10));
180  RegisterExtension(kExt2, CreateTime(20));
181  RegisterExtension(kExt3, CreateTime(30));
182
183  epvm_.SetExtensionPref(kExt1, kPref1, kRegular, CreateVal("val1"));
184  epvm_.SetExtensionPref(kExt2, kPref1, kRegular, CreateVal("val2"));
185  epvm_.SetExtensionPref(kExt3, kPref1, kRegular, CreateVal("val3"));
186
187  epvm_.SetExtensionPref(kExt1, kPref2, kRegular, CreateVal("val4"));
188  epvm_.SetExtensionPref(kExt3, kPref2, kRegular, CreateVal("val5"));
189
190  epvm_.UnregisterExtension(kExt3);
191
192  EXPECT_EQ("val2", GetValue(kPref1, false));
193  EXPECT_EQ("val4", GetValue(kPref2, false));
194}
195
196// Tests uninstalling an extension that was winning for only some preferences.
197TEST_F(ExtensionPrefValueMapTest, UninstallExtensionFromMiddle) {
198  RegisterExtension(kExt1, CreateTime(10));
199  RegisterExtension(kExt2, CreateTime(20));
200  RegisterExtension(kExt3, CreateTime(30));
201
202  epvm_.SetExtensionPref(kExt1, kPref1, kRegular, CreateVal("val1"));
203  epvm_.SetExtensionPref(kExt2, kPref1, kRegular, CreateVal("val2"));
204  epvm_.SetExtensionPref(kExt3, kPref1, kRegular, CreateVal("val3"));
205
206  epvm_.SetExtensionPref(kExt1, kPref2, kRegular, CreateVal("val4"));
207  epvm_.SetExtensionPref(kExt2, kPref2, kRegular, CreateVal("val5"));
208
209  epvm_.SetExtensionPref(kExt1, kPref3, kRegular, CreateVal("val6"));
210
211  epvm_.SetExtensionPref(kExt2, kPref4, kRegular, CreateVal("val7"));
212
213  epvm_.UnregisterExtension(kExt2);
214
215  EXPECT_EQ("val3", GetValue(kPref1, false));
216  EXPECT_EQ("val4", GetValue(kPref2, false));
217  EXPECT_EQ("val6", GetValue(kPref3, false));
218  EXPECT_EQ(std::string(), GetValue(kPref4, false));
219}
220
221// Tests triggering of notifications to registered observers.
222TEST_F(ExtensionPrefValueMapTest, NotifyWhenNeeded) {
223  using testing::Mock;
224  using testing::StrEq;
225
226  RegisterExtension(kExt1, CreateTime(10));
227
228  ExtensionPrefValueMapObserverMock observer;
229  epvm_.AddObserver(&observer);
230
231  EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1)));
232  epvm_.SetExtensionPref(kExt1, kPref1, kRegular, CreateVal("val1"));
233  Mock::VerifyAndClearExpectations(&observer);
234
235  // Write the same value again.
236  EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1))).Times(0);
237  epvm_.SetExtensionPref(kExt1, kPref1, kRegular, CreateVal("val1"));
238  Mock::VerifyAndClearExpectations(&observer);
239
240  // Override incognito value.
241  EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1)));
242  epvm_.SetExtensionPref(kExt1, kPref1, kRegular, CreateVal("val2"));
243  Mock::VerifyAndClearExpectations(&observer);
244
245  // Override non-incognito value.
246  EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1)));
247  epvm_.SetExtensionPref(kExt1, kPref1, kRegular, CreateVal("val3"));
248  Mock::VerifyAndClearExpectations(&observer);
249
250  // Disable.
251  EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1)));
252  epvm_.SetExtensionState(kExt1, false);
253  Mock::VerifyAndClearExpectations(&observer);
254
255  // Enable.
256  EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1)));
257  epvm_.SetExtensionState(kExt1, true);
258  Mock::VerifyAndClearExpectations(&observer);
259
260  // Uninstall
261  EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1)));
262  epvm_.UnregisterExtension(kExt1);
263  Mock::VerifyAndClearExpectations(&observer);
264
265  epvm_.RemoveObserver(&observer);
266
267  // Write new value --> no notification after removing observer.
268  EXPECT_CALL(observer, OnPrefValueChanged(std::string(kPref1))).Times(0);
269  RegisterExtension(kExt1, CreateTime(10));
270  epvm_.SetExtensionPref(kExt1, kPref1, kRegular, CreateVal("val4"));
271  Mock::VerifyAndClearExpectations(&observer);
272}
273
274// Tests disabling an extension.
275TEST_F(ExtensionPrefValueMapTest, DisableExt) {
276  RegisterExtension(kExt1, CreateTime(10));
277
278  epvm_.SetExtensionPref(kExt1, kPref1, kRegular, CreateVal("val1"));
279  epvm_.SetExtensionState(kExt1, false);
280  EXPECT_EQ(std::string(), GetValue(kPref1, false));
281}
282
283// Tests disabling and reenabling an extension.
284TEST_F(ExtensionPrefValueMapTest, ReenableExt) {
285  RegisterExtension(kExt1, CreateTime(10));
286
287  epvm_.SetExtensionPref(kExt1, kPref1, kRegular, CreateVal("val1"));
288  epvm_.SetExtensionState(kExt1, false);
289  epvm_.SetExtensionState(kExt1, true);
290  EXPECT_EQ("val1", GetValue(kPref1, false));
291}
292
293struct OverrideIncognitoTestCase {
294  OverrideIncognitoTestCase(bool enable_ext1_in_incognito,
295                            bool enable_ext2_in_incognito,
296                            int val_ext1_regular,
297                            int val_ext1_regular_only,
298                            int val_ext1_incognito_pers,
299                            int val_ext1_incognito_sess,
300                            int val_ext2_regular,
301                            int val_ext2_regular_only,
302                            int val_ext2_incognito_pers,
303                            int val_ext2_incognito_sess,
304                            int effective_value_regular,
305                            int effective_value_incognito)
306      : enable_ext1_in_incognito_(enable_ext1_in_incognito),
307        enable_ext2_in_incognito_(enable_ext2_in_incognito),
308        val_ext1_regular_(val_ext1_regular),
309        val_ext1_regular_only_(val_ext1_regular_only),
310        val_ext1_incognito_pers_(val_ext1_incognito_pers),
311        val_ext1_incognito_sess_(val_ext1_incognito_sess),
312        val_ext2_regular_(val_ext2_regular),
313        val_ext2_regular_only_(val_ext2_regular_only),
314        val_ext2_incognito_pers_(val_ext2_incognito_pers),
315        val_ext2_incognito_sess_(val_ext2_incognito_sess),
316        effective_value_regular_(effective_value_regular),
317        effective_value_incognito_(effective_value_incognito) {}
318
319  bool enable_ext1_in_incognito_;
320  bool enable_ext2_in_incognito_;
321
322  // pers. = persistent
323  // sess. = session only
324  int val_ext1_regular_;           // pref value of extension 1
325  int val_ext1_regular_only_;      // pref value of extension 1 regular-only.
326  int val_ext1_incognito_pers_;    // pref value of extension 1 incognito pers.
327  int val_ext1_incognito_sess_;    // pref value of extension 1 incognito sess.
328  int val_ext2_regular_;           // pref value of extension 2
329  int val_ext2_regular_only_;      // pref value of extension 2 regular-only.
330  int val_ext2_incognito_pers_;    // pref value of extension 2 incognito pers.
331  int val_ext2_incognito_sess_;    // pref value of extension 2 incognito sess.
332  int effective_value_regular_;    // desired winner regular
333  int effective_value_incognito_;  // desired winner incognito
334};
335
336class ExtensionPrefValueMapTestIncognitoTests
337    : public ExtensionPrefValueMapTestBase<
338          testing::TestWithParam<OverrideIncognitoTestCase> > {
339};
340
341TEST_P(ExtensionPrefValueMapTestIncognitoTests, OverrideIncognito) {
342  OverrideIncognitoTestCase test = GetParam();
343  const char* strings[] = {
344      "",  // undefined
345      "val1",
346      "val2",
347      "val3",
348      "val4",
349      "val5",
350      "val6",
351      "val7",
352      "val8",
353  };
354
355  const bool kEnabled = true;
356  epvm_.RegisterExtension(
357      kExt1, CreateTime(10), kEnabled, test.enable_ext1_in_incognito_);
358  epvm_.RegisterExtension(
359      kExt2, CreateTime(20), kEnabled, test.enable_ext2_in_incognito_);
360  if (test.val_ext1_regular_) {
361    epvm_.SetExtensionPref(kExt1, kPref1, kRegular,
362                           CreateVal(strings[test.val_ext1_regular_]));
363  }
364  if (test.val_ext1_regular_only_) {
365    epvm_.SetExtensionPref(kExt1, kPref1, kRegularOnly,
366                           CreateVal(strings[test.val_ext1_regular_only_]));
367  }
368  if (test.val_ext1_incognito_pers_) {
369    epvm_.SetExtensionPref(kExt1, kPref1, kIncognitoPersistent,
370                           CreateVal(strings[test.val_ext1_incognito_pers_]));
371  }
372  if (test.val_ext1_incognito_sess_) {
373    epvm_.SetExtensionPref(kExt1, kPref1, kIncognitoSessionOnly,
374                           CreateVal(strings[test.val_ext1_incognito_sess_]));
375  }
376  if (test.val_ext2_regular_) {
377    epvm_.SetExtensionPref(kExt2, kPref1, kRegular,
378                           CreateVal(strings[test.val_ext2_regular_]));
379  }
380  if (test.val_ext2_regular_only_) {
381    epvm_.SetExtensionPref(kExt2, kPref1, kRegularOnly,
382                           CreateVal(strings[test.val_ext2_regular_only_]));
383  }
384  if (test.val_ext2_incognito_pers_) {
385    epvm_.SetExtensionPref(kExt2, kPref1, kIncognitoPersistent,
386                           CreateVal(strings[test.val_ext2_incognito_pers_]));
387  }
388  if (test.val_ext2_incognito_sess_) {
389    epvm_.SetExtensionPref(kExt2, kPref1, kIncognitoSessionOnly,
390                           CreateVal(strings[test.val_ext2_incognito_sess_]));
391  }
392  std::string actual;
393  EXPECT_EQ(strings[test.effective_value_regular_], GetValue(kPref1, false));
394  EXPECT_EQ(strings[test.effective_value_incognito_], GetValue(kPref1, true));
395  epvm_.UnregisterExtension(kExt1);
396  epvm_.UnregisterExtension(kExt2);
397}
398
399INSTANTIATE_TEST_CASE_P(
400    ExtensionPrefValueMapTestIncognitoTestsInstance,
401    ExtensionPrefValueMapTestIncognitoTests,
402    testing::Values(
403        // e.g. (true, 1, 0, 0, 0,  0, 0, 7, 0,  1, 7), means:
404        // ext1 regular is set to "val1", ext2 incognito persistent is set to
405        // "val7"
406        // --> the winning regular value is "val1", the winning incognito
407        //     value is "val7".
408        OverrideIncognitoTestCase(true, true, 1, 0, 0, 0,  0, 0, 0, 0,  1, 1),
409        OverrideIncognitoTestCase(true, true, 1, 2, 0, 0,  0, 0, 0, 0,  2, 1),
410        OverrideIncognitoTestCase(true, true, 1, 0, 3, 0,  0, 0, 0, 0,  1, 3),
411        OverrideIncognitoTestCase(true, true, 1, 0, 0, 4,  0, 0, 0, 0,  1, 4),
412        OverrideIncognitoTestCase(true, true, 1, 0, 3, 4,  0, 0, 0, 0,  1, 4),
413        OverrideIncognitoTestCase(true, true, 1, 2, 3, 0,  0, 0, 0, 0,  2, 3),
414        OverrideIncognitoTestCase(true, true, 1, 0, 0, 0,  5, 0, 0, 0,  5, 5),
415        OverrideIncognitoTestCase(true, true, 1, 2, 3, 0,  5, 0, 0, 0,  5, 5),
416        OverrideIncognitoTestCase(true, true, 1, 0, 0, 0,  0, 6, 0, 0,  6, 1),
417        OverrideIncognitoTestCase(true, true, 1, 0, 3, 0,  5, 6, 0, 0,  6, 5),
418        OverrideIncognitoTestCase(true, true, 1, 0, 0, 4,  5, 6, 0, 0,  6, 5),
419        OverrideIncognitoTestCase(true, true, 1, 0, 0, 0,  0, 0, 7, 0,  1, 7),
420        OverrideIncognitoTestCase(true, true, 1, 2, 0, 0,  5, 0, 7, 0,  5, 7),
421        OverrideIncognitoTestCase(true, true, 1, 2, 0, 0,  5, 0, 0, 8,  5, 8),
422        OverrideIncognitoTestCase(true, true, 1, 2, 0, 0,  5, 0, 7, 8,  5, 8),
423        OverrideIncognitoTestCase(true, true, 1, 2, 3, 0,  0, 6, 7, 0,  6, 7),
424        // Same tests as above but w/o incognito permission.
425        OverrideIncognitoTestCase(false, false, 1, 0, 0, 0,  0, 0, 0, 0,  1, 0),
426        OverrideIncognitoTestCase(false, false, 1, 2, 0, 0,  0, 0, 0, 0,  2, 0),
427        OverrideIncognitoTestCase(false, false, 1, 0, 3, 0,  0, 0, 0, 0,  1, 0),
428        OverrideIncognitoTestCase(false, false, 1, 0, 0, 4,  0, 0, 0, 0,  1, 0),
429        OverrideIncognitoTestCase(false, false, 1, 0, 3, 4,  0, 0, 0, 0,  1, 0),
430        OverrideIncognitoTestCase(false, false, 1, 2, 3, 0,  0, 0, 0, 0,  2, 0),
431        OverrideIncognitoTestCase(false, false, 1, 0, 0, 0,  5, 0, 0, 0,  5, 0),
432        OverrideIncognitoTestCase(false, false, 1, 2, 3, 0,  5, 0, 0, 0,  5, 0),
433        OverrideIncognitoTestCase(false, false, 1, 0, 0, 0,  0, 6, 0, 0,  6, 0),
434        OverrideIncognitoTestCase(false, false, 1, 0, 3, 0,  5, 6, 0, 0,  6, 0),
435        OverrideIncognitoTestCase(false, false, 1, 0, 0, 4,  5, 6, 0, 0,  6, 0),
436        OverrideIncognitoTestCase(false, false, 1, 0, 0, 0,  0, 0, 7, 0,  1, 0),
437        OverrideIncognitoTestCase(false, false, 1, 2, 0, 0,  5, 0, 7, 0,  5, 0),
438        OverrideIncognitoTestCase(false, false, 1, 2, 0, 0,  5, 0, 0, 8,  5, 0),
439        OverrideIncognitoTestCase(false, false, 1, 2, 0, 0,  5, 0, 7, 8,  5, 0),
440        OverrideIncognitoTestCase(false, false, 1, 2, 3, 0,  0, 6, 7, 0,  6, 0)
441        ));
442