blob: 125c192bc0ce3c44b10141035b621345a896eef6 [file] [log] [blame]
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +00001/*
2 * Copyright (C) 2008 Nuanti Ltd.
jmalonzo@webkit.orgaaaea3b2009-08-08 07:39:48 +00003 * Copyright (C) 2009 Jan Alonzo
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00004 * Copyright (C) 2009, 2010, 2011, 2012, 2019 Igalia S.L.
mario@webkit.orgfecbacd2013-03-04 17:06:15 +00005 * Copyright (C) 2013 Samsung Electronics
xan@webkit.orge4387102009-04-09 11:08:48 +00006 *
7 * Portions from Mozilla a11y, copyright as follows:
8 *
9 * The Original Code is mozilla.org code.
10 *
11 * The Initial Developer of the Original Code is
12 * Sun Microsystems, Inc.
13 * Portions created by the Initial Developer are Copyright (C) 2002
14 * the Initial Developer. All Rights Reserved.
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +000015 *
16 * This library is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU Library General Public
18 * License as published by the Free Software Foundation; either
19 * version 2 of the License, or (at your option) any later version.
20 *
21 * This library is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * Library General Public License for more details.
25 *
26 * You should have received a copy of the GNU Library General Public License
27 * along with this library; see the file COPYING.LIB. If not, write to
28 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
29 * Boston, MA 02110-1301, USA.
30 */
31
32#include "config.h"
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +000033#include "WebKitAccessible.h"
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +000034
psaavedra@igalia.com5b9fe192019-07-11 21:51:24 +000035#if ENABLE(ACCESSIBILITY)
ddkilzer@apple.com8d878632008-11-09 19:50:37 +000036
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +000037#include "AXObjectCache.h"
mario.prada@samsung.com4fb934b2013-12-17 18:08:34 +000038#include "AccessibilityList.h"
akling@apple.com88e05f62013-09-16 15:17:24 +000039#include "AccessibilityListBoxOption.h"
cdumez@apple.comb04d5742014-10-22 21:45:20 +000040#include "AccessibilityTable.h"
jdiggs@igalia.com466ea212017-05-01 21:19:09 +000041#include "AccessibilityTableCell.h"
jdiggs@igalia.com238c5802017-10-04 00:03:12 +000042#include "AccessibilityTableRow.h"
alp@webkit.orgc7738992008-05-27 02:48:14 +000043#include "Document.h"
commit-queue@webkit.org02ea7a22017-03-03 06:35:25 +000044#include "Editing.h"
alp@webkit.orgc7738992008-05-27 02:48:14 +000045#include "Frame.h"
46#include "FrameView.h"
xan@webkit.org9561b2c2009-05-20 14:33:19 +000047#include "HTMLNames.h"
xan@webkit.org45b26ac2009-10-27 12:20:35 +000048#include "HTMLTableElement.h"
mario@webkit.org9adab662012-01-23 10:21:03 +000049#include "HostWindow.h"
jdiggs@igalia.com3504d462016-03-16 01:45:57 +000050#include "RenderAncestorIterator.h"
hyatt@apple.com80914862017-03-06 18:00:35 +000051#include "RenderBlock.h"
mario@webkit.org970eaf32012-01-24 18:37:45 +000052#include "RenderObject.h"
jdiggs@igalia.com2f555dc2016-03-05 21:35:57 +000053#include "SVGElement.h"
mario@webkit.org6a24ba12010-12-14 15:35:22 +000054#include "Settings.h"
commit-queue@webkit.org74bd2e82010-09-12 11:16:14 +000055#include "TextIterator.h"
tkent@chromium.org8c35c122013-03-06 13:00:14 +000056#include "VisibleUnits.h"
mario@webkit.org7f95c622010-11-01 15:05:36 +000057#include "WebKitAccessibleHyperlink.h"
mario@webkit.orgdeec8392012-01-23 14:45:23 +000058#include "WebKitAccessibleInterfaceAction.h"
mario@webkit.orgbe1ce552012-01-24 11:03:51 +000059#include "WebKitAccessibleInterfaceComponent.h"
mario@webkit.orgf8344ff2012-01-24 11:40:44 +000060#include "WebKitAccessibleInterfaceDocument.h"
mario@webkit.orgfc51ca62012-01-24 11:47:51 +000061#include "WebKitAccessibleInterfaceEditableText.h"
mario@webkit.org4dbd9822012-01-24 11:55:18 +000062#include "WebKitAccessibleInterfaceHyperlinkImpl.h"
mario@webkit.org70243532012-01-24 11:58:52 +000063#include "WebKitAccessibleInterfaceHypertext.h"
mario@webkit.orgda3e6082012-01-24 12:04:16 +000064#include "WebKitAccessibleInterfaceImage.h"
mario@webkit.org7e5931d2012-01-24 12:25:13 +000065#include "WebKitAccessibleInterfaceSelection.h"
mario@webkit.orgcd9f1b32012-01-24 18:28:22 +000066#include "WebKitAccessibleInterfaceTable.h"
k.czech@samsung.com2608de92014-02-27 11:28:31 +000067#include "WebKitAccessibleInterfaceTableCell.h"
mario@webkit.org987d7372012-01-24 18:02:08 +000068#include "WebKitAccessibleInterfaceText.h"
mario@webkit.org980269e2012-01-24 16:22:57 +000069#include "WebKitAccessibleInterfaceValue.h"
mario@webkit.org7ceffa42012-01-23 11:55:01 +000070#include "WebKitAccessibleUtil.h"
xan@webkit.orge4387102009-04-09 11:08:48 +000071#include <glib/gprintf.h>
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +000072#include <wtf/glib/WTFGType.h>
benjamin@webkit.org9d72cb02013-04-22 22:52:23 +000073#include <wtf/text/CString.h>
mario@webkit.org8c5dd902012-11-09 19:47:40 +000074
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +000075using namespace WebCore;
76
mario@webkit.orgfecbacd2013-03-04 17:06:15 +000077struct _WebKitAccessiblePrivate {
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +000078 AccessibilityObject* object;
79
mario@webkit.orgfecbacd2013-03-04 17:06:15 +000080 // Cached data for AtkObject.
81 CString accessibleName;
82 CString accessibleDescription;
83
84 // Cached data for AtkAction.
85 CString actionName;
86 CString actionKeyBinding;
87
88 // Cached data for AtkDocument.
89 CString documentLocale;
90 CString documentType;
91 CString documentEncoding;
92 CString documentURI;
93
94 // Cached data for AtkImage.
95 CString imageDescription;
96};
97
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +000098WEBKIT_DEFINE_TYPE(WebKitAccessible, webkit_accessible, ATK_TYPE_OBJECT)
mario@webkit.orgfecbacd2013-03-04 17:06:15 +000099
xan@webkit.orgc886cc62009-04-09 11:17:48 +0000100static AccessibilityObject* fallbackObject()
101{
akling@apple.comad2beb52014-12-25 07:50:20 +0000102 static AccessibilityObject* object = &AccessibilityListBoxOption::create().leakRef();
xan@webkit.orgc886cc62009-04-09 11:17:48 +0000103 return object;
104}
105
mario@webkit.org5c966772012-01-24 18:48:50 +0000106static const gchar* webkitAccessibleGetName(AtkObject* object)
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +0000107{
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000108 auto* accessible = WEBKIT_ACCESSIBLE(object);
109 returnValIfWebKitAccessibleIsInvalid(accessible, nullptr);
mario@webkit.orgff8cf0f2013-09-27 09:44:20 +0000110
jdiggs@igalia.come184cee2016-05-18 07:12:09 +0000111 Vector<AccessibilityText> textOrder;
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000112 accessible->priv->object->accessibilityText(textOrder);
jdiggs@igalia.come184cee2016-05-18 07:12:09 +0000113
114 for (const auto& text : textOrder) {
115 // FIXME: This check is here because AccessibilityNodeObject::titleElementText()
116 // appends an empty String for the LabelByElementText source when there is a
117 // titleUIElement(). Removing this check makes some fieldsets lose their name.
118 if (text.text.isEmpty())
119 continue;
120
121 // WebCore Accessibility should provide us with the text alternative computation
122 // in the order defined by that spec. So take the first thing that our platform
123 // does not expose via the AtkObject description.
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000124 if (text.textSource != AccessibilityTextSource::Help && text.textSource != AccessibilityTextSource::Summary)
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000125 return webkitAccessibleCacheAndReturnAtkProperty(accessible, AtkCachedAccessibleName, text.text.utf8());
commit-queue@webkit.org802c0122012-09-11 01:41:27 +0000126 }
127
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000128 return webkitAccessibleCacheAndReturnAtkProperty(accessible, AtkCachedAccessibleName, "");
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +0000129}
130
mario@webkit.org5c966772012-01-24 18:48:50 +0000131static const gchar* webkitAccessibleGetDescription(AtkObject* object)
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +0000132{
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000133 auto* accessible = WEBKIT_ACCESSIBLE(object);
134 returnValIfWebKitAccessibleIsInvalid(accessible, nullptr);
mario@webkit.orgff8cf0f2013-09-27 09:44:20 +0000135
jdiggs@igalia.come184cee2016-05-18 07:12:09 +0000136 Vector<AccessibilityText> textOrder;
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000137 accessible->priv->object->accessibilityText(textOrder);
jdiggs@igalia.com2f555dc2016-03-05 21:35:57 +0000138
jdiggs@igalia.come184cee2016-05-18 07:12:09 +0000139 bool nameTextAvailable = false;
140 for (const auto& text : textOrder) {
141 // WebCore Accessibility should provide us with the text alternative computation
142 // in the order defined by that spec. So take the first thing that our platform
143 // does not expose via the AtkObject name.
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000144 if (text.textSource == AccessibilityTextSource::Help || text.textSource == AccessibilityTextSource::Summary)
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000145 return webkitAccessibleCacheAndReturnAtkProperty(accessible, AtkCachedAccessibleDescription, text.text.utf8());
jdiggs@igalia.com2f555dc2016-03-05 21:35:57 +0000146
jdiggs@igalia.come184cee2016-05-18 07:12:09 +0000147 // If there is no other text alternative, the title tag contents will have been
148 // used for the AtkObject name. We don't want to duplicate it here.
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000149 if (text.textSource == AccessibilityTextSource::TitleTag && nameTextAvailable)
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000150 return webkitAccessibleCacheAndReturnAtkProperty(accessible, AtkCachedAccessibleDescription, text.text.utf8());
jdiggs@igalia.come184cee2016-05-18 07:12:09 +0000151
152 nameTextAvailable = true;
jdiggs@igalia.com2f555dc2016-03-05 21:35:57 +0000153 }
154
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000155 return webkitAccessibleCacheAndReturnAtkProperty(accessible, AtkCachedAccessibleDescription, "");
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +0000156}
157
m.pakula@samsung.come026b6a2013-11-06 18:17:03 +0000158static void removeAtkRelationByType(AtkRelationSet* relationSet, AtkRelationType relationType)
159{
160 int count = atk_relation_set_get_n_relations(relationSet);
161 for (int i = 0; i < count; i++) {
162 AtkRelation* relation = atk_relation_set_get_relation(relationSet, i);
163 if (atk_relation_get_relation_type(relation) == relationType) {
164 atk_relation_set_remove(relationSet, relation);
165 break;
166 }
167 }
168}
169
eric@webkit.org0f6cb452009-10-22 23:07:56 +0000170static void setAtkRelationSetFromCoreObject(AccessibilityObject* coreObject, AtkRelationSet* relationSet)
171{
jdiggs@igalia.com3504d462016-03-16 01:45:57 +0000172 // Elements with aria-labelledby should have the labelled-by relation as per the ARIA AAM spec.
173 // Controls with a label element and fieldsets with a legend element should also use this relation
174 // as per the HTML AAM spec. The reciprocal label-for relation should also be used.
175 removeAtkRelationByType(relationSet, ATK_RELATION_LABELLED_BY);
jdiggs@igalia.com20c43fb2017-06-13 12:42:04 +0000176 removeAtkRelationByType(relationSet, ATK_RELATION_LABEL_FOR);
mario@webkit.org7e9f2412011-04-06 16:50:25 +0000177 if (coreObject->isControl()) {
jdiggs@igalia.com3504d462016-03-16 01:45:57 +0000178 if (AccessibilityObject* label = coreObject->correspondingLabelForControlElement())
carlosgc@webkit.org9d3f9a42019-04-05 07:35:24 +0000179 atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_LABELLED_BY, ATK_OBJECT(label->wrapper()));
jdiggs@igalia.com3504d462016-03-16 01:45:57 +0000180 } else if (coreObject->isFieldset()) {
181 if (AccessibilityObject* label = coreObject->titleUIElement())
carlosgc@webkit.org9d3f9a42019-04-05 07:35:24 +0000182 atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_LABELLED_BY, ATK_OBJECT(label->wrapper()));
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000183 } else if (coreObject->roleValue() == AccessibilityRole::Legend) {
hyatt@apple.com80914862017-03-06 18:00:35 +0000184 if (RenderBlock* renderFieldset = ancestorsOfType<RenderBlock>(*coreObject->renderer()).first()) {
185 if (renderFieldset->isFieldset()) {
186 AccessibilityObject* fieldset = coreObject->axObjectCache()->getOrCreate(renderFieldset);
carlosgc@webkit.org9d3f9a42019-04-05 07:35:24 +0000187 atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_LABEL_FOR, ATK_OBJECT(fieldset->wrapper()));
hyatt@apple.com80914862017-03-06 18:00:35 +0000188 }
m.pakula@samsung.come026b6a2013-11-06 18:17:03 +0000189 }
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000190 } else if (AccessibilityObject* control = coreObject->correspondingControlForLabelElement())
carlosgc@webkit.org9d3f9a42019-04-05 07:35:24 +0000191 atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_LABEL_FOR, ATK_OBJECT(control->wrapper()));
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000192 else {
jdiggs@igalia.com3504d462016-03-16 01:45:57 +0000193 AccessibilityObject::AccessibilityChildrenVector ariaLabelledByElements;
194 coreObject->ariaLabelledByElements(ariaLabelledByElements);
195 for (const auto& accessibilityObject : ariaLabelledByElements)
carlosgc@webkit.org9d3f9a42019-04-05 07:35:24 +0000196 atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_LABELLED_BY, ATK_OBJECT(accessibilityObject->wrapper()));
eric@webkit.org0f6cb452009-10-22 23:07:56 +0000197 }
k.czech@samsung.com22545812014-01-21 09:10:25 +0000198
jdiggs@igalia.com20c43fb2017-06-13 12:42:04 +0000199 // Elements referenced by aria-labelledby should have the label-for relation as per the ARIA AAM spec.
200 AccessibilityObject::AccessibilityChildrenVector labels;
201 coreObject->ariaLabelledByReferencingElements(labels);
202 for (const auto& accessibilityObject : labels)
carlosgc@webkit.org9d3f9a42019-04-05 07:35:24 +0000203 atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_LABEL_FOR, ATK_OBJECT(accessibilityObject->wrapper()));
jdiggs@igalia.com20c43fb2017-06-13 12:42:04 +0000204
jdiggs@igalia.com3504d462016-03-16 01:45:57 +0000205 // Elements with aria-flowto should have the flows-to relation as per the ARIA AAM spec.
206 removeAtkRelationByType(relationSet, ATK_RELATION_FLOWS_TO);
207 AccessibilityObject::AccessibilityChildrenVector ariaFlowToElements;
208 coreObject->ariaFlowToElements(ariaFlowToElements);
209 for (const auto& accessibilityObject : ariaFlowToElements)
carlosgc@webkit.org9d3f9a42019-04-05 07:35:24 +0000210 atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_FLOWS_TO, ATK_OBJECT(accessibilityObject->wrapper()));
k.czech@samsung.com7e9868e2014-01-29 13:16:27 +0000211
jdiggs@igalia.com20c43fb2017-06-13 12:42:04 +0000212 // Elements referenced by aria-flowto should have the flows-from relation as per the ARIA AAM spec.
213 removeAtkRelationByType(relationSet, ATK_RELATION_FLOWS_FROM);
214 AccessibilityObject::AccessibilityChildrenVector flowFrom;
215 coreObject->ariaFlowToReferencingElements(flowFrom);
216 for (const auto& accessibilityObject : flowFrom)
carlosgc@webkit.org9d3f9a42019-04-05 07:35:24 +0000217 atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_FLOWS_FROM, ATK_OBJECT(accessibilityObject->wrapper()));
jdiggs@igalia.com20c43fb2017-06-13 12:42:04 +0000218
jdiggs@igalia.com3504d462016-03-16 01:45:57 +0000219 // Elements with aria-describedby should have the described-by relation as per the ARIA AAM spec.
220 removeAtkRelationByType(relationSet, ATK_RELATION_DESCRIBED_BY);
221 AccessibilityObject::AccessibilityChildrenVector ariaDescribedByElements;
222 coreObject->ariaDescribedByElements(ariaDescribedByElements);
223 for (const auto& accessibilityObject : ariaDescribedByElements)
carlosgc@webkit.org9d3f9a42019-04-05 07:35:24 +0000224 atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_DESCRIBED_BY, ATK_OBJECT(accessibilityObject->wrapper()));
k.czech@samsung.comb8ad4bf2014-02-03 09:16:54 +0000225
jdiggs@igalia.com20c43fb2017-06-13 12:42:04 +0000226 // Elements referenced by aria-describedby should have the description-for relation as per the ARIA AAM spec.
227 removeAtkRelationByType(relationSet, ATK_RELATION_DESCRIPTION_FOR);
228 AccessibilityObject::AccessibilityChildrenVector describers;
229 coreObject->ariaDescribedByReferencingElements(describers);
230 for (const auto& accessibilityObject : describers)
carlosgc@webkit.org9d3f9a42019-04-05 07:35:24 +0000231 atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_DESCRIPTION_FOR, ATK_OBJECT(accessibilityObject->wrapper()));
jdiggs@igalia.com20c43fb2017-06-13 12:42:04 +0000232
jdiggs@igalia.com3504d462016-03-16 01:45:57 +0000233 // Elements with aria-controls should have the controller-for relation as per the ARIA AAM spec.
234 removeAtkRelationByType(relationSet, ATK_RELATION_CONTROLLER_FOR);
235 AccessibilityObject::AccessibilityChildrenVector ariaControls;
236 coreObject->ariaControlsElements(ariaControls);
237 for (const auto& accessibilityObject : ariaControls)
carlosgc@webkit.org9d3f9a42019-04-05 07:35:24 +0000238 atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_CONTROLLER_FOR, ATK_OBJECT(accessibilityObject->wrapper()));
jdiggs@igalia.com20c43fb2017-06-13 12:42:04 +0000239
240 // Elements referenced by aria-controls should have the controlled-by relation as per the ARIA AAM spec.
241 removeAtkRelationByType(relationSet, ATK_RELATION_CONTROLLED_BY);
242 AccessibilityObject::AccessibilityChildrenVector controllers;
243 coreObject->ariaControlsReferencingElements(controllers);
244 for (const auto& accessibilityObject : controllers)
carlosgc@webkit.org9d3f9a42019-04-05 07:35:24 +0000245 atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_CONTROLLED_BY, ATK_OBJECT(accessibilityObject->wrapper()));
jdiggs@igalia.com20c43fb2017-06-13 12:42:04 +0000246
247 // Elements with aria-owns should have the node-parent-of relation as per the ARIA AAM spec.
248 removeAtkRelationByType(relationSet, ATK_RELATION_NODE_PARENT_OF);
249 AccessibilityObject::AccessibilityChildrenVector ariaOwns;
250 coreObject->ariaOwnsElements(ariaOwns);
251 for (const auto& accessibilityObject : ariaOwns)
carlosgc@webkit.org9d3f9a42019-04-05 07:35:24 +0000252 atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_NODE_PARENT_OF, ATK_OBJECT(accessibilityObject->wrapper()));
jdiggs@igalia.com20c43fb2017-06-13 12:42:04 +0000253
254 // Elements referenced by aria-owns should have the node-child-of relation as per the ARIA AAM spec.
255 removeAtkRelationByType(relationSet, ATK_RELATION_NODE_CHILD_OF);
256 AccessibilityObject::AccessibilityChildrenVector owners;
257 coreObject->ariaOwnsReferencingElements(owners);
258 for (const auto& accessibilityObject : owners)
carlosgc@webkit.org9d3f9a42019-04-05 07:35:24 +0000259 atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_NODE_CHILD_OF, ATK_OBJECT(accessibilityObject->wrapper()));
jdiggs@igalia.com3a11d3f2017-06-26 16:45:34 +0000260
261#if ATK_CHECK_VERSION(2, 25, 2)
262 // Elements with aria-details should have the details relation as per the ARIA AAM spec.
263 removeAtkRelationByType(relationSet, ATK_RELATION_DETAILS);
264 AccessibilityObject::AccessibilityChildrenVector ariaDetails;
265 coreObject->ariaDetailsElements(ariaDetails);
266 for (const auto& accessibilityObject : ariaDetails)
carlosgc@webkit.org9d3f9a42019-04-05 07:35:24 +0000267 atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_DETAILS, ATK_OBJECT(accessibilityObject->wrapper()));
jdiggs@igalia.com3a11d3f2017-06-26 16:45:34 +0000268
269 // Elements referenced by aria-details should have the details-for relation as per the ARIA AAM spec.
270 removeAtkRelationByType(relationSet, ATK_RELATION_DETAILS_FOR);
271 AccessibilityObject::AccessibilityChildrenVector details;
272 coreObject->ariaDetailsReferencingElements(details);
273 for (const auto& accessibilityObject : details)
carlosgc@webkit.org9d3f9a42019-04-05 07:35:24 +0000274 atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_DETAILS_FOR, ATK_OBJECT(accessibilityObject->wrapper()));
jdiggs@igalia.com3a11d3f2017-06-26 16:45:34 +0000275
276 // Elements with aria-errormessage should have the error-message relation as per the ARIA AAM spec.
277 removeAtkRelationByType(relationSet, ATK_RELATION_ERROR_MESSAGE);
278 AccessibilityObject::AccessibilityChildrenVector ariaErrorMessage;
279 coreObject->ariaErrorMessageElements(ariaErrorMessage);
280 for (const auto& accessibilityObject : ariaErrorMessage)
carlosgc@webkit.org9d3f9a42019-04-05 07:35:24 +0000281 atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_ERROR_MESSAGE, ATK_OBJECT(accessibilityObject->wrapper()));
jdiggs@igalia.com3a11d3f2017-06-26 16:45:34 +0000282
283 // Elements referenced by aria-errormessage should have the error-for relation as per the ARIA AAM spec.
284 removeAtkRelationByType(relationSet, ATK_RELATION_ERROR_FOR);
285 AccessibilityObject::AccessibilityChildrenVector errors;
286 coreObject->ariaErrorMessageReferencingElements(errors);
287 for (const auto& accessibilityObject : errors)
carlosgc@webkit.org9d3f9a42019-04-05 07:35:24 +0000288 atk_relation_set_add_relation_by_type(relationSet, ATK_RELATION_ERROR_FOR, ATK_OBJECT(accessibilityObject->wrapper()));
jdiggs@igalia.com3a11d3f2017-06-26 16:45:34 +0000289#endif
eric@webkit.org0f6cb452009-10-22 23:07:56 +0000290}
291
mario@webkit.org86390a12011-01-07 17:34:02 +0000292static bool isRootObject(AccessibilityObject* coreObject)
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +0000293{
mario@webkit.org86390a12011-01-07 17:34:02 +0000294 // The root accessible object in WebCore is always an object with
295 // the ScrolledArea role with one child with the WebArea role.
296 if (!coreObject || !coreObject->isScrollView())
297 return false;
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +0000298
mario@webkit.org86390a12011-01-07 17:34:02 +0000299 AccessibilityObject* firstChild = coreObject->firstChild();
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000300 return firstChild && firstChild->isWebArea();
eric@webkit.org1f5f7fe2009-11-04 10:35:56 +0000301}
302
mario@webkit.org5c966772012-01-24 18:48:50 +0000303static AtkObject* webkitAccessibleGetParent(AtkObject* object)
eric@webkit.org1f5f7fe2009-11-04 10:35:56 +0000304{
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000305 auto* accessible = WEBKIT_ACCESSIBLE(object);
306 returnValIfWebKitAccessibleIsInvalid(accessible, nullptr);
mario@webkit.orgff8cf0f2013-09-27 09:44:20 +0000307
mario@webkit.org46e9b262011-11-17 11:50:07 +0000308 // Check first if the parent has been already set.
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000309 AtkObject* accessibleParent = ATK_OBJECT_CLASS(webkit_accessible_parent_class)->get_parent(object);
mario@webkit.org46e9b262011-11-17 11:50:07 +0000310 if (accessibleParent)
311 return accessibleParent;
312
313 // Parent not set yet, so try to find it in the hierarchy.
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000314 auto* coreObject = accessible->priv->object;
315 auto* coreParent = coreObject->parentObjectUnignored();
316 if (!coreParent && isRootObject(coreObject)) {
317 // The top level object claims to not have a parent. This makes it
318 // impossible for assistive technologies to ascend the accessible
319 // hierarchy all the way to the application. (Bug 30489)
320 if (!coreObject->document())
321 return nullptr;
322 }
eric@webkit.org1f5f7fe2009-11-04 10:35:56 +0000323
carlosgc@webkit.org9d3f9a42019-04-05 07:35:24 +0000324 return coreParent ? ATK_OBJECT(coreParent->wrapper()) : nullptr;
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +0000325}
326
mario@webkit.org5c966772012-01-24 18:48:50 +0000327static gint webkitAccessibleGetNChildren(AtkObject* object)
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +0000328{
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000329 auto* accessible = WEBKIT_ACCESSIBLE(object);
330 returnValIfWebKitAccessibleIsInvalid(accessible, 0);
mario@webkit.orgff8cf0f2013-09-27 09:44:20 +0000331
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000332 return accessible->priv->object->children().size();
mario@webkit.org868b5ea2011-06-24 09:06:32 +0000333}
334
mario@webkit.org5c966772012-01-24 18:48:50 +0000335static AtkObject* webkitAccessibleRefChild(AtkObject* object, gint index)
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +0000336{
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000337 auto* accessible = WEBKIT_ACCESSIBLE(object);
338 returnValIfWebKitAccessibleIsInvalid(accessible, nullptr);
mario@webkit.orgff8cf0f2013-09-27 09:44:20 +0000339
mario@webkit.org868b5ea2011-06-24 09:06:32 +0000340 if (index < 0)
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000341 return nullptr;
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +0000342
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000343 const auto& children = accessible->priv->object->children();
jdiggs@igalia.come8a090d2014-12-03 02:02:36 +0000344 if (static_cast<size_t>(index) >= children.size())
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000345 return nullptr;
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +0000346
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000347 auto& coreChild = children[index];
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +0000348 if (!coreChild)
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000349 return nullptr;
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +0000350
carlosgc@webkit.org2dd6e722019-04-22 07:58:11 +0000351 auto* child = coreChild->wrapper();
352 if (!child)
353 return nullptr;
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +0000354
carlosgc@webkit.org2dd6e722019-04-22 07:58:11 +0000355 atk_object_set_parent(ATK_OBJECT(child), object);
356 return ATK_OBJECT(g_object_ref(child));
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +0000357}
358
mario@webkit.org5c966772012-01-24 18:48:50 +0000359static gint webkitAccessibleGetIndexInParent(AtkObject* object)
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +0000360{
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000361 auto* accessible = WEBKIT_ACCESSIBLE(object);
362 returnValIfWebKitAccessibleIsInvalid(accessible, -1);
mario@webkit.orgff8cf0f2013-09-27 09:44:20 +0000363
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000364 auto* coreObject = accessible->priv->object;
365 auto* parent = coreObject->parentObjectUnignored();
mario@webkit.org86390a12011-01-07 17:34:02 +0000366 if (!parent && isRootObject(coreObject)) {
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000367 if (!coreObject->document())
368 return -1;
369
370 auto* atkParent = parent ? ATK_OBJECT(parent->wrapper()) : nullptr;
eric@webkit.org1f5f7fe2009-11-04 10:35:56 +0000371 if (!atkParent)
372 return -1;
373
374 unsigned count = atk_object_get_n_accessible_children(atkParent);
375 for (unsigned i = 0; i < count; ++i) {
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000376 GRefPtr<AtkObject> child = adoptGRef(atk_object_ref_accessible_child(atkParent, i));
377 if (child.get() == object)
eric@webkit.org1f5f7fe2009-11-04 10:35:56 +0000378 return i;
379 }
380 }
xan@webkit.org1f5349a2009-10-27 09:20:21 +0000381
commit-queue@webkit.org54a624e2013-01-16 18:00:17 +0000382 if (!parent)
383 return -1;
384
commit-queue@webkit.orgbf183552012-02-22 09:28:57 +0000385 size_t index = parent->children().find(coreObject);
386 return (index == WTF::notFound) ? -1 : index;
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +0000387}
388
mario@webkit.org5c966772012-01-24 18:48:50 +0000389static AtkAttributeSet* webkitAccessibleGetAttributes(AtkObject* object)
eric@webkit.org84496192009-10-17 20:00:33 +0000390{
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000391 auto* accessible = WEBKIT_ACCESSIBLE(object);
392 returnValIfWebKitAccessibleIsInvalid(accessible, nullptr);
mario@webkit.orgff8cf0f2013-09-27 09:44:20 +0000393
commit-queue@webkit.org9a24e2d2015-05-29 04:53:35 +0000394 AtkAttributeSet* attributeSet = nullptr;
mario@webkit.org8c5dd902012-11-09 19:47:40 +0000395#if PLATFORM(GTK)
mario@webkit.orgf8344ff2012-01-24 11:40:44 +0000396 attributeSet = addToAtkAttributeSet(attributeSet, "toolkit", "WebKitGtk");
carlosgc@webkit.orgfdfb04c2019-05-21 12:45:08 +0000397#elif PLATFORM(WPE)
398 attributeSet = addToAtkAttributeSet(attributeSet, "toolkit", "WPEWebKit");
mario@webkit.org8c5dd902012-11-09 19:47:40 +0000399#endif
eric@webkit.orgf4efc402010-05-15 09:55:52 +0000400
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000401 auto* coreObject = accessible->priv->object;
commit-queue@webkit.orga9398dd2010-10-26 19:19:29 +0000402
commit-queue@webkit.org357dc222013-01-10 00:09:41 +0000403 // Hack needed for WebKit2 tests because obtaining an element by its ID
404 // cannot be done from the UIProcess. Assistive technologies have no need
405 // for this information.
jdiggs@igalia.combcff9522014-11-28 00:24:43 +0000406 Element* element = coreObject->element() ? coreObject->element() : coreObject->actionElement();
407 if (element) {
jdiggs@igalia.com5a8352d2015-06-17 20:03:13 +0000408 String tagName = element->tagName();
409 if (!tagName.isEmpty())
darin@apple.com4d716f22016-02-01 05:46:20 +0000410 attributeSet = addToAtkAttributeSet(attributeSet, "tag", tagName.convertToASCIILowercase().utf8().data());
jdiggs@igalia.combcff9522014-11-28 00:24:43 +0000411 String id = element->getIdAttribute().string();
commit-queue@webkit.org357dc222013-01-10 00:09:41 +0000412 if (!id.isEmpty())
413 attributeSet = addToAtkAttributeSet(attributeSet, "html-id", id.utf8().data());
414 }
415
jdiggs@igalia.com7ccbaee2017-10-03 01:02:47 +0000416 int level = coreObject->isHeading() ? coreObject->headingLevel() : coreObject->hierarchicalLevel();
417 if (level) {
418 String value = String::number(level);
mario@webkit.orgf8344ff2012-01-24 11:40:44 +0000419 attributeSet = addToAtkAttributeSet(attributeSet, "level", value.utf8().data());
eric@webkit.org84496192009-10-17 20:00:33 +0000420 }
commit-queue@webkit.orga9398dd2010-10-26 19:19:29 +0000421
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000422 if (coreObject->roleValue() == AccessibilityRole::MathElement) {
423 if (coreObject->isMathMultiscriptObject(AccessibilityMathMultiscriptObjectType::PreSuperscript) || coreObject->isMathMultiscriptObject(AccessibilityMathMultiscriptObjectType::PreSubscript))
jdiggs@igalia.com6b8c1732015-01-28 17:02:32 +0000424 attributeSet = addToAtkAttributeSet(attributeSet, "multiscript-type", "pre");
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000425 else if (coreObject->isMathMultiscriptObject(AccessibilityMathMultiscriptObjectType::PostSuperscript) || coreObject->isMathMultiscriptObject(AccessibilityMathMultiscriptObjectType::PostSubscript))
jdiggs@igalia.com6b8c1732015-01-28 17:02:32 +0000426 attributeSet = addToAtkAttributeSet(attributeSet, "multiscript-type", "post");
427 }
428
andresg_22@apple.com3374e6d2020-02-24 00:54:42 +0000429 if (is<AccessibilityTable>(*coreObject) && downcast<AccessibilityTable>(*coreObject).isExposable()) {
jdiggs@igalia.com466ea212017-05-01 21:19:09 +0000430 auto& table = downcast<AccessibilityTable>(*coreObject);
n_wang@apple.com70650372017-11-19 06:59:59 +0000431 int rowCount = table.axRowCount();
jdiggs@igalia.com466ea212017-05-01 21:19:09 +0000432 if (rowCount)
433 attributeSet = addToAtkAttributeSet(attributeSet, "rowcount", String::number(rowCount).utf8().data());
434
n_wang@apple.com70650372017-11-19 06:59:59 +0000435 int columnCount = table.axColumnCount();
jdiggs@igalia.com466ea212017-05-01 21:19:09 +0000436 if (columnCount)
437 attributeSet = addToAtkAttributeSet(attributeSet, "colcount", String::number(columnCount).utf8().data());
jdiggs@igalia.com238c5802017-10-04 00:03:12 +0000438 } else if (is<AccessibilityTableRow>(*coreObject)) {
439 auto& row = downcast<AccessibilityTableRow>(*coreObject);
n_wang@apple.com70650372017-11-19 06:59:59 +0000440 int rowIndex = row.axRowIndex();
jdiggs@igalia.com238c5802017-10-04 00:03:12 +0000441 if (rowIndex != -1)
442 attributeSet = addToAtkAttributeSet(attributeSet, "rowindex", String::number(rowIndex).utf8().data());
443 } else if (is<AccessibilityTableCell>(*coreObject)) {
jdiggs@igalia.com466ea212017-05-01 21:19:09 +0000444 auto& cell = downcast<AccessibilityTableCell>(*coreObject);
n_wang@apple.com70650372017-11-19 06:59:59 +0000445 int rowIndex = cell.axRowIndex();
jdiggs@igalia.com466ea212017-05-01 21:19:09 +0000446 if (rowIndex != -1)
447 attributeSet = addToAtkAttributeSet(attributeSet, "rowindex", String::number(rowIndex).utf8().data());
448
n_wang@apple.com70650372017-11-19 06:59:59 +0000449 int columnIndex = cell.axColumnIndex();
jdiggs@igalia.com466ea212017-05-01 21:19:09 +0000450 if (columnIndex != -1)
451 attributeSet = addToAtkAttributeSet(attributeSet, "colindex", String::number(columnIndex).utf8().data());
452
n_wang@apple.com70650372017-11-19 06:59:59 +0000453 int rowSpan = cell.axRowSpan();
jdiggs@igalia.com466ea212017-05-01 21:19:09 +0000454 if (rowSpan != -1)
455 attributeSet = addToAtkAttributeSet(attributeSet, "rowspan", String::number(rowSpan).utf8().data());
456
n_wang@apple.com70650372017-11-19 06:59:59 +0000457 int columnSpan = cell.axColumnSpan();
jdiggs@igalia.com466ea212017-05-01 21:19:09 +0000458 if (columnSpan != -1)
459 attributeSet = addToAtkAttributeSet(attributeSet, "colspan", String::number(columnSpan).utf8().data());
460 }
commit-queue@webkit.orga9398dd2010-10-26 19:19:29 +0000461
commit-queue@webkit.org2db4aaa2012-12-10 01:09:32 +0000462 String placeholder = coreObject->placeholderValue();
463 if (!placeholder.isEmpty())
464 attributeSet = addToAtkAttributeSet(attributeSet, "placeholder-text", placeholder.utf8().data());
465
n_wang@apple.com319609c2017-11-17 02:24:53 +0000466 if (coreObject->supportsAutoComplete())
467 attributeSet = addToAtkAttributeSet(attributeSet, "autocomplete", coreObject->autoCompleteValue().utf8().data());
jdiggs@igalia.com6d1214c2017-04-30 18:12:30 +0000468
n_wang@apple.com319609c2017-11-17 02:24:53 +0000469 if (coreObject->supportsHasPopup())
commit-queue@webkit.org4e345dc2019-07-02 20:24:24 +0000470 attributeSet = addToAtkAttributeSet(attributeSet, "haspopup", coreObject->popupValue().utf8().data());
commit-queue@webkit.org5945f762013-07-16 12:55:56 +0000471
n_wang@apple.com319609c2017-11-17 02:24:53 +0000472 if (coreObject->supportsCurrent())
473 attributeSet = addToAtkAttributeSet(attributeSet, "current", coreObject->currentValue().utf8().data());
jdiggs@igalia.com1975e352017-04-26 23:26:49 +0000474
jdiggs@igalia.com7f1cb422017-10-09 17:12:34 +0000475 // The Core AAM states that an explicitly-set value should be exposed, including "none".
476 if (coreObject->hasAttribute(HTMLNames::aria_sortAttr)) {
477 switch (coreObject->sortDirection()) {
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000478 case AccessibilitySortDirection::Invalid:
jdiggs@igalia.com7f1cb422017-10-09 17:12:34 +0000479 break;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000480 case AccessibilitySortDirection::Ascending:
jdiggs@igalia.com7f1cb422017-10-09 17:12:34 +0000481 attributeSet = addToAtkAttributeSet(attributeSet, "sort", "ascending");
482 break;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000483 case AccessibilitySortDirection::Descending:
jdiggs@igalia.com7f1cb422017-10-09 17:12:34 +0000484 attributeSet = addToAtkAttributeSet(attributeSet, "sort", "descending");
485 break;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000486 case AccessibilitySortDirection::Other:
jdiggs@igalia.com7f1cb422017-10-09 17:12:34 +0000487 attributeSet = addToAtkAttributeSet(attributeSet, "sort", "other");
488 break;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000489 case AccessibilitySortDirection::None:
jdiggs@igalia.com7f1cb422017-10-09 17:12:34 +0000490 attributeSet = addToAtkAttributeSet(attributeSet, "sort", "none");
491 }
mario@webkit.orge2f7e782013-09-18 08:28:59 +0000492 }
commit-queue@webkit.org88d00b62013-09-03 11:29:33 +0000493
n_wang@apple.com70650372017-11-19 06:59:59 +0000494 if (coreObject->supportsPosInSet())
495 attributeSet = addToAtkAttributeSet(attributeSet, "posinset", String::number(coreObject->posInSet()).utf8().data());
k.czech@samsung.comdcc76c72014-03-11 09:04:08 +0000496
n_wang@apple.com70650372017-11-19 06:59:59 +0000497 if (coreObject->supportsSetSize())
498 attributeSet = addToAtkAttributeSet(attributeSet, "setsize", String::number(coreObject->setSize()).utf8().data());
k.czech@samsung.comdcc76c72014-03-11 09:04:08 +0000499
n_wang@apple.comba6eaf42017-11-17 23:14:18 +0000500 String isReadOnly = coreObject->readOnlyValue();
jdiggs@igalia.com23022cc2016-05-11 07:14:31 +0000501 if (!isReadOnly.isEmpty())
502 attributeSet = addToAtkAttributeSet(attributeSet, "readonly", isReadOnly.utf8().data());
503
jdiggs@igalia.com6ccb7782016-05-18 18:57:33 +0000504 String valueDescription = coreObject->valueDescription();
505 if (!valueDescription.isEmpty())
506 attributeSet = addToAtkAttributeSet(attributeSet, "valuetext", valueDescription.utf8().data());
507
jdiggs@igalia.com55b92622015-05-22 06:12:05 +0000508 // According to the W3C Core Accessibility API Mappings 1.1, section 5.4.1 General Rules:
509 // "User agents must expose the WAI-ARIA role string if the API supports a mechanism to do so."
510 // In the case of ATK, the mechanism to do so is an object attribute pair (xml-roles:"string").
jdiggs@igalia.com41069912017-04-20 08:48:53 +0000511 // We cannot use the computedRoleString for this purpose because it is not limited to elements
512 // with ARIA roles, and it might not contain the actual ARIA role value (e.g. DPub ARIA).
513 String roleString = coreObject->getAttribute(HTMLNames::roleAttr);
514 if (!roleString.isEmpty())
515 attributeSet = addToAtkAttributeSet(attributeSet, "xml-roles", roleString.utf8().data());
516
517 String computedRoleString = coreObject->computedRoleString();
518 if (!computedRoleString.isEmpty()) {
519 attributeSet = addToAtkAttributeSet(attributeSet, "computed-role", computedRoleString.utf8().data());
520
521 // The HTML AAM maps several elements to ARIA landmark roles. In order for the type of landmark
522 // to be obtainable in the same fashion as an ARIA landmark, fall back on the computedRoleString.
jdiggs@igalia.com69e004a2019-07-11 13:36:50 +0000523 // We also want to do this for the style-format-group element types so that the type of format
524 // group it is doesn't get lost to a generic platform role.
525 if (coreObject->ariaRoleAttribute() == AccessibilityRole::Unknown
526 && (coreObject->isLandmark() || coreObject->isStyleFormatGroup()))
jdiggs@igalia.com41069912017-04-20 08:48:53 +0000527 attributeSet = addToAtkAttributeSet(attributeSet, "xml-roles", computedRoleString.utf8().data());
mario.prada@samsung.come10ceaa2013-12-11 19:49:39 +0000528 }
529
jdiggs@igalia.com9cef8aa2016-04-29 16:44:30 +0000530 String roleDescription = coreObject->roleDescription();
531 if (!roleDescription.isEmpty())
532 attributeSet = addToAtkAttributeSet(attributeSet, "roledescription", roleDescription.utf8().data());
533
jdiggs@igalia.com3614dca2017-09-24 11:52:36 +0000534 // We need to expose the live region attributes even if the live region is currently disabled/off.
n_wang@apple.com319609c2017-11-17 02:24:53 +0000535 if (auto liveContainer = coreObject->liveRegionAncestor(false)) {
536 String liveStatus = liveContainer->liveRegionStatus();
537 String relevant = liveContainer->liveRegionRelevant();
darin@apple.com0ce67df2019-06-17 01:48:13 +0000538 bool isAtom = liveContainer->liveRegionAtomic();
jdiggs@igalia.com3614dca2017-09-24 11:52:36 +0000539 String liveRole = roleString.isEmpty() ? computedRoleString : roleString;
540
541 // According to the Core AAM, we need to expose the above properties with "container-" prefixed
542 // object attributes regardless of whether the container is this object, or an ancestor of it.
543 attributeSet = addToAtkAttributeSet(attributeSet, "container-live", liveStatus.utf8().data());
544 attributeSet = addToAtkAttributeSet(attributeSet, "container-relevant", relevant.utf8().data());
darin@apple.com0ce67df2019-06-17 01:48:13 +0000545 if (isAtom)
jdiggs@igalia.com3614dca2017-09-24 11:52:36 +0000546 attributeSet = addToAtkAttributeSet(attributeSet, "container-atomic", "true");
547 if (!liveRole.isEmpty())
548 attributeSet = addToAtkAttributeSet(attributeSet, "container-live-role", liveRole.utf8().data());
549
550 // According to the Core AAM, if this object is the live region (rather than its descendant),
551 // we must expose the above properties on the object without a "container-" prefix.
552 if (liveContainer == coreObject) {
553 attributeSet = addToAtkAttributeSet(attributeSet, "live", liveStatus.utf8().data());
554 attributeSet = addToAtkAttributeSet(attributeSet, "relevant", relevant.utf8().data());
darin@apple.com0ce67df2019-06-17 01:48:13 +0000555 if (isAtom)
jdiggs@igalia.com3614dca2017-09-24 11:52:36 +0000556 attributeSet = addToAtkAttributeSet(attributeSet, "atomic", "true");
darin@apple.com0ce67df2019-06-17 01:48:13 +0000557 } else if (!isAtom && coreObject->liveRegionAtomic())
jdiggs@igalia.com3614dca2017-09-24 11:52:36 +0000558 attributeSet = addToAtkAttributeSet(attributeSet, "atomic", "true");
559 }
560
jdiggs@igalia.com4ae31f42017-10-03 17:56:50 +0000561 // The Core AAM states the author-provided value should be exposed as-is.
562 String dropEffect = coreObject->getAttribute(HTMLNames::aria_dropeffectAttr);
563 if (!dropEffect.isEmpty())
564 attributeSet = addToAtkAttributeSet(attributeSet, "dropeffect", dropEffect.utf8().data());
565
566 if (coreObject->isARIAGrabbed())
567 attributeSet = addToAtkAttributeSet(attributeSet, "grabbed", "true");
568 else if (coreObject->supportsARIADragging())
569 attributeSet = addToAtkAttributeSet(attributeSet, "grabbed", "false");
570
jdiggs@igalia.com861dc182017-10-11 17:04:42 +0000571 // The Core AAM states the author-provided value should be exposed as-is.
darin@apple.com0ce67df2019-06-17 01:48:13 +0000572 const AtomString& keyShortcuts = coreObject->keyShortcutsValue();
jdiggs@igalia.com861dc182017-10-11 17:04:42 +0000573 if (!keyShortcuts.isEmpty())
574 attributeSet = addToAtkAttributeSet(attributeSet, "keyshortcuts", keyShortcuts.string().utf8().data());
575
eric@webkit.org84496192009-10-17 20:00:33 +0000576 return attributeSet;
577}
578
mario.prada@samsung.com4fb934b2013-12-17 18:08:34 +0000579static AtkRole atkRole(AccessibilityObject* coreObject)
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +0000580{
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000581 switch (coreObject->roleValue()) {
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000582 case AccessibilityRole::ApplicationAlert:
commit-queue@webkit.orgb68dfdf2013-12-06 13:58:38 +0000583 return ATK_ROLE_ALERT;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000584 case AccessibilityRole::ApplicationAlertDialog:
585 case AccessibilityRole::ApplicationDialog:
commit-queue@webkit.orgb68dfdf2013-12-06 13:58:38 +0000586 return ATK_ROLE_DIALOG;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000587 case AccessibilityRole::ApplicationStatus:
commit-queue@webkit.orgb68dfdf2013-12-06 13:58:38 +0000588 return ATK_ROLE_STATUSBAR;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000589 case AccessibilityRole::Unknown:
xan@webkit.org0ea2f732009-04-27 21:56:05 +0000590 return ATK_ROLE_UNKNOWN;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000591 case AccessibilityRole::Audio:
jdiggs@igalia.comc7a2f562014-11-16 07:32:08 +0000592 return ATK_ROLE_AUDIO;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000593 case AccessibilityRole::Video:
jdiggs@igalia.comc7a2f562014-11-16 07:32:08 +0000594 return ATK_ROLE_VIDEO;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000595 case AccessibilityRole::Button:
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +0000596 return ATK_ROLE_PUSH_BUTTON;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000597 case AccessibilityRole::Switch:
598 case AccessibilityRole::ToggleButton:
commit-queue@webkit.org6152cb92012-08-23 00:36:06 +0000599 return ATK_ROLE_TOGGLE_BUTTON;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000600 case AccessibilityRole::RadioButton:
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +0000601 return ATK_ROLE_RADIO_BUTTON;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000602 case AccessibilityRole::CheckBox:
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +0000603 return ATK_ROLE_CHECK_BOX;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000604 case AccessibilityRole::Slider:
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +0000605 return ATK_ROLE_SLIDER;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000606 case AccessibilityRole::TabGroup:
607 case AccessibilityRole::TabList:
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +0000608 return ATK_ROLE_PAGE_TAB_LIST;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000609 case AccessibilityRole::TextField:
610 case AccessibilityRole::TextArea:
611 case AccessibilityRole::SearchField:
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +0000612 return ATK_ROLE_ENTRY;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000613 case AccessibilityRole::StaticText:
jdiggs@igalia.com12f11cb2016-04-29 13:08:03 +0000614 return ATK_ROLE_STATIC;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000615 case AccessibilityRole::Outline:
616 case AccessibilityRole::Tree:
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +0000617 return ATK_ROLE_TREE;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000618 case AccessibilityRole::TreeItem:
commit-queue@webkit.orgb68dfdf2013-12-06 13:58:38 +0000619 return ATK_ROLE_TREE_ITEM;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000620 case AccessibilityRole::MenuBar:
xan@webkit.org0ea2f732009-04-27 21:56:05 +0000621 return ATK_ROLE_MENU_BAR;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000622 case AccessibilityRole::MenuListPopup:
623 case AccessibilityRole::Menu:
xan@webkit.org0ea2f732009-04-27 21:56:05 +0000624 return ATK_ROLE_MENU;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000625 case AccessibilityRole::MenuListOption:
626 case AccessibilityRole::MenuItem:
627 case AccessibilityRole::MenuButton:
xan@webkit.org0ea2f732009-04-27 21:56:05 +0000628 return ATK_ROLE_MENU_ITEM;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000629 case AccessibilityRole::MenuItemCheckbox:
mario.prada@samsung.com092b72a2013-12-16 15:58:34 +0000630 return ATK_ROLE_CHECK_MENU_ITEM;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000631 case AccessibilityRole::MenuItemRadio:
commit-queue@webkit.org413f75b2013-09-11 11:31:14 +0000632 return ATK_ROLE_RADIO_MENU_ITEM;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000633 case AccessibilityRole::Column:
mario@webkit.org9adab662012-01-23 10:21:03 +0000634 // return ATK_ROLE_TABLE_COLUMN_HEADER; // Is this right?
xan@webkit.org0ea2f732009-04-27 21:56:05 +0000635 return ATK_ROLE_UNKNOWN; // Matches Mozilla
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000636 case AccessibilityRole::Row:
jdiggs@igalia.come8a090d2014-12-03 02:02:36 +0000637 return ATK_ROLE_TABLE_ROW;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000638 case AccessibilityRole::Toolbar:
xan@webkit.org0ea2f732009-04-27 21:56:05 +0000639 return ATK_ROLE_TOOL_BAR;
jdiggs@igalia.com959318d2019-03-20 13:09:02 +0000640 case AccessibilityRole::Meter:
641 return ATK_ROLE_LEVEL_BAR;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000642 case AccessibilityRole::BusyIndicator:
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000643 case AccessibilityRole::ProgressIndicator:
jdiggs@igalia.com959318d2019-03-20 13:09:02 +0000644 return ATK_ROLE_PROGRESS_BAR;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000645 case AccessibilityRole::Window:
xan@webkit.org0ea2f732009-04-27 21:56:05 +0000646 return ATK_ROLE_WINDOW;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000647 case AccessibilityRole::PopUpButton:
n_wang@apple.com319609c2017-11-17 02:24:53 +0000648 return coreObject->hasPopup() ? ATK_ROLE_PUSH_BUTTON : ATK_ROLE_COMBO_BOX;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000649 case AccessibilityRole::ComboBox:
xan@webkit.org0ea2f732009-04-27 21:56:05 +0000650 return ATK_ROLE_COMBO_BOX;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000651 case AccessibilityRole::SplitGroup:
xan@webkit.org0ea2f732009-04-27 21:56:05 +0000652 return ATK_ROLE_SPLIT_PANE;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000653 case AccessibilityRole::Splitter:
mario.prada@samsung.comae97a652013-12-10 20:12:56 +0000654 return ATK_ROLE_SEPARATOR;
jdiggs@igalia.comfeb6f002015-02-24 17:20:01 +0000655#if PLATFORM(GTK)
mcatanzaro@igalia.come0f103e2019-06-21 14:20:00 +0000656 case AccessibilityRole::ColorWell:
jdiggs@igalia.comfeb6f002015-02-24 17:20:01 +0000657 // ATK_ROLE_COLOR_CHOOSER is defined as a dialog (i.e. it's what appears when you push the button).
658 return ATK_ROLE_PUSH_BUTTON;
jdiggs@igalia.comfeb6f002015-02-24 17:20:01 +0000659#endif
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000660 case AccessibilityRole::List:
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +0000661 return ATK_ROLE_LIST;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000662 case AccessibilityRole::ScrollBar:
xan@webkit.org0ea2f732009-04-27 21:56:05 +0000663 return ATK_ROLE_SCROLL_BAR;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000664 case AccessibilityRole::ScrollArea:
665 case AccessibilityRole::TabPanel:
mario@webkit.org86390a12011-01-07 17:34:02 +0000666 return ATK_ROLE_SCROLL_PANE;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000667 case AccessibilityRole::Grid:
668 case AccessibilityRole::Table:
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +0000669 return ATK_ROLE_TABLE;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000670 case AccessibilityRole::TreeGrid:
jdiggs@igalia.com8c934782017-04-30 18:11:56 +0000671 return ATK_ROLE_TREE_TABLE;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000672 case AccessibilityRole::Application:
xan@webkit.org0ea2f732009-04-27 21:56:05 +0000673 return ATK_ROLE_APPLICATION;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000674 case AccessibilityRole::ApplicationGroup:
675 case AccessibilityRole::Feed:
676 case AccessibilityRole::Figure:
jdiggs@igalia.com3e7e23a2018-01-22 19:16:52 +0000677 case AccessibilityRole::GraphicsObject:
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000678 case AccessibilityRole::Group:
679 case AccessibilityRole::RadioGroup:
680 case AccessibilityRole::SVGRoot:
xan@webkit.org0ea2f732009-04-27 21:56:05 +0000681 return ATK_ROLE_PANEL;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000682 case AccessibilityRole::RowHeader:
commit-queue@webkit.orgc150a072014-10-10 08:32:58 +0000683 return ATK_ROLE_ROW_HEADER;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000684 case AccessibilityRole::ColumnHeader:
commit-queue@webkit.orgc150a072014-10-10 08:32:58 +0000685 return ATK_ROLE_COLUMN_HEADER;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000686 case AccessibilityRole::Caption:
jdiggs@igalia.come8a090d2014-12-03 02:02:36 +0000687 return ATK_ROLE_CAPTION;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000688 case AccessibilityRole::Cell:
689 case AccessibilityRole::GridCell:
jdiggs@igalia.com63bfc542014-06-05 23:53:17 +0000690 return coreObject->inheritsPresentationalRole() ? ATK_ROLE_SECTION : ATK_ROLE_TABLE_CELL;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000691 case AccessibilityRole::Link:
692 case AccessibilityRole::WebCoreLink:
693 case AccessibilityRole::ImageMapLink:
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +0000694 return ATK_ROLE_LINK;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000695 case AccessibilityRole::ImageMap:
jdiggs@igalia.com51d2ebf2014-11-22 18:18:11 +0000696 return ATK_ROLE_IMAGE_MAP;
jdiggs@igalia.com3e7e23a2018-01-22 19:16:52 +0000697 case AccessibilityRole::GraphicsSymbol:
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000698 case AccessibilityRole::Image:
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +0000699 return ATK_ROLE_IMAGE;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000700 case AccessibilityRole::ListMarker:
jmalonzo@webkit.orgad9783b2009-05-23 22:22:52 +0000701 return ATK_ROLE_TEXT;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000702 case AccessibilityRole::DocumentArticle:
mario.prada@samsung.com2a1d5622013-12-16 15:17:58 +0000703 return ATK_ROLE_ARTICLE;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000704 case AccessibilityRole::Document:
jdiggs@igalia.com3e7e23a2018-01-22 19:16:52 +0000705 case AccessibilityRole::GraphicsDocument:
xan@webkit.org0ea2f732009-04-27 21:56:05 +0000706 return ATK_ROLE_DOCUMENT_FRAME;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000707 case AccessibilityRole::DocumentNote:
mario.prada@samsung.comc4a5eca2013-12-16 16:18:30 +0000708 return ATK_ROLE_COMMENT;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000709 case AccessibilityRole::Heading:
xan@webkit.org0ea2f732009-04-27 21:56:05 +0000710 return ATK_ROLE_HEADING;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000711 case AccessibilityRole::ListBox:
jdiggs@igalia.comb0b62552016-11-19 21:12:24 +0000712 // https://rawgit.com/w3c/aria/master/core-aam/core-aam.html#role-map-listbox
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000713 return coreObject->isDescendantOfRole(AccessibilityRole::ComboBox) ? ATK_ROLE_MENU : ATK_ROLE_LIST_BOX;
714 case AccessibilityRole::ListItem:
jdiggs@igalia.com63bfc542014-06-05 23:53:17 +0000715 return coreObject->inheritsPresentationalRole() ? ATK_ROLE_SECTION : ATK_ROLE_LIST_ITEM;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000716 case AccessibilityRole::ListBoxOption:
717 return coreObject->isDescendantOfRole(AccessibilityRole::ComboBox) ? ATK_ROLE_MENU_ITEM : ATK_ROLE_LIST_ITEM;
718 case AccessibilityRole::Paragraph:
mario@webkit.org56f6bf22011-03-30 16:51:08 +0000719 return ATK_ROLE_PARAGRAPH;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000720 case AccessibilityRole::Label:
721 case AccessibilityRole::Legend:
mario@webkit.org56f6bf22011-03-30 16:51:08 +0000722 return ATK_ROLE_LABEL;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000723 case AccessibilityRole::Blockquote:
jdiggs@igalia.comabd4d5f2014-11-16 16:51:08 +0000724 return ATK_ROLE_BLOCK_QUOTE;
jdiggs@igalia.com8920b742017-05-25 16:43:23 +0000725#if ATK_CHECK_VERSION(2, 25, 2)
mcatanzaro@igalia.come0f103e2019-06-21 14:20:00 +0000726 case AccessibilityRole::Footnote:
jdiggs@igalia.com8920b742017-05-25 16:43:23 +0000727 return ATK_ROLE_FOOTNOTE;
728#endif
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000729 case AccessibilityRole::ApplicationTextGroup:
730 case AccessibilityRole::Div:
731 case AccessibilityRole::Pre:
732 case AccessibilityRole::SVGText:
733 case AccessibilityRole::TextGroup:
mario@webkit.org56f6bf22011-03-30 16:51:08 +0000734 return ATK_ROLE_SECTION;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000735 case AccessibilityRole::Footer:
jdiggs@igalia.com45e97142014-11-16 07:26:41 +0000736 return ATK_ROLE_FOOTER;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000737 case AccessibilityRole::Form:
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000738 if (coreObject->ariaRoleAttribute() != AccessibilityRole::Unknown)
jdiggs@igalia.com9b67c3b2017-10-10 21:29:24 +0000739 return ATK_ROLE_LANDMARK;
mario@webkit.org56f6bf22011-03-30 16:51:08 +0000740 return ATK_ROLE_FORM;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000741 case AccessibilityRole::Canvas:
commit-queue@webkit.org52f67612012-09-07 05:09:04 +0000742 return ATK_ROLE_CANVAS;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000743 case AccessibilityRole::HorizontalRule:
dmazzoni@google.comf3cf2c42012-09-07 23:46:45 +0000744 return ATK_ROLE_SEPARATOR;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000745 case AccessibilityRole::SpinButton:
commit-queue@webkit.orgc985400e2012-09-21 20:03:57 +0000746 return ATK_ROLE_SPIN_BUTTON;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000747 case AccessibilityRole::Tab:
commit-queue@webkit.org52553892012-12-13 15:43:38 +0000748 return ATK_ROLE_PAGE_TAB;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000749 case AccessibilityRole::UserInterfaceTooltip:
commit-queue@webkit.orgb68dfdf2013-12-06 13:58:38 +0000750 return ATK_ROLE_TOOL_TIP;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000751 case AccessibilityRole::WebArea:
commit-queue@webkit.orgb68dfdf2013-12-06 13:58:38 +0000752 return ATK_ROLE_DOCUMENT_WEB;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000753 case AccessibilityRole::WebApplication:
mario.prada@samsung.come10ceaa2013-12-11 19:49:39 +0000754 return ATK_ROLE_EMBEDDED;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000755 case AccessibilityRole::ApplicationLog:
mario.prada@samsung.comc4a5eca2013-12-16 16:18:30 +0000756 return ATK_ROLE_LOG;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000757 case AccessibilityRole::ApplicationMarquee:
mario.prada@samsung.comc4a5eca2013-12-16 16:18:30 +0000758 return ATK_ROLE_MARQUEE;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000759 case AccessibilityRole::ApplicationTimer:
mario.prada@samsung.comc4a5eca2013-12-16 16:18:30 +0000760 return ATK_ROLE_TIMER;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000761 case AccessibilityRole::Definition:
mario.prada@samsung.comc4a5eca2013-12-16 16:18:30 +0000762 return ATK_ROLE_DEFINITION;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000763 case AccessibilityRole::DocumentMath:
mario.prada@samsung.comc4a5eca2013-12-16 16:18:30 +0000764 return ATK_ROLE_MATH;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000765 case AccessibilityRole::MathElement:
jdiggs@igalia.com0f83ca32014-12-09 18:31:53 +0000766 if (coreObject->isMathRow())
767 return ATK_ROLE_PANEL;
768 if (coreObject->isMathTable())
769 return ATK_ROLE_TABLE;
770 if (coreObject->isMathTableRow())
771 return ATK_ROLE_TABLE_ROW;
772 if (coreObject->isMathTableCell())
773 return ATK_ROLE_TABLE_CELL;
jdiggs@igalia.com6b8c1732015-01-28 17:02:32 +0000774 if (coreObject->isMathSubscriptSuperscript() || coreObject->isMathMultiscript())
775 return ATK_ROLE_SECTION;
jdiggs@igalia.com6b8c1732015-01-28 17:02:32 +0000776 if (coreObject->isMathFraction())
777 return ATK_ROLE_MATH_FRACTION;
778 if (coreObject->isMathSquareRoot() || coreObject->isMathRoot())
779 return ATK_ROLE_MATH_ROOT;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000780 if (coreObject->isMathScriptObject(AccessibilityMathScriptObjectType::Subscript)
781 || coreObject->isMathMultiscriptObject(AccessibilityMathMultiscriptObjectType::PreSubscript) || coreObject->isMathMultiscriptObject(AccessibilityMathMultiscriptObjectType::PostSubscript))
jdiggs@igalia.com6b8c1732015-01-28 17:02:32 +0000782 return ATK_ROLE_SUBSCRIPT;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000783 if (coreObject->isMathScriptObject(AccessibilityMathScriptObjectType::Superscript)
784 || coreObject->isMathMultiscriptObject(AccessibilityMathMultiscriptObjectType::PreSuperscript) || coreObject->isMathMultiscriptObject(AccessibilityMathMultiscriptObjectType::PostSuperscript))
jdiggs@igalia.com6b8c1732015-01-28 17:02:32 +0000785 return ATK_ROLE_SUPERSCRIPT;
jdiggs@igalia.com0f83ca32014-12-09 18:31:53 +0000786 if (coreObject->isMathToken())
787 return ATK_ROLE_STATIC;
jdiggs@igalia.com0f83ca32014-12-09 18:31:53 +0000788 return ATK_ROLE_UNKNOWN;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000789 case AccessibilityRole::LandmarkBanner:
790 case AccessibilityRole::LandmarkComplementary:
791 case AccessibilityRole::LandmarkContentInfo:
792 case AccessibilityRole::LandmarkDocRegion:
793 case AccessibilityRole::LandmarkMain:
794 case AccessibilityRole::LandmarkNavigation:
795 case AccessibilityRole::LandmarkRegion:
796 case AccessibilityRole::LandmarkSearch:
mario.prada@samsung.come10ceaa2013-12-11 19:49:39 +0000797 return ATK_ROLE_LANDMARK;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000798 case AccessibilityRole::DescriptionList:
mario.prada@samsung.com4fb934b2013-12-17 18:08:34 +0000799 return ATK_ROLE_DESCRIPTION_LIST;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000800 case AccessibilityRole::Term:
801 case AccessibilityRole::DescriptionListTerm:
mario.prada@samsung.com4fb934b2013-12-17 18:08:34 +0000802 return ATK_ROLE_DESCRIPTION_TERM;
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000803 case AccessibilityRole::DescriptionListDetail:
mario.prada@samsung.com4fb934b2013-12-17 18:08:34 +0000804 return ATK_ROLE_DESCRIPTION_VALUE;
jdiggs@igalia.com69e004a2019-07-11 13:36:50 +0000805 case AccessibilityRole::Deletion:
806#if ATK_CHECK_VERSION(2, 33, 3)
807 return ATK_ROLE_CONTENT_DELETION;
808#else
jdiggs@igalia.com0ec0d332016-04-29 01:30:34 +0000809 return ATK_ROLE_STATIC;
jdiggs@igalia.com69e004a2019-07-11 13:36:50 +0000810#endif
811 case AccessibilityRole::Insertion:
812#if ATK_CHECK_VERSION(2, 33, 3)
813 return ATK_ROLE_CONTENT_INSERTION;
814#else
815 return ATK_ROLE_STATIC;
816#endif
817 case AccessibilityRole::Subscript:
818 return ATK_ROLE_SUBSCRIPT;
819 case AccessibilityRole::Superscript:
820 return ATK_ROLE_SUPERSCRIPT;
821 case AccessibilityRole::Inline:
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000822 case AccessibilityRole::SVGTextPath:
823 case AccessibilityRole::SVGTSpan:
824 case AccessibilityRole::Time:
jdiggs@igalia.com85721d12014-12-03 19:51:28 +0000825 return ATK_ROLE_STATIC;
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +0000826 default:
827 return ATK_ROLE_UNKNOWN;
828 }
829}
830
mario@webkit.org5c966772012-01-24 18:48:50 +0000831static AtkRole webkitAccessibleGetRole(AtkObject* object)
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +0000832{
jdiggs@igalia.com00e44c42014-11-13 22:11:41 +0000833 // ATK_ROLE_UNKNOWN should only be applied in cases where there is a valid
834 // WebCore accessible object for which the platform role mapping is unknown.
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000835 auto* accessible = WEBKIT_ACCESSIBLE(object);
836 returnValIfWebKitAccessibleIsInvalid(accessible, ATK_ROLE_INVALID);
jmalonzo@webkit.org7ce37142009-05-20 11:16:01 +0000837
838 // Note: Why doesn't WebCore have a password field for this
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000839 if (accessible->priv->object->isPasswordField())
jmalonzo@webkit.org7ce37142009-05-20 11:16:01 +0000840 return ATK_ROLE_PASSWORD_TEXT;
841
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +0000842 return atkRole(accessible->priv->object);
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +0000843}
844
mario@webkit.org6a24ba12010-12-14 15:35:22 +0000845static bool isTextWithCaret(AccessibilityObject* coreObject)
846{
847 if (!coreObject || !coreObject->isAccessibilityRenderObject())
848 return false;
849
850 Document* document = coreObject->document();
851 if (!document)
852 return false;
853
854 Frame* frame = document->frame();
855 if (!frame)
856 return false;
857
akling@apple.com17523502013-08-17 10:58:40 +0000858 if (!frame->settings().caretBrowsingEnabled())
mario@webkit.org6a24ba12010-12-14 15:35:22 +0000859 return false;
860
861 // Check text objects and paragraphs only.
carlosgc@webkit.org9d3f9a42019-04-05 07:35:24 +0000862 auto* axObject = coreObject->wrapper();
863 AtkRole role = axObject ? atk_object_get_role(ATK_OBJECT(axObject)) : ATK_ROLE_INVALID;
mario@webkit.org6a24ba12010-12-14 15:35:22 +0000864 if (role != ATK_ROLE_TEXT && role != ATK_ROLE_PARAGRAPH)
865 return false;
866
867 // Finally, check whether the caret is set in the current object.
868 VisibleSelection selection = coreObject->selection();
869 if (!selection.isCaret())
870 return false;
871
872 return selectionBelongsToObject(coreObject, selection);
873}
874
xan@webkit.org8be15d62009-04-09 11:20:57 +0000875static void setAtkStateSetFromCoreObject(AccessibilityObject* coreObject, AtkStateSet* stateSet)
876{
eric@webkit.org2dd47342009-10-26 11:42:42 +0000877 AccessibilityObject* parent = coreObject->parentObject();
878 bool isListBoxOption = parent && parent->isListBox();
xan@webkit.org8be15d62009-04-09 11:20:57 +0000879
eric@webkit.org2dd47342009-10-26 11:42:42 +0000880 // Please keep the state list in alphabetical order
jdiggs@igalia.com1975e352017-04-26 23:26:49 +0000881 if ((isListBoxOption && coreObject->isSelectedOptionActive())
n_wang@apple.com319609c2017-11-17 02:24:53 +0000882 || coreObject->currentState() != AccessibilityCurrentState::False)
commit-queue@webkit.orgc4299262013-12-02 10:40:07 +0000883 atk_state_set_add_state(stateSet, ATK_STATE_ACTIVE);
884
jdiggs@igalia.com77cdc2a2016-11-19 08:08:03 +0000885 if (coreObject->isBusy())
886 atk_state_set_add_state(stateSet, ATK_STATE_BUSY);
887
jdiggs@igalia.com23022cc2016-05-11 07:14:31 +0000888 if (coreObject->supportsChecked() && coreObject->canSetValueAttribute())
889 atk_state_set_add_state(stateSet, ATK_STATE_CHECKABLE);
jdiggs@igalia.com23022cc2016-05-11 07:14:31 +0000890
xan@webkit.org8be15d62009-04-09 11:20:57 +0000891 if (coreObject->isChecked())
892 atk_state_set_add_state(stateSet, ATK_STATE_CHECKED);
893
jdiggs@igalia.com23022cc2016-05-11 07:14:31 +0000894 if ((coreObject->isTextControl() || coreObject->isNonNativeTextControl()) && coreObject->canSetValueAttribute())
xan@webkit.org8be15d62009-04-09 11:20:57 +0000895 atk_state_set_add_state(stateSet, ATK_STATE_EDITABLE);
896
xan@webkit.orgdf7d13a2009-06-26 09:12:44 +0000897 // FIXME: Put both ENABLED and SENSITIVE together here for now
898 if (coreObject->isEnabled()) {
xan@webkit.org8be15d62009-04-09 11:20:57 +0000899 atk_state_set_add_state(stateSet, ATK_STATE_ENABLED);
xan@webkit.orgdf7d13a2009-06-26 09:12:44 +0000900 atk_state_set_add_state(stateSet, ATK_STATE_SENSITIVE);
901 }
xan@webkit.org8be15d62009-04-09 11:20:57 +0000902
mario@webkit.org8ce6a152010-11-30 21:16:14 +0000903 if (coreObject->canSetExpandedAttribute())
904 atk_state_set_add_state(stateSet, ATK_STATE_EXPANDABLE);
905
906 if (coreObject->isExpanded())
907 atk_state_set_add_state(stateSet, ATK_STATE_EXPANDED);
908
xan@webkit.org8be15d62009-04-09 11:20:57 +0000909 if (coreObject->canSetFocusAttribute())
910 atk_state_set_add_state(stateSet, ATK_STATE_FOCUSABLE);
911
jdiggs@igalia.com0a5cab12017-10-20 16:30:20 +0000912 // According to the Core AAM, if the element which is focused has a valid aria-activedescendant,
913 // we should not expose the focused state on the element which is actually focused, but instead
914 // on its active descendant.
915 if ((coreObject->isFocused() && !coreObject->activeDescendant()) || isTextWithCaret(coreObject))
xan@webkit.org8be15d62009-04-09 11:20:57 +0000916 atk_state_set_add_state(stateSet, ATK_STATE_FOCUSED);
jdiggs@igalia.com0a5cab12017-10-20 16:30:20 +0000917 else if (coreObject->isActiveDescendantOfFocusedContainer()) {
918 atk_state_set_add_state(stateSet, ATK_STATE_FOCUSABLE);
919 atk_state_set_add_state(stateSet, ATK_STATE_FOCUSED);
920 }
xan@webkit.org8be15d62009-04-09 11:20:57 +0000921
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000922 if (coreObject->orientation() == AccessibilityOrientation::Horizontal)
commit-queue@webkit.org471dff52013-03-20 08:12:15 +0000923 atk_state_set_add_state(stateSet, ATK_STATE_HORIZONTAL);
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000924 else if (coreObject->orientation() == AccessibilityOrientation::Vertical)
commit-queue@webkit.org471dff52013-03-20 08:12:15 +0000925 atk_state_set_add_state(stateSet, ATK_STATE_VERTICAL);
xan@webkit.org8be15d62009-04-09 11:20:57 +0000926
n_wang@apple.com319609c2017-11-17 02:24:53 +0000927 if (coreObject->hasPopup())
jdiggs@igalia.com47c0ab012017-04-26 19:30:08 +0000928 atk_state_set_add_state(stateSet, ATK_STATE_HAS_POPUP);
929
xan@webkit.org8be15d62009-04-09 11:20:57 +0000930 if (coreObject->isIndeterminate())
931 atk_state_set_add_state(stateSet, ATK_STATE_INDETERMINATE);
jdiggs@igalia.com06ff93c2017-10-04 07:33:08 +0000932 else if (coreObject->isCheckboxOrRadio() || coreObject->isMenuItem() || coreObject->isToggleButton()) {
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000933 if (coreObject->checkboxOrRadioValue() == AccessibilityButtonState::Mixed)
k.czech@samsung.com43a89312014-01-07 11:28:04 +0000934 atk_state_set_add_state(stateSet, ATK_STATE_INDETERMINATE);
935 }
936
n_wang@apple.comba6eaf42017-11-17 23:14:18 +0000937 if (coreObject->isModalNode())
jdiggs@igalia.com96ae08c2017-04-28 18:17:26 +0000938 atk_state_set_add_state(stateSet, ATK_STATE_MODAL);
939
mario@webkit.orge0f00f12013-10-08 10:55:25 +0000940 if (coreObject->invalidStatus() != "false")
941 atk_state_set_add_state(stateSet, ATK_STATE_INVALID_ENTRY);
942
jhoneycutt@apple.com8acea082010-01-14 01:16:15 +0000943 if (coreObject->isMultiSelectable())
xan@webkit.org8be15d62009-04-09 11:20:57 +0000944 atk_state_set_add_state(stateSet, ATK_STATE_MULTISELECTABLE);
945
946 // TODO: ATK_STATE_OPAQUE
947
948 if (coreObject->isPressed())
949 atk_state_set_add_state(stateSet, ATK_STATE_PRESSED);
950
n_wang@apple.comba6eaf42017-11-17 23:14:18 +0000951 if (!coreObject->canSetValueAttribute() && (coreObject->supportsReadOnly()))
jdiggs@igalia.com23022cc2016-05-11 07:14:31 +0000952 atk_state_set_add_state(stateSet, ATK_STATE_READ_ONLY);
jdiggs@igalia.com23022cc2016-05-11 07:14:31 +0000953
commit-queue@webkit.org60f8d312013-06-21 10:33:34 +0000954 if (coreObject->isRequired())
955 atk_state_set_add_state(stateSet, ATK_STATE_REQUIRED);
956
xan@webkit.org8be15d62009-04-09 11:20:57 +0000957 // TODO: ATK_STATE_SELECTABLE_TEXT
958
eric@webkit.org2dd47342009-10-26 11:42:42 +0000959 if (coreObject->canSetSelectedAttribute()) {
960 atk_state_set_add_state(stateSet, ATK_STATE_SELECTABLE);
mario@webkit.org8c5dd902012-11-09 19:47:40 +0000961 // Items in focusable lists have both STATE_SELECT{ABLE,ED}
962 // and STATE_FOCUS{ABLE,ED}. We'll fake the latter based on
963 // the former.
eric@webkit.org2dd47342009-10-26 11:42:42 +0000964 if (isListBoxOption)
965 atk_state_set_add_state(stateSet, ATK_STATE_FOCUSABLE);
966 }
967
968 if (coreObject->isSelected()) {
xan@webkit.org8be15d62009-04-09 11:20:57 +0000969 atk_state_set_add_state(stateSet, ATK_STATE_SELECTED);
mario@webkit.org8c5dd902012-11-09 19:47:40 +0000970 // Items in focusable lists have both STATE_SELECT{ABLE,ED}
eric@webkit.org2dd47342009-10-26 11:42:42 +0000971 // and STATE_FOCUS{ABLE,ED}. We'll fake the latter based on the
972 // former.
973 if (isListBoxOption)
974 atk_state_set_add_state(stateSet, ATK_STATE_FOCUSED);
975 }
xan@webkit.org8be15d62009-04-09 11:20:57 +0000976
xan@webkit.orgdf7d13a2009-06-26 09:12:44 +0000977 // FIXME: Group both SHOWING and VISIBLE here for now
978 // Not sure how to handle this in WebKit, see bug
979 // http://bugzilla.gnome.org/show_bug.cgi?id=509650 for other
mario@webkit.org8c5dd902012-11-09 19:47:40 +0000980 // issues with SHOWING vs VISIBLE.
xan@webkit.orgdf7d13a2009-06-26 09:12:44 +0000981 if (!coreObject->isOffScreen()) {
xan@webkit.org8be15d62009-04-09 11:20:57 +0000982 atk_state_set_add_state(stateSet, ATK_STATE_SHOWING);
xan@webkit.orgdf7d13a2009-06-26 09:12:44 +0000983 atk_state_set_add_state(stateSet, ATK_STATE_VISIBLE);
984 }
xan@webkit.org8be15d62009-04-09 11:20:57 +0000985
986 // Mutually exclusive, so we group these two
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000987 if (coreObject->roleValue() == AccessibilityRole::TextArea || coreObject->ariaIsMultiline())
xan@webkit.org8be15d62009-04-09 11:20:57 +0000988 atk_state_set_add_state(stateSet, ATK_STATE_MULTI_LINE);
achristensen@apple.comf80908b2017-10-27 00:37:06 +0000989 else if (coreObject->roleValue() == AccessibilityRole::TextField || coreObject->roleValue() == AccessibilityRole::SearchField)
jdiggs@igalia.com18b89b82016-11-14 17:39:10 +0000990 atk_state_set_add_state(stateSet, ATK_STATE_SINGLE_LINE);
xan@webkit.org8be15d62009-04-09 11:20:57 +0000991
992 // TODO: ATK_STATE_SENSITIVE
993
n_wang@apple.com319609c2017-11-17 02:24:53 +0000994 if (coreObject->supportsAutoComplete() && coreObject->autoCompleteValue() != "none")
jdiggs@igalia.com6d1214c2017-04-30 18:12:30 +0000995 atk_state_set_add_state(stateSet, ATK_STATE_SUPPORTS_AUTOCOMPLETION);
996
xan@webkit.org8be15d62009-04-09 11:20:57 +0000997 if (coreObject->isVisited())
998 atk_state_set_add_state(stateSet, ATK_STATE_VISITED);
999}
1000
mario@webkit.org5c966772012-01-24 18:48:50 +00001001static AtkStateSet* webkitAccessibleRefStateSet(AtkObject* object)
xan@webkit.org8be15d62009-04-09 11:20:57 +00001002{
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001003 auto* accessible = WEBKIT_ACCESSIBLE(object);
1004 AtkStateSet* stateSet = ATK_OBJECT_CLASS(webkit_accessible_parent_class)->ref_state_set(object);
xan@webkit.org8be15d62009-04-09 11:20:57 +00001005
mario@webkit.orgff8cf0f2013-09-27 09:44:20 +00001006 // Make sure the layout is updated to really know whether the object
1007 // is defunct or not, so we can return the proper state.
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001008 accessible->priv->object->updateBackingStore();
mario@webkit.orgff8cf0f2013-09-27 09:44:20 +00001009
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001010 if (accessible->priv->object == fallbackObject()) {
xan@webkit.org8be15d62009-04-09 11:20:57 +00001011 atk_state_set_add_state(stateSet, ATK_STATE_DEFUNCT);
1012 return stateSet;
1013 }
1014
mario@webkit.org6a24ba12010-12-14 15:35:22 +00001015 // Text objects must be focusable.
1016 AtkRole role = atk_object_get_role(object);
1017 if (role == ATK_ROLE_TEXT || role == ATK_ROLE_PARAGRAPH)
1018 atk_state_set_add_state(stateSet, ATK_STATE_FOCUSABLE);
xan@webkit.org8be15d62009-04-09 11:20:57 +00001019
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001020 setAtkStateSetFromCoreObject(accessible->priv->object, stateSet);
xan@webkit.org8be15d62009-04-09 11:20:57 +00001021 return stateSet;
1022}
1023
mario@webkit.org5c966772012-01-24 18:48:50 +00001024static AtkRelationSet* webkitAccessibleRefRelationSet(AtkObject* object)
eric@webkit.org0f6cb452009-10-22 23:07:56 +00001025{
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001026 auto* accessible = WEBKIT_ACCESSIBLE(object);
1027 returnValIfWebKitAccessibleIsInvalid(accessible, nullptr);
mario@webkit.orgff8cf0f2013-09-27 09:44:20 +00001028
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001029 AtkRelationSet* relationSet = ATK_OBJECT_CLASS(webkit_accessible_parent_class)->ref_relation_set(object);
1030 setAtkRelationSetFromCoreObject(accessible->priv->object, relationSet);
eric@webkit.org0f6cb452009-10-22 23:07:56 +00001031 return relationSet;
1032}
1033
mario@webkit.org5c966772012-01-24 18:48:50 +00001034static void webkitAccessibleInit(AtkObject* object, gpointer data)
xan@webkit.orge4387102009-04-09 11:08:48 +00001035{
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001036 if (ATK_OBJECT_CLASS(webkit_accessible_parent_class)->initialize)
1037 ATK_OBJECT_CLASS(webkit_accessible_parent_class)->initialize(object, data);
xan@webkit.orge4387102009-04-09 11:08:48 +00001038
mario@webkit.orgfecbacd2013-03-04 17:06:15 +00001039 WebKitAccessible* accessible = WEBKIT_ACCESSIBLE(object);
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001040 accessible->priv->object = reinterpret_cast<AccessibilityObject*>(data);
xan@webkit.orge4387102009-04-09 11:08:48 +00001041}
1042
commit-queue@webkit.org120f5652013-06-12 21:39:42 +00001043static const gchar* webkitAccessibleGetObjectLocale(AtkObject* object)
1044{
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001045 auto* accessible = WEBKIT_ACCESSIBLE(object);
1046 returnValIfWebKitAccessibleIsInvalid(accessible, nullptr);
mario@webkit.orgff8cf0f2013-09-27 09:44:20 +00001047
1048 if (ATK_IS_DOCUMENT(object)) {
commit-queue@webkit.org120f5652013-06-12 21:39:42 +00001049 // TODO: Should we fall back on lang xml:lang when the following comes up empty?
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001050 String language = accessible->priv->object->language();
commit-queue@webkit.org120f5652013-06-12 21:39:42 +00001051 if (!language.isEmpty())
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001052 return webkitAccessibleCacheAndReturnAtkProperty(accessible, AtkCachedDocumentLocale, language.utf8());
commit-queue@webkit.org120f5652013-06-12 21:39:42 +00001053
1054 } else if (ATK_IS_TEXT(object)) {
commit-queue@webkit.org9a24e2d2015-05-29 04:53:35 +00001055 const gchar* locale = nullptr;
commit-queue@webkit.org120f5652013-06-12 21:39:42 +00001056
1057 AtkAttributeSet* textAttributes = atk_text_get_default_attributes(ATK_TEXT(object));
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001058 for (auto* attributes = textAttributes; attributes; attributes = attributes->next) {
1059 auto* atkAttribute = static_cast<AtkAttribute*>(attributes->data);
commit-queue@webkit.org120f5652013-06-12 21:39:42 +00001060 if (!strcmp(atkAttribute->name, atk_text_attribute_get_name(ATK_TEXT_ATTR_LANGUAGE))) {
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001061 locale = webkitAccessibleCacheAndReturnAtkProperty(accessible, AtkCachedDocumentLocale, atkAttribute->value);
commit-queue@webkit.org120f5652013-06-12 21:39:42 +00001062 break;
1063 }
1064 }
commit-queue@webkit.org120f5652013-06-12 21:39:42 +00001065 atk_attribute_set_free(textAttributes);
1066
1067 return locale;
1068 }
1069
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001070 return nullptr;
commit-queue@webkit.org120f5652013-06-12 21:39:42 +00001071}
1072
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001073static void webkit_accessible_class_init(WebKitAccessibleClass* klass)
xan@webkit.orge4387102009-04-09 11:08:48 +00001074{
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001075 auto* atkObjectClass = ATK_OBJECT_CLASS(klass);
1076 atkObjectClass->initialize = webkitAccessibleInit;
1077 atkObjectClass->get_name = webkitAccessibleGetName;
1078 atkObjectClass->get_description = webkitAccessibleGetDescription;
1079 atkObjectClass->get_parent = webkitAccessibleGetParent;
1080 atkObjectClass->get_n_children = webkitAccessibleGetNChildren;
1081 atkObjectClass->ref_child = webkitAccessibleRefChild;
1082 atkObjectClass->get_role = webkitAccessibleGetRole;
1083 atkObjectClass->ref_state_set = webkitAccessibleRefStateSet;
1084 atkObjectClass->get_index_in_parent = webkitAccessibleGetIndexInParent;
1085 atkObjectClass->get_attributes = webkitAccessibleGetAttributes;
1086 atkObjectClass->ref_relation_set = webkitAccessibleRefRelationSet;
1087 atkObjectClass->get_object_locale = webkitAccessibleGetObjectLocale;
xan@webkit.orge4387102009-04-09 11:08:48 +00001088}
1089
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001090static const GInterfaceInfo atkInterfacesInitFunctions[] = {
1091 {reinterpret_cast<GInterfaceInitFunc>(reinterpret_cast<GCallback>(webkitAccessibleActionInterfaceInit)), nullptr, nullptr},
1092 {reinterpret_cast<GInterfaceInitFunc>(reinterpret_cast<GCallback>(webkitAccessibleSelectionInterfaceInit)), nullptr, nullptr},
1093 {reinterpret_cast<GInterfaceInitFunc>(reinterpret_cast<GCallback>(webkitAccessibleEditableTextInterfaceInit)), nullptr, nullptr},
1094 {reinterpret_cast<GInterfaceInitFunc>(reinterpret_cast<GCallback>(webkitAccessibleTextInterfaceInit)), nullptr, nullptr},
1095 {reinterpret_cast<GInterfaceInitFunc>(reinterpret_cast<GCallback>(webkitAccessibleComponentInterfaceInit)), nullptr, nullptr},
1096 {reinterpret_cast<GInterfaceInitFunc>(reinterpret_cast<GCallback>(webkitAccessibleImageInterfaceInit)), nullptr, nullptr},
1097 {reinterpret_cast<GInterfaceInitFunc>(reinterpret_cast<GCallback>(webkitAccessibleTableInterfaceInit)), nullptr, nullptr},
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001098 {reinterpret_cast<GInterfaceInitFunc>(reinterpret_cast<GCallback>(webkitAccessibleTableCellInterfaceInit)), nullptr, nullptr},
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001099 {reinterpret_cast<GInterfaceInitFunc>(reinterpret_cast<GCallback>(webkitAccessibleHypertextInterfaceInit)), nullptr, nullptr},
1100 {reinterpret_cast<GInterfaceInitFunc>(reinterpret_cast<GCallback>(webkitAccessibleHyperlinkImplInterfaceInit)), nullptr, nullptr},
1101 {reinterpret_cast<GInterfaceInitFunc>(reinterpret_cast<GCallback>(webkitAccessibleDocumentInterfaceInit)), nullptr, nullptr},
1102 {reinterpret_cast<GInterfaceInitFunc>(reinterpret_cast<GCallback>(webkitAccessibleValueInterfaceInit)), nullptr, nullptr}
xan@webkit.orge4387102009-04-09 11:08:48 +00001103};
1104
1105enum WAIType {
k.czech@samsung.com3871a7a2014-02-27 14:22:14 +00001106 WAIAction,
1107 WAISelection,
1108 WAIEditableText,
1109 WAIText,
1110 WAIComponent,
1111 WAIImage,
1112 WAITable,
k.czech@samsung.com3871a7a2014-02-27 14:22:14 +00001113 WAITableCell,
k.czech@samsung.com3871a7a2014-02-27 14:22:14 +00001114 WAIHypertext,
1115 WAIHyperlink,
1116 WAIDocument,
1117 WAIValue,
xan@webkit.orge4387102009-04-09 11:08:48 +00001118};
1119
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001120static GType atkInterfaceTypeFromWAIType(WAIType type)
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +00001121{
mario@webkit.org7f95c622010-11-01 15:05:36 +00001122 switch (type) {
k.czech@samsung.com3871a7a2014-02-27 14:22:14 +00001123 case WAIAction:
mario@webkit.org7f95c622010-11-01 15:05:36 +00001124 return ATK_TYPE_ACTION;
k.czech@samsung.com3871a7a2014-02-27 14:22:14 +00001125 case WAISelection:
mario@webkit.org7f95c622010-11-01 15:05:36 +00001126 return ATK_TYPE_SELECTION;
k.czech@samsung.com3871a7a2014-02-27 14:22:14 +00001127 case WAIEditableText:
mario@webkit.org7f95c622010-11-01 15:05:36 +00001128 return ATK_TYPE_EDITABLE_TEXT;
k.czech@samsung.com3871a7a2014-02-27 14:22:14 +00001129 case WAIText:
mario@webkit.org7f95c622010-11-01 15:05:36 +00001130 return ATK_TYPE_TEXT;
k.czech@samsung.com3871a7a2014-02-27 14:22:14 +00001131 case WAIComponent:
mario@webkit.org7f95c622010-11-01 15:05:36 +00001132 return ATK_TYPE_COMPONENT;
k.czech@samsung.com3871a7a2014-02-27 14:22:14 +00001133 case WAIImage:
mario@webkit.org7f95c622010-11-01 15:05:36 +00001134 return ATK_TYPE_IMAGE;
k.czech@samsung.com3871a7a2014-02-27 14:22:14 +00001135 case WAITable:
mario@webkit.org7f95c622010-11-01 15:05:36 +00001136 return ATK_TYPE_TABLE;
k.czech@samsung.com3871a7a2014-02-27 14:22:14 +00001137 case WAITableCell:
k.czech@samsung.com2608de92014-02-27 11:28:31 +00001138 return ATK_TYPE_TABLE_CELL;
k.czech@samsung.com3871a7a2014-02-27 14:22:14 +00001139 case WAIHypertext:
mario@webkit.org7f95c622010-11-01 15:05:36 +00001140 return ATK_TYPE_HYPERTEXT;
k.czech@samsung.com3871a7a2014-02-27 14:22:14 +00001141 case WAIHyperlink:
mario@webkit.org7f95c622010-11-01 15:05:36 +00001142 return ATK_TYPE_HYPERLINK_IMPL;
k.czech@samsung.com3871a7a2014-02-27 14:22:14 +00001143 case WAIDocument:
mario@webkit.org7f95c622010-11-01 15:05:36 +00001144 return ATK_TYPE_DOCUMENT;
k.czech@samsung.com3871a7a2014-02-27 14:22:14 +00001145 case WAIValue:
mario@webkit.org04e38e92011-03-28 10:16:38 +00001146 return ATK_TYPE_VALUE;
mario@webkit.org7f95c622010-11-01 15:05:36 +00001147 }
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +00001148
mario@webkit.org7f95c622010-11-01 15:05:36 +00001149 return G_TYPE_INVALID;
xan@webkit.orge4387102009-04-09 11:08:48 +00001150}
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +00001151
commit-queue@webkit.orgca1b1d22012-08-22 01:37:04 +00001152static bool roleIsTextType(AccessibilityRole role)
1153{
achristensen@apple.comf80908b2017-10-27 00:37:06 +00001154 return role == AccessibilityRole::Paragraph
1155 || role == AccessibilityRole::Heading
1156 || role == AccessibilityRole::Div
1157 || role == AccessibilityRole::Cell
1158 || role == AccessibilityRole::Link
1159 || role == AccessibilityRole::WebCoreLink
1160 || role == AccessibilityRole::ListItem
1161 || role == AccessibilityRole::Pre
1162 || role == AccessibilityRole::GridCell
1163 || role == AccessibilityRole::TextGroup
carlosgc@webkit.orgb93535b2019-04-11 08:25:36 +00001164 || role == AccessibilityRole::ApplicationTextGroup
1165 || role == AccessibilityRole::ApplicationGroup;
commit-queue@webkit.orgca1b1d22012-08-22 01:37:04 +00001166}
1167
andresg_22@apple.com5c90e232019-10-30 20:44:34 +00001168static guint16 interfaceMaskFromObject(AXCoreObject* coreObject)
xan@webkit.orge4387102009-04-09 11:08:48 +00001169{
1170 guint16 interfaceMask = 0;
alp@webkit.orgc7738992008-05-27 02:48:14 +00001171
xan@webkit.org92b91692009-04-21 07:02:17 +00001172 // Component interface is always supported
k.czech@samsung.com3871a7a2014-02-27 14:22:14 +00001173 interfaceMask |= 1 << WAIComponent;
xan@webkit.org92b91692009-04-21 07:02:17 +00001174
mario@webkit.org7f95c622010-11-01 15:05:36 +00001175 AccessibilityRole role = coreObject->roleValue();
1176
xan@webkit.orgb3c59bf2009-04-21 07:01:27 +00001177 // Action
mario@webkit.org8ce6a152010-11-30 21:16:14 +00001178 // As the implementation of the AtkAction interface is a very
1179 // basic one (just relays in executing the default action for each
1180 // object, and only supports having one action per object), it is
1181 // better just to implement this interface for every instance of
1182 // the WebKitAccessible class and let WebCore decide what to do.
k.czech@samsung.com3871a7a2014-02-27 14:22:14 +00001183 interfaceMask |= 1 << WAIAction;
xan@webkit.orgb3c59bf2009-04-21 07:01:27 +00001184
eric@webkit.orgf84ff632009-10-29 17:34:39 +00001185 // Selection
jdiggs@igalia.comb0b62552016-11-19 21:12:24 +00001186 if (coreObject->canHaveSelectedChildren() || coreObject->isMenuList())
k.czech@samsung.com3871a7a2014-02-27 14:22:14 +00001187 interfaceMask |= 1 << WAISelection;
eric@webkit.orgf84ff632009-10-29 17:34:39 +00001188
mario@webkit.org9f0aee12011-04-11 21:02:23 +00001189 // Get renderer if available.
commit-queue@webkit.org9a24e2d2015-05-29 04:53:35 +00001190 RenderObject* renderer = nullptr;
mario@webkit.org9f0aee12011-04-11 21:02:23 +00001191 if (coreObject->isAccessibilityRenderObject())
1192 renderer = coreObject->renderer();
1193
1194 // Hyperlink (links and embedded objects).
1195 if (coreObject->isLink() || (renderer && renderer->isReplaced()))
k.czech@samsung.com3871a7a2014-02-27 14:22:14 +00001196 interfaceMask |= 1 << WAIHyperlink;
mario@webkit.org9f0aee12011-04-11 21:02:23 +00001197
mario.prada@samsung.com56598be2014-04-09 15:05:58 +00001198 // Text, Editable Text & Hypertext
achristensen@apple.comf80908b2017-10-27 00:37:06 +00001199 if (role == AccessibilityRole::StaticText || coreObject->isMenuListOption())
k.czech@samsung.com3871a7a2014-02-27 14:22:14 +00001200 interfaceMask |= 1 << WAIText;
jdiggs@igalia.com23022cc2016-05-11 07:14:31 +00001201 else if (coreObject->isTextControl() || coreObject->isNonNativeTextControl()) {
mario.prada@samsung.com56598be2014-04-09 15:05:58 +00001202 interfaceMask |= 1 << WAIText;
jdiggs@igalia.com23022cc2016-05-11 07:14:31 +00001203 if (coreObject->canSetValueAttribute())
mario.prada@samsung.com56598be2014-04-09 15:05:58 +00001204 interfaceMask |= 1 << WAIEditableText;
1205 } else if (!coreObject->isWebArea()) {
achristensen@apple.comf80908b2017-10-27 00:37:06 +00001206 if (role != AccessibilityRole::Table) {
mario.prada@samsung.com56598be2014-04-09 15:05:58 +00001207 interfaceMask |= 1 << WAIHypertext;
jdiggs@igalia.comad83c352014-12-10 19:57:33 +00001208 if ((renderer && renderer->childrenInline()) || roleIsTextType(role) || coreObject->isMathToken())
mario.prada@samsung.com56598be2014-04-09 15:05:58 +00001209 interfaceMask |= 1 << WAIText;
1210 }
mario@webkit.org7f95c622010-11-01 15:05:36 +00001211
mario.prada@samsung.com56598be2014-04-09 15:05:58 +00001212 // Add the TEXT interface for list items whose
1213 // first accessible child has a text renderer
achristensen@apple.comf80908b2017-10-27 00:37:06 +00001214 if (role == AccessibilityRole::ListItem) {
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001215 const auto& children = coreObject->children();
1216 if (!children.isEmpty())
1217 interfaceMask |= interfaceMaskFromObject(children[0].get());
commit-queue@webkit.org1f3aafe2010-09-22 07:49:34 +00001218 }
mario@webkit.org7f95c622010-11-01 15:05:36 +00001219 }
xan@webkit.orge4387102009-04-09 11:08:48 +00001220
xan@webkit.orge43e70b2009-04-27 21:33:55 +00001221 // Image
1222 if (coreObject->isImage())
k.czech@samsung.com3871a7a2014-02-27 14:22:14 +00001223 interfaceMask |= 1 << WAIImage;
xan@webkit.orge43e70b2009-04-27 21:33:55 +00001224
xan@webkit.org45b26ac2009-10-27 12:20:35 +00001225 // Table
jdiggs@igalia.com8c934782017-04-30 18:11:56 +00001226 if (coreObject->isTable())
k.czech@samsung.com3871a7a2014-02-27 14:22:14 +00001227 interfaceMask |= 1 << WAITable;
xan@webkit.org45b26ac2009-10-27 12:20:35 +00001228
achristensen@apple.comf80908b2017-10-27 00:37:06 +00001229 if (role == AccessibilityRole::Cell || role == AccessibilityRole::GridCell || role == AccessibilityRole::ColumnHeader || role == AccessibilityRole::RowHeader)
k.czech@samsung.com3871a7a2014-02-27 14:22:14 +00001230 interfaceMask |= 1 << WAITableCell;
k.czech@samsung.com2608de92014-02-27 11:28:31 +00001231
eric@webkit.org65e12ba2009-11-01 21:22:30 +00001232 // Document
achristensen@apple.comf80908b2017-10-27 00:37:06 +00001233 if (role == AccessibilityRole::WebArea)
k.czech@samsung.com3871a7a2014-02-27 14:22:14 +00001234 interfaceMask |= 1 << WAIDocument;
eric@webkit.org65e12ba2009-11-01 21:22:30 +00001235
mario@webkit.org04e38e92011-03-28 10:16:38 +00001236 // Value
jdiggs@igalia.com353e8722017-04-28 17:08:57 +00001237 if (coreObject->supportsRangeValue())
k.czech@samsung.com3871a7a2014-02-27 14:22:14 +00001238 interfaceMask |= 1 << WAIValue;
mario@webkit.org04e38e92011-03-28 10:16:38 +00001239
commit-queue@webkit.orgfd70fd32013-09-04 14:19:02 +00001240#if ENABLE(INPUT_TYPE_COLOR)
1241 // Color type.
achristensen@apple.comf80908b2017-10-27 00:37:06 +00001242 if (role == AccessibilityRole::ColorWell)
k.czech@samsung.com3871a7a2014-02-27 14:22:14 +00001243 interfaceMask |= 1 << WAIText;
commit-queue@webkit.orgfd70fd32013-09-04 14:19:02 +00001244#endif
1245
xan@webkit.orge4387102009-04-09 11:08:48 +00001246 return interfaceMask;
1247}
1248
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001249static const char* uniqueAccessibilityTypeName(guint16 interfaceMask)
xan@webkit.orge4387102009-04-09 11:08:48 +00001250{
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001251#define WAI_TYPE_NAME_LEN (30) // Enough for prefix + 5 hex characters (max).
xan@webkit.orge4387102009-04-09 11:08:48 +00001252 static char name[WAI_TYPE_NAME_LEN + 1];
eric@webkit.org4ff6fd72009-11-10 09:53:33 +00001253
xan@webkit.orge4387102009-04-09 11:08:48 +00001254 g_sprintf(name, "WAIType%x", interfaceMask);
1255 name[WAI_TYPE_NAME_LEN] = '\0';
eric@webkit.org4ff6fd72009-11-10 09:53:33 +00001256
xan@webkit.orge4387102009-04-09 11:08:48 +00001257 return name;
1258}
1259
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001260static GType accessibilityTypeFromObject(AccessibilityObject* coreObject)
xan@webkit.orge4387102009-04-09 11:08:48 +00001261{
1262 static const GTypeInfo typeInfo = {
1263 sizeof(WebKitAccessibleClass),
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001264 nullptr, // GBaseInitFunc
1265 nullptr, // GBaseFinalizeFunc
1266 nullptr, // GClassInitFunc
1267 nullptr, // GClassFinalizeFunc
1268 nullptr, // class data
1269 sizeof(WebKitAccessible), // instance size
1270 0, // nb preallocs
1271 nullptr, // GInstanceInitFunc
1272 nullptr // value table
xan@webkit.orge4387102009-04-09 11:08:48 +00001273 };
1274
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001275 guint16 interfaceMask = interfaceMaskFromObject(coreObject);
1276 const char* atkTypeName = uniqueAccessibilityTypeName(interfaceMask);
1277 if (GType type = g_type_from_name(atkTypeName))
xan@webkit.orge4387102009-04-09 11:08:48 +00001278 return type;
1279
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001280 GType type = g_type_register_static(WEBKIT_TYPE_ACCESSIBLE, atkTypeName, &typeInfo, static_cast<GTypeFlags>(0));
1281 for (unsigned i = 0; i < G_N_ELEMENTS(atkInterfacesInitFunctions); ++i) {
1282 if (interfaceMask & (1 << i)) {
xan@webkit.orge4387102009-04-09 11:08:48 +00001283 g_type_add_interface_static(type,
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001284 atkInterfaceTypeFromWAIType(static_cast<WAIType>(i)),
1285 &atkInterfacesInitFunctions[i]);
1286 }
xan@webkit.orge4387102009-04-09 11:08:48 +00001287 }
1288
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +00001289 return type;
1290}
1291
mario@webkit.orgaacb2172012-01-23 11:43:28 +00001292WebKitAccessible* webkitAccessibleNew(AccessibilityObject* coreObject)
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +00001293{
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001294 auto* object = ATK_OBJECT(g_object_new(accessibilityTypeFromObject(coreObject), nullptr));
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +00001295 atk_object_initialize(object, coreObject);
1296 return WEBKIT_ACCESSIBLE(object);
1297}
1298
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001299AccessibilityObject& webkitAccessibleGetAccessibilityObject(WebKitAccessible* accessible)
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +00001300{
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001301 ASSERT(WEBKIT_IS_ACCESSIBLE(accessible));
1302 return *accessible->priv->object;
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +00001303}
1304
mario@webkit.orgaacb2172012-01-23 11:43:28 +00001305void webkitAccessibleDetach(WebKitAccessible* accessible)
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +00001306{
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001307 ASSERT(WEBKIT_IS_ACCESSIBLE(accessible));
1308 ASSERT(accessible->priv->object != fallbackObject());
alp@webkit.orgc7738992008-05-27 02:48:14 +00001309
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001310 if (accessible->priv->object->roleValue() == AccessibilityRole::WebArea)
1311 atk_object_notify_state_change(ATK_OBJECT(accessible), ATK_STATE_DEFUNCT, TRUE);
mario@webkit.org92daa812011-02-16 17:12:38 +00001312
alp@webkit.orgc7738992008-05-27 02:48:14 +00001313 // We replace the WebCore AccessibilityObject with a fallback object that
1314 // provides default implementations to avoid repetitive null-checking after
1315 // detachment.
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001316 accessible->priv->object = fallbackObject();
alp@webkit.org3a5e7ca2008-05-20 01:12:20 +00001317}
1318
mario@webkit.orgff8cf0f2013-09-27 09:44:20 +00001319bool webkitAccessibleIsDetached(WebKitAccessible* accessible)
1320{
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001321 ASSERT(WEBKIT_IS_ACCESSIBLE(accessible));
1322 return accessible->priv->object == fallbackObject();
mario@webkit.orgff8cf0f2013-09-27 09:44:20 +00001323}
1324
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001325const char* webkitAccessibleCacheAndReturnAtkProperty(WebKitAccessible* accessible, AtkCachedProperty property, CString&& value)
eric@webkit.org2fade492010-01-11 12:03:36 +00001326{
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001327 ASSERT(WEBKIT_IS_ACCESSIBLE(accessible));
eric@webkit.org2fade492010-01-11 12:03:36 +00001328
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001329 WebKitAccessiblePrivate* priv = accessible->priv;
commit-queue@webkit.org9a24e2d2015-05-29 04:53:35 +00001330 CString* propertyPtr = nullptr;
mario@webkit.orgfecbacd2013-03-04 17:06:15 +00001331
1332 switch (property) {
1333 case AtkCachedAccessibleName:
1334 propertyPtr = &priv->accessibleName;
1335 break;
mario@webkit.orgfecbacd2013-03-04 17:06:15 +00001336 case AtkCachedAccessibleDescription:
1337 propertyPtr = &priv->accessibleDescription;
1338 break;
mario@webkit.orgfecbacd2013-03-04 17:06:15 +00001339 case AtkCachedActionName:
1340 propertyPtr = &priv->actionName;
1341 break;
mario@webkit.orgfecbacd2013-03-04 17:06:15 +00001342 case AtkCachedActionKeyBinding:
1343 propertyPtr = &priv->actionKeyBinding;
1344 break;
mario@webkit.orgfecbacd2013-03-04 17:06:15 +00001345 case AtkCachedDocumentLocale:
1346 propertyPtr = &priv->documentLocale;
1347 break;
mario@webkit.orgfecbacd2013-03-04 17:06:15 +00001348 case AtkCachedDocumentType:
1349 propertyPtr = &priv->documentType;
1350 break;
mario@webkit.orgfecbacd2013-03-04 17:06:15 +00001351 case AtkCachedDocumentEncoding:
1352 propertyPtr = &priv->documentEncoding;
1353 break;
mario@webkit.orgfecbacd2013-03-04 17:06:15 +00001354 case AtkCachedDocumentURI:
1355 propertyPtr = &priv->documentURI;
1356 break;
mario@webkit.orgfecbacd2013-03-04 17:06:15 +00001357 case AtkCachedImageDescription:
1358 propertyPtr = &priv->imageDescription;
1359 break;
mario@webkit.orgfecbacd2013-03-04 17:06:15 +00001360 default:
1361 ASSERT_NOT_REACHED();
1362 }
1363
1364 // Don't invalidate old memory if not stricly needed, since other
1365 // callers might be still holding on to it.
carlosgc@webkit.orged2d42a2019-04-08 08:11:19 +00001366 if (*propertyPtr != value)
1367 *propertyPtr = WTFMove(value);
mario@webkit.orgfecbacd2013-03-04 17:06:15 +00001368
1369 return (*propertyPtr).data();
1370}
1371
psaavedra@igalia.com5b9fe192019-07-11 21:51:24 +00001372#endif // ENABLE(ACCESSIBILITY)