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 "base/command_line.h"
6#include "base/files/file_path.h"
7#include "base/location.h"
8#include "base/path_service.h"
9#include "base/single_thread_task_runner.h"
10#include "base/strings/string_number_conversions.h"
11#include "base/test/scoped_feature_list.h"
12#include "base/threading/thread_task_runner_handle.h"
13#include "build/build_config.h"
14#include "chrome/browser/extensions/api/automation_internal/automation_event_router.h"
15#include "chrome/browser/extensions/chrome_extension_function.h"
16#include "chrome/browser/extensions/extension_apitest.h"
17#include "chrome/browser/ui/tabs/tab_strip_model.h"
18#include "chrome/common/chrome_paths.h"
19#include "chrome/common/chrome_switches.h"
20#include "chrome/common/extensions/api/automation_internal.h"
21#include "chrome/common/extensions/chrome_extension_messages.h"
22#include "chrome/common/pref_names.h"
23#include "chrome/test/base/ui_test_utils.h"
24#include "components/prefs/pref_service.h"
25#include "content/public/browser/ax_event_notification_details.h"
26#include "content/public/browser/render_widget_host.h"
27#include "content/public/browser/render_widget_host_view.h"
28#include "content/public/browser/web_contents.h"
29#include "content/public/common/content_features.h"
30#include "extensions/test/extension_test_message_listener.h"
31#include "net/dns/mock_host_resolver.h"
32#include "net/test/embedded_test_server/embedded_test_server.h"
33#include "testing/gtest/include/gtest/gtest.h"
34#include "ui/accessibility/accessibility_switches.h"
35#include "ui/accessibility/ax_node.h"
36#include "ui/accessibility/ax_serializable_tree.h"
37#include "ui/accessibility/ax_tree.h"
38#include "ui/accessibility/ax_tree_serializer.h"
39#include "ui/accessibility/tree_generator.h"
40#include "ui/display/display_switches.h"
41
42#if defined(OS_CHROMEOS)
43#include "ash/accelerators/accelerator_controller.h"
44#include "ash/shell.h"
45#include "chrome/browser/ui/aura/accessibility/automation_manager_aura.h"
46#endif
47
48namespace extensions {
49
50namespace {
51static const char kDomain[] = "a.com";
52static const char kSitesDir[] = "automation/sites";
53static const char kGotTree[] = "got_tree";
54} // anonymous namespace
55
56class AutomationApiTest : public ExtensionApiTest {
57 protected:
58 GURL GetURLForPath(const std::string& host, const std::string& path) {
59 std::string port = base::NumberToString(embedded_test_server()->port());
60 GURL::Replacements replacements;
61 replacements.SetHostStr(host);
62 replacements.SetPortStr(port);
63 GURL url =
64 embedded_test_server()->GetURL(path).ReplaceComponents(replacements);
65 return url;
66 }
67
68 void StartEmbeddedTestServer() {
69 base::FilePath test_data;
70 ASSERT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &test_data));
71 embedded_test_server()->ServeFilesFromDirectory(
72 test_data.AppendASCII("extensions/api_test")
73 .AppendASCII(kSitesDir));
74 ASSERT_TRUE(ExtensionApiTest::StartEmbeddedTestServer());
75 }
76
77 public:
78 void SetUp() override {
79 scoped_feature_list_.InitAndEnableFeature(
80 features::kExperimentalAccessibilityLabels);
81 ExtensionApiTest::SetUp();
82 }
83
84 void SetUpOnMainThread() override {
85 ExtensionApiTest::SetUpOnMainThread();
86 host_resolver()->AddRule("*", "127.0.0.1");
87 }
88
89 base::test::ScopedFeatureList scoped_feature_list_;
90};
91
92IN_PROC_BROWSER_TEST_F(AutomationApiTest, TestRendererAccessibilityEnabled) {
93 StartEmbeddedTestServer();
94 const GURL url = GetURLForPath(kDomain, "/index.html");
95 ui_test_utils::NavigateToURL(browser(), url);
96
97 ASSERT_EQ(1, browser()->tab_strip_model()->count());
98 content::WebContents* const tab =
99 browser()->tab_strip_model()->GetWebContentsAt(0);
100 ASSERT_FALSE(tab->IsFullAccessibilityModeForTesting());
101 ASSERT_FALSE(tab->IsWebContentsOnlyAccessibilityModeForTesting());
102
103 base::FilePath extension_path =
104 test_data_dir_.AppendASCII("automation/tests/basic");
105 ExtensionTestMessageListener got_tree(kGotTree, false /* no reply */);
106 LoadExtension(extension_path);
107 ASSERT_TRUE(got_tree.WaitUntilSatisfied());
108
109 ASSERT_FALSE(tab->IsFullAccessibilityModeForTesting());
110 ASSERT_TRUE(tab->IsWebContentsOnlyAccessibilityModeForTesting());
111}
112
113IN_PROC_BROWSER_TEST_F(AutomationApiTest, SanityCheck) {
114 StartEmbeddedTestServer();
115 ASSERT_TRUE(RunExtensionSubtest("automation/tests/tabs", "sanity_check.html"))
116 << message_;
117}
118
119IN_PROC_BROWSER_TEST_F(AutomationApiTest, ImageLabels) {
120 StartEmbeddedTestServer();
121 const GURL url = GetURLForPath(kDomain, "/index.html");
122 ui_test_utils::NavigateToURL(browser(), url);
123
124 // Enable image labels.
125 browser()->profile()->GetPrefs()->SetBoolean(
126 prefs::kAccessibilityImageLabelsEnabled, true);
127
128 // Initially there should be no accessibility mode set.
129 ASSERT_EQ(1, browser()->tab_strip_model()->count());
130 content::WebContents* const web_contents =
131 browser()->tab_strip_model()->GetWebContentsAt(0);
132 ASSERT_EQ(ui::AXMode(), web_contents->GetAccessibilityMode());
133
134 // Enable automation.
135 base::FilePath extension_path =
136 test_data_dir_.AppendASCII("automation/tests/basic");
137 ExtensionTestMessageListener got_tree(kGotTree, false /* no reply */);
138 LoadExtension(extension_path);
139 ASSERT_TRUE(got_tree.WaitUntilSatisfied());
140
141 // Now the AXMode should include kLabelImages.
142 ui::AXMode expected_mode = ui::kAXModeWebContentsOnly;
143 expected_mode.set_mode(ui::AXMode::kLabelImages, true);
144 EXPECT_EQ(expected_mode, web_contents->GetAccessibilityMode());
145}
146
147// TODO(aboxhall): Fix flakiness
148IN_PROC_BROWSER_TEST_F(AutomationApiTest, DISABLED_GetTreeByTabId) {
149 StartEmbeddedTestServer();
150 ASSERT_TRUE(RunExtensionSubtest("automation/tests/tabs", "tab_id.html"))
151 << message_;
152}
153
154IN_PROC_BROWSER_TEST_F(AutomationApiTest, Events) {
155 StartEmbeddedTestServer();
156 ASSERT_TRUE(RunExtensionSubtest("automation/tests/tabs", "events.html"))
157 << message_;
158}
159
160IN_PROC_BROWSER_TEST_F(AutomationApiTest, Actions) {
161 StartEmbeddedTestServer();
162 ASSERT_TRUE(RunExtensionSubtest("automation/tests/tabs", "actions.html"))
163 << message_;
164}
165
166IN_PROC_BROWSER_TEST_F(AutomationApiTest, Location) {
167 StartEmbeddedTestServer();
168 ASSERT_TRUE(RunExtensionSubtest("automation/tests/tabs", "location.html"))
169 << message_;
170}
171
172IN_PROC_BROWSER_TEST_F(AutomationApiTest, Location2) {
173 StartEmbeddedTestServer();
174 ASSERT_TRUE(RunExtensionSubtest("automation/tests/tabs", "location2.html"))
175 << message_;
176}
177
178IN_PROC_BROWSER_TEST_F(AutomationApiTest, BoundsForRange) {
179 StartEmbeddedTestServer();
180 ASSERT_TRUE(RunExtensionSubtest("automation/tests/tabs",
181 "bounds_for_range.html"))
182 << message_;
183}
184
185IN_PROC_BROWSER_TEST_F(AutomationApiTest, LineStartOffsets) {
186 StartEmbeddedTestServer();
187 ASSERT_TRUE(
188 RunExtensionSubtest("automation/tests/tabs", "line_start_offsets.html"))
189 << message_;
190}
191
192IN_PROC_BROWSER_TEST_F(AutomationApiTest, ImageData) {
193 StartEmbeddedTestServer();
194 ASSERT_TRUE(RunExtensionSubtest("automation/tests/tabs", "image_data.html"))
195 << message_;
196}
197
198IN_PROC_BROWSER_TEST_F(AutomationApiTest, TableProperties) {
199 StartEmbeddedTestServer();
200 ASSERT_TRUE(
201 RunExtensionSubtest("automation/tests/tabs", "table_properties.html"))
202 << message_;
203}
204
205IN_PROC_BROWSER_TEST_F(AutomationApiTest, TabsAutomationBooleanPermissions) {
206 StartEmbeddedTestServer();
207 ASSERT_TRUE(RunExtensionSubtest(
208 "automation/tests/tabs_automation_boolean", "permissions.html"))
209 << message_;
210}
211
212IN_PROC_BROWSER_TEST_F(AutomationApiTest, TabsAutomationBooleanActions) {
213 StartEmbeddedTestServer();
214 ASSERT_TRUE(RunExtensionSubtest(
215 "automation/tests/tabs_automation_boolean", "actions.html"))
216 << message_;
217}
218
219IN_PROC_BROWSER_TEST_F(AutomationApiTest, TabsAutomationHostsPermissions) {
220 StartEmbeddedTestServer();
221 ASSERT_TRUE(RunExtensionSubtest(
222 "automation/tests/tabs_automation_hosts", "permissions.html"))
223 << message_;
224}
225
226#if defined(USE_AURA)
227// TODO(https://crbug.com/754870): Disabled due to flakiness.
228IN_PROC_BROWSER_TEST_F(AutomationApiTest, DISABLED_Desktop) {
229 ASSERT_TRUE(RunExtensionSubtest("automation/tests/desktop", "desktop.html"))
230 << message_;
231}
232
233#if defined(OS_CHROMEOS)
234// TODO(https://crbug.com/754870): Flaky on CrOS sanitizers.
235IN_PROC_BROWSER_TEST_F(AutomationApiTest, DISABLED_DesktopInitialFocus) {
236 ASSERT_TRUE(
237 RunExtensionSubtest("automation/tests/desktop", "initial_focus.html"))
238 << message_;
239}
240
241IN_PROC_BROWSER_TEST_F(AutomationApiTest, DesktopFocusWeb) {
242 ASSERT_TRUE(
243 RunExtensionSubtest("automation/tests/desktop", "focus_web.html"))
244 << message_;
245}
246
247// TODO(https://crbug.com/622387): flaky.
248IN_PROC_BROWSER_TEST_F(AutomationApiTest, DISABLED_DesktopFocusIframe) {
249 StartEmbeddedTestServer();
250 ASSERT_TRUE(
251 RunExtensionSubtest("automation/tests/desktop", "focus_iframe.html"))
252 << message_;
253}
254
255// TODO(https://crbug.com/622387): flaky.
256IN_PROC_BROWSER_TEST_F(AutomationApiTest, DISABLED_DesktopHitTestIframe) {
257 StartEmbeddedTestServer();
258 ASSERT_TRUE(
259 RunExtensionSubtest("automation/tests/desktop", "hit_test_iframe.html"))
260 << message_;
261}
262
263// TODO(https://crbug.com/892960): flaky.
264IN_PROC_BROWSER_TEST_F(AutomationApiTest, DISABLED_DesktopFocusViews) {
265 AutomationManagerAura::GetInstance()->Enable();
266 // Trigger the shelf subtree to be computed.
267 ash::Shell::Get()->accelerator_controller()->PerformActionIfEnabled(
268 ash::FOCUS_SHELF);
269
270 ASSERT_TRUE(
271 RunExtensionSubtest("automation/tests/desktop", "focus_views.html"))
272 << message_;
273}
274
275IN_PROC_BROWSER_TEST_F(AutomationApiTest, DesktopGetNextTextMatch) {
276 StartEmbeddedTestServer();
277 ASSERT_TRUE(RunExtensionSubtest("automation/tests/desktop",
278 "get_next_text_match.html"))
279 << message_;
280}
281
282IN_PROC_BROWSER_TEST_F(AutomationApiTest, LocationInWebView) {
283 StartEmbeddedTestServer();
284 ASSERT_TRUE(RunPlatformAppTest("automation/tests/webview")) << message_;
285}
286#endif
287
288IN_PROC_BROWSER_TEST_F(AutomationApiTest, DesktopNotRequested) {
289 ASSERT_TRUE(RunExtensionSubtest("automation/tests/tabs",
290 "desktop_not_requested.html")) << message_;
291}
292
293#if defined(OS_CHROMEOS)
294// TODO(https://crbug.com/894016): flaky.
295IN_PROC_BROWSER_TEST_F(AutomationApiTest, DISABLED_DesktopActions) {
296 AutomationManagerAura::GetInstance()->Enable();
297 // Trigger the shelf subtree to be computed.
298 ash::Shell::Get()->accelerator_controller()->PerformActionIfEnabled(
299 ash::FOCUS_SHELF);
300
301 ASSERT_TRUE(RunExtensionSubtest("automation/tests/desktop", "actions.html"))
302 << message_;
303}
304
305IN_PROC_BROWSER_TEST_F(AutomationApiTest, DesktopHitTest) {
306 ASSERT_TRUE(RunExtensionSubtest("automation/tests/desktop", "hit_test.html"))
307 << message_;
308}
309
310// TODO(https://crbug.com/754870): flaky.
311IN_PROC_BROWSER_TEST_F(AutomationApiTest, DISABLED_DesktopLoadTabs) {
312 ASSERT_TRUE(RunExtensionSubtest("automation/tests/desktop", "load_tabs.html"))
313 << message_;
314}
315#endif // defined(OS_CHROMEOS)
316#else // !defined(USE_AURA)
317IN_PROC_BROWSER_TEST_F(AutomationApiTest, DesktopNotSupported) {
318 ASSERT_TRUE(RunExtensionSubtest("automation/tests/desktop",
319 "desktop_not_supported.html"))
320 << message_;
321}
322#endif // defined(USE_AURA)
323
324// Flaky test on site_per_browser_tests: https://crbug.com/833318
325IN_PROC_BROWSER_TEST_F(AutomationApiTest, DISABLED_CloseTab) {
326 StartEmbeddedTestServer();
327 ASSERT_TRUE(RunExtensionSubtest("automation/tests/tabs", "close_tab.html"))
328 << message_;
329}
330
331IN_PROC_BROWSER_TEST_F(AutomationApiTest, QuerySelector) {
332 StartEmbeddedTestServer();
333 ASSERT_TRUE(
334 RunExtensionSubtest("automation/tests/tabs", "queryselector.html"))
335 << message_;
336}
337
338IN_PROC_BROWSER_TEST_F(AutomationApiTest, Find) {
339 StartEmbeddedTestServer();
340 ASSERT_TRUE(RunExtensionSubtest("automation/tests/tabs", "find.html"))
341 << message_;
342}
343
344IN_PROC_BROWSER_TEST_F(AutomationApiTest, Attributes) {
345 StartEmbeddedTestServer();
346 ASSERT_TRUE(RunExtensionSubtest("automation/tests/tabs", "attributes.html"))
347 << message_;
348}
349
350IN_PROC_BROWSER_TEST_F(AutomationApiTest, ReverseRelations) {
351 StartEmbeddedTestServer();
352 ASSERT_TRUE(
353 RunExtensionSubtest("automation/tests/tabs", "reverse_relations.html"))
354 << message_;
355}
356
357IN_PROC_BROWSER_TEST_F(AutomationApiTest, TreeChange) {
358 StartEmbeddedTestServer();
359 ASSERT_TRUE(RunExtensionSubtest("automation/tests/tabs", "tree_change.html"))
360 << message_;
361}
362
363IN_PROC_BROWSER_TEST_F(AutomationApiTest, TreeChangeIndirect) {
364 StartEmbeddedTestServer();
365 ASSERT_TRUE(
366 RunExtensionSubtest("automation/tests/tabs", "tree_change_indirect.html"))
367 << message_;
368}
369
370IN_PROC_BROWSER_TEST_F(AutomationApiTest, DocumentSelection) {
371 StartEmbeddedTestServer();
372 ASSERT_TRUE(
373 RunExtensionSubtest("automation/tests/tabs", "document_selection.html"))
374 << message_;
375}
376
377IN_PROC_BROWSER_TEST_F(AutomationApiTest, HitTest) {
378 StartEmbeddedTestServer();
379 ASSERT_TRUE(RunExtensionSubtest("automation/tests/tabs", "hit_test.html"))
380 << message_;
381}
382
383class AutomationApiTestWithLanguageDetection : public AutomationApiTest {
384 protected:
385 void SetUpCommandLine(base::CommandLine* command_line) override {
386 AutomationApiTest::SetUpCommandLine(command_line);
387 command_line->AppendSwitch(
388 ::switches::kEnableExperimentalAccessibilityLanguageDetection);
389 }
390};
391
392IN_PROC_BROWSER_TEST_F(AutomationApiTestWithLanguageDetection,
393 DetectedLanguage) {
394 StartEmbeddedTestServer();
395 ASSERT_TRUE(
396 RunExtensionSubtest("automation/tests/tabs", "detected_language.html"))
397 << message_;
398}
399
400#if defined(OS_CHROMEOS)
401
402class AutomationApiTestWithDeviceScaleFactor : public AutomationApiTest {
403 protected:
404 void SetUpCommandLine(base::CommandLine* command_line) override {
405 AutomationApiTest::SetUpCommandLine(command_line);
406 command_line->AppendSwitchASCII(switches::kForceDeviceScaleFactor, "2.0");
407 }
408};
409
410IN_PROC_BROWSER_TEST_F(AutomationApiTestWithDeviceScaleFactor, LocationScaled) {
411 StartEmbeddedTestServer();
412 ASSERT_TRUE(RunPlatformAppTest("automation/tests/location_scaled"))
413 << message_;
414}
415
416IN_PROC_BROWSER_TEST_F(AutomationApiTestWithDeviceScaleFactor, HitTest) {
417 StartEmbeddedTestServer();
418 ASSERT_TRUE(RunExtensionSubtest("automation/tests/desktop", "hit_test.html"))
419 << message_;
420}
421
422#endif // defined(OS_CHROMEOS)
423
424} // namespace extensions
425