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