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