Home | History | Annotate | Download | only in preference
      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 
     20 using base::Value;
     21 
     22 namespace keys = extension_manifest_keys;
     23 
     24 namespace extensions {
     25 
     26 namespace {
     27 
     28 const char kPref1[] = "path1.subpath";
     29 const char kPref2[] = "path2";
     30 const char kPref3[] = "path3";
     31 const char kPref4[] = "path4";
     32 
     33 // Default values in case an extension pref value is not overridden.
     34 const char kDefaultPref1[] = "default pref 1";
     35 const char kDefaultPref2[] = "default pref 2";
     36 const char kDefaultPref3[] = "default pref 3";
     37 const 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).
     44 class 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 
     63 class 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 
     90 ExtensionControlledPrefsTest::ExtensionControlledPrefsTest()
     91     : PrefsPrepopulatedTestBase(),
     92       test_preference_api_(&prefs_) {
     93 }
     94 
     95 ExtensionControlledPrefsTest::~ExtensionControlledPrefsTest() {
     96 }
     97 
     98 void 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 
    110 void 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 
    119 void 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 
    128 void ExtensionControlledPrefsTest::
    129 InstallExtensionControlledPrefIncognitoSessionOnly(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 
    137 void ExtensionControlledPrefsTest::InstallExtension(Extension* extension) {
    138   EnsureExtensionInstalled(extension);
    139 }
    140 
    141 void ExtensionControlledPrefsTest::UninstallExtension(
    142     const std::string& extension_id) {
    143   EnsureExtensionUninstalled(extension_id);
    144 }
    145 
    146 void 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 
    165 void 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 
    180 class 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 };
    192 TEST_F(ControlledPrefsInstallOneExtension,
    193        ControlledPrefsInstallOneExtension) { }
    194 
    195 // Check that we do not forget persistent incognito values after a reload.
    196 class 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 };
    219 TEST_F(ControlledPrefsInstallIncognitoPersistent,
    220        ControlledPrefsInstallIncognitoPersistent) { }
    221 
    222 // Check that we forget 'session only' incognito values after a reload.
    223 class 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 };
    255 TEST_F(ControlledPrefsInstallIncognitoSessionOnly,
    256        ControlledPrefsInstallIncognitoSessionOnly) { }
    257 
    258 class 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 };
    286 TEST_F(ControlledPrefsUninstallExtension,
    287        ControlledPrefsUninstallExtension) { }
    288 
    289 // Tests triggering of notifications to registered observers.
    290 class 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 };
    361 TEST_F(ControlledPrefsNotifyWhenNeeded,
    362        ControlledPrefsNotifyWhenNeeded) { }
    363 
    364 // Tests disabling an extension.
    365 class 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 };
    378 TEST_F(ControlledPrefsDisableExtension, ControlledPrefsDisableExtension) { }
    379 
    380 // Tests disabling and reenabling an extension.
    381 class 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 };
    393 TEST_F(ControlledPrefsDisableExtension, ControlledPrefsReenableExtension) { }
    394 
    395 // Mock class to test whether objects are deleted correctly.
    396 class 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 
    407 class 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 };
    439 TEST_F(ControlledPrefsSetExtensionControlledPref,
    440        ControlledPrefsSetExtensionControlledPref) { }
    441 
    442 // Tests that the switches::kDisableExtensions command-line flag prevents
    443 // extension controlled preferences from being enacted.
    444 class 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 };
    468 TEST_F(ControlledPrefsDisableExtensions, ControlledPrefsDisableExtensions) { }
    469 
    470 }  // namespace extensions
    471