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