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