Commit f64aa4d4 authored by Meredith Lane's avatar Meredith Lane Committed by Commit Bot

Fixes aria-owns to work with reparenting children.

The spec is unclear on whether or not this is actually a bug with
aria-owns. It was discovered during implementation of Element Reflection
that nodes were unable to be aria-owned by other nodes, if they had
previously been aria-owned. This change allows for nodes to be
reparented, providing the previous relationship has been removed.

BUG=981423

R=dmazzoni, aleventhal, chrishall

Change-Id: Ie6757868c6165df28b5217e5bb41a4bd00eb0478
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1942593
Commit-Queue: Meredith Lane <meredithl@chromium.org>
Reviewed-by: default avatarDominic Mazzoni <dmazzoni@chromium.org>
Cr-Commit-Position: refs/heads/master@{#721398}
parent 2b835963
...@@ -3045,9 +3045,6 @@ void AXNodeObject::ComputeAriaOwnsChildren( ...@@ -3045,9 +3045,6 @@ void AXNodeObject::ComputeAriaOwnsChildren(
return; return;
} }
if (!HasAttribute(html_names::kAriaOwnsAttr))
return;
// Case 2: aria-owns attribute // Case 2: aria-owns attribute
TokenVectorFromAttribute(id_vector, html_names::kAriaOwnsAttr); TokenVectorFromAttribute(id_vector, html_names::kAriaOwnsAttr);
AXObjectCache().UpdateAriaOwns(this, id_vector, owned_children); AXObjectCache().UpdateAriaOwns(this, id_vector, owned_children);
......
...@@ -157,7 +157,12 @@ void AXRelationCache::UpdateAriaOwns( ...@@ -157,7 +157,12 @@ void AXRelationCache::UpdateAriaOwns(
// //
// Figure out the children that are owned by this object and are in the // Figure out the children that are owned by this object and are in the
// tree. // tree.
TreeScope& scope = owner->GetNode()->GetTreeScope();
Node* node = owner->GetNode();
if (!node)
return;
TreeScope& scope = node->GetTreeScope();
Vector<AXID> validated_owned_child_axids; Vector<AXID> validated_owned_child_axids;
for (const String& id_name : owned_id_vector) { for (const String& id_name : owned_id_vector) {
Element* element = scope.getElementById(AtomicString(id_name)); Element* element = scope.getElementById(AtomicString(id_name));
......
...@@ -8,10 +8,10 @@ ...@@ -8,10 +8,10 @@
<script> <script>
test(function(t) { test(function(t) {
var axFutureParent = accessibilityController.accessibleElementById("future_parent"); const axFutureParent = accessibilityController.accessibleElementById("future_parent");
assert_equals(axFutureParent.childrenCount, 0); assert_equals(axFutureParent.childrenCount, 0);
var futureParent = document.getElementById("future_parent"); const futureParent = document.getElementById("future_parent");
var child = document.createElement("li"); const child = document.createElement("li");
child.id = "future_child"; child.id = "future_child";
assert_equals(axFutureParent.childrenCount, 0, "before appending child"); assert_equals(axFutureParent.childrenCount, 0, "before appending child");
...@@ -49,9 +49,9 @@ test(function(t) { ...@@ -49,9 +49,9 @@ test(function(t) {
<script> <script>
test(function(t) { test(function(t) {
var source1 = document.getElementById("source1"); const source1 = document.getElementById("source1");
var target = document.getElementById("target"); const target = document.getElementById("target");
var axSource1 = accessibilityController.accessibleElementById("source1"); const axSource1 = accessibilityController.accessibleElementById("source1");
assert_equals(axSource1.childrenCount, 0); assert_equals(axSource1.childrenCount, 0);
...@@ -75,7 +75,7 @@ test(function(t) { ...@@ -75,7 +75,7 @@ test(function(t) {
<script> <script>
test(function(t) test(function(t)
{ {
var axLogicalParent = accessibilityController.accessibleElementById("logical_parent"); const axLogicalParent = accessibilityController.accessibleElementById("logical_parent");
assert_equals(axLogicalParent.childrenCount, 4); assert_equals(axLogicalParent.childrenCount, 4);
assert_equals(axLogicalParent.childAtIndex(0).childAtIndex(0).name, "1"); assert_equals(axLogicalParent.childAtIndex(0).childAtIndex(0).name, "1");
...@@ -94,3 +94,36 @@ test(function(t) ...@@ -94,3 +94,36 @@ test(function(t)
assert_equals(axLogicalParent.childAtIndex(3).childAtIndex(0).name, "3"); assert_equals(axLogicalParent.childAtIndex(3).childAtIndex(0).name, "3");
}, "A parent can use aria-owns to reorder its children into a more logical AX ordering."); }, "A parent can use aria-owns to reorder its children into a more logical AX ordering.");
</script> </script>
<div class="container">
<div id="original_parent" role="group" aria-owns="kidnapping_target"></div>
<div id="kidnapping_target">Target</div>
<div id="kidnapping_parent" role="group"></div>
<div id="new_parent" role="group"></div>
</div>
<script>
test(function(t) {
const axOriginalParent = accessibilityController.accessibleElementById("original_parent");
const axKidnappingParent = accessibilityController.accessibleElementById("kidnapping_parent");
const axNewParent = accessibilityController.accessibleElementById("new_parent");
assert_equals(axOriginalParent.childrenCount, 1);
assert_equals(axOriginalParent.childAtIndex(0).childAtIndex(0).name, "Target");
// The child cannot be "kidnapped" while a valid aria-owns still exists.
kidnapping_parent.setAttribute("aria-owns", "kidnapping_target");
assert_equals(axKidnappingParent.childrenCount, 0);
assert_equals(axOriginalParent.childrenCount, 1);
assert_equals(axOriginalParent.childAtIndex(0).childAtIndex(0).name, "Target");
kidnapping_parent.removeAttribute("aria-owns");
// If the parentage is removed, the child can be owned by something else.
original_parent.removeAttribute("aria-owns");
// TODO(meredithl): investigate how to set this attribute before removing it from
// the original parent.
new_parent.setAttribute("aria-owns", "kidnapping_target");
assert_equals(axNewParent.childrenCount, 1);
assert_equals(axNewParent.childAtIndex(0).childAtIndex(0).name, "Target");
}, "An element can be reparented by aria-owns if the original relationship is removed");
</script>
...@@ -16,17 +16,16 @@ ...@@ -16,17 +16,16 @@
<script> <script>
test(function(t) test(function(t)
{ {
var axList1 = accessibilityController.accessibleElementById("list1"); const axList1 = accessibilityController.accessibleElementById("list1");
console.log('axList1: ' + axList1);
assert_equals(axList1.role, "AXRole: AXListBox"); assert_equals(axList1.role, "AXRole: AXListBox");
assert_equals(axList1.childrenCount, 3); assert_equals(axList1.childrenCount, 3);
var axItem = axList1.childAtIndex(0); const axItem = axList1.childAtIndex(0);
assert_equals(axList1.childAtIndex(0).name, "One"); assert_equals(axList1.childAtIndex(0).name, "One");
assert_equals(axList1.childAtIndex(1).name, "Two"); assert_equals(axList1.childAtIndex(1).name, "Two");
assert_equals(axList1.childAtIndex(2).name, "Three"); assert_equals(axList1.childAtIndex(2).name, "Three");
var axList2 = accessibilityController.accessibleElementById("list2"); const axList2 = accessibilityController.accessibleElementById("list2");
assert_equals(axList2.role, "AXRole: AXListBox"); assert_equals(axList2.role, "AXRole: AXListBox");
assert_equals(axList2.childrenCount, 1); assert_equals(axList2.childrenCount, 1);
assert_equals(axList2.childAtIndex(0).name, "Four"); assert_equals(axList2.childAtIndex(0).name, "Four");
...@@ -44,13 +43,13 @@ test(function(t) ...@@ -44,13 +43,13 @@ test(function(t)
<script> <script>
test(function(t) test(function(t)
{ {
var axParent1 = accessibilityController.accessibleElementById("parent1"); const axParent1 = accessibilityController.accessibleElementById("parent1");
var axParent2 = accessibilityController.accessibleElementById("parent2"); const axParent2 = accessibilityController.accessibleElementById("parent2");
var axParent3 = accessibilityController.accessibleElementById("parent3"); const axParent3 = accessibilityController.accessibleElementById("parent3");
var axChild = accessibilityController.accessibleElementById("child"); const axChild = accessibilityController.accessibleElementById("child");
// Either parent1 or parent2 should own the child, but either one is okay. // Either parent1 or parent2 should own the child, but either one is okay.
var axActualParent = axChild.parentElement(); const axActualParent = axChild.parentElement();
assert_true(axActualParent.isEqual(axParent1) || axActualParent.isEqual(axParent2)); assert_true(axActualParent.isEqual(axParent1) || axActualParent.isEqual(axParent2));
if (axActualParent.isEqual(axParent1)) { if (axActualParent.isEqual(axParent1)) {
assert_equals(axParent1.childrenCount, 1); assert_equals(axParent1.childrenCount, 1);
...@@ -82,10 +81,10 @@ test(function(t) ...@@ -82,10 +81,10 @@ test(function(t)
// Since there's no valid resolution to the cycle of aria-owns, // Since there's no valid resolution to the cycle of aria-owns,
// just assert that each element's parent is either its real parent // just assert that each element's parent is either its real parent
// or its aria-owned parent, it doesn't matter which one. // or its aria-owned parent, it doesn't matter which one.
var axXYZ = accessibilityController.accessibleElementById("xyz"); const axXYZ = accessibilityController.accessibleElementById("xyz");
var axX = accessibilityController.accessibleElementById("x"); const axX = accessibilityController.accessibleElementById("x");
var axY = accessibilityController.accessibleElementById("y"); const axY = accessibilityController.accessibleElementById("y");
var axZ = accessibilityController.accessibleElementById("z"); const axZ = accessibilityController.accessibleElementById("z");
assert_true(axX.parentElement().isEqual(axXYZ) || assert_true(axX.parentElement().isEqual(axXYZ) ||
axX.parentElement().isEqual(axZ)); axX.parentElement().isEqual(axZ));
assert_true(axY.parentElement().isEqual(axXYZ) || assert_true(axY.parentElement().isEqual(axXYZ) ||
...@@ -104,8 +103,8 @@ test(function(t) ...@@ -104,8 +103,8 @@ test(function(t)
<script> <script>
test(function(t) test(function(t)
{ {
var axRealParent = accessibilityController.accessibleElementById("real-parent"); const axRealParent = accessibilityController.accessibleElementById("real-parent");
var axOwnsSelf = accessibilityController.accessibleElementById("owns-self"); const axOwnsSelf = accessibilityController.accessibleElementById("owns-self");
assert_true(axOwnsSelf.parentElement().isEqual(axRealParent)); assert_true(axOwnsSelf.parentElement().isEqual(axRealParent));
assert_equals(axOwnsSelf.childrenCount, 0); assert_equals(axOwnsSelf.childrenCount, 0);
...@@ -121,8 +120,8 @@ test(function(t) ...@@ -121,8 +120,8 @@ test(function(t)
<script> <script>
test(function(t) test(function(t)
{ {
var axYancy = accessibilityController.accessibleElementById("yancy"); const axYancy = accessibilityController.accessibleElementById("yancy");
var axFry = accessibilityController.accessibleElementById("fry"); const axFry = accessibilityController.accessibleElementById("fry");
assert_equals(axFry.childrenCount, 0); assert_equals(axFry.childrenCount, 0);
assert_equals(axYancy.childrenCount, 1); assert_equals(axYancy.childrenCount, 1);
...@@ -142,7 +141,7 @@ test(function(t) ...@@ -142,7 +141,7 @@ test(function(t)
<script> <script>
test(function(t) test(function(t)
{ {
var axLogicalParent = accessibilityController.accessibleElementById("logical_parent"); const axLogicalParent = accessibilityController.accessibleElementById("logical_parent");
assert_equals(axLogicalParent.childrenCount, 4); assert_equals(axLogicalParent.childrenCount, 4);
assert_equals(axLogicalParent.childAtIndex(0).childAtIndex(0).name, "1"); assert_equals(axLogicalParent.childAtIndex(0).childAtIndex(0).name, "1");
...@@ -160,19 +159,19 @@ test(function(t) ...@@ -160,19 +159,19 @@ test(function(t)
<script> <script>
test(function(t) test(function(t)
{ {
var axDeadParent = accessibilityController.accessibleElementById( const axDeadParent = accessibilityController.accessibleElementById(
"dead_parent"); "dead_parent");
assert_equals(axDeadParent.role, "AXRole: AXList"); assert_equals(axDeadParent.role, "AXRole: AXList");
assert_equals(axDeadParent.childrenCount, 1); assert_equals(axDeadParent.childrenCount, 1);
var axOrphan = axDeadParent.childAtIndex(0); const axOrphan = axDeadParent.childAtIndex(0);
assert_equals(axOrphan.role, "AXRole: AXListItem"); assert_equals(axOrphan.role, "AXRole: AXListItem");
assert_equals(axOrphan.parentElement().role, "AXRole: AXList"); assert_equals(axOrphan.parentElement().role, "AXRole: AXList");
var deadParent = document.getElementById("dead_parent"); const deadParent = document.getElementById("dead_parent");
deadParent.parentElement.removeChild(deadParent); deadParent.parentElement.removeChild(deadParent);
var orphan = document.getElementById("orphan"); const orphan = document.getElementById("orphan");
orphan.setAttribute("id", "o2"); orphan.setAttribute("id", "o2");
orphan.setAttribute("id", "orphan"); orphan.setAttribute("id", "orphan");
}, "No crash if an aria-owns parent is deleted and the child is re-added."); }, "No crash if an aria-owns parent is deleted and the child is re-added.");
......
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