Commit ea4c3e61 authored by Julie Jeongeun Kim's avatar Julie Jeongeun Kim Committed by Commit Bot

[a11y] Handle a widget destroyed for GetIndexInParent

This CL handles the case that a widget is destroyed and its content
view is alive when GetIndexInParent is called with the view.

For instance, OmniboxPopupContentsView is not destroyed even though
|popup_| widget is destroyed and Orca calls
atk_object_get_index_in_parent on the view. Since it doesn't on the
children list, it meets DCHECK from
AXPlatformNodeBase::GetIndexInParent().

Since GetParent() returns the application node for views if it
doesn't have the parent, checking the parent doesn't work for this
case.

This change overrides GetIndexInParent at AXPlatformNodeAuraLinux
and before calling AXPlatformNodeBase::GetIndexInParent() it checks
if the node is valid.

AX-Relnotes: n/a.
Bug: 1122523
Change-Id: Iba6c8cb852a8e91c775bf5f8c14bc54e83e15643
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2379395
Commit-Queue: Nektarios Paisios <nektar@chromium.org>
Reviewed-by: default avatarNektarios Paisios <nektar@chromium.org>
Cr-Commit-Position: refs/heads/master@{#803455}
parent 778ad11d
......@@ -3301,6 +3301,21 @@ bool AXPlatformNodeAuraLinux::IsPlatformCheckable() const {
return AXPlatformNodeBase::IsPlatformCheckable();
}
base::Optional<int> AXPlatformNodeAuraLinux::GetIndexInParent() {
AXPlatformNode* parent =
AXPlatformNode::FromNativeViewAccessible(GetParent());
// Even though the node doesn't have its parent, GetParent() could return the
// application. Since the detached view has the kUnknown role and the
// restriction is kDisabled, it early returns before finding the index.
if (parent == AXPlatformNodeAuraLinux::application() &&
GetData().role == ax::mojom::Role::kUnknown &&
GetData().GetRestriction() == ax::mojom::Restriction::kDisabled) {
return base::nullopt;
}
return AXPlatformNodeBase::GetIndexInParent();
}
void AXPlatformNodeAuraLinux::EnsureAtkObjectIsValid() {
if (atk_object_) {
// If the object's role changes and that causes its
......
......@@ -241,6 +241,7 @@ class AX_EXPORT AXPlatformNodeAuraLinux : public AXPlatformNodeBase {
// AXPlatformNodeBase overrides.
void Init(AXPlatformNodeDelegate* delegate) override;
bool IsPlatformCheckable() const override;
base::Optional<int> GetIndexInParent() override;
bool IsNameExposed();
......
......@@ -144,5 +144,38 @@ TEST_F(ViewAXPlatformNodeDelegateAuraLinuxTest, AuraChildWidgets) {
g_object_unref(second_child);
}
// Tests if atk_object_get_index_in_parent doesn't DCHECK when a widget is
// destroyed while still owning its content view.
TEST_F(ViewAXPlatformNodeDelegateAuraLinuxTest, IndexInParent) {
// Create the Widget that will represent the application
Widget parent_widget;
Widget::InitParams init_params =
CreateParams(Widget::InitParams::TYPE_WINDOW);
init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
parent_widget.Init(std::move(init_params));
parent_widget.Show();
// |widget| will be destroyed later.
std::unique_ptr<Widget> widget = std::make_unique<Widget>();
Widget::InitParams child_init_params =
CreateParams(Widget::InitParams::TYPE_POPUP);
child_init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
child_init_params.parent = parent_widget.GetNativeView();
widget->Init(std::move(child_init_params));
widget->Show();
View contents;
// Set it as owned by client in order to keep |contents| even though |widget|
// is destroyed.
contents.set_owned_by_client();
widget->SetContentsView(&contents);
AtkObject* atk_object = contents.GetNativeViewAccessible();
EXPECT_EQ(0, atk_object_get_index_in_parent(atk_object));
widget.reset();
EXPECT_EQ(-1, atk_object_get_index_in_parent(atk_object));
}
} // namespace test
} // namespace views
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