policy_loader_win_unittest.cc revision a1401311d1ab56c4ed0a474bd38c108f75cb0cd9
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/file_util.h" 19#include "base/files/file_path.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 41using base::UTF8ToUTF16; 42using base::UTF16ToUTF8; 43using base::win::RegKey; 44 45namespace policy { 46 47namespace { 48 49// Constants for registry key names. 50const wchar_t kPathSep[] = L"\\"; 51const wchar_t kThirdParty[] = L"3rdparty"; 52const wchar_t kMandatory[] = L"policy"; 53const wchar_t kRecommended[] = L"recommended"; 54const char kSchema[] = "schema"; 55const 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. 62bool 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. 146class 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. 169class 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. 220class 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 295ScopedGroupPolicyRegistrySandbox::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 317ScopedGroupPolicyRegistrySandbox::~ScopedGroupPolicyRegistrySandbox() { 318 RemoveOverrides(); 319 DeleteKeys(); 320} 321 322void 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 329void ScopedGroupPolicyRegistrySandbox::RemoveOverrides() { 330 ASSERT_HRESULT_SUCCEEDED(RegOverridePredefKey(HKEY_LOCAL_MACHINE, 0)); 331 ASSERT_HRESULT_SUCCEEDED(RegOverridePredefKey(HKEY_CURRENT_USER, 0)); 332} 333 334void 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 340RegistryTestHarness::RegistryTestHarness(HKEY hive, PolicyScope scope) 341 : PolicyProviderTestHarness(POLICY_LEVEL_MANDATORY, scope), hive_(hive) {} 342 343RegistryTestHarness::~RegistryTestHarness() {} 344 345void RegistryTestHarness::SetUp() {} 346 347ConfigurationPolicyProvider* 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 356void RegistryTestHarness::InstallEmptyPolicy() {} 357 358void 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 367void 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 376void 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 385void 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 406void 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 417void 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 439DWORD 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 448BOOL RegistryTestHarness::FreeGPOList(PGROUP_POLICY_OBJECT gpo_list) { 449 return TRUE; 450} 451 452// static 453PolicyProviderTestHarness* RegistryTestHarness::CreateHKCU() { 454 return new RegistryTestHarness(HKEY_CURRENT_USER, POLICY_SCOPE_USER); 455} 456 457// static 458PolicyProviderTestHarness* RegistryTestHarness::CreateHKLM() { 459 return new RegistryTestHarness(HKEY_LOCAL_MACHINE, POLICY_SCOPE_MACHINE); 460} 461 462PRegTestHarness::PRegTestHarness() 463 : PolicyProviderTestHarness(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE) {} 464 465PRegTestHarness::~PRegTestHarness() {} 466 467void 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 479ConfigurationPolicyProvider* 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 487void PRegTestHarness::InstallEmptyPolicy() {} 488 489void PRegTestHarness::InstallStringPolicy(const std::string& policy_name, 490 const std::string& policy_value) { 491 AppendStringToPRegFile(kTestPolicyKey, policy_name, policy_value); 492} 493 494void PRegTestHarness::InstallIntegerPolicy(const std::string& policy_name, 495 int policy_value) { 496 AppendDWORDToPRegFile(kTestPolicyKey, policy_name, policy_value); 497} 498 499void PRegTestHarness::InstallBooleanPolicy(const std::string& policy_name, 500 bool policy_value) { 501 AppendDWORDToPRegFile(kTestPolicyKey, policy_name, policy_value); 502} 503 504void PRegTestHarness::InstallStringListPolicy( 505 const std::string& policy_name, 506 const base::ListValue* policy_value) { 507 AppendPolicyToPRegFile(kTestPolicyKey, policy_name, policy_value); 508} 509 510void 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 518void 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 542DWORD 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 551BOOL PRegTestHarness::FreeGPOList(PGROUP_POLICY_OBJECT gpo_list) { 552 return TRUE; 553} 554 555// static 556PolicyProviderTestHarness* PRegTestHarness::Create() { 557 return new PRegTestHarness(); 558} 559 560// static 561void 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 569void 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 598void 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 606void 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 619void 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. 679INSTANTIATE_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. 687INSTANTIATE_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. 695class 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 790const base::char16 PolicyLoaderWinTest::kTestPolicyKey[] = 791 L"SOFTWARE\\Policies\\Chromium"; 792 793TEST_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 base::Value::CreateStringValue("hklm"), NULL); 809 EXPECT_TRUE(Matches(expected)); 810} 811 812TEST_F(PolicyLoaderWinTest, Merge3rdPartyPolicies) { 813 // Policy for the same extension will be provided at the 4 level/scope 814 // combinations, to verify that they overlap as expected. 815 const PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, "merge"); 816 ASSERT_TRUE(RegisterSchema( 817 ns, 818 "{" 819 " \"type\": \"object\"," 820 " \"properties\": {" 821 " \"a\": { \"type\": \"string\" }," 822 " \"b\": { \"type\": \"string\" }," 823 " \"c\": { \"type\": \"string\" }," 824 " \"d\": { \"type\": \"string\" }" 825 " }" 826 "}")); 827 828 const base::string16 kPathSuffix = 829 kTestPolicyKey + base::ASCIIToUTF16("\\3rdparty\\extensions\\merge"); 830 831 const char kUserMandatory[] = "user-mandatory"; 832 const char kUserRecommended[] = "user-recommended"; 833 const char kMachineMandatory[] = "machine-mandatory"; 834 const char kMachineRecommended[] = "machine-recommended"; 835 836 base::DictionaryValue policy; 837 policy.SetString("a", kMachineMandatory); 838 EXPECT_TRUE(InstallValue(policy, HKEY_LOCAL_MACHINE, 839 kPathSuffix, kMandatory)); 840 policy.SetString("a", kUserMandatory); 841 policy.SetString("b", kUserMandatory); 842 EXPECT_TRUE(InstallValue(policy, HKEY_CURRENT_USER, 843 kPathSuffix, kMandatory)); 844 policy.SetString("a", kMachineRecommended); 845 policy.SetString("b", kMachineRecommended); 846 policy.SetString("c", kMachineRecommended); 847 EXPECT_TRUE(InstallValue(policy, HKEY_LOCAL_MACHINE, 848 kPathSuffix, kRecommended)); 849 policy.SetString("a", kUserRecommended); 850 policy.SetString("b", kUserRecommended); 851 policy.SetString("c", kUserRecommended); 852 policy.SetString("d", kUserRecommended); 853 EXPECT_TRUE(InstallValue(policy, HKEY_CURRENT_USER, 854 kPathSuffix, kRecommended)); 855 856 PolicyBundle expected; 857 PolicyMap& expected_policy = expected.Get(ns); 858 expected_policy.Set("a", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, 859 base::Value::CreateStringValue(kMachineMandatory), NULL); 860 expected_policy.Set("b", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, 861 base::Value::CreateStringValue(kUserMandatory), NULL); 862 expected_policy.Set("c", POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_MACHINE, 863 base::Value::CreateStringValue(kMachineRecommended), 864 NULL); 865 expected_policy.Set("d", POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER, 866 base::Value::CreateStringValue(kUserRecommended), NULL); 867 EXPECT_TRUE(Matches(expected)); 868} 869 870TEST_F(PolicyLoaderWinTest, LoadStringEncodedValues) { 871 // Create a dictionary with all the types that can be stored encoded in a 872 // string. 873 const PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, "string"); 874 ASSERT_TRUE(RegisterSchema( 875 ns, 876 "{" 877 " \"type\": \"object\"," 878 " \"id\": \"MainType\"," 879 " \"properties\": {" 880 " \"null\": { \"type\": \"null\" }," 881 " \"bool\": { \"type\": \"boolean\" }," 882 " \"int\": { \"type\": \"integer\" }," 883 " \"double\": { \"type\": \"number\" }," 884 " \"list\": {" 885 " \"type\": \"array\"," 886 " \"items\": { \"$ref\": \"MainType\" }" 887 " }," 888 " \"dict\": { \"$ref\": \"MainType\" }" 889 " }" 890 "}")); 891 892 base::DictionaryValue policy; 893 policy.Set("null", base::Value::CreateNullValue()); 894 policy.SetBoolean("bool", true); 895 policy.SetInteger("int", -123); 896 policy.SetDouble("double", 456.78e9); 897 base::ListValue list; 898 list.Append(policy.DeepCopy()); 899 list.Append(policy.DeepCopy()); 900 policy.Set("list", list.DeepCopy()); 901 // Encode |policy| before adding the "dict" entry. 902 std::string encoded_dict; 903 base::JSONWriter::Write(&policy, &encoded_dict); 904 ASSERT_FALSE(encoded_dict.empty()); 905 policy.Set("dict", policy.DeepCopy()); 906 std::string encoded_list; 907 base::JSONWriter::Write(&list, &encoded_list); 908 ASSERT_FALSE(encoded_list.empty()); 909 base::DictionaryValue encoded_policy; 910 encoded_policy.SetString("null", ""); 911 encoded_policy.SetString("bool", "1"); 912 encoded_policy.SetString("int", "-123"); 913 encoded_policy.SetString("double", "456.78e9"); 914 encoded_policy.SetString("list", encoded_list); 915 encoded_policy.SetString("dict", encoded_dict); 916 917 const base::string16 kPathSuffix = 918 kTestPolicyKey + base::ASCIIToUTF16("\\3rdparty\\extensions\\string"); 919 EXPECT_TRUE( 920 InstallValue(encoded_policy, HKEY_CURRENT_USER, kPathSuffix, kMandatory)); 921 922 PolicyBundle expected; 923 expected.Get(ns).LoadFrom(&policy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER); 924 EXPECT_TRUE(Matches(expected)); 925} 926 927TEST_F(PolicyLoaderWinTest, LoadIntegerEncodedValues) { 928 const PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, "int"); 929 ASSERT_TRUE(RegisterSchema( 930 ns, 931 "{" 932 " \"type\": \"object\"," 933 " \"properties\": {" 934 " \"bool\": { \"type\": \"boolean\" }," 935 " \"int\": { \"type\": \"integer\" }," 936 " \"double\": { \"type\": \"number\" }" 937 " }" 938 "}")); 939 940 base::DictionaryValue encoded_policy; 941 encoded_policy.SetInteger("bool", 1); 942 encoded_policy.SetInteger("int", 123); 943 encoded_policy.SetInteger("double", 456); 944 945 const base::string16 kPathSuffix = 946 kTestPolicyKey + base::ASCIIToUTF16("\\3rdparty\\extensions\\int"); 947 EXPECT_TRUE( 948 InstallValue(encoded_policy, HKEY_CURRENT_USER, kPathSuffix, kMandatory)); 949 950 base::DictionaryValue policy; 951 policy.SetBoolean("bool", true); 952 policy.SetInteger("int", 123); 953 policy.SetDouble("double", 456.0); 954 PolicyBundle expected; 955 expected.Get(ns).LoadFrom(&policy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER); 956 EXPECT_TRUE(Matches(expected)); 957} 958 959TEST_F(PolicyLoaderWinTest, DefaultPropertySchemaType) { 960 // Build a schema for an "object" with a default schema for its properties. 961 // Note that the top-level object can't have "additionalProperties", so 962 // a "policy" property is used instead. 963 const PolicyNamespace ns(POLICY_DOMAIN_EXTENSIONS, "test"); 964 ASSERT_TRUE(RegisterSchema( 965 ns, 966 "{" 967 " \"type\": \"object\"," 968 " \"properties\": {" 969 " \"policy\": {" 970 " \"type\": \"object\"," 971 " \"properties\": {" 972 " \"special-int1\": { \"type\": \"integer\" }," 973 " \"special-int2\": { \"type\": \"integer\" }" 974 " }," 975 " \"additionalProperties\": { \"type\": \"number\" }" 976 " }" 977 " }" 978 "}")); 979 980 // Write some test values. 981 base::DictionaryValue policy; 982 // These special values have a specific schema for them. 983 policy.SetInteger("special-int1", 123); 984 policy.SetString("special-int2", "-456"); 985 // Other values default to be loaded as doubles. 986 policy.SetInteger("double1", 789.0); 987 policy.SetString("double2", "123.456e7"); 988 policy.SetString("invalid", "omg"); 989 base::DictionaryValue all_policies; 990 all_policies.Set("policy", policy.DeepCopy()); 991 992 const base::string16 kPathSuffix = 993 kTestPolicyKey + base::ASCIIToUTF16("\\3rdparty\\extensions\\test"); 994 EXPECT_TRUE( 995 InstallValue(all_policies, HKEY_CURRENT_USER, kPathSuffix, kMandatory)); 996 997 base::DictionaryValue expected_policy; 998 expected_policy.SetInteger("special-int1", 123); 999 expected_policy.SetInteger("special-int2", -456); 1000 expected_policy.SetDouble("double1", 789.0); 1001 expected_policy.SetDouble("double2", 123.456e7); 1002 base::DictionaryValue expected_policies; 1003 expected_policies.Set("policy", expected_policy.DeepCopy()); 1004 PolicyBundle expected; 1005 expected.Get(ns).LoadFrom( 1006 &expected_policies, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER); 1007 EXPECT_TRUE(Matches(expected)); 1008} 1009 1010TEST_F(PolicyLoaderWinTest, AppliedPolicyNotPresent) { 1011 InstallRegistrySentinel(); 1012 gpo_list_ = NULL; 1013 gpo_list_status_ = ERROR_SUCCESS; 1014 1015 PolicyBundle empty; 1016 EXPECT_TRUE(Matches(empty)); 1017} 1018 1019TEST_F(PolicyLoaderWinTest, AppliedPolicyEmpty) { 1020 InstallRegistrySentinel(); 1021 base::FilePath gpo_dir(test_data_dir_.AppendASCII("empty")); 1022 GROUP_POLICY_OBJECT gpo; 1023 InitGPO(&gpo, 0, gpo_dir, NULL, NULL); 1024 gpo_list_ = &gpo; 1025 gpo_list_status_ = ERROR_SUCCESS; 1026 1027 PolicyBundle empty; 1028 EXPECT_TRUE(Matches(empty)); 1029} 1030 1031TEST_F(PolicyLoaderWinTest, AppliedPolicyInDomain) { 1032 base::win::SetDomainStateForTesting(true); 1033 InstallRegistrySentinel(); 1034 base::FilePath gpo_dir(test_data_dir_.AppendASCII("empty")); 1035 GROUP_POLICY_OBJECT gpo; 1036 InitGPO(&gpo, 0, gpo_dir, NULL, NULL); 1037 gpo_list_ = &gpo; 1038 gpo_list_status_ = ERROR_SUCCESS; 1039 1040 PolicyBundle empty; 1041 EXPECT_TRUE(MatchesRegistrySentinel()); 1042} 1043 1044TEST_F(PolicyLoaderWinTest, AppliedPolicyNonExistingFile) { 1045 InstallRegistrySentinel(); 1046 GROUP_POLICY_OBJECT gpo; 1047 InitGPO(&gpo, 0, test_data_dir_, NULL, NULL); 1048 gpo_list_ = &gpo; 1049 gpo_list_status_ = ERROR_SUCCESS; 1050 1051 EXPECT_TRUE(MatchesRegistrySentinel()); 1052} 1053 1054TEST_F(PolicyLoaderWinTest, AppliedPolicyBadPath) { 1055 InstallRegistrySentinel(); 1056 base::FilePath gpo_dir(test_data_dir_.AppendASCII("bad")); 1057 GROUP_POLICY_OBJECT gpo; 1058 InitGPO(&gpo, 0, gpo_dir, NULL, NULL); 1059 gpo_list_ = &gpo; 1060 gpo_list_status_ = ERROR_SUCCESS; 1061 1062 EXPECT_TRUE(MatchesRegistrySentinel()); 1063} 1064 1065TEST_F(PolicyLoaderWinTest, AppliedPolicyPresent) { 1066 InstallRegistrySentinel(); 1067 base::FilePath gpo_dir(test_data_dir_.AppendASCII("test1")); 1068 GROUP_POLICY_OBJECT gpo; 1069 InitGPO(&gpo, 0, gpo_dir, NULL, NULL); 1070 gpo_list_ = &gpo; 1071 gpo_list_status_ = ERROR_SUCCESS; 1072 1073 EXPECT_TRUE(MatchesTestBundle()); 1074} 1075 1076TEST_F(PolicyLoaderWinTest, AppliedPolicyMerged) { 1077 InstallRegistrySentinel(); 1078 base::FilePath gpo1_dir(test_data_dir_.AppendASCII("test2")); 1079 base::FilePath gpo2_dir(test_data_dir_.AppendASCII("test1")); 1080 GROUP_POLICY_OBJECT gpo1; 1081 GROUP_POLICY_OBJECT gpo2; 1082 InitGPO(&gpo1, 0, gpo1_dir, &gpo2, NULL); 1083 InitGPO(&gpo2, 0, gpo2_dir, NULL, &gpo1); 1084 gpo_list_ = &gpo1; 1085 gpo_list_status_ = ERROR_SUCCESS; 1086 1087 EXPECT_TRUE(MatchesTestBundle()); 1088} 1089 1090TEST_F(PolicyLoaderWinTest, AppliedPolicyDisabled) { 1091 InstallRegistrySentinel(); 1092 base::FilePath gpo1_dir(test_data_dir_.AppendASCII("test1")); 1093 base::FilePath gpo2_dir(test_data_dir_.AppendASCII("test2")); 1094 GROUP_POLICY_OBJECT gpo1; 1095 GROUP_POLICY_OBJECT gpo2; 1096 InitGPO(&gpo1, 0, gpo1_dir, &gpo2, NULL); 1097 InitGPO(&gpo2, GPO_FLAG_DISABLE, gpo2_dir, NULL, &gpo1); 1098 gpo_list_ = &gpo1; 1099 gpo_list_status_ = ERROR_SUCCESS; 1100 1101 EXPECT_TRUE(MatchesTestBundle()); 1102} 1103 1104TEST_F(PolicyLoaderWinTest, AppliedPolicyForcedPolicy) { 1105 InstallRegistrySentinel(); 1106 base::FilePath gpo1_dir(test_data_dir_.AppendASCII("test1")); 1107 base::FilePath gpo2_dir(test_data_dir_.AppendASCII("test2")); 1108 GROUP_POLICY_OBJECT gpo1; 1109 GROUP_POLICY_OBJECT gpo2; 1110 InitGPO(&gpo1, GPO_FLAG_FORCE, gpo1_dir, &gpo2, NULL); 1111 InitGPO(&gpo2, 0, gpo2_dir, NULL, &gpo1); 1112 gpo_list_ = &gpo1; 1113 gpo_list_status_ = ERROR_SUCCESS; 1114 1115 EXPECT_TRUE(MatchesTestBundle()); 1116} 1117 1118TEST_F(PolicyLoaderWinTest, AppliedPolicyUNCPath) { 1119 InstallRegistrySentinel(); 1120 base::FilePath gpo_dir(test_data_dir_.AppendASCII("test1")); 1121 base::FilePath unc_path(L"\\\\some_share\\GPO"); 1122 GROUP_POLICY_OBJECT gpo1; 1123 GROUP_POLICY_OBJECT gpo2; 1124 InitGPO(&gpo1, 0, gpo_dir, &gpo2, NULL); 1125 InitGPO(&gpo2, 0, unc_path, NULL, &gpo1); 1126 gpo_list_ = &gpo1; 1127 gpo_list_status_ = ERROR_SUCCESS; 1128 1129 EXPECT_TRUE(MatchesRegistrySentinel()); 1130} 1131 1132TEST_F(PolicyLoaderWinTest, LoadExtensionPolicyAlternativeSpelling) { 1133 base::FilePath gpo_dir( 1134 test_data_dir_.AppendASCII("extension_alternative_spelling")); 1135 GROUP_POLICY_OBJECT gpo; 1136 InitGPO(&gpo, 0, gpo_dir, NULL, NULL); 1137 gpo_list_ = &gpo; 1138 gpo_list_status_ = ERROR_SUCCESS; 1139 1140 const char kTestSchema[] = 1141 "{" 1142 " \"type\": \"object\"," 1143 " \"properties\": {" 1144 " \"policy 1\": { \"type\": \"integer\" }," 1145 " \"policy 2\": { \"type\": \"integer\" }" 1146 " }" 1147 "}"; 1148 const PolicyNamespace ns_a( 1149 POLICY_DOMAIN_EXTENSIONS, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); 1150 const PolicyNamespace ns_b( 1151 POLICY_DOMAIN_EXTENSIONS, "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"); 1152 ASSERT_TRUE(RegisterSchema(ns_a, kTestSchema)); 1153 ASSERT_TRUE(RegisterSchema(ns_b, kTestSchema)); 1154 1155 PolicyBundle expected; 1156 base::DictionaryValue expected_a; 1157 expected_a.SetInteger("policy 1", 3); 1158 expected_a.SetInteger("policy 2", 3); 1159 expected.Get(ns_a).LoadFrom( 1160 &expected_a, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE); 1161 base::DictionaryValue expected_b; 1162 expected_b.SetInteger("policy 1", 2); 1163 expected.Get(ns_b).LoadFrom( 1164 &expected_b, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE); 1165 EXPECT_TRUE(Matches(expected)); 1166} 1167 1168TEST_F(PolicyLoaderWinTest, LBSSupport) { 1169 const PolicyNamespace ns( 1170 POLICY_DOMAIN_EXTENSIONS, "heildphpnddilhkemkielfhnkaagiabh"); 1171 schema_registry_.RegisterComponent(ns, Schema()); 1172 1173 const char kIncompleteSchema[] = 1174 "{" 1175 " \"type\": \"object\"," 1176 " \"properties\": {" 1177 " \"url_list\": { \"type\": \"array\" }," 1178 " \"url_greylist\": { \"type\": \"array\" }" 1179 " }" 1180 "}"; 1181 1182 const base::string16 kPathSuffix = 1183 kTestPolicyKey + base::ASCIIToUTF16("\\3rdparty\\extensions"); 1184 1185 base::ListValue list; 1186 list.AppendString("youtube.com"); 1187 base::DictionaryValue policy; 1188 policy.Set("url_list", list.DeepCopy()); 1189 policy.SetString("alternative_browser_path", "c:\\legacy\\browser.exe"); 1190 base::DictionaryValue root; 1191 root.Set(base::UTF16ToUTF8(kMandatory), policy.DeepCopy()); 1192 root.SetString(kSchema, kIncompleteSchema); 1193 EXPECT_TRUE(InstallValue(root, HKEY_LOCAL_MACHINE, 1194 kPathSuffix, base::ASCIIToUTF16(ns.component_id))); 1195 1196 PolicyBundle expected; 1197 PolicyMap& expected_policy = expected.Get(ns); 1198 expected_policy.Set("alternative_browser_path", 1199 POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, 1200 new base::StringValue("c:\\legacy\\browser.exe"), NULL); 1201 expected_policy.Set("url_list", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE, 1202 list.DeepCopy(), NULL); 1203 EXPECT_TRUE(Matches(expected)); 1204} 1205 1206} // namespace policy 1207