diff options
author | dconnelly@chromium.org <dconnelly@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-02 14:33:46 +0000 |
---|---|---|
committer | dconnelly@chromium.org <dconnelly@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-12-02 14:33:46 +0000 |
commit | afefdcf4a25113f849908605c946ccfa6a914811 (patch) | |
tree | a50035aa981fd588561d99ec9166984698dbe92d /components | |
parent | bed2900b838897a24c8a86a95fd93d8166c6928a (diff) | |
download | chromium_src-afefdcf4a25113f849908605c946ccfa6a914811.zip chromium_src-afefdcf4a25113f849908605c946ccfa6a914811.tar.gz chromium_src-afefdcf4a25113f849908605c946ccfa6a914811.tar.bz2 |
Move ConfigurationPolicyProvider, etc. to components/policy.
This facilitates the refactoring of chrome/browser/policy into a layered
component.
BUG=271392
NOTRY=true
Review URL: https://codereview.chromium.org/92153002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@238097 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'components')
8 files changed, 883 insertions, 2 deletions
diff --git a/components/components_tests.gyp b/components/components_tests.gyp index 81e65a4..3e33547 100644 --- a/components/components_tests.gyp +++ b/components/components_tests.gyp @@ -174,6 +174,9 @@ }, }], ['configuration_policy==1', { + 'dependencies': [ + 'components.gyp:policy_test_support', + ], 'sources': [ 'policy/core/common/policy_bundle_unittest.cc', 'policy/core/common/policy_map_unittest.cc', diff --git a/components/policy.gypi b/components/policy.gypi index 4580dea..17b5cf9 100644 --- a/components/policy.gypi +++ b/components/policy.gypi @@ -21,11 +21,13 @@ 'conditions': [ ['configuration_policy==1', { 'sources': [ - 'policy/core/common/policy_bundle.cc', - 'policy/core/common/policy_bundle.h', + 'policy/core/common/configuration_policy_provider.cc', + 'policy/core/common/configuration_policy_provider.h', 'policy/core/common/external_data_fetcher.cc', 'policy/core/common/external_data_fetcher.h', 'policy/core/common/external_data_manager.h', + 'policy/core/common/policy_bundle.cc', + 'policy/core/common/policy_bundle.h', 'policy/core/common/policy_details.h', 'policy/core/common/policy_namespace.cc', 'policy/core/common/policy_namespace.h', @@ -64,4 +66,33 @@ ], }, ], + 'conditions': [ + ['configuration_policy==1', { + 'targets': [ + { + 'target_name': 'policy_test_support', + 'type': 'static_library', + # This must be undefined so that POLICY_EXPORT works correctly in + # the static_library build. + 'defines!': [ + 'POLICY_COMPONENT_IMPLEMENTATION', + ], + 'dependencies': [ + 'policy_component', + '../testing/gmock.gyp:gmock', + '../testing/gtest.gyp:gtest', + ], + 'include_dirs': [ + '..', + ], + 'sources': [ + 'policy/core/common/configuration_policy_provider_test.cc', + 'policy/core/common/configuration_policy_provider_test.h', + 'policy/core/common/mock_configuration_policy_provider.cc', + 'policy/core/common/mock_configuration_policy_provider.h', + ], + }, + ], + }], + ], } diff --git a/components/policy/core/common/configuration_policy_provider.cc b/components/policy/core/common/configuration_policy_provider.cc new file mode 100644 index 0000000..01070c8 --- /dev/null +++ b/components/policy/core/common/configuration_policy_provider.cc @@ -0,0 +1,76 @@ +// 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 "components/policy/core/common/configuration_policy_provider.h" + +#include "base/callback.h" +#include "components/policy/core/common/external_data_fetcher.h" +#include "components/policy/core/common/policy_map.h" + +namespace policy { + +ConfigurationPolicyProvider::Observer::~Observer() {} + +ConfigurationPolicyProvider::ConfigurationPolicyProvider() + : did_shutdown_(false), + schema_registry_(NULL) {} + +ConfigurationPolicyProvider::~ConfigurationPolicyProvider() { + DCHECK(did_shutdown_); +} + +void ConfigurationPolicyProvider::Init(SchemaRegistry* registry) { + schema_registry_ = registry; + schema_registry_->AddObserver(this); +} + +void ConfigurationPolicyProvider::Shutdown() { + did_shutdown_ = true; + if (schema_registry_) { + // Unit tests don't initialize the BrowserPolicyConnector but call + // shutdown; handle that. + schema_registry_->RemoveObserver(this); + schema_registry_ = NULL; + } +} + +bool ConfigurationPolicyProvider::IsInitializationComplete( + PolicyDomain domain) const { + return true; +} + +void ConfigurationPolicyProvider::UpdatePolicy( + scoped_ptr<PolicyBundle> bundle) { + if (bundle.get()) + policy_bundle_.Swap(bundle.get()); + else + policy_bundle_.Clear(); + FOR_EACH_OBSERVER(ConfigurationPolicyProvider::Observer, + observer_list_, + OnUpdatePolicy(this)); +} + +SchemaRegistry* ConfigurationPolicyProvider::schema_registry() const { + return schema_registry_; +} + +const scoped_refptr<SchemaMap>& +ConfigurationPolicyProvider::schema_map() const { + return schema_registry_->schema_map(); +} + +void ConfigurationPolicyProvider::AddObserver(Observer* observer) { + observer_list_.AddObserver(observer); +} + +void ConfigurationPolicyProvider::RemoveObserver(Observer* observer) { + observer_list_.RemoveObserver(observer); +} + +void ConfigurationPolicyProvider::OnSchemaRegistryUpdated( + bool has_new_schemas) {} + +void ConfigurationPolicyProvider::OnSchemaRegistryReady() {} + +} // namespace policy diff --git a/components/policy/core/common/configuration_policy_provider.h b/components/policy/core/common/configuration_policy_provider.h new file mode 100644 index 0000000..f2b746d --- /dev/null +++ b/components/policy/core/common/configuration_policy_provider.h @@ -0,0 +1,103 @@ +// 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. + +#ifndef COMPONENTS_POLICY_CORE_COMMON_CONFIGURATION_POLICY_PROVIDER_H_ +#define COMPONENTS_POLICY_CORE_COMMON_CONFIGURATION_POLICY_PROVIDER_H_ + +#include "base/basictypes.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/observer_list.h" +#include "components/policy/core/common/policy_bundle.h" +#include "components/policy/core/common/policy_namespace.h" +#include "components/policy/core/common/schema_registry.h" +#include "components/policy/policy_export.h" + +namespace policy { + +// A mostly-abstract super class for platform-specific policy providers. +// Platform-specific policy providers (Windows Group Policy, gconf, +// etc.) should implement a subclass of this class. +class POLICY_EXPORT ConfigurationPolicyProvider + : public SchemaRegistry::Observer { + public: + class POLICY_EXPORT Observer { + public: + virtual ~Observer(); + virtual void OnUpdatePolicy(ConfigurationPolicyProvider* provider) = 0; + }; + + ConfigurationPolicyProvider(); + + // Policy providers can be deleted quite late during shutdown of the browser, + // and it's not guaranteed that the message loops will still be running when + // this is invoked. Override Shutdown() instead for cleanup code that needs + // to post to the FILE thread, for example. + virtual ~ConfigurationPolicyProvider(); + + // Invoked as soon as the main message loops are spinning. Policy providers + // are created early during startup to provide the initial policies; the + // Init() call allows them to perform initialization tasks that require + // running message loops. + // The policy provider will load policy for the components registered in + // the |schema_registry| whose domain is supported by this provider. + virtual void Init(SchemaRegistry* registry); + + // Must be invoked before deleting the provider. Implementations can override + // this method to do appropriate cleanup while threads are still running, and + // must also invoke ConfigurationPolicyProvider::Shutdown(). + // The provider should keep providing the current policies after Shutdown() + // is invoked, it only has to stop updating. + virtual void Shutdown(); + + // Returns the current PolicyBundle. + const PolicyBundle& policies() const { return policy_bundle_; } + + // Check whether this provider has completed initialization for the given + // policy |domain|. This is used to detect whether initialization is done in + // case implementations need to do asynchronous operations for initialization. + virtual bool IsInitializationComplete(PolicyDomain domain) const; + + // Asks the provider to refresh its policies. All the updates caused by this + // call will be visible on the next call of OnUpdatePolicy on the observers, + // which are guaranteed to happen even if the refresh fails. + // It is possible that Shutdown() is called first though, and + // OnUpdatePolicy won't be called if that happens. + virtual void RefreshPolicies() = 0; + + // Observers must detach themselves before the provider is deleted. + virtual void AddObserver(Observer* observer); + virtual void RemoveObserver(Observer* observer); + + // SchemaRegistry::Observer: + virtual void OnSchemaRegistryUpdated(bool has_new_schemas) OVERRIDE; + virtual void OnSchemaRegistryReady() OVERRIDE; + + protected: + // Subclasses must invoke this to update the policies currently served by + // this provider. UpdatePolicy() takes ownership of |policies|. + // The observers are notified after the policies are updated. + void UpdatePolicy(scoped_ptr<PolicyBundle> bundle); + + SchemaRegistry* schema_registry() const; + + const scoped_refptr<SchemaMap>& schema_map() const; + + private: + // The policies currently configured at this provider. + PolicyBundle policy_bundle_; + + // Whether Shutdown() has been invoked. + bool did_shutdown_; + + SchemaRegistry* schema_registry_; + + ObserverList<Observer, true> observer_list_; + + DISALLOW_COPY_AND_ASSIGN(ConfigurationPolicyProvider); +}; + +} // namespace policy + +#endif // COMPONENTS_POLICY_CORE_COMMON_CONFIGURATION_POLICY_PROVIDER_H_ diff --git a/components/policy/core/common/configuration_policy_provider_test.cc b/components/policy/core/common/configuration_policy_provider_test.cc new file mode 100644 index 0000000..8c5ef32 --- /dev/null +++ b/components/policy/core/common/configuration_policy_provider_test.cc @@ -0,0 +1,403 @@ +// 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 "components/policy/core/common/configuration_policy_provider_test.h" + +#include "base/bind.h" +#include "base/callback.h" +#include "base/message_loop/message_loop_proxy.h" +#include "base/values.h" +#include "components/policy/core/common/configuration_policy_provider.h" +#include "components/policy/core/common/external_data_fetcher.h" +#include "components/policy/core/common/mock_configuration_policy_provider.h" +#include "components/policy/core/common/policy_bundle.h" +#include "components/policy/core/common/policy_map.h" +#include "components/policy/core/common/policy_namespace.h" +#include "testing/gmock/include/gmock/gmock.h" + +using ::testing::Mock; +using ::testing::_; + +namespace policy { + +const char kTestChromeSchema[] = + "{" + " \"type\": \"object\"," + " \"properties\": {" + " \"StringPolicy\": { \"type\": \"string\" }," + " \"BooleanPolicy\": { \"type\": \"boolean\" }," + " \"IntegerPolicy\": { \"type\": \"integer\" }," + " \"StringListPolicy\": {" + " \"type\": \"array\"," + " \"items\": { \"type\": \"string\" }" + " }," + " \"DictionaryPolicy\": {" + " \"type\": \"object\"," + " \"properties\": {" + " \"bool\": { \"type\": \"boolean\" }," + " \"double\": { \"type\": \"number\" }," + " \"int\": { \"type\": \"integer\" }," + " \"string\": { \"type\": \"string\" }," + " \"array\": {" + " \"type\": \"array\"," + " \"items\": { \"type\": \"string\" }" + " }," + " \"dictionary\": {" + " \"type\": \"object\"," + " \"properties\": {" + " \"sub\": { \"type\": \"string\" }," + " \"sublist\": {" + " \"type\": \"array\"," + " \"items\": {" + " \"type\": \"object\"," + " \"properties\": {" + " \"aaa\": { \"type\": \"integer\" }," + " \"bbb\": { \"type\": \"integer\" }," + " \"ccc\": { \"type\": \"string\" }," + " \"ddd\": { \"type\": \"string\" }" + " }" + " }" + " }" + " }" + " }," + " \"list\": {" + " \"type\": \"array\"," + " \"items\": {" + " \"type\": \"object\"," + " \"properties\": {" + " \"subdictindex\": { \"type\": \"integer\" }," + " \"subdict\": {" + " \"type\": \"object\"," + " \"properties\": {" + " \"bool\": { \"type\": \"boolean\" }," + " \"double\": { \"type\": \"number\" }," + " \"int\": { \"type\": \"integer\" }," + " \"string\": { \"type\": \"string\" }" + " }" + " }" + " }" + " }" + " }," + " \"dict\": {" + " \"type\": \"object\"," + " \"properties\": {" + " \"bool\": { \"type\": \"boolean\" }," + " \"double\": { \"type\": \"number\" }," + " \"int\": { \"type\": \"integer\" }," + " \"string\": { \"type\": \"string\" }," + " \"list\": {" + " \"type\": \"array\"," + " \"items\": {" + " \"type\": \"object\"," + " \"properties\": {" + " \"subdictindex\": { \"type\": \"integer\" }," + " \"subdict\": {" + " \"type\": \"object\"," + " \"properties\": {" + " \"bool\": { \"type\": \"boolean\" }," + " \"double\": { \"type\": \"number\" }," + " \"int\": { \"type\": \"integer\" }," + " \"string\": { \"type\": \"string\" }" + " }" + " }" + " }" + " }" + " }" + " }" + " }" + " }" + " }" + " }" + "}"; + +namespace test_keys { + +const char kKeyString[] = "StringPolicy"; +const char kKeyBoolean[] = "BooleanPolicy"; +const char kKeyInteger[] = "IntegerPolicy"; +const char kKeyStringList[] = "StringListPolicy"; +const char kKeyDictionary[] = "DictionaryPolicy"; + +} // namespace test_keys + +PolicyTestBase::PolicyTestBase() {} + +PolicyTestBase::~PolicyTestBase() {} + +void PolicyTestBase::SetUp() { + std::string error; + chrome_schema_ = Schema::Parse(kTestChromeSchema, &error); + ASSERT_TRUE(chrome_schema_.valid()) << error; + schema_registry_.RegisterComponent(PolicyNamespace(POLICY_DOMAIN_CHROME, ""), + chrome_schema_); +} + +void PolicyTestBase::TearDown() { + loop_.RunUntilIdle(); +} + +PolicyProviderTestHarness::PolicyProviderTestHarness(PolicyLevel level, + PolicyScope scope) + : level_(level), scope_(scope) {} + +PolicyProviderTestHarness::~PolicyProviderTestHarness() {} + +PolicyLevel PolicyProviderTestHarness::policy_level() const { + return level_; +} + +PolicyScope PolicyProviderTestHarness::policy_scope() const { + return scope_; +} + +void PolicyProviderTestHarness::Install3rdPartyPolicy( + const base::DictionaryValue* policies) { + FAIL(); +} + +ConfigurationPolicyProviderTest::ConfigurationPolicyProviderTest() {} + +ConfigurationPolicyProviderTest::~ConfigurationPolicyProviderTest() {} + +void ConfigurationPolicyProviderTest::SetUp() { + PolicyTestBase::SetUp(); + + test_harness_.reset((*GetParam())()); + test_harness_->SetUp(); + + Schema extension_schema = + chrome_schema_.GetKnownProperty(test_keys::kKeyDictionary); + ASSERT_TRUE(extension_schema.valid()); + schema_registry_.RegisterComponent( + PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), + extension_schema); + schema_registry_.RegisterComponent( + PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, + "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"), + extension_schema); + schema_registry_.RegisterComponent( + PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, + "cccccccccccccccccccccccccccccccc"), + extension_schema); + + provider_.reset(test_harness_->CreateProvider(&schema_registry_, + loop_.message_loop_proxy())); + provider_->Init(&schema_registry_); + // Some providers do a reload on init. Make sure any notifications generated + // are fired now. + loop_.RunUntilIdle(); + + const PolicyBundle kEmptyBundle; + EXPECT_TRUE(provider_->policies().Equals(kEmptyBundle)); +} + +void ConfigurationPolicyProviderTest::TearDown() { + // Give providers the chance to clean up after themselves on the file thread. + provider_->Shutdown(); + provider_.reset(); + + PolicyTestBase::TearDown(); +} + +void ConfigurationPolicyProviderTest::CheckValue( + const char* policy_name, + const base::Value& expected_value, + base::Closure install_value) { + // Install the value, reload policy and check the provider for the value. + install_value.Run(); + provider_->RefreshPolicies(); + loop_.RunUntilIdle(); + PolicyBundle expected_bundle; + expected_bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())) + .Set(policy_name, + test_harness_->policy_level(), + test_harness_->policy_scope(), + expected_value.DeepCopy(), + NULL); + EXPECT_TRUE(provider_->policies().Equals(expected_bundle)); + // TODO(joaodasilva): set the policy in the POLICY_DOMAIN_EXTENSIONS too, + // and extend the |expected_bundle|, once all providers are ready. +} + +TEST_P(ConfigurationPolicyProviderTest, Empty) { + provider_->RefreshPolicies(); + loop_.RunUntilIdle(); + const PolicyBundle kEmptyBundle; + EXPECT_TRUE(provider_->policies().Equals(kEmptyBundle)); +} + +TEST_P(ConfigurationPolicyProviderTest, StringValue) { + const char kTestString[] = "string_value"; + base::StringValue expected_value(kTestString); + CheckValue(test_keys::kKeyString, + expected_value, + base::Bind(&PolicyProviderTestHarness::InstallStringPolicy, + base::Unretained(test_harness_.get()), + test_keys::kKeyString, + kTestString)); +} + +TEST_P(ConfigurationPolicyProviderTest, BooleanValue) { + base::FundamentalValue expected_value(true); + CheckValue(test_keys::kKeyBoolean, + expected_value, + base::Bind(&PolicyProviderTestHarness::InstallBooleanPolicy, + base::Unretained(test_harness_.get()), + test_keys::kKeyBoolean, + true)); +} + +TEST_P(ConfigurationPolicyProviderTest, IntegerValue) { + base::FundamentalValue expected_value(42); + CheckValue(test_keys::kKeyInteger, + expected_value, + base::Bind(&PolicyProviderTestHarness::InstallIntegerPolicy, + base::Unretained(test_harness_.get()), + test_keys::kKeyInteger, + 42)); +} + +TEST_P(ConfigurationPolicyProviderTest, StringListValue) { + base::ListValue expected_value; + expected_value.Set(0U, base::Value::CreateStringValue("first")); + expected_value.Set(1U, base::Value::CreateStringValue("second")); + CheckValue(test_keys::kKeyStringList, + expected_value, + base::Bind(&PolicyProviderTestHarness::InstallStringListPolicy, + base::Unretained(test_harness_.get()), + test_keys::kKeyStringList, + &expected_value)); +} + +TEST_P(ConfigurationPolicyProviderTest, DictionaryValue) { + base::DictionaryValue expected_value; + expected_value.SetBoolean("bool", true); + expected_value.SetDouble("double", 123.456); + expected_value.SetInteger("int", 123); + expected_value.SetString("string", "omg"); + + base::ListValue* list = new base::ListValue(); + list->Set(0U, base::Value::CreateStringValue("first")); + list->Set(1U, base::Value::CreateStringValue("second")); + expected_value.Set("array", list); + + base::DictionaryValue* dict = new base::DictionaryValue(); + dict->SetString("sub", "value"); + list = new base::ListValue(); + base::DictionaryValue* sub = new base::DictionaryValue(); + sub->SetInteger("aaa", 111); + sub->SetInteger("bbb", 222); + list->Append(sub); + sub = new base::DictionaryValue(); + sub->SetString("ccc", "333"); + sub->SetString("ddd", "444"); + list->Append(sub); + dict->Set("sublist", list); + expected_value.Set("dictionary", dict); + + CheckValue(test_keys::kKeyDictionary, + expected_value, + base::Bind(&PolicyProviderTestHarness::InstallDictionaryPolicy, + base::Unretained(test_harness_.get()), + test_keys::kKeyDictionary, + &expected_value)); +} + +TEST_P(ConfigurationPolicyProviderTest, RefreshPolicies) { + PolicyBundle bundle; + EXPECT_TRUE(provider_->policies().Equals(bundle)); + + // OnUpdatePolicy is called even when there are no changes. + MockConfigurationPolicyObserver observer; + provider_->AddObserver(&observer); + EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(1); + provider_->RefreshPolicies(); + loop_.RunUntilIdle(); + Mock::VerifyAndClearExpectations(&observer); + + EXPECT_TRUE(provider_->policies().Equals(bundle)); + + // OnUpdatePolicy is called when there are changes. + test_harness_->InstallStringPolicy(test_keys::kKeyString, "value"); + EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(1); + provider_->RefreshPolicies(); + loop_.RunUntilIdle(); + Mock::VerifyAndClearExpectations(&observer); + + bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())) + .Set(test_keys::kKeyString, + test_harness_->policy_level(), + test_harness_->policy_scope(), + base::Value::CreateStringValue("value"), + NULL); + EXPECT_TRUE(provider_->policies().Equals(bundle)); + provider_->RemoveObserver(&observer); +} + +Configuration3rdPartyPolicyProviderTest:: + Configuration3rdPartyPolicyProviderTest() {} + +Configuration3rdPartyPolicyProviderTest:: + ~Configuration3rdPartyPolicyProviderTest() {} + +TEST_P(Configuration3rdPartyPolicyProviderTest, Load3rdParty) { + base::DictionaryValue policy_dict; + policy_dict.SetBoolean("bool", true); + policy_dict.SetDouble("double", 123.456); + policy_dict.SetInteger("int", 789); + policy_dict.SetString("string", "string value"); + + base::ListValue* list = new base::ListValue(); + for (int i = 0; i < 2; ++i) { + base::DictionaryValue* dict = new base::DictionaryValue(); + dict->SetInteger("subdictindex", i); + dict->Set("subdict", policy_dict.DeepCopy()); + list->Append(dict); + } + policy_dict.Set("list", list); + policy_dict.Set("dict", policy_dict.DeepCopy()); + + // Install these policies as a Chrome policy. + test_harness_->InstallDictionaryPolicy(test_keys::kKeyDictionary, + &policy_dict); + // Install them as 3rd party policies too. + base::DictionaryValue policy_3rdparty; + policy_3rdparty.Set("extensions.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + policy_dict.DeepCopy()); + policy_3rdparty.Set("extensions.bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + policy_dict.DeepCopy()); + // Install invalid 3rd party policies that shouldn't be loaded. These also + // help detecting memory leaks in the code paths that detect invalid input. + policy_3rdparty.Set("invalid-domain.component", policy_dict.DeepCopy()); + policy_3rdparty.Set("extensions.cccccccccccccccccccccccccccccccc", + base::Value::CreateStringValue("invalid-value")); + test_harness_->Install3rdPartyPolicy(&policy_3rdparty); + + provider_->RefreshPolicies(); + loop_.RunUntilIdle(); + + PolicyMap expected_policy; + expected_policy.Set(test_keys::kKeyDictionary, + test_harness_->policy_level(), + test_harness_->policy_scope(), + policy_dict.DeepCopy(), + NULL); + PolicyBundle expected_bundle; + expected_bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())) + .CopyFrom(expected_policy); + expected_policy.Clear(); + expected_policy.LoadFrom(&policy_dict, + test_harness_->policy_level(), + test_harness_->policy_scope()); + expected_bundle.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")) + .CopyFrom(expected_policy); + expected_bundle.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, + "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb")) + .CopyFrom(expected_policy); + EXPECT_TRUE(provider_->policies().Equals(expected_bundle)); +} + +} // namespace policy diff --git a/components/policy/core/common/configuration_policy_provider_test.h b/components/policy/core/common/configuration_policy_provider_test.h new file mode 100644 index 0000000..b0dc6d4 --- /dev/null +++ b/components/policy/core/common/configuration_policy_provider_test.h @@ -0,0 +1,152 @@ +// 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. + +#ifndef COMPONENTS_POLICY_CORE_COMMON_CONFIGURATION_POLICY_PROVIDER_TEST_H_ +#define COMPONENTS_POLICY_CORE_COMMON_CONFIGURATION_POLICY_PROVIDER_TEST_H_ + +#include <string> + +#include "base/basictypes.h" +#include "base/callback_forward.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop.h" +#include "components/policy/core/common/policy_types.h" +#include "components/policy/core/common/schema.h" +#include "components/policy/core/common/schema_registry.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace base { +class DictionaryValue; +class ListValue; +class SequencedTaskRunner; +class Value; +} + +namespace policy { + +class ConfigurationPolicyProvider; + +namespace test_keys { + +extern const char kKeyString[]; +extern const char kKeyBoolean[]; +extern const char kKeyInteger[]; +extern const char kKeyStringList[]; +extern const char kKeyDictionary[]; + +} // namespace test_keys + +class PolicyTestBase : public testing::Test { + public: + PolicyTestBase(); + virtual ~PolicyTestBase(); + + // testing::Test: + virtual void SetUp() OVERRIDE; + virtual void TearDown() OVERRIDE; + + protected: + Schema chrome_schema_; + SchemaRegistry schema_registry_; + + // Create an actual IO loop (needed by FilePathWatcher). + base::MessageLoopForIO loop_; + + private: + DISALLOW_COPY_AND_ASSIGN(PolicyTestBase); +}; + +// An interface for creating a test policy provider and creating a policy +// provider instance for testing. Used as the parameter to the abstract +// ConfigurationPolicyProviderTest below. +class PolicyProviderTestHarness { + public: + // |level| and |scope| are the level and scope of the policies returned by + // the providers from CreateProvider(). + PolicyProviderTestHarness(PolicyLevel level, PolicyScope scope); + virtual ~PolicyProviderTestHarness(); + + // Actions to run at gtest SetUp() time. + virtual void SetUp() = 0; + + // Create a new policy provider. + virtual ConfigurationPolicyProvider* CreateProvider( + SchemaRegistry* registry, + scoped_refptr<base::SequencedTaskRunner> task_runner) = 0; + + // Returns the policy level and scope set by the policy provider. + PolicyLevel policy_level() const; + PolicyScope policy_scope() const; + + // Helpers to configure the environment the policy provider reads from. + virtual void InstallEmptyPolicy() = 0; + virtual void InstallStringPolicy(const std::string& policy_name, + const std::string& policy_value) = 0; + virtual void InstallIntegerPolicy(const std::string& policy_name, + int policy_value) = 0; + virtual void InstallBooleanPolicy(const std::string& policy_name, + bool policy_value) = 0; + virtual void InstallStringListPolicy(const std::string& policy_name, + const base::ListValue* policy_value) = 0; + virtual void InstallDictionaryPolicy( + const std::string& policy_name, + const base::DictionaryValue* policy_value) = 0; + + // Not every provider supports installing 3rd party policy. Those who do + // should override this method; the default just makes the test fail. + virtual void Install3rdPartyPolicy(const base::DictionaryValue* policies); + + private: + PolicyLevel level_; + PolicyScope scope_; + + DISALLOW_COPY_AND_ASSIGN(PolicyProviderTestHarness); +}; + +// A factory method for creating a test harness. +typedef PolicyProviderTestHarness* (*CreatePolicyProviderTestHarness)(); + +// Abstract policy provider test. This is meant to be instantiated for each +// policy provider implementation, passing in a suitable harness factory +// function as the test parameter. +class ConfigurationPolicyProviderTest + : public PolicyTestBase, + public testing::WithParamInterface<CreatePolicyProviderTestHarness> { + protected: + ConfigurationPolicyProviderTest(); + virtual ~ConfigurationPolicyProviderTest(); + + virtual void SetUp() OVERRIDE; + virtual void TearDown() OVERRIDE; + + // Installs a valid policy and checks whether the provider returns the + // |expected_value|. + void CheckValue(const char* policy_name, + const base::Value& expected_value, + base::Closure install_value); + + scoped_ptr<PolicyProviderTestHarness> test_harness_; + scoped_ptr<ConfigurationPolicyProvider> provider_; + + private: + DISALLOW_COPY_AND_ASSIGN(ConfigurationPolicyProviderTest); +}; + +// An extension of ConfigurationPolicyProviderTest that also tests loading of +// 3rd party policy. Policy provider implementations that support loading of +// 3rd party policy should also instantiate these tests. +class Configuration3rdPartyPolicyProviderTest + : public ConfigurationPolicyProviderTest { + protected: + Configuration3rdPartyPolicyProviderTest(); + virtual ~Configuration3rdPartyPolicyProviderTest(); + + private: + DISALLOW_COPY_AND_ASSIGN(Configuration3rdPartyPolicyProviderTest); +}; + +} // namespace policy + +#endif // COMPONENTS_POLICY_CORE_COMMON_CONFIGURATION_POLICY_PROVIDER_TEST_H_ diff --git a/components/policy/core/common/mock_configuration_policy_provider.cc b/components/policy/core/common/mock_configuration_policy_provider.cc new file mode 100644 index 0000000..387b8d4 --- /dev/null +++ b/components/policy/core/common/mock_configuration_policy_provider.cc @@ -0,0 +1,47 @@ +// 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 "components/policy/core/common/mock_configuration_policy_provider.h" + +#include <string> + +#include "base/memory/scoped_ptr.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "components/policy/core/common/policy_bundle.h" + +using testing::Invoke; + +namespace policy { + +MockConfigurationPolicyProvider::MockConfigurationPolicyProvider() {} + +MockConfigurationPolicyProvider::~MockConfigurationPolicyProvider() {} + +void MockConfigurationPolicyProvider::UpdateChromePolicy( + const PolicyMap& policy) { + scoped_ptr<PolicyBundle> bundle(new PolicyBundle()); + bundle->Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())) + .CopyFrom(policy); + UpdatePolicy(bundle.Pass()); + if (base::MessageLoop::current()) + base::RunLoop().RunUntilIdle(); +} + +void MockConfigurationPolicyProvider::SetAutoRefresh() { + EXPECT_CALL(*this, RefreshPolicies()).WillRepeatedly( + Invoke(this, &MockConfigurationPolicyProvider::RefreshWithSamePolicies)); +} + +void MockConfigurationPolicyProvider::RefreshWithSamePolicies() { + scoped_ptr<PolicyBundle> bundle(new PolicyBundle); + bundle->CopyFrom(policies()); + UpdatePolicy(bundle.Pass()); +} + +MockConfigurationPolicyObserver::MockConfigurationPolicyObserver() {} + +MockConfigurationPolicyObserver::~MockConfigurationPolicyObserver() {} + +} // namespace policy diff --git a/components/policy/core/common/mock_configuration_policy_provider.h b/components/policy/core/common/mock_configuration_policy_provider.h new file mode 100644 index 0000000..d891140 --- /dev/null +++ b/components/policy/core/common/mock_configuration_policy_provider.h @@ -0,0 +1,66 @@ +// 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. + +#ifndef COMPONENTS_POLICY_CORE_COMMON_MOCK_CONFIGURATION_POLICY_PROVIDER_H_ +#define COMPONENTS_POLICY_CORE_COMMON_MOCK_CONFIGURATION_POLICY_PROVIDER_H_ + +#include "base/basictypes.h" +#include "components/policy/core/common/configuration_policy_provider.h" +#include "components/policy/core/common/policy_map.h" +#include "components/policy/core/common/schema_registry.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace policy { + +// Mock ConfigurationPolicyProvider implementation that supplies canned +// values for polices. +// TODO(joaodasilva, mnissler): introduce an implementation that non-policy +// code can use that doesn't require the usual boilerplate. +// http://crbug.com/242087 +class MockConfigurationPolicyProvider : public ConfigurationPolicyProvider { + public: + MockConfigurationPolicyProvider(); + virtual ~MockConfigurationPolicyProvider(); + + MOCK_CONST_METHOD1(IsInitializationComplete, bool(PolicyDomain domain)); + MOCK_METHOD0(RefreshPolicies, void()); + + // Make public for tests. + using ConfigurationPolicyProvider::UpdatePolicy; + + // Utility method that invokes UpdatePolicy() with a PolicyBundle that maps + // the Chrome namespace to a copy of |policy|. + void UpdateChromePolicy(const PolicyMap& policy); + + // Convenience method so that tests don't need to create a registry to create + // this mock. + using ConfigurationPolicyProvider::Init; + void Init() { + ConfigurationPolicyProvider::Init(®istry_); + } + + // Convenience method that installs an expectation on RefreshPolicies that + // just notifies the observers and serves the same policies. + void SetAutoRefresh(); + + private: + void RefreshWithSamePolicies(); + + SchemaRegistry registry_; + + DISALLOW_COPY_AND_ASSIGN(MockConfigurationPolicyProvider); +}; + +class MockConfigurationPolicyObserver + : public ConfigurationPolicyProvider::Observer { + public: + MockConfigurationPolicyObserver(); + virtual ~MockConfigurationPolicyObserver(); + + MOCK_METHOD1(OnUpdatePolicy, void(ConfigurationPolicyProvider*)); +}; + +} // namespace policy + +#endif // COMPONENTS_POLICY_CORE_COMMON_MOCK_CONFIGURATION_POLICY_PROVIDER_H_ |