accessibility_features_apitest.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
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::kSpokenFeedbackEnabled;
72    if (feature == "largeCursor")
73      return prefs::kLargeCursorEnabled;
74    if (feature == "stickyKeys")
75      return prefs::kStickyKeysEnabled;
76    if (feature == "highContrast")
77      return prefs::kHighContrastEnabled;
78    if (feature == "screenMagnifier")
79      return prefs::kScreenMagnifierEnabled;
80    if (feature == "autoclick")
81      return prefs::kAutoclickEnabled;
82    if (feature == "virtualKeyboard")
83      return prefs::kVirtualKeyboardEnabled;
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
164INSTANTIATE_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.
170IN_PROC_BROWSER_TEST_P(AccessibilityFeaturesApiTest, Get) {
171  std::vector<std::string> enabled_features;
172  enabled_features.push_back("largeCursor");
173  enabled_features.push_back("stickyKeys");
174  enabled_features.push_back("highContrast");
175
176  std::vector<std::string> disabled_features;
177  disabled_features.push_back("spokenFeedback");
178  disabled_features.push_back("screenMagnifier");
179  disabled_features.push_back("autoclick");
180  disabled_features.push_back("virtualKeyboard");
181
182  ASSERT_TRUE(
183      InitPrefServiceForTest(GetPrefs(), enabled_features, disabled_features));
184
185  std::string test_arg;
186  ASSERT_TRUE(GenerateTestArg(
187      "getterTest", enabled_features, disabled_features, &test_arg));
188  EXPECT_TRUE(
189      RunPlatformAppTestWithArg(GetTestExtensionPath(), test_arg.c_str()));
190}
191
192// Tests that an extension with modify permission can modify accessibility
193// features, while an extension that doesn't have the permission can't.
194IN_PROC_BROWSER_TEST_P(AccessibilityFeaturesApiTest, Set) {
195  std::vector<std::string> enabled_features;
196  enabled_features.push_back("spokenFeedback");
197  enabled_features.push_back("stickyKeys");
198  enabled_features.push_back("autoclick");
199  enabled_features.push_back("virtualKeyboard");
200
201  std::vector<std::string> disabled_features;
202  disabled_features.push_back("largeCursor");
203  disabled_features.push_back("highContrast");
204  disabled_features.push_back("screenMagnifier");
205
206  ASSERT_TRUE(
207      InitPrefServiceForTest(GetPrefs(), enabled_features, disabled_features));
208
209  std::string test_arg;
210  ASSERT_TRUE(GenerateTestArg(
211      "setterTest", enabled_features, disabled_features, &test_arg));
212
213  // The test extension attempts to flip all feature values.
214  ASSERT_TRUE(
215      RunPlatformAppTestWithArg(GetTestExtensionPath(), test_arg.c_str()));
216
217  // The test tries to flip the feature states.
218  if (ShouldModifyingFeatureSucceed()) {
219    VerifyPrefServiceState(GetPrefs(), disabled_features, enabled_features);
220  } else {
221    VerifyPrefServiceState(GetPrefs(), enabled_features, disabled_features);
222  }
223}
224
225// Tests that an extension with read permission is notified when accessibility
226// features change.
227IN_PROC_BROWSER_TEST_F(AccessibilityFeaturesApiTest, ObserveFeatures) {
228  std::vector<std::string> enabled_features;
229  enabled_features.push_back("largeCursor");
230  enabled_features.push_back("stickyKeys");
231  enabled_features.push_back("highContrast");
232
233  std::vector<std::string> disabled_features;
234  disabled_features.push_back("screenMagnifier");
235
236  ASSERT_TRUE(
237      InitPrefServiceForTest(GetPrefs(), enabled_features, disabled_features));
238
239  std::string test_arg;
240  ASSERT_TRUE(GenerateTestArg(
241      "observerTest", enabled_features, disabled_features, &test_arg));
242
243  // The test extension is supposed to report result twice when runnign this
244  // test. First time when in initializes it's feature listeners, and second
245  // time, when gets all expected events. This is done so the extension is
246  // running when the accessibility features are flipped; oterwise, the
247  // extension may not see events.
248  ASSERT_TRUE(RunPlatformAppTestWithArg(kTestExtensionPathReadPermission,
249                                        test_arg.c_str()));
250
251  // This should flip all features.
252  ASSERT_TRUE(
253      InitPrefServiceForTest(GetPrefs(), disabled_features, enabled_features));
254
255  // Catch the second result notification sent by the test extension.
256  ResultCatcher result_catcher;
257  ASSERT_TRUE(result_catcher.GetNextResult()) << result_catcher.message();
258}
259
260}  // namespace
261
262}  // namespace extensions
263