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 "chrome/browser/policy/policy_loader_win.h" | 5 #include "chrome/browser/policy/policy_loader_win.h" |
6 | 6 |
7 #include <windows.h> | 7 #include <windows.h> |
8 | 8 |
9 #include "base/json/json_writer.h" | 9 #include "base/json/json_writer.h" |
10 #include "base/string16.h" | 10 #include "base/string16.h" |
11 #include "base/string_number_conversions.h" | 11 #include "base/string_number_conversions.h" |
12 #include "base/string_util.h" | |
12 #include "base/utf_string_conversions.h" | 13 #include "base/utf_string_conversions.h" |
13 #include "base/win/registry.h" | 14 #include "base/win/registry.h" |
14 #include "chrome/browser/policy/async_policy_provider.h" | 15 #include "chrome/browser/policy/async_policy_provider.h" |
15 #include "chrome/browser/policy/configuration_policy_provider_test.h" | 16 #include "chrome/browser/policy/configuration_policy_provider_test.h" |
16 #include "chrome/browser/policy/policy_bundle.h" | 17 #include "chrome/browser/policy/policy_bundle.h" |
17 #include "chrome/browser/policy/policy_map.h" | 18 #include "chrome/browser/policy/policy_map.h" |
18 #include "policy/policy_constants.h" | 19 #include "policy/policy_constants.h" |
19 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
20 | 21 |
21 using base::win::RegKey; | 22 using base::win::RegKey; |
22 | 23 |
23 namespace policy { | 24 namespace policy { |
24 | 25 |
25 namespace { | 26 namespace { |
26 | 27 |
27 const wchar_t kUnitTestRegistrySubKey[] = L"SOFTWARE\\Chromium Unit Tests"; | 28 const wchar_t kUnitTestRegistrySubKey[] = L"SOFTWARE\\Chromium Unit Tests"; |
28 const wchar_t kUnitTestMachineOverrideSubKey[] = | 29 const wchar_t kUnitTestMachineOverrideSubKey[] = |
29 L"SOFTWARE\\Chromium Unit Tests\\HKLM Override"; | 30 L"SOFTWARE\\Chromium Unit Tests\\HKLM Override"; |
30 const wchar_t kUnitTestUserOverrideSubKey[] = | 31 const wchar_t kUnitTestUserOverrideSubKey[] = |
31 L"SOFTWARE\\Chromium Unit Tests\\HKCU Override"; | 32 L"SOFTWARE\\Chromium Unit Tests\\HKCU Override"; |
32 | 33 |
33 // Installs |dict| at the given |path|, in the given |hive|. Currently only | 34 const wchar_t kPathSep[] = L"\\"; |
34 // string, int and dictionary types are converted; other types cause a failure. | 35 |
35 // Returns false if there was any failure, and true if |dict| was successfully | 36 // Registry key where 3rd party policy is stored. |
36 // written. | 37 const wchar_t kThirdParty[] = L"3rdparty"; |
37 // TODO(joaodasilva): generate a schema for |dict| too, so that all types can | 38 |
38 // be retrieved. | 39 // Keys for mandatory and recommended policy and schema under the registry key |
39 bool InstallDictionary(const base::DictionaryValue& dict, | 40 // for a component. |
40 HKEY hive, | 41 const wchar_t kMandatory[] = L"policy"; |
41 const string16& path) { | 42 const wchar_t kRecommended[] = L"recommended"; |
43 const wchar_t kSchema[] = L"schema"; | |
44 | |
45 // JSON-schema key that indicates an entry's type. | |
46 const char kType[] = "type"; | |
47 // JSON-schema key that indicates an object entry's properties. | |
48 const char kProperties[] = "properties"; | |
49 // JSON-schema key that indicates an object entry's default schema. | |
50 const char kAdditionalProperties[] = "additionalProperties"; | |
51 // JSON-schema key that indicates the schema for the items of an array entry. | |
52 const char kItems[] = "items"; | |
Mattias Nissler (ping if slow)
2012/06/27 14:52:10
nit: You could convert these to static members in
Joao da Silva
2012/06/27 16:55:28
I've added them to a namespace within ::policy, so
Mattias Nissler (ping if slow)
2012/06/28 10:00:28
I think that's a fair solution. I'm not sure wheth
| |
53 | |
54 // Installs |value| in the given registry |path| and |hive|, under the key | |
55 // |name|. Returns false on errors. | |
56 // Some of the possible Value types are stored after a conversion (e.g. doubles | |
57 // are stored as strings), and can only be retrieved if a corresponding schema | |
58 // is written. | |
59 bool InstallValue(const base::Value& value, | |
60 HKEY hive, | |
61 const string16& path, | |
62 const string16& name) { | |
42 // KEY_ALL_ACCESS causes the ctor to create the key if it does not exist yet. | 63 // KEY_ALL_ACCESS causes the ctor to create the key if it does not exist yet. |
43 RegKey key(hive, path.c_str(), KEY_ALL_ACCESS); | 64 RegKey key(hive, path.c_str(), KEY_ALL_ACCESS); |
44 const string16 kPathSep = ASCIIToUTF16("\\"); | 65 switch (value.GetType()) { |
66 case base::Value::TYPE_NULL: | |
67 return key.WriteValue(name.c_str(), L"") == ERROR_SUCCESS; | |
45 | 68 |
46 for (base::DictionaryValue::Iterator it(dict); it.HasNext(); it.Advance()) { | 69 case base::Value::TYPE_BOOLEAN: { |
47 string16 name(UTF8ToUTF16(it.key())); | 70 bool bool_value; |
48 switch (it.value().GetType()) { | 71 if (!value.GetAsBoolean(&bool_value)) |
49 case base::Value::TYPE_STRING: { | 72 return false; |
50 string16 value; | 73 return key.WriteValue(name.c_str(), bool_value ? 1 : 0) == ERROR_SUCCESS; |
51 if (!it.value().GetAsString(&value)) | 74 } |
75 | |
76 case base::Value::TYPE_INTEGER: { | |
77 int int_value; | |
78 if (!value.GetAsInteger(&int_value)) | |
79 return false; | |
80 return key.WriteValue(name.c_str(), int_value) == ERROR_SUCCESS; | |
81 } | |
82 | |
83 case base::Value::TYPE_DOUBLE: { | |
84 double double_value; | |
85 if (!value.GetAsDouble(&double_value)) | |
86 return false; | |
87 string16 str_value = UTF8ToUTF16(base::DoubleToString(double_value)); | |
88 return key.WriteValue(name.c_str(), str_value.c_str()) == ERROR_SUCCESS; | |
89 } | |
90 | |
91 case base::Value::TYPE_STRING: { | |
92 string16 str_value; | |
93 if (!value.GetAsString(&str_value)) | |
94 return false; | |
95 return key.WriteValue(name.c_str(), str_value.c_str()) == ERROR_SUCCESS; | |
96 } | |
97 | |
98 case base::Value::TYPE_DICTIONARY: { | |
99 const base::DictionaryValue* sub_dict = NULL; | |
100 if (!value.GetAsDictionary(&sub_dict)) | |
101 return false; | |
102 for (base::DictionaryValue::Iterator it(*sub_dict); | |
103 it.HasNext(); it.Advance()) { | |
104 if (!InstallValue(it.value(), hive, path + kPathSep + name, | |
105 UTF8ToUTF16(it.key()))) { | |
52 return false; | 106 return false; |
53 if (key.WriteValue(name.c_str(), value.c_str()) != ERROR_SUCCESS) | 107 } |
108 } | |
109 return true; | |
110 } | |
111 | |
112 case base::Value::TYPE_LIST: { | |
113 const base::ListValue* list = NULL; | |
114 if (!value.GetAsList(&list)) | |
115 return false; | |
116 for (size_t i = 0; i < list->GetSize(); ++i) { | |
117 base::Value* item; | |
118 if (!list->Get(i, &item)) | |
54 return false; | 119 return false; |
55 break; | 120 if (!InstallValue(*item, hive, path + kPathSep + name, |
121 base::UintToString16(i + 1))) { | |
122 return false; | |
123 } | |
56 } | 124 } |
125 return true; | |
126 } | |
57 | 127 |
58 case base::Value::TYPE_INTEGER: { | 128 case base::Value::TYPE_BINARY: |
59 int value; | 129 return false; |
60 if (!it.value().GetAsInteger(&value)) | 130 } |
61 return false; | 131 NOTREACHED(); |
62 if (key.WriteValue(name.c_str(), value) != ERROR_SUCCESS) | 132 return false; |
63 return false; | 133 } |
64 break; | 134 |
135 // Builds a JSON schema that represents the types contained in |value|. | |
136 // Ownership is transferred to the caller. | |
137 base::DictionaryValue* BuildSchema(const base::Value& value) { | |
138 base::DictionaryValue* schema = new base::DictionaryValue(); | |
139 switch (value.GetType()) { | |
140 case base::Value::TYPE_NULL: | |
141 schema->SetString(kType, "null"); | |
142 break; | |
143 case base::Value::TYPE_BOOLEAN: | |
144 schema->SetString(kType, "boolean"); | |
145 break; | |
146 case base::Value::TYPE_INTEGER: | |
147 schema->SetString(kType, "integer"); | |
148 break; | |
149 case base::Value::TYPE_DOUBLE: | |
150 schema->SetString(kType, "number"); | |
151 break; | |
152 case base::Value::TYPE_STRING: | |
153 schema->SetString(kType, "string"); | |
154 break; | |
155 | |
156 case base::Value::TYPE_LIST: { | |
157 // Assumes every list element has the same type. | |
158 const base::ListValue* list = NULL; | |
159 if (value.GetAsList(&list) && !list->empty()) { | |
160 schema->SetString(kType, "array"); | |
161 schema->Set(kItems, BuildSchema(**list->begin())); | |
65 } | 162 } |
163 break; | |
164 } | |
66 | 165 |
67 case base::Value::TYPE_DICTIONARY: { | 166 case base::Value::TYPE_DICTIONARY: { |
68 const base::DictionaryValue* sub_dict = NULL; | 167 const base::DictionaryValue* dict = NULL; |
69 if (!it.value().GetAsDictionary(&sub_dict)) | 168 if (value.GetAsDictionary(&dict)) { |
70 return false; | 169 base::DictionaryValue* properties = new base::DictionaryValue(); |
71 if (!InstallDictionary(*sub_dict, hive, path + kPathSep + name)) | 170 for (base::DictionaryValue::Iterator it(*dict); |
72 return false; | 171 it.HasNext(); it.Advance()) { |
73 break; | 172 properties->Set(it.key(), BuildSchema(it.value())); |
173 } | |
174 schema->SetString(kType, "object"); | |
175 schema->Set(kProperties, properties); | |
74 } | 176 } |
177 break; | |
178 } | |
75 | 179 |
76 default: | 180 case base::Value::TYPE_BINARY: |
77 return false; | 181 break; |
78 } | |
79 } | 182 } |
80 return true; | 183 return schema; |
184 } | |
185 | |
186 // Writes a JSON |schema| at the registry entry |name| at |path| | |
187 // in the given |hive|. Returns false on failure. | |
188 bool WriteSchema(const base::DictionaryValue& schema, | |
189 HKEY hive, | |
190 const string16& path, | |
191 const string16& name) { | |
192 std::string encoded; | |
193 base::JSONWriter::Write(&schema, &encoded); | |
194 if (encoded.empty()) | |
195 return false; | |
196 string16 encoded16 = UTF8ToUTF16(encoded); | |
197 // KEY_ALL_ACCESS causes the ctor to create the key if it does not exist yet. | |
198 RegKey key(hive, path.c_str(), KEY_ALL_ACCESS); | |
199 return key.WriteValue(name.c_str(), encoded16.c_str()) == ERROR_SUCCESS; | |
200 } | |
201 | |
202 // Builds a JSON schema for |value| and writes it at the registry entry |name| | |
203 // at |path| in the given |hive|. Returns false on failure. | |
204 bool InstallSchema(const base::Value& value, | |
205 HKEY hive, | |
206 const string16& path, | |
207 const string16& name) { | |
208 scoped_ptr<base::DictionaryValue> schema_dict(BuildSchema(value)); | |
209 return WriteSchema(*schema_dict, hive, path, name); | |
81 } | 210 } |
82 | 211 |
83 // This class provides sandboxing and mocking for the parts of the Windows | 212 // This class provides sandboxing and mocking for the parts of the Windows |
84 // Registry implementing Group Policy. It prepares two temporary sandbox keys | 213 // Registry implementing Group Policy. It prepares two temporary sandbox keys |
85 // in |kUnitTestRegistrySubKey|, one for HKLM and one for HKCU. A test's calls | 214 // in |kUnitTestRegistrySubKey|, one for HKLM and one for HKCU. A test's calls |
86 // to the registry are redirected by Windows to these sandboxes, allowing the | 215 // to the registry are redirected by Windows to these sandboxes, allowing the |
87 // tests to manipulate and access policy as if it were active, but without | 216 // tests to manipulate and access policy as if it were active, but without |
88 // actually changing the parts of the Registry that are managed by Group | 217 // actually changing the parts of the Registry that are managed by Group |
89 // Policy. | 218 // Policy. |
90 class ScopedGroupPolicyRegistrySandbox { | 219 class ScopedGroupPolicyRegistrySandbox { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
123 virtual void InstallIntegerPolicy(const std::string& policy_name, | 252 virtual void InstallIntegerPolicy(const std::string& policy_name, |
124 int policy_value) OVERRIDE; | 253 int policy_value) OVERRIDE; |
125 virtual void InstallBooleanPolicy(const std::string& policy_name, | 254 virtual void InstallBooleanPolicy(const std::string& policy_name, |
126 bool policy_value) OVERRIDE; | 255 bool policy_value) OVERRIDE; |
127 virtual void InstallStringListPolicy( | 256 virtual void InstallStringListPolicy( |
128 const std::string& policy_name, | 257 const std::string& policy_name, |
129 const base::ListValue* policy_value) OVERRIDE; | 258 const base::ListValue* policy_value) OVERRIDE; |
130 virtual void InstallDictionaryPolicy( | 259 virtual void InstallDictionaryPolicy( |
131 const std::string& policy_name, | 260 const std::string& policy_name, |
132 const base::DictionaryValue* policy_value) OVERRIDE; | 261 const base::DictionaryValue* policy_value) OVERRIDE; |
262 virtual void Install3rdPartyPolicy( | |
263 const base::DictionaryValue* policies) OVERRIDE; | |
133 | 264 |
134 // Creates a harness instance that will install policy in HKCU or HKLM, | 265 // Creates a harness instance that will install policy in HKCU or HKLM, |
135 // respectively. | 266 // respectively. |
136 static PolicyProviderTestHarness* CreateHKCU(); | 267 static PolicyProviderTestHarness* CreateHKCU(); |
137 static PolicyProviderTestHarness* CreateHKLM(); | 268 static PolicyProviderTestHarness* CreateHKLM(); |
138 | 269 |
139 private: | 270 private: |
140 HKEY hive_; | 271 HKEY hive_; |
141 | 272 |
142 ScopedGroupPolicyRegistrySandbox registry_sandbox_; | 273 ScopedGroupPolicyRegistrySandbox registry_sandbox_; |
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
240 void TestHarness::InstallDictionaryPolicy( | 371 void TestHarness::InstallDictionaryPolicy( |
241 const std::string& policy_name, | 372 const std::string& policy_name, |
242 const base::DictionaryValue* policy_value) { | 373 const base::DictionaryValue* policy_value) { |
243 std::string json; | 374 std::string json; |
244 base::JSONWriter::Write(policy_value, &json); | 375 base::JSONWriter::Write(policy_value, &json); |
245 RegKey key(hive_, kRegistryMandatorySubKey, KEY_ALL_ACCESS); | 376 RegKey key(hive_, kRegistryMandatorySubKey, KEY_ALL_ACCESS); |
246 key.WriteValue(UTF8ToUTF16(policy_name).c_str(), | 377 key.WriteValue(UTF8ToUTF16(policy_name).c_str(), |
247 UTF8ToUTF16(json).c_str()); | 378 UTF8ToUTF16(json).c_str()); |
248 } | 379 } |
249 | 380 |
381 void TestHarness::Install3rdPartyPolicy(const base::DictionaryValue* policies) { | |
382 // The first level entries are domains, and the second level entries map | |
383 // components to their policy. | |
384 const string16 kPathPrefix = string16(kRegistryMandatorySubKey) + kPathSep + | |
385 kThirdParty + kPathSep; | |
386 for (base::DictionaryValue::Iterator domain(*policies); | |
387 domain.HasNext(); domain.Advance()) { | |
388 const base::DictionaryValue* components = NULL; | |
389 if (!domain.value().GetAsDictionary(&components)) { | |
390 ADD_FAILURE(); | |
391 continue; | |
392 } | |
393 for (base::DictionaryValue::Iterator component(*components); | |
394 component.HasNext(); component.Advance()) { | |
395 const string16 path = string16(kRegistryMandatorySubKey) + kPathSep + | |
396 kThirdParty + kPathSep + | |
397 UTF8ToUTF16(domain.key()) + kPathSep + | |
398 UTF8ToUTF16(component.key()); | |
399 InstallValue(component.value(), hive_, path, kMandatory); | |
400 EXPECT_TRUE(InstallSchema(component.value(), hive_, path, kSchema)); | |
401 } | |
402 } | |
403 } | |
404 | |
250 // static | 405 // static |
251 PolicyProviderTestHarness* TestHarness::CreateHKCU() { | 406 PolicyProviderTestHarness* TestHarness::CreateHKCU() { |
252 return new TestHarness(HKEY_CURRENT_USER, POLICY_SCOPE_USER); | 407 return new TestHarness(HKEY_CURRENT_USER, POLICY_SCOPE_USER); |
253 } | 408 } |
254 | 409 |
255 // static | 410 // static |
256 PolicyProviderTestHarness* TestHarness::CreateHKLM() { | 411 PolicyProviderTestHarness* TestHarness::CreateHKLM() { |
257 return new TestHarness(HKEY_LOCAL_MACHINE, POLICY_SCOPE_MACHINE); | 412 return new TestHarness(HKEY_LOCAL_MACHINE, POLICY_SCOPE_MACHINE); |
258 } | 413 } |
259 | 414 |
260 } // namespace | 415 } // namespace |
261 | 416 |
262 // Instantiate abstract test case for basic policy reading tests. | 417 // Instantiate abstract test case for basic policy reading tests. |
263 INSTANTIATE_TEST_CASE_P( | 418 INSTANTIATE_TEST_CASE_P( |
264 PolicyProviderWinTest, | 419 PolicyProviderWinTest, |
265 ConfigurationPolicyProviderTest, | 420 ConfigurationPolicyProviderTest, |
266 testing::Values(TestHarness::CreateHKCU, TestHarness::CreateHKLM)); | 421 testing::Values(TestHarness::CreateHKCU, TestHarness::CreateHKLM)); |
267 | 422 |
423 // Instantiate abstract test case for 3rd party policy reading tests. | |
424 INSTANTIATE_TEST_CASE_P( | |
425 ThirdPartyPolicyProviderWinTest, | |
426 Configuration3rdPartyPolicyProviderTest, | |
427 testing::Values(TestHarness::CreateHKCU, TestHarness::CreateHKLM)); | |
428 | |
268 // Test cases for windows policy provider specific functionality. | 429 // Test cases for windows policy provider specific functionality. |
269 class PolicyLoaderWinTest : public PolicyTestBase { | 430 class PolicyLoaderWinTest : public PolicyTestBase { |
270 protected: | 431 protected: |
271 PolicyLoaderWinTest() {} | 432 PolicyLoaderWinTest() {} |
272 virtual ~PolicyLoaderWinTest() {} | 433 virtual ~PolicyLoaderWinTest() {} |
273 | 434 |
435 bool Matches(const PolicyBundle& expected) { | |
436 PolicyLoaderWin loader(&test_policy_definitions::kList); | |
437 scoped_ptr<PolicyBundle> loaded(loader.Load()); | |
438 return loaded->Equals(expected); | |
439 } | |
440 | |
274 ScopedGroupPolicyRegistrySandbox registry_sandbox_; | 441 ScopedGroupPolicyRegistrySandbox registry_sandbox_; |
275 }; | 442 }; |
276 | 443 |
277 TEST_F(PolicyLoaderWinTest, HKLMOverHKCU) { | 444 TEST_F(PolicyLoaderWinTest, HKLMOverHKCU) { |
278 RegKey hklm_key(HKEY_LOCAL_MACHINE, kRegistryMandatorySubKey, KEY_ALL_ACCESS); | 445 RegKey hklm_key(HKEY_LOCAL_MACHINE, kRegistryMandatorySubKey, KEY_ALL_ACCESS); |
279 hklm_key.WriteValue(UTF8ToUTF16(test_policy_definitions::kKeyString).c_str(), | 446 hklm_key.WriteValue(UTF8ToUTF16(test_policy_definitions::kKeyString).c_str(), |
280 UTF8ToUTF16("hklm").c_str()); | 447 UTF8ToUTF16("hklm").c_str()); |
281 RegKey hkcu_key(HKEY_CURRENT_USER, kRegistryMandatorySubKey, KEY_ALL_ACCESS); | 448 RegKey hkcu_key(HKEY_CURRENT_USER, kRegistryMandatorySubKey, KEY_ALL_ACCESS); |
282 hkcu_key.WriteValue(UTF8ToUTF16(test_policy_definitions::kKeyString).c_str(), | 449 hkcu_key.WriteValue(UTF8ToUTF16(test_policy_definitions::kKeyString).c_str(), |
283 UTF8ToUTF16("hkcu").c_str()); | 450 UTF8ToUTF16("hkcu").c_str()); |
284 | 451 |
285 PolicyLoaderWin loader(&test_policy_definitions::kList); | 452 PolicyBundle expected; |
286 scoped_ptr<PolicyBundle> bundle(loader.Load()); | 453 expected.Get(POLICY_DOMAIN_CHROME, "") |
287 | |
288 PolicyBundle expected_bundle; | |
289 expected_bundle.Get(POLICY_DOMAIN_CHROME, "") | |
290 .Set(test_policy_definitions::kKeyString, | 454 .Set(test_policy_definitions::kKeyString, |
291 POLICY_LEVEL_MANDATORY, | 455 POLICY_LEVEL_MANDATORY, |
292 POLICY_SCOPE_MACHINE, | 456 POLICY_SCOPE_MACHINE, |
293 base::Value::CreateStringValue("hklm")); | 457 base::Value::CreateStringValue("hklm")); |
294 EXPECT_TRUE(bundle->Equals(expected_bundle)); | 458 EXPECT_TRUE(Matches(expected)); |
295 } | 459 } |
296 | 460 |
297 // TODO(joaodasilva): share tests for 3rd party policy with | 461 TEST_F(PolicyLoaderWinTest, Load3rdPartyWithoutSchema) { |
298 // ConfigDirPolicyProvider once PolicyLoaderWin is able to load all types. | |
299 TEST_F(PolicyLoaderWinTest, Load3rdParty) { | |
300 base::DictionaryValue dict; | 462 base::DictionaryValue dict; |
301 dict.SetString("str", "string value"); | 463 dict.SetString("str", "string value"); |
302 dict.SetInteger("int", 123); | 464 dict.SetInteger("int", 123); |
303 dict.Set("subdict", dict.DeepCopy()); | 465 dict.Set("subdict", dict.DeepCopy()); |
304 dict.Set("subsubdict", dict.DeepCopy()); | 466 dict.Set("subsubdict", dict.DeepCopy()); |
305 dict.Set("subsubsubdict", dict.DeepCopy()); | 467 dict.Set("subsubsubdict", dict.DeepCopy()); |
306 | 468 |
307 base::DictionaryValue policy_dict; | 469 base::DictionaryValue policy_dict; |
308 policy_dict.Set("3rdparty.extensions.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.policy", | 470 policy_dict.Set("extensions.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.policy", |
309 dict.DeepCopy()); | 471 dict.DeepCopy()); |
310 policy_dict.Set("3rdparty.extensions.bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.policy", | 472 policy_dict.Set("extensions.bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.policy", |
311 dict.DeepCopy()); | 473 dict.DeepCopy()); |
312 EXPECT_TRUE(InstallDictionary(policy_dict, HKEY_LOCAL_MACHINE, | 474 EXPECT_TRUE(InstallValue(policy_dict, HKEY_LOCAL_MACHINE, |
313 kRegistryMandatorySubKey)); | 475 kRegistryMandatorySubKey, kThirdParty)); |
314 | 476 |
315 PolicyBundle expected; | 477 PolicyBundle expected; |
316 expected.Get(POLICY_DOMAIN_EXTENSIONS, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") | 478 expected.Get(POLICY_DOMAIN_EXTENSIONS, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") |
317 .LoadFrom(&dict, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE); | 479 .LoadFrom(&dict, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE); |
318 expected.Get(POLICY_DOMAIN_EXTENSIONS, "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb") | 480 expected.Get(POLICY_DOMAIN_EXTENSIONS, "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb") |
319 .LoadFrom(&dict, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE); | 481 .LoadFrom(&dict, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE); |
320 | 482 EXPECT_TRUE(Matches(expected)); |
321 PolicyLoaderWin loader(&test_policy_definitions::kList); | |
322 scoped_ptr<PolicyBundle> loaded(loader.Load()); | |
323 EXPECT_TRUE(loaded->Equals(expected)); | |
324 } | 483 } |
325 | 484 |
326 TEST_F(PolicyLoaderWinTest, Merge3rdPartyPolicies) { | 485 TEST_F(PolicyLoaderWinTest, Merge3rdPartyPolicies) { |
327 // Policy for the same extension will be provided at the 4 level/scope | 486 // Policy for the same extension will be provided at the 4 level/scope |
328 // combinations, to verify that they overlap as expected. | 487 // combinations, to verify that they overlap as expected. |
329 | 488 |
330 const string16 kPathSuffix = | 489 const string16 kPathSuffix = |
331 kRegistryMandatorySubKey + ASCIIToUTF16("\\3rdparty\\extensions\\merge"); | 490 kRegistryMandatorySubKey + ASCIIToUTF16("\\3rdparty\\extensions\\merge"); |
332 const string16 kMandatoryPath = kPathSuffix + ASCIIToUTF16("\\policy"); | |
333 const string16 kRecommendedPath = kPathSuffix + ASCIIToUTF16("\\recommended"); | |
334 | 491 |
335 const char kUserMandatory[] = "user-mandatory"; | 492 const char kUserMandatory[] = "user-mandatory"; |
336 const char kUserRecommended[] = "user-recommended"; | 493 const char kUserRecommended[] = "user-recommended"; |
337 const char kMachineMandatory[] = "machine-mandatory"; | 494 const char kMachineMandatory[] = "machine-mandatory"; |
338 const char kMachineRecommended[] = "machine-recommended"; | 495 const char kMachineRecommended[] = "machine-recommended"; |
339 | 496 |
340 base::DictionaryValue policy; | 497 base::DictionaryValue policy; |
341 policy.SetString("a", kMachineMandatory); | 498 policy.SetString("a", kMachineMandatory); |
342 EXPECT_TRUE(InstallDictionary(policy, HKEY_LOCAL_MACHINE, kMandatoryPath)); | 499 EXPECT_TRUE(InstallValue(policy, HKEY_LOCAL_MACHINE, |
500 kPathSuffix, kMandatory)); | |
343 policy.SetString("a", kUserMandatory); | 501 policy.SetString("a", kUserMandatory); |
344 policy.SetString("b", kUserMandatory); | 502 policy.SetString("b", kUserMandatory); |
345 EXPECT_TRUE(InstallDictionary(policy, HKEY_CURRENT_USER, kMandatoryPath)); | 503 EXPECT_TRUE(InstallValue(policy, HKEY_CURRENT_USER, |
504 kPathSuffix, kMandatory)); | |
346 policy.SetString("a", kMachineRecommended); | 505 policy.SetString("a", kMachineRecommended); |
347 policy.SetString("b", kMachineRecommended); | 506 policy.SetString("b", kMachineRecommended); |
348 policy.SetString("c", kMachineRecommended); | 507 policy.SetString("c", kMachineRecommended); |
349 EXPECT_TRUE(InstallDictionary(policy, HKEY_LOCAL_MACHINE, kRecommendedPath)); | 508 EXPECT_TRUE(InstallValue(policy, HKEY_LOCAL_MACHINE, |
509 kPathSuffix, kRecommended)); | |
350 policy.SetString("a", kUserRecommended); | 510 policy.SetString("a", kUserRecommended); |
351 policy.SetString("b", kUserRecommended); | 511 policy.SetString("b", kUserRecommended); |
352 policy.SetString("c", kUserRecommended); | 512 policy.SetString("c", kUserRecommended); |
353 policy.SetString("d", kUserRecommended); | 513 policy.SetString("d", kUserRecommended); |
354 EXPECT_TRUE(InstallDictionary(policy, HKEY_CURRENT_USER, kRecommendedPath)); | 514 EXPECT_TRUE(InstallValue(policy, HKEY_CURRENT_USER, |
515 kPathSuffix, kRecommended)); | |
355 | 516 |
356 PolicyBundle expected; | 517 PolicyBundle expected; |
357 PolicyMap& expected_policy = expected.Get(POLICY_DOMAIN_EXTENSIONS, "merge"); | 518 PolicyMap& expected_policy = expected.Get(POLICY_DOMAIN_EXTENSIONS, "merge"); |
358 expected_policy.Set("a", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, | 519 expected_policy.Set("a", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, |
359 base::Value::CreateStringValue(kMachineMandatory)); | 520 base::Value::CreateStringValue(kMachineMandatory)); |
360 expected_policy.Set("b", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, | 521 expected_policy.Set("b", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, |
361 base::Value::CreateStringValue(kUserMandatory)); | 522 base::Value::CreateStringValue(kUserMandatory)); |
362 expected_policy.Set("c", POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_MACHINE, | 523 expected_policy.Set("c", POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_MACHINE, |
363 base::Value::CreateStringValue(kMachineRecommended)); | 524 base::Value::CreateStringValue(kMachineRecommended)); |
364 expected_policy.Set("d", POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER, | 525 expected_policy.Set("d", POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER, |
365 base::Value::CreateStringValue(kUserRecommended)); | 526 base::Value::CreateStringValue(kUserRecommended)); |
527 EXPECT_TRUE(Matches(expected)); | |
528 } | |
366 | 529 |
367 PolicyLoaderWin loader(&test_policy_definitions::kList); | 530 TEST_F(PolicyLoaderWinTest, LoadStringEncodedValues) { |
368 scoped_ptr<PolicyBundle> loaded(loader.Load()); | 531 // Create a dictionary with all the types that can be stored encoded in a |
369 EXPECT_TRUE(loaded->Equals(expected)); | 532 // string, to pass to InstallSchema(). Also build an equivalent dictionary |
533 // with the encoded values, to pass to InstallValue(). | |
534 base::DictionaryValue policy; | |
535 policy.Set("null", base::Value::CreateNullValue()); | |
536 policy.SetBoolean("bool", true); | |
537 policy.SetInteger("int", -123); | |
538 policy.SetDouble("double", 456.78e9); | |
539 base::ListValue list; | |
540 list.Append(policy.DeepCopy()); | |
541 list.Append(policy.DeepCopy()); | |
542 policy.Set("list", list.DeepCopy()); | |
543 // Encode |policy| before adding the "dict" entry. | |
544 std::string encoded_dict; | |
545 base::JSONWriter::Write(&policy, &encoded_dict); | |
546 ASSERT_FALSE(encoded_dict.empty()); | |
547 policy.Set("dict", policy.DeepCopy()); | |
548 | |
549 std::string encoded_list; | |
550 base::JSONWriter::Write(&list, &encoded_list); | |
551 ASSERT_FALSE(encoded_list.empty()); | |
552 base::DictionaryValue encoded_policy; | |
553 encoded_policy.SetString("null", ""); | |
554 encoded_policy.SetString("bool", "1"); | |
555 encoded_policy.SetString("int", "-123"); | |
556 encoded_policy.SetString("double", "456.78e9"); | |
557 encoded_policy.SetString("list", encoded_list); | |
558 encoded_policy.SetString("dict", encoded_dict); | |
559 | |
560 const string16 kPathSuffix = | |
561 kRegistryMandatorySubKey + ASCIIToUTF16("\\3rdparty\\extensions\\string"); | |
562 EXPECT_TRUE(InstallSchema(policy, HKEY_CURRENT_USER, kPathSuffix, kSchema)); | |
563 EXPECT_TRUE( | |
564 InstallValue(encoded_policy, HKEY_CURRENT_USER, kPathSuffix, kMandatory)); | |
565 | |
566 PolicyBundle expected; | |
567 expected.Get(POLICY_DOMAIN_EXTENSIONS, "string") | |
568 .LoadFrom(&policy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER); | |
569 EXPECT_TRUE(Matches(expected)); | |
570 } | |
571 | |
572 TEST_F(PolicyLoaderWinTest, LoadIntegerEncodedValues) { | |
573 base::DictionaryValue policy; | |
574 policy.SetBoolean("bool", true); | |
575 policy.SetInteger("int", 123); | |
576 policy.SetDouble("double", 456.0); | |
577 | |
578 base::DictionaryValue encoded_policy; | |
579 encoded_policy.SetInteger("bool", 1); | |
580 encoded_policy.SetInteger("int", 123); | |
581 encoded_policy.SetInteger("double", 456); | |
582 | |
583 const string16 kPathSuffix = | |
584 kRegistryMandatorySubKey + ASCIIToUTF16("\\3rdparty\\extensions\\int"); | |
585 EXPECT_TRUE(InstallSchema(policy, HKEY_CURRENT_USER, kPathSuffix, kSchema)); | |
586 EXPECT_TRUE( | |
587 InstallValue(encoded_policy, HKEY_CURRENT_USER, kPathSuffix, kMandatory)); | |
588 | |
589 PolicyBundle expected; | |
590 expected.Get(POLICY_DOMAIN_EXTENSIONS, "int") | |
591 .LoadFrom(&policy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER); | |
592 EXPECT_TRUE(Matches(expected)); | |
593 } | |
594 | |
595 TEST_F(PolicyLoaderWinTest, DefaultPropertySchemaType) { | |
596 // Build a schema for an "object" with a default schema for its properties. | |
597 base::DictionaryValue default_schema; | |
598 default_schema.SetString(kType, "number"); | |
599 base::DictionaryValue integer_schema; | |
600 integer_schema.SetString(kType, "integer"); | |
601 base::DictionaryValue properties; | |
602 properties.Set("special-int1", integer_schema.DeepCopy()); | |
603 properties.Set("special-int2", integer_schema.DeepCopy()); | |
604 base::DictionaryValue schema; | |
605 schema.SetString(kType, "object"); | |
606 schema.Set(kProperties, properties.DeepCopy()); | |
607 schema.Set(kAdditionalProperties, default_schema.DeepCopy()); | |
608 | |
609 const string16 kPathSuffix = | |
610 kRegistryMandatorySubKey + ASCIIToUTF16("\\3rdparty\\extensions\\test"); | |
611 EXPECT_TRUE(WriteSchema(schema, HKEY_CURRENT_USER, kPathSuffix, kSchema)); | |
612 | |
613 // Write some test values. | |
614 base::DictionaryValue policy; | |
615 // These special values have a specific schema for them. | |
616 policy.SetInteger("special-int1", 123); | |
617 policy.SetString("special-int2", "-456"); | |
618 // Other values default to be loaded as doubles. | |
619 policy.SetInteger("double1", 789.0); | |
620 policy.SetString("double2", "123.456e7"); | |
621 policy.SetString("invalid", "omg"); | |
622 EXPECT_TRUE(InstallValue(policy, HKEY_CURRENT_USER, kPathSuffix, kMandatory)); | |
623 | |
624 base::DictionaryValue expected_policy; | |
625 expected_policy.SetInteger("special-int1", 123); | |
626 expected_policy.SetInteger("special-int2", -456); | |
627 expected_policy.SetDouble("double1", 789.0); | |
628 expected_policy.SetDouble("double2", 123.456e7); | |
629 PolicyBundle expected; | |
630 expected.Get(POLICY_DOMAIN_EXTENSIONS, "test") | |
631 .LoadFrom(&expected_policy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER); | |
632 EXPECT_TRUE(Matches(expected)); | |
370 } | 633 } |
371 | 634 |
372 } // namespace policy | 635 } // namespace policy |
OLD | NEW |