Home | History | Annotate | Download | only in common
      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/files/file_path.h"
     19 #include "base/files/file_util.h"
     20 #include "base/files/scoped_temp_dir.h"
     21 #include "base/json/json_writer.h"
     22 #include "base/path_service.h"
     23 #include "base/process/process.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
   1219