recommendation_restorer_unittest.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
1// Copyright 2013 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/chromeos/policy/recommendation_restorer.h"
6
7#include "ash/magnifier/magnifier_constants.h"
8#include "base/memory/scoped_ptr.h"
9#include "base/prefs/pref_notifier_impl.h"
10#include "base/prefs/testing_pref_store.h"
11#include "base/strings/utf_string_conversions.h"
12#include "base/test/test_simple_task_runner.h"
13#include "base/thread_task_runner_handle.h"
14#include "base/time/time.h"
15#include "base/values.h"
16#include "chrome/browser/chromeos/policy/recommendation_restorer_factory.h"
17#include "chrome/browser/prefs/browser_prefs.h"
18#include "chrome/browser/prefs/pref_service_syncable.h"
19#include "chrome/common/chrome_constants.h"
20#include "chrome/common/chrome_notification_types.h"
21#include "chrome/common/pref_names.h"
22#include "chrome/test/base/testing_browser_process.h"
23#include "chrome/test/base/testing_pref_service_syncable.h"
24#include "chrome/test/base/testing_profile.h"
25#include "chrome/test/base/testing_profile_manager.h"
26#include "components/user_prefs/pref_registry_syncable.h"
27#include "content/public/browser/notification_details.h"
28#include "content/public/browser/notification_service.h"
29#include "content/public/browser/notification_source.h"
30#include "testing/gtest/include/gtest/gtest.h"
31
32namespace policy {
33
34namespace {
35  // The amount of idle time after which recommended values are restored.
36  const int kRestoreDelayInMs = 60 * 1000;  // 1 minute.
37}  // namespace
38
39class RecommendationRestorerTest : public testing::Test {
40 protected:
41  RecommendationRestorerTest();
42
43  // testing::Test:
44  virtual void SetUp() OVERRIDE;
45
46  void SetRecommendedValues();
47  void SetUserSettings();
48
49  void CreateLoginProfile();
50  void CreateUserProfile();
51
52  void NotifyOfSessionStart();
53  void NotifyOfUserActivity();
54
55  void VerifyPrefFollowsUser(const char* pref_name,
56                             const base::Value& expected_value) const;
57  void VerifyPrefsFollowUser() const;
58  void VerifyPrefFollowsRecommendation(const char* pref_name,
59                                       const base::Value& expected_value) const;
60  void VerifyPrefsFollowRecommendations() const;
61
62  void VerifyNotListeningForNotifications() const;
63  void VerifyTimerIsStopped() const;
64  void VerifyTimerIsRunning() const;
65
66  TestingPrefStore* recommended_prefs_;  // Not owned.
67  TestingPrefServiceSyncable* prefs_;    // Not owned.
68  RecommendationRestorer* restorer_;     // Not owned.
69
70  scoped_refptr<base::TestSimpleTaskRunner> runner_;
71  base::ThreadTaskRunnerHandle runner_handler_;
72
73 private:
74  scoped_ptr<PrefServiceSyncable> prefs_owner_;
75
76  TestingProfileManager profile_manager_;
77
78  DISALLOW_COPY_AND_ASSIGN(RecommendationRestorerTest);
79};
80
81RecommendationRestorerTest::RecommendationRestorerTest()
82    : recommended_prefs_(new TestingPrefStore),
83      prefs_(new TestingPrefServiceSyncable(
84          new TestingPrefStore,
85          new TestingPrefStore,
86          recommended_prefs_,
87          new user_prefs::PrefRegistrySyncable,
88          new PrefNotifierImpl)),
89      restorer_(NULL),
90      runner_(new base::TestSimpleTaskRunner),
91      runner_handler_(runner_),
92      prefs_owner_(prefs_),
93      profile_manager_(TestingBrowserProcess::GetGlobal()) {
94  chrome::RegisterUserPrefs(prefs_->registry());
95}
96
97void RecommendationRestorerTest::SetUp() {
98  testing::Test::SetUp();
99  ASSERT_TRUE(profile_manager_.SetUp());
100}
101
102void RecommendationRestorerTest::SetRecommendedValues() {
103  recommended_prefs_->SetBoolean(prefs::kLargeCursorEnabled, false);
104  recommended_prefs_->SetBoolean(prefs::kSpokenFeedbackEnabled, false);
105  recommended_prefs_->SetBoolean(prefs::kHighContrastEnabled, false);
106  recommended_prefs_->SetBoolean(prefs::kScreenMagnifierEnabled, false);
107  recommended_prefs_->SetInteger(prefs::kScreenMagnifierType, 0);
108}
109
110void RecommendationRestorerTest::SetUserSettings() {
111  prefs_->SetBoolean(prefs::kLargeCursorEnabled, true);
112  prefs_->SetBoolean(prefs::kSpokenFeedbackEnabled, true);
113  prefs_->SetBoolean(prefs::kHighContrastEnabled, true);
114  prefs_->SetBoolean(prefs::kScreenMagnifierEnabled, true);
115  prefs_->SetInteger(prefs::kScreenMagnifierType, ash::MAGNIFIER_FULL);
116}
117
118void RecommendationRestorerTest::CreateLoginProfile() {
119  ASSERT_FALSE(restorer_);
120  TestingProfile* profile = profile_manager_.CreateTestingProfile(
121      chrome::kInitialProfile, prefs_owner_.Pass(),
122      UTF8ToUTF16(chrome::kInitialProfile), 0);
123  restorer_ = RecommendationRestorerFactory::GetForProfile(profile);
124  EXPECT_TRUE(restorer_);
125}
126
127void RecommendationRestorerTest::CreateUserProfile() {
128  ASSERT_FALSE(restorer_);
129  TestingProfile* profile = profile_manager_.CreateTestingProfile(
130      "user", prefs_owner_.Pass(), UTF8ToUTF16("user"), 0);
131  restorer_ = RecommendationRestorerFactory::GetForProfile(profile);
132  EXPECT_TRUE(restorer_);
133}
134
135void RecommendationRestorerTest::NotifyOfSessionStart() {
136  ASSERT_TRUE(restorer_);
137  restorer_->Observe(chrome::NOTIFICATION_LOGIN_USER_CHANGED,
138                     content::Source<RecommendationRestorerTest>(this),
139                     content::NotificationService::NoDetails());
140}
141
142void RecommendationRestorerTest::NotifyOfUserActivity() {
143  ASSERT_TRUE(restorer_);
144  restorer_->OnUserActivity();
145}
146
147void RecommendationRestorerTest::VerifyPrefFollowsUser(
148    const char* pref_name,
149    const base::Value& expected_value) const {
150  const PrefServiceSyncable::Preference* pref =
151      prefs_->FindPreference(pref_name);
152  ASSERT_TRUE(pref);
153  EXPECT_TRUE(pref->HasUserSetting());
154  const base::Value* value = pref->GetValue();
155  ASSERT_TRUE(value);
156  EXPECT_TRUE(expected_value.Equals(value));
157}
158
159void RecommendationRestorerTest::VerifyPrefsFollowUser() const {
160  VerifyPrefFollowsUser(prefs::kLargeCursorEnabled,
161                        base::FundamentalValue(true));
162  VerifyPrefFollowsUser(prefs::kSpokenFeedbackEnabled,
163                        base::FundamentalValue(true));
164  VerifyPrefFollowsUser(prefs::kHighContrastEnabled,
165                        base::FundamentalValue(true));
166  VerifyPrefFollowsUser(prefs::kScreenMagnifierEnabled,
167                        base::FundamentalValue(true));
168  VerifyPrefFollowsUser(prefs::kScreenMagnifierType,
169                        base::FundamentalValue(ash::MAGNIFIER_FULL));
170}
171
172void RecommendationRestorerTest::VerifyPrefFollowsRecommendation(
173    const char* pref_name,
174    const base::Value& expected_value) const {
175  const PrefServiceSyncable::Preference* pref =
176      prefs_->FindPreference(pref_name);
177  ASSERT_TRUE(pref);
178  EXPECT_TRUE(pref->IsRecommended());
179  EXPECT_FALSE(pref->HasUserSetting());
180  const base::Value* value = pref->GetValue();
181  ASSERT_TRUE(value);
182  EXPECT_TRUE(expected_value.Equals(value));
183}
184
185void RecommendationRestorerTest::VerifyPrefsFollowRecommendations() const {
186  VerifyPrefFollowsRecommendation(prefs::kLargeCursorEnabled,
187                                  base::FundamentalValue(false));
188  VerifyPrefFollowsRecommendation(prefs::kSpokenFeedbackEnabled,
189                                  base::FundamentalValue(false));
190  VerifyPrefFollowsRecommendation(prefs::kHighContrastEnabled,
191                                  base::FundamentalValue(false));
192  VerifyPrefFollowsRecommendation(prefs::kScreenMagnifierEnabled,
193                                  base::FundamentalValue(false));
194  VerifyPrefFollowsRecommendation(prefs::kScreenMagnifierType,
195                                  base::FundamentalValue(0));
196}
197
198void RecommendationRestorerTest::VerifyNotListeningForNotifications() const {
199  ASSERT_TRUE(restorer_);
200  EXPECT_TRUE(restorer_->pref_change_registrar_.IsEmpty());
201  EXPECT_TRUE(restorer_->notification_registrar_.IsEmpty());
202}
203
204void RecommendationRestorerTest::VerifyTimerIsStopped() const {
205  ASSERT_TRUE(restorer_);
206  EXPECT_FALSE(restorer_->restore_timer_.IsRunning());
207}
208
209void RecommendationRestorerTest::VerifyTimerIsRunning() const {
210  ASSERT_TRUE(restorer_);
211  EXPECT_TRUE(restorer_->restore_timer_.IsRunning());
212  EXPECT_EQ(base::TimeDelta::FromMilliseconds(kRestoreDelayInMs),
213            restorer_->restore_timer_.GetCurrentDelay());
214}
215
216TEST_F(RecommendationRestorerTest, CreateForUserProfile) {
217  // Verifies that when a RecommendationRestorer is created for a user profile,
218  // it does not start listening for any notifications, does not clear user
219  // settings on initialization and does not start a timer that will clear user
220  // settings eventually.
221  SetRecommendedValues();
222  SetUserSettings();
223
224  CreateUserProfile();
225  VerifyNotListeningForNotifications();
226  VerifyPrefsFollowUser();
227  VerifyTimerIsStopped();
228}
229
230TEST_F(RecommendationRestorerTest, NoRecommendations) {
231  // Verifies that when no recommended values have been set and a
232  // RecommendationRestorer is created for the login profile, it does not clear
233  // user settings on initialization and does not start a timer that will clear
234  // user settings eventually.
235  SetUserSettings();
236
237  CreateLoginProfile();
238  VerifyPrefsFollowUser();
239  VerifyTimerIsStopped();
240}
241
242TEST_F(RecommendationRestorerTest, RestoreOnStartup) {
243  // Verifies that when recommended values have been set and a
244  // RecommendationRestorer is created for the login profile, it clears user
245  // settings on initialization.
246  SetRecommendedValues();
247  SetUserSettings();
248
249  CreateLoginProfile();
250  VerifyPrefsFollowRecommendations();
251  VerifyTimerIsStopped();
252}
253
254TEST_F(RecommendationRestorerTest, RestoreOnRecommendationChangeOnLoginScreen) {
255  // Verifies that if recommended values change while the login screen is being
256  // shown, a timer is started that will clear user settings eventually.
257  SetUserSettings();
258
259  CreateLoginProfile();
260
261  VerifyTimerIsStopped();
262  recommended_prefs_->SetBoolean(prefs::kLargeCursorEnabled, false);
263  VerifyPrefFollowsUser(prefs::kLargeCursorEnabled,
264                        base::FundamentalValue(true));
265  VerifyTimerIsRunning();
266  runner_->RunUntilIdle();
267  VerifyPrefFollowsRecommendation(prefs::kLargeCursorEnabled,
268                                  base::FundamentalValue(false));
269
270  VerifyTimerIsStopped();
271  recommended_prefs_->SetBoolean(prefs::kSpokenFeedbackEnabled, false);
272  VerifyPrefFollowsUser(prefs::kSpokenFeedbackEnabled,
273                        base::FundamentalValue(true));
274  VerifyTimerIsRunning();
275  runner_->RunUntilIdle();
276  VerifyPrefFollowsRecommendation(prefs::kSpokenFeedbackEnabled,
277                                  base::FundamentalValue(false));
278
279  VerifyTimerIsStopped();
280  recommended_prefs_->SetBoolean(prefs::kHighContrastEnabled, false);
281  VerifyPrefFollowsUser(prefs::kHighContrastEnabled,
282                        base::FundamentalValue(true));
283  VerifyTimerIsRunning();
284  runner_->RunUntilIdle();
285  VerifyPrefFollowsRecommendation(prefs::kHighContrastEnabled,
286                                  base::FundamentalValue(false));
287
288  VerifyTimerIsStopped();
289  recommended_prefs_->SetBoolean(prefs::kScreenMagnifierEnabled, false);
290  recommended_prefs_->SetInteger(prefs::kScreenMagnifierType, 0);
291  VerifyPrefFollowsUser(prefs::kScreenMagnifierEnabled,
292                        base::FundamentalValue(true));
293  VerifyPrefFollowsUser(prefs::kScreenMagnifierType,
294                        base::FundamentalValue(ash::MAGNIFIER_FULL));
295  VerifyTimerIsRunning();
296  runner_->RunUntilIdle();
297  VerifyPrefFollowsRecommendation(prefs::kScreenMagnifierEnabled,
298                                  base::FundamentalValue(false));
299  VerifyPrefFollowsRecommendation(prefs::kScreenMagnifierType,
300                                  base::FundamentalValue(0));
301
302  VerifyTimerIsStopped();
303}
304
305TEST_F(RecommendationRestorerTest, RestoreOnRecommendationChangeInUserSession) {
306  // Verifies that if recommended values change while a user session is in
307  // progress, user settings are cleared immediately.
308  SetUserSettings();
309
310  CreateLoginProfile();
311  NotifyOfSessionStart();
312
313  VerifyPrefFollowsUser(prefs::kLargeCursorEnabled,
314                        base::FundamentalValue(true));
315  recommended_prefs_->SetBoolean(prefs::kLargeCursorEnabled, false);
316  VerifyTimerIsStopped();
317  VerifyPrefFollowsRecommendation(prefs::kLargeCursorEnabled,
318                                  base::FundamentalValue(false));
319
320  VerifyPrefFollowsUser(prefs::kSpokenFeedbackEnabled,
321                        base::FundamentalValue(true));
322  recommended_prefs_->SetBoolean(prefs::kSpokenFeedbackEnabled, false);
323  VerifyTimerIsStopped();
324  VerifyPrefFollowsRecommendation(prefs::kSpokenFeedbackEnabled,
325                                  base::FundamentalValue(false));
326
327  VerifyPrefFollowsUser(prefs::kHighContrastEnabled,
328                        base::FundamentalValue(true));
329  recommended_prefs_->SetBoolean(prefs::kHighContrastEnabled, false);
330  VerifyTimerIsStopped();
331  VerifyPrefFollowsRecommendation(prefs::kHighContrastEnabled,
332                                  base::FundamentalValue(false));
333
334  VerifyPrefFollowsUser(prefs::kScreenMagnifierEnabled,
335                        base::FundamentalValue(true));
336  VerifyPrefFollowsUser(prefs::kScreenMagnifierType,
337                        base::FundamentalValue(ash::MAGNIFIER_FULL));
338  recommended_prefs_->SetBoolean(prefs::kScreenMagnifierEnabled, false);
339  recommended_prefs_->SetInteger(prefs::kScreenMagnifierType, 0);
340  VerifyTimerIsStopped();
341  VerifyPrefFollowsRecommendation(prefs::kScreenMagnifierEnabled,
342                                  base::FundamentalValue(false));
343  VerifyPrefFollowsRecommendation(prefs::kScreenMagnifierType,
344                                  base::FundamentalValue(0));
345}
346
347TEST_F(RecommendationRestorerTest, DoNothingOnUserChange) {
348  // Verifies that if no recommended values have been set and user settings
349  // change, the user settings are not cleared immediately and no timer is
350  // started that will clear the user settings eventually.
351  CreateLoginProfile();
352
353  prefs_->SetBoolean(prefs::kLargeCursorEnabled, true);
354  VerifyPrefFollowsUser(prefs::kLargeCursorEnabled,
355                        base::FundamentalValue(true));
356  VerifyTimerIsStopped();
357
358  prefs_->SetBoolean(prefs::kSpokenFeedbackEnabled, true);
359  VerifyPrefFollowsUser(prefs::kSpokenFeedbackEnabled,
360                        base::FundamentalValue(true));
361  VerifyTimerIsStopped();
362
363  prefs_->SetBoolean(prefs::kHighContrastEnabled, true);
364  VerifyPrefFollowsUser(prefs::kHighContrastEnabled,
365                        base::FundamentalValue(true));
366  VerifyTimerIsStopped();
367
368  prefs_->SetBoolean(prefs::kScreenMagnifierEnabled, true);
369  VerifyPrefFollowsUser(prefs::kScreenMagnifierEnabled,
370                        base::FundamentalValue(true));
371  VerifyTimerIsStopped();
372
373  prefs_->SetBoolean(prefs::kScreenMagnifierEnabled, true);
374  prefs_->SetInteger(prefs::kScreenMagnifierType, ash::MAGNIFIER_FULL);
375  VerifyPrefFollowsUser(prefs::kScreenMagnifierEnabled,
376                        base::FundamentalValue(true));
377  VerifyPrefFollowsUser(prefs::kScreenMagnifierType,
378                        base::FundamentalValue(ash::MAGNIFIER_FULL));
379  VerifyTimerIsStopped();
380}
381
382TEST_F(RecommendationRestorerTest, RestoreOnUserChange) {
383  // Verifies that if recommended values have been set and user settings change
384  // while the login screen is being shown, a timer is started that will clear
385  // the user settings eventually.
386  SetRecommendedValues();
387
388  CreateLoginProfile();
389
390  VerifyTimerIsStopped();
391  prefs_->SetBoolean(prefs::kLargeCursorEnabled, true);
392  VerifyPrefFollowsUser(prefs::kLargeCursorEnabled,
393                        base::FundamentalValue(true));
394  VerifyTimerIsRunning();
395  runner_->RunUntilIdle();
396  VerifyPrefFollowsRecommendation(prefs::kLargeCursorEnabled,
397                                  base::FundamentalValue(false));
398
399  VerifyTimerIsStopped();
400  prefs_->SetBoolean(prefs::kSpokenFeedbackEnabled, true);
401  VerifyPrefFollowsUser(prefs::kSpokenFeedbackEnabled,
402                        base::FundamentalValue(true));
403  VerifyTimerIsRunning();
404  runner_->RunUntilIdle();
405  VerifyPrefFollowsRecommendation(prefs::kSpokenFeedbackEnabled,
406                                  base::FundamentalValue(false));
407
408  VerifyTimerIsStopped();
409  prefs_->SetBoolean(prefs::kHighContrastEnabled, true);
410  VerifyPrefFollowsUser(prefs::kHighContrastEnabled,
411                        base::FundamentalValue(true));
412  VerifyTimerIsRunning();
413  runner_->RunUntilIdle();
414  VerifyPrefFollowsRecommendation(prefs::kHighContrastEnabled,
415                                  base::FundamentalValue(false));
416
417  VerifyTimerIsStopped();
418  prefs_->SetBoolean(prefs::kScreenMagnifierEnabled, true);
419  prefs_->SetInteger(prefs::kScreenMagnifierType, ash::MAGNIFIER_FULL);
420  VerifyPrefFollowsUser(prefs::kScreenMagnifierEnabled,
421                        base::FundamentalValue(true));
422  VerifyPrefFollowsUser(prefs::kScreenMagnifierType,
423                        base::FundamentalValue(ash::MAGNIFIER_FULL));
424  VerifyTimerIsRunning();
425  runner_->RunUntilIdle();
426  VerifyPrefFollowsRecommendation(prefs::kScreenMagnifierEnabled,
427                                  base::FundamentalValue(false));
428  VerifyPrefFollowsRecommendation(prefs::kScreenMagnifierType,
429                                  base::FundamentalValue(0));
430
431  VerifyTimerIsStopped();
432}
433
434TEST_F(RecommendationRestorerTest, RestoreOnSessionStart) {
435  // Verifies that if recommended values have been set, user settings have
436  // changed and a session is then started, the user settings are cleared
437  // immediately and the timer that would have cleared them eventually on the
438  // login screen is stopped.
439  SetRecommendedValues();
440
441  CreateLoginProfile();
442  SetUserSettings();
443
444  NotifyOfSessionStart();
445  VerifyPrefsFollowRecommendations();
446  VerifyTimerIsStopped();
447}
448
449TEST_F(RecommendationRestorerTest, DoNothingOnSessionStart) {
450  // Verifies that if recommended values have not been set, user settings have
451  // changed and a session is then started, the user settings are not cleared
452  // immediately.
453  CreateLoginProfile();
454  SetUserSettings();
455
456  NotifyOfSessionStart();
457  VerifyPrefsFollowUser();
458  VerifyTimerIsStopped();
459}
460
461TEST_F(RecommendationRestorerTest, UserActivityResetsTimer) {
462  // Verifies that user activity resets the timer which clears user settings.
463  recommended_prefs_->SetBoolean(prefs::kLargeCursorEnabled, false);
464
465  CreateLoginProfile();
466
467  prefs_->SetBoolean(prefs::kLargeCursorEnabled, true);
468  VerifyTimerIsRunning();
469
470  // Notify that there is user activity, then fast forward until the originally
471  // set timer fires.
472  NotifyOfUserActivity();
473  runner_->RunPendingTasks();
474  VerifyPrefFollowsUser(prefs::kLargeCursorEnabled,
475                        base::FundamentalValue(true));
476
477  // Fast forward until the reset timer fires.
478  VerifyTimerIsRunning();
479  runner_->RunUntilIdle();
480  VerifyPrefFollowsRecommendation(prefs::kLargeCursorEnabled,
481                                  base::FundamentalValue(false));
482  VerifyTimerIsStopped();
483}
484
485}  // namespace policy
486