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