root/chrome/browser/extensions/api/preference/preference_api_prefs_unittest.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. content_settings_
  2. extension_prefs
  3. extension_pref_value_map
  4. content_settings_store
  5. content_settings_store
  6. test_preference_api_
  7. RegisterPreferences
  8. InstallExtensionControlledPref
  9. InstallExtensionControlledPrefIncognito
  10. InstallExtensionControlledPrefIncognitoSessionOnly
  11. InstallExtension
  12. UninstallExtension
  13. EnsureExtensionInstalled
  14. EnsureExtensionUninstalled
  15. Initialize
  16. Verify
  17. TEST_F
  18. Initialize
  19. Verify
  20. TEST_F
  21. Initialize
  22. Verify
  23. TEST_F
  24. Initialize
  25. Verify
  26. TEST_F
  27. Initialize
  28. Verify
  29. TEST_F
  30. Initialize
  31. Verify
  32. TEST_F
  33. Initialize
  34. Verify
  35. TEST_F
  36. Initialize
  37. Verify
  38. TEST_F
  39. Initialize
  40. Verify
  41. TEST_F

// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string>

#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/prefs/mock_pref_change_callback.h"
#include "base/values.h"
#include "chrome/browser/extensions/./extension_prefs_unittest.h"
#include "chrome/browser/extensions/api/content_settings/content_settings_service.h"
#include "chrome/browser/extensions/api/preference/preference_api.h"
#include "chrome/test/base/testing_profile.h"
#include "components/user_prefs/pref_registry_syncable.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/common/extension.h"
#include "testing/gtest/include/gtest/gtest.h"

using base::Value;

namespace extensions {

namespace {

const char kPref1[] = "path1.subpath";
const char kPref2[] = "path2";
const char kPref3[] = "path3";
const char kPref4[] = "path4";

// Default values in case an extension pref value is not overridden.
const char kDefaultPref1[] = "default pref 1";
const char kDefaultPref2[] = "default pref 2";
const char kDefaultPref3[] = "default pref 3";
const char kDefaultPref4[] = "default pref 4";

}  // namespace

// An implementation of the PreferenceAPI which returns the ExtensionPrefs and
// ExtensionPrefValueMap from the TestExtensionPrefs, rather than from a
// profile (which we don't create in unittests).
class TestPreferenceAPI : public PreferenceAPIBase {
 public:
  explicit TestPreferenceAPI(TestExtensionPrefs* test_extension_prefs,
                             ContentSettingsService* content_settings)
      : test_extension_prefs_(test_extension_prefs),
        content_settings_(content_settings) {}
  ~TestPreferenceAPI() {}

 private:
  // PreferenceAPIBase implementation.
  virtual ExtensionPrefs* extension_prefs() OVERRIDE {
    return test_extension_prefs_->prefs();
  }
  virtual ExtensionPrefValueMap* extension_pref_value_map() OVERRIDE {
    return test_extension_prefs_->extension_pref_value_map();
  }
  virtual scoped_refptr<ContentSettingsStore> content_settings_store()
      OVERRIDE {
    return content_settings_->content_settings_store();
  }

  TestExtensionPrefs* test_extension_prefs_;
  ContentSettingsService* content_settings_;

  DISALLOW_COPY_AND_ASSIGN(TestPreferenceAPI);
};

class ExtensionControlledPrefsTest : public PrefsPrepopulatedTestBase {
 public:
  ExtensionControlledPrefsTest();
  virtual ~ExtensionControlledPrefsTest();

  virtual void RegisterPreferences(user_prefs::PrefRegistrySyncable* registry)
      OVERRIDE;
  void InstallExtensionControlledPref(Extension* extension,
                                      const std::string& key,
                                      base::Value* value);
  void InstallExtensionControlledPrefIncognito(Extension* extension,
                                               const std::string& key,
                                               base::Value* value);
  void InstallExtensionControlledPrefIncognitoSessionOnly(
      Extension* extension,
      const std::string& key,
      base::Value* value);
  void InstallExtension(Extension* extension);
  void UninstallExtension(const std::string& extension_id);

  scoped_refptr<ContentSettingsStore> content_settings_store() {
    return content_settings_->content_settings_store();
  }

 protected:
  void EnsureExtensionInstalled(Extension* extension);
  void EnsureExtensionUninstalled(const std::string& extension_id);

  TestingProfile profile_;
  ContentSettingsService* content_settings_;
  TestPreferenceAPI test_preference_api_;
};

ExtensionControlledPrefsTest::ExtensionControlledPrefsTest()
    : PrefsPrepopulatedTestBase(),
      content_settings_(ContentSettingsService::Get(&profile_)),
      test_preference_api_(&prefs_, content_settings_) {
  prefs_.prefs()->AddObserver(content_settings_);
}

ExtensionControlledPrefsTest::~ExtensionControlledPrefsTest() {
}

void ExtensionControlledPrefsTest::RegisterPreferences(
    user_prefs::PrefRegistrySyncable* registry) {
  registry->RegisterStringPref(
      kPref1, kDefaultPref1, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
  registry->RegisterStringPref(
      kPref2, kDefaultPref2, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
  registry->RegisterStringPref(
      kPref3, kDefaultPref3, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
  registry->RegisterStringPref(
      kPref4, kDefaultPref4, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
}

void ExtensionControlledPrefsTest::InstallExtensionControlledPref(
    Extension* extension,
    const std::string& key,
    base::Value* value) {
  EnsureExtensionInstalled(extension);
  test_preference_api_.SetExtensionControlledPref(
      extension->id(), key, kExtensionPrefsScopeRegular, value);
}

void ExtensionControlledPrefsTest::InstallExtensionControlledPrefIncognito(
    Extension* extension,
    const std::string& key,
    base::Value* value) {
  EnsureExtensionInstalled(extension);
  test_preference_api_.SetExtensionControlledPref(
      extension->id(), key, kExtensionPrefsScopeIncognitoPersistent, value);
}

void ExtensionControlledPrefsTest::
InstallExtensionControlledPrefIncognitoSessionOnly(Extension* extension,
                                                   const std::string& key,
                                                   base::Value* value) {
  EnsureExtensionInstalled(extension);
  test_preference_api_.SetExtensionControlledPref(
      extension->id(), key, kExtensionPrefsScopeIncognitoSessionOnly, value);
}

void ExtensionControlledPrefsTest::InstallExtension(Extension* extension) {
  EnsureExtensionInstalled(extension);
}

void ExtensionControlledPrefsTest::UninstallExtension(
    const std::string& extension_id) {
  EnsureExtensionUninstalled(extension_id);
}

void ExtensionControlledPrefsTest::EnsureExtensionInstalled(
    Extension* extension) {
  // Install extension the first time a preference is set for it.
  Extension* extensions[] = { extension1(),
                              extension2(),
                              extension3(),
                              extension4() };
  for (size_t i = 0; i < kNumInstalledExtensions; ++i) {
    if (extension == extensions[i] && !installed_[i]) {
      prefs()->OnExtensionInstalled(extension,
                                    Extension::ENABLED,
                                    false,
                                    syncer::StringOrdinal(),
                                    std::string());
      prefs()->SetIsIncognitoEnabled(extension->id(), true);
      installed_[i] = true;
      break;
    }
  }
}

void ExtensionControlledPrefsTest::EnsureExtensionUninstalled(
    const std::string& extension_id) {
  Extension* extensions[] = { extension1(),
                              extension2(),
                              extension3(),
                              extension4() };
  for (size_t i = 0; i < kNumInstalledExtensions; ++i) {
    if (extensions[i]->id() == extension_id) {
      installed_[i] = false;
      break;
    }
  }
  prefs()->OnExtensionUninstalled(extension_id, Manifest::INTERNAL, false);
}

class ControlledPrefsInstallOneExtension
    : public ExtensionControlledPrefsTest {
  virtual void Initialize() OVERRIDE {
    InstallExtensionControlledPref(extension1(),
                                   kPref1,
                                   new base::StringValue("val1"));
  }
  virtual void Verify() OVERRIDE {
    std::string actual = prefs()->pref_service()->GetString(kPref1);
    EXPECT_EQ("val1", actual);
  }
};
TEST_F(ControlledPrefsInstallOneExtension,
       ControlledPrefsInstallOneExtension) { }

// Check that we do not forget persistent incognito values after a reload.
class ControlledPrefsInstallIncognitoPersistent
    : public ExtensionControlledPrefsTest {
 public:
  virtual void Initialize() OVERRIDE {
    InstallExtensionControlledPref(
        extension1(), kPref1, new base::StringValue("val1"));
    InstallExtensionControlledPrefIncognito(
        extension1(), kPref1, new base::StringValue("val2"));
    scoped_ptr<PrefService> incog_prefs(prefs_.CreateIncognitoPrefService());
    std::string actual = incog_prefs->GetString(kPref1);
    EXPECT_EQ("val2", actual);
  }

  virtual void Verify() OVERRIDE {
    // Main pref service shall see only non-incognito settings.
    std::string actual = prefs()->pref_service()->GetString(kPref1);
    EXPECT_EQ("val1", actual);
    // Incognito pref service shall see incognito values.
    scoped_ptr<PrefService> incog_prefs(prefs_.CreateIncognitoPrefService());
    actual = incog_prefs->GetString(kPref1);
    EXPECT_EQ("val2", actual);
  }
};
TEST_F(ControlledPrefsInstallIncognitoPersistent,
       ControlledPrefsInstallIncognitoPersistent) { }

// Check that we forget 'session only' incognito values after a reload.
class ControlledPrefsInstallIncognitoSessionOnly
    : public ExtensionControlledPrefsTest {
 public:
  ControlledPrefsInstallIncognitoSessionOnly() : iteration_(0) {}

  virtual void Initialize() OVERRIDE {
    InstallExtensionControlledPref(
        extension1(), kPref1, new base::StringValue("val1"));
    InstallExtensionControlledPrefIncognitoSessionOnly(
        extension1(), kPref1, new base::StringValue("val2"));
    scoped_ptr<PrefService> incog_prefs(prefs_.CreateIncognitoPrefService());
    std::string actual = incog_prefs->GetString(kPref1);
    EXPECT_EQ("val2", actual);
  }
  virtual void Verify() OVERRIDE {
    // Main pref service shall see only non-incognito settings.
    std::string actual = prefs()->pref_service()->GetString(kPref1);
    EXPECT_EQ("val1", actual);
    // Incognito pref service shall see session-only incognito values only
    // during first run. Once the pref service was reloaded, all values shall be
    // discarded.
    scoped_ptr<PrefService> incog_prefs(prefs_.CreateIncognitoPrefService());
    actual = incog_prefs->GetString(kPref1);
    if (iteration_ == 0) {
      EXPECT_EQ("val2", actual);
    } else {
      EXPECT_EQ("val1", actual);
    }
    ++iteration_;
  }
  int iteration_;
};
TEST_F(ControlledPrefsInstallIncognitoSessionOnly,
       ControlledPrefsInstallIncognitoSessionOnly) { }

class ControlledPrefsUninstallExtension : public ExtensionControlledPrefsTest {
  virtual void Initialize() OVERRIDE {
    InstallExtensionControlledPref(
        extension1(), kPref1, new base::StringValue("val1"));
    InstallExtensionControlledPref(
        extension1(), kPref2, new base::StringValue("val2"));
    scoped_refptr<ContentSettingsStore> store = content_settings_store();
    ContentSettingsPattern pattern =
        ContentSettingsPattern::FromString("http://[*.]example.com");
    store->SetExtensionContentSetting(extension1()->id(),
                                      pattern, pattern,
                                      CONTENT_SETTINGS_TYPE_IMAGES,
                                      std::string(),
                                      CONTENT_SETTING_BLOCK,
                                      kExtensionPrefsScopeRegular);

    UninstallExtension(extension1()->id());
  }
  virtual void Verify() OVERRIDE {
    EXPECT_FALSE(prefs()->HasPrefForExtension(extension1()->id()));

    std::string actual;
    actual = prefs()->pref_service()->GetString(kPref1);
    EXPECT_EQ(kDefaultPref1, actual);
    actual = prefs()->pref_service()->GetString(kPref2);
    EXPECT_EQ(kDefaultPref2, actual);
  }
};
TEST_F(ControlledPrefsUninstallExtension,
       ControlledPrefsUninstallExtension) { }

// Tests triggering of notifications to registered observers.
class ControlledPrefsNotifyWhenNeeded : public ExtensionControlledPrefsTest {
  virtual void Initialize() OVERRIDE {
    using testing::_;
    using testing::Mock;
    using testing::StrEq;

    MockPrefChangeCallback observer(prefs()->pref_service());
    PrefChangeRegistrar registrar;
    registrar.Init(prefs()->pref_service());
    registrar.Add(kPref1, observer.GetCallback());

    MockPrefChangeCallback incognito_observer(prefs()->pref_service());
    scoped_ptr<PrefService> incog_prefs(prefs_.CreateIncognitoPrefService());
    PrefChangeRegistrar incognito_registrar;
    incognito_registrar.Init(incog_prefs.get());
    incognito_registrar.Add(kPref1, incognito_observer.GetCallback());

    // Write value and check notification.
    EXPECT_CALL(observer, OnPreferenceChanged(_));
    EXPECT_CALL(incognito_observer, OnPreferenceChanged(_));
    InstallExtensionControlledPref(extension1(), kPref1,
        new base::StringValue("https://www.chromium.org"));
    Mock::VerifyAndClearExpectations(&observer);
    Mock::VerifyAndClearExpectations(&incognito_observer);

    // Write same value.
    EXPECT_CALL(observer, OnPreferenceChanged(_)).Times(0);
    EXPECT_CALL(incognito_observer, OnPreferenceChanged(_)).Times(0);
    InstallExtensionControlledPref(extension1(), kPref1,
        new base::StringValue("https://www.chromium.org"));
    Mock::VerifyAndClearExpectations(&observer);
    Mock::VerifyAndClearExpectations(&incognito_observer);

    // Change value.
    EXPECT_CALL(observer, OnPreferenceChanged(_));
    EXPECT_CALL(incognito_observer, OnPreferenceChanged(_));
    InstallExtensionControlledPref(extension1(), kPref1,
        new base::StringValue("chrome://newtab"));
    Mock::VerifyAndClearExpectations(&observer);
    Mock::VerifyAndClearExpectations(&incognito_observer);
    // Change only incognito persistent value.
    EXPECT_CALL(observer, OnPreferenceChanged(_)).Times(0);
    EXPECT_CALL(incognito_observer, OnPreferenceChanged(_));
    InstallExtensionControlledPrefIncognito(extension1(), kPref1,
        new base::StringValue("chrome://newtab2"));
    Mock::VerifyAndClearExpectations(&observer);
    Mock::VerifyAndClearExpectations(&incognito_observer);

    // Change only incognito session-only value.
    EXPECT_CALL(observer, OnPreferenceChanged(_)).Times(0);
    EXPECT_CALL(incognito_observer, OnPreferenceChanged(_));
    InstallExtensionControlledPrefIncognito(extension1(), kPref1,
        new base::StringValue("chrome://newtab3"));
    Mock::VerifyAndClearExpectations(&observer);
    Mock::VerifyAndClearExpectations(&incognito_observer);

    // Uninstall.
    EXPECT_CALL(observer, OnPreferenceChanged(_));
    EXPECT_CALL(incognito_observer, OnPreferenceChanged(_));
    UninstallExtension(extension1()->id());
    Mock::VerifyAndClearExpectations(&observer);
    Mock::VerifyAndClearExpectations(&incognito_observer);

    registrar.Remove(kPref1);
    incognito_registrar.Remove(kPref1);
  }
  virtual void Verify() OVERRIDE {
    std::string actual = prefs()->pref_service()->GetString(kPref1);
    EXPECT_EQ(kDefaultPref1, actual);
  }
};
TEST_F(ControlledPrefsNotifyWhenNeeded,
       ControlledPrefsNotifyWhenNeeded) { }

// Tests disabling an extension.
class ControlledPrefsDisableExtension : public ExtensionControlledPrefsTest {
  virtual void Initialize() OVERRIDE {
    InstallExtensionControlledPref(
        extension1(), kPref1, new base::StringValue("val1"));
    std::string actual = prefs()->pref_service()->GetString(kPref1);
    EXPECT_EQ("val1", actual);
    prefs()->SetExtensionState(extension1()->id(), Extension::DISABLED);
  }
  virtual void Verify() OVERRIDE {
    std::string actual = prefs()->pref_service()->GetString(kPref1);
    EXPECT_EQ(kDefaultPref1, actual);
  }
};
TEST_F(ControlledPrefsDisableExtension, ControlledPrefsDisableExtension) { }

// Tests disabling and reenabling an extension.
class ControlledPrefsReenableExtension : public ExtensionControlledPrefsTest {
  virtual void Initialize() OVERRIDE {
    InstallExtensionControlledPref(
        extension1(), kPref1, new base::StringValue("val1"));
    prefs()->SetExtensionState(extension1()->id(), Extension::DISABLED);
    prefs()->SetExtensionState(extension1()->id(), Extension::ENABLED);
  }
  virtual void Verify() OVERRIDE {
    std::string actual = prefs()->pref_service()->GetString(kPref1);
    EXPECT_EQ("val1", actual);
  }
};
TEST_F(ControlledPrefsDisableExtension, ControlledPrefsReenableExtension) { }

// Mock class to test whether objects are deleted correctly.
class MockStringValue : public base::StringValue {
 public:
  explicit MockStringValue(const std::string& in_value)
      : base::StringValue(in_value) {
  }
  virtual ~MockStringValue() {
    Die();
  }
  MOCK_METHOD0(Die, void());
};

class ControlledPrefsSetExtensionControlledPref
    : public ExtensionControlledPrefsTest {
 public:
  virtual void Initialize() OVERRIDE {
    MockStringValue* v1 = new MockStringValue("https://www.chromium.org");
    MockStringValue* v2 = new MockStringValue("https://www.chromium.org");
    MockStringValue* v1i = new MockStringValue("https://www.chromium.org");
    MockStringValue* v2i = new MockStringValue("https://www.chromium.org");
    // Ownership is taken, value shall not be deleted.
    EXPECT_CALL(*v1, Die()).Times(0);
    EXPECT_CALL(*v1i, Die()).Times(0);
    InstallExtensionControlledPref(extension1(), kPref1, v1);
    InstallExtensionControlledPrefIncognito(extension1(), kPref1, v1i);
    testing::Mock::VerifyAndClearExpectations(v1);
    testing::Mock::VerifyAndClearExpectations(v1i);
    // Make sure there is no memory leak and both values are deleted.
    EXPECT_CALL(*v1, Die()).Times(1);
    EXPECT_CALL(*v1i, Die()).Times(1);
    EXPECT_CALL(*v2, Die()).Times(1);
    EXPECT_CALL(*v2i, Die()).Times(1);
    InstallExtensionControlledPref(extension1(), kPref1, v2);
    InstallExtensionControlledPrefIncognito(extension1(), kPref1, v2i);
    prefs_.RecreateExtensionPrefs();
    testing::Mock::VerifyAndClearExpectations(v1);
    testing::Mock::VerifyAndClearExpectations(v1i);
    testing::Mock::VerifyAndClearExpectations(v2);
    testing::Mock::VerifyAndClearExpectations(v2i);
  }

  virtual void Verify() OVERRIDE {
  }
};
TEST_F(ControlledPrefsSetExtensionControlledPref,
       ControlledPrefsSetExtensionControlledPref) { }

// Tests that the switches::kDisableExtensions command-line flag prevents
// extension controlled preferences from being enacted.
class ControlledPrefsDisableExtensions : public ExtensionControlledPrefsTest {
 public:
  ControlledPrefsDisableExtensions()
      : iteration_(0) {}
  virtual ~ControlledPrefsDisableExtensions() {}
  virtual void Initialize() OVERRIDE {
    InstallExtensionControlledPref(
        extension1(), kPref1, new base::StringValue("val1"));
    // This becomes only active in the second verification phase.
    prefs_.set_extensions_disabled(true);
  }
  virtual void Verify() OVERRIDE {
    std::string actual = prefs()->pref_service()->GetString(kPref1);
    if (iteration_ == 0) {
      EXPECT_EQ("val1", actual);
      ++iteration_;
    } else {
      EXPECT_EQ(kDefaultPref1, actual);
    }
  }

 private:
  int iteration_;
};
TEST_F(ControlledPrefsDisableExtensions, ControlledPrefsDisableExtensions) { }

}  // namespace extensions

/* [<][>][^][v][top][bottom][index][help] */