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