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