pref_service_unittest.cc revision 513209b27ff55e2841eac0e4120199c23acce758
1// Copyright (c) 2010 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 <string> 6 7#include "app/test/data/resource.h" 8#include "base/command_line.h" 9#include "base/scoped_ptr.h" 10#include "base/values.h" 11#include "chrome/browser/policy/configuration_policy_pref_store.h" 12#include "chrome/browser/policy/mock_configuration_policy_provider.h" 13#include "chrome/browser/prefs/browser_prefs.h" 14#include "chrome/browser/prefs/command_line_pref_store.h" 15#include "chrome/browser/prefs/default_pref_store.h" 16#include "chrome/browser/prefs/dummy_pref_store.h" 17#include "chrome/browser/prefs/pref_change_registrar.h" 18#include "chrome/browser/prefs/pref_value_store.h" 19#include "chrome/common/chrome_paths.h" 20#include "chrome/common/chrome_switches.h" 21#include "chrome/common/notification_observer_mock.h" 22#include "chrome/common/notification_service.h" 23#include "chrome/common/notification_type.h" 24#include "chrome/common/pref_names.h" 25#include "chrome/test/testing_pref_service.h" 26#include "testing/gmock/include/gmock/gmock.h" 27#include "testing/gtest/include/gtest/gtest.h" 28 29using testing::_; 30using testing::Mock; 31using testing::Pointee; 32using testing::Property; 33 34namespace { 35 36class TestPrefObserver : public NotificationObserver { 37 public: 38 TestPrefObserver(const PrefService* prefs, 39 const std::string& pref_name, 40 const std::string& new_pref_value) 41 : observer_fired_(false), 42 prefs_(prefs), 43 pref_name_(pref_name), 44 new_pref_value_(new_pref_value) {} 45 virtual ~TestPrefObserver() {} 46 47 virtual void Observe(NotificationType type, 48 const NotificationSource& source, 49 const NotificationDetails& details) { 50 EXPECT_EQ(type.value, NotificationType::PREF_CHANGED); 51 const PrefService* prefs_in = Source<PrefService>(source).ptr(); 52 EXPECT_EQ(prefs_in, prefs_); 53 const std::string* pref_name_in = Details<std::string>(details).ptr(); 54 EXPECT_EQ(*pref_name_in, pref_name_); 55 EXPECT_EQ(new_pref_value_, prefs_in->GetString("homepage")); 56 observer_fired_ = true; 57 } 58 59 bool observer_fired() { return observer_fired_; } 60 61 void Reset(const std::string& new_pref_value) { 62 observer_fired_ = false; 63 new_pref_value_ = new_pref_value; 64 } 65 66 private: 67 bool observer_fired_; 68 const PrefService* prefs_; 69 const std::string pref_name_; 70 std::string new_pref_value_; 71}; 72 73} // namespace 74 75// TODO(port): port this test to POSIX. 76#if defined(OS_WIN) 77TEST(PrefServiceTest, LocalizedPrefs) { 78 TestingPrefService prefs; 79 const char kBoolean[] = "boolean"; 80 const char kInteger[] = "integer"; 81 const char kString[] = "string"; 82 prefs.RegisterLocalizedBooleanPref(kBoolean, IDS_LOCALE_BOOL); 83 prefs.RegisterLocalizedIntegerPref(kInteger, IDS_LOCALE_INT); 84 prefs.RegisterLocalizedStringPref(kString, IDS_LOCALE_STRING); 85 86 // The locale default should take preference over the user default. 87 EXPECT_FALSE(prefs.GetBoolean(kBoolean)); 88 EXPECT_EQ(1, prefs.GetInteger(kInteger)); 89 EXPECT_EQ("hello", prefs.GetString(kString)); 90 91 prefs.SetBoolean(kBoolean, true); 92 EXPECT_TRUE(prefs.GetBoolean(kBoolean)); 93 prefs.SetInteger(kInteger, 5); 94 EXPECT_EQ(5, prefs.GetInteger(kInteger)); 95 prefs.SetString(kString, "foo"); 96 EXPECT_EQ("foo", prefs.GetString(kString)); 97} 98#endif 99 100TEST(PrefServiceTest, NoObserverFire) { 101 TestingPrefService prefs; 102 103 const char pref_name[] = "homepage"; 104 prefs.RegisterStringPref(pref_name, std::string()); 105 106 const std::string new_pref_value("http://www.google.com/"); 107 TestPrefObserver obs(&prefs, pref_name, new_pref_value); 108 109 PrefChangeRegistrar registrar; 110 registrar.Init(&prefs); 111 registrar.Add(pref_name, &obs); 112 // This should fire the checks in TestPrefObserver::Observe. 113 prefs.SetString(pref_name, new_pref_value); 114 115 // Make sure the observer was actually fired. 116 EXPECT_TRUE(obs.observer_fired()); 117 118 // Setting the pref to the same value should not set the pref value a second 119 // time. 120 obs.Reset(new_pref_value); 121 prefs.SetString(pref_name, new_pref_value); 122 EXPECT_FALSE(obs.observer_fired()); 123 124 // Clearing the pref should cause the pref to fire. 125 obs.Reset(std::string()); 126 prefs.ClearPref(pref_name); 127 EXPECT_TRUE(obs.observer_fired()); 128 129 // Clearing the pref again should not cause the pref to fire. 130 obs.Reset(std::string()); 131 prefs.ClearPref(pref_name); 132 EXPECT_FALSE(obs.observer_fired()); 133} 134 135TEST(PrefServiceTest, HasPrefPath) { 136 TestingPrefService prefs; 137 138 const char path[] = "fake.path"; 139 140 // Shouldn't initially have a path. 141 EXPECT_FALSE(prefs.HasPrefPath(path)); 142 143 // Register the path. This doesn't set a value, so the path still shouldn't 144 // exist. 145 prefs.RegisterStringPref(path, std::string()); 146 EXPECT_FALSE(prefs.HasPrefPath(path)); 147 148 // Set a value and make sure we have a path. 149 prefs.SetString(path, "blah"); 150 EXPECT_TRUE(prefs.HasPrefPath(path)); 151} 152 153TEST(PrefServiceTest, Observers) { 154 const char pref_name[] = "homepage"; 155 156 TestingPrefService prefs; 157 prefs.SetUserPref(pref_name, Value::CreateStringValue("http://www.cnn.com")); 158 prefs.RegisterStringPref(pref_name, std::string()); 159 160 const std::string new_pref_value("http://www.google.com/"); 161 TestPrefObserver obs(&prefs, pref_name, new_pref_value); 162 PrefChangeRegistrar registrar; 163 registrar.Init(&prefs); 164 registrar.Add(pref_name, &obs); 165 // This should fire the checks in TestPrefObserver::Observe. 166 prefs.SetString(pref_name, new_pref_value); 167 168 // Make sure the tests were actually run. 169 EXPECT_TRUE(obs.observer_fired()); 170 171 // Now try adding a second pref observer. 172 const std::string new_pref_value2("http://www.youtube.com/"); 173 obs.Reset(new_pref_value2); 174 TestPrefObserver obs2(&prefs, pref_name, new_pref_value2); 175 registrar.Add(pref_name, &obs2); 176 // This should fire the checks in obs and obs2. 177 prefs.SetString(pref_name, new_pref_value2); 178 EXPECT_TRUE(obs.observer_fired()); 179 EXPECT_TRUE(obs2.observer_fired()); 180 181 // Make sure obs2 still works after removing obs. 182 registrar.Remove(pref_name, &obs); 183 obs.Reset(std::string()); 184 obs2.Reset(new_pref_value); 185 // This should only fire the observer in obs2. 186 prefs.SetString(pref_name, new_pref_value); 187 EXPECT_FALSE(obs.observer_fired()); 188 EXPECT_TRUE(obs2.observer_fired()); 189} 190 191TEST(PrefServiceTest, ProxyFromCommandLineNotPolicy) { 192 CommandLine command_line(CommandLine::NO_PROGRAM); 193 command_line.AppendSwitch(switches::kProxyAutoDetect); 194 TestingPrefService prefs(NULL, &command_line); 195 browser::RegisterUserPrefs(&prefs); 196 EXPECT_TRUE(prefs.GetBoolean(prefs::kProxyAutoDetect)); 197 const PrefService::Preference* pref = 198 prefs.FindPreference(prefs::kProxyAutoDetect); 199 ASSERT_TRUE(pref); 200 EXPECT_FALSE(pref->IsManaged()); 201} 202 203TEST(PrefServiceTest, ProxyPolicyOverridesCommandLineOptions) { 204 CommandLine command_line(CommandLine::NO_PROGRAM); 205 command_line.AppendSwitchASCII(switches::kProxyBypassList, "123"); 206 command_line.AppendSwitchASCII(switches::kProxyPacUrl, "456"); 207 command_line.AppendSwitchASCII(switches::kProxyServer, "789"); 208 scoped_ptr<policy::MockConfigurationPolicyProvider> provider( 209 new policy::MockConfigurationPolicyProvider()); 210 Value* mode_value = Value::CreateIntegerValue( 211 policy::kPolicyManuallyConfiguredProxyMode); 212 provider->AddPolicy(policy::kPolicyProxyServerMode, mode_value); 213 provider->AddPolicy(policy::kPolicyProxyBypassList, 214 Value::CreateStringValue("abc")); 215 provider->AddPolicy(policy::kPolicyProxyPacUrl, 216 Value::CreateStringValue("def")); 217 provider->AddPolicy(policy::kPolicyProxyServer, 218 Value::CreateStringValue("ghi")); 219 220 // First verify that command-line options are set correctly when 221 // there is no policy in effect. 222 TestingPrefService prefs(NULL, &command_line); 223 browser::RegisterUserPrefs(&prefs); 224 EXPECT_FALSE(prefs.GetBoolean(prefs::kProxyAutoDetect)); 225 EXPECT_FALSE(prefs.GetBoolean(prefs::kNoProxyServer)); 226 EXPECT_EQ("789", prefs.GetString(prefs::kProxyServer)); 227 EXPECT_EQ("456", prefs.GetString(prefs::kProxyPacUrl)); 228 EXPECT_EQ("123", prefs.GetString(prefs::kProxyBypassList)); 229 230 // Try a second time time with the managed PrefStore in place, the 231 // manual proxy policy should have removed all traces of the command 232 // line and replaced them with the policy versions. 233 TestingPrefService prefs2(provider.get(), &command_line); 234 browser::RegisterUserPrefs(&prefs2); 235 EXPECT_FALSE(prefs2.GetBoolean(prefs::kProxyAutoDetect)); 236 EXPECT_FALSE(prefs2.GetBoolean(prefs::kNoProxyServer)); 237 EXPECT_EQ("ghi", prefs2.GetString(prefs::kProxyServer)); 238 EXPECT_EQ("def", prefs2.GetString(prefs::kProxyPacUrl)); 239 EXPECT_EQ("abc", prefs2.GetString(prefs::kProxyBypassList)); 240} 241 242TEST(PrefServiceTest, ProxyPolicyOverridesUnrelatedCommandLineOptions) { 243 CommandLine command_line(CommandLine::NO_PROGRAM); 244 command_line.AppendSwitchASCII(switches::kProxyBypassList, "123"); 245 command_line.AppendSwitchASCII(switches::kProxyPacUrl, "456"); 246 command_line.AppendSwitchASCII(switches::kProxyServer, "789"); 247 scoped_ptr<policy::MockConfigurationPolicyProvider> provider( 248 new policy::MockConfigurationPolicyProvider()); 249 Value* mode_value = Value::CreateIntegerValue( 250 policy::kPolicyUseSystemProxyMode); 251 provider->AddPolicy(policy::kPolicyProxyServerMode, mode_value); 252 253 // First verify that command-line options are set correctly when 254 // there is no policy in effect. 255 TestingPrefService prefs(NULL, &command_line); 256 browser::RegisterUserPrefs(&prefs); 257 EXPECT_FALSE(prefs.GetBoolean(prefs::kProxyAutoDetect)); 258 EXPECT_FALSE(prefs.GetBoolean(prefs::kNoProxyServer)); 259 EXPECT_EQ("789", prefs.GetString(prefs::kProxyServer)); 260 EXPECT_EQ("456", prefs.GetString(prefs::kProxyPacUrl)); 261 EXPECT_EQ("123", prefs.GetString(prefs::kProxyBypassList)); 262 263 // Try a second time time with the managed PrefStore in place, the 264 // no proxy policy should have removed all traces of the command 265 // line proxy settings, even though they were not the specific one 266 // set in policy. 267 TestingPrefService prefs2(provider.get(), &command_line); 268 browser::RegisterUserPrefs(&prefs2); 269 EXPECT_FALSE(prefs2.GetBoolean(prefs::kProxyAutoDetect)); 270 EXPECT_FALSE(prefs2.GetBoolean(prefs::kNoProxyServer)); 271 EXPECT_EQ(std::string(), prefs2.GetString(prefs::kProxyServer)); 272 EXPECT_EQ(std::string(), prefs2.GetString(prefs::kProxyPacUrl)); 273 EXPECT_EQ(std::string(), prefs2.GetString(prefs::kProxyBypassList)); 274} 275 276TEST(PrefServiceTest, ProxyPolicyOverridesCommandLineNoProxy) { 277 CommandLine command_line(CommandLine::NO_PROGRAM); 278 command_line.AppendSwitch(switches::kNoProxyServer); 279 scoped_ptr<policy::MockConfigurationPolicyProvider> provider( 280 new policy::MockConfigurationPolicyProvider()); 281 Value* mode_value = Value::CreateIntegerValue( 282 policy::kPolicyAutoDetectProxyMode); 283 provider->AddPolicy(policy::kPolicyProxyServerMode, mode_value); 284 285 // First verify that command-line options are set correctly when 286 // there is no policy in effect. 287 TestingPrefService prefs(NULL, &command_line); 288 browser::RegisterUserPrefs(&prefs); 289 EXPECT_FALSE(prefs.GetBoolean(prefs::kProxyAutoDetect)); 290 EXPECT_TRUE(prefs.GetBoolean(prefs::kNoProxyServer)); 291 EXPECT_EQ(std::string(), prefs.GetString(prefs::kProxyServer)); 292 EXPECT_EQ(std::string(), prefs.GetString(prefs::kProxyPacUrl)); 293 EXPECT_EQ(std::string(), prefs.GetString(prefs::kProxyBypassList)); 294 295 // Try a second time time with the managed PrefStore in place, the 296 // auto-detect should be overridden. The default pref store must be 297 // in place with the appropriate default value for this to work. 298 TestingPrefService prefs2(provider.get(), &command_line); 299 browser::RegisterUserPrefs(&prefs2); 300 EXPECT_TRUE(prefs2.GetBoolean(prefs::kProxyAutoDetect)); 301 EXPECT_FALSE(prefs2.GetBoolean(prefs::kNoProxyServer)); 302 EXPECT_EQ(std::string(), prefs2.GetString(prefs::kProxyServer)); 303 EXPECT_EQ(std::string(), prefs2.GetString(prefs::kProxyPacUrl)); 304 EXPECT_EQ(std::string(), prefs2.GetString(prefs::kProxyBypassList)); 305} 306 307TEST(PrefServiceTest, ProxyPolicyOverridesCommandLineAutoDetect) { 308 CommandLine command_line(CommandLine::NO_PROGRAM); 309 command_line.AppendSwitch(switches::kProxyAutoDetect); 310 scoped_ptr<policy::MockConfigurationPolicyProvider> provider( 311 new policy::MockConfigurationPolicyProvider()); 312 Value* mode_value = Value::CreateIntegerValue( 313 policy::kPolicyNoProxyServerMode); 314 provider->AddPolicy(policy::kPolicyProxyServerMode, mode_value); 315 316 // First verify that the auto-detect is set if there is no managed 317 // PrefStore. 318 TestingPrefService prefs(NULL, &command_line); 319 browser::RegisterUserPrefs(&prefs); 320 EXPECT_TRUE(prefs.GetBoolean(prefs::kProxyAutoDetect)); 321 EXPECT_FALSE(prefs.GetBoolean(prefs::kNoProxyServer)); 322 EXPECT_EQ(std::string(), prefs.GetString(prefs::kProxyServer)); 323 EXPECT_EQ(std::string(), prefs.GetString(prefs::kProxyPacUrl)); 324 EXPECT_EQ(std::string(), prefs.GetString(prefs::kProxyBypassList)); 325 326 // Try a second time time with the managed PrefStore in place, the 327 // auto-detect should be overridden. The default pref store must be 328 // in place with the appropriate default value for this to work. 329 TestingPrefService prefs2(provider.get(), &command_line); 330 browser::RegisterUserPrefs(&prefs2); 331 EXPECT_FALSE(prefs2.GetBoolean(prefs::kProxyAutoDetect)); 332 EXPECT_TRUE(prefs2.GetBoolean(prefs::kNoProxyServer)); 333 EXPECT_EQ(std::string(), prefs2.GetString(prefs::kProxyServer)); 334 EXPECT_EQ(std::string(), prefs2.GetString(prefs::kProxyPacUrl)); 335 EXPECT_EQ(std::string(), prefs2.GetString(prefs::kProxyBypassList)); 336} 337 338class PrefServiceSetValueTest : public testing::Test { 339 protected: 340 static const char kName[]; 341 static const char kValue[]; 342 343 PrefServiceSetValueTest() 344 : name_string_(kName), 345 null_value_(Value::CreateNullValue()) {} 346 347 void SetExpectNoNotification() { 348 EXPECT_CALL(observer_, Observe(_, _, _)).Times(0); 349 } 350 351 void SetExpectPrefChanged() { 352 EXPECT_CALL(observer_, 353 Observe(NotificationType(NotificationType::PREF_CHANGED), _, 354 Property(&Details<std::string>::ptr, 355 Pointee(name_string_)))); 356 } 357 358 TestingPrefService prefs_; 359 std::string name_string_; 360 scoped_ptr<Value> null_value_; 361 NotificationObserverMock observer_; 362}; 363 364const char PrefServiceSetValueTest::kName[] = "name"; 365const char PrefServiceSetValueTest::kValue[] = "value"; 366 367TEST_F(PrefServiceSetValueTest, SetStringValue) { 368 const char default_string[] = "default"; 369 const scoped_ptr<Value> default_value( 370 Value::CreateStringValue(default_string)); 371 prefs_.RegisterStringPref(kName, default_string); 372 373 PrefChangeRegistrar registrar; 374 registrar.Init(&prefs_); 375 registrar.Add(kName, &observer_); 376 377 // Changing the controlling store from default to user triggers notification. 378 SetExpectPrefChanged(); 379 prefs_.Set(kName, *default_value); 380 Mock::VerifyAndClearExpectations(&observer_); 381 382 SetExpectNoNotification(); 383 prefs_.Set(kName, *default_value); 384 Mock::VerifyAndClearExpectations(&observer_); 385 386 const scoped_ptr<Value> new_value(Value::CreateStringValue(kValue)); 387 SetExpectPrefChanged(); 388 prefs_.Set(kName, *new_value); 389 EXPECT_EQ(kValue, prefs_.GetString(kName)); 390} 391 392TEST_F(PrefServiceSetValueTest, SetDictionaryValue) { 393 prefs_.RegisterDictionaryPref(kName); 394 PrefChangeRegistrar registrar; 395 registrar.Init(&prefs_); 396 registrar.Add(kName, &observer_); 397 398 // Dictionary values are special: setting one to NULL is the same as clearing 399 // the user value, allowing the NULL default to take (or keep) control. 400 SetExpectNoNotification(); 401 prefs_.Set(kName, *null_value_); 402 Mock::VerifyAndClearExpectations(&observer_); 403 404 DictionaryValue new_value; 405 new_value.SetString(kName, kValue); 406 SetExpectPrefChanged(); 407 prefs_.Set(kName, new_value); 408 Mock::VerifyAndClearExpectations(&observer_); 409 DictionaryValue* dict = prefs_.GetMutableDictionary(kName); 410 EXPECT_EQ(1U, dict->size()); 411 std::string out_value; 412 dict->GetString(kName, &out_value); 413 EXPECT_EQ(kValue, out_value); 414 415 SetExpectNoNotification(); 416 prefs_.Set(kName, new_value); 417 Mock::VerifyAndClearExpectations(&observer_); 418 419 SetExpectPrefChanged(); 420 prefs_.Set(kName, *null_value_); 421 Mock::VerifyAndClearExpectations(&observer_); 422 dict = prefs_.GetMutableDictionary(kName); 423 EXPECT_EQ(0U, dict->size()); 424} 425 426TEST_F(PrefServiceSetValueTest, SetListValue) { 427 prefs_.RegisterListPref(kName); 428 PrefChangeRegistrar registrar; 429 registrar.Init(&prefs_); 430 registrar.Add(kName, &observer_); 431 432 // List values are special: setting one to NULL is the same as clearing the 433 // user value, allowing the NULL default to take (or keep) control. 434 SetExpectNoNotification(); 435 prefs_.Set(kName, *null_value_); 436 Mock::VerifyAndClearExpectations(&observer_); 437 438 ListValue new_value; 439 new_value.Append(Value::CreateStringValue(kValue)); 440 SetExpectPrefChanged(); 441 prefs_.Set(kName, new_value); 442 Mock::VerifyAndClearExpectations(&observer_); 443 const ListValue* list = prefs_.GetMutableList(kName); 444 ASSERT_EQ(1U, list->GetSize()); 445 std::string out_value; 446 list->GetString(0, &out_value); 447 EXPECT_EQ(kValue, out_value); 448 449 SetExpectNoNotification(); 450 prefs_.Set(kName, new_value); 451 Mock::VerifyAndClearExpectations(&observer_); 452 453 SetExpectPrefChanged(); 454 prefs_.Set(kName, *null_value_); 455 Mock::VerifyAndClearExpectations(&observer_); 456 list = prefs_.GetMutableList(kName); 457 EXPECT_EQ(0U, list->GetSize()); 458} 459