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