accessibility_manager_browsertest.cc revision 1e9bf3e0803691d0a228da41fc608347b6db4340
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/login/helper.h"
15#include "chrome/browser/chromeos/login/login_utils.h"
16#include "chrome/browser/chromeos/login/user_manager.h"
17#include "chrome/browser/chromeos/login/user_manager_impl.h"
18#include "chrome/browser/chromeos/profiles/profile_helper.h"
19#include "chrome/browser/extensions/api/braille_display_private/stub_braille_controller.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/in_process_browser_test.h"
24#include "chrome/test/base/testing_profile.h"
25#include "chromeos/chromeos_switches.h"
26#include "content/public/browser/notification_service.h"
27#include "testing/gtest/include/gtest/gtest.h"
28
29using extensions::api::braille_display_private::BrailleObserver;
30using extensions::api::braille_display_private::DisplayState;
31using extensions::api::braille_display_private::StubBrailleController;
32
33namespace chromeos {
34
35namespace {
36
37const char kTestUserName[] = "owner@invalid.domain";
38
39const int kTestAutoclickDelayMs = 2000;
40
41// Test user name for locally managed user. The domain part must be matched
42// with UserManager::kLocallyManagedUserDomain.
43const char kTestLocallyManagedUserName[] = "test@locally-managed.localhost";
44
45class MockAccessibilityObserver : public content::NotificationObserver {
46 public:
47  MockAccessibilityObserver() : observed_(false),
48                                observed_enabled_(false),
49                                observed_type_(-1) {
50    registrar_.Add(
51        this,
52        chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_SPOKEN_FEEDBACK,
53        content::NotificationService::AllSources());
54    registrar_.Add(
55        this,
56        chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_HIGH_CONTRAST_MODE,
57        content::NotificationService::AllSources());
58  }
59  virtual ~MockAccessibilityObserver() {}
60
61  bool observed() const { return observed_; }
62  bool observed_enabled() const { return observed_enabled_; }
63  int observed_type() const { return observed_type_; }
64
65  void reset() { observed_ = false; }
66
67 private:
68  // content::NotificationObserver implimentation:
69  virtual void Observe(int type,
70                       const content::NotificationSource& source,
71                       const content::NotificationDetails& details) OVERRIDE {
72    AccessibilityStatusEventDetails* accessibility_status =
73        content::Details<AccessibilityStatusEventDetails>(
74            details).ptr();
75    ASSERT_FALSE(observed_);
76
77    switch (type) {
78      case chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_SPOKEN_FEEDBACK:
79        observed_ = true;
80        observed_enabled_ = accessibility_status->enabled;
81        observed_type_ = type;
82        break;
83      case chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_HIGH_CONTRAST_MODE:
84        observed_ = true;
85        observed_enabled_ = accessibility_status->enabled;
86        observed_type_ = type;
87        break;
88    }
89  }
90
91  bool observed_;
92  bool observed_enabled_;
93  int observed_type_;
94
95  content::NotificationRegistrar registrar_;
96
97  DISALLOW_COPY_AND_ASSIGN(MockAccessibilityObserver);
98};
99
100class MockBrailleController : public StubBrailleController {
101 public:
102
103  MockBrailleController() : available_(false), observer_(NULL) {}
104
105  virtual scoped_ptr<DisplayState> GetDisplayState() OVERRIDE {
106    scoped_ptr<DisplayState> state(new DisplayState());
107    state->available = available_;
108    return state.Pass();
109  }
110
111  virtual void AddObserver(BrailleObserver* observer) OVERRIDE {
112    ASSERT_EQ(NULL, observer_);
113    observer_ = observer;
114  }
115
116  virtual void RemoveObserver(BrailleObserver* observer) OVERRIDE {
117    ASSERT_EQ(observer_, observer);
118  }
119
120  void SetAvailable(bool available) {
121    available_ = available;
122  }
123
124  BrailleObserver* GetObserver() {
125    return observer_;
126  }
127
128 private:
129  bool available_;
130  BrailleObserver* observer_;
131};
132
133void SetLargeCursorEnabled(bool enabled) {
134  return AccessibilityManager::Get()->EnableLargeCursor(enabled);
135}
136
137bool IsLargeCursorEnabled() {
138  return AccessibilityManager::Get()->IsLargeCursorEnabled();
139}
140
141void SetHighContrastEnabled(bool enabled) {
142  return AccessibilityManager::Get()->EnableHighContrast(enabled);
143}
144
145bool IsHighContrastEnabled() {
146  return AccessibilityManager::Get()->IsHighContrastEnabled();
147}
148
149void SetSpokenFeedbackEnabled(bool enabled) {
150  return AccessibilityManager::Get()->EnableSpokenFeedback(
151      enabled, ash::A11Y_NOTIFICATION_NONE);
152}
153
154bool IsSpokenFeedbackEnabled() {
155  return AccessibilityManager::Get()->IsSpokenFeedbackEnabled();
156}
157
158void SetAutoclickEnabled(bool enabled) {
159  return AccessibilityManager::Get()->EnableAutoclick(enabled);
160}
161
162bool IsAutoclickEnabled() {
163  return AccessibilityManager::Get()->IsAutoclickEnabled();
164}
165
166void SetAutoclickDelay(int delay_ms) {
167  return AccessibilityManager::Get()->SetAutoclickDelay(delay_ms);
168}
169
170int GetAutoclickDelay() {
171  return AccessibilityManager::Get()->GetAutoclickDelay();
172}
173
174Profile* GetProfile() {
175  Profile* profile = ProfileManager::GetDefaultProfileOrOffTheRecord();
176  DCHECK(profile);
177  return profile;
178}
179
180PrefService* GetPrefs() {
181  return GetProfile()->GetPrefs();
182}
183
184void SetLargeCursorEnabledPref(bool enabled) {
185  GetPrefs()->SetBoolean(prefs::kLargeCursorEnabled, enabled);
186}
187
188void SetHighContrastEnabledPref(bool enabled) {
189  GetPrefs()->SetBoolean(prefs::kHighContrastEnabled, enabled);
190}
191
192void SetSpokenFeedbackEnabledPref(bool enabled) {
193  GetPrefs()->SetBoolean(prefs::kSpokenFeedbackEnabled, enabled);
194}
195
196void SetAutoclickEnabledPref(bool enabled) {
197  GetPrefs()->SetBoolean(prefs::kAutoclickEnabled, enabled);
198}
199
200void SetAutoclickDelayPref(int delay_ms) {
201  GetPrefs()->SetInteger(prefs::kAutoclickDelayMs, delay_ms);
202}
203
204bool GetLargeCursorEnabledFromPref() {
205  return GetPrefs()->GetBoolean(prefs::kLargeCursorEnabled);
206}
207
208bool GetHighContrastEnabledFromPref() {
209  return GetPrefs()->GetBoolean(prefs::kHighContrastEnabled);
210}
211
212bool GetSpokenFeedbackEnabledFromPref() {
213  return GetPrefs()->GetBoolean(prefs::kSpokenFeedbackEnabled);
214}
215
216bool GetAutoclickEnabledFromPref() {
217  return GetPrefs()->GetBoolean(prefs::kAutoclickEnabled);
218}
219
220int GetAutoclickDelayFromPref() {
221  return GetPrefs()->GetInteger(prefs::kAutoclickDelayMs);
222}
223
224}  // anonymouse namespace
225
226class AccessibilityManagerTest : public InProcessBrowserTest {
227 protected:
228  AccessibilityManagerTest() : default_autoclick_delay_(0) {}
229  virtual ~AccessibilityManagerTest() {}
230
231  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
232    command_line->AppendSwitch(chromeos::switches::kLoginManager);
233    command_line->AppendSwitchASCII(chromeos::switches::kLoginProfile,
234                                    TestingProfile::kTestUserProfileDir);
235  }
236
237  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
238    AccessibilityManager::SetBrailleControllerForTest(&braille_controller_);
239  }
240
241  virtual void SetUpOnMainThread() OVERRIDE {
242    // Sets the login-screen profile.
243    AccessibilityManager::Get()->
244        SetProfileForTest(ProfileHelper::GetSigninProfile());
245    default_autoclick_delay_ = GetAutoclickDelay();
246  }
247
248  virtual void CleanUpOnMainThread() OVERRIDE {
249    AccessibilityManager::SetBrailleControllerForTest(NULL);
250  }
251
252  int default_autoclick_delay() const { return default_autoclick_delay_; }
253
254  int default_autoclick_delay_;
255
256  content::NotificationRegistrar registrar_;
257
258  MockBrailleController braille_controller_;
259  DISALLOW_COPY_AND_ASSIGN(AccessibilityManagerTest);
260};
261
262IN_PROC_BROWSER_TEST_F(AccessibilityManagerTest, Login) {
263  // Confirms that a11y features are disabled on the login screen.
264  EXPECT_FALSE(IsLargeCursorEnabled());
265  EXPECT_FALSE(IsSpokenFeedbackEnabled());
266  EXPECT_FALSE(IsHighContrastEnabled());
267  EXPECT_FALSE(IsAutoclickEnabled());
268  EXPECT_EQ(default_autoclick_delay(), GetAutoclickDelay());
269
270  // Logs in.
271  UserManager::Get()->UserLoggedIn(kTestUserName, kTestUserName, true);
272
273  // Confirms that the features still disabled just after login.
274  EXPECT_FALSE(IsLargeCursorEnabled());
275  EXPECT_FALSE(IsSpokenFeedbackEnabled());
276  EXPECT_FALSE(IsHighContrastEnabled());
277  EXPECT_FALSE(IsAutoclickEnabled());
278  EXPECT_EQ(default_autoclick_delay(), GetAutoclickDelay());
279
280  UserManager::Get()->SessionStarted();
281
282  // Confirms that the features are still disabled just after login.
283  EXPECT_FALSE(IsLargeCursorEnabled());
284  EXPECT_FALSE(IsSpokenFeedbackEnabled());
285  EXPECT_FALSE(IsHighContrastEnabled());
286  EXPECT_FALSE(IsAutoclickEnabled());
287  EXPECT_EQ(default_autoclick_delay(), GetAutoclickDelay());
288
289  // Enables large cursor.
290  SetLargeCursorEnabled(true);
291  // Confirms that large cursor is enabled.
292  EXPECT_TRUE(IsLargeCursorEnabled());
293
294  // Enables spoken feedback.
295  SetSpokenFeedbackEnabled(true);
296  // Confirms that the spoken feedback is enabled.
297  EXPECT_TRUE(IsSpokenFeedbackEnabled());
298
299  // Enables high contrast.
300  SetHighContrastEnabled(true);
301  // Confirms that high cotrast is enabled.
302  EXPECT_TRUE(IsHighContrastEnabled());
303
304  // Enables autoclick.
305  SetAutoclickEnabled(true);
306  // Confirms that autoclick is enabled.
307  EXPECT_TRUE(IsAutoclickEnabled());
308
309  // Test that autoclick delay is set properly.
310  SetAutoclickDelay(kTestAutoclickDelayMs);
311  EXPECT_EQ(kTestAutoclickDelayMs, GetAutoclickDelay());
312}
313
314IN_PROC_BROWSER_TEST_F(AccessibilityManagerTest, BrailleOnLoginScreen) {
315  EXPECT_FALSE(IsSpokenFeedbackEnabled());
316
317  // Signal the accessibility manager that a braille display was connected.
318  braille_controller_.SetAvailable(true);
319  braille_controller_.GetObserver()->OnDisplayStateChanged(
320      *braille_controller_.GetDisplayState());
321
322  // Confirms that the spoken feedback is enabled.
323  EXPECT_TRUE(IsSpokenFeedbackEnabled());
324}
325
326IN_PROC_BROWSER_TEST_F(AccessibilityManagerTest, TypePref) {
327  // Logs in.
328  UserManager::Get()->UserLoggedIn(kTestUserName, kTestUserName, true);
329  UserManager::Get()->SessionStarted();
330
331  // Confirms that the features are disabled just after login.
332  EXPECT_FALSE(IsLargeCursorEnabled());
333  EXPECT_FALSE(IsSpokenFeedbackEnabled());
334  EXPECT_FALSE(IsHighContrastEnabled());
335  EXPECT_FALSE(IsAutoclickEnabled());
336  EXPECT_EQ(default_autoclick_delay(), GetAutoclickDelay());
337
338  // Sets the pref as true to enable the large cursor.
339  SetLargeCursorEnabledPref(true);
340  // Confirms that the large cursor is enabled.
341  EXPECT_TRUE(IsLargeCursorEnabled());
342
343  // Sets the pref as true to enable the spoken feedback.
344  SetSpokenFeedbackEnabledPref(true);
345  // Confirms that the spoken feedback is enabled.
346  EXPECT_TRUE(IsSpokenFeedbackEnabled());
347
348  // Sets the pref as true to enable high contrast mode.
349  SetHighContrastEnabledPref(true);
350  // Confirms that the high contrast mode is enabled.
351  EXPECT_TRUE(IsHighContrastEnabled());
352
353  // Sets the pref as true to enable autoclick.
354  SetAutoclickEnabledPref(true);
355  // Confirms that autoclick is enabled.
356  EXPECT_TRUE(IsAutoclickEnabled());
357
358  // Set autoclick delay pref.
359  SetAutoclickDelayPref(kTestAutoclickDelayMs);
360  // Confirm that the correct value is set.
361  EXPECT_EQ(kTestAutoclickDelayMs, GetAutoclickDelay());
362
363  SetLargeCursorEnabledPref(false);
364  EXPECT_FALSE(IsLargeCursorEnabled());
365
366  SetSpokenFeedbackEnabledPref(false);
367  EXPECT_FALSE(IsSpokenFeedbackEnabled());
368
369  SetHighContrastEnabledPref(false);
370  EXPECT_FALSE(IsHighContrastEnabled());
371
372  SetAutoclickEnabledPref(false);
373  EXPECT_FALSE(IsAutoclickEnabled());
374}
375
376IN_PROC_BROWSER_TEST_F(AccessibilityManagerTest, ResumeSavedPref) {
377  // Loads the profile of the user.
378  UserManager::Get()->UserLoggedIn(kTestUserName, kTestUserName, true);
379
380  // Sets the pref to enable large cursor before login.
381  SetLargeCursorEnabledPref(true);
382  EXPECT_FALSE(IsLargeCursorEnabled());
383
384  // Sets the pref to enable spoken feedback before login.
385  SetSpokenFeedbackEnabledPref(true);
386  EXPECT_FALSE(IsSpokenFeedbackEnabled());
387
388  // Sets the pref to enable high contrast before login.
389  SetHighContrastEnabledPref(true);
390  EXPECT_FALSE(IsHighContrastEnabled());
391
392  // Sets the pref to enable autoclick before login.
393  SetAutoclickEnabledPref(true);
394  EXPECT_FALSE(IsAutoclickEnabled());
395
396  // Sets the autoclick delay pref before login but the
397  // initial value should not change.
398  SetAutoclickDelayPref(kTestAutoclickDelayMs);
399  EXPECT_EQ(default_autoclick_delay(), GetAutoclickDelay());
400
401  // Logs in.
402  UserManager::Get()->SessionStarted();
403
404  // Confirms that features are enabled by restring from pref just after login.
405  EXPECT_TRUE(IsLargeCursorEnabled());
406  EXPECT_TRUE(IsSpokenFeedbackEnabled());
407  EXPECT_TRUE(IsHighContrastEnabled());
408  EXPECT_TRUE(IsAutoclickEnabled());
409  EXPECT_EQ(kTestAutoclickDelayMs, GetAutoclickDelay());
410}
411
412IN_PROC_BROWSER_TEST_F(AccessibilityManagerTest,
413                       ChangingTypeInvokesNotification) {
414  MockAccessibilityObserver observer;
415
416  // Logs in.
417  UserManager::Get()->UserLoggedIn(kTestUserName, kTestUserName, true);
418  UserManager::Get()->SessionStarted();
419
420  EXPECT_FALSE(observer.observed());
421  observer.reset();
422
423  SetSpokenFeedbackEnabled(true);
424  EXPECT_TRUE(observer.observed());
425  EXPECT_TRUE(observer.observed_enabled());
426  EXPECT_EQ(observer.observed_type(),
427            chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_SPOKEN_FEEDBACK);
428  EXPECT_TRUE(IsSpokenFeedbackEnabled());
429
430  observer.reset();
431  SetSpokenFeedbackEnabled(false);
432  EXPECT_TRUE(observer.observed());
433  EXPECT_FALSE(observer.observed_enabled());
434  EXPECT_EQ(observer.observed_type(),
435            chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_SPOKEN_FEEDBACK);
436  EXPECT_FALSE(IsSpokenFeedbackEnabled());
437
438  observer.reset();
439  SetHighContrastEnabled(true);
440  EXPECT_TRUE(observer.observed());
441  EXPECT_TRUE(observer.observed_enabled());
442  EXPECT_EQ(observer.observed_type(),
443            chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_HIGH_CONTRAST_MODE);
444  EXPECT_TRUE(IsHighContrastEnabled());
445
446  observer.reset();
447  SetHighContrastEnabled(false);
448  EXPECT_TRUE(observer.observed());
449  EXPECT_FALSE(observer.observed_enabled());
450  EXPECT_EQ(observer.observed_type(),
451            chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_HIGH_CONTRAST_MODE);
452  EXPECT_FALSE(IsHighContrastEnabled());
453}
454
455IN_PROC_BROWSER_TEST_F(AccessibilityManagerTest,
456                       ChangingTypePrefInvokesNotification) {
457  MockAccessibilityObserver observer;
458
459  // Logs in.
460  UserManager::Get()->UserLoggedIn(kTestUserName, kTestUserName, true);
461  UserManager::Get()->SessionStarted();
462
463  EXPECT_FALSE(observer.observed());
464  observer.reset();
465
466  SetSpokenFeedbackEnabledPref(true);
467  EXPECT_TRUE(observer.observed());
468  EXPECT_TRUE(observer.observed_enabled());
469  EXPECT_EQ(observer.observed_type(),
470            chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_SPOKEN_FEEDBACK);
471  EXPECT_TRUE(IsSpokenFeedbackEnabled());
472
473  observer.reset();
474  SetSpokenFeedbackEnabledPref(false);
475  EXPECT_TRUE(observer.observed());
476  EXPECT_FALSE(observer.observed_enabled());
477  EXPECT_EQ(observer.observed_type(),
478            chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_SPOKEN_FEEDBACK);
479  EXPECT_FALSE(IsSpokenFeedbackEnabled());
480
481  observer.reset();
482  SetHighContrastEnabledPref(true);
483  EXPECT_TRUE(observer.observed());
484  EXPECT_TRUE(observer.observed_enabled());
485  EXPECT_EQ(observer.observed_type(),
486            chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_HIGH_CONTRAST_MODE);
487  EXPECT_TRUE(IsHighContrastEnabled());
488
489  observer.reset();
490  SetHighContrastEnabledPref(false);
491  EXPECT_TRUE(observer.observed());
492  EXPECT_FALSE(observer.observed_enabled());
493  EXPECT_EQ(observer.observed_type(),
494            chrome::NOTIFICATION_CROS_ACCESSIBILITY_TOGGLE_HIGH_CONTRAST_MODE);
495  EXPECT_FALSE(IsHighContrastEnabled());
496}
497
498class AccessibilityManagerUserTypeTest
499    : public AccessibilityManagerTest,
500      public ::testing::WithParamInterface<const char*> {
501 protected:
502  AccessibilityManagerUserTypeTest() {}
503  virtual ~AccessibilityManagerUserTypeTest() {}
504
505  DISALLOW_COPY_AND_ASSIGN(AccessibilityManagerUserTypeTest);
506};
507
508// TODO(yoshiki): Enable a test for retail mode.
509INSTANTIATE_TEST_CASE_P(
510    UserTypeInstantiation,
511    AccessibilityManagerUserTypeTest,
512    ::testing::Values(kTestUserName,
513                      UserManager::kGuestUserName,
514                      //UserManager::kRetailModeUserName,
515                      kTestLocallyManagedUserName));
516
517IN_PROC_BROWSER_TEST_P(AccessibilityManagerUserTypeTest,
518                       EnableOnLoginScreenAndLogin) {
519  // Enables large cursor.
520  SetLargeCursorEnabled(true);
521  EXPECT_TRUE(IsLargeCursorEnabled());
522  // Enables spoken feedback.
523  SetSpokenFeedbackEnabled(true);
524  EXPECT_TRUE(IsSpokenFeedbackEnabled());
525  // Enables high contrast.
526  SetHighContrastEnabled(true);
527  EXPECT_TRUE(IsHighContrastEnabled());
528  // Enables autoclick.
529  SetAutoclickEnabled(true);
530  EXPECT_TRUE(IsAutoclickEnabled());
531  // Set autoclick delay.
532  SetAutoclickDelay(kTestAutoclickDelayMs);
533  EXPECT_EQ(kTestAutoclickDelayMs, GetAutoclickDelay());
534
535  // Logs in.
536  const char* user_name = GetParam();
537  UserManager::Get()->UserLoggedIn(user_name, user_name, true);
538
539  // Confirms that the features are still enabled just after login.
540  EXPECT_TRUE(IsLargeCursorEnabled());
541  EXPECT_TRUE(IsSpokenFeedbackEnabled());
542  EXPECT_TRUE(IsHighContrastEnabled());
543  EXPECT_TRUE(IsAutoclickEnabled());
544  EXPECT_EQ(kTestAutoclickDelayMs, GetAutoclickDelay());
545
546  UserManager::Get()->SessionStarted();
547
548  // Confirms that the features keep enabled after session starts.
549  EXPECT_TRUE(IsLargeCursorEnabled());
550  EXPECT_TRUE(IsSpokenFeedbackEnabled());
551  EXPECT_TRUE(IsHighContrastEnabled());
552  EXPECT_TRUE(IsAutoclickEnabled());
553  EXPECT_EQ(kTestAutoclickDelayMs, GetAutoclickDelay());
554
555  // Confirms that the prefs have been copied to the user's profile.
556  EXPECT_TRUE(GetLargeCursorEnabledFromPref());
557  EXPECT_TRUE(GetSpokenFeedbackEnabledFromPref());
558  EXPECT_TRUE(GetHighContrastEnabledFromPref());
559  EXPECT_TRUE(GetAutoclickEnabledFromPref());
560  EXPECT_EQ(kTestAutoclickDelayMs, GetAutoclickDelayFromPref());
561}
562
563}  // namespace chromeos
564