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