1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "chrome/browser/policy/configuration_policy_provider_test.h" 6 7 #include "base/bind.h" 8 #include "base/callback.h" 9 #include "base/memory/scoped_ptr.h" 10 #include "base/values.h" 11 #include "chrome/browser/policy/configuration_policy_provider.h" 12 #include "chrome/browser/policy/external_data_fetcher.h" 13 #include "chrome/browser/policy/mock_configuration_policy_provider.h" 14 #include "chrome/browser/policy/policy_bundle.h" 15 #include "chrome/browser/policy/policy_map.h" 16 #include "policy/policy_constants.h" 17 #include "testing/gmock/include/gmock/gmock.h" 18 19 using content::BrowserThread; 20 using ::testing::Mock; 21 using ::testing::_; 22 23 namespace policy { 24 25 namespace test_policy_definitions { 26 27 const char kKeyString[] = "StringPolicy"; 28 const char kKeyBoolean[] = "BooleanPolicy"; 29 const char kKeyInteger[] = "IntegerPolicy"; 30 const char kKeyStringList[] = "StringListPolicy"; 31 const char kKeyDictionary[] = "DictionaryPolicy"; 32 33 static const PolicyDefinitionList::Entry kEntries[] = { 34 { kKeyString, base::Value::TYPE_STRING }, 35 { kKeyBoolean, base::Value::TYPE_BOOLEAN }, 36 { kKeyInteger, base::Value::TYPE_INTEGER }, 37 { kKeyStringList, base::Value::TYPE_LIST }, 38 { kKeyDictionary, base::Value::TYPE_DICTIONARY }, 39 }; 40 41 const PolicyDefinitionList kList = { 42 kEntries, kEntries + arraysize(kEntries) 43 }; 44 45 } // namespace test_policy_definitions 46 47 PolicyTestBase::PolicyTestBase() 48 : ui_thread_(BrowserThread::UI, &loop_), 49 file_thread_(BrowserThread::FILE, &loop_) {} 50 51 PolicyTestBase::~PolicyTestBase() {} 52 53 void PolicyTestBase::TearDown() { 54 loop_.RunUntilIdle(); 55 } 56 57 PolicyProviderTestHarness::PolicyProviderTestHarness(PolicyLevel level, 58 PolicyScope scope) 59 : level_(level), scope_(scope) {} 60 61 PolicyProviderTestHarness::~PolicyProviderTestHarness() {} 62 63 PolicyLevel PolicyProviderTestHarness::policy_level() const { 64 return level_; 65 } 66 67 PolicyScope PolicyProviderTestHarness::policy_scope() const { 68 return scope_; 69 } 70 71 void PolicyProviderTestHarness::Install3rdPartyPolicy( 72 const base::DictionaryValue* policies) { 73 FAIL(); 74 } 75 76 ConfigurationPolicyProviderTest::ConfigurationPolicyProviderTest() {} 77 78 ConfigurationPolicyProviderTest::~ConfigurationPolicyProviderTest() {} 79 80 void ConfigurationPolicyProviderTest::SetUp() { 81 PolicyTestBase::SetUp(); 82 83 test_harness_.reset((*GetParam())()); 84 test_harness_->SetUp(); 85 86 provider_.reset( 87 test_harness_->CreateProvider(&test_policy_definitions::kList)); 88 provider_->Init(); 89 // Some providers do a reload on init. Make sure any notifications generated 90 // are fired now. 91 loop_.RunUntilIdle(); 92 93 const PolicyBundle kEmptyBundle; 94 EXPECT_TRUE(provider_->policies().Equals(kEmptyBundle)); 95 } 96 97 void ConfigurationPolicyProviderTest::TearDown() { 98 // Give providers the chance to clean up after themselves on the file thread. 99 provider_->Shutdown(); 100 provider_.reset(); 101 102 PolicyTestBase::TearDown(); 103 } 104 105 void ConfigurationPolicyProviderTest::CheckValue( 106 const char* policy_name, 107 const base::Value& expected_value, 108 base::Closure install_value) { 109 // Install the value, reload policy and check the provider for the value. 110 install_value.Run(); 111 provider_->RefreshPolicies(); 112 loop_.RunUntilIdle(); 113 PolicyBundle expected_bundle; 114 expected_bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())) 115 .Set(policy_name, 116 test_harness_->policy_level(), 117 test_harness_->policy_scope(), 118 expected_value.DeepCopy(), 119 NULL); 120 EXPECT_TRUE(provider_->policies().Equals(expected_bundle)); 121 // TODO(joaodasilva): set the policy in the POLICY_DOMAIN_EXTENSIONS too, 122 // and extend the |expected_bundle|, once all providers are ready. 123 } 124 125 TEST_P(ConfigurationPolicyProviderTest, Empty) { 126 provider_->RefreshPolicies(); 127 loop_.RunUntilIdle(); 128 const PolicyBundle kEmptyBundle; 129 EXPECT_TRUE(provider_->policies().Equals(kEmptyBundle)); 130 } 131 132 TEST_P(ConfigurationPolicyProviderTest, StringValue) { 133 const char kTestString[] = "string_value"; 134 base::StringValue expected_value(kTestString); 135 CheckValue(test_policy_definitions::kKeyString, 136 expected_value, 137 base::Bind(&PolicyProviderTestHarness::InstallStringPolicy, 138 base::Unretained(test_harness_.get()), 139 test_policy_definitions::kKeyString, 140 kTestString)); 141 } 142 143 TEST_P(ConfigurationPolicyProviderTest, BooleanValue) { 144 base::FundamentalValue expected_value(true); 145 CheckValue(test_policy_definitions::kKeyBoolean, 146 expected_value, 147 base::Bind(&PolicyProviderTestHarness::InstallBooleanPolicy, 148 base::Unretained(test_harness_.get()), 149 test_policy_definitions::kKeyBoolean, 150 true)); 151 } 152 153 TEST_P(ConfigurationPolicyProviderTest, IntegerValue) { 154 base::FundamentalValue expected_value(42); 155 CheckValue(test_policy_definitions::kKeyInteger, 156 expected_value, 157 base::Bind(&PolicyProviderTestHarness::InstallIntegerPolicy, 158 base::Unretained(test_harness_.get()), 159 test_policy_definitions::kKeyInteger, 160 42)); 161 } 162 163 TEST_P(ConfigurationPolicyProviderTest, StringListValue) { 164 base::ListValue expected_value; 165 expected_value.Set(0U, base::Value::CreateStringValue("first")); 166 expected_value.Set(1U, base::Value::CreateStringValue("second")); 167 CheckValue(test_policy_definitions::kKeyStringList, 168 expected_value, 169 base::Bind(&PolicyProviderTestHarness::InstallStringListPolicy, 170 base::Unretained(test_harness_.get()), 171 test_policy_definitions::kKeyStringList, 172 &expected_value)); 173 } 174 175 TEST_P(ConfigurationPolicyProviderTest, DictionaryValue) { 176 base::DictionaryValue expected_value; 177 expected_value.SetBoolean("bool", true); 178 expected_value.SetInteger("int", 123); 179 expected_value.SetString("str", "omg"); 180 181 base::ListValue* list = new base::ListValue(); 182 list->Set(0U, base::Value::CreateStringValue("first")); 183 list->Set(1U, base::Value::CreateStringValue("second")); 184 expected_value.Set("list", list); 185 186 base::DictionaryValue* dict = new base::DictionaryValue(); 187 dict->SetString("sub", "value"); 188 list = new base::ListValue(); 189 base::DictionaryValue* sub = new base::DictionaryValue(); 190 sub->SetInteger("aaa", 111); 191 sub->SetInteger("bbb", 222); 192 list->Append(sub); 193 sub = new base::DictionaryValue(); 194 sub->SetString("ccc", "333"); 195 sub->SetString("ddd", "444"); 196 list->Append(sub); 197 dict->Set("sublist", list); 198 expected_value.Set("dict", dict); 199 200 CheckValue(test_policy_definitions::kKeyDictionary, 201 expected_value, 202 base::Bind(&PolicyProviderTestHarness::InstallDictionaryPolicy, 203 base::Unretained(test_harness_.get()), 204 test_policy_definitions::kKeyDictionary, 205 &expected_value)); 206 } 207 208 TEST_P(ConfigurationPolicyProviderTest, RefreshPolicies) { 209 PolicyBundle bundle; 210 EXPECT_TRUE(provider_->policies().Equals(bundle)); 211 212 // OnUpdatePolicy is called even when there are no changes. 213 MockConfigurationPolicyObserver observer; 214 provider_->AddObserver(&observer); 215 EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(1); 216 provider_->RefreshPolicies(); 217 loop_.RunUntilIdle(); 218 Mock::VerifyAndClearExpectations(&observer); 219 220 EXPECT_TRUE(provider_->policies().Equals(bundle)); 221 222 // OnUpdatePolicy is called when there are changes. 223 test_harness_->InstallStringPolicy(test_policy_definitions::kKeyString, 224 "value"); 225 EXPECT_CALL(observer, OnUpdatePolicy(provider_.get())).Times(1); 226 provider_->RefreshPolicies(); 227 loop_.RunUntilIdle(); 228 Mock::VerifyAndClearExpectations(&observer); 229 230 bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())) 231 .Set(test_policy_definitions::kKeyString, 232 test_harness_->policy_level(), 233 test_harness_->policy_scope(), 234 base::Value::CreateStringValue("value"), 235 NULL); 236 EXPECT_TRUE(provider_->policies().Equals(bundle)); 237 provider_->RemoveObserver(&observer); 238 } 239 240 TEST(ConfigurationPolicyProviderTest, FixDeprecatedPolicies) { 241 PolicyMap policy_map; 242 policy_map.Set(key::kProxyServerMode, 243 POLICY_LEVEL_MANDATORY, 244 POLICY_SCOPE_USER, 245 base::Value::CreateIntegerValue(3), 246 NULL); 247 248 // Both these policies should be ignored, since there's a higher priority 249 // policy available. 250 policy_map.Set(key::kProxyMode, 251 POLICY_LEVEL_RECOMMENDED, 252 POLICY_SCOPE_USER, 253 base::Value::CreateStringValue("pac_script"), 254 NULL); 255 policy_map.Set(key::kProxyPacUrl, 256 POLICY_LEVEL_RECOMMENDED, 257 POLICY_SCOPE_USER, 258 base::Value::CreateStringValue("http://example.com/wpad.dat"), 259 NULL); 260 261 MockConfigurationPolicyProvider provider; 262 provider.Init(); 263 provider.UpdateChromePolicy(policy_map); 264 265 PolicyBundle expected_bundle; 266 base::DictionaryValue* expected_value = new base::DictionaryValue(); 267 expected_value->SetInteger(key::kProxyServerMode, 3); 268 expected_bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())) 269 .Set(key::kProxySettings, 270 POLICY_LEVEL_MANDATORY, 271 POLICY_SCOPE_USER, 272 expected_value, 273 NULL); 274 EXPECT_TRUE(provider.policies().Equals(expected_bundle)); 275 provider.Shutdown(); 276 } 277 278 Configuration3rdPartyPolicyProviderTest:: 279 Configuration3rdPartyPolicyProviderTest() {} 280 281 Configuration3rdPartyPolicyProviderTest:: 282 ~Configuration3rdPartyPolicyProviderTest() {} 283 284 TEST_P(Configuration3rdPartyPolicyProviderTest, Load3rdParty) { 285 base::DictionaryValue policy_dict; 286 policy_dict.SetBoolean("bool", true); 287 policy_dict.SetDouble("double", 123.456); 288 policy_dict.SetInteger("int", 789); 289 policy_dict.SetString("str", "string value"); 290 291 base::ListValue* list = new base::ListValue(); 292 for (int i = 0; i < 2; ++i) { 293 base::DictionaryValue* dict = new base::DictionaryValue(); 294 dict->SetInteger("subdictindex", i); 295 dict->Set("subdict", policy_dict.DeepCopy()); 296 list->Append(dict); 297 } 298 policy_dict.Set("list", list); 299 policy_dict.Set("dict", policy_dict.DeepCopy()); 300 301 // Install these policies as a Chrome policy. 302 test_harness_->InstallDictionaryPolicy( 303 test_policy_definitions::kKeyDictionary, &policy_dict); 304 // Install them as 3rd party policies too. 305 base::DictionaryValue policy_3rdparty; 306 policy_3rdparty.Set("extensions.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 307 policy_dict.DeepCopy()); 308 policy_3rdparty.Set("extensions.bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", 309 policy_dict.DeepCopy()); 310 // Install invalid 3rd party policies that shouldn't be loaded. These also 311 // help detecting memory leaks in the code paths that detect invalid input. 312 policy_3rdparty.Set("invalid-domain.component", policy_dict.DeepCopy()); 313 policy_3rdparty.Set("extensions.cccccccccccccccccccccccccccccccc", 314 base::Value::CreateStringValue("invalid-value")); 315 test_harness_->Install3rdPartyPolicy(&policy_3rdparty); 316 317 provider_->RefreshPolicies(); 318 loop_.RunUntilIdle(); 319 320 PolicyMap expected_policy; 321 expected_policy.Set(test_policy_definitions::kKeyDictionary, 322 test_harness_->policy_level(), 323 test_harness_->policy_scope(), 324 policy_dict.DeepCopy(), 325 NULL); 326 PolicyBundle expected_bundle; 327 expected_bundle.Get(PolicyNamespace(POLICY_DOMAIN_CHROME, std::string())) 328 .CopyFrom(expected_policy); 329 expected_policy.Clear(); 330 expected_policy.LoadFrom(&policy_dict, 331 test_harness_->policy_level(), 332 test_harness_->policy_scope()); 333 expected_bundle.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, 334 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")) 335 .CopyFrom(expected_policy); 336 expected_bundle.Get(PolicyNamespace(POLICY_DOMAIN_EXTENSIONS, 337 "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb")) 338 .CopyFrom(expected_policy); 339 EXPECT_TRUE(provider_->policies().Equals(expected_bundle)); 340 } 341 342 } // namespace policy 343