preference_api_prefs_unittest.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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      prefs()->SetIsIncognitoEnabled(extension->id(), true);
157      installed_[i] = true;
158      break;
159    }
160  }
161}
162
163void ExtensionControlledPrefsTest::EnsureExtensionUninstalled(
164    const std::string& extension_id) {
165  Extension* extensions[] = { extension1(),
166                              extension2(),
167                              extension3(),
168                              extension4() };
169  for (size_t i = 0; i < kNumInstalledExtensions; ++i) {
170    if (extensions[i]->id() == extension_id) {
171      installed_[i] = false;
172      break;
173    }
174  }
175  prefs()->OnExtensionUninstalled(extension_id, Manifest::INTERNAL, false);
176}
177
178class ControlledPrefsInstallOneExtension
179    : public ExtensionControlledPrefsTest {
180  virtual void Initialize() OVERRIDE {
181    InstallExtensionControlledPref(extension1(),
182                                   kPref1,
183                                   new base::StringValue("val1"));
184  }
185  virtual void Verify() OVERRIDE {
186    std::string actual = prefs()->pref_service()->GetString(kPref1);
187    EXPECT_EQ("val1", actual);
188  }
189};
190TEST_F(ControlledPrefsInstallOneExtension,
191       ControlledPrefsInstallOneExtension) { }
192
193// Check that we do not forget persistent incognito values after a reload.
194class ControlledPrefsInstallIncognitoPersistent
195    : public ExtensionControlledPrefsTest {
196 public:
197  virtual void Initialize() OVERRIDE {
198    InstallExtensionControlledPref(
199        extension1(), kPref1, new base::StringValue("val1"));
200    InstallExtensionControlledPrefIncognito(
201        extension1(), kPref1, new base::StringValue("val2"));
202    scoped_ptr<PrefService> incog_prefs(prefs_.CreateIncognitoPrefService());
203    std::string actual = incog_prefs->GetString(kPref1);
204    EXPECT_EQ("val2", actual);
205  }
206
207  virtual void Verify() OVERRIDE {
208    // Main pref service shall see only non-incognito settings.
209    std::string actual = prefs()->pref_service()->GetString(kPref1);
210    EXPECT_EQ("val1", actual);
211    // Incognito pref service shall see incognito values.
212    scoped_ptr<PrefService> incog_prefs(prefs_.CreateIncognitoPrefService());
213    actual = incog_prefs->GetString(kPref1);
214    EXPECT_EQ("val2", actual);
215  }
216};
217TEST_F(ControlledPrefsInstallIncognitoPersistent,
218       ControlledPrefsInstallIncognitoPersistent) { }
219
220// Check that we forget 'session only' incognito values after a reload.
221class ControlledPrefsInstallIncognitoSessionOnly
222    : public ExtensionControlledPrefsTest {
223 public:
224  ControlledPrefsInstallIncognitoSessionOnly() : iteration_(0) {}
225
226  virtual void Initialize() OVERRIDE {
227    InstallExtensionControlledPref(
228        extension1(), kPref1, new base::StringValue("val1"));
229    InstallExtensionControlledPrefIncognitoSessionOnly(
230        extension1(), kPref1, new base::StringValue("val2"));
231    scoped_ptr<PrefService> incog_prefs(prefs_.CreateIncognitoPrefService());
232    std::string actual = incog_prefs->GetString(kPref1);
233    EXPECT_EQ("val2", actual);
234  }
235  virtual void Verify() OVERRIDE {
236    // Main pref service shall see only non-incognito settings.
237    std::string actual = prefs()->pref_service()->GetString(kPref1);
238    EXPECT_EQ("val1", actual);
239    // Incognito pref service shall see session-only incognito values only
240    // during first run. Once the pref service was reloaded, all values shall be
241    // discarded.
242    scoped_ptr<PrefService> incog_prefs(prefs_.CreateIncognitoPrefService());
243    actual = incog_prefs->GetString(kPref1);
244    if (iteration_ == 0) {
245      EXPECT_EQ("val2", actual);
246    } else {
247      EXPECT_EQ("val1", actual);
248    }
249    ++iteration_;
250  }
251  int iteration_;
252};
253TEST_F(ControlledPrefsInstallIncognitoSessionOnly,
254       ControlledPrefsInstallIncognitoSessionOnly) { }
255
256class ControlledPrefsUninstallExtension : public ExtensionControlledPrefsTest {
257  virtual void Initialize() OVERRIDE {
258    InstallExtensionControlledPref(
259        extension1(), kPref1, new base::StringValue("val1"));
260    InstallExtensionControlledPref(
261        extension1(), kPref2, new base::StringValue("val2"));
262    ContentSettingsStore* store = prefs()->content_settings_store();
263    ContentSettingsPattern pattern =
264        ContentSettingsPattern::FromString("http://[*.]example.com");
265    store->SetExtensionContentSetting(extension1()->id(),
266                                      pattern, pattern,
267                                      CONTENT_SETTINGS_TYPE_IMAGES,
268                                      std::string(),
269                                      CONTENT_SETTING_BLOCK,
270                                      kExtensionPrefsScopeRegular);
271
272    UninstallExtension(extension1()->id());
273  }
274  virtual void Verify() OVERRIDE {
275    EXPECT_FALSE(prefs()->HasPrefForExtension(extension1()->id()));
276
277    std::string actual;
278    actual = prefs()->pref_service()->GetString(kPref1);
279    EXPECT_EQ(kDefaultPref1, actual);
280    actual = prefs()->pref_service()->GetString(kPref2);
281    EXPECT_EQ(kDefaultPref2, actual);
282  }
283};
284TEST_F(ControlledPrefsUninstallExtension,
285       ControlledPrefsUninstallExtension) { }
286
287// Tests triggering of notifications to registered observers.
288class ControlledPrefsNotifyWhenNeeded : public ExtensionControlledPrefsTest {
289  virtual void Initialize() OVERRIDE {
290    using testing::_;
291    using testing::Mock;
292    using testing::StrEq;
293
294    MockPrefChangeCallback observer(prefs()->pref_service());
295    PrefChangeRegistrar registrar;
296    registrar.Init(prefs()->pref_service());
297    registrar.Add(kPref1, observer.GetCallback());
298
299    MockPrefChangeCallback incognito_observer(prefs()->pref_service());
300    scoped_ptr<PrefService> incog_prefs(prefs_.CreateIncognitoPrefService());
301    PrefChangeRegistrar incognito_registrar;
302    incognito_registrar.Init(incog_prefs.get());
303    incognito_registrar.Add(kPref1, incognito_observer.GetCallback());
304
305    // Write value and check notification.
306    EXPECT_CALL(observer, OnPreferenceChanged(_));
307    EXPECT_CALL(incognito_observer, OnPreferenceChanged(_));
308    InstallExtensionControlledPref(extension1(), kPref1,
309        new base::StringValue("https://www.chromium.org"));
310    Mock::VerifyAndClearExpectations(&observer);
311    Mock::VerifyAndClearExpectations(&incognito_observer);
312
313    // Write same value.
314    EXPECT_CALL(observer, OnPreferenceChanged(_)).Times(0);
315    EXPECT_CALL(incognito_observer, OnPreferenceChanged(_)).Times(0);
316    InstallExtensionControlledPref(extension1(), kPref1,
317        new base::StringValue("https://www.chromium.org"));
318    Mock::VerifyAndClearExpectations(&observer);
319    Mock::VerifyAndClearExpectations(&incognito_observer);
320
321    // Change value.
322    EXPECT_CALL(observer, OnPreferenceChanged(_));
323    EXPECT_CALL(incognito_observer, OnPreferenceChanged(_));
324    InstallExtensionControlledPref(extension1(), kPref1,
325        new base::StringValue("chrome://newtab"));
326    Mock::VerifyAndClearExpectations(&observer);
327    Mock::VerifyAndClearExpectations(&incognito_observer);
328    // Change only incognito persistent value.
329    EXPECT_CALL(observer, OnPreferenceChanged(_)).Times(0);
330    EXPECT_CALL(incognito_observer, OnPreferenceChanged(_));
331    InstallExtensionControlledPrefIncognito(extension1(), kPref1,
332        new base::StringValue("chrome://newtab2"));
333    Mock::VerifyAndClearExpectations(&observer);
334    Mock::VerifyAndClearExpectations(&incognito_observer);
335
336    // Change only incognito session-only value.
337    EXPECT_CALL(observer, OnPreferenceChanged(_)).Times(0);
338    EXPECT_CALL(incognito_observer, OnPreferenceChanged(_));
339    InstallExtensionControlledPrefIncognito(extension1(), kPref1,
340        new base::StringValue("chrome://newtab3"));
341    Mock::VerifyAndClearExpectations(&observer);
342    Mock::VerifyAndClearExpectations(&incognito_observer);
343
344    // Uninstall.
345    EXPECT_CALL(observer, OnPreferenceChanged(_));
346    EXPECT_CALL(incognito_observer, OnPreferenceChanged(_));
347    UninstallExtension(extension1()->id());
348    Mock::VerifyAndClearExpectations(&observer);
349    Mock::VerifyAndClearExpectations(&incognito_observer);
350
351    registrar.Remove(kPref1);
352    incognito_registrar.Remove(kPref1);
353  }
354  virtual void Verify() OVERRIDE {
355    std::string actual = prefs()->pref_service()->GetString(kPref1);
356    EXPECT_EQ(kDefaultPref1, actual);
357  }
358};
359TEST_F(ControlledPrefsNotifyWhenNeeded,
360       ControlledPrefsNotifyWhenNeeded) { }
361
362// Tests disabling an extension.
363class ControlledPrefsDisableExtension : public ExtensionControlledPrefsTest {
364  virtual void Initialize() OVERRIDE {
365    InstallExtensionControlledPref(
366        extension1(), kPref1, new base::StringValue("val1"));
367    std::string actual = prefs()->pref_service()->GetString(kPref1);
368    EXPECT_EQ("val1", actual);
369    prefs()->SetExtensionState(extension1()->id(), Extension::DISABLED);
370  }
371  virtual void Verify() OVERRIDE {
372    std::string actual = prefs()->pref_service()->GetString(kPref1);
373    EXPECT_EQ(kDefaultPref1, actual);
374  }
375};
376TEST_F(ControlledPrefsDisableExtension, ControlledPrefsDisableExtension) { }
377
378// Tests disabling and reenabling an extension.
379class ControlledPrefsReenableExtension : public ExtensionControlledPrefsTest {
380  virtual void Initialize() OVERRIDE {
381    InstallExtensionControlledPref(
382        extension1(), kPref1, new base::StringValue("val1"));
383    prefs()->SetExtensionState(extension1()->id(), Extension::DISABLED);
384    prefs()->SetExtensionState(extension1()->id(), Extension::ENABLED);
385  }
386  virtual void Verify() OVERRIDE {
387    std::string actual = prefs()->pref_service()->GetString(kPref1);
388    EXPECT_EQ("val1", actual);
389  }
390};
391TEST_F(ControlledPrefsDisableExtension, ControlledPrefsReenableExtension) { }
392
393// Mock class to test whether objects are deleted correctly.
394class MockStringValue : public base::StringValue {
395 public:
396  explicit MockStringValue(const std::string& in_value)
397      : base::StringValue(in_value) {
398  }
399  virtual ~MockStringValue() {
400    Die();
401  }
402  MOCK_METHOD0(Die, void());
403};
404
405class ControlledPrefsSetExtensionControlledPref
406    : public ExtensionControlledPrefsTest {
407 public:
408  virtual void Initialize() OVERRIDE {
409    MockStringValue* v1 = new MockStringValue("https://www.chromium.org");
410    MockStringValue* v2 = new MockStringValue("https://www.chromium.org");
411    MockStringValue* v1i = new MockStringValue("https://www.chromium.org");
412    MockStringValue* v2i = new MockStringValue("https://www.chromium.org");
413    // Ownership is taken, value shall not be deleted.
414    EXPECT_CALL(*v1, Die()).Times(0);
415    EXPECT_CALL(*v1i, Die()).Times(0);
416    InstallExtensionControlledPref(extension1(), kPref1, v1);
417    InstallExtensionControlledPrefIncognito(extension1(), kPref1, v1i);
418    testing::Mock::VerifyAndClearExpectations(v1);
419    testing::Mock::VerifyAndClearExpectations(v1i);
420    // Make sure there is no memory leak and both values are deleted.
421    EXPECT_CALL(*v1, Die()).Times(1);
422    EXPECT_CALL(*v1i, Die()).Times(1);
423    EXPECT_CALL(*v2, Die()).Times(1);
424    EXPECT_CALL(*v2i, Die()).Times(1);
425    InstallExtensionControlledPref(extension1(), kPref1, v2);
426    InstallExtensionControlledPrefIncognito(extension1(), kPref1, v2i);
427    prefs_.RecreateExtensionPrefs();
428    testing::Mock::VerifyAndClearExpectations(v1);
429    testing::Mock::VerifyAndClearExpectations(v1i);
430    testing::Mock::VerifyAndClearExpectations(v2);
431    testing::Mock::VerifyAndClearExpectations(v2i);
432  }
433
434  virtual void Verify() OVERRIDE {
435  }
436};
437TEST_F(ControlledPrefsSetExtensionControlledPref,
438       ControlledPrefsSetExtensionControlledPref) { }
439
440// Tests that the switches::kDisableExtensions command-line flag prevents
441// extension controlled preferences from being enacted.
442class ControlledPrefsDisableExtensions : public ExtensionControlledPrefsTest {
443 public:
444  ControlledPrefsDisableExtensions()
445      : iteration_(0) {}
446  virtual ~ControlledPrefsDisableExtensions() {}
447  virtual void Initialize() OVERRIDE {
448    InstallExtensionControlledPref(
449        extension1(), kPref1, new base::StringValue("val1"));
450    // This becomes only active in the second verification phase.
451    prefs_.set_extensions_disabled(true);
452  }
453  virtual void Verify() OVERRIDE {
454    std::string actual = prefs()->pref_service()->GetString(kPref1);
455    if (iteration_ == 0) {
456      EXPECT_EQ("val1", actual);
457      ++iteration_;
458    } else {
459      EXPECT_EQ(kDefaultPref1, actual);
460    }
461  }
462
463 private:
464  int iteration_;
465};
466TEST_F(ControlledPrefsDisableExtensions, ControlledPrefsDisableExtensions) { }
467
468}  // namespace extensions
469