| Index: chrome/browser/policy/policy_loader_win_unittest.cc
 | 
| diff --git a/chrome/browser/policy/policy_loader_win_unittest.cc b/chrome/browser/policy/policy_loader_win_unittest.cc
 | 
| deleted file mode 100644
 | 
| index 12ee9f6dc95fe38be7fc45120c7ed34418fe631f..0000000000000000000000000000000000000000
 | 
| --- a/chrome/browser/policy/policy_loader_win_unittest.cc
 | 
| +++ /dev/null
 | 
| @@ -1,1218 +0,0 @@
 | 
| -// Copyright (c) 2012 The Chromium Authors. All rights reserved.
 | 
| -// Use of this source code is governed by a BSD-style license that can be
 | 
| -// found in the LICENSE file.
 | 
| -
 | 
| -#include "chrome/browser/policy/policy_loader_win.h"
 | 
| -
 | 
| -#include <windows.h>
 | 
| -#include <userenv.h>
 | 
| -
 | 
| -#include <algorithm>
 | 
| -#include <cstring>
 | 
| -#include <functional>
 | 
| -#include <iterator>
 | 
| -#include <vector>
 | 
| -
 | 
| -#include "base/base_paths.h"
 | 
| -#include "base/callback.h"
 | 
| -#include "base/file_util.h"
 | 
| -#include "base/files/file_path.h"
 | 
| -#include "base/files/scoped_temp_dir.h"
 | 
| -#include "base/json/json_writer.h"
 | 
| -#include "base/path_service.h"
 | 
| -#include "base/process/process.h"
 | 
| -#include "base/strings/string16.h"
 | 
| -#include "base/strings/string_number_conversions.h"
 | 
| -#include "base/strings/string_util.h"
 | 
| -#include "base/strings/stringprintf.h"
 | 
| -#include "base/strings/utf_string_conversions.h"
 | 
| -#include "base/sys_byteorder.h"
 | 
| -#include "base/win/registry.h"
 | 
| -#include "chrome/browser/policy/preg_parser_win.h"
 | 
| -#include "components/json_schema/json_schema_constants.h"
 | 
| -#include "components/policy/core/common/async_policy_provider.h"
 | 
| -#include "components/policy/core/common/configuration_policy_provider_test.h"
 | 
| -#include "components/policy/core/common/external_data_fetcher.h"
 | 
| -#include "components/policy/core/common/policy_bundle.h"
 | 
| -#include "components/policy/core/common/policy_map.h"
 | 
| -#include "components/policy/core/common/schema_map.h"
 | 
| -#include "testing/gtest/include/gtest/gtest.h"
 | 
| -
 | 
| -namespace schema = json_schema_constants;
 | 
| -
 | 
| -using base::win::RegKey;
 | 
| -
 | 
| -namespace policy {
 | 
| -
 | 
| -namespace {
 | 
| -
 | 
| -// Constants for registry key names.
 | 
| -const wchar_t kPathSep[] = L"\\";
 | 
| -const wchar_t kThirdParty[] = L"3rdparty";
 | 
| -const wchar_t kMandatory[] = L"policy";
 | 
| -const wchar_t kRecommended[] = L"recommended";
 | 
| -const wchar_t kSchema[] = L"schema";
 | 
| -const wchar_t kTestPolicyKey[] = L"chrome.policy.key";
 | 
| -
 | 
| -// Installs |value| in the given registry |path| and |hive|, under the key
 | 
| -// |name|. Returns false on errors.
 | 
| -// Some of the possible Value types are stored after a conversion (e.g. doubles
 | 
| -// are stored as strings), and can only be retrieved if a corresponding schema
 | 
| -// is written.
 | 
| -bool InstallValue(const base::Value& value,
 | 
| -                  HKEY hive,
 | 
| -                  const string16& path,
 | 
| -                  const string16& name) {
 | 
| -  // KEY_ALL_ACCESS causes the ctor to create the key if it does not exist yet.
 | 
| -  RegKey key(hive, path.c_str(), KEY_ALL_ACCESS);
 | 
| -  EXPECT_TRUE(key.Valid());
 | 
| -  switch (value.GetType()) {
 | 
| -    case base::Value::TYPE_NULL:
 | 
| -      return key.WriteValue(name.c_str(), L"") == ERROR_SUCCESS;
 | 
| -
 | 
| -    case base::Value::TYPE_BOOLEAN: {
 | 
| -      bool bool_value;
 | 
| -      if (!value.GetAsBoolean(&bool_value))
 | 
| -        return false;
 | 
| -      return key.WriteValue(name.c_str(), bool_value ? 1 : 0) == ERROR_SUCCESS;
 | 
| -    }
 | 
| -
 | 
| -    case base::Value::TYPE_INTEGER: {
 | 
| -      int int_value;
 | 
| -      if (!value.GetAsInteger(&int_value))
 | 
| -        return false;
 | 
| -      return key.WriteValue(name.c_str(), int_value) == ERROR_SUCCESS;
 | 
| -    }
 | 
| -
 | 
| -    case base::Value::TYPE_DOUBLE: {
 | 
| -      double double_value;
 | 
| -      if (!value.GetAsDouble(&double_value))
 | 
| -        return false;
 | 
| -      string16 str_value = UTF8ToUTF16(base::DoubleToString(double_value));
 | 
| -      return key.WriteValue(name.c_str(), str_value.c_str()) == ERROR_SUCCESS;
 | 
| -    }
 | 
| -
 | 
| -    case base::Value::TYPE_STRING: {
 | 
| -      string16 str_value;
 | 
| -      if (!value.GetAsString(&str_value))
 | 
| -        return false;
 | 
| -      return key.WriteValue(name.c_str(), str_value.c_str()) == ERROR_SUCCESS;
 | 
| -    }
 | 
| -
 | 
| -    case base::Value::TYPE_DICTIONARY: {
 | 
| -      const base::DictionaryValue* sub_dict = NULL;
 | 
| -      if (!value.GetAsDictionary(&sub_dict))
 | 
| -        return false;
 | 
| -      for (base::DictionaryValue::Iterator it(*sub_dict);
 | 
| -           !it.IsAtEnd(); it.Advance()) {
 | 
| -        if (!InstallValue(it.value(), hive, path + kPathSep + name,
 | 
| -                          UTF8ToUTF16(it.key()))) {
 | 
| -          return false;
 | 
| -        }
 | 
| -      }
 | 
| -      return true;
 | 
| -    }
 | 
| -
 | 
| -    case base::Value::TYPE_LIST: {
 | 
| -      const base::ListValue* list = NULL;
 | 
| -      if (!value.GetAsList(&list))
 | 
| -        return false;
 | 
| -      for (size_t i = 0; i < list->GetSize(); ++i) {
 | 
| -        const base::Value* item;
 | 
| -        if (!list->Get(i, &item))
 | 
| -          return false;
 | 
| -        if (!InstallValue(*item, hive, path + kPathSep + name,
 | 
| -                          base::UintToString16(i + 1))) {
 | 
| -          return false;
 | 
| -        }
 | 
| -      }
 | 
| -      return true;
 | 
| -    }
 | 
| -
 | 
| -    case base::Value::TYPE_BINARY:
 | 
| -      return false;
 | 
| -  }
 | 
| -  NOTREACHED();
 | 
| -  return false;
 | 
| -}
 | 
| -
 | 
| -// Builds a JSON schema that represents the types contained in |value|.
 | 
| -// Ownership is transferred to the caller.
 | 
| -base::DictionaryValue* BuildSchema(const base::Value& value) {
 | 
| -  base::DictionaryValue* schema = new base::DictionaryValue();
 | 
| -  switch (value.GetType()) {
 | 
| -    case base::Value::TYPE_NULL:
 | 
| -      schema->SetString(schema::kType, "null");
 | 
| -      break;
 | 
| -    case base::Value::TYPE_BOOLEAN:
 | 
| -      schema->SetString(schema::kType, "boolean");
 | 
| -      break;
 | 
| -    case base::Value::TYPE_INTEGER:
 | 
| -      schema->SetString(schema::kType, "integer");
 | 
| -      break;
 | 
| -    case base::Value::TYPE_DOUBLE:
 | 
| -      schema->SetString(schema::kType, "number");
 | 
| -      break;
 | 
| -    case base::Value::TYPE_STRING:
 | 
| -      schema->SetString(schema::kType, "string");
 | 
| -      break;
 | 
| -
 | 
| -    case base::Value::TYPE_LIST: {
 | 
| -      // Assumes every list element has the same type.
 | 
| -      const base::ListValue* list = NULL;
 | 
| -      if (value.GetAsList(&list) && !list->empty()) {
 | 
| -        schema->SetString(schema::kType, "array");
 | 
| -        schema->Set(schema::kItems, BuildSchema(**list->begin()));
 | 
| -      }
 | 
| -      break;
 | 
| -    }
 | 
| -
 | 
| -    case base::Value::TYPE_DICTIONARY: {
 | 
| -      const base::DictionaryValue* dict = NULL;
 | 
| -      if (value.GetAsDictionary(&dict)) {
 | 
| -        base::DictionaryValue* properties = new base::DictionaryValue();
 | 
| -        for (base::DictionaryValue::Iterator it(*dict);
 | 
| -             !it.IsAtEnd(); it.Advance()) {
 | 
| -          properties->Set(it.key(), BuildSchema(it.value()));
 | 
| -        }
 | 
| -        schema->SetString(schema::kType, "object");
 | 
| -        schema->Set(schema::kProperties, properties);
 | 
| -      }
 | 
| -      break;
 | 
| -    }
 | 
| -
 | 
| -    case base::Value::TYPE_BINARY:
 | 
| -      break;
 | 
| -  }
 | 
| -  return schema;
 | 
| -}
 | 
| -
 | 
| -// Writes a JSON |schema| at the registry entry |name| at |path|
 | 
| -// in the given |hive|. Returns false on failure.
 | 
| -bool WriteSchema(const base::DictionaryValue& schema,
 | 
| -                 HKEY hive,
 | 
| -                 const string16& path,
 | 
| -                 const string16& name) {
 | 
| -  std::string encoded;
 | 
| -  base::JSONWriter::Write(&schema, &encoded);
 | 
| -  if (encoded.empty())
 | 
| -    return false;
 | 
| -  string16 encoded16 = UTF8ToUTF16(encoded);
 | 
| -  // KEY_ALL_ACCESS causes the ctor to create the key if it does not exist yet.
 | 
| -  RegKey key(hive, path.c_str(), KEY_ALL_ACCESS);
 | 
| -  EXPECT_TRUE(key.Valid());
 | 
| -  return key.WriteValue(name.c_str(), encoded16.c_str()) == ERROR_SUCCESS;
 | 
| -}
 | 
| -
 | 
| -// Builds a JSON schema for |value| and writes it at the registry entry |name|
 | 
| -// at |path| in the given |hive|. Returns false on failure.
 | 
| -bool InstallSchema(const base::Value& value,
 | 
| -                   HKEY hive,
 | 
| -                   const string16& path,
 | 
| -                   const string16& name) {
 | 
| -  scoped_ptr<base::DictionaryValue> schema_dict(BuildSchema(value));
 | 
| -  return WriteSchema(*schema_dict, hive, path, name);
 | 
| -}
 | 
| -
 | 
| -// This class provides sandboxing and mocking for the parts of the Windows
 | 
| -// Registry implementing Group Policy. It prepares two temporary sandbox keys,
 | 
| -// one for HKLM and one for HKCU. A test's calls to the registry are redirected
 | 
| -// by Windows to these sandboxes, allowing the tests to manipulate and access
 | 
| -// policy as if it were active, but without actually changing the parts of the
 | 
| -// Registry that are managed by Group Policy.
 | 
| -class ScopedGroupPolicyRegistrySandbox {
 | 
| - public:
 | 
| -  ScopedGroupPolicyRegistrySandbox();
 | 
| -  ~ScopedGroupPolicyRegistrySandbox();
 | 
| -
 | 
| - private:
 | 
| -  void ActivateOverrides();
 | 
| -  void RemoveOverrides();
 | 
| -
 | 
| -  // Deletes the sandbox keys.
 | 
| -  void DeleteKeys();
 | 
| -
 | 
| -  std::wstring key_name_;
 | 
| -
 | 
| -  // Keys are created for the lifetime of a test to contain
 | 
| -  // the sandboxed HKCU and HKLM hives, respectively.
 | 
| -  RegKey temp_hkcu_hive_key_;
 | 
| -  RegKey temp_hklm_hive_key_;
 | 
| -
 | 
| -  DISALLOW_COPY_AND_ASSIGN(ScopedGroupPolicyRegistrySandbox);
 | 
| -};
 | 
| -
 | 
| -// A test harness that feeds policy via the Chrome GPO registry subtree.
 | 
| -class RegistryTestHarness : public PolicyProviderTestHarness,
 | 
| -                            public AppliedGPOListProvider {
 | 
| - public:
 | 
| -  RegistryTestHarness(HKEY hive, PolicyScope scope);
 | 
| -  virtual ~RegistryTestHarness();
 | 
| -
 | 
| -  // PolicyProviderTestHarness:
 | 
| -  virtual void SetUp() OVERRIDE;
 | 
| -
 | 
| -  virtual ConfigurationPolicyProvider* CreateProvider(
 | 
| -      SchemaRegistry* registry,
 | 
| -      scoped_refptr<base::SequencedTaskRunner> task_runner) OVERRIDE;
 | 
| -
 | 
| -  virtual void InstallEmptyPolicy() OVERRIDE;
 | 
| -  virtual void InstallStringPolicy(const std::string& policy_name,
 | 
| -                                   const std::string& policy_value) OVERRIDE;
 | 
| -  virtual void InstallIntegerPolicy(const std::string& policy_name,
 | 
| -                                    int policy_value) OVERRIDE;
 | 
| -  virtual void InstallBooleanPolicy(const std::string& policy_name,
 | 
| -                                    bool policy_value) OVERRIDE;
 | 
| -  virtual void InstallStringListPolicy(
 | 
| -      const std::string& policy_name,
 | 
| -      const base::ListValue* policy_value) OVERRIDE;
 | 
| -  virtual void InstallDictionaryPolicy(
 | 
| -      const std::string& policy_name,
 | 
| -      const base::DictionaryValue* policy_value) OVERRIDE;
 | 
| -  virtual void Install3rdPartyPolicy(
 | 
| -      const base::DictionaryValue* policies) OVERRIDE;
 | 
| -
 | 
| -  // AppliedGPOListProvider:
 | 
| -  virtual DWORD GetAppliedGPOList(DWORD flags,
 | 
| -                                  LPCTSTR machine_name,
 | 
| -                                  PSID sid_user,
 | 
| -                                  GUID* extension_guid,
 | 
| -                                  PGROUP_POLICY_OBJECT* gpo_list) OVERRIDE;
 | 
| -  virtual BOOL FreeGPOList(PGROUP_POLICY_OBJECT gpo_list) OVERRIDE;
 | 
| -
 | 
| -  // Creates a harness instance that will install policy in HKCU or HKLM,
 | 
| -  // respectively.
 | 
| -  static PolicyProviderTestHarness* CreateHKCU();
 | 
| -  static PolicyProviderTestHarness* CreateHKLM();
 | 
| -
 | 
| - private:
 | 
| -  HKEY hive_;
 | 
| -
 | 
| -  ScopedGroupPolicyRegistrySandbox registry_sandbox_;
 | 
| -
 | 
| -  DISALLOW_COPY_AND_ASSIGN(RegistryTestHarness);
 | 
| -};
 | 
| -
 | 
| -// A test harness that generates PReg files for the provider to read.
 | 
| -class PRegTestHarness : public PolicyProviderTestHarness,
 | 
| -                        public AppliedGPOListProvider {
 | 
| - public:
 | 
| -  PRegTestHarness();
 | 
| -  virtual ~PRegTestHarness();
 | 
| -
 | 
| -  // PolicyProviderTestHarness:
 | 
| -  virtual void SetUp() OVERRIDE;
 | 
| -
 | 
| -  virtual ConfigurationPolicyProvider* CreateProvider(
 | 
| -      SchemaRegistry* registry,
 | 
| -      scoped_refptr<base::SequencedTaskRunner> task_runner) OVERRIDE;
 | 
| -
 | 
| -  virtual void InstallEmptyPolicy() OVERRIDE;
 | 
| -  virtual void InstallStringPolicy(const std::string& policy_name,
 | 
| -                                   const std::string& policy_value) OVERRIDE;
 | 
| -  virtual void InstallIntegerPolicy(const std::string& policy_name,
 | 
| -                                    int policy_value) OVERRIDE;
 | 
| -  virtual void InstallBooleanPolicy(const std::string& policy_name,
 | 
| -                                    bool policy_value) OVERRIDE;
 | 
| -  virtual void InstallStringListPolicy(
 | 
| -      const std::string& policy_name,
 | 
| -      const base::ListValue* policy_value) OVERRIDE;
 | 
| -  virtual void InstallDictionaryPolicy(
 | 
| -      const std::string& policy_name,
 | 
| -      const base::DictionaryValue* policy_value) OVERRIDE;
 | 
| -  virtual void Install3rdPartyPolicy(
 | 
| -      const base::DictionaryValue* policies) OVERRIDE;
 | 
| -
 | 
| -  // AppliedGPOListProvider:
 | 
| -  virtual DWORD GetAppliedGPOList(DWORD flags,
 | 
| -                                  LPCTSTR machine_name,
 | 
| -                                  PSID sid_user,
 | 
| -                                  GUID* extension_guid,
 | 
| -                                  PGROUP_POLICY_OBJECT* gpo_list) OVERRIDE;
 | 
| -  virtual BOOL FreeGPOList(PGROUP_POLICY_OBJECT gpo_list) OVERRIDE;
 | 
| -
 | 
| -  // Creates a harness instance.
 | 
| -  static PolicyProviderTestHarness* Create();
 | 
| -
 | 
| - private:
 | 
| -  // Helper to append a string16 to an uint8 buffer.
 | 
| -  static void AppendChars(std::vector<uint8>* buffer, const string16& chars);
 | 
| -
 | 
| -  // Appends a record with the given fields to the PReg file.
 | 
| -  void AppendRecordToPRegFile(const string16& path,
 | 
| -                              const std::string& key,
 | 
| -                              DWORD type,
 | 
| -                              DWORD size,
 | 
| -                              uint8* data);
 | 
| -
 | 
| -  // Appends the given DWORD |value| for |path| + |key| to the PReg file.
 | 
| -  void AppendDWORDToPRegFile(const string16& path,
 | 
| -                             const std::string& key,
 | 
| -                             DWORD value);
 | 
| -
 | 
| -  // Appends the given string |value| for |path| + |key| to the PReg file.
 | 
| -  void AppendStringToPRegFile(const string16& path,
 | 
| -                              const std::string& key,
 | 
| -                              const std::string& value);
 | 
| -
 | 
| -  // Appends the given policy |value| for |path| + |key| to the PReg file,
 | 
| -  // converting and recursing as necessary.
 | 
| -  void AppendPolicyToPRegFile(const string16& path,
 | 
| -                              const std::string& key,
 | 
| -                              const base::Value* value);
 | 
| -
 | 
| -  base::ScopedTempDir temp_dir_;
 | 
| -  base::FilePath preg_file_path_;
 | 
| -  GROUP_POLICY_OBJECT gpo_;
 | 
| -
 | 
| -  DISALLOW_COPY_AND_ASSIGN(PRegTestHarness);
 | 
| -};
 | 
| -
 | 
| -ScopedGroupPolicyRegistrySandbox::ScopedGroupPolicyRegistrySandbox() {
 | 
| -  // Generate a unique registry key for the override for each test. This
 | 
| -  // makes sure that tests executing in parallel won't delete each other's
 | 
| -  // key, at DeleteKeys().
 | 
| -  key_name_ = ASCIIToWide(base::StringPrintf(
 | 
| -        "SOFTWARE\\chromium unittest %d",
 | 
| -        base::Process::Current().pid()));
 | 
| -  std::wstring hklm_key_name = key_name_ + L"\\HKLM";
 | 
| -  std::wstring hkcu_key_name = key_name_ + L"\\HKCU";
 | 
| -
 | 
| -  // Create the subkeys to hold the overridden HKLM and HKCU
 | 
| -  // policy settings.
 | 
| -  temp_hklm_hive_key_.Create(HKEY_CURRENT_USER,
 | 
| -                             hklm_key_name.c_str(),
 | 
| -                             KEY_ALL_ACCESS);
 | 
| -  temp_hkcu_hive_key_.Create(HKEY_CURRENT_USER,
 | 
| -                             hkcu_key_name.c_str(),
 | 
| -                             KEY_ALL_ACCESS);
 | 
| -
 | 
| -  ActivateOverrides();
 | 
| -}
 | 
| -
 | 
| -ScopedGroupPolicyRegistrySandbox::~ScopedGroupPolicyRegistrySandbox() {
 | 
| -  RemoveOverrides();
 | 
| -  DeleteKeys();
 | 
| -}
 | 
| -
 | 
| -void ScopedGroupPolicyRegistrySandbox::ActivateOverrides() {
 | 
| -  ASSERT_HRESULT_SUCCEEDED(RegOverridePredefKey(HKEY_LOCAL_MACHINE,
 | 
| -                                                temp_hklm_hive_key_.Handle()));
 | 
| -  ASSERT_HRESULT_SUCCEEDED(RegOverridePredefKey(HKEY_CURRENT_USER,
 | 
| -                                                temp_hkcu_hive_key_.Handle()));
 | 
| -}
 | 
| -
 | 
| -void ScopedGroupPolicyRegistrySandbox::RemoveOverrides() {
 | 
| -  ASSERT_HRESULT_SUCCEEDED(RegOverridePredefKey(HKEY_LOCAL_MACHINE, 0));
 | 
| -  ASSERT_HRESULT_SUCCEEDED(RegOverridePredefKey(HKEY_CURRENT_USER, 0));
 | 
| -}
 | 
| -
 | 
| -void ScopedGroupPolicyRegistrySandbox::DeleteKeys() {
 | 
| -  RegKey key(HKEY_CURRENT_USER, key_name_.c_str(), KEY_ALL_ACCESS);
 | 
| -  ASSERT_TRUE(key.Valid());
 | 
| -  key.DeleteKey(L"");
 | 
| -}
 | 
| -
 | 
| -RegistryTestHarness::RegistryTestHarness(HKEY hive, PolicyScope scope)
 | 
| -    : PolicyProviderTestHarness(POLICY_LEVEL_MANDATORY, scope), hive_(hive) {}
 | 
| -
 | 
| -RegistryTestHarness::~RegistryTestHarness() {}
 | 
| -
 | 
| -void RegistryTestHarness::SetUp() {}
 | 
| -
 | 
| -ConfigurationPolicyProvider* RegistryTestHarness::CreateProvider(
 | 
| -    SchemaRegistry* registry,
 | 
| -    scoped_refptr<base::SequencedTaskRunner> task_runner) {
 | 
| -  scoped_ptr<AsyncPolicyLoader> loader(
 | 
| -      new PolicyLoaderWin(task_runner, kTestPolicyKey, this));
 | 
| -  return new AsyncPolicyProvider(registry, loader.Pass());
 | 
| -}
 | 
| -
 | 
| -void RegistryTestHarness::InstallEmptyPolicy() {}
 | 
| -
 | 
| -void RegistryTestHarness::InstallStringPolicy(
 | 
| -    const std::string& policy_name,
 | 
| -    const std::string& policy_value) {
 | 
| -  RegKey key(hive_, kTestPolicyKey, KEY_ALL_ACCESS);
 | 
| -  ASSERT_TRUE(key.Valid());
 | 
| -  ASSERT_HRESULT_SUCCEEDED(key.WriteValue(UTF8ToUTF16(policy_name).c_str(),
 | 
| -                                          UTF8ToUTF16(policy_value).c_str()));
 | 
| -}
 | 
| -
 | 
| -void RegistryTestHarness::InstallIntegerPolicy(
 | 
| -    const std::string& policy_name,
 | 
| -    int policy_value) {
 | 
| -  RegKey key(hive_, kTestPolicyKey, KEY_ALL_ACCESS);
 | 
| -  ASSERT_TRUE(key.Valid());
 | 
| -  key.WriteValue(UTF8ToUTF16(policy_name).c_str(),
 | 
| -                 static_cast<DWORD>(policy_value));
 | 
| -}
 | 
| -
 | 
| -void RegistryTestHarness::InstallBooleanPolicy(
 | 
| -    const std::string& policy_name,
 | 
| -    bool policy_value) {
 | 
| -  RegKey key(hive_, kTestPolicyKey, KEY_ALL_ACCESS);
 | 
| -  ASSERT_TRUE(key.Valid());
 | 
| -  key.WriteValue(UTF8ToUTF16(policy_name).c_str(),
 | 
| -                 static_cast<DWORD>(policy_value));
 | 
| -}
 | 
| -
 | 
| -void RegistryTestHarness::InstallStringListPolicy(
 | 
| -    const std::string& policy_name,
 | 
| -    const base::ListValue* policy_value) {
 | 
| -  RegKey key(hive_,
 | 
| -             (string16(kTestPolicyKey) + ASCIIToUTF16("\\") +
 | 
| -              UTF8ToUTF16(policy_name)).c_str(),
 | 
| -             KEY_ALL_ACCESS);
 | 
| -  ASSERT_TRUE(key.Valid());
 | 
| -  int index = 1;
 | 
| -  for (base::ListValue::const_iterator element(policy_value->begin());
 | 
| -       element != policy_value->end();
 | 
| -       ++element) {
 | 
| -    std::string element_value;
 | 
| -    if (!(*element)->GetAsString(&element_value))
 | 
| -      continue;
 | 
| -    std::string name(base::IntToString(index++));
 | 
| -    key.WriteValue(UTF8ToUTF16(name).c_str(),
 | 
| -                   UTF8ToUTF16(element_value).c_str());
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -void RegistryTestHarness::InstallDictionaryPolicy(
 | 
| -    const std::string& policy_name,
 | 
| -    const base::DictionaryValue* policy_value) {
 | 
| -  std::string json;
 | 
| -  base::JSONWriter::Write(policy_value, &json);
 | 
| -  RegKey key(hive_, kTestPolicyKey, KEY_ALL_ACCESS);
 | 
| -  ASSERT_TRUE(key.Valid());
 | 
| -  key.WriteValue(UTF8ToUTF16(policy_name).c_str(),
 | 
| -                 UTF8ToUTF16(json).c_str());
 | 
| -}
 | 
| -
 | 
| -void RegistryTestHarness::Install3rdPartyPolicy(
 | 
| -    const base::DictionaryValue* policies) {
 | 
| -  // The first level entries are domains, and the second level entries map
 | 
| -  // components to their policy.
 | 
| -  const string16 kPathPrefix = string16(kTestPolicyKey) + kPathSep +
 | 
| -                               kThirdParty + kPathSep;
 | 
| -  for (base::DictionaryValue::Iterator domain(*policies);
 | 
| -       !domain.IsAtEnd(); domain.Advance()) {
 | 
| -    const base::DictionaryValue* components = NULL;
 | 
| -    if (!domain.value().GetAsDictionary(&components)) {
 | 
| -      ADD_FAILURE();
 | 
| -      continue;
 | 
| -    }
 | 
| -    for (base::DictionaryValue::Iterator component(*components);
 | 
| -         !component.IsAtEnd(); component.Advance()) {
 | 
| -      const string16 path = kPathPrefix +
 | 
| -                            UTF8ToUTF16(domain.key()) + kPathSep +
 | 
| -                            UTF8ToUTF16(component.key());
 | 
| -      InstallValue(component.value(), hive_, path, kMandatory);
 | 
| -      EXPECT_TRUE(InstallSchema(component.value(), hive_, path, kSchema));
 | 
| -    }
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -DWORD RegistryTestHarness::GetAppliedGPOList(DWORD flags,
 | 
| -                                             LPCTSTR machine_name,
 | 
| -                                             PSID sid_user,
 | 
| -                                             GUID* extension_guid,
 | 
| -                                             PGROUP_POLICY_OBJECT* gpo_list) {
 | 
| -  *gpo_list = NULL;
 | 
| -  return ERROR_ACCESS_DENIED;
 | 
| -}
 | 
| -
 | 
| -BOOL RegistryTestHarness::FreeGPOList(PGROUP_POLICY_OBJECT gpo_list) {
 | 
| -  return TRUE;
 | 
| -}
 | 
| -
 | 
| -// static
 | 
| -PolicyProviderTestHarness* RegistryTestHarness::CreateHKCU() {
 | 
| -  return new RegistryTestHarness(HKEY_CURRENT_USER, POLICY_SCOPE_USER);
 | 
| -}
 | 
| -
 | 
| -// static
 | 
| -PolicyProviderTestHarness* RegistryTestHarness::CreateHKLM() {
 | 
| -  return new RegistryTestHarness(HKEY_LOCAL_MACHINE, POLICY_SCOPE_MACHINE);
 | 
| -}
 | 
| -
 | 
| -PRegTestHarness::PRegTestHarness()
 | 
| -    : PolicyProviderTestHarness(POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE) {}
 | 
| -
 | 
| -PRegTestHarness::~PRegTestHarness() {}
 | 
| -
 | 
| -void PRegTestHarness::SetUp() {
 | 
| -  ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
 | 
| -  preg_file_path_ = temp_dir_.path().Append(PolicyLoaderWin::kPRegFileName);
 | 
| -  ASSERT_TRUE(file_util::WriteFile(preg_file_path_,
 | 
| -                                   preg_parser::kPRegFileHeader,
 | 
| -                                   arraysize(preg_parser::kPRegFileHeader)));
 | 
| -
 | 
| -  memset(&gpo_, 0, sizeof(GROUP_POLICY_OBJECT));
 | 
| -  gpo_.lpFileSysPath = const_cast<wchar_t*>(temp_dir_.path().value().c_str());
 | 
| -}
 | 
| -
 | 
| -ConfigurationPolicyProvider* PRegTestHarness::CreateProvider(
 | 
| -    SchemaRegistry* registry,
 | 
| -    scoped_refptr<base::SequencedTaskRunner> task_runner) {
 | 
| -  scoped_ptr<AsyncPolicyLoader> loader(
 | 
| -      new PolicyLoaderWin(task_runner, kTestPolicyKey, this));
 | 
| -  return new AsyncPolicyProvider(registry, loader.Pass());
 | 
| -}
 | 
| -
 | 
| -void PRegTestHarness::InstallEmptyPolicy() {}
 | 
| -
 | 
| -void PRegTestHarness::InstallStringPolicy(const std::string& policy_name,
 | 
| -                                          const std::string& policy_value) {
 | 
| -  AppendStringToPRegFile(kTestPolicyKey, policy_name, policy_value);
 | 
| -}
 | 
| -
 | 
| -void PRegTestHarness::InstallIntegerPolicy(const std::string& policy_name,
 | 
| -                                           int policy_value) {
 | 
| -  AppendDWORDToPRegFile(kTestPolicyKey, policy_name, policy_value);
 | 
| -}
 | 
| -
 | 
| -void PRegTestHarness::InstallBooleanPolicy(const std::string& policy_name,
 | 
| -                                           bool policy_value) {
 | 
| -  AppendDWORDToPRegFile(kTestPolicyKey, policy_name, policy_value);
 | 
| -}
 | 
| -
 | 
| -void PRegTestHarness::InstallStringListPolicy(
 | 
| -    const std::string& policy_name,
 | 
| -    const base::ListValue* policy_value) {
 | 
| -  AppendPolicyToPRegFile(kTestPolicyKey, policy_name, policy_value);
 | 
| -}
 | 
| -
 | 
| -void PRegTestHarness::InstallDictionaryPolicy(
 | 
| -    const std::string& policy_name,
 | 
| -    const base::DictionaryValue* policy_value) {
 | 
| -  std::string json;
 | 
| -  base::JSONWriter::Write(policy_value, &json);
 | 
| -  AppendStringToPRegFile(kTestPolicyKey, policy_name, json);
 | 
| -}
 | 
| -
 | 
| -void PRegTestHarness::Install3rdPartyPolicy(
 | 
| -    const base::DictionaryValue* policies) {
 | 
| -  // The first level entries are domains, and the second level entries map
 | 
| -  // components to their policy.
 | 
| -  const string16 kPathPrefix = string16(kTestPolicyKey) + kPathSep +
 | 
| -                               kThirdParty + kPathSep;
 | 
| -  for (base::DictionaryValue::Iterator domain(*policies);
 | 
| -       !domain.IsAtEnd(); domain.Advance()) {
 | 
| -    const base::DictionaryValue* components = NULL;
 | 
| -    if (!domain.value().GetAsDictionary(&components)) {
 | 
| -      ADD_FAILURE();
 | 
| -      continue;
 | 
| -    }
 | 
| -    const string16 domain_path = kPathPrefix + UTF8ToUTF16(domain.key());
 | 
| -    for (base::DictionaryValue::Iterator component(*components);
 | 
| -         !component.IsAtEnd(); component.Advance()) {
 | 
| -      const string16 component_path =
 | 
| -          domain_path + kPathSep + UTF8ToUTF16(component.key());
 | 
| -      AppendPolicyToPRegFile(component_path, UTF16ToUTF8(kMandatory),
 | 
| -                             &component.value());
 | 
| -
 | 
| -      scoped_ptr<base::DictionaryValue> schema_dict(
 | 
| -          BuildSchema(component.value()));
 | 
| -      std::string schema_json;
 | 
| -      base::JSONWriter::Write(schema_dict.get(), &schema_json);
 | 
| -      if (!schema_json.empty()) {
 | 
| -        AppendStringToPRegFile(component_path, UTF16ToUTF8(kSchema),
 | 
| -                               schema_json);
 | 
| -      }
 | 
| -    }
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -DWORD PRegTestHarness::GetAppliedGPOList(DWORD flags,
 | 
| -                                         LPCTSTR machine_name,
 | 
| -                                         PSID sid_user,
 | 
| -                                         GUID* extension_guid,
 | 
| -                                         PGROUP_POLICY_OBJECT* gpo_list) {
 | 
| -  *gpo_list = flags & GPO_LIST_FLAG_MACHINE ? &gpo_ : NULL;
 | 
| -  return ERROR_SUCCESS;
 | 
| -}
 | 
| -
 | 
| -BOOL PRegTestHarness::FreeGPOList(PGROUP_POLICY_OBJECT gpo_list) {
 | 
| -  return TRUE;
 | 
| -}
 | 
| -
 | 
| -// static
 | 
| -PolicyProviderTestHarness* PRegTestHarness::Create() {
 | 
| -  return new PRegTestHarness();
 | 
| -}
 | 
| -
 | 
| -// static
 | 
| -void PRegTestHarness::AppendChars(std::vector<uint8>* buffer,
 | 
| -                                  const string16& chars) {
 | 
| -  for (string16::const_iterator c(chars.begin()); c != chars.end(); ++c) {
 | 
| -    buffer->push_back(*c & 0xff);
 | 
| -    buffer->push_back((*c >> 8) & 0xff);
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -void PRegTestHarness::AppendRecordToPRegFile(const string16& path,
 | 
| -                                             const std::string& key,
 | 
| -                                             DWORD type,
 | 
| -                                             DWORD size,
 | 
| -                                             uint8* data) {
 | 
| -  std::vector<uint8> buffer;
 | 
| -  AppendChars(&buffer, L"[");
 | 
| -  AppendChars(&buffer, path);
 | 
| -  AppendChars(&buffer, string16(L"\0;", 2));
 | 
| -  AppendChars(&buffer, UTF8ToUTF16(key));
 | 
| -  AppendChars(&buffer, string16(L"\0;", 2));
 | 
| -  type = base::ByteSwapToLE32(type);
 | 
| -  uint8* type_data = reinterpret_cast<uint8*>(&type);
 | 
| -  buffer.insert(buffer.end(), type_data, type_data + sizeof(DWORD));
 | 
| -  AppendChars(&buffer, L";");
 | 
| -  size = base::ByteSwapToLE32(size);
 | 
| -  uint8* size_data = reinterpret_cast<uint8*>(&size);
 | 
| -  buffer.insert(buffer.end(), size_data, size_data + sizeof(DWORD));
 | 
| -  AppendChars(&buffer, L";");
 | 
| -  buffer.insert(buffer.end(), data, data + size);
 | 
| -  AppendChars(&buffer, L"]");
 | 
| -
 | 
| -  ASSERT_EQ(buffer.size(),
 | 
| -            file_util::AppendToFile(
 | 
| -                preg_file_path_,
 | 
| -                reinterpret_cast<const char*>(vector_as_array(&buffer)),
 | 
| -                buffer.size()));
 | 
| -}
 | 
| -
 | 
| -void PRegTestHarness::AppendDWORDToPRegFile(const string16& path,
 | 
| -                                            const std::string& key,
 | 
| -                                            DWORD value) {
 | 
| -  value = base::ByteSwapToLE32(value);
 | 
| -  AppendRecordToPRegFile(path, key, REG_DWORD, sizeof(DWORD),
 | 
| -                         reinterpret_cast<uint8*>(&value));
 | 
| -}
 | 
| -
 | 
| -void PRegTestHarness::AppendStringToPRegFile(const string16& path,
 | 
| -                                             const std::string& key,
 | 
| -                                             const std::string& value) {
 | 
| -  string16 string16_value(UTF8ToUTF16(value));
 | 
| -  std::vector<char16> data;
 | 
| -  std::transform(string16_value.begin(), string16_value.end(),
 | 
| -                 std::back_inserter(data), std::ptr_fun(base::ByteSwapToLE16));
 | 
| -  data.push_back(base::ByteSwapToLE16(L'\0'));
 | 
| -
 | 
| -  AppendRecordToPRegFile(path, key, REG_SZ, data.size() * sizeof(char16),
 | 
| -                         reinterpret_cast<uint8*>(vector_as_array(&data)));
 | 
| -}
 | 
| -
 | 
| -void PRegTestHarness::AppendPolicyToPRegFile(const string16& path,
 | 
| -                                             const std::string& key,
 | 
| -                                             const base::Value* value) {
 | 
| -  switch (value->GetType()) {
 | 
| -    case base::Value::TYPE_BOOLEAN: {
 | 
| -      bool boolean_value = false;
 | 
| -      ASSERT_TRUE(value->GetAsBoolean(&boolean_value));
 | 
| -      AppendDWORDToPRegFile(path, key, boolean_value);
 | 
| -      break;
 | 
| -    }
 | 
| -    case base::Value::TYPE_INTEGER: {
 | 
| -      int int_value = 0;
 | 
| -      ASSERT_TRUE(value->GetAsInteger(&int_value));
 | 
| -      AppendDWORDToPRegFile(path, key, int_value);
 | 
| -      break;
 | 
| -    }
 | 
| -    case base::Value::TYPE_DOUBLE: {
 | 
| -      double double_value = 0;
 | 
| -      ASSERT_TRUE(value->GetAsDouble(&double_value));
 | 
| -      AppendStringToPRegFile(path, key, base::DoubleToString(double_value));
 | 
| -      break;
 | 
| -    }
 | 
| -    case base::Value::TYPE_STRING: {
 | 
| -      std::string string_value;
 | 
| -      ASSERT_TRUE(value->GetAsString(&string_value));
 | 
| -      AppendStringToPRegFile(path, key, string_value);
 | 
| -      break;
 | 
| -    }
 | 
| -    case base::Value::TYPE_DICTIONARY: {
 | 
| -      string16 subpath = path + kPathSep + UTF8ToUTF16(key);
 | 
| -      const base::DictionaryValue* dict = NULL;
 | 
| -      ASSERT_TRUE(value->GetAsDictionary(&dict));
 | 
| -      for (base::DictionaryValue::Iterator entry(*dict); !entry.IsAtEnd();
 | 
| -           entry.Advance()) {
 | 
| -        AppendPolicyToPRegFile(subpath, entry.key(), &entry.value());
 | 
| -      }
 | 
| -      break;
 | 
| -    }
 | 
| -    case base::Value::TYPE_LIST: {
 | 
| -      string16 subpath = path + kPathSep + UTF8ToUTF16(key);
 | 
| -      const base::ListValue* list = NULL;
 | 
| -      ASSERT_TRUE(value->GetAsList(&list));
 | 
| -      for (size_t i = 0; i < list->GetSize(); ++i) {
 | 
| -        const base::Value* entry = NULL;
 | 
| -        ASSERT_TRUE(list->Get(i, &entry));
 | 
| -        AppendPolicyToPRegFile(subpath, base::IntToString(i + 1), entry);
 | 
| -      }
 | 
| -      break;
 | 
| -    }
 | 
| -    case base::Value::TYPE_BINARY:
 | 
| -    case base::Value::TYPE_NULL: {
 | 
| -      ADD_FAILURE();
 | 
| -      break;
 | 
| -    }
 | 
| -  }
 | 
| -}
 | 
| -
 | 
| -}  // namespace
 | 
| -
 | 
| -// Instantiate abstract test case for basic policy reading tests.
 | 
| -INSTANTIATE_TEST_CASE_P(
 | 
| -    PolicyProviderWinTest,
 | 
| -    ConfigurationPolicyProviderTest,
 | 
| -    testing::Values(RegistryTestHarness::CreateHKCU,
 | 
| -                    RegistryTestHarness::CreateHKLM,
 | 
| -                    PRegTestHarness::Create));
 | 
| -
 | 
| -// Instantiate abstract test case for 3rd party policy reading tests.
 | 
| -INSTANTIATE_TEST_CASE_P(
 | 
| -    ThirdPartyPolicyProviderWinTest,
 | 
| -    Configuration3rdPartyPolicyProviderTest,
 | 
| -    testing::Values(RegistryTestHarness::CreateHKCU,
 | 
| -                    RegistryTestHarness::CreateHKLM,
 | 
| -                    PRegTestHarness::Create));
 | 
| -
 | 
| -// Test cases for windows policy provider specific functionality.
 | 
| -class PolicyLoaderWinTest : public PolicyTestBase,
 | 
| -                            public AppliedGPOListProvider {
 | 
| - protected:
 | 
| -  // The policy key this tests places data under. This must match the data
 | 
| -  // files in chrome/test/data/policy/gpo.
 | 
| -  static const char16 kTestPolicyKey[];
 | 
| -
 | 
| -  PolicyLoaderWinTest()
 | 
| -      : gpo_list_(NULL),
 | 
| -        gpo_list_status_(ERROR_ACCESS_DENIED) {}
 | 
| -  virtual ~PolicyLoaderWinTest() {}
 | 
| -
 | 
| -  virtual void SetUp() OVERRIDE {
 | 
| -    PolicyTestBase::SetUp();
 | 
| -
 | 
| -    ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &test_data_dir_));
 | 
| -    test_data_dir_ = test_data_dir_.AppendASCII("chrome")
 | 
| -                                   .AppendASCII("test")
 | 
| -                                   .AppendASCII("data")
 | 
| -                                   .AppendASCII("policy")
 | 
| -                                   .AppendASCII("gpo");
 | 
| -
 | 
| -    // Unknown components will be filtered out. Register their names with an
 | 
| -    // invalid schema to avoid that.
 | 
| -    ComponentMap components;
 | 
| -    components["aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"] = Schema();
 | 
| -    components["bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"] = Schema();
 | 
| -    components["int"] = Schema();
 | 
| -    components["merge"] = Schema();
 | 
| -    components["string"] = Schema();
 | 
| -    components["test"] = Schema();
 | 
| -    schema_registry_.RegisterComponents(POLICY_DOMAIN_EXTENSIONS, components);
 | 
| -  }
 | 
| -
 | 
| -  // AppliedGPOListProvider:
 | 
| -  virtual DWORD GetAppliedGPOList(DWORD flags,
 | 
| -                                  LPCTSTR machine_name,
 | 
| -                                  PSID sid_user,
 | 
| -                                  GUID* extension_guid,
 | 
| -                                  PGROUP_POLICY_OBJECT* gpo_list) OVERRIDE {
 | 
| -    *gpo_list = gpo_list_;
 | 
| -    return gpo_list_status_;
 | 
| -  }
 | 
| -  virtual BOOL FreeGPOList(PGROUP_POLICY_OBJECT gpo_list) OVERRIDE {
 | 
| -    return TRUE;
 | 
| -  }
 | 
| -
 | 
| -  void InitGPO(GROUP_POLICY_OBJECT* gpo,
 | 
| -               DWORD options,
 | 
| -               const base::FilePath& path,
 | 
| -               GROUP_POLICY_OBJECT* next,
 | 
| -               GROUP_POLICY_OBJECT* prev) {
 | 
| -    memset(gpo, 0, sizeof(GROUP_POLICY_OBJECT));
 | 
| -    gpo->dwOptions = options;
 | 
| -    gpo->lpFileSysPath = const_cast<wchar_t*>(path.value().c_str());
 | 
| -    gpo->pNext = next;
 | 
| -    gpo->pPrev = prev;
 | 
| -  }
 | 
| -
 | 
| -  bool Matches(const PolicyBundle& expected) {
 | 
| -    PolicyLoaderWin loader(loop_.message_loop_proxy(), kTestPolicyKey, this);
 | 
| -    scoped_ptr<PolicyBundle> loaded(
 | 
| -        loader.InitialLoad(schema_registry_.schema_map()));
 | 
| -    return loaded->Equals(expected);
 | 
| -  }
 | 
| -
 | 
| -  void InstallRegistrySentinel() {
 | 
| -    RegKey hklm_key(HKEY_CURRENT_USER, kTestPolicyKey, KEY_ALL_ACCESS);
 | 
| -    ASSERT_TRUE(hklm_key.Valid());
 | 
| -    hklm_key.WriteValue(
 | 
| -        UTF8ToUTF16(test_keys::kKeyString).c_str(),
 | 
| -        UTF8ToUTF16("registry").c_str());
 | 
| -  }
 | 
| -
 | 
| -  bool MatchesRegistrySentinel() {
 | 
| -    base::DictionaryValue expected_policy;
 | 
| -    expected_policy.SetString(test_keys::kKeyString, "registry");
 | 
| -    PolicyBundle expected;
 | 
| -    expected.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
 | 
| -        .LoadFrom(&expected_policy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER);
 | 
| -    return Matches(expected);
 | 
| -  }
 | 
| -
 | 
| -  bool MatchesTestBundle() {
 | 
| -    base::DictionaryValue expected_policy;
 | 
| -    expected_policy.SetBoolean(test_keys::kKeyBoolean, true);
 | 
| -    expected_policy.SetString(test_keys::kKeyString, "GPO");
 | 
| -    expected_policy.SetInteger(test_keys::kKeyInteger, 42);
 | 
| -    scoped_ptr<base::ListValue> list(new base::ListValue());
 | 
| -    list->AppendString("GPO 1");
 | 
| -    list->AppendString("GPO 2");
 | 
| -    expected_policy.Set(test_keys::kKeyStringList, list.release());
 | 
| -    PolicyBundle expected;
 | 
| -    expected.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
 | 
| -        .LoadFrom(&expected_policy, POLICY_LEVEL_MANDATORY,
 | 
| -                  POLICY_SCOPE_MACHINE);
 | 
| -    return Matches(expected);
 | 
| -  }
 | 
| -
 | 
| -  ScopedGroupPolicyRegistrySandbox registry_sandbox_;
 | 
| -  PGROUP_POLICY_OBJECT gpo_list_;
 | 
| -  DWORD gpo_list_status_;
 | 
| -  base::FilePath test_data_dir_;
 | 
| -};
 | 
| -
 | 
| -const char16 PolicyLoaderWinTest::kTestPolicyKey[] =
 | 
| -    L"SOFTWARE\\Policies\\Chromium";
 | 
| -
 | 
| -TEST_F(PolicyLoaderWinTest, HKLMOverHKCU) {
 | 
| -  RegKey hklm_key(HKEY_LOCAL_MACHINE, kTestPolicyKey, KEY_ALL_ACCESS);
 | 
| -  ASSERT_TRUE(hklm_key.Valid());
 | 
| -  hklm_key.WriteValue(UTF8ToUTF16(test_keys::kKeyString).c_str(),
 | 
| -                      UTF8ToUTF16("hklm").c_str());
 | 
| -  RegKey hkcu_key(HKEY_CURRENT_USER, kTestPolicyKey, KEY_ALL_ACCESS);
 | 
| -  ASSERT_TRUE(hkcu_key.Valid());
 | 
| -  hkcu_key.WriteValue(UTF8ToUTF16(test_keys::kKeyString).c_str(),
 | 
| -                      UTF8ToUTF16("hkcu").c_str());
 | 
| -
 | 
| -  PolicyBundle expected;
 | 
| -  expected.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string()))
 | 
| -      .Set(test_keys::kKeyString,
 | 
| -           POLICY_LEVEL_MANDATORY,
 | 
| -           POLICY_SCOPE_MACHINE,
 | 
| -           base::Value::CreateStringValue("hklm"), NULL);
 | 
| -  EXPECT_TRUE(Matches(expected));
 | 
| -}
 | 
| -
 | 
| -TEST_F(PolicyLoaderWinTest, Load3rdPartyWithoutSchema) {
 | 
| -  base::DictionaryValue dict;
 | 
| -  dict.SetString("str", "string value");
 | 
| -  dict.SetInteger("int", 123);
 | 
| -  dict.Set("subdict", dict.DeepCopy());
 | 
| -  dict.Set("subsubdict", dict.DeepCopy());
 | 
| -  dict.Set("subsubsubdict", dict.DeepCopy());
 | 
| -
 | 
| -  base::DictionaryValue policy_dict;
 | 
| -  policy_dict.Set("extensions.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.policy",
 | 
| -                  dict.DeepCopy());
 | 
| -  policy_dict.Set("extensions.bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.policy",
 | 
| -                  dict.DeepCopy());
 | 
| -  EXPECT_TRUE(InstallValue(policy_dict, HKEY_LOCAL_MACHINE,
 | 
| -                           kTestPolicyKey, kThirdParty));
 | 
| -
 | 
| -  PolicyBundle expected;
 | 
| -  expected.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
 | 
| -                               "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
 | 
| -      .LoadFrom(&dict, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE);
 | 
| -  expected.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
 | 
| -                               "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"))
 | 
| -      .LoadFrom(&dict, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE);
 | 
| -  EXPECT_TRUE(Matches(expected));
 | 
| -}
 | 
| -
 | 
| -TEST_F(PolicyLoaderWinTest, Merge3rdPartyPolicies) {
 | 
| -  // Policy for the same extension will be provided at the 4 level/scope
 | 
| -  // combinations, to verify that they overlap as expected.
 | 
| -
 | 
| -  const string16 kPathSuffix =
 | 
| -      kTestPolicyKey + ASCIIToUTF16("\\3rdparty\\extensions\\merge");
 | 
| -
 | 
| -  const char kUserMandatory[] = "user-mandatory";
 | 
| -  const char kUserRecommended[] = "user-recommended";
 | 
| -  const char kMachineMandatory[] = "machine-mandatory";
 | 
| -  const char kMachineRecommended[] = "machine-recommended";
 | 
| -
 | 
| -  base::DictionaryValue policy;
 | 
| -  policy.SetString("a", kMachineMandatory);
 | 
| -  EXPECT_TRUE(InstallValue(policy, HKEY_LOCAL_MACHINE,
 | 
| -                           kPathSuffix, kMandatory));
 | 
| -  policy.SetString("a", kUserMandatory);
 | 
| -  policy.SetString("b", kUserMandatory);
 | 
| -  EXPECT_TRUE(InstallValue(policy, HKEY_CURRENT_USER,
 | 
| -                           kPathSuffix, kMandatory));
 | 
| -  policy.SetString("a", kMachineRecommended);
 | 
| -  policy.SetString("b", kMachineRecommended);
 | 
| -  policy.SetString("c", kMachineRecommended);
 | 
| -  EXPECT_TRUE(InstallValue(policy, HKEY_LOCAL_MACHINE,
 | 
| -                           kPathSuffix, kRecommended));
 | 
| -  policy.SetString("a", kUserRecommended);
 | 
| -  policy.SetString("b", kUserRecommended);
 | 
| -  policy.SetString("c", kUserRecommended);
 | 
| -  policy.SetString("d", kUserRecommended);
 | 
| -  EXPECT_TRUE(InstallValue(policy, HKEY_CURRENT_USER,
 | 
| -                           kPathSuffix, kRecommended));
 | 
| -
 | 
| -  PolicyBundle expected;
 | 
| -  PolicyMap& expected_policy =
 | 
| -      expected.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "merge"));
 | 
| -  expected_policy.Set("a", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE,
 | 
| -                      base::Value::CreateStringValue(kMachineMandatory), NULL);
 | 
| -  expected_policy.Set("b", POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER,
 | 
| -                      base::Value::CreateStringValue(kUserMandatory), NULL);
 | 
| -  expected_policy.Set("c", POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_MACHINE,
 | 
| -                      base::Value::CreateStringValue(kMachineRecommended),
 | 
| -                      NULL);
 | 
| -  expected_policy.Set("d", POLICY_LEVEL_RECOMMENDED, POLICY_SCOPE_USER,
 | 
| -                      base::Value::CreateStringValue(kUserRecommended), NULL);
 | 
| -  EXPECT_TRUE(Matches(expected));
 | 
| -}
 | 
| -
 | 
| -TEST_F(PolicyLoaderWinTest, LoadStringEncodedValues) {
 | 
| -  // Create a dictionary with all the types that can be stored encoded in a
 | 
| -  // string, to pass to InstallSchema(). Also build an equivalent dictionary
 | 
| -  // with the encoded values, to pass to InstallValue().
 | 
| -  base::DictionaryValue policy;
 | 
| -  policy.Set("null", base::Value::CreateNullValue());
 | 
| -  policy.SetBoolean("bool", true);
 | 
| -  policy.SetInteger("int", -123);
 | 
| -  policy.SetDouble("double", 456.78e9);
 | 
| -  base::ListValue list;
 | 
| -  list.Append(policy.DeepCopy());
 | 
| -  list.Append(policy.DeepCopy());
 | 
| -  policy.Set("list", list.DeepCopy());
 | 
| -  // Encode |policy| before adding the "dict" entry.
 | 
| -  std::string encoded_dict;
 | 
| -  base::JSONWriter::Write(&policy, &encoded_dict);
 | 
| -  ASSERT_FALSE(encoded_dict.empty());
 | 
| -  policy.Set("dict", policy.DeepCopy());
 | 
| -
 | 
| -  std::string encoded_list;
 | 
| -  base::JSONWriter::Write(&list, &encoded_list);
 | 
| -  ASSERT_FALSE(encoded_list.empty());
 | 
| -  base::DictionaryValue encoded_policy;
 | 
| -  encoded_policy.SetString("null", "");
 | 
| -  encoded_policy.SetString("bool", "1");
 | 
| -  encoded_policy.SetString("int", "-123");
 | 
| -  encoded_policy.SetString("double", "456.78e9");
 | 
| -  encoded_policy.SetString("list", encoded_list);
 | 
| -  encoded_policy.SetString("dict", encoded_dict);
 | 
| -
 | 
| -  const string16 kPathSuffix =
 | 
| -      kTestPolicyKey + ASCIIToUTF16("\\3rdparty\\extensions\\string");
 | 
| -  EXPECT_TRUE(InstallSchema(policy, HKEY_CURRENT_USER, kPathSuffix, kSchema));
 | 
| -  EXPECT_TRUE(
 | 
| -      InstallValue(encoded_policy, HKEY_CURRENT_USER, kPathSuffix, kMandatory));
 | 
| -
 | 
| -  PolicyBundle expected;
 | 
| -  expected.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "string"))
 | 
| -      .LoadFrom(&policy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER);
 | 
| -  EXPECT_TRUE(Matches(expected));
 | 
| -}
 | 
| -
 | 
| -TEST_F(PolicyLoaderWinTest, LoadIntegerEncodedValues) {
 | 
| -  base::DictionaryValue policy;
 | 
| -  policy.SetBoolean("bool", true);
 | 
| -  policy.SetInteger("int", 123);
 | 
| -  policy.SetDouble("double", 456.0);
 | 
| -
 | 
| -  base::DictionaryValue encoded_policy;
 | 
| -  encoded_policy.SetInteger("bool", 1);
 | 
| -  encoded_policy.SetInteger("int", 123);
 | 
| -  encoded_policy.SetInteger("double", 456);
 | 
| -
 | 
| -  const string16 kPathSuffix =
 | 
| -      kTestPolicyKey + ASCIIToUTF16("\\3rdparty\\extensions\\int");
 | 
| -  EXPECT_TRUE(InstallSchema(policy, HKEY_CURRENT_USER, kPathSuffix, kSchema));
 | 
| -  EXPECT_TRUE(
 | 
| -      InstallValue(encoded_policy, HKEY_CURRENT_USER, kPathSuffix, kMandatory));
 | 
| -
 | 
| -  PolicyBundle expected;
 | 
| -  expected.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "int"))
 | 
| -      .LoadFrom(&policy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER);
 | 
| -  EXPECT_TRUE(Matches(expected));
 | 
| -}
 | 
| -
 | 
| -TEST_F(PolicyLoaderWinTest, DefaultPropertySchemaType) {
 | 
| -  // Build a schema for an "object" with a default schema for its properties.
 | 
| -  base::DictionaryValue default_schema;
 | 
| -  default_schema.SetString(schema::kType, "number");
 | 
| -  base::DictionaryValue integer_schema;
 | 
| -  integer_schema.SetString(schema::kType, "integer");
 | 
| -  base::DictionaryValue properties;
 | 
| -  properties.Set("special-int1", integer_schema.DeepCopy());
 | 
| -  properties.Set("special-int2", integer_schema.DeepCopy());
 | 
| -  base::DictionaryValue schema;
 | 
| -  schema.SetString(schema::kType, "object");
 | 
| -  schema.Set(schema::kProperties, properties.DeepCopy());
 | 
| -  schema.Set(schema::kAdditionalProperties, default_schema.DeepCopy());
 | 
| -
 | 
| -  const string16 kPathSuffix =
 | 
| -      kTestPolicyKey + ASCIIToUTF16("\\3rdparty\\extensions\\test");
 | 
| -  EXPECT_TRUE(WriteSchema(schema, HKEY_CURRENT_USER, kPathSuffix, kSchema));
 | 
| -
 | 
| -  // Write some test values.
 | 
| -  base::DictionaryValue policy;
 | 
| -  // These special values have a specific schema for them.
 | 
| -  policy.SetInteger("special-int1", 123);
 | 
| -  policy.SetString("special-int2", "-456");
 | 
| -  // Other values default to be loaded as doubles.
 | 
| -  policy.SetInteger("double1", 789.0);
 | 
| -  policy.SetString("double2", "123.456e7");
 | 
| -  policy.SetString("invalid", "omg");
 | 
| -  EXPECT_TRUE(InstallValue(policy, HKEY_CURRENT_USER, kPathSuffix, kMandatory));
 | 
| -
 | 
| -  base::DictionaryValue expected_policy;
 | 
| -  expected_policy.SetInteger("special-int1", 123);
 | 
| -  expected_policy.SetInteger("special-int2", -456);
 | 
| -  expected_policy.SetDouble("double1", 789.0);
 | 
| -  expected_policy.SetDouble("double2", 123.456e7);
 | 
| -  expected_policy.Set("invalid", base::Value::CreateNullValue());
 | 
| -  PolicyBundle expected;
 | 
| -  expected.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, "test"))
 | 
| -      .LoadFrom(&expected_policy, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER);
 | 
| -  EXPECT_TRUE(Matches(expected));
 | 
| -}
 | 
| -
 | 
| -TEST_F(PolicyLoaderWinTest, AppliedPolicyNotPresent) {
 | 
| -  InstallRegistrySentinel();
 | 
| -  gpo_list_ = NULL;
 | 
| -  gpo_list_status_ = ERROR_SUCCESS;
 | 
| -
 | 
| -  PolicyBundle empty;
 | 
| -  EXPECT_TRUE(Matches(empty));
 | 
| -}
 | 
| -
 | 
| -TEST_F(PolicyLoaderWinTest, AppliedPolicyEmpty) {
 | 
| -  InstallRegistrySentinel();
 | 
| -  base::FilePath gpo_dir(test_data_dir_.AppendASCII("empty"));
 | 
| -  GROUP_POLICY_OBJECT gpo;
 | 
| -  InitGPO(&gpo, 0, gpo_dir, NULL, NULL);
 | 
| -  gpo_list_ = &gpo;
 | 
| -  gpo_list_status_ = ERROR_SUCCESS;
 | 
| -
 | 
| -  PolicyBundle empty;
 | 
| -  EXPECT_TRUE(Matches(empty));
 | 
| -}
 | 
| -
 | 
| -TEST_F(PolicyLoaderWinTest, AppliedPolicyNonExistingFile) {
 | 
| -  InstallRegistrySentinel();
 | 
| -  GROUP_POLICY_OBJECT gpo;
 | 
| -  InitGPO(&gpo, 0, test_data_dir_, NULL, NULL);
 | 
| -  gpo_list_ = &gpo;
 | 
| -  gpo_list_status_ = ERROR_SUCCESS;
 | 
| -
 | 
| -  EXPECT_TRUE(MatchesRegistrySentinel());
 | 
| -}
 | 
| -
 | 
| -TEST_F(PolicyLoaderWinTest, AppliedPolicyBadPath) {
 | 
| -  InstallRegistrySentinel();
 | 
| -  base::FilePath gpo_dir(test_data_dir_.AppendASCII("bad"));
 | 
| -  GROUP_POLICY_OBJECT gpo;
 | 
| -  InitGPO(&gpo, 0, gpo_dir, NULL, NULL);
 | 
| -  gpo_list_ = &gpo;
 | 
| -  gpo_list_status_ = ERROR_SUCCESS;
 | 
| -
 | 
| -  EXPECT_TRUE(MatchesRegistrySentinel());
 | 
| -}
 | 
| -
 | 
| -TEST_F(PolicyLoaderWinTest, AppliedPolicyPresent) {
 | 
| -  InstallRegistrySentinel();
 | 
| -  base::FilePath gpo_dir(test_data_dir_.AppendASCII("test1"));
 | 
| -  GROUP_POLICY_OBJECT gpo;
 | 
| -  InitGPO(&gpo, 0, gpo_dir, NULL, NULL);
 | 
| -  gpo_list_ = &gpo;
 | 
| -  gpo_list_status_ = ERROR_SUCCESS;
 | 
| -
 | 
| -  EXPECT_TRUE(MatchesTestBundle());
 | 
| -}
 | 
| -
 | 
| -TEST_F(PolicyLoaderWinTest, AppliedPolicyMerged) {
 | 
| -  InstallRegistrySentinel();
 | 
| -  base::FilePath gpo1_dir(test_data_dir_.AppendASCII("test2"));
 | 
| -  base::FilePath gpo2_dir(test_data_dir_.AppendASCII("test1"));
 | 
| -  GROUP_POLICY_OBJECT gpo1;
 | 
| -  GROUP_POLICY_OBJECT gpo2;
 | 
| -  InitGPO(&gpo1, 0, gpo1_dir, &gpo2, NULL);
 | 
| -  InitGPO(&gpo2, 0, gpo2_dir, NULL, &gpo1);
 | 
| -  gpo_list_ = &gpo1;
 | 
| -  gpo_list_status_ = ERROR_SUCCESS;
 | 
| -
 | 
| -  EXPECT_TRUE(MatchesTestBundle());
 | 
| -}
 | 
| -
 | 
| -TEST_F(PolicyLoaderWinTest, AppliedPolicyDisabled) {
 | 
| -  InstallRegistrySentinel();
 | 
| -  base::FilePath gpo1_dir(test_data_dir_.AppendASCII("test1"));
 | 
| -  base::FilePath gpo2_dir(test_data_dir_.AppendASCII("test2"));
 | 
| -  GROUP_POLICY_OBJECT gpo1;
 | 
| -  GROUP_POLICY_OBJECT gpo2;
 | 
| -  InitGPO(&gpo1, 0, gpo1_dir, &gpo2, NULL);
 | 
| -  InitGPO(&gpo2, GPO_FLAG_DISABLE, gpo2_dir, NULL, &gpo1);
 | 
| -  gpo_list_ = &gpo1;
 | 
| -  gpo_list_status_ = ERROR_SUCCESS;
 | 
| -
 | 
| -  EXPECT_TRUE(MatchesTestBundle());
 | 
| -}
 | 
| -
 | 
| -TEST_F(PolicyLoaderWinTest, AppliedPolicyForcedPolicy) {
 | 
| -  InstallRegistrySentinel();
 | 
| -  base::FilePath gpo1_dir(test_data_dir_.AppendASCII("test1"));
 | 
| -  base::FilePath gpo2_dir(test_data_dir_.AppendASCII("test2"));
 | 
| -  GROUP_POLICY_OBJECT gpo1;
 | 
| -  GROUP_POLICY_OBJECT gpo2;
 | 
| -  InitGPO(&gpo1, GPO_FLAG_FORCE, gpo1_dir, &gpo2, NULL);
 | 
| -  InitGPO(&gpo2, 0, gpo2_dir, NULL, &gpo1);
 | 
| -  gpo_list_ = &gpo1;
 | 
| -  gpo_list_status_ = ERROR_SUCCESS;
 | 
| -
 | 
| -  EXPECT_TRUE(MatchesTestBundle());
 | 
| -}
 | 
| -
 | 
| -TEST_F(PolicyLoaderWinTest, AppliedPolicyUNCPath) {
 | 
| -  InstallRegistrySentinel();
 | 
| -  base::FilePath gpo_dir(test_data_dir_.AppendASCII("test1"));
 | 
| -  base::FilePath unc_path(L"\\\\some_share\\GPO");
 | 
| -  GROUP_POLICY_OBJECT gpo1;
 | 
| -  GROUP_POLICY_OBJECT gpo2;
 | 
| -  InitGPO(&gpo1, 0, gpo_dir, &gpo2, NULL);
 | 
| -  InitGPO(&gpo2, 0, unc_path, NULL, &gpo1);
 | 
| -  gpo_list_ = &gpo1;
 | 
| -  gpo_list_status_ = ERROR_SUCCESS;
 | 
| -
 | 
| -  EXPECT_TRUE(MatchesRegistrySentinel());
 | 
| -}
 | 
| -
 | 
| -TEST_F(PolicyLoaderWinTest, LoadExtensionPolicyAlternativeSpelling) {
 | 
| -  base::FilePath gpo_dir(
 | 
| -      test_data_dir_.AppendASCII("extension_alternative_spelling"));
 | 
| -  GROUP_POLICY_OBJECT gpo;
 | 
| -  InitGPO(&gpo, 0, gpo_dir, NULL, NULL);
 | 
| -  gpo_list_ = &gpo;
 | 
| -  gpo_list_status_ = ERROR_SUCCESS;
 | 
| -
 | 
| -  PolicyBundle expected;
 | 
| -  base::DictionaryValue expected_a;
 | 
| -  expected_a.SetInteger("policy 1", 3);
 | 
| -  expected_a.SetInteger("policy 2", 3);
 | 
| -  expected.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
 | 
| -                               "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
 | 
| -      .LoadFrom(&expected_a, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE);
 | 
| -  base::DictionaryValue expected_b;
 | 
| -  expected_b.SetInteger("policy 1", 2);
 | 
| -  expected.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS,
 | 
| -                               "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"))
 | 
| -      .LoadFrom(&expected_b, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_MACHINE);
 | 
| -  EXPECT_TRUE(Matches(expected));
 | 
| -}
 | 
| -
 | 
| -}  // namespace policy
 | 
| 
 |