blob: 74b663c213362762a4379edfdfb6e4a75579042b [file] [log] [blame]
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "build/build_config.h"
#include "content/browser/accessibility/browser_accessibility.h"
#include "content/browser/accessibility/browser_accessibility_manager.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/test/accessibility_notification_waiter.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/content_browser_test.h"
#include "content/public/test/content_browser_test_utils.h"
#include "content/shell/browser/shell.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
class AccessibilityLineLayoutBrowserTest : public ContentBrowserTest {
public:
AccessibilityLineLayoutBrowserTest() = default;
~AccessibilityLineLayoutBrowserTest() override = default;
protected:
BrowserAccessibility* FindButton(BrowserAccessibility* node) {
if (node->GetRole() == ax::mojom::Role::kButton)
return node;
for (unsigned i = 0; i < node->PlatformChildCount(); i++) {
if (BrowserAccessibility* button = FindButton(node->PlatformGetChild(i)))
return button;
}
return nullptr;
}
int CountNextPreviousOnLineLinks(BrowserAccessibility* node,
bool do_not_count_inline_text) {
int line_link_count = 0;
if (do_not_count_inline_text &&
node->GetRole() == ax::mojom::Role::kInlineTextBox) {
int next_on_line_id =
node->GetIntAttribute(ax::mojom::IntAttribute::kNextOnLineId);
if (next_on_line_id != ui::kInvalidAXNodeID) {
BrowserAccessibility* other =
node->manager()->GetFromID(next_on_line_id);
EXPECT_NE(nullptr, other) << "Next on line link is invalid.";
line_link_count++;
}
int previous_on_line_id =
node->GetIntAttribute(ax::mojom::IntAttribute::kPreviousOnLineId);
if (previous_on_line_id != ui::kInvalidAXNodeID) {
BrowserAccessibility* other =
node->manager()->GetFromID(previous_on_line_id);
EXPECT_NE(nullptr, other) << "Previous on line link is invalid.";
line_link_count++;
}
}
for (auto it = node->InternalChildrenBegin();
it != node->InternalChildrenEnd(); ++it)
line_link_count +=
CountNextPreviousOnLineLinks(it.get(), do_not_count_inline_text);
return line_link_count;
}
};
// http://crbug.com/868830 - the patch that enabled this test to pass
// caused a performance regression.
IN_PROC_BROWSER_TEST_F(AccessibilityLineLayoutBrowserTest,
DISABLED_WholeBlockIsUpdated) {
ASSERT_TRUE(embedded_test_server()->Start());
AccessibilityNotificationWaiter waiter(shell()->web_contents(),
ui::kAXModeComplete,
ax::mojom::Event::kLoadComplete);
GURL url(embedded_test_server()->GetURL("/accessibility/lines/lines.html"));
EXPECT_TRUE(NavigateToURL(shell(), url));
ASSERT_TRUE(waiter.WaitForNotification());
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
BrowserAccessibilityManager* manager =
web_contents->GetRootBrowserAccessibilityManager();
// There should be at least 2 links between nodes on the same line.
int line_link_count = CountNextPreviousOnLineLinks(
manager->GetBrowserAccessibilityRoot(), false);
ASSERT_GE(line_link_count, 2);
// Find the button and click it.
BrowserAccessibility* button =
FindButton(manager->GetBrowserAccessibilityRoot());
ASSERT_NE(nullptr, button);
manager->DoDefaultAction(*button);
// When done the page will change the button text to "Done".
WaitForAccessibilityTreeToContainNodeWithName(web_contents, "Done");
// There should be at least 2 links between nodes on the same line,
// though not necessarily the same as before.
line_link_count = CountNextPreviousOnLineLinks(
manager->GetBrowserAccessibilityRoot(), false);
ASSERT_GE(line_link_count, 2);
}
// http://crbug.com/868830 - the patch that enabled this test to pass caused a
// performance regression. (Android doesn't generate InlineTextBoxes
// immediately; we can wait for them but without the aforementioned fix the
// updated tree isn't processed to create the Next/PreviousOnLine links.)
#if !BUILDFLAG(IS_ANDROID)
// TODO(crbug.com/41488668): Disabled on chromeos due to failing on
// linux-chromeos-dbg.
#if BUILDFLAG(IS_CHROMEOS)
#define MAYBE_NestedLayoutNGInlineFormattingContext \
DISABLED_NestedLayoutNGInlineFormattingContext
#else
#define MAYBE_NestedLayoutNGInlineFormattingContext \
NestedLayoutNGInlineFormattingContext
#endif
IN_PROC_BROWSER_TEST_F(AccessibilityLineLayoutBrowserTest,
MAYBE_NestedLayoutNGInlineFormattingContext) {
ASSERT_TRUE(embedded_test_server()->Start());
AccessibilityNotificationWaiter waiter(shell()->web_contents(),
ui::kAXModeComplete,
ax::mojom::Event::kLoadComplete);
GURL url(embedded_test_server()->GetURL(
"/accessibility/lines/lines-inline-nested.html"));
EXPECT_TRUE(NavigateToURL(shell(), url));
ASSERT_TRUE(waiter.WaitForNotification());
WebContentsImpl* web_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
BrowserAccessibilityManager* manager =
web_contents->GetRootBrowserAccessibilityManager();
AccessibilityNotificationWaiter waiter2(shell()->web_contents(),
ui::kAXModeComplete,
ax::mojom::Event::kTreeChanged);
manager->LoadInlineTextBoxes(*manager->GetBrowserAccessibilityRoot());
ASSERT_TRUE(waiter2.WaitForNotification());
// There are three pieces of text, and they should be cross-linked:
// before <-> inside <-> after
int line_link_count = CountNextPreviousOnLineLinks(
manager->GetBrowserAccessibilityRoot(), true);
ASSERT_EQ(line_link_count, 4);
}
#endif // !BUILDFLAG(IS_ANDROID)
} // namespace content