Commit 03ae2f46 authored by Julie Jeongeun Kim's avatar Julie Jeongeun Kim Committed by Commit Bot

[a11y] Return nullopt on GetIndexInParent if there is a modal dialog

When a modal dialog appears, GetChildCount and ChildAtIndex just
consider the modal dialog and skip other children. Since
GetIndexInParent compares itself with all siblings to get the
index, if the parent has a modal dialog, it couldn't find anything
matched.

This CL returns nullopt on GetIndexInParent if its parent has a
modal dialog.

AX-Relnotes: n/a.
Bug: 1104282
Change-Id: I3c8b45fe96aa188fd29aa63bc5fd4b1fc0bac476
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2299664
Commit-Queue: Julie Kim <jkim@igalia.com>
Reviewed-by: default avatarNektarios Paisios <nektar@chromium.org>
Cr-Commit-Position: refs/heads/master@{#790734}
parent 1d796f2b
...@@ -8,9 +8,11 @@ ...@@ -8,9 +8,11 @@
#include "base/macros.h" #include "base/macros.h"
#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/tab_modal_confirm_dialog.h"
#include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/in_process_browser_test.h"
#include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/browser_test.h" #include "content/public/test/browser_test.h"
#include "ui/accessibility/platform/ax_platform_node.h" #include "ui/accessibility/platform/ax_platform_node.h"
...@@ -49,6 +51,59 @@ IN_PROC_BROWSER_TEST_F(AuraLinuxAccessibilityInProcessBrowserTest, ...@@ -49,6 +51,59 @@ IN_PROC_BROWSER_TEST_F(AuraLinuxAccessibilityInProcessBrowserTest,
} }
} }
class TestTabModalConfirmDialogDelegate : public TabModalConfirmDialogDelegate {
public:
explicit TestTabModalConfirmDialogDelegate(content::WebContents* contents)
: TabModalConfirmDialogDelegate(contents) {}
base::string16 GetTitle() override {
return base::ASCIIToUTF16("Dialog Title");
}
base::string16 GetDialogMessage() override { return base::string16(); }
DISALLOW_COPY_AND_ASSIGN(TestTabModalConfirmDialogDelegate);
};
// Open a tab-modal dialog and test IndexInParent with the modal dialog.
IN_PROC_BROWSER_TEST_F(AuraLinuxAccessibilityInProcessBrowserTest,
IndexInParentWithModal) {
BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser());
AtkObject* native_view_accessible =
browser_view->GetWidget()->GetRootView()->GetNativeViewAccessible();
EXPECT_NE(nullptr, native_view_accessible);
// The root view has a child that is a client role for Chromium.
int n_children = atk_object_get_n_accessible_children(native_view_accessible);
ASSERT_EQ(1, n_children);
AtkObject* client =
atk_object_ref_accessible_child(native_view_accessible, 0);
ASSERT_EQ(0, atk_object_get_index_in_parent(client));
// Opens a tab-modal dialog.
content::WebContents* contents = browser_view->GetActiveWebContents();
auto delegate = std::make_unique<TestTabModalConfirmDialogDelegate>(contents);
TabModalConfirmDialog* dialog =
TabModalConfirmDialog::Create(std::move(delegate), contents);
// The root view still has one child that is a dialog role since if it has a
// modal dialog it hides the rest of the children.
n_children = atk_object_get_n_accessible_children(native_view_accessible);
ASSERT_EQ(1, n_children);
AtkObject* dialog_node =
atk_object_ref_accessible_child(native_view_accessible, 0);
ASSERT_EQ(0, atk_object_get_index_in_parent(dialog_node));
// The client has an invalid value for the index in parent since it's hidden
// by the dialog.
ASSERT_EQ(-1, atk_object_get_index_in_parent(client));
dialog->CloseDialog();
// It has a valid value for the client after the dialog is closed.
ASSERT_EQ(0, atk_object_get_index_in_parent(client));
g_object_unref(client);
g_object_unref(dialog_node);
}
static AtkObject* FindParentFrame(AtkObject* object) { static AtkObject* FindParentFrame(AtkObject* object) {
while (object) { while (object) {
if (atk_object_get_role(object) == ATK_ROLE_FRAME) if (atk_object_get_role(object) == ATK_ROLE_FRAME)
......
...@@ -1496,6 +1496,10 @@ gfx::NativeViewAccessible BrowserAccessibility::ChildAtIndex(int index) { ...@@ -1496,6 +1496,10 @@ gfx::NativeViewAccessible BrowserAccessibility::ChildAtIndex(int index) {
return child->GetNativeViewAccessible(); return child->GetNativeViewAccessible();
} }
bool BrowserAccessibility::HasModalDialog() const {
return false;
}
gfx::NativeViewAccessible BrowserAccessibility::GetFirstChild() { gfx::NativeViewAccessible BrowserAccessibility::GetFirstChild() {
BrowserAccessibility* child = PlatformGetFirstChild(); BrowserAccessibility* child = PlatformGetFirstChild();
if (!child) if (!child)
......
...@@ -433,6 +433,7 @@ class CONTENT_EXPORT BrowserAccessibility : public ui::AXPlatformNodeDelegate { ...@@ -433,6 +433,7 @@ class CONTENT_EXPORT BrowserAccessibility : public ui::AXPlatformNodeDelegate {
gfx::NativeViewAccessible GetParent() override; gfx::NativeViewAccessible GetParent() override;
int GetChildCount() const override; int GetChildCount() const override;
gfx::NativeViewAccessible ChildAtIndex(int index) override; gfx::NativeViewAccessible ChildAtIndex(int index) override;
bool HasModalDialog() const override;
gfx::NativeViewAccessible GetFirstChild() override; gfx::NativeViewAccessible GetFirstChild() override;
gfx::NativeViewAccessible GetLastChild() override; gfx::NativeViewAccessible GetLastChild() override;
gfx::NativeViewAccessible GetNextSibling() override; gfx::NativeViewAccessible GetNextSibling() override;
......
...@@ -182,6 +182,11 @@ base::Optional<int> AXPlatformNodeBase::GetIndexInParent() { ...@@ -182,6 +182,11 @@ base::Optional<int> AXPlatformNodeBase::GetIndexInParent() {
if (parent->ChildAtIndex(i) == current) if (parent->ChildAtIndex(i) == current)
return i; return i;
} }
// If the parent has a modal dialog, it doesn't count other children.
if (parent->delegate_ && parent->delegate_->HasModalDialog())
return base::nullopt;
NOTREACHED() NOTREACHED()
<< "Unable to find the child in the list of its parent's children."; << "Unable to find the child in the list of its parent's children.";
return base::nullopt; return base::nullopt;
......
...@@ -115,6 +115,9 @@ class AX_EXPORT AXPlatformNodeDelegate { ...@@ -115,6 +115,9 @@ class AX_EXPORT AXPlatformNodeDelegate {
// Get the child of a node given a 0-based index. // Get the child of a node given a 0-based index.
virtual gfx::NativeViewAccessible ChildAtIndex(int index) = 0; virtual gfx::NativeViewAccessible ChildAtIndex(int index) = 0;
// Returns true if it has a modal dialog.
virtual bool HasModalDialog() const = 0;
// Gets the first child of a node, or nullptr if no children exist. // Gets the first child of a node, or nullptr if no children exist.
virtual gfx::NativeViewAccessible GetFirstChild() = 0; virtual gfx::NativeViewAccessible GetFirstChild() = 0;
......
...@@ -94,6 +94,10 @@ gfx::NativeViewAccessible AXPlatformNodeDelegateBase::ChildAtIndex(int index) { ...@@ -94,6 +94,10 @@ gfx::NativeViewAccessible AXPlatformNodeDelegateBase::ChildAtIndex(int index) {
return nullptr; return nullptr;
} }
bool AXPlatformNodeDelegateBase::HasModalDialog() const {
return false;
}
gfx::NativeViewAccessible AXPlatformNodeDelegateBase::GetFirstChild() { gfx::NativeViewAccessible AXPlatformNodeDelegateBase::GetFirstChild() {
if (GetChildCount() > 0) if (GetChildCount() > 0)
return ChildAtIndex(0); return ChildAtIndex(0);
......
...@@ -62,6 +62,9 @@ class AX_EXPORT AXPlatformNodeDelegateBase : public AXPlatformNodeDelegate { ...@@ -62,6 +62,9 @@ class AX_EXPORT AXPlatformNodeDelegateBase : public AXPlatformNodeDelegate {
// Get the child of a node given a 0-based index. // Get the child of a node given a 0-based index.
gfx::NativeViewAccessible ChildAtIndex(int index) override; gfx::NativeViewAccessible ChildAtIndex(int index) override;
// Returns true if it has a modal dialog.
bool HasModalDialog() const override;
gfx::NativeViewAccessible GetFirstChild() override; gfx::NativeViewAccessible GetFirstChild() override;
gfx::NativeViewAccessible GetLastChild() override; gfx::NativeViewAccessible GetLastChild() override;
gfx::NativeViewAccessible GetNextSibling() override; gfx::NativeViewAccessible GetNextSibling() override;
......
...@@ -345,6 +345,10 @@ gfx::NativeViewAccessible ViewAXPlatformNodeDelegate::ChildAtIndex(int index) { ...@@ -345,6 +345,10 @@ gfx::NativeViewAccessible ViewAXPlatformNodeDelegate::ChildAtIndex(int index) {
return nullptr; return nullptr;
} }
bool ViewAXPlatformNodeDelegate::HasModalDialog() const {
return GetChildWidgets().is_tab_modal_showing;
}
gfx::NativeViewAccessible ViewAXPlatformNodeDelegate::GetNSWindow() { gfx::NativeViewAccessible ViewAXPlatformNodeDelegate::GetNSWindow() {
NOTREACHED(); NOTREACHED();
return nullptr; return nullptr;
......
...@@ -58,6 +58,7 @@ class ViewAXPlatformNodeDelegate : public ViewAccessibility, ...@@ -58,6 +58,7 @@ class ViewAXPlatformNodeDelegate : public ViewAccessibility,
const ui::AXNodeData& GetData() const override; const ui::AXNodeData& GetData() const override;
int GetChildCount() const override; int GetChildCount() const override;
gfx::NativeViewAccessible ChildAtIndex(int index) override; gfx::NativeViewAccessible ChildAtIndex(int index) override;
bool HasModalDialog() const override;
gfx::NativeViewAccessible GetNSWindow() override; gfx::NativeViewAccessible GetNSWindow() override;
gfx::NativeViewAccessible GetNativeViewAccessible() override; gfx::NativeViewAccessible GetNativeViewAccessible() override;
gfx::NativeViewAccessible GetParent() override; gfx::NativeViewAccessible GetParent() override;
......
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