accessibility_features_apitest.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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
20namespace extensions {
21
22namespace {
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.
27const char kTestNameKey[] = "testName";
28// Key for list of features enabled when the test is initialized.
29const char kEnabledFeaturesKey[] = "enabled";
30// Key for list fo features disabled when the test is initialized.
31const char kDisabledFeaturesKey[] = "disabled";
32
33// A test extension path. The extension has only |accessibilityFeatures.read|
34// permission.
35const char kTestExtensionPathReadPermission[] =
36    "accessibility_features/read_permission/";
37// A test extension path. The extension has only |accessibilityFeatures.modify|
38// permission.
39const 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).
45class AccessibilityFeaturesApiTest : public ExtensionApiTest,
46                                     public testing::WithParamInterface<bool> {
47 public:
48  AccessibilityFeaturesApiTest() {}
49  virtual ~AccessibilityFeaturesApiTest() {}
50
51 protected:
52  // Returns pref service to be used to initialize and later verify
53  // accessibility preference values.
54  PrefService* GetPrefs() { return browser()->profile()->GetPrefs(); }
55
56  // Returns the path of the extension that should be used in a parameterized
57  // test.
58  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).
66  bool ShouldModifyingFeatureSucceed() const { return GetParam(); }
67
68  // Returns preference path for accessibility features as defined by the API.
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.
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.
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.
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// Disabled now as this test is being flaky, see http://crbug.com/384266.
165INSTANTIATE_TEST_CASE_P(
166    DISABLED_AccessibilityFeatureaApiTestInstantiatePermission,
167    AccessibilityFeaturesApiTest,
168    testing::Bool());
169
170// Tests that an extension with read permission can read accessibility features
171// state, while an extension that doesn't have the permission cannot.
172IN_PROC_BROWSER_TEST_P(AccessibilityFeaturesApiTest, Get) {
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}
193
194// Tests that an extension with modify permission can modify accessibility
195// features, while an extension that doesn't have the permission can't.
196IN_PROC_BROWSER_TEST_P(AccessibilityFeaturesApiTest, Set) {
197  std::vector<std::string> enabled_features;
198  enabled_features.push_back("spokenFeedback");
199  enabled_features.push_back("stickyKeys");
200  enabled_features.push_back("autoclick");
201  enabled_features.push_back("virtualKeyboard");
202
203  std::vector<std::string> disabled_features;
204  disabled_features.push_back("largeCursor");
205  disabled_features.push_back("highContrast");
206  disabled_features.push_back("screenMagnifier");
207
208  ASSERT_TRUE(
209      InitPrefServiceForTest(GetPrefs(), enabled_features, disabled_features));
210
211  std::string test_arg;
212  ASSERT_TRUE(GenerateTestArg(
213      "setterTest", enabled_features, disabled_features, &test_arg));
214
215  // The test extension attempts to flip all feature values.
216  ASSERT_TRUE(
217      RunPlatformAppTestWithArg(GetTestExtensionPath(), test_arg.c_str()));
218
219  // The test tries to flip the feature states.
220  if (ShouldModifyingFeatureSucceed()) {
221    VerifyPrefServiceState(GetPrefs(), disabled_features, enabled_features);
222  } else {
223    VerifyPrefServiceState(GetPrefs(), enabled_features, disabled_features);
224  }
225}
226
227// Tests that an extension with read permission is notified when accessibility
228// features change.
229IN_PROC_BROWSER_TEST_F(AccessibilityFeaturesApiTest, ObserveFeatures) {
230  std::vector<std::string> enabled_features;
231  enabled_features.push_back("largeCursor");
232  enabled_features.push_back("stickyKeys");
233  enabled_features.push_back("highContrast");
234
235  std::vector<std::string> disabled_features;
236  disabled_features.push_back("screenMagnifier");
237
238  ASSERT_TRUE(
239      InitPrefServiceForTest(GetPrefs(), enabled_features, disabled_features));
240
241  std::string test_arg;
242  ASSERT_TRUE(GenerateTestArg(
243      "observerTest", enabled_features, disabled_features, &test_arg));
244
245  // The test extension is supposed to report result twice when runnign this
246  // test. First time when in initializes it's feature listeners, and second
247  // time, when gets all expected events. This is done so the extension is
248  // running when the accessibility features are flipped; oterwise, the
249  // extension may not see events.
250  ASSERT_TRUE(RunPlatformAppTestWithArg(kTestExtensionPathReadPermission,
251                                        test_arg.c_str()));
252
253  // This should flip all features.
254  ASSERT_TRUE(
255      InitPrefServiceForTest(GetPrefs(), disabled_features, enabled_features));
256
257  // Catch the second result notification sent by the test extension.
258  ResultCatcher result_catcher;
259  ASSERT_TRUE(result_catcher.GetNextResult()) << result_catcher.message();
260}
261
262}  // namespace
263
264}  // namespace extensions
265