1// Copyright (c) 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/accessibility/accessibility_manager.h" 6 7#include "ash/magnifier/magnification_controller.h" 8#include "ash/shell.h" 9#include "base/command_line.h" 10#include "base/prefs/pref_service.h" 11#include "chrome/browser/browser_process.h" 12#include "chrome/browser/chrome_notification_types.h" 13#include "chrome/browser/chromeos/accessibility/magnification_manager.h" 14#include "chrome/browser/chromeos/cros/cros_in_process_browser_test.h" 15#include "chrome/browser/chromeos/login/helper.h" 16#include "chrome/browser/chromeos/login/login_utils.h" 17#include "chrome/browser/chromeos/login/user_manager.h" 18#include "chrome/browser/chromeos/login/user_manager_impl.h" 19#include "chrome/browser/chromeos/profiles/profile_helper.h" 20#include "chrome/browser/profiles/profile.h" 21#include "chrome/browser/profiles/profile_manager.h" 22#include "chrome/common/pref_names.h" 23#include "chrome/test/base/testing_profile.h" 24#include "chromeos/chromeos_switches.h" 25#include "content/public/browser/notification_service.h" 26#include "testing/gtest/include/gtest/gtest.h" 27 28namespace chromeos { 29 30namespace { 31 32const char kTestUserName[] = "owner@invalid.domain"; 33 34// Test user name for locally managed user. The domain part must be matched 35// with UserManager::kLocallyManagedUserDomain. 36const char kTestLocallyManagedUserName[] = "test@locally-managed.localhost"; 37 38class MockAccessibilityObserver : public content::NotificationObserver { 39 public: 40 MockAccessibilityObserver() : observed_(false), 41 observed_enabled_(false), 42 observed_type_(-1) { 43 registrar_.Add( 44 this, 45 chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_SPOKEN_FEEDBACK, 46 content::NotificationService::AllSources()); 47 registrar_.Add( 48 this, 49 chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_HIGH_CONTRAST_MODE, 50 content::NotificationService::AllSources()); 51 } 52 virtual ~MockAccessibilityObserver() {} 53 54 bool observed() const { return observed_; } 55 bool observed_enabled() const { return observed_enabled_; } 56 int observed_type() const { return observed_type_; } 57 58 void reset() { observed_ = false; } 59 60 private: 61 // content::NotificationObserver implimentation: 62 virtual void Observe(int type, 63 const content::NotificationSource& source, 64 const content::NotificationDetails& details) OVERRIDE { 65 AccessibilityStatusEventDetails* accessibility_status = 66 content::Details<AccessibilityStatusEventDetails>( 67 details).ptr(); 68 ASSERT_FALSE(observed_); 69 70 switch (type) { 71 case chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_SPOKEN_FEEDBACK: 72 observed_ = true; 73 observed_enabled_ = accessibility_status->enabled; 74 observed_type_ = type; 75 break; 76 case chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_HIGH_CONTRAST_MODE: 77 observed_ = true; 78 observed_enabled_ = accessibility_status->enabled; 79 observed_type_ = type; 80 break; 81 } 82 } 83 84 bool observed_; 85 bool observed_enabled_; 86 int observed_type_; 87 88 content::NotificationRegistrar registrar_; 89 90 DISALLOW_COPY_AND_ASSIGN(MockAccessibilityObserver); 91}; 92 93void SetLargeCursorEnabled(bool enabled) { 94 return AccessibilityManager::Get()->EnableLargeCursor(enabled); 95} 96 97bool IsLargeCursorEnabled() { 98 return AccessibilityManager::Get()->IsLargeCursorEnabled(); 99} 100 101void SetHighContrastEnabled(bool enabled) { 102 return AccessibilityManager::Get()->EnableHighContrast(enabled); 103} 104 105bool IsHighContrastEnabled() { 106 return AccessibilityManager::Get()->IsHighContrastEnabled(); 107} 108 109void SetSpokenFeedbackEnabled(bool enabled) { 110 return AccessibilityManager::Get()->EnableSpokenFeedback( 111 enabled, ash::A11Y_NOTIFICATION_NONE); 112} 113 114bool IsSpokenFeedbackEnabled() { 115 return AccessibilityManager::Get()->IsSpokenFeedbackEnabled(); 116} 117 118Profile* GetProfile() { 119 Profile* profile = ProfileManager::GetDefaultProfileOrOffTheRecord(); 120 DCHECK(profile); 121 return profile; 122} 123 124PrefService* GetPrefs() { 125 return GetProfile()->GetPrefs(); 126} 127 128void SetLargeCursorEnabledPref(bool enabled) { 129 GetPrefs()->SetBoolean(prefs::kLargeCursorEnabled, enabled); 130} 131 132void SetHighContrastEnabledPref(bool enabled) { 133 GetPrefs()->SetBoolean(prefs::kHighContrastEnabled, enabled); 134} 135 136void SetSpokenFeedbackEnabledPref(bool enabled) { 137 GetPrefs()->SetBoolean(prefs::kSpokenFeedbackEnabled, enabled); 138} 139 140bool GetLargeCursorEnabledFromPref() { 141 return GetPrefs()->GetBoolean(prefs::kLargeCursorEnabled); 142} 143 144bool GetHighContrastEnabledFromPref() { 145 return GetPrefs()->GetBoolean(prefs::kHighContrastEnabled); 146} 147 148bool GetSpokenFeedbackEnabledFromPref() { 149 return GetPrefs()->GetBoolean(prefs::kSpokenFeedbackEnabled); 150} 151 152} // anonymouse namespace 153 154class AccessibilityManagerTest : public CrosInProcessBrowserTest { 155 protected: 156 AccessibilityManagerTest() {} 157 virtual ~AccessibilityManagerTest() {} 158 159 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 160 command_line->AppendSwitch(chromeos::switches::kLoginManager); 161 command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile, 162 TestingProfile::kTestUserProfileDir); 163 } 164 165 virtual void SetUpOnMainThread() OVERRIDE { 166 // Sets the login-screen profile. 167 AccessibilityManager::Get()-> 168 SetProfileForTest(ProfileHelper::GetSigninProfile()); 169 } 170 171 content::NotificationRegistrar registrar_; 172 DISALLOW_COPY_AND_ASSIGN(AccessibilityManagerTest); 173}; 174 175IN_PROC_BROWSER_TEST_F(AccessibilityManagerTest, Login) { 176 // Confirms that a11y features are disabled on the login screen. 177 EXPECT_FALSE(IsLargeCursorEnabled()); 178 EXPECT_FALSE(IsSpokenFeedbackEnabled()); 179 EXPECT_FALSE(IsHighContrastEnabled()); 180 181 // Logs in. 182 UserManager::Get()->UserLoggedIn(kTestUserName, kTestUserName, true); 183 184 // Confirms that the features still disabled just after login. 185 EXPECT_FALSE(IsLargeCursorEnabled()); 186 EXPECT_FALSE(IsSpokenFeedbackEnabled()); 187 EXPECT_FALSE(IsHighContrastEnabled()); 188 189 UserManager::Get()->SessionStarted(); 190 191 // Confirms that the features are still disabled just after login. 192 EXPECT_FALSE(IsLargeCursorEnabled()); 193 EXPECT_FALSE(IsSpokenFeedbackEnabled()); 194 EXPECT_FALSE(IsHighContrastEnabled()); 195 196 // Enables large cursor. 197 SetLargeCursorEnabled(true); 198 // Confirms that large cursor is enabled. 199 EXPECT_TRUE(IsLargeCursorEnabled()); 200 201 // Enables spoken feedback. 202 SetSpokenFeedbackEnabled(true); 203 // Confirms that the spoken feedback is enabled. 204 EXPECT_TRUE(IsSpokenFeedbackEnabled()); 205 206 // Enables high contrast. 207 SetHighContrastEnabled(true); 208 // Confirms that high cotrast is enabled. 209 EXPECT_TRUE(IsHighContrastEnabled()); 210} 211 212IN_PROC_BROWSER_TEST_F(AccessibilityManagerTest, TypePref) { 213 // Logs in. 214 UserManager::Get()->UserLoggedIn(kTestUserName, kTestUserName, true); 215 UserManager::Get()->SessionStarted(); 216 217 // Confirms that the features are disabled just after login. 218 EXPECT_FALSE(IsLargeCursorEnabled()); 219 EXPECT_FALSE(IsSpokenFeedbackEnabled()); 220 EXPECT_FALSE(IsHighContrastEnabled()); 221 222 // Sets the pref as true to enable the large cursor. 223 SetLargeCursorEnabledPref(true); 224 // Confirms that the large cursor is enabled. 225 EXPECT_TRUE(IsLargeCursorEnabled()); 226 227 // Sets the pref as true to enable the spoken feedback. 228 SetSpokenFeedbackEnabledPref(true); 229 // Confirms that the spoken feedback is enabled. 230 EXPECT_TRUE(IsSpokenFeedbackEnabled()); 231 232 // Enables the high contrast mode. 233 SetHighContrastEnabled(true); 234 // Confirms that the high contrast mode is enabled. 235 EXPECT_TRUE(IsHighContrastEnabled()); 236 237 SetLargeCursorEnabledPref(false); 238 EXPECT_FALSE(IsLargeCursorEnabled()); 239 240 SetSpokenFeedbackEnabledPref(false); 241 EXPECT_FALSE(IsSpokenFeedbackEnabled()); 242 243 SetHighContrastEnabledPref(false); 244 EXPECT_FALSE(IsHighContrastEnabled()); 245} 246 247IN_PROC_BROWSER_TEST_F(AccessibilityManagerTest, ResumeSavedPref) { 248 // Loads the profile of the user. 249 UserManager::Get()->UserLoggedIn(kTestUserName, kTestUserName, true); 250 251 // Sets the pref to enable large cursor before login. 252 SetLargeCursorEnabledPref(true); 253 EXPECT_FALSE(IsLargeCursorEnabled()); 254 255 // Sets the pref to enable spoken feedback before login. 256 SetSpokenFeedbackEnabledPref(true); 257 EXPECT_FALSE(IsSpokenFeedbackEnabled()); 258 259 // Sets the pref to enable high contrast before login. 260 SetHighContrastEnabledPref(true); 261 EXPECT_FALSE(IsHighContrastEnabled()); 262 263 // Logs in. 264 UserManager::Get()->SessionStarted(); 265 266 // Confirms that features are enabled by restring from pref just after login. 267 EXPECT_TRUE(IsLargeCursorEnabled()); 268 EXPECT_TRUE(IsSpokenFeedbackEnabled()); 269 EXPECT_TRUE(IsHighContrastEnabled()); 270} 271 272IN_PROC_BROWSER_TEST_F(AccessibilityManagerTest, 273 ChangingTypeInvokesNotification) { 274 MockAccessibilityObserver observer; 275 276 // Logs in. 277 UserManager::Get()->UserLoggedIn(kTestUserName, kTestUserName, true); 278 UserManager::Get()->SessionStarted(); 279 280 EXPECT_FALSE(observer.observed()); 281 observer.reset(); 282 283 SetSpokenFeedbackEnabled(true); 284 EXPECT_TRUE(observer.observed()); 285 EXPECT_TRUE(observer.observed_enabled()); 286 EXPECT_EQ(observer.observed_type(), 287 chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_SPOKEN_FEEDBACK); 288 EXPECT_TRUE(IsSpokenFeedbackEnabled()); 289 290 observer.reset(); 291 SetSpokenFeedbackEnabled(false); 292 EXPECT_TRUE(observer.observed()); 293 EXPECT_FALSE(observer.observed_enabled()); 294 EXPECT_EQ(observer.observed_type(), 295 chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_SPOKEN_FEEDBACK); 296 EXPECT_FALSE(IsSpokenFeedbackEnabled()); 297 298 observer.reset(); 299 SetHighContrastEnabled(true); 300 EXPECT_TRUE(observer.observed()); 301 EXPECT_TRUE(observer.observed_enabled()); 302 EXPECT_EQ(observer.observed_type(), 303 chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_HIGH_CONTRAST_MODE); 304 EXPECT_TRUE(IsHighContrastEnabled()); 305 306 observer.reset(); 307 SetHighContrastEnabled(false); 308 EXPECT_TRUE(observer.observed()); 309 EXPECT_FALSE(observer.observed_enabled()); 310 EXPECT_EQ(observer.observed_type(), 311 chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_HIGH_CONTRAST_MODE); 312 EXPECT_FALSE(IsHighContrastEnabled()); 313} 314 315IN_PROC_BROWSER_TEST_F(AccessibilityManagerTest, 316 ChangingTypePrefInvokesNotification) { 317 MockAccessibilityObserver observer; 318 319 // Logs in. 320 UserManager::Get()->UserLoggedIn(kTestUserName, kTestUserName, true); 321 UserManager::Get()->SessionStarted(); 322 323 EXPECT_FALSE(observer.observed()); 324 observer.reset(); 325 326 SetSpokenFeedbackEnabledPref(true); 327 EXPECT_TRUE(observer.observed()); 328 EXPECT_TRUE(observer.observed_enabled()); 329 EXPECT_EQ(observer.observed_type(), 330 chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_SPOKEN_FEEDBACK); 331 EXPECT_TRUE(IsSpokenFeedbackEnabled()); 332 333 observer.reset(); 334 SetSpokenFeedbackEnabledPref(false); 335 EXPECT_TRUE(observer.observed()); 336 EXPECT_FALSE(observer.observed_enabled()); 337 EXPECT_EQ(observer.observed_type(), 338 chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_SPOKEN_FEEDBACK); 339 EXPECT_FALSE(IsSpokenFeedbackEnabled()); 340 341 observer.reset(); 342 SetHighContrastEnabledPref(true); 343 EXPECT_TRUE(observer.observed()); 344 EXPECT_TRUE(observer.observed_enabled()); 345 EXPECT_EQ(observer.observed_type(), 346 chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_HIGH_CONTRAST_MODE); 347 EXPECT_TRUE(IsHighContrastEnabled()); 348 349 observer.reset(); 350 SetHighContrastEnabledPref(false); 351 EXPECT_TRUE(observer.observed()); 352 EXPECT_FALSE(observer.observed_enabled()); 353 EXPECT_EQ(observer.observed_type(), 354 chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_HIGH_CONTRAST_MODE); 355 EXPECT_FALSE(IsHighContrastEnabled()); 356} 357 358class AccessibilityManagerUserTypeTest 359 : public AccessibilityManagerTest, 360 public ::testing::WithParamInterface<const char*> { 361 protected: 362 AccessibilityManagerUserTypeTest() {} 363 virtual ~AccessibilityManagerUserTypeTest() {} 364 365 DISALLOW_COPY_AND_ASSIGN(AccessibilityManagerUserTypeTest); 366}; 367 368// TODO(yoshiki): Enable a test for retail mode. 369INSTANTIATE_TEST_CASE_P( 370 UserTypeInstantiation, 371 AccessibilityManagerUserTypeTest, 372 ::testing::Values(kTestUserName, 373 UserManager::kGuestUserName, 374 //UserManager::kRetailModeUserName, 375 kTestLocallyManagedUserName)); 376 377IN_PROC_BROWSER_TEST_P(AccessibilityManagerUserTypeTest, 378 EnableOnLoginScreenAndLogin) { 379 // Enables large cursor. 380 SetLargeCursorEnabled(true); 381 EXPECT_TRUE(IsLargeCursorEnabled()); 382 // Enables spoken feedback. 383 SetSpokenFeedbackEnabled(true); 384 EXPECT_TRUE(IsSpokenFeedbackEnabled()); 385 // Enables high contrast. 386 SetHighContrastEnabled(true); 387 EXPECT_TRUE(IsHighContrastEnabled()); 388 389 // Logs in. 390 const char* user_name = GetParam(); 391 UserManager::Get()->UserLoggedIn(user_name, user_name, true); 392 393 // Confirms that the features are still enabled just after login. 394 EXPECT_TRUE(IsLargeCursorEnabled()); 395 EXPECT_TRUE(IsSpokenFeedbackEnabled()); 396 EXPECT_TRUE(IsHighContrastEnabled()); 397 398 UserManager::Get()->SessionStarted(); 399 400 // Confirms that the features keep enabled after session starts. 401 EXPECT_TRUE(IsLargeCursorEnabled()); 402 EXPECT_TRUE(IsSpokenFeedbackEnabled()); 403 EXPECT_TRUE(IsHighContrastEnabled()); 404 405 // Confirms that the prefs have been copied to the user's profile. 406 EXPECT_TRUE(GetLargeCursorEnabledFromPref()); 407 EXPECT_TRUE(GetSpokenFeedbackEnabledFromPref()); 408 EXPECT_TRUE(GetHighContrastEnabledFromPref()); 409} 410 411} // namespace chromeos 412