pref_service_unittest.cc revision ddb351dbec246cf1fab5ec20d2d5520909041de1
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 <string>
6
7#include "app/test/data/resource.h"
8#include "base/command_line.h"
9#include "base/memory/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/pref_change_registrar.h"
16#include "chrome/browser/prefs/pref_observer_mock.h"
17#include "chrome/browser/prefs/pref_service_mock_builder.h"
18#include "chrome/browser/prefs/pref_value_store.h"
19#include "chrome/browser/prefs/proxy_config_dictionary.h"
20#include "chrome/browser/prefs/testing_pref_store.h"
21#include "chrome/common/chrome_paths.h"
22#include "chrome/common/chrome_switches.h"
23#include "chrome/common/pref_names.h"
24#include "chrome/test/testing_pref_service.h"
25#include "testing/gmock/include/gmock/gmock.h"
26#include "testing/gtest/include/gtest/gtest.h"
27
28using testing::_;
29using testing::Mock;
30
31// TODO(port): port this test to POSIX.
32#if defined(OS_WIN)
33TEST(PrefServiceTest, LocalizedPrefs) {
34  TestingPrefService prefs;
35  const char kBoolean[] = "boolean";
36  const char kInteger[] = "integer";
37  const char kString[] = "string";
38  prefs.RegisterLocalizedBooleanPref(kBoolean, IDS_LOCALE_BOOL);
39  prefs.RegisterLocalizedIntegerPref(kInteger, IDS_LOCALE_INT);
40  prefs.RegisterLocalizedStringPref(kString, IDS_LOCALE_STRING);
41
42  // The locale default should take preference over the user default.
43  EXPECT_FALSE(prefs.GetBoolean(kBoolean));
44  EXPECT_EQ(1, prefs.GetInteger(kInteger));
45  EXPECT_EQ("hello", prefs.GetString(kString));
46
47  prefs.SetBoolean(kBoolean, true);
48  EXPECT_TRUE(prefs.GetBoolean(kBoolean));
49  prefs.SetInteger(kInteger, 5);
50  EXPECT_EQ(5, prefs.GetInteger(kInteger));
51  prefs.SetString(kString, "foo");
52  EXPECT_EQ("foo", prefs.GetString(kString));
53}
54#endif
55
56TEST(PrefServiceTest, NoObserverFire) {
57  TestingPrefService prefs;
58
59  const char pref_name[] = "homepage";
60  prefs.RegisterStringPref(pref_name, std::string());
61
62  const char new_pref_value[] = "http://www.google.com/";
63  PrefObserverMock obs;
64  PrefChangeRegistrar registrar;
65  registrar.Init(&prefs);
66  registrar.Add(pref_name, &obs);
67
68  // This should fire the checks in PrefObserverMock::Observe.
69  const StringValue expected_value(new_pref_value);
70  obs.Expect(&prefs, pref_name, &expected_value);
71  prefs.SetString(pref_name, new_pref_value);
72  Mock::VerifyAndClearExpectations(&obs);
73
74  // Setting the pref to the same value should not set the pref value a second
75  // time.
76  EXPECT_CALL(obs, Observe(_, _, _)).Times(0);
77  prefs.SetString(pref_name, new_pref_value);
78  Mock::VerifyAndClearExpectations(&obs);
79
80  // Clearing the pref should cause the pref to fire.
81  const StringValue expected_default_value("");
82  obs.Expect(&prefs, pref_name, &expected_default_value);
83  prefs.ClearPref(pref_name);
84  Mock::VerifyAndClearExpectations(&obs);
85
86  // Clearing the pref again should not cause the pref to fire.
87  EXPECT_CALL(obs, Observe(_, _, _)).Times(0);
88  prefs.ClearPref(pref_name);
89  Mock::VerifyAndClearExpectations(&obs);
90}
91
92TEST(PrefServiceTest, HasPrefPath) {
93  TestingPrefService prefs;
94
95  const char path[] = "fake.path";
96
97  // Shouldn't initially have a path.
98  EXPECT_FALSE(prefs.HasPrefPath(path));
99
100  // Register the path. This doesn't set a value, so the path still shouldn't
101  // exist.
102  prefs.RegisterStringPref(path, std::string());
103  EXPECT_FALSE(prefs.HasPrefPath(path));
104
105  // Set a value and make sure we have a path.
106  prefs.SetString(path, "blah");
107  EXPECT_TRUE(prefs.HasPrefPath(path));
108}
109
110TEST(PrefServiceTest, Observers) {
111  const char pref_name[] = "homepage";
112
113  TestingPrefService prefs;
114  prefs.SetUserPref(pref_name, Value::CreateStringValue("http://www.cnn.com"));
115  prefs.RegisterStringPref(pref_name, std::string());
116
117  const char new_pref_value[] = "http://www.google.com/";
118  const StringValue expected_new_pref_value(new_pref_value);
119  PrefObserverMock obs;
120  PrefChangeRegistrar registrar;
121  registrar.Init(&prefs);
122  registrar.Add(pref_name, &obs);
123
124  // This should fire the checks in PrefObserverMock::Observe.
125  obs.Expect(&prefs, pref_name, &expected_new_pref_value);
126  prefs.SetString(pref_name, new_pref_value);
127  Mock::VerifyAndClearExpectations(&obs);
128
129  // Now try adding a second pref observer.
130  const char new_pref_value2[] = "http://www.youtube.com/";
131  const StringValue expected_new_pref_value2(new_pref_value2);
132  PrefObserverMock obs2;
133  obs.Expect(&prefs, pref_name, &expected_new_pref_value2);
134  obs2.Expect(&prefs, pref_name, &expected_new_pref_value2);
135  registrar.Add(pref_name, &obs2);
136  // This should fire the checks in obs and obs2.
137  prefs.SetString(pref_name, new_pref_value2);
138  Mock::VerifyAndClearExpectations(&obs);
139  Mock::VerifyAndClearExpectations(&obs2);
140
141  // Make sure obs2 still works after removing obs.
142  registrar.Remove(pref_name, &obs);
143  EXPECT_CALL(obs, Observe(_, _, _)).Times(0);
144  obs2.Expect(&prefs, pref_name, &expected_new_pref_value);
145  // This should only fire the observer in obs2.
146  prefs.SetString(pref_name, new_pref_value);
147  Mock::VerifyAndClearExpectations(&obs);
148  Mock::VerifyAndClearExpectations(&obs2);
149}
150
151// Make sure that if a preference changes type, so the wrong type is stored in
152// the user pref file, it uses the correct fallback value instead.
153TEST(PrefServiceTest, GetValueChangedType) {
154  const int kTestValue = 10;
155  TestingPrefService prefs;
156  prefs.RegisterIntegerPref(prefs::kStabilityLaunchCount, kTestValue);
157
158  // Check falling back to a recommended value.
159  prefs.SetUserPref(prefs::kStabilityLaunchCount,
160                    Value::CreateStringValue("not an integer"));
161  const PrefService::Preference* pref =
162      prefs.FindPreference(prefs::kStabilityLaunchCount);
163  ASSERT_TRUE(pref);
164  const Value* value = pref->GetValue();
165  ASSERT_TRUE(value);
166  EXPECT_EQ(Value::TYPE_INTEGER, value->GetType());
167  int actual_int_value = -1;
168  EXPECT_TRUE(value->GetAsInteger(&actual_int_value));
169  EXPECT_EQ(kTestValue, actual_int_value);
170}
171
172void assertProxyMode(const ProxyConfigDictionary& dict,
173                     ProxyPrefs::ProxyMode expected_mode) {
174  ProxyPrefs::ProxyMode actual_mode;
175  ASSERT_TRUE(dict.GetMode(&actual_mode));
176  EXPECT_EQ(expected_mode, actual_mode);
177}
178
179void assertProxyServer(const ProxyConfigDictionary& dict,
180                       const std::string& expected) {
181  std::string actual;
182  if (!expected.empty()) {
183    ASSERT_TRUE(dict.GetProxyServer(&actual));
184    EXPECT_EQ(expected, actual);
185  } else {
186    EXPECT_FALSE(dict.GetProxyServer(&actual));
187  }
188}
189
190void assertPacUrl(const ProxyConfigDictionary& dict,
191                  const std::string& expected) {
192  std::string actual;
193  if (!expected.empty()) {
194    ASSERT_TRUE(dict.GetPacUrl(&actual));
195    EXPECT_EQ(expected, actual);
196  } else {
197    EXPECT_FALSE(dict.GetPacUrl(&actual));
198  }
199}
200
201void assertBypassList(const ProxyConfigDictionary& dict,
202                      const std::string& expected) {
203  std::string actual;
204  if (!expected.empty()) {
205    ASSERT_TRUE(dict.GetBypassList(&actual));
206    EXPECT_EQ(expected, actual);
207  } else {
208    EXPECT_FALSE(dict.GetBypassList(&actual));
209  }
210}
211
212void assertProxyModeWithoutParams(const ProxyConfigDictionary& dict,
213                                  ProxyPrefs::ProxyMode proxy_mode) {
214  assertProxyMode(dict, proxy_mode);
215  assertProxyServer(dict, "");
216  assertPacUrl(dict, "");
217  assertBypassList(dict, "");
218}
219
220TEST(PrefServiceTest, ProxyPolicyOverridesCommandLineOptions) {
221  CommandLine command_line(CommandLine::NO_PROGRAM);
222  command_line.AppendSwitchASCII(switches::kProxyBypassList, "123");
223  command_line.AppendSwitchASCII(switches::kProxyServer, "789");
224  scoped_ptr<policy::MockConfigurationPolicyProvider> provider(
225      new policy::MockConfigurationPolicyProvider());
226  Value* mode_name = Value::CreateStringValue(
227      ProxyPrefs::kFixedServersProxyModeName);
228  provider->AddPolicy(policy::kPolicyProxyMode, mode_name);
229  provider->AddPolicy(policy::kPolicyProxyBypassList,
230                      Value::CreateStringValue("abc"));
231  provider->AddPolicy(policy::kPolicyProxyServer,
232                      Value::CreateStringValue("ghi"));
233
234  // First verify that command-line options are set correctly when
235  // there is no policy in effect.
236  PrefServiceMockBuilder builder;
237  builder.WithCommandLine(&command_line);
238  scoped_ptr<PrefService> prefs(builder.Create());
239  browser::RegisterUserPrefs(prefs.get());
240  ProxyConfigDictionary dict(prefs->GetDictionary(prefs::kProxy));
241  assertProxyMode(dict, ProxyPrefs::MODE_FIXED_SERVERS);
242  assertProxyServer(dict, "789");
243  assertPacUrl(dict, "");
244  assertBypassList(dict, "123");
245
246  // Try a second time time with the managed PrefStore in place, the
247  // manual proxy policy should have removed all traces of the command
248  // line and replaced them with the policy versions.
249  builder.WithCommandLine(&command_line);
250  builder.WithManagedPlatformProvider(provider.get());
251  scoped_ptr<PrefService> prefs2(builder.Create());
252  browser::RegisterUserPrefs(prefs2.get());
253  ProxyConfigDictionary dict2(prefs2->GetDictionary(prefs::kProxy));
254  assertProxyMode(dict2, ProxyPrefs::MODE_FIXED_SERVERS);
255  assertProxyServer(dict2, "ghi");
256  assertPacUrl(dict2, "");
257  assertBypassList(dict2, "abc");
258}
259
260TEST(PrefServiceTest, ProxyPolicyOverridesUnrelatedCommandLineOptions) {
261  CommandLine command_line(CommandLine::NO_PROGRAM);
262  command_line.AppendSwitchASCII(switches::kProxyBypassList, "123");
263  command_line.AppendSwitchASCII(switches::kProxyServer, "789");
264  scoped_ptr<policy::MockConfigurationPolicyProvider> provider(
265      new policy::MockConfigurationPolicyProvider());
266  Value* mode_name = Value::CreateStringValue(
267      ProxyPrefs::kAutoDetectProxyModeName);
268  provider->AddPolicy(policy::kPolicyProxyMode, mode_name);
269
270  // First verify that command-line options are set correctly when
271  // there is no policy in effect.
272  PrefServiceMockBuilder builder;
273  builder.WithCommandLine(&command_line);
274  scoped_ptr<PrefService> prefs(builder.Create());
275  browser::RegisterUserPrefs(prefs.get());
276  ProxyConfigDictionary dict(prefs->GetDictionary(prefs::kProxy));
277  assertProxyMode(dict, ProxyPrefs::MODE_FIXED_SERVERS);
278  assertProxyServer(dict, "789");
279  assertPacUrl(dict, "");
280  assertBypassList(dict, "123");
281
282  // Try a second time time with the managed PrefStore in place, the
283  // no proxy policy should have removed all traces of the command
284  // line proxy settings, even though they were not the specific one
285  // set in policy.
286  builder.WithCommandLine(&command_line);
287  builder.WithManagedPlatformProvider(provider.get());
288  scoped_ptr<PrefService> prefs2(builder.Create());
289  browser::RegisterUserPrefs(prefs2.get());
290  ProxyConfigDictionary dict2(prefs2->GetDictionary(prefs::kProxy));
291  assertProxyModeWithoutParams(dict2, ProxyPrefs::MODE_AUTO_DETECT);
292}
293
294TEST(PrefServiceTest, ProxyPolicyOverridesCommandLineNoProxy) {
295  CommandLine command_line(CommandLine::NO_PROGRAM);
296  command_line.AppendSwitch(switches::kNoProxyServer);
297  scoped_ptr<policy::MockConfigurationPolicyProvider> provider(
298      new policy::MockConfigurationPolicyProvider());
299  Value* mode_name = Value::CreateStringValue(
300      ProxyPrefs::kAutoDetectProxyModeName);
301  provider->AddPolicy(policy::kPolicyProxyMode, mode_name);
302
303  // First verify that command-line options are set correctly when
304  // there is no policy in effect.
305  PrefServiceMockBuilder builder;
306  builder.WithCommandLine(&command_line);
307  scoped_ptr<PrefService> prefs(builder.Create());
308  browser::RegisterUserPrefs(prefs.get());
309  ProxyConfigDictionary dict(prefs->GetDictionary(prefs::kProxy));
310  assertProxyModeWithoutParams(dict, ProxyPrefs::MODE_DIRECT);
311
312  // Try a second time time with the managed PrefStore in place, the
313  // auto-detect should be overridden. The default pref store must be
314  // in place with the appropriate default value for this to work.
315  builder.WithCommandLine(&command_line);
316  builder.WithManagedPlatformProvider(provider.get());
317  scoped_ptr<PrefService> prefs2(builder.Create());
318  browser::RegisterUserPrefs(prefs2.get());
319  ProxyConfigDictionary dict2(prefs2->GetDictionary(prefs::kProxy));
320  assertProxyModeWithoutParams(dict2, ProxyPrefs::MODE_AUTO_DETECT);
321}
322
323TEST(PrefServiceTest, ProxyPolicyOverridesCommandLineAutoDetect) {
324  CommandLine command_line(CommandLine::NO_PROGRAM);
325  command_line.AppendSwitch(switches::kProxyAutoDetect);
326  scoped_ptr<policy::MockConfigurationPolicyProvider> provider(
327      new policy::MockConfigurationPolicyProvider());
328  Value* mode_name = Value::CreateStringValue(
329      ProxyPrefs::kDirectProxyModeName);
330  provider->AddPolicy(policy::kPolicyProxyMode, mode_name);
331
332  // First verify that the auto-detect is set if there is no managed
333  // PrefStore.
334  PrefServiceMockBuilder builder;
335  builder.WithCommandLine(&command_line);
336  scoped_ptr<PrefService> prefs(builder.Create());
337  browser::RegisterUserPrefs(prefs.get());
338  ProxyConfigDictionary dict(prefs->GetDictionary(prefs::kProxy));
339  assertProxyModeWithoutParams(dict, ProxyPrefs::MODE_AUTO_DETECT);
340
341  // Try a second time time with the managed PrefStore in place, the
342  // auto-detect should be overridden. The default pref store must be
343  // in place with the appropriate default value for this to work.
344  builder.WithCommandLine(&command_line);
345  builder.WithManagedPlatformProvider(provider.get());
346  scoped_ptr<PrefService> prefs2(builder.Create());
347  browser::RegisterUserPrefs(prefs2.get());
348  ProxyConfigDictionary dict2(prefs2->GetDictionary(prefs::kProxy));
349  assertProxyModeWithoutParams(dict2, ProxyPrefs::MODE_DIRECT);
350}
351
352class PrefServiceSetValueTest : public testing::Test {
353 protected:
354  static const char kName[];
355  static const char kValue[];
356
357  TestingPrefService prefs_;
358  PrefObserverMock observer_;
359};
360
361const char PrefServiceSetValueTest::kName[] = "name";
362const char PrefServiceSetValueTest::kValue[] = "value";
363
364TEST_F(PrefServiceSetValueTest, SetStringValue) {
365  const char default_string[] = "default";
366  const StringValue default_value(default_string);
367  prefs_.RegisterStringPref(kName, default_string);
368
369  PrefChangeRegistrar registrar;
370  registrar.Init(&prefs_);
371  registrar.Add(kName, &observer_);
372
373  // Changing the controlling store from default to user triggers notification.
374  observer_.Expect(&prefs_, kName, &default_value);
375  prefs_.Set(kName, default_value);
376  Mock::VerifyAndClearExpectations(&observer_);
377
378  EXPECT_CALL(observer_, Observe(_, _, _)).Times(0);
379  prefs_.Set(kName, default_value);
380  Mock::VerifyAndClearExpectations(&observer_);
381
382  StringValue new_value(kValue);
383  observer_.Expect(&prefs_, kName, &new_value);
384  prefs_.Set(kName, new_value);
385  Mock::VerifyAndClearExpectations(&observer_);
386}
387
388TEST_F(PrefServiceSetValueTest, SetDictionaryValue) {
389  prefs_.RegisterDictionaryPref(kName);
390  PrefChangeRegistrar registrar;
391  registrar.Init(&prefs_);
392  registrar.Add(kName, &observer_);
393
394  EXPECT_CALL(observer_, Observe(_, _, _)).Times(0);
395  prefs_.RemoveUserPref(kName);
396  Mock::VerifyAndClearExpectations(&observer_);
397
398  DictionaryValue new_value;
399  new_value.SetString(kName, kValue);
400  observer_.Expect(&prefs_, kName, &new_value);
401  prefs_.Set(kName, new_value);
402  Mock::VerifyAndClearExpectations(&observer_);
403
404  EXPECT_CALL(observer_, Observe(_, _, _)).Times(0);
405  prefs_.Set(kName, new_value);
406  Mock::VerifyAndClearExpectations(&observer_);
407
408  DictionaryValue empty;
409  observer_.Expect(&prefs_, kName, &empty);
410  prefs_.Set(kName, empty);
411  Mock::VerifyAndClearExpectations(&observer_);
412}
413
414TEST_F(PrefServiceSetValueTest, SetListValue) {
415  prefs_.RegisterListPref(kName);
416  PrefChangeRegistrar registrar;
417  registrar.Init(&prefs_);
418  registrar.Add(kName, &observer_);
419
420  EXPECT_CALL(observer_, Observe(_, _, _)).Times(0);
421  prefs_.RemoveUserPref(kName);
422  Mock::VerifyAndClearExpectations(&observer_);
423
424  ListValue new_value;
425  new_value.Append(Value::CreateStringValue(kValue));
426  observer_.Expect(&prefs_, kName, &new_value);
427  prefs_.Set(kName, new_value);
428  Mock::VerifyAndClearExpectations(&observer_);
429
430  EXPECT_CALL(observer_, Observe(_, _, _)).Times(0);
431  prefs_.Set(kName, new_value);
432  Mock::VerifyAndClearExpectations(&observer_);
433
434  ListValue empty;
435  observer_.Expect(&prefs_, kName, &empty);
436  prefs_.Set(kName, empty);
437  Mock::VerifyAndClearExpectations(&observer_);
438}
439