Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(916)

Unified Diff: third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp

Issue 2589273002: Add sparse accessibility attribute interface to Blink (Closed)
Patch Set: Address feedback Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp
diff --git a/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp b/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp
index 58b6cd37e5ce8175a7e970004de4385f78d8dd0f..b757252a60da4b9ab39b34ab36d08473fbd29c93 100644
--- a/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp
+++ b/third_party/WebKit/Source/modules/accessibility/AXNodeObject.cpp
@@ -32,6 +32,7 @@
#include "core/dom/DocumentUserGestureToken.h"
#include "core/dom/Element.h"
#include "core/dom/NodeTraversal.h"
+#include "core/dom/QualifiedName.h"
#include "core/dom/Text.h"
#include "core/dom/shadow/FlatTreeTraversal.h"
#include "core/editing/EditingUtilities.h"
@@ -70,6 +71,132 @@ namespace blink {
using namespace HTMLNames;
+class SparseAttributeSetter {
+ USING_FAST_MALLOC(SparseAttributeSetter);
+
+ public:
+ virtual void run(const AXObject&,
+ AXSparseAttributeClient&,
+ const AtomicString& value) = 0;
+};
+
+class BoolAttributeSetter : public SparseAttributeSetter {
+ public:
+ BoolAttributeSetter(AXBoolAttribute attribute) : m_attribute(attribute) {}
+
+ private:
+ AXBoolAttribute m_attribute;
+
+ void run(const AXObject& obj,
+ AXSparseAttributeClient& attributeMap,
+ const AtomicString& value) override {
+ attributeMap.addBoolAttribute(m_attribute,
+ equalIgnoringCase(value, "true"));
+ }
+};
+
+class StringAttributeSetter : public SparseAttributeSetter {
+ public:
+ StringAttributeSetter(AXStringAttribute attribute) : m_attribute(attribute) {}
+
+ private:
+ AXStringAttribute m_attribute;
+
+ void run(const AXObject& obj,
+ AXSparseAttributeClient& attributeMap,
+ const AtomicString& value) override {
+ attributeMap.addStringAttribute(m_attribute, value);
+ }
+};
+
+class ObjectAttributeSetter : public SparseAttributeSetter {
+ public:
+ ObjectAttributeSetter(AXObjectAttribute attribute) : m_attribute(attribute) {}
+
+ private:
+ AXObjectAttribute m_attribute;
+
+ void run(const AXObject& obj,
+ AXSparseAttributeClient& attributeMap,
+ const AtomicString& value) override {
+ if (value.isNull() || value.isEmpty())
+ return;
+
+ Node* node = obj.getNode();
+ if (!node || !node->isElementNode())
+ return;
+ Element* target = toElement(node)->treeScope().getElementById(value);
+ if (!target)
+ return;
+ AXObject* axTarget = obj.axObjectCache().getOrCreate(target);
+ if (axTarget)
+ attributeMap.addObjectAttribute(m_attribute, *axTarget);
+ }
+};
+
+class ObjectVectorAttributeSetter : public SparseAttributeSetter {
+ public:
+ ObjectVectorAttributeSetter(AXObjectVectorAttribute attribute)
+ : m_attribute(attribute) {}
+
+ private:
+ AXObjectVectorAttribute m_attribute;
+
+ void run(const AXObject& obj,
+ AXSparseAttributeClient& attributeMap,
+ const AtomicString& value) override {
+ Node* node = obj.getNode();
+ if (!node || !node->isElementNode())
+ return;
+
+ String attributeValue = value.getString();
+ if (attributeValue.isEmpty())
+ return;
+
+ attributeValue.simplifyWhiteSpace();
+ Vector<String> ids;
+ attributeValue.split(' ', ids);
+ if (ids.isEmpty())
+ return;
+
+ HeapVector<Member<AXObject>> objects;
+ TreeScope& scope = node->treeScope();
+ for (const auto& id : ids) {
+ if (Element* idElement = scope.getElementById(AtomicString(id))) {
+ AXObject* axIdElement = obj.axObjectCache().getOrCreate(idElement);
+ if (axIdElement && !axIdElement->accessibilityIsIgnored())
+ objects.append(axIdElement);
+ }
+ }
+
+ attributeMap.addObjectVectorAttribute(m_attribute, objects);
+ }
+};
+
+using AXSparseAttributeSetterMap =
+ HashMap<QualifiedName, SparseAttributeSetter*>;
+
+static AXSparseAttributeSetterMap& getSparseAttributeSetterMap() {
+ // Use a map from attribute name to properties of that attribute.
+ // That way we only need to iterate over the list of attributes once,
+ // rather than calling getAttribute() once for each possible obscure
+ // accessibility attribute.
+ DEFINE_STATIC_LOCAL(AXSparseAttributeSetterMap, axSparseAttributeSetterMap,
+ ());
+ if (axSparseAttributeSetterMap.isEmpty()) {
+ axSparseAttributeSetterMap.set(
+ aria_activedescendantAttr,
+ new ObjectAttributeSetter(AXObjectAttribute::AriaActiveDescendant));
+ axSparseAttributeSetterMap.set(
+ aria_controlsAttr,
+ new ObjectVectorAttributeSetter(AXObjectVectorAttribute::AriaControls));
+ axSparseAttributeSetterMap.set(
+ aria_flowtoAttr,
+ new ObjectVectorAttributeSetter(AXObjectVectorAttribute::AriaFlowTo));
+ }
+ return axSparseAttributeSetterMap;
+}
+
AXNodeObject::AXNodeObject(Node* node, AXObjectCacheImpl& axObjectCache)
: AXObject(axObjectCache),
m_ariaRole(UnknownRole),
@@ -753,6 +880,22 @@ void AXNodeObject::detach() {
m_node = nullptr;
}
+void AXNodeObject::getSparseAXAttributes(
+ AXSparseAttributeClient& sparseAttributeClient) const {
+ Node* node = this->getNode();
+ if (!node || !node->isElementNode())
+ return;
+
+ AXSparseAttributeSetterMap& axSparseAttributeSetterMap =
+ getSparseAttributeSetterMap();
+ AttributeCollection attributes = toElement(node)->attributesWithoutUpdate();
+ for (const Attribute& attr : attributes) {
+ SparseAttributeSetter* setter = axSparseAttributeSetterMap.get(attr.name());
+ if (setter)
+ setter->run(*this, sparseAttributeClient, attr.value());
+ }
+}
+
bool AXNodeObject::isAnchor() const {
return !isNativeImage() && isLink();
}

Powered by Google App Engine
This is Rietveld 408576698