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 @@
#include "base/macros.h"
#include "chrome/browser/ui/browser.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/test/base/in_process_browser_test.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 "ui/accessibility/platform/ax_platform_node.h"
......@@ -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) {
while (object) {
if (atk_object_get_role(object) == ATK_ROLE_FRAME)
......
......@@ -1496,6 +1496,10 @@ gfx::NativeViewAccessible BrowserAccessibility::ChildAtIndex(int index) {
return child->GetNativeViewAccessible();
}
bool BrowserAccessibility::HasModalDialog() const {
return false;
}
gfx::NativeViewAccessible BrowserAccessibility::GetFirstChild() {
BrowserAccessibility* child = PlatformGetFirstChild();
if (!child)
......
......@@ -433,6 +433,7 @@ class CONTENT_EXPORT BrowserAccessibility : public ui::AXPlatformNodeDelegate {
gfx::NativeViewAccessible GetParent() override;
int GetChildCount() const override;
gfx::NativeViewAccessible ChildAtIndex(int index) override;
bool HasModalDialog() const override;
gfx::NativeViewAccessible GetFirstChild() override;
gfx::NativeViewAccessible GetLastChild() override;
gfx::NativeViewAccessible GetNextSibling() override;
......
......@@ -182,6 +182,11 @@ base::Optional<int> AXPlatformNodeBase::GetIndexInParent() {
if (parent->ChildAtIndex(i) == current)
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()
<< "Unable to find the child in the list of its parent's children.";
return base::nullopt;
......
......@@ -115,6 +115,9 @@ class AX_EXPORT AXPlatformNodeDelegate {
// Get the child of a node given a 0-based index.
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.
virtual gfx::NativeViewAccessible GetFirstChild() = 0;
......
......@@ -94,6 +94,10 @@ gfx::NativeViewAccessible AXPlatformNodeDelegateBase::ChildAtIndex(int index) {
return nullptr;
}
bool AXPlatformNodeDelegateBase::HasModalDialog() const {
return false;
}
gfx::NativeViewAccessible AXPlatformNodeDelegateBase::GetFirstChild() {
if (GetChildCount() > 0)
return ChildAtIndex(0);
......
......@@ -62,6 +62,9 @@ class AX_EXPORT AXPlatformNodeDelegateBase : public AXPlatformNodeDelegate {
// Get the child of a node given a 0-based index.
gfx::NativeViewAccessible ChildAtIndex(int index) override;
// Returns true if it has a modal dialog.
bool HasModalDialog() const override;
gfx::NativeViewAccessible GetFirstChild() override;
gfx::NativeViewAccessible GetLastChild() override;
gfx::NativeViewAccessible GetNextSibling() override;
......
......@@ -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;
......
......@@ -58,6 +58,7 @@ 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;
......
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