| Index: components/policy/core/common/policy_loader_win_unittest.cc
|
| diff --git a/components/policy/core/common/policy_loader_win_unittest.cc b/components/policy/core/common/policy_loader_win_unittest.cc
|
| index 8bd800023a75018e793a1676827a028fb0372dd8..e63bf966b358df130e5a349590a84d6d9fe03a85 100644
|
| --- a/components/policy/core/common/policy_loader_win_unittest.cc
|
| +++ b/components/policy/core/common/policy_loader_win_unittest.cc
|
| @@ -28,7 +28,6 @@
|
| #include "base/strings/utf_string_conversions.h"
|
| #include "base/sys_byteorder.h"
|
| #include "base/win/registry.h"
|
| -#include "components/json_schema/json_schema_constants.h"
|
| #include "components/policy/core/common/async_policy_provider.h"
|
| #include "components/policy/core/common/configuration_policy_provider_test.h"
|
| #include "components/policy/core/common/external_data_fetcher.h"
|
| @@ -38,8 +37,6 @@
|
| #include "components/policy/core/common/schema_map.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
|
|
| -namespace schema = json_schema_constants;
|
| -
|
| using base::win::RegKey;
|
|
|
| namespace policy {
|
| @@ -51,7 +48,7 @@ const wchar_t kPathSep[] = L"\\";
|
| const wchar_t kThirdParty[] = L"3rdparty";
|
| const wchar_t kMandatory[] = L"policy";
|
| const wchar_t kRecommended[] = L"recommended";
|
| -const wchar_t kSchema[] = L"schema";
|
| +const char kSchema[] = "schema";
|
| const wchar_t kTestPolicyKey[] = L"chrome.policy.key";
|
|
|
| // Installs |value| in the given registry |path| and |hive|, under the key
|
| @@ -136,84 +133,6 @@ bool InstallValue(const base::Value& value,
|
| 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.IsAtEnd(); 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);
|
| - EXPECT_TRUE(key.Valid());
|
| - 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,
|
| // one for HKLM and one for HKCU. A test's calls to the registry are redirected
|
| @@ -508,7 +427,6 @@ void RegistryTestHarness::Install3rdPartyPolicy(
|
| UTF8ToUTF16(domain.key()) + kPathSep +
|
| UTF8ToUTF16(component.key());
|
| InstallValue(component.value(), hive_, path, kMandatory);
|
| - EXPECT_TRUE(InstallSchema(component.value(), hive_, path, kSchema));
|
| }
|
| }
|
| }
|
| @@ -611,15 +529,6 @@ void PRegTestHarness::Install3rdPartyPolicy(
|
| domain_path + kPathSep + UTF8ToUTF16(component.key());
|
| AppendPolicyToPRegFile(component_path, UTF16ToUTF8(kMandatory),
|
| &component.value());
|
| -
|
| - scoped_ptr<base::DictionaryValue> schema_dict(
|
| - BuildSchema(component.value()));
|
| - std::string schema_json;
|
| - base::JSONWriter::Write(schema_dict.get(), &schema_json);
|
| - if (!schema_json.empty()) {
|
| - AppendStringToPRegFile(component_path, UTF16ToUTF8(kSchema),
|
| - schema_json);
|
| - }
|
| }
|
| }
|
| }
|
| @@ -798,17 +707,6 @@ class PolicyLoaderWinTest : public PolicyTestBase,
|
| .AppendASCII("data")
|
| .AppendASCII("policy")
|
| .AppendASCII("gpo");
|
| -
|
| - // Unknown components will be filtered out. Register their names with an
|
| - // invalid schema to avoid that.
|
| - ComponentMap components;
|
| - components["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"] = Schema();
|
| - components["bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"] = Schema();
|
| - components["int"] = Schema();
|
| - components["merge"] = Schema();
|
| - components["string"] = Schema();
|
| - components["test"] = Schema();
|
| - schema_registry_.RegisterComponents(POLICY_DOMAIN_EXTENSIONS, components);
|
| }
|
|
|
| // AppliedGPOListProvider:
|
| @@ -904,35 +802,21 @@ TEST_F(PolicyLoaderWinTest, HKLMOverHKCU) {
|
| 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,
|
| - kTestPolicyKey, kThirdParty));
|
| -
|
| - PolicyBundle expected;
|
| - expected.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
|
| - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
|
| - .LoadFrom(&dict, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE);
|
| - expected.Get(PolicyNamespace(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 PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, "merge");
|
| + ASSERT_TRUE(RegisterSchema(
|
| + ns,
|
| + "{"
|
| + " \"type\": \"object\","
|
| + " \"properties\": {"
|
| + " \"a\": { \"type\": \"string\" },"
|
| + " \"b\": { \"type\": \"string\" },"
|
| + " \"c\": { \"type\": \"string\" },"
|
| + " \"d\": { \"type\": \"string\" }"
|
| + " }"
|
| + "}"));
|
|
|
| const string16 kPathSuffix =
|
| kTestPolicyKey + ASCIIToUTF16("\\3rdparty\\extensions\\merge");
|
| @@ -963,8 +847,7 @@ TEST_F(PolicyLoaderWinTest, Merge3rdPartyPolicies) {
|
| kPathSuffix, kRecommended));
|
|
|
| PolicyBundle expected;
|
| - PolicyMap& expected_policy =
|
| - expected.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "merge"));
|
| + PolicyMap& expected_policy = expected.Get(ns);
|
| expected_policy.Set("a", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
|
| base::Value::CreateStringValue(kMachineMandatory), NULL);
|
| expected_policy.Set("b", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
|
| @@ -979,8 +862,26 @@ TEST_F(PolicyLoaderWinTest, Merge3rdPartyPolicies) {
|
|
|
| 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().
|
| + // string.
|
| + const PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, "string");
|
| + ASSERT_TRUE(RegisterSchema(
|
| + ns,
|
| + "{"
|
| + " \"type\": \"object\","
|
| + " \"id\": \"MainType\","
|
| + " \"properties\": {"
|
| + " \"null\": { \"type\": \"null\" },"
|
| + " \"bool\": { \"type\": \"boolean\" },"
|
| + " \"int\": { \"type\": \"integer\" },"
|
| + " \"double\": { \"type\": \"number\" },"
|
| + " \"list\": {"
|
| + " \"type\": \"array\","
|
| + " \"items\": { \"$ref\": \"MainType\" }"
|
| + " },"
|
| + " \"dict\": { \"$ref\": \"MainType\" }"
|
| + " }"
|
| + "}"));
|
| +
|
| base::DictionaryValue policy;
|
| policy.Set("null", base::Value::CreateNullValue());
|
| policy.SetBoolean("bool", true);
|
| @@ -995,7 +896,6 @@ TEST_F(PolicyLoaderWinTest, LoadStringEncodedValues) {
|
| 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());
|
| @@ -1009,21 +909,26 @@ TEST_F(PolicyLoaderWinTest, LoadStringEncodedValues) {
|
|
|
| const string16 kPathSuffix =
|
| kTestPolicyKey + 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(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "string"))
|
| - .LoadFrom(&policy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER);
|
| + expected.Get(ns).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);
|
| + const PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, "int");
|
| + ASSERT_TRUE(RegisterSchema(
|
| + ns,
|
| + "{"
|
| + " \"type\": \"object\","
|
| + " \"properties\": {"
|
| + " \"bool\": { \"type\": \"boolean\" },"
|
| + " \"int\": { \"type\": \"integer\" },"
|
| + " \"double\": { \"type\": \"number\" }"
|
| + " }"
|
| + "}"));
|
|
|
| base::DictionaryValue encoded_policy;
|
| encoded_policy.SetInteger("bool", 1);
|
| @@ -1032,33 +937,38 @@ TEST_F(PolicyLoaderWinTest, LoadIntegerEncodedValues) {
|
|
|
| const string16 kPathSuffix =
|
| kTestPolicyKey + ASCIIToUTF16("\\3rdparty\\extensions\\int");
|
| - EXPECT_TRUE(InstallSchema(policy, HKEY_CURRENT_USER, kPathSuffix, kSchema));
|
| EXPECT_TRUE(
|
| InstallValue(encoded_policy, HKEY_CURRENT_USER, kPathSuffix, kMandatory));
|
|
|
| + base::DictionaryValue policy;
|
| + policy.SetBoolean("bool", true);
|
| + policy.SetInteger("int", 123);
|
| + policy.SetDouble("double", 456.0);
|
| PolicyBundle expected;
|
| - expected.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "int"))
|
| - .LoadFrom(&policy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER);
|
| + expected.Get(ns).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 =
|
| - kTestPolicyKey + ASCIIToUTF16("\\3rdparty\\extensions\\test");
|
| - EXPECT_TRUE(WriteSchema(schema, HKEY_CURRENT_USER, kPathSuffix, kSchema));
|
| + // Note that the top-level object can't have "additionalProperties", so
|
| + // a "policy" property is used instead.
|
| + const PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, "test");
|
| + ASSERT_TRUE(RegisterSchema(
|
| + ns,
|
| + "{"
|
| + " \"type\": \"object\","
|
| + " \"properties\": {"
|
| + " \"policy\": {"
|
| + " \"type\": \"object\","
|
| + " \"properties\": {"
|
| + " \"special-int1\": { \"type\": \"integer\" },"
|
| + " \"special-int2\": { \"type\": \"integer\" }"
|
| + " },"
|
| + " \"additionalProperties\": { \"type\": \"number\" }"
|
| + " }"
|
| + " }"
|
| + "}"));
|
|
|
| // Write some test values.
|
| base::DictionaryValue policy;
|
| @@ -1069,17 +979,24 @@ TEST_F(PolicyLoaderWinTest, DefaultPropertySchemaType) {
|
| 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 all_policies;
|
| + all_policies.Set("policy", policy.DeepCopy());
|
| +
|
| + const string16 kPathSuffix =
|
| + kTestPolicyKey + ASCIIToUTF16("\\3rdparty\\extensions\\test");
|
| + EXPECT_TRUE(
|
| + InstallValue(all_policies, 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);
|
| - expected_policy.Set("invalid", base::Value::CreateNullValue());
|
| + base::DictionaryValue expected_policies;
|
| + expected_policies.Set("policy", expected_policy.DeepCopy());
|
| PolicyBundle expected;
|
| - expected.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "test"))
|
| - .LoadFrom(&expected_policy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER);
|
| + expected.Get(ns).LoadFrom(
|
| + &expected_policies, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER);
|
| EXPECT_TRUE(Matches(expected));
|
| }
|
|
|
| @@ -1200,18 +1117,69 @@ TEST_F(PolicyLoaderWinTest, LoadExtensionPolicyAlternativeSpelling) {
|
| gpo_list_ = &gpo;
|
| gpo_list_status_ = ERROR_SUCCESS;
|
|
|
| + const char kTestSchema[] =
|
| + "{"
|
| + " \"type\": \"object\","
|
| + " \"properties\": {"
|
| + " \"policy 1\": { \"type\": \"integer\" },"
|
| + " \"policy 2\": { \"type\": \"integer\" }"
|
| + " }"
|
| + "}";
|
| + const PolicyNamespace ns_a(
|
| + POLICY_DOMAIN_EXTENSIONS, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
|
| + const PolicyNamespace ns_b(
|
| + POLICY_DOMAIN_EXTENSIONS, "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
|
| + ASSERT_TRUE(RegisterSchema(ns_a, kTestSchema));
|
| + ASSERT_TRUE(RegisterSchema(ns_b, kTestSchema));
|
| +
|
| PolicyBundle expected;
|
| base::DictionaryValue expected_a;
|
| expected_a.SetInteger("policy 1", 3);
|
| expected_a.SetInteger("policy 2", 3);
|
| - expected.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
|
| - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
|
| - .LoadFrom(&expected_a, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE);
|
| + expected.Get(ns_a).LoadFrom(
|
| + &expected_a, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE);
|
| base::DictionaryValue expected_b;
|
| expected_b.SetInteger("policy 1", 2);
|
| - expected.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
|
| - "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"))
|
| - .LoadFrom(&expected_b, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE);
|
| + expected.Get(ns_b).LoadFrom(
|
| + &expected_b, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE);
|
| + EXPECT_TRUE(Matches(expected));
|
| +}
|
| +
|
| +TEST_F(PolicyLoaderWinTest, LBSSupport) {
|
| + const PolicyNamespace ns(
|
| + POLICY_DOMAIN_EXTENSIONS, "heildphpnddilhkemkielfhnkaagiabh");
|
| + schema_registry_.RegisterComponent(ns, Schema());
|
| +
|
| + const char kIncompleteSchema[] =
|
| + "{"
|
| + " \"type\": \"object\","
|
| + " \"properties\": {"
|
| + " \"url_list\": { \"type\": \"array\" },"
|
| + " \"url_greylist\": { \"type\": \"array\" }"
|
| + " }"
|
| + "}";
|
| +
|
| + const string16 kPathSuffix =
|
| + kTestPolicyKey + ASCIIToUTF16("\\3rdparty\\extensions");
|
| +
|
| + base::ListValue list;
|
| + list.AppendString("youtube.com");
|
| + base::DictionaryValue policy;
|
| + policy.Set("url_list", list.DeepCopy());
|
| + policy.SetString("alternative_browser_path", "c:\\legacy\\browser.exe");
|
| + base::DictionaryValue root;
|
| + root.Set(UTF16ToUTF8(kMandatory), policy.DeepCopy());
|
| + root.SetString(kSchema, kIncompleteSchema);
|
| + EXPECT_TRUE(InstallValue(root, HKEY_LOCAL_MACHINE,
|
| + kPathSuffix, ASCIIToUTF16(ns.component_id)));
|
| +
|
| + PolicyBundle expected;
|
| + PolicyMap& expected_policy = expected.Get(ns);
|
| + expected_policy.Set("alternative_browser_path",
|
| + POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
|
| + new base::StringValue("c:\\legacy\\browser.exe"), NULL);
|
| + expected_policy.Set("url_list", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
|
| + list.DeepCopy(), NULL);
|
| EXPECT_TRUE(Matches(expected));
|
| }
|
|
|
|
|