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"
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"
40 using base::win::RegKey
;
46 // Constants for registry key names.
47 const wchar_t kPathSep
[] = L
"\\";
48 const wchar_t kThirdParty
[] = L
"3rdparty";
49 const wchar_t kMandatory
[] = L
"policy";
50 const wchar_t kRecommended
[] = L
"recommended";
51 const char kSchema
[] = "schema";
52 const wchar_t kTestPolicyKey
[] = L
"chrome.policy.key";
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
59 bool InstallValue(const base::Value
& value
,
61 const base::string16
& path
,
62 const base::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
;
70 case base::Value::TYPE_BOOLEAN
: {
72 if (!value
.GetAsBoolean(&bool_value
))
74 return key
.WriteValue(name
.c_str(), bool_value
? 1 : 0) == ERROR_SUCCESS
;
77 case base::Value::TYPE_INTEGER
: {
79 if (!value
.GetAsInteger(&int_value
))
81 return key
.WriteValue(name
.c_str(), int_value
) == ERROR_SUCCESS
;
84 case base::Value::TYPE_DOUBLE
: {
86 if (!value
.GetAsDouble(&double_value
))
88 base::string16 str_value
=
89 UTF8ToUTF16(base::DoubleToString(double_value
));
90 return key
.WriteValue(name
.c_str(), str_value
.c_str()) == ERROR_SUCCESS
;
93 case base::Value::TYPE_STRING
: {
94 base::string16 str_value
;
95 if (!value
.GetAsString(&str_value
))
97 return key
.WriteValue(name
.c_str(), str_value
.c_str()) == ERROR_SUCCESS
;
100 case base::Value::TYPE_DICTIONARY
: {
101 const base::DictionaryValue
* sub_dict
= NULL
;
102 if (!value
.GetAsDictionary(&sub_dict
))
104 for (base::DictionaryValue::Iterator
it(*sub_dict
);
105 !it
.IsAtEnd(); it
.Advance()) {
106 if (!InstallValue(it
.value(), hive
, path
+ kPathSep
+ name
,
107 UTF8ToUTF16(it
.key()))) {
114 case base::Value::TYPE_LIST
: {
115 const base::ListValue
* list
= NULL
;
116 if (!value
.GetAsList(&list
))
118 for (size_t i
= 0; i
< list
->GetSize(); ++i
) {
119 const base::Value
* item
;
120 if (!list
->Get(i
, &item
))
122 if (!InstallValue(*item
, hive
, path
+ kPathSep
+ name
,
123 base::UintToString16(i
+ 1))) {
130 case base::Value::TYPE_BINARY
:
137 // This class provides sandboxing and mocking for the parts of the Windows
138 // Registry implementing Group Policy. It prepares two temporary sandbox keys,
139 // one for HKLM and one for HKCU. A test's calls to the registry are redirected
140 // by Windows to these sandboxes, allowing the tests to manipulate and access
141 // policy as if it were active, but without actually changing the parts of the
142 // Registry that are managed by Group Policy.
143 class ScopedGroupPolicyRegistrySandbox
{
145 ScopedGroupPolicyRegistrySandbox();
146 ~ScopedGroupPolicyRegistrySandbox();
149 void ActivateOverrides();
150 void RemoveOverrides();
152 // Deletes the sandbox keys.
155 std::wstring key_name_
;
157 // Keys are created for the lifetime of a test to contain
158 // the sandboxed HKCU and HKLM hives, respectively.
159 RegKey temp_hkcu_hive_key_
;
160 RegKey temp_hklm_hive_key_
;
162 DISALLOW_COPY_AND_ASSIGN(ScopedGroupPolicyRegistrySandbox
);
165 // A test harness that feeds policy via the Chrome GPO registry subtree.
166 class RegistryTestHarness
: public PolicyProviderTestHarness
,
167 public AppliedGPOListProvider
{
169 RegistryTestHarness(HKEY hive
, PolicyScope scope
);
170 virtual ~RegistryTestHarness();
172 // PolicyProviderTestHarness:
173 virtual void SetUp() OVERRIDE
;
175 virtual ConfigurationPolicyProvider
* CreateProvider(
176 SchemaRegistry
* registry
,
177 scoped_refptr
<base::SequencedTaskRunner
> task_runner
) OVERRIDE
;
179 virtual void InstallEmptyPolicy() OVERRIDE
;
180 virtual void InstallStringPolicy(const std::string
& policy_name
,
181 const std::string
& policy_value
) OVERRIDE
;
182 virtual void InstallIntegerPolicy(const std::string
& policy_name
,
183 int policy_value
) OVERRIDE
;
184 virtual void InstallBooleanPolicy(const std::string
& policy_name
,
185 bool policy_value
) OVERRIDE
;
186 virtual void InstallStringListPolicy(
187 const std::string
& policy_name
,
188 const base::ListValue
* policy_value
) OVERRIDE
;
189 virtual void InstallDictionaryPolicy(
190 const std::string
& policy_name
,
191 const base::DictionaryValue
* policy_value
) OVERRIDE
;
192 virtual void Install3rdPartyPolicy(
193 const base::DictionaryValue
* policies
) OVERRIDE
;
195 // AppliedGPOListProvider:
196 virtual DWORD
GetAppliedGPOList(DWORD flags
,
197 LPCTSTR machine_name
,
199 GUID
* extension_guid
,
200 PGROUP_POLICY_OBJECT
* gpo_list
) OVERRIDE
;
201 virtual BOOL
FreeGPOList(PGROUP_POLICY_OBJECT gpo_list
) OVERRIDE
;
203 // Creates a harness instance that will install policy in HKCU or HKLM,
205 static PolicyProviderTestHarness
* CreateHKCU();
206 static PolicyProviderTestHarness
* CreateHKLM();
211 ScopedGroupPolicyRegistrySandbox registry_sandbox_
;
213 DISALLOW_COPY_AND_ASSIGN(RegistryTestHarness
);
216 // A test harness that generates PReg files for the provider to read.
217 class PRegTestHarness
: public PolicyProviderTestHarness
,
218 public AppliedGPOListProvider
{
221 virtual ~PRegTestHarness();
223 // PolicyProviderTestHarness:
224 virtual void SetUp() OVERRIDE
;
226 virtual ConfigurationPolicyProvider
* CreateProvider(
227 SchemaRegistry
* registry
,
228 scoped_refptr
<base::SequencedTaskRunner
> task_runner
) OVERRIDE
;
230 virtual void InstallEmptyPolicy() OVERRIDE
;
231 virtual void InstallStringPolicy(const std::string
& policy_name
,
232 const std::string
& policy_value
) OVERRIDE
;
233 virtual void InstallIntegerPolicy(const std::string
& policy_name
,
234 int policy_value
) OVERRIDE
;
235 virtual void InstallBooleanPolicy(const std::string
& policy_name
,
236 bool policy_value
) OVERRIDE
;
237 virtual void InstallStringListPolicy(
238 const std::string
& policy_name
,
239 const base::ListValue
* policy_value
) OVERRIDE
;
240 virtual void InstallDictionaryPolicy(
241 const std::string
& policy_name
,
242 const base::DictionaryValue
* policy_value
) OVERRIDE
;
243 virtual void Install3rdPartyPolicy(
244 const base::DictionaryValue
* policies
) OVERRIDE
;
246 // AppliedGPOListProvider:
247 virtual DWORD
GetAppliedGPOList(DWORD flags
,
248 LPCTSTR machine_name
,
250 GUID
* extension_guid
,
251 PGROUP_POLICY_OBJECT
* gpo_list
) OVERRIDE
;
252 virtual BOOL
FreeGPOList(PGROUP_POLICY_OBJECT gpo_list
) OVERRIDE
;
254 // Creates a harness instance.
255 static PolicyProviderTestHarness
* Create();
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
,
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
,
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_
= ASCIIToWide(base::StringPrintf(
297 "SOFTWARE\\chromium unittest %d",
298 base::Process::Current().pid()));
299 std::wstring hklm_key_name
= key_name_
+ L
"\\HKLM";
300 std::wstring hkcu_key_name
= key_name_
+ L
"\\HKCU";
302 // Create the subkeys to hold the overridden HKLM and HKCU
304 temp_hklm_hive_key_
.Create(HKEY_CURRENT_USER
,
305 hklm_key_name
.c_str(),
307 temp_hkcu_hive_key_
.Create(HKEY_CURRENT_USER
,
308 hkcu_key_name
.c_str(),
314 ScopedGroupPolicyRegistrySandbox::~ScopedGroupPolicyRegistrySandbox() {
319 void ScopedGroupPolicyRegistrySandbox::ActivateOverrides() {
320 ASSERT_HRESULT_SUCCEEDED(RegOverridePredefKey(HKEY_LOCAL_MACHINE
,
321 temp_hklm_hive_key_
.Handle()));
322 ASSERT_HRESULT_SUCCEEDED(RegOverridePredefKey(HKEY_CURRENT_USER
,
323 temp_hkcu_hive_key_
.Handle()));
326 void ScopedGroupPolicyRegistrySandbox::RemoveOverrides() {
327 ASSERT_HRESULT_SUCCEEDED(RegOverridePredefKey(HKEY_LOCAL_MACHINE
, 0));
328 ASSERT_HRESULT_SUCCEEDED(RegOverridePredefKey(HKEY_CURRENT_USER
, 0));
331 void ScopedGroupPolicyRegistrySandbox::DeleteKeys() {
332 RegKey
key(HKEY_CURRENT_USER
, key_name_
.c_str(), KEY_ALL_ACCESS
);
333 ASSERT_TRUE(key
.Valid());
337 RegistryTestHarness::RegistryTestHarness(HKEY hive
, PolicyScope scope
)
338 : PolicyProviderTestHarness(POLICY_LEVEL_MANDATORY
, scope
), hive_(hive
) {}
340 RegistryTestHarness::~RegistryTestHarness() {}
342 void RegistryTestHarness::SetUp() {}
344 ConfigurationPolicyProvider
* RegistryTestHarness::CreateProvider(
345 SchemaRegistry
* registry
,
346 scoped_refptr
<base::SequencedTaskRunner
> task_runner
) {
347 scoped_ptr
<AsyncPolicyLoader
> loader(
348 new PolicyLoaderWin(task_runner
, kTestPolicyKey
, this));
349 return new AsyncPolicyProvider(registry
, loader
.Pass());
352 void RegistryTestHarness::InstallEmptyPolicy() {}
354 void RegistryTestHarness::InstallStringPolicy(
355 const std::string
& policy_name
,
356 const std::string
& policy_value
) {
357 RegKey
key(hive_
, kTestPolicyKey
, KEY_ALL_ACCESS
);
358 ASSERT_TRUE(key
.Valid());
359 ASSERT_HRESULT_SUCCEEDED(key
.WriteValue(UTF8ToUTF16(policy_name
).c_str(),
360 UTF8ToUTF16(policy_value
).c_str()));
363 void RegistryTestHarness::InstallIntegerPolicy(
364 const std::string
& policy_name
,
366 RegKey
key(hive_
, kTestPolicyKey
, KEY_ALL_ACCESS
);
367 ASSERT_TRUE(key
.Valid());
368 key
.WriteValue(UTF8ToUTF16(policy_name
).c_str(),
369 static_cast<DWORD
>(policy_value
));
372 void RegistryTestHarness::InstallBooleanPolicy(
373 const std::string
& policy_name
,
375 RegKey
key(hive_
, kTestPolicyKey
, KEY_ALL_ACCESS
);
376 ASSERT_TRUE(key
.Valid());
377 key
.WriteValue(UTF8ToUTF16(policy_name
).c_str(),
378 static_cast<DWORD
>(policy_value
));
381 void RegistryTestHarness::InstallStringListPolicy(
382 const std::string
& policy_name
,
383 const base::ListValue
* policy_value
) {
385 (base::string16(kTestPolicyKey
) + ASCIIToUTF16("\\") +
386 UTF8ToUTF16(policy_name
)).c_str(),
388 ASSERT_TRUE(key
.Valid());
390 for (base::ListValue::const_iterator
element(policy_value
->begin());
391 element
!= policy_value
->end();
393 std::string element_value
;
394 if (!(*element
)->GetAsString(&element_value
))
396 std::string
name(base::IntToString(index
++));
397 key
.WriteValue(UTF8ToUTF16(name
).c_str(),
398 UTF8ToUTF16(element_value
).c_str());
402 void RegistryTestHarness::InstallDictionaryPolicy(
403 const std::string
& policy_name
,
404 const base::DictionaryValue
* policy_value
) {
406 base::JSONWriter::Write(policy_value
, &json
);
407 RegKey
key(hive_
, kTestPolicyKey
, KEY_ALL_ACCESS
);
408 ASSERT_TRUE(key
.Valid());
409 key
.WriteValue(UTF8ToUTF16(policy_name
).c_str(),
410 UTF8ToUTF16(json
).c_str());
413 void RegistryTestHarness::Install3rdPartyPolicy(
414 const base::DictionaryValue
* policies
) {
415 // The first level entries are domains, and the second level entries map
416 // components to their policy.
417 const base::string16 kPathPrefix
=
418 base::string16(kTestPolicyKey
) + kPathSep
+ kThirdParty
+ kPathSep
;
419 for (base::DictionaryValue::Iterator
domain(*policies
);
420 !domain
.IsAtEnd(); domain
.Advance()) {
421 const base::DictionaryValue
* components
= NULL
;
422 if (!domain
.value().GetAsDictionary(&components
)) {
426 for (base::DictionaryValue::Iterator
component(*components
);
427 !component
.IsAtEnd(); component
.Advance()) {
428 const base::string16 path
= kPathPrefix
+
429 UTF8ToUTF16(domain
.key()) + kPathSep
+ UTF8ToUTF16(component
.key());
430 InstallValue(component
.value(), hive_
, path
, kMandatory
);
435 DWORD
RegistryTestHarness::GetAppliedGPOList(DWORD flags
,
436 LPCTSTR machine_name
,
438 GUID
* extension_guid
,
439 PGROUP_POLICY_OBJECT
* gpo_list
) {
441 return ERROR_ACCESS_DENIED
;
444 BOOL
RegistryTestHarness::FreeGPOList(PGROUP_POLICY_OBJECT gpo_list
) {
449 PolicyProviderTestHarness
* RegistryTestHarness::CreateHKCU() {
450 return new RegistryTestHarness(HKEY_CURRENT_USER
, POLICY_SCOPE_USER
);
454 PolicyProviderTestHarness
* RegistryTestHarness::CreateHKLM() {
455 return new RegistryTestHarness(HKEY_LOCAL_MACHINE
, POLICY_SCOPE_MACHINE
);
458 PRegTestHarness::PRegTestHarness()
459 : PolicyProviderTestHarness(POLICY_LEVEL_MANDATORY
, POLICY_SCOPE_MACHINE
) {}
461 PRegTestHarness::~PRegTestHarness() {}
463 void PRegTestHarness::SetUp() {
464 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
465 preg_file_path_
= temp_dir_
.path().Append(PolicyLoaderWin::kPRegFileName
);
466 ASSERT_TRUE(file_util::WriteFile(preg_file_path_
,
467 preg_parser::kPRegFileHeader
,
468 arraysize(preg_parser::kPRegFileHeader
)));
470 memset(&gpo_
, 0, sizeof(GROUP_POLICY_OBJECT
));
471 gpo_
.lpFileSysPath
= const_cast<wchar_t*>(temp_dir_
.path().value().c_str());
474 ConfigurationPolicyProvider
* PRegTestHarness::CreateProvider(
475 SchemaRegistry
* registry
,
476 scoped_refptr
<base::SequencedTaskRunner
> task_runner
) {
477 scoped_ptr
<AsyncPolicyLoader
> loader(
478 new PolicyLoaderWin(task_runner
, kTestPolicyKey
, this));
479 return new AsyncPolicyProvider(registry
, loader
.Pass());
482 void PRegTestHarness::InstallEmptyPolicy() {}
484 void PRegTestHarness::InstallStringPolicy(const std::string
& policy_name
,
485 const std::string
& policy_value
) {
486 AppendStringToPRegFile(kTestPolicyKey
, policy_name
, policy_value
);
489 void PRegTestHarness::InstallIntegerPolicy(const std::string
& policy_name
,
491 AppendDWORDToPRegFile(kTestPolicyKey
, policy_name
, policy_value
);
494 void PRegTestHarness::InstallBooleanPolicy(const std::string
& policy_name
,
496 AppendDWORDToPRegFile(kTestPolicyKey
, policy_name
, policy_value
);
499 void PRegTestHarness::InstallStringListPolicy(
500 const std::string
& policy_name
,
501 const base::ListValue
* policy_value
) {
502 AppendPolicyToPRegFile(kTestPolicyKey
, policy_name
, policy_value
);
505 void PRegTestHarness::InstallDictionaryPolicy(
506 const std::string
& policy_name
,
507 const base::DictionaryValue
* policy_value
) {
509 base::JSONWriter::Write(policy_value
, &json
);
510 AppendStringToPRegFile(kTestPolicyKey
, policy_name
, json
);
513 void PRegTestHarness::Install3rdPartyPolicy(
514 const base::DictionaryValue
* policies
) {
515 // The first level entries are domains, and the second level entries map
516 // components to their policy.
517 const base::string16 kPathPrefix
=
518 base::string16(kTestPolicyKey
) + kPathSep
+ kThirdParty
+ kPathSep
;
519 for (base::DictionaryValue::Iterator
domain(*policies
);
520 !domain
.IsAtEnd(); domain
.Advance()) {
521 const base::DictionaryValue
* components
= NULL
;
522 if (!domain
.value().GetAsDictionary(&components
)) {
526 const base::string16 domain_path
= kPathPrefix
+ UTF8ToUTF16(domain
.key());
527 for (base::DictionaryValue::Iterator
component(*components
);
528 !component
.IsAtEnd(); component
.Advance()) {
529 const base::string16 component_path
=
530 domain_path
+ kPathSep
+ UTF8ToUTF16(component
.key());
531 AppendPolicyToPRegFile(component_path
, UTF16ToUTF8(kMandatory
),
537 DWORD
PRegTestHarness::GetAppliedGPOList(DWORD flags
,
538 LPCTSTR machine_name
,
540 GUID
* extension_guid
,
541 PGROUP_POLICY_OBJECT
* gpo_list
) {
542 *gpo_list
= flags
& GPO_LIST_FLAG_MACHINE
? &gpo_
: NULL
;
543 return ERROR_SUCCESS
;
546 BOOL
PRegTestHarness::FreeGPOList(PGROUP_POLICY_OBJECT gpo_list
) {
551 PolicyProviderTestHarness
* PRegTestHarness::Create() {
552 return new PRegTestHarness();
556 void PRegTestHarness::AppendChars(std::vector
<uint8
>* buffer
,
557 const base::string16
& chars
) {
558 for (base::string16::const_iterator
c(chars
.begin()); c
!= chars
.end(); ++c
) {
559 buffer
->push_back(*c
& 0xff);
560 buffer
->push_back((*c
>> 8) & 0xff);
564 void PRegTestHarness::AppendRecordToPRegFile(const base::string16
& path
,
565 const std::string
& key
,
569 std::vector
<uint8
> buffer
;
570 AppendChars(&buffer
, L
"[");
571 AppendChars(&buffer
, path
);
572 AppendChars(&buffer
, base::string16(L
"\0;", 2));
573 AppendChars(&buffer
, UTF8ToUTF16(key
));
574 AppendChars(&buffer
, base::string16(L
"\0;", 2));
575 type
= base::ByteSwapToLE32(type
);
576 uint8
* type_data
= reinterpret_cast<uint8
*>(&type
);
577 buffer
.insert(buffer
.end(), type_data
, type_data
+ sizeof(DWORD
));
578 AppendChars(&buffer
, L
";");
579 size
= base::ByteSwapToLE32(size
);
580 uint8
* size_data
= reinterpret_cast<uint8
*>(&size
);
581 buffer
.insert(buffer
.end(), size_data
, size_data
+ sizeof(DWORD
));
582 AppendChars(&buffer
, L
";");
583 buffer
.insert(buffer
.end(), data
, data
+ size
);
584 AppendChars(&buffer
, L
"]");
586 ASSERT_EQ(buffer
.size(),
587 file_util::AppendToFile(
589 reinterpret_cast<const char*>(vector_as_array(&buffer
)),
593 void PRegTestHarness::AppendDWORDToPRegFile(const base::string16
& path
,
594 const std::string
& key
,
596 value
= base::ByteSwapToLE32(value
);
597 AppendRecordToPRegFile(path
, key
, REG_DWORD
, sizeof(DWORD
),
598 reinterpret_cast<uint8
*>(&value
));
601 void PRegTestHarness::AppendStringToPRegFile(const base::string16
& path
,
602 const std::string
& key
,
603 const std::string
& value
) {
604 base::string16
string16_value(UTF8ToUTF16(value
));
605 std::vector
<char16
> data
;
606 std::transform(string16_value
.begin(), string16_value
.end(),
607 std::back_inserter(data
), std::ptr_fun(base::ByteSwapToLE16
));
608 data
.push_back(base::ByteSwapToLE16(L
'\0'));
610 AppendRecordToPRegFile(path
, key
, REG_SZ
, data
.size() * sizeof(char16
),
611 reinterpret_cast<uint8
*>(vector_as_array(&data
)));
614 void PRegTestHarness::AppendPolicyToPRegFile(const base::string16
& path
,
615 const std::string
& key
,
616 const base::Value
* value
) {
617 switch (value
->GetType()) {
618 case base::Value::TYPE_BOOLEAN
: {
619 bool boolean_value
= false;
620 ASSERT_TRUE(value
->GetAsBoolean(&boolean_value
));
621 AppendDWORDToPRegFile(path
, key
, boolean_value
);
624 case base::Value::TYPE_INTEGER
: {
626 ASSERT_TRUE(value
->GetAsInteger(&int_value
));
627 AppendDWORDToPRegFile(path
, key
, int_value
);
630 case base::Value::TYPE_DOUBLE
: {
631 double double_value
= 0;
632 ASSERT_TRUE(value
->GetAsDouble(&double_value
));
633 AppendStringToPRegFile(path
, key
, base::DoubleToString(double_value
));
636 case base::Value::TYPE_STRING
: {
637 std::string string_value
;
638 ASSERT_TRUE(value
->GetAsString(&string_value
));
639 AppendStringToPRegFile(path
, key
, string_value
);
642 case base::Value::TYPE_DICTIONARY
: {
643 base::string16 subpath
= path
+ kPathSep
+ UTF8ToUTF16(key
);
644 const base::DictionaryValue
* dict
= NULL
;
645 ASSERT_TRUE(value
->GetAsDictionary(&dict
));
646 for (base::DictionaryValue::Iterator
entry(*dict
); !entry
.IsAtEnd();
648 AppendPolicyToPRegFile(subpath
, entry
.key(), &entry
.value());
652 case base::Value::TYPE_LIST
: {
653 base::string16 subpath
= path
+ kPathSep
+ UTF8ToUTF16(key
);
654 const base::ListValue
* list
= NULL
;
655 ASSERT_TRUE(value
->GetAsList(&list
));
656 for (size_t i
= 0; i
< list
->GetSize(); ++i
) {
657 const base::Value
* entry
= NULL
;
658 ASSERT_TRUE(list
->Get(i
, &entry
));
659 AppendPolicyToPRegFile(subpath
, base::IntToString(i
+ 1), entry
);
663 case base::Value::TYPE_BINARY
:
664 case base::Value::TYPE_NULL
: {
673 // Instantiate abstract test case for basic policy reading tests.
674 INSTANTIATE_TEST_CASE_P(
675 PolicyProviderWinTest
,
676 ConfigurationPolicyProviderTest
,
677 testing::Values(RegistryTestHarness::CreateHKCU
,
678 RegistryTestHarness::CreateHKLM
,
679 PRegTestHarness::Create
));
681 // Instantiate abstract test case for 3rd party policy reading tests.
682 INSTANTIATE_TEST_CASE_P(
683 ThirdPartyPolicyProviderWinTest
,
684 Configuration3rdPartyPolicyProviderTest
,
685 testing::Values(RegistryTestHarness::CreateHKCU
,
686 RegistryTestHarness::CreateHKLM
,
687 PRegTestHarness::Create
));
689 // Test cases for windows policy provider specific functionality.
690 class PolicyLoaderWinTest
: public PolicyTestBase
,
691 public AppliedGPOListProvider
{
693 // The policy key this tests places data under. This must match the data
694 // files in chrome/test/data/policy/gpo.
695 static const char16 kTestPolicyKey
[];
697 PolicyLoaderWinTest()
699 gpo_list_status_(ERROR_ACCESS_DENIED
) {}
700 virtual ~PolicyLoaderWinTest() {}
702 virtual void SetUp() OVERRIDE
{
703 PolicyTestBase::SetUp();
705 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT
, &test_data_dir_
));
706 test_data_dir_
= test_data_dir_
.AppendASCII("chrome")
709 .AppendASCII("policy")
713 // AppliedGPOListProvider:
714 virtual DWORD
GetAppliedGPOList(DWORD flags
,
715 LPCTSTR machine_name
,
717 GUID
* extension_guid
,
718 PGROUP_POLICY_OBJECT
* gpo_list
) OVERRIDE
{
719 *gpo_list
= gpo_list_
;
720 return gpo_list_status_
;
722 virtual BOOL
FreeGPOList(PGROUP_POLICY_OBJECT gpo_list
) OVERRIDE
{
726 void InitGPO(GROUP_POLICY_OBJECT
* gpo
,
728 const base::FilePath
& path
,
729 GROUP_POLICY_OBJECT
* next
,
730 GROUP_POLICY_OBJECT
* prev
) {
731 memset(gpo
, 0, sizeof(GROUP_POLICY_OBJECT
));
732 gpo
->dwOptions
= options
;
733 gpo
->lpFileSysPath
= const_cast<wchar_t*>(path
.value().c_str());
738 bool Matches(const PolicyBundle
& expected
) {
739 PolicyLoaderWin
loader(loop_
.message_loop_proxy(), kTestPolicyKey
, this);
740 scoped_ptr
<PolicyBundle
> loaded(
741 loader
.InitialLoad(schema_registry_
.schema_map()));
742 return loaded
->Equals(expected
);
745 void InstallRegistrySentinel() {
746 RegKey
hklm_key(HKEY_CURRENT_USER
, kTestPolicyKey
, KEY_ALL_ACCESS
);
747 ASSERT_TRUE(hklm_key
.Valid());
749 UTF8ToUTF16(test_keys::kKeyString
).c_str(),
750 UTF8ToUTF16("registry").c_str());
753 bool MatchesRegistrySentinel() {
754 base::DictionaryValue expected_policy
;
755 expected_policy
.SetString(test_keys::kKeyString
, "registry");
756 PolicyBundle expected
;
757 expected
.Get(PolicyNamespace(POLICY_DOMAIN_CHROME
, std::string()))
758 .LoadFrom(&expected_policy
, POLICY_LEVEL_MANDATORY
, POLICY_SCOPE_USER
);
759 return Matches(expected
);
762 bool MatchesTestBundle() {
763 base::DictionaryValue expected_policy
;
764 expected_policy
.SetBoolean(test_keys::kKeyBoolean
, true);
765 expected_policy
.SetString(test_keys::kKeyString
, "GPO");
766 expected_policy
.SetInteger(test_keys::kKeyInteger
, 42);
767 scoped_ptr
<base::ListValue
> list(new base::ListValue());
768 list
->AppendString("GPO 1");
769 list
->AppendString("GPO 2");
770 expected_policy
.Set(test_keys::kKeyStringList
, list
.release());
771 PolicyBundle expected
;
772 expected
.Get(PolicyNamespace(POLICY_DOMAIN_CHROME
, std::string()))
773 .LoadFrom(&expected_policy
, POLICY_LEVEL_MANDATORY
,
774 POLICY_SCOPE_MACHINE
);
775 return Matches(expected
);
778 ScopedGroupPolicyRegistrySandbox registry_sandbox_
;
779 PGROUP_POLICY_OBJECT gpo_list_
;
780 DWORD gpo_list_status_
;
781 base::FilePath test_data_dir_
;
784 const char16
PolicyLoaderWinTest::kTestPolicyKey
[] =
785 L
"SOFTWARE\\Policies\\Chromium";
787 TEST_F(PolicyLoaderWinTest
, HKLMOverHKCU
) {
788 RegKey
hklm_key(HKEY_LOCAL_MACHINE
, kTestPolicyKey
, KEY_ALL_ACCESS
);
789 ASSERT_TRUE(hklm_key
.Valid());
790 hklm_key
.WriteValue(UTF8ToUTF16(test_keys::kKeyString
).c_str(),
791 UTF8ToUTF16("hklm").c_str());
792 RegKey
hkcu_key(HKEY_CURRENT_USER
, kTestPolicyKey
, KEY_ALL_ACCESS
);
793 ASSERT_TRUE(hkcu_key
.Valid());
794 hkcu_key
.WriteValue(UTF8ToUTF16(test_keys::kKeyString
).c_str(),
795 UTF8ToUTF16("hkcu").c_str());
797 PolicyBundle expected
;
798 expected
.Get(PolicyNamespace(POLICY_DOMAIN_CHROME
, std::string()))
799 .Set(test_keys::kKeyString
,
800 POLICY_LEVEL_MANDATORY
,
801 POLICY_SCOPE_MACHINE
,
802 base::Value::CreateStringValue("hklm"), NULL
);
803 EXPECT_TRUE(Matches(expected
));
806 TEST_F(PolicyLoaderWinTest
, Merge3rdPartyPolicies
) {
807 // Policy for the same extension will be provided at the 4 level/scope
808 // combinations, to verify that they overlap as expected.
809 const PolicyNamespace
ns(POLICY_DOMAIN_EXTENSIONS
, "merge");
810 ASSERT_TRUE(RegisterSchema(
813 " \"type\": \"object\","
815 " \"a\": { \"type\": \"string\" },"
816 " \"b\": { \"type\": \"string\" },"
817 " \"c\": { \"type\": \"string\" },"
818 " \"d\": { \"type\": \"string\" }"
822 const base::string16 kPathSuffix
=
823 kTestPolicyKey
+ ASCIIToUTF16("\\3rdparty\\extensions\\merge");
825 const char kUserMandatory
[] = "user-mandatory";
826 const char kUserRecommended
[] = "user-recommended";
827 const char kMachineMandatory
[] = "machine-mandatory";
828 const char kMachineRecommended
[] = "machine-recommended";
830 base::DictionaryValue policy
;
831 policy
.SetString("a", kMachineMandatory
);
832 EXPECT_TRUE(InstallValue(policy
, HKEY_LOCAL_MACHINE
,
833 kPathSuffix
, kMandatory
));
834 policy
.SetString("a", kUserMandatory
);
835 policy
.SetString("b", kUserMandatory
);
836 EXPECT_TRUE(InstallValue(policy
, HKEY_CURRENT_USER
,
837 kPathSuffix
, kMandatory
));
838 policy
.SetString("a", kMachineRecommended
);
839 policy
.SetString("b", kMachineRecommended
);
840 policy
.SetString("c", kMachineRecommended
);
841 EXPECT_TRUE(InstallValue(policy
, HKEY_LOCAL_MACHINE
,
842 kPathSuffix
, kRecommended
));
843 policy
.SetString("a", kUserRecommended
);
844 policy
.SetString("b", kUserRecommended
);
845 policy
.SetString("c", kUserRecommended
);
846 policy
.SetString("d", kUserRecommended
);
847 EXPECT_TRUE(InstallValue(policy
, HKEY_CURRENT_USER
,
848 kPathSuffix
, kRecommended
));
850 PolicyBundle expected
;
851 PolicyMap
& expected_policy
= expected
.Get(ns
);
852 expected_policy
.Set("a", POLICY_LEVEL_MANDATORY
, POLICY_SCOPE_MACHINE
,
853 base::Value::CreateStringValue(kMachineMandatory
), NULL
);
854 expected_policy
.Set("b", POLICY_LEVEL_MANDATORY
, POLICY_SCOPE_USER
,
855 base::Value::CreateStringValue(kUserMandatory
), NULL
);
856 expected_policy
.Set("c", POLICY_LEVEL_RECOMMENDED
, POLICY_SCOPE_MACHINE
,
857 base::Value::CreateStringValue(kMachineRecommended
),
859 expected_policy
.Set("d", POLICY_LEVEL_RECOMMENDED
, POLICY_SCOPE_USER
,
860 base::Value::CreateStringValue(kUserRecommended
), NULL
);
861 EXPECT_TRUE(Matches(expected
));
864 TEST_F(PolicyLoaderWinTest
, LoadStringEncodedValues
) {
865 // Create a dictionary with all the types that can be stored encoded in a
867 const PolicyNamespace
ns(POLICY_DOMAIN_EXTENSIONS
, "string");
868 ASSERT_TRUE(RegisterSchema(
871 " \"type\": \"object\","
872 " \"id\": \"MainType\","
874 " \"null\": { \"type\": \"null\" },"
875 " \"bool\": { \"type\": \"boolean\" },"
876 " \"int\": { \"type\": \"integer\" },"
877 " \"double\": { \"type\": \"number\" },"
879 " \"type\": \"array\","
880 " \"items\": { \"$ref\": \"MainType\" }"
882 " \"dict\": { \"$ref\": \"MainType\" }"
886 base::DictionaryValue policy
;
887 policy
.Set("null", base::Value::CreateNullValue());
888 policy
.SetBoolean("bool", true);
889 policy
.SetInteger("int", -123);
890 policy
.SetDouble("double", 456.78e9
);
891 base::ListValue list
;
892 list
.Append(policy
.DeepCopy());
893 list
.Append(policy
.DeepCopy());
894 policy
.Set("list", list
.DeepCopy());
895 // Encode |policy| before adding the "dict" entry.
896 std::string encoded_dict
;
897 base::JSONWriter::Write(&policy
, &encoded_dict
);
898 ASSERT_FALSE(encoded_dict
.empty());
899 policy
.Set("dict", policy
.DeepCopy());
900 std::string encoded_list
;
901 base::JSONWriter::Write(&list
, &encoded_list
);
902 ASSERT_FALSE(encoded_list
.empty());
903 base::DictionaryValue encoded_policy
;
904 encoded_policy
.SetString("null", "");
905 encoded_policy
.SetString("bool", "1");
906 encoded_policy
.SetString("int", "-123");
907 encoded_policy
.SetString("double", "456.78e9");
908 encoded_policy
.SetString("list", encoded_list
);
909 encoded_policy
.SetString("dict", encoded_dict
);
911 const base::string16 kPathSuffix
=
912 kTestPolicyKey
+ ASCIIToUTF16("\\3rdparty\\extensions\\string");
914 InstallValue(encoded_policy
, HKEY_CURRENT_USER
, kPathSuffix
, kMandatory
));
916 PolicyBundle expected
;
917 expected
.Get(ns
).LoadFrom(&policy
, POLICY_LEVEL_MANDATORY
, POLICY_SCOPE_USER
);
918 EXPECT_TRUE(Matches(expected
));
921 TEST_F(PolicyLoaderWinTest
, LoadIntegerEncodedValues
) {
922 const PolicyNamespace
ns(POLICY_DOMAIN_EXTENSIONS
, "int");
923 ASSERT_TRUE(RegisterSchema(
926 " \"type\": \"object\","
928 " \"bool\": { \"type\": \"boolean\" },"
929 " \"int\": { \"type\": \"integer\" },"
930 " \"double\": { \"type\": \"number\" }"
934 base::DictionaryValue encoded_policy
;
935 encoded_policy
.SetInteger("bool", 1);
936 encoded_policy
.SetInteger("int", 123);
937 encoded_policy
.SetInteger("double", 456);
939 const base::string16 kPathSuffix
=
940 kTestPolicyKey
+ ASCIIToUTF16("\\3rdparty\\extensions\\int");
942 InstallValue(encoded_policy
, HKEY_CURRENT_USER
, kPathSuffix
, kMandatory
));
944 base::DictionaryValue policy
;
945 policy
.SetBoolean("bool", true);
946 policy
.SetInteger("int", 123);
947 policy
.SetDouble("double", 456.0);
948 PolicyBundle expected
;
949 expected
.Get(ns
).LoadFrom(&policy
, POLICY_LEVEL_MANDATORY
, POLICY_SCOPE_USER
);
950 EXPECT_TRUE(Matches(expected
));
953 TEST_F(PolicyLoaderWinTest
, DefaultPropertySchemaType
) {
954 // Build a schema for an "object" with a default schema for its properties.
955 // Note that the top-level object can't have "additionalProperties", so
956 // a "policy" property is used instead.
957 const PolicyNamespace
ns(POLICY_DOMAIN_EXTENSIONS
, "test");
958 ASSERT_TRUE(RegisterSchema(
961 " \"type\": \"object\","
964 " \"type\": \"object\","
966 " \"special-int1\": { \"type\": \"integer\" },"
967 " \"special-int2\": { \"type\": \"integer\" }"
969 " \"additionalProperties\": { \"type\": \"number\" }"
974 // Write some test values.
975 base::DictionaryValue policy
;
976 // These special values have a specific schema for them.
977 policy
.SetInteger("special-int1", 123);
978 policy
.SetString("special-int2", "-456");
979 // Other values default to be loaded as doubles.
980 policy
.SetInteger("double1", 789.0);
981 policy
.SetString("double2", "123.456e7");
982 policy
.SetString("invalid", "omg");
983 base::DictionaryValue all_policies
;
984 all_policies
.Set("policy", policy
.DeepCopy());
986 const base::string16 kPathSuffix
=
987 kTestPolicyKey
+ ASCIIToUTF16("\\3rdparty\\extensions\\test");
989 InstallValue(all_policies
, HKEY_CURRENT_USER
, kPathSuffix
, kMandatory
));
991 base::DictionaryValue expected_policy
;
992 expected_policy
.SetInteger("special-int1", 123);
993 expected_policy
.SetInteger("special-int2", -456);
994 expected_policy
.SetDouble("double1", 789.0);
995 expected_policy
.SetDouble("double2", 123.456e7
);
996 base::DictionaryValue expected_policies
;
997 expected_policies
.Set("policy", expected_policy
.DeepCopy());
998 PolicyBundle expected
;
999 expected
.Get(ns
).LoadFrom(
1000 &expected_policies
, POLICY_LEVEL_MANDATORY
, POLICY_SCOPE_USER
);
1001 EXPECT_TRUE(Matches(expected
));
1004 TEST_F(PolicyLoaderWinTest
, AppliedPolicyNotPresent
) {
1005 InstallRegistrySentinel();
1007 gpo_list_status_
= ERROR_SUCCESS
;
1010 EXPECT_TRUE(Matches(empty
));
1013 TEST_F(PolicyLoaderWinTest
, AppliedPolicyEmpty
) {
1014 InstallRegistrySentinel();
1015 base::FilePath
gpo_dir(test_data_dir_
.AppendASCII("empty"));
1016 GROUP_POLICY_OBJECT gpo
;
1017 InitGPO(&gpo
, 0, gpo_dir
, NULL
, NULL
);
1019 gpo_list_status_
= ERROR_SUCCESS
;
1022 EXPECT_TRUE(Matches(empty
));
1025 TEST_F(PolicyLoaderWinTest
, AppliedPolicyNonExistingFile
) {
1026 InstallRegistrySentinel();
1027 GROUP_POLICY_OBJECT gpo
;
1028 InitGPO(&gpo
, 0, test_data_dir_
, NULL
, NULL
);
1030 gpo_list_status_
= ERROR_SUCCESS
;
1032 EXPECT_TRUE(MatchesRegistrySentinel());
1035 TEST_F(PolicyLoaderWinTest
, AppliedPolicyBadPath
) {
1036 InstallRegistrySentinel();
1037 base::FilePath
gpo_dir(test_data_dir_
.AppendASCII("bad"));
1038 GROUP_POLICY_OBJECT gpo
;
1039 InitGPO(&gpo
, 0, gpo_dir
, NULL
, NULL
);
1041 gpo_list_status_
= ERROR_SUCCESS
;
1043 EXPECT_TRUE(MatchesRegistrySentinel());
1046 TEST_F(PolicyLoaderWinTest
, AppliedPolicyPresent
) {
1047 InstallRegistrySentinel();
1048 base::FilePath
gpo_dir(test_data_dir_
.AppendASCII("test1"));
1049 GROUP_POLICY_OBJECT gpo
;
1050 InitGPO(&gpo
, 0, gpo_dir
, NULL
, NULL
);
1052 gpo_list_status_
= ERROR_SUCCESS
;
1054 EXPECT_TRUE(MatchesTestBundle());
1057 TEST_F(PolicyLoaderWinTest
, AppliedPolicyMerged
) {
1058 InstallRegistrySentinel();
1059 base::FilePath
gpo1_dir(test_data_dir_
.AppendASCII("test2"));
1060 base::FilePath
gpo2_dir(test_data_dir_
.AppendASCII("test1"));
1061 GROUP_POLICY_OBJECT gpo1
;
1062 GROUP_POLICY_OBJECT gpo2
;
1063 InitGPO(&gpo1
, 0, gpo1_dir
, &gpo2
, NULL
);
1064 InitGPO(&gpo2
, 0, gpo2_dir
, NULL
, &gpo1
);
1066 gpo_list_status_
= ERROR_SUCCESS
;
1068 EXPECT_TRUE(MatchesTestBundle());
1071 TEST_F(PolicyLoaderWinTest
, AppliedPolicyDisabled
) {
1072 InstallRegistrySentinel();
1073 base::FilePath
gpo1_dir(test_data_dir_
.AppendASCII("test1"));
1074 base::FilePath
gpo2_dir(test_data_dir_
.AppendASCII("test2"));
1075 GROUP_POLICY_OBJECT gpo1
;
1076 GROUP_POLICY_OBJECT gpo2
;
1077 InitGPO(&gpo1
, 0, gpo1_dir
, &gpo2
, NULL
);
1078 InitGPO(&gpo2
, GPO_FLAG_DISABLE
, gpo2_dir
, NULL
, &gpo1
);
1080 gpo_list_status_
= ERROR_SUCCESS
;
1082 EXPECT_TRUE(MatchesTestBundle());
1085 TEST_F(PolicyLoaderWinTest
, AppliedPolicyForcedPolicy
) {
1086 InstallRegistrySentinel();
1087 base::FilePath
gpo1_dir(test_data_dir_
.AppendASCII("test1"));
1088 base::FilePath
gpo2_dir(test_data_dir_
.AppendASCII("test2"));
1089 GROUP_POLICY_OBJECT gpo1
;
1090 GROUP_POLICY_OBJECT gpo2
;
1091 InitGPO(&gpo1
, GPO_FLAG_FORCE
, gpo1_dir
, &gpo2
, NULL
);
1092 InitGPO(&gpo2
, 0, gpo2_dir
, NULL
, &gpo1
);
1094 gpo_list_status_
= ERROR_SUCCESS
;
1096 EXPECT_TRUE(MatchesTestBundle());
1099 TEST_F(PolicyLoaderWinTest
, AppliedPolicyUNCPath
) {
1100 InstallRegistrySentinel();
1101 base::FilePath
gpo_dir(test_data_dir_
.AppendASCII("test1"));
1102 base::FilePath
unc_path(L
"\\\\some_share\\GPO");
1103 GROUP_POLICY_OBJECT gpo1
;
1104 GROUP_POLICY_OBJECT gpo2
;
1105 InitGPO(&gpo1
, 0, gpo_dir
, &gpo2
, NULL
);
1106 InitGPO(&gpo2
, 0, unc_path
, NULL
, &gpo1
);
1108 gpo_list_status_
= ERROR_SUCCESS
;
1110 EXPECT_TRUE(MatchesRegistrySentinel());
1113 TEST_F(PolicyLoaderWinTest
, LoadExtensionPolicyAlternativeSpelling
) {
1114 base::FilePath
gpo_dir(
1115 test_data_dir_
.AppendASCII("extension_alternative_spelling"));
1116 GROUP_POLICY_OBJECT gpo
;
1117 InitGPO(&gpo
, 0, gpo_dir
, NULL
, NULL
);
1119 gpo_list_status_
= ERROR_SUCCESS
;
1121 const char kTestSchema
[] =
1123 " \"type\": \"object\","
1124 " \"properties\": {"
1125 " \"policy 1\": { \"type\": \"integer\" },"
1126 " \"policy 2\": { \"type\": \"integer\" }"
1129 const PolicyNamespace
ns_a(
1130 POLICY_DOMAIN_EXTENSIONS
, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
1131 const PolicyNamespace
ns_b(
1132 POLICY_DOMAIN_EXTENSIONS
, "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb");
1133 ASSERT_TRUE(RegisterSchema(ns_a
, kTestSchema
));
1134 ASSERT_TRUE(RegisterSchema(ns_b
, kTestSchema
));
1136 PolicyBundle expected
;
1137 base::DictionaryValue expected_a
;
1138 expected_a
.SetInteger("policy 1", 3);
1139 expected_a
.SetInteger("policy 2", 3);
1140 expected
.Get(ns_a
).LoadFrom(
1141 &expected_a
, POLICY_LEVEL_MANDATORY
, POLICY_SCOPE_MACHINE
);
1142 base::DictionaryValue expected_b
;
1143 expected_b
.SetInteger("policy 1", 2);
1144 expected
.Get(ns_b
).LoadFrom(
1145 &expected_b
, POLICY_LEVEL_MANDATORY
, POLICY_SCOPE_MACHINE
);
1146 EXPECT_TRUE(Matches(expected
));
1149 TEST_F(PolicyLoaderWinTest
, LBSSupport
) {
1150 const PolicyNamespace
ns(
1151 POLICY_DOMAIN_EXTENSIONS
, "heildphpnddilhkemkielfhnkaagiabh");
1152 schema_registry_
.RegisterComponent(ns
, Schema());
1154 const char kIncompleteSchema
[] =
1156 " \"type\": \"object\","
1157 " \"properties\": {"
1158 " \"url_list\": { \"type\": \"array\" },"
1159 " \"url_greylist\": { \"type\": \"array\" }"
1163 const base::string16 kPathSuffix
=
1164 kTestPolicyKey
+ ASCIIToUTF16("\\3rdparty\\extensions");
1166 base::ListValue list
;
1167 list
.AppendString("youtube.com");
1168 base::DictionaryValue policy
;
1169 policy
.Set("url_list", list
.DeepCopy());
1170 policy
.SetString("alternative_browser_path", "c:\\legacy\\browser.exe");
1171 base::DictionaryValue root
;
1172 root
.Set(UTF16ToUTF8(kMandatory
), policy
.DeepCopy());
1173 root
.SetString(kSchema
, kIncompleteSchema
);
1174 EXPECT_TRUE(InstallValue(root
, HKEY_LOCAL_MACHINE
,
1175 kPathSuffix
, ASCIIToUTF16(ns
.component_id
)));
1177 PolicyBundle expected
;
1178 PolicyMap
& expected_policy
= expected
.Get(ns
);
1179 expected_policy
.Set("alternative_browser_path",
1180 POLICY_LEVEL_MANDATORY
, POLICY_SCOPE_MACHINE
,
1181 new base::StringValue("c:\\legacy\\browser.exe"), NULL
);
1182 expected_policy
.Set("url_list", POLICY_LEVEL_MANDATORY
, POLICY_SCOPE_MACHINE
,
1183 list
.DeepCopy(), NULL
);
1184 EXPECT_TRUE(Matches(expected
));
1187 } // namespace policy