Home | History | Annotate | Download | only in policy
      1 // Copyright (c) 2011 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 <gtest/gtest.h>
      6 #include <windows.h>
      7 
      8 #include "base/memory/scoped_ptr.h"
      9 #include "base/message_loop.h"
     10 #include "base/stl_util-inl.h"
     11 #include "base/string_number_conversions.h"
     12 #include "base/string_piece.h"
     13 #include "base/utf_string_conversions.h"
     14 #include "base/win/registry.h"
     15 #include "chrome/browser/policy/asynchronous_policy_loader.h"
     16 #include "chrome/browser/policy/configuration_policy_pref_store.h"
     17 #include "chrome/browser/policy/configuration_policy_provider_win.h"
     18 #include "chrome/browser/policy/mock_configuration_policy_store.h"
     19 #include "chrome/common/pref_names.h"
     20 #include "content/browser/browser_thread.h"
     21 #include "policy/policy_constants.h"
     22 #include "testing/gtest/include/gtest/gtest.h"
     23 
     24 using base::win::RegKey;
     25 
     26 namespace policy {
     27 
     28 const wchar_t kUnitTestRegistrySubKey[] = L"SOFTWARE\\Chromium Unit Tests";
     29 const wchar_t kUnitTestMachineOverrideSubKey[] =
     30     L"SOFTWARE\\Chromium Unit Tests\\HKLM Override";
     31 const wchar_t kUnitTestUserOverrideSubKey[] =
     32     L"SOFTWARE\\Chromium Unit Tests\\HKCU Override";
     33 
     34 namespace {
     35 
     36 // Holds policy type, corresponding policy name string and a valid value for use
     37 // in parametrized value tests.
     38 class PolicyTestParams {
     39  public:
     40   // Assumes ownership of |hklm_value| and |hkcu_value|.
     41   PolicyTestParams(ConfigurationPolicyType type,
     42                    const char* policy_name,
     43                    Value* hklm_value,
     44                    Value* hkcu_value)
     45       : type_(type),
     46         policy_name_(policy_name),
     47         hklm_value_(hklm_value),
     48         hkcu_value_(hkcu_value) {}
     49 
     50   // testing::TestWithParam does copy the parameters, so provide copy
     51   // constructor and assignment operator.
     52   PolicyTestParams(const PolicyTestParams& other)
     53       : type_(other.type_),
     54         policy_name_(other.policy_name_),
     55         hklm_value_(other.hklm_value_->DeepCopy()),
     56         hkcu_value_(other.hkcu_value_->DeepCopy()) {}
     57 
     58   const PolicyTestParams& operator=(PolicyTestParams other) {
     59     swap(other);
     60     return *this;
     61   }
     62 
     63   void swap(PolicyTestParams& other) {
     64     std::swap(type_, other.type_);
     65     std::swap(policy_name_, other.policy_name_);
     66     hklm_value_.swap(other.hklm_value_);
     67     hkcu_value_.swap(other.hkcu_value_);
     68   }
     69 
     70   ConfigurationPolicyType type() const { return type_; }
     71   const char* policy_name() const { return policy_name_; }
     72   const Value* hklm_value() const { return hklm_value_.get(); }
     73   const Value* hkcu_value() const { return hkcu_value_.get(); }
     74 
     75   // Factory methods for different value types.
     76   static PolicyTestParams ForStringPolicy(
     77       ConfigurationPolicyType type,
     78       const char* policy_name) {
     79     return PolicyTestParams(type,
     80                             policy_name,
     81                             Value::CreateStringValue("string_a"),
     82                             Value::CreateStringValue("string_b"));
     83   }
     84   static PolicyTestParams ForBooleanPolicy(
     85       ConfigurationPolicyType type,
     86       const char* policy_name) {
     87     return PolicyTestParams(type,
     88                             policy_name,
     89                             Value::CreateBooleanValue(true),
     90                             Value::CreateBooleanValue(false));
     91   }
     92   static PolicyTestParams ForIntegerPolicy(
     93       ConfigurationPolicyType type,
     94       const char* policy_name) {
     95     return PolicyTestParams(type,
     96                             policy_name,
     97                             Value::CreateIntegerValue(42),
     98                             Value::CreateIntegerValue(17));
     99   }
    100   static PolicyTestParams ForListPolicy(
    101       ConfigurationPolicyType type,
    102       const char* policy_name) {
    103     ListValue* hklm_value = new ListValue;
    104     hklm_value->Set(0U, Value::CreateStringValue("It's a plane!"));
    105     ListValue* hkcu_value = new ListValue;
    106     hkcu_value->Set(0U, Value::CreateStringValue("It's a bird!"));
    107     hkcu_value->Set(0U, Value::CreateStringValue("It's a flying carpet!"));
    108     return PolicyTestParams(type, policy_name, hklm_value, hkcu_value);
    109   }
    110 
    111  private:
    112   ConfigurationPolicyType type_;
    113   const char* policy_name_;
    114   scoped_ptr<Value> hklm_value_;
    115   scoped_ptr<Value> hkcu_value_;
    116 };
    117 
    118 }  // namespace
    119 
    120 // This test class provides sandboxing and mocking for the parts of the
    121 // Windows Registry implementing Group Policy. The |SetUp| method prepares
    122 // two temporary sandbox keys in |kUnitTestRegistrySubKey|, one for HKLM and one
    123 // for HKCU. A test's calls to the registry are redirected by Windows to these
    124 // sandboxes, allowing the tests to manipulate and access policy as if it
    125 // were active, but without actually changing the parts of the Registry that
    126 // are managed by Group Policy.
    127 class ConfigurationPolicyProviderWinTest
    128     : public testing::TestWithParam<PolicyTestParams> {
    129  public:
    130   ConfigurationPolicyProviderWinTest();
    131 
    132   // testing::Test method overrides:
    133   virtual void SetUp();
    134   virtual void TearDown();
    135 
    136   void ActivateOverrides();
    137   void DeactivateOverrides();
    138 
    139   // Deletes the registry key created during the tests.
    140   void DeleteRegistrySandbox();
    141 
    142   // Write a string value to the registry.
    143   void WriteString(HKEY hive, const char* name, const wchar_t* value);
    144   // Write a DWORD value to the registry.
    145   void WriteDWORD(HKEY hive, const char* name, DWORD value);
    146 
    147   // Write the given value to the registry.
    148   void WriteValue(HKEY hive, const char* name, const Value* value);
    149   // Write a value that is not compatible with the given |value|.
    150   void WriteInvalidValue(HKEY hive, const char* name, const Value* value);
    151 
    152  protected:
    153   scoped_ptr<MockConfigurationPolicyStore> store_;
    154   scoped_ptr<ConfigurationPolicyProviderWin> provider_;
    155 
    156   // A message loop must be declared and instantiated for these tests,
    157   // because Windows policy provider create WaitableEvents and
    158   // ObjectWatchers that require the tests to have a MessageLoop associated
    159   // with the thread executing the tests.
    160   MessageLoop loop_;
    161 
    162  private:
    163   BrowserThread ui_thread_;
    164   BrowserThread file_thread_;
    165 
    166   // Keys are created for the lifetime of a test to contain
    167   // the sandboxed HKCU and HKLM hives, respectively.
    168   RegKey temp_hkcu_hive_key_;
    169   RegKey temp_hklm_hive_key_;
    170 };
    171 
    172 ConfigurationPolicyProviderWinTest::ConfigurationPolicyProviderWinTest()
    173     : ui_thread_(BrowserThread::UI, &loop_),
    174       file_thread_(BrowserThread::FILE, &loop_),
    175       temp_hklm_hive_key_(HKEY_CURRENT_USER, kUnitTestMachineOverrideSubKey,
    176                           KEY_READ),
    177       temp_hkcu_hive_key_(HKEY_CURRENT_USER, kUnitTestUserOverrideSubKey,
    178                           KEY_READ) {
    179 }
    180 
    181 void ConfigurationPolicyProviderWinTest::SetUp() {
    182   // Cleanup any remnants of previous tests.
    183   DeleteRegistrySandbox();
    184 
    185   // Create the subkeys to hold the overridden HKLM and HKCU
    186   // policy settings.
    187   temp_hklm_hive_key_.Create(HKEY_CURRENT_USER,
    188                              kUnitTestMachineOverrideSubKey,
    189                              KEY_ALL_ACCESS);
    190   temp_hkcu_hive_key_.Create(HKEY_CURRENT_USER,
    191                              kUnitTestUserOverrideSubKey,
    192                              KEY_ALL_ACCESS);
    193 
    194   ActivateOverrides();
    195 
    196   store_.reset(new MockConfigurationPolicyStore);
    197   provider_.reset(new ConfigurationPolicyProviderWin(
    198       ConfigurationPolicyPrefStore::GetChromePolicyDefinitionList()));
    199 }
    200 
    201 void ConfigurationPolicyProviderWinTest::TearDown() {
    202   DeactivateOverrides();
    203   DeleteRegistrySandbox();
    204   loop_.RunAllPending();
    205 }
    206 
    207 void ConfigurationPolicyProviderWinTest::ActivateOverrides() {
    208   HRESULT result = RegOverridePredefKey(HKEY_LOCAL_MACHINE,
    209                                         temp_hklm_hive_key_.Handle());
    210   EXPECT_EQ(ERROR_SUCCESS, result);
    211   result = RegOverridePredefKey(HKEY_CURRENT_USER,
    212                                 temp_hkcu_hive_key_.Handle());
    213   EXPECT_EQ(ERROR_SUCCESS, result);
    214 }
    215 
    216 void ConfigurationPolicyProviderWinTest::DeactivateOverrides() {
    217   uint32 result = RegOverridePredefKey(HKEY_LOCAL_MACHINE, 0);
    218   EXPECT_EQ(ERROR_SUCCESS, result);
    219   result = RegOverridePredefKey(HKEY_CURRENT_USER, 0);
    220   EXPECT_EQ(ERROR_SUCCESS, result);
    221 }
    222 
    223 void ConfigurationPolicyProviderWinTest::DeleteRegistrySandbox() {
    224   temp_hklm_hive_key_.Close();
    225   temp_hkcu_hive_key_.Close();
    226   RegKey key(HKEY_CURRENT_USER, kUnitTestRegistrySubKey, KEY_ALL_ACCESS);
    227   key.DeleteKey(L"");
    228 }
    229 
    230 void ConfigurationPolicyProviderWinTest::WriteString(HKEY hive,
    231                                                      const char* name,
    232                                                      const wchar_t* value) {
    233   RegKey key(hive, policy::kRegistrySubKey, KEY_ALL_ACCESS);
    234   key.WriteValue(UTF8ToUTF16(name).c_str(), value);
    235 }
    236 
    237 void ConfigurationPolicyProviderWinTest::WriteDWORD(HKEY hive,
    238                                                     const char* name,
    239                                                     DWORD value) {
    240   RegKey key(hive, policy::kRegistrySubKey, KEY_ALL_ACCESS);
    241   key.WriteValue(UTF8ToUTF16(name).c_str(), value);
    242 }
    243 
    244 void ConfigurationPolicyProviderWinTest::WriteValue(HKEY hive,
    245                                                     const char* name,
    246                                                     const Value* value) {
    247   switch (value->GetType()) {
    248     case Value::TYPE_BOOLEAN: {
    249       bool v;
    250       ASSERT_TRUE(value->GetAsBoolean(&v));
    251       WriteDWORD(hive, name, v);
    252       break;
    253     }
    254     case Value::TYPE_INTEGER: {
    255       int v;
    256       ASSERT_TRUE(value->GetAsInteger(&v));
    257       WriteDWORD(hive, name, v);
    258       break;
    259     }
    260     case Value::TYPE_STRING: {
    261       std::string v;
    262       ASSERT_TRUE(value->GetAsString(&v));
    263       WriteString(hive, name, UTF8ToUTF16(v).c_str());
    264       break;
    265     }
    266     case Value::TYPE_LIST: {
    267       const ListValue* list = static_cast<const ListValue*>(value);
    268       RegKey key(hive,
    269                  (string16(policy::kRegistrySubKey) + ASCIIToUTF16("\\") +
    270                   UTF8ToUTF16(name)).c_str(),
    271                  KEY_ALL_ACCESS);
    272       int index = 1;
    273       for (ListValue::const_iterator element(list->begin());
    274            element != list->end(); ++element) {
    275         ASSERT_TRUE((*element)->IsType(Value::TYPE_STRING));
    276         std::string element_value;
    277         ASSERT_TRUE((*element)->GetAsString(&element_value));
    278         key.WriteValue(base::IntToString16(index++).c_str(),
    279                        UTF8ToUTF16(element_value).c_str());
    280       }
    281       break;
    282     }
    283     default:
    284       FAIL() << "Unsupported value type " << value->GetType();
    285       break;
    286   }
    287 }
    288 
    289 void ConfigurationPolicyProviderWinTest::WriteInvalidValue(HKEY hive,
    290                                                            const char* name,
    291                                                            const Value* value) {
    292   if (value->IsType(Value::TYPE_STRING))
    293     WriteDWORD(hive, name, -1);
    294   else
    295     WriteString(hive, name, L"bad value");
    296 }
    297 
    298 TEST_P(ConfigurationPolicyProviderWinTest, Default) {
    299   provider_->Provide(store_.get());
    300   EXPECT_TRUE(store_->policy_map().empty());
    301 }
    302 
    303 TEST_P(ConfigurationPolicyProviderWinTest, InvalidValue) {
    304   WriteInvalidValue(HKEY_LOCAL_MACHINE,
    305                     GetParam().policy_name(),
    306                     GetParam().hklm_value());
    307   WriteInvalidValue(HKEY_CURRENT_USER,
    308                     GetParam().policy_name(),
    309                     GetParam().hkcu_value());
    310   provider_->loader()->Reload();
    311   loop_.RunAllPending();
    312   provider_->Provide(store_.get());
    313   EXPECT_TRUE(store_->policy_map().empty());
    314 }
    315 
    316 TEST_P(ConfigurationPolicyProviderWinTest, HKLM) {
    317   WriteValue(HKEY_LOCAL_MACHINE,
    318              GetParam().policy_name(),
    319              GetParam().hklm_value());
    320   provider_->loader()->Reload();
    321   loop_.RunAllPending();
    322   provider_->Provide(store_.get());
    323   const Value* value = store_->Get(GetParam().type());
    324   ASSERT_TRUE(value);
    325   EXPECT_TRUE(value->Equals(GetParam().hklm_value()));
    326 }
    327 
    328 TEST_P(ConfigurationPolicyProviderWinTest, HKCU) {
    329   WriteValue(HKEY_CURRENT_USER,
    330              GetParam().policy_name(),
    331              GetParam().hkcu_value());
    332   provider_->loader()->Reload();
    333   loop_.RunAllPending();
    334   provider_->Provide(store_.get());
    335   const Value* value = store_->Get(GetParam().type());
    336   ASSERT_TRUE(value);
    337   EXPECT_TRUE(value->Equals(GetParam().hkcu_value()));
    338 }
    339 
    340 TEST_P(ConfigurationPolicyProviderWinTest, HKLMOverHKCU) {
    341   WriteValue(HKEY_LOCAL_MACHINE,
    342              GetParam().policy_name(),
    343              GetParam().hklm_value());
    344   WriteValue(HKEY_CURRENT_USER,
    345              GetParam().policy_name(),
    346              GetParam().hkcu_value());
    347   provider_->loader()->Reload();
    348   loop_.RunAllPending();
    349   provider_->Provide(store_.get());
    350   const Value* value = store_->Get(GetParam().type());
    351   ASSERT_TRUE(value);
    352   EXPECT_TRUE(value->Equals(GetParam().hklm_value()));
    353 }
    354 
    355 // Instantiate the test case for all supported policies.
    356 INSTANTIATE_TEST_CASE_P(
    357     ConfigurationPolicyProviderWinTestInstance,
    358     ConfigurationPolicyProviderWinTest,
    359     testing::Values(
    360         PolicyTestParams::ForStringPolicy(
    361             kPolicyHomepageLocation,
    362             key::kHomepageLocation),
    363         PolicyTestParams::ForBooleanPolicy(
    364             kPolicyHomepageIsNewTabPage,
    365             key::kHomepageIsNewTabPage),
    366         PolicyTestParams::ForIntegerPolicy(
    367             kPolicyRestoreOnStartup,
    368             key::kRestoreOnStartup),
    369         PolicyTestParams::ForListPolicy(
    370             kPolicyRestoreOnStartupURLs,
    371             key::kRestoreOnStartupURLs),
    372         PolicyTestParams::ForBooleanPolicy(
    373             kPolicyDefaultSearchProviderEnabled,
    374             key::kDefaultSearchProviderEnabled),
    375         PolicyTestParams::ForStringPolicy(
    376             kPolicyDefaultSearchProviderName,
    377             key::kDefaultSearchProviderName),
    378         PolicyTestParams::ForStringPolicy(
    379             kPolicyDefaultSearchProviderKeyword,
    380             key::kDefaultSearchProviderKeyword),
    381         PolicyTestParams::ForStringPolicy(
    382             kPolicyDefaultSearchProviderSearchURL,
    383             key::kDefaultSearchProviderSearchURL),
    384         PolicyTestParams::ForStringPolicy(
    385             kPolicyDefaultSearchProviderSuggestURL,
    386             key::kDefaultSearchProviderSuggestURL),
    387         PolicyTestParams::ForStringPolicy(
    388             kPolicyDefaultSearchProviderInstantURL,
    389             key::kDefaultSearchProviderInstantURL),
    390         PolicyTestParams::ForStringPolicy(
    391             kPolicyDefaultSearchProviderIconURL,
    392             key::kDefaultSearchProviderIconURL),
    393         PolicyTestParams::ForStringPolicy(
    394             kPolicyDefaultSearchProviderEncodings,
    395             key::kDefaultSearchProviderEncodings),
    396         PolicyTestParams::ForStringPolicy(
    397             kPolicyProxyMode,
    398             key::kProxyMode),
    399         PolicyTestParams::ForIntegerPolicy(
    400             kPolicyProxyServerMode,
    401             key::kProxyServerMode),
    402         PolicyTestParams::ForStringPolicy(
    403             kPolicyProxyServer,
    404             key::kProxyServer),
    405         PolicyTestParams::ForStringPolicy(
    406             kPolicyProxyPacUrl,
    407             key::kProxyPacUrl),
    408         PolicyTestParams::ForStringPolicy(
    409             kPolicyProxyBypassList,
    410             key::kProxyBypassList),
    411         PolicyTestParams::ForBooleanPolicy(
    412             kPolicyAlternateErrorPagesEnabled,
    413             key::kAlternateErrorPagesEnabled),
    414         PolicyTestParams::ForBooleanPolicy(
    415             kPolicySearchSuggestEnabled,
    416             key::kSearchSuggestEnabled),
    417         PolicyTestParams::ForBooleanPolicy(
    418             kPolicyDnsPrefetchingEnabled,
    419             key::kDnsPrefetchingEnabled),
    420         PolicyTestParams::ForBooleanPolicy(
    421             kPolicySafeBrowsingEnabled,
    422             key::kSafeBrowsingEnabled),
    423         PolicyTestParams::ForBooleanPolicy(
    424             kPolicyMetricsReportingEnabled,
    425             key::kMetricsReportingEnabled),
    426         PolicyTestParams::ForBooleanPolicy(
    427             kPolicyPasswordManagerEnabled,
    428             key::kPasswordManagerEnabled),
    429         PolicyTestParams::ForListPolicy(
    430             kPolicyDisabledPlugins,
    431             key::kDisabledPlugins),
    432         PolicyTestParams::ForListPolicy(
    433             kPolicyDisabledPluginsExceptions,
    434             key::kDisabledPluginsExceptions),
    435         PolicyTestParams::ForListPolicy(
    436             kPolicyEnabledPlugins,
    437             key::kEnabledPlugins),
    438         PolicyTestParams::ForBooleanPolicy(
    439             kPolicyAutoFillEnabled,
    440             key::kAutoFillEnabled),
    441         PolicyTestParams::ForBooleanPolicy(
    442             kPolicySyncDisabled,
    443             key::kSyncDisabled),
    444         PolicyTestParams::ForStringPolicy(
    445             kPolicyApplicationLocaleValue,
    446             key::kApplicationLocaleValue),
    447         PolicyTestParams::ForListPolicy(
    448             kPolicyExtensionInstallWhitelist,
    449             key::kExtensionInstallWhitelist),
    450         PolicyTestParams::ForListPolicy(
    451             kPolicyExtensionInstallBlacklist,
    452             key::kExtensionInstallBlacklist),
    453         PolicyTestParams::ForBooleanPolicy(
    454             kPolicyShowHomeButton,
    455             key::kShowHomeButton),
    456         PolicyTestParams::ForBooleanPolicy(
    457             kPolicyPrintingEnabled,
    458             key::kPrintingEnabled),
    459         PolicyTestParams::ForIntegerPolicy(
    460             kPolicyPolicyRefreshRate,
    461             key::kPolicyRefreshRate),
    462         PolicyTestParams::ForBooleanPolicy(
    463             kPolicyInstantEnabled,
    464             key::kInstantEnabled),
    465         PolicyTestParams::ForBooleanPolicy(
    466             kPolicyIncognitoEnabled,
    467             key::kIncognitoEnabled),
    468         PolicyTestParams::ForBooleanPolicy(
    469             kPolicyDisablePluginFinder,
    470             key::kDisablePluginFinder),
    471         PolicyTestParams::ForBooleanPolicy(
    472             kPolicyClearSiteDataOnExit,
    473             key::kClearSiteDataOnExit),
    474         PolicyTestParams::ForStringPolicy(
    475             kPolicyDownloadDirectory,
    476             key::kDownloadDirectory),
    477         PolicyTestParams::ForBooleanPolicy(
    478             kPolicyDefaultBrowserSettingEnabled,
    479             key::kDefaultBrowserSettingEnabled),
    480         PolicyTestParams::ForBooleanPolicy(
    481             kPolicyCloudPrintProxyEnabled,
    482             key::kCloudPrintProxyEnabled),
    483         PolicyTestParams::ForBooleanPolicy(
    484             kPolicyTranslateEnabled,
    485             key::kTranslateEnabled),
    486         PolicyTestParams::ForBooleanPolicy(
    487             kPolicyAllowOutdatedPlugins,
    488             key::kAllowOutdatedPlugins),
    489         PolicyTestParams::ForBooleanPolicy(
    490             kPolicyBookmarkBarEnabled,
    491             key::kBookmarkBarEnabled),
    492         PolicyTestParams::ForBooleanPolicy(
    493             kPolicyEditBookmarksEnabled,
    494             key::kEditBookmarksEnabled),
    495         PolicyTestParams::ForBooleanPolicy(
    496             kPolicyAllowFileSelectionDialogs,
    497             key::kAllowFileSelectionDialogs),
    498         PolicyTestParams::ForListPolicy(
    499             kPolicyDisabledSchemes,
    500             key::kDisabledSchemes)));
    501 
    502 }  // namespace policy
    503