AXIsolatedObject support for table rows and ARIA tree/grid rows.
[WebKit-https.git] / Source / WebCore / accessibility / mac / WebAccessibilityObjectWrapperMac.mm
1 /*
2  * Copyright (C) 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #import "config.h"
30 #import "WebAccessibilityObjectWrapperMac.h"
31
32 #if ENABLE(ACCESSIBILITY) && PLATFORM(MAC)
33
34 #import "AXObjectCache.h"
35 #import "AccessibilityARIAGridRow.h"
36 #import "AccessibilityLabel.h"
37 #import "AccessibilityList.h"
38 #import "AccessibilityListBox.h"
39 #import "AccessibilityProgressIndicator.h"
40 #import "AccessibilityRenderObject.h"
41 #import "AccessibilityScrollView.h"
42 #import "AccessibilitySpinButton.h"
43 #import "AccessibilityTable.h"
44 #import "AccessibilityTableCell.h"
45 #import "AccessibilityTableColumn.h"
46 #import "AccessibilityTableRow.h"
47 #import "Chrome.h"
48 #import "ChromeClient.h"
49 #import "ColorMac.h"
50 #import "ContextMenuController.h"
51 #import "Editing.h"
52 #import "Editor.h"
53 #import "Font.h"
54 #import "FontCascade.h"
55 #import "Frame.h"
56 #import "FrameLoaderClient.h"
57 #import "FrameSelection.h"
58 #import "HTMLAnchorElement.h"
59 #import "HTMLAreaElement.h"
60 #import "HTMLFrameOwnerElement.h"
61 #import "HTMLImageElement.h"
62 #import "HTMLInputElement.h"
63 #import "HTMLNames.h"
64 #import "LocalizedStrings.h"
65 #import "Page.h"
66 #import "PluginDocument.h"
67 #import "PluginViewBase.h"
68 #import "RenderInline.h"
69 #import "RenderTextControl.h"
70 #import "RenderView.h"
71 #import "RenderWidget.h"
72 #import "ScrollView.h"
73 #import "TextCheckerClient.h"
74 #import "TextCheckingHelper.h"
75 #import "TextDecorationPainter.h"
76 #import "TextIterator.h"
77 #import "VisibleUnits.h"
78 #import "WebCoreFrameView.h"
79 #import <pal/spi/cocoa/NSAccessibilitySPI.h>
80 #import <pal/spi/mac/HIServicesSPI.h>
81 #import <wtf/ObjCRuntimeExtras.h>
82 #if ENABLE(TREE_DEBUGGING) || ENABLE(METER_ELEMENT)
83 #import <wtf/text/StringBuilder.h>
84 #endif
85
86 using namespace WebCore;
87 using namespace HTMLNames;
88
89 // Cell Tables
90 #ifndef NSAccessibilitySelectedCellsAttribute
91 #define NSAccessibilitySelectedCellsAttribute @"AXSelectedCells"
92 #endif
93
94 #ifndef NSAccessibilityVisibleCellsAttribute
95 #define NSAccessibilityVisibleCellsAttribute @"AXVisibleCells"
96 #endif
97
98 #ifndef NSAccessibilityRowIndexRangeAttribute
99 #define NSAccessibilityRowIndexRangeAttribute @"AXRowIndexRange"
100 #endif
101
102 #ifndef NSAccessibilityColumnIndexRangeAttribute
103 #define NSAccessibilityColumnIndexRangeAttribute @"AXColumnIndexRange"
104 #endif
105
106 #ifndef NSAccessibilityCellForColumnAndRowParameterizedAttribute
107 #define NSAccessibilityCellForColumnAndRowParameterizedAttribute @"AXCellForColumnAndRow"
108 #endif
109
110 #ifndef NSAccessibilityCellRole
111 #define NSAccessibilityCellRole @"AXCell"
112 #endif
113
114 // Lists
115 #ifndef NSAccessibilityContentListSubrole
116 #define NSAccessibilityContentListSubrole @"AXContentList"
117 #endif
118
119 #ifndef NSAccessibilityDefinitionListSubrole
120 #define NSAccessibilityDefinitionListSubrole @"AXDefinitionList"
121 #endif
122
123 #ifndef NSAccessibilityDescriptionListSubrole
124 #define NSAccessibilityDescriptionListSubrole @"AXDescriptionList"
125 #endif
126
127 #ifndef NSAccessibilityContentSeparatorSubrole
128 #define NSAccessibilityContentSeparatorSubrole @"AXContentSeparator"
129 #endif
130
131 #ifndef NSAccessibilityRubyBaseSubRole
132 #define NSAccessibilityRubyBaseSubrole @"AXRubyBase"
133 #endif
134
135 #ifndef NSAccessibilityRubyBlockSubrole
136 #define NSAccessibilityRubyBlockSubrole @"AXRubyBlock"
137 #endif
138
139 #ifndef NSAccessibilityRubyInlineSubrole
140 #define NSAccessibilityRubyInlineSubrole @"AXRubyInline"
141 #endif
142
143 #ifndef NSAccessibilityRubyRunSubrole
144 #define NSAccessibilityRubyRunSubrole @"AXRubyRun"
145 #endif
146
147 #ifndef NSAccessibilityRubyTextSubrole
148 #define NSAccessibilityRubyTextSubrole @"AXRubyText"
149 #endif
150
151 // Miscellaneous
152 #ifndef NSAccessibilityBlockQuoteLevelAttribute
153 #define NSAccessibilityBlockQuoteLevelAttribute @"AXBlockQuoteLevel"
154 #endif
155
156 #ifndef NSAccessibilityChildrenInNavigationOrderAttribute
157 #define NSAccessibilityChildrenInNavigationOrderAttribute @"AXChildrenInNavigationOrder"
158 #endif
159
160 #ifndef NSAccessibilityAccessKeyAttribute
161 #define NSAccessibilityAccessKeyAttribute @"AXAccessKey"
162 #endif
163
164 #ifndef NSAccessibilityValueAutofilledAttribute
165 #define NSAccessibilityValueAutofilledAttribute @"AXValueAutofilled"
166 #endif
167
168 #ifndef NSAccessibilityValueAutofillAvailableAttribute
169 #define NSAccessibilityValueAutofillAvailableAttribute @"AXValueAutofillAvailable"
170 #endif
171
172 #ifndef NSAccessibilityValueAutofillTypeAttribute
173 #define NSAccessibilityValueAutofillTypeAttribute @"AXValueAutofillType"
174 #endif
175
176 #ifndef NSAccessibilityLanguageAttribute
177 #define NSAccessibilityLanguageAttribute @"AXLanguage"
178 #endif
179
180 #ifndef NSAccessibilityRequiredAttribute
181 #define NSAccessibilityRequiredAttribute @"AXRequired"
182 #endif
183
184 #ifndef NSAccessibilityInvalidAttribute
185 #define NSAccessibilityInvalidAttribute @"AXInvalid"
186 #endif
187
188 #ifndef NSAccessibilityOwnsAttribute
189 #define NSAccessibilityOwnsAttribute @"AXOwns"
190 #endif
191
192 #ifndef NSAccessibilityGrabbedAttribute
193 #define NSAccessibilityGrabbedAttribute @"AXGrabbed"
194 #endif
195
196 #ifndef NSAccessibilityDatetimeValueAttribute
197 #define NSAccessibilityDatetimeValueAttribute @"AXDateTimeValue"
198 #endif
199
200 #ifndef NSAccessibilityInlineTextAttribute
201 #define NSAccessibilityInlineTextAttribute @"AXInlineText"
202 #endif
203
204 #ifndef NSAccessibilityDropEffectsAttribute
205 #define NSAccessibilityDropEffectsAttribute @"AXDropEffects"
206 #endif
207
208 #ifndef NSAccessibilityARIALiveAttribute
209 #define NSAccessibilityARIALiveAttribute @"AXARIALive"
210 #endif
211
212 #ifndef NSAccessibilityARIAAtomicAttribute
213 #define NSAccessibilityARIAAtomicAttribute @"AXARIAAtomic"
214 #endif
215
216 #ifndef NSAccessibilityARIARelevantAttribute
217 #define NSAccessibilityARIARelevantAttribute @"AXARIARelevant"
218 #endif
219
220 #ifndef NSAccessibilityElementBusyAttribute
221 #define NSAccessibilityElementBusyAttribute @"AXElementBusy"
222 #endif
223
224 #ifndef NSAccessibilityARIAPosInSetAttribute
225 #define NSAccessibilityARIAPosInSetAttribute @"AXARIAPosInSet"
226 #endif
227
228 #ifndef NSAccessibilityARIASetSizeAttribute
229 #define NSAccessibilityARIASetSizeAttribute @"AXARIASetSize"
230 #endif
231
232 #ifndef NSAccessibilityLoadingProgressAttribute
233 #define NSAccessibilityLoadingProgressAttribute @"AXLoadingProgress"
234 #endif
235
236 #ifndef NSAccessibilityHasPopupAttribute
237 #define NSAccessibilityHasPopupAttribute @"AXHasPopup"
238 #endif
239
240 #ifndef NSAccessibilityPopupValueAttribute
241 #define NSAccessibilityPopupValueAttribute @"AXPopupValue"
242 #endif
243
244 #ifndef NSAccessibilityPlaceholderValueAttribute
245 #define NSAccessibilityPlaceholderValueAttribute @"AXPlaceholderValue"
246 #endif
247
248 #define NSAccessibilityTextMarkerIsValidParameterizedAttribute @"AXTextMarkerIsValid"
249 #define NSAccessibilityIndexForTextMarkerParameterizedAttribute @"AXIndexForTextMarker"
250 #define NSAccessibilityTextMarkerForIndexParameterizedAttribute @"AXTextMarkerForIndex"
251
252 #ifndef NSAccessibilityScrollToVisibleAction
253 #define NSAccessibilityScrollToVisibleAction @"AXScrollToVisible"
254 #endif
255
256 #ifndef NSAccessibilityPathAttribute
257 #define NSAccessibilityPathAttribute @"AXPath"
258 #endif
259
260 #ifndef NSAccessibilityExpandedTextValueAttribute
261 #define NSAccessibilityExpandedTextValueAttribute @"AXExpandedTextValue"
262 #endif
263
264 #ifndef NSAccessibilityIsMultiSelectableAttribute
265 #define NSAccessibilityIsMultiSelectableAttribute @"AXIsMultiSelectable"
266 #endif
267
268 #ifndef NSAccessibilityDocumentURIAttribute
269 #define NSAccessibilityDocumentURIAttribute @"AXDocumentURI"
270 #endif
271
272 #ifndef NSAccessibilityDocumentEncodingAttribute
273 #define NSAccessibilityDocumentEncodingAttribute @"AXDocumentEncoding"
274 #endif
275
276 #ifndef NSAccessibilityAriaControlsAttribute
277 #define NSAccessibilityAriaControlsAttribute @"AXARIAControls"
278 #endif
279
280 #define NSAccessibilityDOMIdentifierAttribute @"AXDOMIdentifier"
281 #define NSAccessibilityDOMClassListAttribute @"AXDOMClassList"
282
283 #ifndef NSAccessibilityARIACurrentAttribute
284 #define NSAccessibilityARIACurrentAttribute @"AXARIACurrent"
285 #endif
286
287 // Table/grid attributes
288 #ifndef NSAccessibilityARIAColumnIndexAttribute
289 #define NSAccessibilityARIAColumnIndexAttribute @"AXARIAColumnIndex"
290 #endif
291
292 #ifndef NSAccessibilityARIARowIndexAttribute
293 #define NSAccessibilityARIARowIndexAttribute @"AXARIARowIndex"
294 #endif
295
296 #ifndef NSAccessibilityARIAColumnCountAttribute
297 #define NSAccessibilityARIAColumnCountAttribute @"AXARIAColumnCount"
298 #endif
299
300 #ifndef NSAccessibilityARIARowCountAttribute
301 #define NSAccessibilityARIARowCountAttribute @"AXARIARowCount"
302 #endif
303
304
305 #ifndef NSAccessibilityUIElementCountForSearchPredicateParameterizedAttribute
306 #define NSAccessibilityUIElementCountForSearchPredicateParameterizedAttribute @"AXUIElementCountForSearchPredicate"
307 #endif
308
309 #ifndef NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute
310 #define NSAccessibilityUIElementsForSearchPredicateParameterizedAttribute @"AXUIElementsForSearchPredicate"
311 #endif
312
313 // Text markers
314 #ifndef NSAccessibilityEndTextMarkerForBoundsParameterizedAttribute
315 #define NSAccessibilityEndTextMarkerForBoundsParameterizedAttribute @"AXEndTextMarkerForBounds"
316 #endif
317
318 #ifndef NSAccessibilityStartTextMarkerForBoundsParameterizedAttribute
319 #define NSAccessibilityStartTextMarkerForBoundsParameterizedAttribute @"AXStartTextMarkerForBounds"
320 #endif
321
322 #ifndef NSAccessibilityLineTextMarkerRangeForTextMarkerParameterizedAttribute
323 #define NSAccessibilityLineTextMarkerRangeForTextMarkerParameterizedAttribute @"AXLineTextMarkerRangeForTextMarker"
324 #endif
325
326 #ifndef NSAccessibilityMisspellingTextMarkerRangeParameterizedAttribute
327 #define NSAccessibilityMisspellingTextMarkerRangeParameterizedAttribute @"AXMisspellingTextMarkerRange"
328 #endif
329
330 // Text selection
331 #ifndef NSAccessibilitySelectTextActivity
332 #define NSAccessibilitySelectTextActivity @"AXSelectTextActivity"
333 #endif
334
335 #ifndef NSAccessibilitySelectTextActivityFindAndReplace
336 #define NSAccessibilitySelectTextActivityFindAndReplace @"AXSelectTextActivityFindAndReplace"
337 #endif
338
339 #ifndef NSAccessibilitySelectTextActivityFindAndSelect
340 #define NSAccessibilitySelectTextActivityFindAndSelect @"AXSelectTextActivityFindAndSelect"
341 #endif
342
343 #ifndef kAXSelectTextActivityFindAndCapitalize
344 #define kAXSelectTextActivityFindAndCapitalize @"AXSelectTextActivityFindAndCapitalize"
345 #endif
346
347 #ifndef kAXSelectTextActivityFindAndLowercase
348 #define kAXSelectTextActivityFindAndLowercase @"AXSelectTextActivityFindAndLowercase"
349 #endif
350
351 #ifndef kAXSelectTextActivityFindAndUppercase
352 #define kAXSelectTextActivityFindAndUppercase @"AXSelectTextActivityFindAndUppercase"
353 #endif
354
355 #ifndef NSAccessibilitySelectTextAmbiguityResolution
356 #define NSAccessibilitySelectTextAmbiguityResolution @"AXSelectTextAmbiguityResolution"
357 #endif
358
359 #ifndef NSAccessibilitySelectTextAmbiguityResolutionClosestAfterSelection
360 #define NSAccessibilitySelectTextAmbiguityResolutionClosestAfterSelection @"AXSelectTextAmbiguityResolutionClosestAfterSelection"
361 #endif
362
363 #ifndef NSAccessibilitySelectTextAmbiguityResolutionClosestBeforeSelection
364 #define NSAccessibilitySelectTextAmbiguityResolutionClosestBeforeSelection @"AXSelectTextAmbiguityResolutionClosestBeforeSelection"
365 #endif
366
367 #ifndef NSAccessibilitySelectTextAmbiguityResolutionClosestToSelection
368 #define NSAccessibilitySelectTextAmbiguityResolutionClosestToSelection @"AXSelectTextAmbiguityResolutionClosestToSelection"
369 #endif
370
371 #ifndef NSAccessibilitySelectTextReplacementString
372 #define NSAccessibilitySelectTextReplacementString @"AXSelectTextReplacementString"
373 #endif
374
375 #ifndef NSAccessibilitySelectTextSearchStrings
376 #define NSAccessibilitySelectTextSearchStrings @"AXSelectTextSearchStrings"
377 #endif
378
379 #ifndef NSAccessibilitySelectTextWithCriteriaParameterizedAttribute
380 #define NSAccessibilitySelectTextWithCriteriaParameterizedAttribute @"AXSelectTextWithCriteria"
381 #endif
382
383 // Text search
384
385 #ifndef NSAccessibilitySearchTextWithCriteriaParameterizedAttribute
386 /* Performs a text search with the given parameters.
387  Returns an NSArray of text marker ranges of the search hits.
388  */
389 #define NSAccessibilitySearchTextWithCriteriaParameterizedAttribute @"AXSearchTextWithCriteria"
390 #endif
391
392 #ifndef NSAccessibilitySearchTextSearchStrings
393 // NSArray of strings to search for.
394 #define NSAccessibilitySearchTextSearchStrings @"AXSearchTextSearchStrings"
395 #endif
396
397 #ifndef NSAccessibilitySearchTextStartFrom
398 // NSString specifying the start point of the search: selection, begin or end.
399 #define NSAccessibilitySearchTextStartFrom @"AXSearchTextStartFrom"
400 #endif
401
402 #ifndef NSAccessibilitySearchTextStartFromBegin
403 // Value for SearchTextStartFrom.
404 #define NSAccessibilitySearchTextStartFromBegin @"AXSearchTextStartFromBegin"
405 #endif
406
407 #ifndef NSAccessibilitySearchTextStartFromSelection
408 // Value for SearchTextStartFrom.
409 #define NSAccessibilitySearchTextStartFromSelection @"AXSearchTextStartFromSelection"
410 #endif
411
412 #ifndef NSAccessibilitySearchTextStartFromEnd
413 // Value for SearchTextStartFrom.
414 #define NSAccessibilitySearchTextStartFromEnd @"AXSearchTextStartFromEnd"
415 #endif
416
417 #ifndef NSAccessibilitySearchTextDirection
418 // NSString specifying the direction of the search: forward, backward, closest, all.
419 #define NSAccessibilitySearchTextDirection @"AXSearchTextDirection"
420 #endif
421
422 #ifndef NSAccessibilitySearchTextDirectionForward
423 // Value for SearchTextDirection.
424 #define NSAccessibilitySearchTextDirectionForward @"AXSearchTextDirectionForward"
425 #endif
426
427 #ifndef NSAccessibilitySearchTextDirectionBackward
428 // Value for SearchTextDirection.
429 #define NSAccessibilitySearchTextDirectionBackward @"AXSearchTextDirectionBackward"
430 #endif
431
432 #ifndef NSAccessibilitySearchTextDirectionClosest
433 // Value for SearchTextDirection.
434 #define NSAccessibilitySearchTextDirectionClosest @"AXSearchTextDirectionClosest"
435 #endif
436
437 #ifndef NSAccessibilitySearchTextDirectionAll
438 // Value for SearchTextDirection.
439 #define NSAccessibilitySearchTextDirectionAll @"AXSearchTextDirectionAll"
440 #endif
441
442 // Text operations
443
444 #ifndef NSAccessibilityTextOperationParameterizedAttribute
445 // Performs an operation on the given text.
446 #define NSAccessibilityTextOperationParameterizedAttribute @"AXTextOperation"
447 #endif
448
449 #ifndef NSAccessibilityTextOperationMarkerRanges
450 // Text on which to perform operation.
451 #define NSAccessibilityTextOperationMarkerRanges @"AXTextOperationMarkerRanges"
452 #endif
453
454 #ifndef NSAccessibilityTextOperationType
455 // The type of operation to be performed: select, replace, capitalize....
456 #define NSAccessibilityTextOperationType @"AXTextOperationType"
457 #endif
458
459 #ifndef NSAccessibilityTextOperationSelect
460 // Value for TextOperationType.
461 #define NSAccessibilityTextOperationSelect @"TextOperationSelect"
462 #endif
463
464 #ifndef NSAccessibilityTextOperationReplace
465 // Value for TextOperationType.
466 #define NSAccessibilityTextOperationReplace @"TextOperationReplace"
467 #endif
468
469 #ifndef NSAccessibilityTextOperationCapitalize
470 // Value for TextOperationType.
471 #define NSAccessibilityTextOperationCapitalize @"Capitalize"
472 #endif
473
474 #ifndef NSAccessibilityTextOperationLowercase
475 // Value for TextOperationType.
476 #define NSAccessibilityTextOperationLowercase @"Lowercase"
477 #endif
478
479 #ifndef NSAccessibilityTextOperationUppercase
480 // Value for TextOperationType.
481 #define NSAccessibilityTextOperationUppercase @"Uppercase"
482 #endif
483
484 #ifndef NSAccessibilityTextOperationReplacementString
485 // Replacement text for operation replace.
486 #define NSAccessibilityTextOperationReplacementString @"AXTextOperationReplacementString"
487 #endif
488
489 // Math attributes
490 #define NSAccessibilityMathRootRadicandAttribute @"AXMathRootRadicand"
491 #define NSAccessibilityMathRootIndexAttribute @"AXMathRootIndex"
492 #define NSAccessibilityMathFractionDenominatorAttribute @"AXMathFractionDenominator"
493 #define NSAccessibilityMathFractionNumeratorAttribute @"AXMathFractionNumerator"
494 #define NSAccessibilityMathBaseAttribute @"AXMathBase"
495 #define NSAccessibilityMathSubscriptAttribute @"AXMathSubscript"
496 #define NSAccessibilityMathSuperscriptAttribute @"AXMathSuperscript"
497 #define NSAccessibilityMathUnderAttribute @"AXMathUnder"
498 #define NSAccessibilityMathOverAttribute @"AXMathOver"
499 #define NSAccessibilityMathFencedOpenAttribute @"AXMathFencedOpen"
500 #define NSAccessibilityMathFencedCloseAttribute @"AXMathFencedClose"
501 #define NSAccessibilityMathLineThicknessAttribute @"AXMathLineThickness"
502 #define NSAccessibilityMathPrescriptsAttribute @"AXMathPrescripts"
503 #define NSAccessibilityMathPostscriptsAttribute @"AXMathPostscripts"
504
505 #ifndef NSAccessibilityPreventKeyboardDOMEventDispatchAttribute
506 #define NSAccessibilityPreventKeyboardDOMEventDispatchAttribute @"AXPreventKeyboardDOMEventDispatch"
507 #endif
508
509 #ifndef NSAccessibilityCaretBrowsingEnabledAttribute
510 #define NSAccessibilityCaretBrowsingEnabledAttribute @"AXCaretBrowsingEnabled"
511 #endif
512
513 #ifndef NSAccessibilityWebSessionIDAttribute
514 #define NSAccessibilityWebSessionIDAttribute @"AXWebSessionID"
515 #endif
516
517 #ifndef NSAccessibilitFocusableAncestorAttribute
518 #define NSAccessibilityFocusableAncestorAttribute @"AXFocusableAncestor"
519 #endif
520
521 #ifndef NSAccessibilityEditableAncestorAttribute
522 #define NSAccessibilityEditableAncestorAttribute @"AXEditableAncestor"
523 #endif
524
525 #ifndef NSAccessibilityHighestEditableAncestorAttribute
526 #define NSAccessibilityHighestEditableAncestorAttribute @"AXHighestEditableAncestor"
527 #endif
528
529 #ifndef NSAccessibilityLinkRelationshipTypeAttribute
530 #define NSAccessibilityLinkRelationshipTypeAttribute @"AXLinkRelationshipType"
531 #endif
532
533 #ifndef NSAccessibilityRelativeFrameAttribute
534 #define NSAccessibilityRelativeFrameAttribute @"AXRelativeFrame"
535 #endif
536
537 extern "C" AXUIElementRef NSAccessibilityCreateAXUIElementRef(id element);
538
539 @implementation WebAccessibilityObjectWrapper
540
541 - (void)unregisterUniqueIdForUIElement
542 {
543     NSAccessibilityUnregisterUniqueIdForUIElement(self);
544 }
545
546 - (void)detach
547 {
548     // Send unregisterUniqueIdForUIElement unconditionally because if it is
549     // ever accidentally not done (via other bugs in our AX implementation) you
550     // end up with a crash like <rdar://problem/4273149>.  It is safe and not
551     // expensive to send even if the object is not registered.
552     [self unregisterUniqueIdForUIElement];
553     [super detach];
554 }
555
556 - (id)attachmentView
557 {
558     ASSERT(self.axBackingObject->isAttachment());
559
560     return Accessibility::retrieveAutoreleasedValueFromMainThread<id>([protectedSelf = RetainPtr<WebAccessibilityObjectWrapper>(self)] () -> RetainPtr<id> {
561         auto* widget = protectedSelf.get().axBackingObject->widgetForAttachmentView();
562         if (!widget)
563             return nil;
564         return NSAccessibilityUnignoredDescendant(widget->platformWidget());
565     });
566 }
567
568 #pragma mark SystemInterface wrappers
569
570 static inline BOOL AXObjectIsTextMarker(id object)
571 {
572     return object && CFGetTypeID((__bridge CFTypeRef)object) == AXTextMarkerGetTypeID();
573 }
574
575 static inline BOOL AXObjectIsTextMarkerRange(id object)
576 {
577     return object && CFGetTypeID((__bridge CFTypeRef)object) == AXTextMarkerRangeGetTypeID();
578 }
579
580 static id AXTextMarkerRange(id startMarker, id endMarker)
581 {
582     ASSERT(startMarker != nil);
583     ASSERT(endMarker != nil);
584     ASSERT(CFGetTypeID((__bridge CFTypeRef)startMarker) == AXTextMarkerGetTypeID());
585     ASSERT(CFGetTypeID((__bridge CFTypeRef)endMarker) == AXTextMarkerGetTypeID());
586     return CFBridgingRelease(AXTextMarkerRangeCreate(kCFAllocatorDefault, (AXTextMarkerRef)startMarker, (AXTextMarkerRef)endMarker));
587 }
588
589 static id AXTextMarkerRangeStart(id range)
590 {
591     ASSERT(range != nil);
592     ASSERT(CFGetTypeID((__bridge CFTypeRef)range) == AXTextMarkerRangeGetTypeID());
593     return CFBridgingRelease(AXTextMarkerRangeCopyStartMarker((AXTextMarkerRangeRef)range));
594 }
595
596 static id AXTextMarkerRangeEnd(id range)
597 {
598     ASSERT(range != nil);
599     ASSERT(CFGetTypeID((__bridge CFTypeRef)range) == AXTextMarkerRangeGetTypeID());
600     return CFBridgingRelease(AXTextMarkerRangeCopyEndMarker((AXTextMarkerRangeRef)range));
601 }
602
603 #pragma mark Other helpers
604
605 - (IntRect)screenToContents:(const IntRect&)rect
606 {
607     ASSERT(isMainThread());
608
609     Document* document = self.axBackingObject->document();
610     if (!document)
611         return IntRect();
612     
613     FrameView* frameView = document->view();
614     if (!frameView)
615         return IntRect();
616     
617     IntPoint startPoint = frameView->screenToContents(rect.minXMaxYCorner());
618     IntPoint endPoint = frameView->screenToContents(rect.maxXMinYCorner());
619     return IntRect(startPoint.x(), startPoint.y(), endPoint.x() - startPoint.x(), endPoint.y() - startPoint.y());
620 }
621
622 #pragma mark Select text helpers
623
624 // To be deprecated.
625 static std::pair<AccessibilitySearchTextCriteria, AccessibilityTextOperation> accessibilityTextCriteriaForParameterizedAttribute(const NSDictionary *parameterizedAttribute)
626 {
627     AccessibilitySearchTextCriteria criteria;
628     AccessibilityTextOperation operation;
629
630     NSString *activityParameter = [parameterizedAttribute objectForKey:NSAccessibilitySelectTextActivity];
631     NSString *ambiguityResolutionParameter = [parameterizedAttribute objectForKey:NSAccessibilitySelectTextAmbiguityResolution];
632     NSString *replacementStringParameter = [parameterizedAttribute objectForKey:NSAccessibilitySelectTextReplacementString];
633     NSArray *searchStringsParameter = [parameterizedAttribute objectForKey:NSAccessibilitySelectTextSearchStrings];
634
635     if ([activityParameter isKindOfClass:[NSString class]]) {
636         if ([activityParameter isEqualToString:NSAccessibilitySelectTextActivityFindAndReplace])
637             operation.type = AccessibilityTextOperationType::Replace;
638         else if ([activityParameter isEqualToString:kAXSelectTextActivityFindAndCapitalize])
639             operation.type = AccessibilityTextOperationType::Capitalize;
640         else if ([activityParameter isEqualToString:kAXSelectTextActivityFindAndLowercase])
641             operation.type = AccessibilityTextOperationType::Lowercase;
642         else if ([activityParameter isEqualToString:kAXSelectTextActivityFindAndUppercase])
643             operation.type = AccessibilityTextOperationType::Uppercase;
644     }
645
646     criteria.direction = AccessibilitySearchTextDirection::Closest;
647     if ([ambiguityResolutionParameter isKindOfClass:[NSString class]]) {
648         if ([ambiguityResolutionParameter isEqualToString:NSAccessibilitySelectTextAmbiguityResolutionClosestAfterSelection])
649             criteria.direction = AccessibilitySearchTextDirection::Forward;
650         else if ([ambiguityResolutionParameter isEqualToString:NSAccessibilitySelectTextAmbiguityResolutionClosestBeforeSelection])
651             criteria.direction = AccessibilitySearchTextDirection::Backward;
652     }
653
654     if ([replacementStringParameter isKindOfClass:[NSString class]])
655         operation.replacementText = replacementStringParameter;
656
657     if ([searchStringsParameter isKindOfClass:[NSArray class]]) {
658         size_t searchStringsCount = static_cast<size_t>([searchStringsParameter count]);
659         criteria.searchStrings.reserveInitialCapacity(searchStringsCount);
660         for (NSString *searchString in searchStringsParameter) {
661             if ([searchString isKindOfClass:[NSString class]])
662                 criteria.searchStrings.uncheckedAppend(searchString);
663         }
664     }
665
666     return std::make_pair(criteria, operation);
667 }
668
669 static AccessibilitySearchTextCriteria accessibilitySearchTextCriteriaForParameterizedAttribute(const NSDictionary *params)
670 {
671     AccessibilitySearchTextCriteria criteria;
672
673     NSArray *searchStrings = [params objectForKey:NSAccessibilitySearchTextSearchStrings];
674     NSString *start = [params objectForKey:NSAccessibilitySearchTextStartFrom];
675     NSString *direction = [params objectForKey:NSAccessibilitySearchTextDirection];
676
677     if ([searchStrings isKindOfClass:[NSArray class]]) {
678         size_t searchStringsCount = static_cast<size_t>([searchStrings count]);
679         criteria.searchStrings.reserveInitialCapacity(searchStringsCount);
680         for (NSString *searchString in searchStrings) {
681             if ([searchString isKindOfClass:[NSString class]])
682                 criteria.searchStrings.uncheckedAppend(searchString);
683         }
684     }
685
686     if ([start isKindOfClass:[NSString class]]) {
687         if ([start isEqualToString:NSAccessibilitySearchTextStartFromBegin])
688             criteria.start = AccessibilitySearchTextStartFrom::Begin;
689         else if ([start isEqualToString:NSAccessibilitySearchTextStartFromEnd])
690             criteria.start = AccessibilitySearchTextStartFrom::End;
691     }
692
693     if ([direction isKindOfClass:[NSString class]]) {
694         if ([direction isEqualToString:NSAccessibilitySearchTextDirectionBackward])
695             criteria.direction = AccessibilitySearchTextDirection::Backward;
696         else if ([direction isEqualToString:NSAccessibilitySearchTextDirectionClosest])
697             criteria.direction = AccessibilitySearchTextDirection::Closest;
698         else if ([direction isEqualToString:NSAccessibilitySearchTextDirectionAll])
699             criteria.direction = AccessibilitySearchTextDirection::All;
700     }
701
702     return criteria;
703 }
704
705 static AccessibilityTextOperation accessibilityTextOperationForParameterizedAttribute(WebAccessibilityObjectWrapper *obj, const NSDictionary *parameterizedAttribute)
706 {
707     AccessibilityTextOperation operation;
708
709     NSArray *markerRanges = [parameterizedAttribute objectForKey:NSAccessibilityTextOperationMarkerRanges];
710     NSString *operationType = [parameterizedAttribute objectForKey:NSAccessibilityTextOperationType];
711     NSString *replacementString = [parameterizedAttribute objectForKey:NSAccessibilityTextOperationReplacementString];
712
713     if ([markerRanges isKindOfClass:[NSArray class]]) {
714         size_t count = static_cast<size_t>(markerRanges.count);
715         operation.textRanges.reserveInitialCapacity(count);
716         for (id markerRange : markerRanges)
717             operation.textRanges.append([obj rangeForTextMarkerRange:markerRange]);
718     }
719
720     if ([operationType isKindOfClass:[NSString class]]) {
721         if ([operationType isEqualToString:NSAccessibilityTextOperationReplace])
722             operation.type = AccessibilityTextOperationType::Replace;
723         else if ([operationType isEqualToString:NSAccessibilityTextOperationCapitalize])
724             operation.type = AccessibilityTextOperationType::Capitalize;
725         else if ([operationType isEqualToString:NSAccessibilityTextOperationLowercase])
726             operation.type = AccessibilityTextOperationType::Lowercase;
727         else if ([operationType isEqualToString:NSAccessibilityTextOperationUppercase])
728             operation.type = AccessibilityTextOperationType::Uppercase;
729     }
730
731     if ([replacementString isKindOfClass:[NSString class]])
732         operation.replacementText = replacementString;
733
734     return operation;
735 }
736
737 static std::pair<RefPtr<Range>, AccessibilitySearchDirection> accessibilityMisspellingSearchCriteriaForParameterizedAttribute(WebAccessibilityObjectWrapper *object, const NSDictionary *params)
738 {
739     std::pair<RefPtr<Range>, AccessibilitySearchDirection> criteria;
740
741     criteria.first = [object rangeForTextMarkerRange:[params objectForKey:@"AXStartTextMarkerRange"]];
742
743     NSNumber *forward = [params objectForKey:NSAccessibilitySearchTextDirection];
744     if ([forward isKindOfClass:[NSNumber class]])
745         criteria.second = [forward boolValue] ? AccessibilitySearchDirection::Next : AccessibilitySearchDirection::Previous;
746     else
747         criteria.second = AccessibilitySearchDirection::Next;
748
749     return criteria;
750 }
751
752 #pragma mark Text Marker helpers
753
754 static BOOL getBytesFromAXTextMarker(CFTypeRef textMarker, void* bytes, size_t length)
755 {
756     if (!textMarker)
757         return NO;
758
759     AXTextMarkerRef ref = (AXTextMarkerRef)textMarker;
760     ASSERT(CFGetTypeID(ref) == AXTextMarkerGetTypeID());
761     if (CFGetTypeID(ref) != AXTextMarkerGetTypeID())
762         return NO;
763
764     CFIndex expectedLength = length;
765     if (AXTextMarkerGetLength(ref) != expectedLength)
766         return NO;
767
768     memcpy(bytes, AXTextMarkerGetBytePtr(ref), length);
769     return YES;
770 }
771
772 static bool isTextMarkerIgnored(id textMarker)
773 {
774     if (!textMarker)
775         return false;
776     
777     TextMarkerData textMarkerData;
778     if (!getBytesFromAXTextMarker((__bridge CFTypeRef)textMarker, &textMarkerData, sizeof(textMarkerData)))
779         return false;
780     
781     return textMarkerData.ignored;
782 }
783
784 - (AccessibilityObject*)accessibilityObjectForTextMarker:(id)textMarker
785 {
786     return accessibilityObjectForTextMarker(self.axBackingObject->axObjectCache(), textMarker);
787 }
788
789 static AccessibilityObject* accessibilityObjectForTextMarker(AXObjectCache* cache, id textMarker)
790 {
791     if (!textMarker || !cache || isTextMarkerIgnored(textMarker))
792         return nullptr;
793     
794     TextMarkerData textMarkerData;
795     if (!getBytesFromAXTextMarker((__bridge CFTypeRef)textMarker, &textMarkerData, sizeof(textMarkerData)))
796         return nullptr;
797     return cache->accessibilityObjectForTextMarkerData(textMarkerData);
798 }
799
800 - (id)textMarkerRangeFromRange:(const RefPtr<Range>)range
801 {
802     if (auto* backingObject = self.axBackingObject)
803         return textMarkerRangeFromRange(backingObject->axObjectCache(), range);
804     return nil;
805 }
806
807 static id textMarkerRangeFromRange(AXObjectCache* cache, const RefPtr<Range> range)
808 {
809     id startTextMarker = startOrEndTextmarkerForRange(cache, range, true);
810     id endTextMarker = startOrEndTextmarkerForRange(cache, range, false);
811     return textMarkerRangeFromMarkers(startTextMarker, endTextMarker);
812 }
813
814 - (id)startOrEndTextMarkerForRange:(const RefPtr<Range>)range isStart:(BOOL)isStart
815 {
816     return startOrEndTextmarkerForRange(self.axBackingObject->axObjectCache(), range, isStart);
817 }
818
819 static id startOrEndTextmarkerForRange(AXObjectCache* cache, RefPtr<Range> range, bool isStart)
820 {
821     if (!cache)
822         return nil;
823     
824     TextMarkerData textMarkerData;
825     cache->startOrEndTextMarkerDataForRange(textMarkerData, range, isStart);
826     if (!textMarkerData.axID)
827         return nil;
828     
829     return CFBridgingRelease(AXTextMarkerCreate(kCFAllocatorDefault, (const UInt8*)&textMarkerData, sizeof(textMarkerData)));
830 }
831
832 static id nextTextMarkerForCharacterOffset(AXObjectCache* cache, CharacterOffset& characterOffset)
833 {
834     if (!cache)
835         return nil;
836     
837     TextMarkerData textMarkerData;
838     cache->textMarkerDataForNextCharacterOffset(textMarkerData, characterOffset);
839     if (!textMarkerData.axID)
840         return nil;
841     return CFBridgingRelease(AXTextMarkerCreate(kCFAllocatorDefault, (const UInt8*)&textMarkerData, sizeof(textMarkerData)));
842 }
843
844 static id previousTextMarkerForCharacterOffset(AXObjectCache* cache, CharacterOffset& characterOffset)
845 {
846     if (!cache)
847         return nil;
848     
849     TextMarkerData textMarkerData;
850     cache->textMarkerDataForPreviousCharacterOffset(textMarkerData, characterOffset);
851     if (!textMarkerData.axID)
852         return nil;
853     return CFBridgingRelease(AXTextMarkerCreate(kCFAllocatorDefault, (const UInt8*)&textMarkerData, sizeof(textMarkerData)));
854 }
855
856 - (id)nextTextMarkerForCharacterOffset:(CharacterOffset&)characterOffset
857 {
858     return nextTextMarkerForCharacterOffset(self.axBackingObject->axObjectCache(), characterOffset);
859 }
860
861 - (id)previousTextMarkerForCharacterOffset:(CharacterOffset&)characterOffset
862 {
863     return previousTextMarkerForCharacterOffset(self.axBackingObject->axObjectCache(), characterOffset);
864 }
865
866 - (id)textMarkerForCharacterOffset:(CharacterOffset&)characterOffset
867 {
868     return textMarkerForCharacterOffset(self.axBackingObject->axObjectCache(), characterOffset);
869 }
870
871 static id textMarkerForCharacterOffset(AXObjectCache* cache, const CharacterOffset& characterOffset)
872 {
873     if (!cache)
874         return nil;
875     
876     TextMarkerData textMarkerData;
877     cache->textMarkerDataForCharacterOffset(textMarkerData, characterOffset);
878     if (!textMarkerData.axID && !textMarkerData.ignored)
879         return nil;
880     
881     return CFBridgingRelease(AXTextMarkerCreate(kCFAllocatorDefault, (const UInt8*)&textMarkerData, sizeof(textMarkerData)));
882 }
883
884 - (RefPtr<Range>)rangeForTextMarkerRange:(id)textMarkerRange
885 {
886     if (!textMarkerRange)
887         return nullptr;
888     
889     id startTextMarker = AXTextMarkerRangeStart(textMarkerRange);
890     id endTextMarker = AXTextMarkerRangeEnd(textMarkerRange);
891     
892     if (!startTextMarker || !endTextMarker)
893         return nullptr;
894     
895     AXObjectCache* cache = self.axBackingObject->axObjectCache();
896     if (!cache)
897         return nullptr;
898     
899     CharacterOffset startCharacterOffset = [self characterOffsetForTextMarker:startTextMarker];
900     CharacterOffset endCharacterOffset = [self characterOffsetForTextMarker:endTextMarker];
901     return cache->rangeForUnorderedCharacterOffsets(startCharacterOffset, endCharacterOffset);
902 }
903
904 static CharacterOffset characterOffsetForTextMarker(AXObjectCache* cache, CFTypeRef textMarker)
905 {
906     if (!cache || !textMarker)
907         return CharacterOffset();
908     
909     TextMarkerData textMarkerData;
910     if (!getBytesFromAXTextMarker(textMarker, &textMarkerData, sizeof(textMarkerData)))
911         return CharacterOffset();
912     
913     return cache->characterOffsetForTextMarkerData(textMarkerData);
914 }
915
916 - (CharacterOffset)characterOffsetForTextMarker:(id)textMarker
917 {
918     return characterOffsetForTextMarker(self.axBackingObject->axObjectCache(), (__bridge CFTypeRef)textMarker);
919 }
920
921 static id textMarkerForVisiblePosition(AXObjectCache* cache, const VisiblePosition& visiblePos)
922 {
923     ASSERT(cache);
924     if (!cache)
925         return nil;
926     
927     auto textMarkerData = cache->textMarkerDataForVisiblePosition(visiblePos);
928     if (!textMarkerData)
929         return nil;
930
931     return CFBridgingRelease(AXTextMarkerCreate(kCFAllocatorDefault, (const UInt8*)&textMarkerData.value(), sizeof(textMarkerData.value())));
932 }
933
934 - (id)textMarkerForVisiblePosition:(const VisiblePosition &)visiblePos
935 {
936     return textMarkerForVisiblePosition(self.axBackingObject->axObjectCache(), visiblePos);
937 }
938
939 - (id)textMarkerForFirstPositionInTextControl:(HTMLTextFormControlElement &)textControl
940 {
941     auto *cache = self.axBackingObject->axObjectCache();
942     if (!cache)
943         return nil;
944
945     auto textMarkerData = cache->textMarkerDataForFirstPositionInTextControl(textControl);
946     if (!textMarkerData)
947         return nil;
948
949     return CFBridgingRelease(AXTextMarkerCreate(kCFAllocatorDefault, (const UInt8*)&textMarkerData.value(), sizeof(textMarkerData.value())));
950 }
951
952 static VisiblePosition visiblePositionForTextMarker(AXObjectCache* cache, CFTypeRef textMarker)
953 {
954     ASSERT(cache);
955     
956     if (!textMarker)
957         return VisiblePosition();
958     TextMarkerData textMarkerData;
959     if (!getBytesFromAXTextMarker(textMarker, &textMarkerData, sizeof(textMarkerData)))
960         return VisiblePosition();
961     
962     return cache->visiblePositionForTextMarkerData(textMarkerData);
963 }
964
965 - (VisiblePosition)visiblePositionForTextMarker:(id)textMarker
966 {
967     return visiblePositionForTextMarker(self.axBackingObject->axObjectCache(), (__bridge CFTypeRef)textMarker);
968 }
969
970 static VisiblePosition visiblePositionForStartOfTextMarkerRange(AXObjectCache* cache, id textMarkerRange)
971 {
972     return visiblePositionForTextMarker(cache, (__bridge CFTypeRef)AXTextMarkerRangeStart(textMarkerRange));
973 }
974
975 static VisiblePosition visiblePositionForEndOfTextMarkerRange(AXObjectCache* cache, id textMarkerRange)
976 {
977     return visiblePositionForTextMarker(cache, (__bridge CFTypeRef)AXTextMarkerRangeEnd(textMarkerRange));
978 }
979
980 static id textMarkerRangeFromMarkers(id textMarker1, id textMarker2)
981 {
982     if (!textMarker1 || !textMarker2)
983         return nil;
984     
985     return AXTextMarkerRange(textMarker1, textMarker2);
986 }
987
988 // When modifying attributed strings, the range can come from a source which may provide faulty information (e.g. the spell checker).
989 // To protect against such cases the range should be validated before adding or removing attributes.
990 static BOOL AXAttributedStringRangeIsValid(NSAttributedString *attrString, NSRange range)
991 {
992     return (range.location < [attrString length] && NSMaxRange(range) <= [attrString length]);
993 }
994
995 static void AXAttributeStringSetFont(NSMutableAttributedString *attrString, NSString *attribute, CTFontRef font, NSRange range)
996 {
997     if (!AXAttributedStringRangeIsValid(attrString, range))
998         return;
999
1000     if (font) {
1001         NSDictionary *dictionary = @{
1002             NSAccessibilityFontNameKey: (__bridge NSString *)adoptCF(CTFontCopyPostScriptName(font)).get(),
1003             NSAccessibilityFontFamilyKey: (__bridge NSString *)adoptCF(CTFontCopyFamilyName(font)).get(),
1004             NSAccessibilityVisibleNameKey: (__bridge NSString *)adoptCF(CTFontCopyDisplayName(font)).get(),
1005             NSAccessibilityFontSizeKey: @(CTFontGetSize(font)),
1006         };
1007         [attrString addAttribute:attribute value:dictionary range:range];
1008     } else
1009         [attrString removeAttribute:attribute range:range];
1010     
1011 }
1012
1013 static void AXAttributeStringSetColor(NSMutableAttributedString* attrString, NSString* attribute, NSColor* color, NSRange range)
1014 {
1015     if (!AXAttributedStringRangeIsValid(attrString, range))
1016         return;
1017
1018     if (color) {
1019         CGColorRef cgColor = color.CGColor;
1020         id existingColor = [attrString attribute:attribute atIndex:range.location effectiveRange:nil];
1021         if (!existingColor || !CGColorEqualToColor((__bridge CGColorRef)existingColor, cgColor))
1022             [attrString addAttribute:attribute value:(__bridge id)cgColor range:range];
1023     } else
1024         [attrString removeAttribute:attribute range:range];
1025 }
1026
1027 static void AXAttributeStringSetNumber(NSMutableAttributedString* attrString, NSString* attribute, NSNumber* number, NSRange range)
1028 {
1029     if (!AXAttributedStringRangeIsValid(attrString, range))
1030         return;
1031     
1032     if (number)
1033         [attrString addAttribute:attribute value:number range:range];
1034     else
1035         [attrString removeAttribute:attribute range:range];
1036 }
1037
1038 static void AXAttributeStringSetStyle(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
1039 {
1040     const RenderStyle& style = renderer->style();
1041     
1042     // set basic font info
1043     AXAttributeStringSetFont(attrString, NSAccessibilityFontTextAttribute, style.fontCascade().primaryFont().getCTFont(), range);
1044     
1045     // set basic colors
1046     AXAttributeStringSetColor(attrString, NSAccessibilityForegroundColorTextAttribute, nsColor(style.visitedDependentColor(CSSPropertyColor)), range);
1047     AXAttributeStringSetColor(attrString, NSAccessibilityBackgroundColorTextAttribute, nsColor(style.visitedDependentColor(CSSPropertyBackgroundColor)), range);
1048     
1049     // set super/sub scripting
1050     VerticalAlign alignment = style.verticalAlign();
1051     if (alignment == VerticalAlign::Sub)
1052         AXAttributeStringSetNumber(attrString, NSAccessibilitySuperscriptTextAttribute, [NSNumber numberWithInt:(-1)], range);
1053     else if (alignment == VerticalAlign::Super)
1054         AXAttributeStringSetNumber(attrString, NSAccessibilitySuperscriptTextAttribute, [NSNumber numberWithInt:1], range);
1055     else
1056         [attrString removeAttribute:NSAccessibilitySuperscriptTextAttribute range:range];
1057     
1058     // set shadow
1059     if (style.textShadow())
1060         AXAttributeStringSetNumber(attrString, NSAccessibilityShadowTextAttribute, @YES, range);
1061     else
1062         [attrString removeAttribute:NSAccessibilityShadowTextAttribute range:range];
1063     
1064     // set underline and strikethrough
1065     auto decor = style.textDecorationsInEffect();
1066     if (!(decor & TextDecoration::Underline)) {
1067         [attrString removeAttribute:NSAccessibilityUnderlineTextAttribute range:range];
1068         [attrString removeAttribute:NSAccessibilityUnderlineColorTextAttribute range:range];
1069     }
1070     
1071     if (!(decor & TextDecoration::LineThrough)) {
1072         [attrString removeAttribute:NSAccessibilityStrikethroughTextAttribute range:range];
1073         [attrString removeAttribute:NSAccessibilityStrikethroughColorTextAttribute range:range];
1074     }
1075
1076     if (decor & TextDecoration::Underline || decor & TextDecoration::LineThrough) {
1077         // FIXME: Should the underline style be reported here?
1078         auto decorationStyles = TextDecorationPainter::stylesForRenderer(*renderer, decor);
1079
1080         if (decor & TextDecoration::Underline) {
1081             AXAttributeStringSetNumber(attrString, NSAccessibilityUnderlineTextAttribute, @YES, range);
1082             AXAttributeStringSetColor(attrString, NSAccessibilityUnderlineColorTextAttribute, nsColor(decorationStyles.underlineColor), range);
1083         }
1084         
1085         if (decor & TextDecoration::LineThrough) {
1086             AXAttributeStringSetNumber(attrString, NSAccessibilityStrikethroughTextAttribute, @YES, range);
1087             AXAttributeStringSetColor(attrString, NSAccessibilityStrikethroughColorTextAttribute, nsColor(decorationStyles.linethroughColor), range);
1088         }
1089     }
1090     
1091     // Indicate background highlighting.
1092     for (Node* node = renderer->node(); node; node = node->parentNode()) {
1093         if (node->hasTagName(markTag))
1094             AXAttributeStringSetNumber(attrString, @"AXHighlight", @YES, range);
1095     }
1096 }
1097
1098 static void AXAttributeStringSetBlockquoteLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
1099 {
1100     if (!AXAttributedStringRangeIsValid(attrString, range))
1101         return;
1102     
1103     AccessibilityObject* obj = renderer->document().axObjectCache()->getOrCreate(renderer);
1104     int quoteLevel = obj->blockquoteLevel();
1105     
1106     if (quoteLevel)
1107         [attrString addAttribute:NSAccessibilityBlockQuoteLevelAttribute value:[NSNumber numberWithInt:quoteLevel] range:range];
1108     else
1109         [attrString removeAttribute:NSAccessibilityBlockQuoteLevelAttribute range:range];
1110 }
1111
1112 static void AXAttributeStringSetSpelling(NSMutableAttributedString* attrString, Node* node, StringView text, NSRange range)
1113 {
1114     ASSERT(node);
1115     
1116     // If this node is not inside editable content, do not run the spell checker on the text.
1117     if (!node->document().axObjectCache()->rootAXEditableElement(node))
1118         return;
1119
1120     if (unifiedTextCheckerEnabled(node->document().frame())) {
1121         // Check the spelling directly since document->markersForNode() does not store the misspelled marking when the cursor is in a word.
1122         TextCheckerClient* checker = node->document().frame()->editor().textChecker();
1123         
1124         // checkTextOfParagraph is the only spelling/grammar checker implemented in WK1 and WK2
1125         Vector<TextCheckingResult> results;
1126         checkTextOfParagraph(*checker, text, TextCheckingType::Spelling, results, node->document().frame()->selection().selection());
1127         
1128         size_t size = results.size();
1129         for (unsigned i = 0; i < size; i++) {
1130             const TextCheckingResult& result = results[i];
1131             AXAttributeStringSetNumber(attrString, NSAccessibilityMisspelledTextAttribute, @YES, NSMakeRange(result.location + range.location, result.length));
1132 #if PLATFORM(MAC)
1133             AXAttributeStringSetNumber(attrString, NSAccessibilityMarkedMisspelledTextAttribute, @YES, NSMakeRange(result.location + range.location, result.length));
1134 #endif
1135         }
1136         return;
1137     }
1138
1139     for (unsigned currentPosition = 0; currentPosition < text.length(); ) {
1140         int misspellingLocation = -1;
1141         int misspellingLength = 0;
1142         node->document().frame()->editor().textChecker()->checkSpellingOfString(text.substring(currentPosition), &misspellingLocation, &misspellingLength);
1143         if (misspellingLocation == -1 || !misspellingLength)
1144             break;
1145         
1146         NSRange spellRange = NSMakeRange(range.location + currentPosition + misspellingLocation, misspellingLength);
1147         AXAttributeStringSetNumber(attrString, NSAccessibilityMisspelledTextAttribute, @YES, spellRange);
1148 #if PLATFORM(MAC)
1149         AXAttributeStringSetNumber(attrString, NSAccessibilityMarkedMisspelledTextAttribute, @YES, spellRange);
1150 #endif
1151
1152         currentPosition += misspellingLocation + misspellingLength;
1153     }
1154 }
1155
1156 static void AXAttributeStringSetExpandedTextValue(NSMutableAttributedString *attrString, RenderObject* renderer, NSRange range)
1157 {
1158     if (!renderer || !AXAttributedStringRangeIsValid(attrString, range))
1159         return;
1160     AccessibilityObject* axObject = renderer->document().axObjectCache()->getOrCreate(renderer);
1161     if (axObject->supportsExpandedTextValue())
1162         [attrString addAttribute:NSAccessibilityExpandedTextValueAttribute value:axObject->expandedTextValue() range:range];
1163     else
1164         [attrString removeAttribute:NSAccessibilityExpandedTextValueAttribute range:range];
1165 }
1166
1167 static void AXAttributeStringSetHeadingLevel(NSMutableAttributedString* attrString, RenderObject* renderer, NSRange range)
1168 {
1169     if (!renderer)
1170         return;
1171     
1172     if (!AXAttributedStringRangeIsValid(attrString, range))
1173         return;
1174     
1175     // Sometimes there are objects between the text and the heading.
1176     // In those cases the parent hierarchy should be queried to see if there is a heading level.
1177     int parentHeadingLevel = 0;
1178     AccessibilityObject* parentObject = renderer->document().axObjectCache()->getOrCreate(renderer->parent());
1179     for (; parentObject; parentObject = parentObject->parentObject()) {
1180         parentHeadingLevel = parentObject->headingLevel();
1181         if (parentHeadingLevel)
1182             break;
1183     }
1184     
1185     if (parentHeadingLevel)
1186         [attrString addAttribute:@"AXHeadingLevel" value:[NSNumber numberWithInt:parentHeadingLevel] range:range];
1187     else
1188         [attrString removeAttribute:@"AXHeadingLevel" range:range];
1189 }
1190
1191 static void AXAttributeStringSetElement(NSMutableAttributedString* attrString, NSString* attribute, AccessibilityObject* object, NSRange range)
1192 {
1193     if (!AXAttributedStringRangeIsValid(attrString, range))
1194         return;
1195     
1196     if (is<AccessibilityRenderObject>(object)) {
1197         // make a serializable AX object
1198         
1199         RenderObject* renderer = downcast<AccessibilityRenderObject>(*object).renderer();
1200         if (!renderer)
1201             return;
1202         
1203         AXObjectCache* cache = renderer->document().axObjectCache();
1204         if (!cache)
1205             return;
1206         
1207         id objectWrapper = object->wrapper();
1208         if ([attribute isEqualToString:NSAccessibilityAttachmentTextAttribute] && object->isAttachment() && [objectWrapper attachmentView])
1209             objectWrapper = [objectWrapper attachmentView];
1210         
1211         AXUIElementRef axElement = NSAccessibilityCreateAXUIElementRef(objectWrapper);
1212         if (axElement) {
1213             [attrString addAttribute:attribute value:(__bridge id)axElement range:range];
1214             CFRelease(axElement);
1215         }
1216     } else
1217         [attrString removeAttribute:attribute range:range];
1218 }
1219
1220 static void AXAttributedStringAppendText(NSMutableAttributedString* attrString, Node* node, StringView text, bool spellCheck)
1221 {
1222     // skip invisible text
1223     RenderObject* renderer = node->renderer();
1224     if (!renderer)
1225         return;
1226     
1227     // easier to calculate the range before appending the string
1228     NSRange attrStringRange = NSMakeRange([attrString length], text.length());
1229     
1230     // append the string from this node
1231     [[attrString mutableString] appendString:text.createNSStringWithoutCopying().get()];
1232     
1233     // add new attributes and remove irrelevant inherited ones
1234     // NOTE: color attributes are handled specially because -[NSMutableAttributedString addAttribute: value: range:] does not merge
1235     // identical colors.  Workaround is to not replace an existing color attribute if it matches what we are adding.  This also means
1236     // we cannot just pre-remove all inherited attributes on the appended string, so we have to remove the irrelevant ones individually.
1237     
1238     // remove inherited attachment from prior AXAttributedStringAppendReplaced
1239     [attrString removeAttribute:NSAccessibilityAttachmentTextAttribute range:attrStringRange];
1240     if (spellCheck) {
1241 #if PLATFORM(MAC)
1242         [attrString removeAttribute:NSAccessibilityMarkedMisspelledTextAttribute range:attrStringRange];
1243 #endif
1244         [attrString removeAttribute:NSAccessibilityMisspelledTextAttribute range:attrStringRange];
1245     }
1246     
1247     // set new attributes
1248     AXAttributeStringSetStyle(attrString, renderer, attrStringRange);
1249     AXAttributeStringSetHeadingLevel(attrString, renderer, attrStringRange);
1250     AXAttributeStringSetBlockquoteLevel(attrString, renderer, attrStringRange);
1251     AXAttributeStringSetExpandedTextValue(attrString, renderer, attrStringRange);
1252     AXAttributeStringSetElement(attrString, NSAccessibilityLinkTextAttribute, AccessibilityObject::anchorElementForNode(node), attrStringRange);
1253     
1254     // do spelling last because it tends to break up the range
1255     if (spellCheck)
1256         AXAttributeStringSetSpelling(attrString, node, text, attrStringRange);
1257 }
1258
1259 static NSString* nsStringForReplacedNode(Node* replacedNode)
1260 {
1261     // we should always be given a rendered node and a replaced node, but be safe
1262     // replaced nodes are either attachments (widgets) or images
1263     if (!replacedNode || !isRendererReplacedElement(replacedNode->renderer()) || replacedNode->isTextNode()) {
1264         ASSERT_NOT_REACHED();
1265         return nil;
1266     }
1267     
1268     // create an AX object, but skip it if it is not supposed to be seen
1269     RefPtr<AccessibilityObject> obj = replacedNode->renderer()->document().axObjectCache()->getOrCreate(replacedNode->renderer());
1270     if (obj->accessibilityIsIgnored())
1271         return nil;
1272     
1273     // use the attachmentCharacter to represent the replaced node
1274     const UniChar attachmentChar = NSAttachmentCharacter;
1275     return [NSString stringWithCharacters:&attachmentChar length:1];
1276 }
1277
1278 - (NSAttributedString*)doAXAttributedStringForTextMarkerRange:(id)textMarkerRange spellCheck:(BOOL)spellCheck
1279 {
1280     return Accessibility::retrieveValueFromMainThread<NSAttributedString *>([&textMarkerRange, &spellCheck, protectedSelf = RetainPtr<WebAccessibilityObjectWrapper>(self)] () -> NSAttributedString * {
1281         auto* backingObject = protectedSelf.get().axBackingObject;
1282         if (!backingObject)
1283             return nil;
1284
1285         RefPtr<Range> range = [protectedSelf rangeForTextMarkerRange:textMarkerRange];
1286         NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] init];
1287         TextIterator it(range.get());
1288         while (!it.atEnd()) {
1289             // locate the node and starting offset for this range
1290             Node& node = it.range()->startContainer();
1291             ASSERT(&node == &it.range()->endContainer());
1292             int offset = it.range()->startOffset();
1293
1294             // non-zero length means textual node, zero length means replaced node (AKA "attachments" in AX)
1295             if (it.text().length()) {
1296                 // Add the text of the list marker item if necessary.
1297                 String listMarkerText = AccessibilityObject::listMarkerTextForNodeAndPosition(&node, VisiblePosition(it.range()->startPosition()));
1298                 if (!listMarkerText.isEmpty())
1299                     AXAttributedStringAppendText(attrString, &node, listMarkerText, spellCheck);
1300                 AXAttributedStringAppendText(attrString, &node, it.text(), spellCheck);
1301             } else {
1302                 Node* replacedNode = node.traverseToChildAt(offset);
1303                 NSString *attachmentString = nsStringForReplacedNode(replacedNode);
1304                 if (attachmentString) {
1305                     NSRange attrStringRange = NSMakeRange([attrString length], [attachmentString length]);
1306
1307                     // append the placeholder string
1308                     [[attrString mutableString] appendString:attachmentString];
1309
1310                     // remove all inherited attributes
1311                     [attrString setAttributes:nil range:attrStringRange];
1312
1313                     // add the attachment attribute
1314                     AccessibilityObject* obj = replacedNode->renderer()->document().axObjectCache()->getOrCreate(replacedNode->renderer());
1315                     AXAttributeStringSetElement(attrString, NSAccessibilityAttachmentTextAttribute, obj, attrStringRange);
1316                 }
1317             }
1318             it.advance();
1319         }
1320
1321         return [attrString autorelease];
1322     });
1323 }
1324
1325 static id textMarkerRangeFromVisiblePositions(AXObjectCache* cache, const VisiblePosition& startPosition, const VisiblePosition& endPosition)
1326 {
1327     if (!cache)
1328         return nil;
1329     
1330     id startTextMarker = textMarkerForVisiblePosition(cache, startPosition);
1331     id endTextMarker = textMarkerForVisiblePosition(cache, endPosition);
1332     return textMarkerRangeFromMarkers(startTextMarker, endTextMarker);
1333 }
1334
1335 - (id)textMarkerRangeFromVisiblePositions:(const VisiblePosition&)startPosition endPosition:(const VisiblePosition&)endPosition
1336 {
1337     return textMarkerRangeFromVisiblePositions(self.axBackingObject->axObjectCache(), startPosition, endPosition);
1338 }
1339
1340 ALLOW_DEPRECATED_IMPLEMENTATIONS_BEGIN
1341 - (NSArray*)accessibilityActionNames
1342 ALLOW_DEPRECATED_IMPLEMENTATIONS_END
1343 {
1344     auto* backingObject = self.updateObjectBackingStore;
1345     if (!backingObject)
1346         return nil;
1347
1348     // All elements should get ShowMenu and ScrollToVisible.
1349     // But certain earlier VoiceOver versions do not support scroll to visible, and it confuses them to see it in the list.
1350     static NSArray *defaultElementActions = [[NSArray alloc] initWithObjects:NSAccessibilityShowMenuAction, NSAccessibilityScrollToVisibleAction, nil];
1351
1352     // Action elements allow Press.
1353     // The order is important to VoiceOver, which expects the 'default' action to be the first action. In this case the default action should be press.
1354     static NSArray *actionElementActions = [[NSArray alloc] initWithObjects:NSAccessibilityPressAction, NSAccessibilityShowMenuAction, NSAccessibilityScrollToVisibleAction, nil];
1355
1356     // Menu elements allow Press and Cancel.
1357     static NSArray *menuElementActions = [[actionElementActions arrayByAddingObject:NSAccessibilityCancelAction] retain];
1358
1359     // Slider elements allow Increment/Decrement.
1360     static NSArray *sliderActions = [[defaultElementActions arrayByAddingObjectsFromArray:[NSArray arrayWithObjects:NSAccessibilityIncrementAction, NSAccessibilityDecrementAction, nil]] retain];
1361
1362     NSArray *actions;
1363     if (backingObject->supportsPressAction())
1364         actions = actionElementActions;
1365     else if (backingObject->isMenuRelated())
1366         actions = menuElementActions;
1367     else if (backingObject->isSlider())
1368         actions = sliderActions;
1369     else if (backingObject->isAttachment())
1370         actions = [[self attachmentView] accessibilityActionNames];
1371     else
1372         actions = defaultElementActions;
1373
1374     return actions;
1375 }
1376
1377 - (NSArray*)additionalAccessibilityAttributeNames
1378 {
1379     auto* backingObject = self.axBackingObject;
1380     if (!backingObject)
1381         return nil;
1382
1383     NSMutableArray *additional = [NSMutableArray array];
1384     if (backingObject->supportsARIAOwns())
1385         [additional addObject:NSAccessibilityOwnsAttribute];
1386
1387     if (backingObject->isToggleButton())
1388         [additional addObject:NSAccessibilityValueAttribute];
1389
1390     if (backingObject->supportsExpanded() || backingObject->isSummary())
1391         [additional addObject:NSAccessibilityExpandedAttribute];
1392
1393     if (backingObject->isScrollbar()
1394         || backingObject->isRadioGroup()
1395         || backingObject->isSplitter()
1396         || backingObject->isToolbar())
1397         [additional addObject:NSAccessibilityOrientationAttribute];
1398
1399     if (backingObject->supportsARIADragging())
1400         [additional addObject:NSAccessibilityGrabbedAttribute];
1401
1402     if (backingObject->supportsARIADropping())
1403         [additional addObject:NSAccessibilityDropEffectsAttribute];
1404
1405     if (backingObject->isTable() && backingObject->isExposable() && backingObject->supportsSelectedRows())
1406         [additional addObject:NSAccessibilitySelectedRowsAttribute];
1407
1408     if (backingObject->supportsLiveRegion()) {
1409         [additional addObject:NSAccessibilityARIALiveAttribute];
1410         [additional addObject:NSAccessibilityARIARelevantAttribute];
1411     }
1412
1413     if (backingObject->supportsSetSize())
1414         [additional addObject:NSAccessibilityARIASetSizeAttribute];
1415
1416     if (backingObject->supportsPosInSet())
1417         [additional addObject:NSAccessibilityARIAPosInSetAttribute];
1418
1419     AccessibilitySortDirection sortDirection = backingObject->sortDirection();
1420     if (sortDirection != AccessibilitySortDirection::None && sortDirection != AccessibilitySortDirection::Invalid)
1421         [additional addObject:NSAccessibilitySortDirectionAttribute];
1422
1423     // If an object is a child of a live region, then add these
1424     if (backingObject->isInsideLiveRegion())
1425         [additional addObject:NSAccessibilityARIAAtomicAttribute];
1426
1427     // All objects should expose the ARIA busy attribute (ARIA 1.1 with ISSUE-538).
1428     [additional addObject:NSAccessibilityElementBusyAttribute];
1429
1430     // Popup buttons on the Mac expose the value attribute.
1431     if (backingObject->isPopUpButton())
1432         [additional addObject:NSAccessibilityValueAttribute];
1433
1434     if (backingObject->supportsDatetimeAttribute())
1435         [additional addObject:NSAccessibilityDatetimeValueAttribute];
1436
1437     if (backingObject->supportsRequiredAttribute())
1438         [additional addObject:NSAccessibilityRequiredAttribute];
1439
1440     if (backingObject->hasPopup())
1441         [additional addObject:NSAccessibilityHasPopupAttribute];
1442
1443     if (backingObject->isMathRoot()) {
1444         // The index of a square root is always known, so there's no object associated with it.
1445         if (!backingObject->isMathSquareRoot())
1446             [additional addObject:NSAccessibilityMathRootIndexAttribute];
1447         [additional addObject:NSAccessibilityMathRootRadicandAttribute];
1448     } else if (backingObject->isMathFraction()) {
1449         [additional addObject:NSAccessibilityMathFractionNumeratorAttribute];
1450         [additional addObject:NSAccessibilityMathFractionDenominatorAttribute];
1451         [additional addObject:NSAccessibilityMathLineThicknessAttribute];
1452     } else if (backingObject->isMathSubscriptSuperscript()) {
1453         [additional addObject:NSAccessibilityMathBaseAttribute];
1454         [additional addObject:NSAccessibilityMathSubscriptAttribute];
1455         [additional addObject:NSAccessibilityMathSuperscriptAttribute];
1456     } else if (backingObject->isMathUnderOver()) {
1457         [additional addObject:NSAccessibilityMathBaseAttribute];
1458         [additional addObject:NSAccessibilityMathUnderAttribute];
1459         [additional addObject:NSAccessibilityMathOverAttribute];
1460     } else if (backingObject->isMathFenced()) {
1461         [additional addObject:NSAccessibilityMathFencedOpenAttribute];
1462         [additional addObject:NSAccessibilityMathFencedCloseAttribute];
1463     } else if (backingObject->isMathMultiscript()) {
1464         [additional addObject:NSAccessibilityMathBaseAttribute];
1465         [additional addObject:NSAccessibilityMathPrescriptsAttribute];
1466         [additional addObject:NSAccessibilityMathPostscriptsAttribute];
1467     }
1468
1469     if (backingObject->supportsPath())
1470         [additional addObject:NSAccessibilityPathAttribute];
1471
1472     if (backingObject->supportsExpandedTextValue())
1473         [additional addObject:NSAccessibilityExpandedTextValueAttribute];
1474
1475 #if ENABLE(ACCESSIBILITY_ISOLATED_TREE)
1476     if (_AXUIElementRequestServicedBySecondaryAXThread() && AXObjectCache::clientSupportsIsolatedTree())
1477         [additional addObject:NSAccessibilityRelativeFrameAttribute];
1478 #endif
1479     
1480     return additional;
1481 }
1482
1483 ALLOW_DEPRECATED_IMPLEMENTATIONS_BEGIN
1484 - (NSArray*)accessibilityAttributeNames
1485 ALLOW_DEPRECATED_IMPLEMENTATIONS_END
1486 {
1487     auto* backingObject = self.axBackingObject;
1488     if (!backingObject)
1489         return nil;
1490
1491     if (backingObject->isAttachment())
1492         return [[self attachmentView] accessibilityAttributeNames];
1493
1494     static NSArray* attributes = nil;
1495     static NSArray* anchorAttrs = nil;
1496     static NSArray* webAreaAttrs = nil;
1497     static NSArray* textAttrs = nil;
1498     static NSArray* listAttrs = nil;
1499     static NSArray* listBoxAttrs = nil;
1500     static NSArray* rangeAttrs = nil;
1501     static NSArray* commonMenuAttrs = nil;
1502     static NSArray* menuAttrs = nil;
1503     static NSArray* menuBarAttrs = nil;
1504     static NSArray* menuItemAttrs = nil;
1505     static NSArray* menuButtonAttrs = nil;
1506     static NSArray* controlAttrs = nil;
1507     static NSArray* tableAttrs = nil;
1508     static NSArray* tableRowAttrs = nil;
1509     static NSArray* tableColAttrs = nil;
1510     static NSArray* tableCellAttrs = nil;
1511     static NSArray* groupAttrs = nil;
1512     static NSArray* inputImageAttrs = nil;
1513     static NSArray* passwordFieldAttrs = nil;
1514     static NSArray* tabListAttrs = nil;
1515     static NSArray* comboBoxAttrs = nil;
1516     static NSArray* outlineAttrs = nil;
1517     static NSArray* outlineRowAttrs = nil;
1518     static NSArray* buttonAttrs = nil;
1519     static NSArray* scrollViewAttrs = nil;
1520     static NSArray* incrementorAttrs = nil;
1521     NSMutableArray* tempArray;
1522     if (attributes == nil) {
1523         attributes = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,
1524             NSAccessibilitySubroleAttribute,
1525             NSAccessibilityRoleDescriptionAttribute,
1526             NSAccessibilityChildrenAttribute,
1527             NSAccessibilityHelpAttribute,
1528             NSAccessibilityParentAttribute,
1529             NSAccessibilityPositionAttribute,
1530             NSAccessibilitySizeAttribute,
1531             NSAccessibilityTitleAttribute,
1532             NSAccessibilityDescriptionAttribute,
1533             NSAccessibilityValueAttribute,
1534             NSAccessibilityFocusedAttribute,
1535             NSAccessibilityEnabledAttribute,
1536             NSAccessibilityWindowAttribute,
1537             @"AXSelectedTextMarkerRange",
1538             @"AXStartTextMarker",
1539             @"AXEndTextMarker",
1540             @"AXVisited",
1541             NSAccessibilityLinkedUIElementsAttribute,
1542             NSAccessibilitySelectedAttribute,
1543             NSAccessibilityBlockQuoteLevelAttribute,
1544             NSAccessibilityTopLevelUIElementAttribute,
1545             NSAccessibilityLanguageAttribute,
1546             NSAccessibilityDOMIdentifierAttribute,
1547             NSAccessibilityDOMClassListAttribute,
1548             NSAccessibilityFocusableAncestorAttribute,
1549             NSAccessibilityEditableAncestorAttribute,
1550             NSAccessibilityHighestEditableAncestorAttribute,
1551             nil];
1552     }
1553     if (commonMenuAttrs == nil) {
1554         commonMenuAttrs = [[NSArray alloc] initWithObjects: NSAccessibilityRoleAttribute,
1555                            NSAccessibilityRoleDescriptionAttribute,
1556                            NSAccessibilityChildrenAttribute,
1557                            NSAccessibilityParentAttribute,
1558                            NSAccessibilityEnabledAttribute,
1559                            NSAccessibilityPositionAttribute,
1560                            NSAccessibilitySizeAttribute,
1561                            nil];
1562     }
1563     if (anchorAttrs == nil) {
1564         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1565         [tempArray addObject:NSAccessibilityURLAttribute];
1566         [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1567         [tempArray addObject:NSAccessibilityLinkRelationshipTypeAttribute];
1568         anchorAttrs = [[NSArray alloc] initWithArray:tempArray];
1569         [tempArray release];
1570     }
1571     if (webAreaAttrs == nil) {
1572         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1573         // WebAreas should not expose AXSubrole.
1574         [tempArray removeObject:NSAccessibilitySubroleAttribute];
1575         // WebAreas should not expose ancestor attributes
1576         [tempArray removeObject:NSAccessibilityFocusableAncestorAttribute];
1577         [tempArray removeObject:NSAccessibilityEditableAncestorAttribute];
1578         [tempArray removeObject:NSAccessibilityHighestEditableAncestorAttribute];
1579         [tempArray addObject:@"AXLinkUIElements"];
1580         [tempArray addObject:@"AXLoaded"];
1581         [tempArray addObject:@"AXLayoutCount"];
1582         [tempArray addObject:NSAccessibilityLoadingProgressAttribute];
1583         [tempArray addObject:NSAccessibilityURLAttribute];
1584         [tempArray addObject:NSAccessibilityCaretBrowsingEnabledAttribute];
1585         [tempArray addObject:NSAccessibilityPreventKeyboardDOMEventDispatchAttribute];
1586         [tempArray addObject:NSAccessibilityWebSessionIDAttribute];
1587         webAreaAttrs = [[NSArray alloc] initWithArray:tempArray];
1588         [tempArray release];
1589     }
1590     if (textAttrs == nil) {
1591         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1592         [tempArray addObject:NSAccessibilityNumberOfCharactersAttribute];
1593         [tempArray addObject:NSAccessibilitySelectedTextAttribute];
1594         [tempArray addObject:NSAccessibilitySelectedTextRangeAttribute];
1595         [tempArray addObject:NSAccessibilityVisibleCharacterRangeAttribute];
1596         [tempArray addObject:NSAccessibilityInsertionPointLineNumberAttribute];
1597         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1598         [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1599         [tempArray addObject:NSAccessibilityRequiredAttribute];
1600         [tempArray addObject:NSAccessibilityInvalidAttribute];
1601         [tempArray addObject:NSAccessibilityPlaceholderValueAttribute];
1602         [tempArray addObject:NSAccessibilityValueAutofilledAttribute];
1603         textAttrs = [[NSArray alloc] initWithArray:tempArray];
1604         [tempArray release];
1605     }
1606     if (listAttrs == nil) {
1607         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1608         [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
1609         [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
1610         [tempArray addObject:NSAccessibilityOrientationAttribute];
1611         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1612         listAttrs = [[NSArray alloc] initWithArray:tempArray];
1613         [tempArray release];
1614     }
1615     if (listBoxAttrs == nil) {
1616         tempArray = [[NSMutableArray alloc] initWithArray:listAttrs];
1617         [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1618         [tempArray addObject:NSAccessibilityRequiredAttribute];
1619         [tempArray addObject:NSAccessibilityInvalidAttribute];
1620         [tempArray addObject:NSAccessibilityOrientationAttribute];
1621         listBoxAttrs = [[NSArray alloc] initWithArray:tempArray];
1622         [tempArray release];
1623     }
1624     if (rangeAttrs == nil) {
1625         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1626         [tempArray addObject:NSAccessibilityMinValueAttribute];
1627         [tempArray addObject:NSAccessibilityMaxValueAttribute];
1628         [tempArray addObject:NSAccessibilityOrientationAttribute];
1629         [tempArray addObject:NSAccessibilityValueDescriptionAttribute];
1630         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1631         rangeAttrs = [[NSArray alloc] initWithArray:tempArray];
1632         [tempArray release];
1633     }
1634     if (menuBarAttrs == nil) {
1635         tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
1636         [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
1637         [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
1638         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1639         [tempArray addObject:NSAccessibilityOrientationAttribute];
1640         menuBarAttrs = [[NSArray alloc] initWithArray:tempArray];
1641         [tempArray release];
1642     }
1643     if (menuAttrs == nil) {
1644         tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
1645         [tempArray addObject:NSAccessibilitySelectedChildrenAttribute];
1646         [tempArray addObject:NSAccessibilityVisibleChildrenAttribute];
1647         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1648         [tempArray addObject:NSAccessibilityOrientationAttribute];
1649         menuAttrs = [[NSArray alloc] initWithArray:tempArray];
1650         [tempArray release];
1651     }
1652     if (menuItemAttrs == nil) {
1653         tempArray = [[NSMutableArray alloc] initWithArray:commonMenuAttrs];
1654         [tempArray addObject:NSAccessibilityTitleAttribute];
1655         [tempArray addObject:NSAccessibilityDescriptionAttribute];
1656         [tempArray addObject:NSAccessibilityHelpAttribute];
1657         [tempArray addObject:NSAccessibilitySelectedAttribute];
1658         [tempArray addObject:NSAccessibilityValueAttribute];
1659         [tempArray addObject:(NSString*)kAXMenuItemCmdCharAttribute];
1660         [tempArray addObject:(NSString*)kAXMenuItemCmdVirtualKeyAttribute];
1661         [tempArray addObject:(NSString*)kAXMenuItemCmdGlyphAttribute];
1662         [tempArray addObject:(NSString*)kAXMenuItemCmdModifiersAttribute];
1663         [tempArray addObject:(NSString*)kAXMenuItemMarkCharAttribute];
1664         [tempArray addObject:(NSString*)kAXMenuItemPrimaryUIElementAttribute];
1665         [tempArray addObject:NSAccessibilityServesAsTitleForUIElementsAttribute];
1666         [tempArray addObject:NSAccessibilityFocusedAttribute];
1667         menuItemAttrs = [[NSArray alloc] initWithArray:tempArray];
1668         [tempArray release];
1669     }
1670     if (menuButtonAttrs == nil) {
1671         menuButtonAttrs = [[NSArray alloc] initWithObjects:NSAccessibilityRoleAttribute,
1672                            NSAccessibilityRoleDescriptionAttribute,
1673                            NSAccessibilityParentAttribute,
1674                            NSAccessibilityPositionAttribute,
1675                            NSAccessibilitySizeAttribute,
1676                            NSAccessibilityWindowAttribute,
1677                            NSAccessibilityEnabledAttribute,
1678                            NSAccessibilityFocusedAttribute,
1679                            NSAccessibilityTitleAttribute,
1680                            NSAccessibilityChildrenAttribute, nil];
1681     }
1682     if (controlAttrs == nil) {
1683         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1684         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1685         [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1686         [tempArray addObject:NSAccessibilityRequiredAttribute];
1687         [tempArray addObject:NSAccessibilityInvalidAttribute];
1688         controlAttrs = [[NSArray alloc] initWithArray:tempArray];
1689         [tempArray release];
1690     }
1691     if (incrementorAttrs == nil) {
1692         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1693         [tempArray addObject:NSAccessibilityIncrementButtonAttribute];
1694         [tempArray addObject:NSAccessibilityDecrementButtonAttribute];
1695         [tempArray addObject:NSAccessibilityValueDescriptionAttribute];
1696         [tempArray addObject:NSAccessibilityMinValueAttribute];
1697         [tempArray addObject:NSAccessibilityMaxValueAttribute];
1698         incrementorAttrs = [[NSArray alloc] initWithArray:tempArray];
1699         [tempArray release];
1700     }
1701     if (buttonAttrs == nil) {
1702         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1703         // Buttons should not expose AXValue.
1704         [tempArray removeObject:NSAccessibilityValueAttribute];
1705         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1706         [tempArray addObject:NSAccessibilityAccessKeyAttribute];
1707         buttonAttrs = [[NSArray alloc] initWithArray:tempArray];
1708         [tempArray release];
1709     }
1710     if (comboBoxAttrs == nil) {
1711         tempArray = [[NSMutableArray alloc] initWithArray:controlAttrs];
1712         [tempArray addObject:NSAccessibilityExpandedAttribute];
1713         [tempArray addObject:NSAccessibilityOrientationAttribute];
1714         comboBoxAttrs = [[NSArray alloc] initWithArray:tempArray];
1715         [tempArray release];
1716     }
1717     if (tableAttrs == nil) {
1718         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1719         [tempArray addObject:NSAccessibilityRowsAttribute];
1720         [tempArray addObject:NSAccessibilityVisibleRowsAttribute];
1721         [tempArray addObject:NSAccessibilityColumnsAttribute];
1722         [tempArray addObject:NSAccessibilityVisibleColumnsAttribute];
1723         [tempArray addObject:NSAccessibilityVisibleCellsAttribute];
1724         [tempArray addObject:NSAccessibilityColumnHeaderUIElementsAttribute];
1725         [tempArray addObject:NSAccessibilityRowHeaderUIElementsAttribute];
1726         [tempArray addObject:NSAccessibilityHeaderAttribute];
1727         [tempArray addObject:NSAccessibilityColumnCountAttribute];
1728         [tempArray addObject:NSAccessibilityRowCountAttribute];
1729         [tempArray addObject:NSAccessibilityARIAColumnCountAttribute];
1730         [tempArray addObject:NSAccessibilityARIARowCountAttribute];
1731         tableAttrs = [[NSArray alloc] initWithArray:tempArray];
1732         [tempArray release];
1733     }
1734     if (tableRowAttrs == nil) {
1735         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1736         [tempArray addObject:NSAccessibilityIndexAttribute];
1737         tableRowAttrs = [[NSArray alloc] initWithArray:tempArray];
1738         [tempArray release];
1739     }
1740     if (tableColAttrs == nil) {
1741         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1742         [tempArray addObject:NSAccessibilityIndexAttribute];
1743         [tempArray addObject:NSAccessibilityHeaderAttribute];
1744         [tempArray addObject:NSAccessibilityRowsAttribute];
1745         [tempArray addObject:NSAccessibilityVisibleRowsAttribute];
1746         tableColAttrs = [[NSArray alloc] initWithArray:tempArray];
1747         [tempArray release];
1748     }
1749     if (tableCellAttrs == nil) {
1750         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1751         [tempArray addObject:NSAccessibilityRowIndexRangeAttribute];
1752         [tempArray addObject:NSAccessibilityColumnIndexRangeAttribute];
1753         [tempArray addObject:NSAccessibilityColumnHeaderUIElementsAttribute];
1754         [tempArray addObject:NSAccessibilityRowHeaderUIElementsAttribute];
1755         [tempArray addObject:NSAccessibilityARIAColumnIndexAttribute];
1756         [tempArray addObject:NSAccessibilityARIARowIndexAttribute];
1757         tableCellAttrs = [[NSArray alloc] initWithArray:tempArray];
1758         [tempArray release];
1759     }
1760     if (groupAttrs == nil) {
1761         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1762         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1763         groupAttrs = [[NSArray alloc] initWithArray:tempArray];
1764         [tempArray release];
1765     }
1766     if (inputImageAttrs == nil) {
1767         tempArray = [[NSMutableArray alloc] initWithArray:buttonAttrs];
1768         [tempArray addObject:NSAccessibilityURLAttribute];
1769         inputImageAttrs = [[NSArray alloc] initWithArray:tempArray];
1770         [tempArray release];
1771     }
1772     if (passwordFieldAttrs == nil) {
1773         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1774         [tempArray addObject:NSAccessibilityTitleUIElementAttribute];
1775         [tempArray addObject:NSAccessibilityRequiredAttribute];
1776         [tempArray addObject:NSAccessibilityInvalidAttribute];
1777         [tempArray addObject:NSAccessibilityPlaceholderValueAttribute];
1778         [tempArray addObject:NSAccessibilityValueAutofilledAttribute];
1779         passwordFieldAttrs = [[NSArray alloc] initWithArray:tempArray];
1780         [tempArray release];
1781     }
1782     if (tabListAttrs == nil) {
1783         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1784         [tempArray addObject:NSAccessibilityTabsAttribute];
1785         [tempArray addObject:NSAccessibilityContentsAttribute];
1786         [tempArray addObject:NSAccessibilityOrientationAttribute];
1787         tabListAttrs = [[NSArray alloc] initWithArray:tempArray];
1788         [tempArray release];
1789     }
1790     if (outlineAttrs == nil) {
1791         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1792         [tempArray addObject:NSAccessibilitySelectedRowsAttribute];
1793         [tempArray addObject:NSAccessibilityRowsAttribute];
1794         [tempArray addObject:NSAccessibilityColumnsAttribute];
1795         [tempArray addObject:NSAccessibilityOrientationAttribute];
1796         outlineAttrs = [[NSArray alloc] initWithArray:tempArray];
1797         [tempArray release];
1798     }
1799     if (outlineRowAttrs == nil) {
1800         tempArray = [[NSMutableArray alloc] initWithArray:tableRowAttrs];
1801         [tempArray addObject:NSAccessibilityDisclosingAttribute];
1802         [tempArray addObject:NSAccessibilityDisclosedByRowAttribute];
1803         [tempArray addObject:NSAccessibilityDisclosureLevelAttribute];
1804         [tempArray addObject:NSAccessibilityDisclosedRowsAttribute];
1805         outlineRowAttrs = [[NSArray alloc] initWithArray:tempArray];
1806         [tempArray release];
1807     }
1808     if (scrollViewAttrs == nil) {
1809         tempArray = [[NSMutableArray alloc] initWithArray:attributes];
1810         [tempArray addObject:NSAccessibilityContentsAttribute];
1811         [tempArray addObject:NSAccessibilityHorizontalScrollBarAttribute];
1812         [tempArray addObject:NSAccessibilityVerticalScrollBarAttribute];
1813         scrollViewAttrs = [[NSArray alloc] initWithArray:tempArray];
1814         [tempArray release];
1815     }
1816
1817     NSArray *objectAttributes = attributes;
1818
1819     if (backingObject->isPasswordField())
1820         objectAttributes = passwordFieldAttrs;
1821     else if (backingObject->isWebArea())
1822         objectAttributes = webAreaAttrs;
1823     else if (backingObject->isTextControl())
1824         objectAttributes = textAttrs;
1825     else if (backingObject->isLink() || backingObject->isImage())
1826         objectAttributes = anchorAttrs;
1827     else if (backingObject->isTable() && backingObject->isExposable())
1828         objectAttributes = tableAttrs;
1829     else if (backingObject->isTableColumn())
1830         objectAttributes = tableColAttrs;
1831     else if (backingObject->isTableCell())
1832         objectAttributes = tableCellAttrs;
1833     else if (backingObject->isTableRow()) {
1834         // An ARIA table row can be collapsed and expanded, so it needs the extra attributes.
1835         if (backingObject->isARIATreeGridRow())
1836             objectAttributes = outlineRowAttrs;
1837         else
1838             objectAttributes = tableRowAttrs;
1839     } else if (backingObject->isTree())
1840         objectAttributes = outlineAttrs;
1841     else if (backingObject->isTreeItem())
1842         objectAttributes = outlineRowAttrs;
1843     else if (backingObject->isListBox())
1844         objectAttributes = listBoxAttrs;
1845     else if (backingObject->isList())
1846         objectAttributes = listAttrs;
1847     else if (backingObject->isComboBox())
1848         objectAttributes = comboBoxAttrs;
1849     else if (backingObject->isProgressIndicator() || backingObject->isSlider())
1850         objectAttributes = rangeAttrs;
1851     // These are processed in order because an input image is a button, and a button is a control.
1852     else if (backingObject->isInputImage())
1853         objectAttributes = inputImageAttrs;
1854     else if (backingObject->isButton())
1855         objectAttributes = buttonAttrs;
1856     else if (backingObject->isControl())
1857         objectAttributes = controlAttrs;
1858
1859     else if (backingObject->isGroup() || backingObject->isListItem())
1860         objectAttributes = groupAttrs;
1861     else if (backingObject->isTabList())
1862         objectAttributes = tabListAttrs;
1863     else if (backingObject->isScrollView())
1864         objectAttributes = scrollViewAttrs;
1865     else if (backingObject->isSpinButton())
1866         objectAttributes = incrementorAttrs;
1867     else if (backingObject->isMenu())
1868         objectAttributes = menuAttrs;
1869     else if (backingObject->isMenuBar())
1870         objectAttributes = menuBarAttrs;
1871     else if (backingObject->isMenuButton())
1872         objectAttributes = menuButtonAttrs;
1873     else if (backingObject->isMenuItem())
1874         objectAttributes = menuItemAttrs;
1875
1876     NSArray *additionalAttributes = [self additionalAccessibilityAttributeNames];
1877     if ([additionalAttributes count])
1878         objectAttributes = [objectAttributes arrayByAddingObjectsFromArray:additionalAttributes];
1879
1880     // Only expose AXARIACurrent attribute when the element is set to be current item.
1881     if (backingObject->currentState() != AccessibilityCurrentState::False)
1882         objectAttributes = [objectAttributes arrayByAddingObjectsFromArray:@[ NSAccessibilityARIACurrentAttribute ]];
1883
1884     // AppKit needs to know the screen height in order to do the coordinate conversion.
1885     objectAttributes = [objectAttributes arrayByAddingObjectsFromArray:@[ NSAccessibilityPrimaryScreenHeightAttribute ]];
1886
1887     return objectAttributes;
1888 }
1889
1890 - (VisiblePositionRange)visiblePositionRangeForTextMarkerRange:(id)textMarkerRange
1891 {
1892     if (!textMarkerRange)
1893         return VisiblePositionRange();
1894     AXObjectCache* cache = self.axBackingObject->axObjectCache();
1895     return VisiblePositionRange(visiblePositionForStartOfTextMarkerRange(cache, textMarkerRange), visiblePositionForEndOfTextMarkerRange(cache, textMarkerRange));
1896 }
1897
1898 - (NSArray*)renderWidgetChildren
1899 {
1900     return Accessibility::retrieveValueFromMainThread<NSArray *>([protectedSelf = RetainPtr<WebAccessibilityObjectWrapper>(self)] () -> NSArray * {
1901         auto* backingObject = protectedSelf.get().axBackingObject;
1902         if (!backingObject)
1903             return nil;
1904
1905         Widget* widget = backingObject->widget();
1906         if (!widget)
1907             return nil;
1908         ALLOW_DEPRECATED_DECLARATIONS_BEGIN
1909         return [(widget->platformWidget()) accessibilityAttributeValue:NSAccessibilityChildrenAttribute];
1910         ALLOW_DEPRECATED_DECLARATIONS_END
1911     });
1912 }
1913
1914 - (id)remoteAccessibilityParentObject
1915 {
1916     ASSERT(isMainThread());
1917     if (!self.axBackingObject)
1918         return nil;
1919
1920     if (auto* document = self.axBackingObject->document()) {
1921         if (auto* frame = document->frame())
1922             return frame->loader().client().accessibilityRemoteObject();
1923     }
1924
1925     return nil;
1926 }
1927
1928 static void convertToVector(NSArray* array, AccessibilityObject::AccessibilityChildrenVector& vector)
1929 {
1930     unsigned length = [array count];
1931     vector.reserveInitialCapacity(length);
1932     for (unsigned i = 0; i < length; ++i) {
1933         AXCoreObject* obj = [[array objectAtIndex:i] axBackingObject];
1934         if (obj)
1935             vector.append(obj);
1936     }
1937 }
1938
1939 static NSMutableArray *convertStringsToNSArray(const Vector<String>& vector)
1940 {
1941     NSMutableArray *array = [NSMutableArray arrayWithCapacity:vector.size()];
1942     for (const auto& string : vector)
1943         [array addObject:string];
1944     return array;
1945 }
1946
1947 - (id)textMarkerRangeForSelection
1948 {
1949     VisibleSelection selection = self.axBackingObject->selection();
1950     if (selection.isNone())
1951         return nil;
1952     return [self textMarkerRangeFromVisiblePositions:selection.visibleStart() endPosition:selection.visibleEnd()];
1953 }
1954
1955 - (id)associatedPluginParent
1956 {
1957     return Accessibility::retrieveAutoreleasedValueFromMainThread<id>([protectedSelf = RetainPtr<WebAccessibilityObjectWrapper>(self)] () -> RetainPtr<id> {
1958         if (!protectedSelf.get().axBackingObject || !protectedSelf.get().axBackingObject->hasApplePDFAnnotationAttribute())
1959             return nil;
1960     
1961         if (!protectedSelf.get().axBackingObject->document()->isPluginDocument())
1962             return nil;
1963         
1964         Widget* pluginWidget = static_cast<PluginDocument*>(protectedSelf.get().axBackingObject->document())->pluginWidget();
1965         if (!pluginWidget || !pluginWidget->isPluginViewBase())
1966             return nil;
1967         
1968         return static_cast<PluginViewBase*>(pluginWidget)->accessibilityAssociatedPluginParentForElement(protectedSelf.get().axBackingObject->element());
1969     });
1970 }
1971
1972 static void WebTransformCGPathToNSBezierPath(void* info, const CGPathElement *element)
1973 {
1974     NSBezierPath *bezierPath = (__bridge NSBezierPath *)info;
1975     switch (element->type) {
1976     case kCGPathElementMoveToPoint:
1977         [bezierPath moveToPoint:NSPointFromCGPoint(element->points[0])];
1978         break;
1979     case kCGPathElementAddLineToPoint:
1980         [bezierPath lineToPoint:NSPointFromCGPoint(element->points[0])];
1981         break;
1982     case kCGPathElementAddCurveToPoint:
1983         [bezierPath curveToPoint:NSPointFromCGPoint(element->points[0]) controlPoint1:NSPointFromCGPoint(element->points[1]) controlPoint2:NSPointFromCGPoint(element->points[2])];
1984         break;
1985     case kCGPathElementCloseSubpath:
1986         [bezierPath closePath];
1987         break;
1988     default:
1989         break;
1990     }
1991 }
1992
1993 - (NSBezierPath *)bezierPathFromPath:(CGPathRef)path
1994 {
1995     NSBezierPath *bezierPath = [NSBezierPath bezierPath];
1996     CGPathApply(path, (__bridge void*)bezierPath, WebTransformCGPathToNSBezierPath);
1997     return bezierPath;
1998 }
1999
2000 - (NSBezierPath *)path
2001 {
2002     Path path = self.axBackingObject->elementPath();
2003     if (path.isEmpty())
2004         return NULL;
2005     
2006     CGPathRef transformedPath = [self convertPathToScreenSpace:path];
2007     return [self bezierPathFromPath:transformedPath];
2008 }
2009
2010 - (NSNumber *)primaryScreenHeight
2011 {
2012     FloatRect screenRect = screenRectForPrimaryScreen();
2013     return [NSNumber numberWithFloat:screenRect.height()];
2014 }
2015
2016 - (size_t)childrenVectorSize
2017 {
2018     return self.axBackingObject->children().size();
2019 }
2020
2021 - (NSArray<WebAccessibilityObjectWrapper *> *)childrenVectorArray
2022 {
2023     return convertToNSArray(self.axBackingObject->children());
2024 }
2025
2026 - (NSValue *)position
2027 {
2028 #if ENABLE(ACCESSIBILITY_ISOLATED_TREE)
2029     if (_AXUIElementRequestServicedBySecondaryAXThread())
2030         return [NSValue valueWithPoint:(NSPoint)self.axBackingObject->relativeFrame().location()];
2031 #endif
2032         
2033     auto rect = snappedIntRect(self.axBackingObject->elementRect());
2034     
2035     // The Cocoa accessibility API wants the lower-left corner.
2036     auto floatPoint = FloatPoint(rect.x(), rect.maxY());
2037
2038     auto floatRect = FloatRect(floatPoint, FloatSize());
2039     CGPoint cgPoint = [self convertRectToSpace:floatRect space:AccessibilityConversionSpace::Screen].origin;
2040     return [NSValue valueWithPoint:NSPointFromCGPoint(cgPoint)];
2041 }
2042
2043 - (NSString*)role
2044 {
2045     ALLOW_DEPRECATED_DECLARATIONS_BEGIN
2046     if (self.axBackingObject->isAttachment())
2047         return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityRoleAttribute];
2048     ALLOW_DEPRECATED_DECLARATIONS_END
2049
2050     NSString *string = self.axBackingObject->rolePlatformString();
2051     if (string.length)
2052         return string;
2053     return NSAccessibilityUnknownRole;
2054 }
2055
2056 ALLOW_DEPRECATED_DECLARATIONS_BEGIN
2057 - (NSString*)subrole
2058 {
2059     if (self.axBackingObject->isPasswordField())
2060         return NSAccessibilitySecureTextFieldSubrole;
2061     if (self.axBackingObject->isSearchField())
2062         return NSAccessibilitySearchFieldSubrole;
2063     
2064     if (self.axBackingObject->isAttachment()) {
2065         NSView* attachView = [self attachmentView];
2066         if ([[attachView accessibilityAttributeNames] containsObject:NSAccessibilitySubroleAttribute])
2067             return [attachView accessibilityAttributeValue:NSAccessibilitySubroleAttribute];
2068     }
2069     
2070     if (self.axBackingObject->isMeter())
2071         return @"AXMeter";
2072     
2073     AccessibilityRole role = self.axBackingObject->roleValue();
2074     if (role == AccessibilityRole::HorizontalRule)
2075         return NSAccessibilityContentSeparatorSubrole;
2076     if (role == AccessibilityRole::ToggleButton)
2077         return NSAccessibilityToggleSubrole;
2078     if (role == AccessibilityRole::Footer)
2079         return @"AXFooter";
2080
2081     if (self.axBackingObject->roleValue() == AccessibilityRole::SpinButtonPart) {
2082         if (self.axBackingObject->isIncrementor())
2083             return NSAccessibilityIncrementArrowSubrole;
2084         return NSAccessibilityDecrementArrowSubrole;
2085     }
2086     
2087     if (self.axBackingObject->isFileUploadButton())
2088         return @"AXFileUploadButton";
2089     
2090     if (self.axBackingObject->isTreeItem())
2091         return NSAccessibilityOutlineRowSubrole;
2092     
2093     if (self.axBackingObject->isFieldset())
2094         return @"AXFieldset";
2095
2096     if (self.axBackingObject->isList()) {
2097         if (self.axBackingObject->isUnorderedList() || self.axBackingObject->isOrderedList())
2098             return NSAccessibilityContentListSubrole;
2099         if (self.axBackingObject->isDescriptionList()) {
2100             return NSAccessibilityDescriptionListSubrole;
2101         }
2102     }
2103
2104     // ARIA content subroles.
2105     switch (role) {
2106     case AccessibilityRole::LandmarkBanner:
2107         return @"AXLandmarkBanner";
2108     case AccessibilityRole::LandmarkComplementary:
2109         return @"AXLandmarkComplementary";
2110     case AccessibilityRole::LandmarkContentInfo:
2111         return @"AXLandmarkContentInfo";
2112     case AccessibilityRole::LandmarkMain:
2113         return @"AXLandmarkMain";
2114     case AccessibilityRole::LandmarkNavigation:
2115         return @"AXLandmarkNavigation";
2116     case AccessibilityRole::LandmarkDocRegion:
2117     case AccessibilityRole::LandmarkRegion:
2118         return @"AXLandmarkRegion";
2119     case AccessibilityRole::LandmarkSearch:
2120         return @"AXLandmarkSearch";
2121     case AccessibilityRole::ApplicationAlert:
2122         return @"AXApplicationAlert";
2123     case AccessibilityRole::ApplicationAlertDialog:
2124         return @"AXApplicationAlertDialog";
2125     case AccessibilityRole::ApplicationDialog:
2126         return @"AXApplicationDialog";
2127     case AccessibilityRole::ApplicationGroup:
2128     case AccessibilityRole::ApplicationTextGroup:
2129     case AccessibilityRole::Feed:
2130     case AccessibilityRole::Footnote:
2131         return @"AXApplicationGroup";
2132     case AccessibilityRole::ApplicationLog:
2133         return @"AXApplicationLog";
2134     case AccessibilityRole::ApplicationMarquee:
2135         return @"AXApplicationMarquee";
2136     case AccessibilityRole::ApplicationStatus:
2137         return @"AXApplicationStatus";
2138     case AccessibilityRole::ApplicationTimer:
2139         return @"AXApplicationTimer";
2140     case AccessibilityRole::Document:
2141     case AccessibilityRole::GraphicsDocument:
2142         return @"AXDocument";
2143     case AccessibilityRole::DocumentArticle:
2144         return @"AXDocumentArticle";
2145     case AccessibilityRole::DocumentMath:
2146         return @"AXDocumentMath";
2147     case AccessibilityRole::DocumentNote:
2148         return @"AXDocumentNote";
2149     case AccessibilityRole::UserInterfaceTooltip:
2150         return @"AXUserInterfaceTooltip";
2151     case AccessibilityRole::TabPanel:
2152         return @"AXTabPanel";
2153     case AccessibilityRole::Definition:
2154         return @"AXDefinition";
2155     case AccessibilityRole::DescriptionListTerm:
2156     case AccessibilityRole::Term:
2157         return @"AXTerm";
2158     case AccessibilityRole::DescriptionListDetail:
2159         return @"AXDescription";
2160     case AccessibilityRole::WebApplication:
2161         return @"AXWebApplication";
2162         // Default doesn't return anything, so roles defined below can be chosen.
2163     default:
2164         break;
2165     }
2166     
2167     if (role == AccessibilityRole::MathElement) {
2168         if (self.axBackingObject->isMathFraction())
2169             return @"AXMathFraction";
2170         if (self.axBackingObject->isMathFenced())
2171             return @"AXMathFenced";
2172         if (self.axBackingObject->isMathSubscriptSuperscript())
2173             return @"AXMathSubscriptSuperscript";
2174         if (self.axBackingObject->isMathRow())
2175             return @"AXMathRow";
2176         if (self.axBackingObject->isMathUnderOver())
2177             return @"AXMathUnderOver";
2178         if (self.axBackingObject->isMathSquareRoot())
2179             return @"AXMathSquareRoot";
2180         if (self.axBackingObject->isMathRoot())
2181             return @"AXMathRoot";
2182         if (self.axBackingObject->isMathText())
2183             return @"AXMathText";
2184         if (self.axBackingObject->isMathNumber())
2185             return @"AXMathNumber";
2186         if (self.axBackingObject->isMathIdentifier())
2187             return @"AXMathIdentifier";
2188         if (self.axBackingObject->isMathTable())
2189             return @"AXMathTable";
2190         if (self.axBackingObject->isMathTableRow())
2191             return @"AXMathTableRow";
2192         if (self.axBackingObject->isMathTableCell())
2193             return @"AXMathTableCell";
2194         if (self.axBackingObject->isMathFenceOperator())
2195             return @"AXMathFenceOperator";
2196         if (self.axBackingObject->isMathSeparatorOperator())
2197             return @"AXMathSeparatorOperator";
2198         if (self.axBackingObject->isMathOperator())
2199             return @"AXMathOperator";
2200         if (self.axBackingObject->isMathMultiscript())
2201             return @"AXMathMultiscript";
2202     }
2203     
2204     if (role == AccessibilityRole::Video)
2205         return @"AXVideo";
2206     if (role == AccessibilityRole::Audio)
2207         return @"AXAudio";
2208     if (role == AccessibilityRole::Details)
2209         return @"AXDetails";
2210     if (role == AccessibilityRole::Summary)
2211         return @"AXSummary";
2212     if (role == AccessibilityRole::Time)
2213         return @"AXTimeGroup";
2214
2215     if (self.axBackingObject->isMediaTimeline())
2216         return NSAccessibilityTimelineSubrole;
2217
2218     if (self.axBackingObject->isSwitch())
2219         return NSAccessibilitySwitchSubrole;
2220
2221     if (role == AccessibilityRole::Insertion)
2222         return @"AXInsertStyleGroup";
2223     if (role == AccessibilityRole::Deletion)
2224         return @"AXDeleteStyleGroup";
2225     if (role == AccessibilityRole::Superscript)
2226         return @"AXSuperscriptStyleGroup";
2227     if (role == AccessibilityRole::Subscript)
2228         return @"AXSubscriptStyleGroup";
2229
2230     if (self.axBackingObject->isStyleFormatGroup()) {
2231         auto tagName = self.axBackingObject->tagName();
2232         if (tagName == kbdTag)
2233             return @"AXKeyboardInputStyleGroup";
2234         if (tagName == codeTag)
2235             return @"AXCodeStyleGroup";
2236         if (tagName == preTag)
2237             return @"AXPreformattedStyleGroup";
2238         if (tagName == sampTag)
2239             return @"AXSampleStyleGroup";
2240         if (tagName == varTag)
2241             return @"AXVariableStyleGroup";
2242         if (tagName == citeTag)
2243             return @"AXCiteStyleGroup";
2244         ASSERT_NOT_REACHED();
2245     }
2246     
2247     // Ruby subroles
2248     switch (role) {
2249     case AccessibilityRole::RubyBase:
2250         return NSAccessibilityRubyBaseSubrole;
2251     case AccessibilityRole::RubyBlock:
2252         return NSAccessibilityRubyBlockSubrole;
2253     case AccessibilityRole::RubyInline:
2254         return NSAccessibilityRubyInlineSubrole;
2255     case AccessibilityRole::RubyRun:
2256         return NSAccessibilityRubyRunSubrole;
2257     case AccessibilityRole::RubyText:
2258         return NSAccessibilityRubyTextSubrole;
2259     default:
2260         break;
2261     }
2262     
2263     return nil;
2264 }
2265 ALLOW_DEPRECATED_DECLARATIONS_END
2266
2267 - (NSString*)roleDescription
2268 {
2269     if (!self.axBackingObject)
2270         return nil;
2271
2272     ALLOW_DEPRECATED_DECLARATIONS_BEGIN
2273     // attachments have the AXImage role, but a different subrole
2274     if (self.axBackingObject->isAttachment())
2275         return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityRoleDescriptionAttribute];
2276     ALLOW_DEPRECATED_DECLARATIONS_END
2277
2278     String roleDescription = self.axBackingObject->roleDescription();
2279     if (!roleDescription.isEmpty())
2280         return roleDescription;
2281
2282     NSString *axRole = self.axBackingObject->rolePlatformString();
2283     // Fallback to the system default role description.
2284     // If we get the same string back, then as a last resort, return unknown.
2285     NSString *defaultRoleDescription = NSAccessibilityRoleDescription(axRole, [self subrole]);
2286
2287     // On earlier Mac versions (Lion), using a non-standard subrole would result in a role description
2288     // being returned that looked like AXRole:AXSubrole. To make all platforms have the same role descriptions
2289     // we should fallback on a role description ignoring the subrole in these cases.
2290     if ([defaultRoleDescription isEqualToString:[NSString stringWithFormat:@"%@:%@", axRole, [self subrole]]])
2291         defaultRoleDescription = NSAccessibilityRoleDescription(axRole, nil);
2292     
2293     if (![defaultRoleDescription isEqualToString:axRole])
2294         return defaultRoleDescription;
2295     
2296     return NSAccessibilityRoleDescription(NSAccessibilityUnknownRole, nil);
2297 }
2298
2299 - (NSString *)computedRoleString
2300 {
2301     if (!self.axBackingObject)
2302         return nil;
2303     return self.axBackingObject->computedRoleString();
2304 }
2305
2306 - (id)scrollViewParent
2307 {
2308     return Accessibility::retrieveAutoreleasedValueFromMainThread<id>([protectedSelf = RetainPtr<WebAccessibilityObjectWrapper>(self)] () -> RetainPtr<id> {
2309         if (!is<AccessibilityScrollView>(protectedSelf.get().axBackingObject))
2310             return nil;
2311
2312         // If this scroll view provides it's parent object (because it's a sub-frame), then
2313         // we should not find the remoteAccessibilityParent.
2314         if (protectedSelf.get().axBackingObject->parentObject())
2315             return nil;
2316
2317         ScrollView* scroll = downcast<AccessibilityScrollView>(*protectedSelf.get().axBackingObject).scrollView();
2318         if (!scroll)
2319             return nil;
2320
2321         if (scroll->platformWidget())
2322             return NSAccessibilityUnignoredAncestor(scroll->platformWidget());
2323
2324         return [protectedSelf remoteAccessibilityParentObject];
2325     });
2326 }
2327
2328 - (id)windowElement:(NSString*)attributeName
2329 {
2330     return Accessibility::retrieveAutoreleasedValueFromMainThread<id>([attributeName, protectedSelf = RetainPtr<WebAccessibilityObjectWrapper>(self)] () -> RetainPtr<id> {
2331         id remoteParent = [protectedSelf remoteAccessibilityParentObject];
2332         if (remoteParent) {
2333             ALLOW_DEPRECATED_DECLARATIONS_BEGIN
2334             return [remoteParent accessibilityAttributeValue:attributeName];
2335             ALLOW_DEPRECATED_DECLARATIONS_END
2336         }
2337
2338         auto* backingObject = protectedSelf.get().axBackingObject;
2339         if (!backingObject)
2340             return nil;
2341
2342         if (auto* fv = backingObject->documentFrameView())
2343             return [fv->platformWidget() window];
2344
2345         return nil;
2346     });
2347 }
2348
2349 // FIXME: split up this function in a better way.
2350 // suggestions: Use a hash table that maps attribute names to function calls,
2351 // or maybe pointers to member functions
2352 ALLOW_DEPRECATED_IMPLEMENTATIONS_BEGIN
2353 - (id)accessibilityAttributeValue:(NSString*)attributeName
2354 ALLOW_DEPRECATED_IMPLEMENTATIONS_END
2355 {
2356     auto* backingObject = self.updateObjectBackingStore;
2357     if (!backingObject)
2358         return nil;
2359
2360     if (backingObject->isDetachedFromParent())
2361         return nil;
2362
2363     if ([attributeName isEqualToString: NSAccessibilityRoleAttribute])
2364         return [self role];
2365
2366     if ([attributeName isEqualToString: NSAccessibilitySubroleAttribute])
2367         return [self subrole];
2368
2369     if ([attributeName isEqualToString: NSAccessibilityRoleDescriptionAttribute])
2370         return [self roleDescription];
2371
2372     // AXARIARole is only used by DumpRenderTree (so far).
2373     if ([attributeName isEqualToString:@"AXARIARole"])
2374         return [self computedRoleString];
2375
2376     if ([attributeName isEqualToString: NSAccessibilityParentAttribute]) {
2377
2378         // This will return the parent of the AXWebArea, if this is a web area.
2379         id scrollViewParent = [self scrollViewParent];
2380         if (scrollViewParent)
2381             return scrollViewParent;
2382
2383         // Tree item (changed to AXRows) can only report the tree (AXOutline) as its parent.
2384         if (backingObject->isTreeItem()) {
2385             auto parent = backingObject->parentObjectUnignored();
2386             while (parent) {
2387                 if (parent->isTree())
2388                     return parent->wrapper();
2389                 parent = parent->parentObjectUnignored();
2390             }
2391         }
2392
2393         auto parent = backingObject->parentObjectUnignored();
2394         if (!parent)
2395             return nil;
2396
2397         // In WebKit1, the scroll view is provided by the system (the attachment view), so the parent
2398         // should be reported directly as such.
2399         if (backingObject->isWebArea() && parent->isAttachment())
2400             return [parent->wrapper() attachmentView];
2401
2402         return parent->wrapper();
2403     }
2404
2405     if ([attributeName isEqualToString: NSAccessibilityChildrenAttribute] || [attributeName isEqualToString: NSAccessibilityChildrenInNavigationOrderAttribute]) {
2406         if (!self.childrenVectorSize) {
2407             NSArray* children = [self renderWidgetChildren];
2408             if (children != nil)
2409                 return children;
2410         }
2411
2412         // The tree's (AXOutline) children are supposed to be its rows and columns.
2413         // The ARIA spec doesn't have columns, so we just need rows.
2414         if (backingObject->isTree())
2415             return [self accessibilityAttributeValue:NSAccessibilityRowsAttribute];
2416
2417         // A tree item should only expose its content as its children (not its rows)
2418         if (backingObject->isTreeItem()) {
2419             AccessibilityObject::AccessibilityChildrenVector contentCopy;
2420             backingObject->ariaTreeItemContent(contentCopy);
2421             return convertToNSArray(contentCopy);
2422         }
2423
2424         return self.childrenVectorArray;
2425     }
2426
2427     if ([attributeName isEqualToString: NSAccessibilitySelectedChildrenAttribute]) {
2428         if (backingObject->canHaveSelectedChildren()) {
2429             AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
2430             backingObject->selectedChildren(selectedChildrenCopy);
2431             return convertToNSArray(selectedChildrenCopy);
2432         }
2433         return nil;
2434     }
2435
2436     if ([attributeName isEqualToString: NSAccessibilityVisibleChildrenAttribute]) {
2437         if (backingObject->isListBox()) {
2438             AccessibilityObject::AccessibilityChildrenVector visibleChildrenCopy;
2439             backingObject->visibleChildren(visibleChildrenCopy);
2440             return convertToNSArray(visibleChildrenCopy);
2441         }
2442
2443         if (backingObject->isList())
2444             return [self accessibilityAttributeValue:NSAccessibilityChildrenAttribute];
2445
2446         return nil;
2447     }
2448
2449
2450     if (backingObject->isWebArea()) {
2451         if ([attributeName isEqualToString:@"AXLinkUIElements"]) {
2452             AccessibilityObject::AccessibilityChildrenVector links;
2453             downcast<AccessibilityRenderObject>(*backingObject).getDocumentLinks(links);
2454             return convertToNSArray(links);
2455         }
2456         if ([attributeName isEqualToString:@"AXLoaded"])
2457             return [NSNumber numberWithBool:backingObject->isLoaded()];
2458         if ([attributeName isEqualToString:@"AXLayoutCount"])
2459             return [NSNumber numberWithInt:backingObject->layoutCount()];
2460         if ([attributeName isEqualToString:NSAccessibilityLoadingProgressAttribute])
2461             return [NSNumber numberWithDouble:backingObject->estimatedLoadingProgress()];
2462         if ([attributeName isEqualToString:NSAccessibilityPreventKeyboardDOMEventDispatchAttribute])
2463             return [NSNumber numberWithBool:backingObject->preventKeyboardDOMEventDispatch()];
2464         if ([attributeName isEqualToString:NSAccessibilityCaretBrowsingEnabledAttribute])
2465             return [NSNumber numberWithBool:backingObject->caretBrowsingEnabled()];
2466         if ([attributeName isEqualToString:NSAccessibilityWebSessionIDAttribute])
2467             return @(backingObject->sessionID());
2468     }
2469
2470     if (backingObject->isTextControl()) {
2471         if ([attributeName isEqualToString: NSAccessibilityNumberOfCharactersAttribute]) {
2472             int length = backingObject->textLength();
2473             if (length < 0)
2474                 return nil;
2475             return [NSNumber numberWithUnsignedInt:length];
2476         }
2477         if ([attributeName isEqualToString: NSAccessibilitySelectedTextAttribute]) {
2478             String selectedText = backingObject->selectedText();
2479             if (selectedText.isNull())
2480                 return nil;
2481             return (NSString*)selectedText;
2482         }
2483         if ([attributeName isEqualToString: NSAccessibilitySelectedTextRangeAttribute]) {
2484             PlainTextRange textRange = backingObject->selectedTextRange();
2485             return [NSValue valueWithRange:NSMakeRange(textRange.start, textRange.length)];
2486         }
2487         // TODO: Get actual visible range. <rdar://problem/4712101>
2488         if ([attributeName isEqualToString: NSAccessibilityVisibleCharacterRangeAttribute])
2489             return backingObject->isPasswordField() ? nil : [NSValue valueWithRange: NSMakeRange(0, backingObject->textLength())];
2490         if ([attributeName isEqualToString: NSAccessibilityInsertionPointLineNumberAttribute]) {
2491             // if selectionEnd > 0, then there is selected text and this question should not be answered
2492             if (backingObject->isPasswordField() || backingObject->selectionEnd() > 0)
2493                 return nil;
2494
2495             auto focusedObject = downcast<AccessibilityObject>(backingObject->focusedUIElement());
2496             if (focusedObject != backingObject)
2497                 return nil;
2498
2499             VisiblePosition focusedPosition = focusedObject->visiblePositionForIndex(focusedObject->selectionStart(), true);
2500             int lineNumber = backingObject->lineForPosition(focusedPosition);
2501             if (lineNumber < 0)
2502                 return nil;
2503
2504             return [NSNumber numberWithInt:lineNumber];
2505         }
2506     }
2507
2508     if ([attributeName isEqualToString: NSAccessibilityURLAttribute]) {
2509         URL url = backingObject->url();
2510         if (url.isNull())
2511             return nil;
2512         return (NSURL*)url;
2513     }
2514
2515     if ([attributeName isEqualToString:NSAccessibilityIncrementButtonAttribute]) {
2516         auto incrementButton = backingObject->incrementButton();
2517         return incrementButton ? incrementButton->wrapper() : nil;
2518     }
2519
2520     if ([attributeName isEqualToString:NSAccessibilityDecrementButtonAttribute]) {
2521         auto decrementButton = backingObject->decrementButton();
2522         return decrementButton ? decrementButton->wrapper() : nil;
2523     }
2524
2525     if ([attributeName isEqualToString: @"AXVisited"])
2526         return [NSNumber numberWithBool: backingObject->isVisited()];
2527
2528     if ([attributeName isEqualToString: NSAccessibilityTitleAttribute]) {
2529         if (backingObject->isAttachment()) {
2530             if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityTitleAttribute])
2531                 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityTitleAttribute];
2532         }
2533
2534         // Meter elements should communicate their content via AXValueDescription.
2535         if (backingObject->isMeter())
2536             return [NSString string];
2537
2538         // Summary element should use its text node as AXTitle.
2539         if (backingObject->isSummary())
2540             return backingObject->textUnderElement();
2541
2542         return [self baseAccessibilityTitle];
2543     }
2544
2545     if ([attributeName isEqualToString: NSAccessibilityDescriptionAttribute]) {
2546         if (backingObject->isAttachment()) {
2547             if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityDescriptionAttribute])
2548                 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityDescriptionAttribute];
2549         }
2550         return [self baseAccessibilityDescription];
2551     }
2552
2553     if ([attributeName isEqualToString: NSAccessibilityValueAttribute]) {
2554         if (backingObject->isAttachment()) {
2555             if ([[[self attachmentView] accessibilityAttributeNames] containsObject:NSAccessibilityValueAttribute])
2556                 return [[self attachmentView] accessibilityAttributeValue:NSAccessibilityValueAttribute];
2557         }
2558         if (backingObject->supportsRangeValue())
2559             return [NSNumber numberWithFloat:backingObject->valueForRange()];
2560         if (backingObject->roleValue() == AccessibilityRole::SliderThumb)
2561             return [NSNumber numberWithFloat:backingObject->parentObject()->valueForRange()];
2562         if (backingObject->isHeading())
2563             return [NSNumber numberWithInt:backingObject->headingLevel()];
2564
2565         if (backingObject->isCheckboxOrRadio() || backingObject->isMenuItem() || backingObject->isSwitch() || backingObject->isToggleButton()) {
2566             switch (backingObject->checkboxOrRadioValue()) {
2567             case AccessibilityButtonState::Off:
2568                 return [NSNumber numberWithInt:0];
2569             case AccessibilityButtonState::On:
2570                 return [NSNumber numberWithInt:1];
2571             case AccessibilityButtonState::Mixed:
2572                 return [NSNumber numberWithInt:2];
2573             }
2574         }
2575
2576         // radio groups return the selected radio button as the AXValue
2577         if (backingObject->isRadioGroup()) {
2578             AXCoreObject* radioButton = backingObject->selectedRadioButton();
2579             if (!radioButton)
2580                 return nil;
2581             return radioButton->wrapper();
2582         }
2583
2584         if (backingObject->isTabList()) {
2585             AXCoreObject* tabItem = backingObject->selectedTabItem();
2586             if (!tabItem)
2587                 return nil;
2588             return tabItem->wrapper();
2589         }
2590
2591         if (backingObject->isTabItem())
2592             return [NSNumber numberWithInt:backingObject->isSelected()];
2593
2594         if (backingObject->isColorWell()) {
2595             int r, g, b;
2596             backingObject->colorValue(r, g, b);
2597             return [NSString stringWithFormat:@"rgb %7.5f %7.5f %7.5f 1", r / 255., g / 255., b / 255.];
2598         }
2599
2600         return backingObject->stringValue();
2601     }
2602
2603     if ([attributeName isEqualToString:(NSString *)kAXMenuItemMarkCharAttribute]) {
2604         const unichar ch = 0x2713; // ✓ used on Mac for selected menu items.
2605         return (backingObject->isChecked()) ? [NSString stringWithCharacters:&ch length:1] : nil;
2606     }
2607
2608     if ([attributeName isEqualToString: NSAccessibilityMinValueAttribute]) {
2609         // Indeterminate progress indicator should return 0.
2610         if (backingObject->ariaRoleAttribute() == AccessibilityRole::ProgressIndicator && !backingObject->hasARIAValueNow())
2611             return @0;
2612         return [NSNumber numberWithFloat:backingObject->minValueForRange()];
2613     }
2614
2615     if ([attributeName isEqualToString: NSAccessibilityMaxValueAttribute]) {
2616         // Indeterminate progress indicator should return 0.
2617         if (backingObject->ariaRoleAttribute() == AccessibilityRole::ProgressIndicator && !backingObject->hasARIAValueNow())
2618             return @0;
2619         return [NSNumber numberWithFloat:backingObject->maxValueForRange()];
2620     }
2621
2622     if ([attributeName isEqualToString: NSAccessibilityHelpAttribute])
2623         return [self baseAccessibilityHelpText];
2624
2625     if ([attributeName isEqualToString: NSAccessibilityFocusedAttribute])
2626         return [NSNumber numberWithBool: backingObject->isFocused()];
2627
2628     if ([attributeName isEqualToString: NSAccessibilityEnabledAttribute])
2629         return [NSNumber numberWithBool: backingObject->isEnabled()];
2630
2631     if ([attributeName isEqualToString: NSAccessibilitySizeAttribute]) {
2632         IntSize s = snappedIntRect(backingObject->elementRect()).size();
2633         return [NSValue valueWithSize: NSMakeSize(s.width(), s.height())];
2634     }
2635
2636     if ([attributeName isEqualToString: NSAccessibilityPrimaryScreenHeightAttribute])
2637         return [self primaryScreenHeight];
2638     if ([attributeName isEqualToString: NSAccessibilityPositionAttribute])
2639         return [self position];
2640     if ([attributeName isEqualToString:NSAccessibilityPathAttribute])
2641         return [self path];
2642
2643     if ([attributeName isEqualToString:NSAccessibilityWindowAttribute]
2644         || [attributeName isEqualToString:NSAccessibilityTopLevelUIElementAttribute])
2645         return [self windowElement:attributeName];
2646
2647     if ([attributeName isEqualToString:NSAccessibilityAccessKeyAttribute]) {
2648         AtomString accessKey = backingObject->accessKey();
2649         if (accessKey.isNull())
2650             return nil;
2651         return accessKey;
2652     }
2653
2654     if ([attributeName isEqualToString:NSAccessibilityLinkRelationshipTypeAttribute])
2655         return backingObject->linkRelValue();
2656
2657     if ([attributeName isEqualToString:NSAccessibilityTabsAttribute]) {
2658         if (backingObject->isTabList()) {
2659             AccessibilityObject::AccessibilityChildrenVector tabsChildren;
2660             backingObject->tabChildren(tabsChildren);
2661             return convertToNSArray(tabsChildren);
2662         }
2663     }
2664
2665     if ([attributeName isEqualToString:NSAccessibilityContentsAttribute]) {
2666         // The contents of a tab list are all the children except the tabs.
2667         if (backingObject->isTabList()) {
2668             auto children = self.childrenVectorArray;
2669             AccessibilityObject::AccessibilityChildrenVector tabs;
2670             backingObject->tabChildren(tabs);
2671             auto tabsChildren = convertToNSArray(tabs);
2672
2673             NSMutableArray *contents = [NSMutableArray array];
2674             for (id childWrapper in children) {
2675                 if ([tabsChildren containsObject:childWrapper])
2676                     [contents addObject:childWrapper];
2677             }
2678             return contents;
2679         }
2680
2681         if (backingObject->isScrollView()) {
2682             // A scrollView's contents are everything except the scroll bars.
2683             auto children = self.childrenVectorArray;
2684             NSMutableArray *contents = [NSMutableArray array];
2685
2686             for (WebAccessibilityObjectWrapper *childWrapper in children) {
2687                 if (auto backingObject = [childWrapper axBackingObject]) {
2688                     if (!backingObject->isScrollbar())
2689                         [contents addObject:childWrapper];
2690                 }
2691             }
2692             return contents;
2693         }
2694     }
2695
2696     if (backingObject->isTable() && backingObject->isExposable()) {
2697         if ([attributeName isEqualToString:NSAccessibilityRowsAttribute])
2698             return convertToNSArray(backingObject->rows());
2699
2700         if ([attributeName isEqualToString:NSAccessibilityVisibleRowsAttribute])
2701             return convertToNSArray(backingObject->visibleRows());
2702
2703         // TODO: distinguish between visible and non-visible columns
2704         if ([attributeName isEqualToString:NSAccessibilityColumnsAttribute]
2705             || [attributeName isEqualToString:NSAccessibilityVisibleColumnsAttribute])
2706             return convertToNSArray(backingObject->columns());
2707
2708         if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
2709             AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
2710             backingObject->selectedChildren(selectedChildrenCopy);
2711             return convertToNSArray(selectedChildrenCopy);
2712         }
2713
2714         // HTML tables don't support these attributes.
2715         if ([attributeName isEqualToString:NSAccessibilitySelectedColumnsAttribute]
2716             || [attributeName isEqualToString:NSAccessibilitySelectedCellsAttribute])
2717             return nil;
2718
2719         if ([attributeName isEqualToString:NSAccessibilityColumnHeaderUIElementsAttribute])
2720             return convertToNSArray(backingObject->columnHeaders());
2721
2722         if ([attributeName isEqualToString:NSAccessibilityHeaderAttribute]) {
2723             auto* headerContainer = backingObject->headerContainer();
2724             return headerContainer ? headerContainer->wrapper() : nil;
2725         }
2726
2727         if ([attributeName isEqualToString:NSAccessibilityRowHeaderUIElementsAttribute])
2728             return convertToNSArray(backingObject->rowHeaders());
2729
2730         if ([attributeName isEqualToString:NSAccessibilityVisibleCellsAttribute])
2731             return convertToNSArray(backingObject->cells());
2732
2733         if ([attributeName isEqualToString:NSAccessibilityColumnCountAttribute])
2734             return @(backingObject->columnCount());
2735
2736         if ([attributeName isEqualToString:NSAccessibilityRowCountAttribute])
2737             return @(backingObject->rowCount());
2738
2739         if ([attributeName isEqualToString:NSAccessibilityARIAColumnCountAttribute])
2740             return @(backingObject->axColumnCount());
2741
2742         if ([attributeName isEqualToString:NSAccessibilityARIARowCountAttribute])
2743             return @(backingObject->axRowCount());
2744     }
2745
2746     if (backingObject->isTableColumn()) {
2747         if ([attributeName isEqualToString:NSAccessibilityIndexAttribute])
2748             return [NSNumber numberWithUnsignedInt:backingObject->columnIndex()];
2749
2750         // rows attribute for a column is the list of all the elements in that column at each row
2751         if ([attributeName isEqualToString:NSAccessibilityRowsAttribute]
2752             || [attributeName isEqualToString:NSAccessibilityVisibleRowsAttribute])
2753             return convertToNSArray(backingObject->children());
2754
2755         if ([attributeName isEqualToString:NSAccessibilityHeaderAttribute]) {
2756             auto* header = backingObject->columnHeader();
2757             return header ? header->wrapper() : nil;
2758         }
2759     }
2760
2761     if (backingObject->isTableCell()) {
2762         if ([attributeName isEqualToString:NSAccessibilityRowIndexRangeAttribute]) {
2763             auto rowRange = backingObject->rowIndexRange();
2764             return [NSValue valueWithRange:NSMakeRange(rowRange.first, rowRange.second)];
2765         }
2766
2767         if ([attributeName isEqualToString:NSAccessibilityColumnIndexRangeAttribute]) {
2768             auto columnRange = backingObject->columnIndexRange();
2769             return [NSValue valueWithRange:NSMakeRange(columnRange.first, columnRange.second)];
2770         }
2771
2772         if ([attributeName isEqualToString:NSAccessibilityColumnHeaderUIElementsAttribute])
2773             return convertToNSArray(backingObject->columnHeaders());
2774
2775         if ([attributeName isEqualToString:NSAccessibilityRowHeaderUIElementsAttribute])
2776             return convertToNSArray(backingObject->rowHeaders());
2777
2778         if ([attributeName isEqualToString:NSAccessibilityARIAColumnIndexAttribute])
2779             return @(backingObject->axColumnIndex());
2780
2781         if ([attributeName isEqualToString:NSAccessibilityARIARowIndexAttribute])
2782             return @(backingObject->axRowIndex());
2783     }
2784
2785     if (backingObject->isTree()) {
2786         if ([attributeName isEqualToString:NSAccessibilitySelectedRowsAttribute]) {
2787             AccessibilityObject::AccessibilityChildrenVector selectedChildrenCopy;
2788             backingObject->selectedChildren(selectedChildrenCopy);
2789             return convertToNSArray(selectedChildrenCopy);
2790         }
2791         if ([attributeName isEqualToString:NSAccessibilityRowsAttribute]) {
2792             AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2793             backingObject->ariaTreeRows(rowsCopy);
2794             return convertToNSArray(rowsCopy);
2795         }
2796
2797         // TreeRoles do not support columns, but Mac AX expects to be able to ask about columns at the least.
2798         if ([attributeName isEqualToString:NSAccessibilityColumnsAttribute])
2799             return [NSArray array];
2800     }
2801
2802     if ([attributeName isEqualToString:NSAccessibilityIndexAttribute]) {
2803         if (backingObject->isTreeItem()) {
2804             AXCoreObject* parent = backingObject->parentObject();
2805             for (; parent && !parent->isTree(); parent = parent->parentObject())
2806             { }
2807
2808             if (!parent)
2809                 return nil;
2810
2811             // Find the index of this item by iterating the parents.
2812             AccessibilityObject::AccessibilityChildrenVector rowsCopy;
2813             parent->ariaTreeRows(rowsCopy);
2814             size_t count = rowsCopy.size();
2815             for (size_t k = 0; k < count; ++k)
2816                 if (rowsCopy[k]->wrapper() == self)
2817                     return [NSNumber numberWithUnsignedInt:k];
2818
2819             return nil;
2820         }
2821
2822         if (backingObject->isTableRow())
2823             return [NSNumber numberWithInt:backingObject->rowIndex()];
2824     }
2825
2826     // The rows that are considered inside this row.
2827     if ([attributeName isEqualToString:NSAccessibilityDisclosedRowsAttribute]) {
2828         if (backingObject->isTreeItem() || backingObject->isARIATreeGridRow())
2829             return convertToNSArray(backingObject->disclosedRows());
2830     }
2831
2832     // The row that contains this row. It should be the same as the first parent that is a treeitem.
2833     if ([attributeName isEqualToString:NSAccessibilityDisclosedByRowAttribute]) {
2834         if (backingObject->isTreeItem()) {
2835             AXCoreObject* parent = backingObject->parentObject();
2836             while (parent) {
2837                 if (parent->isTreeItem())
2838                     return parent->wrapper();
2839                 // If the parent is the tree itself, then this value == nil.
2840                 if (parent->isTree())
2841                     return nil;
2842                 parent = parent->parentObject();
2843             }
2844             return nil;
2845         }
2846
2847         if (backingObject->isARIATreeGridRow()) {
2848             auto* row = backingObject->disclosedByRow();
2849             return row ? row->wrapper() : nil;
2850         }
2851     }
2852
2853     if ([attributeName isEqualToString:NSAccessibilityDisclosureLevelAttribute]) {
2854         // Convert from 1-based level (from aria-level spec) to 0-based level (Mac)
2855         int level = backingObject->hierarchicalLevel();
2856         if (level > 0)
2857             level -= 1;
2858         return [NSNumber numberWithInt:level];
2859     }
2860     if ([attributeName isEqualToString:NSAccessibilityDisclosingAttribute])
2861         return [NSNumber numberWithBool:backingObject->isExpanded()];
2862
2863     if (backingObject->isList() && [attributeName isEqualToString:NSAccessibilityOrientationAttribute])
2864         return NSAccessibilityVerticalOrientationValue;
2865
2866     if ([attributeName isEqualToString: @"AXSelectedTextMarkerRange"])
2867         return [self textMarkerRangeForSelection];
2868
2869     if ([attributeName isEqualToString: @"AXStartTextMarker"])
2870         return [self textMarkerForVisiblePosition:startOfDocument(backingObject->document())];
2871     if ([attributeName isEqualToString: @"AXEndTextMarker"])
2872         return [self textMarkerForVisiblePosition:endOfDocument(backingObject->document())];
2873
2874     if ([attributeName isEqualToString:NSAccessibilityBlockQuoteLevelAttribute])
2875         return [NSNumber numberWithUnsignedInt:backingObject->blockquoteLevel()];
2876     if ([attributeName isEqualToString:@"AXTableLevel"])
2877         return [NSNumber numberWithInt:backingObject->tableLevel()];
2878
2879     if ([attributeName isEqualToString: NSAccessibilityLinkedUIElementsAttribute]) {
2880         AccessibilityObject::AccessibilityChildrenVector linkedUIElements;
2881         backingObject->linkedUIElements(linkedUIElements);
2882         return convertToNSArray(linkedUIElements);
2883     }
2884
2885     if ([attributeName isEqualToString: NSAccessibilitySelectedAttribute])
2886         return [NSNumber numberWithBool:backingObject->isSelected()];
2887
2888     if ([attributeName isEqualToString: NSAccessibilityARIACurrentAttribute])
2889         return backingObject->currentValue();
2890
2891     if ([attributeName isEqualToString: NSAccessibilityServesAsTitleForUIElementsAttribute] && backingObject->isMenuButton()) {
2892         AccessibilityObject* uiElement = downcast<AccessibilityRenderObject>(*backingObject).menuForMenuButton();
2893         if (uiElement)
2894             return [NSArray arrayWithObject:uiElement->wrapper()];
2895     }
2896
2897     if ([attributeName isEqualToString:NSAccessibilityTitleUIElementAttribute]) {
2898         if (!backingObject->exposesTitleUIElement())
2899             return nil;
2900
2901         AXCoreObject* obj = backingObject->titleUIElement();
2902         if (obj)
2903             return obj->wrapper();
2904         return nil;
2905     }
2906
2907     if ([attributeName isEqualToString:NSAccessibilityValueDescriptionAttribute])
2908         return backingObject->valueDescription();
2909
2910     if ([attributeName isEqualToString:NSAccessibilityOrientationAttribute]) {
2911         AccessibilityOrientation elementOrientation = backingObject->orientation();
2912         if (elementOrientation == AccessibilityOrientation::Vertical)
2913             return NSAccessibilityVerticalOrientationValue;
2914         if (elementOrientation == AccessibilityOrientation::Horizontal)
2915             return NSAccessibilityHorizontalOrientationValue;
2916         if (elementOrientation == AccessibilityOrientation::Undefined)
2917             return NSAccessibilityUnknownOrientationValue;
2918         return nil;
2919     }
2920
2921     if ([attributeName isEqualToString:NSAccessibilityHorizontalScrollBarAttribute]) {
2922         AXCoreObject* scrollBar = backingObject->scrollBar(AccessibilityOrientation::Horizontal);
2923         if (scrollBar)
2924             return scrollBar->wrapper();
2925         return nil;
2926     }
2927     if ([attributeName isEqualToString:NSAccessibilityVerticalScrollBarAttribute]) {
2928         AXCoreObject* scrollBar = backingObject->scrollBar(AccessibilityOrientation::Vertical);
2929         if (scrollBar)
2930             return scrollBar->wrapper();
2931         return nil;
2932     }
2933
2934     if ([attributeName isEqualToString:NSAccessibilitySortDirectionAttribute]) {
2935         switch (backingObject->sortDirection()) {
2936         case AccessibilitySortDirection::Ascending:
2937             return NSAccessibilityAscendingSortDirectionValue;
2938         case AccessibilitySortDirection::Descending:
2939             return NSAccessibilityDescendingSortDirectionValue;
2940         default:
2941             return NSAccessibilityUnknownSortDirectionValue;
2942         }
2943     }
2944
2945     if ([attributeName isEqualToString:NSAccessibilityLanguageAttribute])
2946         return backingObject->language();
2947
2948     if ([attributeName isEqualToString:NSAccessibilityExpandedAttribute])
2949         return [NSNumber numberWithBool:backingObject->isExpanded()];
2950
2951     if ([attributeName isEqualToString:NSAccessibilityRequiredAttribute])
2952         return [NSNumber numberWithBool:backingObject->isRequired()];
2953
2954     if ([attributeName isEqualToString:NSAccessibilityInvalidAttribute])
2955         return backingObject->invalidStatus();
2956
2957     if ([attributeName isEqualToString:NSAccessibilityOwnsAttribute]) {
2958         AccessibilityObject::AccessibilityChildrenVector ariaOwns;
2959         backingObject->ariaOwnsElements(ariaOwns);
2960         return convertToNSArray(ariaOwns);
2961     }
2962
2963     if ([attributeName isEqualToString:NSAccessibilityARIAPosInSetAttribute])
2964         return [NSNumber numberWithInt:backingObject->posInSet()];
2965     if ([attributeName isEqualToString:NSAccessibilityARIASetSizeAttribute])
2966         return [NSNumber numberWithInt:backingObject->setSize()];
2967
2968     if ([attributeName isEqualToString:NSAccessibilityGrabbedAttribute])
2969         return [NSNumber numberWithBool:backingObject->isARIAGrabbed()];
2970
2971     if ([attributeName isEqualToString:NSAccessibilityDropEffectsAttribute]) {
2972         Vector<String> dropEffects = backingObject->determineARIADropEffects();
2973         return convertStringsToNSArray(dropEffects);
2974     }
2975
2976     if ([attributeName isEqualToString:NSAccessibilityPlaceholderValueAttribute])
2977         return backingObject->placeholderValue();
2978
2979     if ([attributeName isEqualToString:NSAccessibilityValueAutofillAvailableAttribute])
2980         return @(backingObject->isValueAutofillAvailable());
2981
2982     if ([attributeName isEqualToString:NSAccessibilityValueAutofillTypeAttribute]) {
2983         switch (backingObject->valueAutofillButtonType()) {
2984         case AutoFillButtonType::None:
2985             return @"none";
2986         case AutoFillButtonType::Credentials:
2987             return @"credentials";
2988         case AutoFillButtonType::Contacts:
2989             return @"contacts";
2990         case AutoFillButtonType::StrongPassword:
2991             return @"strong password";
2992         case AutoFillButtonType::CreditCard:
2993             return @"credit card";
2994         }
2995     }
2996
2997     if ([attributeName isEqualToString:NSAccessibilityValueAutofilledAttribute])
2998         return @(backingObject->isValueAutofilled());
2999
3000     if ([attributeName isEqualToString:NSAccessibilityHasPopupAttribute])
3001         return [NSNumber numberWithBool:backingObject->hasPopup()];
3002
3003     if ([attributeName isEqualToString:NSAccessibilityDatetimeValueAttribute])
3004         return backingObject->datetimeAttributeValue();
3005
3006     if ([attributeName isEqualToString:NSAccessibilityInlineTextAttribute])
3007         return @(backingObject->isInlineText());
3008
3009     // ARIA Live region attributes.
3010     if ([attributeName isEqualToString:NSAccessibilityARIALiveAttribute])
3011         return backingObject->liveRegionStatus();
3012     if ([attributeName isEqualToString:NSAccessibilityARIARelevantAttribute])
3013         return backingObject->liveRegionRelevant();
3014     if ([attributeName isEqualToString:NSAccessibilityARIAAtomicAttribute])
3015         return [NSNumber numberWithBool:backingObject->liveRegionAtomic()];
3016     if ([attributeName isEqualToString:NSAccessibilityElementBusyAttribute])
3017         return [NSNumber numberWithBool:backingObject->isBusy()];
3018
3019     // MathML Attributes.
3020     if (backingObject->isMathElement()) {
3021         if ([attributeName isEqualToString:NSAccessibilityMathRootIndexAttribute])
3022             return (backingObject->mathRootIndexObject()) ? backingObject->mathRootIndexObject()->wrapper() : 0;
3023         if ([attributeName isEqualToString:NSAccessibilityMathRootRadicandAttribute])
3024             return (backingObject->mathRadicandObject()) ? backingObject->mathRadicandObject()->wrapper() : 0;
3025         if ([attributeName isEqualToString:NSAccessibilityMathFractionNumeratorAttribute])
3026             return (backingObject->mathNumeratorObject()) ? backingObject->mathNumeratorObject()->wrapper() : 0;
3027         if ([attributeName isEqualToString:NSAccessibilityMathFractionDenominatorAttribute])
3028             return (backingObject->mathDenominatorObject()) ? backingObject->mathDenominatorObject()->wrapper() : 0;
3029         if ([attributeName isEqualToString:NSAccessibilityMathBaseAttribute])
3030             return (backingObject->mathBaseObject()) ? backingObject->mathBaseObject()->wrapper() : 0;
3031         if ([attributeName isEqualToString:NSAccessibilityMathSubscriptAttribute])
3032             return (backingObject->mathSubscriptObject()) ? backingObject->mathSubscriptObject()->wrapper() : 0;
3033         if ([attributeName isEqualToString:NSAccessibilityMathSuperscriptAttribute])
3034             return (backingObject->mathSuperscriptObject()) ? backingObject->mathSuperscriptObject()->wrapper() : 0;
3035         if ([attributeName isEqualToString:NSAccessibilityMathUnderAttribute])
3036             return (backingObject->mathUnderObject()) ? backingObject->mathUnderObject()->wrapper() : 0;
3037         if ([attributeName isEqualToString:NSAccessibilityMathOverAttribute])
3038             return (backingObject->mathOverObject()) ? backingObject->mathOverObject()->wrapper() : 0;
3039         if ([attributeName isEqualToString:NSAccessibilityMathFencedOpenAttribute])
3040             return backingObject->mathFencedOpenString();
3041         if ([attributeName isEqualToString:NSAccessibilityMathFencedCloseAttribute])
3042             return backingObject->mathFencedCloseString();
3043         if ([attributeName isEqualToString:NSAccessibilityMathLineThicknessAttribute])
3044             return [NSNumber numberWithInteger:backingObject->mathLineThickness()];
3045         if ([attributeName isEqualToString:NSAccessibilityMathPostscriptsAttribute])
3046             return [self accessibilityMathPostscriptPairs];
3047         if ([attributeName isEqualToString:NSAccessibilityMathPrescriptsAttribute])
3048             return [self accessibilityMathPrescriptPairs];
3049     }
3050
3051     if ([attributeName isEqualToString:NSAccessibilityExpandedTextValueAttribute])
3052         return backingObject->expandedTextValue();
3053
3054     if ([attributeName isEqualToString:NSAccessibilityDOMIdentifierAttribute])
3055         return backingObject->identifierAttribute();
3056     if ([attributeName isEqualToString:NSAccessibilityDOMClassListAttribute]) {
3057         Vector<String> classList;
3058         backingObject->classList(classList);
3059         return convertStringsToNSArray(classList);
3060     }
3061
3062     // This allows us to connect to a plugin that creates a shadow node for editing (like PDFs).
3063     if ([attributeName isEqualToString:@"_AXAssociatedPluginParent"])
3064         return [self associatedPluginParent];
3065
3066     // this is used only by DumpRenderTree for testing
3067     if ([attributeName isEqualToString:@"AXClickPoint"])
3068         return [NSValue valueWithPoint:backingObject->clickPoint()];
3069
3070     // This is used by DRT to verify CSS3 speech works.
3071     if ([attributeName isEqualToString:@"AXDRTSpeechAttribute"])
3072         return [self baseAccessibilitySpeechHint];
3073
3074     // Used by DRT to find an accessible node by its element id.
3075     if ([attributeName isEqualToString:@"AXDRTElementIdAttribute"])
3076         return backingObject->identifierAttribute();
3077
3078     if ([attributeName isEqualToString:@"AXAutocompleteValue"])
3079         return backingObject->autoCompleteValue();
3080
3081     if ([attributeName isEqualToString:NSAccessibilityPopupValueAttribute])
3082         return backingObject->popupValue();
3083
3084     if ([attributeName isEqualToString:@"AXKeyShortcutsValue"])
3085         return backingObject->keyShortcutsValue();
3086
3087     if ([attributeName isEqualToString:@"AXARIAPressedIsPresent"])
3088         return [NSNumber numberWithBool:backingObject->pressedIsPresent()];
3089
3090     if ([attributeName isEqualToString:@"AXIsMultiline"])
3091         return [NSNumber numberWithBool:backingObject->ariaIsMultiline()];
3092
3093     if ([attributeName isEqualToString:@"AXReadOnlyValue"])
3094         return backingObject->readOnlyValue();
3095
3096     if ([attributeName isEqualToString:@"AXIsActiveDescendantOfFocusedContainer"])
3097         return [NSNumber numberWithBool:backingObject->isActiveDescendantOfFocusedContainer()];
3098
3099     if ([attributeName isEqualToString:@"AXDetailsElements"]) {
3100         AccessibilityObject::AccessibilityChildrenVector details;
3101         backingObject->ariaDetailsElements(details);
3102       &