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 <string>
6
7#include "ash/magnifier/magnifier_constants.h"
8#include "base/basictypes.h"
9#include "base/bind.h"
10#include "base/bind_helpers.h"
11#include "base/command_line.h"
12#include "base/compiler_specific.h"
13#include "base/location.h"
14#include "base/message_loop/message_loop.h"
15#include "base/prefs/pref_change_registrar.h"
16#include "base/prefs/pref_service.h"
17#include "base/run_loop.h"
18#include "base/values.h"
19#include "chrome/browser/chromeos/accessibility/accessibility_manager.h"
20#include "chrome/browser/chromeos/accessibility/magnification_manager.h"
21#include "chrome/browser/chromeos/policy/device_policy_builder.h"
22#include "chrome/browser/chromeos/policy/device_policy_cros_browser_test.h"
23#include "chrome/browser/chromeos/policy/proto/chrome_device_policy.pb.h"
24#include "chrome/browser/chromeos/profiles/profile_helper.h"
25#include "chrome/browser/lifetime/application_lifetime.h"
26#include "chrome/browser/profiles/profile.h"
27#include "chrome/browser/profiles/profile_manager.h"
28#include "chrome/common/pref_names.h"
29#include "chromeos/chromeos_switches.h"
30#include "testing/gtest/include/gtest/gtest.h"
31
32namespace em = enterprise_management;
33
34namespace policy {
35
36namespace {
37
38const em::AccessibilitySettingsProto_ScreenMagnifierType kFullScreenMagnifier =
39    em::AccessibilitySettingsProto_ScreenMagnifierType_SCREEN_MAGNIFIER_TYPE_FULL;
40
41// Spins the loop until a notification is received from |prefs| that the value
42// of |pref_name| has changed. If the notification is received before Wait()
43// has been called, Wait() returns immediately and no loop is spun.
44class PrefChangeWatcher {
45 public:
46  PrefChangeWatcher(const char* pref_name, PrefService* prefs);
47
48  void Wait();
49
50  void OnPrefChange();
51
52 private:
53  bool pref_changed_;
54
55  base::RunLoop run_loop_;
56  PrefChangeRegistrar registrar_;
57
58  DISALLOW_COPY_AND_ASSIGN(PrefChangeWatcher);
59};
60
61PrefChangeWatcher::PrefChangeWatcher(const char* pref_name,
62                                     PrefService* prefs)
63    : pref_changed_(false) {
64  registrar_.Init(prefs);
65  registrar_.Add(pref_name, base::Bind(&PrefChangeWatcher::OnPrefChange,
66                                       base::Unretained(this)));
67}
68
69void PrefChangeWatcher::Wait() {
70  if (!pref_changed_)
71    run_loop_.Run();
72}
73
74void PrefChangeWatcher::OnPrefChange() {
75  pref_changed_ = true;
76  run_loop_.Quit();
77}
78
79}  // namespace
80
81class LoginScreenDefaultPolicyBrowsertestBase
82    : public DevicePolicyCrosBrowserTest {
83 protected:
84  LoginScreenDefaultPolicyBrowsertestBase();
85  virtual ~LoginScreenDefaultPolicyBrowsertestBase();
86
87  // DevicePolicyCrosBrowserTest:
88  virtual void SetUpInProcessBrowserTestFixture() OVERRIDE;
89  virtual void SetUpOnMainThread() OVERRIDE;
90
91  void RefreshDevicePolicyAndWaitForPrefChange(const char* pref_name);
92
93  Profile* login_profile_;
94
95 private:
96  DISALLOW_COPY_AND_ASSIGN(LoginScreenDefaultPolicyBrowsertestBase);
97};
98
99class LoginScreenDefaultPolicyLoginScreenBrowsertest
100    : public LoginScreenDefaultPolicyBrowsertestBase {
101 protected:
102  LoginScreenDefaultPolicyLoginScreenBrowsertest();
103  virtual ~LoginScreenDefaultPolicyLoginScreenBrowsertest();
104
105  // LoginScreenDefaultPolicyBrowsertestBase:
106  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE;
107  virtual void SetUpOnMainThread() OVERRIDE;
108  virtual void TearDownOnMainThread() OVERRIDE;
109
110  void VerifyPrefFollowsRecommendation(const char* pref_name,
111                                       const base::Value& recommended_value);
112
113 private:
114  DISALLOW_COPY_AND_ASSIGN(LoginScreenDefaultPolicyLoginScreenBrowsertest);
115};
116
117class LoginScreenDefaultPolicyInSessionBrowsertest
118    : public LoginScreenDefaultPolicyBrowsertestBase {
119 protected:
120  LoginScreenDefaultPolicyInSessionBrowsertest();
121  virtual ~LoginScreenDefaultPolicyInSessionBrowsertest();
122
123  // LoginScreenDefaultPolicyBrowsertestBase:
124  virtual void SetUpOnMainThread() OVERRIDE;
125
126  void VerifyPrefFollowsDefault(const char* pref_name);
127
128 private:
129  DISALLOW_COPY_AND_ASSIGN(LoginScreenDefaultPolicyInSessionBrowsertest);
130};
131
132LoginScreenDefaultPolicyBrowsertestBase::
133    LoginScreenDefaultPolicyBrowsertestBase() : login_profile_(NULL) {
134}
135
136LoginScreenDefaultPolicyBrowsertestBase::
137    ~LoginScreenDefaultPolicyBrowsertestBase() {
138}
139
140void LoginScreenDefaultPolicyBrowsertestBase::
141    SetUpInProcessBrowserTestFixture() {
142  InstallOwnerKey();
143  MarkAsEnterpriseOwned();
144  DevicePolicyCrosBrowserTest::SetUpInProcessBrowserTestFixture();
145}
146
147void LoginScreenDefaultPolicyBrowsertestBase::SetUpOnMainThread() {
148  DevicePolicyCrosBrowserTest::SetUpOnMainThread();
149  login_profile_ = chromeos::ProfileHelper::GetSigninProfile();
150  ASSERT_TRUE(login_profile_);
151}
152
153void LoginScreenDefaultPolicyBrowsertestBase::
154    RefreshDevicePolicyAndWaitForPrefChange(const char* pref_name) {
155  PrefChangeWatcher watcher(pref_name, login_profile_->GetPrefs());
156  RefreshDevicePolicy();
157  watcher.Wait();
158}
159
160LoginScreenDefaultPolicyLoginScreenBrowsertest::
161    LoginScreenDefaultPolicyLoginScreenBrowsertest() {
162}
163
164LoginScreenDefaultPolicyLoginScreenBrowsertest::
165    ~LoginScreenDefaultPolicyLoginScreenBrowsertest() {
166}
167
168void LoginScreenDefaultPolicyLoginScreenBrowsertest::SetUpCommandLine(
169    CommandLine* command_line) {
170  LoginScreenDefaultPolicyBrowsertestBase::SetUpCommandLine(command_line);
171  command_line->AppendSwitch(chromeos::switches::kLoginManager);
172  command_line->AppendSwitch(chromeos::switches::kForceLoginManagerInTests);
173}
174
175void LoginScreenDefaultPolicyLoginScreenBrowsertest::SetUpOnMainThread() {
176  LoginScreenDefaultPolicyBrowsertestBase::SetUpOnMainThread();
177
178  // Set the login screen profile.
179  chromeos::AccessibilityManager* accessibility_manager =
180      chromeos::AccessibilityManager::Get();
181  ASSERT_TRUE(accessibility_manager);
182  accessibility_manager->SetProfileForTest(
183      chromeos::ProfileHelper::GetSigninProfile());
184
185  chromeos::MagnificationManager* magnification_manager =
186      chromeos::MagnificationManager::Get();
187  ASSERT_TRUE(magnification_manager);
188  magnification_manager->SetProfileForTest(
189      chromeos::ProfileHelper::GetSigninProfile());
190}
191
192void LoginScreenDefaultPolicyLoginScreenBrowsertest::TearDownOnMainThread() {
193  base::MessageLoop::current()->PostTask(FROM_HERE,
194                                         base::Bind(&chrome::AttemptExit));
195  base::RunLoop().RunUntilIdle();
196  LoginScreenDefaultPolicyBrowsertestBase::TearDownOnMainThread();
197}
198
199void LoginScreenDefaultPolicyLoginScreenBrowsertest::
200    VerifyPrefFollowsRecommendation(const char* pref_name,
201                                    const base::Value& recommended_value) {
202  const PrefService::Preference* pref =
203      login_profile_->GetPrefs()->FindPreference(pref_name);
204  ASSERT_TRUE(pref);
205  EXPECT_FALSE(pref->IsManaged());
206  EXPECT_FALSE(pref->IsDefaultValue());
207  EXPECT_TRUE(base::Value::Equals(&recommended_value, pref->GetValue()));
208  EXPECT_TRUE(base::Value::Equals(&recommended_value,
209                                  pref->GetRecommendedValue()));
210}
211
212LoginScreenDefaultPolicyInSessionBrowsertest::
213    LoginScreenDefaultPolicyInSessionBrowsertest() {
214}
215
216LoginScreenDefaultPolicyInSessionBrowsertest::
217    ~LoginScreenDefaultPolicyInSessionBrowsertest() {
218}
219
220void LoginScreenDefaultPolicyInSessionBrowsertest::SetUpOnMainThread() {
221  LoginScreenDefaultPolicyBrowsertestBase::SetUpOnMainThread();
222}
223
224void LoginScreenDefaultPolicyInSessionBrowsertest::VerifyPrefFollowsDefault(
225    const char* pref_name) {
226  Profile* profile = ProfileManager::GetActiveUserProfile();
227  ASSERT_TRUE(profile);
228  const PrefService::Preference* pref =
229      profile->GetPrefs()->FindPreference(pref_name);
230  ASSERT_TRUE(pref);
231  EXPECT_FALSE(pref->IsManaged());
232  EXPECT_TRUE(pref->IsDefaultValue());
233  EXPECT_FALSE(pref->GetRecommendedValue());
234}
235
236IN_PROC_BROWSER_TEST_F(LoginScreenDefaultPolicyLoginScreenBrowsertest,
237                       DeviceLoginScreenDefaultLargeCursorEnabled) {
238  // Verifies that the default state of the large cursor accessibility feature
239  // on the login screen can be controlled through device policy.
240
241  // Enable the large cursor through device policy and wait for the change to
242  // take effect.
243  em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
244  proto.mutable_accessibility_settings()->
245      set_login_screen_default_large_cursor_enabled(true);
246  RefreshDevicePolicyAndWaitForPrefChange(
247      prefs::kAccessibilityLargeCursorEnabled);
248
249  // Verify that the pref which controls the large cursor in the login profile
250  // has changed to the policy-supplied default.
251  VerifyPrefFollowsRecommendation(prefs::kAccessibilityLargeCursorEnabled,
252                                  base::FundamentalValue(true));
253
254  // Verify that the large cursor is enabled.
255  chromeos::AccessibilityManager* accessibility_manager =
256      chromeos::AccessibilityManager::Get();
257  ASSERT_TRUE(accessibility_manager);
258  EXPECT_TRUE(accessibility_manager->IsLargeCursorEnabled());
259}
260
261IN_PROC_BROWSER_TEST_F(LoginScreenDefaultPolicyLoginScreenBrowsertest,
262                       DeviceLoginScreenDefaultSpokenFeedbackEnabled) {
263  // Verifies that the default state of the spoken feedback accessibility
264  // feature on the login screen can be controlled through device policy.
265
266  // Enable spoken feedback through device policy and wait for the change to
267  // take effect.
268  em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
269  proto.mutable_accessibility_settings()->
270      set_login_screen_default_spoken_feedback_enabled(true);
271  RefreshDevicePolicyAndWaitForPrefChange(
272      prefs::kAccessibilitySpokenFeedbackEnabled);
273
274  // Verify that the pref which controls spoken feedback in the login profile
275  // has changed to the policy-supplied default.
276  VerifyPrefFollowsRecommendation(prefs::kAccessibilitySpokenFeedbackEnabled,
277                                  base::FundamentalValue(true));
278
279  // Verify that spoken feedback is enabled.
280  chromeos::AccessibilityManager* accessibility_manager =
281      chromeos::AccessibilityManager::Get();
282  ASSERT_TRUE(accessibility_manager);
283  EXPECT_TRUE(accessibility_manager->IsSpokenFeedbackEnabled());
284}
285
286IN_PROC_BROWSER_TEST_F(LoginScreenDefaultPolicyLoginScreenBrowsertest,
287                       DeviceLoginScreenDefaultHighContrastEnabled) {
288  // Verifies that the default state of the high contrast mode accessibility
289  // feature on the login screen can be controlled through device policy.
290
291  // Enable high contrast mode through device policy and wait for the change to
292  // take effect.
293  em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
294  proto.mutable_accessibility_settings()->
295      set_login_screen_default_high_contrast_enabled(true);
296  RefreshDevicePolicyAndWaitForPrefChange(
297      prefs::kAccessibilityHighContrastEnabled);
298
299  // Verify that the pref which controls high contrast mode in the login profile
300  // has changed to the policy-supplied default.
301  VerifyPrefFollowsRecommendation(prefs::kAccessibilityHighContrastEnabled,
302                                  base::FundamentalValue(true));
303
304  // Verify that high contrast mode is enabled.
305  chromeos::AccessibilityManager* accessibility_manager =
306      chromeos::AccessibilityManager::Get();
307  ASSERT_TRUE(accessibility_manager);
308  EXPECT_TRUE(accessibility_manager->IsHighContrastEnabled());
309}
310
311IN_PROC_BROWSER_TEST_F(LoginScreenDefaultPolicyLoginScreenBrowsertest,
312                       DeviceLoginScreenDefaultScreenMagnifierType) {
313  // Verifies that the default screen magnifier type enabled on the login screen
314  // can be controlled through device policy.
315
316  // Set the screen magnifier type through device policy and wait for the change
317  // to take effect.
318  em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
319  proto.mutable_accessibility_settings()->
320      set_login_screen_default_screen_magnifier_type(kFullScreenMagnifier);
321  RefreshDevicePolicyAndWaitForPrefChange(
322      prefs::kAccessibilityScreenMagnifierType);
323
324  // Verify that the prefs which control the screen magnifier type have changed
325  // to the policy-supplied default.
326  VerifyPrefFollowsRecommendation(prefs::kAccessibilityScreenMagnifierEnabled,
327                                  base::FundamentalValue(true));
328  VerifyPrefFollowsRecommendation(prefs::kAccessibilityScreenMagnifierType,
329                                  base::FundamentalValue(ash::MAGNIFIER_FULL));
330
331  // Verify that the full-screen magnifier is enabled.
332  chromeos::MagnificationManager* magnification_manager =
333      chromeos::MagnificationManager::Get();
334  ASSERT_TRUE(magnification_manager);
335  EXPECT_TRUE(magnification_manager->IsMagnifierEnabled());
336  EXPECT_EQ(ash::MAGNIFIER_FULL, magnification_manager->GetMagnifierType());
337}
338
339IN_PROC_BROWSER_TEST_F(LoginScreenDefaultPolicyInSessionBrowsertest,
340                       DeviceLoginScreenDefaultLargeCursorEnabled) {
341  // Verifies that changing the default state of the large cursor accessibility
342  // feature on the login screen through policy does not affect its state in a
343  // session.
344
345  // Enable the large cursor through device policy and wait for the change to
346  // take effect.
347  em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
348  proto.mutable_accessibility_settings()->
349      set_login_screen_default_large_cursor_enabled(true);
350  RefreshDevicePolicyAndWaitForPrefChange(
351      prefs::kAccessibilityLargeCursorEnabled);
352
353  // Verify that the pref which controls the large cursor in the session is
354  // unchanged.
355  VerifyPrefFollowsDefault(prefs::kAccessibilityLargeCursorEnabled);
356
357  // Verify that the large cursor is disabled.
358  chromeos::AccessibilityManager* accessibility_manager =
359      chromeos::AccessibilityManager::Get();
360  ASSERT_TRUE(accessibility_manager);
361  EXPECT_FALSE(accessibility_manager->IsLargeCursorEnabled());
362}
363
364IN_PROC_BROWSER_TEST_F(LoginScreenDefaultPolicyInSessionBrowsertest,
365                       DeviceLoginScreenDefaultSpokenFeedbackEnabled) {
366  // Verifies that changing the default state of the spoken feedback
367  // accessibility feature on the login screen through policy does not affect
368  // its state in a session.
369
370  // Enable spoken feedback through device policy and wait for the change to
371  // take effect.
372  em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
373  proto.mutable_accessibility_settings()->
374      set_login_screen_default_spoken_feedback_enabled(true);
375  RefreshDevicePolicyAndWaitForPrefChange(
376      prefs::kAccessibilitySpokenFeedbackEnabled);
377
378  // Verify that the pref which controls the spoken feedback in the session is
379  // unchanged.
380  VerifyPrefFollowsDefault(prefs::kAccessibilitySpokenFeedbackEnabled);
381
382  // Verify that spoken feedback is disabled.
383  chromeos::AccessibilityManager* accessibility_manager =
384      chromeos::AccessibilityManager::Get();
385  ASSERT_TRUE(accessibility_manager);
386  EXPECT_FALSE(accessibility_manager->IsSpokenFeedbackEnabled());
387}
388
389IN_PROC_BROWSER_TEST_F(LoginScreenDefaultPolicyInSessionBrowsertest,
390                       DeviceLoginScreenDefaultHighContrastEnabled) {
391  // Verifies that changing the default state of the high contrast mode
392  // accessibility feature on the login screen through policy does not affect
393  // its state in a session.
394
395  // Enable high contrast mode through device policy and wait for the change to
396  // take effect.
397  em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
398  proto.mutable_accessibility_settings()->
399      set_login_screen_default_high_contrast_enabled(true);
400  RefreshDevicePolicyAndWaitForPrefChange(
401      prefs::kAccessibilityHighContrastEnabled);
402
403  // Verify that the pref which controls high contrast mode in the session is
404  // unchanged.
405  VerifyPrefFollowsDefault(prefs::kAccessibilityHighContrastEnabled);
406
407  // Verify that high contrast mode is disabled.
408  chromeos::AccessibilityManager* accessibility_manager =
409      chromeos::AccessibilityManager::Get();
410  ASSERT_TRUE(accessibility_manager);
411  EXPECT_FALSE(accessibility_manager->IsHighContrastEnabled());
412}
413
414IN_PROC_BROWSER_TEST_F(LoginScreenDefaultPolicyInSessionBrowsertest,
415                       DeviceLoginScreenDefaultScreenMagnifierType) {
416  // Verifies that changing the default screen magnifier type enabled on the
417  // login screen through policy does not affect its state in a session.
418
419  // Set the screen magnifier type through device policy and wait for the change
420  // to take effect.
421  em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
422  proto.mutable_accessibility_settings()->
423      set_login_screen_default_screen_magnifier_type(kFullScreenMagnifier);
424  RefreshDevicePolicyAndWaitForPrefChange(
425      prefs::kAccessibilityScreenMagnifierType);
426
427  // Verify that the prefs which control the screen magnifier in the session are
428  // unchanged.
429  VerifyPrefFollowsDefault(prefs::kAccessibilityScreenMagnifierEnabled);
430  VerifyPrefFollowsDefault(prefs::kAccessibilityScreenMagnifierType);
431
432  // Verify that the screen magnifier is disabled.
433  chromeos::MagnificationManager* magnification_manager =
434      chromeos::MagnificationManager::Get();
435  ASSERT_TRUE(magnification_manager);
436  EXPECT_FALSE(magnification_manager->IsMagnifierEnabled());
437  EXPECT_EQ(ash::kDefaultMagnifierType,
438            magnification_manager->GetMagnifierType());
439}
440
441IN_PROC_BROWSER_TEST_F(LoginScreenDefaultPolicyLoginScreenBrowsertest,
442                       DeviceLoginScreenDefaultVirtualKeyboardEnabled) {
443  // Verifies that the default state of the on-screen keyboard accessibility
444  // feature on the login screen can be controlled through device policy.
445
446  // Enable the on-screen keyboard through device policy and wait for the change
447  // to take effect.
448  em::ChromeDeviceSettingsProto& proto(device_policy()->payload());
449  proto.mutable_accessibility_settings()->
450      set_login_screen_default_virtual_keyboard_enabled(true);
451  RefreshDevicePolicyAndWaitForPrefChange(
452      prefs::kAccessibilityVirtualKeyboardEnabled);
453
454  // Verify that the pref which controls the on-screen keyboard in the login
455  // profile has changed to the policy-supplied default.
456  VerifyPrefFollowsRecommendation(prefs::kAccessibilityVirtualKeyboardEnabled,
457                                  base::FundamentalValue(true));
458
459  // Verify that the on-screen keyboard is enabled.
460  chromeos::AccessibilityManager* accessibility_manager =
461      chromeos::AccessibilityManager::Get();
462  ASSERT_TRUE(accessibility_manager);
463  EXPECT_TRUE(accessibility_manager->IsVirtualKeyboardEnabled());
464}
465
466} // namespace policy
467