summaryrefslogtreecommitdiff
path: root/chromium/ui/views/accessibility
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/ui/views/accessibility')
-rw-r--r--chromium/ui/views/accessibility/accessibility_alert_window.cc2
-rw-r--r--chromium/ui/views/accessibility/accessibility_alert_window.h4
-rw-r--r--chromium/ui/views/accessibility/accessibility_alert_window_unittest.cc83
-rw-r--r--chromium/ui/views/accessibility/ax_tree_source_views.h2
-rw-r--r--chromium/ui/views/accessibility/ax_virtual_view.cc26
-rw-r--r--chromium/ui/views/accessibility/ax_virtual_view.h9
-rw-r--r--chromium/ui/views/accessibility/view_ax_platform_node_delegate.cc57
-rw-r--r--chromium/ui/views/accessibility/view_ax_platform_node_delegate.h11
-rw-r--r--chromium/ui/views/accessibility/view_ax_platform_node_delegate_auralinux_unittest.cc4
-rw-r--r--chromium/ui/views/accessibility/view_ax_platform_node_delegate_unittest.cc44
-rw-r--r--chromium/ui/views/accessibility/view_ax_platform_node_delegate_win_unittest.cc5
-rw-r--r--chromium/ui/views/accessibility/views_ax_tree_manager.h2
12 files changed, 221 insertions, 28 deletions
diff --git a/chromium/ui/views/accessibility/accessibility_alert_window.cc b/chromium/ui/views/accessibility/accessibility_alert_window.cc
index 4c5b0e47f60..9afdb5263f9 100644
--- a/chromium/ui/views/accessibility/accessibility_alert_window.cc
+++ b/chromium/ui/views/accessibility/accessibility_alert_window.cc
@@ -29,7 +29,7 @@ AccessibilityAlertWindow::AccessibilityAlertWindow(aura::Window* parent,
AccessibilityAlertWindow::~AccessibilityAlertWindow() = default;
void AccessibilityAlertWindow::HandleAlert(const std::string& alert_string) {
- if (!alert_window_->parent())
+ if (!alert_window_ || !alert_window_->parent())
return;
alert_window_->SetTitle(base::UTF8ToUTF16(alert_string));
diff --git a/chromium/ui/views/accessibility/accessibility_alert_window.h b/chromium/ui/views/accessibility/accessibility_alert_window.h
index 999c55e9f78..5895a714ea8 100644
--- a/chromium/ui/views/accessibility/accessibility_alert_window.h
+++ b/chromium/ui/views/accessibility/accessibility_alert_window.h
@@ -8,6 +8,7 @@
#include <memory>
#include <string>
+#include "base/gtest_prod_util.h"
#include "base/scoped_observer.h"
#include "ui/aura/env.h"
#include "ui/aura/env_observer.h"
@@ -35,6 +36,9 @@ class VIEWS_EXPORT AccessibilityAlertWindow : public aura::EnvObserver {
void HandleAlert(const std::string& alert_string);
private:
+ FRIEND_TEST_ALL_PREFIXES(AccessibilityAlertWindowTest, HandleAlert);
+ FRIEND_TEST_ALL_PREFIXES(AccessibilityAlertWindowTest, OnWillDestroyEnv);
+
// aura::EnvObserver:
void OnWillDestroyEnv() override;
diff --git a/chromium/ui/views/accessibility/accessibility_alert_window_unittest.cc b/chromium/ui/views/accessibility/accessibility_alert_window_unittest.cc
new file mode 100644
index 00000000000..60af94effee
--- /dev/null
+++ b/chromium/ui/views/accessibility/accessibility_alert_window_unittest.cc
@@ -0,0 +1,83 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/accessibility/accessibility_alert_window.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/accessibility/ax_enums.mojom.h"
+#include "ui/aura/window.h"
+#include "ui/compositor/layer_type.h"
+#include "ui/views/accessibility/ax_aura_obj_cache.h"
+#include "ui/views/accessibility/ax_aura_obj_wrapper.h"
+#include "ui/views/test/views_test_base.h"
+
+namespace views {
+
+class FakeAXAuraObjCacheDelegate : public AXAuraObjCache::Delegate {
+ public:
+ FakeAXAuraObjCacheDelegate() = default;
+ FakeAXAuraObjCacheDelegate(const FakeAXAuraObjCacheDelegate&) = delete;
+ FakeAXAuraObjCacheDelegate& operator=(const FakeAXAuraObjCacheDelegate&) =
+ delete;
+ ~FakeAXAuraObjCacheDelegate() override = default;
+
+ void OnChildWindowRemoved(AXAuraObjWrapper* parent) override {}
+ void OnEvent(AXAuraObjWrapper* aura_obj,
+ ax::mojom::Event event_type) override {
+ if (event_type == ax::mojom::Event::kAlert)
+ count_++;
+ }
+
+ int count() { return count_; }
+ void set_count(int count) { count_ = count; }
+
+ private:
+ int count_ = 0;
+};
+
+class AccessibilityAlertWindowTest : public ViewsTestBase {
+ public:
+ AccessibilityAlertWindowTest() = default;
+ AccessibilityAlertWindowTest(const AccessibilityAlertWindowTest&) = delete;
+ AccessibilityAlertWindowTest& operator=(const AccessibilityAlertWindowTest&) =
+ delete;
+ ~AccessibilityAlertWindowTest() override = default;
+
+ protected:
+ void SetUp() override {
+ ViewsTestBase::SetUp();
+
+ parent_ = std::make_unique<aura::Window>(nullptr);
+ parent_->Init(ui::LAYER_SOLID_COLOR);
+ }
+
+ std::unique_ptr<aura::Window> parent_;
+ AXAuraObjCache cache;
+};
+
+TEST_F(AccessibilityAlertWindowTest, HandleAlert) {
+ FakeAXAuraObjCacheDelegate delegate;
+ cache.SetDelegate(&delegate);
+
+ AccessibilityAlertWindow window(parent_.get(), &cache);
+
+ window.HandleAlert("test");
+ EXPECT_EQ(1, delegate.count());
+
+ delegate.set_count(0);
+ window.OnWillDestroyEnv();
+
+ window.HandleAlert("test");
+ EXPECT_EQ(0, delegate.count());
+}
+
+TEST_F(AccessibilityAlertWindowTest, OnWillDestroyEnv) {
+ AccessibilityAlertWindow window(parent_.get(), &cache);
+ window.OnWillDestroyEnv();
+
+ EXPECT_FALSE(window.observer_.IsObservingSources());
+ EXPECT_FALSE(window.alert_window_);
+}
+
+} // namespace views
diff --git a/chromium/ui/views/accessibility/ax_tree_source_views.h b/chromium/ui/views/accessibility/ax_tree_source_views.h
index 37317b530b5..a867cd971bc 100644
--- a/chromium/ui/views/accessibility/ax_tree_source_views.h
+++ b/chromium/ui/views/accessibility/ax_tree_source_views.h
@@ -61,6 +61,8 @@ class VIEWS_EXPORT AXTreeSourceViews
// Useful for debugging.
std::string ToString(views::AXAuraObjWrapper* root, std::string prefix);
+ const ui::AXTreeID tree_id_for_test() const { return tree_id_; }
+
private:
// The top-level object to use for the AX tree. See class comment.
AXAuraObjWrapper* const root_ = nullptr;
diff --git a/chromium/ui/views/accessibility/ax_virtual_view.cc b/chromium/ui/views/accessibility/ax_virtual_view.cc
index 060d4a77c65..cc9f8aae5fe 100644
--- a/chromium/ui/views/accessibility/ax_virtual_view.cc
+++ b/chromium/ui/views/accessibility/ax_virtual_view.cc
@@ -21,6 +21,7 @@
#include "ui/base/ui_base_types.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/views/accessibility/view_accessibility.h"
+#include "ui/views/accessibility/view_ax_platform_node_delegate.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
@@ -284,7 +285,7 @@ gfx::NativeViewAccessible AXVirtualView::ChildAtIndex(int index) {
return nullptr;
}
-#if !defined(OS_MACOSX)
+#if !defined(OS_APPLE)
gfx::NativeViewAccessible AXVirtualView::GetNSWindow() {
NOTREACHED();
return nullptr;
@@ -386,7 +387,10 @@ gfx::NativeViewAccessible AXVirtualView::GetFocus() {
}
ui::AXPlatformNode* AXVirtualView::GetFromNodeID(int32_t id) {
- // TODO(nektar): Implement.
+ AXVirtualView* virtual_view = GetFromId(id);
+ if (virtual_view) {
+ return virtual_view->ax_platform_node();
+ }
return nullptr;
}
@@ -423,6 +427,18 @@ gfx::AcceleratedWidget AXVirtualView::GetTargetForNativeAccessibilityEvent() {
return gfx::kNullAcceleratedWidget;
}
+base::Optional<bool> AXVirtualView::GetTableHasColumnOrRowHeaderNode() const {
+ return GetDelegate()->GetTableHasColumnOrRowHeaderNode();
+}
+
+std::vector<int32_t> AXVirtualView::GetColHeaderNodeIds() const {
+ return GetDelegate()->GetColHeaderNodeIds();
+}
+
+std::vector<int32_t> AXVirtualView::GetColHeaderNodeIds(int col_index) const {
+ return GetDelegate()->GetColHeaderNodeIds(col_index);
+}
+
bool AXVirtualView::IsIgnored() const {
return GetData().IsIgnored();
}
@@ -473,6 +489,12 @@ View* AXVirtualView::GetOwnerView() const {
return nullptr;
}
+ViewAXPlatformNodeDelegate* AXVirtualView::GetDelegate() const {
+ DCHECK(GetOwnerView());
+ return static_cast<ViewAXPlatformNodeDelegate*>(
+ &GetOwnerView()->GetViewAccessibility());
+}
+
AXVirtualViewWrapper* AXVirtualView::GetOrCreateWrapper(
views::AXAuraObjCache* cache) {
#if defined(USE_AURA)
diff --git a/chromium/ui/views/accessibility/ax_virtual_view.h b/chromium/ui/views/accessibility/ax_virtual_view.h
index 6b1f9eeda4a..299d106a01b 100644
--- a/chromium/ui/views/accessibility/ax_virtual_view.h
+++ b/chromium/ui/views/accessibility/ax_virtual_view.h
@@ -40,6 +40,7 @@ namespace views {
class AXAuraObjCache;
class View;
class ViewAccessibility;
+class ViewAXPlatformNodeDelegate;
// Implements a virtual view that is used only for accessibility.
//
@@ -99,6 +100,8 @@ class VIEWS_EXPORT AXVirtualView : public ui::AXPlatformNodeDelegateBase {
}
AXVirtualView* virtual_parent_view() { return virtual_parent_view_; }
+ ui::AXPlatformNode* ax_platform_node() { return ax_platform_node_; }
+
// Returns true if |view| is contained within the hierarchy of this
// AXVirtualView, even as an indirect descendant. Will return true if |view|
// is also this AXVirtualView.
@@ -153,10 +156,16 @@ class VIEWS_EXPORT AXVirtualView : public ui::AXPlatformNodeDelegateBase {
bool IsOffscreen() const override;
const ui::AXUniqueId& GetUniqueId() const override;
gfx::AcceleratedWidget GetTargetForNativeAccessibilityEvent() override;
+ base::Optional<bool> GetTableHasColumnOrRowHeaderNode() const override;
+ std::vector<int32_t> GetColHeaderNodeIds() const override;
+ std::vector<int32_t> GetColHeaderNodeIds(int col_index) const override;
// Gets the real View that owns our shallowest virtual ancestor,, if any.
View* GetOwnerView() const;
+ // Gets the view platform delegate if exists, otherwise nullptr.
+ ViewAXPlatformNodeDelegate* GetDelegate() const;
+
// Gets or creates a wrapper suitable for use with tree sources.
AXVirtualViewWrapper* GetOrCreateWrapper(views::AXAuraObjCache* cache);
diff --git a/chromium/ui/views/accessibility/view_ax_platform_node_delegate.cc b/chromium/ui/views/accessibility/view_ax_platform_node_delegate.cc
index 35dce74a77b..00b72e939ed 100644
--- a/chromium/ui/views/accessibility/view_ax_platform_node_delegate.cc
+++ b/chromium/ui/views/accessibility/view_ax_platform_node_delegate.cc
@@ -213,7 +213,7 @@ void ViewAXPlatformNodeDelegate::NotifyAccessibilityEvent(
ax_platform_node_->NotifyAccessibilityEvent(event_type);
}
-#if defined(OS_MACOSX)
+#if defined(OS_APPLE)
void ViewAXPlatformNodeDelegate::AnnounceText(const base::string16& text) {
ax_platform_node_->AnnounceText(text);
}
@@ -345,6 +345,10 @@ gfx::NativeViewAccessible ViewAXPlatformNodeDelegate::ChildAtIndex(int index) {
return nullptr;
}
+bool ViewAXPlatformNodeDelegate::HasModalDialog() const {
+ return GetChildWidgets().is_tab_modal_showing;
+}
+
gfx::NativeViewAccessible ViewAXPlatformNodeDelegate::GetNSWindow() {
NOTREACHED();
return nullptr;
@@ -377,6 +381,17 @@ bool ViewAXPlatformNodeDelegate::IsLeaf() const {
return ViewAccessibility::IsLeaf() || AXPlatformNodeDelegateBase::IsLeaf();
}
+bool ViewAXPlatformNodeDelegate::IsToplevelBrowserWindow() {
+ // Note: only used on Desktop Linux. Other platforms don't have an application
+ // node so this would never return true.
+ ui::AXNodeData data = GetData();
+ if (data.role != ax::mojom::Role::kWindow)
+ return false;
+
+ AXPlatformNodeDelegate* parent = GetParentDelegate();
+ return parent && parent->GetData().role == ax::mojom::Role::kApplication;
+}
+
gfx::Rect ViewAXPlatformNodeDelegate::GetBoundsRect(
const ui::AXCoordinateSystem coordinate_system,
const ui::AXClippingBehavior clipping_behavior,
@@ -525,6 +540,46 @@ const ui::AXUniqueId& ViewAXPlatformNodeDelegate::GetUniqueId() const {
return ViewAccessibility::GetUniqueId();
}
+base::Optional<bool>
+ViewAXPlatformNodeDelegate::GetTableHasColumnOrRowHeaderNode() const {
+ if (!GetAncestorTableView())
+ return false;
+ return !GetAncestorTableView()->visible_columns().empty();
+}
+
+std::vector<int32_t> ViewAXPlatformNodeDelegate::GetColHeaderNodeIds() const {
+ std::vector<int32_t> col_header_ids;
+ if (!virtual_children().empty()) {
+ for (const std::unique_ptr<AXVirtualView>& header_cell :
+ virtual_children().front()->children()) {
+ const ui::AXNodeData& header_data = header_cell->GetData();
+ if (header_data.role == ax::mojom::Role::kColumnHeader) {
+ col_header_ids.push_back(header_data.id);
+ }
+ }
+ }
+ return col_header_ids;
+}
+
+std::vector<int32_t> ViewAXPlatformNodeDelegate::GetColHeaderNodeIds(
+ int col_index) const {
+ std::vector<int32_t> columns = GetColHeaderNodeIds();
+ if (columns.size() <= size_t{col_index}) {
+ return {};
+ }
+ return {columns[col_index]};
+}
+
+TableView* ViewAXPlatformNodeDelegate::GetAncestorTableView() const {
+ ui::AXNodeData data;
+ view()->GetViewAccessibility().GetAccessibleNodeData(&data);
+
+ if (!ui::IsTableLike(data.role))
+ return nullptr;
+
+ return static_cast<TableView*>(view());
+}
+
bool ViewAXPlatformNodeDelegate::IsOrderedSetItem() const {
const ui::AXNodeData& data = GetData();
return (view()->GetGroup() >= 0) ||
diff --git a/chromium/ui/views/accessibility/view_ax_platform_node_delegate.h b/chromium/ui/views/accessibility/view_ax_platform_node_delegate.h
index 8d3ddca5571..923e54ac9bb 100644
--- a/chromium/ui/views/accessibility/view_ax_platform_node_delegate.h
+++ b/chromium/ui/views/accessibility/view_ax_platform_node_delegate.h
@@ -17,6 +17,7 @@
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/views/accessibility/view_accessibility.h"
+#include "ui/views/controls/table/table_view.h"
#include "ui/views/widget/widget_observer.h"
namespace ui {
@@ -45,7 +46,7 @@ class ViewAXPlatformNodeDelegate : public ViewAccessibility,
// ViewAccessibility:
gfx::NativeViewAccessible GetNativeObject() const override;
void NotifyAccessibilityEvent(ax::mojom::Event event_type) override;
-#if defined(OS_MACOSX)
+#if defined(OS_APPLE)
void AnnounceText(const base::string16& text) override;
#endif
void FireFocusAfterMenuClose() override;
@@ -58,11 +59,13 @@ class ViewAXPlatformNodeDelegate : public ViewAccessibility,
const ui::AXNodeData& GetData() const override;
int GetChildCount() const override;
gfx::NativeViewAccessible ChildAtIndex(int index) override;
+ bool HasModalDialog() const override;
gfx::NativeViewAccessible GetNSWindow() override;
gfx::NativeViewAccessible GetNativeViewAccessible() override;
gfx::NativeViewAccessible GetParent() override;
bool IsChildOfLeaf() const override;
bool IsLeaf() const override;
+ bool IsToplevelBrowserWindow() override;
gfx::Rect GetBoundsRect(
const ui::AXCoordinateSystem coordinate_system,
const ui::AXClippingBehavior clipping_behavior,
@@ -81,6 +84,9 @@ class ViewAXPlatformNodeDelegate : public ViewAccessibility,
bool IsMinimized() const override;
// Also in |ViewAccessibility|.
const ui::AXUniqueId& GetUniqueId() const override;
+ base::Optional<bool> GetTableHasColumnOrRowHeaderNode() const override;
+ std::vector<int32_t> GetColHeaderNodeIds() const override;
+ std::vector<int32_t> GetColHeaderNodeIds(int col_index) const override;
// Ordered-set-like and item-like nodes.
bool IsOrderedSetItem() const override;
@@ -106,6 +112,9 @@ class ViewAXPlatformNodeDelegate : public ViewAccessibility,
ChildWidgetsResult GetChildWidgets() const;
+ // Gets the real TableView, otherwise nullptr.
+ TableView* GetAncestorTableView() const;
+
// We own this, but it is reference-counted on some platforms so we can't use
// a unique_ptr. It is destroyed in the destructor.
ui::AXPlatformNode* ax_platform_node_;
diff --git a/chromium/ui/views/accessibility/view_ax_platform_node_delegate_auralinux_unittest.cc b/chromium/ui/views/accessibility/view_ax_platform_node_delegate_auralinux_unittest.cc
index 3f8100365a7..b7bf51dc1a8 100644
--- a/chromium/ui/views/accessibility/view_ax_platform_node_delegate_auralinux_unittest.cc
+++ b/chromium/ui/views/accessibility/view_ax_platform_node_delegate_auralinux_unittest.cc
@@ -36,6 +36,10 @@ TEST_F(ViewAXPlatformNodeDelegateAuraLinuxTest, TextfieldAccessibility) {
textfield->SetAccessibleName(base::UTF8ToUTF16("Name"));
content->AddChildView(textfield);
+ ASSERT_EQ(0, atk_object_get_n_accessible_children(
+ textfield->GetNativeViewAccessible()))
+ << "Text fields should be leaf nodes on this platform, otherwise no "
+ "descendants will be recognized by assistive software.";
AtkText* atk_text = ATK_TEXT(textfield->GetNativeViewAccessible());
ASSERT_NE(nullptr, atk_text);
diff --git a/chromium/ui/views/accessibility/view_ax_platform_node_delegate_unittest.cc b/chromium/ui/views/accessibility/view_ax_platform_node_delegate_unittest.cc
index cf4bc178a1d..51fd747d4bc 100644
--- a/chromium/ui/views/accessibility/view_ax_platform_node_delegate_unittest.cc
+++ b/chromium/ui/views/accessibility/view_ax_platform_node_delegate_unittest.cc
@@ -40,6 +40,28 @@ class TestButton : public Button {
~TestButton() override = default;
};
+class TestAXEventObserver : public AXEventObserver {
+ public:
+ explicit TestAXEventObserver(AXAuraObjCache* cache) : cache_(cache) {
+ AXEventManager::Get()->AddObserver(this);
+ }
+ TestAXEventObserver(const TestAXEventObserver&) = delete;
+ TestAXEventObserver& operator=(const TestAXEventObserver&) = delete;
+ ~TestAXEventObserver() override {
+ AXEventManager::Get()->RemoveObserver(this);
+ }
+
+ // AXEventObserver:
+ void OnViewEvent(View* view, ax::mojom::Event event_type) override {
+ std::vector<AXAuraObjWrapper*> out_children;
+ AXAuraObjWrapper* ax_obj = cache_->GetOrCreate(view->GetWidget());
+ ax_obj->GetChildren(&out_children);
+ }
+
+ private:
+ AXAuraObjCache* cache_;
+};
+
} // namespace
class ViewAXPlatformNodeDelegateTest : public ViewsTestBase {
@@ -412,28 +434,6 @@ class DerivedTestView : public View {
void OnBlur() override { SetVisible(false); }
};
-class TestAXEventObserver : public AXEventObserver {
- public:
- explicit TestAXEventObserver(AXAuraObjCache* cache) : cache_(cache) {
- AXEventManager::Get()->AddObserver(this);
- }
- TestAXEventObserver(const TestAXEventObserver&) = delete;
- TestAXEventObserver& operator=(const TestAXEventObserver&) = delete;
- ~TestAXEventObserver() override {
- AXEventManager::Get()->RemoveObserver(this);
- }
-
- // AXEventObserver:
- void OnViewEvent(View* view, ax::mojom::Event event_type) override {
- std::vector<AXAuraObjWrapper*> out_children;
- AXAuraObjWrapper* ax_obj = cache_->GetOrCreate(view->GetWidget());
- ax_obj->GetChildren(&out_children);
- }
-
- private:
- AXAuraObjCache* cache_;
-};
-
using ViewAccessibilityTest = ViewsTestBase;
// Check if the destruction of the widget ends successfully if |view|'s
diff --git a/chromium/ui/views/accessibility/view_ax_platform_node_delegate_win_unittest.cc b/chromium/ui/views/accessibility/view_ax_platform_node_delegate_win_unittest.cc
index 00ffe077cd7..460b47fe4b2 100644
--- a/chromium/ui/views/accessibility/view_ax_platform_node_delegate_win_unittest.cc
+++ b/chromium/ui/views/accessibility/view_ax_platform_node_delegate_win_unittest.cc
@@ -89,6 +89,11 @@ TEST_F(ViewAXPlatformNodeDelegateWinTest, TextfieldAccessibility) {
content_accessible->get_accChild(child_index, &textfield_dispatch));
ASSERT_EQ(S_OK, textfield_dispatch.As(&textfield_accessible));
+ ASSERT_EQ(S_OK, textfield_accessible->get_accChildCount(&child_count));
+ EXPECT_EQ(0, child_count)
+ << "Text fields should be leaf nodes on this platform, otherwise no "
+ "descendants will be recognized by assistive software.";
+
ScopedBstr name;
ScopedVariant childid_self(CHILDID_SELF);
ASSERT_EQ(S_OK,
diff --git a/chromium/ui/views/accessibility/views_ax_tree_manager.h b/chromium/ui/views/accessibility/views_ax_tree_manager.h
index 5212d3d2a44..324af2d35b5 100644
--- a/chromium/ui/views/accessibility/views_ax_tree_manager.h
+++ b/chromium/ui/views/accessibility/views_ax_tree_manager.h
@@ -87,7 +87,7 @@ class VIEWS_EXPORT ViewsAXTreeManager : public ui::AXTreeManager,
ui::AXNode* GetRootAsAXNode() const override;
ui::AXNode* GetParentNodeFromParentTreeAsAXNode() const override;
- // AXActionHandler implementation.
+ // AXActionHandlerBase implementation.
void PerformAction(const ui::AXActionData& data) override;
// AXEventObserver implementation.