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.
8 #include "base/json/json_writer.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/values.h"
12 #include "chrome/browser/extensions/extension_apitest.h"
13 #include "chrome/common/pref_names.h"
14 #include "extensions/test/result_catcher.h"
16 // API tests for chrome.accessibilityFeatures API.
17 // Note that the API is implemented using preference API infrastructure.
18 // See preference_api.cc for the list of accessibility features exposed by the
19 // API and the related preferences.
21 namespace extensions
{
25 // Keys for data in the test config argument that will be set for the test app
27 // The test that the app should run.
28 const char kTestNameKey
[] = "testName";
29 // Key for list of features enabled when the test is initialized.
30 const char kEnabledFeaturesKey
[] = "enabled";
31 // Key for list fo features disabled when the test is initialized.
32 const char kDisabledFeaturesKey
[] = "disabled";
34 // A test extension path. The extension has only |accessibilityFeatures.read|
36 const char kTestExtensionPathReadPermission
[] =
37 "accessibility_features/read_permission/";
38 // A test extension path. The extension has only |accessibilityFeatures.modify|
40 const char kTestExtensionPathMofifyPermission
[] =
41 "accessibility_features/modify_permission/";
43 // Accessibility features API test.
44 // Tests are parameterized by whether the test extension is write-only (the
45 // parameter value is true) or read-only (the parameter value is false).
46 class AccessibilityFeaturesApiTest
: public ExtensionApiTest
,
47 public testing::WithParamInterface
<bool> {
49 AccessibilityFeaturesApiTest() {}
50 virtual ~AccessibilityFeaturesApiTest() {}
53 // Returns pref service to be used to initialize and later verify
54 // accessibility preference values.
55 PrefService
* GetPrefs() { return browser()->profile()->GetPrefs(); }
57 // Returns the path of the extension that should be used in a parameterized
59 std::string
GetTestExtensionPath() const {
61 return kTestExtensionPathMofifyPermission
;
62 return kTestExtensionPathReadPermission
;
65 // Whether a parameterized test should have been able to modify accessibility
66 // preferences (i.e. whether the test extension had modify permission).
67 bool ShouldModifyingFeatureSucceed() const { return GetParam(); }
69 // Returns preference path for accessibility features as defined by the API.
70 const char* const GetPrefForFeature(const std::string
& feature
) {
71 if (feature
== "spokenFeedback")
72 return prefs::kAccessibilitySpokenFeedbackEnabled
;
73 if (feature
== "largeCursor")
74 return prefs::kAccessibilityLargeCursorEnabled
;
75 if (feature
== "stickyKeys")
76 return prefs::kAccessibilityStickyKeysEnabled
;
77 if (feature
== "highContrast")
78 return prefs::kAccessibilityHighContrastEnabled
;
79 if (feature
== "screenMagnifier")
80 return prefs::kAccessibilityScreenMagnifierEnabled
;
81 if (feature
== "autoclick")
82 return prefs::kAccessibilityAutoclickEnabled
;
83 if (feature
== "virtualKeyboard")
84 return prefs::kAccessibilityVirtualKeyboardEnabled
;
88 // Initializes preferences before running the test extension.
89 // |prefs| Pref service which should be initializzed.
90 // |enabled_features| List of boolean preference whose value should be set to
92 // |disabled_features| List of boolean preferences whose value should be set
94 bool InitPrefServiceForTest(
96 const std::vector
<std::string
>& enabled_features
,
97 const std::vector
<std::string
>& disabled_features
) {
98 for (size_t i
= 0; i
< enabled_features
.size(); ++i
) {
99 const char* const pref_name
= GetPrefForFeature(enabled_features
[i
]);
100 EXPECT_TRUE(pref_name
) << "Invalid feature " << enabled_features
[i
];
103 prefs
->SetBoolean(pref_name
, true);
106 for (size_t i
= 0; i
< disabled_features
.size(); ++i
) {
107 const char* const pref_name
= GetPrefForFeature(disabled_features
[i
]);
108 EXPECT_TRUE(pref_name
) << "Invalid feature " << disabled_features
[i
];
111 prefs
->SetBoolean(pref_name
, false);
116 // Verifies that preferences have the expected value.
117 // |prefs| The pref service to be verified.
118 // |enabled_features| The list of boolean preferences whose value should be
120 // |disabled_features| The list of boolean preferences whose value should be
122 void VerifyPrefServiceState(
124 const std::vector
<std::string
>& enabled_features
,
125 const std::vector
<std::string
>& disabled_features
) {
126 for (size_t i
= 0; i
< enabled_features
.size(); ++i
) {
127 const char* const pref_name
= GetPrefForFeature(enabled_features
[i
]);
128 ASSERT_TRUE(pref_name
) << "Invalid feature " << enabled_features
[i
];
129 ASSERT_TRUE(prefs
->GetBoolean(pref_name
));
132 for (size_t i
= 0; i
< disabled_features
.size(); ++i
) {
133 const char* const pref_name
= GetPrefForFeature(disabled_features
[i
]);
134 ASSERT_TRUE(pref_name
) << "Invalid feature " << disabled_features
[i
];
135 ASSERT_FALSE(prefs
->GetBoolean(pref_name
));
139 // Given the test name and list of enabled and disabled features, generates
140 // and sets the JSON string that should be given to the test extension as
141 // test configuration.
142 // The result is saved to |result|. The return value is whether the test
143 // argument was successfully generated.
144 bool GenerateTestArg(const std::string
& test_name
,
145 const std::vector
<std::string
>& enabled_features
,
146 const std::vector
<std::string
>& disabled_features
,
147 std::string
* result
) {
148 base::DictionaryValue test_arg
;
149 test_arg
.SetString(kTestNameKey
, test_name
);
151 scoped_ptr
<base::ListValue
> enabled_list(new base::ListValue
);
152 for (size_t i
= 0; i
< enabled_features
.size(); ++i
)
153 enabled_list
->AppendString(enabled_features
[i
]);
154 test_arg
.Set(kEnabledFeaturesKey
, enabled_list
.release());
156 scoped_ptr
<base::ListValue
> disabled_list(new base::ListValue
);
157 for (size_t i
= 0; i
< disabled_features
.size(); ++i
)
158 disabled_list
->AppendString(disabled_features
[i
]);
159 test_arg
.Set(kDisabledFeaturesKey
, disabled_list
.release());
161 return base::JSONWriter::Write(test_arg
, result
);
165 INSTANTIATE_TEST_CASE_P(AccessibilityFeatureaApiTestInstantiatePermission
,
166 AccessibilityFeaturesApiTest
,
169 // Tests that an extension with read permission can read accessibility features
170 // state, while an extension that doesn't have the permission cannot.
171 IN_PROC_BROWSER_TEST_P(AccessibilityFeaturesApiTest
, Get
) {
172 // WARNING: Make sure that spoken feedback is not among enabled_features
173 // (see |Set| test for the reason).
174 std::vector
<std::string
> enabled_features
;
175 enabled_features
.push_back("largeCursor");
176 enabled_features
.push_back("stickyKeys");
177 enabled_features
.push_back("highContrast");
179 std::vector
<std::string
> disabled_features
;
180 disabled_features
.push_back("spokenFeedback");
181 disabled_features
.push_back("screenMagnifier");
182 disabled_features
.push_back("autoclick");
183 disabled_features
.push_back("virtualKeyboard");
186 InitPrefServiceForTest(GetPrefs(), enabled_features
, disabled_features
));
188 std::string test_arg
;
189 ASSERT_TRUE(GenerateTestArg(
190 "getterTest", enabled_features
, disabled_features
, &test_arg
));
192 RunPlatformAppTestWithArg(GetTestExtensionPath(), test_arg
.c_str()))
196 // Tests that an extension with modify permission can modify accessibility
197 // features, while an extension that doesn't have the permission can't.
198 IN_PROC_BROWSER_TEST_P(AccessibilityFeaturesApiTest
, Set
) {
199 // WARNING: Make sure that spoken feedback does not get enabled at this point
200 // (before the test app is loaded), as that may break the test:
201 // |RunPlatformAppTestWithArg| waits for the test extension to load by
202 // waiting for EXTENSION_LOADED notification to be observed. It also assumes
203 // that there is only one extension being loaded during this time (it finishes
204 // when the first notification is seen). Enabling spoken feedback here would
205 // break this assumption as it would induce loading of ChromeVox extension.
206 std::vector
<std::string
> enabled_features
;
207 enabled_features
.push_back("stickyKeys");
208 enabled_features
.push_back("autoclick");
209 enabled_features
.push_back("virtualKeyboard");
211 std::vector
<std::string
> disabled_features
;
212 disabled_features
.push_back("spokenFeedback");
213 disabled_features
.push_back("largeCursor");
214 disabled_features
.push_back("highContrast");
215 disabled_features
.push_back("screenMagnifier");
218 InitPrefServiceForTest(GetPrefs(), enabled_features
, disabled_features
));
220 std::string test_arg
;
221 ASSERT_TRUE(GenerateTestArg(
222 "setterTest", enabled_features
, disabled_features
, &test_arg
));
224 // The test extension attempts to flip all feature values.
226 RunPlatformAppTestWithArg(GetTestExtensionPath(), test_arg
.c_str()))
229 // The test tries to flip the feature states.
230 if (ShouldModifyingFeatureSucceed()) {
231 VerifyPrefServiceState(GetPrefs(), disabled_features
, enabled_features
);
233 VerifyPrefServiceState(GetPrefs(), enabled_features
, disabled_features
);
237 // Tests that an extension with read permission is notified when accessibility
239 IN_PROC_BROWSER_TEST_F(AccessibilityFeaturesApiTest
, ObserveFeatures
) {
240 // WARNING: Make sure that spoken feedback is not among enabled_features
241 // (see |Set| test for the reason).
242 std::vector
<std::string
> enabled_features
;
243 enabled_features
.push_back("largeCursor");
244 enabled_features
.push_back("stickyKeys");
245 enabled_features
.push_back("highContrast");
247 std::vector
<std::string
> disabled_features
;
248 disabled_features
.push_back("screenMagnifier");
251 InitPrefServiceForTest(GetPrefs(), enabled_features
, disabled_features
));
253 std::string test_arg
;
254 ASSERT_TRUE(GenerateTestArg(
255 "observerTest", enabled_features
, disabled_features
, &test_arg
));
257 // The test extension is supposed to report result twice when runnign this
258 // test. First time when in initializes it's feature listeners, and second
259 // time, when gets all expected events. This is done so the extension is
260 // running when the accessibility features are flipped; oterwise, the
261 // extension may not see events.
262 ASSERT_TRUE(RunPlatformAppTestWithArg(kTestExtensionPathReadPermission
,
266 // This should flip all features.
268 InitPrefServiceForTest(GetPrefs(), disabled_features
, enabled_features
));
270 // Catch the second result notification sent by the test extension.
271 ResultCatcher result_catcher
;
272 ASSERT_TRUE(result_catcher
.GetNextResult()) << result_catcher
.message();
277 } // namespace extensions