Commit ed4c9d7a authored by Chris Hall's avatar Chris Hall Committed by Commit Bot

Migrating methods from AXLayoutObject to AxNodeObject.

 - Migrating IsDefault method
 - Migrating HasPopup method
 - Inverting control flow for NativeRoleIgnoringAria

Written collaboratively with Aboxhall and Meredithl.

Change-Id: Ic516fecf0f9e9d010e033ec46c8bd09df7869983
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2186874Reviewed-by: default avatarAlice Boxhall <aboxhall@chromium.org>
Reviewed-by: default avatarDominic Mazzoni <dmazzoni@chromium.org>
Commit-Queue: Chris Hall <chrishall@chromium.org>
Cr-Commit-Position: refs/heads/master@{#774035}
parent 445af931
......@@ -170,14 +170,8 @@ static bool IsImageOrAltText(LayoutBoxModelObject* box, Node* node) {
return false;
}
ax::mojom::blink::Role AXLayoutObject::NativeRoleIgnoringAria() const {
// DOM role takes precedence over layout role.
// For example, <h4 style="display:table"> is a heading, not a table.
ax::mojom::blink::Role dom_role = AXNodeObject::NativeRoleIgnoringAria();
if (dom_role != ax::mojom::blink::Role::kGenericContainer &&
dom_role != ax::mojom::blink::Role::kUnknown)
return dom_role;
ax::mojom::blink::Role AXLayoutObject::RoleFromLayoutObject(
ax::mojom::blink::Role dom_role) const {
// Markup did not provide a specific role, so attempt to determine one
// from the computed style.
Node* node = layout_object_->GetNode();
......@@ -230,6 +224,9 @@ ax::mojom::blink::Role AXLayoutObject::NativeRoleIgnoringAria() const {
if (layout_object_->IsHR())
return ax::mojom::blink::Role::kSplitter;
// TODO(accessibility): refactor this method to take no argument and instead
// default to returning kUnknownRole, the caller can then check for this and
// return a different value if they prefer.
return dom_role;
}
......@@ -1634,42 +1631,6 @@ void AXLayoutObject::AriaDescribedbyElements(
describedby);
}
ax::mojom::blink::HasPopup AXLayoutObject::HasPopup() const {
const AtomicString& has_popup =
GetAOMPropertyOrARIAAttribute(AOMStringProperty::kHasPopUp);
if (!has_popup.IsNull()) {
if (EqualIgnoringASCIICase(has_popup, "false"))
return ax::mojom::blink::HasPopup::kFalse;
if (EqualIgnoringASCIICase(has_popup, "listbox"))
return ax::mojom::blink::HasPopup::kListbox;
if (EqualIgnoringASCIICase(has_popup, "tree"))
return ax::mojom::blink::HasPopup::kTree;
if (EqualIgnoringASCIICase(has_popup, "grid"))
return ax::mojom::blink::HasPopup::kGrid;
if (EqualIgnoringASCIICase(has_popup, "dialog"))
return ax::mojom::blink::HasPopup::kDialog;
// To provide backward compatibility with ARIA 1.0 content,
// user agents MUST treat an aria-haspopup value of true
// as equivalent to a value of menu.
// And unknown value also return menu too.
if (EqualIgnoringASCIICase(has_popup, "true") ||
EqualIgnoringASCIICase(has_popup, "menu") || !has_popup.IsEmpty())
return ax::mojom::blink::HasPopup::kMenu;
}
// ARIA 1.1 default value of haspopup for combobox is "listbox".
if (RoleValue() == ax::mojom::blink::Role::kComboBoxMenuButton ||
RoleValue() == ax::mojom::blink::Role::kTextFieldWithComboBox)
return ax::mojom::blink::HasPopup::kListbox;
return AXObject::HasPopup();
}
// TODO : Aria-dropeffect and aria-grabbed are deprecated in aria 1.1
// Also those properties are expected to be replaced by a new feature in
// a future version of WAI-ARIA. After that we will re-implement them
......
......@@ -52,7 +52,6 @@ class MODULES_EXPORT AXLayoutObject : public AXNodeObject {
LayoutObject* GetLayoutObject() const final { return layout_object_; }
ScrollableArea* GetScrollableAreaIfScrollable() const final;
ax::mojom::blink::Role DetermineAccessibilityRole() override;
ax::mojom::blink::Role NativeRoleIgnoringAria() const override;
// If this is an anonymous node, returns the node of its containing layout
// block, otherwise returns the node of this layout object.
......@@ -137,7 +136,6 @@ class MODULES_EXPORT AXLayoutObject : public AXNodeObject {
void AriaDescribedbyElements(AXObjectVector&) const override;
void AriaOwnsElements(AXObjectVector&) const override;
ax::mojom::blink::HasPopup HasPopup() const override;
bool SupportsARIADragging() const override;
void Dropeffects(
Vector<ax::mojom::blink::Dropeffect>& dropeffects) const override;
......@@ -205,6 +203,17 @@ class MODULES_EXPORT AXLayoutObject : public AXNodeObject {
// alert.
AXObject* ErrorMessage() const override;
//
// Layout object specific methods.
//
// These methods may eventually migrate over to AXNodeObject.
//
// If we can't determine a useful role from the DOM node, attempt to determine
// a role from the layout object.
ax::mojom::blink::Role RoleFromLayoutObject(
ax::mojom::blink::Role dom_role) const override;
private:
bool IsTabItemSelected() const;
AXObject* AccessibilityImageMapHitTest(HTMLAreaElement*,
......
......@@ -644,7 +644,7 @@ ax::mojom::blink::Role AXNodeObject::DetermineTableCellRole() const {
// DataList(), aria-pressed, the parent's tag, role on an iframe, etc.
ax::mojom::blink::Role AXNodeObject::NativeRoleIgnoringAria() const {
if (!GetNode())
return ax::mojom::blink::Role::kUnknown;
return RoleFromLayoutObject(ax::mojom::blink::Role::kUnknown);
// |HTMLAnchorElement| sets isLink only when it has kHrefAttr.
if (GetNode()->IsLink()) {
......@@ -678,7 +678,7 @@ ax::mojom::blink::Role AXNodeObject::NativeRoleIgnoringAria() const {
parent = LayoutTreeBuilderTraversal::Parent(*parent);
if (parent && IsA<HTMLDetailsElement>(parent))
return ax::mojom::blink::Role::kDisclosureTriangle;
return ax::mojom::blink::Role::kUnknown;
return RoleFromLayoutObject(ax::mojom::blink::Role::kUnknown);
}
// Chrome exposes both table markup and table CSS as a tables, letting
......@@ -773,7 +773,7 @@ ax::mojom::blink::Role AXNodeObject::NativeRoleIgnoringAria() const {
return ax::mojom::blink::Role::kHeading;
if (IsA<HTMLDivElement>(*GetNode()))
return ax::mojom::blink::Role::kGenericContainer;
return RoleFromLayoutObject(ax::mojom::blink::Role::kGenericContainer);
if (IsA<HTMLMeterElement>(*GetNode()))
return ax::mojom::blink::Role::kMeter;
......@@ -860,14 +860,14 @@ ax::mojom::blink::Role AXNodeObject::NativeRoleIgnoringAria() const {
return ax::mojom::blink::Role::kSection;
if (GetNode()->HasTagName(html_names::kAddressTag))
return ax::mojom::blink::Role::kGenericContainer;
return RoleFromLayoutObject(ax::mojom::blink::Role::kGenericContainer);
if (IsA<HTMLDialogElement>(*GetNode()))
return ax::mojom::blink::Role::kDialog;
// The HTML element.
if (IsA<HTMLHtmlElement>(GetNode()))
return ax::mojom::blink::Role::kGenericContainer;
return RoleFromLayoutObject(ax::mojom::blink::Role::kGenericContainer);
// Treat <iframe> and <frame> the same.
if (IsA<HTMLIFrameElement>(*GetNode()) || IsA<HTMLFrameElement>(*GetNode())) {
......@@ -920,7 +920,7 @@ ax::mojom::blink::Role AXNodeObject::NativeRoleIgnoringAria() const {
if (IsFieldset())
return ax::mojom::blink::Role::kGroup;
return ax::mojom::blink::Role::kUnknown;
return RoleFromLayoutObject(ax::mojom::blink::Role::kUnknown);
}
ax::mojom::blink::Role AXNodeObject::DetermineAccessibilityRole() {
......@@ -1133,6 +1133,21 @@ bool AXNodeObject::IsControllingVideoElement() const {
MediaControlElementsHelper::ToParentMediaElement(node));
}
bool AXNodeObject::IsDefault() const {
if (IsDetached())
return false;
// Checks for any kind of disabled, including aria-disabled.
if (Restriction() == kRestrictionDisabled ||
RoleValue() != ax::mojom::blink::Role::kButton) {
return false;
}
// Will only match :default pseudo class if it's the first default button in
// a form.
return GetElement()->MatchesDefaultPseudoClass();
}
bool AXNodeObject::ComputeIsEditableRoot() const {
Node* node = GetNode();
if (!node)
......@@ -2155,6 +2170,42 @@ bool AXNodeObject::HasAriaAttribute() const {
return false;
}
ax::mojom::blink::HasPopup AXNodeObject::HasPopup() const {
const AtomicString& has_popup =
GetAOMPropertyOrARIAAttribute(AOMStringProperty::kHasPopUp);
if (!has_popup.IsNull()) {
if (EqualIgnoringASCIICase(has_popup, "false"))
return ax::mojom::blink::HasPopup::kFalse;
if (EqualIgnoringASCIICase(has_popup, "listbox"))
return ax::mojom::blink::HasPopup::kListbox;
if (EqualIgnoringASCIICase(has_popup, "tree"))
return ax::mojom::blink::HasPopup::kTree;
if (EqualIgnoringASCIICase(has_popup, "grid"))
return ax::mojom::blink::HasPopup::kGrid;
if (EqualIgnoringASCIICase(has_popup, "dialog"))
return ax::mojom::blink::HasPopup::kDialog;
// To provide backward compatibility with ARIA 1.0 content,
// user agents MUST treat an aria-haspopup value of true
// as equivalent to a value of menu.
// And unknown value also return menu too.
if (EqualIgnoringASCIICase(has_popup, "true") ||
EqualIgnoringASCIICase(has_popup, "menu") || !has_popup.IsEmpty())
return ax::mojom::blink::HasPopup::kMenu;
}
// ARIA 1.1 default value of haspopup for combobox is "listbox".
if (RoleValue() == ax::mojom::blink::Role::kComboBoxMenuButton ||
RoleValue() == ax::mojom::blink::Role::kTextFieldWithComboBox)
return ax::mojom::blink::HasPopup::kListbox;
return AXObject::HasPopup();
}
// Returns the nearest block-level LayoutBlockFlow ancestor
static LayoutBlockFlow* NonInlineBlockFlow(LayoutObject* object) {
LayoutObject* current = object;
......
......@@ -95,6 +95,7 @@ class MODULES_EXPORT AXNodeObject : public AXObject {
// Check object role or purpose.
bool IsControllingVideoElement() const;
bool IsDefault() const override;
bool IsMultiline() const override;
bool IsEditable() const override { return IsNativeTextControl(); }
bool ComputeIsEditableRoot() const override;
......@@ -158,6 +159,8 @@ class MODULES_EXPORT AXNodeObject : public AXObject {
ax::mojom::blink::Role AriaRoleAttribute() const final;
bool HasAriaAttribute() const override;
ax::mojom::blink::HasPopup HasPopup() const override;
// AX name calculation.
String GetName(ax::mojom::blink::NameFrom&,
AXObjectVector* name_objects) const override;
......@@ -238,6 +241,17 @@ class MODULES_EXPORT AXNodeObject : public AXObject {
return nullptr;
}
//
// Layout object specific methods.
//
// If we can't determine a useful role from the DOM node, attempt to determine
// a role from the layout object.
virtual ax::mojom::blink::Role RoleFromLayoutObject(
ax::mojom::blink::Role dom_role) const {
return dom_role;
}
FRIEND_TEST_ALL_PREFIXES(AccessibilityTest, SetNeedsToUpdateChildren);
FRIEND_TEST_ALL_PREFIXES(AccessibilityTest, UpdateChildrenIfNecessary);
......
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