| // Copyright (c) 2012 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 "chrome/browser/policy/policy_loader_win.h" |
| |
| #include <windows.h> |
| |
| #include "base/json/json_writer.h" |
| #include "base/string16.h" |
| #include "base/string_number_conversions.h" |
| #include "base/string_util.h" |
| #include "base/utf_string_conversions.h" |
| #include "base/win/registry.h" |
| #include "chrome/browser/policy/async_policy_provider.h" |
| #include "chrome/browser/policy/configuration_policy_provider_test.h" |
| #include "chrome/browser/policy/policy_bundle.h" |
| #include "chrome/browser/policy/policy_map.h" |
| #include "chrome/common/json_schema_constants.h" |
| #include "policy/policy_constants.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace schema = json_schema_constants; |
| |
| using base::win::RegKey; |
| using namespace policy::registry_constants; |
| |
| namespace policy { |
| |
| namespace { |
| |
| const wchar_t kUnitTestRegistrySubKey[] = L"SOFTWARE\\Chromium Unit Tests"; |
| const wchar_t kUnitTestMachineOverrideSubKey[] = |
| L"SOFTWARE\\Chromium Unit Tests\\HKLM Override"; |
| const wchar_t kUnitTestUserOverrideSubKey[] = |
| L"SOFTWARE\\Chromium Unit Tests\\HKCU Override"; |
| |
| // Installs |value| in the given registry |path| and |hive|, under the key |
| // |name|. Returns false on errors. |
| // Some of the possible Value types are stored after a conversion (e.g. doubles |
| // are stored as strings), and can only be retrieved if a corresponding schema |
| // is written. |
| bool InstallValue(const base::Value& value, |
| HKEY hive, |
| const string16& path, |
| const string16& name) { |
| // KEY_ALL_ACCESS causes the ctor to create the key if it does not exist yet. |
| RegKey key(hive, path.c_str(), KEY_ALL_ACCESS); |
| switch (value.GetType()) { |
| case base::Value::TYPE_NULL: |
| return key.WriteValue(name.c_str(), L"") == ERROR_SUCCESS; |
| |
| case base::Value::TYPE_BOOLEAN: { |
| bool bool_value; |
| if (!value.GetAsBoolean(&bool_value)) |
| return false; |
| return key.WriteValue(name.c_str(), bool_value ? 1 : 0) == ERROR_SUCCESS; |
| } |
| |
| case base::Value::TYPE_INTEGER: { |
| int int_value; |
| if (!value.GetAsInteger(&int_value)) |
| return false; |
| return key.WriteValue(name.c_str(), int_value) == ERROR_SUCCESS; |
| } |
| |
| case base::Value::TYPE_DOUBLE: { |
| double double_value; |
| if (!value.GetAsDouble(&double_value)) |
| return false; |
| string16 str_value = UTF8ToUTF16(base::DoubleToString(double_value)); |
| return key.WriteValue(name.c_str(), str_value.c_str()) == ERROR_SUCCESS; |
| } |
| |
| case base::Value::TYPE_STRING: { |
| string16 str_value; |
| if (!value.GetAsString(&str_value)) |
| return false; |
| return key.WriteValue(name.c_str(), str_value.c_str()) == ERROR_SUCCESS; |
| } |
| |
| case base::Value::TYPE_DICTIONARY: { |
| const base::DictionaryValue* sub_dict = NULL; |
| if (!value.GetAsDictionary(&sub_dict)) |
| return false; |
| for (base::DictionaryValue::Iterator it(*sub_dict); |
| it.HasNext(); it.Advance()) { |
| if (!InstallValue(it.value(), hive, path + kPathSep + name, |
| UTF8ToUTF16(it.key()))) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| case base::Value::TYPE_LIST: { |
| const base::ListValue* list = NULL; |
| if (!value.GetAsList(&list)) |
| return false; |
| for (size_t i = 0; i < list->GetSize(); ++i) { |
| const base::Value* item; |
| if (!list->Get(i, &item)) |
| return false; |
| if (!InstallValue(*item, hive, path + kPathSep + name, |
| base::UintToString16(i + 1))) { |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| case base::Value::TYPE_BINARY: |
| return false; |
| } |
| NOTREACHED(); |
| return false; |
| } |
| |
| // Builds a JSON schema that represents the types contained in |value|. |
| // Ownership is transferred to the caller. |
| base::DictionaryValue* BuildSchema(const base::Value& value) { |
| base::DictionaryValue* schema = new base::DictionaryValue(); |
| switch (value.GetType()) { |
| case base::Value::TYPE_NULL: |
| schema->SetString(schema::kType, "null"); |
| break; |
| case base::Value::TYPE_BOOLEAN: |
| schema->SetString(schema::kType, "boolean"); |
| break; |
| case base::Value::TYPE_INTEGER: |
| schema->SetString(schema::kType, "integer"); |
| break; |
| case base::Value::TYPE_DOUBLE: |
| schema->SetString(schema::kType, "number"); |
| break; |
| case base::Value::TYPE_STRING: |
| schema->SetString(schema::kType, "string"); |
| break; |
| |
| case base::Value::TYPE_LIST: { |
| // Assumes every list element has the same type. |
| const base::ListValue* list = NULL; |
| if (value.GetAsList(&list) && !list->empty()) { |
| schema->SetString(schema::kType, "array"); |
| schema->Set(schema::kItems, BuildSchema(**list->begin())); |
| } |
| break; |
| } |
| |
| case base::Value::TYPE_DICTIONARY: { |
| const base::DictionaryValue* dict = NULL; |
| if (value.GetAsDictionary(&dict)) { |
| base::DictionaryValue* properties = new base::DictionaryValue(); |
| for (base::DictionaryValue::Iterator it(*dict); |
| it.HasNext(); it.Advance()) { |
| properties->Set(it.key(), BuildSchema(it.value())); |
| } |
| schema->SetString(schema::kType, "object"); |
| schema->Set(schema::kProperties, properties); |
| } |
| break; |
| } |
| |
| case base::Value::TYPE_BINARY: |
| break; |
| } |
| return schema; |
| } |
| |
| // Writes a JSON |schema| at the registry entry |name| at |path| |
| // in the given |hive|. Returns false on failure. |
| bool WriteSchema(const base::DictionaryValue& schema, |
| HKEY hive, |
| const string16& path, |
| const string16& name) { |
| std::string encoded; |
| base::JSONWriter::Write(&schema, &encoded); |
| if (encoded.empty()) |
| return false; |
| string16 encoded16 = UTF8ToUTF16(encoded); |
| // KEY_ALL_ACCESS causes the ctor to create the key if it does not exist yet. |
| RegKey key(hive, path.c_str(), KEY_ALL_ACCESS); |
| return key.WriteValue(name.c_str(), encoded16.c_str()) == ERROR_SUCCESS; |
| } |
| |
| // Builds a JSON schema for |value| and writes it at the registry entry |name| |
| // at |path| in the given |hive|. Returns false on failure. |
| bool InstallSchema(const base::Value& value, |
| HKEY hive, |
| const string16& path, |
| const string16& name) { |
| scoped_ptr<base::DictionaryValue> schema_dict(BuildSchema(value)); |
| return WriteSchema(*schema_dict, hive, path, name); |
| } |
| |
| // This class provides sandboxing and mocking for the parts of the Windows |
| // Registry implementing Group Policy. It prepares two temporary sandbox keys |
| // in |kUnitTestRegistrySubKey|, one for HKLM and one for HKCU. A test's calls |
| // to the registry are redirected by Windows to these sandboxes, allowing the |
| // tests to manipulate and access policy as if it were active, but without |
| // actually changing the parts of the Registry that are managed by Group |
| // Policy. |
| class ScopedGroupPolicyRegistrySandbox { |
| public: |
| ScopedGroupPolicyRegistrySandbox(); |
| ~ScopedGroupPolicyRegistrySandbox(); |
| |
| private: |
| void ActivateOverrides(); |
| void RemoveOverrides(); |
| |
| // Deletes the sandbox keys. |
| void DeleteKeys(); |
| |
| // Keys are created for the lifetime of a test to contain |
| // the sandboxed HKCU and HKLM hives, respectively. |
| RegKey temp_hkcu_hive_key_; |
| RegKey temp_hklm_hive_key_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ScopedGroupPolicyRegistrySandbox); |
| }; |
| |
| class TestHarness : public PolicyProviderTestHarness { |
| public: |
| explicit TestHarness(HKEY hive, PolicyScope scope); |
| virtual ~TestHarness(); |
| |
| virtual void SetUp() OVERRIDE; |
| |
| virtual ConfigurationPolicyProvider* CreateProvider( |
| const PolicyDefinitionList* policy_definition_list) OVERRIDE; |
| |
| virtual void InstallEmptyPolicy() OVERRIDE; |
| virtual void InstallStringPolicy(const std::string& policy_name, |
| const std::string& policy_value) OVERRIDE; |
| virtual void InstallIntegerPolicy(const std::string& policy_name, |
| int policy_value) OVERRIDE; |
| virtual void InstallBooleanPolicy(const std::string& policy_name, |
| bool policy_value) OVERRIDE; |
| virtual void InstallStringListPolicy( |
| const std::string& policy_name, |
| const base::ListValue* policy_value) OVERRIDE; |
| virtual void InstallDictionaryPolicy( |
| const std::string& policy_name, |
| const base::DictionaryValue* policy_value) OVERRIDE; |
| virtual void Install3rdPartyPolicy( |
| const base::DictionaryValue* policies) OVERRIDE; |
| |
| // Creates a harness instance that will install policy in HKCU or HKLM, |
| // respectively. |
| static PolicyProviderTestHarness* CreateHKCU(); |
| static PolicyProviderTestHarness* CreateHKLM(); |
| |
| private: |
| HKEY hive_; |
| |
| ScopedGroupPolicyRegistrySandbox registry_sandbox_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TestHarness); |
| }; |
| |
| ScopedGroupPolicyRegistrySandbox::ScopedGroupPolicyRegistrySandbox() { |
| // Cleanup any remnants of previous tests. |
| DeleteKeys(); |
| |
| // Create the subkeys to hold the overridden HKLM and HKCU |
| // policy settings. |
| temp_hklm_hive_key_.Create(HKEY_CURRENT_USER, |
| kUnitTestMachineOverrideSubKey, |
| KEY_ALL_ACCESS); |
| temp_hkcu_hive_key_.Create(HKEY_CURRENT_USER, |
| kUnitTestUserOverrideSubKey, |
| KEY_ALL_ACCESS); |
| |
| ActivateOverrides(); |
| } |
| |
| ScopedGroupPolicyRegistrySandbox::~ScopedGroupPolicyRegistrySandbox() { |
| RemoveOverrides(); |
| DeleteKeys(); |
| } |
| |
| void ScopedGroupPolicyRegistrySandbox::ActivateOverrides() { |
| ASSERT_HRESULT_SUCCEEDED(RegOverridePredefKey(HKEY_LOCAL_MACHINE, |
| temp_hklm_hive_key_.Handle())); |
| ASSERT_HRESULT_SUCCEEDED(RegOverridePredefKey(HKEY_CURRENT_USER, |
| temp_hkcu_hive_key_.Handle())); |
| } |
| |
| void ScopedGroupPolicyRegistrySandbox::RemoveOverrides() { |
| ASSERT_HRESULT_SUCCEEDED(RegOverridePredefKey(HKEY_LOCAL_MACHINE, 0)); |
| ASSERT_HRESULT_SUCCEEDED(RegOverridePredefKey(HKEY_CURRENT_USER, 0)); |
| } |
| |
| void ScopedGroupPolicyRegistrySandbox::DeleteKeys() { |
| RegKey key(HKEY_CURRENT_USER, kUnitTestRegistrySubKey, KEY_ALL_ACCESS); |
| key.DeleteKey(L""); |
| } |
| |
| TestHarness::TestHarness(HKEY hive, PolicyScope scope) |
| : PolicyProviderTestHarness(POLICY_LEVEL_MANDATORY, scope), hive_(hive) {} |
| |
| TestHarness::~TestHarness() {} |
| |
| void TestHarness::SetUp() {} |
| |
| ConfigurationPolicyProvider* TestHarness::CreateProvider( |
| const PolicyDefinitionList* policy_list) { |
| scoped_ptr<AsyncPolicyLoader> loader(new PolicyLoaderWin(policy_list)); |
| return new AsyncPolicyProvider(loader.Pass()); |
| } |
| |
| void TestHarness::InstallEmptyPolicy() {} |
| |
| void TestHarness::InstallStringPolicy(const std::string& policy_name, |
| const std::string& policy_value) { |
| RegKey key(hive_, kRegistryMandatorySubKey, KEY_ALL_ACCESS); |
| key.WriteValue(UTF8ToUTF16(policy_name).c_str(), |
| UTF8ToUTF16(policy_value).c_str()); |
| } |
| |
| void TestHarness::InstallIntegerPolicy(const std::string& policy_name, |
| int policy_value) { |
| RegKey key(hive_, kRegistryMandatorySubKey, KEY_ALL_ACCESS); |
| key.WriteValue(UTF8ToUTF16(policy_name).c_str(), |
| static_cast<DWORD>(policy_value)); |
| } |
| |
| void TestHarness::InstallBooleanPolicy(const std::string& policy_name, |
| bool policy_value) { |
| RegKey key(hive_, kRegistryMandatorySubKey, KEY_ALL_ACCESS); |
| key.WriteValue(UTF8ToUTF16(policy_name).c_str(), |
| static_cast<DWORD>(policy_value)); |
| } |
| |
| void TestHarness::InstallStringListPolicy(const std::string& policy_name, |
| const base::ListValue* policy_value) { |
| RegKey key(hive_, |
| (string16(kRegistryMandatorySubKey) + ASCIIToUTF16("\\") + |
| UTF8ToUTF16(policy_name)).c_str(), |
| KEY_ALL_ACCESS); |
| int index = 1; |
| for (base::ListValue::const_iterator element(policy_value->begin()); |
| element != policy_value->end(); |
| ++element) { |
| std::string element_value; |
| if (!(*element)->GetAsString(&element_value)) |
| continue; |
| std::string name(base::IntToString(index++)); |
| key.WriteValue(UTF8ToUTF16(name).c_str(), |
| UTF8ToUTF16(element_value).c_str()); |
| } |
| } |
| |
| void TestHarness::InstallDictionaryPolicy( |
| const std::string& policy_name, |
| const base::DictionaryValue* policy_value) { |
| std::string json; |
| base::JSONWriter::Write(policy_value, &json); |
| RegKey key(hive_, kRegistryMandatorySubKey, KEY_ALL_ACCESS); |
| key.WriteValue(UTF8ToUTF16(policy_name).c_str(), |
| UTF8ToUTF16(json).c_str()); |
| } |
| |
| void TestHarness::Install3rdPartyPolicy(const base::DictionaryValue* policies) { |
| // The first level entries are domains, and the second level entries map |
| // components to their policy. |
| const string16 kPathPrefix = string16(kRegistryMandatorySubKey) + kPathSep + |
| kThirdParty + kPathSep; |
| for (base::DictionaryValue::Iterator domain(*policies); |
| domain.HasNext(); domain.Advance()) { |
| const base::DictionaryValue* components = NULL; |
| if (!domain.value().GetAsDictionary(&components)) { |
| ADD_FAILURE(); |
| continue; |
| } |
| for (base::DictionaryValue::Iterator component(*components); |
| component.HasNext(); component.Advance()) { |
| const string16 path = string16(kRegistryMandatorySubKey) + kPathSep + |
| kThirdParty + kPathSep + |
| UTF8ToUTF16(domain.key()) + kPathSep + |
| UTF8ToUTF16(component.key()); |
| InstallValue(component.value(), hive_, path, kMandatory); |
| EXPECT_TRUE(InstallSchema(component.value(), hive_, path, kSchema)); |
| } |
| } |
| } |
| |
| // static |
| PolicyProviderTestHarness* TestHarness::CreateHKCU() { |
| return new TestHarness(HKEY_CURRENT_USER, POLICY_SCOPE_USER); |
| } |
| |
| // static |
| PolicyProviderTestHarness* TestHarness::CreateHKLM() { |
| return new TestHarness(HKEY_LOCAL_MACHINE, POLICY_SCOPE_MACHINE); |
| } |
| |
| } // namespace |
| |
| // Instantiate abstract test case for basic policy reading tests. |
| INSTANTIATE_TEST_CASE_P( |
| PolicyProviderWinTest, |
| ConfigurationPolicyProviderTest, |
| testing::Values(TestHarness::CreateHKCU, TestHarness::CreateHKLM)); |
| |
| // Instantiate abstract test case for 3rd party policy reading tests. |
| INSTANTIATE_TEST_CASE_P( |
| ThirdPartyPolicyProviderWinTest, |
| Configuration3rdPartyPolicyProviderTest, |
| testing::Values(TestHarness::CreateHKCU, TestHarness::CreateHKLM)); |
| |
| // Test cases for windows policy provider specific functionality. |
| class PolicyLoaderWinTest : public PolicyTestBase { |
| protected: |
| PolicyLoaderWinTest() {} |
| virtual ~PolicyLoaderWinTest() {} |
| |
| bool Matches(const PolicyBundle& expected) { |
| PolicyLoaderWin loader(&test_policy_definitions::kList); |
| scoped_ptr<PolicyBundle> loaded(loader.Load()); |
| return loaded->Equals(expected); |
| } |
| |
| ScopedGroupPolicyRegistrySandbox registry_sandbox_; |
| }; |
| |
| TEST_F(PolicyLoaderWinTest, HKLMOverHKCU) { |
| RegKey hklm_key(HKEY_LOCAL_MACHINE, kRegistryMandatorySubKey, KEY_ALL_ACCESS); |
| hklm_key.WriteValue(UTF8ToUTF16(test_policy_definitions::kKeyString).c_str(), |
| UTF8ToUTF16("hklm").c_str()); |
| RegKey hkcu_key(HKEY_CURRENT_USER, kRegistryMandatorySubKey, KEY_ALL_ACCESS); |
| hkcu_key.WriteValue(UTF8ToUTF16(test_policy_definitions::kKeyString).c_str(), |
| UTF8ToUTF16("hkcu").c_str()); |
| |
| PolicyBundle expected; |
| expected.Get(POLICY_DOMAIN_CHROME, "") |
| .Set(test_policy_definitions::kKeyString, |
| POLICY_LEVEL_MANDATORY, |
| POLICY_SCOPE_MACHINE, |
| base::Value::CreateStringValue("hklm")); |
| EXPECT_TRUE(Matches(expected)); |
| } |
| |
| TEST_F(PolicyLoaderWinTest, Load3rdPartyWithoutSchema) { |
| base::DictionaryValue dict; |
| dict.SetString("str", "string value"); |
| dict.SetInteger("int", 123); |
| dict.Set("subdict", dict.DeepCopy()); |
| dict.Set("subsubdict", dict.DeepCopy()); |
| dict.Set("subsubsubdict", dict.DeepCopy()); |
| |
| base::DictionaryValue policy_dict; |
| policy_dict.Set("extensions.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.policy", |
| dict.DeepCopy()); |
| policy_dict.Set("extensions.bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.policy", |
| dict.DeepCopy()); |
| EXPECT_TRUE(InstallValue(policy_dict, HKEY_LOCAL_MACHINE, |
| kRegistryMandatorySubKey, kThirdParty)); |
| |
| PolicyBundle expected; |
| expected.Get(POLICY_DOMAIN_EXTENSIONS, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") |
| .LoadFrom(&dict, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE); |
| expected.Get(POLICY_DOMAIN_EXTENSIONS, "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb") |
| .LoadFrom(&dict, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE); |
| EXPECT_TRUE(Matches(expected)); |
| } |
| |
| TEST_F(PolicyLoaderWinTest, Merge3rdPartyPolicies) { |
| // Policy for the same extension will be provided at the 4 level/scope |
| // combinations, to verify that they overlap as expected. |
| |
| const string16 kPathSuffix = |
| kRegistryMandatorySubKey + ASCIIToUTF16("\\3rdparty\\extensions\\merge"); |
| |
| const char kUserMandatory[] = "user-mandatory"; |
| const char kUserRecommended[] = "user-recommended"; |
| const char kMachineMandatory[] = "machine-mandatory"; |
| const char kMachineRecommended[] = "machine-recommended"; |
| |
| base::DictionaryValue policy; |
| policy.SetString("a", kMachineMandatory); |
| EXPECT_TRUE(InstallValue(policy, HKEY_LOCAL_MACHINE, |
| kPathSuffix, kMandatory)); |
| policy.SetString("a", kUserMandatory); |
| policy.SetString("b", kUserMandatory); |
| EXPECT_TRUE(InstallValue(policy, HKEY_CURRENT_USER, |
| kPathSuffix, kMandatory)); |
| policy.SetString("a", kMachineRecommended); |
| policy.SetString("b", kMachineRecommended); |
| policy.SetString("c", kMachineRecommended); |
| EXPECT_TRUE(InstallValue(policy, HKEY_LOCAL_MACHINE, |
| kPathSuffix, kRecommended)); |
| policy.SetString("a", kUserRecommended); |
| policy.SetString("b", kUserRecommended); |
| policy.SetString("c", kUserRecommended); |
| policy.SetString("d", kUserRecommended); |
| EXPECT_TRUE(InstallValue(policy, HKEY_CURRENT_USER, |
| kPathSuffix, kRecommended)); |
| |
| PolicyBundle expected; |
| PolicyMap& expected_policy = expected.Get(POLICY_DOMAIN_EXTENSIONS, "merge"); |
| expected_policy.Set("a", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, |
| base::Value::CreateStringValue(kMachineMandatory)); |
| expected_policy.Set("b", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, |
| base::Value::CreateStringValue(kUserMandatory)); |
| expected_policy.Set("c", POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_MACHINE, |
| base::Value::CreateStringValue(kMachineRecommended)); |
| expected_policy.Set("d", POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER, |
| base::Value::CreateStringValue(kUserRecommended)); |
| EXPECT_TRUE(Matches(expected)); |
| } |
| |
| TEST_F(PolicyLoaderWinTest, LoadStringEncodedValues) { |
| // Create a dictionary with all the types that can be stored encoded in a |
| // string, to pass to InstallSchema(). Also build an equivalent dictionary |
| // with the encoded values, to pass to InstallValue(). |
| base::DictionaryValue policy; |
| policy.Set("null", base::Value::CreateNullValue()); |
| policy.SetBoolean("bool", true); |
| policy.SetInteger("int", -123); |
| policy.SetDouble("double", 456.78e9); |
| base::ListValue list; |
| list.Append(policy.DeepCopy()); |
| list.Append(policy.DeepCopy()); |
| policy.Set("list", list.DeepCopy()); |
| // Encode |policy| before adding the "dict" entry. |
| std::string encoded_dict; |
| base::JSONWriter::Write(&policy, &encoded_dict); |
| ASSERT_FALSE(encoded_dict.empty()); |
| policy.Set("dict", policy.DeepCopy()); |
| |
| std::string encoded_list; |
| base::JSONWriter::Write(&list, &encoded_list); |
| ASSERT_FALSE(encoded_list.empty()); |
| base::DictionaryValue encoded_policy; |
| encoded_policy.SetString("null", ""); |
| encoded_policy.SetString("bool", "1"); |
| encoded_policy.SetString("int", "-123"); |
| encoded_policy.SetString("double", "456.78e9"); |
| encoded_policy.SetString("list", encoded_list); |
| encoded_policy.SetString("dict", encoded_dict); |
| |
| const string16 kPathSuffix = |
| kRegistryMandatorySubKey + ASCIIToUTF16("\\3rdparty\\extensions\\string"); |
| EXPECT_TRUE(InstallSchema(policy, HKEY_CURRENT_USER, kPathSuffix, kSchema)); |
| EXPECT_TRUE( |
| InstallValue(encoded_policy, HKEY_CURRENT_USER, kPathSuffix, kMandatory)); |
| |
| PolicyBundle expected; |
| expected.Get(POLICY_DOMAIN_EXTENSIONS, "string") |
| .LoadFrom(&policy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER); |
| EXPECT_TRUE(Matches(expected)); |
| } |
| |
| TEST_F(PolicyLoaderWinTest, LoadIntegerEncodedValues) { |
| base::DictionaryValue policy; |
| policy.SetBoolean("bool", true); |
| policy.SetInteger("int", 123); |
| policy.SetDouble("double", 456.0); |
| |
| base::DictionaryValue encoded_policy; |
| encoded_policy.SetInteger("bool", 1); |
| encoded_policy.SetInteger("int", 123); |
| encoded_policy.SetInteger("double", 456); |
| |
| const string16 kPathSuffix = |
| kRegistryMandatorySubKey + ASCIIToUTF16("\\3rdparty\\extensions\\int"); |
| EXPECT_TRUE(InstallSchema(policy, HKEY_CURRENT_USER, kPathSuffix, kSchema)); |
| EXPECT_TRUE( |
| InstallValue(encoded_policy, HKEY_CURRENT_USER, kPathSuffix, kMandatory)); |
| |
| PolicyBundle expected; |
| expected.Get(POLICY_DOMAIN_EXTENSIONS, "int") |
| .LoadFrom(&policy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER); |
| EXPECT_TRUE(Matches(expected)); |
| } |
| |
| TEST_F(PolicyLoaderWinTest, DefaultPropertySchemaType) { |
| // Build a schema for an "object" with a default schema for its properties. |
| base::DictionaryValue default_schema; |
| default_schema.SetString(schema::kType, "number"); |
| base::DictionaryValue integer_schema; |
| integer_schema.SetString(schema::kType, "integer"); |
| base::DictionaryValue properties; |
| properties.Set("special-int1", integer_schema.DeepCopy()); |
| properties.Set("special-int2", integer_schema.DeepCopy()); |
| base::DictionaryValue schema; |
| schema.SetString(schema::kType, "object"); |
| schema.Set(schema::kProperties, properties.DeepCopy()); |
| schema.Set(schema::kAdditionalProperties, default_schema.DeepCopy()); |
| |
| const string16 kPathSuffix = |
| kRegistryMandatorySubKey + ASCIIToUTF16("\\3rdparty\\extensions\\test"); |
| EXPECT_TRUE(WriteSchema(schema, HKEY_CURRENT_USER, kPathSuffix, kSchema)); |
| |
| // Write some test values. |
| base::DictionaryValue policy; |
| // These special values have a specific schema for them. |
| policy.SetInteger("special-int1", 123); |
| policy.SetString("special-int2", "-456"); |
| // Other values default to be loaded as doubles. |
| policy.SetInteger("double1", 789.0); |
| policy.SetString("double2", "123.456e7"); |
| policy.SetString("invalid", "omg"); |
| EXPECT_TRUE(InstallValue(policy, HKEY_CURRENT_USER, kPathSuffix, kMandatory)); |
| |
| base::DictionaryValue expected_policy; |
| expected_policy.SetInteger("special-int1", 123); |
| expected_policy.SetInteger("special-int2", -456); |
| expected_policy.SetDouble("double1", 789.0); |
| expected_policy.SetDouble("double2", 123.456e7); |
| PolicyBundle expected; |
| expected.Get(POLICY_DOMAIN_EXTENSIONS, "test") |
| .LoadFrom(&expected_policy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER); |
| EXPECT_TRUE(Matches(expected)); |
| } |
| |
| } // namespace policy |