1// Copyright 2014 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 <sys/types.h>
6
7#include "ash/shell.h"
8#include "base/compiler_specific.h"
9#include "base/macros.h"
10#include "base/prefs/pref_service.h"
11#include "chrome/browser/browser_process.h"
12#include "chrome/browser/chromeos/input_method/input_method_manager_impl.h"
13#include "chrome/browser/chromeos/login/login_manager_test.h"
14#include "chrome/browser/chromeos/login/startup_utils.h"
15#include "chrome/browser/chromeos/login/ui/user_adding_screen.h"
16#include "chrome/browser/chromeos/preferences.h"
17#include "chrome/browser/chromeos/profiles/profile_helper.h"
18#include "chrome/browser/chromeos/settings/cros_settings.h"
19#include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h"
20#include "chrome/browser/chromeos/system/fake_input_device_settings.h"
21#include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h"
22#include "chrome/common/pref_names.h"
23#include "chromeos/chromeos_switches.h"
24#include "chromeos/ime/fake_ime_keyboard.h"
25#include "components/feedback/tracing_manager.h"
26#include "components/user_manager/user_manager.h"
27#include "content/public/test/test_utils.h"
28#include "testing/gtest/include/gtest/gtest.h"
29#include "ui/events/event_utils.h"
30
31namespace chromeos {
32
33namespace {
34
35const char* kTestUsers[] = {"test-user1@gmail.com", "test-user2@gmail.com"};
36
37}  // namespace
38
39class PreferencesTest : public LoginManagerTest {
40 public:
41  PreferencesTest()
42      : LoginManagerTest(true),
43        input_settings_(NULL),
44        keyboard_(NULL) {}
45
46  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
47    LoginManagerTest::SetUpCommandLine(command_line);
48    command_line->AppendSwitch(switches::kStubCrosSettings);
49  }
50
51  virtual void SetUpOnMainThread() OVERRIDE {
52    LoginManagerTest::SetUpOnMainThread();
53    input_settings_ = new system::FakeInputDeviceSettings();
54    system::InputDeviceSettings::SetSettingsForTesting(input_settings_);
55    keyboard_ = new input_method::FakeImeKeyboard();
56    static_cast<input_method::InputMethodManagerImpl*>(
57        input_method::InputMethodManager::Get())
58        ->SetImeKeyboardForTesting(keyboard_);
59    CrosSettings::Get()->SetString(kDeviceOwner, kTestUsers[0]);
60  }
61
62  // Sets set of preferences in given |prefs|. Value of prefernece depends of
63  // |variant| value. For opposite |variant| values all preferences receive
64  // different values.
65  void SetPrefs(PrefService* prefs, bool variant) {
66    prefs->SetBoolean(prefs::kTapToClickEnabled, variant);
67    prefs->SetBoolean(prefs::kPrimaryMouseButtonRight, !variant);
68    prefs->SetBoolean(prefs::kTapDraggingEnabled, variant);
69    prefs->SetBoolean(prefs::kEnableTouchpadThreeFingerClick, !variant);
70    prefs->SetBoolean(prefs::kNaturalScroll, variant);
71    prefs->SetInteger(prefs::kMouseSensitivity, !variant);
72    prefs->SetInteger(prefs::kTouchpadSensitivity, variant);
73    prefs->SetBoolean(prefs::kTouchHudProjectionEnabled, !variant);
74    prefs->SetBoolean(prefs::kLanguageXkbAutoRepeatEnabled, variant);
75    prefs->SetInteger(prefs::kLanguageXkbAutoRepeatDelay, variant ? 100 : 500);
76    prefs->SetInteger(prefs::kLanguageXkbAutoRepeatInterval, variant ? 1 : 4);
77    prefs->SetString(prefs::kLanguagePreloadEngines,
78                     variant ? "xkb:us::eng,xkb:us:dvorak:eng"
79                             : "xkb:us::eng,xkb:ru::rus");
80  }
81
82  void CheckSettingsCorrespondToPrefs(PrefService* prefs) {
83    EXPECT_EQ(prefs->GetBoolean(prefs::kTapToClickEnabled),
84              input_settings_->current_touchpad_settings().GetTapToClick());
85    EXPECT_EQ(prefs->GetBoolean(prefs::kPrimaryMouseButtonRight),
86              input_settings_->current_mouse_settings()
87                  .GetPrimaryButtonRight());
88    EXPECT_EQ(prefs->GetBoolean(prefs::kTapDraggingEnabled),
89              input_settings_->current_touchpad_settings().GetTapDragging());
90    EXPECT_EQ(prefs->GetBoolean(prefs::kEnableTouchpadThreeFingerClick),
91              input_settings_->current_touchpad_settings()
92                  .GetThreeFingerClick());
93    EXPECT_EQ(prefs->GetInteger(prefs::kMouseSensitivity),
94              input_settings_->current_mouse_settings().GetSensitivity());
95    EXPECT_EQ(prefs->GetInteger(prefs::kTouchpadSensitivity),
96              input_settings_->current_touchpad_settings().GetSensitivity());
97    EXPECT_EQ(prefs->GetBoolean(prefs::kTouchHudProjectionEnabled),
98              ash::Shell::GetInstance()->is_touch_hud_projection_enabled());
99    EXPECT_EQ(prefs->GetBoolean(prefs::kLanguageXkbAutoRepeatEnabled),
100              keyboard_->auto_repeat_is_enabled_);
101    input_method::AutoRepeatRate rate = keyboard_->last_auto_repeat_rate_;
102    EXPECT_EQ(prefs->GetInteger(prefs::kLanguageXkbAutoRepeatDelay),
103              (int)rate.initial_delay_in_ms);
104    EXPECT_EQ(prefs->GetInteger(prefs::kLanguageXkbAutoRepeatInterval),
105              (int)rate.repeat_interval_in_ms);
106    EXPECT_EQ(prefs->GetString(prefs::kLanguageCurrentInputMethod),
107              input_method::InputMethodManager::Get()
108                  ->GetActiveIMEState()
109                  ->GetCurrentInputMethod()
110                  .id());
111  }
112
113  void CheckLocalStateCorrespondsToPrefs(PrefService* prefs) {
114    PrefService* local_state = g_browser_process->local_state();
115    EXPECT_EQ(local_state->GetBoolean(prefs::kOwnerTapToClickEnabled),
116              prefs->GetBoolean(prefs::kTapToClickEnabled));
117    EXPECT_EQ(local_state->GetBoolean(prefs::kOwnerPrimaryMouseButtonRight),
118              prefs->GetBoolean(prefs::kPrimaryMouseButtonRight));
119  }
120
121  void DisableAnimations() {
122    // Disable animations for user transitions.
123    chrome::MultiUserWindowManagerChromeOS* manager =
124        static_cast<chrome::MultiUserWindowManagerChromeOS*>(
125            chrome::MultiUserWindowManager::GetInstance());
126    manager->SetAnimationSpeedForTest(
127        chrome::MultiUserWindowManagerChromeOS::ANIMATION_SPEED_DISABLED);
128  }
129
130 private:
131  system::FakeInputDeviceSettings* input_settings_;
132  input_method::FakeImeKeyboard* keyboard_;
133
134  DISALLOW_COPY_AND_ASSIGN(PreferencesTest);
135};
136
137IN_PROC_BROWSER_TEST_F(PreferencesTest, PRE_MultiProfiles) {
138  RegisterUser(kTestUsers[0]);
139  RegisterUser(kTestUsers[1]);
140  chromeos::StartupUtils::MarkOobeCompleted();
141}
142
143IN_PROC_BROWSER_TEST_F(PreferencesTest, MultiProfiles) {
144  user_manager::UserManager* user_manager = user_manager::UserManager::Get();
145
146  // Add first user and init its preferences. Check that corresponding
147  // settings has been changed.
148  LoginUser(kTestUsers[0]);
149  const user_manager::User* user1 = user_manager->FindUser(kTestUsers[0]);
150  PrefService* prefs1 =
151      ProfileHelper::Get()->GetProfileByUserUnsafe(user1)->GetPrefs();
152  SetPrefs(prefs1, false);
153  content::RunAllPendingInMessageLoop();
154  CheckSettingsCorrespondToPrefs(prefs1);
155
156  // Add second user and init its prefs with different values.
157  UserAddingScreen::Get()->Start();
158  content::RunAllPendingInMessageLoop();
159  DisableAnimations();
160  AddUser(kTestUsers[1]);
161  content::RunAllPendingInMessageLoop();
162  const user_manager::User* user2 = user_manager->FindUser(kTestUsers[1]);
163  EXPECT_TRUE(user2->is_active());
164  PrefService* prefs2 =
165      ProfileHelper::Get()->GetProfileByUserUnsafe(user2)->GetPrefs();
166  SetPrefs(prefs2, true);
167
168  // Check that settings were changed accordingly.
169  EXPECT_TRUE(user2->is_active());
170  CheckSettingsCorrespondToPrefs(prefs2);
171
172  // Check that changing prefs of the active user doesn't affect prefs of the
173  // inactive user.
174  scoped_ptr<base::DictionaryValue> prefs_backup =
175      prefs1->GetPreferenceValues();
176  SetPrefs(prefs2, false);
177  CheckSettingsCorrespondToPrefs(prefs2);
178  EXPECT_TRUE(prefs_backup->Equals(prefs1->GetPreferenceValues().get()));
179  SetPrefs(prefs2, true);
180  CheckSettingsCorrespondToPrefs(prefs2);
181  EXPECT_TRUE(prefs_backup->Equals(prefs1->GetPreferenceValues().get()));
182
183  // Check that changing prefs of the inactive user doesn't affect prefs of the
184  // active user.
185  prefs_backup = prefs2->GetPreferenceValues();
186  SetPrefs(prefs1, true);
187  CheckSettingsCorrespondToPrefs(prefs2);
188  EXPECT_TRUE(prefs_backup->Equals(prefs2->GetPreferenceValues().get()));
189  SetPrefs(prefs1, false);
190  CheckSettingsCorrespondToPrefs(prefs2);
191  EXPECT_TRUE(prefs_backup->Equals(prefs2->GetPreferenceValues().get()));
192
193  // Check that changing non-owner prefs doesn't change corresponding local
194  // state prefs and vice versa.
195  EXPECT_EQ(user_manager->GetOwnerEmail(), kTestUsers[0]);
196  CheckLocalStateCorrespondsToPrefs(prefs1);
197  prefs2->SetBoolean(prefs::kTapToClickEnabled,
198                     !prefs1->GetBoolean(prefs::kTapToClickEnabled));
199  CheckLocalStateCorrespondsToPrefs(prefs1);
200  prefs1->SetBoolean(prefs::kTapToClickEnabled,
201                     !prefs1->GetBoolean(prefs::kTapToClickEnabled));
202  CheckLocalStateCorrespondsToPrefs(prefs1);
203
204  // Switch user back.
205  user_manager->SwitchActiveUser(kTestUsers[0]);
206  CheckSettingsCorrespondToPrefs(prefs1);
207  CheckLocalStateCorrespondsToPrefs(prefs1);
208}
209
210}  // namespace chromeos
211