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