OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "components/policy/core/common/policy_loader_win.h" | 5 #include "components/policy/core/common/policy_loader_win.h" |
6 | 6 |
7 #include <windows.h> | 7 #include <windows.h> |
8 #include <userenv.h> | 8 #include <userenv.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
(...skipping 10 matching lines...) Expand all Loading... |
21 #include "base/json/json_writer.h" | 21 #include "base/json/json_writer.h" |
22 #include "base/path_service.h" | 22 #include "base/path_service.h" |
23 #include "base/process/process.h" | 23 #include "base/process/process.h" |
24 #include "base/strings/string16.h" | 24 #include "base/strings/string16.h" |
25 #include "base/strings/string_number_conversions.h" | 25 #include "base/strings/string_number_conversions.h" |
26 #include "base/strings/string_util.h" | 26 #include "base/strings/string_util.h" |
27 #include "base/strings/stringprintf.h" | 27 #include "base/strings/stringprintf.h" |
28 #include "base/strings/utf_string_conversions.h" | 28 #include "base/strings/utf_string_conversions.h" |
29 #include "base/sys_byteorder.h" | 29 #include "base/sys_byteorder.h" |
30 #include "base/win/registry.h" | 30 #include "base/win/registry.h" |
31 #include "components/json_schema/json_schema_constants.h" | |
32 #include "components/policy/core/common/async_policy_provider.h" | 31 #include "components/policy/core/common/async_policy_provider.h" |
33 #include "components/policy/core/common/configuration_policy_provider_test.h" | 32 #include "components/policy/core/common/configuration_policy_provider_test.h" |
34 #include "components/policy/core/common/external_data_fetcher.h" | 33 #include "components/policy/core/common/external_data_fetcher.h" |
35 #include "components/policy/core/common/policy_bundle.h" | 34 #include "components/policy/core/common/policy_bundle.h" |
36 #include "components/policy/core/common/policy_map.h" | 35 #include "components/policy/core/common/policy_map.h" |
37 #include "components/policy/core/common/preg_parser_win.h" | 36 #include "components/policy/core/common/preg_parser_win.h" |
38 #include "components/policy/core/common/schema_map.h" | 37 #include "components/policy/core/common/schema_map.h" |
39 #include "testing/gtest/include/gtest/gtest.h" | 38 #include "testing/gtest/include/gtest/gtest.h" |
40 | 39 |
41 namespace schema = json_schema_constants; | |
42 | |
43 using base::win::RegKey; | 40 using base::win::RegKey; |
44 | 41 |
45 namespace policy { | 42 namespace policy { |
46 | 43 |
47 namespace { | 44 namespace { |
48 | 45 |
49 // Constants for registry key names. | 46 // Constants for registry key names. |
50 const wchar_t kPathSep[] = L"\\"; | 47 const wchar_t kPathSep[] = L"\\"; |
51 const wchar_t kThirdParty[] = L"3rdparty"; | 48 const wchar_t kThirdParty[] = L"3rdparty"; |
52 const wchar_t kMandatory[] = L"policy"; | 49 const wchar_t kMandatory[] = L"policy"; |
53 const wchar_t kRecommended[] = L"recommended"; | 50 const wchar_t kRecommended[] = L"recommended"; |
54 const wchar_t kSchema[] = L"schema"; | 51 const char kSchema[] = "schema"; |
55 const wchar_t kTestPolicyKey[] = L"chrome.policy.key"; | 52 const wchar_t kTestPolicyKey[] = L"chrome.policy.key"; |
56 | 53 |
57 // Installs |value| in the given registry |path| and |hive|, under the key | 54 // Installs |value| in the given registry |path| and |hive|, under the key |
58 // |name|. Returns false on errors. | 55 // |name|. Returns false on errors. |
59 // Some of the possible Value types are stored after a conversion (e.g. doubles | 56 // Some of the possible Value types are stored after a conversion (e.g. doubles |
60 // are stored as strings), and can only be retrieved if a corresponding schema | 57 // are stored as strings), and can only be retrieved if a corresponding schema |
61 // is written. | 58 // is written. |
62 bool InstallValue(const base::Value& value, | 59 bool InstallValue(const base::Value& value, |
63 HKEY hive, | 60 HKEY hive, |
64 const string16& path, | 61 const string16& path, |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 return true; | 126 return true; |
130 } | 127 } |
131 | 128 |
132 case base::Value::TYPE_BINARY: | 129 case base::Value::TYPE_BINARY: |
133 return false; | 130 return false; |
134 } | 131 } |
135 NOTREACHED(); | 132 NOTREACHED(); |
136 return false; | 133 return false; |
137 } | 134 } |
138 | 135 |
139 // Builds a JSON schema that represents the types contained in |value|. | |
140 // Ownership is transferred to the caller. | |
141 base::DictionaryValue* BuildSchema(const base::Value& value) { | |
142 base::DictionaryValue* schema = new base::DictionaryValue(); | |
143 switch (value.GetType()) { | |
144 case base::Value::TYPE_NULL: | |
145 schema->SetString(schema::kType, "null"); | |
146 break; | |
147 case base::Value::TYPE_BOOLEAN: | |
148 schema->SetString(schema::kType, "boolean"); | |
149 break; | |
150 case base::Value::TYPE_INTEGER: | |
151 schema->SetString(schema::kType, "integer"); | |
152 break; | |
153 case base::Value::TYPE_DOUBLE: | |
154 schema->SetString(schema::kType, "number"); | |
155 break; | |
156 case base::Value::TYPE_STRING: | |
157 schema->SetString(schema::kType, "string"); | |
158 break; | |
159 | |
160 case base::Value::TYPE_LIST: { | |
161 // Assumes every list element has the same type. | |
162 const base::ListValue* list = NULL; | |
163 if (value.GetAsList(&list) && !list->empty()) { | |
164 schema->SetString(schema::kType, "array"); | |
165 schema->Set(schema::kItems, BuildSchema(**list->begin())); | |
166 } | |
167 break; | |
168 } | |
169 | |
170 case base::Value::TYPE_DICTIONARY: { | |
171 const base::DictionaryValue* dict = NULL; | |
172 if (value.GetAsDictionary(&dict)) { | |
173 base::DictionaryValue* properties = new base::DictionaryValue(); | |
174 for (base::DictionaryValue::Iterator it(*dict); | |
175 !it.IsAtEnd(); it.Advance()) { | |
176 properties->Set(it.key(), BuildSchema(it.value())); | |
177 } | |
178 schema->SetString(schema::kType, "object"); | |
179 schema->Set(schema::kProperties, properties); | |
180 } | |
181 break; | |
182 } | |
183 | |
184 case base::Value::TYPE_BINARY: | |
185 break; | |
186 } | |
187 return schema; | |
188 } | |
189 | |
190 // Writes a JSON |schema| at the registry entry |name| at |path| | |
191 // in the given |hive|. Returns false on failure. | |
192 bool WriteSchema(const base::DictionaryValue& schema, | |
193 HKEY hive, | |
194 const string16& path, | |
195 const string16& name) { | |
196 std::string encoded; | |
197 base::JSONWriter::Write(&schema, &encoded); | |
198 if (encoded.empty()) | |
199 return false; | |
200 string16 encoded16 = UTF8ToUTF16(encoded); | |
201 // KEY_ALL_ACCESS causes the ctor to create the key if it does not exist yet. | |
202 RegKey key(hive, path.c_str(), KEY_ALL_ACCESS); | |
203 EXPECT_TRUE(key.Valid()); | |
204 return key.WriteValue(name.c_str(), encoded16.c_str()) == ERROR_SUCCESS; | |
205 } | |
206 | |
207 // Builds a JSON schema for |value| and writes it at the registry entry |name| | |
208 // at |path| in the given |hive|. Returns false on failure. | |
209 bool InstallSchema(const base::Value& value, | |
210 HKEY hive, | |
211 const string16& path, | |
212 const string16& name) { | |
213 scoped_ptr<base::DictionaryValue> schema_dict(BuildSchema(value)); | |
214 return WriteSchema(*schema_dict, hive, path, name); | |
215 } | |
216 | |
217 // This class provides sandboxing and mocking for the parts of the Windows | 136 // This class provides sandboxing and mocking for the parts of the Windows |
218 // Registry implementing Group Policy. It prepares two temporary sandbox keys, | 137 // Registry implementing Group Policy. It prepares two temporary sandbox keys, |
219 // one for HKLM and one for HKCU. A test's calls to the registry are redirected | 138 // one for HKLM and one for HKCU. A test's calls to the registry are redirected |
220 // by Windows to these sandboxes, allowing the tests to manipulate and access | 139 // by Windows to these sandboxes, allowing the tests to manipulate and access |
221 // policy as if it were active, but without actually changing the parts of the | 140 // policy as if it were active, but without actually changing the parts of the |
222 // Registry that are managed by Group Policy. | 141 // Registry that are managed by Group Policy. |
223 class ScopedGroupPolicyRegistrySandbox { | 142 class ScopedGroupPolicyRegistrySandbox { |
224 public: | 143 public: |
225 ScopedGroupPolicyRegistrySandbox(); | 144 ScopedGroupPolicyRegistrySandbox(); |
226 ~ScopedGroupPolicyRegistrySandbox(); | 145 ~ScopedGroupPolicyRegistrySandbox(); |
(...skipping 274 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
501 if (!domain.value().GetAsDictionary(&components)) { | 420 if (!domain.value().GetAsDictionary(&components)) { |
502 ADD_FAILURE(); | 421 ADD_FAILURE(); |
503 continue; | 422 continue; |
504 } | 423 } |
505 for (base::DictionaryValue::Iterator component(*components); | 424 for (base::DictionaryValue::Iterator component(*components); |
506 !component.IsAtEnd(); component.Advance()) { | 425 !component.IsAtEnd(); component.Advance()) { |
507 const string16 path = kPathPrefix + | 426 const string16 path = kPathPrefix + |
508 UTF8ToUTF16(domain.key()) + kPathSep + | 427 UTF8ToUTF16(domain.key()) + kPathSep + |
509 UTF8ToUTF16(component.key()); | 428 UTF8ToUTF16(component.key()); |
510 InstallValue(component.value(), hive_, path, kMandatory); | 429 InstallValue(component.value(), hive_, path, kMandatory); |
511 EXPECT_TRUE(InstallSchema(component.value(), hive_, path, kSchema)); | |
512 } | 430 } |
513 } | 431 } |
514 } | 432 } |
515 | 433 |
516 DWORD RegistryTestHarness::GetAppliedGPOList(DWORD flags, | 434 DWORD RegistryTestHarness::GetAppliedGPOList(DWORD flags, |
517 LPCTSTR machine_name, | 435 LPCTSTR machine_name, |
518 PSID sid_user, | 436 PSID sid_user, |
519 GUID* extension_guid, | 437 GUID* extension_guid, |
520 PGROUP_POLICY_OBJECT* gpo_list) { | 438 PGROUP_POLICY_OBJECT* gpo_list) { |
521 *gpo_list = NULL; | 439 *gpo_list = NULL; |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
604 ADD_FAILURE(); | 522 ADD_FAILURE(); |
605 continue; | 523 continue; |
606 } | 524 } |
607 const string16 domain_path = kPathPrefix + UTF8ToUTF16(domain.key()); | 525 const string16 domain_path = kPathPrefix + UTF8ToUTF16(domain.key()); |
608 for (base::DictionaryValue::Iterator component(*components); | 526 for (base::DictionaryValue::Iterator component(*components); |
609 !component.IsAtEnd(); component.Advance()) { | 527 !component.IsAtEnd(); component.Advance()) { |
610 const string16 component_path = | 528 const string16 component_path = |
611 domain_path + kPathSep + UTF8ToUTF16(component.key()); | 529 domain_path + kPathSep + UTF8ToUTF16(component.key()); |
612 AppendPolicyToPRegFile(component_path, UTF16ToUTF8(kMandatory), | 530 AppendPolicyToPRegFile(component_path, UTF16ToUTF8(kMandatory), |
613 &component.value()); | 531 &component.value()); |
614 | |
615 scoped_ptr<base::DictionaryValue> schema_dict( | |
616 BuildSchema(component.value())); | |
617 std::string schema_json; | |
618 base::JSONWriter::Write(schema_dict.get(), &schema_json); | |
619 if (!schema_json.empty()) { | |
620 AppendStringToPRegFile(component_path, UTF16ToUTF8(kSchema), | |
621 schema_json); | |
622 } | |
623 } | 532 } |
624 } | 533 } |
625 } | 534 } |
626 | 535 |
627 DWORD PRegTestHarness::GetAppliedGPOList(DWORD flags, | 536 DWORD PRegTestHarness::GetAppliedGPOList(DWORD flags, |
628 LPCTSTR machine_name, | 537 LPCTSTR machine_name, |
629 PSID sid_user, | 538 PSID sid_user, |
630 GUID* extension_guid, | 539 GUID* extension_guid, |
631 PGROUP_POLICY_OBJECT* gpo_list) { | 540 PGROUP_POLICY_OBJECT* gpo_list) { |
632 *gpo_list = flags & GPO_LIST_FLAG_MACHINE ? &gpo_ : NULL; | 541 *gpo_list = flags & GPO_LIST_FLAG_MACHINE ? &gpo_ : NULL; |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
791 | 700 |
792 virtual void SetUp() OVERRIDE { | 701 virtual void SetUp() OVERRIDE { |
793 PolicyTestBase::SetUp(); | 702 PolicyTestBase::SetUp(); |
794 | 703 |
795 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &test_data_dir_)); | 704 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &test_data_dir_)); |
796 test_data_dir_ = test_data_dir_.AppendASCII("chrome") | 705 test_data_dir_ = test_data_dir_.AppendASCII("chrome") |
797 .AppendASCII("test") | 706 .AppendASCII("test") |
798 .AppendASCII("data") | 707 .AppendASCII("data") |
799 .AppendASCII("policy") | 708 .AppendASCII("policy") |
800 .AppendASCII("gpo"); | 709 .AppendASCII("gpo"); |
801 | |
802 // Unknown components will be filtered out. Register their names with an | |
803 // invalid schema to avoid that. | |
804 ComponentMap components; | |
805 components["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"] = Schema(); | |
806 components["bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"] = Schema(); | |
807 components["int"] = Schema(); | |
808 components["merge"] = Schema(); | |
809 components["string"] = Schema(); | |
810 components["test"] = Schema(); | |
811 schema_registry_.RegisterComponents(POLICY_DOMAIN_EXTENSIONS, components); | |
812 } | 710 } |
813 | 711 |
814 // AppliedGPOListProvider: | 712 // AppliedGPOListProvider: |
815 virtual DWORD GetAppliedGPOList(DWORD flags, | 713 virtual DWORD GetAppliedGPOList(DWORD flags, |
816 LPCTSTR machine_name, | 714 LPCTSTR machine_name, |
817 PSID sid_user, | 715 PSID sid_user, |
818 GUID* extension_guid, | 716 GUID* extension_guid, |
819 PGROUP_POLICY_OBJECT* gpo_list) OVERRIDE { | 717 PGROUP_POLICY_OBJECT* gpo_list) OVERRIDE { |
820 *gpo_list = gpo_list_; | 718 *gpo_list = gpo_list_; |
821 return gpo_list_status_; | 719 return gpo_list_status_; |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
897 | 795 |
898 PolicyBundle expected; | 796 PolicyBundle expected; |
899 expected.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())) | 797 expected.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())) |
900 .Set(test_keys::kKeyString, | 798 .Set(test_keys::kKeyString, |
901 POLICY_LEVEL_MANDATORY, | 799 POLICY_LEVEL_MANDATORY, |
902 POLICY_SCOPE_MACHINE, | 800 POLICY_SCOPE_MACHINE, |
903 base::Value::CreateStringValue("hklm"), NULL); | 801 base::Value::CreateStringValue("hklm"), NULL); |
904 EXPECT_TRUE(Matches(expected)); | 802 EXPECT_TRUE(Matches(expected)); |
905 } | 803 } |
906 | 804 |
907 TEST_F(PolicyLoaderWinTest, Load3rdPartyWithoutSchema) { | |
908 base::DictionaryValue dict; | |
909 dict.SetString("str", "string value"); | |
910 dict.SetInteger("int", 123); | |
911 dict.Set("subdict", dict.DeepCopy()); | |
912 dict.Set("subsubdict", dict.DeepCopy()); | |
913 dict.Set("subsubsubdict", dict.DeepCopy()); | |
914 | |
915 base::DictionaryValue policy_dict; | |
916 policy_dict.Set("extensions.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.policy", | |
917 dict.DeepCopy()); | |
918 policy_dict.Set("extensions.bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.policy", | |
919 dict.DeepCopy()); | |
920 EXPECT_TRUE(InstallValue(policy_dict, HKEY_LOCAL_MACHINE, | |
921 kTestPolicyKey, kThirdParty)); | |
922 | |
923 PolicyBundle expected; | |
924 expected.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, | |
925 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")) | |
926 .LoadFrom(&dict, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE); | |
927 expected.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, | |
928 "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb")) | |
929 .LoadFrom(&dict, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE); | |
930 EXPECT_TRUE(Matches(expected)); | |
931 } | |
932 | |
933 TEST_F(PolicyLoaderWinTest, Merge3rdPartyPolicies) { | 805 TEST_F(PolicyLoaderWinTest, Merge3rdPartyPolicies) { |
934 // Policy for the same extension will be provided at the 4 level/scope | 806 // Policy for the same extension will be provided at the 4 level/scope |
935 // combinations, to verify that they overlap as expected. | 807 // combinations, to verify that they overlap as expected. |
| 808 const PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, "merge"); |
| 809 ASSERT_TRUE(RegisterSchema( |
| 810 ns, |
| 811 "{" |
| 812 " \"type\": \"object\"," |
| 813 " \"properties\": {" |
| 814 " \"a\": { \"type\": \"string\" }," |
| 815 " \"b\": { \"type\": \"string\" }," |
| 816 " \"c\": { \"type\": \"string\" }," |
| 817 " \"d\": { \"type\": \"string\" }" |
| 818 " }" |
| 819 "}")); |
936 | 820 |
937 const string16 kPathSuffix = | 821 const string16 kPathSuffix = |
938 kTestPolicyKey + ASCIIToUTF16("\\3rdparty\\extensions\\merge"); | 822 kTestPolicyKey + ASCIIToUTF16("\\3rdparty\\extensions\\merge"); |
939 | 823 |
940 const char kUserMandatory[] = "user-mandatory"; | 824 const char kUserMandatory[] = "user-mandatory"; |
941 const char kUserRecommended[] = "user-recommended"; | 825 const char kUserRecommended[] = "user-recommended"; |
942 const char kMachineMandatory[] = "machine-mandatory"; | 826 const char kMachineMandatory[] = "machine-mandatory"; |
943 const char kMachineRecommended[] = "machine-recommended"; | 827 const char kMachineRecommended[] = "machine-recommended"; |
944 | 828 |
945 base::DictionaryValue policy; | 829 base::DictionaryValue policy; |
(...skipping 10 matching lines...) Expand all Loading... |
956 EXPECT_TRUE(InstallValue(policy, HKEY_LOCAL_MACHINE, | 840 EXPECT_TRUE(InstallValue(policy, HKEY_LOCAL_MACHINE, |
957 kPathSuffix, kRecommended)); | 841 kPathSuffix, kRecommended)); |
958 policy.SetString("a", kUserRecommended); | 842 policy.SetString("a", kUserRecommended); |
959 policy.SetString("b", kUserRecommended); | 843 policy.SetString("b", kUserRecommended); |
960 policy.SetString("c", kUserRecommended); | 844 policy.SetString("c", kUserRecommended); |
961 policy.SetString("d", kUserRecommended); | 845 policy.SetString("d", kUserRecommended); |
962 EXPECT_TRUE(InstallValue(policy, HKEY_CURRENT_USER, | 846 EXPECT_TRUE(InstallValue(policy, HKEY_CURRENT_USER, |
963 kPathSuffix, kRecommended)); | 847 kPathSuffix, kRecommended)); |
964 | 848 |
965 PolicyBundle expected; | 849 PolicyBundle expected; |
966 PolicyMap& expected_policy = | 850 PolicyMap& expected_policy = expected.Get(ns); |
967 expected.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "merge")); | |
968 expected_policy.Set("a", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, | 851 expected_policy.Set("a", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, |
969 base::Value::CreateStringValue(kMachineMandatory), NULL); | 852 base::Value::CreateStringValue(kMachineMandatory), NULL); |
970 expected_policy.Set("b", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, | 853 expected_policy.Set("b", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, |
971 base::Value::CreateStringValue(kUserMandatory), NULL); | 854 base::Value::CreateStringValue(kUserMandatory), NULL); |
972 expected_policy.Set("c", POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_MACHINE, | 855 expected_policy.Set("c", POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_MACHINE, |
973 base::Value::CreateStringValue(kMachineRecommended), | 856 base::Value::CreateStringValue(kMachineRecommended), |
974 NULL); | 857 NULL); |
975 expected_policy.Set("d", POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER, | 858 expected_policy.Set("d", POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER, |
976 base::Value::CreateStringValue(kUserRecommended), NULL); | 859 base::Value::CreateStringValue(kUserRecommended), NULL); |
977 EXPECT_TRUE(Matches(expected)); | 860 EXPECT_TRUE(Matches(expected)); |
978 } | 861 } |
979 | 862 |
980 TEST_F(PolicyLoaderWinTest, LoadStringEncodedValues) { | 863 TEST_F(PolicyLoaderWinTest, LoadStringEncodedValues) { |
981 // Create a dictionary with all the types that can be stored encoded in a | 864 // Create a dictionary with all the types that can be stored encoded in a |
982 // string, to pass to InstallSchema(). Also build an equivalent dictionary | 865 // string. |
983 // with the encoded values, to pass to InstallValue(). | 866 const PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, "string"); |
| 867 ASSERT_TRUE(RegisterSchema( |
| 868 ns, |
| 869 "{" |
| 870 " \"type\": \"object\"," |
| 871 " \"id\": \"MainType\"," |
| 872 " \"properties\": {" |
| 873 " \"null\": { \"type\": \"null\" }," |
| 874 " \"bool\": { \"type\": \"boolean\" }," |
| 875 " \"int\": { \"type\": \"integer\" }," |
| 876 " \"double\": { \"type\": \"number\" }," |
| 877 " \"list\": {" |
| 878 " \"type\": \"array\"," |
| 879 " \"items\": { \"$ref\": \"MainType\" }" |
| 880 " }," |
| 881 " \"dict\": { \"$ref\": \"MainType\" }" |
| 882 " }" |
| 883 "}")); |
| 884 |
984 base::DictionaryValue policy; | 885 base::DictionaryValue policy; |
985 policy.Set("null", base::Value::CreateNullValue()); | 886 policy.Set("null", base::Value::CreateNullValue()); |
986 policy.SetBoolean("bool", true); | 887 policy.SetBoolean("bool", true); |
987 policy.SetInteger("int", -123); | 888 policy.SetInteger("int", -123); |
988 policy.SetDouble("double", 456.78e9); | 889 policy.SetDouble("double", 456.78e9); |
989 base::ListValue list; | 890 base::ListValue list; |
990 list.Append(policy.DeepCopy()); | 891 list.Append(policy.DeepCopy()); |
991 list.Append(policy.DeepCopy()); | 892 list.Append(policy.DeepCopy()); |
992 policy.Set("list", list.DeepCopy()); | 893 policy.Set("list", list.DeepCopy()); |
993 // Encode |policy| before adding the "dict" entry. | 894 // Encode |policy| before adding the "dict" entry. |
994 std::string encoded_dict; | 895 std::string encoded_dict; |
995 base::JSONWriter::Write(&policy, &encoded_dict); | 896 base::JSONWriter::Write(&policy, &encoded_dict); |
996 ASSERT_FALSE(encoded_dict.empty()); | 897 ASSERT_FALSE(encoded_dict.empty()); |
997 policy.Set("dict", policy.DeepCopy()); | 898 policy.Set("dict", policy.DeepCopy()); |
998 | |
999 std::string encoded_list; | 899 std::string encoded_list; |
1000 base::JSONWriter::Write(&list, &encoded_list); | 900 base::JSONWriter::Write(&list, &encoded_list); |
1001 ASSERT_FALSE(encoded_list.empty()); | 901 ASSERT_FALSE(encoded_list.empty()); |
1002 base::DictionaryValue encoded_policy; | 902 base::DictionaryValue encoded_policy; |
1003 encoded_policy.SetString("null", ""); | 903 encoded_policy.SetString("null", ""); |
1004 encoded_policy.SetString("bool", "1"); | 904 encoded_policy.SetString("bool", "1"); |
1005 encoded_policy.SetString("int", "-123"); | 905 encoded_policy.SetString("int", "-123"); |
1006 encoded_policy.SetString("double", "456.78e9"); | 906 encoded_policy.SetString("double", "456.78e9"); |
1007 encoded_policy.SetString("list", encoded_list); | 907 encoded_policy.SetString("list", encoded_list); |
1008 encoded_policy.SetString("dict", encoded_dict); | 908 encoded_policy.SetString("dict", encoded_dict); |
1009 | 909 |
1010 const string16 kPathSuffix = | 910 const string16 kPathSuffix = |
1011 kTestPolicyKey + ASCIIToUTF16("\\3rdparty\\extensions\\string"); | 911 kTestPolicyKey + ASCIIToUTF16("\\3rdparty\\extensions\\string"); |
1012 EXPECT_TRUE(InstallSchema(policy, HKEY_CURRENT_USER, kPathSuffix, kSchema)); | |
1013 EXPECT_TRUE( | 912 EXPECT_TRUE( |
1014 InstallValue(encoded_policy, HKEY_CURRENT_USER, kPathSuffix, kMandatory)); | 913 InstallValue(encoded_policy, HKEY_CURRENT_USER, kPathSuffix, kMandatory)); |
1015 | 914 |
1016 PolicyBundle expected; | 915 PolicyBundle expected; |
1017 expected.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "string")) | 916 expected.Get(ns).LoadFrom(&policy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER); |
1018 .LoadFrom(&policy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER); | |
1019 EXPECT_TRUE(Matches(expected)); | 917 EXPECT_TRUE(Matches(expected)); |
1020 } | 918 } |
1021 | 919 |
1022 TEST_F(PolicyLoaderWinTest, LoadIntegerEncodedValues) { | 920 TEST_F(PolicyLoaderWinTest, LoadIntegerEncodedValues) { |
1023 base::DictionaryValue policy; | 921 const PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, "int"); |
1024 policy.SetBoolean("bool", true); | 922 ASSERT_TRUE(RegisterSchema( |
1025 policy.SetInteger("int", 123); | 923 ns, |
1026 policy.SetDouble("double", 456.0); | 924 "{" |
| 925 " \"type\": \"object\"," |
| 926 " \"properties\": {" |
| 927 " \"bool\": { \"type\": \"boolean\" }," |
| 928 " \"int\": { \"type\": \"integer\" }," |
| 929 " \"double\": { \"type\": \"number\" }" |
| 930 " }" |
| 931 "}")); |
1027 | 932 |
1028 base::DictionaryValue encoded_policy; | 933 base::DictionaryValue encoded_policy; |
1029 encoded_policy.SetInteger("bool", 1); | 934 encoded_policy.SetInteger("bool", 1); |
1030 encoded_policy.SetInteger("int", 123); | 935 encoded_policy.SetInteger("int", 123); |
1031 encoded_policy.SetInteger("double", 456); | 936 encoded_policy.SetInteger("double", 456); |
1032 | 937 |
1033 const string16 kPathSuffix = | 938 const string16 kPathSuffix = |
1034 kTestPolicyKey + ASCIIToUTF16("\\3rdparty\\extensions\\int"); | 939 kTestPolicyKey + ASCIIToUTF16("\\3rdparty\\extensions\\int"); |
1035 EXPECT_TRUE(InstallSchema(policy, HKEY_CURRENT_USER, kPathSuffix, kSchema)); | |
1036 EXPECT_TRUE( | 940 EXPECT_TRUE( |
1037 InstallValue(encoded_policy, HKEY_CURRENT_USER, kPathSuffix, kMandatory)); | 941 InstallValue(encoded_policy, HKEY_CURRENT_USER, kPathSuffix, kMandatory)); |
1038 | 942 |
| 943 base::DictionaryValue policy; |
| 944 policy.SetBoolean("bool", true); |
| 945 policy.SetInteger("int", 123); |
| 946 policy.SetDouble("double", 456.0); |
1039 PolicyBundle expected; | 947 PolicyBundle expected; |
1040 expected.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "int")) | 948 expected.Get(ns).LoadFrom(&policy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER); |
1041 .LoadFrom(&policy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER); | |
1042 EXPECT_TRUE(Matches(expected)); | 949 EXPECT_TRUE(Matches(expected)); |
1043 } | 950 } |
1044 | 951 |
1045 TEST_F(PolicyLoaderWinTest, DefaultPropertySchemaType) { | 952 TEST_F(PolicyLoaderWinTest, DefaultPropertySchemaType) { |
1046 // Build a schema for an "object" with a default schema for its properties. | 953 // Build a schema for an "object" with a default schema for its properties. |
1047 base::DictionaryValue default_schema; | 954 // Note that the top-level object can't have "additionalProperties", so |
1048 default_schema.SetString(schema::kType, "number"); | 955 // a "policy" property is used instead. |
1049 base::DictionaryValue integer_schema; | 956 const PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, "test"); |
1050 integer_schema.SetString(schema::kType, "integer"); | 957 ASSERT_TRUE(RegisterSchema( |
1051 base::DictionaryValue properties; | 958 ns, |
1052 properties.Set("special-int1", integer_schema.DeepCopy()); | 959 "{" |
1053 properties.Set("special-int2", integer_schema.DeepCopy()); | 960 " \"type\": \"object\"," |
1054 base::DictionaryValue schema; | 961 " \"properties\": {" |
1055 schema.SetString(schema::kType, "object"); | 962 " \"policy\": {" |
1056 schema.Set(schema::kProperties, properties.DeepCopy()); | 963 " \"type\": \"object\"," |
1057 schema.Set(schema::kAdditionalProperties, default_schema.DeepCopy()); | 964 " \"properties\": {" |
1058 | 965 " \"special-int1\": { \"type\": \"integer\" }," |
1059 const string16 kPathSuffix = | 966 " \"special-int2\": { \"type\": \"integer\" }" |
1060 kTestPolicyKey + ASCIIToUTF16("\\3rdparty\\extensions\\test"); | 967 " }," |
1061 EXPECT_TRUE(WriteSchema(schema, HKEY_CURRENT_USER, kPathSuffix, kSchema)); | 968 " \"additionalProperties\": { \"type\": \"number\" }" |
| 969 " }" |
| 970 " }" |
| 971 "}")); |
1062 | 972 |
1063 // Write some test values. | 973 // Write some test values. |
1064 base::DictionaryValue policy; | 974 base::DictionaryValue policy; |
1065 // These special values have a specific schema for them. | 975 // These special values have a specific schema for them. |
1066 policy.SetInteger("special-int1", 123); | 976 policy.SetInteger("special-int1", 123); |
1067 policy.SetString("special-int2", "-456"); | 977 policy.SetString("special-int2", "-456"); |
1068 // Other values default to be loaded as doubles. | 978 // Other values default to be loaded as doubles. |
1069 policy.SetInteger("double1", 789.0); | 979 policy.SetInteger("double1", 789.0); |
1070 policy.SetString("double2", "123.456e7"); | 980 policy.SetString("double2", "123.456e7"); |
1071 policy.SetString("invalid", "omg"); | 981 policy.SetString("invalid", "omg"); |
1072 EXPECT_TRUE(InstallValue(policy, HKEY_CURRENT_USER, kPathSuffix, kMandatory)); | 982 base::DictionaryValue all_policies; |
| 983 all_policies.Set("policy", policy.DeepCopy()); |
| 984 |
| 985 const string16 kPathSuffix = |
| 986 kTestPolicyKey + ASCIIToUTF16("\\3rdparty\\extensions\\test"); |
| 987 EXPECT_TRUE( |
| 988 InstallValue(all_policies, HKEY_CURRENT_USER, kPathSuffix, kMandatory)); |
1073 | 989 |
1074 base::DictionaryValue expected_policy; | 990 base::DictionaryValue expected_policy; |
1075 expected_policy.SetInteger("special-int1", 123); | 991 expected_policy.SetInteger("special-int1", 123); |
1076 expected_policy.SetInteger("special-int2", -456); | 992 expected_policy.SetInteger("special-int2", -456); |
1077 expected_policy.SetDouble("double1", 789.0); | 993 expected_policy.SetDouble("double1", 789.0); |
1078 expected_policy.SetDouble("double2", 123.456e7); | 994 expected_policy.SetDouble("double2", 123.456e7); |
1079 expected_policy.Set("invalid", base::Value::CreateNullValue()); | 995 base::DictionaryValue expected_policies; |
| 996 expected_policies.Set("policy", expected_policy.DeepCopy()); |
1080 PolicyBundle expected; | 997 PolicyBundle expected; |
1081 expected.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "test")) | 998 expected.Get(ns).LoadFrom( |
1082 .LoadFrom(&expected_policy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER); | 999 &expected_policies, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER); |
1083 EXPECT_TRUE(Matches(expected)); | 1000 EXPECT_TRUE(Matches(expected)); |
1084 } | 1001 } |
1085 | 1002 |
1086 TEST_F(PolicyLoaderWinTest, AppliedPolicyNotPresent) { | 1003 TEST_F(PolicyLoaderWinTest, AppliedPolicyNotPresent) { |
1087 InstallRegistrySentinel(); | 1004 InstallRegistrySentinel(); |
1088 gpo_list_ = NULL; | 1005 gpo_list_ = NULL; |
1089 gpo_list_status_ = ERROR_SUCCESS; | 1006 gpo_list_status_ = ERROR_SUCCESS; |
1090 | 1007 |
1091 PolicyBundle empty; | 1008 PolicyBundle empty; |
1092 EXPECT_TRUE(Matches(empty)); | 1009 EXPECT_TRUE(Matches(empty)); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1193 } | 1110 } |
1194 | 1111 |
1195 TEST_F(PolicyLoaderWinTest, LoadExtensionPolicyAlternativeSpelling) { | 1112 TEST_F(PolicyLoaderWinTest, LoadExtensionPolicyAlternativeSpelling) { |
1196 base::FilePath gpo_dir( | 1113 base::FilePath gpo_dir( |
1197 test_data_dir_.AppendASCII("extension_alternative_spelling")); | 1114 test_data_dir_.AppendASCII("extension_alternative_spelling")); |
1198 GROUP_POLICY_OBJECT gpo; | 1115 GROUP_POLICY_OBJECT gpo; |
1199 InitGPO(&gpo, 0, gpo_dir, NULL, NULL); | 1116 InitGPO(&gpo, 0, gpo_dir, NULL, NULL); |
1200 gpo_list_ = &gpo; | 1117 gpo_list_ = &gpo; |
1201 gpo_list_status_ = ERROR_SUCCESS; | 1118 gpo_list_status_ = ERROR_SUCCESS; |
1202 | 1119 |
| 1120 const char kTestSchema[] = |
| 1121 "{" |
| 1122 " \"type\": \"object\"," |
| 1123 " \"properties\": {" |
| 1124 " \"policy 1\": { \"type\": \"integer\" }," |
| 1125 " \"policy 2\": { \"type\": \"integer\" }" |
| 1126 " }" |
| 1127 "}"; |
| 1128 const PolicyNamespace ns_a( |
| 1129 POLICY_DOMAIN_EXTENSIONS, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); |
| 1130 const PolicyNamespace ns_b( |
| 1131 POLICY_DOMAIN_EXTENSIONS, "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"); |
| 1132 ASSERT_TRUE(RegisterSchema(ns_a, kTestSchema)); |
| 1133 ASSERT_TRUE(RegisterSchema(ns_b, kTestSchema)); |
| 1134 |
1203 PolicyBundle expected; | 1135 PolicyBundle expected; |
1204 base::DictionaryValue expected_a; | 1136 base::DictionaryValue expected_a; |
1205 expected_a.SetInteger("policy 1", 3); | 1137 expected_a.SetInteger("policy 1", 3); |
1206 expected_a.SetInteger("policy 2", 3); | 1138 expected_a.SetInteger("policy 2", 3); |
1207 expected.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, | 1139 expected.Get(ns_a).LoadFrom( |
1208 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")) | 1140 &expected_a, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE); |
1209 .LoadFrom(&expected_a, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE); | |
1210 base::DictionaryValue expected_b; | 1141 base::DictionaryValue expected_b; |
1211 expected_b.SetInteger("policy 1", 2); | 1142 expected_b.SetInteger("policy 1", 2); |
1212 expected.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, | 1143 expected.Get(ns_b).LoadFrom( |
1213 "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb")) | 1144 &expected_b, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE); |
1214 .LoadFrom(&expected_b, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE); | |
1215 EXPECT_TRUE(Matches(expected)); | 1145 EXPECT_TRUE(Matches(expected)); |
1216 } | 1146 } |
1217 | 1147 |
| 1148 TEST_F(PolicyLoaderWinTest, LBSSupport) { |
| 1149 const PolicyNamespace ns( |
| 1150 POLICY_DOMAIN_EXTENSIONS, "heildphpnddilhkemkielfhnkaagiabh"); |
| 1151 schema_registry_.RegisterComponent(ns, Schema()); |
| 1152 |
| 1153 const char kIncompleteSchema[] = |
| 1154 "{" |
| 1155 " \"type\": \"object\"," |
| 1156 " \"properties\": {" |
| 1157 " \"url_list\": { \"type\": \"array\" }," |
| 1158 " \"url_greylist\": { \"type\": \"array\" }" |
| 1159 " }" |
| 1160 "}"; |
| 1161 |
| 1162 const string16 kPathSuffix = |
| 1163 kTestPolicyKey + ASCIIToUTF16("\\3rdparty\\extensions"); |
| 1164 |
| 1165 base::ListValue list; |
| 1166 list.AppendString("youtube.com"); |
| 1167 base::DictionaryValue policy; |
| 1168 policy.Set("url_list", list.DeepCopy()); |
| 1169 policy.SetString("alternative_browser_path", "c:\\legacy\\browser.exe"); |
| 1170 base::DictionaryValue root; |
| 1171 root.Set(UTF16ToUTF8(kMandatory), policy.DeepCopy()); |
| 1172 root.SetString(kSchema, kIncompleteSchema); |
| 1173 EXPECT_TRUE(InstallValue(root, HKEY_LOCAL_MACHINE, |
| 1174 kPathSuffix, ASCIIToUTF16(ns.component_id))); |
| 1175 |
| 1176 PolicyBundle expected; |
| 1177 PolicyMap& expected_policy = expected.Get(ns); |
| 1178 expected_policy.Set("alternative_browser_path", |
| 1179 POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, |
| 1180 new base::StringValue("c:\\legacy\\browser.exe"), NULL); |
| 1181 expected_policy.Set("url_list", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, |
| 1182 list.DeepCopy(), NULL); |
| 1183 EXPECT_TRUE(Matches(expected)); |
| 1184 } |
| 1185 |
1218 } // namespace policy | 1186 } // namespace policy |
OLD | NEW |