AX: Expose pointers to SVG elements referenced by aria-labelledby
https://bugs.webkit.org/show_bug.cgi?id=155481

Reviewed by Chris Fleizach.

Source/WebCore:

Expose elements referenced by aria-labelledby via ATK_RELATION_LABELLED_BY.
Stop calling the supportsARIA* methods before getting the elements referred
to by the associated ARIA property in the accessible wrapper for ATK and
the inspector: Getting the elements will be just as fast when there are no
such elements, and faster when there are.

Modified the w3c-svg-name-calculation.html test to include AXTitleUIElement
in its output.

* accessibility/AccessibilityObject.cpp:
(WebCore::AccessibilityObject::supportsARIAAttributes):
(WebCore::AccessibilityObject::ariaElementsFromAttribute): Added.
(WebCore::AccessibilityObject::ariaControlsElements): Added.
(WebCore::AccessibilityObject::ariaDescribedByElements): Added.
(WebCore::AccessibilityObject::ariaFlowToElements): Added.
(WebCore::AccessibilityObject::ariaLabelledByElements): Added.
(WebCore::AccessibilityObject::ariaOwnsElements): Added.
* accessibility/AccessibilityObject.h:
(WebCore::AccessibilityObject::ariaOwnsElements): No longer virtual.
(WebCore::AccessibilityObject::supportsARIAFlowTo): Deleted.
(WebCore::AccessibilityObject::ariaFlowToElements): No longer virtual.
(WebCore::AccessibilityObject::supportsARIADescribedBy): Deleted.
(WebCore::AccessibilityObject::ariaDescribedByElements): No longer virtual.
(WebCore::AccessibilityObject::supportsARIAControls): Deleted.
(WebCore::AccessibilityObject::ariaControlsElements): No longer virtual.
* accessibility/AccessibilityRenderObject.cpp:
(WebCore::AccessibilityRenderObject::ariaElementsFromAttribute): Moved to AccessibilityObject.
(WebCore::AccessibilityRenderObject::supportsARIAFlowTo): Deleted.
(WebCore::AccessibilityRenderObject::ariaFlowToElements): Moved to AccessibilityObject.
(WebCore::AccessibilityRenderObject::supportsARIADescribedBy): Deleted.
(WebCore::AccessibilityRenderObject::ariaDescribedByElements): Moved to AccessibilityObject.
(WebCore::AccessibilityRenderObject::supportsARIAControls): Deleted.
(WebCore::AccessibilityRenderObject::ariaControlsElements): Moved to AccessibilityObject.
(WebCore::AccessibilityRenderObject::ariaOwnsElements): Moved to AccessibilityObject.
* accessibility/AccessibilityRenderObject.h:
* accessibility/atk/WebKitAccessibleWrapperAtk.cpp:
(setAtkRelationSetFromCoreObject):
* inspector/InspectorDOMAgent.cpp:
(WebCore::InspectorDOMAgent::buildObjectForAccessibilityProperties):

LayoutTests:

* accessibility/w3c-svg-name-calculation.html: Modified to also output AXTitleUIElement.
* platform/gtk/accessibility/w3c-svg-name-calculation-expected.txt: Updated.
* platform/mac/accessibility/w3c-svg-name-calculation-expected.txt: Updated.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@198254 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog
index 9a6cb03..9bad3ec 100644
--- a/LayoutTests/ChangeLog
+++ b/LayoutTests/ChangeLog
@@ -1,3 +1,14 @@
+2016-03-15  Joanmarie Diggs  <jdiggs@igalia.com>
+
+        AX: Expose pointers to SVG elements referenced by aria-labelledby
+        https://bugs.webkit.org/show_bug.cgi?id=155481
+
+        Reviewed by Chris Fleizach.
+
+        * accessibility/w3c-svg-name-calculation.html: Modified to also output AXTitleUIElement.
+        * platform/gtk/accessibility/w3c-svg-name-calculation-expected.txt: Updated.
+        * platform/mac/accessibility/w3c-svg-name-calculation-expected.txt: Updated.
+
 2016-03-15  Tim Horton  <timothy_horton@apple.com>
 
         iOS <attachment> element should allow customization of action text color
diff --git a/LayoutTests/accessibility/w3c-svg-name-calculation.html b/LayoutTests/accessibility/w3c-svg-name-calculation.html
index 9d8dfdf..f7e34c2 100644
--- a/LayoutTests/accessibility/w3c-svg-name-calculation.html
+++ b/LayoutTests/accessibility/w3c-svg-name-calculation.html
@@ -316,6 +316,7 @@
        result = axElement.title + "\n\t" + axElement.description;
        if (accessibilityController.platformName == "mac")
            result += "\n\t" + axElement.helpText;
+       result += "\n\tAXTitleUIElement: " + (axElement.titleUIElement() ? "non-null" : "null");
        return result;
     }
 
diff --git a/LayoutTests/platform/gtk/accessibility/w3c-svg-name-calculation-expected.txt b/LayoutTests/platform/gtk/accessibility/w3c-svg-name-calculation-expected.txt
index 496bdad..70c74cf 100644
--- a/LayoutTests/platform/gtk/accessibility/w3c-svg-name-calculation-expected.txt
+++ b/LayoutTests/platform/gtk/accessibility/w3c-svg-name-calculation-expected.txt
@@ -7,186 +7,232 @@
 	Expected name: end
 	AXTitle: end
 	AXDescription: abc
+	AXTitleUIElement: non-null
 test2:
 	Expected name: end
 	AXTitle: end
 	AXDescription: 
+	AXTitleUIElement: non-null
 test3:
 	Expected name: end
 	AXTitle: end
 	AXDescription: abc
+	AXTitleUIElement: non-null
 test4:
 	Expected name: end
 	AXTitle: end
 	AXDescription: 
+	AXTitleUIElement: non-null
 test5:
 	Expected name: hello
 	AXTitle: hello
 	AXDescription: abc
+	AXTitleUIElement: null
 test6:
 	Expected name: hello
 	AXTitle: hello
 	AXDescription: 
+	AXTitleUIElement: null
 test7:
 	Expected name: abc
 	AXTitle: abc
 	AXDescription: 
+	AXTitleUIElement: null
 test8:
 	Expected name: hi
 	AXTitle: hi
 	AXDescription: 
+	AXTitleUIElement: null
 test9:
 	Expected name: hi
 	AXTitle: hi
 	AXDescription: 
+	AXTitleUIElement: null
 test10:
 	Expected name: hi
 	AXTitle: hi
 	AXDescription: 
+	AXTitleUIElement: null
 test11:
 	Expected name: hola
 	AXTitle: hola
 	AXDescription: 
+	AXTitleUIElement: null
 test12:
 	Expected name: hola
 	AXTitle: hola
 	AXDescription: 
+	AXTitleUIElement: null
 test13:
 	Expected name: hola
 	AXTitle: hola
 	AXDescription: 
+	AXTitleUIElement: null
 test14:
 	Expected name: bob
 	AXTitle: bob
 	AXDescription: abc
+	AXTitleUIElement: null
 test15:
 	Expected name: bob
 	AXTitle: bob
 	AXDescription: 
+	AXTitleUIElement: null
 test16:
 	Expected name: abc
 	AXTitle: abc
 	AXDescription: 
+	AXTitleUIElement: null
 test17:
 	Expected name: (empty)
 	AXTitle: 
 	AXDescription: 
+	AXTitleUIElement: null
 test18:
 	Expected name: waz up
 	AXTitle: waz up
 	AXDescription: 
+	AXTitleUIElement: null
 test19:
 	Expected name: Hallo
 	AXTitle: Hallo
 	AXDescription: 
+	AXTitleUIElement: null
 test20:
 	Expected name: the end
 	AXTitle: the end
 	AXDescription: 
+	AXTitleUIElement: non-null
 test21:
 	Expected name: big end
 	AXTitle: big end
 	AXDescription: 
+	AXTitleUIElement: non-null
 test22:
 	Expected name: big end
 	AXTitle: big end
 	AXDescription: 
+	AXTitleUIElement: non-null
 test23:
 	Expected name: end
 	AXTitle: end
 	AXDescription: 
+	AXTitleUIElement: non-null
 test24:
 	Expected name: end
 	AXTitle: end
 	AXDescription: 
+	AXTitleUIElement: null
 test25:
 	Expected name: booth
 	AXTitle: booth
 	AXDescription: 
+	AXTitleUIElement: null
 test26:
 	Expected name: table
 	AXTitle: table
 	AXDescription: 
+	AXTitleUIElement: null
 test27:
 	Expected name: counter
 	AXTitle: counter
 	AXDescription: 
+	AXTitleUIElement: null
 test28:
 	Expected name: counter
 	AXTitle: counter
 	AXDescription: 
+	AXTitleUIElement: null
 test29:
 	Expected name: counter
 	AXTitle: counter
 	AXDescription: 
+	AXTitleUIElement: null
 test30:
 	Expected name: boulder
 	AXTitle: boulder
 	AXDescription: 
+	AXTitleUIElement: non-null
 test31:
 	Expected name: stone
 	AXTitle: stone
 	AXDescription: 
+	AXTitleUIElement: null
 test32:
 	Expected name: pebble
 	AXTitle: pebble
 	AXDescription: 
+	AXTitleUIElement: null
 test33:
 	Expected name: rock
 	AXTitle: rock
 	AXDescription: 
+	AXTitleUIElement: null
 test34:
 	Expected name: rock
 	AXTitle: rock
 	AXDescription: 
+	AXTitleUIElement: null
 test35:
 	Expected name: stone
 	AXTitle: stone
 	AXDescription: 
+	AXTitleUIElement: null
 test36:
 	Expected name: stone
 	AXTitle: stone
 	AXDescription: 
+	AXTitleUIElement: null
 test37:
 	Expected name: piedra
 	AXTitle: piedra
 	AXDescription: 
+	AXTitleUIElement: null
 test38:
 	Expected name: piedra
 	AXTitle: piedra
 	AXDescription: 
+	AXTitleUIElement: null
 test39:
 	Expected name: stone
 	AXTitle: stone
 	AXDescription: 
+	AXTitleUIElement: null
 test40:
 	Expected name: stone
 	AXTitle: stone
 	AXDescription: 
+	AXTitleUIElement: null
 test41:
 	Expected name: (empty)
 	AXTitle: 
 	AXDescription: 
+	AXTitleUIElement: null
 test42:
 	Expected name: (empty)
 	AXTitle:  
 	AXDescription: 
+	AXTitleUIElement: null
 test43:
 	Expected name: (empty)
 	AXTitle: 
 	AXDescription: 
+	AXTitleUIElement: null
 test44:
 	Expected name: (empty)
 	AXTitle:  
 	AXDescription: 
+	AXTitleUIElement: null
 test45:
 	Expected name: (empty)
 	AXTitle: 
 	AXDescription:  
+	AXTitleUIElement: null
 test46:
 	Expected name: (empty)
 	AXTitle:  
 	AXDescription: 	
+	AXTitleUIElement: null
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/LayoutTests/platform/mac/accessibility/w3c-svg-name-calculation-expected.txt b/LayoutTests/platform/mac/accessibility/w3c-svg-name-calculation-expected.txt
index e01df5c..3b6d1e5 100644
--- a/LayoutTests/platform/mac/accessibility/w3c-svg-name-calculation-expected.txt
+++ b/LayoutTests/platform/mac/accessibility/w3c-svg-name-calculation-expected.txt
@@ -8,231 +8,277 @@
 	AXTitle: 
 	AXDescription: end
 	AXHelp: abc
+	AXTitleUIElement: null
 test2:
 	Expected name: end
 	AXTitle: 
 	AXDescription: end
 	AXHelp: 
+	AXTitleUIElement: null
 test3:
 	Expected name: end
 	AXTitle: 
 	AXDescription: end
 	AXHelp: abc
+	AXTitleUIElement: null
 test4:
 	Expected name: end
 	AXTitle: 
 	AXDescription: end
 	AXHelp: 
+	AXTitleUIElement: null
 test5:
 	Expected name: hello
 	AXTitle: 
 	AXDescription: hello
 	AXHelp: abc
+	AXTitleUIElement: null
 test6:
 	Expected name: hello
 	AXTitle: 
 	AXDescription: hello
 	AXHelp: 
+	AXTitleUIElement: null
 test7:
 	Expected name: abc
 	AXTitle: 
 	AXDescription: abc
 	AXHelp: 
+	AXTitleUIElement: null
 test8:
 	Expected name: hi
 	AXTitle: 
 	AXDescription: hi
 	AXHelp: 
+	AXTitleUIElement: null
 test9:
 	Expected name: hi
 	AXTitle: 
 	AXDescription: hi
 	AXHelp: 
+	AXTitleUIElement: null
 test10:
 	Expected name: hi
 	AXTitle: 
 	AXDescription: hi
 	AXHelp: 
+	AXTitleUIElement: null
 test11:
 	Expected name: hola
 	AXTitle: 
 	AXDescription: hola
 	AXHelp: 
+	AXTitleUIElement: null
 test12:
 	Expected name: hola
 	AXTitle: 
 	AXDescription: hola
 	AXHelp: 
+	AXTitleUIElement: null
 test13:
 	Expected name: hola
 	AXTitle: 
 	AXDescription: hola
 	AXHelp: 
+	AXTitleUIElement: null
 test14:
 	Expected name: bob
 	AXTitle: 
 	AXDescription: bob
 	AXHelp: abc
+	AXTitleUIElement: null
 test15:
 	Expected name: bob
 	AXTitle: 
 	AXDescription: bob
 	AXHelp: 
+	AXTitleUIElement: null
 test16:
 	Expected name: abc
 	AXTitle: 
 	AXDescription: abc
 	AXHelp: 
+	AXTitleUIElement: null
 test17:
 	Expected name: (empty)
 	AXTitle: 
 	AXDescription: 
 	AXHelp: 
+	AXTitleUIElement: null
 test18:
 	Expected name: waz up
 	AXTitle: 
 	AXDescription: waz up
 	AXHelp: 
+	AXTitleUIElement: null
 test19:
 	Expected name: Hallo
 	AXTitle: 
 	AXDescription: Hallo
 	AXHelp: 
+	AXTitleUIElement: null
 test20:
 	Expected name: the end
 	AXTitle: 
 	AXDescription: the end
 	AXHelp: 
+	AXTitleUIElement: null
 test21:
 	Expected name: big end
 	AXTitle: 
 	AXDescription: big end
 	AXHelp: 
+	AXTitleUIElement: null
 test22:
 	Expected name: big end
 	AXTitle: 
 	AXDescription: big end
 	AXHelp: 
+	AXTitleUIElement: null
 test23:
 	Expected name: end
 	AXTitle: 
 	AXDescription: end
 	AXHelp: 
+	AXTitleUIElement: null
 test24:
 	Expected name: end
 	AXTitle: 
 	AXDescription: end
 	AXHelp: 
+	AXTitleUIElement: null
 test25:
 	Expected name: booth
 	AXTitle: 
 	AXDescription: booth
 	AXHelp: 
+	AXTitleUIElement: null
 test26:
 	Expected name: table
 	AXTitle: 
 	AXDescription: table
 	AXHelp: 
+	AXTitleUIElement: null
 test27:
 	Expected name: counter
 	AXTitle: 
 	AXDescription: counter
 	AXHelp: 
+	AXTitleUIElement: null
 test28:
 	Expected name: counter
 	AXTitle: 
 	AXDescription: counter
 	AXHelp: 
+	AXTitleUIElement: null
 test29:
 	Expected name: counter
 	AXTitle: 
 	AXDescription: counter
 	AXHelp: 
+	AXTitleUIElement: null
 test30:
 	Expected name: boulder
 	AXTitle: 
 	AXDescription: boulder
 	AXHelp: 
+	AXTitleUIElement: null
 test31:
 	Expected name: stone
 	AXTitle: 
 	AXDescription: stone
 	AXHelp: 
+	AXTitleUIElement: null
 test32:
 	Expected name: pebble
 	AXTitle: 
 	AXDescription: pebble
 	AXHelp: 
+	AXTitleUIElement: null
 test33:
 	Expected name: rock
 	AXTitle: 
 	AXDescription: rock
 	AXHelp: 
+	AXTitleUIElement: null
 test34:
 	Expected name: rock
 	AXTitle: 
 	AXDescription: rock
 	AXHelp: 
+	AXTitleUIElement: null
 test35:
 	Expected name: stone
 	AXTitle: 
 	AXDescription: stone
 	AXHelp: 
+	AXTitleUIElement: null
 test36:
 	Expected name: stone
 	AXTitle: 
 	AXDescription: stone
 	AXHelp: 
+	AXTitleUIElement: null
 test37:
 	Expected name: piedra
 	AXTitle: 
 	AXDescription: piedra
 	AXHelp: 
+	AXTitleUIElement: null
 test38:
 	Expected name: piedra
 	AXTitle: 
 	AXDescription: piedra
 	AXHelp: 
+	AXTitleUIElement: null
 test39:
 	Expected name: stone
 	AXTitle: 
 	AXDescription: stone
 	AXHelp: 
+	AXTitleUIElement: null
 test40:
 	Expected name: stone
 	AXTitle: 
 	AXDescription: stone
 	AXHelp: 
+	AXTitleUIElement: null
 test41:
 	Expected name: (empty)
 	AXTitle: 
 	AXDescription: 
 	AXHelp: 
+	AXTitleUIElement: null
 test42:
 	Expected name: (empty)
 	AXTitle: 
 	AXDescription:  
 	AXHelp: 
+	AXTitleUIElement: null
 test43:
 	Expected name: (empty)
 	AXTitle: 
 	AXDescription: 
 	AXHelp: 
+	AXTitleUIElement: null
 test44:
 	Expected name: (empty)
 	AXTitle: 
 	AXDescription:  
 	AXHelp: 
+	AXTitleUIElement: null
 test45:
 	Expected name: (empty)
 	AXTitle: 
 	AXDescription: 
 	AXHelp:  
+	AXTitleUIElement: null
 test46:
 	Expected name: (empty)
 	AXTitle: 
 	AXDescription:  
 	AXHelp: 	
+	AXTitleUIElement: null
 PASS successfullyParsed is true
 
 TEST COMPLETE
diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog
index 8bd44af..e355616 100644
--- a/Source/WebCore/ChangeLog
+++ b/Source/WebCore/ChangeLog
@@ -1,3 +1,50 @@
+2016-03-15  Joanmarie Diggs  <jdiggs@igalia.com>
+
+        AX: Expose pointers to SVG elements referenced by aria-labelledby
+        https://bugs.webkit.org/show_bug.cgi?id=155481
+
+        Reviewed by Chris Fleizach.
+
+        Expose elements referenced by aria-labelledby via ATK_RELATION_LABELLED_BY.
+        Stop calling the supportsARIA* methods before getting the elements referred
+        to by the associated ARIA property in the accessible wrapper for ATK and
+        the inspector: Getting the elements will be just as fast when there are no
+        such elements, and faster when there are.
+
+        Modified the w3c-svg-name-calculation.html test to include AXTitleUIElement
+        in its output.
+
+        * accessibility/AccessibilityObject.cpp:
+        (WebCore::AccessibilityObject::supportsARIAAttributes):
+        (WebCore::AccessibilityObject::ariaElementsFromAttribute): Added.
+        (WebCore::AccessibilityObject::ariaControlsElements): Added.
+        (WebCore::AccessibilityObject::ariaDescribedByElements): Added.
+        (WebCore::AccessibilityObject::ariaFlowToElements): Added.
+        (WebCore::AccessibilityObject::ariaLabelledByElements): Added.
+        (WebCore::AccessibilityObject::ariaOwnsElements): Added.
+        * accessibility/AccessibilityObject.h:
+        (WebCore::AccessibilityObject::ariaOwnsElements): No longer virtual.
+        (WebCore::AccessibilityObject::supportsARIAFlowTo): Deleted.
+        (WebCore::AccessibilityObject::ariaFlowToElements): No longer virtual.
+        (WebCore::AccessibilityObject::supportsARIADescribedBy): Deleted.
+        (WebCore::AccessibilityObject::ariaDescribedByElements): No longer virtual.
+        (WebCore::AccessibilityObject::supportsARIAControls): Deleted.
+        (WebCore::AccessibilityObject::ariaControlsElements): No longer virtual.
+        * accessibility/AccessibilityRenderObject.cpp:
+        (WebCore::AccessibilityRenderObject::ariaElementsFromAttribute): Moved to AccessibilityObject.
+        (WebCore::AccessibilityRenderObject::supportsARIAFlowTo): Deleted.
+        (WebCore::AccessibilityRenderObject::ariaFlowToElements): Moved to AccessibilityObject.
+        (WebCore::AccessibilityRenderObject::supportsARIADescribedBy): Deleted.
+        (WebCore::AccessibilityRenderObject::ariaDescribedByElements): Moved to AccessibilityObject.
+        (WebCore::AccessibilityRenderObject::supportsARIAControls): Deleted.
+        (WebCore::AccessibilityRenderObject::ariaControlsElements): Moved to AccessibilityObject.
+        (WebCore::AccessibilityRenderObject::ariaOwnsElements): Moved to AccessibilityObject.
+        * accessibility/AccessibilityRenderObject.h:
+        * accessibility/atk/WebKitAccessibleWrapperAtk.cpp:
+        (setAtkRelationSetFromCoreObject):
+        * inspector/InspectorDOMAgent.cpp:
+        (WebCore::InspectorDOMAgent::buildObjectForAccessibilityProperties):
+
 2016-03-15  Simon Fraser  <simon.fraser@apple.com>
 
         Occasional crash under GraphicsContext::platformContext when dragging Google maps
diff --git a/Source/WebCore/accessibility/AccessibilityObject.cpp b/Source/WebCore/accessibility/AccessibilityObject.cpp
index 938b599..dd03536 100644
--- a/Source/WebCore/accessibility/AccessibilityObject.cpp
+++ b/Source/WebCore/accessibility/AccessibilityObject.cpp
@@ -2241,13 +2241,13 @@
     return supportsARIALiveRegion()
         || supportsARIADragging()
         || supportsARIADropping()
-        || supportsARIAFlowTo()
         || supportsARIAOwns()
         || hasAttribute(aria_atomicAttr)
         || hasAttribute(aria_busyAttr)
         || hasAttribute(aria_controlsAttr)
         || hasAttribute(aria_describedbyAttr)
         || hasAttribute(aria_disabledAttr)
+        || hasAttribute(aria_flowtoAttr)
         || hasAttribute(aria_haspopupAttr)
         || hasAttribute(aria_invalidAttr)
         || hasAttribute(aria_labelAttr)
@@ -2976,4 +2976,42 @@
     return is<HTMLInputElement>(element) && downcast<HTMLInputElement>(*element).isPasswordField();
 }
 
+void AccessibilityObject::ariaElementsFromAttribute(AccessibilityChildrenVector& children, const QualifiedName& attributeName) const
+{
+    Vector<Element*> elements;
+    elementsFromAttribute(elements, attributeName);
+    AXObjectCache* cache = axObjectCache();
+    for (const auto& element : elements) {
+        if (AccessibilityObject* axObject = cache->getOrCreate(element))
+            children.append(axObject);
+    }
+}
+
+void AccessibilityObject::ariaControlsElements(AccessibilityChildrenVector& ariaControls) const
+{
+    ariaElementsFromAttribute(ariaControls, aria_controlsAttr);
+}
+
+void AccessibilityObject::ariaDescribedByElements(AccessibilityChildrenVector& ariaDescribedBy) const
+{
+    ariaElementsFromAttribute(ariaDescribedBy, aria_describedbyAttr);
+}
+
+void AccessibilityObject::ariaFlowToElements(AccessibilityChildrenVector& flowTo) const
+{
+    ariaElementsFromAttribute(flowTo, aria_flowtoAttr);
+}
+
+void AccessibilityObject::ariaLabelledByElements(AccessibilityChildrenVector& ariaLabelledBy) const
+{
+    ariaElementsFromAttribute(ariaLabelledBy, aria_labelledbyAttr);
+    if (!ariaLabelledBy.size())
+        ariaElementsFromAttribute(ariaLabelledBy, aria_labeledbyAttr);
+}
+
+void AccessibilityObject::ariaOwnsElements(AccessibilityChildrenVector& axObjects) const
+{
+    ariaElementsFromAttribute(axObjects, aria_ownsAttr);
+}
+
 } // namespace WebCore
diff --git a/Source/WebCore/accessibility/AccessibilityObject.h b/Source/WebCore/accessibility/AccessibilityObject.h
index 452f08b..f48a688 100644
--- a/Source/WebCore/accessibility/AccessibilityObject.h
+++ b/Source/WebCore/accessibility/AccessibilityObject.h
@@ -614,14 +614,14 @@
     virtual double estimatedLoadingProgress() const { return 0; }
     static bool isARIAControl(AccessibilityRole);
     static bool isARIAInput(AccessibilityRole);
+
     virtual bool supportsARIAOwns() const { return false; }
-    virtual void ariaOwnsElements(AccessibilityChildrenVector&) const { }
-    virtual bool supportsARIAFlowTo() const { return false; }
-    virtual void ariaFlowToElements(AccessibilityChildrenVector&) const { }
-    virtual bool supportsARIADescribedBy() const { return false; }
-    virtual void ariaDescribedByElements(AccessibilityChildrenVector&) const { }
-    virtual bool supportsARIAControls() const { return false; }
-    virtual void ariaControlsElements(AccessibilityChildrenVector&) const { }
+    void ariaControlsElements(AccessibilityChildrenVector&) const;
+    void ariaDescribedByElements(AccessibilityChildrenVector&) const;
+    void ariaFlowToElements(AccessibilityChildrenVector&) const;
+    void ariaLabelledByElements(AccessibilityChildrenVector&) const;
+    void ariaOwnsElements(AccessibilityChildrenVector&) const;
+
     virtual bool ariaHasPopup() const { return false; }
     bool ariaPressedIsPresent() const;
     bool ariaIsMultiline() const;
@@ -1060,6 +1060,8 @@
     bool isOnscreen() const;
     bool dispatchTouchEvent();
 
+    void ariaElementsFromAttribute(AccessibilityChildrenVector&, const QualifiedName&) const;
+
 #if (PLATFORM(GTK) || PLATFORM(EFL)) && HAVE(ACCESSIBILITY)
     bool allowsTextRanges() const;
     unsigned getLengthForTextRange() const;
diff --git a/Source/WebCore/accessibility/AccessibilityRenderObject.cpp b/Source/WebCore/accessibility/AccessibilityRenderObject.cpp
index 0ca2961..be4cf9b 100644
--- a/Source/WebCore/accessibility/AccessibilityRenderObject.cpp
+++ b/Source/WebCore/accessibility/AccessibilityRenderObject.cpp
@@ -1003,47 +1003,6 @@
     return elementAttributeValue(aria_haspopupAttr);
 }
 
-void AccessibilityRenderObject::ariaElementsFromAttribute(AccessibilityChildrenVector& children, const QualifiedName& attributeName) const
-{
-    Vector<Element*> elements;
-    elementsFromAttribute(elements, attributeName);
-    AXObjectCache* cache = axObjectCache();
-    for (const auto& element : elements) {
-        if (AccessibilityObject* axObject = cache->getOrCreate(element))
-            children.append(axObject);
-    }
-}
-
-bool AccessibilityRenderObject::supportsARIAFlowTo() const
-{
-    return !getAttribute(aria_flowtoAttr).isEmpty();
-}
-    
-void AccessibilityRenderObject::ariaFlowToElements(AccessibilityChildrenVector& flowTo) const
-{
-    ariaElementsFromAttribute(flowTo, aria_flowtoAttr);
-}
-
-bool AccessibilityRenderObject::supportsARIADescribedBy() const
-{
-    return !getAttribute(aria_describedbyAttr).isEmpty();
-}
-
-void AccessibilityRenderObject::ariaDescribedByElements(AccessibilityChildrenVector& ariaDescribedBy) const
-{
-    ariaElementsFromAttribute(ariaDescribedBy, aria_describedbyAttr);
-}
-
-bool AccessibilityRenderObject::supportsARIAControls() const
-{
-    return !getAttribute(aria_controlsAttr).isEmpty();
-}
-
-void AccessibilityRenderObject::ariaControlsElements(AccessibilityChildrenVector& ariaControls) const
-{
-    ariaElementsFromAttribute(ariaControls, aria_controlsAttr);
-}
-
 bool AccessibilityRenderObject::supportsARIADropping() const 
 {
     const AtomicString& dropEffect = getAttribute(aria_dropeffectAttr);
@@ -1735,11 +1694,6 @@
         downcast<HTMLTextAreaElement>(element).setValue(string);
 }
 
-void AccessibilityRenderObject::ariaOwnsElements(AccessibilityChildrenVector& axObjects) const
-{
-    ariaElementsFromAttribute(axObjects, aria_ownsAttr);
-}
-
 bool AccessibilityRenderObject::supportsARIAOwns() const
 {
     if (!m_renderer)
diff --git a/Source/WebCore/accessibility/AccessibilityRenderObject.h b/Source/WebCore/accessibility/AccessibilityRenderObject.h
index 1c5faae..b6872fe 100644
--- a/Source/WebCore/accessibility/AccessibilityRenderObject.h
+++ b/Source/WebCore/accessibility/AccessibilityRenderObject.h
@@ -107,7 +107,6 @@
     AccessibilityObject* correspondingControlForLabelElement() const override;
     AccessibilityObject* correspondingLabelForControlElement() const override;
 
-    void ariaOwnsElements(AccessibilityChildrenVector&) const override;
     bool supportsARIAOwns() const override;
     bool isPresentationalChildOfAriaRole() const override;
     bool ariaRoleHasPresentationalChildren() const override;
@@ -176,12 +175,6 @@
     IntRect boundsForRange(const RefPtr<Range>) const override;
     IntRect boundsForRects(LayoutRect&, LayoutRect&, RefPtr<Range>) const;
     void setSelectedVisiblePositionRange(const VisiblePositionRange&) const override;
-    bool supportsARIAFlowTo() const override;
-    void ariaFlowToElements(AccessibilityChildrenVector&) const override;
-    bool supportsARIADescribedBy() const override;
-    void ariaDescribedByElements(AccessibilityChildrenVector&) const override;
-    bool supportsARIAControls() const override;
-    void ariaControlsElements(AccessibilityChildrenVector&) const override;
     bool ariaHasPopup() const override;
 
     bool supportsARIADropping() const override;
@@ -215,7 +208,6 @@
 protected:
     explicit AccessibilityRenderObject(RenderObject*);
     void setRenderObject(RenderObject* renderer) { m_renderer = renderer; }
-    void ariaElementsFromAttribute(AccessibilityChildrenVector&, const QualifiedName&) const;
     bool needsToUpdateChildren() const { return m_childrenDirty; }
     ScrollableArea* getScrollableAreaIfScrollable() const override;
     void scrollTo(const IntPoint&) const override;
diff --git a/Source/WebCore/accessibility/atk/WebKitAccessibleWrapperAtk.cpp b/Source/WebCore/accessibility/atk/WebKitAccessibleWrapperAtk.cpp
index 5ffe2ea..5ea1a5c 100644
--- a/Source/WebCore/accessibility/atk/WebKitAccessibleWrapperAtk.cpp
+++ b/Source/WebCore/accessibility/atk/WebKitAccessibleWrapperAtk.cpp
@@ -44,6 +44,8 @@
 #include "HTMLNames.h"
 #include "HTMLTableElement.h"
 #include "HostWindow.h"
+#include "RenderAncestorIterator.h"
+#include "RenderFieldset.h"
 #include "RenderObject.h"
 #include "SVGElement.h"
 #include "Settings.h"
@@ -228,63 +230,53 @@
 
 static void setAtkRelationSetFromCoreObject(AccessibilityObject* coreObject, AtkRelationSet* relationSet)
 {
-    if (coreObject->isFieldset()) {
-        AccessibilityObject* label = coreObject->titleUIElement();
-        if (label) {
-            removeAtkRelationByType(relationSet, ATK_RELATION_LABELLED_BY);
-            atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_LABELLED_BY, label->wrapper());
-        }
-        return;
-    }
+    // FIXME: We're not implementing all the relation types, most notably the inverse/reciprocal
+    // types. Filed as bug 155494.
 
-    if (coreObject->roleValue() == LegendRole) {
-        for (AccessibilityObject* parent = coreObject->parentObjectUnignored(); parent; parent = parent->parentObjectUnignored()) {
-            if (parent->isFieldset()) {
-                atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_LABEL_FOR, parent->wrapper());
-                break;
-            }
-        }
-        return;
-    }
-
+    // Elements with aria-labelledby should have the labelled-by relation as per the ARIA AAM spec.
+    // Controls with a label element and fieldsets with a legend element should also use this relation
+    // as per the HTML AAM spec. The reciprocal label-for relation should also be used.
+    removeAtkRelationByType(relationSet, ATK_RELATION_LABELLED_BY);
     if (coreObject->isControl()) {
-        AccessibilityObject* label = coreObject->correspondingLabelForControlElement();
-        if (label) {
-            removeAtkRelationByType(relationSet, ATK_RELATION_LABELLED_BY);
+        if (AccessibilityObject* label = coreObject->correspondingLabelForControlElement())
             atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_LABELLED_BY, label->wrapper());
+    } else if (coreObject->isFieldset()) {
+        if (AccessibilityObject* label = coreObject->titleUIElement())
+            atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_LABELLED_BY, label->wrapper());
+    } else if (coreObject->roleValue() == LegendRole) {
+        if (RenderFieldset* renderFieldset = ancestorsOfType<RenderFieldset>(*coreObject->renderer()).first()) {
+            AccessibilityObject* fieldset = coreObject->axObjectCache()->getOrCreate(renderFieldset);
+            atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_LABEL_FOR, fieldset->wrapper());
         }
+    } else if (AccessibilityObject* control = coreObject->correspondingControlForLabelElement()) {
+        atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_LABEL_FOR, control->wrapper());
     } else {
-        AccessibilityObject* control = coreObject->correspondingControlForLabelElement();
-        if (control)
-            atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_LABEL_FOR, control->wrapper());
+        AccessibilityObject::AccessibilityChildrenVector ariaLabelledByElements;
+        coreObject->ariaLabelledByElements(ariaLabelledByElements);
+        for (const auto& accessibilityObject : ariaLabelledByElements)
+            atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_LABELLED_BY, accessibilityObject->wrapper());
     }
 
-    // Check whether object supports aria-flowto
-    if (coreObject->supportsARIAFlowTo()) {
-        removeAtkRelationByType(relationSet, ATK_RELATION_FLOWS_TO);
-        AccessibilityObject::AccessibilityChildrenVector ariaFlowToElements;
-        coreObject->ariaFlowToElements(ariaFlowToElements);
-        for (const auto& accessibilityObject : ariaFlowToElements)
-            atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_FLOWS_TO, accessibilityObject->wrapper());
-    }
+    // Elements with aria-flowto should have the flows-to relation as per the ARIA AAM spec.
+    removeAtkRelationByType(relationSet, ATK_RELATION_FLOWS_TO);
+    AccessibilityObject::AccessibilityChildrenVector ariaFlowToElements;
+    coreObject->ariaFlowToElements(ariaFlowToElements);
+    for (const auto& accessibilityObject : ariaFlowToElements)
+        atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_FLOWS_TO, accessibilityObject->wrapper());
 
-    // Check whether object supports aria-describedby. It provides an additional information for the user.
-    if (coreObject->supportsARIADescribedBy()) {
-        removeAtkRelationByType(relationSet, ATK_RELATION_DESCRIBED_BY);
-        AccessibilityObject::AccessibilityChildrenVector ariaDescribedByElements;
-        coreObject->ariaDescribedByElements(ariaDescribedByElements);
-        for (const auto& accessibilityObject : ariaDescribedByElements)
-            atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_DESCRIBED_BY, accessibilityObject->wrapper());
-    }
+    // Elements with aria-describedby should have the described-by relation as per the ARIA AAM spec.
+    removeAtkRelationByType(relationSet, ATK_RELATION_DESCRIBED_BY);
+    AccessibilityObject::AccessibilityChildrenVector ariaDescribedByElements;
+    coreObject->ariaDescribedByElements(ariaDescribedByElements);
+    for (const auto& accessibilityObject : ariaDescribedByElements)
+        atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_DESCRIBED_BY, accessibilityObject->wrapper());
 
-    // Check whether object supports aria-controls. It provides information about elements that are controlled by the current object.
-    if (coreObject->supportsARIAControls()) {
-        removeAtkRelationByType(relationSet, ATK_RELATION_CONTROLLER_FOR);
-        AccessibilityObject::AccessibilityChildrenVector ariaControls;
-        coreObject->ariaControlsElements(ariaControls);
-        for (const auto& accessibilityObject : ariaControls)
-            atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_CONTROLLER_FOR, accessibilityObject->wrapper());
-    }
+    // Elements with aria-controls should have the controller-for relation as per the ARIA AAM spec.
+    removeAtkRelationByType(relationSet, ATK_RELATION_CONTROLLER_FOR);
+    AccessibilityObject::AccessibilityChildrenVector ariaControls;
+    coreObject->ariaControlsElements(ariaControls);
+    for (const auto& accessibilityObject : ariaControls)
+        atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_CONTROLLER_FOR, accessibilityObject->wrapper());
 }
 
 static gpointer webkitAccessibleParentClass = nullptr;
diff --git a/Source/WebCore/inspector/InspectorDOMAgent.cpp b/Source/WebCore/inspector/InspectorDOMAgent.cpp
index 136a2b9..71bfa94 100644
--- a/Source/WebCore/inspector/InspectorDOMAgent.cpp
+++ b/Source/WebCore/inspector/InspectorDOMAgent.cpp
@@ -1590,14 +1590,12 @@
             
             processAccessibilityChildren(axObject, WTFMove(childNodeIds));
             
-            if (axObject->supportsARIAControls()) {
-                Vector<Element*> controlledElements;
-                axObject->elementsFromAttribute(controlledElements, aria_controlsAttr);
-                if (controlledElements.size()) {
-                    controlledNodeIds = Inspector::Protocol::Array<int>::create();
-                    for (Element* controlledElement : controlledElements)
-                        controlledNodeIds->addItem(pushNodePathToFrontend(controlledElement));
-                }
+            Vector<Element*> controlledElements;
+            axObject->elementsFromAttribute(controlledElements, aria_controlsAttr);
+            if (controlledElements.size()) {
+                controlledNodeIds = Inspector::Protocol::Array<int>::create();
+                for (Element* controlledElement : controlledElements)
+                    controlledNodeIds->addItem(pushNodePathToFrontend(controlledElement));
             }
             
             switch (axObject->ariaCurrentState()) {
@@ -1632,14 +1630,12 @@
             if (supportsExpanded)
                 expanded = axObject->isExpanded();
 
-            if (axObject->supportsARIAFlowTo()) {
-                Vector<Element*> flowedElements;
-                axObject->elementsFromAttribute(flowedElements, aria_flowtoAttr);
-                if (flowedElements.size()) {
-                    flowedNodeIds = Inspector::Protocol::Array<int>::create();
-                    for (Element* flowedElement : flowedElements)
-                        flowedNodeIds->addItem(pushNodePathToFrontend(flowedElement));
-                }
+            Vector<Element*> flowedElements;
+            axObject->elementsFromAttribute(flowedElements, aria_flowtoAttr);
+            if (flowedElements.size()) {
+                flowedNodeIds = Inspector::Protocol::Array<int>::create();
+                for (Element* flowedElement : flowedElements)
+                    flowedNodeIds->addItem(pushNodePathToFrontend(flowedElement));
             }
             
             if (is<Element>(*node)) {