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 3 // found in the LICENSE file. 4 5 #include "components/policy/core/common/policy_loader_win.h" 6 7 #include <windows.h> 8 #include <userenv.h> 9 10 #include <algorithm> 11 #include <cstring> 12 #include <functional> 13 #include <iterator> 14 #include <vector> 15 16 #include "base/base_paths.h" 17 #include "base/callback.h" 18 #include "base/files/file_path.h" 19 #include "base/files/file_util.h" 20 #include "base/files/scoped_temp_dir.h" 21 #include "base/json/json_writer.h" 22 #include "base/path_service.h" 23 #include "base/process/process.h" 24 #include "base/strings/string16.h" 25 #include "base/strings/string_number_conversions.h" 26 #include "base/strings/string_util.h" 27 #include "base/strings/stringprintf.h" 28 #include "base/strings/utf_string_conversions.h" 29 #include "base/sys_byteorder.h" 30 #include "base/win/registry.h" 31 #include "base/win/win_util.h" 32 #include "components/policy/core/common/async_policy_provider.h" 33 #include "components/policy/core/common/configuration_policy_provider_test.h" 34 #include "components/policy/core/common/external_data_fetcher.h" 35 #include "components/policy/core/common/policy_bundle.h" 36 #include "components/policy/core/common/policy_map.h" 37 #include "components/policy/core/common/preg_parser_win.h" 38 #include "components/policy/core/common/schema_map.h" 39 #include "testing/gtest/include/gtest/gtest.h" 40 41 using base::UTF8ToUTF16; 42 using base::UTF16ToUTF8; 43 using base::win::RegKey; 44 45 namespace policy { 46 47 namespace { 48 49 // Constants for registry key names. 50 const wchar_t kPathSep[] = L"\\"; 51 const wchar_t kThirdParty[] = L"3rdparty"; 52 const wchar_t kMandatory[] = L"policy"; 53 const wchar_t kRecommended[] = L"recommended"; 54 const char kSchema[] = "schema"; 55 const wchar_t kTestPolicyKey[] = L"chrome.policy.key"; 56 57 // Installs |value| in the given registry |path| and |hive|, under the key 58 // |name|. Returns false on errors. 59 // 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 61 // is written. 62 bool InstallValue(const base::Value& value, 63 HKEY hive, 64 const base::string16& path, 65 const base::string16& name) { 66 // KEY_ALL_ACCESS causes the ctor to create the key if it does not exist yet. 67 RegKey key(hive, path.c_str(), KEY_ALL_ACCESS); 68 EXPECT_TRUE(key.Valid()); 69 switch (value.GetType()) { 70 case base::Value::TYPE_NULL: 71 return key.WriteValue(name.c_str(), L"") == ERROR_SUCCESS; 72 73 case base::Value::TYPE_BOOLEAN: { 74 bool bool_value; 75 if (!value.GetAsBoolean(&bool_value)) 76 return false; 77 return key.WriteValue(name.c_str(), bool_value ? 1 : 0) == ERROR_SUCCESS; 78 } 79 80 case base::Value::TYPE_INTEGER: { 81 int int_value; 82 if (!value.GetAsInteger(&int_value)) 83 return false; 84 return key.WriteValue(name.c_str(), int_value) == ERROR_SUCCESS; 85 } 86 87 case base::Value::TYPE_DOUBLE: { 88 double double_value; 89 if (!value.GetAsDouble(&double_value)) 90 return false; 91 base::string16 str_value = 92 UTF8ToUTF16(base::DoubleToString(double_value)); 93 return key.WriteValue(name.c_str(), str_value.c_str()) == ERROR_SUCCESS; 94 } 95 96 case base::Value::TYPE_STRING: { 97 base::string16 str_value; 98 if (!value.GetAsString(&str_value)) 99 return false; 100 return key.WriteValue(name.c_str(), str_value.c_str()) == ERROR_SUCCESS; 101 } 102 103 case base::Value::TYPE_DICTIONARY: { 104 const base::DictionaryValue* sub_dict = NULL; 105 if (!value.GetAsDictionary(&sub_dict)) 106 return false; 107 for (base::DictionaryValue::Iterator it(*sub_dict); 108 !it.IsAtEnd(); it.Advance()) { 109 if (!InstallValue(it.value(), hive, path + kPathSep + name, 110 UTF8ToUTF16(it.key()))) { 111 return false; 112 } 113 } 114 return true; 115 } 116 117 case base::Value::TYPE_LIST: { 118 const base::ListValue* list = NULL; 119 if (!value.GetAsList(&list)) 120 return false; 121 for (size_t i = 0; i < list->GetSize(); ++i) { 122 const base::Value* item; 123 if (!list->Get(i, &item)) 124 return false; 125 if (!InstallValue(*item, hive, path + kPathSep + name, 126 base::UintToString16(i + 1))) { 127 return false; 128 } 129 } 130 return true; 131 } 132 133 case base::Value::TYPE_BINARY: 134 return false; 135 } 136 NOTREACHED(); 137 return false; 138 } 139 140 // This class provides sandboxing and mocking for the parts of the Windows 141 // Registry implementing Group Policy. It prepares two temporary sandbox keys, 142 // one for HKLM and one for HKCU. A test's calls to the registry are redirected 143 // by Windows to these sandboxes, allowing the tests to manipulate and access 144 // policy as if it were active, but without actually changing the parts of the 145 // Registry that are managed by Group Policy. 146 class ScopedGroupPolicyRegistrySandbox { 147 public: 148 ScopedGroupPolicyRegistrySandbox(); 149 ~ScopedGroupPolicyRegistrySandbox(); 150 151 private: 152 void ActivateOverrides(); 153 void RemoveOverrides(); 154 155 // Deletes the sandbox keys. 156 void DeleteKeys(); 157 158 std::wstring key_name_; 159 160 // Keys are created for the lifetime of a test to contain 161 // the sandboxed HKCU and HKLM hives, respectively. 162 RegKey temp_hkcu_hive_key_; 163 RegKey temp_hklm_hive_key_; 164 165 DISALLOW_COPY_AND_ASSIGN(ScopedGroupPolicyRegistrySandbox); 166 }; 167 168 // A test harness that feeds policy via the Chrome GPO registry subtree. 169 class RegistryTestHarness : public PolicyProviderTestHarness, 170 public AppliedGPOListProvider { 171 public: 172 RegistryTestHarness(HKEY hive, PolicyScope scope); 173 virtual ~RegistryTestHarness(); 174 175 // PolicyProviderTestHarness: 176 virtual void SetUp() OVERRIDE; 177 178 virtual ConfigurationPolicyProvider* CreateProvider( 179 SchemaRegistry* registry, 180 scoped_refptr<base::SequencedTaskRunner> task_runner) OVERRIDE; 181 182 virtual void InstallEmptyPolicy() OVERRIDE; 183 virtual void InstallStringPolicy(const std::string& policy_name, 184 const std::string& policy_value) OVERRIDE; 185 virtual void InstallIntegerPolicy(const std::string& policy_name, 186 int policy_value) OVERRIDE; 187 virtual void InstallBooleanPolicy(const std::string& policy_name, 188 bool policy_value) OVERRIDE; 189 virtual void InstallStringListPolicy( 190 const std::string& policy_name, 191 const base::ListValue* policy_value) OVERRIDE; 192 virtual void InstallDictionaryPolicy( 193 const std::string& policy_name, 194 const base::DictionaryValue* policy_value) OVERRIDE; 195 virtual void Install3rdPartyPolicy( 196 const base::DictionaryValue* policies) OVERRIDE; 197 198 // AppliedGPOListProvider: 199 virtual DWORD GetAppliedGPOList(DWORD flags, 200 LPCTSTR machine_name, 201 PSID sid_user, 202 GUID* extension_guid, 203 PGROUP_POLICY_OBJECT* gpo_list) OVERRIDE; 204 virtual BOOL FreeGPOList(PGROUP_POLICY_OBJECT gpo_list) OVERRIDE; 205 206 // Creates a harness instance that will install policy in HKCU or HKLM, 207 // respectively. 208 static PolicyProviderTestHarness* CreateHKCU(); 209 static PolicyProviderTestHarness* CreateHKLM(); 210 211 private: 212 HKEY hive_; 213 214 ScopedGroupPolicyRegistrySandbox registry_sandbox_; 215 216 DISALLOW_COPY_AND_ASSIGN(RegistryTestHarness); 217 }; 218 219 // A test harness that generates PReg files for the provider to read. 220 class PRegTestHarness : public PolicyProviderTestHarness, 221 public AppliedGPOListProvider { 222 public: 223 PRegTestHarness(); 224 virtual ~PRegTestHarness(); 225 226 // PolicyProviderTestHarness: 227 virtual void SetUp() OVERRIDE; 228 229 virtual ConfigurationPolicyProvider* CreateProvider( 230 SchemaRegistry* registry, 231 scoped_refptr<base::SequencedTaskRunner> task_runner) OVERRIDE; 232 233 virtual void InstallEmptyPolicy() OVERRIDE; 234 virtual void InstallStringPolicy(const std::string& policy_name, 235 const std::string& policy_value) OVERRIDE; 236 virtual void InstallIntegerPolicy(const std::string& policy_name, 237 int policy_value) OVERRIDE; 238 virtual void InstallBooleanPolicy(const std::string& policy_name, 239 bool policy_value) OVERRIDE; 240 virtual void InstallStringListPolicy( 241 const std::string& policy_name, 242 const base::ListValue* policy_value) OVERRIDE; 243 virtual void InstallDictionaryPolicy( 244 const std::string& policy_name, 245 const base::DictionaryValue* policy_value) OVERRIDE; 246 virtual void Install3rdPartyPolicy( 247 const base::DictionaryValue* policies) OVERRIDE; 248 249 // AppliedGPOListProvider: 250 virtual DWORD GetAppliedGPOList(DWORD flags, 251 LPCTSTR machine_name, 252 PSID sid_user, 253 GUID* extension_guid, 254 PGROUP_POLICY_OBJECT* gpo_list) OVERRIDE; 255 virtual BOOL FreeGPOList(PGROUP_POLICY_OBJECT gpo_list) OVERRIDE; 256 257 // Creates a harness instance. 258 static PolicyProviderTestHarness* Create(); 259 260 private: 261 // Helper to append a base::string16 to an uint8 buffer. 262 static void AppendChars(std::vector<uint8>* buffer, 263 const base::string16& chars); 264 265 // Appends a record with the given fields to the PReg file. 266 void AppendRecordToPRegFile(const base::string16& path, 267 const std::string& key, 268 DWORD type, 269 DWORD size, 270 uint8* data); 271 272 // Appends the given DWORD |value| for |path| + |key| to the PReg file. 273 void AppendDWORDToPRegFile(const base::string16& path, 274 const std::string& key, 275 DWORD value); 276 277 // Appends the given string |value| for |path| + |key| to the PReg file. 278 void AppendStringToPRegFile(const base::string16& path, 279 const std::string& key, 280 const std::string& value); 281 282 // Appends the given policy |value| for |path| + |key| to the PReg file, 283 // converting and recursing as necessary. 284 void AppendPolicyToPRegFile(const base::string16& path, 285 const std::string& key, 286 const base::Value* value); 287 288 base::ScopedTempDir temp_dir_; 289 base::FilePath preg_file_path_; 290 GROUP_POLICY_OBJECT gpo_; 291 292 DISALLOW_COPY_AND_ASSIGN(PRegTestHarness); 293 }; 294 295 ScopedGroupPolicyRegistrySandbox::ScopedGroupPolicyRegistrySandbox() { 296 // Generate a unique registry key for the override for each test. This 297 // makes sure that tests executing in parallel won't delete each other's 298 // key, at DeleteKeys(). 299 key_name_ = base::ASCIIToWide(base::StringPrintf( 300 "SOFTWARE\\chromium unittest %d", 301 base::Process::Current().pid())); 302 std::wstring hklm_key_name = key_name_ + L"\\HKLM"; 303 std::wstring hkcu_key_name = key_name_ + L"\\HKCU"; 304 305 // Create the subkeys to hold the overridden HKLM and HKCU 306 // policy settings. 307 temp_hklm_hive_key_.Create(HKEY_CURRENT_USER, 308 hklm_key_name.c_str(), 309 KEY_ALL_ACCESS); 310 temp_hkcu_hive_key_.Create(HKEY_CURRENT_USER, 311 hkcu_key_name.c_str(), 312 KEY_ALL_ACCESS); 313 314 ActivateOverrides(); 315 } 316 317 ScopedGroupPolicyRegistrySandbox::~ScopedGroupPolicyRegistrySandbox() { 318 RemoveOverrides(); 319 DeleteKeys(); 320 } 321 322 void ScopedGroupPolicyRegistrySandbox::ActivateOverrides() { 323 ASSERT_HRESULT_SUCCEEDED(RegOverridePredefKey(HKEY_LOCAL_MACHINE, 324 temp_hklm_hive_key_.Handle())); 325 ASSERT_HRESULT_SUCCEEDED(RegOverridePredefKey(HKEY_CURRENT_USER, 326 temp_hkcu_hive_key_.Handle())); 327 } 328 329 void ScopedGroupPolicyRegistrySandbox::RemoveOverrides() { 330 ASSERT_HRESULT_SUCCEEDED(RegOverridePredefKey(HKEY_LOCAL_MACHINE, 0)); 331 ASSERT_HRESULT_SUCCEEDED(RegOverridePredefKey(HKEY_CURRENT_USER, 0)); 332 } 333 334 void ScopedGroupPolicyRegistrySandbox::DeleteKeys() { 335 RegKey key(HKEY_CURRENT_USER, key_name_.c_str(), KEY_ALL_ACCESS); 336 ASSERT_TRUE(key.Valid()); 337 key.DeleteKey(L""); 338 } 339 340 RegistryTestHarness::RegistryTestHarness(HKEY hive, PolicyScope scope) 341 : PolicyProviderTestHarness(POLICY_LEVEL_MANDATORY, scope), hive_(hive) {} 342 343 RegistryTestHarness::~RegistryTestHarness() {} 344 345 void RegistryTestHarness::SetUp() {} 346 347 ConfigurationPolicyProvider* RegistryTestHarness::CreateProvider( 348 SchemaRegistry* registry, 349 scoped_refptr<base::SequencedTaskRunner> task_runner) { 350 base::win::SetDomainStateForTesting(true); 351 scoped_ptr<AsyncPolicyLoader> loader( 352 new PolicyLoaderWin(task_runner, kTestPolicyKey, this)); 353 return new AsyncPolicyProvider(registry, loader.Pass()); 354 } 355 356 void RegistryTestHarness::InstallEmptyPolicy() {} 357 358 void RegistryTestHarness::InstallStringPolicy( 359 const std::string& policy_name, 360 const std::string& policy_value) { 361 RegKey key(hive_, kTestPolicyKey, KEY_ALL_ACCESS); 362 ASSERT_TRUE(key.Valid()); 363 ASSERT_HRESULT_SUCCEEDED(key.WriteValue(UTF8ToUTF16(policy_name).c_str(), 364 UTF8ToUTF16(policy_value).c_str())); 365 } 366 367 void RegistryTestHarness::InstallIntegerPolicy( 368 const std::string& policy_name, 369 int policy_value) { 370 RegKey key(hive_, kTestPolicyKey, KEY_ALL_ACCESS); 371 ASSERT_TRUE(key.Valid()); 372 key.WriteValue(UTF8ToUTF16(policy_name).c_str(), 373 static_cast<DWORD>(policy_value)); 374 } 375 376 void RegistryTestHarness::InstallBooleanPolicy( 377 const std::string& policy_name, 378 bool policy_value) { 379 RegKey key(hive_, kTestPolicyKey, KEY_ALL_ACCESS); 380 ASSERT_TRUE(key.Valid()); 381 key.WriteValue(UTF8ToUTF16(policy_name).c_str(), 382 static_cast<DWORD>(policy_value)); 383 } 384 385 void RegistryTestHarness::InstallStringListPolicy( 386 const std::string& policy_name, 387 const base::ListValue* policy_value) { 388 RegKey key(hive_, 389 (base::string16(kTestPolicyKey) + base::ASCIIToUTF16("\\") + 390 UTF8ToUTF16(policy_name)).c_str(), 391 KEY_ALL_ACCESS); 392 ASSERT_TRUE(key.Valid()); 393 int index = 1; 394 for (base::ListValue::const_iterator element(policy_value->begin()); 395 element != policy_value->end(); 396 ++element) { 397 std::string element_value; 398 if (!(*element)->GetAsString(&element_value)) 399 continue; 400 std::string name(base::IntToString(index++)); 401 key.WriteValue(UTF8ToUTF16(name).c_str(), 402 UTF8ToUTF16(element_value).c_str()); 403 } 404 } 405 406 void RegistryTestHarness::InstallDictionaryPolicy( 407 const std::string& policy_name, 408 const base::DictionaryValue* policy_value) { 409 std::string json; 410 base::JSONWriter::Write(policy_value, &json); 411 RegKey key(hive_, kTestPolicyKey, KEY_ALL_ACCESS); 412 ASSERT_TRUE(key.Valid()); 413 key.WriteValue(UTF8ToUTF16(policy_name).c_str(), 414 UTF8ToUTF16(json).c_str()); 415 } 416 417 void RegistryTestHarness::Install3rdPartyPolicy( 418 const base::DictionaryValue* policies) { 419 // The first level entries are domains, and the second level entries map 420 // components to their policy. 421 const base::string16 kPathPrefix = 422 base::string16(kTestPolicyKey) + kPathSep + kThirdParty + kPathSep; 423 for (base::DictionaryValue::Iterator domain(*policies); 424 !domain.IsAtEnd(); domain.Advance()) { 425 const base::DictionaryValue* components = NULL; 426 if (!domain.value().GetAsDictionary(&components)) { 427 ADD_FAILURE(); 428 continue; 429 } 430 for (base::DictionaryValue::Iterator component(*components); 431 !component.IsAtEnd(); component.Advance()) { 432 const base::string16 path = kPathPrefix + 433 UTF8ToUTF16(domain.key()) + kPathSep + UTF8ToUTF16(component.key()); 434 InstallValue(component.value(), hive_, path, kMandatory); 435 } 436 } 437 } 438 439 DWORD RegistryTestHarness::GetAppliedGPOList(DWORD flags, 440 LPCTSTR machine_name, 441 PSID sid_user, 442 GUID* extension_guid, 443 PGROUP_POLICY_OBJECT* gpo_list) { 444 *gpo_list = NULL; 445 return ERROR_ACCESS_DENIED; 446 } 447 448 BOOL RegistryTestHarness::FreeGPOList(PGROUP_POLICY_OBJECT gpo_list) { 449 return TRUE; 450 } 451 452 // static 453 PolicyProviderTestHarness* RegistryTestHarness::CreateHKCU() { 454 return new RegistryTestHarness(HKEY_CURRENT_USER, POLICY_SCOPE_USER); 455 } 456 457 // static 458 PolicyProviderTestHarness* RegistryTestHarness::CreateHKLM() { 459 return new RegistryTestHarness(HKEY_LOCAL_MACHINE, POLICY_SCOPE_MACHINE); 460 } 461 462 PRegTestHarness::PRegTestHarness() 463 : PolicyProviderTestHarness(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE) {} 464 465 PRegTestHarness::~PRegTestHarness() {} 466 467 void PRegTestHarness::SetUp() { 468 base::win::SetDomainStateForTesting(false); 469 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 470 preg_file_path_ = temp_dir_.path().Append(PolicyLoaderWin::kPRegFileName); 471 ASSERT_TRUE(base::WriteFile(preg_file_path_, 472 preg_parser::kPRegFileHeader, 473 arraysize(preg_parser::kPRegFileHeader))); 474 475 memset(&gpo_, 0, sizeof(GROUP_POLICY_OBJECT)); 476 gpo_.lpFileSysPath = const_cast<wchar_t*>(temp_dir_.path().value().c_str()); 477 } 478 479 ConfigurationPolicyProvider* PRegTestHarness::CreateProvider( 480 SchemaRegistry* registry, 481 scoped_refptr<base::SequencedTaskRunner> task_runner) { 482 scoped_ptr<AsyncPolicyLoader> loader( 483 new PolicyLoaderWin(task_runner, kTestPolicyKey, this)); 484 return new AsyncPolicyProvider(registry, loader.Pass()); 485 } 486 487 void PRegTestHarness::InstallEmptyPolicy() {} 488 489 void PRegTestHarness::InstallStringPolicy(const std::string& policy_name, 490 const std::string& policy_value) { 491 AppendStringToPRegFile(kTestPolicyKey, policy_name, policy_value); 492 } 493 494 void PRegTestHarness::InstallIntegerPolicy(const std::string& policy_name, 495 int policy_value) { 496 AppendDWORDToPRegFile(kTestPolicyKey, policy_name, policy_value); 497 } 498 499 void PRegTestHarness::InstallBooleanPolicy(const std::string& policy_name, 500 bool policy_value) { 501 AppendDWORDToPRegFile(kTestPolicyKey, policy_name, policy_value); 502 } 503 504 void PRegTestHarness::InstallStringListPolicy( 505 const std::string& policy_name, 506 const base::ListValue* policy_value) { 507 AppendPolicyToPRegFile(kTestPolicyKey, policy_name, policy_value); 508 } 509 510 void PRegTestHarness::InstallDictionaryPolicy( 511 const std::string& policy_name, 512 const base::DictionaryValue* policy_value) { 513 std::string json; 514 base::JSONWriter::Write(policy_value, &json); 515 AppendStringToPRegFile(kTestPolicyKey, policy_name, json); 516 } 517 518 void PRegTestHarness::Install3rdPartyPolicy( 519 const base::DictionaryValue* policies) { 520 // The first level entries are domains, and the second level entries map 521 // components to their policy. 522 const base::string16 kPathPrefix = 523 base::string16(kTestPolicyKey) + kPathSep + kThirdParty + kPathSep; 524 for (base::DictionaryValue::Iterator domain(*policies); 525 !domain.IsAtEnd(); domain.Advance()) { 526 const base::DictionaryValue* components = NULL; 527 if (!domain.value().GetAsDictionary(&components)) { 528 ADD_FAILURE(); 529 continue; 530 } 531 const base::string16 domain_path = kPathPrefix + UTF8ToUTF16(domain.key()); 532 for (base::DictionaryValue::Iterator component(*components); 533 !component.IsAtEnd(); component.Advance()) { 534 const base::string16 component_path = 535 domain_path + kPathSep + UTF8ToUTF16(component.key()); 536 AppendPolicyToPRegFile(component_path, UTF16ToUTF8(kMandatory), 537 &component.value()); 538 } 539 } 540 } 541 542 DWORD PRegTestHarness::GetAppliedGPOList(DWORD flags, 543 LPCTSTR machine_name, 544 PSID sid_user, 545 GUID* extension_guid, 546 PGROUP_POLICY_OBJECT* gpo_list) { 547 *gpo_list = flags & GPO_LIST_FLAG_MACHINE ? &gpo_ : NULL; 548 return ERROR_SUCCESS; 549 } 550 551 BOOL PRegTestHarness::FreeGPOList(PGROUP_POLICY_OBJECT gpo_list) { 552 return TRUE; 553 } 554 555 // static 556 PolicyProviderTestHarness* PRegTestHarness::Create() { 557 return new PRegTestHarness(); 558 } 559 560 // static 561 void PRegTestHarness::AppendChars(std::vector<uint8>* buffer, 562 const base::string16& chars) { 563 for (base::string16::const_iterator c(chars.begin()); c != chars.end(); ++c) { 564 buffer->push_back(*c & 0xff); 565 buffer->push_back((*c >> 8) & 0xff); 566 } 567 } 568 569 void PRegTestHarness::AppendRecordToPRegFile(const base::string16& path, 570 const std::string& key, 571 DWORD type, 572 DWORD size, 573 uint8* data) { 574 std::vector<uint8> buffer; 575 AppendChars(&buffer, L"["); 576 AppendChars(&buffer, path); 577 AppendChars(&buffer, base::string16(L"\0;", 2)); 578 AppendChars(&buffer, UTF8ToUTF16(key)); 579 AppendChars(&buffer, base::string16(L"\0;", 2)); 580 type = base::ByteSwapToLE32(type); 581 uint8* type_data = reinterpret_cast<uint8*>(&type); 582 buffer.insert(buffer.end(), type_data, type_data + sizeof(DWORD)); 583 AppendChars(&buffer, L";"); 584 size = base::ByteSwapToLE32(size); 585 uint8* size_data = reinterpret_cast<uint8*>(&size); 586 buffer.insert(buffer.end(), size_data, size_data + sizeof(DWORD)); 587 AppendChars(&buffer, L";"); 588 buffer.insert(buffer.end(), data, data + size); 589 AppendChars(&buffer, L"]"); 590 591 ASSERT_EQ(buffer.size(), 592 base::AppendToFile( 593 preg_file_path_, 594 reinterpret_cast<const char*>(vector_as_array(&buffer)), 595 buffer.size())); 596 } 597 598 void PRegTestHarness::AppendDWORDToPRegFile(const base::string16& path, 599 const std::string& key, 600 DWORD value) { 601 value = base::ByteSwapToLE32(value); 602 AppendRecordToPRegFile(path, key, REG_DWORD, sizeof(DWORD), 603 reinterpret_cast<uint8*>(&value)); 604 } 605 606 void PRegTestHarness::AppendStringToPRegFile(const base::string16& path, 607 const std::string& key, 608 const std::string& value) { 609 base::string16 string16_value(UTF8ToUTF16(value)); 610 std::vector<base::char16> data; 611 std::transform(string16_value.begin(), string16_value.end(), 612 std::back_inserter(data), std::ptr_fun(base::ByteSwapToLE16)); 613 data.push_back(base::ByteSwapToLE16(L'\0')); 614 615 AppendRecordToPRegFile(path, key, REG_SZ, data.size() * sizeof(base::char16), 616 reinterpret_cast<uint8*>(vector_as_array(&data))); 617 } 618 619 void PRegTestHarness::AppendPolicyToPRegFile(const base::string16& path, 620 const std::string& key, 621 const base::Value* value) { 622 switch (value->GetType()) { 623 case base::Value::TYPE_BOOLEAN: { 624 bool boolean_value = false; 625 ASSERT_TRUE(value->GetAsBoolean(&boolean_value)); 626 AppendDWORDToPRegFile(path, key, boolean_value); 627 break; 628 } 629 case base::Value::TYPE_INTEGER: { 630 int int_value = 0; 631 ASSERT_TRUE(value->GetAsInteger(&int_value)); 632 AppendDWORDToPRegFile(path, key, int_value); 633 break; 634 } 635 case base::Value::TYPE_DOUBLE: { 636 double double_value = 0; 637 ASSERT_TRUE(value->GetAsDouble(&double_value)); 638 AppendStringToPRegFile(path, key, base::DoubleToString(double_value)); 639 break; 640 } 641 case base::Value::TYPE_STRING: { 642 std::string string_value; 643 ASSERT_TRUE(value->GetAsString(&string_value)); 644 AppendStringToPRegFile(path, key, string_value); 645 break; 646 } 647 case base::Value::TYPE_DICTIONARY: { 648 base::string16 subpath = path + kPathSep + UTF8ToUTF16(key); 649 const base::DictionaryValue* dict = NULL; 650 ASSERT_TRUE(value->GetAsDictionary(&dict)); 651 for (base::DictionaryValue::Iterator entry(*dict); !entry.IsAtEnd(); 652 entry.Advance()) { 653 AppendPolicyToPRegFile(subpath, entry.key(), &entry.value()); 654 } 655 break; 656 } 657 case base::Value::TYPE_LIST: { 658 base::string16 subpath = path + kPathSep + UTF8ToUTF16(key); 659 const base::ListValue* list = NULL; 660 ASSERT_TRUE(value->GetAsList(&list)); 661 for (size_t i = 0; i < list->GetSize(); ++i) { 662 const base::Value* entry = NULL; 663 ASSERT_TRUE(list->Get(i, &entry)); 664 AppendPolicyToPRegFile(subpath, base::IntToString(i + 1), entry); 665 } 666 break; 667 } 668 case base::Value::TYPE_BINARY: 669 case base::Value::TYPE_NULL: { 670 ADD_FAILURE(); 671 break; 672 } 673 } 674 } 675 676 } // namespace 677 678 // Instantiate abstract test case for basic policy reading tests. 679 INSTANTIATE_TEST_CASE_P( 680 PolicyProviderWinTest, 681 ConfigurationPolicyProviderTest, 682 testing::Values(RegistryTestHarness::CreateHKCU, 683 RegistryTestHarness::CreateHKLM, 684 PRegTestHarness::Create)); 685 686 // Instantiate abstract test case for 3rd party policy reading tests. 687 INSTANTIATE_TEST_CASE_P( 688 ThirdPartyPolicyProviderWinTest, 689 Configuration3rdPartyPolicyProviderTest, 690 testing::Values(RegistryTestHarness::CreateHKCU, 691 RegistryTestHarness::CreateHKLM, 692 PRegTestHarness::Create)); 693 694 // Test cases for windows policy provider specific functionality. 695 class PolicyLoaderWinTest : public PolicyTestBase, 696 public AppliedGPOListProvider { 697 protected: 698 // The policy key this tests places data under. This must match the data 699 // files in chrome/test/data/policy/gpo. 700 static const base::char16 kTestPolicyKey[]; 701 702 PolicyLoaderWinTest() 703 : gpo_list_(NULL), 704 gpo_list_status_(ERROR_ACCESS_DENIED) {} 705 virtual ~PolicyLoaderWinTest() {} 706 707 virtual void SetUp() OVERRIDE { 708 base::win::SetDomainStateForTesting(false); 709 PolicyTestBase::SetUp(); 710 711 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &test_data_dir_)); 712 test_data_dir_ = test_data_dir_.AppendASCII("chrome") 713 .AppendASCII("test") 714 .AppendASCII("data") 715 .AppendASCII("policy") 716 .AppendASCII("gpo"); 717 } 718 719 // AppliedGPOListProvider: 720 virtual DWORD GetAppliedGPOList(DWORD flags, 721 LPCTSTR machine_name, 722 PSID sid_user, 723 GUID* extension_guid, 724 PGROUP_POLICY_OBJECT* gpo_list) OVERRIDE { 725 *gpo_list = gpo_list_; 726 return gpo_list_status_; 727 } 728 virtual BOOL FreeGPOList(PGROUP_POLICY_OBJECT gpo_list) OVERRIDE { 729 return TRUE; 730 } 731 732 void InitGPO(GROUP_POLICY_OBJECT* gpo, 733 DWORD options, 734 const base::FilePath& path, 735 GROUP_POLICY_OBJECT* next, 736 GROUP_POLICY_OBJECT* prev) { 737 memset(gpo, 0, sizeof(GROUP_POLICY_OBJECT)); 738 gpo->dwOptions = options; 739 gpo->lpFileSysPath = const_cast<wchar_t*>(path.value().c_str()); 740 gpo->pNext = next; 741 gpo->pPrev = prev; 742 } 743 744 bool Matches(const PolicyBundle& expected) { 745 PolicyLoaderWin loader(loop_.message_loop_proxy(), kTestPolicyKey, this); 746 scoped_ptr<PolicyBundle> loaded( 747 loader.InitialLoad(schema_registry_.schema_map())); 748 return loaded->Equals(expected); 749 } 750 751 void InstallRegistrySentinel() { 752 RegKey hklm_key(HKEY_CURRENT_USER, kTestPolicyKey, KEY_ALL_ACCESS); 753 ASSERT_TRUE(hklm_key.Valid()); 754 hklm_key.WriteValue( 755 UTF8ToUTF16(test_keys::kKeyString).c_str(), 756 UTF8ToUTF16("registry").c_str()); 757 } 758 759 bool MatchesRegistrySentinel() { 760 base::DictionaryValue expected_policy; 761 expected_policy.SetString(test_keys::kKeyString, "registry"); 762 PolicyBundle expected; 763 expected.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())) 764 .LoadFrom(&expected_policy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER); 765 return Matches(expected); 766 } 767 768 bool MatchesTestBundle() { 769 base::DictionaryValue expected_policy; 770 expected_policy.SetBoolean(test_keys::kKeyBoolean, true); 771 expected_policy.SetString(test_keys::kKeyString, "GPO"); 772 expected_policy.SetInteger(test_keys::kKeyInteger, 42); 773 scoped_ptr<base::ListValue> list(new base::ListValue()); 774 list->AppendString("GPO 1"); 775 list->AppendString("GPO 2"); 776 expected_policy.Set(test_keys::kKeyStringList, list.release()); 777 PolicyBundle expected; 778 expected.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())) 779 .LoadFrom(&expected_policy, POLICY_LEVEL_MANDATORY, 780 POLICY_SCOPE_MACHINE); 781 return Matches(expected); 782 } 783 784 ScopedGroupPolicyRegistrySandbox registry_sandbox_; 785 PGROUP_POLICY_OBJECT gpo_list_; 786 DWORD gpo_list_status_; 787 base::FilePath test_data_dir_; 788 }; 789 790 const base::char16 PolicyLoaderWinTest::kTestPolicyKey[] = 791 L"SOFTWARE\\Policies\\Chromium"; 792 793 TEST_F(PolicyLoaderWinTest, HKLMOverHKCU) { 794 RegKey hklm_key(HKEY_LOCAL_MACHINE, kTestPolicyKey, KEY_ALL_ACCESS); 795 ASSERT_TRUE(hklm_key.Valid()); 796 hklm_key.WriteValue(UTF8ToUTF16(test_keys::kKeyString).c_str(), 797 UTF8ToUTF16("hklm").c_str()); 798 RegKey hkcu_key(HKEY_CURRENT_USER, kTestPolicyKey, KEY_ALL_ACCESS); 799 ASSERT_TRUE(hkcu_key.Valid()); 800 hkcu_key.WriteValue(UTF8ToUTF16(test_keys::kKeyString).c_str(), 801 UTF8ToUTF16("hkcu").c_str()); 802 803 PolicyBundle expected; 804 expected.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())) 805 .Set(test_keys::kKeyString, 806 POLICY_LEVEL_MANDATORY, 807 POLICY_SCOPE_MACHINE, 808 new base::StringValue("hklm"), 809 NULL); 810 EXPECT_TRUE(Matches(expected)); 811 } 812 813 TEST_F(PolicyLoaderWinTest, Merge3rdPartyPolicies) { 814 // Policy for the same extension will be provided at the 4 level/scope 815 // combinations, to verify that they overlap as expected. 816 const PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, "merge"); 817 ASSERT_TRUE(RegisterSchema( 818 ns, 819 "{" 820 " \"type\": \"object\"," 821 " \"properties\": {" 822 " \"a\": { \"type\": \"string\" }," 823 " \"b\": { \"type\": \"string\" }," 824 " \"c\": { \"type\": \"string\" }," 825 " \"d\": { \"type\": \"string\" }" 826 " }" 827 "}")); 828 829 const base::string16 kPathSuffix = 830 kTestPolicyKey + base::ASCIIToUTF16("\\3rdparty\\extensions\\merge"); 831 832 const char kUserMandatory[] = "user-mandatory"; 833 const char kUserRecommended[] = "user-recommended"; 834 const char kMachineMandatory[] = "machine-mandatory"; 835 const char kMachineRecommended[] = "machine-recommended"; 836 837 base::DictionaryValue policy; 838 policy.SetString("a", kMachineMandatory); 839 EXPECT_TRUE(InstallValue(policy, HKEY_LOCAL_MACHINE, 840 kPathSuffix, kMandatory)); 841 policy.SetString("a", kUserMandatory); 842 policy.SetString("b", kUserMandatory); 843 EXPECT_TRUE(InstallValue(policy, HKEY_CURRENT_USER, 844 kPathSuffix, kMandatory)); 845 policy.SetString("a", kMachineRecommended); 846 policy.SetString("b", kMachineRecommended); 847 policy.SetString("c", kMachineRecommended); 848 EXPECT_TRUE(InstallValue(policy, HKEY_LOCAL_MACHINE, 849 kPathSuffix, kRecommended)); 850 policy.SetString("a", kUserRecommended); 851 policy.SetString("b", kUserRecommended); 852 policy.SetString("c", kUserRecommended); 853 policy.SetString("d", kUserRecommended); 854 EXPECT_TRUE(InstallValue(policy, HKEY_CURRENT_USER, 855 kPathSuffix, kRecommended)); 856 857 PolicyBundle expected; 858 PolicyMap& expected_policy = expected.Get(ns); 859 expected_policy.Set("a", 860 POLICY_LEVEL_MANDATORY, 861 POLICY_SCOPE_MACHINE, 862 new base::StringValue(kMachineMandatory), 863 NULL); 864 expected_policy.Set("b", 865 POLICY_LEVEL_MANDATORY, 866 POLICY_SCOPE_USER, 867 new base::StringValue(kUserMandatory), 868 NULL); 869 expected_policy.Set("c", 870 POLICY_LEVEL_RECOMMENDED, 871 POLICY_SCOPE_MACHINE, 872 new base::StringValue(kMachineRecommended), 873 NULL); 874 expected_policy.Set("d", 875 POLICY_LEVEL_RECOMMENDED, 876 POLICY_SCOPE_USER, 877 new base::StringValue(kUserRecommended), 878 NULL); 879 EXPECT_TRUE(Matches(expected)); 880 } 881 882 TEST_F(PolicyLoaderWinTest, LoadStringEncodedValues) { 883 // Create a dictionary with all the types that can be stored encoded in a 884 // string. 885 const PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, "string"); 886 ASSERT_TRUE(RegisterSchema( 887 ns, 888 "{" 889 " \"type\": \"object\"," 890 " \"id\": \"MainType\"," 891 " \"properties\": {" 892 " \"null\": { \"type\": \"null\" }," 893 " \"bool\": { \"type\": \"boolean\" }," 894 " \"int\": { \"type\": \"integer\" }," 895 " \"double\": { \"type\": \"number\" }," 896 " \"list\": {" 897 " \"type\": \"array\"," 898 " \"items\": { \"$ref\": \"MainType\" }" 899 " }," 900 " \"dict\": { \"$ref\": \"MainType\" }" 901 " }" 902 "}")); 903 904 base::DictionaryValue policy; 905 policy.Set("null", base::Value::CreateNullValue()); 906 policy.SetBoolean("bool", true); 907 policy.SetInteger("int", -123); 908 policy.SetDouble("double", 456.78e9); 909 base::ListValue list; 910 list.Append(policy.DeepCopy()); 911 list.Append(policy.DeepCopy()); 912 policy.Set("list", list.DeepCopy()); 913 // Encode |policy| before adding the "dict" entry. 914 std::string encoded_dict; 915 base::JSONWriter::Write(&policy, &encoded_dict); 916 ASSERT_FALSE(encoded_dict.empty()); 917 policy.Set("dict", policy.DeepCopy()); 918 std::string encoded_list; 919 base::JSONWriter::Write(&list, &encoded_list); 920 ASSERT_FALSE(encoded_list.empty()); 921 base::DictionaryValue encoded_policy; 922 encoded_policy.SetString("null", ""); 923 encoded_policy.SetString("bool", "1"); 924 encoded_policy.SetString("int", "-123"); 925 encoded_policy.SetString("double", "456.78e9"); 926 encoded_policy.SetString("list", encoded_list); 927 encoded_policy.SetString("dict", encoded_dict); 928 929 const base::string16 kPathSuffix = 930 kTestPolicyKey + base::ASCIIToUTF16("\\3rdparty\\extensions\\string"); 931 EXPECT_TRUE( 932 InstallValue(encoded_policy, HKEY_CURRENT_USER, kPathSuffix, kMandatory)); 933 934 PolicyBundle expected; 935 expected.Get(ns).LoadFrom(&policy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER); 936 EXPECT_TRUE(Matches(expected)); 937 } 938 939 TEST_F(PolicyLoaderWinTest, LoadIntegerEncodedValues) { 940 const PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, "int"); 941 ASSERT_TRUE(RegisterSchema( 942 ns, 943 "{" 944 " \"type\": \"object\"," 945 " \"properties\": {" 946 " \"bool\": { \"type\": \"boolean\" }," 947 " \"int\": { \"type\": \"integer\" }," 948 " \"double\": { \"type\": \"number\" }" 949 " }" 950 "}")); 951 952 base::DictionaryValue encoded_policy; 953 encoded_policy.SetInteger("bool", 1); 954 encoded_policy.SetInteger("int", 123); 955 encoded_policy.SetInteger("double", 456); 956 957 const base::string16 kPathSuffix = 958 kTestPolicyKey + base::ASCIIToUTF16("\\3rdparty\\extensions\\int"); 959 EXPECT_TRUE( 960 InstallValue(encoded_policy, HKEY_CURRENT_USER, kPathSuffix, kMandatory)); 961 962 base::DictionaryValue policy; 963 policy.SetBoolean("bool", true); 964 policy.SetInteger("int", 123); 965 policy.SetDouble("double", 456.0); 966 PolicyBundle expected; 967 expected.Get(ns).LoadFrom(&policy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER); 968 EXPECT_TRUE(Matches(expected)); 969 } 970 971 TEST_F(PolicyLoaderWinTest, DefaultPropertySchemaType) { 972 // Build a schema for an "object" with a default schema for its properties. 973 // Note that the top-level object can't have "additionalProperties", so 974 // a "policy" property is used instead. 975 const PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, "test"); 976 ASSERT_TRUE(RegisterSchema( 977 ns, 978 "{" 979 " \"type\": \"object\"," 980 " \"properties\": {" 981 " \"policy\": {" 982 " \"type\": \"object\"," 983 " \"properties\": {" 984 " \"special-int1\": { \"type\": \"integer\" }," 985 " \"special-int2\": { \"type\": \"integer\" }" 986 " }," 987 " \"additionalProperties\": { \"type\": \"number\" }" 988 " }" 989 " }" 990 "}")); 991 992 // Write some test values. 993 base::DictionaryValue policy; 994 // These special values have a specific schema for them. 995 policy.SetInteger("special-int1", 123); 996 policy.SetString("special-int2", "-456"); 997 // Other values default to be loaded as doubles. 998 policy.SetInteger("double1", 789.0); 999 policy.SetString("double2", "123.456e7"); 1000 policy.SetString("invalid", "omg"); 1001 base::DictionaryValue all_policies; 1002 all_policies.Set("policy", policy.DeepCopy()); 1003 1004 const base::string16 kPathSuffix = 1005 kTestPolicyKey + base::ASCIIToUTF16("\\3rdparty\\extensions\\test"); 1006 EXPECT_TRUE( 1007 InstallValue(all_policies, HKEY_CURRENT_USER, kPathSuffix, kMandatory)); 1008 1009 base::DictionaryValue expected_policy; 1010 expected_policy.SetInteger("special-int1", 123); 1011 expected_policy.SetInteger("special-int2", -456); 1012 expected_policy.SetDouble("double1", 789.0); 1013 expected_policy.SetDouble("double2", 123.456e7); 1014 base::DictionaryValue expected_policies; 1015 expected_policies.Set("policy", expected_policy.DeepCopy()); 1016 PolicyBundle expected; 1017 expected.Get(ns).LoadFrom( 1018 &expected_policies, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER); 1019 EXPECT_TRUE(Matches(expected)); 1020 } 1021 1022 TEST_F(PolicyLoaderWinTest, AppliedPolicyNotPresent) { 1023 InstallRegistrySentinel(); 1024 gpo_list_ = NULL; 1025 gpo_list_status_ = ERROR_SUCCESS; 1026 1027 PolicyBundle empty; 1028 EXPECT_TRUE(Matches(empty)); 1029 } 1030 1031 TEST_F(PolicyLoaderWinTest, AppliedPolicyEmpty) { 1032 InstallRegistrySentinel(); 1033 base::FilePath gpo_dir(test_data_dir_.AppendASCII("empty")); 1034 GROUP_POLICY_OBJECT gpo; 1035 InitGPO(&gpo, 0, gpo_dir, NULL, NULL); 1036 gpo_list_ = &gpo; 1037 gpo_list_status_ = ERROR_SUCCESS; 1038 1039 PolicyBundle empty; 1040 EXPECT_TRUE(Matches(empty)); 1041 } 1042 1043 TEST_F(PolicyLoaderWinTest, AppliedPolicyInDomain) { 1044 base::win::SetDomainStateForTesting(true); 1045 InstallRegistrySentinel(); 1046 base::FilePath gpo_dir(test_data_dir_.AppendASCII("empty")); 1047 GROUP_POLICY_OBJECT gpo; 1048 InitGPO(&gpo, 0, gpo_dir, NULL, NULL); 1049 gpo_list_ = &gpo; 1050 gpo_list_status_ = ERROR_SUCCESS; 1051 1052 PolicyBundle empty; 1053 EXPECT_TRUE(MatchesRegistrySentinel()); 1054 } 1055 1056 TEST_F(PolicyLoaderWinTest, AppliedPolicyNonExistingFile) { 1057 InstallRegistrySentinel(); 1058 GROUP_POLICY_OBJECT gpo; 1059 InitGPO(&gpo, 0, test_data_dir_, NULL, NULL); 1060 gpo_list_ = &gpo; 1061 gpo_list_status_ = ERROR_SUCCESS; 1062 1063 EXPECT_TRUE(MatchesRegistrySentinel()); 1064 } 1065 1066 TEST_F(PolicyLoaderWinTest, AppliedPolicyBadPath) { 1067 InstallRegistrySentinel(); 1068 base::FilePath gpo_dir(test_data_dir_.AppendASCII("bad")); 1069 GROUP_POLICY_OBJECT gpo; 1070 InitGPO(&gpo, 0, gpo_dir, NULL, NULL); 1071 gpo_list_ = &gpo; 1072 gpo_list_status_ = ERROR_SUCCESS; 1073 1074 EXPECT_TRUE(MatchesRegistrySentinel()); 1075 } 1076 1077 TEST_F(PolicyLoaderWinTest, AppliedPolicyPresent) { 1078 InstallRegistrySentinel(); 1079 base::FilePath gpo_dir(test_data_dir_.AppendASCII("test1")); 1080 GROUP_POLICY_OBJECT gpo; 1081 InitGPO(&gpo, 0, gpo_dir, NULL, NULL); 1082 gpo_list_ = &gpo; 1083 gpo_list_status_ = ERROR_SUCCESS; 1084 1085 EXPECT_TRUE(MatchesTestBundle()); 1086 } 1087 1088 TEST_F(PolicyLoaderWinTest, AppliedPolicyMerged) { 1089 InstallRegistrySentinel(); 1090 base::FilePath gpo1_dir(test_data_dir_.AppendASCII("test2")); 1091 base::FilePath gpo2_dir(test_data_dir_.AppendASCII("test1")); 1092 GROUP_POLICY_OBJECT gpo1; 1093 GROUP_POLICY_OBJECT gpo2; 1094 InitGPO(&gpo1, 0, gpo1_dir, &gpo2, NULL); 1095 InitGPO(&gpo2, 0, gpo2_dir, NULL, &gpo1); 1096 gpo_list_ = &gpo1; 1097 gpo_list_status_ = ERROR_SUCCESS; 1098 1099 EXPECT_TRUE(MatchesTestBundle()); 1100 } 1101 1102 TEST_F(PolicyLoaderWinTest, AppliedPolicyDisabled) { 1103 InstallRegistrySentinel(); 1104 base::FilePath gpo1_dir(test_data_dir_.AppendASCII("test1")); 1105 base::FilePath gpo2_dir(test_data_dir_.AppendASCII("test2")); 1106 GROUP_POLICY_OBJECT gpo1; 1107 GROUP_POLICY_OBJECT gpo2; 1108 InitGPO(&gpo1, 0, gpo1_dir, &gpo2, NULL); 1109 InitGPO(&gpo2, GPO_FLAG_DISABLE, gpo2_dir, NULL, &gpo1); 1110 gpo_list_ = &gpo1; 1111 gpo_list_status_ = ERROR_SUCCESS; 1112 1113 EXPECT_TRUE(MatchesTestBundle()); 1114 } 1115 1116 TEST_F(PolicyLoaderWinTest, AppliedPolicyForcedPolicy) { 1117 InstallRegistrySentinel(); 1118 base::FilePath gpo1_dir(test_data_dir_.AppendASCII("test1")); 1119 base::FilePath gpo2_dir(test_data_dir_.AppendASCII("test2")); 1120 GROUP_POLICY_OBJECT gpo1; 1121 GROUP_POLICY_OBJECT gpo2; 1122 InitGPO(&gpo1, GPO_FLAG_FORCE, gpo1_dir, &gpo2, NULL); 1123 InitGPO(&gpo2, 0, gpo2_dir, NULL, &gpo1); 1124 gpo_list_ = &gpo1; 1125 gpo_list_status_ = ERROR_SUCCESS; 1126 1127 EXPECT_TRUE(MatchesTestBundle()); 1128 } 1129 1130 TEST_F(PolicyLoaderWinTest, AppliedPolicyUNCPath) { 1131 InstallRegistrySentinel(); 1132 base::FilePath gpo_dir(test_data_dir_.AppendASCII("test1")); 1133 base::FilePath unc_path(L"\\\\some_share\\GPO"); 1134 GROUP_POLICY_OBJECT gpo1; 1135 GROUP_POLICY_OBJECT gpo2; 1136 InitGPO(&gpo1, 0, gpo_dir, &gpo2, NULL); 1137 InitGPO(&gpo2, 0, unc_path, NULL, &gpo1); 1138 gpo_list_ = &gpo1; 1139 gpo_list_status_ = ERROR_SUCCESS; 1140 1141 EXPECT_TRUE(MatchesRegistrySentinel()); 1142 } 1143 1144 TEST_F(PolicyLoaderWinTest, LoadExtensionPolicyAlternativeSpelling) { 1145 base::FilePath gpo_dir( 1146 test_data_dir_.AppendASCII("extension_alternative_spelling")); 1147 GROUP_POLICY_OBJECT gpo; 1148 InitGPO(&gpo, 0, gpo_dir, NULL, NULL); 1149 gpo_list_ = &gpo; 1150 gpo_list_status_ = ERROR_SUCCESS; 1151 1152 const char kTestSchema[] = 1153 "{" 1154 " \"type\": \"object\"," 1155 " \"properties\": {" 1156 " \"policy 1\": { \"type\": \"integer\" }," 1157 " \"policy 2\": { \"type\": \"integer\" }" 1158 " }" 1159 "}"; 1160 const PolicyNamespace ns_a( 1161 POLICY_DOMAIN_EXTENSIONS, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); 1162 const PolicyNamespace ns_b( 1163 POLICY_DOMAIN_EXTENSIONS, "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"); 1164 ASSERT_TRUE(RegisterSchema(ns_a, kTestSchema)); 1165 ASSERT_TRUE(RegisterSchema(ns_b, kTestSchema)); 1166 1167 PolicyBundle expected; 1168 base::DictionaryValue expected_a; 1169 expected_a.SetInteger("policy 1", 3); 1170 expected_a.SetInteger("policy 2", 3); 1171 expected.Get(ns_a).LoadFrom( 1172 &expected_a, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE); 1173 base::DictionaryValue expected_b; 1174 expected_b.SetInteger("policy 1", 2); 1175 expected.Get(ns_b).LoadFrom( 1176 &expected_b, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE); 1177 EXPECT_TRUE(Matches(expected)); 1178 } 1179 1180 TEST_F(PolicyLoaderWinTest, LBSSupport) { 1181 const PolicyNamespace ns( 1182 POLICY_DOMAIN_EXTENSIONS, "heildphpnddilhkemkielfhnkaagiabh"); 1183 schema_registry_.RegisterComponent(ns, Schema()); 1184 1185 const char kIncompleteSchema[] = 1186 "{" 1187 " \"type\": \"object\"," 1188 " \"properties\": {" 1189 " \"url_list\": { \"type\": \"array\" }," 1190 " \"url_greylist\": { \"type\": \"array\" }" 1191 " }" 1192 "}"; 1193 1194 const base::string16 kPathSuffix = 1195 kTestPolicyKey + base::ASCIIToUTF16("\\3rdparty\\extensions"); 1196 1197 base::ListValue list; 1198 list.AppendString("youtube.com"); 1199 base::DictionaryValue policy; 1200 policy.Set("url_list", list.DeepCopy()); 1201 policy.SetString("alternative_browser_path", "c:\\legacy\\browser.exe"); 1202 base::DictionaryValue root; 1203 root.Set(base::UTF16ToUTF8(kMandatory), policy.DeepCopy()); 1204 root.SetString(kSchema, kIncompleteSchema); 1205 EXPECT_TRUE(InstallValue(root, HKEY_LOCAL_MACHINE, 1206 kPathSuffix, base::ASCIIToUTF16(ns.component_id))); 1207 1208 PolicyBundle expected; 1209 PolicyMap& expected_policy = expected.Get(ns); 1210 expected_policy.Set("alternative_browser_path", 1211 POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, 1212 new base::StringValue("c:\\legacy\\browser.exe"), NULL); 1213 expected_policy.Set("url_list", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, 1214 list.DeepCopy(), NULL); 1215 EXPECT_TRUE(Matches(expected)); 1216 } 1217 1218 } // namespace policy 1219