Commit 5c6c8e99 authored by Julie Jeongeun Kim's avatar Julie Jeongeun Kim Committed by Commit Bot

a11y: Enable accessibility on auralinux when API calls are made

This change introduces a mechanism to enable accessibility (on
auralinux) by creating the kApplication node and waiting until there
is a API query to enable accessibility fully. This is done to ensure
chromium will avoid performance overhead for users who don't need
accessibility, by not creating ATKObjects when they are not being
used.

Accessibility is enabled when one of two conditions are met:

1. A client queries an ATKObject API.
2. An AXMode is set on AccessibilityNotificationWaiter (used during
   testing).

This is implemented by using AXMode set on the AXPlatformNode, when
this is set it will allow for all ATK objects to be created. This
change does not remove the need to specify environmental variables and
the commandline flag.

The original author of this patch is Jessica Tallon<jtallon@igalia.com>

Bug: 977112
Change-Id: Ie5e46347296507d214df345320d3d58c9921c84d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2060359Reviewed-by: default avatarScott Violet <sky@chromium.org>
Reviewed-by: default avatarDominic Mazzoni <dmazzoni@chromium.org>
Commit-Queue: Julie Kim <jkim@igalia.com>
Cr-Commit-Position: refs/heads/master@{#744905}
parent 77e94e1a
......@@ -555,6 +555,8 @@ void AccessibilityUIMessageHandler::RequestWebContentsTree(
// because we are about to show the accessibility tree
web_contents->SetAccessibilityMode(
ui::AXMode(ui::AXMode::kNativeAPIs | ui::AXMode::kWebContents));
// Enable AXMode to access to AX objects.
ui::AXPlatformNode::NotifyAddAXModeFlags(ui::kAXModeComplete);
std::vector<content::AccessibilityTreeFormatter::PropertyFilter>
property_filters;
......
......@@ -39,6 +39,7 @@
#include "components/autofill/core/browser/personal_data_manager_observer.h"
#include "components/autofill/core/browser/validation.h"
#include "components/autofill/core/common/autofill_features.h"
#include "content/public/browser/browser_accessibility_state.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/accessibility_notification_waiter.h"
......@@ -589,6 +590,8 @@ class AutofillAccessibilityTest : public AutofillTest {
// Test that autofill available state is correctly set on accessibility node.
IN_PROC_BROWSER_TEST_F(AutofillAccessibilityTest, TestAutofillState) {
content::BrowserAccessibilityState::GetInstance()->EnableAccessibility();
// Navigate to url.
GURL url =
embedded_test_server()->GetURL("/autofill/duplicate_profiles_test.html");
......@@ -596,10 +599,9 @@ IN_PROC_BROWSER_TEST_F(AutofillAccessibilityTest, TestAutofillState) {
params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
ui_test_utils::NavigateToURL(&params);
// Enable accessibility.
content::EnableAccessibilityForWebContents(web_contents());
// Wait for accessibility notification.
content::AccessibilityNotificationWaiter layout_waiter_one(
web_contents(), ui::kAXModeComplete, ax::mojom::Event::kLayoutComplete);
web_contents(), ui::kAXModeComplete, ax::mojom::Event::kLoadComplete);
layout_waiter_one.WaitForNotification();
// Focus target form field.
......@@ -639,7 +641,7 @@ IN_PROC_BROWSER_TEST_F(AutofillAccessibilityTest, TestAutofillState) {
// Reload page.
ui_test_utils::NavigateToURL(&params);
content::AccessibilityNotificationWaiter layout_waiter_two(
web_contents(), ui::kAXModeComplete, ax::mojom::Event::kLayoutComplete);
web_contents(), ui::kAXModeComplete, ax::mojom::Event::kLoadComplete);
layout_waiter_two.WaitForNotification();
// Focus target form field.
......@@ -661,6 +663,7 @@ IN_PROC_BROWSER_TEST_F(AutofillAccessibilityTest, TestAutofillState) {
// accessibility node. Test autocomplete in this file since it uses the same
// infrastructure as autofill.
IN_PROC_BROWSER_TEST_F(AutofillAccessibilityTest, TestAutocompleteState) {
content::BrowserAccessibilityState::GetInstance()->EnableAccessibility();
// Navigate to url.
GURL url =
embedded_test_server()->GetURL("/autofill/duplicate_profiles_test.html");
......@@ -668,10 +671,9 @@ IN_PROC_BROWSER_TEST_F(AutofillAccessibilityTest, TestAutocompleteState) {
params.disposition = WindowOpenDisposition::NEW_FOREGROUND_TAB;
ui_test_utils::NavigateToURL(&params);
// Enable accessibility.
content::EnableAccessibilityForWebContents(web_contents());
// Wait for accessibility notification.
content::AccessibilityNotificationWaiter layout_waiter_one(
web_contents(), ui::kAXModeComplete, ax::mojom::Event::kLayoutComplete);
web_contents(), ui::kAXModeComplete, ax::mojom::Event::kLoadComplete);
layout_waiter_one.WaitForNotification();
// Focus target form field.
......@@ -707,7 +709,7 @@ IN_PROC_BROWSER_TEST_F(AutofillAccessibilityTest, TestAutocompleteState) {
// Reload page.
ui_test_utils::NavigateToURL(&params);
content::AccessibilityNotificationWaiter layout_waiter_two(
web_contents(), ui::kAXModeComplete, ax::mojom::Event::kLayoutComplete);
web_contents(), ui::kAXModeComplete, ax::mojom::Event::kLoadComplete);
layout_waiter_two.WaitForNotification();
// Focus target form field.
......
......@@ -11,10 +11,17 @@
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "content/public/browser/render_widget_host_view.h"
#include "ui/accessibility/platform/ax_platform_node.h"
class AuraLinuxAccessibilityInProcessBrowserTest : public InProcessBrowserTest {
public:
void SetUp() override {
ui::AXPlatformNode::NotifyAddAXModeFlags(ui::kAXModeComplete);
InProcessBrowserTest::SetUp();
}
protected:
AuraLinuxAccessibilityInProcessBrowserTest() {}
AuraLinuxAccessibilityInProcessBrowserTest() = default;
void VerifyEmbedRelationships();
......
......@@ -34,11 +34,14 @@ class BrowserAccessibilityAuraLinuxTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityAuraLinuxTest);
};
BrowserAccessibilityAuraLinuxTest::BrowserAccessibilityAuraLinuxTest() {}
BrowserAccessibilityAuraLinuxTest::BrowserAccessibilityAuraLinuxTest() =
default;
BrowserAccessibilityAuraLinuxTest::~BrowserAccessibilityAuraLinuxTest() {}
BrowserAccessibilityAuraLinuxTest::~BrowserAccessibilityAuraLinuxTest() =
default;
void BrowserAccessibilityAuraLinuxTest::SetUp() {
ui::AXPlatformNode::NotifyAddAXModeFlags(ui::kAXModeComplete);
test_browser_accessibility_delegate_ =
std::make_unique<TestBrowserAccessibilityDelegate>();
}
......
......@@ -215,6 +215,9 @@ void BrowserAccessibilityStateImpl::AddAccessibilityModeFlags(ui::AXMode mode) {
if (accessibility_mode_ == previous_mode)
return;
// Proxy the AXMode to AXPlatformNode to enable accessibility.
ui::AXPlatformNode::NotifyAddAXModeFlags(accessibility_mode_);
// Retrieve only newly added modes for the purposes of logging.
int new_mode_flags = mode.mode() & (~previous_mode.mode());
if (new_mode_flags & ui::AXMode::kNativeAPIs)
......
......@@ -28,11 +28,12 @@ class BrowserAccessibilityTest : public testing::Test {
DISALLOW_COPY_AND_ASSIGN(BrowserAccessibilityTest);
};
BrowserAccessibilityTest::BrowserAccessibilityTest() {}
BrowserAccessibilityTest::BrowserAccessibilityTest() = default;
BrowserAccessibilityTest::~BrowserAccessibilityTest() {}
BrowserAccessibilityTest::~BrowserAccessibilityTest() = default;
void BrowserAccessibilityTest::SetUp() {
ui::AXPlatformNode::NotifyAddAXModeFlags(ui::kAXModeComplete);
test_browser_accessibility_delegate_ =
std::make_unique<TestBrowserAccessibilityDelegate>();
}
......
......@@ -15,6 +15,7 @@
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_accessibility_state.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_plugin_guest_manager.h"
#include "content/public/browser/web_contents.h"
......@@ -44,6 +45,11 @@ AccessibilityNotificationWaiter::AccessibilityNotificationWaiter(
ListenToAllFrames(web_contents);
static_cast<WebContentsImpl*>(web_contents)
->AddAccessibilityMode(accessibility_mode);
// Add the the accessibility mode on BrowserAccessibilityState so it can be
// also be added to AXPlatformNode, auralinux uses this to determine if it
// should enable accessibility or not.
BrowserAccessibilityState::GetInstance()->AddAccessibilityModeFlags(
accessibility_mode);
}
AccessibilityNotificationWaiter::AccessibilityNotificationWaiter(
......@@ -57,9 +63,14 @@ AccessibilityNotificationWaiter::AccessibilityNotificationWaiter(
ListenToAllFrames(web_contents);
static_cast<WebContentsImpl*>(web_contents)
->AddAccessibilityMode(accessibility_mode);
// Add the the accessibility mode on BrowserAccessibilityState so it can be
// also be added to AXPlatformNode, auralinux uses this to determine if it
// should enable accessibility or not.
BrowserAccessibilityState::GetInstance()->AddAccessibilityModeFlags(
accessibility_mode);
}
AccessibilityNotificationWaiter::~AccessibilityNotificationWaiter() {}
AccessibilityNotificationWaiter::~AccessibilityNotificationWaiter() = default;
void AccessibilityNotificationWaiter::ListenToAllFrames(
WebContents* web_contents) {
......
......@@ -22,6 +22,10 @@ class AXPlatformNodeAuraLinuxTest : public AXPlatformNodeTest {
AXPlatformNodeAuraLinuxTest& operator=(const AXPlatformNodeAuraLinuxTest&) =
delete;
void SetUp() override {
AXPlatformNode::NotifyAddAXModeFlags(kAXModeComplete);
}
protected:
AXPlatformNodeAuraLinux* GetPlatformNode(AXNode* node) {
TestAXNodeWrapper* wrapper =
......
......@@ -63,6 +63,10 @@ TEST(AXPlatformNodeBaseTest, InnerTextIgnoresInvisibleAndIgnored) {
auto* root = static_cast<AXPlatformNodeBase*>(
TestAXNodeWrapper::GetOrCreate(&tree, tree.root())->ax_platform_node());
// Set an AXMode on the AXPlatformNode as some platforms (auralinux) use it to
// determine if it should enable accessibility.
AXPlatformNodeBase::NotifyAddAXModeFlags(kAXModeComplete);
EXPECT_EQ(root->GetInnerText(), base::UTF8ToUTF16("abde"));
// Setting invisible or ignored on a static text node causes it to be included
......
......@@ -13,6 +13,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/platform/ax_platform_node.h"
#include "ui/accessibility/platform/ax_platform_node_delegate.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
......@@ -51,6 +52,7 @@ class AXVirtualViewTest : public ViewsTestBase {
void SetUp() override {
ViewsTestBase::SetUp();
ui::AXPlatformNode::NotifyAddAXModeFlags(ui::kAXModeComplete);
widget_ = new Widget;
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
......
......@@ -175,9 +175,6 @@ ViewAXPlatformNodeDelegateAuraLinux::ViewAXPlatformNodeDelegateAuraLinux(
view->AddObserver(this);
}
ViewAXPlatformNodeDelegateAuraLinux::~ViewAXPlatformNodeDelegateAuraLinux() =
default;
gfx::NativeViewAccessible ViewAXPlatformNodeDelegateAuraLinux::GetParent() {
if (gfx::NativeViewAccessible parent =
ViewAXPlatformNodeDelegate::GetParent())
......
......@@ -20,7 +20,6 @@ class ViewAXPlatformNodeDelegateAuraLinux : public ViewAXPlatformNodeDelegate,
const ViewAXPlatformNodeDelegateAuraLinux&) = delete;
ViewAXPlatformNodeDelegateAuraLinux& operator=(
const ViewAXPlatformNodeDelegateAuraLinux&) = delete;
~ViewAXPlatformNodeDelegateAuraLinux() override;
// |ViewAXPlatformNodeDelegate| overrides:
gfx::NativeViewAccessible GetParent() override;
......
......@@ -6,6 +6,7 @@
#include <atk/atk.h>
#include "ui/accessibility/platform/ax_platform_node.h"
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/test/views_test_base.h"
......@@ -16,6 +17,10 @@ class ViewAXPlatformNodeDelegateAuraLinuxTest : public ViewsTestBase {
public:
ViewAXPlatformNodeDelegateAuraLinuxTest() = default;
~ViewAXPlatformNodeDelegateAuraLinuxTest() override = default;
void SetUp() override {
ViewsTestBase::SetUp();
ui::AXPlatformNode::NotifyAddAXModeFlags(ui::kAXModeComplete);
}
};
TEST_F(ViewAXPlatformNodeDelegateAuraLinuxTest, TextfieldAccessibility) {
......
......@@ -8,6 +8,7 @@
#include "ui/accessibility/ax_action_data.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/platform/ax_platform_node.h"
#include "ui/accessibility/platform/ax_platform_node_base.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_conversions.h"
......@@ -48,6 +49,7 @@ class ViewAXPlatformNodeDelegateTest : public ViewsTestBase {
void SetUp() override {
ViewsTestBase::SetUp();
ui::AXPlatformNode::NotifyAddAXModeFlags(ui::kAXModeComplete);
widget_ = new Widget;
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
......
......@@ -18,6 +18,7 @@
#include "ipc/ipc_message.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/platform/ax_platform_node.h"
#include "ui/events/event.h"
#include "ui/views/focus/focus_manager.h"
#include "ui/views/views_delegate.h"
......@@ -32,6 +33,16 @@ WebView::WebContentsCreator* GetCreatorForTesting() {
return creator.get();
}
// Updates the parent accessible object on the NativeView. As WebView overrides
// GetNativeViewAccessible() to return the accessible from the WebContents, it
// needs to ensure the accessible from the parent is set on the NativeView.
void UpdateNativeViewHostAccessibleParent(NativeViewHost* holder,
View* parent) {
if (!parent)
return;
holder->SetParentAccessible(parent->GetNativeViewAccessible());
}
} // namespace
WebView::ScopedWebContentsCreatorForTesting::ScopedWebContentsCreatorForTesting(
......@@ -49,9 +60,12 @@ WebView::ScopedWebContentsCreatorForTesting::
// WebView, public:
WebView::WebView(content::BrowserContext* browser_context)
: browser_context_(browser_context) {}
: browser_context_(browser_context) {
ui::AXPlatformNode::AddAXModeObserver(this);
}
WebView::~WebView() {
ui::AXPlatformNode::RemoveAXModeObserver(this);
SetWebContents(nullptr); // Make sure all necessary tear-down takes place.
}
......@@ -251,6 +265,17 @@ gfx::NativeViewAccessible WebView::GetNativeViewAccessible() {
return View::GetNativeViewAccessible();
}
void WebView::OnAXModeAdded(ui::AXMode mode) {
if (!web_contents())
return;
// Normally, it is set during AttachWebContentsNativeView when the WebView is
// created but this may not happen on some platforms as the accessible object
// may not have been present when this WebView was created. So, update it when
// AX mode is added.
UpdateNativeViewHostAccessibleParent(holder(), parent());
}
////////////////////////////////////////////////////////////////////////////////
// WebView, content::WebContentsDelegate implementation:
......@@ -363,8 +388,7 @@ void WebView::AttachWebContentsNativeView() {
holder_->Layout();
// We set the parent accessible of the native view to be our parent.
if (parent())
holder_->SetParentAccessible(parent()->GetNativeViewAccessible());
UpdateNativeViewHostAccessibleParent(holder(), parent());
// The WebContents is not focused automatically when attached, so we need to
// tell the WebContents it has focus if this has focus.
......
......@@ -13,6 +13,7 @@
#include "base/macros.h"
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
#include "ui/accessibility/ax_mode_observer.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/views/controls/native/native_view_host.h"
#include "ui/views/controls/webview/webview_export.h"
......@@ -36,7 +37,8 @@ namespace views {
// whenever possible.
class WEBVIEW_EXPORT WebView : public View,
public content::WebContentsDelegate,
public content::WebContentsObserver {
public content::WebContentsObserver,
public ui::AXModeObserver {
public:
METADATA_HEADER(WebView);
......@@ -158,6 +160,9 @@ class WEBVIEW_EXPORT WebView : public View,
content::RenderWidgetHost* render_widget_host) override;
void RenderProcessGone(base::TerminationStatus status) override;
// Override from ui::AXModeObserver
void OnAXModeAdded(ui::AXMode mode) override;
private:
friend class WebViewUnitTest;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment