Diff
Modified: trunk/LayoutTests/ChangeLog (224991 => 224992)
--- trunk/LayoutTests/ChangeLog 2017-11-17 23:10:45 UTC (rev 224991)
+++ trunk/LayoutTests/ChangeLog 2017-11-17 23:14:18 UTC (rev 224992)
@@ -1,3 +1,13 @@
+2017-11-17 Nan Wang <n_w...@apple.com>
+
+ AX: AOM: Implement boolean type properties
+ https://bugs.webkit.org/show_bug.cgi?id=179496
+
+ Reviewed by Chris Fleizach.
+
+ * accessibility/mac/AOM-bool-properties-expected.txt: Added.
+ * accessibility/mac/AOM-bool-properties.html: Added.
+
2017-11-17 Megan Gardner <megan_gard...@apple.com>
Turn on selection layout tests that are already working on iOS
Added: trunk/LayoutTests/accessibility/mac/AOM-bool-properties-expected.txt (0 => 224992)
--- trunk/LayoutTests/accessibility/mac/AOM-bool-properties-expected.txt (rev 0)
+++ trunk/LayoutTests/accessibility/mac/AOM-bool-properties-expected.txt 2017-11-17 23:14:18 UTC (rev 224992)
@@ -0,0 +1,56 @@
+outside of dialog
+
+dialog
+This tests boolean type Accessibility Object Model properties.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+
+Test AOM boolean properties can be cleared.
+PASS axNode.boolAttributeValue('AXARIAAtomic') is true
+PASS node.accessibleNode.atomic is null
+PASS axNode.boolAttributeValue('AXARIAAtomic') is false
+PASS node.accessibleNode.atomic is null
+PASS axNode.boolAttributeValue('AXARIAAtomic') is true
+
+Busy support
+PASS axNode.boolAttributeValue('AXElementBusy') is false
+PASS axNode.boolAttributeValue('AXElementBusy') is true
+
+Disabled support
+PASS axNode.isEnabled is true
+PASS axNode.isEnabled is false
+
+Expanded support
+PASS axNode.isExpanded is false
+PASS axNode.isExpanded is true
+
+Hidden support
+PASS axNode.isIgnored is false
+PASS axNode == null || axNode == undefined is true
+
+Modal support
+PASS dialogBackgroundAccessible() is true
+PASS dialogBackgroundAccessible() is false
+
+Multiline support
+PASS axNode.boolAttributeValue('AXIsMultiline') is false
+PASS axNode.boolAttributeValue('AXIsMultiline') is true
+
+Multiselectable support
+PASS axNode.isMultiSelectable is false
+PASS axNode.isMultiSelectable is true
+
+ReadOnly support
+PASS axNode.stringAttributeValue('AXReadOnlyValue') is "false"
+PASS axNode.stringAttributeValue('AXReadOnlyValue') is "true"
+
+Required support
+PASS axNode.isRequired is false
+PASS axNode.isRequired is true
+
+Selected support
+PASS axNode.isSelected is false
+PASS axNode.isSelected is true
+
Added: trunk/LayoutTests/accessibility/mac/AOM-bool-properties.html (0 => 224992)
--- trunk/LayoutTests/accessibility/mac/AOM-bool-properties.html (rev 0)
+++ trunk/LayoutTests/accessibility/mac/AOM-bool-properties.html 2017-11-17 23:14:18 UTC (rev 224992)
@@ -0,0 +1,165 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+<script src=""
+<script src=""
+</head>
+<body>
+
+<div role="region" id="atomic" aria-atomic="true"></div>
+<div role="status" id="busy"></div>
+<div role="checkbox" id="disabled"></div>
+<div role="button" id="expanded"></div>
+<div role="button" id="hidden"></div>
+<div>
+<p id="bgContent">outside of dialog</p>
+<div role="dialog" id="modal">dialog</div>
+</div>
+<div role="textbox" id="multiline"></div>
+<div role="listbox" id="multiselectable"></div>
+<div role="textbox" id="readOnly"></div>
+<div role="textbox" id="required"></div>
+<div role="option" id="selected"></div>
+
+<p id="description"></p>
+<div id="console"></div>
+
+<script>
+ description("This tests boolean type Accessibility Object Model properties.");
+ if (window.accessibilityController) {
+ var node;
+ var axNode;
+
+ testClearBooleanProperty();
+ testBusy();
+ testDisabled();
+ testExpanded();
+ testHidden();
+ testModal();
+ testMultiline();
+ testMultiselectable();
+ testReadOnly();
+ testRequired();
+ testSelected();
+ }
+
+ function dialogBackgroundAccessible() {
+ var bgContent = accessibilityController.accessibleElementById("bgContent");
+ if (!bgContent)
+ return false;
+ return !bgContent.isIgnored;
+ }
+
+ function testClearBooleanProperty() {
+ debug("\nTest AOM boolean properties can be cleared.");
+ node = document.getElementById("atomic");
+ axNode = accessibilityController.accessibleElementById("atomic");
+ // Boolean value should be null if not set.
+ shouldBeTrue("axNode.boolAttributeValue('AXARIAAtomic')");
+ shouldBeNull("node.accessibleNode.atomic");
+ // Set the AOM property
+ node.accessibleNode.atomic = false;
+ shouldBeFalse("axNode.boolAttributeValue('AXARIAAtomic')");
+ // Clear the AOM property
+ node.accessibleNode.atomic = null;
+ shouldBeNull("node.accessibleNode.atomic");
+ shouldBeTrue("axNode.boolAttributeValue('AXARIAAtomic')");
+ }
+
+ function testBusy() {
+ debug("\nBusy support");
+ node = document.getElementById("busy");
+ axNode = accessibilityController.accessibleElementById("busy");
+ shouldBeFalse("axNode.boolAttributeValue('AXElementBusy')");
+ node.accessibleNode.busy = true;
+ shouldBeTrue("axNode.boolAttributeValue('AXElementBusy')");
+ }
+
+ function testDisabled() {
+ debug("\nDisabled support");
+ node = document.getElementById("disabled");
+ axNode = accessibilityController.accessibleElementById("disabled");
+ shouldBeTrue("axNode.isEnabled");
+ node.accessibleNode.disabled = true;
+ shouldBeFalse("axNode.isEnabled");
+ }
+
+ function testExpanded() {
+ debug("\nExpanded support");
+ node = document.getElementById("expanded");
+ axNode = accessibilityController.accessibleElementById("expanded");
+ shouldBeFalse("axNode.isExpanded");
+ node.accessibleNode.expanded = true;
+ shouldBeTrue("axNode.isExpanded");
+ }
+
+ function testHidden() {
+ debug("\nHidden support");
+ node = document.getElementById("hidden");
+ axNode = accessibilityController.accessibleElementById("hidden");
+ shouldBeFalse("axNode.isIgnored");
+
+ node.accessibleNode.hidden = true;
+ axNode = accessibilityController.accessibleElementById("hidden");
+ shouldBeTrue("axNode == null || axNode == undefined");
+ }
+
+ function testModal() {
+ debug("\nModal support");
+ node = document.getElementById("modal");
+ axNode = accessibilityController.accessibleElementById("modal");
+ shouldBeTrue("dialogBackgroundAccessible()");
+ node.accessibleNode.modal = true;
+ shouldBeFalse("dialogBackgroundAccessible()");
+ node.accessibleNode.modal = false;
+ }
+
+ function testMultiline() {
+ debug("\nMultiline support");
+ node = document.getElementById("multiline");
+ axNode = accessibilityController.accessibleElementById("multiline");
+ shouldBeFalse("axNode.boolAttributeValue('AXIsMultiline')");
+ node.accessibleNode.multiline = true;
+ shouldBeTrue("axNode.boolAttributeValue('AXIsMultiline')");
+ }
+
+ function testMultiselectable() {
+ debug("\nMultiselectable support");
+ node = document.getElementById("multiselectable");
+ axNode = accessibilityController.accessibleElementById("multiselectable");
+ shouldBeFalse("axNode.isMultiSelectable");
+ node.accessibleNode.multiselectable = true;
+ shouldBeTrue("axNode.isMultiSelectable");
+ }
+
+ function testReadOnly() {
+ debug("\nReadOnly support");
+ node = document.getElementById("readOnly");
+ axNode = accessibilityController.accessibleElementById("readOnly");
+ shouldBeEqualToString("axNode.stringAttributeValue('AXReadOnlyValue')", "false");
+ node.accessibleNode.readOnly = true;
+ shouldBeEqualToString("axNode.stringAttributeValue('AXReadOnlyValue')", "true");
+ }
+
+ function testRequired() {
+ debug("\nRequired support");
+ node = document.getElementById("required");
+ axNode = accessibilityController.accessibleElementById("required");
+ shouldBeFalse("axNode.isRequired");
+ node.accessibleNode.required = true;
+ shouldBeTrue("axNode.isRequired");
+ }
+
+ function testSelected() {
+ debug("\nSelected support");
+ node = document.getElementById("selected");
+ axNode = accessibilityController.accessibleElementById("selected");
+ shouldBeFalse("axNode.isSelected");
+ node.accessibleNode.selected = true;
+ shouldBeTrue("axNode.isSelected");
+ }
+
+</script>
+<script src=""
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (224991 => 224992)
--- trunk/Source/WebCore/ChangeLog 2017-11-17 23:10:45 UTC (rev 224991)
+++ trunk/Source/WebCore/ChangeLog 2017-11-17 23:14:18 UTC (rev 224992)
@@ -1,3 +1,125 @@
+2017-11-17 Nan Wang <n_w...@apple.com>
+
+ AX: AOM: Implement boolean type properties
+ https://bugs.webkit.org/show_bug.cgi?id=179496
+
+ Reviewed by Chris Fleizach.
+
+ Accessibility Object Model
+ Explainer: https://wicg.github.io/aom/explainer.html
+ Spec: https://wicg.github.io/aom/spec/
+
+ Implemented the boolean type properties for Accessibility Object Modal.
+
+ Test: accessibility/mac/AOM-bool-properties.html
+
+ * accessibility/AXObjectCache.cpp:
+ (WebCore::AXObjectCache::AXObjectCache):
+ (WebCore::AXObjectCache::~AXObjectCache):
+ (WebCore::AXObjectCache::findModalNodes):
+ (WebCore::AXObjectCache::updateCurrentModalNode):
+ (WebCore::AXObjectCache::modalNode):
+ (WebCore::AXObjectCache::remove):
+ (WebCore::AXObjectCache::handleMenuItemSelected):
+ (WebCore::AXObjectCache::focusModalNode):
+ (WebCore::AXObjectCache::focusModalNodeTimerFired):
+ (WebCore::AXObjectCache::handleAttributeChanged):
+ (WebCore::AXObjectCache::handleModalChange):
+ (WebCore::isNodeAriaVisible):
+ (WebCore::AXObjectCache::findAriaModalNodes): Deleted.
+ (WebCore::AXObjectCache::updateCurrentAriaModalNode): Deleted.
+ (WebCore::AXObjectCache::ariaModalNode): Deleted.
+ (WebCore::AXObjectCache::focusAriaModalNode): Deleted.
+ (WebCore::AXObjectCache::focusAriaModalNodeTimerFired): Deleted.
+ (WebCore::AXObjectCache::handleAriaModalChange): Deleted.
+ * accessibility/AXObjectCache.h:
+ (WebCore::AXObjectCache::AXObjectCache):
+ (WebCore::AXObjectCache::modalNode):
+ (WebCore::AXObjectCache::focusModalNodeTimerFired):
+ (WebCore::AXObjectCache::handleModalChange):
+ (WebCore::AXObjectCache::ariaModalNode): Deleted.
+ (WebCore::AXObjectCache::focusAriaModalNodeTimerFired): Deleted.
+ (WebCore::AXObjectCache::handleAriaModalChange): Deleted.
+ * accessibility/AccessibilityARIAGrid.cpp:
+ (WebCore::AccessibilityARIAGrid::isMultiSelectable const):
+ * accessibility/AccessibilityARIAGridCell.cpp:
+ (WebCore::AccessibilityARIAGridCell::readOnlyValue const):
+ (WebCore::AccessibilityARIAGridCell::ariaReadOnlyValue const): Deleted.
+ * accessibility/AccessibilityARIAGridCell.h:
+ * accessibility/AccessibilityListBoxOption.cpp:
+ (WebCore::AccessibilityListBoxOption::isEnabled const):
+ * accessibility/AccessibilityNodeObject.cpp:
+ (WebCore::AccessibilityNodeObject::isEnabled const):
+ (WebCore::AccessibilityNodeObject::isMultiSelectable const):
+ (WebCore::AccessibilityNodeObject::isRequired const):
+ (WebCore::shouldUseAccessibilityObjectInnerText):
+ (WebCore::AccessibilityNodeObject::canSetValueAttribute const):
+ * accessibility/AccessibilityObject.cpp:
+ (WebCore::AccessibilityObject::supportsReadOnly const):
+ (WebCore::AccessibilityObject::readOnlyValue const):
+ (WebCore::AccessibilityObject::ariaIsMultiline const):
+ (WebCore::AccessibilityObject::isModalDescendant const):
+ (WebCore::AccessibilityObject::isModalNode const):
+ (WebCore::AccessibilityObject::ignoredFromModalPresence const):
+ (WebCore::AccessibilityObject::boolValueForProperty const):
+ (WebCore::AccessibilityObject::supportsARIAAttributes const):
+ (WebCore::AccessibilityObject::supportsExpanded const):
+ (WebCore::AccessibilityObject::isExpanded const):
+ (WebCore::AccessibilityObject::isAXHidden const):
+ (WebCore::AccessibilityObject::defaultObjectInclusion const):
+ (WebCore::AccessibilityObject::setIsIgnoredFromParentDataForChild):
+ (WebCore::AccessibilityObject::supportsARIAReadOnly const): Deleted.
+ (WebCore::AccessibilityObject::ariaReadOnlyValue const): Deleted.
+ (WebCore::AccessibilityObject::isAriaModalDescendant const): Deleted.
+ (WebCore::AccessibilityObject::isAriaModalNode const): Deleted.
+ (WebCore::AccessibilityObject::ignoredFromARIAModalPresence const): Deleted.
+ (WebCore::AccessibilityObject::isARIAHidden const): Deleted.
+ * accessibility/AccessibilityObject.h:
+ (WebCore::AccessibilityObject::isHidden const):
+ * accessibility/AccessibilityRenderObject.cpp:
+ (WebCore::AccessibilityRenderObject::defaultObjectInclusion const):
+ (WebCore::AccessibilityRenderObject::isSelected const):
+ (WebCore::AccessibilityRenderObject::canSetExpandedAttribute const):
+ (WebCore::AccessibilityRenderObject::liveRegionAtomic const):
+ (WebCore::AccessibilityRenderObject::isBusy const):
+ * accessibility/AccessibleNode.cpp:
+ (WebCore::ariaAttributeMap):
+ (WebCore::isPropertyValueBoolean):
+ (WebCore::AccessibleNode::effectiveBoolValueForElement):
+ (WebCore::AccessibleNode::boolValueForProperty):
+ (WebCore::AccessibleNode::setBoolProperty):
+ (WebCore::AccessibleNode::atomic const):
+ (WebCore::AccessibleNode::setAtomic):
+ (WebCore::AccessibleNode::busy const):
+ (WebCore::AccessibleNode::setBusy):
+ (WebCore::AccessibleNode::disabled const):
+ (WebCore::AccessibleNode::setDisabled):
+ (WebCore::AccessibleNode::expanded const):
+ (WebCore::AccessibleNode::setExpanded):
+ (WebCore::AccessibleNode::hidden const):
+ (WebCore::AccessibleNode::setHidden):
+ (WebCore::AccessibleNode::modal const):
+ (WebCore::AccessibleNode::setModal):
+ (WebCore::AccessibleNode::multiline const):
+ (WebCore::AccessibleNode::setMultiline):
+ (WebCore::AccessibleNode::multiselectable const):
+ (WebCore::AccessibleNode::setMultiselectable):
+ (WebCore::AccessibleNode::readOnly const):
+ (WebCore::AccessibleNode::setReadOnly):
+ (WebCore::AccessibleNode::required const):
+ (WebCore::AccessibleNode::setRequired):
+ (WebCore::AccessibleNode::selected const):
+ (WebCore::AccessibleNode::setSelected):
+ * accessibility/AccessibleNode.h:
+ * accessibility/AccessibleNode.idl:
+ * accessibility/atk/WebKitAccessibleWrapperAtk.cpp:
+ (webkitAccessibleGetAttributes):
+ (setAtkStateSetFromCoreObject):
+ * accessibility/mac/WebAccessibilityObjectWrapperMac.mm:
+ (-[WebAccessibilityObjectWrapper accessibilityAttributeValue:]):
+ * inspector/agents/InspectorDOMAgent.cpp:
+ (WebCore::InspectorDOMAgent::buildObjectForAccessibilityProperties):
+
2017-11-17 Alex Christensen <achristen...@webkit.org>
Clean up URL.h
Modified: trunk/Source/WebCore/accessibility/AXObjectCache.cpp (224991 => 224992)
--- trunk/Source/WebCore/accessibility/AXObjectCache.cpp 2017-11-17 23:10:45 UTC (rev 224991)
+++ trunk/Source/WebCore/accessibility/AXObjectCache.cpp 2017-11-17 23:14:18 UTC (rev 224992)
@@ -117,7 +117,7 @@
// Post value change notifications for password fields or elements contained in password fields at a 40hz interval to thwart analysis of typing cadence
static const Seconds accessibilityPasswordValueChangeNotificationInterval { 25_ms };
static const Seconds accessibilityLiveRegionChangedNotificationInterval { 20_ms };
-static const Seconds accessibilityFocusAriaModalNodeNotificationInterval { 50_ms };
+static const Seconds accessibilityFocusModalNodeNotificationInterval { 50_ms };
AccessibilityObjectInclusion AXComputedObjectAttributeCache::getIgnored(AXID id) const
{
@@ -191,10 +191,10 @@
, m_notificationPostTimer(*this, &AXObjectCache::notificationPostTimerFired)
, m_passwordNotificationPostTimer(*this, &AXObjectCache::passwordNotificationPostTimerFired)
, m_liveRegionChangedPostTimer(*this, &AXObjectCache::liveRegionChangedNotificationPostTimerFired)
- , m_focusAriaModalNodeTimer(*this, &AXObjectCache::focusAriaModalNodeTimerFired)
- , m_currentAriaModalNode(nullptr)
+ , m_focusModalNodeTimer(*this, &AXObjectCache::focusModalNodeTimerFired)
+ , m_currentModalNode(nullptr)
{
- findAriaModalNodes();
+ findModalNodes();
}
AXObjectCache::~AXObjectCache()
@@ -201,7 +201,7 @@
{
m_notificationPostTimer.stop();
m_liveRegionChangedPostTimer.stop();
- m_focusAriaModalNodeTimer.stop();
+ m_focusModalNodeTimer.stop();
for (const auto& object : m_objects.values()) {
detachWrapper(object.get(), AccessibilityDetachmentType::CacheDestroyed);
@@ -210,7 +210,7 @@
}
}
-void AXObjectCache::findAriaModalNodes()
+void AXObjectCache::findModalNodes()
{
// Traverse the DOM tree to look for the aria-modal=true nodes.
for (Element* element = ElementTraversal::firstWithin(document().rootNode()); element; element = ElementTraversal::nextIncludingPseudo(*element)) {
@@ -218,27 +218,27 @@
// Must have dialog or alertdialog role
if (!nodeHasRole(element, "dialog") && !nodeHasRole(element, "alertdialog"))
continue;
- if (!equalLettersIgnoringASCIICase(element->attributeWithoutSynchronization(aria_modalAttr), "true"))
+ if (!AccessibleNode::effectiveBoolValueForElement(*element, AXPropertyName::Modal).value())
continue;
- m_ariaModalNodesSet.add(element);
+ m_modalNodesSet.add(element);
}
// Set the current valid aria-modal node if possible.
- updateCurrentAriaModalNode();
+ updateCurrentModalNode();
}
-void AXObjectCache::updateCurrentAriaModalNode()
+void AXObjectCache::updateCurrentModalNode()
{
// There might be multiple nodes with aria-modal=true set.
// We use this function to pick the one we want.
- m_currentAriaModalNode = nullptr;
- if (m_ariaModalNodesSet.isEmpty())
+ m_currentModalNode = nullptr;
+ if (m_modalNodesSet.isEmpty())
return;
// We only care about the nodes which are visible.
ListHashSet<RefPtr<Node>> visibleNodes;
- for (auto& object : m_ariaModalNodesSet) {
+ for (auto& object : m_modalNodesSet) {
if (isNodeVisible(object))
visibleNodes.add(object);
}
@@ -250,14 +250,14 @@
Node* focusedNode = document().focusedElement();
for (auto& object : visibleNodes) {
if (focusedNode != nullptr && focusedNode->isDescendantOf(object.get())) {
- m_currentAriaModalNode = object.get();
+ m_currentModalNode = object.get();
break;
}
}
// If none of the nodes are focused, we want to pick the last dialog in the DOM.
- if (!m_currentAriaModalNode)
- m_currentAriaModalNode = visibleNodes.last().get();
+ if (!m_currentModalNode)
+ m_currentModalNode = visibleNodes.last().get();
}
bool AXObjectCache::isNodeVisible(Node* node) const
@@ -279,20 +279,20 @@
return true;
}
-Node* AXObjectCache::ariaModalNode()
+Node* AXObjectCache::modalNode()
{
// This function returns the valid aria modal node.
- if (m_ariaModalNodesSet.isEmpty())
+ if (m_modalNodesSet.isEmpty())
return nullptr;
// Check the current valid aria modal node first.
// Usually when one dialog sets aria-modal=true, that dialog is the one we want.
- if (isNodeVisible(m_currentAriaModalNode))
- return m_currentAriaModalNode;
+ if (isNodeVisible(m_currentModalNode))
+ return m_currentModalNode;
- // Recompute the valid aria modal node when m_currentAriaModalNode is null or hidden.
- updateCurrentAriaModalNode();
- return isNodeVisible(m_currentAriaModalNode) ? m_currentAriaModalNode : nullptr;
+ // Recompute the valid aria modal node when m_currentModalNode is null or hidden.
+ updateCurrentModalNode();
+ return isNodeVisible(m_currentModalNode) ? m_currentModalNode : nullptr;
}
AccessibilityObject* AXObjectCache::focusedImageMapUIElement(HTMLAreaElement* areaElement)
@@ -739,10 +739,10 @@
m_nodeObjectMapping.remove(node);
// Cleanup for aria modal nodes.
- if (m_currentAriaModalNode == node)
- m_currentAriaModalNode = nullptr;
- if (m_ariaModalNodesSet.contains(node))
- m_ariaModalNodesSet.remove(node);
+ if (m_currentModalNode == node)
+ m_currentModalNode = nullptr;
+ if (m_modalNodesSet.contains(node))
+ m_modalNodesSet.remove(node);
if (node->renderer()) {
remove(node->renderer());
@@ -1022,7 +1022,7 @@
if (!nodeHasRole(node, "menuitem") && !nodeHasRole(node, "menuitemradio") && !nodeHasRole(node, "menuitemcheckbox"))
return;
- if (!downcast<Element>(*node).focused() && !equalLettersIgnoringASCIICase(downcast<Element>(*node).attributeWithoutSynchronization(aria_selectedAttr), "true"))
+ if (!downcast<Element>(*node).focused() && !AccessibleNode::effectiveBoolValueForElement(downcast<Element>(*node), AXPropertyName::Selected).value())
return;
postNotification(getOrCreate(node), &document(), AXMenuListItemSelected);
@@ -1392,26 +1392,26 @@
return nullptr;
}
-void AXObjectCache::focusAriaModalNode()
+void AXObjectCache::focusModalNode()
{
- if (m_focusAriaModalNodeTimer.isActive())
- m_focusAriaModalNodeTimer.stop();
+ if (m_focusModalNodeTimer.isActive())
+ m_focusModalNodeTimer.stop();
- m_focusAriaModalNodeTimer.startOneShot(accessibilityFocusAriaModalNodeNotificationInterval);
+ m_focusModalNodeTimer.startOneShot(accessibilityFocusModalNodeNotificationInterval);
}
-void AXObjectCache::focusAriaModalNodeTimerFired()
+void AXObjectCache::focusModalNodeTimerFired()
{
- if (!m_currentAriaModalNode)
+ if (!m_currentModalNode)
return;
// Don't set focus if we are already focusing onto some element within
// the dialog.
- if (m_currentAriaModalNode->contains(document().focusedElement()))
+ if (m_currentModalNode->contains(document().focusedElement()))
return;
- if (AccessibilityObject* currentAriaModalNodeObject = getOrCreate(m_currentAriaModalNode)) {
- if (AccessibilityObject* focusable = firstFocusableChild(currentAriaModalNodeObject))
+ if (AccessibilityObject* currentModalNodeObject = getOrCreate(m_currentModalNode)) {
+ if (AccessibilityObject* focusable = firstFocusableChild(currentModalNodeObject))
focusable->setFocused(true);
}
}
@@ -1481,7 +1481,7 @@
else if (attrName == aria_invalidAttr)
postNotification(element, AXObjectCache::AXInvalidStatusChanged);
else if (attrName == aria_modalAttr)
- handleAriaModalChange(element);
+ handleModalChange(element);
else if (attrName == aria_currentAttr)
postNotification(element, AXObjectCache::AXCurrentChanged);
else if (attrName == aria_disabledAttr)
@@ -1496,7 +1496,7 @@
postNotification(element, AXObjectCache::AXAriaAttributeChanged);
}
-void AXObjectCache::handleAriaModalChange(Node* node)
+void AXObjectCache::handleModalChange(Node* node)
{
if (!is<Element>(node))
return;
@@ -1505,18 +1505,18 @@
return;
stopCachingComputedObjectAttributes();
- if (equalLettersIgnoringASCIICase(downcast<Element>(*node).attributeWithoutSynchronization(aria_modalAttr), "true")) {
+ if (AccessibleNode::effectiveBoolValueForElement(downcast<Element>(*node), AXPropertyName::Modal).value()) {
// Add the newly modified node to the modal nodes set, and set it to be the current valid aria modal node.
- // We will recompute the current valid aria modal node in ariaModalNode() when this node is not visible.
- m_ariaModalNodesSet.add(node);
- m_currentAriaModalNode = node;
+ // We will recompute the current valid aria modal node in modalNode() when this node is not visible.
+ m_modalNodesSet.add(node);
+ m_currentModalNode = node;
} else {
// Remove the node from the modal nodes set. There might be other visible modal nodes, so we recompute here.
- m_ariaModalNodesSet.remove(node);
- updateCurrentAriaModalNode();
+ m_modalNodesSet.remove(node);
+ updateCurrentModalNode();
}
- if (m_currentAriaModalNode)
- focusAriaModalNode();
+ if (m_currentModalNode)
+ focusModalNode();
startCachingComputedObjectAttributesUntilTreeMutates();
}
@@ -2878,19 +2878,21 @@
// 3) if aria-hidden=false, and the object is NOT rendered, then it must have
// aria-hidden=false on each parent until it gets to a rendered object
// 3b) a text node inherits a parents aria-hidden value
- bool requiresAriaHiddenFalse = !node->renderer();
- bool ariaHiddenFalsePresent = false;
+ bool requiresAXHiddenFalse = !node->renderer();
+ bool axHiddenFalsePresent = false;
for (Node* testNode = node; testNode; testNode = testNode->parentNode()) {
if (is<Element>(*testNode)) {
- const AtomicString& ariaHiddenValue = downcast<Element>(*testNode).attributeWithoutSynchronization(aria_hiddenAttr);
- if (equalLettersIgnoringASCIICase(ariaHiddenValue, "true"))
+ std::optional<bool> hiddenValue = AccessibleNode::effectiveBoolValueForElement(downcast<Element>(*testNode), AXPropertyName::Hidden);
+ bool axHiddenFalse = false;
+ if (hiddenValue) {
+ if (hiddenValue.value())
+ return false;
+ axHiddenFalse = true;
+ }
+ if (!testNode->renderer() && !axHiddenFalse)
return false;
-
- bool ariaHiddenFalse = equalLettersIgnoringASCIICase(ariaHiddenValue, "false");
- if (!testNode->renderer() && !ariaHiddenFalse)
- return false;
- if (!ariaHiddenFalsePresent && ariaHiddenFalse)
- ariaHiddenFalsePresent = true;
+ if (!axHiddenFalsePresent && axHiddenFalse)
+ axHiddenFalsePresent = true;
// We should break early when it gets to a rendered object.
if (testNode->renderer())
break;
@@ -2897,7 +2899,7 @@
}
}
- return !requiresAriaHiddenFalse || ariaHiddenFalsePresent;
+ return !requiresAXHiddenFalse || axHiddenFalsePresent;
}
AccessibilityObject* AXObjectCache::rootWebArea()
Modified: trunk/Source/WebCore/accessibility/AXObjectCache.h (224991 => 224992)
--- trunk/Source/WebCore/accessibility/AXObjectCache.h 2017-11-17 23:10:45 UTC (rev 224991)
+++ trunk/Source/WebCore/accessibility/AXObjectCache.h 2017-11-17 23:14:18 UTC (rev 224992)
@@ -182,8 +182,8 @@
void handleAriaExpandedChange(Node*);
void handleScrollbarUpdate(ScrollView*);
- void handleAriaModalChange(Node*);
- Node* ariaModalNode();
+ void handleModalChange(Node*);
+ Node* modalNode();
void handleAttributeChanged(const QualifiedName& attrName, Element*);
void recomputeIsIgnored(RenderObject* renderer);
@@ -312,7 +312,7 @@
void postTextStateChangeNotification(Node*, const AXTextStateChangeIntent&, const VisibleSelection&);
void postTextStateChangeNotification(const Position&, const AXTextStateChangeIntent&, const VisibleSelection&);
void postLiveRegionChangeNotification(AccessibilityObject*);
- void focusAriaModalNode();
+ void focusModalNode();
enum AXLoadingEvent {
AXLoadingStarted,
@@ -401,7 +401,7 @@
void liveRegionChangedNotificationPostTimerFired();
- void focusAriaModalNodeTimerFired();
+ void focusModalNodeTimerFired();
void postTextStateChangeNotification(AccessibilityObject*, const AXTextStateChangeIntent&, const VisibleSelection&);
@@ -413,8 +413,8 @@
void handleMenuItemSelected(Node*);
// aria-modal related
- void findAriaModalNodes();
- void updateCurrentAriaModalNode();
+ void findModalNodes();
+ void updateCurrentModalNode();
bool isNodeVisible(Node*) const;
Document& m_document;
@@ -439,9 +439,9 @@
Timer m_liveRegionChangedPostTimer;
ListHashSet<RefPtr<AccessibilityObject>> m_liveRegionObjectsSet;
- Timer m_focusAriaModalNodeTimer;
- Node* m_currentAriaModalNode;
- ListHashSet<Node*> m_ariaModalNodesSet;
+ Timer m_focusModalNodeTimer;
+ Node* m_currentModalNode;
+ ListHashSet<Node*> m_modalNodesSet;
AXTextStateChangeIntent m_textSelectionIntent;
ListHashSet<Element*> m_deferredRecomputeIsIgnoredList;
@@ -472,7 +472,7 @@
inline AccessibilityReplacedText::AccessibilityReplacedText(const VisibleSelection&) { }
inline void AccessibilityReplacedText::postTextStateChangeNotification(AXObjectCache*, AXTextEditType, const String&, const VisibleSelection&) { }
inline void AXComputedObjectAttributeCache::setIgnored(AXID, AccessibilityObjectInclusion) { }
-inline AXObjectCache::AXObjectCache(Document& document) : m_document(document), m_notificationPostTimer(*this, &AXObjectCache::notificationPostTimerFired), m_passwordNotificationPostTimer(*this, &AXObjectCache::passwordNotificationPostTimerFired), m_liveRegionChangedPostTimer(*this, &AXObjectCache::liveRegionChangedNotificationPostTimerFired), m_focusAriaModalNodeTimer(*this, &AXObjectCache::focusAriaModalNodeTimerFired) { }
+inline AXObjectCache::AXObjectCache(Document& document) : m_document(document), m_notificationPostTimer(*this, &AXObjectCache::notificationPostTimerFired), m_passwordNotificationPostTimer(*this, &AXObjectCache::passwordNotificationPostTimerFired), m_liveRegionChangedPostTimer(*this, &AXObjectCache::liveRegionChangedNotificationPostTimerFired), m_focusModalNodeTimer(*this, &AXObjectCache::focusModalNodeTimerFired) { }
inline AXObjectCache::~AXObjectCache() { }
inline AccessibilityObject* AXObjectCache::focusedUIElementForPage(const Page*) { return nullptr; }
inline AccessibilityObject* AXObjectCache::get(RenderObject*) { return nullptr; }
@@ -489,7 +489,7 @@
inline void AXObjectCache::stopCachingComputedObjectAttributes() { }
inline bool isNodeAriaVisible(Node*) { return true; }
inline const Element* AXObjectCache::rootAXEditableElement(const Node*) { return nullptr; }
-inline Node* AXObjectCache::ariaModalNode() { return nullptr; }
+inline Node* AXObjectCache::modalNode() { return nullptr; }
inline void AXObjectCache::attachWrapper(AccessibilityObject*) { }
inline void AXObjectCache::checkedStateChanged(Node*) { }
inline void AXObjectCache::childrenChanged(AccessibilityObject*) { }
@@ -500,12 +500,12 @@
inline void AXObjectCache::deferTextChangedIfNeeded(Node*) { }
inline void AXObjectCache::deferSelectedChildrenChangedIfNeeded(Element&) { }
inline void AXObjectCache::detachWrapper(AccessibilityObject*, AccessibilityDetachmentType) { }
-inline void AXObjectCache::focusAriaModalNodeTimerFired() { }
+inline void AXObjectCache::focusModalNodeTimerFired() { }
inline void AXObjectCache::frameLoadingEventNotification(Frame*, AXLoadingEvent) { }
inline void AXObjectCache::frameLoadingEventPlatformNotification(AccessibilityObject*, AXLoadingEvent) { }
inline void AXObjectCache::handleActiveDescendantChanged(Node*) { }
inline void AXObjectCache::handleAriaExpandedChange(Node*) { }
-inline void AXObjectCache::handleAriaModalChange(Node*) { }
+inline void AXObjectCache::handleModalChange(Node*) { }
inline void AXObjectCache::handleAriaRoleChanged(Node*) { }
inline void AXObjectCache::handleAttributeChanged(const QualifiedName&, Element*) { }
inline void AXObjectCache::handleFocusedUIElementChanged(Node*, Node*) { }
Modified: trunk/Source/WebCore/accessibility/AccessibilityARIAGrid.cpp (224991 => 224992)
--- trunk/Source/WebCore/accessibility/AccessibilityARIAGrid.cpp 2017-11-17 23:10:45 UTC (rev 224991)
+++ trunk/Source/WebCore/accessibility/AccessibilityARIAGrid.cpp 2017-11-17 23:14:18 UTC (rev 224992)
@@ -82,8 +82,10 @@
bool AccessibilityARIAGrid::isMultiSelectable() const
{
- const AtomicString& ariaMultiSelectable = getAttribute(HTMLNames::aria_multiselectableAttr);
- return !equalLettersIgnoringASCIICase(ariaMultiSelectable, "false");
+ std::optional<bool> multiSelectable = boolValueForProperty(AXPropertyName::Multiselectable);
+ if (multiSelectable && !multiSelectable.value())
+ return false;
+ return true;
}
void AccessibilityARIAGrid::addRowDescendant(AccessibilityObject* rowChild, HashSet<AccessibilityObject*>& appendedRows, unsigned& columnCount)
Modified: trunk/Source/WebCore/accessibility/AccessibilityARIAGridCell.cpp (224991 => 224992)
--- trunk/Source/WebCore/accessibility/AccessibilityARIAGridCell.cpp 2017-11-17 23:10:45 UTC (rev 224991)
+++ trunk/Source/WebCore/accessibility/AccessibilityARIAGridCell.cpp 2017-11-17 23:14:18 UTC (rev 224992)
@@ -177,15 +177,15 @@
return parentTable();
}
-String AccessibilityARIAGridCell::ariaReadOnlyValue() const
+String AccessibilityARIAGridCell::readOnlyValue() const
{
- if (hasAttribute(aria_readonlyAttr))
- return getAttribute(aria_readonlyAttr).string().convertToASCIILowercase();
+ if (hasProperty(AXPropertyName::ReadOnly))
+ return boolValueForProperty(AXPropertyName::ReadOnly).value() ? "true" : "false";
// ARIA 1.1 requires user agents to propagate the grid's aria-readonly value to all
// gridcell elements if the property is not present on the gridcell element itelf.
if (AccessibilityObject* parent = parentTable())
- return parent->ariaReadOnlyValue();
+ return parent->readOnlyValue();
return String();
}
Modified: trunk/Source/WebCore/accessibility/AccessibilityARIAGridCell.h (224991 => 224992)
--- trunk/Source/WebCore/accessibility/AccessibilityARIAGridCell.h 2017-11-17 23:10:45 UTC (rev 224991)
+++ trunk/Source/WebCore/accessibility/AccessibilityARIAGridCell.h 2017-11-17 23:14:18 UTC (rev 224992)
@@ -48,7 +48,7 @@
AccessibilityTable* parentTable() const override;
AccessibilityObject* parentRowGroup() const;
unsigned ariaRowSpanWithRowIndex(unsigned index) const;
- String ariaReadOnlyValue() const override;
+ String readOnlyValue() const override;
};
} // namespace WebCore
Modified: trunk/Source/WebCore/accessibility/AccessibilityListBoxOption.cpp (224991 => 224992)
--- trunk/Source/WebCore/accessibility/AccessibilityListBoxOption.cpp 2017-11-17 23:10:45 UTC (rev 224991)
+++ trunk/Source/WebCore/accessibility/AccessibilityListBoxOption.cpp 2017-11-17 23:14:18 UTC (rev 224992)
@@ -63,7 +63,7 @@
if (is<HTMLOptGroupElement>(m_optionElement))
return false;
- if (equalLettersIgnoringASCIICase(getAttribute(aria_disabledAttr), "true"))
+ if (boolValueForProperty(AXPropertyName::Disabled).value())
return false;
if (m_optionElement->hasAttributeWithoutSynchronization(disabledAttr))
Modified: trunk/Source/WebCore/accessibility/AccessibilityNodeObject.cpp (224991 => 224992)
--- trunk/Source/WebCore/accessibility/AccessibilityNodeObject.cpp 2017-11-17 23:10:45 UTC (rev 224991)
+++ trunk/Source/WebCore/accessibility/AccessibilityNodeObject.cpp 2017-11-17 23:14:18 UTC (rev 224992)
@@ -625,11 +625,11 @@
{
// ARIA says that the disabled status applies to the current element and all descendant elements.
for (AccessibilityObject* object = const_cast<AccessibilityNodeObject*>(this); object; object = object->parentObject()) {
- const AtomicString& disabledStatus = object->getAttribute(aria_disabledAttr);
- if (equalLettersIgnoringASCIICase(disabledStatus, "true"))
- return false;
- if (equalLettersIgnoringASCIICase(disabledStatus, "false"))
+ if (std::optional<bool> disabled = object->boolValueForProperty(AXPropertyName::Disabled)) {
+ if (disabled.value())
+ return false;
break;
+ }
}
if (roleValue() == AccessibilityRole::HorizontalRule)
@@ -704,11 +704,9 @@
bool AccessibilityNodeObject::isMultiSelectable() const
{
- const AtomicString& ariaMultiSelectable = getAttribute(aria_multiselectableAttr);
- if (equalLettersIgnoringASCIICase(ariaMultiSelectable, "true"))
- return true;
- if (equalLettersIgnoringASCIICase(ariaMultiSelectable, "false"))
- return false;
+ std::optional<bool> multiSelectable = boolValueForProperty(AXPropertyName::Multiselectable);
+ if (multiSelectable)
+ return multiSelectable.value();
return node() && node()->hasTagName(selectTag) && downcast<HTMLSelectElement>(*node()).multiple();
}
@@ -716,11 +714,9 @@
bool AccessibilityNodeObject::isRequired() const
{
// Explicit aria-required values should trump native required attributes.
- const AtomicString& requiredValue = getAttribute(aria_requiredAttr);
- if (equalLettersIgnoringASCIICase(requiredValue, "true"))
- return true;
- if (equalLettersIgnoringASCIICase(requiredValue, "false"))
- return false;
+ std::optional<bool> axRequired = boolValueForProperty(AXPropertyName::Required);
+ if (axRequired)
+ return axRequired.value();
Node* n = this->node();
if (is<HTMLFormControlElement>(n))
@@ -1688,7 +1684,7 @@
&& !obj->accessibleNameDerivesFromContent())
return false;
- if (equalLettersIgnoringASCIICase(obj->getAttribute(aria_hiddenAttr), "true"))
+ if (obj->boolValueForProperty(AXPropertyName::Hidden).value())
return false;
// If something doesn't expose any children, then we can always take the inner text content.
@@ -2077,7 +2073,7 @@
return !input.isReadOnly();
}
- String readOnly = ariaReadOnlyValue();
+ String readOnly = readOnlyValue();
if (!readOnly.isEmpty())
return readOnly == "true" ? false : true;
@@ -2093,12 +2089,12 @@
#if PLATFORM(GTK)
// In ATK, input types which support aria-readonly are treated as having a
// settable value if the user can modify the widget's value or its state.
- if (supportsARIAReadOnly())
+ if (supportsReadOnly())
return true;
if (isRadioButton()) {
auto radioGroup = radioGroupAncestor();
- return radioGroup ? radioGroup->ariaReadOnlyValue() != "true" : true;
+ return radioGroup ? radioGroup->readOnlyValue() != "true" : true;
}
#endif
Modified: trunk/Source/WebCore/accessibility/AccessibilityObject.cpp (224991 => 224992)
--- trunk/Source/WebCore/accessibility/AccessibilityObject.cpp 2017-11-17 23:10:45 UTC (rev 224991)
+++ trunk/Source/WebCore/accessibility/AccessibilityObject.cpp 2017-11-17 23:14:18 UTC (rev 224992)
@@ -1634,7 +1634,7 @@
return contentEditableAttributeIsEnabled(element());
}
-bool AccessibilityObject::supportsARIAReadOnly() const
+bool AccessibilityObject::supportsReadOnly() const
{
AccessibilityRole role = roleValue();
@@ -1657,12 +1657,12 @@
|| isPasswordField();
}
-String AccessibilityObject::ariaReadOnlyValue() const
+String AccessibilityObject::readOnlyValue() const
{
- if (!hasAttribute(aria_readonlyAttr))
- return ariaRoleAttribute() != AccessibilityRole::Unknown && supportsARIAReadOnly() ? "false" : String();
+ if (!hasProperty(AXPropertyName::ReadOnly))
+ return ariaRoleAttribute() != AccessibilityRole::Unknown && supportsReadOnly() ? "false" : String();
- return getAttribute(aria_readonlyAttr).string().convertToASCIILowercase();
+ return boolValueForProperty(AXPropertyName::ReadOnly).value() ? "true" : "false";
}
bool AccessibilityObject::supportsAutoComplete() const
@@ -1988,7 +1988,7 @@
bool AccessibilityObject::ariaIsMultiline() const
{
- return equalLettersIgnoringASCIICase(getAttribute(aria_multilineAttr), "true");
+ return boolValueForProperty(AXPropertyName::Multiline).value();
}
String AccessibilityObject::invalidStatus() const
@@ -2076,32 +2076,32 @@
}
}
-bool AccessibilityObject::isAriaModalDescendant(Node* ariaModalNode) const
+bool AccessibilityObject::isModalDescendant(Node* modalNode) const
{
- if (!ariaModalNode || !this->element())
+ if (!modalNode || !this->element())
return false;
- if (this->element() == ariaModalNode)
+ if (this->element() == modalNode)
return true;
// ARIA 1.1 aria-modal, indicates whether an element is modal when displayed.
// For the decendants of the modal object, they should also be considered as aria-modal=true.
for (auto& ancestor : elementAncestors(this->element())) {
- if (&ancestor == ariaModalNode)
+ if (&ancestor == modalNode)
return true;
}
return false;
}
-bool AccessibilityObject::isAriaModalNode() const
+bool AccessibilityObject::isModalNode() const
{
if (AXObjectCache* cache = axObjectCache())
- return node() && cache->ariaModalNode() == node();
+ return node() && cache->modalNode() == node();
return false;
}
-bool AccessibilityObject::ignoredFromARIAModalPresence() const
+bool AccessibilityObject::ignoredFromModalPresence() const
{
// We shouldn't ignore the top node.
if (!node() || !node()->parentNode())
@@ -2111,16 +2111,16 @@
if (!cache)
return false;
- // ariaModalNode is the current displayed modal dialog.
- Node* ariaModalNode = cache->ariaModalNode();
- if (!ariaModalNode)
+ // modalNode is the current displayed modal dialog.
+ Node* modalNode = cache->modalNode();
+ if (!modalNode)
return false;
// We only want to ignore the objects within the same frame as the modal dialog.
- if (ariaModalNode->document().frame() != this->frame())
+ if (modalNode->document().frame() != this->frame())
return false;
- return !isAriaModalDescendant(ariaModalNode);
+ return !isModalDescendant(modalNode);
}
bool AccessibilityObject::hasTagName(const QualifiedName& tagName) const
@@ -2159,6 +2159,13 @@
return nullAtom();
}
+std::optional<bool> AccessibilityObject::boolValueForProperty(AXPropertyName propertyKey) const
+{
+ if (Element* element = this->element())
+ return AccessibleNode::effectiveBoolValueForElement(*element, propertyKey);
+ return std::nullopt;
+}
+
// Lacking concrete evidence of orientation, horizontal means width > height. vertical is height > width;
AccessibilityOrientation AccessibilityObject::orientation() const
{
@@ -2523,13 +2530,13 @@
|| supportsARIADragging()
|| supportsARIADropping()
|| supportsARIAOwns()
- || hasAttribute(aria_atomicAttr)
- || hasAttribute(aria_busyAttr)
+ || hasProperty(AXPropertyName::Atomic)
+ || hasProperty(AXPropertyName::Busy)
|| hasAttribute(aria_controlsAttr)
|| hasProperty(AXPropertyName::Current)
|| hasAttribute(aria_describedbyAttr)
|| hasAttribute(aria_detailsAttr)
- || hasAttribute(aria_disabledAttr)
+ || hasProperty(AXPropertyName::Disabled)
|| hasAttribute(aria_errormessageAttr)
|| hasAttribute(aria_flowtoAttr)
|| hasProperty(AXPropertyName::HasPopUp)
@@ -2692,8 +2699,7 @@
bool AccessibilityObject::supportsExpanded() const
{
// Undefined values should not result in this attribute being exposed to ATs according to ARIA.
- const AtomicString& expanded = getAttribute(aria_expandedAttr);
- if (equalLettersIgnoringASCIICase(expanded, "true") || equalLettersIgnoringASCIICase(expanded, "false"))
+ if (boolValueForProperty(AXPropertyName::Expanded))
return true;
switch (roleValue()) {
case AccessibilityRole::ComboBox:
@@ -2707,7 +2713,7 @@
bool AccessibilityObject::isExpanded() const
{
- if (equalLettersIgnoringASCIICase(getAttribute(aria_expandedAttr), "true"))
+ if (boolValueForProperty(AXPropertyName::Expanded).value())
return true;
if (is<HTMLDetailsElement>(node()))
@@ -3173,10 +3179,10 @@
// ARIA component of hidden definition.
// http://www.w3.org/TR/wai-aria/terms#def_hidden
-bool AccessibilityObject::isARIAHidden() const
+bool AccessibilityObject::isAXHidden() const
{
return AccessibilityObject::matchedParent(*this, true, [] (const AccessibilityObject& object) {
- return equalLettersIgnoringASCIICase(object.getAttribute(aria_hiddenAttr), "true");
+ return object.boolValueForProperty(AXPropertyName::Hidden).value();
}) != nullptr;
}
@@ -3210,10 +3216,10 @@
{
bool useParentData = !m_isIgnoredFromParentData.isNull();
- if (useParentData ? m_isIgnoredFromParentData.isARIAHidden : isARIAHidden())
+ if (useParentData ? m_isIgnoredFromParentData.isAXHidden : isAXHidden())
return AccessibilityObjectInclusion::IgnoreObject;
- if (ignoredFromARIAModalPresence())
+ if (ignoredFromModalPresence())
return AccessibilityObjectInclusion::IgnoreObject;
if (useParentData ? m_isIgnoredFromParentData.isPresentationalChildOfAriaRole : isPresentationalChildOfAriaRole())
@@ -3509,11 +3515,11 @@
AccessibilityIsIgnoredFromParentData result = AccessibilityIsIgnoredFromParentData(this);
if (!m_isIgnoredFromParentData.isNull()) {
- result.isARIAHidden = m_isIgnoredFromParentData.isARIAHidden || equalLettersIgnoringASCIICase(child->getAttribute(aria_hiddenAttr), "true");
+ result.isAXHidden = m_isIgnoredFromParentData.isAXHidden || child->boolValueForProperty(AXPropertyName::Hidden).value();
result.isPresentationalChildOfAriaRole = m_isIgnoredFromParentData.isPresentationalChildOfAriaRole || ariaRoleHasPresentationalChildren();
result.isDescendantOfBarrenParent = m_isIgnoredFromParentData.isDescendantOfBarrenParent || !canHaveChildren();
} else {
- result.isARIAHidden = child->isARIAHidden();
+ result.isAXHidden = child->isAXHidden();
result.isPresentationalChildOfAriaRole = child->isPresentationalChildOfAriaRole();
result.isDescendantOfBarrenParent = child->isDescendantOfBarrenParent();
}
Modified: trunk/Source/WebCore/accessibility/AccessibilityObject.h (224991 => 224992)
--- trunk/Source/WebCore/accessibility/AccessibilityObject.h 2017-11-17 23:10:45 UTC (rev 224991)
+++ trunk/Source/WebCore/accessibility/AccessibilityObject.h 2017-11-17 23:14:18 UTC (rev 224992)
@@ -300,7 +300,7 @@
// we avoid going up the parent chain for each element while traversing the tree with useful information already.
struct AccessibilityIsIgnoredFromParentData {
AccessibilityObject* parent { nullptr };
- bool isARIAHidden { false };
+ bool isAXHidden { false };
bool isPresentationalChildOfAriaRole { false };
bool isDescendantOfBarrenParent { false };
@@ -704,9 +704,9 @@
const String keyShortcutsValue() const;
// This function checks if the object should be ignored when there's a modal dialog displayed.
- bool ignoredFromARIAModalPresence() const;
- bool isAriaModalDescendant(Node*) const;
- bool isAriaModalNode() const;
+ bool ignoredFromModalPresence() const;
+ bool isModalDescendant(Node*) const;
+ bool isModalNode() const;
bool supportsARIASetSize() const;
bool supportsARIAPosInSet() const;
@@ -895,6 +895,7 @@
bool hasProperty(AXPropertyName) const;
const String stringValueForProperty(AXPropertyName) const;
+ std::optional<bool> boolValueForProperty(AXPropertyName) const;
virtual VisiblePositionRange visiblePositionRange() const { return VisiblePositionRange(); }
virtual VisiblePositionRange visiblePositionRangeForLine(unsigned) const { return VisiblePositionRange(); }
@@ -990,8 +991,8 @@
static bool contentEditableAttributeIsEnabled(Element*);
bool hasContentEditableAttributeSet() const;
- bool supportsARIAReadOnly() const;
- virtual String ariaReadOnlyValue() const;
+ bool supportsReadOnly() const;
+ virtual String readOnlyValue() const;
bool supportsAutoComplete() const;
String autoCompleteValue() const;
@@ -1072,9 +1073,9 @@
virtual void mathPostscripts(AccessibilityMathMultiscriptPairs&) { }
// Visibility.
- bool isARIAHidden() const;
+ bool isAXHidden() const;
bool isDOMHidden() const;
- bool isHidden() const { return isARIAHidden() || isDOMHidden(); }
+ bool isHidden() const { return isAXHidden() || isDOMHidden(); }
#if HAVE(ACCESSIBILITY)
#if PLATFORM(GTK)
Modified: trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp (224991 => 224992)
--- trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp 2017-11-17 23:10:45 UTC (rev 224991)
+++ trunk/Source/WebCore/accessibility/AccessibilityRenderObject.cpp 2017-11-17 23:14:18 UTC (rev 224992)
@@ -1140,9 +1140,11 @@
if (m_renderer->style().visibility() != VISIBLE) {
// aria-hidden is meant to override visibility as the determinant in AX hierarchy inclusion.
- if (equalLettersIgnoringASCIICase(getAttribute(aria_hiddenAttr), "false"))
- return AccessibilityObjectInclusion::DefaultBehavior;
-
+ if (std::optional<bool> hidden = boolValueForProperty(AXPropertyName::Hidden)) {
+ if (!hidden.value())
+ return AccessibilityObjectInclusion::DefaultBehavior;
+ }
+
return AccessibilityObjectInclusion::IgnoreObject;
}
@@ -1630,7 +1632,7 @@
if (!m_renderer->node())
return false;
- if (equalLettersIgnoringASCIICase(getAttribute(aria_selectedAttr), "true"))
+ if (boolValueForProperty(AXPropertyName::Selected).value())
return true;
if (isTabItem() && isTabItemSelected())
@@ -2942,8 +2944,9 @@
return true;
// An object can be expanded if it aria-expanded is true or false.
- const AtomicString& ariaExpanded = getAttribute(aria_expandedAttr);
- return equalLettersIgnoringASCIICase(ariaExpanded, "true") || equalLettersIgnoringASCIICase(ariaExpanded, "false");
+ if (boolValueForProperty(AXPropertyName::Expanded))
+ return true;
+ return false;
}
bool AccessibilityRenderObject::canSetTextRangeAttributes() const
@@ -3276,11 +3279,8 @@
bool AccessibilityRenderObject::liveRegionAtomic() const
{
- const AtomicString& atomic = getAttribute(aria_atomicAttr);
- if (equalLettersIgnoringASCIICase(atomic, "true"))
- return true;
- if (equalLettersIgnoringASCIICase(atomic, "false"))
- return false;
+ if (std::optional<bool> atomic = boolValueForProperty(AXPropertyName::Atomic))
+ return atomic.value();
// WAI-ARIA "alert" and "status" roles have an implicit aria-atomic value of true.
switch (roleValue()) {
@@ -3294,7 +3294,7 @@
bool AccessibilityRenderObject::isBusy() const
{
- return elementAttributeValue(aria_busyAttr);
+ return boolValueForProperty(AXPropertyName::Busy).value();
}
bool AccessibilityRenderObject::canHaveSelectedChildren() const
Modified: trunk/Source/WebCore/accessibility/AccessibleNode.cpp (224991 => 224992)
--- trunk/Source/WebCore/accessibility/AccessibleNode.cpp 2017-11-17 23:10:45 UTC (rev 224991)
+++ trunk/Source/WebCore/accessibility/AccessibleNode.cpp 2017-11-17 23:14:18 UTC (rev 224992)
@@ -45,20 +45,31 @@
AXPropertyName name;
QualifiedName ariaAttribute;
} attributes[] = {
+ { AXPropertyName::Atomic, aria_atomicAttr },
{ AXPropertyName::Autocomplete, aria_autocompleteAttr },
+ { AXPropertyName::Busy, aria_busyAttr },
{ AXPropertyName::Checked, aria_checkedAttr },
{ AXPropertyName::Current, aria_currentAttr },
+ { AXPropertyName::Disabled, aria_disabledAttr },
+ { AXPropertyName::Expanded, aria_expandedAttr },
{ AXPropertyName::HasPopUp, aria_haspopupAttr },
+ { AXPropertyName::Hidden, aria_hiddenAttr },
{ AXPropertyName::Invalid, aria_invalidAttr },
{ AXPropertyName::KeyShortcuts, aria_keyshortcutsAttr },
{ AXPropertyName::Label, aria_labelAttr },
{ AXPropertyName::Live, aria_liveAttr },
+ { AXPropertyName::Modal, aria_modalAttr },
+ { AXPropertyName::Multiline, aria_multilineAttr },
+ { AXPropertyName::Multiselectable, aria_multiselectableAttr },
{ AXPropertyName::Orientation, aria_orientationAttr },
{ AXPropertyName::Placeholder, aria_placeholderAttr },
{ AXPropertyName::Pressed, aria_pressedAttr },
+ { AXPropertyName::ReadOnly, aria_readonlyAttr },
{ AXPropertyName::Relevant, aria_relevantAttr },
+ { AXPropertyName::Required, aria_requiredAttr },
{ AXPropertyName::Role, roleAttr },
{ AXPropertyName::RoleDescription, aria_roledescriptionAttr },
+ { AXPropertyName::Selected, aria_selectedAttr },
{ AXPropertyName::Sort, aria_sortAttr },
{ AXPropertyName::ValueText, aria_valuetextAttr }
};
@@ -95,6 +106,26 @@
}
}
+static bool isPropertyValueBoolean(AXPropertyName propertyName)
+{
+ switch (propertyName) {
+ case AXPropertyName::Atomic:
+ case AXPropertyName::Busy:
+ case AXPropertyName::Disabled:
+ case AXPropertyName::Expanded:
+ case AXPropertyName::Hidden:
+ case AXPropertyName::Modal:
+ case AXPropertyName::Multiline:
+ case AXPropertyName::Multiselectable:
+ case AXPropertyName::ReadOnly:
+ case AXPropertyName::Required:
+ case AXPropertyName::Selected:
+ return true;
+ default:
+ return false;
+ }
+}
+
bool AccessibleNode::hasProperty(Element& element, AXPropertyName propertyName)
{
if (auto* accessibleNode = element.existingAccessibleNode()) {
@@ -147,6 +178,42 @@
m_propertyMap.set(propertyName, value);
}
+std::optional<bool> AccessibleNode::effectiveBoolValueForElement(Element& element, AXPropertyName propertyName)
+{
+ std::optional<bool> value = boolValueForProperty(element, propertyName);
+ if (value)
+ return *value;
+
+ AtomicString attributeValue;
+ if (ariaAttributeMap().contains(propertyName) && isPropertyValueBoolean(propertyName))
+ attributeValue = element.attributeWithoutSynchronization(ariaAttributeMap().get(propertyName));
+
+ if (equalIgnoringASCIICase(attributeValue, "true"))
+ return true;
+ if (equalIgnoringASCIICase(attributeValue, "false"))
+ return false;
+ return std::nullopt;
+}
+
+std::optional<bool> AccessibleNode::boolValueForProperty(Element& element, AXPropertyName propertyName)
+{
+ const PropertyValueVariant&& variant = AccessibleNode::valueForProperty(element, propertyName);
+ if (WTF::holds_alternative<std::nullptr_t>(variant))
+ return std::nullopt;
+ if (WTF::holds_alternative<bool>(variant))
+ return WTF::get<bool>(variant);
+ return std::nullopt;
+}
+
+void AccessibleNode::setBoolProperty(std::optional<bool> value, AXPropertyName propertyName)
+{
+ if (!value) {
+ m_propertyMap.remove(propertyName);
+ return;
+ }
+ m_propertyMap.set(propertyName, *value);
+}
+
void AccessibleNode::notifyAttributeChanged(const WebCore::QualifiedName& name)
{
if (AXObjectCache* cache = m_ownerElement.document().axObjectCache())
@@ -153,6 +220,17 @@
cache->handleAttributeChanged(name, &m_ownerElement);
}
+std::optional<bool> AccessibleNode::atomic() const
+{
+ return boolValueForProperty(m_ownerElement, AXPropertyName::Atomic);
+}
+
+void AccessibleNode::setAtomic(std::optional<bool> value)
+{
+ setBoolProperty(value, AXPropertyName::Atomic);
+ notifyAttributeChanged(aria_atomicAttr);
+}
+
String AccessibleNode::autocomplete() const
{
return stringValueForProperty(m_ownerElement, AXPropertyName::Autocomplete);
@@ -164,6 +242,17 @@
notifyAttributeChanged(aria_autocompleteAttr);
}
+std::optional<bool> AccessibleNode::busy() const
+{
+ return boolValueForProperty(m_ownerElement, AXPropertyName::Busy);
+}
+
+void AccessibleNode::setBusy(std::optional<bool> value)
+{
+ setBoolProperty(value, AXPropertyName::Busy);
+ notifyAttributeChanged(aria_busyAttr);
+}
+
String AccessibleNode::checked() const
{
return stringValueForProperty(m_ownerElement, AXPropertyName::Checked);
@@ -186,6 +275,28 @@
notifyAttributeChanged(aria_currentAttr);
}
+std::optional<bool> AccessibleNode::disabled() const
+{
+ return boolValueForProperty(m_ownerElement, AXPropertyName::Disabled);
+}
+
+void AccessibleNode::setDisabled(std::optional<bool> value)
+{
+ setBoolProperty(value, AXPropertyName::Disabled);
+ notifyAttributeChanged(aria_disabledAttr);
+}
+
+std::optional<bool> AccessibleNode::expanded() const
+{
+ return boolValueForProperty(m_ownerElement, AXPropertyName::Expanded);
+}
+
+void AccessibleNode::setExpanded(std::optional<bool> value)
+{
+ setBoolProperty(value, AXPropertyName::Expanded);
+ notifyAttributeChanged(aria_expandedAttr);
+}
+
String AccessibleNode::hasPopUp() const
{
return stringValueForProperty(m_ownerElement, AXPropertyName::HasPopUp);
@@ -197,6 +308,17 @@
notifyAttributeChanged(aria_haspopupAttr);
}
+std::optional<bool> AccessibleNode::hidden() const
+{
+ return boolValueForProperty(m_ownerElement, AXPropertyName::Hidden);
+}
+
+void AccessibleNode::setHidden(std::optional<bool> value)
+{
+ setBoolProperty(value, AXPropertyName::Hidden);
+ notifyAttributeChanged(aria_hiddenAttr);
+}
+
String AccessibleNode::invalid() const
{
return stringValueForProperty(m_ownerElement, AXPropertyName::Invalid);
@@ -241,6 +363,39 @@
notifyAttributeChanged(aria_labelAttr);
}
+std::optional<bool> AccessibleNode::modal() const
+{
+ return boolValueForProperty(m_ownerElement, AXPropertyName::Modal);
+}
+
+void AccessibleNode::setModal(std::optional<bool> value)
+{
+ setBoolProperty(value, AXPropertyName::Modal);
+ notifyAttributeChanged(aria_modalAttr);
+}
+
+std::optional<bool> AccessibleNode::multiline() const
+{
+ return boolValueForProperty(m_ownerElement, AXPropertyName::Multiline);
+}
+
+void AccessibleNode::setMultiline(std::optional<bool> value)
+{
+ setBoolProperty(value, AXPropertyName::Multiline);
+ notifyAttributeChanged(aria_multilineAttr);
+}
+
+std::optional<bool> AccessibleNode::multiselectable() const
+{
+ return boolValueForProperty(m_ownerElement, AXPropertyName::Multiselectable);
+}
+
+void AccessibleNode::setMultiselectable(std::optional<bool> value)
+{
+ setBoolProperty(value, AXPropertyName::Multiselectable);
+ notifyAttributeChanged(aria_multiselectableAttr);
+}
+
String AccessibleNode::orientation() const
{
return stringValueForProperty(m_ownerElement, AXPropertyName::Orientation);
@@ -274,6 +429,17 @@
notifyAttributeChanged(aria_pressedAttr);
}
+std::optional<bool> AccessibleNode::readOnly() const
+{
+ return boolValueForProperty(m_ownerElement, AXPropertyName::ReadOnly);
+}
+
+void AccessibleNode::setReadOnly(std::optional<bool> value)
+{
+ setBoolProperty(value, AXPropertyName::ReadOnly);
+ notifyAttributeChanged(aria_readonlyAttr);
+}
+
String AccessibleNode::relevant() const
{
return stringValueForProperty(m_ownerElement, AXPropertyName::Relevant);
@@ -285,6 +451,17 @@
notifyAttributeChanged(aria_relevantAttr);
}
+std::optional<bool> AccessibleNode::required() const
+{
+ return boolValueForProperty(m_ownerElement, AXPropertyName::Required);
+}
+
+void AccessibleNode::setRequired(std::optional<bool> value)
+{
+ setBoolProperty(value, AXPropertyName::Required);
+ notifyAttributeChanged(aria_requiredAttr);
+}
+
String AccessibleNode::role() const
{
return stringValueForProperty(m_ownerElement, AXPropertyName::Role);
@@ -307,6 +484,17 @@
notifyAttributeChanged(aria_roledescriptionAttr);
}
+std::optional<bool> AccessibleNode::selected() const
+{
+ return boolValueForProperty(m_ownerElement, AXPropertyName::Selected);
+}
+
+void AccessibleNode::setSelected(std::optional<bool> value)
+{
+ setBoolProperty(value, AXPropertyName::Selected);
+ notifyAttributeChanged(aria_selectedAttr);
+}
+
String AccessibleNode::sort() const
{
return stringValueForProperty(m_ownerElement, AXPropertyName::Sort);
Modified: trunk/Source/WebCore/accessibility/AccessibleNode.h (224991 => 224992)
--- trunk/Source/WebCore/accessibility/AccessibleNode.h 2017-11-17 23:10:45 UTC (rev 224991)
+++ trunk/Source/WebCore/accessibility/AccessibleNode.h 2017-11-17 23:14:18 UTC (rev 224992)
@@ -36,24 +36,35 @@
namespace WebCore {
-typedef Variant<String, bool, int> PropertyValueVariant;
+typedef Variant<std::nullptr_t, String, bool, int> PropertyValueVariant;
enum class AXPropertyName {
None,
+ Atomic,
Autocomplete,
+ Busy,
Checked,
Current,
+ Disabled,
+ Expanded,
HasPopUp,
+ Hidden,
Invalid,
KeyShortcuts,
Label,
Live,
+ Modal,
+ Multiline,
+ Multiselectable,
Orientation,
Placeholder,
Pressed,
+ ReadOnly,
Relevant,
+ Required,
Role,
RoleDescription,
+ Selected,
Sort,
ValueText
};
@@ -83,11 +94,18 @@
void deref() { m_ownerElement.deref(); }
static const String effectiveStringValueForElement(Element&, AXPropertyName);
+ static std::optional<bool> effectiveBoolValueForElement(Element&, AXPropertyName);
static bool hasProperty(Element&, AXPropertyName);
+ std::optional<bool> atomic() const;
+ void setAtomic(std::optional<bool>);
+
String autocomplete() const;
void setAutocomplete(const String&);
+ std::optional<bool> busy() const;
+ void setBusy(std::optional<bool>);
+
String checked() const;
void setChecked(const String&);
@@ -94,9 +112,18 @@
String current() const;
void setCurrent(const String&);
+ std::optional<bool> disabled() const;
+ void setDisabled(std::optional<bool>);
+
+ std::optional<bool> expanded() const;
+ void setExpanded(std::optional<bool>);
+
String hasPopUp() const;
void setHasPopUp(const String&);
+ std::optional<bool> hidden() const;
+ void setHidden(std::optional<bool>);
+
String invalid() const;
void setInvalid(const String&);
@@ -109,6 +136,15 @@
String label() const;
void setLabel(const String&);
+ std::optional<bool> modal() const;
+ void setModal(std::optional<bool>);
+
+ std::optional<bool> multiline() const;
+ void setMultiline(std::optional<bool>);
+
+ std::optional<bool> multiselectable() const;
+ void setMultiselectable(std::optional<bool>);
+
String orientation() const;
void setOrientation(const String&);
@@ -118,9 +154,15 @@
String pressed() const;
void setPressed(const String&);
+ std::optional<bool> readOnly() const;
+ void setReadOnly(std::optional<bool>);
+
String relevant() const;
void setRelevant(const String&);
+ std::optional<bool> required() const;
+ void setRequired(std::optional<bool>);
+
String role() const;
void setRole(const String&);
@@ -127,6 +169,9 @@
String roleDescription() const;
void setRoleDescription(const String&);
+ std::optional<bool> selected() const;
+ void setSelected(std::optional<bool>);
+
String sort() const;
void setSort(const String&);
@@ -136,7 +181,9 @@
private:
static const PropertyValueVariant valueForProperty(Element&, AXPropertyName);
static const String stringValueForProperty(Element&, AXPropertyName);
+ static std::optional<bool> boolValueForProperty(Element&, AXPropertyName);
void setStringProperty(const String&, AXPropertyName);
+ void setBoolProperty(std::optional<bool>, AXPropertyName);
void notifyAttributeChanged(const WebCore::QualifiedName&);
Modified: trunk/Source/WebCore/accessibility/AccessibleNode.idl (224991 => 224992)
--- trunk/Source/WebCore/accessibility/AccessibleNode.idl 2017-11-17 23:10:45 UTC (rev 224991)
+++ trunk/Source/WebCore/accessibility/AccessibleNode.idl 2017-11-17 23:14:18 UTC (rev 224992)
@@ -27,20 +27,31 @@
SkipVTableValidation,
EnabledAtRuntime=AccessibilityObjectModel,
] interface AccessibleNode {
+ attribute boolean? atomic;
attribute DOMString? autocomplete;
+ attribute boolean? busy;
attribute DOMString? checked;
attribute DOMString? current;
+ attribute boolean? disabled;
+ attribute boolean? expanded;
attribute DOMString? hasPopUp;
+ attribute boolean? hidden;
attribute DOMString? invalid;
attribute DOMString? keyShortcuts;
attribute DOMString? label;
attribute DOMString? live;
+ attribute boolean? modal;
+ attribute boolean? multiline;
+ attribute boolean? multiselectable;
attribute DOMString? orientation;
attribute DOMString? placeholder;
attribute DOMString? pressed;
+ attribute boolean? readOnly;
attribute DOMString? relevant;
+ attribute boolean? required;
attribute DOMString? role;
attribute DOMString? roleDescription;
+ attribute boolean? selected;
attribute DOMString? sort;
attribute DOMString? valueText;
};
Modified: trunk/Source/WebCore/accessibility/atk/WebKitAccessibleWrapperAtk.cpp (224991 => 224992)
--- trunk/Source/WebCore/accessibility/atk/WebKitAccessibleWrapperAtk.cpp 2017-11-17 23:10:45 UTC (rev 224991)
+++ trunk/Source/WebCore/accessibility/atk/WebKitAccessibleWrapperAtk.cpp 2017-11-17 23:14:18 UTC (rev 224992)
@@ -533,7 +533,7 @@
if (coreObject->supportsARIASetSize())
attributeSet = addToAtkAttributeSet(attributeSet, "setsize", String::number(coreObject->ariaSetSize()).utf8().data());
- String isReadOnly = coreObject->ariaReadOnlyValue();
+ String isReadOnly = coreObject->readOnlyValue();
if (!isReadOnly.isEmpty())
attributeSet = addToAtkAttributeSet(attributeSet, "readonly", isReadOnly.utf8().data());
@@ -987,7 +987,7 @@
atk_state_set_add_state(stateSet, ATK_STATE_INDETERMINATE);
}
- if (coreObject->isAriaModalNode())
+ if (coreObject->isModalNode())
atk_state_set_add_state(stateSet, ATK_STATE_MODAL);
if (coreObject->invalidStatus() != "false")
@@ -1002,7 +1002,7 @@
atk_state_set_add_state(stateSet, ATK_STATE_PRESSED);
#if ATK_CHECK_VERSION(2,15,3)
- if (!coreObject->canSetValueAttribute() && (coreObject->supportsARIAReadOnly()))
+ if (!coreObject->canSetValueAttribute() && (coreObject->supportsReadOnly()))
atk_state_set_add_state(stateSet, ATK_STATE_READ_ONLY);
#endif
Modified: trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm (224991 => 224992)
--- trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm 2017-11-17 23:10:45 UTC (rev 224991)
+++ trunk/Source/WebCore/accessibility/mac/WebAccessibilityObjectWrapperMac.mm 2017-11-17 23:14:18 UTC (rev 224992)
@@ -3196,6 +3196,12 @@
if ([attributeName isEqualToString:@"AXARIAPressedIsPresent"])
return [NSNumber numberWithBool:m_object->pressedIsPresent()];
+ if ([attributeName isEqualToString:@"AXIsMultiline"])
+ return [NSNumber numberWithBool:m_object->ariaIsMultiline()];
+
+ if ([attributeName isEqualToString:@"AXReadOnlyValue"])
+ return m_object->readOnlyValue();
+
if (m_object->isWebArea() && [attributeName isEqualToString:NSAccessibilityPreventKeyboardDOMEventDispatchAttribute])
return [NSNumber numberWithBool:m_object->preventKeyboardDOMEventDispatch()];
Modified: trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp (224991 => 224992)
--- trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp 2017-11-17 23:10:45 UTC (rev 224991)
+++ trunk/Source/WebCore/inspector/agents/InspectorDOMAgent.cpp 2017-11-17 23:14:18 UTC (rev 224992)
@@ -1819,7 +1819,7 @@
else // Future versions of ARIA may allow additional truthy values. Ex. format, order, or size.
invalid = Inspector::Protocol::DOM::AccessibilityProperties::Invalid::True;
- if (axObject->isARIAHidden() || axObject->isDOMHidden())
+ if (axObject->isAXHidden() || axObject->isDOMHidden())
hidden = true;
label = axObject->computedLabel();