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) { ...@@ -170,14 +170,8 @@ static bool IsImageOrAltText(LayoutBoxModelObject* box, Node* node) {
return false; return false;
} }
ax::mojom::blink::Role AXLayoutObject::NativeRoleIgnoringAria() const { ax::mojom::blink::Role AXLayoutObject::RoleFromLayoutObject(
// DOM role takes precedence over layout role. ax::mojom::blink::Role dom_role) const {
// 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;
// Markup did not provide a specific role, so attempt to determine one // Markup did not provide a specific role, so attempt to determine one
// from the computed style. // from the computed style.
Node* node = layout_object_->GetNode(); Node* node = layout_object_->GetNode();
...@@ -230,6 +224,9 @@ ax::mojom::blink::Role AXLayoutObject::NativeRoleIgnoringAria() const { ...@@ -230,6 +224,9 @@ ax::mojom::blink::Role AXLayoutObject::NativeRoleIgnoringAria() const {
if (layout_object_->IsHR()) if (layout_object_->IsHR())
return ax::mojom::blink::Role::kSplitter; 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; return dom_role;
} }
...@@ -1634,42 +1631,6 @@ void AXLayoutObject::AriaDescribedbyElements( ...@@ -1634,42 +1631,6 @@ void AXLayoutObject::AriaDescribedbyElements(
describedby); 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 // 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 // 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 // a future version of WAI-ARIA. After that we will re-implement them
......
...@@ -52,7 +52,6 @@ class MODULES_EXPORT AXLayoutObject : public AXNodeObject { ...@@ -52,7 +52,6 @@ class MODULES_EXPORT AXLayoutObject : public AXNodeObject {
LayoutObject* GetLayoutObject() const final { return layout_object_; } LayoutObject* GetLayoutObject() const final { return layout_object_; }
ScrollableArea* GetScrollableAreaIfScrollable() const final; ScrollableArea* GetScrollableAreaIfScrollable() const final;
ax::mojom::blink::Role DetermineAccessibilityRole() override; 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 // If this is an anonymous node, returns the node of its containing layout
// block, otherwise returns the node of this layout object. // block, otherwise returns the node of this layout object.
...@@ -137,7 +136,6 @@ class MODULES_EXPORT AXLayoutObject : public AXNodeObject { ...@@ -137,7 +136,6 @@ class MODULES_EXPORT AXLayoutObject : public AXNodeObject {
void AriaDescribedbyElements(AXObjectVector&) const override; void AriaDescribedbyElements(AXObjectVector&) const override;
void AriaOwnsElements(AXObjectVector&) const override; void AriaOwnsElements(AXObjectVector&) const override;
ax::mojom::blink::HasPopup HasPopup() const override;
bool SupportsARIADragging() const override; bool SupportsARIADragging() const override;
void Dropeffects( void Dropeffects(
Vector<ax::mojom::blink::Dropeffect>& dropeffects) const override; Vector<ax::mojom::blink::Dropeffect>& dropeffects) const override;
...@@ -205,6 +203,17 @@ class MODULES_EXPORT AXLayoutObject : public AXNodeObject { ...@@ -205,6 +203,17 @@ class MODULES_EXPORT AXLayoutObject : public AXNodeObject {
// alert. // alert.
AXObject* ErrorMessage() const override; 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: private:
bool IsTabItemSelected() const; bool IsTabItemSelected() const;
AXObject* AccessibilityImageMapHitTest(HTMLAreaElement*, AXObject* AccessibilityImageMapHitTest(HTMLAreaElement*,
......
...@@ -644,7 +644,7 @@ ax::mojom::blink::Role AXNodeObject::DetermineTableCellRole() const { ...@@ -644,7 +644,7 @@ ax::mojom::blink::Role AXNodeObject::DetermineTableCellRole() const {
// DataList(), aria-pressed, the parent's tag, role on an iframe, etc. // DataList(), aria-pressed, the parent's tag, role on an iframe, etc.
ax::mojom::blink::Role AXNodeObject::NativeRoleIgnoringAria() const { ax::mojom::blink::Role AXNodeObject::NativeRoleIgnoringAria() const {
if (!GetNode()) if (!GetNode())
return ax::mojom::blink::Role::kUnknown; return RoleFromLayoutObject(ax::mojom::blink::Role::kUnknown);
// |HTMLAnchorElement| sets isLink only when it has kHrefAttr. // |HTMLAnchorElement| sets isLink only when it has kHrefAttr.
if (GetNode()->IsLink()) { if (GetNode()->IsLink()) {
...@@ -678,7 +678,7 @@ ax::mojom::blink::Role AXNodeObject::NativeRoleIgnoringAria() const { ...@@ -678,7 +678,7 @@ ax::mojom::blink::Role AXNodeObject::NativeRoleIgnoringAria() const {
parent = LayoutTreeBuilderTraversal::Parent(*parent); parent = LayoutTreeBuilderTraversal::Parent(*parent);
if (parent && IsA<HTMLDetailsElement>(parent)) if (parent && IsA<HTMLDetailsElement>(parent))
return ax::mojom::blink::Role::kDisclosureTriangle; 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 // Chrome exposes both table markup and table CSS as a tables, letting
...@@ -773,7 +773,7 @@ ax::mojom::blink::Role AXNodeObject::NativeRoleIgnoringAria() const { ...@@ -773,7 +773,7 @@ ax::mojom::blink::Role AXNodeObject::NativeRoleIgnoringAria() const {
return ax::mojom::blink::Role::kHeading; return ax::mojom::blink::Role::kHeading;
if (IsA<HTMLDivElement>(*GetNode())) if (IsA<HTMLDivElement>(*GetNode()))
return ax::mojom::blink::Role::kGenericContainer; return RoleFromLayoutObject(ax::mojom::blink::Role::kGenericContainer);
if (IsA<HTMLMeterElement>(*GetNode())) if (IsA<HTMLMeterElement>(*GetNode()))
return ax::mojom::blink::Role::kMeter; return ax::mojom::blink::Role::kMeter;
...@@ -860,14 +860,14 @@ ax::mojom::blink::Role AXNodeObject::NativeRoleIgnoringAria() const { ...@@ -860,14 +860,14 @@ ax::mojom::blink::Role AXNodeObject::NativeRoleIgnoringAria() const {
return ax::mojom::blink::Role::kSection; return ax::mojom::blink::Role::kSection;
if (GetNode()->HasTagName(html_names::kAddressTag)) if (GetNode()->HasTagName(html_names::kAddressTag))
return ax::mojom::blink::Role::kGenericContainer; return RoleFromLayoutObject(ax::mojom::blink::Role::kGenericContainer);
if (IsA<HTMLDialogElement>(*GetNode())) if (IsA<HTMLDialogElement>(*GetNode()))
return ax::mojom::blink::Role::kDialog; return ax::mojom::blink::Role::kDialog;
// The HTML element. // The HTML element.
if (IsA<HTMLHtmlElement>(GetNode())) if (IsA<HTMLHtmlElement>(GetNode()))
return ax::mojom::blink::Role::kGenericContainer; return RoleFromLayoutObject(ax::mojom::blink::Role::kGenericContainer);
// Treat <iframe> and <frame> the same. // Treat <iframe> and <frame> the same.
if (IsA<HTMLIFrameElement>(*GetNode()) || IsA<HTMLFrameElement>(*GetNode())) { if (IsA<HTMLIFrameElement>(*GetNode()) || IsA<HTMLFrameElement>(*GetNode())) {
...@@ -920,7 +920,7 @@ ax::mojom::blink::Role AXNodeObject::NativeRoleIgnoringAria() const { ...@@ -920,7 +920,7 @@ ax::mojom::blink::Role AXNodeObject::NativeRoleIgnoringAria() const {
if (IsFieldset()) if (IsFieldset())
return ax::mojom::blink::Role::kGroup; 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() { ax::mojom::blink::Role AXNodeObject::DetermineAccessibilityRole() {
...@@ -1133,6 +1133,21 @@ bool AXNodeObject::IsControllingVideoElement() const { ...@@ -1133,6 +1133,21 @@ bool AXNodeObject::IsControllingVideoElement() const {
MediaControlElementsHelper::ToParentMediaElement(node)); 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 { bool AXNodeObject::ComputeIsEditableRoot() const {
Node* node = GetNode(); Node* node = GetNode();
if (!node) if (!node)
...@@ -2155,6 +2170,42 @@ bool AXNodeObject::HasAriaAttribute() const { ...@@ -2155,6 +2170,42 @@ bool AXNodeObject::HasAriaAttribute() const {
return false; 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 // Returns the nearest block-level LayoutBlockFlow ancestor
static LayoutBlockFlow* NonInlineBlockFlow(LayoutObject* object) { static LayoutBlockFlow* NonInlineBlockFlow(LayoutObject* object) {
LayoutObject* current = object; LayoutObject* current = object;
......
...@@ -95,6 +95,7 @@ class MODULES_EXPORT AXNodeObject : public AXObject { ...@@ -95,6 +95,7 @@ class MODULES_EXPORT AXNodeObject : public AXObject {
// Check object role or purpose. // Check object role or purpose.
bool IsControllingVideoElement() const; bool IsControllingVideoElement() const;
bool IsDefault() const override;
bool IsMultiline() const override; bool IsMultiline() const override;
bool IsEditable() const override { return IsNativeTextControl(); } bool IsEditable() const override { return IsNativeTextControl(); }
bool ComputeIsEditableRoot() const override; bool ComputeIsEditableRoot() const override;
...@@ -158,6 +159,8 @@ class MODULES_EXPORT AXNodeObject : public AXObject { ...@@ -158,6 +159,8 @@ class MODULES_EXPORT AXNodeObject : public AXObject {
ax::mojom::blink::Role AriaRoleAttribute() const final; ax::mojom::blink::Role AriaRoleAttribute() const final;
bool HasAriaAttribute() const override; bool HasAriaAttribute() const override;
ax::mojom::blink::HasPopup HasPopup() const override;
// AX name calculation. // AX name calculation.
String GetName(ax::mojom::blink::NameFrom&, String GetName(ax::mojom::blink::NameFrom&,
AXObjectVector* name_objects) const override; AXObjectVector* name_objects) const override;
...@@ -238,6 +241,17 @@ class MODULES_EXPORT AXNodeObject : public AXObject { ...@@ -238,6 +241,17 @@ class MODULES_EXPORT AXNodeObject : public AXObject {
return nullptr; 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, SetNeedsToUpdateChildren);
FRIEND_TEST_ALL_PREFIXES(AccessibilityTest, UpdateChildrenIfNecessary); 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