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