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