preference_api_prefs_unittest.cc revision a36e5920737c6adbddd3e43b760e5de8431db6e0
1// Copyright 2013 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 <string>
6
7#include "base/memory/ref_counted.h"
8#include "base/memory/scoped_ptr.h"
9#include "base/prefs/mock_pref_change_callback.h"
10#include "base/values.h"
11#include "chrome/browser/extensions/api/preference/preference_api.h"
12#include "chrome/browser/extensions/extension_prefs.h"
13#include "chrome/browser/extensions/extension_prefs_unittest.h"
14#include "chrome/common/extensions/extension.h"
15#include "chrome/common/extensions/extension_manifest_constants.h"
16#include "chrome/test/base/testing_profile.h"
17#include "components/user_prefs/pref_registry_syncable.h"
18#include "testing/gtest/include/gtest/gtest.h"
19
20using base::Value;
21
22namespace keys = extension_manifest_keys;
23
24namespace extensions {
25
26namespace {
27
28const char kPref1[] = "path1.subpath";
29const char kPref2[] = "path2";
30const char kPref3[] = "path3";
31const char kPref4[] = "path4";
32
33// Default values in case an extension pref value is not overridden.
34const char kDefaultPref1[] = "default pref 1";
35const char kDefaultPref2[] = "default pref 2";
36const char kDefaultPref3[] = "default pref 3";
37const char kDefaultPref4[] = "default pref 4";
38
39}  // namespace
40
41// An implementation of the PreferenceAPI which returns the ExtensionPrefs and
42// ExtensionPrefValueMap from the TestExtensionPrefs, rather than from a
43// profile (which we don't create in unittests).
44class TestPreferenceAPI : public PreferenceAPIBase {
45 public:
46  explicit TestPreferenceAPI(TestExtensionPrefs* test_extension_prefs)
47      : test_extension_prefs_(test_extension_prefs) { }
48  ~TestPreferenceAPI() { }
49 private:
50  // PreferenceAPIBase implementation.
51  virtual ExtensionPrefs* extension_prefs() OVERRIDE {
52    return test_extension_prefs_->prefs();
53  }
54  virtual ExtensionPrefValueMap* extension_pref_value_map() OVERRIDE {
55    return test_extension_prefs_->extension_pref_value_map();
56  }
57
58  TestExtensionPrefs* test_extension_prefs_;
59
60  DISALLOW_COPY_AND_ASSIGN(TestPreferenceAPI);
61};
62
63class ExtensionControlledPrefsTest : public PrefsPrepopulatedTestBase {
64 public:
65  ExtensionControlledPrefsTest();
66  virtual ~ExtensionControlledPrefsTest();
67
68  virtual void RegisterPreferences(user_prefs::PrefRegistrySyncable* registry)
69      OVERRIDE;
70  void InstallExtensionControlledPref(Extension* extension,
71                                      const std::string& key,
72                                      base::Value* value);
73  void InstallExtensionControlledPrefIncognito(Extension* extension,
74                                               const std::string& key,
75                                               base::Value* value);
76  void InstallExtensionControlledPrefIncognitoSessionOnly(
77      Extension* extension,
78      const std::string& key,
79      base::Value* value);
80  void InstallExtension(Extension* extension);
81  void UninstallExtension(const std::string& extension_id);
82
83 protected:
84  void EnsureExtensionInstalled(Extension* extension);
85  void EnsureExtensionUninstalled(const std::string& extension_id);
86
87  TestPreferenceAPI test_preference_api_;
88};
89
90ExtensionControlledPrefsTest::ExtensionControlledPrefsTest()
91    : PrefsPrepopulatedTestBase(),
92      test_preference_api_(&prefs_) {
93}
94
95ExtensionControlledPrefsTest::~ExtensionControlledPrefsTest() {
96}
97
98void ExtensionControlledPrefsTest::RegisterPreferences(
99    user_prefs::PrefRegistrySyncable* registry) {
100  registry->RegisterStringPref(
101      kPref1, kDefaultPref1, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
102  registry->RegisterStringPref(
103      kPref2, kDefaultPref2, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
104  registry->RegisterStringPref(
105      kPref3, kDefaultPref3, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
106  registry->RegisterStringPref(
107      kPref4, kDefaultPref4, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
108}
109
110void ExtensionControlledPrefsTest::InstallExtensionControlledPref(
111    Extension* extension,
112    const std::string& key,
113    Value* value) {
114  EnsureExtensionInstalled(extension);
115  test_preference_api_.SetExtensionControlledPref(
116      extension->id(), key, kExtensionPrefsScopeRegular, value);
117}
118
119void ExtensionControlledPrefsTest::InstallExtensionControlledPrefIncognito(
120    Extension* extension,
121    const std::string& key,
122    Value* value) {
123  EnsureExtensionInstalled(extension);
124  test_preference_api_.SetExtensionControlledPref(
125      extension->id(), key, kExtensionPrefsScopeIncognitoPersistent, value);
126}
127
128void ExtensionControlledPrefsTest::
129InstallExtensionControlledPrefIncognitoSessionOnly(Extension* extension,
130                                                   const std::string& key,
131                                                   Value* value) {
132  EnsureExtensionInstalled(extension);
133  test_preference_api_.SetExtensionControlledPref(
134      extension->id(), key, kExtensionPrefsScopeIncognitoSessionOnly, value);
135}
136
137void ExtensionControlledPrefsTest::InstallExtension(Extension* extension) {
138  EnsureExtensionInstalled(extension);
139}
140
141void ExtensionControlledPrefsTest::UninstallExtension(
142    const std::string& extension_id) {
143  EnsureExtensionUninstalled(extension_id);
144}
145
146void ExtensionControlledPrefsTest::EnsureExtensionInstalled(
147    Extension* extension) {
148  // Install extension the first time a preference is set for it.
149  Extension* extensions[] = { extension1(),
150                              extension2(),
151                              extension3(),
152                              extension4() };
153  for (size_t i = 0; i < kNumInstalledExtensions; ++i) {
154    if (extension == extensions[i] && !installed_[i]) {
155      prefs()->OnExtensionInstalled(extension,
156                                    Extension::ENABLED,
157                                    Blacklist::NOT_BLACKLISTED,
158                                    syncer::StringOrdinal());
159      installed_[i] = true;
160      break;
161    }
162  }
163}
164
165void ExtensionControlledPrefsTest::EnsureExtensionUninstalled(
166    const std::string& extension_id) {
167  Extension* extensions[] = { extension1(),
168                              extension2(),
169                              extension3(),
170                              extension4() };
171  for (size_t i = 0; i < kNumInstalledExtensions; ++i) {
172    if (extensions[i]->id() == extension_id) {
173      installed_[i] = false;
174      break;
175    }
176  }
177  prefs()->OnExtensionUninstalled(extension_id, Manifest::INTERNAL, false);
178}
179
180class ControlledPrefsInstallOneExtension
181    : public ExtensionControlledPrefsTest {
182  virtual void Initialize() OVERRIDE {
183    InstallExtensionControlledPref(extension1(),
184                                   kPref1,
185                                   Value::CreateStringValue("val1"));
186  }
187  virtual void Verify() OVERRIDE {
188    std::string actual = prefs()->pref_service()->GetString(kPref1);
189    EXPECT_EQ("val1", actual);
190  }
191};
192TEST_F(ControlledPrefsInstallOneExtension,
193       ControlledPrefsInstallOneExtension) { }
194
195// Check that we do not forget persistent incognito values after a reload.
196class ControlledPrefsInstallIncognitoPersistent
197    : public ExtensionControlledPrefsTest {
198 public:
199  virtual void Initialize() OVERRIDE {
200    InstallExtensionControlledPref(
201        extension1(), kPref1, Value::CreateStringValue("val1"));
202    InstallExtensionControlledPrefIncognito(
203        extension1(), kPref1, Value::CreateStringValue("val2"));
204    scoped_ptr<PrefService> incog_prefs(prefs_.CreateIncognitoPrefService());
205    std::string actual = incog_prefs->GetString(kPref1);
206    EXPECT_EQ("val2", actual);
207  }
208
209  virtual void Verify() OVERRIDE {
210    // Main pref service shall see only non-incognito settings.
211    std::string actual = prefs()->pref_service()->GetString(kPref1);
212    EXPECT_EQ("val1", actual);
213    // Incognito pref service shall see incognito values.
214    scoped_ptr<PrefService> incog_prefs(prefs_.CreateIncognitoPrefService());
215    actual = incog_prefs->GetString(kPref1);
216    EXPECT_EQ("val2", actual);
217  }
218};
219TEST_F(ControlledPrefsInstallIncognitoPersistent,
220       ControlledPrefsInstallIncognitoPersistent) { }
221
222// Check that we forget 'session only' incognito values after a reload.
223class ControlledPrefsInstallIncognitoSessionOnly
224    : public ExtensionControlledPrefsTest {
225 public:
226  ControlledPrefsInstallIncognitoSessionOnly() : iteration_(0) {}
227
228  virtual void Initialize() OVERRIDE {
229    InstallExtensionControlledPref(
230        extension1(), kPref1, Value::CreateStringValue("val1"));
231    InstallExtensionControlledPrefIncognitoSessionOnly(
232        extension1(), kPref1, Value::CreateStringValue("val2"));
233    scoped_ptr<PrefService> incog_prefs(prefs_.CreateIncognitoPrefService());
234    std::string actual = incog_prefs->GetString(kPref1);
235    EXPECT_EQ("val2", actual);
236  }
237  virtual void Verify() OVERRIDE {
238    // Main pref service shall see only non-incognito settings.
239    std::string actual = prefs()->pref_service()->GetString(kPref1);
240    EXPECT_EQ("val1", actual);
241    // Incognito pref service shall see session-only incognito values only
242    // during first run. Once the pref service was reloaded, all values shall be
243    // discarded.
244    scoped_ptr<PrefService> incog_prefs(prefs_.CreateIncognitoPrefService());
245    actual = incog_prefs->GetString(kPref1);
246    if (iteration_ == 0) {
247      EXPECT_EQ("val2", actual);
248    } else {
249      EXPECT_EQ("val1", actual);
250    }
251    ++iteration_;
252  }
253  int iteration_;
254};
255TEST_F(ControlledPrefsInstallIncognitoSessionOnly,
256       ControlledPrefsInstallIncognitoSessionOnly) { }
257
258class ControlledPrefsUninstallExtension : public ExtensionControlledPrefsTest {
259  virtual void Initialize() OVERRIDE {
260    InstallExtensionControlledPref(
261        extension1(), kPref1, Value::CreateStringValue("val1"));
262    InstallExtensionControlledPref(
263        extension1(), kPref2, Value::CreateStringValue("val2"));
264    ContentSettingsStore* store = prefs()->content_settings_store();
265    ContentSettingsPattern pattern =
266        ContentSettingsPattern::FromString("http://[*.]example.com");
267    store->SetExtensionContentSetting(extension1()->id(),
268                                      pattern, pattern,
269                                      CONTENT_SETTINGS_TYPE_IMAGES,
270                                      std::string(),
271                                      CONTENT_SETTING_BLOCK,
272                                      kExtensionPrefsScopeRegular);
273
274    UninstallExtension(extension1()->id());
275  }
276  virtual void Verify() OVERRIDE {
277    EXPECT_FALSE(prefs()->HasPrefForExtension(extension1()->id()));
278
279    std::string actual;
280    actual = prefs()->pref_service()->GetString(kPref1);
281    EXPECT_EQ(kDefaultPref1, actual);
282    actual = prefs()->pref_service()->GetString(kPref2);
283    EXPECT_EQ(kDefaultPref2, actual);
284  }
285};
286TEST_F(ControlledPrefsUninstallExtension,
287       ControlledPrefsUninstallExtension) { }
288
289// Tests triggering of notifications to registered observers.
290class ControlledPrefsNotifyWhenNeeded : public ExtensionControlledPrefsTest {
291  virtual void Initialize() OVERRIDE {
292    using testing::_;
293    using testing::Mock;
294    using testing::StrEq;
295
296    MockPrefChangeCallback observer(prefs()->pref_service());
297    PrefChangeRegistrar registrar;
298    registrar.Init(prefs()->pref_service());
299    registrar.Add(kPref1, observer.GetCallback());
300
301    MockPrefChangeCallback incognito_observer(prefs()->pref_service());
302    scoped_ptr<PrefService> incog_prefs(prefs_.CreateIncognitoPrefService());
303    PrefChangeRegistrar incognito_registrar;
304    incognito_registrar.Init(incog_prefs.get());
305    incognito_registrar.Add(kPref1, incognito_observer.GetCallback());
306
307    // Write value and check notification.
308    EXPECT_CALL(observer, OnPreferenceChanged(_));
309    EXPECT_CALL(incognito_observer, OnPreferenceChanged(_));
310    InstallExtensionControlledPref(extension1(), kPref1,
311        Value::CreateStringValue("https://www.chromium.org"));
312    Mock::VerifyAndClearExpectations(&observer);
313    Mock::VerifyAndClearExpectations(&incognito_observer);
314
315    // Write same value.
316    EXPECT_CALL(observer, OnPreferenceChanged(_)).Times(0);
317    EXPECT_CALL(incognito_observer, OnPreferenceChanged(_)).Times(0);
318    InstallExtensionControlledPref(extension1(), kPref1,
319        Value::CreateStringValue("https://www.chromium.org"));
320    Mock::VerifyAndClearExpectations(&observer);
321    Mock::VerifyAndClearExpectations(&incognito_observer);
322
323    // Change value.
324    EXPECT_CALL(observer, OnPreferenceChanged(_));
325    EXPECT_CALL(incognito_observer, OnPreferenceChanged(_));
326    InstallExtensionControlledPref(extension1(), kPref1,
327        Value::CreateStringValue("chrome://newtab"));
328    Mock::VerifyAndClearExpectations(&observer);
329    Mock::VerifyAndClearExpectations(&incognito_observer);
330    // Change only incognito persistent value.
331    EXPECT_CALL(observer, OnPreferenceChanged(_)).Times(0);
332    EXPECT_CALL(incognito_observer, OnPreferenceChanged(_));
333    InstallExtensionControlledPrefIncognito(extension1(), kPref1,
334        Value::CreateStringValue("chrome://newtab2"));
335    Mock::VerifyAndClearExpectations(&observer);
336    Mock::VerifyAndClearExpectations(&incognito_observer);
337
338    // Change only incognito session-only value.
339    EXPECT_CALL(observer, OnPreferenceChanged(_)).Times(0);
340    EXPECT_CALL(incognito_observer, OnPreferenceChanged(_));
341    InstallExtensionControlledPrefIncognito(extension1(), kPref1,
342        Value::CreateStringValue("chrome://newtab3"));
343    Mock::VerifyAndClearExpectations(&observer);
344    Mock::VerifyAndClearExpectations(&incognito_observer);
345
346    // Uninstall.
347    EXPECT_CALL(observer, OnPreferenceChanged(_));
348    EXPECT_CALL(incognito_observer, OnPreferenceChanged(_));
349    UninstallExtension(extension1()->id());
350    Mock::VerifyAndClearExpectations(&observer);
351    Mock::VerifyAndClearExpectations(&incognito_observer);
352
353    registrar.Remove(kPref1);
354    incognito_registrar.Remove(kPref1);
355  }
356  virtual void Verify() OVERRIDE {
357    std::string actual = prefs()->pref_service()->GetString(kPref1);
358    EXPECT_EQ(kDefaultPref1, actual);
359  }
360};
361TEST_F(ControlledPrefsNotifyWhenNeeded,
362       ControlledPrefsNotifyWhenNeeded) { }
363
364// Tests disabling an extension.
365class ControlledPrefsDisableExtension : public ExtensionControlledPrefsTest {
366  virtual void Initialize() OVERRIDE {
367    InstallExtensionControlledPref(
368        extension1(), kPref1, Value::CreateStringValue("val1"));
369    std::string actual = prefs()->pref_service()->GetString(kPref1);
370    EXPECT_EQ("val1", actual);
371    prefs()->SetExtensionState(extension1()->id(), Extension::DISABLED);
372  }
373  virtual void Verify() OVERRIDE {
374    std::string actual = prefs()->pref_service()->GetString(kPref1);
375    EXPECT_EQ(kDefaultPref1, actual);
376  }
377};
378TEST_F(ControlledPrefsDisableExtension, ControlledPrefsDisableExtension) { }
379
380// Tests disabling and reenabling an extension.
381class ControlledPrefsReenableExtension : public ExtensionControlledPrefsTest {
382  virtual void Initialize() OVERRIDE {
383    InstallExtensionControlledPref(
384        extension1(), kPref1, Value::CreateStringValue("val1"));
385    prefs()->SetExtensionState(extension1()->id(), Extension::DISABLED);
386    prefs()->SetExtensionState(extension1()->id(), Extension::ENABLED);
387  }
388  virtual void Verify() OVERRIDE {
389    std::string actual = prefs()->pref_service()->GetString(kPref1);
390    EXPECT_EQ("val1", actual);
391  }
392};
393TEST_F(ControlledPrefsDisableExtension, ControlledPrefsReenableExtension) { }
394
395// Mock class to test whether objects are deleted correctly.
396class MockStringValue : public StringValue {
397 public:
398  explicit MockStringValue(const std::string& in_value)
399      : StringValue(in_value) {
400  }
401  virtual ~MockStringValue() {
402    Die();
403  }
404  MOCK_METHOD0(Die, void());
405};
406
407class ControlledPrefsSetExtensionControlledPref
408    : public ExtensionControlledPrefsTest {
409 public:
410  virtual void Initialize() OVERRIDE {
411    MockStringValue* v1 = new MockStringValue("https://www.chromium.org");
412    MockStringValue* v2 = new MockStringValue("https://www.chromium.org");
413    MockStringValue* v1i = new MockStringValue("https://www.chromium.org");
414    MockStringValue* v2i = new MockStringValue("https://www.chromium.org");
415    // Ownership is taken, value shall not be deleted.
416    EXPECT_CALL(*v1, Die()).Times(0);
417    EXPECT_CALL(*v1i, Die()).Times(0);
418    InstallExtensionControlledPref(extension1(), kPref1, v1);
419    InstallExtensionControlledPrefIncognito(extension1(), kPref1, v1i);
420    testing::Mock::VerifyAndClearExpectations(v1);
421    testing::Mock::VerifyAndClearExpectations(v1i);
422    // Make sure there is no memory leak and both values are deleted.
423    EXPECT_CALL(*v1, Die()).Times(1);
424    EXPECT_CALL(*v1i, Die()).Times(1);
425    EXPECT_CALL(*v2, Die()).Times(1);
426    EXPECT_CALL(*v2i, Die()).Times(1);
427    InstallExtensionControlledPref(extension1(), kPref1, v2);
428    InstallExtensionControlledPrefIncognito(extension1(), kPref1, v2i);
429    prefs_.RecreateExtensionPrefs();
430    testing::Mock::VerifyAndClearExpectations(v1);
431    testing::Mock::VerifyAndClearExpectations(v1i);
432    testing::Mock::VerifyAndClearExpectations(v2);
433    testing::Mock::VerifyAndClearExpectations(v2i);
434  }
435
436  virtual void Verify() OVERRIDE {
437  }
438};
439TEST_F(ControlledPrefsSetExtensionControlledPref,
440       ControlledPrefsSetExtensionControlledPref) { }
441
442// Tests that the switches::kDisableExtensions command-line flag prevents
443// extension controlled preferences from being enacted.
444class ControlledPrefsDisableExtensions : public ExtensionControlledPrefsTest {
445 public:
446  ControlledPrefsDisableExtensions()
447      : iteration_(0) {}
448  virtual ~ControlledPrefsDisableExtensions() {}
449  virtual void Initialize() OVERRIDE {
450    InstallExtensionControlledPref(
451        extension1(), kPref1, Value::CreateStringValue("val1"));
452    // This becomes only active in the second verification phase.
453    prefs_.set_extensions_disabled(true);
454  }
455  virtual void Verify() OVERRIDE {
456    std::string actual = prefs()->pref_service()->GetString(kPref1);
457    if (iteration_ == 0) {
458      EXPECT_EQ("val1", actual);
459      ++iteration_;
460    } else {
461      EXPECT_EQ(kDefaultPref1, actual);
462    }
463  }
464
465 private:
466  int iteration_;
467};
468TEST_F(ControlledPrefsDisableExtensions, ControlledPrefsDisableExtensions) { }
469
470}  // namespace extensions
471